Monday, April 26, 2010

First Meeting of the "Software Craftsmanship in Israel" Group

I am pleased to announce that we are planning to have our fist “Software Craftsmanship in Israel” group meeting on Wednesday, May 26th.

Who should attend?
Everybody who cares about Software Development as a Professional.
You are welcome to pass this announcement onto anyone you think may be interested.

Does the meeting require any knowledge of a specific technology?
NO. NONE. ZIPPO.
The sole purpose of “Software Craftsmanship” is to improve our skills in Software Engineering and Development and it doesn’t require any particular technological knowledge.
The examples, tutorials and hands-on exercises may be done using .NET, Java, Python, Ruby and whatever technology you would like to use.
Members will be encouraged to pair up with someone they have not worked with before, thus enhancing their perspective and knowledge.
If you have a laptop with your environments set-up, you are most welcome to bring it to the meetings.

How much does it cost?
Absolutely nothing, the event is free and open for everybody’s participation.
What’s the first meeting's agenda?
Introducing the Software Craftsmanship in Israel Group
Introducing the Software Craftsmanship Manifest and Goals

What is “Software Craftsmanship”? – A Short Presentation
Hands-On

Summary

When and Where?
 When:
           Wednesday, May 26th
           From 18:30 to 20:00
 Where:
            The exact place hasn't yet been finalized, please follow the announcement on the LinkedIn registration event:

How to register?
Use the following LinkedIn event registration.
If you don’t have a LinkedIn account you can send me an email in order to reserve a place.

Please take a few seconds to register either using the LinkedIn event registration or by sending me an email.

That’s all,
Let’s roll it out!

Friday, April 16, 2010

Writing Readable Code - Complex Object Construction

(Cross post from IRefactor)

Once upon a time, there was a class called Invoice. Its responsibility was to calculate a final
price being presented to the customer.

Time went on; The autumn passed, the winter fade out and the spring was already at the door and our class started to rust.
Each time a developer found a new set of relevant parameters (that should have been passed to the Invoice class) he added a new constructor, to support them.

And so it happened, that after a while, two fellows stumbled on the class:

"What's that rusty thing, my dear?" said G.Ollum "I don't understand; What constructor should I invoke on the Invoice class? Does it matter how should I create the Invoice object? The class has more than 20 constructors; How in the world, somebody would understand what to do?"

"Let me see, what's the problem" said D.Eagol


    public class Invoice
    {
        public Customer Customer { get; private set; }
        public DateTime ContractDate { get; private set; }
        public TimeSpan ServiceContinuum { get; private set; }
        public double BaseFee { get; private set; }
        public double ServiceFee { get; private set; }
 
        //... a lot of other members ...
 
        public Invoice(Customer customer)
        {
            Customer = customer;
        }
 
        public Invoice(Customer customer, DateTime contractDate)
            : this(customer)
        {
        }
 
        public Invoice(Customer customer, DateTime contractDate, double baseFee)
            : this(customer, contractDate)
        {
        }
 
        public Invoice(Customer customer, TimeSpan serviceContinuum, double serviceFee)
            : this(customer)
        {
        }
 
        //... a lot of other constructors ...
    }

"It seems that you are right G.Olum", said D.Eagol after looking at the code, "You have a lot of
different constructors, each instantiates a slightly different type of Invoice object, mainly because there are a lot of optional parameters to the Invoice class. There are also required ones; Look at the Customer parameter being accepted in each and every constructor."

"Moreover", continued D.Eagol, "The world has changed and something that shouldn't have been forgotten, was lost."

"What's that, my dear?", inquired G.Olum

"Well, you cannot name your constructors. That's why it is so difficult for you to find how to instantiate
the class. If you were supplied methods with meaningful, intention revealing names then you would be able to create a required object", explained D.Eagol

"So, what can I do?", cried G.Olum

"Let's summarise what you really want to do and then see how to accomplish it", said D.Eagol

You want to:
  • Create a complex object, with:

    • A few required parameters
    • A few (or many) optional parameters
You don't want to:
  • Use constructors - they are nameless and we fear of them
So, let's create an internal class whose sole responsibility will be to shadow that complex
creation
.
Our inner class will provide a meaningful method name for each optional parameter of the Invoice class.
The required parameters will be passed to one(and only one) inner's class constructor. Since, that inner class
deals with construction, let's call him a Builder.

Here is, how it should look:


    public sealed class Invoice
    {
        public Customer Customer { get; private set; }
        public DateTime ContractDate { get; private set; }
        public TimeSpan ServiceContinuum { get; private set; }
        public double BaseFee { get; private set; }
        public double ServiceFee { get; private set; }
 
        private Invoice()
        {
        }
 
        public class Builder
        {
            private Customer customer;
            private DateTime contractDate;
            private TimeSpan serviceContinuum;
            private double baseFee;
            private double serviceFee;
 
 
            public Builder(Customer customer)
            {
                this.customer = customer;
            }
 
            public Builder SignedOn(DateTime signDate)
            {
                this.contractDate = signDate;
 
                return this;
            }
 
            public Builder ServiceAgreementForPeriodOf(TimeSpan serviceContinuum)
            {
                this.serviceContinuum = serviceContinuum;
 
                return this;
            }
 
            public Builder ServiceBaseFee(double baseFee)
            {
                this.baseFee = baseFee;
 
                return this;
            }
 
            public Builder ServiceFee(double serviceFee)
            {
                this.serviceFee = serviceFee;
 
                return this;
            }
 
            public Invoice Build()
            {
                Invoice invoice = new Invoice 
                { 
                    Customer = this.customer, 
                    ContractDate = this.contractDate, 
                    ServiceContinuum = this.serviceContinuum, 
                    BaseFee = this.baseFee, 
                    ServiceFee = this.serviceFee 
                };
 
                return invoice;
 
            }
        }
    }

"You see", continued D.Eagol, "That's what you have accomplished:"

  • The Invoice's constructor is private - only the Builder can return an Invoice, through its Build method
  • The Builder's constructor receives the Invoice's required parameter: Customer
  • The Builder provides meaningful method names for eachof the Invoice's optional parameters and utilizes Fluent interface in order to provide a more readable form of setting those parameters
"And here, how the instantiation looks like:"


 Invoice.Builder invoiceBuilder = new Invoice.Builder(Customer.CustomerA);
            Invoice invoice = invoiceBuilder
                                    .SignedOn(Date("4/7/2010 08:00:00 PM"))
                                    .ServiceAgreementForPeriodOf(Days(30))
                                    .ServiceBaseFee(1000)
                                  .Build();

"Now it really shines!", finished D.Eagol, "What do you say G.Olum?"

"Give us that, D.eagol, my love... It's my birthday...and I wants it!", gurgled G.Olum.