Implementation Patterns

Author: Kent Beck
3.5
All Stack Overflow 11

Comments

by cherouvim   2017-08-20

Although it is in Java, this is the book I recommend for people who want to optimize/modernize their coding style: http://www.amazon.com/Implementation-Patterns-Addison-Wesley-Signature-Kent/dp/0321413091

by marcio   2017-08-20

In your case, stick with the constructor. The information belongs in Customer and 4 fields are fine.

In the case you have many required and optional fields the constructor is not the best solution. As @boojiboy said, it's hard to read and it's also hard to write client code.

@contagious suggested using the default pattern and setters for optional attributs. That mandates that the fields are mutable, but that's a minor problem.

Joshua Block on Effective Java 2 say that in this case you should consider a builder. An example taken from the book:

 public class NutritionFacts {  
   private final int servingSize;  
   private final int servings;  
   private final int calories;  
   private final int fat;  
   private final int sodium;  
   private final int carbohydrate;  

   public static class Builder {  
     // required parameters  
     private final int servingSize;  
     private final int servings;  

     // optional parameters  
     private int calories         = 0;  
     private int fat              = 0;  
     private int carbohydrate     = 0;  
     private int sodium           = 0;  

     public Builder(int servingSize, int servings) {  
      this.servingSize = servingSize;  
       this.servings = servings;  
    }  

     public Builder calories(int val)  
       { calories = val;       return this; }  
     public Builder fat(int val)  
       { fat = val;            return this; }  
     public Builder carbohydrate(int val)  
       { carbohydrate = val;   return this; }  
     public Builder sodium(int val)  
       { sodium = val;         return this; }  

     public NutritionFacts build() {  
       return new NutritionFacts(this);  
     }  
   }  

   private NutritionFacts(Builder builder) {  
     servingSize       = builder.servingSize;  
     servings          = builder.servings;  
     calories          = builder.calories;  
     fat               = builder.fat;  
     soduim            = builder.sodium;  
     carbohydrate      = builder.carbohydrate;  
   }  
}  

And then use it like this:

NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8).
      calories(100).sodium(35).carbohydrate(27).build();

The example above was taken from Effective Java 2

And that doesn't only applies to constructor. Citing Kent Beck in Implementation Patterns:

setOuterBounds(x, y, width, height);
setInnerBounds(x + 2, y + 2, width - 4, height - 4);

Making the rectangle explicit as an object explains the code better:

setOuterBounds(bounds);
setInnerBounds(bounds.expand(-2));
by anonymous   2017-08-20

Check out Implementation Patterns by Kent Beck. There is a particular pattern I am thinking of that may help in this situation... it is called "Guards". Rather than having tons of conditions, you can break them out into a guard, which makes it clear which are the adverse conditions in a method.

So for example, if you have a method that does something, but there are certain conditions where it shouldn't do something, rather than:

public void doSomething() {
    if (condition1 && condition2 && condition3 && condition4) {
        // do something
    }
}

You could change it to:

public void doSomething() {
    if (!condition1) {
        return;
    }

    if (!condition2) {
        return;
    }

    if (!condition3) {
        return;
    }

    if (!condition4) {
        return;
    }

    // do something
}

It's a bit more verbose, but a lot more readable, especially when you start having weird nesting, the guard can help (combined with extracting methods).

I HIGHLY recommend that book by the way.