Archive

Posts Tagged ‘Project Management’

The General Principle of Software Quality

December 28, 2009 Leave a comment

I’m reading Steve McConnell’s excellent book Code Complete at the moment, which is packed full of useful information.  One thing that particularly jumped out at me is the General Principle of Software Quality.  I’ll get straight to the point, although perhaps a bit of ‘X Factor’-style suspense will spice things up a bit:

The General Principle of Software Quality…………..

Is………………………………

Improving Quality Reduces Development Costs.

This simple but counter-intuitive statement has a potentially massive impact on the way you write software.  The basic premise is that in most software development efforts, finding and fixing defects takes up a large proportion of the construction time, and so writing high-quality code with minimal defects from the start, even though it may require a little more effort upfront, is one of the best ways of reducing the total development time.  (Because as we all know, time is money!)

This being Steve McConnell, of course, everything is backed up by hard data and studies, in this case including NASA’a Software Engineering Laboratory, which found:

.. quality assurance was associated with decreased error rate but did not increase overall development cost

and a study at IBM:

Software projects with the lowest levels of defects had the shortest development schedules and the highest development productivity… software defect removal is actually the most expensive and time-consuming form of work for software

If you’re already coding based on this assumption then, as Mark & Lard would say, Carry On!  (Of course, it’s always good to be sure you’re right, and have some data to back you up in an argument).  But I’ve worked at quite a few places where management and developers alike take the opposite approach – as soon as the schedule starts to get a bit tight, quality is the first thing to suffer, with things like coding standards, testing, and reviews getting squeezed or dropped altogether in an effort to hit that deadline.  Unfortunately, this self-destructive behaviour leads to a vicious cycle which is only ever going to cause the project to get into a worse and worse state, getting delivered way later than it needed to (if it ever gets delivered at all).

So, what is quality code and how do we keep it high?  There are two main areas which are involved that tend to go hand-in-hand: the structure of the code itself (which should be readable, understandable, and generally maintainable), and the number of defects it contains.

Maintainable Code

Code structure and maintainability is important because, as many people have pointed out in the past, code is read more often than it’s written.  Even before the maintenance phase, code is often changed during initial development – functionality is added, defects are fixed, code is refactored, streams are merged.  If the code is hard to understand, it’s much more likely that changes will introduce new defects – and this is magnified during maintenance, when a different set of developers are working on the code.  And when you consider that Yourdon reports that developers making a small (1-5 line) code change have a shocking 50% or more likelihood of introducing a new defect, you can see why easily maintainable code is so important.  I won’t go into detail here about what constitutes maintainable code, but things like well-named variables and routines, cohesive classes and routines (with a strong purpose), short routines, and loosely coupled classes all help.  (See Code Complete or any other development book for more details!)

Once you’ve discovered how to write maintainable code, the best tools at your disposal to ensure it’s being done by your development team are to write a set of coding standards, and then hold code reviews to ensure the standards are being met – more on that later.  Of course, people can’t write good code if they don’t know how, so getting developers up to speed in the first place (using training courses, pair programming, code reviews, etc) is also important here.  And tell them that maintainability is the primary goal of their code, not (for example) minimal lines or performance – you might be surprised how well most developers respond to such goals (which is of course covered in the book, with evidence from yet more studies!) 

Defect-Free Code

Nobody plans to put defects in their code, and in a perfect world it wouldn’t be an issue.  Unfortunately, in this world it’s a very real issue and one that has to be taken into account at an early stage:

Studies at the Software Engineering Institute have found that developers insert an average of 1 to 3 defects per hour into their designs and 5 to 8 defects per hour into code (Humphrey 1997)

Other studies have shown error densities of between 25 and 100 defects per 1000 lines of code, depending on project size.  These defects have many causes – incorrect requirements, design problems, coding errors, mis-communications, changes to poorly understood code, typos, and so on.  Although most are caused by developers and appear in the code, defects in the requirements and design are also common and can have a much greater impact, and also have to be dealt with.

So now that we’ve come to accept that defects are a part of life, what can we do about them?  A large helping of unit tests lovingly applied using TDD will presumably do the trick?  Well, it’s certainly a good start, but only part of the answer according to McConnell.  The following table lists some of the activities which can be used to help find and prevent defects (the number shown is the average percentage of defects in a system found by that method):

Method Defects Found
Informal Design Reviews 35%
Formal Design Inspections 55%
Informal Code Reviews 25%
Formal Code Inspections 60%
Unit Test 30%
Integration Test 35%
Regression Test 25%
System Test 40%

There were a couple of things that surprised me about this.  The first, as I’ve been concentrating so much on TDD and unit testing lately, was how few of the defects were found by unit testing.  Although it’s not as bad as it seems – the numbers for unit testing were actually from 15 to 50%, so done well it can be more effective, and if you have automated unit tests then this will also cover you to some degree for regression testing too, further boosting it’s usefulness.

The second surprising element was how useful code reviews can be, particularly considering how easy to implement and less time-consuming they are compared to full unit testing.  Some people recommend code reviews as one of the first things you should implement in a development team (for example Roy Osherove), and based on this it’s easy to see why.  Of course, there is a little work involved – get some standards/guidelines in place, decide on a good format for the reviews (the more formal the better, apparently), and so on – but it does seem like quite an easy win for quality.  And it works just as well for requirements and design as it does for code!  Plus you get the extra benefits of spread knowledge, developer learning, and shared code ownership.

A Strategy for Quality

The important thing to take from this is that no single technique is enough – you need multiple methods to ensure high software quality.  Don’t forget that the percentages found are cumulative, so a 50% + 50% detection rate would only find you 75% of the defects.  And the different methods also tend to uncover different kinds of defects and quality issues – no unit test is going to point out all the magic numbers being used, for example, and it can be hard to spot an off-by-one error just by looking at the code.  Different people also tend to spot different errors, another plus point for some kind of review.

Conclusion

I think you get the message by now.  The key point to remember is that you always need to aim for high quality code: Plan your quality strategy by using multiple methods, make sure everyone knows what they are and that quality is a primary goal, and don’t stop doing them at the first hint of a slipping deadline!

Check out this article by Steve McConnell, which covers much the same subject, but with much more authority than I could ever muster.

One more time: Improving Quality Reduces Development Costs! Don’t forget to tell your project manager.

Advertisements
Categories: Development Tags: ,

The Mythical Man-Month

September 4, 2009 Leave a comment

As part of my learning drive, I decided to read some of the books I’ve been hearing about. The first one I decided to tackle was the often-quoted Mythical Man-Month (TMMM) by Frederick Brooks, originally written in 1975 based on Brooks’ experience managing development of systems including IBM’s Operating System/360. This was a time when mainframes roamed the earth, assembler was still the language of choice for many, and memory cost around $100,000 a Meg. Although I thought the book would be somewhat outdated, with it’s small size (at 300-odd pages) I figured I might actually be able to finish it this side of Christmas!

Mythical Man-Month Book Cover

The Mythical Man-Month Cover

Now, some of this book is indeed out of date – there is much talk of assembler, 5-foot tall system manuals, batch programming and debugging due to lack of system time, and other problems associated with the huge expense of computer systems. Some is also applicable only to really big systems – at it’s peak, the OS/360 team employed over 1000 people, and over 5000 man-years went into it’s design, construction, testing & documentation! And I thought our project was big..
But the surprising thing is how relevent most of the book still is today – indeed, there are still active online discussions regarding some of the points, and the book is even referred to by those in other industries (EXAMPLES). I would say of the original 15 chapters, at least 10 of them are still totally applicable today – and more than that, contain lessons that many of the IT managers and developers I’ve worked with would do well to learn. In fact, in some ways it’s quite dishartening to realise that the things we still struggle with today are the same problems we had back then, and while in some ways we’ve moved forward, in many ways we’re no better off now than we were more than 30 years ago. (Yeah I’m talking about you, estimating difficulties/maintenence nightmares/changing requirements/project slippage!) The most disturbing thing is that there are solutions described for many of these problems, and here in 2009 there are still many who don’t employ them!
Anyway, below I’ve listed a few of the more pertinent points raised in the book, as well as some thoughts on them. I must warn you, this is a rather lengthy post – but then it is a book full of good ideas. I mean, how many books can you name that are still so well known nearly 35 years after they were published, or ones that have a law named after them for that matter?! (Brooks law – see XXXX). So I hope you have a comfy chair..
Estimation
———-
Difficult to estimate – developers optimists by nature,tend to think in terms of exchangeable man-months, when falling behind often more people added (using petrol to put out a fire).
Developers tend to think about isolated development – turning into finished product, and part of a programming system, takes 9x longer.
Optimism – we tend to think that things will go well. For a single task, this may be true, as there are a range of chances. But for a whole system made of many tasks, the chance that all of them will go well is almost negligable.
Man-Months – men & months only interchangeable when the task requires no communication between workers, such as cotton picking. The more communication needed, and less the task can be partitioned, the more overhead there is for adding each new person. Some very complex tasks with high communication needs and very limited flexibility in partitioning, adding more people can actually take longer:
Brooks law – adding manpower to a late software project makes it later
Some tasks are also sequential:
‘Takes 9 months to make a baby regardless of how many women are involved’
Many IT systems suffer from both of these issues.
1/3 planning, 1/6 coding, 1/4 component test, 1/4 system test (based on waterfall)
Most projects don’t allow enough time for system testing, which is where many go wrong. Problems here at the end of the schedule particularly bad, as they are a surprise to everyone, and can be difficult to identify and fix. Also very expensive, as fully staffed, and not delivering could have large financial implications.
Deadlines often set by clients, but software will take as long as it takes whatever they say. Omlette example – customer wants omlette in 2 minutes. They can have it raw, or wait for it. (Or cook can turn up the heat, so it’s burned on the outside and raw in the middle).
Overall – we need to develop methods of estimating more accurately, including recording productivity rates, bug incidence counts, and creating estimation rules. Until then, managers must take these things into account and give realistic estimates, whether the client likes them or not.
What happens when project late – e.g. task with 4 milestones should take 4 months, but 1st task takes 2 months? People usually add manpower, but taking the communication overhead into account, they will need to add quite a lot more early on to realise any benefit, and ths will often not help anyway. This is taken into account in agile, with measurement of velocity.
Recent arguments against Brooks law – ‘cathedral and bazaar’, open source
Conceptual Integrity
——————–
Brooks states that conceptual integrity is the most important aspect of systems design – it’s more important to have a coherent model than extra functionality. Like cathedrals created over many generations – often different parts are of different styles, and while each may be magnificent, the overall effect is jarring. Reims is the counter example, where several generations have stuck to the original concept, sacrificing some of their own ideas to keep the overall design ideas intact.
Conceptual Integrity achieved by having a single (or very few) Architects – single philosophy for how the system works. Not a technical architect, more a ‘user experience’ manager responsible for the UI, and the user’s mental model of the software (including it’s interfaces with other systems). Architect works on behalf of the user, making the most of the available systems to get the most benefit for the customer.
While some think this leaves less freedom to the implementors and leads to an aristocracy with the architects ruling over the developer plebs, this has to be partly the case to achieve the integrity, but in reality the developers still get full reign on how the system works from a technical perspective.
Second System Effect
——————–
The second system is a designer’s most dangerous. In the first, ‘he knows he doesn’t know what he’s doing, so he does it carefully and with great restraint’. But all of the extra ideas are saved up, and put into the second system.
Productivity
————
Also, productivity doesn’t increase linearly as systems grow – data shows an exponent of around 1.5, so as system complexity (LOC) increases, man-months spent creating it increase at a greater rate.
There is also the problem of wasted time – in one study, estimates wree done carefully but the coding work still took around twice as long as expected. When time was recorded at a low level, it was found that only roughly half the time was taken actually coding, the other half was spent in meetings, unrelated work, personal time, etc.
Throw One Away – Accepting Change
———————————
In chemical engineering, you don’t go straight from a lab process to production, they build a ‘pilot plant’ first to try scaling up the process. We need to do this in software, but usually don’t. The first system we make is often crap, and we need to start over. This is almost inevitable, so we should plan for this.
This is in fact just one aspect of the fact of change – requirements change, technologies change, and you need to be prepared . ‘The first step is to accept the fact of change as a way of life, rather than an untoward and annoying exception. […] both the actual need and the user’s perception of than need will change as systems are built, tested and used.’ (Talking about the situation for hardware) ‘…the very existance of a tangible object serves to contain and quantize user demand for changes. Both the tractability and the invisibility of the software product expose it’s builders to perpetual changes in requirements.’ The designer
Brooks gives advice on designing for change, including modularisation, well-defined interfaces, and good documentation of these.
The book also discusses the importance of enabling change in the organisation, which is much harder. Cosgrove reccomends that all plans, milestones and schedules should be treated as tentative to facilitate change.
(Brooks later points out that this is only appropriate to waterfall-style development and not iterative).
Two Steps Forward, One Step Back – Software Maintenance
——————————————————-
When software is mainained, usually this ‘maintenance’ involves adding extra functionality. The problem is, this new functionality has a good chance (20-50%) of introducing new b=ugs themselves. In addition, bug fixes that are applied sometimes fix the local problem, but go on to create further problems in other parts of the system. A study of OS releases showed that as time goes on, structure gets broken and entropy increases in the system, and more and more time is spent fixing the defects introduced by the releases. Eventually, adding new functionality is not worth the effort and the system must be replaced. ‘Program maintenance is an entropy-increasing process, and even its most skillful execution merely delays the subsidence of the system into unfixable obsolescence.’
Testing
——-
A lot of bugs come from areas of the system that are under-specified.
Build scaffolding – there could well he half as much code in scaffolding as in actual code. (Some early TDD!) ‘One form of scaffolding is the <i>dummy component</i>, which consists only of interfaces and some faked data or some small test cases.’
Project Slippage
—————-
Most projects don’t suffer a catastrophic failure, they go wrong a bit at a time. ‘How does a project get to be a year late? …One day at a time’. ‘Usually, however, the disaster is due to termites, not tornadoes; and the schedule has slipped imperceptibly but inexorably.’
One way to battle this is to have very specific, unabmiguous milestones. People don’t like to give bad news, and if something has a fuzzy meaning, it’s all to easy to fool yourself and your manager that things are going Ok. Studies show that people gradually reduce over estimates as time goes on, but underestimates stay low until around three weeks before the deadline.
Brooks talks about how small delays often get ignored, but as soon as you start accepting these delays, the whole project can slip. You need to stay on top of things – the team needs to have ‘hustle’, as baseball coaches would say. PERT charts (apparently like GANTT charts today) can be useful to identify the slippages that really are problematic as they’re on the critical path. (This is like the ‘broken window’ anology discussed in TPP).
——
This being the anniversary edition, it included all 16 of the original essays from ’75, plus a couple of new ones and reflection on the ideas presented in that first edition.
No Silver Bullet (1986)
———————–
There wil be no magnitude increase in productivity in the next 10 years. Two kins of complexity in a system – Essential and Accidental (incidental). Essesntial is core to the problem and incidental is the complexity caused by our way of programming it. The central argument is that as essential complexity can’t really be changed, so unless the incidental complexity accounts for over 9/10 of the overall complexity, even shrinking it to zero wouldn’t increase productivity tenfold. Brooks thinks it accounts for way less that that, and also that the biggest problems with accidental complexity have now been removed, so those improvements will be fairly small from here on out. As such, we need to focus on attacking the essential complexity of software. To do this, Brooks advises:
– Buying instead of building
– Rapid prototyping in planned iterations to help get the requirements right
– Growing systems organically, adding functionality as they are used
‘I believe the hard part of building software to be the specification, design, and testing of this conceptual construct, not the labour of representing it and testing the fidelity of this representation.’
‘The hardest single part of building a software system is deciding precisely what to build.’ – This is really difficult, and causes big problems when it’s wrong. This is why Brooks advocates rapid prototyping to work out the user requirements.
He also talks about growing software as opposed to building it – developing increamentally, starting out with a skeleton system that goes from end-to-end, and fleshing out the details as you go along (Like ‘tracer bullets’ in PP). This aids team morale considerably, and it means you always have a working system.
Brooks isn’t being pessimistic as some suggest, and doesn’t say we can’t EVER achieve such an increase, or that we can’t do it by combining multiple techniques – just that there won’t be a single cure to end all development woes.
30 Years On
———–
In the last chapter, Brooks goes over some of the suggestions. He states that a few of them are based on Waterfall, and while they are correct in terms of dealing with that approach, iterative development has now taken over and negates the need for some of those suggestions.
‘The waterfall model, which was the way most people thought about software projects in 1975, unfortunately got enshrined into [the DoD specification] for all military software. Thsi ensured it’s survival well past the time when most thoughtful practitioners had recognized it’s inadequacy and abandoned it. Fortunately, the DoD has since begun to see the light.’
The book ends on something of a high, with Brooks describing how when he finished college in the 50s, he could read all computer journals and conference proceedings. As time has gone on, he’s had to kiss goodbye to sub-discipline after sub-discipline, because there’s so much to know. So much opportunity for learning, research, and thought. ‘What a marvellous predicament! Not only is the end not in sight, the pace is not slackening. We have many future joys.’

Well, some of it is indeed out of date – there is much talk of assembler, 5-foot tall system manuals, batch programming, lack of system space/time, and other problems associated with the huge expense of computer systems back then. Some is also applicable only to really big systems – at it’s peak, the OS/360 team employed over 1000 people, and over 5000 man-years went into it’s development & maintenance! And I thought our ACME work management system was big..

But the surprising thing is how relevant most of the book still is today – indeed, there are still active online discussions regarding many of the points. I would say of the original 15 chapters, at least 10 of them are still totally applicable today, as they concentrate on the human side of software management. More than that, they contain lessons that many of the IT managers and developers I’ve worked with would do well to learn. In fact, in some ways it’s quite disheartening to realise that the things we still struggle with today are the same as those we struggled with back then – in many ways, it seems we’re no better off now than we were more than 30 years ago. It’s not so much that there are no solutions to the problems, more that there are no easy solutions – software development is hard. And it’s also an essentially different beast to the kind of things we’ve had to manage before, such as building projects, and yet many people still approach it using the same techniques and expect the same results. Of course, it’s still a young industry, so perhaps if a few more people read this book and those like it, in another 30 years, we might be starting to get somewhere..

Anyway, below I’ve discussed a few of the more pertinent points raised in the book. I must warn you, this is a rather lengthy post – but then it is a book full of good ideas. I mean, how many books can you name that are still so well known nearly 35 years after they were published, or ones that have a law named after them for that matter?! So I hope you have a comfy chair.

Estimation

As most developers would agree, software is inherently difficult to estimate – but it’s not always clear why. Early on in the book, Brooks gives some of the reasons behind this – as with points throughout the text, backed up by impartial research where possible:

  • Developers are Optimists – we tend to imagine things going well. While this may happen for an individual piece of work, the chances of everything going well on a project are negligible, but instead of taking this into account we tend to add up all of the ‘best-case scenario’ estimates and arrive at an unrealistic overall figure.
  • Developers Consider Isolated Development – on seeing some new application or website, you’ll often hear a dev say ‘that’s easy, I could code that in a weekend!’. I’ve heard this many times, even from experienced developers. The fact is, knocking up a quick program that works on a single machine is generally easy – it’s turning this into a polished, tested, documented product that works in a full-scale environment that takes the time.
  • Men and Months are not Interchangeable – certain tasks can be split up amongst people and retain the same efficiency. The sort of tasks this applies to are those with no communication required, no overlap between the different partitions – sewing a field, for example. Writing software is not such a task. As more people get involved, more communication is required, and efficiency drops – in fact at a certain point, adding more people can start to increase the time taken to complete the overall task. This is often not taken into account, and projects are planned with a certain number of ‘man-months’ divided between an arbitrary number of workers, with the end result being missed deadlines.
  • Productivity doesn’t increase Linearly – as studies into large-scale developments have shown, the rate of work decreases as systems grow. Data show an exponent of around 1.5, so as system complexity increases (as measured in lines of code), it takes increasingly more effort to add extra functionality. This isn’t something most people take into account, but can make a huge difference for larger developments.
  • Not all Time is Used – in further studies, when time was recorded at a low level, it was found that only about half of a developer’s time was spent on project development, with the other half occupied by meetings, unrelated work, personal items, and so on.

    While most people are aware of the general problems, if not the specific causes, I for one always seem to end up on projects with unreasonable deadlines. I think this is a combination of the factors above, along with what Brooks alludes to in the book – that it can be very difficult to explain to a customer why it’s going to take such a seemingly long time to create what appears to be a simple application. Until we have a more solid foundation for software estimation (which doesn’t seem forthcoming), software managers need to trust their experience and give realistic dates, and not bow to client pressure and give ridiculously optimistic dates that aren’t going to help anybody in the long run.

    Project Overrun

    Related to the difficulties in estimation is the often-cited problem of software projects often going way, way, waaaaaay past their initial due date – usually with enormous increases in budget to boot. As well as estimation issues, Brooks gives several other factors which contribute to this problem – although he later points out that most of these only really apply to waterfall style development, which has been superseded by incremental development in many cases (which someone would tell my manager..)

    One such factor, which is extremely common if my experiences are anything to go by, is that the deadlines are often set by the customer. This is likened to the cooking of an omelet – the customer might say he wants his omelet in two minutes. And after two minutes, if the omelet is not cooked, he can either wait – or eat it raw. The cook may try to help by turning up the heat, but you’ll just end up with an omelet which is burned on the outside and raw on the inside. Sadly, I’ve worked on a couple of projects where the customer ended up with a burned/raw application because ‘it has to be finished by X!’

    The book also suggests that most projects don’t give enough time to testing, which can be a fatal mistake. A lot of issues are not found until the testing phase, by which time the deadline has nearly arrived – slippage here comes as a surprise to everyone, as things seemed to be going well, and once the wheels of enterprise have been put into motion, late delivery can have serious financial implications. Brooks even gives his breakdown of project times (again, this only applies to waterfall) – 1/3 planning, 1/6 coding, 1/4 component test, and 1/4 system test.

    Also discussed is what happens when it’s realised that the deadline is slipping. Often, if it gets near the end of a project and there are schedule problems, more resource gets allocated to the project – but what with the man-month interchangeability problem, and the time it takes to get new people up to speed, such actions will only ever make things worse. It’s the old ‘using petrol to put out a fire’ theme, which is where we get Brooks’ Law:

    Adding manpower to a late software project makes it later.

    Conceptual Integrity

    Conceptual integrity within a system is about keeping the way it works coherent – following a core set of principles that apply throughout the program, from a user’s perspective. Brooks states that conceptual integrity is the most important aspect of systems design – it’s more important to have a coherent model than extra functionality. This is difficult to achieve in software, which is usually designed and nearly always built by multiple people.

    Cathedrals created over many generations have similar issues – often different parts are of different styles, and while each may be magnificent, the overall effect is jarring. Reims is the counter-example, where several generations have stuck to the original concept, sacrificing some of their own ideas to keep the overall design ideas intact. Conceptual Integrity can be achieved by having a single (or very few) Architects, who share a single philosophy for how the system works.

    When Brooks talks of an architect, he doesn’t mean a technical architect as I would think, more a ‘user experience’ manager responsible for the UI and the user’s mental model of the software. The architect works on behalf of the user, making the most of the available systems to get the most benefit for the customer. This is an interesting concept and not something I’ve seen much of – typically, on the medium-sized business application I’ve seen, there is no-one really considering the user experience. The BAs will collect and define the user requirements, but will have little input into the actual interface of the system, which is usually left up to the developers.

    I would think this may be more of an issue for larger systems, but Brooks states he’d have one architect role defined in teams as small as four, so it’s definitely something I’ll try to look further into in future projects.

    Second System Effect

    Another of the many phrases you’ve probably heard that comes from this book is the ‘second system effect’. The idea is that the second system anyone designs is the most dangerous and most likely to fail. In the first, ‘he knows he doesn’t know what he’s doing, so he does it carefully and with great restraint’. But all of those good ideas he has are saved up, and all piled into the second system.

    Accepting Change

    The thing that surprised me the most in TMMM was the recognition back in ’75 of the need to adapt to requirements change as the project progresses. Although development was all done in a waterfall fashion, the language used to describe dealing with change sounds like something straight out of an agile book:

    ‘The first step is to accept the fact of change as a way of life, rather than an untoward and annoying exception. […] both the actual need and the user’s perception of that need will change as systems are built, tested and used.’

    Brooks gives advice on designing for change, including modularisation, well-defined interfaces, and good documentation of these. Another piece of advice is to always Throw One Away – with new types of system, you are still working out the best way of tackling problems, so you should plan to use the first as a prototype and not use it at all in production.

    The book explains that we need to be prepared for change, because as well as technical and business changes, the users will not know exactly what they want until they try the system – this is one of the main driving forces behind agile/iterative development, which Brooks now recognises as a better way of developing software. In a recent look back at the original articles, Brooks states:

    ‘The waterfall model, which was the way most people thought about software projects in 1975, unfortunately got enshrined into [the DoD specification] for all military software. This ensured it’s survival well past the time when most thoughtful practitioners had recognized it’s inadequacy and abandoned it. Fortunately, the DoD has since begun to see the light.’

    Software Maintenance

    When software is maintained, unlike maintenance of things such as mechanical or electrical systems, usually this ‘maintenance’ involves adding extra functionality. The problem is, this new functionality has a good chance (a reported 20-50%) of introducing new bugs – ‘Two steps forward, one step back’. In addition, bug fixes that are applied sometimes fix the local problem, but go on to create further problems in other parts of the system.

    A study of OS releases showed that as time goes on, structure gets broken and entropy increases in the system, and more and more time is spent fixing the defects introduced by the releases. Eventually, adding new functionality is not worth the effort and the system must be replaced. As Brooks succinctly puts it,

    ‘Program maintenance is an entropy-increasing process, and even its most skillful execution merely delays the subsidence of the system into unfixable obsolescence.’

    Project Slippage

    Most projects don’t suffer a catastrophic failure, they get slowly later as time goes on. ‘How does a project get to be a year late? …One day at a time.’

    Brooks suggests one way to battle this is to have very specific, unambiguous milestones. People don’t like to give bad news, and if something has a fuzzy meaning, it’s all to easy to fool yourself and your manager that things are going Ok. Studies show that people gradually reduce over-estimates as time goes on, but underestimates stay low until around three weeks before the deadline.

    Brooks talks about how small delays often get ignored, but as soon as you start accepting these delays, the whole project can slip. You need to stay on top of things – the team needs to have ‘hustle’, as baseball coaches would say.

    PERT charts (apparently like GANTT charts today) can be useful to identify the slippages that really are problematic as they’re on the critical path.

    No Silver Bullet (1986)

    This being the anniversary edition, there are an extra couple of sections, including this well-known essay from 1986. The basic precept is this: there will be no magnitude (10x) increase in development productivity in the next 10 years. One of the core concepts here is that there are two kinds of complexity in a system – essential and accidental (or incidental). Essential is core to the problem and incidental is the complexity caused by our way of programming it.

    The central argument is that unless the incidental complexity accounts for over 9/10 of the overall complexity, even shrinking it to zero wouldn’t increase productivity tenfold. Brooks thinks it accounts for way less that that, as the biggest problems (low-level languages, batch debugging, etc) have now been removed, so improvements will be fairly small from here on out. As such, we need to focus on attacking the essential complexity of software. To do this, Brooks suggests:

    • Buying instead of building software
    • Rapid prototyping in planned iterations to help get the requirements right
    • Growing systems organically, adding functionality as they are used

    These are all forward-looking views for ’86 which have largely been borne out in the intervening years. The last two points are related to the problems of capturing and identifying requirements properly, which Brooks sees as being the most difficult area, which is where we can make the most improvements:

    ‘The hardest single part of building a software system is deciding precisely what to build.’

    30 Years On

    At the end of the book, Brooks looks back on the assumptions and ideas presented those many years ago. Most have proved to be correct, although a few of them are based on Waterfall development, and while they are correct in terms of that approach, iterative development has rendered some of those ideas redundant.

    The book ends on something of a high, with Brooks describing how when he finished college in the 50s, he could read all computer journals and conference proceedings. As time has gone on, he’s had to kiss goodbye to sub-discipline after sub-discipline, because there’s so much to know. So much opportunity for learning, research, and thought – ‘What a marvellous predicament! Not only is the end not in sight, the pace is not slackening. We have many future joys.’

    Amen.