Hi Leif,

if I write a function I only use once, I usually just inline it.  Unless of 
> course I believe deep in my heart I'll have need of it somewhere else soon


So your motivation for the Extract Method 
<http://refactoring.com/catalog/extractMethod.html> refactoring is sharing 
of logic. There are others.
My motivation in this exercise was to separate intention from 
implementation.
Here is Kent Beck in an excerpt from Refactoring: Improving the Design of 
Existing Code 
<http://www.amazon.co.uk/Refactoring-Improving-Design-Existing-Technology/dp/0201485672>:
 
 

Given software engineers' infatuation with indirection, it may not surprise 
you to learn that most refactoring introduces more indirection into a 
program. Refactoring tends to break big objects into several smaller ones 
and big methods into several smaller ones.

Indirection is a two-edged sword, however. Every time you break one thing 
into two pieces, you have more things to manage. It also can make a program 
harder to read as an object delegates to an object delegating to an 
object. So you'd like to minimize indirection.

Not so fast, buddy. Indirection can pay for itself. Here are some of the 
ways.


   - *To enable sharing of logic. *For example, a submethod invoked in two 
      different places or a method in a superclass shared by all subclasses.
      - *To explain intention and implementation separately.* Choosing the 
      name of each class and the name of each method gives you an 
      opportunity to explain what you intend. The internals of the class or 
      methodexplain how the intention is realized. If the internals also 
      are written in terms of intention in yet smaller pieces, you can write 
code 
      that communicates most of the important information about its own 
structure.
      - *To isolate change.* I use an object in two different places. I 
      want to change the behavior in one of the two cases. If I change the 
      object, I risk changing both. So I first make a subclass and refer to it 
in 
      the case that is changing. Now I can modify the subclass without risking 
an 
      inadvertent change to the other case.
      - *To encode conditional logic. *Objects have a fabulous mechanism, 
      polymorphic messages, to flexibly but clearly express conditional logic. 
      By changing explicit conditionals to messages, you can often reduce 
      duplication, add clarity, and increase flexibility all at the same time.
   
Here is the refactoring game: Maintaining the current behavior of the 
system, how can you make your system more valuable, either by increasing 
its quality or by reducing its cost?

The most common variant of the game is to look at your program. Identify a 
place where it is missing one or more of the benefits of indirection. Put 
in that indirection without changing the existing behavior. Now you have a 
more valuable program because it has more qualities that we will appreciate 
tomorrow.

Philip

On Tuesday, 9 December 2014 05:06:22 UTC, Leif wrote:
>
> Hi, Philip.
>
> I had the same urge as David--I tried it out, glossing over any formal 
> rules.  Here's what I came up with:
> https://gist.github.com/leifp/ae37c3b6f1b497f13f1e
>
> In truth, I think David's solution is more readable and maintainable.  But 
> I think "maintainability" is a pretty tricky concept:
>
> My code makes a seq of maps describing rows, and then turns them into 
> strings at the end.  This is probably more work to understand than David's 
> solution.  But is it less maintainable?  Well, currently, the answer is 
> "yes," but what if I need to output a diamond in several different 
> formats?  What if marketing wants each row to be a different color and 
> font?  I would start to favor my solution in that case.  My point is that 
> the difference between "maintainable" and "horrible" is evident, but the 
> difference between "maintainable" and "easily maintainable" depends on 
> predicting the future somewhat.
>
> I also favor a slightly less verbose style.  A function is an abstraction, 
> and you seem to be writing functions for very concrete steps. I think you 
> have most of the correct abstractions for your solution method, you just 
> need to consolidate the more concrete steps.  Something like:
>
> flip-bottom-up -> flip (or vertical- and horizontal-flip)
> join-together-side-by-side -> beside
> put-one-on-top-of-the-other -> stack (or ontop, or ...)
> reverse-every-row -> (map reverse rows) ; very readable to clojure 
> programmers
>
> (let [top-right (create-top-right-quadrant-for letter)
>        right (stack top-right
>                           (flip top-right))
>        diamond (beside (map reverse (drop-first-col right)) right)]
>   (display diamond))
>
> The broad takeaway is: if I write a function I only use once, I usually 
> just inline it.  Unless of course I believe deep in my heart I'll have need 
> of it somewhere else soon :).  
> This is somewhat a matter of taste, and again, the requirements history 
> usually determines what gets abstracted into functions, and history can be 
> messy. :)
>
> Hope that helps,
> Leif
>
> On Saturday, December 6, 2014 5:48:02 AM UTC-5, Philip Schwarz wrote:
>>
>> 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 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.

Reply via email to