Talk:No Silver Bullet

From Wikipedia, the free encyclopedia
Jump to: navigation, search
WikiProject Software / Computing   
WikiProject icon This article is within the scope of WikiProject Software, a collaborative effort to improve the coverage of software on Wikipedia. If you would like to participate, please visit the project page, where you can join the discussion and see a list of open tasks.
 ???  This article has not yet received a rating on the project's quality scale.
 ???  This article has not yet received a rating on the project's importance scale.
Taskforce icon
This article is supported by WikiProject Computing.
 

No need to paste the ENTIRE "No Silver Bullet" article here! I deleted it as it takes up space unnecessarily and, besides, it is linked in the references section of the Wikipedia article. We need this space to discuss the actual Wikipedia article. Thanks. 82.43.195.131 15:55, 16 October 2006 (UTC)

I don't think the edits of 86.139.127.180 are in good faith. Example: "As frustrating as this may be, he is most probably right. Most of us are blub programmers." 69.156.156.191 21:17, 5 February 2007 (UTC)

Tenets in NSB[edit]

  • Immediacy - enables one to maintain an overview of complexity. The slow turnaround of batch programming means that one inevitably forgets the minutiae, if not the very thrust, of what one was thinking when he stopped programming and called for compilation and execution. This interruption is costly in time, for one must refresh one s memory. The most serious effect may well be the decay of the grasp of all that is going on in a complex system. —Preceding unsigned comment added by 192.174.37.50 (talk) 23:43, 15 December 2009 (UTC)

swapped accidental and essential[edit]

I think this interpretation is wrong: "It should be noted that Brooks states that this limitation to programmer productivity only applies to essential complexity and he advocated challenges to accidental complexity which he believes can lead to significant (perhaps greater than 10 fold in a 10 year period) improvements." I think brooks says that accidental (which is not meant as "by accident", but as "self made by developers") complexity was almost eliminated in the last few years (he makes this clear in the 1995 edition of the The Mythical Man-Month), but still there is no technique insight to improve the productivity of a software team by an order of magnitude it 10 years because we cannot tackle the essential complexity of the problems to be solved. Oderbolz 10:29, 14 October 2007 (UTC)

I agree, that is totally backwards. I've swapped it around to "... advocated challenges to essential complexity...". --68.0.124.33 (talk) 21:28, 23 September 2008 (UTC)

Critics[edit]

What about putting some information on critics of the article? Like this one: Why Software Is Bad and What We Can Do to Fix It

See also How to Construct 100% Bug-Free Software, also by Savain. He addresses specific claims by Brooks and how to handle essential complexity.

Savain is not only a kook, but he has explicitly rejected the suggestion of submitting his ideas to a peer-reviewed journal. So it looks like his ideas are not only inadmissable into Wikipedia, they will always be so.—greenrd (talk) 16:05, 3 May 2010 (UTC)
Ouch! I just read his blog, not only is he a kook, he is also very aggressive and insulting. Another weirdo with a blog. 200.114.149.47 (talk) 21:29, 24 August 2010 (UTC)
Ad hominem arguments are not only useless and time wasting, they are a sign of cowardice.

I think this article shows well that Brooks paper is misunderstood by many. When Savain writes "No other paper in the annals of software engineering has had a more detrimental effect on humanity's efforts to find a solution to the software reliability crisis. Almost single-handedly, it succeeded in convincing the entire software development community that there is no hope in trying to find a solution." he fails to see that brooks writes from an optimistic position. Brooks admits that IT has seen a 6 order of magnitude improvement in performance, but he essentially says that the human problem will remain, no matter what technology we use. Also Savain says: " When Brooks wrote his famous paper, he apparently did not realize that his arguments applied only to algorithmic complexity." Brooks does not speak about a specific way to write software, his argument is valid for algorithmic or other software. For me, the most important part of brooks article is this: "I believe the hard part of building software to be the specification, design, and testing of this conceptual construct, not the labor of representing it and testing the fidelity of the representation. We still make syntax errors, to be sure; but they are fuzz compared with the conceptual errors in most systems." The problem is not a technical one (as Weinberg puts it: its always a people problem). Our rules and laws, our processes are complex, that is why it is hard to model them correctly. —Preceding unsigned comment added by Oderbolz (talkcontribs) 10:49, 14 October 2007 (UTC) \

I don't think it's worthwhile to debate Savain's points. He is a kook. His arguments don't make sense, they are a mix of nonsensical statements and insults. 201.231.81.53 (talk) 04:54, 4 November 2011 (UTC)

Dubious[edit]

The "abridged" version of the "No Silver Bullet" article differs in more ways than length from other versions on the web. It makes some assertions that aren't in the others, and removes some text that would tend to contradict the new assertions. Finally, it appears to support notions about micropayment software licensing schemes that the author of the abridgement would personally profit from, and which were unlikely to have been considered seriously by the real Fred P. Brooks. I vote that it be removed or permanently marked as propagandized. 24.165.61.213 (talk) 08:08, 26 December 2007 (UTC)

DMC 13 Aug 2008[edit]

"Accidental Complexity" is easy to generate with one line of C++. This is a real example from production S3 code.

Keep in mind that since we pay BOM dollars for the CPU that runs this, every machine instruction literally costs the company money.

An "old school" method to set the machine width below might be "dMachineWidth = 20.0", and translate into 1 to 3 machine instructions. The code below translated into 96 instructions that we can see, and with calls into compiler functions probably makes the total overhead over 140 machine instructions.

The S3 code is: "CModel::Instance()->GetJob().GetJobStat().SetMachineWidth(dMachineWidth);"

First, a call is made to get the instance of the Model object, then a call to get the Job object, then a call to get the JobStat object, then finally a call to set the Machine Width.

Here's what the source looks like in machine code:

 00023     8b 45 f8         mov     eax, DWORD PTR _this$[ebp]
 00026  dd 40 10         fld     QWORD PTR [eax+16]
 00029  d9 9d 30 ff ff ff                fstp    DWORD PTR tv94[ebp]
 0002f  d9 85 30 ff ff ff                fld     DWORD PTR tv94[ebp]
 00035  51               push    ecx
 00036  d9 1c 24         fstp    DWORD PTR [esp]
 00039  e8 00 00 00 00   call    ?Instance@CModel@@SAPAV1@XZ ; CModel::Instance
 0003e  8b c8            mov     ecx, eax
 00040  e8 00 00 00 00   call    ?GetJob@CModel@@QAEAAVJobProxy@@XZ ; CModel::GetJob
 00045  8b c8            mov     ecx, eax
 00047  e8 00 00 00 00   call    ?GetJobStat@JobProxy@@QAEAAVJobStat@@XZ ; JobProxy::GetJobStat
 0004c  8b c8            mov     ecx, eax
 0004e  e8 00 00 00 00   call    ?SetMachineWidth@JobStat@@QAEXM@Z ; JobStat::SetMachineWidth

It contains the four calls, and those functions in turn are (beginning with "CModel::Instance()")

 00000     55               push    ebp
 00001  8b ec            mov     ebp, esp
 00003  81 ec c0 00 00 00                sub     esp, 192               ; 000000c0H
 00009  53               push    ebx
 0000a  56               push    esi
 0000b  57               push    edi
 0000c  8d bd 40 ff ff ff                lea     edi, DWORD PTR [ebp-192]
 00012  b9 30 00 00 00   mov     ecx, 48                        ; 00000030H
 00017  b8 cc cc cc cc   mov     eax, -858993460                ; ccccccccH
 0001c  f3 ab            rep stosd
 0001e  b9 00 00 00 00   mov     ecx, OFFSET ?instance@?1??Instance@CModel@@SAPAV2@XZ@4V2@A
 00023  e8 00 00 00 00   call    ??1CModel@@QAE@XZ ; CModel::~CModel
 00028  5f               pop     edi
 00029  5e               pop     esi
 0002a  5b               pop     ebx
 0002b  81 c4 c0 00 00 00                add     esp, 192               ; 000000c0H
 00031  3b ec            cmp     ebp, esp
 00033  e8 00 00 00 00   call    __RTC_CheckEsp
 00038  8b e5            mov     esp, ebp
 0003a  5d               pop     ebp
 0003b  c3               ret     0

Note that at address 00023 and 00033 there are two calls to compiler functions. We have no idea how much overhead is there, but likely at least 20+ instructions per call, and perhaps many more.

Here's the GetJob() call:

 00000     55               push    ebp
 00001  8b ec            mov     ebp, esp
 00003  81 ec cc 00 00 00                sub     esp, 204               ; 000000ccH
 00009  53               push    ebx
 0000a  56               push    esi
 0000b  57               push    edi
 0000c  51               push    ecx
 0000d  8d bd 34 ff ff ff                lea     edi, DWORD PTR [ebp-204]
 00013  b9 33 00 00 00   mov     ecx, 51                        ; 00000033H
 00018  b8 cc cc cc cc   mov     eax, -858993460                ; ccccccccH
 0001d  f3 ab            rep stosd
 0001f  59               pop     ecx
 00020  89 4d f8         mov     DWORD PTR _this$[ebp], ecx
 00023  8b 45 f8         mov     eax, DWORD PTR _this$[ebp]
 00026  05 10 23 00 00   add     eax, 8976              ; 00002310H
 0002b  5f               pop     edi
 0002c  5e               pop     esi
 0002d  5b               pop     ebx
 0002e  8b e5            mov     esp, ebp
 00030  5d               pop     ebp
 00031  c3               ret     0

Now GetJobStat():

 00000     55               push    ebp
 00001  8b ec            mov     ebp, esp
 00003  81 ec cc 00 00 00                sub     esp, 204               ; 000000ccH
 00009  53               push    ebx
 0000a  56               push    esi
 0000b  57               push    edi
 0000c  51               push    ecx
 0000d  8d bd 34 ff ff ff                lea     edi, DWORD PTR [ebp-204]
 00013  b9 33 00 00 00   mov     ecx, 51                        ; 00000033H
 00018  b8 cc cc cc cc   mov     eax, -858993460                ; ccccccccH
 0001d  f3 ab            rep stosd
 0001f  59               pop     ecx
 00020  89 4d f8         mov     DWORD PTR _this$[ebp], ecx
 00023  8b 45 f8         mov     eax, DWORD PTR _this$[ebp]
 00026  05 4f 01 00 00   add     eax, 335               ; 0000014fH
 0002b  5f               pop     edi
 0002c  5e               pop     esi
 0002d  5b               pop     ebx
 0002e  8b e5            mov     esp, ebp
 00030  5d               pop     ebp
 00031  c3               ret     0

Finally! We set the machine width:

 00000     55               push    ebp
 00001  8b ec            mov     ebp, esp
 00003  81 ec cc 00 00 00                sub     esp, 204               ; 000000ccH
 00009  53               push    ebx
 0000a  56               push    esi
 0000b  57               push    edi
 0000c  51               push    ecx
 0000d  8d bd 34 ff ff ff                lea     edi, DWORD PTR [ebp-204]
 00013  b9 33 00 00 00   mov     ecx, 51                        ; 00000033H
 00018  b8 cc cc cc cc   mov     eax, -858993460                ; ccccccccH
 0001d  f3 ab            rep stosd
 0001f  59               pop     ecx
 00020  89 4d f8         mov     DWORD PTR _this$[ebp], ecx
99  
m_Stat.fMachineWidthM = fWidth;
 00023     8b 45 f8         mov     eax, DWORD PTR _this$[ebp]
 00026  d9 45 08         fld     DWORD PTR _fWidth$[ebp]
 00029  d9 58 3b         fstp    DWORD PTR [eax+59]
100  
}
 0002c     5f               pop     edi
 0002d  5e               pop     esi
 0002e  5b               pop     ebx
 0002f  8b e5            mov     esp, ebp
 00031  5d               pop     ebp
 00032  c2 04 00         ret     4

That was one line of source code. The following are the next three lines:

 CModel::Instance()->GetJob().GetJobStat().SetOverlap(dIntentionalOverlap);
 CModel::Instance()->GetJob().GetJobStat().SetAntOffset(fAntennaXOffset);
 CModel::Instance()->GetJob().UpdateStatModifiedTime();


Including the first line, the "Instance()->GetJob()" pair was called four times, and "GetJobStat()" three times, each time returning the same value. The total instructions for accomplishing four trivial tasks was no doubt over 500 machine instructions. But that could have been dramatically reduced had the "Instance()->GetJob()" been used to set a local pointer, and "GetJobStat()" the same, and then used those pointers to access the end functions.

Even better, if the relevant job class (no doubt only one exists at a time) been kept as a global pointer, then the machine instructions would have only been a fraction. But no doubt that's not a kosher method.

In my old-school ideal, these values would be global to the whole project and set here directly, probably resulting in 10 or so instructions, probably a 50x improvement in efficiency. The code for "Instance()", "GetJob()", "GetJobStat()", and the various "set" functions wouldn't have needed to be written or maintained. How all that extra code and complexity can possibly be a "better" way to write software I haven't a clue. Unnecessary complexity is never a good thing. —Preceding unsigned comment added by 208.77.60.70 (talk) 23:19, 13 August 2008 (UTC)

That is not what brookes meant by accidental complexity. Brookes ignores the complexity the CPU has to deal with and cares primary about the complexity the programmer needs to worry about. Compare "walk forward one step" to "lift left foot; adjust balance; move left foot forward; adjust balance; put down left foot; adjust balance". Both programs have the same essential complexity (they both take one step forward) but the second has considerably more accidental complexity. The example you've given is a bit contrived, why are we not keeping pointers (in the local scope) to the start of our current job and the job itself? Thus what I dislike about the example is that it has accidental complexity we can get rid of (the redundent and repeated function calls). Even with that though I much prefer it to global vars and implicit data passing! Pcecificly if you disagree with OOP then I would encourage you to read Brooke's mythical man month, make sure it is the aniversary version with the extra chapters. I say this because I too did not "get" OOP until I read Brookes, specifically the chapter where he changes his opinion on data hiding.

174.0.170.217 (talk) 18:09, 16 May 2011 (UTC)

Merge[edit]

I don't see why we need 3 articles (two of which are stubs—well, one stub article and one stubby section in another) to discuss the distinction between accidental and essential complexity, as defined by Brooks in this paper. JMP EAX (talk) 08:53, 24 July 2014 (UTC)

I agree, perhaps the other articles could become redirects? Unit158 (talk) 03:48, 31 July 2014 (UTC)
Okay, I'm gonna do that. JMP EAX (talk) 06:10, 1 August 2014 (UTC)
And Yes check.svg Done. I've actually made a dab at essential complexity. There wasn't much material to actually merge here, although the phrasing might have been a little better in the former stubs... JMP EAX (talk) 07:02, 1 August 2014 (UTC)