Posts categorized "Software Architecture"

September 10, 2007

Saint-Exupery on Engineering Elegance

"A designer knows he has achieved perfection not when there is nothing left to add, but when there is nothing left to take away."
                                - Antoine Saint-Exupery

August 28, 2007

Design principle from creator of first Wiki

“What is the simplest thing that could possibly work?”
                                                              - Ward Cunningham

July 14, 2007

Robust KISS

My father would remind me to KISS - Keep It Simple Stupid!

This often came up after I did something that wasn't simple but was stupid.

Dilbert's 9 rules for financial planning provide a great example of the KISS principle.

  1. Make a will.
  2. Pay off your credit cards.
  3. Get term life insurance if you have a family to support.
  4. Fund your 401(k) to the maximum.
  5. Fund your IRA to the maximum.
  6. Buy a house if you want to live in a house and you can afford it.
  7. Put six months’ expenses in a money market fund.
  8. Take whatever money is left over and invest 70% in a stock index fund and 30% in a bond fund through any discount broker and never touch it until retirement.
  9. If any of this confuses you, or you have something special going on (retirement, college planning, tax issues) hire a fee-based financial planner, not one who charges a percentage of your portfolio.
    From Dilbert and the Way of the Weasel

These are simple rules that provide excellent guidance in a very complex field.

For 95% of the people in the country following these rules would improve their personal finances and would save in aggregate $100 of billions.   

These rules may be the optimum strategy for only a fraction of us.  I don't claim they are optimal for 95%.  My claim is that for 95% of the population these rules will provide a better outcome compared to what they are actually doing today.

What lessons can we take from Dilbert's financial advice that will apply to growing a software venture?

A-list software ventures tend to be populated with smart driven type-A personalities.  Who are capable of dealing with a  high degree of complexity and who like to demonstrate that ability.  People who often are more skilled at coming up with clever insights than they are at communicating simple actionable ideas.  Many of these folks tend towards a paradoxical combination of perfectionism and a fire-fighting mentality.   Which in turn leads to strategies/policies/plans that are either

    A) truly baroque and complex in an effort to create fine-tuned optimization
    OR
    B) non-existent - replaced instead by reactive ad hoc  behavior

With this context I see 3 key lessons from Dilbert's fine example of KISS in action.

1) Simple is better than none

Most people don't have a financial plan of any kind.  Clearly following Dilbert's simple rules would make them much better off, even if it does not provide the best of all possible worlds.

Similarly, it is incredibly common for fast-growing software ventures to live without clearly stated and widely understood strategies, policies, and plans. 

In some of these cases a few individuals have in their heads sophisticated ideas for how to address these needs.  Ideas that don't translate easily to simple declarative statements that get immediately written down.  The expectation seems to be that through example and osmosis these sophisticated ideas will transfer to the rest of the team.

In other cases, everyone is too busy reacting, firefighting, and addressing the 'obvious' urgent needs to bother writing down specific plans or practices.

In other cases, the desire to create a very elaborate and complete plan leads to  a long planning cycle, so that many such cycles are started but none are every completed before they are interrupted. This is one reason why striving for a truly complete specification can be the wrong thing to do a simple spec that is up to date and conveys critical info is better than striving for a 'complete' spec and in effect living with none.

In all cases, it would be better to write down, clearly communicate, and then consistently live by some simple plan than to live without any at all.

2) Communication and execution matter more than cleverness and optimization

When it comes to personal finance many people do too much rather than too little.  People tend to overestimate their ability to optimize their financial results through cleverness and activity.  They tend to underestimate the value of simplicity, consistency, and low-costs.  This is why almost everyone who actively trades stocks does worse than if they just paid credit cards and then invested in a cross section of index funds. 

Similarly at software ventures we tend to use our cleverness to try and get the best possible results through creation of a complicated plan.  We tend to underestimate the value of simplicity.  Simple plans are easier to communicate, easier to execute, and easier to adjust as you get new data. 

These benefits from simplicity apply both in business planning and to software design.  The most elegant technical improvements often come when we innovate via simplification.

One clever person with an intricate vision of how all the pieces fit together, isn't enough to make a team succeed. Coming up with a simple approach that can be effectively communicated to everyone is a mark of true understanding.   

As Pooh pointed out in the Tao of Pooh:

"Rabbit's clever," said Pooh thoughtfully.
"Yes,"said Piglet, "Rabbit's clever."
"And he has Brain."
"Yes," said Piglet, "Rabbit has Brain."
There was a long silence.
"I suppose," said Pooh, "that that's why he never understands anything."

Lots of folks at software ventures are like Rabbit.  They show off their cleverness with intricate plans that they never get everyone to understand and that are impossible for mere mortals to execute.  When what is really required to get an effective common understanding is simplicity.

3) Robustness matters

Of course not all simple plans are created equal.  Simple by itself does not guarantee success. The plan needs to be simple and effective.

One measure of effectiveness is robustness.  Wikipedia has a nice definition:

Robustness is the quality of being able to withstand stresses, pressures, or changes in procedure or circumstance. A system, organism or design may be said to be "robust" if it is capable of coping well with variations (sometimes unpredictable variations) in its operating environment with minimal damage, alteration or loss of functionality.

Dilbert's financial plan seems robust to me and that is a very good thing.

Simplicity often improves robustness, as it is easier for a simple system to adapt to changing circumstances.

However, it is possible to go too far.  As we strive for simplicity in our software designs and business plans, we don't want to make a plan that will only work in our immediate circumstances.  We want to create something that is "as simple as possible but no simpler" and one good measure of that is the likely robustness of that plan in the face of a changing environment.

                                                                               copyright 2007 Kerry Champion

March 27, 2007

What Do Supreme Court Justices And Software Architects Have In Common?

What do Supreme Court Justices and Software Architects have in common?  More than you might think.  Here are some common characteristics:

  • Freakish intellectual ability is common among the most successful and is highly admired within the profession
  • Self-confidence in your opinions and analytic abilities is a must
  • Both deal with very complicated and demanding problems that never have a single obvious answer and almost never have an answer that is "provably" better than all others
  • In both professions success in the early stages of your career requires concentrated independent work
  • Both frequently have strong philosophies that they believe in passionately (in one case a judicial philosophy in the other a design philosophy)
  • Both highly value elegance and consistency

Therefore it is not too surprising that you see some common behavior patterns across the two very different jobs.

Jeffery Rosen had an excellent article in Atlantic Monthly recently where he talked at some length about what behaviors distinguish more effective and less effective justices. 

This is perhaps an oversimplification, but I took the following away from the article.   

Two distinct archetypes seen on the court are:

1) If you are an Argumentative Academic you will

  • Independently develop the most elegant and compelling analysis of the problem and define the "answer" to be implemented. 
  • Make sure that analysis is consistent with your own previous arguments and writings.
  • Make sure the proposed answer is consistent with your own philosophy.
  • Bring this already formed result to the discussion with your team mates. 
  • In your own mind see this discussion as an argument to be won or lost.  Fight to the death to make sure you win the argument.
  • If by chance you lose the argument, don't try to help craft a better final result rather register your dissent and go looking for another  problem to work on.
  • See your job as "winning the argument" in favor of your independently formed judgment of the best answer

2) If you are a Result-Oriented Realist you will

  • See your job as creating great results (products or judgments as the case may be) and creating an institution (organization, culture, process) that repeatedly produces great results.
  • Define "great result" as the best possible result given all the circumstances and constraints.
  • Don't abandon your own philosophy and point of view.  Use them as a foundation for pushing the team to produce the best possible results.  But do that in the context of working with your peers to create a unified result.
  • Recognize that others on the team can have vital contributions even if they don't have the same level of intellectual horsepower as yourself.
  • Recognize the value of consistency and strive to achieve it.  But don't put consistency as a higher priority than results.
  • Don't let the need to compromise be an excuse for giving up.  Strive for the highest possible standard of quality and longevity.

Here are a couple relevant passages from the article

... On the Court, the brilliant academics are less successful, over time, than the collegial pragmatists. The self-centered loners are less effective than the convivial team players. The resentful braggarts wear less well than the secure justices who know who they are. The narcissists wield judicial power less sure-handedly than the judges who show personal as well as judicial humility. The loose cannons shoot themselves in the foot, while those who know when to hold their tongues appear more judicious. (A justice often achieves more by saying less.) The ideological purists are marginalized on the Court, while those who understand when not to take each principle to its logical extreme are vindicated by history. Justices who view cases in purely philosophical terms are less sure-footed than those who are aware of a case’s practical effects. And those with the common touch win broader support than those who live entirely in abstractions.

... Jefferson and Holmes were repeatedly outfoxed by the less scholarly John Marshall and John Marshall Harlan—judicial thinkers whose conviviality, practicality, and sense of the possible allowed them to transform the law in their own image.

... Marshall, after all, had a strong philosophy of his own, rooted in vigorous protections for national power and property rights, but he chose not to press his philosophy in cases he knew he couldn’t win. (Remember his axiom: “I am not fond of butting against a wall in sport.”) Although conservative Federalists charged that he was too fond of popularity, Marshall was not noted for his willingness to compromise—but he articulated his principles in ways that his opponents were able to accept. Part of what made Marshall trustworthy, Roberts told me, was that “he was not a deal maker, not a broker. That’s not how he facilitated consensus. He had strongly felt principles, principles for which he had risked his life … But he was willing to explain, to talk it out with people, and he had a prodigious intellect but he didn’t scare people off with it … He was friendly, open—people trusted him—and [he] was able to bring people along.”

Obviously a lot of the points here could apply to software architects as well.  Here is one short passage from above, translated to apply to the software world:

The ideological purists are marginalized [over time], while those who understand when not to take each principle to its logical extreme are vindicated by [producing great products that end  up widely used]. [Architects] who view [design issues] in purely philosophical terms are less sure-footed than those who are aware of [each decision's] practical effects. And those with the common touch win broader support than those who live entirely in abstractions.

That sounds about right.

In the end the Argumentative Academic values most that "his personal opinion is acknowledged as right", the Result-Oriented Realist values most "getting the team to consistently deliver a great result".

The lesson from the Supreme Court is that over time Result-Oriented Realists are way more effective than Argumentative Academics.  That is a lesson that we could take to heart in the software world. 

Being a realist should not stop you from having audacious goals and and being satisfied with nothing less than delivering a great product.  Being a realist does not mean limited expectations, it does mean developing a more practical results oriented approach for meeting your grand expectations.

Previous post on related topics include: a description of why an evolutionist approach is often better than a big bang approach, discussion of why great is better than perfect, a warning regarding groupthink (the opposite problem to what is described above, in groupthink no one is willing to challenge the group consensus), and a reminder that architects are often more influential than the managers who nominally have more authority.

 

                                                                                 copyright 2007 Kerry Champion

 

March 24, 2007

The View From Mount Improbable

Penguin has published a nifty little book called "The View From Mount Improbable" in it Richard Dawkins explains how the eye evolved through a series of incremental steps.  This is an important argument to make, as creationists often use the eye as an example of an organ that is so complicated and so perfect that it could not have evolved but must have been created in one master stroke.  (Central concepts from Dawkins argument have analogs that are critical in planning software architectures, we will get to that  in a little bit, first the biology.)

Darwin himself admits the difficulty:

"To suppose that the eye, with all  its inimitable contrivances for adjusting the focus to different distances, for admitting different amounts of light,  and for the correction of spherical and chromatic aberration, could have been formed by natural selection, seems, I freely confess, absurd to the highest degree."

What Darwin, Dawkins, and the other evolutionists have done is show how the human eye was formed through a series of incremental steps, where each step required only a limited change, and each step resulted in a functioning organ.  In fact many of these intermediate forms still exist today in other creatures, the "non-directional light sensitive skins of starfish" are a good example of an early form.  While it is impossible to imagine that you could go from no eye to a fully formed human eye in a single mutation, it is possible to imagine a single mutation triggering each of these individual intermediate steps.  And since each intermediate step is a functioning organ that has at least slightly improved upon its predecessor it is easy to see how natural selection would spread that new version through the population.

In software development we also have arguments about what is the most plausible way to create something that is complex and perfect.  Two typical options can be thought of as the "creationist" approach and the "evolutionist" approach:

  1. Creationist: Assign a very smart design team.  Have them create an elegant design that fulfills your full concept for the product.  Immediately start to implement this final form of the product.
       
  2. Evolutionist:  Lay out a plan for series of intermediate versions of the product.  Carefully design the first step  (keeping in mind that the codebase will be evolved and reused, so put emphasis on compartmentalization, factoring, and good interfaces), don't take the time to fully design the later steps.  Make each intermediate step something that is deployed with users, or at least with beta users.  Be prepared to adjust the plan based on feedback you get at each intermediate step.

The "creationists"  argue:

  • It takes too long to make all these intermediate versions.
  • What is the point of writing a bunch of code that will only get reworked or replaced as you evolve the product.
  • Intermediate versions lead to legacy problems (interfaces you have to support, migration plans you have to implement, etc.) that you will regret.
  • The competition is not going to waste time with these intermediate versions.  They will leapfrog us.
  • Why limit yourself to designs that can be reached through incremental steps, what if the "best possible design" can not be reached through incremental steps.

The "evolutionists" argue:

  • Not understanding the real requirements is the biggest issue.  Users themselves typically don't know what they ultimately want.  Only getting something in use can resolve this issue.
  • It is only after you have written it once that you really understand how to write it right.
  • Naval gazing in your conference room does not lead to true understanding.  Putting software into use, careful analysis of the reaction, and rapidly evolving the offering is what leads to true enlightenment
  • Having working intermediate versions gives you more flexibility when it comes to the point of making the features vs. schedule trade-offs.
  • Working intermediate versions improves your ability to get continued funding.  This is true whether your funding comes from a VC firm or a senior management budget committee.
  • The goal is not finding the "best possible design", the goal is finding a great design that meets your audacious goals with minimum risk.

Which approach is best depends on your specific circumstances: scope of the project, relevance of team's previous experience, clarity of requirements, etc.  However, most of the time I am an "evolutionist". 

Smart people tend to over-estimate their ability to go directly (via their own mental horsepower) to the correct final answer.  Usually getting the optimum offering requires interaction and evolution.

Let's return to biology for a moment.  The eye is not perfect.  Remember those exercises you did in Junior High science class, they proved that we all have a blind spot, none of us can see in the infrared and some of us are color blind.  A perfect design would not have these traits.  However, as Darwin pointed out the eye is a great design.  So great that many believed omnipotence was required to create it.  I believe it ended up great, because each modification was tested in real use before it was incorporated in the final result.  This lesson is worth keeping in mind when you go to create your next great design.

Previous posts touched on some related topics: why great is often better than perfect; why we so often miss the real requirements; why interfaces are more important than code; and why a "truly complete" design is not what you want.
                                                                                 copyright 2007 Kerry Champion

March 19, 2007

Great Products vs. Perfect Products

Google Maps on Blackberry Pearl is a great product, according to this blog post by Jonathan Schwartz.

I won't even attempt linking to all the blog posts that are in rapture over the iPhone.

There are a handful of products that have this "Wow!" factor, people just fall in love with them.  Even in the case of the iPhone, when it has not shipped yet. 

Given the personal gratification and financial rewards (seen Apples stock price recently?!) that come from delivering great products, why is it you see so many products that make you say "What were they thinking?" and so few that bring out that "Wow!"

To create great product I believe you must:

  1. find people who are passionate about getting the design right
  2. put them in key roles
  3. allow them to do their jobs

Sounds like a simple formula doesn't it, but it is surprisingly hard to pull off.

Part of that difficulty comes from confusion between "great products" and "perfect products":

Great Products:

  • are based on intelligent trade-offs
  • are aimed at a clear-cut target user
  • take risks
  • have timely delivery and are products "of the moment"
  • give joy to their creators via their enthusiastic widespread use

Perfect Products:

  • try to be all things to all people
  • are designed to avoid failure
  • are delivered just at the moment that they are no longer relevant (if they are delivered at all)
  • give joy to their creators via the contemplation of their intended design and the demo of the latest exciting "prototype"

Often passionate folks will talk the language of "great products" but then act like they are building a "perfect product".   This is sad when it happens, both because the product at hand ends up a failure, but even more because it conditions the business folks who lived through the train-wreck to never again listen to a passionate designer striving for greatness.

Aiming for greatness is the right thing to do and is worth the risks,  just recognize the differences between greatness and perfection.

                                                                                 copyright 2007 Kerry Champion


March 15, 2007

Groupthink and Software Design

"Groupthink may cause groups to make hasty, irrational decisions, where individual doubts are set aside, for fear of upsetting the group'€™s balance. The term is usually used as a derogatory term after the results of a bad decision."   - Wikipedia

Irving Janis created the original definition of groupthink.

More than once I've seen a team working extremely hard on a year long effort to implement a software design, where the software design was fundamentally flawed, with no one on the team actively questioning the assumptions in the design.  I believe that groupthink is often a root cause of this type of failure.

Here are common behaviors I have observed that lead into the groupthink trap:

  1. Individuals high in the hierarchy (formal or informal) express an opinion when the task is first assigned to a group.  This creates a prepackaged answer before you even start. 
  2. Rationalization is tolerated in the culture.  Team members assume that it's invariant human nature, and don't bother correcting it when they see it.
  3. Don't consult with trusted experts from outside of the group.  Avoid technical and customer advisory boards.
  4. Never request that knowledgeable insiders act as "devil's advocate"
  5. The common attitude is "we don't have time to think about it lets just do it."
  6. There is no distinction made between critical defining decisions and trivial decisions, both are given the same level of scrutiny.  This leads to minimal scrutiny for all decisions.
  7. Fall in love with your own ideas.  Don't bother building into the culture a distrust of NIH.
  8. Don't bother keeping a lookout for "early latching."  When searching for an answer humans tend to latch on to the first reasonable answer (using a low barrier of acceptance) and then use a much higher standard when considering other possible answers in comparison to this initial answer.  Don't bother looking for this pattern.
  9. Focus your energy driving local optimization based on unquestioned assumptions.

Sloppy professional habits and a normal desire for group harmony are common drivers of these behaviors.  However another common driver in software ventures is the natural desire to deliver quicker and deliver more. 

Delivering the wrong thing fast isn't what creates a success.  Having a team that lives in perfect harmony in their comfort zone isn't what creates a success.  Success comes from building a culture that rejects both groupthink and analysis paralysis.  


                                                                                copyright 2007 Kerry Champion

 

March 07, 2007

Innovation Via Simplification

Innovations can be categorized into all kinds of different buckets:

  • technical implementation innovations
  • business model innovations
  • process innovations
  • "brave new world" innovations
  • "faster, cheaper, better" innovations
  • etc. etc.

I dearly love "simplifying innovations", that's my favorite category.

To create value through innovation you don't have to add a new feature or create a new service.  Through insight and experimentation you can add just as much value by simplifying.  Discovering how to allow the user to achieve their goals via:

  • a cleaner more intuitive UI
  • a more efficient production process
  • a shorter cycle time in the search/purchase cycle
  • an implementation that may be missing a few bells and whistles but is more compact, higher performance, less error prone
  • etc. etc.

Google and Linux are both good examples of innovation through simplification.

Google's original value prop (things have changed over time) had three cornerstones:

  1. more accurate search results
  2. faster return of those results
  3. a clean and simple home page

Of those three it was the "clean and simple home page" that was the most obvious differentiation to the typical user.   Yahoo and every other "Web Portal" seemed to be competing by seeing how many options, how many features, how much links, and how much text they could cram onto their home page.  Google appeared stunningly different by taking the exact opposite approach, simplifying the UI and focusing on doing one thing (search) extraordinarily well.  That innovation via simplification is what got them launched on the road to success.  The fact they may be drifting from that now does not change the value of the lesson.

Linux is a similar story.  The original Linux implementation clearly had less functionality and fewer device drivers than Windows and the existing UNIX implementations.  The innovations people valued (that made up for what Linux lacked) where all things that simplified the process and the product:

  1. Open source development model. 
    Made it simpler to fix it yourself or buy support/modifications from any of a hundred different vendors
  2. Download for free distribution model.
    Vastly simplified the purchase and license enforcement process.
  3. A design ethic that stressed smaller/faster/fully-reviewed
    Resulted in software that was more reliable, less buggy, more secure, more likely to run on low-end hardware, and delivered better performance on uniprocessors.

The best cultures are the ones that measure success by how simple and obvious the final design is, rather than by how elaborate and baroque it is.  This is true whether you are designing a software product, or a marketing campaign, or a customer support policy.

Often innovation via simplification takes a certain kind of bravery.  You must trust your judgment about what is the right trade-off and not fall into the trap of "lets give them one of everything, because we can't decide what really matters."  This is exactly the kind of bravery and judgment that is required to make a great product.

Learning how to effectively hear the customer is an important step in this process.  As is learning how to avoid too many product commitments too early in the process.

Principled Innovation has a good post on Radical Simplicity, that is worth looking at.  I will leave you with one quote from that post:

“Simplicity is the ultimate sophistication.” (Leonardo da Vinci)


                                                                                 copyright 2007 Kerry Champion

February 18, 2007

Never Your Code Alone

Giles Bowkett added a fresh perspective on the Software as Legos Meme yesterday.  One of his points is that you should not assume too quickly that you have to create a new building block from scratch, but you should first look harder at what you already have.

This thinking about building blocks reminds me of an important observation that is often overlooked.

When studying how software engineers actually spend their time it is a truism that they spend only a  minority of their time designing specific algorithms, defining specific data structures and writing fresh code. 

So where does the rest of the time go?  Well there are several ways to slice it. 

It is often pointed out that more time is spent on maintenance and evolution than on greenfield creation.  That is certainly true.

It is also pointed out that more design time is spent on refining requirements than on actual internals design.  That is also true.

However, in this posting I am interested in another point.  Less often noted is the fact that they typical developer needs to spend more time dealing with the interfaces he interacts with than he does dealing with the core code he authors.  Recognizing that this is true, encourages developers to make targeted investments up front that will save them time and improve quality in the end.

By "interfaces" I mean all interfaces: system interfaces (OS functionality, UI toolkits), major application components (databases, user directories, security libraries), shared data structures, and the internal interfaces to other components under development.  Most engineers tend to underweight the importance of having a truly complete understanding of the interfaces they are using, blithely assuming the actual behavior will be obvious from the declared interface and they will just figure it out as they go along.  This leads to: expensive to fix bugs discovered late in the process, a tendency to rebuild functionality that already exists in another module, and a tendency to constrain user functionality because you are not getting full leverage from the interfaces that are available.

When assigned a new module a responsible developer will go through and read all the code in that module and make sure he understands the code he will be modifying.  He will then go on and write (or extend) some unit tests that demonstrate he really understands that code.  However, he typically does not invest comparable effort to understand the interfaces his code is using.  It is worthwhile to take some steps up front: carefully reading the interfaces, understanding the implementation behind those interfaces, and where needed writing test code that shows the actual behavior of ambiguous interfaces

Investing  the effort to understand not just your code but the interfaces you have available will save time and effort in the long run.  Often this kind of investment is pushed aside by more "urgent" tasks, but this is one of those times you must find a way to get "important" tasks done, even if they don't feel "urgent" at the moment.

                                                                                 copyright 2007 Kerry Champion

April 2008

Sun Mon Tue Wed Thu Fri Sat
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30      
Blog powered by TypePad