关于软件设计的一些问题

2022-02-22 21:41:53 +08:00
 lanlanye

不知道各位写代码时会不会经常觉得遇到以下问题:

  1. 某个听起来很自然的功能实现起来却需要绕很大一圈。
  2. 某个功能的实现不可避免的会影响到许多不相关的功能。
  3. 迭代到某个阶段,软件的响应越来越慢,逻辑越来越复杂,开发人员已经搞不懂自己在做什么了。

...

以上只是我遇到许许多多问题中的一小部分,毕业快两年,我时常觉得自己写出的东西随着功能的增加离自己的设想越来越远,即使满足了业务需要也无法让自己满意。

我认为开发难以进行的根源往往不是因为开发人员不会写业务代码,而是设计上出现了不合理的地方,有时是因为初期没有时间仔细考虑,有时是因为不可避免的需要与其他项目耦合,然而归根结底是开发者的设计能力不足,没能让软件保持低耦合与高内聚。

近一个多月的时间,我试着通过各种渠道补充相关知识,从 数据库设计的一个小问题 到流行的架构模式和设计模式逐步学习,深感从 Python 开始开发一定程度上让我低估了面向对象设计的重要性。

以下是我最近读过或正在读的书单(按时间顺序):

  1. 《数学之美》
  2. 《 SQL 反模式》
  3. 微软公开的 Azure 设计模式说明
  4. 《实现领域驱动设计》
  5. 《设计模式》
  6. 《领域驱动设计·精简版》
  7. 《领域驱动设计·软件核心复杂性应对之道》

顺序上存在一些不合理的地方,比如《实现领域驱动设计》中提到了许多我难以理解的概念,这些概念是通过穿插着阅读后面几本书以及通过搜索引擎才逐渐能够理解的(以及我至今也没能把这本书彻底读完),这些书中也会引用其他人的著作,受限于时间我也没能逐个阅读,比如《分析模式》、《重构》等。

可是直至目前我依然有很多疑问:印象里不久前还经常被人提起的“函数式编程”有什么优势?如果面向对象设计是一种“最佳实践”,为什么后来诞生的语言没有特别强调自己面向对象的特性?

简言之,我隐约感觉自己遇到了瓶颈,我不确定这些疑惑是否会随着不断学习而得到解答,同时也很担心自己绕了远路钻了牛角尖,所以 希望站内的大佬们可以推荐一些相关书籍或者分享一些自己的学习经历、见解

另外,我建了一个 QQ 群,希望 和我有同样困惑或相似目标 的人能够加入进来共同交流进步。这是一个尝试,我希望它是一个单纯的技术交流群,没有日常寒暄和无意义水群,不会因为过多的消息被人屏蔽,如果实在做不到我也可能解散掉它,群号 OTAyMzE0NDEz

3791 次点击
所在节点    程序员
44 条回复
3dwelcome
2022-02-22 22:19:50 +08:00
设计软件就炒股一样。股票里 K 线图有个著名的随机游走策略,导致你不管做短线,中线,还是长线,输赢概率是相同的。微观操盘和宏观操盘上,体验是一致的。

套用在软件开发也类似,从微观设计 API ,和宏观调用 API ,也需要保证开发体验是一致的,才能控制好全局。

不能因为代码增多,就陷入局部细节。要不断的封装对象,隐藏细节,让代码流程保持在一定可供总量。往往代码量太多,又没有合理的封装,才是屎山的开端。

至于“函数式编程的优势”,个人觉得就是能做到无状态编程,没内部状态维护,那么固定输入后,输出结果都是可预测的。能减少一些心智负担。
qaqLjj
2022-02-22 22:30:31 +08:00
请问 ddd 最入门的文档是哪一篇啊,ddd 大名鼎鼎,想了解一下
lanlanye
2022-02-22 22:40:27 +08:00
@qaqLjj 我觉得应该是 InfoQ 这本 https://www.infoq.cn/minibook/domain-driven-design-quickly
《实现领域驱动设计》中将这种称为「 DDD Lite 」或者「战术 DDD 」,因为它对战略设计的部分仅仅解释了一下概念,没有深入,看完后还是得去读原著,但能解释清楚概念已经非常有用了。
3dwelcome
2022-02-22 22:54:57 +08:00
我以前发了一个去函数编程的方案。

也就是用命令式指令,去替代传统函数的封装。类似一点 DSL 的定义。

可惜最后被移到了水深火热专区,因为大家都不信,去了函数后还怎么写代码。

这就是大家编程理念不同,微观上是函数,宏观上就自然升级到了指令。真是残念,我好多贴都去了水区,一去不复返。
qaqLjj
2022-02-22 22:56:01 +08:00
@lanlanye 这本会不会太老了,我看是 07 年发布的,那时候我小学都没毕业
liuhan907
2022-02-22 23:01:45 +08:00
@3dwelcome
指令和函数除了叫法不同,我很难想出还有什么区别啊。。。
lanlanye
2022-02-22 23:05:03 +08:00
@3dwelcome 网络上对函数式编程的解释似乎很杂,类似 Google 的 map+reduce 这种模式我还能理解它的实际意义,但其他场景下到底怎么用我是完全不知道,特别是最近看的书都强调面向对象设计,感觉它们根本没有互相替代的可能。

@qaqLjj Eric Evans 的原著是 03 年的,不排除其中一些概念过时了的可能性,比如当时 web 还没有那么火,之后的移动互联网更是难以想象的,但后来者对这本书的解读感觉还不如原文,我觉得想要理解作者的思想,还是看原文比较好。(《 CSAPP 》出版于 2004 年,理论性的知识并不容易过时)
3dwelcome
2022-02-22 23:11:02 +08:00
@liuhan907 我这里的指令类似于 LUA 脚本定义,每个指令都是负责控制一堆函数体。是函数集的上层抽象。

函数里我一般不习惯牵涉业务,业务太多太杂,命名太辛苦,写一大堆函数没多大必要。而指令大部分都是能和业务实际挂钩的。

可能没代码很难理解,指令可以看成是 onmessage 里的一个个接受命令体,没有自己的函数入口,但能正常调用别的函数。但很可惜那个详细说明的帖子,我自己也找不回了。
liuhan907
2022-02-22 23:14:49 +08:00
@3dwelcome
但是函数难道不符合这个定义么?或者说,你认为的指令和函数本质上的区别是什么,我无法想象。函数本身已经就是对动作过程的描述,再增加一层抽象得到了什么好处呢?或者说,能否解释一下指令嵌套函数的模式和函数嵌套函数的模式有什么优势。
3dwelcome
2022-02-22 23:15:14 +08:00
比如 Restful 的注册函数,正常写法,可能用户注册就是对应一个注册函数。

而我就是一个 RPC 的注册指令,和外部路由绑定后,就直接处理了。
3dwelcome
2022-02-22 23:18:28 +08:00
@liuhan907 "你认为的指令和函数本质上的区别是什么 再增加一层抽象得到了什么好处呢?"

好处就是宏观写法和微观写法隔离开。

你管理几百个函数也许没问题,在几千上万个函数里跳来跳去,还是很有压力的。

我自己建立了一套指令网状体系,可以很快跳到自己需要修改业务的位置。
Mithril
2022-02-22 23:18:56 +08:00
这就是架构师的价值了。
说的是正经的架构师,不是那些满口新技术的 PPT 架构师。
软件架构设计和软件需求本身就是互相制约的,什么样的需求就导致会有什么样的架构设计和技术选型,同时这个架构设计又会反过来制约需求的发展。
所以一个好的产品,需要有足够强力和有经验的架构师和 PM 团队来一起界定需求和架构要互相妥协成一个什么样子,然后后续的开发和需求都围绕着这个共识来做。
这就是 DDD 的第一步了。
taowen
2022-02-22 23:19:08 +08:00
https://zhuanlan.zhihu.com/p/356202989 代码写得不好,不要总觉得是自己抽象得不好
9c04C5dO01Sw5DNL
2022-02-22 23:21:06 +08:00
DDD 就很玄,不如 fp 思想来的实在。
Macolor21
2022-02-22 23:32:10 +08:00
@3dwelcome #8
@3dwelcome #10

没搞清楚你想说的是啥,Scala 函数式编程,有个 Scala 框架叫 Akka 。

基本思想类似于一个 Actor 是一堆函数的集合,如 计算 Actor {
.onMessage(Initilize.class, handleInitilize)
.onMessage(Plus.class, handlePlus)
.onMessage(Minus.class, handleMinus)
}

想要调用函数就是往 Actor 发一个消息,指令。如: computeActor.tell( new Plus(1) ); 就会执行 handlePlus 里面的逻辑

Actor 不会 new 一个 Actor 类的对象出来,而是 invoke 这个函数。
3dwelcome
2022-02-22 23:37:55 +08:00
@Macolor21 以上古的 win32 编程举例吧。

一个 message ,就是一个 WM_USERREG 注册函数,加两个未命名的 wParam 和 lParam 。

没有函数体,不用给函数起名字。只需要 WM_USERREG 和若干个未命名参数,就可以执行一段用户注册的逻辑代码,并顺利返回结果。

反正就是这个意思。
lanlanye
2022-02-22 23:39:14 +08:00
@Mithril 我也是这么想的,只是我们小公司没有正经架构师,所以总是遇到问题。

@taowen 还好,我们产品会参考我的意见,不会出现你说的情况。

@giiiiiithub 确实很玄,但 FP 开始时轻松,随着发展心智负担越来越大(主要是需要保证无状态),还是说有什么成体系的方法论推荐吗?
9c04C5dO01Sw5DNL
2022-02-22 23:58:04 +08:00
@lanlanye FP 也不用入邪教,就对写清晰好测的函数,从小到大构建系统整体或者局部有帮助就行了。 我之前看的是《 functional programming in scala 》以及杂七杂八文章。比如所谓的无状态,其实是把状态推到其他地方隔离起来了,这样关键性的一部分函数就可以是纯的了。
secondwtq
2022-02-22 23:59:44 +08:00
我认为所谓的函数式编程,纯也好不纯也罢,主要的现实意义在于其组合性上
https://v2ex.com/t/807880#r_10977046
mascteen
2022-02-23 00:22:35 +08:00
推荐看看范畴论在语言中的运用

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/835769

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX