As we develop software, it is common to design before we code. On average, I have found that the more time between when design occurs and the actual implementation is developed, the more unexpected detrimental effects surface. A common reason for design problems when integrating external dependencies into a project is that the project team was using what was available from the integration dependency instead of deciding on what they needed and mapping that to a solution. Design by contract made a step in this direction by supplying the idea of a contract between a supplier and client.
Over the past few years, we as an industry have started turning a corner towards a more business driven approach to software development through Agile values, principles, and methods. As we develop software we must take the same business driven approach to design. As anybody who has used Test-Driven Development (TDD) knows, design is a continual part of our development cycle. We design our software through the creation of well defined criteria (tests) and refactor our code mercilously to an acceptable design. Another interesting aspect to TDD is the YAGNI (You Ain’t Gonna Need It) principle which states that one should never add functionality until it is necessary. Instead of designing towards the use of an external dependency we should only integrate upon need. This is why I have coined Need-Driven Design as the business driven approach to software integration design. Need-Driven Design has the following steps:
- Only add external dependencies to your project when the value outweighs the integration costs
- Integrate external dependencies into your project at the last reasonable moment
- Define a well defined interface for interactions with systems which may be out of your project’s full control
- Develop executable criteria for expected interactions with the an interface implementation
- Create integration criteria which meets the expected interface intent and integrates with the external system dependencies
An example of this approach to software design is a project which needs data from an exposed web service. In this example, the web service returns an XML represntation of a customer with the following information:
- Customer Name
- Job Title
- Phone Number
The business has informed us that this external system is the most up to date view of our customers and therefore must be used by the application. This satisfies step 1 of our Need-Driven Design approach. Next, we should develop enough code to know that we need to interact with the external system and where that interaction is going to occur in our application which satisfies step 2. The business case for this example is that our end users must see the customer name, company they work for, and a phone number to reach them at. For this business case, we define an interface that returns only the customer name, company, and phone number which as you can see is less information than the web service returns. After defining the interface to satisfy step 3, we should create executable criteria for interactions with the implementation of this interface and our application. We can use mock objects to do this through the setting of expectations across multiple tests with variable response message signatures. This may lead into the development of validation functions, exception handling, and defined results packaging. This executable criteria from step 4 can now be used as the intent for consuming the exposed web service. Automated integration tests should be developed as criteria for implementing the defined interface for external web service consumption. This will not be a replica of the interface tests defined using mock objects. These tests should make sure that the consumption of the external system dependency maintains the integrity of the defined interface intent described in those tests.
By driving our integration strategies through the steps defined in Need-Driven Design we can decrease integration costs, reduce coupling to external dependencies, and define business driven intent into our applications. Integration can be a headache in development, design, testing, deployment, and operations. Through the steps in Need-Driven Design, we can assure those that pay for maintenance of these integrations get the value they need.