計算機系統的設計原則

計算機系統的設計原則

你可能稱之指南, 啓發法, 或者經驗法則. 這都無所謂, 目的是一樣的 : 提供一哥近似合理的真想. 這些經驗法則可以幫助你理解運行的系統, 使你專注於正確的事情, 重視潛在的問題區.

These are just the initial rules of thumb that I’ve collected over the past year. If you have any other useful rules or heuristics, please send me an email or leave a comment below.

Additional links to other rules of thumb are included in the Further Reading section.

目錄:

  1. General
  2. 設計
  3. 成本
  4. 任務
  5. 硬件
  6. 軟件重用
  7. 優化
  8. 危險信號和危險區
  9. 中斷
  10. 系統功能點規則
  11. 進一步閱讀

通用

  • 保持系統正常運行比在中斷系統後對其進行修復要容易得多。 (詹姆斯·格林寧)
  • 儘可能將錯誤從運行時轉移到編譯時
  • 沒有文檔的程序沒有價值
  • 註釋永遠都不要重述代碼的明顯作用。
  • 註釋應通過描述意圖來輔助後期維護。
  • 頭文件中的所有內容都應至少在兩個源文件中使用
  • Developer productivity is dramatically increased by eliminating distractions and interrupts
    • “Developers who live in cubicles probably aren’t very productive. Check how they manage interruptions.” (Jack Ganssle)
  • “Complexity grows exponentially; Robert Glass figures for every 25% increase in the problem’s difficulty the code doubles in size. A many-million line program can assume a number of states whose size no human can grasp.” (Jack Ganssle)
  • In nature, the optimum is almost always in the middle somewhere. Distrust assertions that the optimum is at an extreme point. (Akin’s Laws)
  • Past experience is excellent for providing a reality check. Too much reality can doom an otherwise worthwhile design, though (Akin’s Laws)
  • As a rule of thumb, every hour you spend on defect prevention will reduce your repair time from three to ten hours. (Steve McConnell)

設計

  • 複雜的系統由有效的簡單系統演變而來(John Gall)
    • “A complex system that works is invariably found to have evolved from a simple system that worked. The inverse proposition also appears to be true: A complex system designed from scratch never works and cannot be made to work. You have to start over, beginning with a working simple system.” (John Gall)
  • If you can’t describe the behavior in plain English, you can’t successfully describe it with code
  • Decompose complex problems into smaller sub-problems
    • If a problem can be decomposed into two or more independently solvable problems, then solve them independently first!
    • After you have implemented and tested the solutions, combine the parts into a larger operation
  • 一個功能應僅執行一項概念性任務
  • 不要解決不存在的問題
  • 解決特定問題,而不是一般情況
  • To design a spacecraft right takes an infinite amount of effort. This is why it’s a good idea to design them to operate when some things are wrong. (Akin’s Laws)
  • Design is an iterative process. The necessary number of iterations is one more than the number you have currently done. This is true at any point in time. (Akin’s Laws)
  • There is never a single right solution. There are always multiple wrong ones, though. (Akin’s Laws)
  • (Edison’s Law) “Better” is the enemy of “good”. (Akin’s Laws)
  • (Shea’s Law) The ability to improve a design occurs primarily at the interfaces. This is also the prime location for screwing it up. (Akin’s Laws)
  • Studies have found that reworking defective requirements, design, and code typically consumes 40 to 50 percent of the total cost of software development. (Steve McConnell, citing Capers Jones)
    • In the worst case, reworking a software requirements problem once the software is in operation typically costs 50 to 200 times what it would take to rework the problem in the requirements stage. (Steve McConnell, citing Boehm and Papaccio)

成本

  • 軟件昂貴
    • “Study after study shows that commercial code, in all of the realities of its undocumented chaos, costs $15 to $30 per line. A lousy 1000 lines of code – and it’s hard to do much in a thousand lines – has a very real cost of perhaps $30,000. The old saw ‘it’s only a software change’ is equivalent to ‘it’s only a brick of gold bullion’.” (Jack Ganssle)
    • “The answer is $15 to $40 per line of code. At the $40 end you can get relatively robust, well designed code suitable for industry applications. The $15 end tends to be code with skimpy design packages and skimpy testing. (In other words, some people spend only $15/line, but their code is of doubtful quality.)” (Phil Koopman)
    • “UPDATE, October 2015. It’s probably more like $25-$50 per line of code now. Costs for projects outsourced to Asia have done up dramatically as wages and competition for scarce coders have increased.” (Phil Koopman)
  • 如果您想減少軟件開發成本,請查看每個需求文檔並粗暴地刪除功能。 (傑克·甘斯勒)
    • 許多功能等於進度緩慢且開發成本昂貴(Jack Ganssle)
  • Non-recurring engineering (NRE) costs must be amortized over every product sold
    • Save NRE dollars by reducing features
    • Save NRE dollars by offloading software functionality into hardware components (increases BOM cost)
      • Only useful if that hardware already exists!
      • Software/hardware partitioning should be assessed early in the design process
    • Save NRE dollars by delivering the product faster (Jack Ganssle)
  • It is easier and cheaper to completely rewrite the 5% of problematic functions than to fix the existing implementation
    • These functions cost four times as much as other functions (Barry Boehm)
    • “Perhaps we really blew it when first writing the code, but if we can identify these crummy routines, toss them out, and start over, we’ll save big bucks.” (Jack Ganssle)

任務

  • 永遠沒有足夠的時間來正確地做它,但是總有足夠的時間來完成它。 (阿金法則)
  • Estimating dates instead of hours guarantees a late project (Jack Ganssle)
    • “Scheduling disasters are inevitable when developers don’t separate calendar time from engineering hours.” (Jack Ganssle)
  • “If the schedule hallucinates a people-utilization factor of much over 50% the project will be behind proportionately.” (Jack Ganssle)
    • “Some data suggests the average developer is only about 55% engaged on new product work. Other routine activities, from handling paperwork to talking about Survivor XVI, burn almost half the work week.” (Jack Ganssle)
  • We often fail to anticipate the difficult areas of development
    • “Isn’t it amazing how badly we estimate schedules for most projects? 80% of embedded systems are delivered late. Most pundits figure the average project consumes twice the development effort originally budgeted.” (Jack Ganssle)
  • 5% of functions consume 80% of debugging time (Jack Ganssle)
    • “I’ve observed that most projects wallow in the debug cycle, which often accounts for half of the entire schedule. Clearly, if we can do something about those few functions that represent most of our troubles, the project will get out the door that much sooner.” (Jack Ganssle)
  • Timelines grow much faster than firmware size – double the lines of code, and the delivery date increases by more than 2x (Barry Boehm)
  • “代碼的前90%佔了開發時間的前90%。 剩下的10%的代碼佔了開發時間的90%。” (湯姆·嘉吉)
  • When porting old code to a new project, if more than about 25% gets modified there’s not much of a schedule boost (Richard Selby)
  • Systems loaded to 90% of the processor capability require 2x development time over systems loaded at 70% or less. 95% loading triples development time. (Jack Ganssle)
    • “When only a few bytes are left, even trivial features can take weeks as developers must rewrite massive sections of code to free up memory or CPU cycles.” (Jack Ganssle)
  • 您制定的時間表似乎是虛構的完整作品,直到您的客戶因不滿足而解僱您爲止。 (阿金法則)
  • Sometimes, the fastest way to get to the end is to throw everything out and start over. (Akin’s Laws)
  • (Patton’s Law of Program Planning) A good plan violently executed now is better than a perfect plan next week. (Akin’s Laws)

硬件

  • 添加硬件會增加電源要求
  • Use of hardware accelerators to offload CPU-based algorithms can reduce power requirements
  • Every sensor is a temperature sensor. Some sensors measure other things as well. (Elecia White)
  • Break out nasty real-time hardware functions into independent CPUs (Jack Ganssle)
    • Handling 1000 interrupts per second from a device? Partition it to its own controller and offload all of the ISR overhead off of the main processor
  • Add hardware whenever it can simplify the software (Jack Ganssle)
    • This will dramatically reduce NRE and software development costs, at a tradeoff for an increase in BOM costs.
    • Systems loaded to 90% of the processor capability require 2x development time over systems loaded at 70% or less. 95% loading triples development time. Add additional hardware to reduce loading. (Jack Ganssle)
  • (阿特金示範法則)當硬件運行正常時,真正重要的訪客不會出現。 (阿金法則)

軟件重用

  • 優先使用已被其他人重複使用的現有經過審查的代碼
    • 例如 使用STL而不是編寫自己的容器
  • Prefer simple, standard communication protocols over custom communication protocols
  • Follow the “Rule of Three”: you are allowed to copy and paste the code once, but that when the same code is replicated three times, it should be extracted into a new procedure (Martin Fowler)
  • Before a package is truly reusable, it must have been reused at least three times (Jack Ganssle)
    • “We’re not smart enough to truly understand the range of applications where a chunk of software may be used. Every domain requires its own unique features and tweaks; till we’ve actually used the code several times, over a wide enough range of apps, we won’t have generalized it enough to have it truly reusable.” (Jack Ganssle)
  • 重用最好在大部分代碼中完成–考慮重用整個驅動程序或庫,而不是重用功能(Jack Ganssle)

優化

  • 過早的優化浪費時間
    • “More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single reason — including blind stupidity.” (W.A. Wulf)
    • “The First Rule of Program Optimization: Don’t do it. The Second Rule of Program Optimization (for experts only!): Don’t do it yet.” (Michael A. Jackson)
  • Only optimize code after you have profiled it to identify the problem area
    • “Bottlenecks occur in surprising places, so don’t try to second guess and put in a speed hack until you have proven that’s where the bottleneck is.” (Rob Pike)
    • “We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%. A good programmer will not be lulled into complacency by such reasoning, he will be wise to look carefully at the critical code; but only after that code has been identified” (Donald Knuth)
  • The Pareto principle can be applied to resource optimization: 80% of resources are used by 20% of operations
    • Alternatively, there is the 90/10 law in software engineering: 90% of the execution time of a program is spent executing 10% of the code
  • Algorithmic optimizations have a greater impact than micro optimizations
    • “Real efficiency gains come from changing the order of complexity of the algorithm, such as changing from O(N2) to O(NlogN) complexity”
  • 切勿爲了獲得感知的效率而犧牲清晰度,尤其是在沒有數據證明效率提高的情況下

危險信號和危險區

  • 當開發人員害怕更改功能時,是時候從頭開始重寫該代碼了(Jack Ganssle)
  • Duplicate code is an indication of poor design or poor programming habits. It must be eliminated.
    • “Duplication is a bad practice because it makes code harder to maintain. When the rule encoded in a replicated piece of code changes, whoever maintains the code will have to change it in all places correctly. This process is error-prone and often leads to problems. If the code exists in only one place, then it can be easily changed there.” (Jack Ganssle)
    • “This rule is can even be applied to small number of lines of code, or even single lines of code. For example, if you want to call a function, and then call it again when it fails, it’s OK to have two call sites; however, if you want to try it five times before giving up, there should only be one call site inside a loop rather than 5 independent calls.” (Jack Ganssle)
  • Avoid shared resources wherever possible (Jack Ganssle)
  • Eliminate globals!
  • Disabling interrupts tends to be A Bad Thing (Jack Ganssle)
    • Even in the best of cases it’ll increase system latency and probably decrease performance
    • Increased latency leads to missed interrupts and mismanaged devices
  • Be wary of solo Enable Interrupt (EI) commands (Jack Ganssle)
    • “An EI located outside an interrupt service routine (ISR) often suggests peril – with the exception of the initial EI in the startup code.” (Jack Ganssle)
    • “When the enable is not part of a DI/EI pair (and these two instructions must be very close to each other to keep latency down and maintainability up) then the code is likely a convoluted, cryptic well; plumbing these depths will age the most eager of developers.” (Jack Ganssle)
  • Be wary when code is peppered with DI/EI Pairs (Jack Ganssle)
    • Excessive use of Disable Interrupt instructions suggests poor design
    • “但是,當出現系統性設計問題時,這些DI / EI對會大量滲入代碼,從而產生許多容易出現折返問題的關鍵區域。 您知道這是怎麼回事:勇敢的開發人員追逐錯誤,發現上下文切換破壞了變量。 彈出快速DI / EI對。 然後還有另一個。 還有一個。 就像是海洛因使用者遭受了最後一擊。 它永遠不會結束。” (傑克·甘斯勒)

中斷

  • 在最短的時間內和最迫切的需求中,保持中斷。 (傑克·甘斯勒)
  • If you disable interrupts in a block of code, re-enable them in the same block (Jack Ganssle)
  • Keep ISRs small
    • Be wary of ISRs longer than half a page of code (Jack Ganssle)
    • In most cases, there should be little-to-no processing inside of the handler (Phillip Johnston)
    • Set a flag, add a value to a queue, and then rely on user-space code to handle more complex tasks
  • Minimize ISR latency to ensure the system does not miss interrupts (Jack Ganssle)
  • Check the design of any ISR that reenables interrupts immediately before returning (Jack Ganssle)
    • Minimize critical sections within the ISR.
    • “允許其他設備中斷ISR很好! 給定足夠的堆棧空間,甚至允許相同的中斷執行此操作。 這表明我們應該創建服務例程,以儘早處理所有非可重入任務(例如維修硬件),發佈EI,然後繼續可重入活動。 然後彈出寄存器並返回。” (傑克·甘斯勒)

避免在中斷處理程序中執行以下操作:(Phillip Johnston)

  • Don’t declare any non-static variables inside the handler
  • Avoid blocking function calls
  • Avoid non-reentrant function calls
  • Avoid any processing that takes non-trivial time
  • Avoid operations with locks as you can deadlock your program in an ISR
  • Avoid operations that involve dynamic memory allocations, as the allocation may require a lock and will take a non-determinate amount of time
  • Avoid stack allocations
    • 根據您的體系結構和操作模型,您的中斷處理程序可能會使用被中斷線程的堆棧或常見的“中斷堆棧”。

功能點經驗法則

A function point is the measure of functionality of a part of a software, which you can read about here. One C function point is about 130 lines of code, on average.

Here are Capers’s rules of thumb, where “FP” means function points. These were extracted from Jack Ganssle’s newsletter.

  • Approximate number of bugs injected in a project: FP1.25
    • Manual code inspections will find about 65% of the bugs. The number is much higher for very disciplined teams.
  • Number of people on the project is about: FP/150
  • Approximate page count for paper documents associated with a project: FP1.15
  • Each test strategy will find about 30% of the bugs that exist.
  • The schedule in months is about: FP0.4
  • Full time number of people required to maintain a project after release: FP/750
  • Requirements grow about 2%/month from the design through coding phases.
  • 將創建的測試用例的大致數量:FP1.2

進一步閱讀

變更日誌

  • 20200602:
    • Removed duplicate entry
  • 20200311:
    • Added additional rules of thumb
  • 20191210:
    • Fixed function point links
  • 20190911:
    • Added a rule of thumb from James Grenning
    • Demoted headings 1 level for uniformity across the website
  • 20190910:
    • Remove duplicate entry (thanks Techr!)
  • 20190909:
    • Added a “Humorous” section
  • 20181228:
    • Added another rule of thumb regarding complexity
  • 20181219:
    • Added additional metrics from Capers Jones
    • Added table of contents
    • Links now open in external tabs
    • Added additional links to Further Reading
  • 20190531:
    • Added laws from Akin’s Laws of Spacecraft Design
  • 20190627:
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章