I'm old enough to have lived through multiple technical cycles. When I started professionally CASE tools were the rage, and OS/2 was still a thing. I even worked on a mainframe for a bit. Then came Client-Server development (as popularized by Windows applications, as strictly speaking the 'client-server' pattern wasn't new). Then Java, the first-generation web applications with application servers and a myriad of Model View Controller frameworks. Then second-generation web development with more responsive JavaScript-based web applications that replicated many of the things that people liked about thick-client applications, and then some. Then big data broke on the scene, and then cloud architectures.
And concurrent to these technical advancements, new development methodologies kept appearing such as Lean, Safe, Scrum, Agile, Extreme Programming, RAD, JAD, Spiral, and so forth to better organize software efforts. As much as each new methodology heaped scorn upon each other, they all reserved the most contempt for Waterfall, the original methodology.
Planning, Analysis, Design, Construction, and Maintenance were for luddites, so the chorus went. Waterfall was the Hive 0.10 of its day - everybody loved hating it, everybody loved measuring itself against it. I not only remember Waterfall, but I remember E&Y's Navigator Methodology, which was a particular expression of Waterfall which contained even more liquid and fell from even greater heights. Navigator was delivered with yards of binders. Even as a career newbie, I thought that was a bit heavyweight.
But the fundamental weakness was that each new methodology tried to claim that it was possible to extract 10-pounds of output from a 5-pound bag of requirements, assuming that anyone had remembered to fill the bag in the first place, and that the contents hadn't shifted or expired since packing. And when the methodology du jour eventually lost its luster it invariably triggered a search for next one. The secret to unlimited productivity had to be somewhere, right?
"Happy families are all alike, every unhappy family is unhappy each in its own way."
—Leo Tolstoy (1828–1910)
Even those not intimately familiar with Russian literature have probably heard that opening line from Anna Karenina. One can replace "families" with "development teams" and the quote still applies. For example, imagine a development team with the following attributes:
It's a good list, right? So, do it. Seriously, just do that.
The hardest part of development is prioritization, and that is because humans are irrational and unpredictable. No development methodology will solve that. It's even more complex with multiple stakeholders, and especially multiple groups of stakeholders. The only way through is documenting needs with a forced-ranked priority and continually reminding people about what they are and what the corresponding statuses. Tools are helpful, but it's more about the communication and understanding around the tooling. The fanciest tool doesn't help if nobody believes what it's telling them.
Someone will inevitably cry, "but we need to be flexible!" And that's fine. It's ok to change priorities from time to time. But the relative priorities have to change too, and likewise the previous expectations that have been set. That is the hard part. No fair getting the previous expectations and the revised expectations; that's crazy talk. And again, that's a human problem. Don't forget that pulling the emergency brake on a software release train arbitrarily in the middle of a trip can land a development effort in a frozen, desolate location. Metaphorically speaking, of course.
Next, design software for the immediate prioritized use cases for the targeted timelines. There are a lot of important qualifiers in the prior sentence, such as "immediate", "prioritized", and "targeted timelines." Software designs always have context because software engineering is the art of tradeoffs. There are always tradeoffs. A tank isn't a sedan which isn't a racecar which isn't a truck, but they are all valid and effective forms of vehicles. We know from the classics such as Design Patterns (Gamma, et al.) and Refactoring (Fowler) that clean software design, configurability, and extensibility are important, but we also frequently forget that utilizing every single design pattern isn't the point. Guessing on use-cases — both functional and technical — almost always makes the outcome worse. Remember Knuth's famous quote: "premature optimization is the root of all evil." He figured that out a long time ago, and the software world has only gotten more complicated since then. Temptations and distractions are everywhere.
Pentagon Wars is an under-rated 1998 dramedy which depicted a fictionalized and satirized development of the Bradley Fighting Vehicle that was trying to be everything to everybody. This is loosely based on the very real and serious book Pentagon Wars by James Burton about weapons design and procurement. It's completely reasonable and expected to make design tradeoffs within what I would call "targeted use cases." Just be aware of when the tradeoffs become so big, they compromise the integrity and efficacy of said case. Engineering is both science and art, and no development methodology can solve that.
I was once at a company where somebody was a huge proponent of the Inversion Of Control pattern. This person was so in love with the pattern that the resulting code was difficult to understand and impossible to test. In fact, the unit tests were all configured to mock implementations to the point where nothing but fake code was being tested. This seems too ridiculous to be true, but it actually happened, and once the actual code was deployed to real customers, it was a disaster. I got pulled in to clean this up because each release required scads of emergency hotfixes. Don't become so enamored with a technical pattern or framework that it obscures one's vision from the real problems that were supposed to be addressed in the first place.
Then automate, automate, automate. Everything from the lowly build process, to unit tests, to environment setup, to deployment, to all forms of monitoring and metric collection. This is as obvious as the "the code should always work and be in a deployable state" mantra. Obvious, but not necessarily easy because it requires discipline to dedicate resources to automation — again, a human factor. The good news is that there have been many improvements and advances in frameworks and techniques in this area in the past few decades that can help. Pick up the Google SRE books for starters.
Figure out the most frequent release cycle that works with the user-base. This can vary by industry, and often technical aspects aren't the gating factor. Be able to release as quickly and easily as possible, with high quality.
Lastly, iterate. Keep going. Delivery velocity is life. The worst thing that can happen to any software product is a feast and famine cycle, and no development methodology can solve that. Maintaining momentum is arguably the hardest aspect, as continuous forward progress is utterly dependent on human factors such as portfolio priorities, resources, budgets, and other things such as how well your software is doing in the market. The difficulties of managing humans and money are as old as time. But it's not hopeless, just hard. So get on it.
I heard this at Strata Data Conference years ago: "if your software is successful, you are never done." Sage advice. Similarly, one can practically ensure a software solution not being successful with erratic delivery.
I've seen too many people effectively throw themselves in front of metaphorical trains for the love of a particular development methodology at the cost of overall project success. But a development methodology is just a "how" - it's not the goal. While no software success can ever be guaranteed, the best chances for development team happiness are to focus on common human factors such as stakeholder alignment, priorities, communication, and the discipline to keep driving forward. And the humility to accept that mistakes will inevitably be made and addressed in a future release, as soon as humanly possible.
As Tolstoy might say, Ни пу́ха, ни пера́, comrade.
Apache Hive was actually pretty good at what it did. SQL is just so darn useful, and to be able to use it over extremely large datasets was a breakthrough of its time. Hive also kept improving, but as I said earlier, most folks unfortunately only seem to want to talk about Hive 0.10, which was the version that most people were using when Hadoop went mainstream.
Doug Meil is a software architect at Ontada. He also founded the Cleveland Big Data Meetup in 2010.
Great post, but I would like to comment on the notion of Productivity. Of course, in a large team, there needs to be some predictable planning to avoid team members running idle while waiting on delivery by other team members. But the overall team productivity, especially with small teams, or single-person projects, which I have been doing a lot, is often pushed by management with no good reason. Just think of it. Why do we program computers? To increase productivity. Productivity is the purpose of software. Productivity as in the title of this post would be expressed in the total cost C dollars of the software. Productivity as the efficiency gain of P percent by N users over M years would be a total benefit B dollars. Software is made once, and typically used by many users over a long timeframe. It would be silly to create software if B would exceed C by only a few percent. Typically, B would be a huge multiple of C, say 10, or 100, or a million. In that light, why would we Search for Unlimited Productivity? Ok, wasted efforts should be avoided, but if someone wants to try something new or to otherwise improve the quality of the source code and thereby raising the production cost of the software somewhat, that should not be seen as a real problem. B would still outstrip C. Even extending the delivery of the software is relative. Users have worked inefficiently without the software for years, so what is the problem of waiting just a little longer? The only explanation I can think of is greed. If a company can earn money by releasing good software, it can make more money by releasing more such software. Often without raising the salaries of the developers. So are we developing software to make life more efficient, or to make our company more profitably?
A note on my comment. My comment was triggered by the title "The Search for Unlimited Productivity" above the blog post in the print edition of CACM of June 2021, p.10 (https://cacm.acm.org/magazines/2021/6/252830). I have some issues with too much focus on the supposed too low productivity of developers. This title is, however, not included on the online post here. Instead, the focus is on Happy Development Teams which makes for a great analysis.
Displaying all 2 comments