At its core, process agility is all about continuous learning, fast feedback loops, and fluid changeability. Unlike pre-agile methods (and even some currently purported agile methods), which assume that people are forward-marching automatons who “better not make mistakes” and must defend the fort against all external forces of change, process agility accommodates the mental limitations and fallibility of REAL human beings.
Having said that, how agile do you think a process which includes a sign-off list like this is:
Imagine that whatever has been “approved” by a ceremonial sheet like this is post-facto found to be laced with errors, inconsistencies, and ambiguities due to natural human fallibility. How likely do you think that finders-of-mistakes will publicly point them out, demand a production line stoppage to fix the turds, and suggest that the director-manager-lead approval gauntlet be traversed again? Conversely, how likely do you think that finders-of-mistakes will say “f*ck-it!“, keep their mouths shut, and keep goose-stepping forward with the herd.
Fear not, dear reader. BD00 has a simple and clean solution to the director-manager-lead approval gauntlet problem. Collapse the list of approvers down to one – the only one that matters:
Please submit your plans for BD00 approval in the comments section. As his executive assistant, I can assure you that his stamp/no-stamp decision will be made pronto. However, don’t call us. We’ll call you.
Induction is the process of synthesizing a generalization from a set of particulars; a mental step up in abstraction from many-to-one.
Deduction is the process of decomposing one generalization into a set of particulars; a mental step down in abstraction from one to many.
A good personal software design process requires iterative execution of both types of sub-processes; with liberal doses of random reflection thrown into the timeline just to muck things up enough so that you can never fully retrace your steps. It’s pure alchemy!
“A distributed system is one in which the failure of a computer you didn’t even know existed can render your own computer unusable.” – Leslie Lamport
I’ve always loved that quote. But that’s only one reason why I was overjoyed when I stumbled upon this article written by Turing award winner Leslie Lamport: “Why We Should Build Software Like We Build Houses”. The other reason is that what he wrote is old school, but still relevant in many contexts:
Most programmers regard anything that doesn’t generate code to be a waste of time. Thinking doesn’t generate code, and writing code without thinking is a recipe for bad code. Before we start to write any piece of code, we should understand what that code is supposed to do. Understanding requires thinking, and thinking is hard. – Leslie Lamport
I recently modified some code I hadn’t written to add one tiny feature to a program. Doing that required understanding an interface. It took me over a day with a debugger to find out what I needed to know about the interface — something that would have taken five minutes with a spec. To avoid introducing bugs, I had to understand the consequences of every change I made. The absence of specs made that extremely difficult. Not wanting to find and read thousands of lines of code that might be affected, I spent days figuring out how to change as little of the existing code as possible. In the end, it took me over a week to add or modify 180 lines of code. And this was for a very minor change to the program. – Leslie Lamport
New age software gurus and hard-core agilistas have always condescendingly trashed the “building a house” and “building a bridge” metaphors for software development. The reasoning is that houses and bridges are made of hard-to-reconfigure atoms, whilst software is forged from simple-to-reconfigure bits. Well, yeah, that’s true, but… size matters.
In small systems, if you discover you made a big mistake three quarters of the way through the project, you can rewrite the whole shebang in short order without having to bend metal or cut wood. But as software systems get larger, at some point the “rewrite-from-scratch” strategy breaks down – and often spectacularly. Without house-like blueprints or bridge-like schema to consult, finding and reasoning about and fixing mistakes can be close to impossible – regardless of which state-of-the-art process you’re using.
Take a look at these three state machine models for intimately developing a chunk of functionally cohesive software:
The key distinguishing feature of the two machines on the right from the pure TDD machine on the left is that some level of design is the initial driver, informer, of the subsequent coding/testing development process. Note that all three methods contain feedback transitions triggered by “learning as we go” events.
In my understanding of TDD, no time is “wasted” upfront thinking about, or capturing, design data at any level of granularity. The pithy mandate from the TDD gods is “red-green-refactor” or die. The design bubbles up solely from the testing/coding cycle in a zen-like flow of intelligence.
Personally, I work in accordance with the DDT model. How about you? For newbies who were solely taught, and only know how to do, TDD, have you ever thought about trying the “traditional” DDT way?
BTW, I learned, tried, and then rejected, TDD as my personal process from “Unit Test Frameworks“. Except for the parts on TDD, it’s a terrific book for learning about unit testing.
Since “design” is an intimately personal process, whatever works for you is fine by BD00. But just because it’s “newer” and has a lot of rabid fan-boys promoting it (including some big and famous consultants), don’t auto-assume TDD is da bomb.
Design is an intimate act of communication between the creator and the created. – Unknown
It seems to have taken awhile, but people are finally speaking out strongly against the papal infallibility of the TDD high priesthood. Michał Bartyzel, Andrew Binstock, and Jim Coplien (who actually has been speaking out against it for years) are a few of these blasphemous heretics.
Any of the “driven” techniques can work, but to insinuate that they are the “only way(s)” to build superior products is arrogant, hubristic, and plain stupid. In mentally challenging, knowledge-intensive work, people have, and always will have, different ways of creating beautiful products.
When I speak with adherents of test-driven development (TDD) in particular, there is a seeming non-comprehension that truly excellent, reliable code was ever developed prior to the advent of this one practice. I sense their view that the long history of code that put man on the moon, ran phone switches, airline reservation systems, and electric grids was all the result of luck or unique talents, rather than a function of careful discipline and development rigor. – Andrew Binstock
“…these promises were not supported by unambiguous and verifiable data in early years of TDD. The enthusiastic reaction to TDD came first and then some (selective?) measurements were made to verify its promises. – Michał Bartyzel
“If you find your testers (or yourself) splitting up functions to support the testing process, you’re destroying your system architecture and code comprehension along with it. Test at a coarser level of granularity.” – Jim Coplien
Personally, I start sketching out quite a bit of a design upfront (OMG!!!!!) in “bent” UML (OMG, OMG!!!!!) prior to writing a single line of code. I then start writing the code and I subsequently write/run some selective unit tests on that code. In summary, I dynamically build/test the code base toward the coarse, “upfront” design as I go. Of course, according to the high priests of TDD, I’m unprofessional and I obviously produce inferior designs and bug-ridden, unmaintainable code. Gosh, it sux to be me.
For more details on how I develop software, check out this four year old post: PAYGO II. And no, I’m not promoting it as better than your personal process or, gasp, the unassailable holy grail of software development… TDD! No books, magazine articles, conference talks, or two-day certification courses are planned. It’s simply better for me, and perhaps only me.
I get e-mails like this all the time:
In four fun-filled days, and for a measly $2000, you too can become a full fledged, CERTIFIED Scrum Master AND Scrum Product Owner. That’s all it takes to catapult you to the top of the software development world. W00t!
Why spend weeks or months struggling to learn a new language, API, framework, technology, or tool when you can nail this trifecta: leapfrog over your programmer peers, break into the highly coveted guild of management, and prefix a big fat “C” to your title? Quick, quick, jump on the bandwagon before it’s too late. Don’t get left behind!
“A person is smart, people are stupid.” – Agent K (Men in Black)
I’m forever fascinated by how large groups of bright and well-meaning individuals often behave so dysfunctionally as a “whole“. How can that be? It’s because the individual “parts” of an organization don’t determine the behavior of the whole. It’s the part-to-part interactions enabled by, and (more importantly) disabled by, the structure of an organization that determines system behavior. By default, hierarchically structured orgs suppress collaborative communications in the horizontal dimension while catalyzing top down command and control communications in the vertical dimension.
In the vertical dimension, the fact that bosses get to unconditionally decide on how to divvy out tasks and rewards to their “subordinates” below ensures that the dweebs in the lower tiers will do whatever the boss wants them to do with little, if any, frictional blowback. In the horizontal dimension, crucial information can be withheld and collaborative communication suppressed because of peer-to-peer competition for the limited number of coveted slots available upstairs in the ever narrowing pyramid.