Skip to content

Latest commit

 

History

History
320 lines (223 loc) · 26.9 KB

software_architecture.md

File metadata and controls

320 lines (223 loc) · 26.9 KB

Software Architecture Design

Software Architecture Design,是一个很大的话题,也是每位工程师应该长期实践和思考,耳熟能详的:六边形架构、洋葱架构、三层架构、CQRS、DDD 都属于其的范畴。与之相关的还有一个话题:Architectural Pattern

架构学习有这几个非常好的学习资料:

个人感觉还是从:数据+算法、Input -> Processor -> Output 的维度去思考系统更简洁。内容会持续补充...

经典架构

The Four Architectures that will inspire your programming 这篇文章中,作者介绍了介绍了四种经典架构:

另一篇文章:4 Great Programming Architectures You should Know 中也提到了这四种架构。

DDD

DDD 是 大神Eric Evans 于 2004 创立的一种软件设计和实现方式,至今仍非常火。它将软件开发分为两个阶段:

  • 以一种领域专家、设计人员、开发人员都能理解的通用语言作为相互交流的工具,在交流的过程中发现领域概念,然后将这些概念设计成一个领域模型;
  • 由领域模型驱动软件设计,用代码来实现该领域模型;

个人感觉 DDD 更像是一种业务分析方法,帮助我们将业务需求转化为系统设计,并确立系统各个模块的职责和相互之间的交互机制,对做业务架构非常有帮助。

快速了解:

经典书籍

在讨论 DDD 时,经常会听到:贫血模型、充血模型这两个概念,这里是一些相关资料:

与 DDD 相关的还有一个概念:四色原型

Hexagonal Architecture - 六边形架构

由 Alistair Cockburn 在 2005 年提出:

这位大神非常高产,是 Agile Movement 的发起者之一,兴趣广泛,他有一篇文章还引用了汉字去解释它的观点:守 – 破 – 離 – 心,很有意思。

这个架构很容易理解,也衍生出了多种变种,看 Intent、Motivation、Nature of the Solution 三节即可了解其思想,对组织代码、拆分系统非常有帮助,跟 Coding 强相关,即学即用,不容错过。它借鉴了 OS 中端口、设备的概念,通过识别一个系统中核心业务、外围实体,区分去可变和不可变成分。个人感觉感觉是对 Input -> Processor -> Output 的再深化。其中有两个重要概念:

  • PORT:应用对外部呈现的一组 API,对一类业务逻辑的封装
  • Adapter:实现 API 和外围实体的桥接

其难点在于:如何定义好编辑并识别 PORT。我的理解是:首先识别出应用自身(我的核心职责是什么)、服务方(外界通过什么服务来使用我)、依赖方(我依赖的服务),服务方、依赖方分别对应 port 和外围。

相关资料:

The Onion Architecture

由 Jeffrey Palermo (Managing Partner/CEO, Microsoft MVP each year since 2006) 提出,原文: http://jeffreypalermo.com/blog/onion-architecture-part-4-after-four-years/

Key tenets of Onion Architecture:

  • The application is built around an independent object model
  • Inner layers define interfaces. Outer layers implement interfaces
  • Direction of coupling is toward the center
  • All application core code can be compiled and run separate from infrastructure

这个架构很容易理解,和六边形架构一脉相承,作者希望解决分层架构带来的一些问题,同时给大家提供一套标准的的模型和语言去描述系统。由于理念很清晰而且实战性很强,基本无太多争议,被广泛应用。

相关资料:

The Clean Architecture

由 Uncle Bob (原名 Robert C. Martin,The Clean Coder 作者) 提出的一种架构:

这位大叔写了很多文章,涉及我们日常听到的各种术语,这类是他的一些资源:

它总结了多种架构的特点,抽象出其共性:

  • Independent of Frameworks. The architecture does not depend on the existence of some library of feature laden software. This allows you to use such frameworks as tools, rather than having to cram your system into their limited constraints.
  • Testable. The business rules can be tested without the UI, Database, Web Server, or any other external element.
  • Independent of UI. The UI can change easily, without changing the rest of the system. A Web UI could be replaced with a console UI, for example, without changing the business rules.
  • Independent of Database. You can swap out Oracle or SQL Server, for Mongo, BigTable, CouchDB, or something else. Your business rules are not bound to the database.
  • Independent of any external agency. In fact your business rules simply don’t know anything at all about the outside world.

这种架构可以看作六边形架构的衍生,和 The Onion Architecture 有异曲同工之妙 对组织大型应用很有参考价值,也有很多语言在实践。

相关资料:

CQRS

CQRS 由 Greg Young 提出,见文档 CQRS Documents by Greg Young,视频 Greg Young - CQRS and Event Sourcing。思想很容易懂,是值得认真研究和掌握的一种架构,用的好的话对提高系统性能非常有帮助。

这里有大神 Martinfowler 的介绍:

Martinfowler 是系统设计领域的大师,ThoughtWorks 的首席科学家,有非常多的文章在流传,他的网站干货满满。

相关资料:

DCI

理论派的典范,由 and James O. Coplien 提出:

两位创始人都是软件架构领域神级人物:

而 DCI 正是为了解决 OO 及 MVC 存在的一些问题而提出的,它从这两种模型的思想根源来深入剖析其存在的问题,并推演出改进方案。被广泛关注,以 Ruby、Java 为典型代表。由于挑战的是两大经典模型,所以引发很多讨论。这篇文章对理解 GUI、OO、MVC 非常有帮助,但真的挺难懂的。这是他们对 OO 的解读:

  • The goal of object-oriented programming pioneers was to capture end user mental models in the code.
  • When a user approaches a GUI, he or she does two things: thinking and doing. For a smooth interaction between man and machine, the computer's "mental" model (also the programmer's mental model) and the end user's mental model must align with each other in kind of mind-meld. In the end, any work that users do on their side of the interface manipulates the objects in the code.
  • Object-oriented programming was supposed to unify the perspectives of the programmer and the end user in computer code: a boon both to usability and program comprehension.
  • Object orientation hasn't fared so well to capture how we reason about doing. There is no obvious "place" for interactions to live, either on the GUI or in the code.
  • Programmers are people, too, and we want them to be able to map from their understanding of user needs to their understanding of the code. Object-oriented programming languages traditionally afford no way to capture collaborations between objects. They don't capture algorithms that flow over those collaborations.

创始人眼中的 MVC 是这样的:

这是他对 MVC 的部分解读:

  • MVC's goal was to provide the illusion of a direct connection from the end user brain to the computer "brain"—its memory and processor. MVC is about people and their mental models—not the Observer pattern.
  • Data are the representation of information. The mind of the end user can interpret these data; then they become information. Information is the term we use for interpreted data. Information is a key element of the end user mental model. A well-designed program does a good job of capturing the information model in the data model, or at least of providing the illusion of doing so. If the software can do that then the user feels that the computer memory is an extension of his or her memory.
  • The job of the model is to "filter" the raw data so the programmer can think about them in terms of simple cognitive models.
  • The View displays the Model on the screen. View provides a simple protocol to pass information to and from the Model. The heart of a View object presents the Model data in one particular way that is of interest to the end user.
  • The Controller creates Views and coordinates Views and Models. It usually takes on the role of interpreting input user gestures, which it receives as keystrokes, locater device data, and other events.
  • Model-View-Controller-User: it does a good job of supporting the thinking part of computer/human interaction.

OO 和 MVC 存在的问题:

  • We can trace much of our failure to capture the end user mental model of doing to a kind of object mythology. Some buzzwords of this mindset included anthropomorphic design, smart objects, and emergent system behavior. We were taught that system behavior should "emerge" from the interaction of dozens, hundreds or thousands of local methods. The word of the day was: think locally, and global behavior would take care of itself.
  • The MVC framework makes it possible for the user to reason about what the system is: the thinking part of the user cognitive model. But there is little in object orientation, and really nothing in MVC, that helps the developer capture doing in the code. The developer doesn't have a place where he or she can look to reason about end user behavioral requirements.
  • The algorithm had to be distributed across the objects, because to have a large method that represented an entire algorithm was believed to not be a "pure" object-oriented design. How did we decide to split up the algorithm and distribute its parts to objects? On the basis of coupling and cohesion. Algorithms (methods) had to be collocated with the object that showed the most affinity for the algorithm: optimizing cohesion.
  • Interesting business functionality often cuts across objects. Object-orientation pushed us into a world where we had to split up the algorithm and distribute it across several objects, doing the best piecemeal job that we could.

DCI 的三个核心概念:

  • Data: representing the user's mental model of things in their world
  • Roles: a (not so) new concept of action that also lives in users' heads. objects capture what objects are, roles capture collections of behaviors that are about what objects do. At their heart, roles embody generic, abstract algorithms. They have no flesh and blood and can't really do anything.
  • Interactions that weave their way through the roles are also not new to programming: we call them algorithms, and they are probably the only design formalism that predates data as having their own vocabulary and rules of thumb.

这三个是独立于编程语言的概念,DCI 试图在编程语言层面找到这几个概念的具体表现。

DCI 的架构理念:

  • The data, that live in the domain objects that are rooted in domain classes;
  • The context that brings live objects into their positions in a scenario, on demand;
  • The interactions, that describe end-user algorithms in terms of the roles, both of which can be found in end users' heads.

感觉 DCI 更像是一种软件分析方法同时配合了如何用 OO 去实现,和具体怎么 coding 相关,不像是系统架构。DCI 试图寻找一种方式帮助我们完成真实世界和代码世界的映射,使得在代码中不仅仅能看到数据,也能看到用户在使用应用过程中的真实行为。它试图在 OO 和数据结构+算法的模型寻求平衡,引入函数式编程的概念来解决 OO 中存在的一些问题。偏理论+学术化,对 DDD 中 Application Core 如何设计有借鉴意义。

相关资料:

说到 OO,相关的还有:

OO 衍生出很多概念、模式,有时候不由得让人会想:需要搞这么复杂吗?已经有一些高人跳出来试图简化概念和术语,让大家能用简单一致的语言交流和编写代码。函数式编程也正在渐渐兴起,有很多人更认为这是编程的未来。还是 对编程模式有兴趣的同学可以顺着这个话题去研究:Programming Paradigm

ECS

Entity–component–system (ECS) is an architectural pattern that is mostly used in game development. ECS follows the composition over inheritance principle that allows greater flexibility in defining entities where every object in a game's scene is an entity (e.g. enemies, bullets, vehicles, etc.). Every entity consists of one or more components which contains data or state. Therefore, the behavior of an entity can be changed at runtime by systems that add, remove or mutate components. This eliminates the ambiguity problems of deep and wide inheritance hierarchies that are difficult to understand, maintain and extend. Common ECS approaches are highly compatible and often combined with data-oriented design techniques.

游戏领域的经典模型,相关的还有这本经典之作: Table of Contents · Game Programming Patterns.

相关资料:

Category theory

待研究和完善

From design patterns to category theory
https://blog.ploeh.dk/2017/10/04/from-design-patterns-to-category-theory/
Design Patterns was a great effort in 1994, and I've personally benefited from it. The catalogue was an attempt to discover good abstractions. What's a good abstraction? As already quoted, it's a model that amplifies the essentials, etcetera. I think a good abstraction should also be intuitive. What's the most intuitive abstractions ever? Mathematics.

优秀文章

每个架构师都应该研究下康威定律
http://36kr.com/p/5042735.html
Conway’ s law: Organizations which design systems [...] are constrained to produce designs which are copies of the communication structures of these organizations. 组织和系统架构之间有一个映射关系(1 ~ 1 mapping),两者不对齐就会出各种各样的问题。作为系统架构师,一定要深入领会康威定律,设计系统架构之前,先看清组织结构,也要看组织文化(民主合作式,集权式,丛林法则式,人才密度),再根据情况调整系统架构或者组织架构。系统架构的目标是解决利益相关者的关注点,架构师要充分和利益相关者沟通,深入理解他们的关注点和痛点,并出架构解决这些关注点。架构主要关注非功能性需求,架构的目标是用于管理复杂性、易变性和不确定性,以确保在长期的系统演化过程中,一部分架构的变化不会对架构的其它部分产生不必要的负面影响。架构,平台不是买来的,也不是用一个开源就能获得的,也不是设计出来,而是长期演化才能落地生根的。

Event Sourcing
http://martinfowler.com/eaaDev/EventSourcing.html
We can query an application's state to find out the current state of the world, and this answers many questions. However there are times when we don't just want to see where we are, we also want to know how we got there. Event Sourcing ensures that all changes to application state are stored as a sequence of events. Not just can we query these events, we can also use the event log to reconstruct past states, and as a foundation to automatically adjust the state to cope with retroactive changes.

GUI Architecture

The Elm Architecture
https://github.com/evancz/elm-architecture-tutorial

其它架构

Kappa Architecture - Where Every Thing Is A Stream
http://milinda.pathirage.org/kappa-architecture.com/
Kappa Architecture is a software architecture pattern. Rather than using a relational DB like SQL or a key-value store like Cassandra, the canonical data store in a Kappa Architecture system is an append-only immutable log. From the log, data is streamed through a computational system and fed into auxiliary stores for serving.

TLA
http://lamport.azurewebsites.net/tla/tla.html
https://learntla.com/introduction/
https://www.hillelwayne.com/post/uncle-bob/
TLA stands for the Temporal Logic of Actions, but it has become a shorthand for referring to the TLA+ specification language and the PlusCal algorithm language, together with their associated tools. TLA+ is based on the idea that the best way to describe things formally is with simple mathematics, and that a specification language should contain as little as possible beyond what is needed to write simple mathematics precisely. TLA+ is especially well suited for writing high-level specifications of concurrent and distributed systems.

Ext

Java 实践

ddd-leaven-v2
https://github.com/BottegaIT/ddd-leaven-v2
https://code.google.com/p/ddd-cqrs-sample/wiki/Introduction
DDD-CqRS sample v2.0 project that helps you with starting out advanced domain modeling using Spring, JPA and testing.

Apache Zest
http://zest.apache.org/
Apache Zest™ is a community based effort exploring Composite Oriented Programming for domain centric application development. This includes evolved concepts from Aspect Oriented Programming, Dependency Injection and Domain Driven Design. Composite Oriented Programming allows developers to work with 'fragments', smaller than classes, and 'compose' fragments into larger 'composites' which acts like the regular objects.

Design pattern samples in Java
http://java-design-patterns.com/
Design patterns are formalized best practices that the programmer can use to solve common problems when designing an application or system. Design patterns can speed up the development process by providing tested, proven development paradigms.

JavaScript 实践

What the Flux? (On Flux, DDD, and CQRS)
Domain-Driven JavaScript Development
Building JavaScript applications based on DDD, CQRS and EventSourcing
Microservices in Node.js using Event Sourcing and CQRS

cqrs-domain
http://cqrs.js.org/pages/domain.html
https://github.com/adrai/node-cqrs-domain
Node-cqrs-domain is a node.js module based on nodeEventStore that. It can be very useful as domain component if you work with (d)ddd, cqrs, eventdenormalizer, host, etc.

DDD-CQRS-Actor framework for javascript
https://github.com/liangzeng/cqrs

eventstore
https://github.com/adrai/node-eventstore
Node-eventstore is a node.js module for multiple databases. It can be very useful as eventstore if you work with (d)ddd, cqrs, eventsourcing, commands and events, etc.