Maverick Software Development
"Design By Use" Development
by Geoffrey Slinkerversion 1.6
March 25, 2006
April 22, 2005
July 1, 2005
July 25, 2005
August 23, 2005
Maverick Development |
Abstract
"Design by Use" development (DBU) improves team resource utilization, software design, software quality, and software maintenance through a set of proven industry methods that have been shown to work together synergistically.Introduction
Are you concerned with keeping your development staffed adequately tasked? Would you like to improve design quality by reducing coupling, improving cohesion, and communicating the domain model? Is the quality of your software important? Do you maximize the R.O.I. of your software by using the software for as many years as possible? If you answered no to any of these questions are you from another planet?As part of my career I have specialized in the rendering of concise solutions to problems. Whether the problem was to be solved with code or with a methodology I have always strived to take the problem that was presented, boil it down to the essence, and provide a solution. I have studied software engineering processes now for over 20 years. I have distilled the essence of what I feel are the most useful methods to use as a foundation to build a process that is efficient and improving.
I have recently thrown all of the traditional methodologies along with agile methodologies that I know into my soup pan and turned up the heat! Then I took the results and have been experimenting with them. It is like a soup that has been cooked in a big pot. You will taste all of the different ingredients if you try or you can ignore the ingredients and just enjoy the combined flavor.
This paper presents a methodology for development that can work as a subcomponent of any encompassing methodology and deliver results in the areas mentioned in the abstract.
Executive Summary
Design by Use (DBU) follows the basic steps:1) Create High Level Design
2) Identify systems and subsystems
3) Identify messages or calls between systems and subsystems
4) Use theses identified messages or calls to specify to each team what they should code and how the message will be made (the message/method signature).
For example: There are two subsystems identified, S1, and S2. There are two teams, T1 and T2. T1 is to write S1 and T2 is to write S2.
S1 calls into S2, let's suppose the message is GetStuffFromS2.
Team 1 writes an Usage Example:
void Main() { MyData data = GetStuffFromS2(1); assert(data.value == 3); }
Team 1 gives this Usage Example to Team 2. T2 uses this to direct what they will develop and the order of development will natually flow from this point. So T2 implements GetStuffFromS2 in their subsystem S2 and they notify T1 when it is available (or if they are using unit tests they will know GetSTuffFromS2 is available when the build light goes green for that test).
S1 is immediately integrated with S2 and even better, it is integrated in a great way, the way the user wants to use the system.
DBU is beyond Test Driven Development (TDD) and Design by Contract (DbC). DBU is concerned with large software systems, multiple teams, coordination, and integration. TDD is a code design activity. DbC is a contract driven process based around invariants, pre-conditions, and post-conditions.
The Approach
The "Why":The problem is keeping all software development teams working and not waiting.
The "When":
When a large software system is being developed with many systems and subsystems and each of these is developed by different teams.
The "How":
The high level design of the system is done with any method that the company agrees upon. A custom diagramming language such as a simplified UML works fine. Subsystems are identified and teams are assigned to each subsystem.The data flows, invocations, calls, dependencies, or whatever you want to call them are identified at the subsystem boundaries. For example, "My subscription subsystem will need to ask the pricing subsystem for a price given a product Id."
At this point the development pump must be primed. All of the teams have their requirements. It doesn't matter if you use Use Cases or User Stories or another way to specify requirements. In an agile methodology this would be one of the last activities of Release Planning. The teams meet together as one and the functionality that will be delivered during this release is decided upon. Each system and subsystem that are participating in this release are identified. If there are systems that are not part of this release the teams responsible for them will not be needed and can work on other systems. Each call into an external system or subsystem that had been identified are listed. The "caller" starts out by writing a usage example. The usage examples are created for the calls identified from the high level design (calls that cross system boundaries) . The usage examples that call into subsystems other than your own are delivered to the proper team. In all software development there are the upstream/downstream situations. (I do not go into the perils of being downstream in this paper.) All of the usage examples will be used to drive the design and development of what's inside a subsystem. This is the low-level design (code) and includes the details not covered in the high-level design (possibly UML).
When all of the usage examples for the subsystem boundaries are identified that can be the teams can coordinate and prioritize the remaining development tasks. This gives a clear picture of who is doing what and how they should do it. There is no waiting because the usage example has with it sample data to drive the call. Therefore no one is waiting for someone upstream to finally call their code.
The usage examples test post conditions after the call into the subsystem. The implementation in the subsystem checks preconditions, invariants, and post conditions. If you taste the flavor of design by contract in this soup you are correct.
From what has been stated so far in the DBU approach the design has presented the overall domain, has identified sub-domains, has exposed the boundaries and entry points, and has allowed for efficient use of resources and scheduling.
Quality is improved through the approach as thus far stated. By having usage examples that drive development integration has already been addressed. Instead of "integrate often" this approach is "integrate immediately". As soon as a component is finished and satisfies the usage example it can be used by consumers. Through this approach the design is very cohesive because sufficient consideration was given to the domain model and the boundary points. The idea that cohesive designs and correct models just emerge from some primordial ooze is a misunderstanding. Instead it comes from the application of knowledge, consideration, experimentation, and application. This approach uses these four factors (knowledge, consideration, experimentation, and application) continuously.
With the usage examples defined and expectations set there is no need for teams to reinvent the wheel. To often teams will not use others code because the quality is suspect or the delivery date is unknown or the solution is a near fit but not a good fit. Eliminating these concerns is just as much a social problem as well as a procedural one. The approach specified here addresses the procedure.
So far improvements in resource utilization, design, and quality have been described. Finally this approach improves the R.O.I. through facilitating software maintenance. By running the usage examples a developer can isolate a piece of code and step through it to understand a legacy system. Often documentation is lost or out of synchronization with the software and a developer just wants to know what the system currently does. When modifying an existing system it is essential to know that changes have not affected the system in undesired ways. By running the usage examples in the role of a regression test the changes can be verified that the effects of the change are isolated to the desired areas. Since each system call into another system is specified the designer's and programmer's intent is specified. This specification can be used to replace entire systems and subsystems. Suppose we want to replace the pricing subsystem our subscription subsystem uses. The usage examples shows exactly where to make the incision.
Summary
1) Improves team resource utilization
a. Through specifying interfaces through usage example one team can clearly specify to another team the functionality that is desired. This is immediate integration. Through this there is less rework during integration that traditionally would come at the end of the development phase.
2) Improves quality
a. Eliminates issues with late integration
b. Builds confidence in subsystems and reduces "silo-ing" and duplicated code.
3) Improves designb. Builds confidence in subsystems and reduces "silo-ing" and duplicated code.
a. Rapidly defines interfaces and exposed entry points.
b. Reduces coupling.
c. Increases cohesion.
b. Reduces coupling.
c. Increases cohesion.
i. through communication
ii. through the dissemination of domain concepts
iii. through the unification of domain models
4) Improves software maintenanceii. through the dissemination of domain concepts
iii. through the unification of domain models
a. By running the usage examples as a regression test one can step through code that is not documented or that is not behaving according to documentation.
b. Usage examples are ran after every modification (small sets of changes) to verify that the changes have not caused problems because of unknown side effects and couplings.
b. Usage examples are ran after every modification (small sets of changes) to verify that the changes have not caused problems because of unknown side effects and couplings.
Conclusion
"Design by Use" development (DBU) improves team resource utilization, software design, software quality, and software maintenance through a set of proven industry methods that have been shown to work together synergistically.Complex software with many systems and subsystems which are developed by several teams of developers is difficult to schedule the order each part will be developed. Integration is often done late. Immediate integration is the key activity.
To flesh out more of the entire process please read "Reporting for Accountability".
No comments:
Post a Comment