Archive
Big Design, But Not All Upfront
When not ranting and raving on this blawg about “great injustices” (LOL) that I perceive are keeping the world from becoming a better place, I design, write, and test real-time radar system software for a living. I use the UML before, during, and after coding to capture, expose, and reason about my software designs. The UML artifacts I concoct serve as a high level coding road map for me; and a communication tool for subject matter experts (in my case, radar system engineers) who don’t know how to (or care to) read C++ code but are keenly interested in how I map their domain-specific requirements/designs into an implementable software design.
I’m not a UML language lawyer and I never intend to be one. Luckily, I’m not forced to use a formal UML-centric tool to generate/evolve my “bent” UML designs (see what I mean by “bent” UML here: Bend It Like Fowler). I simply use MSFT Visio to freely splat symbols and connections on an e-canvas in any way I see fit. Thus, I’m unencumbered by a nanny tool telling me I’m syntactically/semantically “wrong!” and rudely interrupting my thought flow every five minutes.
The 2nd graphic below illustrates an example of one of my typical class diagrams. It models a small, logically cohesive cluster of cooperating classes that represent the “transmit timeline” functionality embedded within a larger “scheduler” component. The scheduler component itself is embedded within yet another, larger scale component composed of a complex amalgam of cooperating hardware and software components; the radar itself.
When fully developed and tested, the radar will be fielded within a hostile environment where it will (hopefully) perform its noble mission of detecting and tracking aircraft in the midst of random noise, unwanted clutter reflections, cleverly uncooperative “enemy” pilots, and atmospheric attenuation/distortion. But I digress, so let me get back to the original intent of this post, which I think has something to do with how and why I use the UML.
The radar transmit timeline is where other necessarily closely coupled scheduler sub-components add/insert commands that tell the radar hardware what to do and when to do it; sometime in the future relative to “now“. As the radar rotates and fires its sophisticated, radio frequency pulse trains out into the ether looking for targets, the scheduler is always “thinking” a few steps ahead of where the antenna beam is currently pointing. The scheduler relentlessly fills the TxTimeline in real time with beam-specific commands. It issues those commands to the hardware early enough for the hardware to be able to queue, setup, and execute the minute transmit details when the antenna arrives at the desired command point. Geeze! I’m digressing yet again off the UML path, so lemme try once more to get back to what I originally wanted to ramble about.
Being an unapologetic UML bender, and not a fan of analysis-paralysis, I never attempt to meticulously show every class attribute, operation, or association on a design diagram. I weave in non-UML symbology as I see fit and I show only those elements I deem important for creating a shared understanding between myself and other interested parties. After all, some low level attributes/operations/classes/associations will “go away” as my learning unfolds and others will “emerge” during coding anyway, so why waste the time?
Notice the “revision number” in the lower right hand corner of the above class diagram. It hints that I continuously keep the diagram in sync with the code as I write it. In fact, I keep the applicable diagram(s) open right next to my code editor as I hack away. As a PAYGO practitioner, I bounce back and forth between code & UML artifacts whenever I want to.
The UML sequence diagram below depicts a visualization of the participatory role of the TxTimeline object in a larger system context comprised of other peer objects within the scheduler. For fear of unethically disclosing intellectual property, I’m not gonna walk through a textual explanation of the operational behavior of the scheduler component as “a whole“. The purpose of presenting the sequence diagram is simply to show you a real case example that “one diagram is not enough” for me to capture the design of any software component containing a substantial amount of “essential complexity“. As a matter of fact, at this current moment in time, I have generated a set of 7+ leveled and balanced class/sequence/activity diagrams to steer my coding effort. I always start coding/testing with class skeletons and I iteratively add muscles/tendons/ligaments/organs to the Frankensteinian beast over time.
In this post, I opened up my trench coat and showed you my… attempted to share with you an intimate glimpse into the way I personally design & develop software. In my process, the design is not done “all upfront“, but a purely subjective mix of mostly high and low level details is indeed created upfront. I think of it as “Big Design, But Not All Upfront“.
Despite what some code-centric, design-agnostic, software development processes advocate, in my mind, it’s not just about the code. The code is simply the lowest level, most concrete, model of the solution. The practices of design generation/capture and code slinging/testing in my world are intimately and inextricably coupled. I’m not smart enough to go directly to code from a user story, a one-liner work backlog entry, a whiteboard doodle, or a set of casual, undocumented, face-to-face conversations. In my domain, real-time surveillance radar systems, expressing and capturing a fair amount of formal detail is (rightly) required up front. So, screw you to any and all NoUML, no-documentation, jihadists who happen to stumble upon this post. 🙂
Monopolistic Providers
In search of economies of scale, centrally planned and controlled economies in nations and corporations tend to create monopolistic providers of goods and services. For example, in corporations, accounting, personnel, and R&D departments are usually deliberately organized as subsidized monopolies. They are subsidized in the sense that the users of their products or services do not pay for them directly; the supplying units are supported financially by funds that are allocated to them from above. The pool from which these funds are drawn is filled by a “tax” allocated from above to the units served. Monopolistic units that are subsidized are generally insensitive and unresponsive to the users of their services, but they are sensitive and responsive to the desires of the higher-level units that subsidize them. These higher level units are even more removed from the units served than the serving units. As a result, they are often unaware of, or unresponsive to, the needs and desires of the internal users of monopolistically provided goods and services. – Russell Ackoff (Ackoff’s Best: His Classic Writings on Management)
OK, time to practice my “bent” UML modeling skills and test your understanding with the class and sequence diagram pair below. The class diagram provides a structural view of a fictional Ackoffian system. The sequence diagram steps through an amalgam of behaviors in a world where monopolies rule. Any questions, comments, critiques, accolades, WTFs?
Empty Lifeline
Check out this “bent” pair of UML sequence diagrams:
The system on the right is pretty loosely coupled, no?
To Call, Or To Be Called. THAT Is The Question.
Except for GUIs, I prefer not to use frameworks for application software development. I simply don’t like to be the controllee. I like to be the controller; to be on top so to speak. I don’t like to be called; I’d rather call.
The UML figure below shows a simple class diagram and sequence diagram pair that illustrate how a typical framework and an application interact. On initialization, your code has to install a bunch of CallBack (CB) functions or objects into the framework. After initialization, your code then waits to be called by the framework with information on Events (E) that you’re interested in processing. You’re code is subservient to the Framework Gods.
After object oriented inheritance and programming by difference, frameworks were supposed to be the next silver bullet in software reuse. Well crafted, niche-based frameworks have their place of course, but they’re not the rage they once were in the 90s. A problem with frameworks, especially homegrown ones, is that in order to be all things to all people, they are often bloated beyond recognition and require steep learning curves. They also often place too much constraint on application developers while at the same time not providing necessary low level functionality that the application developer ends up having to write him/herself. Finding out what you can and can’t do under the “inverted control” structure of a framework is often an exercise in frustration. On the other hand, a framework imposes order and consistency across the set of applications written to conform to it’s operating rules; a boon to keeping maintenance costs down.
The alternative to a framework is a set of interrelated, but not too closely coupled, application domain libraries that the programmer (that’s you and me) can choose from. The UML class and sequence diagram pair below shows how application code interacts with a set of needed and wanted support libraries. Notice who’s on top.
How about you? Do you like to be on top? What has been your experience working with non-GUI application frameworks? How about system-wide frameworks like CORBA or J2EE?
A Change In Funding Source
The figure below shows a dorkily simplistic UML sequence diagram example of the provision of service from a support group (e.g. purchasing, quality assurance, configuration management) to a product development group within a CCH patriarchy. During product development, the team aperiodically requires and requests help from one or more corpo groups who’s raison d’etre is to provide timely support to those who need it. Depending on who’s leading the support group, the service it provides can be highly responsive and of high quality. However, since the standard “system” setup in all CCH corpocracies is as shown in the sequence diagram below, the likelihood of that being true is low. That’s because in centralized patriarchies, all budgets, salaries, and token rewards are doled out by the sugar daddys perched at the top of the pyramid. On the way down, the middlemen in the path take a cut out of the booty for, uh, the added-value “leadership” they provide to those on the next lower rung in the ladder.
In exchange for their yearly/quarterly investments in the lower layers of the caste system, the dudes in the penthouse require periodic status reports (which they can’t understand and which are usually cleverly disguised camouflage) that show progress toward wealth creation from the DICs below.
Since their bread is buttered from the top and not their direct customers, the natural tendency of support groups is to blow off their customers’ needs and concentrate on maximizing their compensation from the top. They do this, either consciously or unconsciously, by adding complexity to the system in the form of Byzantinian procedural labyrinths for customers to follow to show how indispensable they are to the b’ness. As a result, their responsiveness decreases and their customers experience an increase in frustration from shoddily late service.
So how does one fix the standard, dysfunctional, centralized, CCH setup? Check out and ponder the sequence diagram below for a possible attempt at undoing the dysfunctional mess. Can it work? Why, or why not?
By definition, if everyone is doing industry best practice, it’s not best practice. It’s average practice.