Just as the selection of materials has a substantive impact on the form and function of a structure, the concrete choices made by an enterprise have undeniable impacts on the form and function of the enterprise architecture. Creating products without regard to the tools and material in play as well as the characteristics of the business, results in a near continuous struggle to “over-come deficiencies”. Designs become complex, usually evidenced by a greater percentage of code gluing things together than code performing tasks required by the enterprise.
As an example, consider the inclusion of a null date in the account_opened_date column of a banks accounts main account table. The business, in this example a bank, might see a null account open date as an indication of an instance of account which has not yet been assigned to a customer. Or maybe a null integer in the account_balance column is used similarly. The account has been assigned but not yet received its initial deposit. Neither seems particularly harmful. Alas the danger lay just below the seemingly reasonable surface.
On a simple logical level, having a null integer or date is just wrong. A null account value is really an account worth zero dollars. The number zero equally represents the absence of value. The difference seems to be in the use of a null value to imply a state of the account. A null value is being equated with an unassigned account while a zero balance must have been assign to a customer. Combining the accounts value with the state of the account is at best ineffectual and at worst fails to provide a means to handle more than 2 states. How would the account value manage to represent suspended, closed, or transferred states?
From a design perspective, null values are appropriate for simple attributes but are unacceptable for important concepts or entities within a domain. While one might argue that the account balance is merely an attribute of the account, within the context of a banking application the account value is a primary concept of the business. The banks mission is to manage their customers monies … to track, charge, and (if you will forgive me the pun) account for the value entrusted to them. Allowing the account value to be null betrays the enterprises’ priorities.
Implementation carries similar symptoms. A banking institution is like to have multiple locations, departments, and security boundaries creating a complex distributed environment. Creating an account object which is serialized and marshaled across boundaries will fail if it implements non-null-able types with null values. Strongly typed systems, such as .Net, can be tricked into supporting this but it is difficult. Creating such an unnatural implementation tends to signal the beginning of a series battles between the tool and the enterprise. Instead, you can solve the root problem by;
· Creating an account with a default value of zero
· Separating state management from account value using a non null state attribute on the account object paired with an appropriately non-null column in the database.
· Implementing and defensive coding before and exception handlers after business logic to ensure safe, predicable access to calling code.
In the end, if it feels wrong or unbalanced. If it smells wrong, look for another way. Look to your tools and their most natural implementation and adjust your approach to leverage their inherent capabilities.