As Kent Beck notes when discussing guard clauses in Implementation Patterns making a routine have a single entry and exit point ...
"was to prevent the confusion possible
when jumping into and out of many
locations in the same routine. It made
good sense when applied to FORTRAN or
assembly language programs written
with lots of global data where even
understanding which statements were
executed was hard work ... with small methods and mostly local data, it is needlessly conservative."
I find a function written with guard clauses much easier to follow than one long nested bunch of if then else statements.
i second the recommendation for uncle bob's "clean code". but you may wish to take a look at http://www.amazon.com/Implementation-Patterns-Addison-Wesley-Signature-Kent/dp/0321413091 as i think this deals with your specific question a bit better. good code should leap off the page and tell you what it does/how it works.
For such an old programming language (well, maybe not "Lisp" old, but Ruby is older than Java, after all) and a community that fanatic about code quality, style and beauty, the Ruby book market is surprisingly light on "higher level" books.
There are several reasons for this: a lot of Rubyists are already seasoned Smalltalk or Lisp programmers when they pick up Ruby, so they don't need those books. And Ruby and Smalltalk are similar enough that you can just read a Smalltalk book instead. (For example, you can pretty much read Stéphane Ducasse's list of free Smalltalk books from top to bottom.) The same goes for Perl.
Until very recently, the best higher level Ruby book was basically Smalltalk Best Practice Patterns by Kent Beck. (There is a newer version of this book, called Implementation Patterns which uses Java instead of Smalltalk. However, since Kent's Java style is very Smalltalk-ish, it is essentially SBPP, 2nd Ed.) However, since then, several higher level books have been released or are in the works:
Design Patterns in Ruby by Russ Olsen,
Ruby Best Practices by Gregory T. Brown,
Refactoring: Ruby Edition by Jay Fields, Shane Harvie, Martin Fowler and Kent Beck (a re-interpretation of Fowler's book in Ruby) and
Rein Henrichs is (or at least was, as of last year) working on Ruby Best Practice Patterns.
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();
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).
As Kent Beck notes when discussing guard clauses in Implementation Patterns making a routine have a single entry and exit point ...
I find a function written with guard clauses much easier to follow than one long nested bunch of
if then else
statements.i second the recommendation for uncle bob's "clean code". but you may wish to take a look at http://www.amazon.com/Implementation-Patterns-Addison-Wesley-Signature-Kent/dp/0321413091 as i think this deals with your specific question a bit better. good code should leap off the page and tell you what it does/how it works.
For such an old programming language (well, maybe not "Lisp" old, but Ruby is older than Java, after all) and a community that fanatic about code quality, style and beauty, the Ruby book market is surprisingly light on "higher level" books.
There are several reasons for this: a lot of Rubyists are already seasoned Smalltalk or Lisp programmers when they pick up Ruby, so they don't need those books. And Ruby and Smalltalk are similar enough that you can just read a Smalltalk book instead. (For example, you can pretty much read Stéphane Ducasse's list of free Smalltalk books from top to bottom.) The same goes for Perl.
Until very recently, the best higher level Ruby book was basically Smalltalk Best Practice Patterns by Kent Beck. (There is a newer version of this book, called Implementation Patterns which uses Java instead of Smalltalk. However, since Kent's Java style is very Smalltalk-ish, it is essentially SBPP, 2nd Ed.) However, since then, several higher level books have been released or are in the works:
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
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:
And then use it like this:
The example above was taken from Effective Java 2
And that doesn't only applies to constructor. Citing Kent Beck in Implementation Patterns:
Making the rectangle explicit as an object explains the code better:
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:
You could change it to:
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.