Updates from May, 2009 Toggle Comment Threads | Keyboard Shortcuts

  • Tomás Augusto Müller 12:09 am on May 4, 2009 Permalink | Reply
    Tags: ,   

    Conclusion – Nine Steps to Better Software Design Today Exercise 

    We have reached the end of the exercise – Nine Steps to Better Software Design, presented at chapter Object Calisthenics by Jeff Bay in The ThoughtWorks Anthology book from the Pragmatic Programmers.

    Eight of these nine rules are simply ways to visualize and implement the Holy Grail of object-oriented programming—the encapsulation of data. In addition, another drives the appropriate use of polymorphism (not using else and minimizing all conditional logic), and another is a naming strategy that encourages concise and straightforward naming standards, without inconsistently applied and hard-to-pronounce abbreviations.

    Tip from the author:

    In the long run, you will inevitably find that these rules contradict each other in some situations or that applying the rules leads to degenerate results. For the purpose of the exercise, however, spend 20 hours and 1,000 lines writing code that conforms 100% to these rules. You will find yourself having to break old habits and change rules that you may have lived with for your whole programming life. Each of the rules has been chosen such that if you follow it, you will encounter situations that would typically have an obvious (but perhaps incorrect) answer that is not available to you.

    Following these rules with discipline will force you to come up with the harder answers that lead to a much richer understanding of objectoriented programming. If you write 1,000 lines that follow all these rules, you will find that you have created something completely different from what you expected. Follow the rules, and see where you end up. If you keep working at it, the code you are writing might conform to these rules without any conscious effort on your part.

    If you have missed some part of this series, check out the list below with all related posts.

    1. Use only one level of indentation per method.
    2. Don’t use the else keyword.
    3. Wrap all primitives and strings.
    4. Use only one dot per line.
    5. Don’t abbreviate.
    6. Keep all entities small.
    7. Don’t use any classes with more than two instance variables.
    8. Use first-class collections.
    9. Don’t use any getters/setters/properties.

    Happy coding! ; )

     
  • Tomás Augusto Müller 12:07 am on May 4, 2009 Permalink | Reply
    Tags: ,   

    Rule 9: Don’t Use Any Getters/Setters/Properties 

    From the series about the rules of thumb, presented at chapter Object Calisthenics by Jeff Bay in The ThoughtWorks Anthology book from the Pragmatic Programmers (click here to see the the previous rules).

    The rule

    The last sentence of the previous rule leads almost directly to this rule.
    If your objects are now encapsulating the appropriate set of instance variables but the design is still awkward, it is time to examine some more direct violations of encapsulation. The behavior will not follow the instance variable if it can simply ask for the value in its current location.

    The idea behind strong encapsulation boundaries is to force programmers working on the code after you leave it to look for and place behavior into a single place in the object model. This has many beneficial downstream effects, such as a dramatic reduction in duplication errors and a better localization of changes to implement new features. This rule is commonly stated as “Tell, don’t ask.”

     
  • Tomás Augusto Müller 12:05 am on May 4, 2009 Permalink | Reply
    Tags: ,   

    Rule 8: Use First-Class Collections 

    From the series about the rules of thumb, presented at chapter Object Calisthenics by Jeff Bay in The ThoughtWorks Anthology book from the Pragmatic Programmers (click here to see the the previous rules).

    The rule

    The application of this rule is simple: any class that contains a collection should contain no other member variables. Each collection gets wrapped in its own class, so now behaviors related to the collection have a home. You may find that filters become part of this new class.

    Filters may also become function objects in their own right. Also, your new class can handle activities such as joining two groups together or applying a rule to each element of the group. This is an obvious extension of the rule about instance variables but is important for its own sake as well. A collection is really a type of very useful primitive. It has many behaviors but little semantic intent or clues for either the next programmer or the maintainer.

     
  • Tomás Augusto Müller 12:00 am on April 18, 2009 Permalink | Reply
    Tags: ,   

    Rule 7: Don’t Use Any Classes with More Than Two Instance Variables 

    From the series about the rules of thumb, presented at chapter Object Calisthenics by Jeff Bay in The ThoughtWorks Anthology book from the Pragmatic Programmers (click here to see the the previous rules).

    The rule

    Most classes should simply be responsible for handling a single state variable, but a few will require two. Adding a new instance variable to a class immediately decreases the cohesion of that class. In general, while programming under these rules, you’ll find that there are two kinds of classes, those that maintain the state of a single instance variable and those that coordinate two separate variables. In general, don’t mix the two kinds of responsibilities. 

    Now, go back and read the rule number three again. You probably notice that there are few cases where a cohesive single job description can be created for a class with many instance variables.


    Example:

        String first;
        String middle;
        String last;
    }

    The previous code could be decomposed into two classes like this:

    class Name {
        Surname family;
        GivenNames given;
    }

    class Surname {
        String family;
    }

    class GivenNames {
        List names;
    }

    Note that in thinking about how to do the decomposition, the opportunity to separate the concerns of a family name (used for many legal entity restrictions) could be separated from an essentially different kind of name. The GivenName object here contains a list of names, allowing the new model to absorb people with first, middle, and other given names. Frequently, the decomposition of instance variables leads to an understanding of commonality of several related instance variables. Sometimes several related instance variables actually have a related life in a first-class collection.

    Decomposing objects from a set of attributes into a hierarchy of collaborating objects leads much more directly to an effective object model. The recursive application of this rule has led to a very quick decomposition of complex large objects into much simpler models. Behavior naturally follows the instance variables into the appropriate place. If you get stuck, work downward by splitting objects into related halves or upward by picking any two instance variables and making an object out of them.

     
  • Tomás Augusto Müller 12:49 am on March 30, 2009 Permalink | Reply
    Tags: ,   

    Rule 6: Keep All Entities Small 

    From the series about the rules of thumb, presented at chapter Object Calisthenics by Jeff Bay in The ThoughtWorks Anthology book from the Pragmatic Programmers (click here to see the the previous rules).

    Keeping All Entities Small

    This means no class that’s more than fifty lines and no package that’s more than ten files.
    Classes of more than fifty lines usually do more than one thing, which makes them harder to understand and harder to reuse. Fifty-line classes have the added benefit of being visible on one screen without scrolling, which makes them easier to grasp quickly.

    What’s challenging about creating such small classes is that there are often groups of behaviors that make logical sense together. This is where you need to leverage packages. As your classes become smaller and have fewer responsibilities and as you limit package size, you’ll start to see that packages represent clusters of related classes that work together to achieve a goal. Packages, like classes, should be cohesive and have a purpose. Keeping those packages small forces them to have a real identity.

     
  • Tomás Augusto Müller 12:05 am on March 23, 2009 Permalink | Reply
    Tags: ,   

    Rule 5: Don’t Abbreviate 

    From the series about the rules of thumb, presented at chapter Object Calisthenics by Jeff Bay in The ThoughtWorks Anthology book from the Pragmatic Programmers (click here to see the the previous rules).

    It’s often tempting to abbreviate in the names of classes, methods, or variables. Resist the temptation. Abbreviations can be confusing, and they tend to hide larger problems.

    Think about why you want to abbreviate. Is it because you’re typing the same word over and over again? If that’s the case, perhaps your method is used too heavily, and you are missing opportunities to remove duplication.
    Is it because your method names are getting long? This might be a sign of a misplaced responsibility or a missing class.

    Try to keep class and method names to one to two words, and avoid names that duplicate the context. If the class is an Order, the method doesn’t need to be called shipOrder(). Simply name the method ship() so that clients call order.ship() — a simple and clear representation of what’s happening.

    For this exercise, all entities should have a name that is one or two words, with no abbreviations.

     
  • Tomás Augusto Müller 5:28 pm on December 24, 2008 Permalink | Reply
    Tags: ,   

    Rule 4: Use Only One Dot per Line 

    Hey! I’m alive! ;-)
    Just too busy, studing for SCJP (6). Wait for news, soon.

    But for now, let’s continue seeing the rules of thumb, presented at chapter Object Calisthenics by Jeff Bay. If you have missed one of the passed rules, just take a look in older posts at my blog archive.

    Talking about the fourth rule, the law of Demeter is a good place to start.

    From Wikipedia we have this:

    “The Law of Demeter (LoD), or Principle of Least Knowledge, is a design guideline for developing software, particularly object-oriented programs. The guideline was invented at Northeastern University towards the end of 1987, and can be succinctly summarized as “Only talk to your immediate friends.” The fundamental notion is that a given object should assume as little as possible about the structure or properties of anything else (including its subcomponents).”

    But as written in the book, think about it this way:

    "you can play with your toys, with toys that you make,
    and with toys that someone gives you.
    You don’t ever, ever play with your toy’s toys."

    If you have more than one dot on any given line of code, maybe the activity is happening in the wrong place. Maybe your object is dealing with two other objects at once. If this is the case, your object is a middleman; it knows too much about too many people. Consider moving the activity into one of the other objects.

    And watch out, these multiple dots indicate that you’re violating encapsulation, since your object is digging deeply into another object through those dots.

    Analyse closely the code below:

    Without applying the rule:

    class Board {
    ...
    class Piece {
    ...
    String representation;
    }
    class Location {
    ...
    Piece current;
    }
    String boardRepresentation() {
    StringBuffer buf = new StringBuffer();
    for(Location l : squares())
    buf.append(l.current.representation.substring(0, 1));
    return buf.toString();
    }
    }

    Applying the rule:

    class Board {
    ...
    class Piece {
    ...
    private String representation;

    String character() {
    return representation.substring(0, 1);
    }
    void addTo(StringBuffer buf) {
    buf.append(character());
    }
    }

    class Location {
    ...
    private Piece current;

    void addTo(StringBuffer buf) {
    current.addTo(buf);
    }
    }

    String boardRepresentation() {
    StringBuffer buf = new StringBuffer();
    for(Location l : squares())
    l.addTo(buf);
    return buf.toString();
    }
    }

    Gift
    We just created a method with a strong cohesive name and job and is quite likely to be reused. At a glance, the new version is little harder to understand. But isn’t. It simply requires a slightly different approach.
    Oh! I almost forgot! HAPPY CHRISTMAS! Full of happiness and peace for us all!

     
  • Tomás Augusto Müller 1:33 pm on December 9, 2008 Permalink | Reply
    Tags: ,   

    Rule 3: Wrap All Primitives and Strings 

    Continuing the sequence of posts about the “Nine Steps to Better Software Design” exercise proposed in The ThoughtWorks Anthology book.boxes

    This one is very easy and simple. The intent here is to wrap all primitive values (including a simple String value) into small little objects. An primitive value like an int, is just a scalar with no meaning. When a method takes an int as a parameter, the method name needs to express their intent.

    In another hand, if you pass to this same method a object called “ZipCode” for example, is much easier to see what’s happening. And since it isn’t possible to pass another value to a method that takes an ZipCode parameter, your program stay more maintainable.

    With an object, even the small one, you are giving to the compiler and the programmer more information about what the value is and why it is being used, helping you to write semantically correct programs.

    Another thing to see here, is that these small objects (eg: Hour, Money…) also give you a great place to put behavior, that otherwise would have been littered around other classes.

     
  • Tomás Augusto Müller 7:40 pm on October 26, 2008 Permalink | Reply
    Tags: , patterns, ,   

    Rule 2: Don’t Use the else Keyword 

    As Jeff Bay wrote: “Every programmer understands the if/else construct.” This is the simplest conditional logic, avalilable in nearly every programming language. But it also make possible to turns your code into a nasty nested conditional logic that’s impossible to follow or very dificult to read, understand and mantain. Conditionals are also a frequent source of duplication.

    But don’t worry. It’s not only your fault :-)
    Due to ease of simply add another branch to an conditional logic, rather than factoring to a better solution, it is a very common problem that we can see.

    Tip from the book

    Status flags, for example, frequently lead to this kind of trouble:

    public static void endMe() {
    if (status == DONE) {
    doSomething();
    } else {
    <other code>
    }
    }

    You have several options for rewriting this without the else. Form simple cases, use this:

    public static void endMe() {
    if (status == DONE) {
    doSomething();
    return;
    }
    <other code>
    }

    Another tip is make use of ternary operator:

    public static Node head() {
    if (isAdvancing()) {
    return first;
    }
    else {
    return last;
    }
    }

    public static Node head() {
    return isAdvancing() ? first : last;
    }

    Cutting down else keyword

    Look the early return used at first example. Was used to collapse down the lines where else keyword were used. Also take care to not overuse early returns in your code. This can easily reduce clarity and turn the code into a mess again.

    Simple cases can be replaced with guard clauses and early returns. Look at those sites for more information about guard clauses:

    From Coding Horror I’ve taken this nice picture :-) :

    Code Arrow Formation

    In Object-Oriented languages we have polymorphism. It is a powerful tool for handling complex conditional cases, making the design easier to read and maintain, expressing their intent more clearly. Take a look at the Design Patterns book, and find the Strategy pattern. It can be useful to avoid duplicated branchings, and it is a good example of polymorphism. Also see the Null Object pattern, it may help in some situations.

    And keep in mind that some of others rules, like the first one can help here!

    Good luck in your exercise!

     
  • Tomás Augusto Müller 3:39 pm on September 20, 2008 Permalink | Reply
    Tags: , ,   

    Rule 1: Use One Level of Indentation per Method 

    In a previous entry, I’ve written about an exercice based on “rules of tumb”, proposed by Jeff Bay. Here is the first rule.

    Have you ever encountered a large amount of lines all together into a single method, and started wondering “oh hell, where I start…” ? Please! Don’t lie for your self conscience!

    So, this rule is a good way to start.

    The Rule

    Try to ensure that each method does exactly one thing. One control structure, or one block of statements per method. Nested control structures in a method are a signal that you’re working at multiple level of abstraction, and that means you’re doing more than one thing.

    Working with methods that does exactly one thing, and classes doing exactly one thing, your code begins to change, becoming more smaller and increasing exponentially the level of reuse. Or you see a easy opportunity to reuse a method with many responsibilities implemented on hundred lines?

    Another effect of this rule is that each individual method has become much more easier to match its implementation to its name, and the ease of bug hunting.

    Tip from the book

    Use the Extract Method feature of your IDE to pull out behaviors until your methods have only one level of indentation. See the example below:

    class Board {
    String board() {
    StringBuffer buf = new StringBuffer();
    for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++)
    buf.append(data[i][j]);
    buf.append("\n");
    }
    return buf.toString();
    }
    }

    applying the rule, we will see this:

    class Board {
    String board() {
    StringBuffer buf = new StringBuffer();
    collectRows(buf);
    return buf.toString();
    }

    void collectRows(StringBuffer buf) {
    for (int i = 0; i < 10; i++)
    collectRow(buf, i);
    }

    void collectRow(StringBuffer buf, int row) {
    for (int i = 0; i < 10; i++)
    buf.append(data[row][i]);
    buf.append("\n");
    }
    }

    That’s it! Wait for the next one! Till there have a happy programming!

     
c
compose new post
j
next post/next comment
k
previous post/previous comment
r
reply
e
edit
o
show/hide comments
t
go to top
l
go to login
h
show/hide help
shift + esc
cancel
Follow

Get every new post delivered to your Inbox.

%d bloggers like this: