I forgot to mention but https://github.com/bbatsov/clojure-style-guide is a pretty good resource. On 9 Dec 2014 00:24, "Philip Schwarz" <philip.johann.schw...@googlemail.com> wrote:
> Hello David, > > I had set myself the constraint that I wanted the solution to exploit two > symmetries: > (1) The top left and top right of the diamond are mirror images > (2) The top half and bottom half of the diamond are also mirror images > > >I'm assuming you used a TDD process to write this (correct me if > wrong--basing that on the articles you linked to) > I was on a train commuting back home, and what I did was sit in a loop > where I wrote some code and then tweaked it until executing it in the REPL > gave me the part of the diamond that I wanted, by eyeballing the console > output. What a coincidence that in your gist you linked to > http://blog.jayfields.com/2014/01/repl-driven-development.html . I was > looking at exactly that blog post on Sunday to determine if what I had been > doing could be classified as REPL-based? Still not sure. Thoughts? > > My first version of the code was this > <https://gist.github.com/philipschwarz/c7e3be1ac97e482d04bf>: > > (defn print-diamond [letter] > (let [alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ" > position-of (fn [letter] (inc (- (int letter) (int \A)))) > number-of-letters (position-of letter) > dashes (fn [n] (repeat n \-)) > fixed-text-for (fn [letter] (concat (dashes (dec (position-of > letter))) (list letter))) > template (map fixed-text-for (take number-of-letters alphabet)) > pad-with-trailing-dashes (fn [index line] (concat line (dashes (dec > (- number-of-letters index))))) > top-right-quadrant (map-indexed pad-with-trailing-dashes template) > top-left-quadrant (map reverse (map rest (take number-of-letters > top-right-quadrant))) > top-half (map concat top-left-quadrant top-right-quadrant) > diamond (concat top-half (drop 1 (reverse top-half)))] > (doseq [line (map #(apply str %) diamond)] > (println line)))) > > I showed it to Extreme Programming and Agile Guru Ron Jeffries, and the > following conversation ensued: > > > @philip_schwarz 1st stab at Clojure print-diamond using symmetries > identified by @TotherAlistair @RonJeffries @gdinwiddie @sebrose > https://gist.github.com/philipschwarz/c7e3be1ac97e482d04bf > @RonJeffries @philip_schwarz *can people read that and figure out what it > does? *i can't but not a closure person. @totheralistair @gdinwiddie > @sebrose > @philip_schwarz @RonJeffries @TotherAlistair @gdinwiddie @sebrose *I like > defns of top-half & diamond & think they r graspable-ish; top-left-quadrant > less so* > @philip_schwarz one interesting Q for us all is *if one didn't know the > prob could one grok the prog* @totheralistair @gdinwiddie @sebrose > @gdinwiddie .@RonJeffries I think *the program is generally easier to > grok if you've got the tests, too.* @philip_schwarz @TotherAlistair > @sebrose > @philip_schwarz Dec 3 > @gdinwiddie @RonJeffries @TotherAlistair @sebrose agree - I have added > tests: > https://github.com/philipschwarz/diamond-problem-in-clojure/blob/master/test/diamond_problem_in_clojure/core_test.clj > > > I notice you did not write tests. I also notice that you added comments to > your methods. I like your comments. Find them useful. I am not saying the > following applies to your comments, but it will give you an idea of the > programming culture I am part of. In that culture, comments are looked at > with suspicion: > e.g. 1: https://twitter.com/nzkoz/status/538892801941848064 > > <https://pbs.twimg.com/media/B3qIJLFCcAEJLWm.jpg> > > e.g. 2: "The proper use of comments is to compensate for our failure to > express ourself in code." - Robert C. Martin > e.g. 3: "Comments often are used as a deodorant... often ....comments are > there because the code is bad." - Martin Fowler > e.g. 4: > > - Primary Rule: Comments are for things that *cannot* be expressed in > code. > - Redundancy Rule: Comments which restate code must be deleted. > - Single Truth Rule: If the comment says what the code *could* say, > then the code must change to make the comment redundant. > > > In that culture, we aim to use certain implementation patterns that make > comments unnecessary. Also, where possible, the tests act as (executable, > more reliable) documentation. > > Moving on, after writing the terse first version of the code, I set out to > *make > my code more readable*. > > Are you familiar with Robert Martin's dictum?: > > The Three Functions of a s/w module: > * The function it performs while executing > * To afford change. A module that is difficult to change is broken and > needs fixing, even though it works > * *To communicate to its readers. A module that does not communicate is > broken and needs fixing.* > > The rationale for making code more readable is an economic one. Here is a > brief summary of Ken't Beck's thoughts on the matter: > > o Economics is the underlying driver of software design > o Software should be designed to reduce its overall cost > o COST(total) = COST(develop) + COST(maintain) > o The cost of maintenance is much higher than the initial cost of > development > o Maintenance is expensive because understanding existing code is > time-consuming and error-prone > o Making changes is generally easy once you know what needs changing > o COST(maintain) = COST(understand) + COST(change)+ COST(test)+ > COST(deploy) > o Learning what the code does is the expensive part > o One strategy for reducing overall cost is to invest more in initial > development in hope of reducing or eliminating the need for change > o Such efforts have generally failed > o Beck’s strategy for reducing overall costs is to ask all programmers to > address the cost of understanding code during the maintenance phase, by > communicating programmer to programmer > o The immediate benefits of clear code are fewer defects, easier sharing > of code, and smoother development > > TO BE CONTINUED... > > Philip > > On Saturday, 6 December 2014 13:36:47 UTC, David Della Costa wrote: >> >> Hi Philip, >> >> I read your message and immediately wanted to try it myself--I intended >> to leave it at that but I realized I would be remiss if I did not give you >> a little bit of feedback based on my experience. I should add that I was >> kind of fast and loose with my solution (that is, I didn't really read the >> instructions), but it does print out the diamond shape according to what I >> saw in the blog post examples. >> >> First of all, here's what I came up with: >> >> https://gist.github.com/ddellacosta/ba7e03951ba1bafd3ec9 >> >> As you said, you weren't looking for alternative algorithms and I >> recognize that that's not the point. But there are a few things that I >> think are good and/or common Clojure practice that I think I've >> internalized, and writing out an alternative solution helped me to see them. >> >> - I'm assuming you used a TDD process to write this (correct me if >> wrong--basing that on the articles you linked to), but I think a >> repl-driven process may be more common for working through a problem like >> this--i.e. something you can wrap your head around as a whole and solve >> iteratively. That's not to say I and others don't use TDD in Clojure dev, >> but just that it's also quite common to do a lot of this kind of >> development in the repl. >> >> - you're grouping your side-effecting code w/the code that generates the >> diamond data structure here: https://gist.github.com/ddellacosta/ >> ba7e03951ba1bafd3ec9 >> >> While of course the diamond kata is a bit contrived and the point is to >> print stuff out in the end, it also looks like you are trying to be >> thoughtful about how you structure your code. So I would suggest isolating >> your pure functions from your side-effecting code as a sort of basic >> separation, and avoid monolithic functions like the one I linked to above. >> This gives you the freedom to apply the data structure to other processes >> if need be, rather than having to refactor that code later on as soon as >> you need to do something other than printing to the final diamond data >> structure. That is a more compositional approach that is good to follow as >> part of functional programming practice in general. And otherwise it seems >> like you are following this approach--I think you can see this in the shape >> of your code overall. >> >> - Stylistically, I found your naming conventions to be too verbose, with >> not enough information about the actual input and output--I would prefer a >> style like I used in my solution which aims for readable conciseness, while >> documenting what is going in and coming out of my functions. I assume >> Clojure developers reading my code will have a good understanding of the >> core data structures and functions available to manipulate them, and so I >> want to leverage that as much as possible in how I write and document my >> code. >> >> In fact, at this point I prefer using Prismatic's schema ( >> https://github.com/Prismatic/schema) to document as well as provide >> further safety for my functions, and am of the opinion that Clojure's one >> glaring weakness is its approach to typing--but that's another discussion >> and I recognize this is not necessarily a widely-held opinion. >> >> More generally, I think reasonable people could disagree on naming >> conventions and so I would hesitate to say you're doing something "wrong" >> here--I would rather say: the more Clojure code you read the more you'll >> get a sense of how people tend to write. You'll figure out what you want >> to adopt in your own style, and what Clojure devs are going to expect. >> >> - I don't want to get too deep into the algorithm itself but I think you >> would find it more natural to work line by line vs. the way you constructed >> blocks and flipped them right/left, and you'd have less code overall. I >> will boldly claim that my solution may be closer to how other developers >> familiar with Clojure (or functional programming in general) may approach >> it--not that I'm claiming it's the best approach. I do think it is more >> concise without sacrificing readability (which is subjective, I fully >> appreciate). >> >> - I don't know if I've ever once used a main function, and you don't see >> them in libraries, certainly. But that is minor--there's no reason *not* >> to use it, just that I wouldn't expect to see it. >> >> I hope this is useful feedback--good luck in your journey and enjoy >> Clojure! >> >> Dave >> >> >> 2014-12-06 19:48 GMT+09:00 Philip Schwarz <philip.joh...@googlemail.com>: >> >>> Hello, >>> >>> can you please review my first solution to the diamond kata [1] and tear >>> it to bits: let me know all the ways in which YOU would improve the code. >>> >>> I am not so interested in a better algorithm for solving the kata. I am >>> learning Clojure and what I want to know is what YOU would do to make the >>> code more readable/understandable/maintainable, or just to make it >>> follow Clojure idioms and/or conventions that YOU find effective, or to >>> follow a coding style that YOU find more effective. >>> >>> Thanks, >>> >>> Philip >>> >>> [1] https://github.com/philipschwarz/diamond-problem-in-clojure >>> >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "Clojure" group. >>> To post to this group, send email to clo...@googlegroups.com >>> Note that posts from new members are moderated - please be patient with >>> your first post. >>> To unsubscribe from this group, send email to >>> clojure+u...@googlegroups.com >>> For more options, visit this group at >>> http://groups.google.com/group/clojure?hl=en >>> --- >>> You received this message because you are subscribed to the Google >>> Groups "Clojure" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to clojure+u...@googlegroups.com. >>> For more options, visit https://groups.google.com/d/optout. >>> >> >> -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with > your first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en > --- > You received this message because you are subscribed to a topic in the > Google Groups "Clojure" group. > To unsubscribe from this topic, visit > https://groups.google.com/d/topic/clojure/zR5Ny7aoBM0/unsubscribe. > To unsubscribe from this group and all its topics, send an email to > clojure+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.