浏览有关软件设计的文章时,我经常遇到由空前的缩写和偶然提及的开发实践组成的云。
- TDD-好吧,每个人都知道,首先我们编写测试,然后再编写其余代码。
- BDD是一种熟悉的东西,有点像测试,但是很特殊。
- TDD-再来一次? 因此,停止,这里根本不涉及测试。 但是为什么叫它一样?
- DDD-绑定上下文,无处不在的语言,域...
- Fdd
- MDD-认真地,基于图表?
- PDD -...
开发方法按复杂性,应用领域和目标划分。
我认为是时候弄清楚为什么需要它们了,为什么它们太多了,以及它们如何对我们有用。
我们将从最简单到最复杂的方面开始熟悉它们,并考虑使用示例以及它们各自的优缺点。
TDD-测试驱动开发
TDD是一种基于重复较短开发周期的软件开发方法:首先编写涵盖所需更改的测试,然后编写实现所需系统行为并允许您通过书面测试的程序代码。 然后,通过对测试的不断测试来重构编写的代码。
听起来很简单清晰。 许多人都熟悉这种开发方法,甚至Bob叔叔本身也在积极地推广它。
TDD被认为是正确构建应用程序的一种形式。 测试驱动的开发理念是,测试是对程序行为的规范。 如果您认为测试套件是构建过程中必不可少的一部分,则如果测试失败,则该程序不会构建,因为它不正确。 当然,局限性在于程序的正确性仅定义为测试的完整性。 但是,研究表明,基于测试的开发可以将生产中的错误减少40-80%。
当您开始使用TDD时,您可能会觉得运行速度比平常慢。 这是因为您将在“舒适区”之外工作,这很正常。
一旦感觉编写测试已成为工作流程中一个简单而自然的部分,而不再需要在处理项目时考虑使用TDD,便会意识到TDD已渗透到您的工作中。
这种方法使我们能够创建适合于自动测试的应用程序,并通过测试很好地覆盖了代码,因为TK被转换为自动测试的语言,也就是说,程序应做的所有事情都经过检查。 TDD通常还简化了软件实现:消除了实现冗余-如果组件通过了测试,则认为它已经准备就绪。
用这种方法开发的软件产品的体系结构通常更好(在适用于自动测试的应用程序中,组件之间的职责通常分布得很好,并且执行的复杂过程被分解为许多简单的过程)。 通过测试开发的应用程序的稳定性更高,原因是测试涵盖了程序的所有基本功能,并且不断检查其性能。 伴随所有项目或几乎所有项目都经过测试的项目非常多-开发人员可能不怕更改代码,如果出现问题,自动测试的结果将为您提供通知。
通过阅读Kent Beck的《极限编程:通过测试进行开发》,您可以了解有关TDD原理的更多信息。
TDD-类型驱动开发
类型驱动开发是缩写,也包括通过测试进行的开发,因此通常会写全名。
在基于类型进行开发时,您的数据类型和类型签名是程序的规范。 类型还可以作为保证可以更新的文档形式。
类型是小的控制点,因此,我们在整个应用程序中都进行了许多小型测试。 而且,创建类型的成本是最小的,并且不需要更新它们,因为它们是代码库的一部分。
按类型进行开发是构建应用程序的另一种好方法。 与基于测试的开发一样,基于类型的开发可以增加您对代码的信心,并在更改大型代码库时节省时间。
在缺点中,只有随着动态类型化而增加的语言复杂性。 例如,对于JavaScript,此方法比TypeScript难于应用。
在habr上有一篇关于打字的出色文章 。
BDD-行为驱动开发
由于某些方法上的相似性,TDD(测试驱动开发)和BDD(行为驱动开发)经常被专业人员混淆。 有什么区别? 两种方法的概念相似,首先进行测试,然后才开始开发,但是它们的目的完全不同。 当测试由开发人员自己创建时,TDD更多地涉及产品技术实施级别上的编程和测试。 BDD涉及测试人员或分析人员以自然语言 (如果我可以这么说的话)以业务语言描述用户定义的脚本 。
BDD-行为驱动的开发是基于行为的开发。 某个人(或多个人)以“当我按下开始按钮时我想要的用户然后菜单显示为图片的形式”形式书写说明(有特别突出显示的关键字)。 程序员长期编写特殊的工具,将这些描述转换为测试(有时对程序员完全透明)。 然后用测试进行经典开发。
如果您以句子的形式记录测试的名称,并使用业务领域的词汇表来编写方法的名称,则客户,分析师和测试人员都可以清楚地看到所创建的文档。
脚本文本以特定形式编写。
具有(大约给定-给定)一些上下文,
当(注意何时)事件发生时,
然后(大约)然后检查结果。
这样的事情可能会发生:
或另一个俄语示例:
情况1:帐户中有钱+
有钱帐户
和有效的卡
还有一个有现金的 ATM
当客户要求现金时
然后确保该帐户已借记
并确保已发行现金
并确保退回卡
BDD方法与工程实践一起,使我们能够放弃包含不相关信息的旧文档,并即时接收新文档,并将其与项目一起存储,这使分析人员和测试人员更接近代码。
BDD是一个过程,其目标是降低实现新功能的成本。 即使在开发开始时,我们也会得到重要的工件。 例如,可以理解的文档支持。 本文档为所有相关方提供了一个机会,使他们对应该在开发迭代期间实施的产品和用户行为方案形成理解。 使用BDD方法,我们还降低了新成员进入项目的门槛。
BDD的优势是什么?
- 非程序员可读的测试。
- 它们很容易更改。 它们通常是用几乎纯英语写的。
- 它们可以由产品所有者或其他有关方面来编写。
- 测试结果更加人性化。
- 测试与目标编程语言无关。 迁移到另一种语言大大简化了。
缺点:
但是这种方法有其缺点-它既长又昂贵。 即使在开发需求阶段已经需要测试专家的参与,BDD还是很不方便,这延长了开发周期。
解决这种情况的方法可能是选择合适的BDD框架和正确构建的开发流程。
在此处阅读有关BDD的更多信息。
长期以来,许多人都知道测试是所有疾病的灵丹妙药,但事实确实如此吗? 当然,经过全面测试的代码可以更稳定,更可预测地工作,但是测试并不能使我们在设计和任务设置阶段免于出现问题和错误。 以下开发方法可以帮助您。
DDD-域驱动设计
面向主题的设计不是特定的技术或方法。 DDD是一组规则,可让您做出正确的设计决策。 这种方法可以显着加速不熟悉领域中的软件设计过程。
面向主题的设计 (较少涉及问题的英语,域驱动设计,DDD)是一组旨在创建最佳对象系统的原理和方案。 开发过程归结为创建软件抽象,即域模型。 这些模型包括业务逻辑,该业务逻辑在产品的应用区域的实际条件和代码之间建立关系。
在开发人员不是所开发产品领域的专家的情况下,DDD方法特别有用。 例如:程序员无法了解创建软件所需的所有领域,但是通过以主题为导向的方法,借助结构的正确表示,他可以轻松地基于要点和工作区知识来设计应用程序。
在本文中,我试图传达每种软件开发方法的精髓,但是关于DDD,您可以撰写不止一篇文章,并涵盖多个段落中的所有细微差别,但对我而言,这是行不通的。 因此,在解释时,我将提供指向最有价值资源的解释性链接。
域驱动设计的主要目标是消除业务流程的复杂性,其自动化和代码实现。 “域”翻译为“域”,并且在此方法框架内的开发和设计被推离域。
DDD中的关键概念是无处不在的语言。 无处不在的语言促进了项目参与者之间的透明通信。 在所有场合他都是一体的意义上,他不是一个。 相反。 所有参与者都在其中进行交流,所有讨论均以一种语言进行,所有工件应以一种语言进行呈现,即从传统知识开始,以代码结尾。
下一个概念是“域模型”。 该模型是来自无处不在的语言的术语表。 域模型和无处不在的语言都受域驱动设计称为有界上下文的上下文的限制。 他以这样一种方式来限制领域模型,即其中的所有概念都是明确的,并且每个人都知道危险所在。
示例:将实体“人”置于“公开演讲”的上下文中。 在这种情况下,根据DDD,他成为发言人。 而在“家庭”的背景下-丈夫或兄弟。
现在介绍代码。 重要的是,您的代码像一本书一样阅读,对于讲通用项目语言的任何人来说,它都必须简单易懂。 我什么意思
如果在项目语言中使用表达式“已添加产品”,则以下选项不是DDD:
var product =新产品(“苹果”)
product.save()
怎么了 代码说我们以一种奇怪的方式创建了产品并保存了它。 如何全部添加产品? 需要添加它 。 这是DDD代码:
产品::添加('apple');
架构:
从域驱动设计的角度来看,选择哪种架构并不重要。 领域驱动的设计与之无关;领域驱动的设计与语言和交流有关。
但是,如果没有干净的项目体系结构,DDD几乎是不可能的,因为在添加新功能或更改旧功能时,您需要尝试保持代码库的灵活性和透明性。 您可以在一篇很棒的文章中阅读有关端口,适配器和洋葱体系结构的信息 。 上面的图片仅来自此。
我强烈建议您在此处和此处仔细阅读有关DDD的文章。
这到底给了我们什么?
- 几乎所有团队成员都可以阅读项目代码;
- 任务说明变得更加明确;
- 商业逻辑中的错误变得更容易查找;
- 对于质量检查专家而言,扫描代码并查找逻辑错误和错误要容易得多。
缺点:
- 需要高素质的开发人员,尤其是在项目开始时;
- 并非所有客户都愿意为此付出成本,因此在开发过程中所有参与者都必须研究DDD。
FDD-功能驱动开发
FDD-这种方法(简称为FDD)是由Jeff De Luca开发的,并且是面向对象技术领域的公认专家Peter Coad。 FDD是一种尝试,它结合了软件开发行业中最受认可的技术,这些技术以已开发软件对客户的重要功能(属性)为基础。 这种方法的主要目标是按时系统地开发真实的,可运行的软件。
与其他自适应方法一样,它着重于短迭代,每一次迭代都可以确定系统功能的特定部分。 根据FDD,一次迭代持续两周。 FDD有五个过程。 其中的前三个与项目开始有关:
- 开发通用模型;
- 编制所需系统属性的列表;
- 规划每个物业的工作;
- 每个物业的设计;
- 每个物业的建设。
在每次迭代过程中必须完成最后两个步骤。 此外,每个过程都分为任务并具有验证标准。
让我们详细介绍每个项目。
开发通用模型。
开发首先要分析现有任务范围的广度和系统的上下文。 另外,对于每个模拟区域,进行更详细的分析。 初步描述以小组形式汇编,并提交进一步讨论和专家评估。 提出的模型之一或它们的组合成为特定区域的模型之后。 每个任务区域的模型都组合成一个公共的最终模型,该模型可以在工作期间进行更改。
清单功能
在通用模型构建期间收集的信息用于编译功能列表。 功能被组合成所谓的“域”(英语域),然后根据功能属性将其划分为子区域(英语主题区域)。
每个子域对应一个特定的业务流程,并且其步骤成为功能(属性)列表。 这些功能以“操作-结果-对象”的形式表示,例如“检查用户密码”。 每个功能的开发不应超过2周,否则必须将任务分解为较小的迭代。 FDD中的属性列表与SCRUM中的产品待办事项列表相同。
属性(功能)计划
下一阶段是在领先的程序员或团队之间分配功能。
功能设计
为每个属性创建一个设计包。 首席程序员概述了两周内要开发的一小部分属性。 然后,留下每个属性的详细序列图,指定通用模型。 接下来是类和方法的“存根”。 在这一点上,我们必须专注于软件产品的设计。
功能实现
我们编写代码,删除存根,测试。
在对该属性进行测试并将其用于产品中之后,我们采用下一个优先级属性,重复设计/实施周期。
总计,结果是:
- 系统属性文档;
- 精心设计;
- 更容易评估小任务;
- 测试专注于业务任务;
- 复杂的产品创建过程;
- 较短的迭代开发周期使您可以快速增加功能并减少错误。
缺点:
- FDD更适合大型项目。 小型开发团队将无法体验这种方法的所有好处;
- 大量的实施和培训费用。
MDD-模型驱动开发
最近,在出版物中已经非常关注基于MDA(模型驱动的体系结构)和MDD(模型驱动的开发)模型的体系结构和开发主题。 在不赘述的情况下,我们仅突出重点。
模型驱动的开发是一种软件开发样式,其中模型成为主要的开发工件,并从中生成代码和其他工件。
简而言之,开发的全部重点是构建必要的图,我们随后将根据这些图生成项目的工作代码。
MDD的主要目标是最小化与链接到特定系统平台和软件基础结构相关的成本。 毕竟,主要的业务逻辑包含在图表中,并不将我们与选择编程语言和开发工具的范围联系在一起。
让我们离题并考虑一下编译器。 它将高级编程语言转换为机器语言的等效实现。 在这种情况下,该模型是用高级语言编写的程序,该程序隐藏了有关其实现的不相关细节。 在MDD中,我们的图是另一个抽象层次,它不允许我们陷入开发细节中,而只能从整体上看。
«», . ( ).
MDD ‑ . , , . MDD-, . Unified Modeling Language – UML 2.0.
Object Management Group (OMG) :
MDD, , — . .
:
- (Minimum Viable Product) ;
- : , , ;
- ;
- .
:
- MMD , Rational Software Architect, Simulink Sirius;
- ;
- .
PDD — Panic Driven Development
agile , PDD. , .
.
, , . . , ? , .
, , .
. . UX . ? , . , .
.
, , , . , . . , .
.
— . . . . . .
.
, , , — , . . , , , .
, .
, . . , , .
:
:
PDD , , , .
结论
agile . , , .
- Driven Development , DDD, BDD, MDD , .