关于软件设计

面试被虐复盘整理。

周二参加了一场面试,大数据部门。二面时面试官问到了许多面向对象编程、类、继承,编程语言未来的发展之类的问题,答得不好。

其实之前对这些名称有一些了解,包括领域驱动设计啊、编程范式、OOP 啊之类的,但是了解的不深入,并且没有一个整体的概念。回家之后把面试官的问题捋顺了一下,查阅部分资料之后,好像最后都指向了一个方向 —— 软件设计。现整理如下:

是什么

软件设计是一门关注长期变化的学问。初学编程的程序员会追求把一个功能实现出来,他无法看到一个软件长期的变化。

算法和软件设计其实是一样的,二者对抗的都是规模问题。算法对抗的是数据的规模,而软件设计对抗的是需求的规模。数据达到一定规模之后,快速排序比插入排序才更有优势;需求达到一定规模之后,面向对象的编程范式会比面向过程更有优势。

模型

软件开发的目的是什么?

是解决由需求带来的问题,解决的结果是一个可以运行的交付物。比如在线购物的需求,通过电商平台这个方案来解决。

软件设计,就是架通需求和解决方案的桥梁!

区别于解决简单的问题,软件的开发往往是一项长期的工作,会有许多人参与其中。在这种情况下,就需要建立起一个统一的结构,以便于所有人都能有一个共同的理解。这就如同建筑中的图纸,懂建筑的人看了之后,就会产生一个统一的认识。

在软件的开发过程中,这种统一的结构就是模型,而软件设计就是要构建出一套模型

模型,是一个软件的架构。

  • 粒度上可大可小;
  • 好的模型应该“高内聚、低耦合”;
  • 模型可以分层,由底层的模型提供接口,构建出上层的模型。

规范

规范,就是限定了什么样的需求应该以怎样的方式去完成。比如:

  • 与业务处理相关的代码,应该体现在领域模型中;
  • 与网络连接相关的代码,应该写在网关里;
  • 与外部系统集成的代码,需要有防腐层;

显式的、统一的规范可以使项目以一个统一的方式去进行,即便未来设计要演化、规范要调整,项目也要可控得多。

分离关注点

软件开发中最常见一种解决问题的方式就是“分而治之”。大系统拆解为模块,模块再拆分为小功能。值得注意的是,拆解时候要从多维度去考虑,每个维度代表一个关注点,这就是设计中常见的一个说法:分离关注点。

不同的关注点混合在一起可能会带来很多问题,另一方面,分离关注点有助于我们发现不同模块的共性,更好的进行设计。

常见的关注点混淆情况:

  • 技术和业务混淆:
    • 例子:上游系统以推送的方式向当前系统发消息,但是有可能会丢消息,于是开发人员加了一个补偿机制,来请求丢失的消息。业务量大的时候,补偿机制触发频繁,进一步加大服务器负担。问题点在于,推送消息是通信层面的问题,补偿机制将其带到了业务层面,更好的解决方案是选择一个吞吐量更大的消息队列。
  • 不同数据变动方向的混淆:
    • 在 Java 应用里,做数据库访问用 Spring Data JPA 好,还是 MyBatis 好。Spring Data JPA 简化了数据库访问,自动生成对应的 SQL 语句,而 MyBatis 则要自己手写 SQL。从本质上说,之所以出现工具选择的困难,是因为他把两种数据使用频率不同的场景混在一起所造成的。如果将前台访问(处理增删改查)和后台访问(统计报表)分开,纠结也就不复存在了。

包括什么

  • 程序设计语言
    • 模型、接口、运行时
  • 编程范式
    • 结构化编程
    • 面向对象编程
    • 函数式编程
  • 设计模式
    • 发布订阅模式
  • 设计原则
    • 单一职责
    • 开放封闭
    • 接口隔离
  • 设计方法
    • 领域与驱动设计
    • 战略设计
    • 战术设计

初步学习,大致包括以上几个大方面,每个方面拿出来都够说上半天的,后续每个模块会陆续更新单个的文章。

参考

  • 软件设计之美
  • 软加设计的哲学