Why adding people to a late software project makes it later?

That statement is known as Brooks’s Law, and it was coined by the renowned computer scientist and software engineer Frederick P. Brooks. Concretely, the original statement found in his 1975 classic The Mythical Man-Month is “adding manpower to a late software project makes it later”. Basically, the idea is that adding more analysts, designers or programmers to a project running behind the original schedule will delay it even more.

Broadly speaking, the rationale of Brooks’s law is related to knowledge management. First, when new personnel is added to the project, some resources have to be diverted into training or informing the newcomers about the project’s status, vision and philosophy. That will delay the project. Further, when the number of people participating in a project increases, so does the number of communication paths. Thereby, more resources (including time) are required in order to distribute the information. Regarding this point, you may be interested in reading my entry on “Knowledge Sharing” in Software Design, Trials and Errors.

Software Design, Trials and Errors

Good software design always consider potential scenarios of failure. That’s easier said than done. Frequently, even detecting the failure may be a hard task. That’s other reason why design should always favor software construction based on low-coupled components: theoretically, it should be easier to isolate and identify the part at fault. Now, if a failure occurs, what will the system do? Mask the failure? Inform the user about the failure and ask her for directions? Try to automatically recover from failure? Nice questions, even prettier core dumps.

Trial and Error Basket

Today I read a succinct and instructive article by Professor Robert L. Glass, published in Communications of the ACM, Volume 51, Number 6 (2008). Professor Glass is a widely respected expert in the Software Engineering area, and his prose is always very eloquent and a pleasure to read. The specific article is Software Design and the Monkey’s Brain, and it attempts to capture the nature of software design. By the way, if you enjoy that article, you may also like a book by Professor Glass: Software Creativity 2.0, in which he expands on the role of creativity in software engineering and computer programming in general. Essentially, the article Software Design and the Monkey’s Brain deals with two intertwined observations:

  1. Software Design is a sophisticated trial and error (iterative) activity.
  2. Such iterative process mostly occurs inside the mind (at the speed of thought).

In the following, I’ll present my own appreciations on this topic. Regarding the first observation, I think that trial and error (I’ve also found the expression trial by error) is the underlying problem-solving approach of every software engineering methodology, like it or not. Alas, there is no algorithmic, perfectly formalized framework for creating software. In his classic book Object-Oriented Analysis and Design, Grady Booch says:

The amateur software engineer is always in search of magic, some sensational method or tool whose application promises to render software development trivial. It is the mark of the professional software engineer to know that no such panacea exists.

I totally agree. Nevertheless, some people dislike this reality. Referring to Software Engineering, a few (theorist) teachers of mine rejected calling it “Engineering”. These people cannot live without “magic”. Indeed, there are significant conceptual differences between software practitioners and some (stubborn) computer scientists, with regards to Software Engineering’s nature. These scientists are not very fond of the trial and error approach. In his article, Professor Glass presents some past investigations which verified that designing software was a trial and error iterative process. He also reflects on the differences in professional perceptions:

This may not have been a terribly acceptable discovery to computer scientists who presumably had hoped for a more algorithmic or prescriptive approach to design, but to software designers in the trenches of practice, it rang a clear and credible bell.

I like to think of software construction as a synthesis process. Specifically, there are two general factors in tension: human factors and artificial factors. The former, mostly informal, the latter, mostly formal. From the conflict, software emerges. Let’s remember that the synthesis solves the conflict between the parts by reconciling their commonalities, in order to form something new. It’s the task of the software designer to conciliate the best of both worlds. Software designers have to evaluate different trade-offs between human and artificial factors.

As a problem-solving activity, software construction is solution-oriented: the ultimate goal of software is to provide a solution to some specific problem. Such solution is evaluated by means of a model of the solution domain. But before arriving to such solution domain model, we have to form the problem domain model. The problem domain model captures the aspects of reality that are relevant to the problem. Later, designers look for a solution, as told, by trial and error. Additionally, the resources available to the designer, including knowledge, are limited. More often than not, empiricism and experience lead the search for a solution. This has an important consequence: software construction is a non-optimal process; we rarely arrive to the best solution (and which is the best solution?).

On its side, knowledge acquisition is other interesting process. During the entire cycle of development, designers have access to an incomplete knowledge. Gradually, designers learn those concepts pertinent to the problem domain model. And, when we are building the problem domain model, it often occurs that the client perspective of the problem changes, and we have to adjust to the new requirements. Interestingly enough, knowledge acquisition is a nonlinear process. Sometimes, a new piece of information may invalidate all our designs, and we must be prepared to start over.

Continue reading “Software Design, Trials and Errors”

Debugging “hello, world”

The Go command (g) will run the program starting at the given address (in this case, CS:0100) If everything goes right, the program should output the intended “hello, world!” string, and finish with the message “Program terminated normally.”

Yesterday, we took a break after long hours of intensive coding, and a coworker started establishing similarities between our current frantic coding and the (fortunately) gone days of college homework. I specifically recalled a project I had to build by using MS-DEBUG: a simple calculator in assembly, which also required the hassle of dealing with pretty and safe user input. I have no intention of looking for such listings, but I thought about revisiting, for a moment, the old and dear friend MS-DEBUG 🙂 I’ll harness a previous post in this blog, and try to build a little ‘hello, world’ program in MS-DEBUG. I know this has little value outside a personal feeling and a tad of nostalgia, maybe.

I remember that a 100 tells DEBUG to accept code in memory starting out from CS:0100. Ok.

Now comes the data, which here simply consist of the string 'hello, world!'. A neat output, however, would require newlines before and after our intended string. A newline is comprised of a carriage return (CR = ASCII 13) and a line feed (LF = ASCII 10) on the display. As DEBUG only understand hexadecimal numbers, we must use 0Dh and 0Ah for CR and LF, respectively. Except in code, we will represent hexadecimal numbers by following the value with ‘h’.) Fortunately, DEBUG also admits ASCII characters directly (and the pseudo-instructions DB and DW!), so we can express our complete string as

db 0d,0a,"hello, world!",0d,0a,"$"

Continue reading “Debugging “hello, world””