Talk:No Silver Bullet

2007 comments
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)


 * The referenced article is now a dead link. I haven't checked archive.org but a mirror (of one of the early editions) can be found here http://worrydream.com/refs/Brooks-NoSilverBullet.pdf Wizard (talk) 02:01, 12 October 2023 (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

 * 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
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
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 (talk • contribs) 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
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
"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
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 ✅. 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)