"If you fail to plan, you plan to fail"
- Vijay Dhameliya
These Design Bites have a fairly complete discussion about design and how it fits into the
software development process.
They present a nice concrete example of design evolution. There is an overview in
Design Bites Repository (scroll down) and details in all the bites after the
Structure bite.
What is Design?
Design encompasses defining concept, architecture, specification, and code structure, i.e., packages
and top-level objects.
Implementation, covers code creation, builds, testing, and deployment.
Of course, implementation requires design as well, but embedded in an already designed framework
with a single function focus.
This thread focuses on Design - the "What?", "Why?", and "So What?",
flushing out all conceptual details before the "How?" of implementation.
Why do we do it?
Design is intended to make intentional decisions about functionality and structure. If we start with
Implementation most of the decisions are accidental - it's that way because that's how we
built it.
Miss-targeted functionality or badly flawed structure may be beyond the capability of refactoring to
repair into an understandable, smoothly functioning implementation that meets user needs.
Refactoring can improve code maintainability and lubricate the operations and flows of a well
designed code base. It can support addition of small bits of compatible new functionality.
We do that all the time. But it cannot turn a big ball of mud into a sweetly smelling automaton.
So What?
Design helps us make decisions about complexity - functionality tradeoffs. It lets several minds
deliberate about user needs, performance, error handling, and attack footprints. Thus the basis for
decisions is not a very large complex code base that no one understands in its entirety, but instead
an enumerated set of user needs, clear structure, and named set of operations with responsibilities
attached.
Whoops! I thought the clients were going to populate our product's database with their
gigabytes of data. What do you mean that's our job!
Why Not?
For interesting important software products there are often "Why Not?"s to think about.
Some compelling features may be too expensive or too risky to attempt right now. Wait for Version 2.
Some features may charm the developers (see what we can do!) but be quite unimportant to users.
Skillfully handling the "Why?"s and "Why Not?"s is very likely to end successfully.
Design Bites:
This track starts with some specifics about design then focuses on that part dealing with software
structure. We pose a TextFinder project and use that as a basis for
exploring design activities.
It concludes with a very simple line-counting program that morphs from a monolith structure into
a data-flow with plugins. The line-counter is so simple the basic structure would suffice, but
that simplicity allows us to view structural differences between
monolithic,
factored,
data-flow,
type-erase, and
plugin implementations.
We discuss changes needed and compare the complexities of each.
The code above on the right is a snippet of Rust that implements a TypeErase Structure in the
line counting demo. In following bites we show all the Rust code for each version: monolithic,
factored, ... That code is
simple enough you will be able to follow even if you haven't used Rust yet
(you are likely to soon). It's also a great way to start learning Rust.
The DesignBites Repository gives a nice diagramatic overview of the
line-counter evolution, showing the structure of each with comments. Each bite in that sequence
shows structure and code.