将基础架构与应用程序分离
> Photo by Kevin Horvat on Unsplash
在过去的几年中,我遇到了一些我不想谈论的代码。 我总是想知道项目如何才能以这种状态结束,更重要的是,如何防止自己编写遗留代码。
开始一个新项目
开始一个新项目总是很令人兴奋。 使用许多新技术并编写比上次更好的代码的绝好机会。
这看起来像是微服务的完美项目!
别误会我,我喜欢微服务,但您不应该从它开始。 除非您已经在微服务环境中工作,否则这太过分了。
相反,请确保您的代码已准备好进行分离。 有很多方法可以做到这一点。 问题是,您需要走多远。 它仍然只是MVP,我们希望在数周而不是数月内发布项目。 但是,我们也不想为此做噩梦。
在我看来,有两种选择
· 快速而肮脏地建造东西。 当人们开始使用它时,我们会将其丢弃并正确构建。
· 分开应用程序的某些部分,以便我们在需要时可以替换它们。 节省执行时间,而不是分开。
建造和更换
这可能是一个非常好的方法,尤其是当我们快速想测试人们是否喜欢我们的产品时。
但是,当产品成功后,我们将不得不重写所有内容,说实话。 它在生产中运行后真的要从头开始构建吗? 可能不是。
当然,如果产品成功,则有一天它将被重写。 但这可能要花费数年的时间,而且如果不幸的话,您最终可能会处理具有超过一万行代码的文件。
我认为我已在10782行中找到了该错误。
这可能有点夸张,但您明白了。
如果您的目标是测试某个想法,请绝对考虑使用此选项,只需确保对其进行重构即可。
将基础架构与应用程序分离
这将花费更多时间,但是如果项目失败,我们可以将一些代码重用于另一个项目。 但是,如果执行不正确,我们可能最终仍会重构整个项目。
那么,我们如何分隔项目以保持其可维护性呢?
让我们从创建基础架构和应用程序层开始。
基础结构层将包含管理任何网络请求的所有类。 从接收API调用到与数据存储进行通信。 这是项目开始时最重要的部分。
假设我们为MVP选择了一个SQLite数据库。 只要确保实现隐藏在接口后面,我们就可以在必要时轻松替换数据存储。
处理传入请求有点不同。 但是目标是相同的。 我们可以使用命令对象将处理请求的方式与处理请求的方式分开。 让我们看看以下示例。
我们有一个控制器,它接收创建新主题的请求。 控制器会将数据从HTTP请求转换为命令对象。 该对象将包含我们要执行的突变所需的所有数据。 我们可以将此对象传递给位于应用程序层中的服务。 服务本身对HTTP请求一无所知。 因此,我们可以轻松地由消费者替换我们的控制器,甚至可以同时支持两个控制器:
然后,我们的主题服务将决定是否应创建主题。 主题独特吗? 标题符合要求吗? 这些业务规则应放在应用程序层内。 如果所有断言都通过,则服务将在存储库上执行create方法。 请务必仅通过接口引用存储库,这一点很重要。
假设我们现在想用MySQL数据库替换SQLite数据库。 为此,我们只需要创建一个新的存储库,实现现有接口并将其注入主题服务中即可。
通过将基础架构与业务逻辑分开,我们可以更轻松地替换应用程序的某些部分。 当然,仅创建两个文件夹和一些类不足以阻止现有的旧应用程序。 我们仍然需要不时更新我们的服务。
分离不同的上下文
确保将应用程序的不同部分分成各自的上下文。 我们不希望有一个包含数百个控制器的Controller文件夹。 每个上下文都应具有自己的基础结构和应用程序层。 某些类(例如记录器)可以在上下文之间共享。 这些共享的类可以放在Common文件夹中。
src/ Topic/ Application/ Infrastructure/ Account/ Application/ Infrastructure/ Common/
另外,请尝试避免直接引用其他上下文。 您可以使用事件在它们之间进行通信。 如果必须引用另一个上下文,请确保仅在基础结构层中引用它。 当您的应用程序变得很大时,这种分离使迁移到微服务体系结构变得容易得多。
最后的想法
新项目的截止日期通常很紧。 通过将项目分为两层,我们将能够在确保质量和可扩展性的同时快速交付。
关于这个话题还有很多要说的。 如果您喜欢将应用程序划分为不同的层,则可能还需要:
· 六角形建筑
· 分层架构
· 域驱动设计
感谢您阅读本文。 如果喜欢,请考虑关注我,下次再见!
(本文翻译自Stein Janssen的文章《Building Maintainable Software》,参考:
https://levelup.gitconnected.com/building-maintainable-software-50c6bd09c611)
来源:闻数起舞
声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!