I’m so bored with the work that I have at the office so I’ve taken on to reading quite a lot. I started with WF and at the same time started to read “Expert C# 2005 Business Objects” by Rockford Lhotka.
In the first chapter itself, while describing business objects, Lhotka states that “So, a business object that represents an invoice will include not only the data pertaining to the invoice, but also the logic to calculate taxes and amounts due. The object should understand how to post itself to a ledger, and how to perform other accounting tasks that are required. …” (Second Edition – Indian reprint : page 23)
An object should be an abstract representation of an entity or a concept. An object should represent one and only one entity or a concept. The contracts the object may have with other objects should be strictly in need to have basis.
Lhotka states the invoice should contain the logic to calculate taxes. Tax is a concept independent of an invoice entity. The responsibility of invoice with regards to tax is only to support the following two functionalities. 1.) Provide the taxable values 2.) Accept the tax values and use them against the taxable values. The invoice should not even know who does the tax calculation. It should expose the above mentioned functionality in terms of events and methods in the public interface.
Lets take a brief look at the problems that would arise when we implement the tax concept inside the invoice. To start with, it’s difficult to manage. Every time the tax calculation methods are changed, or a new tax is introduced you have to change the code in your invoice and test every functionality that’s associated with the invoice. Secondly, think of security, tax calculation is likely to require more security than the invoice as it could be accessing financial resources, and invoice is an object you are likely to pass around in your application. Not a good combination to go together. And thirdly, this implementation require the invoice object to have contracts with other objects which are required in tax calculation, which further complicates the manageability and possibly impact the structure of the application.
The second thing is, Lhotka states that the invoice object should understand how to post itself to a ledger. It is acceptable for an invoice to know which ledger it is posted in, but to be able to post itself to a ledger, it needs the knowledge of the ledger before it’s actually posted to it. Which is conceptually wrong. The invoice in Lhotka’s example is having a contract to a ledger before it actually gets posted to it. Secondly, posting an invoice to the ledger is neither a responsibility of an invoice nor of a ledger. An invoice should support being posted in a ledger and perhaps hold a reference to the ledger after it’s posted. And the ledger also should support posting invoices to it. But the responsibility of actually doing the act of posting is a responsibility of a third object.
Having such unnecessary contracts and responsibilities in objects causes manageability issues as well as design issues further on. For example if the action of posting an invoice to a ledger becomes more complicated in the future that requires modifications to the invoice class. And if these changes require access to other objects which the invoice by design does not have access to, it’s going to require some risky structural changes to the application as well.