by Geoffrey Slinker
version 1.6
March 25, 2006
April 22, 2005
July 1, 2005
July 25, 2005
August 23, 2005
Accesses: ![]() |
| Maverick Development |
"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.
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.
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 "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.
"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".