Showing posts with label Software Development Management. Show all posts
Showing posts with label Software Development Management. Show all posts

Tuesday, June 19, 2012

Software Architects Need Not Apply

I saw an online job posting several years ago that listed a set of desired software development and programming skills and concluded with the statement, "Architects Need Not Apply." Joe Winchester has written that Those Who Can, Code; Those Who Can't, Architect (beware an extremely obnoxious Flash-based popup) and has stated that part of his proposed Hippocratic Oath for Programmers would be to "swear that my desire to enter the computing profession is not to become an architect." Andriy Solovey has written the post Do We Need Software Architects? 10 Reasons Why Not and Sergey Mikhanov has proclaimed Why I don’t believe in software architects. More recent posts have talked of Frustration with the Role and Purpose of Architects on Software Projects and The frustrated architect. In this post, I look at some of the reasons software architects are often held in low esteem in the software development community.

I have been (and am) a software architect at times and a software developer at times. Often, I must move rapidly between the two roles. This has allowed me to see both sides of the issue and I believe that the best software architects are those who do architecture work, design work, and lower level implementation coding and testing.

In Chapter 5 ("The Second-System Effect") The Mythical Man-Month, Frederick P. Brooks, Jr., wrote of the qualities and characteristics of a successful architect. These are listed next:

  • An architect "suggests" ("not dictates") implementation because the programmer/coder/builder has the "inventive and creative responsibility."
  • An architect should have an idea of how to implement his or her architecture, but should be "prepared to accept any other way that meets the objectives as well."
  • An architect should be "ready to forego credit for suggested improvements."
  • An architect should "listen to the builder's suggestions for architecture improvements."
  • An architect should strive for work to be "spare and clean," avoiding "functional ornamentation" and "extrapolation of functions that are obviated by changes in assumptions and purposes."

Although the first edition of The Mythical Man-Month was published more than 35 years ago in 1975, violations of Brooks's suggestions for being a successful architect remain, in my opinion, the primary reason why software architecture as a discipline has earned some disrespect in the software development community.

One of the problems developers often have with software architects is the feeling that the software architect is micromanaging their technical decisions. As Brooks suggests, successful architects need to listen to the developers' alternative suggestions and recommendations for improvements. Indeed, in some cases, the open-minded architect might even be willing to go with a significant architectural change if the benefits outweigh the costs. In my opinion, good architects (like good software developers) should be willing to learn and even expect to learn from others (including developers).

A common complaint among software developers regarding architects is that architects are so high-level that they miss important details or ignore important concerns with their idealistic architectures. I have found that I'm a better architect when I have recently worked with low-level software implementation. The farther and longer removed I am from design and implementation, the less successful I can be in helping architect the best solutions. Software developers are more confident in the architect's vision when they know that the architect is capable of implementing the architecture himself or herself if needed. An architect needs to be working among the masses and not lounging in the ivory tower. Indeed, it would be nice if the title "software architect" was NOT frequently seen as an euphemism for "can no longer code."

The longer I work in the software development industry, the more convinced I am that "spare and clean" should be the hallmarks of all good designs and architectures. Modern software principles seem to support this. Concepts like Don't Repeat Yourself (DRY) and You Ain't Gonna Need It (YAGNI) have become popular for good reason.

Some software architects have an inflated opinion of their own value due to their title or other recognition. For these types, it is very difficult to follow Brooks's recommendation to "forego credit" for architecture and implementation improvements. Software developers are much more likely to embrace the architect who shares credit as appropriate and does not take credit for the developers' ideas and work.

I think there is a place for software architecture, but a portion of our fellow software architects have harmed the reputation of the discipline. Following Brooks's suggestions can begin to improve the reputation of software architects and their discipline, but, more importantly, can lead to better and more efficient software solutions.

Saturday, May 19, 2012

The Developer/Non-Developer Impedance Mismatch

Most software developers have probably heard of and even had experiences with the object-relational impedance mismatch (often addressed with ORM tools), the object-XML impedance mismatch (often addressed with OXM tools), and even the developer-DBA impedance mismatch. I don't believe that these impedance mismatches are as difficult as they are sometimes made out to be, but for those wishing to mitigate them, we have tools such as Java Persistence API implementations and JDO implementations for dealing with the object-relational mismatch (and some of the developer-DBA impedance mismatch) and similarly have approaches such as JAXB, XMLBeans, JiBX and Apache Commons Digester for dealing with the object-XML mismatch (and .NET's LINQ deals with both ORM and OXM mismatches). At this point in my career, I believe the developer/non-developer impedance mismatch is perhaps the most frustrating impedance mismatch I have run into.

Although there are numerous tools and approaches for dealing with these other types of impedance mismatches, it seems we're woefully short on similarly powerful tools, approaches, and proven practices (my new preferred term for what I think "best practices" was originally intended to mean) for dealing with the developer/non-developer mismatch. In this post, I look at some of the most common areas of developer/non-developer mismatch and speculate as to why they occur and what can be done to address these specific areas of developer/non-developer impedance mismatch.

Sadly, we have much less control over the developer/non-developer impedance mismatch than we do over object-relational or object-XML impedance mismatches. Although in general things like improved communication and education can help, these answers are not as tangible as the ones we're used to for dealing with other types of software development impedance mismatches. As difficult as it is to deal with the developer/non-developer impedance mismatch, we must do so because there are numerous significant stakeholders in the software development process that are not necessarily developers (managers, clients, testers, customers, business analysts, sales people, and more).

DRY Principle / Modularity

Almost to a fault, developers have generally adopted (at least in a theory if not always in practice) the DRY (Don't Repeat Yourself) principles coined in the often-referenced book The Pragmatic Programmer: From Journeyman to Master. Although the term was coined in this 1999 book, the practice had been one that developers for decades had understood to some degree. Regardless of native spoken language or favorite programming language, developers today widely recognize virtues of some degree of DRY-ness. There may be some debate as to what level this should be taken (I've seen it taken past the point of common sense), but most of us agree with the perils of repeated documentation at different levels of the software product or of repeated code (copy-and-paste development).

Benjamin Denckla, in the post "Faith in DRY; no hope for software," writes, "Today we produce software through a laborious, undisciplined process that combines the low quality work of many with the heroic high quality work of a few. ... Not enough people believe in DRY and other good practices like it." I believe this is especially true when one considers the non-developers involved in a software development project. In my experience, the developers generally do see the value in some significant degree of DRY, but non-developer stakeholders see little value in DRY principles.

For purposes of this discussion, I'm including modularity in what I'm calling DRY practices. Most developers know there are numerous reasons to not copy-and-paste the same code into multiple places. For many decades, developers have known to place reusable code in methods, functions, modules, or other constructs that allow the same code to be used in multiple contexts and situations. It doesn't take long for this to become second nature to the experienced developer. Sadly, many non-developers seem to not acknowledge the risks and problems associated with redundant information copied from place to place or believe these risks and problems are more theoretical than real. Although it may not be code we're talking about when we discuss non-developers (it may be documentation, requirements, specifications, test procedures, or a host of other non-code things), the principle still applies: reproducing anything in multiple places leads to problems down the road in terms of maintenance and keeping the many versions synchronized with the latest and greatest. Developers seem to almost intrinsically "get it," but I see it less well received from many non-developers.

Readable and Maintainable Code

Many new software developers and even more non-developers do not recognize the value of code that is more readable and more maintainable. Perhaps the best experience a young developer can have is to maintain and reuse someone else's code. Doing so helps a young developer to recognize the value of writing code as cleanly as possible. Because non-developers never really get this experience, it is not surprising that they don't value cleanness, maintainability, and readability to the same degree as the experienced developer. Many legitimate cries for time to refactor a code base to improve its future maintainability and readability are ignored or promptly dismissed because such efforts' value is not obvious to those making the decisions.

Overbearing Processes and Management Decisions

I have occasionally seen non-developers in management roles trying to coerce developers into very narrow and specific behaviors that they (the managers) believe is best (or worse, that they perceive as giving them the power). These folks rarely have the experience to know the full ramifications of their decisions. Good managers listen to their developers (particularly those with significant experience and in technical leadership roles) before pushing out every "good idea" they have. Experienced developers usually know what it takes to write high-quality software, but it almost takes another experienced software developer to appreciate what they argue for. Alternatively, a manager lacking software development experience can sometimes make better decisions by choosing an experienced developer that he or she trusts with technical decisions. The best non-technical managers recognize their own lack of technical knowledge and work with a trusted technical expert to make good decisions.

Bean Counting and Pencil Pushing

Most software development is done as part of a business venture and it is often inevitable that some degree of bean counting and pencil-pushing will be required.. Clients or consumers directly or indirectly finance the creation of software. It can be difficult for developers to recognize and appreciate the legitimate management and metrics collection that goes on during these business-oriented phases. It can be equally difficult for managers and other non-developers to understand that some things are more subtle than the apparent "bottom line." Non-developers may over-emphasize short-term "bottom line" considerations at the expense of long-term quality and maintainability of the product while developers may overly neglect bottom line considerations and create software products that require too much time and investment to justify their likely return on investment.

The bean counter wants nothing more than to be able to count things like beans. He or she wants to use lines of code, number of defects in various states, number of requirements, and so forth to feel like he or she has a handle on the software development progress being made. It doesn't really matter that these are not created equally and should not be counted as if they are equal.

Battle for Control

It seems to be human nature and common in many relationships between humans to have battles for control. Tension can increase in the relationship between developers and non-developers as each group tries to exert control. Many non-developers, especially if they don't understand development or coding well, resent not being able to control what is added to the baseline. Many developers resent being told what they can put into the baseline, especially when they strongly believe that the non-developer is making arbitrary calls while lacking sufficient knowledge and background to make that call.

The battle for control can become very onerous when both sides are "know-it-alls." When either side is convinced of its superiority, it can be very difficult to get either to budge. Developers often feel their experience and skillset best qualifies them for making all software decisions while clients, managers, and others often feel their position does the same for them.

Coding: Job for a Craftsman or for a Technician?

Good software development managers recognize that software development can be a highly creative and challenging effort and requires skilled people who take pride in their work. Other not-so-good software managers consider software development to be a technician's job. To them, the software developer is not much more than a typist who speaks a programming language. To these managers, a good enough set of requirements and high-level design should and can be implemented by the lowest paid software developers. Some software development is easier than other software development, but the simple technician work has been largely replaced by automation and code generation at this point.

Perhaps the perceptions of technician versus craftsman explain why non-developers tend to be more likely to believe that all developers are plug-and-play while experienced developers realize that there can be a wide disparity in skillsets and knowledge between any two developers.

Appreciation of Software Development Nuances and Subtleties

It usually does not take long for a developer to realize that relatively little in software development is cut and dry. Software development often has a large amount of creativity to it and there are numerous judgment calls to be made. We sometimes call these design decisions or architecture trade-offs. Unfortunately, many who are not software developers do not understand that there are nuances and subtleties and even large amounts of creativity involved in software development. Without lack of these subtle shades, it's not surprising that many of these people without development experience can only think in extremes (technique "A" is good and must be be used by everyone all of the time or technique "A" is always wrong and should be absolutely avoided no matter what). New developers often exhibit this trait as well, but experience usually teaches them to be more willing to judge approaches and techniques against particular contexts and reduce the amount of generalization and assumptions.

Developers Aren't So Different from Others, But Then They Are

The Mythical Man-Month is one of the most often-quoted books in the areas of software development and software development management. One of its great quotes is made early in the work (first sentence of Preface to the First Edition): "In many ways, managing a large computer programming project is like managing any other large undertaking—in more ways than most programmers believe. But in many other ways it is different—in more ways than most professional managers expect." One of the key explanations of the impedance mismatch between developers and non-developer managers seems to lie in this profound statement. Developers, as a group, probably should be more willing to buy into certain proven "traditional" management approaches, but managers need to avoid falling into the trap of thinking that the tactics outlined in the latest business management book will be sufficient for managing software developers.

Opinions on What Values Most

Software developers are people too. As such, they do exhibit the same behaviors as other people. However, there are gross stereotypes of software developers that are not completely without some basis because of the high frequency of those stereotyped traits among software developers. There is great diversity in the software development community in terms of political opinions, interests, and so forth, but the idea of what is most important (quality design and code, work to be proud of, etc.) are fairly common across the industry. On the other hand, software developers (similarly to engineers in various engineering disciplines) seem to overly trivialize the need to respect the bottom line. They often cannot understand when an arguably adequate but not "best" or "perfect" solution is chosen over a better technical solution for non-technical reasons.

Conclusion

We in the software development community tend to deal with mismatches all the time. We often spend significant energy and time "gluing" things together that weren't necessarily designed to go together. Despite all of this technical experience we have making incongruent pieces work together, we still seem to have difficulty resolving perhaps the most difficult and most important mismatch of all: the mismatch between software developers and people who are not software developers. Although there are some positives that come from this (such as checks-and-balances on "science fair projects"), there is significant dysfunction, angst, resentment, and demoralization caused by this impedance mismatch.

Saturday, September 10, 2011

Book Review: The Mythical Man-Month: Essays on Software Engineering, Anniversary Edition

Frederick P. Brooks, Jr.'s The Mythical Man-Month (MM-M) is one of the most famous books in all of software development literature and is arguably THE most famous book on software development management. There are already innumerable reviews of this classic, but I review it again in this post for those software developers who have not read it and want a small overview of what's to like about it. After all, it is PC World's #1 title in the list of Top Ten IT Books Never To Admit You Haven't Read. The full title of the edition I am reviewing in this post is The Mythical Man-Month: Essays on Software Engineering, Anniversary Edition.

The "Anniversary Edition" of The Mythical Man-Month (published in 1995) adds significant content above and beyond what was published in the original edition in 1975. The "Anniversary Edition" contains the original book in its original form (albeit with the inclusion of corrections added in the 1982 reprint) and adds four new chapters. The first fifteen chapters in the Anniversary Edition are the chapters from the original book. The added chapters include Brooks's separate but equally famous IFIPS (1986) / IEEE Computer Magazine (1987) paper No Silver Bullet: Essence and Accidents of Software Engineering and a follow-up called No Silver Bullet ReFired. Chapters 18 and 19 of the Anniversary Edition focus on Brooks's 1995 self-perspective on what he wrote in 1975. Brooks points out what he got wrong and what he got right (there are far more cases of the latter than the former).

There are numerous reviews of The Mythical Man-Month that include exhaustive coverage of the topics and quotes from this book (Wikipedia article, Bernard I. Ng's The Mythical Man-Month summary, Some insights from The Mythical Man Month starting from Chapter 11, The Mythical Man-Month – Extracts I, The Mythical Man-Month – Extracts II, The Mythical Man-Month Lecture, and Review/Summary of The Mythical Man-Month, for example). Rather than repeat an overview of the book's content as a whole, I focus in this post on a few key points and in light of some modern day software best practices and ideologies.

Chapter 19 ("Propositions of The Mythical Man-Month: True or False?") of the "Anniversary Edition" will especially appeal to the reader who is impatient or lacks the time to read the entire book, but wants to get an overall view of Brooks's assertions. Because Brooks uses this chapter to present "the essence of the 1975 book" in "outline form," Brooks's assertions ("facts and rule-of-thumb-type generalizations from experience") from his original book are presented in "stark form" (approximately 20 pages). The presence of this chapter in the "Anniversary Edition" is another reason I don't break the book down chapter-by-chapter here. This chapter does more than simply summarize the assertions from the original book; it also includes some of Brooks's 1995 comments based on 20 more years of observation and the benefit of hindsight.

In his post The Mythical Man Month: Book Review, Mark Needham concludes his review of this book with the statement, "I really enjoyed reading this book and seeing how a lot of the ideas in more modern methodologies were already known about in the 1980s and aren’t in essence new ideas." I wholeheartedly agree with this statement, though the truth of it is possibly even more staggering: these were observations in a book published in 1975 based on Brooks's experiences working on OS/360 development in the mid-1960s and on follow-on conversations in the late 1960s. In other words, some of the things we might think are "new" or "trendy" today have been around and known for 45 years or more! As a side note, this reminds me of an Alan M. Davis presentation to the Denver Java Users Group ("What's New About New Methods of Software Development?") in late 2006 in which he demonstrated how many of the "new" methodologies and tactics of today have very similar predecessors in years past and how we seem to cycle between them over decades.

The following points made by Brooks are especially interesting when one keeps the thought in the back of his or her mind that this book was published in 1975 based on experiences in the mid- to late- 1960s (these quotes are from the Chapter 19 summarization but are based on text in the 1975 edition):

  • "Very good professional programmers are ten times as productive as poor ones..." [craftsmanship]
  • ""A small sharp team is best - as few minds as possible." [agile]
  • "Fixing a defect has a substantial (20 to 50 percent) chance of introducing another. After each fix, one must run the entire bank of test cases previously run against a system to ensure that it has not been damaged in an obscure way." [regression testing]
  • "It is worthwhile to build lots of debugging scaffolding and test code, perhaps even 50 percent as much as the product being debugged." [unit testing]
  • "To keep documentation maintained, it is crucial that it be incorporated in the source program, rather than kept as a separate document ... even high-level language syntax does not at all convey purpose." [DRY principle]

There are many more observations in The Mythical Man-Month that demonstrate that Brooks and other developers of the time understood many of the same basics of software development that we understand (and sometimes "discover" again) today. Many of these are more well-known and are called out in other reviews and so I don't list them here except for these must-list quotes:

  • "More software projects have gone awry for lack of calendar time than for all other causes combined."
  • Brooke's Law: "Adding manpower to a late software project makes it later."
  • "Hence the man-month as a unit for measuring the size of a job is a dangerous and deceptive myth."

One of the sections I found particularly timely (especially for a 1975 book in 2011) was Brooks's coverage of how a software architect can influence implementation. This can be especially sensitive when the architect's vision is not implemented by the developer in the way the architect desired. Brooks's tips seem very practical. He states that the architect must come to terms with the fact that the person implementing the code has "creative responsibility" for that implementation. He further advises that the architect should always have an idea of how to implement any of his or her designs, but must at the same time be willing to accept an equally good alternative approach proposed by the person implementing the code. Brooks further recommends that the architect make all suggestions regarding implementation "quietly and privately," be "ready to forego credit," and be willing to listen to the implementer's "suggestions for architecture improvements." This seems like sound advice to me based on my experiences on both sides of this relationship.

In the 2005 article Quoted Often, Followed Rarely, Brooks states:

The book is really more about management than about technology. The technology has changed immensely, so some of the old chapters are totally out of sync. On the other hand, people haven't changed much. That's why Homer and Shakespeare and the Bible are still relevant, because they're all dealing with human nature. I think that's part of the explanation for this book: The problems of managing people in teams have not changed, though the medium in which people are designing and the tools they are using have. Some people have called the book the "bible of software engineering." I would agree with that in one respect: that is, everybody quotes it, some people read it, and a few people go by it.

The concepts contained in this quote may be the most important thing to convey in a review of The Mythical Man-Month. The appeal of the book is its coverage of and focus on management of people. That has remained timeless and unchanged over the decades. The technologies have definitely changed significantly and that may be the biggest negative about this book. Brooks's examples based on specific products, tools, and languages in 1975 were certainly more illustrative then than they are today for the typical reader. For example, his 1975 book calls PL/I "the only reasonable candidate for system programming today." At times, some of the reading can be a little more challenging with lack of direct experience with the products of which Brooks mentions. However, in most cases, this is not much of a hindrance in the end because of the human element is the focus of the book and this is mostly unchanged even now. In Chapter 19 of the Anniversary Edition, Brooks reflects on the continuing popularity of his book and states: "to the extent that The MM-M is about people and teams, obsolescence should be slow."

The Mythical Man-Month is really about very large enterprise software development projects. This is important to bear in mind when reading things that may seem obvious to someone working on a small project. The last part of the quote above is famous: "Some people have called the book the 'bible of software engineering.' I would agree with that in one respect: that is, everybody quotes it, some people read it, and a few people go by it." Brooks's book is filled with Biblical references and he is obviously acquainted with the Holy Bible. Sadly, Brooks's quote "everybody quotes it, some people read it, and a few people go by it" is all too true today. We'll keep reading it, but it'd be nice to do more to change things in large-scale software development projects.

Some people feel that The Mythical Man-Month is defeatist and even depressing. I don't get the same feeling from reading it. Rather, I feel that it reminds us that certain behaviors are detrimental and dysfunctional. It also reminds us that we shouldn't wait for the "next big thing," but should instead continue to improve our craft as best we can. Many practical tips and suggestions are provided. Brooks obviously loves being in the software development field and this is shown again and again in his book. Brooks concludes the book's "Epilogue: Fifty Years of Wonder, Excitement, and Joy," talking about how he used to be able to "read all the journals and conference proceedings," but eventually had to give up specific interests one by one as the knowledge exploded. He concludes, "Too many interests, too many exciting opportunities for learning, research, and thought. What a marvelous predicament! Not only is the end not in sight, the pace is not slackening. We have many future joys." I definitely agree.

Monday, March 14, 2011

Software Development Isn't About Beans

The term bean counter is often used with a negative connotation. One of the negative connotations often associated with the term "bean counter" is that these folks are incapable of looking past quantitative measures to look into alternative measures that are more qualitative and/or intangible. In software development, bean counting is often particularly ineffective. Attempting to count beans to measure productivity or estimate future work often leads to disappointment and unsatisfied expectations. In this post, I look at some of the ways that software development managers attempt to count "beans" that are not really there or are not really indicative of what they're actually trying to measure.


Lines of Code Are Not Beans

Perhaps the most misleading and falsely assuring software development metric of all time is the infamous line of code. I have blogged previously on the unintended consequences associated with counting lines of code. The reason this is such a terrible metric is that it presumes that every line of source code is a bean that can be counted. There can be some value to measuring lines of code in a large aggregated sense, but any value in this metric is lost as the numbers of lines of code is reduced.

The "bean" assumption is that all lines of code are equally difficult to write and maintain. This is, of course, simply ridiculous. One programming language may be more difficult to write in then another, one developer make write faster than another, one piece of code is more difficult to write than another, and so on. Tactics such as trying to only compares lines of code for the same language or same team of developers might help, but the truth of it is that lines of code will always remain only useful in a very large macro perspective.

I have often found that fewer lines of code can be a little more challenging to write than a greater number of lines of code that do the same thing. In other words, it may take me longer to write fewer, more concise lines than it does to write longer verbose code. The paradox is that fewer lines of code may require more time to write (though often less time to maintain). Not all lines of code are created equal and any presumption of such is folly.


Developers Are Not Beans

Another area in which the bean counters like to count "beans" even when it makes little sense to do so is in terms of staffing. To the bean counter, developers are resources that are easily switched as needed. There is little concern about the differences in experience, skill, and skill set between developers. The idea is that any developer can be plugged into an position interchangeably with any other developer. This is absurd except for on the most trivial of projects.

The consequences of the terrible assumption that all developers are the same quality "bean" is one of the core covered topics in Frederick P. Brooks, Jr.'s software development management classic The Mythical Man-Month. In Chapter 2, Brooks states, the now famous quote, "The man-month as a unit for measuring the size of a job is a dangerous and deceptive myth." He adds, "The man-month is a fallacious and dangerous myth, for it implies that men and months are interchangeable" (Chapter 18, 2.6). Not everyone agrees that this presumption is a problem.


Requirements are Not Beans

Software requirements vary significantly in terms of difficulty involved in implementing them, but they still are often treated as beans of the same type. To the bean counter, implementing ten requirements sounds better than implementing one requirement, although in practice it may be that the single difficult requirement is for functionality that is far more useful than the ten smaller, simpler requirements. Great progress can be perceived in rapidly working off requirements only to become surprisingly slower when the more difficult requirements are encountered. To a bean counter, the "rapid initial productivity" followed by "reduced productivity" is baffling.


Defect Reports Are Not Beans

It is very difficult to resist the urge to count each defect report the same. In practice, there are vast differences in the difficulties of fixing different defects. Appropriate priority settings can help measure the differences in importance or value of defect reports, but it is more challenging to measure the real effort required to resolve a defect. One really nasty defect might require much more effort than numerous easier defects. To the bean counter, though, the expert who takes one week to work off the nasty defect appears less productive than the average developer who can work off many more than that of the easier defects in that same week. Not all bugs are created equal.


Other Bean Counter / Software Development Mismatches

In Open Cubicles Must Die, Jim Showalter discusses how smaller cubicles makes sense to bean counters who can only focus on quantitative measures and not on less tangible consequences such as reduced productivity.


Why Aren't There Software Development Beans?

Brooks's The Mythical Man-Month provides background into why software development tasks are not easily categorized as beans or widgets. Brooks states, "Programming is fun because it gratifies creative longings built deep within us and delights sensibilities." Brooks likens the programmer to the poet, stating, "The programmer, like the poet, works only slightly removed from pure thought-stuff. He builds his castles in the air from air, creating by exertion of the imagination."

Software development is interesting because it combines technology with creativity. It is difficult to measure the "quality" of a poem, a painting, a sculpture, or other creative work of art via quantitative measures. It is similarly difficult to measure the significant creative portion of software development with quantitative measures. Only trivial and uninteresting software development (that which lacks need for creativity) can be measured with quantitative measures. The more challenging and interesting a software project is, and the more creativity it requires, the more difficult it is to measure the project's progress or estimate its costs using the quantitative measures discussed in this post. Software development tasks are not beans and cannot be counted or treated as such.


Why Insist on Beans Where There Aren't Any?

The bean counters don't uniformly misunderstand the nature of the software development business. Most of them understand that not all developers are the same, that not all lines of code are the same, that not all requirements are the same, and that not all defects are the same. The reason they continue to use these metrics like beans is that this is the only way they can make these things fit into their Excel spreadsheets, Microsoft Project projects, or other favorite bean counting tools.

The problem is that the measures described above and similar metrics are "countable" (quantifiable), but are typically so different from each other that counting them arbitrarily makes little sense. It would be like a bean counter counting lima beans, chili beans, coffee beans, and other types of beans as the same type of beans. If one was trying to make coffee or chili, it would matter which type of bean was available! The bean counter has the option to measure the beans by weight rather than by number. This might be a more accurate metric for certain needs. Because software development lacks physical entities that can be counted or weighed, we are stuck doing our best trying to assign "weights," but it is an inexact science.

We often talk in software development about the object-relational impedance mismatch, but a far more difficult such impedance mismatch may be the mismatch between the art of software development and the quantitative side of software development management.


Conclusion

For Java developers, there are many types of "beans" in software development: JavaBeans, Enterprise JavaBeans, JMX Managed Beans, Spring Beans, and so on. These are about the only beans in software development. There is too much creativity involved in software development to easily categorize components of it as beans. That doesn't mean we don't try or that we won't continue trying. After all, we've been doing it since before Brooks published The Mythical Man-Month in 1975.

Monday, September 14, 2009

Beware Software Management Overreaction

One of the most sinking feelings one can feel in software development occurs when a client or management overreacts to some crisis or mistake with onerous new requirements, procedures, and processes. In this blog post, I look at why those in authority sometimes do overreact, describe why overreaction can be dangerous and costly, and outline some ideas regarding how to reduce or prevent overreaction.

Why Do People Overreact in Software Management?

There are several explanations for why people overreact in management of software projects. Most of these are applicable to general overreaction in any area, but do apply specifically to software development.

Emotional

By definition, overreaction is associated with an emotional response that is inappropriate to the circumstances. Emotion can cloud over or completely obscure logic. Many poor decisions in life have been made in the heat of the moment when emotions run high and logic runs low. Emotions are usually high as a direct result of the incident being overreacted to. Often these incidents are most glaring when we can least afford them and stress levels are already high.

Helplessness / At Least Do Something

Another reason one might overreact is out of fear of not knowing how to resolve the situation in a reasonable fashion. If there is a problem with no clear solution, it may feel better temporarily to at least do something even if that "something" is not rationale or even a good idea. Sometimes the best thing to do is to do nothing, at least at first. Calmer heads are more likely to come up with more useful ideas for dealing with a particular issue.

Punishment

Overreaction may be directed at one individual, a team, or even the entire staff as a form of punishment. This is a little different than the previously covered reasons because it is more calculated and deliberate. However, that does not mean emotion is not involved; the desire to punish is often emotionally driven.

Send a Signal

Another calculated reason a person in authority might overreact is that he or she wishes to send a signal to other developers that certain (mis)behaviors are not tolerated. As with the punishment motivation, the person overreacting may be doing so intentionally to send a "stronger signal."

Lack of Understanding of True Cost of Overreaction

In some cases, a person in authority might feel their newly imposed procedure or process is perfectly reasonable because he or she does not understand the true cost and true negative consequences of it. This typically happens when a person with little or no hands-on software development experience attempts to decide on extreme measures related directly to some stage of producing software without consulting people in the know.


How Costly is Overreaction?

The total cost of overreaction is nearly impossible to quantify because it is so highly dependent on the situation and on the degree of overreaction. However, there are many different costs to overreacting and some of them are listed here. To illustrate many of these points, I will be using a simple example of an incident such as breaking the build.

Direct Cost can Exceed Original Incident Cost

Suppose that the build is broken occasionally because of developers in a rush. It is not a frequent event, but does happen from time to time. If the estimated lost developer time is, hypothetical speaking still, about 5 person-hours per week, it makes little sense to impose new procedures and policies that prevent that build breakage that require 50 developers to spend an extra 30 minutes per day checking out their code before merging. That's because 50 developers multipled by 0.5 hours per week means 25 person hours are spent to avoid a 10 person hour problem. That is an overreaction. The cure is worse than the disease.

There are cases where the extra time to avoid the problem may be justifiable. I am especially thinking of situations where one deems the quality benefits of the additional steps to be an advantage. However, if the new procedure is instituted solely to deal with the hours wasted on a broken build, it is nonsensical and counterproductive to institute additional procedures that will take more time than the thing being avoided.

For me personally, it is often better to have one longer work stoppage now and then as opposed to transitioning on a daily basis between the work I really need to accomplish and the mind-numbing steps added to avoid "incidents."

Unintended Consequences

Besides the direct costs of any new initiative instituted as part of an overreaction, there will almost certainly be unintended (and often negative) consequences. I have written before about the dangers of unintended consequences. These are especially challenging to quantify, but always seem to apply. A newly enacted procedure might be intended to reduce a certain undesirable event, but in the process leads to one or more different undesirable events. This can be especially true if the concept sprung from overreaction leads to cloaking bad incidents rather than actually preventing them.

Collateral Damage

One of the reasons that overreaction can be so disheartening to software developers is that we often know that the innocent are going to be treated in the same way as the guilty. Even worse, highly skilled and very experienced developers can sometimes be forced to endure the same restrictions applied to newer and less experienced developers after an incident occurs. In many aspects of like it is a laudable ideal to treat everyone the same, but it is a mistake in software development to treat the craftsman the same as the apprentice. Even worse, it is really despicable to treat the craftsman the same as the incompetent. Processes, procedures, plans, and initiatives spawned from overreaction often lump everyone together and deal with the least common denominator. There are many costs associated with this: lower productivity from the most productive developers, dissatisfaction in the people that are most difficult to replace, and lack of attention on the people who really need it.


How do We Prevent / Reduce Overreaction?

Count to Ten

Often the best way to avoid overreaction is to take the emotion out of it. If you're in the authority position or can influence the person with authority, try to wait at least a day (or preferably over a weekend) to allow emotions to cool and to reconsider the true cost of the incident you are tempted to overreact to.

Understand the Direct Costs of Your Reaction

Some of the worst consequences of overreaction I have seen are those that occur because the person making the decisions did not really understand the costs or consequences of their decisions. Before a decision is made like, "Before doing procedure A, one must always do procedure B," the person forcing that procedure on others should do them in a realistic environment to see how painful and costly they are and to truly determine there effectiveness.

Consider Unintended Consequences

One of the hallmark characteristics of many decisions made in haste and with emotion is that only one consequence is being considered. The decision usually does directly deal with that considered consequence, but it is important to consider the other consequences. As an extreme example, not allowing developers to write code will eliminate the addition of new bugs into the system. However, there are other consequences of this action such as no new code being written or maintained.

Apply Tweaks Rather than Seismic Shifts

One of the problems with overreaction is that it often leads to decisions that are not appropriate in terms of degree of seriousness of the original incident. It can often be better to reduce the first idea one has for dealing with a crisis to a smaller, less significant change and measuring if that is sufficient to meet the problem. Often, if cooler heads prevail, this is what happens anyway.

Acknowledge that Not Everyone is Equal in Experience and Skill

If developers have different grade levels or other indicators of their experience, then why not tailor processes differently for each grade level. If feasible, it would be even better to tailor to each individual. Much of the more successful open source community uses meritocracy in a similar fashion.

Contingency Plans

A big part of overreaction is often due to fear, shock, and a sense of hopelessness. This can be mitigated by considering some of the common things that can happen in software (hardware failures, defects, delays, difficult to maintain code, etc.) and have plans in place beforehand regarding how to handle them. This may help identify small steps that can be taken to reduce the likelihood of the problems in the first place and can provide calm and logic when the incidents do occur. Being proactive allows one to be less reactive.

Admit Mistakes

If a bad plan is put into the place as part of overreaction, the worst thing that can be done is to leave it in place to save face. It is better to admit that a response was overly reactive and either temper it or remove it altogether. This can be difficult to do even though it is the correct thing to do.


Conclusion

It can be very easy to fall into the trap of committing an overreaction to a significant event or incident. Unfortunately, this often exacerbates the problem and exasperates the development team. In this blog posting, I've looked at why we are prone to overreaction, some of the costs of overreaction, and some techniques to reduce the frequency and severity of overreaction.

Please feel free to add in the comments any reasons, costs, or remedies you have observed related to overreaction in software development.

Thursday, October 2, 2008

Similarities of Measuring Software Performance and Measuring Development Progress

I have observed that many lessons from software development experience can be applied to management of software development teams and that the opposite is also true -- many lessons from management of software development teams can be applied in hands-on software development. In this blog entry, I want to examine how lessons learned from software performance monitoring can be applied to appropriate monitoring of software development progress.

There are several issues that make it difficult to accurately measure software performance. Brian Goetz has written extensively on some of the difficulties. In Dynamic Compilation and Performance Management, Goetz outlines how dynamic compilation (such as is used with Java) complicates performance testing. This is one of the more subtle impacts of performance testing. Other and related problems measuring software performance include the fact that performance measurement directly impacts the performance itself (though many have gone to great lengths to reduce this effect), performance metrics can be collected in unrealistic situations (different hardware, different load, different actual running software, etc.), and performance metrics can be misinterpreted.

All of these problems that lurk in performance monitoring (monitoring affecting performance itself, unrealistic tests, and misinterpreted metrics) have counterparts in the similar effort to measure software development progress. Just as one must be careful when measuring software performance, measurement of software development progress must be approached carefully as well.

Too much focus on collecting software development metrics can actually slow down the very software development process that is being measured. Just as using resources to measure software performance impacts that very software's performance, measuring the development progress has some effect on that progress. In measuring software performance, we have learned to use tools and techniques that reduce the impact of the measurements on the performance itself. We need to similarly approach our software development metrics and ensure that the collection of metrics has only a minimum impact on that software development.

One way to reduce the effect of software development metrics on the development is to keep the number of requests for metrics down. Another obvious approach is to only request data that is easily provided and does not require significant effort to collect, organize, and present. There are many tools that are marketed to help reduce the impact on software development that is incurred for metrics collection, but even these can have a detrimental effect on the development progress when used improperly. For example, these tools may require developers to take extra steps or follow extra processes to ensure that their progress is adequately captured. The amount of time spent collecting and preparing reports on the progress of the software development effort can grow to be very expensive and add significant delays and hurdles to the development progress.

Just as software performance tests are useless or even dangerous (because they lead to bad decisions) when they are obtained against situations and environments that are not representative of the actual production environment, measuring the wrong things in software development progress can lead to useless and even detrimental results. I blogged previously on how using lines of code as too granular of a metric can lead to negative consequences because of the unintended consequences of this motivator. Similarly, other poorly chosen metrics can actually lead to bad decisions of developers who are trying to satisfy the metric rather than developing the best code.

Finally, misinterpreted performance results can lead to unnecessary optimizations. In the worst cases, these misinterpreted results might even lead to "optimizations" that actually make the real problem even worse. This can be the case with measuring software development progress as well. Lines of code, number of classes, and similar metrics can be misleading and misinterpreted. Poor decisions can be made on these inadequate metrics that actually hinder the software development process rather than helping.

While measuring the performance of software and measuring software development progress can both be difficult to perform properly, we still attempt to measure these things. In fact, as difficult as they are, we do need to measure them. We need our software to perform to certain levels depending on the context and the expectations of the software's users. Similarly, we need to deliver software by certain agreed dates to meet expectations of customers and potential customers. The key is to perform both of these measurements carefully and to constantly strive to reduce the impact of the measurement itself on what is being measured, to ensure that we are measuring the appropriate things, and to ensure that we interpret the metrics carefully.

The negative consequences of overzealous software development metrics collection has been a known problem for some time. In the software development classic The Mythical Man-Month, Frederick P. Brooks, Jr., articulates on this concept with vivid examples and illustrations obviously earned from his own personal experiences.

So, why don't we do a better job at this in many cases? Perhaps the most plausible explanation is that it is far more difficult to measure appropriately than it is to use the easiest measurement techniques that come to mind. It is easier to test our software's performance without concern for minimizing the impact on the performance itself and it is easier to measure our progress without trying to carefully craft metrics collection techniques that have minimal impact on the developers.

Similarly, it is easier to just test our performance in the first environment that is available rather than putting in the extra effort to replicate the environment and load as accurately as possible. It is also easier to count some arbitrary items such as classes, lines of code, etc. than it is to really try to measure delivered functionality that is not as easy to quantify.

Finally, misinterpretation of results of performance metrics or development progress metrics tends to happen when we are unwilling to put extra effort into really understanding why we are seeing the results. It is always easier to go with the first thing that comes to mind as we look at the results than it is to actually try to dig down into the real meaning of the results.

Many of the lessons we have learned from measuring and optimizing software execution performance can be applied to measuring and optimizing software development progress. Unfortunately, these lessons learned in one side don't always seem to be applied to the other side.

Friday, September 5, 2008

Lines of Code and Unintended Consequences

One of the most insightful articles that I have read (in terms of both general daily life and a software development career) is Steven Kerr's On the Folly of Rewarding A, While Hoping for B. In this article originally published in 1975, Kerr employs descriptive examples to demonstrate how a reward system can often lead to different and even opposite results than intended. Using lines of code to measure effort and developer productivity often feels like something that would be another good example for this article.

In this blog entry, I have no intention of delving into the details of most of the advantages and disadvantages of measuring and collecting metrics by counting lines of code. These are outlined in many online resources such as the Wikipedia entry, Lines of Code - Dispelling the Myths, Estimation Technique: Lines of Code, and You Can't Manage What You Don't Measure. As these articles point out, there are advantages (such as quantifiable nature and simplicity) and disadvantages (such as language differences, developer efficiency differences, problem complexity differences) to using lines of code as a metric.

For this blog entry, my focus is on how the use of lines of code as a metric may serve as a detrimental motivational force for the software developer. In other words, while using lines of code may be meant primarily to measure productivity and to understand how far along a particular task is, the unintended consequence may be poor decisions that favor larger code counts in shorter periods of time. If we applied Kerr's article directly to this discussion, we might rename the article "On the folly of rewarding potentially worse development practices that happen to lead to more lines of code, while hoping for a measurement and estimation approach that helps developers and managers manage their work loads more effectively." This is not nearly as succinct a title as the original title, but does make the point. To be clear, I am not saying that fewer lines of code is always and necessarily better than more lines of code. What I am writing about here are situations when fewer lines of code is preferable to more lines of code, but the motivation to keep that count up might influence the decision.

So how can using lines of code as a primary metric serve as a detrimental motivational force? I will outline some examples where a developer could make a decision to choose a less efficient software development technique because of pressures of delivering a certain expected number of lines of code per day or week or month. I admit that the realization that I am reducing my expected line of code count has occurred to me more than once as I refactored many lines of code into code that was cleaner, more maintainable, and more readable with much fewer lines of code.


Code Generation

I want to avoid the debate about generated code versus hand-written code here. As with so many other things in life, there are times when each has its advantages and may be more appropriate. However, even in cases where hand-writing code may generate superior code, knowledge that one's performance might be measured by the lines of code produced could lead to one using the generation tools.

For example, I like to only provide "set" (or "mutator") methods on my objects when they are known to be needed. I prefer immutable objects generally. However, "set" methods can add significantly to my overall line of code count if I put them in all classes blindly. This is really easy to do with all modern Java IDEs that will automatically generate these methods for me. In this example, measuring my productivity via lines of code might tempt me to deviate from my hard-earned preference for immutable or carefully crafted mutable objects.

This can also go the other way. For example, one might choose to directly write object-relational mapping code rather than use a third-party object-relational mapping (ORM) mapping tool to increase the line of code count. There might be valid reasons for writing one's own ORM code, but I hope that increasing the lines of code count is not one of them. In this example, I might be tempted to make a decision about ORM handling based on lines of code rather than on more technical criteria.

Code generation can be a highly useful tool and truly can make me more productive. However, it can also be used improperly to "hide" the real efficiency and even lead to unneeded code that still must be tested and maintained.


Use of COTS Products

Several of the blog entries and articles on using lines of code as a measurement tool point out one of the challenges of this approach being how to count libraries. For example, the Spring Framework brings much functionality to an application. This is provided not only by the Spring libraries themselves, but also by all the dependencies libraries it employs. Spring can help one avoid much boilerplate code (as discussed in Add Some Spring to Your Oracle JDBC Access). In extreme cases, one might be tempted to not take advantage of Spring or similar frameworks and libraries because rolling one's own code will lead to a higher count of lines of code. There is also a temptation among many of us to succumb to Not Invented Here Syndrome (even when it is not really appropriate) and the lines of code metric motivation does not make this any easier to avoid.


Redundant Code

Years ago, I saw a well-respected project manager for a major software vendor outline how this person's company's IDE made reuse easy. The person went on to demonstrate this feature, which really boiled down to a fancy CTRL-C, CTRL-V copy-and-paste implementation. This, of course, did not appeal to my ideas of proper reuse. However, such copy-and-paste reuse might be appealing to a developer that knows his or her productivity is being measured simply by lines of code rather than by the maintainability of the code.


Refactoring

While there can be drawbacks to inappropriately chosen refactoring (such as breaking working software or delaying delivery at when implemented with poor timing), I have found that refactoring can often provide significant long-term advantages to the software I develop. Perhaps more surprising is that sometimes it even helps in the short-term because it makes my next task easier and quicker to implement. For example, if I see that I'm doing the same thing I've done before in multiple locations, taking the time to refactor this redundant code into methods often makes even the short-term job easier. However, refactoring like this can be especially egregious in terms of performance measured against lines of code because time is being spent to actually reduce the measured lines of code. It can sometimes be difficult to explain (or difficult for that person to believe) how fewer counted lines of code this week than last actually corresponds to more functional software.


Doing Things the Easy Way Rather than the Better Way

If a developer knows that he or she will be rewarded or punished based on the number of lines of code he or she generates, it is tempting to take the easiest problems with the highest degree of boilerplate coding. Likewise, a developer may choose to implement something in the most wordy manner imaginable rather than taking advantage of polymorphism, reflection, and similar techniques to write more concise code. Note that I am not saying that polymorphism and reflection are always the best approaches. In fact, they can be overused and abused and there are times when the complications of these approaches are overkill. However, I am saying that there are times when they are elegant and the most efficient. Unfortunately, writing code that effectively uses reflection or polymorphism can often be more difficult than writing the code with many more lines. So, as a developer with some degree of motivation based on lines of code, it is tempting to write the lengthier code that is easier and quicker to write rather than take the time to carefully craft the smaller code that requires more time to initially write.


Dead Code (UPDATE: This section added on 11 September 2008)

Most of us have witnessed and understand the lurking dangers of dead code or unreachable code. However, placing too much emphasis on total lines of code without any regard for the quality of the underlying code can be a demotivating factor that influences one's decision to eliminate dead code. Because many of the most common negative side effects of dead code (such as maintainability, extra compilation time, more things to break) are spread out over the long term, the total cost of dead code may not be apparent and so it is easy to think that avoiding confrontation over reduced lines of code is easier and better than removing the dead code (and the lines of code that get credited for it). This is representative of many of the factors discussed here: the negative consequences may be spread out enough or incurred far enough in the future that the idea of reducing negative consequences of reducing code count now outweighs the idea of fixing long-term problems or problems whose negative cost will not be incurred until much later.


How Motivating is the Lines of Code Metric?

This is the most difficult question for me to answer quantitatively. While using lines of code as a quantitative metric for measuring performance theoretically can motivate developers to make poor decisions as discussed above, it is not easy to estimate the degree of motivation this metric has. This difficulty arises from the fact that all individuals are different in terms of their responses to the same motivations. I have also observed that the best software developers often place great importance on the quality of their work and their own craftsmanship. Therefore, it may require a high degree of motivation to sway them from doing what they feel is best. However, if one feels his or her job is on the line or that there might be a nasty confrontation or embarrassing review, even such a person with a strong desire to write the best code can be influenced by such a motivation. The degree that lines of code counting will motivate the developer is also highly dependent on the importance and frequency of its use in the work environment. The closer that the measurement of lines of code is seen to being related to rewards or punishments, the more likely it is that lines of code will lead to poor software development decisions.


Is There a Better Way to Measure Productivity and Progress?

It is generally easy to identify how any reward system motivates unintended and/or undesired results. Unfortunately, it is much more difficult to provide better systems because these alternatives often have their own advantages and disadvantages, including their own side effects or unintended consequences. In other words, it is easier to criticize and find fault with any proposed system than it is to come up with a better system.

I have read about many proposed alternatives to using lines of code as a metric and they all have their own problems and disadvantages. No matter what system we use to measure our progress and our efficiency, we can always keep in mind that these numbers are far from absolute or clear. Instead, focus should be on "orders of magnitude" and the realization that not all lines of code are created equal. Other factors to consider include the difficulty coding a particular problem, languages used, newness of the technology, and the other many inadequacies of this measurement approach. If we don't take lines of code as an absolute measurement and consider lines of code as only one facet in a much larger set of considerations, I believe we can reduce the degree of potential negative motivation that lines of code counting can entail. Most importantly, lines of code count should be only considered with other factors such as recent refactoring, difficulty of work involved, and the relationship of lines of code to actual implemented functionality.


Measuring Affects Performance

Just as measuring performance of software actually impacts the very performance we are measuring, it seems that measuring lines of code may actually impact the number of lines of code generated. When we measure software performance, we try to use tools and techniques that have as little impact on the actual performance of the software as possible. Likewise with measuring code productivity and progress, we should try to use whatever tools and approaches will have the least impact on the generated lines of code. We want code to be generated to best solve a particular problem rather than to meet a certain expected total number of lines of code.


Conclusion

The idiom/proverb "The road to Hell is paved with good intentions" is widely popular because of the many true, real-life instances of it that we have all witnessed. Clients, managers, and even developers themselves want and need methods for estimating project sizes and measuring their progress. Unfortunately, these types of estimations and measurements have never been particularly easy. Measuring lines of code is one method for approaching the measurement of progress of a software development project and does have some obvious advantages. However, measuring lines of code also has its disadvantages. One of the primary disadvantages of measuring progress with lines of code is the potentially adverse motivational effect it can have on developers when they must choose between coding to meet this motivation (more lines of code) or applying tried-and-true software development best practices.






UPDATE (11 October 2008): A somewhat related Geek Hero Webcomic is now available and is called Programmer's Salary Policy.


UPDATE (24 December 2008): The following are some related resources that have been published since my original post or that I have come across since my original post.

"Measuring programming progress by lines of code is like measuring aircraft building progress by weight." (quote commonly attributed to Bill Gates)
- Programming Quotes
- A Double Handful of Programming Quotes

Measuring Productivity of Individual Programmers

Lines of Code as a Measure of Progress

Measuring Programming Progress by Lines of Code