關於系統設計原則回顧

来源:http://www.cnblogs.com/wintersun/archive/2017/07/16/7189980.html
-Advertisement-
Play Games

最近有人問我 系統設計的原則,事實上不論今天各個技術棧怎麼演化,那些本質的原則與方法不會變, 讓我們回顧一下 這些原則:•分散關註 Separation of concerns. Divide your application into distinct features with as littl... ...


     最近有人問我 系統設計的原則,事實上不論今天各個技術棧怎麼演化,那些本質的原則與方法不會變, 讓我們回顧一下 這些原則:

分散關註 Separation of concerns. Divide your application into distinct features with as little overlap in functionality as possible. The important factor is minimization of interaction points to achieve high cohesion and low coupling. However, separating functionality at the wrong boundaries can result in high coupling and complexity between features even though the contained functionality within a feature does not significantly overlap. 不同領域的功能,應該由不同的代碼和最小重迭的模塊組成。

•單一職責,功能高內聚 Single Responsibility principle. Each component or module should be responsible for only a specific feature or functionality, or aggregation of cohesive functionality.

•一個模塊不需要知道另一個模塊的內部細節 Principle of Least Knowledge (also known as the Law of Demeter or LoD). A component or object should not know about internal details of other components or objects.

•Don’t repeat yourself (DRY). You should only need to specify intent in one place. For example, in terms of application design, specific functionality should be implemented in only one component; the functionality should not be duplicated in any other component.

•不要過分設計過多模塊 Minimize upfront design. Only design what is necessary. In some cases, you may require upfront comprehensive design and testing if the cost of development or a failure in the design is very high. In other cases, especially for agile development, you can avoid big design upfront (BDUF). If your application requirements are unclear, or if there is a possibility of the design evolving over time, avoid making a large design effort prematurely. This principle is sometimes known as YAGNI ("You ain’t gonna need it").

software-design-cloud-tag595x335

軟體設計 中 SOLID原則

    The Single Responsibility Principle

    There should never be more than one reason for a class to change. Basically, this means that your classes should exist for one purpose only. Responsibility is the heart of this principle, so to rephrase there should never be more than one responsibility per class.

    The Open Closed Principle

    Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification. At first, this seems to be contradictory: how can you make an object behave differently without modifying it? The answer: by using abstractions, or by placing behavior(responsibility) in derivative classes. In other words, by creating base classes with override-able functions, we are able to create new classes that do the same thing differently without changing the base functionality. Further, if properties of the abstracted class need to be compared or organized together, another abstraction should handle this. This is the basis of the "keep all object variables private" argument.

    The Liskov Substitution Principle

    Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it. In other words, if you are calling a method defined at a base class upon an abstracted class, the function must be implemented properly on the subtype class. Or, "when using an object through its base class interface, [the] derived object must not expect such users to obey preconditions that are stronger than those required by the base class."Turns out a square is not a rectangle, at least behavior-wise.

    The Interface Segregation Principle

    Clients should not be forced to depend upon interfaces that they do not use. My favorite version of this is written as "when a client depends upon a class that contains interfaces that the client does not use, but that other clients do use, then that client will be affected by the changes that those other clients force upon the class."

    The Dependency Inversion Principle

    Depend on abstractions, not on concretions or High level modules should not depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions. This is very closely related to the open closed principle we discussed earlier.

    從面向對象OO方向出發,也是設計模式的思想有:

    封裝變化點

    該原則的核心思想是,在程式設計中找出應用中可能需要變化之處,把它們獨立出來以便以後可以輕易的改動或者擴充,而不影響不需要變化的部分, 哪兒變化就封裝哪兒

    面向介面編程

    介面提供了非常優秀的抽象歸納,讓我們的開發工作變得容易很多。一般實現一個系統的時候,通常是將定義與實現合為一體,不加分離的,認為最為理想的系統設計規範應是所有的定義與實現分離,儘管這可能對系統中的某些情況有點麻煩。

    使用組合而不是繼承

    繼承破壞封裝性。基類的很多內部細節都是對派生類可見的,因此這種復用是“白箱復用”;如果基類的實現發生改變,那麼派生類的實現也將隨之改變。這樣就導致了子類行為的不可預知性;從基類繼承來的實現是無法在運行期動態改變的,因此降低了應用的靈活性。繼承關係有很多缺點,如果合理使用組合則可以有效的避免這些缺點,使用組合關係將系統對變化的適應力從靜態提升到動態,而且由於組合將已有對象組合到了新對象中,因此新對象可以調用已有對象的功能。由於組合關係中各個各個對象的內部實現是隱藏的,我們只能通過介面調用,因此我們完全可以在運行期用實現了同樣介面的另外一個對象來代替原對象,從而靈活實現運行期的行為控制。而且使用合成關係有助於保持每個類的職責的單一性,這樣類的層次體系以及類的規模都不太可能增長為不可控制的龐然大物。因此我們優先使用組合而不是繼承。 當然這並不是說繼承是不好的,我們可用的類總是不夠豐富,而使用繼承復用來創建一些實用的類將會不組合來的更快,因此在系統中合理的搭配使用繼承和組合將會使你的系統強大而又牢固。

    還有這些也很重要

Simplicity (KISS)

     The most important principle is keeping things simple. 簡單是軟體設計的目標,簡單的代碼占用時間少,漏洞少,並且易於修改Simplicity should be your northern star, your compass, and your long-term commitment. Keeping software simple is difficult because it is inherently relative. There is no standardized measurement of simplicity, so when you judge what is simpler, you need to first ask yourself for whom and when. For example, is it simpler for you or for your clients? Is it simpler for you to do now or maintain in the future?

低耦合原則(Minimize Coupling)

       代碼的任何一個部分應該減少對其他區域代碼的依賴關係。儘量不要使用共用參數。低耦合往往是完美結構系統和優秀設計的標誌

Designing for scale
     Designing for scale is a difficult art, and each technique described in this section comes with some costs. As an engineer, you need to make careful tradeoffs between endless scalability and the practicality of each solution. To make sure you do not over engineer by preparing for scale that you will never need, you should first carefully estimate the most realistic scalability needs of your system and design accordingly.
Design for Self-Healing
    
The final design principle in this chapter is designing software for high availability and self-healing. A system is considered to be available as long as it performs its functions as expected from the client's perspective. It does not matter if the system is experiencing internal partial failure as long as it does not affect the behavior that clients depend on. In other words, you want to make your system appear as if all of its components were functioning perfectly even when things break and during maintenance times.
Designing For Failure
    
Each application component must be deployed across redundant cloud components, ideally with minimal or no common points of failure
      Each application component must make no assumptions about the underlying infrastructure—it must be able to adapt to changes in the infrastructure without downtime
      Each application component should be partition tolerant—in other words, it should be able to survive network latency (or loss of communication) among the nodes that support that component
      Automation tools must be in place to orchestrate application responses to failures or other changes in the infrastructure

一些設計的實踐

Keep design patterns consistent within each layer. Within a logical layer, where possible, the design of components should be consistent for a particular operation. For example, if you choose to use the Table Data Gateway pattern to create an object that acts as a gateway to tables or views in a database, you should not include another pattern such as Repository, which uses a different paradigm for accessing data and initializing business entities. However, you may need to use different patterns for tasks in a layer that have a large variation in requirements, such as an application that contains business transaction and reporting functionality.
Do not duplicate functionality within an application. There should be only one component providing a specific functionality—this functionality should not be duplicated in any other component. This makes your components cohesive and makes it easier to optimize the components if a specific feature or functionality changes. Duplication of functionality within an application can make it difficult to implement changes, decrease clarity, and introduce potential inconsistencies.
Prefer composition to inheritance. Wherever possible, use composition over inheritance when reusing functionality because inheritance increases the dependency between parent and child classes, thereby limiting the reuse of child classes. This also reduces the inheritance hierarchies, which can become very difficult to deal with.
Establish a coding style and naming convention for development. Check to see if the organization has established coding style and naming standards. If not, you should establish common standards. This provides a consistent model that makes it easier for team members to review code they did not write, which leads to better maintainability.
Maintain system quality using automated QA techniques during development. Use unit testing and other automated Quality Analysis techniques, such as dependency analysis and static code analysis, during development. Define clear behavioral and performance metrics for components and sub-systems, and use automated QA tools during the build process to ensure that local design or implementation decisions do not adversely affect the overall system quality.
Consider the operation of your application. Determine what metrics and operational data are required by the IT infrastructure to ensure the efficient deployment and operation of your application. Designing your application’s components and sub-systems with a clear understanding of their individual operational requirements will significantly ease overall deployment and operation. Use automated QA tools during development to ensure that the correct operational data is provided by your application’s components and sub-systems.

在互聯網系統下產生的一些原則

1.避免單點故障:任何東西都要有兩個。這增加了成本和複雜度,但卻能在可用性和負載性能上獲益。而且,這有助於設計者採用一種分散式優先的思維。可(異地)部署和就近路由接入,破除單點故障;可分佈,可調度的原則

2.橫向擴展,而不是縱向擴展:升級伺服器(縱向)的成本是指數增長的,而增加另一臺商用伺服器(橫向)的成本是線性增長的。
3.儘量減少應用程式核心所需要完成的工作。

4.API優先:將應用程式視為一個提供API的服務,而且,不假定服務的客戶端類型(手機應用、Web站點、桌面應用程式)。

5.提供儘可能新的數據:用戶可能不需要立即看到最新的數據,最終一致性可以帶來更高的可用性。
6.設計時要考慮維護和自動化:不要低估應用程式維護所需要的時間和工作量。軟體首次公開發佈是一個值得稱贊的里程碑,但也標志著真正的工作要開始了。
7.為故障做好準備:將故障對終端用戶的影響最小化。
8.數據上報和監控平臺;
用戶行為數據,系統性能監控數據,系統異常和業務相關數據等的上報
9.數據分級存儲原則:單記憶體cache存儲,記憶體cache+非同步更新,記憶體cache+同步更新;
從三個緯度分析用戶行為模型,決定相關數據的存儲策略:1),能忍受用戶數據的丟失嗎?2),能忍受數據的非及時性嗎? 3),數據的讀寫比例分佈如何?
10.動靜分離原則;
能靜態化儘量靜態化,在代碼和進程部署上,在DNS層上做好動靜分離的系統設計準備
11.輕重分離原則;
保持接入和業務處理的分離,接入儘量輕量化,使得系統具有很好的吞吐量,處理儘量非同步化,使得可以平滑擴展
12. 破除服務依賴原則:同一IDC的其他服務對系統的影響,第三方調用系統介面的隔離和過載保護,依賴第三方服務的監控和安全保護原則等。
13.柔性可用原則;
處理好異常情況下的灰度體驗,區分好關鍵處理路徑和非關鍵路徑,而系統設計要儘量把關鍵路徑轉換成非關鍵路徑
14.非同步化,能非同步的儘量非同步原則;
通過記憶體管道,操作流水等技術進行拼接各個處理模塊
15.灰度原則;
灰度發佈策略是根據用戶號碼段,用戶ip段,還是用戶vip等級,用戶所在城市等進行灰度升級,保證系統的平滑迭代
16.異常的快速響應和一鍵切換原則;
IDC斷電?系統切換到正常的成本是多少?時間呢?需要幾個人操作?牛的系統可以一個人在管理後臺按一個按鈕就可以切換,再按一下就可以切換回來
17.有損服務原則;
用低成本提供海量的服務原則
18.充分利用DNS層做好系統的可分佈設計
19.區分系統行為和用戶行為並分別進行設計,甚至在關鍵時刻可以進行轉換。
20.努力實現無狀態:狀態信息要保存在儘可能少的地方,而且要保存在專門設計的組件中。堅持app_server設計的無狀態設計原則,轉變用戶行為為系統行為,使得app_server具有無狀態的特點
21.多級cache設計以及各個cache的路由設計
22.“大系統小做”原則  
23.強事務模型到最終一致性事務模型的轉換原則
24.儘可能拆分
25.服務架構“去中心化”
26.數據化運營
27.儘可能使用成熟組件
28.儘可能自動化

大規模web系統設計的一些核心原則:

可用性: 一個網站的正常運行時間對於許多公司的聲譽與運作都是至關重要的。對於一些更大的線上零售站點,幾分鐘的不可用都會造成數千或數百萬美元的營收損失,因此系統設計得能夠持續服務,並且能迅速從故障中恢復是技術和業務的最基本要求。分散式系統中的高可用性需要仔細考慮關鍵部件的冗餘,從部分系統故障中迅速恢復,以及問題發生時優雅降級。
性能: 對於多數站點而言,網站的性能已成為一個重要的考慮因素。網站的速度影響著使用和用戶滿意度,以及搜索引擎排名,與營收和是否能留住用戶直接相關。因此,創建一個針對快速響應與低延遲進行優化的系統非常重要。
可靠性: 系統必須是可靠的,這樣相同數據請求才會始終返回相同的數據。數據變換或更新之後,同樣的請求則應該返回新的數據。用戶應該知道一點:如果東西寫入了系統,或者得到存儲,那麼它會持久化並且肯定保持不變以便將來進行檢索。
可擴展性: 對於任何大型分散式系統而言,大小(size)只是需要考慮的規模(scale)問題的一個方面。同樣重要的是努力去提高處理更大負載的能力,這通常被稱為系統的可擴展性。可擴展性以系統的許多不同參數為參考:能夠處理多少額外流量?增加存儲容量有多容易?能夠處理多少更多的事務?
可管理性: 系統設計得易於運維是另一個重要的考慮因素。系統的可管理性等價於運維(維護和更新)的可擴展性。對於可管理性需要考慮的是:問題發生時易於診斷與理解,便於更新或修改,系統運維起來如何簡單(例如:常規運維是否不會引發失敗或異常?)
成本: 成本是一個重要因素。很明顯這包括硬體和軟體成本,但也要考慮系統部署和維護這一方面。系統構建所花費的開發者時間,系統運行所需要的運維工作量,以及培訓工作都應該考慮進去。成本是擁有系統的總成本。

剩下來 就可以圍繞 ISO 9126質量模型:軟體質量模型的6大特性和27個子特性 來進行系統設計與分析,度量, 他們是:

一、功能性:
1、適合性:提供了相應的功能
2、準確性:正確(用戶需要的)
3、互操作性:產品與產品之間交互數據的能力
4、保密安全性:允許經過授權的用戶和系統能夠正常的訪問相應的數據和信息,禁止未授權的用戶訪問.......
5、功能性的依從性:國際/國家/行業/企業 標準規範一致性

二、可靠性:產品在規定的條件下,在規定的時間內完成規定功能的能力
1、成熟性:防止內部錯誤導致軟體失效的能力
2、容錯性:軟體出現故障,自我處理能力
3、易恢復性:失效情況下的恢復能力
4、可靠性的依從性

三、易用性:在指定使用條件下,產品被理解、 學習、使用和吸引用戶的能力
1、易理解性:
2、易學性:
3、易操作性:
4、吸引性:
5、易用性的依從性:

四、效率性:在規定台條件下,相對於所用資源的數量,軟體產品可提供適當性能的能力
1、時間特性:平均事務響應時間,吞吐率,TPS(每秒事務數)
2、資源利用性:CPU 記憶體 磁碟 IO 網路帶寬 隊列 共用記憶體
3、效率依從性:

五、軟體維護性:"四規", 在規定條件下,規定的時間內,使用規定的工具或方法修複規定功能的能力
1、易分析性:分析定位問題的難易程度
2、易改變性:軟體產品使指定的修改可以被實現的能力
3、穩定性:防止意外修改導致程式失效
4、易 測試性:使已修改軟體能被確認的能力
5、維護性的依從性

六、軟體可移植性:從一種環境遷移到另一種環境的能力
1、適應性:適應不同平臺
2、易安裝性:被安裝的能力
3、共存性:
4、易替換性
5、可移植性的依從性:

仔細回顧現在各類的系統平臺,框架,組件,工程方法,都至少包含有上面的設計思想與原則。可能還有遺漏的,後續補充。

--------------------------------------------------------------------------------------------------------------------------------------------

今天先到這兒,希望對您在系統架構設計與評估,團隊管理, 項目管理, 產品管理 有參考作用 , 您可能感興趣的文章:
互聯網電商購物車架構演變案例
互聯網業務場景下消息隊列架構
消息系統架構設計演進
互聯網電商搜索架構演化之一
企業信息化與軟體工程的迷思
企業項目化管理介紹
軟體項目成功之要素
人際溝通風格介紹一
精益IT組織與分享式領導
學習型組織與企業
企業創新文化與等級觀念
組織目標與個人目標
初創公司人才招聘與管理
人才公司環境與企業文化
企業文化、團隊文化與知識共用
高效能的團隊建設
項目管理溝通計劃
構建高效的研發與自動化運維
某大型電商雲平臺實踐
互聯網資料庫架構設計思路
IT基礎架構規劃方案一(網路系統規劃)
餐飲行業解決方案之客戶分析流程
餐飲行業解決方案之採購戰略制定與實施流程
餐飲行業解決方案之業務設計流程
供應鏈需求調研CheckList
企業應用之性能實時度量系統演變

如有想瞭解更多軟體設計與架構, 系統IT,企業信息化, 團隊管理 資訊,請關註我的微信訂閱號:

MegadotnetMicroMsg_thumb1_thumb1_thu[2]


作者:Petter Liu
出處:http://www.cnblogs.com/wintersun/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。
該文章也同時發佈在我的獨立博客中-Petter Liu Blog


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 什麼是電腦程式設計? 簡單的說,它就是告訴電腦要做什麼。電腦可以做很多事情,但是不太擅長自主思考,程式員需要像給小孩子喂飯一樣告訴它具體的細節,並且使電腦能夠理解的語言——演算法。 演算法(Algorithm)是指解題方案的準確而完整的描述,是一系列解決問題的清晰指令,演算法代表著用系統的方法描述 ...
  • Snapman集合了TCC編譯器可以直接編譯執行C語言腳本,其腳本執行效率和C#編譯程式進行效率對比,包括下麵4方面: 1、函數執行效率 2、數字轉換成字元串 3、字元串的疊加 4、MD5演算法 這是C#代碼: using System; using System.Collections.Generi ...
  • 安裝Python-Windows 在開始Python編程前,需要先安裝Python環境。Python安裝包可以到Python的官網下載,官網地址是https://www.python.org/,如果想直接跳過關於Python的介紹相關直接下載安裝包,則可以直接訪問https://www.python ...
  • 最近在折騰Django的WSGI應用,雖然Django自帶的runserver很方便,但是對於複雜的功能它就無能為力了。 首先在Windows上遇到坑了,然後在windows10自帶的Ubuntu遇到坑了,最後在虛擬機上總算解決了。 待補充 ...
  • Java程式預設輸出為Console,如果要想將Console輸出結果保存到文件中,則需要做如下配置: 在JAVA程式上右鍵--> Run As --> Run Configurations 選擇Common視窗,設置文件保存路徑,以及是否以追加方式保存console輸出到文件。 ...
  • 前兩篇《JVM入門——運行時數據區》《JVM常見垃圾回收演算法》所提到的實際上JVM規範以及常用的垃圾回收演算法,具體的JVM實現實際上不止一種,有JRockit、J9等待,當然最有名當屬HotSpot JVM。下麵是HotSpot JVM的整體架構圖,本文著重介紹HotSpot中的垃圾回收器(Garb ...
  • 1.何為列表 1.1 列表作為序列(sequence)的一種,是一組有順序的元素的集合。 1.2 列表是Python中最常用的內置數據類型,用中括弧[元素1,元素2...]括起,以逗號分隔,元素之間沒有任何關係,可以是任何類型。 2.列表的聲明與訪問 3.列表中元素的修改、添加和刪除 3.1 修改列 ...
  • Python網路數據採集3 數據存到CSV以及MySql 先熱熱身,下載某個頁面的所有圖片。 https://www.pythonscraping.com/sites/default/files/lrg_0.jpg http://pythonscraping.com/img/lrg%20(1).jp ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...