软件设计之美
郑晔
推文科技技术VP,前火币网首席架构师
立即订阅
3360 人已学习
课程目录
已更新 32 讲 / 共 36 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 软件设计,应对需求规模的“算法”
免费
课前必读 (3讲)
01 | 软件设计到底是什么?
02 | 分离关注点:软件设计至关重要的第一步
03 | 可测试性: 一个影响软件设计的重要因素
了解一个软件的设计 (4讲)
04 | 三步走:如何了解一个软件的设计?
05 | Spring DI容器:如何分析一个软件的模型?
06 | Ruby on Rails:如何分析一个软件的接口?
07 | Kafka:如何分析一个软件的实现?
设计一个软件—程序设计语言 (5讲)
08 | 语言的模型:如何打破单一语言局限,让设计更好地落地?
09 | 语言的接口:语法和程序库,软件设计的发力点
10 | 语言的实现:运行时,软件设计的地基
11 | DSL:你也可以设计一门自己的语言
加餐 | 再八卦几门语言!
设计一个软件—编程范式 (9讲)
12 | 编程范式:明明写的是Java,为什么被人说成了C代码?
13 | 结构化编程:为什么做设计时仅有结构化编程是不够的?
14 | 面向对象之封装:怎样的封装才算是高内聚?
15 | 面向对象之继承:继承是代码复用的合理方式吗?
16 | 面向对象之多态:为什么“稀疏平常”的多态,是软件设计的大杀器?
17 | 函数式编程:不用函数式编程语言,怎么写函数式的程序?
18 | 函数式编程之组合性:函数式编程为什么如此吸引人?
19 | 函数式编程之不变性:怎样保证我的代码不会被别人破坏?
加餐 | 函数式编程拾遗
设计一个软件—设计原则与模式 (7讲)
20 | 单一职责原则:你的模块到底为谁负责?
21 | 开放封闭原则:不改代码怎么写新功能?
22 | Liskov替换原则:用了继承,子类就设计对了吗?
23 | 接口隔离原则:接口里的方法,你都用得到吗?
24 | 依赖倒置原则:高层代码和底层代码,到底谁该依赖谁?
25 | 设计模式:每一种都是一个特定问题的解决方案
26 | 简单设计:难道一开始就要把设计做复杂吗?
设计一个软件—设计方法 (3讲)
27 | 领域驱动设计:如何从零开始设计一个软件?
28 | 战略设计:如何划分系统的模块?
29 | 战术设计:如何像写故事一样找出模型?
软件设计之美
15
15
1.0x
00:00/00:00
登录|注册

01 | 软件设计到底是什么?

郑晔 2020-05-25
你好!我是郑晔。
一个软件需要设计,这是你一定认同的。但软件设计到底是什么,不同的人却有着不同的理解:
有人认为,设计就是讨论要用什么技术实现功能;
有人认为,设计就是要考虑选择哪些框架和中间件;
有人认为,设计就是设计模式;
有人认为,设计就是 Controller、Service 加 Model;
……
你会发现,如果我们按照这些方式去了解“软件设计”,不仅软件设计的知识会很零散,而且你会像站在流沙之上一般:
今天你刚学会用 Java,明天 JavaScript 成了新宠,还没等你下定决心转向,Rust 又成了一批大公司吹捧的目标;
你终于知道了消息队列在解决什么问题,准备学习强大的 Kafka,这时候有人告诉你 Pulsar 在某些地方表现得更好;
你总算理解了 Observer 模式,却有人告诉你 JDK 中早就提供了原生的支持,但更好的做法应该是用 Guava 的 EventBus;
你好不容易弄清楚 MVC 是怎样回事,却发现后端开发现在的主要工作是写 RESTful 服务,Controller 还没有用,就应该改名成 Resource 了;
……
我们说,软件设计要关注长期变化,需要应对需求规模的膨胀。这些在不断流变的东西可能还没你的软件生命周期长,又怎能支撑起长期的变化呢!
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《软件设计之美》,如需阅读全部文章,
请订阅文章所属专栏新⼈⾸单¥19.9
立即订阅
登录 后留言

精选留言(31)

  • 段启超
    防腐层是模型的一个规范,分享下我对防腐层的认知:
    我接触防腐层的概念是从DDD的限界上下文开始的。Eric用细胞膜的概念来解释“限界”的概念,细胞膜只让细胞需要的物质进入细胞,同样,我们的代码之间业务也存在这个样一个界限,同一个对象的业务含义在不同的上下文中是不一样的。以在网上买书为例,在购买页面,我们的关注点在于这本书的名称,作者,以及分类,库存等信息;提交订单后,这本书就成为了订单上下文中的一个订单item,我们会关注这个item 的数量以及购买他的人是谁,以及书的配送地址等; 订单提交给仓库后,仓库会关心这本书还有没有库存,以及打包状态,分拣,物流等状态。
    防腐层是在限界上下文之间映射(说白了就是交互)的方式,体现在代码上就是一个对象的转换,这个转换的意义在于隔离变化,防止因为对象在一个上下文中的变化扩散到其他的上下文中。

    关于规范:
    规范也是团队文化中很重要的一部分,以持续集成为例子,它的执行严格依赖于团队的开发纪律文化,以为了所谓赶进度而单元测试覆盖很低或者直接不写;采用分支策略方开发,一星期都合并不了主干,类似的人到处倒是,也就因为这一点,很多团队都在持续集成这个环节上掉队了。所以开发规范真的很重要,时刻谨记:混乱始于没有规范。

    作者回复: 非常好的补充!

    2020-05-26
    29
  • Kǎfκã²⁰²⁰
    业务讨论之后进行领域设计,画出出静态模型(包括子系统、模块等)和动态结构(交互等),或者先勾勒接口(内内外系统的区隔),再做模型。实际过程有很多反复,并且会进行角色代入,看模型能否支持业务,直到模型比较稳定

    作者回复: 你们做得很好

    2020-05-25
    4
    14
  • 渺渺兮于怀
    慢慢的,某个瞬间,突然觉得自己的工作不再是码农,而是软件设计,并且在工作中得到强烈的自我肯定。
    一个好的软件设计思路,首先是符合大众习惯行为、符合日常常理,其次再是数据模型设计、技术范畴设计。
    一个好的软件设计实现,往往可以很容易兼容正常合理的需求变更,对开发工作来说,掌握其核心,理论与实践相结合,可以事半功倍!

    作者回复: 你把自己当做码农,你就是码农;你把自己当做优秀的程序员,你就是优秀的程序员。心理学上称之为皮格马利翁效应。

    2020-05-25
    8
  • 木云先森
    还需要前面有个好的产品经理或是业务专家。以及公司有个好的文化。各种频繁的插队的需求,各种前后都无法闭环的需求。都是,软件产品异常大的阻碍

    作者回复: 《10x 程序员工作法》在先,《软件设计之美》在后。

    2020-05-25
    6
  • 渔夫
    很多软件产品的需求都是一点点冒出来的,甚至中途需求还会去溜出去绕个弯,然后又回归,设计有种被牵着鼻子走的感觉,工期紧迭代快,结果就是设计的模型中有大量名不符实的定义,还有很多定义的补丁,实在很糟心,当然需求发展方向终会明朗,这时候就需要重构整理,包括设计和实现,同时又要应对新的业务开发,于是形成了两线或多线作战,苦啊!这样的情况除了增加团队,不知道老师有什么好的建议?

    作者回复: 先去学《10x程序员工作法》,先别让人给自己捣乱,有一个合理的工作计划。如果你没时间学习,没时间做改进,别的东西都不用说了。

    有了一个合理的安排之后,才是说要怎么改进,要怎么做得更好,消除欠下的技术债。

    2020-05-25
    1
    5
  • 晴天了
    设计了1程序 开发完成了。 这时候产品说 在1内部加一条小需求。。 这种情况是不是很抓狂

    作者回复: 是啊是啊,所以要先学《10x 程序员工作法》,让产品经理别捣乱。

    2020-05-25
    4
  • 迈步
    老师您好,我们有一套基于DDD思想的程序开发模板,我们为了避免个体开发差异,所以建议大家都使用统一的开发模板。目前我面临着两个问题
    1、针对某些使用简单分层架构即可解决问题的服务,是允许使用简单分层架构还是使用统一的DDD开发模板?
    2、统一开发模板在一定程度上规避了个体差异上的劣势。那么个体差异上的优势如何更好的体现呢?

    作者回复: 把 DDD 当做一个模板,这个理解方式本身是没有问题的,它就是告诉你,如何把设计中的模型分门别类的放置,后面我们讲 DDD,差不多也是这个思路。

    对于任何一个系统而言,需求都是一点一点增加的,前期不做设计,后期改动起来,难度就非常大了。所以,核心的点在于,设计要做好,别看它现在简单。分层不是你的设计,而构建出你的模型才是设计。

    我不是特别理解你们按照 DDD 思想的开发模板到底是个什么东西,是一个开发框架,还是一个思维工具,所以,不敢妄加判断。

    对于一个团队而言,开发的一致性比个性要重要,因为没有人可以保证一直在一个团队工作下去。

    如果你真的有不错的理念,去做规范和框架的级别的优化、去做算法上的优化,不要在小的地方体现创造力,意义不大。

    2020-06-17
    3
  • Geek_3b1096
    先来补课10x程序员工作法

    作者回复: 先能分清楚问题在哪,然后,再来解决。

    2020-05-27
    2
  • escray
    文章在开篇提出的关于软件设计的问题,其实也是我现在的困惑,因为在做求职前的准备,感觉有很多东西要学,极客时间的专栏那么多,眼花缭乱。如何才能提高自己的求职成功率呢?

    软件开发是为了解决问题,而软件设计就是在需求和解决方案之间的桥梁。

    对于“软件设计就是构建出一套模型”这个说法,我感觉似乎有点过于抽象了,虽然文中列举的那个交易系统模型,确实很简洁、准确。

    如果单独来看“模型”和“规范(约束)”都比较容易理解,但是如果说软件设计就是设计出模型和规范来,又有些不好理解了。特意去看了一下 Wiki:

    Software design is the process by which an agent create a specification of a software artifact, intended to accomplish goals, using a set of primitive components and subject to constraints.

    感觉上自己以前可能更看重软件开发的结果,而忽视了其中的模型和约束。

    在这之前,如果拿到一个项目,大概会先看看是 CS 还是 BS 的,一般会采用 MVC 或者是分层模型,然后再去看看有没有其他的开源软件可以借鉴,之后就开始码程序了,编写代码边修改,可能从整体设计上考虑的比较少。

    看了一下留言,发现自己之前可能局限于个体软件作坊,并没有正式或者完整的软件设计过程。那么我有一个问题:软件设计是只适用于相对复杂一些的软件开发过程么?如果程序本身比较简单,而且是那种“用完即焚”式的,是否还需要设计?

    另外一个问题,就是软件设计和架构设计的区别在哪里?应该不仅仅是范围大小的差别吧 。

    期待后续的专栏。

    作者回复: 非常感谢你的补充!

    我不会为 Hello,World 做设计,因为它真的“用完即焚”,在开篇词里我说过,设计是应对需求规模的算法。需求越来越多,设计和不设计的差别就会体现出来。但是,你不学习软件设计的话,想直接应对复杂软件是不可能的。

    关于软件的设计过程,我们后面会讲到 DDD,你可以关注一下。

    软件设计和架构设计,其实是没有区别的,只不过,通常把高层一些的设计称为架构设计,但我们这里所学的设计原则同样适用于架构设计。

    2020-05-27
    2
  • Wei
    很多IT legacy项目,存在了7,8年甚至更久。对比起项目刚开始的时候,语言,框架,best practices, 需求,人员变更等都往往都已经很不一样了。 对着这种“祖传”项目,往往文档缺失,结构复杂,动一发而牵千全身;

    对这种项目做设计优化,该从哪些方面切入呢?

    作者回复: 设计改进将在专栏的最后与大家讨论,敬请期待!

    2020-05-26
    1
    2
  • 大王拍我去巡山
    前台业务变化快 经常这次上线验证效果不好就推翻重做。对于扩展和规划的要求就更高了。现在都是做一步想三步。根据经验考虑后面会有什么变化。。

    作者回复: 不管什么系统,都有一部分内容是稳定的,一部分内容是不稳定的。所以,我们设计的重点就是把稳定的和不稳定的隔离开来。不稳定的验证不好,丢了就丢了,没什么可惜的。千万不要做过度的设计,浪费精力,后面会讲到简单设计。

    2020-05-26
    2
  • y欧尼酱
    刚开始按照模型和规范走着,后来随着需求的改动,客户不停的催促,代码改动越来越乱,先把工作完成后再改规范,还是有什么好的办法。

    作者回复: 首先,要分清楚哪些是人为的问题,哪些是设计的问题。赶工绝对是人为的问题,需要设置正确的预期,这是《10x 程序员工作法》讨论的范畴。

    其次,如果是设计问题,需要把分清楚哪些是变的部分,哪些是不变的部分。不变的部分花力气去设计,变的部分需要等一等,等它相对稳定一些,再花大力气去设计。

    规范主要是针对你需要花力气去设计的部分,混乱的部分,就先混乱着。让子弹飞一会儿。

    2020-05-26
    2
  • 光明
    简单一点的项目,成员相互讨论(主要讨论业务场景和流程),内心会意即可。

    复杂一点的项目,设计一般落脚在粒度较粗的文档上,往往也以说明业务流程为主,很少对实现过程中的细节文档化。

    所以,我们的项目设计,模型一般会被业务场景和流程替代。文中的「模型」和「规范」,更多取决于工程师了。。。

    作者回复: 对,你说的确实符合大部分做设计的方式。这种设计的关注点在于实现功能,而非构建模型。

    这种做法容易让人忽略掉哪个东西是核心的,是模型,还是流程。流程是容易调整的,而模型如果变了,这个软件整个就变了。做设计的关键是,找到不变的东西。

    2020-05-26
    2
  • 业余爱好者
    向贝佐斯学习,做事情要建立在不变的东西上。

    模型是一个理解世界的抽象模型,就像科学理论一样。好的模型应该是稳定的,简洁的。

    规范也不能朝令夕改,规范就是做事的高层原则,相当于“公理”。公理要么来自于根深蒂固的人性(广义的,中性的,如懒惰,两点之间直线最短),要么就是大量经验教训的积累(如业界各公司如阿里巴巴开发手册之类)。(这里看出为什么小公司规范意识稀缺了,踩得坑不足,积累经验不足,你就是想规范也规范不起来。解决办法就是参考业界或大公司的规范,当然不能照搬。)

    作者回复: 编码规范和设计规范还是有所差异的。编码规范的适用范围会更大一些,设计规范则适用于一个特定的项目。

    2020-05-26
    2
  • 小文同学
    我独立设计的第一个项目整体来说,是失败的。就是盲目模仿前项目,没理解,分层,抽象,接口,模型等设计概念,最终项目陷入很麻烦的技术问题。

    作者回复: 应该说是独立“实现”了一个项目。

    2020-05-25
    2
  • 捞鱼的搬砖奇
    熟悉的声音回来了。

    作者回复: 也欢迎你回来!

    2020-05-25
    2
  • 邵俊达
    老师您好,请问您文章中说的「交易原语」在代码中是如何体现的呢?是指把不同的动作放到一个事务中吗?比如「成交」这个原语是不同账户的出金和入金这两个操作放在一个事务里?

    作者回复: 原语是一个一个小类或小方法,动作则是原语的组合,它是放到一个事务中的。你读“成交”这个动作的理解是对的,是在一个事务中执行的。

    2020-07-14
    1
  • 亚伦碎语
    我们代码里通常把防腐曾叫adapter

    作者回复: 有一些类似的地方,但不完全一样。

    2020-06-12
    1
  • 刘拯均
    诚如郑老师所言,提到软件设计,一开始涌入头脑的便是框架或项目的结构。感觉有很多内容,无法完整的组织在一起。模型+规范,言简意赅,将软件设计的精髓提炼了出来。从“10x程序员”到这里,郑老师一如既往地将最简练、精髓的部分呈现在我们眼前。让我们看到郑老师眼中的程序世界,这给了我们身处泥潭,却能仰望山巅的风景途径。感谢郑老师的分享,加油学习.

    作者回复: 承蒙夸奖,也欢迎邀请更多的小伙伴们一起来学习!

    2020-06-04
    1
  • Jxin
    1.我现在在项目中采用ddd的分层架构。(不要求领域模型设计,仅限定了基本实现规范)
    2.因为整个公司缺乏显示统一的规范,我希望引入ddd的分层架构去限定这个规范。而且,项目本身虽是微服务技术栈,但模型本质还是大单体,用ddd挺好。(如果是真的微服务,不需要采用ddd的分层,ddd分层架构的理念应该在系统架构上去体现,落地到具体微服务包应该要对这些复杂性无感)
    3.起了分层的目录结构,做了下各层作用的讲解,前期大部分需求,我都定义好api,然后让队友们来实现。结果还是不理想。问题不在于知识难不难,而在个人意愿和市场需求。相对于个人代码质量的追求,大多数人更愿意把时间放在技术上。毕竟技术面试占分更高,且武学学会了就是会了,能做到分毫不差,短期既有价值。而内功除了学会,还要积累,短期难有成效。人往往都有点浮躁。

    作者回复: 你们的设计已经算得不错的了。

    2020-05-25
    1
收起评论
31
返回
顶部