-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
精读《架构设计 之 DCI》 #20
Comments
DCI 即 数据(data) 场景(context) 交互(interactive)。 DCI 之所以被提出,是因为传统 mvc 代码,在越来越丰富的交互需求中变得越来越难读。有人会觉得,复杂的需求 mvc 也可以 cover 住,诚然如此,但很少有人能只读一遍源码就能理解程序处理了哪些事情,这是因为人类思维与 mvc 的传统程序设计思想存在鸿沟,我们需要脑补内容很多,才会觉得难度。 现在仍有大量程序使用面向对象的思想表达交互行为,当我们把所有对象之间的关联记录在脑海中时,可能对象之间交互行为会比较清楚,但任无法轻松理解,因为对象的封装会导致内聚性不断增加,交互逻辑会在不同对象之间跳转,对象之间的嵌套关系在复杂系统中无疑是一个理解负担。 DCI 尝试从人类思维角度出发,举一个例子:为什么在看电影时会轻轻松松的理解故事主线呢?回想一下我们看电影的过程,看到一个画面时,我们会思考三件事:
很快把这三件事弄清楚,我们就能快速理解当前场景的逻辑,并且轻松理解该场景继续发生的状况,即便是盗梦空间这种烧脑的电影,当我们搞清楚这三个问题后,就算街道发生了180度扭曲,也不会存在理解障碍,反而可以吃着爆米花享受,直到切换到下一个场景为止。 当我们把街道扭曲 180 度的能力放在街道对象上时,理解就变的复杂了:这个函数什么时候被调用?为什么不好好承载车辆而自己发生扭曲?这就像电影开始时,把电影里播放的所有关于街道的状态都走马灯过一遍:我们看到街道通过了车辆、又卷曲、又发生了爆炸,实在觉得莫名其妙。 理解代码也是如此,当交互行为复杂时,把交互和场景分别抽象出来,以场景为切入点交互数据。 举个例子,传统的 mvc 可能会这么组织代码:
class My {
private name = "ascoders" // 名字
private skills = ["javascript", "nodejs", "切图"] // 技能
private hp = 100 // 生命值??
private account = new Account() // 账户相关
}
class Controller {
private my = new My()
private account = new Account()
private accountController = new AccountController()
public cook() {
// 做饭
}
public coding() {
// 写代码
}
public fireball() {
// 搓火球术。。?
}
public underAttack() {
// 受到攻击??
}
public pay() {
// 支付,用到了 account 与 accountController
}
} 这只是我自己的行为,当我这个对象,与文章对象、付款行为发生联动时,就发生了各种各样的跳转。到目前为止我还不是非常排斥这种做法,毕竟这样是非常主流的,前端数据管理中,不论是 redux,还是 mobx,都类似 MVC。 不论如何,尝试一下 DCI 的思路吧,看看是否会像看电影一样轻松的理解代码: 以上面向对象思想主要表达了 4 个场景,家庭、工作、梦境、购物:
以程序员工作为例,在工作场景下,写代码可以填充我们的钱包,那么我们看到一个程序员的钱包:
case class CodingWallet(name: String, var balance: Int) {
def coding(line: Int) { balance += line * 1 }
} 写一行代码可以赚 1 块钱,它不需要知道在哪个场景被使用,程序员的钱包只要关注把代码变成钱。 交互是基于场景的,所以交互属于场景,写代码赚钱的交互,放在工作场景中:
object MoneyTransferApp extends App {
@context
class MoneyTransfer(wallet: CodingWallet, time: int) {
// 在这个场景中,工作 1 小时,可以写 100 行代码
// 开始工作!
wallet.working
role wallet {
def working() {
wallet.coding(time)
}
}
}
// 钱包默认有 3000 元
val wallet = CodingWallet("wallet", 3000)
// 初始化工作场景,工作了 1 小时
new MoneyTransfer(wallet, 1)
// 此时钱包一共拥有 3100 元
println(wallet.balance)
} 总结一下,就是把数据与交互分开,额外增加了场景,交互属于场景,获取数据进行交互。原文的这张图描述了 DCI 与 MVC 之间的关系: |
抛砖引玉,关于 DCI 项目实践,需要大家来补充 |
作为架构白,看到 DCI 时一头雾水。于是用心补了下相关知识,从中发现了梳理现代前端越来越多的概念、模式和实践这些知识的蛛丝马迹。 现代前端受益于低门槛和开放,伴随 OO 和各种 MV* 盛行,也出现了越来越多的概念、模式和实践。而 DCI 作为 MVC 的补充,试图通过引入函数式编程的一些概念,来平衡 OO 、数据结构和算法模型。值得我们津津乐道的如 Mixins、Multiple dispatch、 依赖注入(DI)、Multi-paradigm design、面向切面编程(AOP)都是不错的。如果对这些感兴趣,深挖下 AngularJS 在这方面的实践会有不少收获。 软件架构设计,是一个很大的话题,也是值得每位工程师长期实践和思考的内容。个人的几点体会:
分享些架构相关的文章: |
@ascoders 纠正个错别字...
|
随着前端ES6 ES7 的一路前行, 我们大前端借鉴和引进了各种其他编程语言中的概念、特性、模式; 我们可以使用函数式Functional编程设计,可以使用面向对象OOP的设计,可以使用面向接口的思想,也可以使用AOP, 可以使用注解,代理、反射,各种设计模式; 在大前端辉煌发展、在数据时代的当下 我们来一起阅读一篇设计相关的老文:
《The DCI Architecture》
The text was updated successfully, but these errors were encountered: