乐趣区

关于后端:软件架构的23个基本原则

软件架构师在做出架构设计时须要遵循一些根本规定,本文介绍的 23 条准则就是其中最根底的规定,是所有软件工程师都须要牢记并实际的准则。原文:23 Basic Principles in Software Architecture[1]

软件体系架构基于一组实用于各种软件系统的根本准则,有教训的架构师晓得这些准则,并且可能在软件产品的正确地位实现特定的准则。上面咱们疾速浏览一下架构师日常遵循的根本准则:

1. 依赖倒置(Dependency Inversion)

这一准则表明依赖的方向应该是形象的,而不是具体实现。如果编译时依赖在运行时执行的方向上流动,就造成了间接依赖。通过依赖倒置,能够反转依赖管制的方向。上面的文章更深刻的探讨了这一准则: How to apply SOLID Software Design Principles to Spring Boot Application (Part 5)[2]

2. 关注点拆散(Separation of Concerns)

这一准则指出,软件系统应该依照所做的工作类型来划分。比方说能够依照业务逻辑、基础设施或用户界面划分为不同的局部。通过将零碎划分为基于不同流动区域的不同局部,使得开发 / 测试 / 部署更加容易。SoC 是软件架构模式 (如畛域驱动设计、六边形架构、整洁架构) 背地的驱动力。

3. 管制反转(Inversion of Control)

该准则相似于依赖倒置准则,但实用于更宽泛的背景。IoC 反转了由不同的第三方框架 (如 Spring Framework) 治理的控制流。与传统 Java EE 程序 (由开发工程师按程序初始化 Beans) 不同,Spring 管制 Bean 的配置,这意味着管制倒置。

4. 依赖注入(Dependency Injection)

该准则意味着依赖应该在运行时通过构造函数注入。在上面的例子中,Action Interface 通过 HumanAction Implementation 注入到 Human 类中,从而决定在运行时实现哪个特定的动作。这种技术提供了管制依赖的灵活性:

package az.alizeynalli.di;

public interface Action {void do();
}

public class HumanAction implements Action {
 
    @Override
    public void do() {System.out.print("run");
    }
}

public class Human  {
     
    Action action;
     
    public Human(Action action) {this.action = action;}
 
    @Override
    public void do() {actoin.do();        
    }
}

    public static void main(String[] args) {Human human = new Human(new HumanAction);
        human.do();}
5. 繁多职责(Single Responsibility)

该准则的次要思维是限定软件系统的每个构建块只承当惟一的责任。无论构建块的作用域是什么,是插件、包、类、函数,甚至是变量,应该只有一个职责。这篇文章更深刻的探讨了这一准则: How to apply SOLID Software Design Principles to Spring Boot Application (Part 1)[3]

6. DRY(Don’t Repeat Yourself)

该准则旨在通过防止反复代码来打消冗余。如果存在针对某些行为的现有性能,则应该重复使用,而不是在多个实例中拷贝雷同的代码片段。

每个常识片段在零碎中都必须有繁多、明确、权威的示意。

7. 开闭准则(Open-Closed)

软件构件应该对扩大凋谢,对批改敞开。

这一原理的简略形容首先是由 Bertrand Meyer 提出的。每次都须要批改的软件系统只会变得一团糟,并且这种凌乱的程序很容易在每次批改时呈现谬误。每个新性能都应该最大限度的减少新代码,最小限度缩小旧代码的更改,现实状况下对旧代码的更改为零。

8. 长久化通明(Persistence Ignorance)

长久化通明的理念是,代码应该不受任何数据库或持久性技术的影响。业务逻辑应该与任何技术无关。如果今天,有更好、更无效、更便宜的长久化技术,应该可能以不影响下层形象的形式扭转零碎的这一部分。

9. YAGNI

You ain’t gonna need it. 这一准则试图防止软件系统的过早优化。开发人员通常会在零碎中适度设计一些货色,以期在未来的某个时候会有帮忙,但这一时刻往往不会到来。

10. 童子军规定(Boy Scout Rule)

在来到的时候要让露营地比来的时候更洁净。

这里的次要思维是,当开发时遇到反模式,要保持重构代码。随着工夫的推移,这会进步代码品质。

11. 里氏替换准则(Liskov-Subsititution)

如果对于每个类型为 S 的对象 o1,都有一个类型为 T 的对象 o2,这样对于用 T 定义的所有程序 P,当 o1 取代 o2 时,P 的行为不变,那么 S 就是 T 的子类型。

Barbara Liskov 的这个定义可能听起来很凌乱,但实质上这个准则简略易懂。如果重述下面的定义,该准则的意思是: 在应用继承时,继承的层次结构应该在性能和业务逻辑方面保持一致。子类应该是能够互相替换的,并且不能扭转父类的行为。作为一个简略的例子,能够用“臭名远扬的正方形 / 矩形”问题。其中正方形不应该是矩形的子类型,因为这两个几何形态的高度和长度的定义是不同的(正方形的高度和长度是相等的,而矩形的高度和长度是不同的)。

12. 封装(Encapsulation)

软件系统的不同构建块应该通过封装来限度外界对其组件的拜访,能够通过在类范畴内设置组件为公有或在插件范畴内设置拜访限度来实现(就 java 而言),从而暗藏信息。

13. 松耦合(Loose Coupling)

软件架构中最重要的准则之一是松耦合,这一准则表明软件系统的依赖关系应该涣散,零碎的一部分发生变化,对其余局部的影响应该最小。松耦合能够通过依赖倒置、异步消息中间件、事件源等实现。上面的文章深入探讨了软件工程中不同模式的耦合: 9 Forms of Coupling in Software Architecture[4]

14. 内聚(Cohesion)

内聚是指模块内的元素依赖的水平。某种意义上说,是对类的办法和数据以及该类所服务的某种对立目标或概念之间关系强度的度量。

构建高内聚的类是一种最佳实际,有利于实现繁多责任准则、松耦合等。

15. 接口隔离(Interface Segregation)

接口隔离准则 指出,不应强制客户端依赖不应用的办法。

应该明确的是,这个准则次要实用于动态类型的编程语言,如 Java、C 等。在像 Python 或 Ruby 这样的动静类型语言中,这个准则没有太大意义。

能够设想这样一种状况,咱们的 Income 和 Expense 用例都依赖于反对这两种用例的业务逻辑性能。因而 Income 用例的很多依赖都和 Expense 用例相干,而 Expense 用例的依赖状况也有雷同的问题。基于以上探讨,ISP 违规状况如下:

package az.alizeynalli.cashflow.core.service;

public interface ConverterService {Income convertIncome(Income income);
    Expense convertExpense(Expense expense);
}

@Component
public class ExpenseConverterServiceImpl implements ConverterService {

    @Override
    public Income convertIncome(Income income) {throw new UnsupportedOperationException();
    }

    @Override
    public Expense convertExpense(Expense expense) {
        // convert expense here
        return expense;
    }
}

@Component
public class IncomeConverterServiceImpl implements ConverterService {

    @Override
    public Income convertIncome(Income income) {
        // convert income here
        return income;
    }

    @Override
    public Expense convertExpense(Expense expense) {throw new UnsupportedOperationException();
    }
}
16. 限界上下文(Bounded Context)

限界上下文是畛域驱动设计的核心模式。通过将大型应用程序或组织合成为独自的概念模块,提供了一种解决复杂性的办法。每个概念模块代表一个上下文,该上下文与其余上下文拆散(因而是有边界的),并且能够独立倒退。现实状况下,每个限界上下文应该能够自在的为其中的概念抉择本人的名称,并且应该独占的拜访本人的长久化存储。[5]

17. 依赖稳固准则(Stable Dependencies)

这一准则指出,软件系统的不同构建块应该只依赖于牢靠、稳固的工件。这个准则在 docker 镜像术语中更有意义,当咱们从 docker hub 导入不同的依赖时,甚至不晓得它们是否牢靠 / 稳固。

18. 多态(Polymorphism)

这实际上属于面向对象编程的 4 大支柱,激励应用能够以多种形式提供的接口,多态性意味着具备多种形式的实体。

19. 模块化(Modularization)

模块化是将软件系统划分为多个独立模块的过程,每个模块独立工作。这一准则是利用于软件系统动态架构的繁多职责拆散准则的另一种模式。

20. 形象(Abstraction)

这也属于面向对象编程的四大支柱:

在钻研物体或零碎时去除物理的、空间的或工夫的细节或属性以集中注意力于更重要的局部,实质上与泛化过程类似。

21. KISS(Keep It Simple, Stupid)

依照字面意思了解,这一准则激励工程师放弃代码简略和愚昧(容易了解),防止别人误会。

22. 增量 / 迭代办法(Incremental/Iterative Approach)

这一准则是麻利软件开发宣言的根底,基于软件系统应该以增量和迭代的形式开发的思维,每一次迭代都会减少零碎性能并保障其运行。

23. 起码常识准则(Least Knowledge)

或者叫信息嫉妒(information envying),是封装或信息暗藏准则的另一个术语,规定软件系统的不同局部应该只领有须要的常识。


相干浏览
  1. Managing Architecture Debt with Dependency Structure Matrix[6]
  2. Hexagonal Architecture Pattern with Spring Boot example[7]
  3. 5 Software Design Patterns implemented in Spring[8]
  4. Cloud-Native Architecture Patterns (Part 1)[9]
  5. Cloud-Native Architecture Patterns (Part 2)[10]

References: \
[1] 23 Basic Principles in Software Architecture: https://azeynalli1990.medium.com/23-basic-principles-in-softw… \
[2] How to apply SOLID Software Design Principles to Spring Boot Application (Part 5): https://medium.com/p/de6abf20e423 \
[3] How to apply SOLID Software Design Principles to Spring Boot Application (Part 1): https://medium.com/p/6b886f6d943e \
[4] 9 Forms of Coupling in Software Architecture: https://medium.com/p/4d5cf2b3e99e \
[5] Architectural Principles: https://docs.microsoft.com/en-us/dotnet/architecture/modern-w… \
[6] Managing Architecture Debt with Dependency Structure Matrix: https://medium.com/p/51f63b6efb4c \
[7] Hexagonal Architecture Pattern with Spring Boot example: https://azeynalli1990.medium.com/hexagonal-architecture-patte… \
[8] 5 Software Design Patterns implemented in Spring: https://azeynalli1990.medium.com/5-software-design-patterns-i… \
[9] Cloud-Native Architecture Patterns (Part 1): https://azeynalli1990.medium.com/cloud-native-architecture-pa… \
[10] Cloud-Native Architecture Patterns (Part 2): https://azeynalli1990.medium.com/cloud-native-architecture-pa…

你好,我是俞凡,在 Motorola 做过研发,当初在 Mavenir 做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI 等技术始终保持着浓重的趣味,平时喜爱浏览、思考,置信继续学习、一生成长,欢送一起交流学习。\
微信公众号:DeepNoMind

本文由 mdnice 多平台公布

退出移动版