有时会有人提到这个词。 在最多样化的环境中。 这个词曾被用来表达许多不同的事物,当一个单词可以表达任何含义时,它最终就意味着什么。 在本文中,我经过大量研究后,以迄今为止最精确的方式解释了我对软件体系结构的看法。
> A library's architecture doesn't define how the books are going to be organized
作为软件制作者,我们将根据目前对编程以及应用程序业务领域的了解,尽力而为地编写代码。
随着时间的流逝,我们不仅学到了编程技术,而且学到了业务领域的特殊性和特征,而且学到了越来越多的东西。
趋势在变化,新的编程技术不断涌现,其中一些在市场上越来越受关注。 随着更多功能添加到软件中,业务领域也不断发展和变化。
因此,我们编写的代码似乎正在慢慢衰减,因为我们在编写时没有掌握新知识。 每次查看较旧的代码时,我们都会更加确信它不再反映出应该解决的最佳模型。
> Code decaying over time
这是正常的。 它从项目开始就发生,并将一直持续到结束。 软件之所以软是因为它被更改了。 重构。 实验过已调整。 已更正。 递增。
但是更改此代码并非易事,因为在大多数情况下,系统很复杂。 变更的影响并不总是很明显。 我们害怕破坏某些东西而感到震惊。 这就是我们编写自动化测试的原因。 能够无所畏惧地更改软件。 为了能够重写,调整,试验,修复。
> Automated tests to measure the impact of change
不仅要知道软件是否可以运行。 如果我们永远都不会改变该系统,那么经过良好的手动测试将非常擅长于确保一个版本能够正常工作。 也许比自动测试更好,因为手动测试是强制性的端到端,并且还可以捕获UX和业务领域中无法预料的问题。
事实证明,编写自动化测试不足以使我们的软件易于更改。 如果代码与实现细节(如UI,数据库以及与其他系统的通信)过于耦合,则代码中的任何更改都将受到这些外部因素强加给我们代码的固有建模的约束。
对业务规则建模方式的任何更改都将在多个自动化测试和实施详细信息中进行更改。 要改善业务规则中变量的名称,就是要使其在数据库,屏幕或其他位置也进行更改。 较大的变化,结构性变化会放松我们的脊柱。
> When one change causes others
这就是创建架构的原因。 在对系统建模时,架构并不是要遵循的秘诀。 这不是术语。 这不是将业务规则组织到类或方法中的方法。 架构不是DDD [1]。
架构是将我们的代码与外部因素隔离开来的方法,因此我们可以自由地以我们目前认为最好的方式对问题的解决方案进行建模和重新建模。 然后重新进行建模。 然后再次。
当今最著名的架构之一是清洁建筑:
在本文中,鲍勃叔叔似乎确实提供了秘诀,术语以及将业务规则组织到类和方法中的方法。 但是,如果仔细阅读,就会发现所有架构的目标都是实现所谓的独立性,即所谓的自由。
自由学习和改造系统而不会破坏一切。 自由清理代码。
这就是为什么有用例(交互器)的原因。 它们代表用户可以在系统中执行的操作。 它们是UI和应用程序之间的通信桥梁。 这就是为什么有Presenters的原因,当涉及到一些额外的处理来呈现信息时,Presenter会从应用程序返回到UI。 它们是外壳的一部分,它们可以不同地命名,也可以具有其他形式,只要它们能够发挥其隔离作用即可。
从那里开始,不应强加严格的规则。 这才是重点。 不受规定的约束。 我们已经编写了所有测试,所有用例和演示者都存在,因此我们拥有更大的自由度来定义实体的状态以及它们的行为方式。
> Once the library's architecture is ready, we can organize the books as we please
因此,我们自己可以定义它们是否应该是函数,类,应该具有多少种方法。 如果它们将在网关(存储库)中实例化,则它们将在构造函数或方法中接收数据。 以及任何其他建模方式。
每个域都有其特殊性。 规则不适合,原则适合。 每个原理都将以给定的方式应用于每个领域。 一切都取决于。 但是要在这一点上前进,我们需要习惯于重新思考。 也许回去做几片kata或dojos。
忘记规则,忘记模式……解决问题的最简单方法是什么?
忘记屏幕,忘记数据库…解决教授提出的大学挑战的最简单算法是什么?
忘记用例,忘记体系结构…编写测试,查看失败,编写可能通过的最少代码,然后进行重构。
忘了上课,忘了界面…更具可读性的是什么? 对于刚开始在公司工作的新手来说,最容易理解的是什么?
忘记模式,忘记继承…我放置此代码的软件包是否一致? 使用此规则的任何人都容易找到它吗?
当然,我们将使用UI,数据库,用例和模式,类,接口和继承。 但是这些东西都是用来帮助我们为解决问题的最简单代码建模的工具。
域的每个部分都有不同的问题。 即使它们看起来都像相同的CRUD。 系统的一部分将需要一个在构造函数中具有数据的实体,另一部分将需要一个在网关内部生成的实体。 另一部分将需要其中包含许多规则的网关。 另一个将有一个仅由其他用例使用的用例,另一个将使它们全部内联。
但是问题更重要:此代码是目前最简单的代码吗? 就是这样,因为过一会我们会学到更多,并将此代码更改为更好的代码。
[1]《域驱动设计》一书探讨了一些概念,这些概念有助于将应用程序与外部因素隔离开来,但目标是以与业务领域一致的方式对业务规则进行建模-这确实非常重要,而另一个主题是 文章-并没有过多地关注独立性和自由性。
(本文翻译自Caio Andrade的文章《What Exactly Is Software Architecture?》,参考:https://medium.com/swlh/what-exactly-is-software-architecture-c1c67d1213f3)