书评:软件设计哲学


这篇文章是关于John Ousterhout的新书“软件设计哲学”的评论:
事实证明,写一篇有关如何将俄罗斯方块AI实现为容器化的Kotlin微服务的文章要比如何编写好的代码要容易得多。
170页的“软件设计哲学”(以下简称PoSD)是一本不起眼的书。John的背景是系统而不是软件工程或编程语言,他从未声称拥有特殊的专业知识。但他的从业者信誉是巨大的。Ousterhout的分布式内存存储系统RAMCloud我见过的最清晰,编码最好的代码之一。他是一个忙于管理大型实验室的教授,他是Tcl语言及其Tk框架的创造者。
PoSD最适合作为操作指南的战术指南。大约四分之一用于命名和评论,其余大部分用于特定模式。该书的建议比“清洁代码”等初学者书籍更高级,但其大部分内容对于高级软件工程师来说都是熟悉的。
遵循Code Simplicity等其他书籍,PoSD首先对高质量代码的好处和复杂性的危险进行了高度的解释。
前几个章节是对软件组织基本概念的一次盛大之旅:分离抽象层次,隔离复杂性,何时分解功能。
但这是第4章,他介绍了这本书的核心理念:深层模块。Ousterhout解释说,接口不仅仅是代码中编写的函数签名。它还包括非正式要素:高级行为,逻辑顺序的限制。
许多模块都很浅薄:他们需要做很多解释,但实际上并没有做那么多。一个好的模块很深:接口应该比实现简单得多。
这个观点是错误的!

当规格长于代码时
听起来“接口应该比实现更短?”听起来很不错。你如何测试它?
对于Ousterhout来说,接口只是一个备注说明和一些关于它是否易于使用和思考的讨论。直觉和经验是这里唯一的仲裁者。这揭示了他的主要盲点。

我之前已经解释   ,软件设计的重要信息不在代码(第2级)中,而是在逻辑中!

规范和推理很少具体写下来,但仍然塑造了代码。

我同意规范通常应该比代码简单得多。但是,任何具有实际规范规范经验的人都可以告诉您,有一些有趣的情况,实际中规范是并且应该比实现更复杂。
有时候,实际上需要一个比代码更复杂的规范。两个主要原因是Ghost状态不精确。Ghost状态是来自验证的概念,描述了某些类型的“微妙”代码。
不精确有例如:

  • 规范:XX的温度在60到90度之间。
  • 实施:XX的温度为70度。

规范更长,这正是因为它能创建抽象的特点所在。如果假设XX正好是70度,然后再设计系统的其余部分,则XX变得难以更换或替换。通过削弱对模块的假设,代码变得更加可演化。

除此之外,还有另一个根本原因:从内部描述内容比从外部描述内容要容易得多。向您展示一个苹果的样子要比回答可能会问到的每个问题要容易得多(有关外部的问题如种子在哪里?当我放下播下时它会如何长大?)。(banq注:接口是有关事物外部描述,接口的实现是有关内部详细描述)
举一个例子:堆栈stack数据结构,大家都同意这是一个有用的抽象。堆栈是按照后进先出顺序执行推送和弹出操作的序列集合,其内部链表的实现非常简短:只需在列表前面添加和删除元素即可。但是如果你使用堆栈,并且你不想接触到这个实现的内部细节,那么你需要一种思考它的方法,它不会引用底层链表细节,一种解决方案是使用堆栈公理,比如说“如果你把东西放到堆栈然后从堆栈中弹出,你会得到旧值”和“如果你曾经把东西推到堆栈上,那么它就不是空的。”
....


名称和类型
在本书的后半部分,我只发现了两个值得注意的建议,我认为这些建议很糟糕。
在本书的最后,Ousterhout的代码如下:

private List<Message> incomingMessageList;

incomingMessageList = new ArrayList<Message>();

为什么它被声明为List,即使它就是一个ArrayList,Ousterhout质疑这点?这不是那么明显吗?毕竟,ArrayList有自己的性能属性。
是的,但它这样做的好处是不必要地将代码绑定到ArrayList的特定实现,并且可以使代码更难以更改。Joshua Bloch在他的“ Effective Java”一书中使用点52“通过接口引用对象”中几乎相同的例子,充分争论了相反的建议。

Ousterhout建议:为每个变量提出完美的名称。
严肃对待名称,不对两个不同的概念使用相同的名称,这是一个好主意。

“使用更精确的类型”是许多软件工程问题的答案。

总结
PoSD是我读过的三本软件设计书之一,属于“中级”类别,这本书有足够的代码示例可以清晰地进行交流。PoSD不是一本完美无瑕的书,也不是原创的,但它是一本很好的书。他收集了许多建议,这些建议已经漫游成一本薄薄的书,还有一些古怪的东西,还有更大的东西。初级工程师需要学习很多东西,高级工程师需要反思很多。