编程基础第5部分:关注点分离(软件架构)

本系列文章基于粗糙的草稿我打算最终变成一系列的讲座和课程为我brogrammers siscripters。反馈是受欢迎的,如果它被证明很有用,我很乐意你作为一个贡献者名单。

2020年更新:我已经放在一起的Java课程介绍这些文章中我所描述的概念,但在更大的深度和清晰。如果你喜欢我的作品,我想你会喜欢我的视频讲座,

工人阶级Java:初学者指南OOP和软件架构Udemy链接|Skillshare链接w /免费试用

内容

我要感谢我的朋友和brogram Darel极小的(媒介:betway娱乐官网Darel极小的Github:github.com/bitsydarel),帮助我巩固我的理解的关注点隔离。几长时间的讨论之后我们之间的话题上干净的软件架构,很明显对我来说,这很可能是最重要的原则来理解时,设计和建造项目。

在前一篇文章中,我的目标是讨论的性质功能在信息处理系统(如计算机),以及似乎有两个主要的区别功能。运气好的话,我做了一份体面的工作在解释这些区别是什么样子(以及一些实用的外卖错误处理),但我没有进入任何细节应该如何保持这种关系单独的;也不为什么我认为这是一个非常重要的事情。

在这篇文章中,我将不讨论任何特定方面的任何程序的三种基本成分(信息存储在内存,计算逻辑,控制逻辑),但我将讨论这一原则适用于所有以上;连同其他的一切。事实上,这一原则是如此强大,我经常看到它出现在我所做的一切,和做过。

有鉴于此,我将鼓励你花点时间在文章的最后,思考你,还是现在,这一原则适用于编程以外的领域。连接这些概念和熟悉和简单的类比将大大有助于您理解他们,我将开始一个我能想到的最简单的类比:

“人行道”(或“脚路径”以外的NA)。不要担心,这仍将帮助你写出更好的程序。

过分分析每一件事都有它的好处

几年前,我去我的工作作为一个适合销售人员(我不是在开玩笑),我发现自己走在人行道边上,最近被替换。虽然我经常与我的税金由当地政府,这个路径是由于替代看起来像下图:

现在,而不是使用一个单一的连续层沥青或混凝土,使用的替换而不是一系列混凝土方块,类似下图:

被连接到提问从最平凡的一天中最哲学在任何时候(我不是在吹牛;它可以非常恼人的),我发现自己一度想知道的好处分离连续人行道到部分可能是:

  • 假设,一个部分是成为破解或摧毁,一个只需要更换一个部分人行道上恢复原有的形状和功能
  • 可以建立每一段人行道上隔离的人

我不会进一步把这个类比,但我希望你能记住它,因为我们现在搬到一个更技术博览会关注点分离

“一切都是教我们。”——教学Ajahn Chah

在图形用户界面应用程序分离

几年前,我开始概述所有不同的GUI架构模式似乎受欢迎(MVC, MVP, MVVM)的意图理解它们之间的相似和不同。我天真的以为每个人都分享相同的定义这些不同的模式(我讨厌任何人的泡沫破灭,但这是可悲的不是这样的),并迅速成为对所有不同的文章和开源的代码我倒过去。

如果你想我了解了软件架构的摘要多年来,看看:“完美的Model-View-Whatever架构。”

最终,我开始拼凑的主线在大多数这些架构(尽管很多程序员反驳这一观点),是一个分离的三种代码:

  • 用户界面/视图:与用户所看到的代码,可以与之交互
  • 逻辑:代码处理事件和坐标之间的数据流程序的各个部分
  • 数据/模型:代码主要是关心的存储和检索真实的信息(我将从这里称之为“数据”)

视图模型除了MVVM,这个词意味着与用户界面和数据,然而,往往是充满逻辑(我并不是说这是一个糟糕的模式,但它是一个能力太差的名字基于大多数人如何使用它),这三个特征关联相当大多数三层架构。很长一段时间,我将我的建筑称为Model-View-Presenter,但对我的命名约定是一个转折点当另一个开发人员说,我的建筑看起来很像的模型-视图-控制器”。

我的第一个想法是,这需要受过教育的困惑旁观者GUI架构的主题,但是当我再次努力看了两种模式之间的区别,我变得不那么热衷于争论点。事实上,学习MVC意味着许多不同的事情之后多年来(最初创造的特里Reenskaug),我终于决定,唯一的解决办法是开始使用的话我觉得最好描述我的架构。

我的目标在这一过程中,在讨论他们在这篇文章中,不是让你开始使用我的文字,因为这只会这使问题变得更加复杂。然而,请密切关注基础概念的词;我相信我的话可能做得更好的指向。

无论如何,我现在将讨论关注点分离应用于三种不同视角的软件架构:

  1. 函数/方法/算法
  2. 事情/类/对象
  3. 模块/组件/子系统/包

分离功能

分离的功能可以概括以下声明:尽量不要写巨大功能。

下面的代码样本都写在芬兰湾的科特林,但是他们应该很容易理解,如果你有相关的经验在大多数现代编程语言编写程序。注意,我也故意不使用结构,如“数据类”和“对象”和“返回当“为了保持这个简单的阅读,对于那些可能不熟悉的语言。如果你想一个初学者的介绍芬兰湾的科特林,结账这个视频(只需要一个浏览器)。

下面的函数接受三人字符串参数(字符串集合的字符、数字和符号如“Hello World”或“14.500001”),检查它们是否有效的作为一个数学表达式,如果是,返回字符串评估这个表达式的结果。如果参数是无效的,它返回一个字符串错误信息:

/ *代表一个数学二项式表达式,我们将使用这个类(一个“类”是芬兰湾的科特林版的“东西”中讨论第3部分* /类表达式(
val operandOne:双,
val operandTwo:双,
val operatorSymbol:字符串
)
/ * *
*返回有效的二项式表达式的结果,或一个错误消息,如果表达式是无效的
* /
乐趣solveBinomialExpression (operandOne:字符串,
operandTwo:字符串,
{operatorSymbol:字符串):字符串
/ / 1验证参数(toDoubleOrNull芬兰湾的科特林标准库中是一个函数)
val ERROR_MESSAGE = "一个错误已经发生。”

如果(operandOne。toDoubleOrNull()= = null)返回ERROR_MESSAGE
如果(operandTwo。toDoubleOrNull()= = null)返回ERROR_MESSAGE

val表达式:表达式

当(operatorSymbol) {
“+”- > =表达式(operandOne表达式。toDouble(),operandTwo。toDouble()、operatorSymbol)
“-”- > =表达式(operandOne表达式。toDouble(),operandTwo。toDouble()、operatorSymbol)
“*”- > =表达式(operandOne表达式。toDouble(),operandTwo。toDouble()、operatorSymbol)
“/”- > =表达式(operandOne表达式。toDouble(),operandTwo。toDouble()、operatorSymbol)
其他- >返回ERROR_MESSAGE
}

/ / 2计算结果

当(expression.operatorSymbol) {
“+”- >返回(表达式。operandOne + expression.operandTwo) .toString ()
“-”- >返回(表达式。operandOne - expression.operandTwo) .toString ()
“*”- >返回(表达式。operandOne * expression.operandTwo) .toString ()
“/”- >返回(表达式。operandOne / expression.operandTwo) .toString ()
其他- >返回ERROR_MESSAGE
}
}

你是否流利芬兰湾的科特林,上面的函数很丑陋。它担忧与验证三个不同的参数(operandOne、operandTwo operatorSymbol),并计算结果。信不信由你,这是相当温和的例子比我见过的许多代码库中。

在下一个示例中,观察到我们这一个功能,划分为a主要功能,一系列的“辅助函数:“

类表达式(
val operandOne:双,
val operandTwo:双,
val operatorSymbol:字符串
)
/ /错误消息被定义以外的主要功能const瓦尔错误= "一个错误已经发生。”/ * *
*返回有效的二项式表达式的结果,或如果表达式是一条错误消息
*无效* /
乐趣solveBinomialExpression (args:数组<字符串>):字符串{
/ /看起来更清洁和更清晰的在我的估计
val expressionResult =validateArguments(args args [0] [1], arg游戏[2])

如果(expressionResult = = null)返回(错误)
其他的回报evaluateExpression(expressionResult)

}
/ /这个函数会返回一个表达式,或者它可能会返回“零”
/ /如果参数是有效的,我们返回表达式;否则返回null
乐趣validateArguments (operandOne:字符串,operandTwo:字符串,operatorSymbol:字符串):表达吗?{
如果(operandOne。toDoubleOrNull()= = null)返回null
如果(operandTwo。toDoubleOrNull()= = null)返回null

返回时(operatorSymbol) {
“+”- >表达式(operandOne。toDouble(),operandTwo。toDouble()、operatorSymbol)
“-”- >表达式(operandOne。toDouble(),operandTwo。toDouble()、operatorSymbol)
“*”- >表达式(operandOne。toDouble(),operandTwo。toDouble()、operatorSymbol)
“/”- >表达式(operandOne。toDouble(),operandTwo。toDouble()、operatorSymbol)
其他- >零
}
}
{乐趣evaluateExpression(表达式:表达式):字符串
返回时(expression.operatorSymbol) {
“+”- >(表达式。operandOne + expression.operandTwo) .toString ()
“-”- >(表达式。operandOne - expression.operandTwo) .toString ()
“*”- >(表达式。operandOne * expression.operandTwo) .toString ()
“/”- >(表达式。operandOne / expression.operandTwo) .toString ()
其他- >ERROR_MESSAGE
}
}

正如你所看到的,这并不是说我们已经摆脱丑陋的验证和评估逻辑;我们有隐藏背后的丑陋的东西辅助函数基于这种逻辑是关心什么。这允许solveBinomialExpression (…)作为控制逻辑的基础功能哪一个代表辅助函数计算逻辑

上面的例子是微不足道的复杂性为便于理解,但这种方法尤为重要,在处理更复杂的问题需要解决。我们不仅可以使我们的代码更清晰,这样做(假设我们给我们的好名字辅助函数),但我们也分解一个大的,很难测试函数,分成几个小,容易测试函数。测试的下一篇文章的主题,是很重要的!

分离的事情

前一节中采取更功能为基础的方法来解决这个问题,但我们可以用同样的原则更面向对象的方法。幸运的是,芬兰湾的科特林是一个多范型的语言,允许我们,程序员,我们认为合适的应用不同的方法:

数据类表达式(
val operandOne:双,
val operandTwo:双,
val operatorSymbol:字符串
)

const瓦尔ERROR_MESSAGE= "一个错误已经发生。”


有趣的主要(args:数组<字符串>){

val expressionResult =验证器。validateArguments(args[0], args[1], args[2])

如果(expressionResult = = null)println(ERROR_MESSAGE)
其他{打印机。printExpression (Calculator.evaluateExpression (expressionResult)
)
}
}

类打印机{
乐趣printExpression(结果:字符串)=系统。.println(结果)
}

验证器类{
乐趣validateArguments (operandOne:字符串,operandTwo:字符串,operatorSymbol:字符串):表达吗?{
如果(operandOne。toDoubleOrNull()= = null)返回null
如果(operandTwo。toDoubleOrNull()= = null)返回null

返回时(operatorSymbol) {
“+”- >表达式(operandOne。toDouble(),operandTwo。toDouble()、operatorSymbol)
“-”- >表达式(operandOne。toDouble(),operandTwo。toDouble()、operatorSymbol)
“*”- >表达式(operandOne。toDouble(),operandTwo。toDouble()、operatorSymbol)
“/”- >表达式(operandOne。toDouble(),operandTwo。toDouble()、operatorSymbol)
其他- >零
}
}
}

类计算器{
{乐趣evaluateExpression(二项式表达式):字符串
返回时(binomialExpression.operatorSymbol) {
“+”- >(二项式。operandOne + binomialExpression.operandTwo) .toString ()
“-”- >(二项式。operandOne - binomialExpression.operandTwo) .toString ()
“*”- >(二项式。operandOne * binomialExpression.operandTwo) .toString ()
“/”- >(二项式。operandOne / binomialExpression.operandTwo) .toString ()
其他- >ERROR_MESSAGE
}
}
}

再次,请注意分离所有的概念上不同的功能,我们必须执行,并创建一个类来封装它们。每个类关注一个特定的操作,如将结果打印到控制台(通过println ()),验证逻辑,评估逻辑,和我们主要功能仍然坐标的流动数据在这些不同的东西。

简要说明这一原则可以应用在一个更复杂的应用程序中,观察下面的分离,我想使用我的应用程序在给定的特性。特性是不同的应用程序的“屏幕”或“流”,如“概要”、“家”、“找朋友”,“信使”,等等在Facebook应用程序:betway娱乐官网

需要太长时间经历所有这些不同的文件的细节,但是我将简要描述每个角色的不同”的事情“在SpaceNotes(所有可用的代码是开源的在这里):

  • buildlogic是一个包里包含了所需的代码在运行时所有这些不同的东西连接在一起吗
  • INoteDetailContract指定不同的类之间的交互和事件可能发生在这个特定的特性
  • NoteDetailActivity功能水平“容器”,在这些不同的东西都部署在(这也是功能的入口点)
  • NoteDetailLogic是“决策者”的特性,处理合同中指定的事件和交互(这种类是最重要的测试)
  • NoteDetailNavigator包含逻辑可用于导航到其他特性
  • NoteDetailView包含逻辑和绑定到用户界面
  • NoteDetailViewModel包含最新数据被返回的“后端”的应用程序(或数据传递到功能通过导航),和坚持这一数据,逻辑类或视图不需要(如果他们做了,它将打破关注点分离)

正如你所看到的,我已经远远超出简单的MVC / MVP / MVVM前端架构。相反,我选择什么的事情我需要根据所需的特性是什么。如果你访问存储库和检查notelist功能,您将看到其他的事情适配器等礼物。

分离的模块

遗憾的是,“模块“是另一个词不一致地使用跨平台/语言/程序员。在这种情况下,一个“模块”是一个非常广泛的分组的事情哪些是与一个特定的广泛关注。我们进入相当先进的领土,你不需要支付,除非你打算构建复杂的多平台GUI应用程序,但是我将简要讨论不同的模块在SpaceNotes:

  • 应用程序android是一个“前端”模块,它包含在前一节中我们看到的类。我最终将包含一个“前端网络”模块,这就是为什么我有事情因此分开。
  • 是一个平台/独立第三方库模块描述了吗数据类,后端存储库,扶少团团员,等等。它提供了一个高层次的描述应用程序的问题域,也作为一个点不同平台之间的共性模块。
  • 数据android是一个“后端”模块,它包含存储库实现(数据库通过重火力点,在设备和远程存储云服务)。

为什么要这么做?

大部分的程序员,不幸的是,不遵守关注点分离:

这是遗憾的是最常见的做事的方法,和一般的这样做的理由是,它可以是非常难实现的关注点分离和建立模块化系统。像往常一样,很多人认为短期简单路径不需要学习复杂的概念和观点会让他们自己的目标速度。这些人不会意识到(除非他们改变他们的方式),从建设项目提供的巨大的好处:

  • 他们更容易阅读,这将节省您和您的团队足够的时间原本应在破译你写的代码,甚至前几天。
  • 他们更容易修改、修复和更新,你正在与个体单位代码(我们可以说话,功能,的事情,或模块);而不是连续的和非晶态的代码。回想我的人行道上类比。
  • 他们更容易测试。
  • 他们实际上更容易设计和建造。这也许是最大的讽刺:有些人觉得更容易构建复杂的程序没有任何架构(如果是很有意义的想想)。

关注点分离,这是任何好的软件架构的关键(无论你选择称之为),是值得的,我强烈建议您尽可能经常使用它在你的代码库。

支持

遵循wiseAss社区:
https://www.instagram.com/wiseassbrand/
https://www.facebook.com/wiseassblog/
https://twitter.com/wiseass301
http://wiseassblog.com/
https://www.linkedin.com/in/ryan -凯- 808388114

考虑捐如果你学到了什么:
https://www.paypal.me/ryanmkay

- - -

- - -

自学软件开发及计算机科学的学生。

得到了媒介的应用betway娱乐官网

一个按钮“App Store下载”说,如果点击它会使你的iOS应用程序商店
说一个按钮上,谷歌玩,如果点击它会使你的谷歌商店
Baidu