Sunarcher

Between Tick and TockThe Occasional Blog of Jamie Z Fox

11.25.2007

Code Is Fact; Design Is Hope

Software is people's way of having machines do their bidding. Learning to command them is a thrill of the highest intellectual order. Developing software engages the mind in an exquisite artistry of creativity, consummate attention to detail, technical acumen, and new code written afresh with insight. Someplace between the spark of inspiration and the release of software, a design typically occurs: sometimes many. Designs are human creations and they are fun to make. They are ideas on a path to become realities. When we're lucky, the idea and reality match. Sometimes when we're more lucky, they don't.

Software is written by people who have banded together in an organization where the work gets done. Our work is intricate and hard. Developers on a payroll are expected to play well with others. In the workplace, the mind's eye shifts from imagining the individual artistry of a lone, pixel-lit wizard at midnight, to that of a work group immersed in their email, white boards, fluorescents, cubicles, meetings, budgets, plans, designs, and codebase. It's an environment of social dynamics: one permeated with ideas, conversations, misunderstandings, disagreements, personalities, politics, resource contention, celebrations, and so on. We inhabit a complicated and complex world. Entropy characterizes all human endeavors. Everything human churns with some level of chaos as our tasks and circumstances continually change. We thrash, in degrees unbeknownst to ourselves. Yet, we get a lot done -- software has become the foundation of modern society.

Whenever groups form from people coming together, chaos looms. Opportunities abound for control and anarchy, mindless management and turmoil, happy people and sad people, inspired teams and resigned individuals. The quality of the outcome is fundamentally enabled and constrained by the collaboration amongst the brainage available to tackle a task and the climate in which they engage. The organizations in which we develop software continually change, as do myriad external forces of technological advance, dynamic market conditions, and workforce globalization. Things change, not all for the better. Vigilance is vital; adaptability a necessity; and a clear understanding of the current circumstances a must.

Forethought is a Righteous Thing. It'd be silly to not carefully consider the situation, to ignore available skills, or to avoid what's been learned in similar circumstances. The future isn't completely uncertain -- some measure of planning would be prudent. Not all advantageous notions spring forth in an initial burst of insight. Writing code can offer a compelling sense of "process gratification" that arises from the simple act of doing it. This force can be so powerful that there's wisdom in holding off a bit and reflecting on what needs to be done. But how much design? How granular? From some points of view, a few sketches are sufficient. Other perspectives advocate that every anticipated activity should be planned and scheduled in precise detail. The notion of a "design" spans both these extremes, irrespective of the underlying presumptions of the future (dynamic or fixed, respectively).

Designs bring structure to the chaos. They can be illuminating intellectual conceptions. A design seeks to guide developers to create a particular software release formed from current ideas. It is an anticipated solution, often to a murky and ambiguous situation. It's a best guess as seen from the perspective of today. A design presents a hope about a future, a desired outcome as seen from long before. Sometimes designs are fluid, open to opportunity and serendipity. Other times they're not -- especially in a bureaucratic workplace. In such situations designs often include plans that specify what gets done when by whom -- a frozen design to be executed by worker-bees. Sometimes this plan reaches years into the future. Such circumstances are an evident absurdity to any but the most naive (or Machiavellian) observer. The latter is particularly pernicious in organizations whose culture rewards false precision over accuracy, posturing, and resource contention. It's the old human game of power vs. performance, all over again.

Designs are snapshots in time, an illusion of how things were (as soon as the notion occurred, it began to age). In such an unchanging world, nothing is learned along the way; insights can be simply dismissed. Neither optimizations nor new algorithms ever occur, so all can be safely ignored. A frozen design deems code to be written based solely on what is known today. What needs to be known is known; or is simple and straightforward to discern and recognize, or so some designers of the "expansive elaboration" persuasion would have us believe.

A frozen design becomes historic: ignorant of every tomorrow. All mismatch between design and outcome becomes a measure of waste, of muda. Irreplaceable time, priceless attention, and synergistic opportunities are all lost. Binding to a hope of tomorrow, instead of a fact of today, limits a design in equal measure. How dated is the design? That's a key question in assessing the value of a design, as are considerations of how fast things are changing. Circumstances will change, designs are anticipatory -- a planned solution. Designs are hope.

Pursuing a presumed perfect solution, based on old methods and known faulty understanding, is a fool's errand, made worse in circumstances known to be uncertain. The search space for the "best" solution is immense and could take eons to traverse; judgment criteria for comparing alternatives are subtle and time-consuming. Sometimes designs leave things open; other times they guess. If the guess becomes cast in a plan as received wisdom, waste is generated.

Elegant designs reflect brilliance, discernment, and innovativeness. When developers architect a test, a feature, a system, et cetera, their designs make manifest a particular weltanschauung by specifying certain categories, constants, classes, and relations amongst them. APIs, event systems, and protocols are likewise determined. Use cases are identified. These concepts and nomenclature become the parlance of the task; it's how people talk about the code to be written. It is what lingers on white board diagrams. The design, hopefully, reflects the best educated guess about a future, presuming things remain the same, yet leaving flexibility because things are sure to change.

Software evolves into a tangled morass of classes and calls with myriad parts and pipes and protocols; developers naturally get boggled. Software is so complex that a full understanding is elusive and prohibitively time-consuming to attain. Moreover, all algorithms have fundamental and opaque trade-offs in all but the most trivial circumstances. Alternative methods typically abound, and every single one brings unanticipated side-effects and induces cryptic corner-cases. Often, a full appreciation of a typical system eludes even the keenest of available minds. Complexity yields emergent phenomena. Yes, there is a ghost in the machine.

A design often announces a schedule and roster and thereby creates its own reality; its own ambiance of how to work gets done and who does it when. Today's design becomes outmoded to the degree that tomorrow differs from today. When designs are a prescriptive script of what to do and when to do it, a steady-state world in being presumed -- unchanging, stagnant in all aspects. This postulates a world where no one learns, opportunity isn't recognized, serendipity is ignored. A design is a conjured illusion of a hoped-for future. Where's the limit of prudence regarding to what extent should a design be accepted as the final authority? Optical illusions in freshman psychology warned us away from being too quick to grab onto any particular perception as being The Truth.

Some designs focus on the goal to be accomplished. Others focus on detailing how the code expected to accomplish the goal shall be written, which makes it a plan. At any point along the way, the code -- not the plan -- is the true measure of finite progress. Most groups typically have at least one or two "flat-earthers" either obsessed by conformance to plan or inherent belief in a frozen design (typically, these aren't people who have written much code).

Code will only do what the code can do. It doesn't make promises; it's not an existential argument of what might be done, as a design may well be. What the code does today is reality. It is what is known. The code is fact. The code does what the code does. By the time the code is completed, circumstances will have changed. The more rapidly that markets and industries change, the quicker that today's design will lag tomorrow's solutions. The longer from today, the greater will be that deviation, causing ever more muda. Designs show what is hoped of the code. Tests reveal the fact of what the code does.

All computer science and software engineering students are cautioned by Knuth: "premature optimization is the root of all evil." A design is by definition a premature optimization. After all, it is the initial, best estimation of the circumstances. It provides the start values for the mental model of what/when/how to bring the software into being. Blockages, dependencies, staff turnover, shifting business priorities, legal surprises, technical breakthroughs, and all those other everyday, work-a-day world realities, haven't yet crept in. But they will. While designs are necessary, they are by no means sufficient. And to the extent that circumstances are dynamic, any manner of sufficiency degrades yet more, in much greater degree for the frozen ones.

The code is an expanding body of facts regarding the design -- what is found to be true and what has been shown to be muda. By focusing on the code -- the fact -- true progress can be judged. A question of balance emerges: plan or adapt? Circumstances often change. Plans seldom keep pace. Lean and agile emphasize deferring commitment as long as possible and to avoid premature decisions. Effective software development becomes an ongoing activity of planning, and using the facts revealed by the code for continual course-correction. The design reflects hope; the code reveals fact. Progress continues until closure is attained.

Saffo's adage "never mistake a clear view for a short distance" intertwines with Eisenhower's wisdom "Plans are nothing; planning is everything." Together, they illuminate an essential notion -- a design is static. It's a plan. Designing, though, is dynamic. Adaptation occurs, people shift attention. People continually scan the horizon; opportunity arises; deliberations ensue while progressing on what appears to a promising path. Hopefully, learning along the way. A design fills one with hope; the code reflects hard facts. Seeing this isn't rocket surgery.

About Me

Previously Engineering Director at Google, cofounder of Niantic Labs, former manger of Google Maps, and related projects.
Advocate for lean principles and agile software development practices. Interests in software services, open source, mobile, organizational patterns, collaboration, HTML5, professional facilitation. I treasure this opportunity of working with brilliant and creative people, focusing on making the world a better place through information, while advancing the professional practice of how organizations can effectively create software of value for users. (The remarks herein are personal, not necessarily my employer's.) Formerly manager at Apple's Advanced Technology Group, Netscape, and Hewlett Packard Labs. Built two software startups, and managed numerous software and research projects at Michigan State and Rensselaer Polytechnic Institute. What a wild ride!