Showing posts with label Architecture. Show all posts
Showing posts with label Architecture. Show all posts

Saturday, December 10, 2022

Code that Fits in Your Head

筆記:

軟體開發方法論:

Test-driven development (TDD,測試驅動開發)

Behaviour-driven development (BDD,行為驅動開發)

Domain-driven development (DDD,領域驅動開發)

Type-driven development (型別驅動開發)

Property-driven development (特性驅動開發)


封裝

描述物件和呼叫者之間有效互動的一種契約。指出有效性的一種方式是說明什麼是無效的。

Design by Contract

封裝的想法:你應該能夠與一個物件進行互動而不需要對它的實作細節有深入的了解。這目的有 2 個:

1. 它使你能夠改變實作,也就是進行重構。

2. 它允許你以抽象的方式思考一個物體

在設計時要明確指出哪些是有效的輸入,哪些是無效的輸入,以及你能對輸出提供哪些保證


Martin Fowler:如果不關注內部品質,你很快就會失去在合理時間內進行改善的能力。

內部品質差勁的狀況。起初進展很快,但隨著時間的推移,要增加新的功能變得越來越困難。即使是小型的變更,也需要程式設計師去了解大面積的程式碼,而且是很難理解的程式碼。

當他們進行改動時,會出現意想不到的損害,導致測試時間長,還有需要修復缺陷

Page 51

J.B. Rainsberger 的說法:程式碼不是一種資產,而是一種責任。

Page 98 

參數化的測試

Page 112

Postel' Law

慎重考慮先決與後置條件:對你發送出去的東西要保守,對你所接受的東西則要寬容。

輸入 null,轉換為空字串 

Page 117

試圖用1個無效的人數初始化某個物件,應該要丟出1個例外。+

Page 119

封裝的概念:

並不是禁止直接對外開放類別的欄位:類別的欄位應該被「封裝」在 getXX 和 setXXX。

主要是 1 個物件應該保證它永遠不會處於無效的狀態。這不是呼叫者的責任。物件最清楚「有效」意味者什麼,以及如何做出這種保證。

物件和呼叫者之間的互動應該遵守一個契約。這是一組先決條件和後置條件。

先決條件述述了呼叫者的責任。然後,如果呼叫程式碼履行了那些義務

後置條件就描述了物件所給予的保證。

[Refactoring]Introduction

 

1. 重構有時候,讓你可以在犯錯時,輕鬆找到 bug 的位置

2. 呆子都寫得出電腦可以了解的程式,但只有優利的程式寫得出人看得懂的程式

3. 決定程式好壞的關鍵在於它有多麼容易被修改。


重構目的:

1. 軟體更容易了解

2. 較快找出 bug

3. 協助提升程式編寫速度 (良好的模組化讓我們只要了解1小部分程式就可以)

Thursday, December 1, 2022

[Architecture] 架构师修炼之道

出色的架構本身最終不足以確保軟體品質

錯誤的架構註定導致產生更多的軟體 bugs

1. 軟體架構導論

1.1 成为软件架构师

1.2 設計思維基礎

2. 架構設計原理

2.1 制定设计策略

2.2 換位思考

2.3 挖掘關鍵架構需求

2.4 主動選擇架構

2.5 架構模式

2.6 建立模型,化繁為簡

2.7 召開架構設計研究會

2.8 展示設計策略

2.9 描述架構

2.10 架構評估

2.11 鼓勵團隊參與架構設計

3.  架構師的工具箱



Sunday, May 8, 2022

[Architecture] 制定设计策略

 在 Architecting: How Much and When 書中,Barry Boehm 證明開發、架構設計、返工是構成項目工期的三個主要部分。

在 Using Risk to Balance Agile and Plan-Driven Methods 書中,Boehm 和 Richard Turner 建議用風險決定何時關注架構。

[Architecture] 設計思維基礎

一、設計思維的四條原則

以人为本(human)

推迟决策(ambiguity)

善于借鉴(redesign)

化虚为实(tangibility)


以人为本

设计的本质是社交。

尊重所有直接和间接与架构有关的人,换位思考,理解他们的感受。


推迟决策

推迟不确定的决策。

模糊的需求、设计、承诺会毁掉项目。不到条件成熟的最后一刻,不要着急做出最终的设计决策。

不影响质量属性和交付进度的设计决策可以放到架构设计之外。


善于借鉴

所有的设计都是在已有设计基础上的重新设计和调整创新。

留心琢磨熟悉的事物——研究以往的设计,探索其中的规律。

多花点时间研究已有的设计,而不是凭空创造一个新的出来。


化虚为实

让想法具体化、有形化,以便于沟通交流。

代码不适合用来讨论质量属性、组件、设计原则、决策结果之类的问题。


二、運用思維模式

思维模式分为:理解、探索、展示、评估


理解问题

主动获取信息,清晰描述问题,理解对方需求,掌握团队风格

探索想法

尝试各种结构的组合,直到找到最能提升目标质量属性的那种组合。

寻找各种解决问题的模式、技术、方案

展示想法

展示想法不仅是为了分享,也是为了检验合理性。

可以用线框图、编写文档、展示数据等方法。

对系统进行建模。

评估适用性

可以针对不同的场景审视某一块架构,还可以通过实验,或者通过检查决策风险来展开评估。

三、思考(Think)、动手(Do)、检查(Check)

TDC 循环



Wednesday, April 13, 2022

[Architecture] 成为软件架构师

 一、軟體架構師的工作內容:

1. 决定何时以及如何交付软件

2. 确保软件能够满足业务目标


由图可见,软件架构师是集业务、技术、面向用户于一身的。具体职责:

1. 从工程角度定义问题。 关注质量属性和那些影响架构设计方向的约束和特性。

2. 分解系统,分配职责。 模块化分解系统。

3. 关注大局。 人员、过程、业务需求以及其它技术和非技术因素都将影响最后的软件系统。

4. 在质量属性之间做出取舍。 找出备选方案,再与各方一起协商如何取舍最合理。

5. 管理技术债务。 将业务需求与技术决策放在一起考虑。

6. 提升团队的架构能力。 结对设计,写文档,批评,当作社交活动

二、什麼是軟件架構

软件架构:关于如何组织软件 一系列重大设计决策的集合

影响到:

  质量属性

  开发进度

  成本

  很多人

  其他软件系统

如何做:

  Software Architecture in Practice

  定义基本结构:

     元素是软件的基本组成部分,关系则描述了元素如何协作完成。

     三種類型的元素和關係:


     模塊結構:

         1. 在於設計階段。

         2. 即使軟件沒有運行,模塊結構存在於文件系統中。

     組件連接器 (C&C):

        1. 運行階段。

        2. 組件可以創建與其它組件的連接、產生新進程以及實例化新物件。

     分配結構

         1. 展示模塊元素與組件連接器,以及這些元素與現實的物件元素之間的協同與響應關係。

         2. 某個元素運行在客戶端,  還是運行在服務器

  动手练习:元素、关系、结构。 元素命名要明确具体、考虑模块结构、运行时结构、分配结构。

  推演质量属性和其他系统属性:

      质量属性包括:可伸缩性、可用性、可维护性、可测试性等。

三、成为团队的架构师

引入团队的设计讨论

指明团队何时应该进行取舍

撰写设计决策

接受更多架构设计职责

从程序员向架构师转变。 任何人一旦做出了影响软件系统结构的决定,都充当了临时架构师

四、开发出色的软件

架构将大问题分解为容易处理的小问题

软件架构告诉大家如何协同工作

软件架构为讨论复杂设计提供了基本词汇

软件架构关注的不仅仅是功能。 还有成本、约束、进度、风险、团队交付能力、质量属性

软件架构让你避免犯重大错误。 架构师并非无所不知,而架构可以帮助我们发现那些今后可能带来麻烦的地方

架构让软件更灵活

https://githubhot.com/repo/icehoo/me/issues/54

Saturday, April 2, 2022

[Architecture] 软件架构模式分析

 https://chinalhr.github.io/post/software-architecture-patterns/#%E5%BE%AE%E6%9C%8D%E5%8A%A1%E6%9E%B6%E6%9E%84microservices-architecture


Study

Thursday, March 24, 2022

[Architecture] 控制反轉 (Inversion of Control) vs 依賴反轉 (Dependency Inversion)

控制反轉 (Inversion of Control) vs 依賴反轉 (Dependency Inversion)

兩者不相等!


依賴倒置原則 (Dependency Inversion Principle, DIP) :

高階模組不應該依賴於低階模組,兩者都該依賴抽象。

抽象不應該依賴於具體實作方式。

具體實作方式則應該依賴抽象。


舉例來說,此程式違反了 依賴倒置原則, 它使高階模組 (Computer) 依賴 低階模組 (英雄聯盟):

====================================================================

class Computer {

    // 依賴於低階模組:『具體』的英雄聯盟,而非 『抽象』的遊戲

    private 英雄聯盟 lol;

    public Computer() {

        // 預設安裝遊戲: 英雄聯盟

        lol = new 英雄聯盟();

    }

    public Computer(英雄聯盟 lol) {

        this.lol = lol;

    }

    public void playGame() {

        if (lol != null)

            lol.play();

    }

}

class 英雄聯盟 {


    public void play() {

        System.out.print("德瑪西雅~");

    }

}

====================================================================

然而,他還是能透過 IoC/DI ,

被動取得 類別 “英雄聯盟” 的實例 lol:

解除了 高階模組 (Computer) 主動對 低階元件 (英雄聯盟) 的實例方式,

卻 解除不了 高階模組 對 低階模組 的 依賴關係。


因為 高階模組 依賴的是 具體實作 (英雄聯盟),

而非 抽象 (介面 or 抽象類別)。


如果想實現 依賴倒置原則 ?

還記得 依賴倒置原則 (Dependency Inversion Principle, DIP) 的結尾嗎?

僅僅將『 高階模組的依賴對象,由具體改為抽象 』,是 不夠 的,

因為高階模組 欲使用 低階模組的物件時,還是 需要自己 new 具體實作類別。


高階模組,依賴於抽象,而非低階模組。

但 要使用 該抽象的 具體產品 (低階模組) 時,


不用也不需要知道是哪種 具體產品

不再自己實例 具體產品,而是 服務容器 會提供給他 。


Reference:

https://notfalse.net/3/ioc-di


[Architecture] IoC/DI

IoC,是一種 設計原則:

藉由 『分離組件 (Components) 的設置與使用』,來降低類別或模組之間的耦合度 (i.e., 解耦)。

Martin Fowler,因認為 “IoC” 的意義易使人困惑,

於 2000 年初,與多位 IoC 提倡者,給予其實作方式一個更具體的名稱

— — "Dependency Injection (依賴注入)"。

由 服務容器 (IoC 容器) 透過 “依賴注入”,給予 高階模組 所需得具體產品:


取代傳統的主動建立實例:




IoC/DI 很好的實現 好萊塢原則 (Hollywood Principle)、

依賴倒置原則 (Dependency Inversion Principle, DIP) 、 開閉原則 (Open-Closed Principle) …etc.,

是框架的必備特徵,當然也是各語言主流框架的核心 (e.g. : Spring, Laravel, .Net MVC …) 。


控制流程有 Framework 完成


callback function as a dependency of the object that it is being passed into. 

DI is the process of providing the callback (the dependency) to the object. (For example: by giving it to the object via its constructor, a method call, a setter, etc.).


翻译: callback是具体的依赖, DI是注入依赖的过程


DI是IoC的子集





IoC(I nversion o f C ontrol ): - 这是一个通用术语,以多种方式实现(事件,代理等)。

DI(D ependency I njection): - DI是IoC的子類型,通過構造函數註入,setter註入或接口註入實現


依賴注入 (Dependency Injection)


有以下三種形式:

  1. 建構元注入 (Constructor Injection)
  2. 設值方法注入 (Setter Injection)
  3. 介面注入 (Interface Injection)


class Computer implements GameInjector {

    private Game game; // 依賴 『抽象』,而非『具體』

    // 建構元注入 (Constructor Injection)
    public Computer(Game game) {
        this.game = game;
    }

    // 設值方法注入 (Setter Injection)
    public void setGame(Game game) {
        this.game = game;
    }

    // 介面注入 (Interface Injection)
    @Override
    public void injectGame(Game game) {
        this.game = game;
    }

    public void playGame() {
        if (game != null) {
            game.play();
        }
    }
}

// 遊戲注入者
// 可以規範: 任何需要 "遊戲" 的模組 都必須實做此介面
interface GameInjector{
    void injectGame(Game game);
}



可以看到程式中,沒有任何 “具體實作類別” 的名稱,
而是由 依賴注入 取得 插件實例,
高階模組,完全沒有與具體實作 耦合,
實現了 依賴倒置原則 (Dependency Inversion Principle, DIP) !


Reference:

https://www.codeproject.com/Articles/592372/Dependency-Injection-DI-vs-Inversion-of-Control-IO

https://stackoverflow.com/questions/6550700/inversion-of-control-vs-dependency-injection

https://martinfowler.com/articles/dipInTheWild.html#YouMeanDependencyInversionRight

[Architecture] Abstract VS Interface 差異

類別實作Interface使用關鍵字implements:類別繼承Abstract Class使用關鍵字extends。

// 類別實作Interface

public class ConcreteClass implements InterfaceA { ... }

// 類別繼承Abstract Class

public class ConcreteClass extends AbstractClassC { ... }


Interface只能繼承(extends)Interface;Abstract Class能繼承類別也能實作Interface。

// Interface只能繼承Interface

public interface InterfaceA extends InterfaceB { ... }

// Abstract Class能繼承類別及實作Interface

public abstract class AbstractClassC extends AbstractClassD implements InterfaceC { ... }


類別能實作多個Interface,Interface能繼承多個Interface;類別只能繼承一個Abstract Class。

// Interface能實作多個Intetface

public interface InterfaceA extends InterfaceB, InterfaceC { ... }

// 類別能實作多個介面

public class ConcreteClass implements InterfaceA, InterfaceB { ... }

// 類別只能繼承一個Abstract Class

public class ConcreteClass extends AbstractClassC { ... }


Interface不可有實作方法(除了static method及Java 8的default method);Abstract Class可以有實作方法,也可以有無實作的抽象方法。

public interface InterfaceA {

    void doSomething(); // 方法無實作
    
    // 靜態方法有實作
    static String getSomething() {
        return "Something";
    }
    
    // Java 8 default methods
    default void doSomeStuff() { 
        System.out.println("do some stuff");
    }
    
}
public abstract class AbstractClassC {
    
    void doSomething() {
        System.out.println("do something"); // 方法有實作
    }

    abstract void doStuff(); // 無實作的抽象方法
    
}

Interface中的變數預設(也只能是)public final static;Abstract Class可自訂變數的存取範圍。

public interface InterfaceA {

    int VALUE = 1; // implicit public static final 

}
public abstract class AbstractClassC {
    
    private int value; // 自訂存取範圍

}

Interface的方法預設(也只能是)public;Abstract Class則可自訂方法的存取範圍(但抽像方法不可為private)。

public interface InterfaceA {

    void doSomething(); // implicit public

}
public abstract class AbstractClassC {
    
    // 自訂存取範圍
    private void doSomething() { 
        System.out.println("do something");
    }

    abstract void doStuff(); // 無實作的抽象方法

}


 Abstract:

Abstract Class 一般都是在 Class 程式碼撰寫過程慢慢被發現, 進而從 Class 提升為 Abstract Class

盡量讓 Abstract Class 擁有最多的共用程式碼,盡量減少資料

Abstract Class 不能 Instance。即不能使用 New 關鍵字初始化

Abstract Class 是必須被衍生 Class 覆寫方法

只有參數宣告,沒有實作的方法,稱為 abstract method

某些情況下,雖然有實作,但我們希望強迫子類別必須 override 該方法時,也可以宣告為abstract method。

Interface 裡的方法一定沒有實作,因此必然為 abstract method。

衍生 Class 可以部份實作

如果 Class 中包含 Abstract Method (抽象方法),那麼此 Class 就必須定義為 Abstract Class

繼承 abstract class 的子類別必須 override 所有父類別的 abstract method,否則子類別也必須宣告為 abstract class。

一個 Class 只能繼承一個 Abstract Class


Interface:

Interface 比較像定規格,一般而言都是一開始就設計、定義,也是另一種的「藍圖」,
一開始在什麼都不知道的情況下,預先設計好相關架構

Interface不能 Instance,不能有建構式

不能有修飾詞,Public、Private…等。 (Public Interface)

對宣告中的變數

public: 外界觀看某物件時 ,所能看到的表象以及溝通的管道 ,所以 Interface 內的變數一定是 public。也就是說即便宣告時沒寫 public 關鍵字 ,Compiler 也會幫我們加上去。

final 成員,通常不希望變數會隨便更動

static:

對宣告中的方法

public: 外界觀看某物件時,所能看到的表象以及溝通的管道。同宣告中的變數之 public

abstract: Interface 沒有實作,裡面定義的 method 只是宣告而已。沒有實作的 method,在 Java 裡用 abstract 這個關鍵字來表達。

當 Interface 繼承多個 Interface ,或 Class 實作多個 Interface 時,如果有多個同名的函數或變數時,應該如何處理 ?

例如 Runnable 和 AnotherRun 這兩個界面都定義了變數 PERIOD 和方法 run。

相同變數名稱:由於 interface內的變數具有 static 的性質,因此使用這些變數時,必須加上 Interface 的名稱才行,如 Runnable.PERIOD,AnotherRun.PERIOD,因此不會造成任何混淆。

相同函數名稱:如果signature (參數個數,型態以及傳回值型態)完全相同,則 Class 只要實作一次即可,例如 Runnable 和 AnotherRun 均定義 void run(),因此 Class D 只要實作一次就好了。如果同名函數符合 Overloading,把它們分別當成不同的 method 即可。如果參數完全相同,但傳回值不同,則違反了Overloading 的原則,會產生 Compile Error。

                             一個 Class 可實作多個 Interface 

Wednesday, March 23, 2022

[Architecture] 寫 code 5 原則

1. 单一职责原则 SRP (解相依性高)

2. 开闭原则 (扩展是开放,修改是封闭的)

3. 里氏替换原则 (利用继承和多态) 

      以父类的形式声明的变量(或形参),赋值为任何继承于这个父类的子类后不影响程序的执行

      不存在继承于 View 但是却没实现draw函数的子类(abstract方法必须实现)

4. 依赖倒置原则 (实现解耦)

5. 接口隔离原则 (类之间的依赖关系应该建立在最小的接口上)

Reference:

https://juejin.cn/post/6844903437700710408#heading-15

Friday, March 11, 2022

[Architecture] 三层架构

分层的核心任务是“高内聚低耦合”的实现。

三层架构:

表示层(UI)

业务逻辑层(BLL)

数据访问层(DAL)



各层之间采用接口相互访问,并通过对象模型的实体类(Model)作为数据传递的载体,不同的对象模型的实体类一般对应于数据库的不同表,实体类的属性与数据库表的字段名一致

分層方式:

数据层

不包含任何代码,只有数据库,还有相关的存储过程。这种模式下,数据层看起来就变得很简单了。只包含所建立的数据库和一些存储过程(注意是存储过程)。其实这些存储过程的建立也是相当复杂的,因为它们可以完成除数据访问外的其他一些很强大的功能,如分页、实现搜索算法等。

数据访问的逻辑就都放在业务层

当然业务层还包含其他一些逻辑代码。我们来看一个示例,假设数据库里有一个表 BOOKS(书),建立一个存储过程 GetAllBooks,用来读取书的信息,这样在业务层里编一个方法 GetBookS()和一个公用数据库访问类,GetBooks()就通过数据库访问类打开连接,执行在存储过程,返回数据 (返回类型可以是 DataT - able,DataSet,DataReader 或 者 实 体 类)。业务层单独编译成一个或者几个 DLL 文件。接着就是表示层了,表示层通过调用GetBookS()返回数据绑定在相关的控件里。业务层的方法都是在表示层调用。一般来说 book.aspx 和 book.aspx.cs 都是表示层的内容,所有前台的设计、相关控件、数据缓存都是属于表示层

数据层还包含所有公共数据访问代码。这种模式和前一种差别不大,主要是把数据访问代码留到数据层。这样可以很方便地实现对多数据库的支持。业务逻辑层直接调用数据层的相关访问数据的代码,完全不必了解底层是什么数据库。其他和前一种没什么分别


Reference:

https://baike.baidu.com/item/%E4%B8%89%E5%B1%82%E6%9E%B6%E6%9E%84/11031448

Tuesday, February 16, 2021

[Architecture ] 持續整合部署 CI / CD

持續整合 CI (Continuous integration)

開發人員透過版控軟體更新程式時會持續將修正版本合併到主版本中,在合併前都需要通過編譯與自動化單元測試,以保障所有修正不會影響到現有版本中。

持續佈署 CD (Continuous Deployment)

持續部署指的是將最新版本自動發部署的過程,會將版控軟體中最新的版本更新至機器上

CI/CD配合工具

在CI/CD執行過程也可搭配 Log蒐集工具與通訊軟體來作為錯誤通報機制

常見版控工具:

自動化建置工具:(CI Server)

Log蒐集工具:

通訊軟體:

實際應用情境

要達成持續整合部署(CI / CD),通常以開放原始碼(Open Source)為基礎,進行功能開發建構的持續控管追蹤。

電子採購系統為例,各個企業組織都有專屬的採購流程、表單,以及資料機密性,配合自有的CI/CD,才能完整掌握公司的供應鏈的優勢利基。

開發團隊 “一定” 要顧好的流程,有這幾個部分:

  1. 版本控制:
    Source code 是開發團隊最重要的資產, 好好的管理它是必要的。所謂的 “管理” 不只是記錄誰改了哪一行 code 而已,他橫跨了整個開發流程,包含開發中的版本,已發行或是以上線的版本,延伸到將來的 hotfix, 或是回報舊版本問題時,是否都能在版控系統內 精確 的定位到當時那份 code… 都在考量的範圍內。
    其實這有點像在製造業的物料管理一樣,序號或是條碼掃描一下,就能知道所有這產品的來歷。在軟體來看,看到版號或是 commit sha, 就要能讓開發團隊追蹤到所有跟 source code 相關的細節。

  2. 自動建置與整合測試:
    大致上就是現在 CI 在講的事情。包含建置 (build, compilation), 測試 (unit test, 其他 auto testing), 其他語法檢查, 源碼掃描等等對程式碼的品質管控機制都包括在內。目的在程式碼有異動時,能第一時間透過自動化的 process 讓 team member 第一時間能掌握這次異動後的系統品質是否仍然可靠?

  3. 發行管理 (Release management):
    包含將 CI 的成品 (artifacts) 經過一連串自動化的程序,部署到執行環境 (dev, qa, production 都算) 上的動作。簡單的說就是把 CI 的東西弄到可以上線測試或是使用的過程。
    版控機制若有不同的分支 (branch), 則不同分支應該有不同的發行方式與規則,如 develop 發行的是 BETA 版,而 master 發行的是 RTM / RC 版本等等。


Reference:

https://columns.chicken-house.net/2017/08/05/what-cicd-do-you-need/

Monday, October 12, 2020

架構遇到問題

 code 寫死就會造成 延展性不佳

        case KeyEvent.DOM_VK_CC:

        case KeyEvent.DOM_VK_SUBTITLE:

            var subObj = this.curData.value[this.selected];

            if (this.subtitle_cc_show == false && this.selected == 0 && (typeof(subObj) == 'object' && (Array.isArray(subObj.value) || subObj.hasOwnProperty('showMode')))) {

                this.curData.focusIndex = this.selected;

                this._list_submenu_init(subObj);

                this.subtitle_cc_show = true;

                return false;

Tuesday, September 29, 2020

C 語言程式記憶體配置概念

 記憶體的使用主要可分為 text、data、bss、stack、heap 與 system 這幾個部分


https://blog.gtwang.org/programming/memory-layout-of-c-program/

堆(heap)與棧(stack)的區別 一

堆(heap)與棧(stack)的區別二


Sunday, September 13, 2020

MVC - three pattern

 




架构, 框架, 设计模式

MVC 是 Observer pattern, Strategy pattern 和 Composite pattern 三个设计模式的演变.

Design Pattern 的核心是 Pattern

MVC这个级别的东西怎么都不可能归类到Pattern(小花样)这一类的东西上。当然更不可以是框架,因为框架不是抽象的,而 MVC 是抽象的。

MVC是一种模式。在Martin Fowler的《企业应用架构模式》中,它属于表现层的架构模式。 (Mode)

MVC 在架构模式中的实现不同可能还会用到工厂模式 (Factory) 和装饰器 (Decorator) 模式。

框架通常是代码重用

设计模式是设计重用

架构则介于两者之间,部分代码重用,部分设计重用,有时分析也可重用。

在软件生产中有 3 种级别的重用

1. 内部重用,即在同一应用中能公共使用的抽象块;

2. 代码重用,即将通用模块组合成库或工具集,以便在多个应用和领域都能使用

3. 应用框架的重用,即为专用领域提供通用的或现成的基础结构,以获得最高级别的重用性。



设计模式是对在某种环境中反复出现的问题以及解决该问题的方案的描述,它比框架更抽象;

框架可以用代码表示,也能直接执行或复用,而对模式而言只有实例才能用代码表示

设计模式是比框架更小的元素,一个框架中往往含有一个或多个设计模式,框架总是针对某一特定应用领域,但同一模式却可适用于各种应用。可以说,框架是软件,而设计模式是软件的知识。

简而言之:框架是大智慧,用来对软件设计进行分工;

设计模式是小技巧,对具体问题提出解决方案,以提高代码复用率,降低耦合度。

n8n index

 【n8n免費本地端部署】Windows版|程式安裝x指令大補帖  【一鍵安裝 n8n】圖文教學,獲得無限額度自動化工具&限時免費升級企業版功能