反光设计
听众
程序员
每天,我们的代码都比前一天更好。
传统的设计方法认为代码不应改变。相反,新特性和功能需要通过添加新代码来支持。传统的设计通过预测可能需要的功能,并以继承、依赖注入等形式构建可扩展的 "钩子",以便将来可以添加这些功能的代码来支持这种设计。开放-封闭原则(Open-Closed Principle)是一项经典的设计准则,说明了这种思维方式:"软件实体(类、模块、函数等)应该是开放的,可以扩展,但不允许修改。
但是,Agile 团队的设计很简单,没有预见未来。他们的设计没有钩子。相反,Agile 团队有能力重构他们的代码并改变其设计。这就为一种完全不同的设计方法创造了机会:在这种方法中,实体不是为了扩展而设计的,而是为了修改而设计的。
我把这种方法称为反思性设计。
反思性设计如何发挥作用
反思性设计与传统设计不同,我称之为预测性设计。在预测性设计中,你要根据当前的需求和对这些需求可能发生的变化的最佳猜测,预测你的软件需要做什么,然后创建一个能清晰预测所有这些需求的设计。
与此相反,反思性设计不推测未来。它只关心你现在正在做的改变。使用反思性设计时,你要根据软件的现有功能分析现有代码,然后找出如何改进代码才能更好地支持当前工作。
-
看看你将要处理的代码。如果不熟悉,请逆向设计。对于复杂的代码,绘制类图或序列图等图表会有所帮助。
-
找出设计中的缺陷。哪些地方难以理解?哪些地方运行不畅?如果你最近使用过这段代码,是什么造成了问题?在你处理当前任务时,什么会妨碍你?
-
先选择一件要改进的事情。想一想设计上的改动,它能清理代码,让你当前的工作更轻松或更好。如果需要对设计进行大的改动,请与你的团队成员一起讨论。
-
逐步重构代码,以实现理想的设计。关注设计变更的实际效果。如果效果不如预期,则应改变方向。
-
重复上述步骤,直到任务完成,代码达到您想要的整洁程度。至少要比开始时好一点点。
实践中的反思性设计
我曾经不得不为我的一个网站更换登录基础架构。我原来的身份验证提供商 Persona 已经停产,因此我需要更换为新的身份验证提供商 Auth0。这是一个很大的变化,需要一个新的注册流程。
我没有事先计划好整个变更,而是采用了反思性设计,一步一步地进行。我专注于第一个故事,即添加一个使用 Auth0 的登录流程。在 Auth0 更改完成之前,它将被功能标志隐藏起来。
我的第一步是逆向设计代码。我已经有好几年没有接触过这些代码了,所以就像从来没有见过一样。幸运的是,虽然代码远非完美,但我一直专注于简单的设计,所以它很容易理解。没有一个方法的代码行数超过 20 行,大多数都少于 10 行。最大的文件只有 167 行。
我从现有的登录端点开始。我没有深入研究,只是查看了每个文件的导入,并追踪了依赖关系。login 端点依赖于PersonaClient 和SubscriberAccount 。PersonaClient 依赖于HttpsRestClient ,后者是第三方代码的封装。SubscriberAccount 依赖于RecurlyClient ,后者又依赖于HttpsRestClient 。
这些关系如图 14-3 所示。实际上,我当时并没有绘制类图,只是在编辑器中打开了文件。这些关系非常简单,我可以把它们全部记在脑子里。
图 14-3. 身份验证设计分析
接下来,我需要找出设计中的缺陷。缺陷有很多。这是我近四年前为网站编写的一些最早的代码,从那时起我学到了很多东西。
-
我没有将逻辑与基础架构分开。相反,
SubscriberAccount ...
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access