前端的干净架构



现代网络非常复杂。框架的数量及其开发速度使开发人员大吃一惊。有人使用新书,有人阅读时尚书籍。但是有时阅读和精力会花在建筑,OOP,TDD,DDD等方面的深度学习中。不辜负期望。有时这些书令人困惑!甚至,最糟糕的是,他们难以置信地提高了FAC!

我将冒险以一种简单的方式提出与前端相关的纯建筑主要思想。我希望这对想要阅读本书的人以及已经阅读但不使用在现实生活中获得的知识的人有用。对于那些对我如何将前端拖到此处感兴趣的人。

动机


在撰写有关一位高级开发人员建议的文章之前,我第一次阅读FAQ大约是一年半。在此之前,Pure Code适用于JavaScript的简短摘录给我留下了深刻的印象(https://github.com/ryanmcdermott/clean-code-javascript)。我将这个标签打开了六个月,以应用最佳实践。而且,我第一次尝试阅读原始的Clean Code失败。也许是因为它太坚持前端项目的功能,或者因为应该通过长期实践来加强阅读。尽管如此,Cheka是实用的指南,您可以获取并立即应用于书面功能(如果您不熟悉,我强烈建议您先阅读它)。

但是使用TA时,它变得越来越复杂-这里有一些原则,法律和技巧,可从整体上构建该程序。没有可以立即使用的详细信息,并且该组件中没有zayuzat。本书旨在改变您编写软件的方式,并为您提供心理工具和指标。认为ChA仅对架构师有用是一个错误,我将尝试使用适合前端的示例来传达这一观点。

业务逻辑和前端




关于ChA,许多人会在他们的想象力中画圈(参见标题下的图),规模巨大的项目,难以置信的复杂业务逻辑以及很多问题-把YuzKeysy放在什么样的爸爸身上?从ChA到原理的适用性到创建手风琴组件的想法令人困惑。但是开发现代界面时出现的问题需要认真对待。现代的界面很复杂,通常很痛苦。首先,让我们找出前端最重要的部分。

众所周知,您需要将业务逻辑与演示文稿分开,并遵守SOLID原则。CHA中的Bob叔叔将详细介绍这一点。但是什么是业务逻辑?R. Martin提供了几个定义和子类别;其中一个听起来大约 所以:
业务逻辑(业务规则)是即使没有自动化也能为组织带来收益的规则。
通常,业务逻辑非常重要。(当听到后方从前台听到业务逻辑时,我会听到咯咯笑声)。但是,我建议领先者放松一下,并记住在我们前面最重要的是什么?而且,无论听起来多么奇怪,最重要的事情就是用户界面。对我来说,了解AA的第一步是要认识到接口逻辑应该在第一圈的中心!(图在标题下)。

我知道这是没有根据的声明,可以对此进行强有力的论证。但是,请记住,经常发生的痛苦变化是痛苦的?我不了解您,但是经常有人要求我更改交互式元素(手风琴,模具,按钮)的行为。值得注意的是,布局(设计)的更改频率要比界面行为的更改频率低得多。注释中特别讨论了变更和参与者(变更的发起者)。

讨厌的霉菌


让我们不必为术语烦恼。我们举一个例子,并澄清一下我所说的接口逻辑。

有几个带有验证和条件映射的输入。您只能填写一个字段,并且该表格有效,但是将显示可选输入。(请注意,我们不在乎哪种数据。主要是交互性)





我希望逻辑清楚。首先,实施过程不会引发任何问题。您将此内容推入框架的一个组件中,并以其他形式大胆地重用它,将其作为一个组成部分和一个独立的部分。您必须在某些地方传递标志,以便稍微更改验证,在某些地方进行一些布局,在某些地方进行连接到父窗体的功能。通常,在薄冰上编码。一次,您将获得这种形式的任务(并使用它)并冻结几天,尽管似乎只有15分钟。该死的经理,模子和无聊的枯燥任务。

错误在哪里?似乎您已经工作了一天多,仔细地考虑了组件的组成,尝试了不同的曲棍球,通过道具传输了模板,与构建表单的框架融合在一起,甚至在编写这些组件时也尝试遵循SOLID。

注意:ChA!中的分量==反应/角和co中的分量。

但是事实是您忘记了突出逻辑。冷静一点,回到任务并进行模拟。

太简单的任务


NA强调架构对于大型项目至关重要。但这并没有否定ChA方法对小型任务的有用性。在我们看来,任务太简单了,无法谈论某种形式的体系结构。以及如何指定一种方法来进行更改(如果不是通过体系结构)?如果您没有定义交互界面的边界和组件,那么将更加容易混淆。记住以什么想法承担着在工作中更改表格的任务。

但是,让我们开始做生意。这是什么形式?我们正在尝试建模,用伪代码表达思想。

ContactFormGroup
  +getValue()
  +isValid()

我认为,我们对外部世界的全部任务是使用两种方法创建对象。听起来很简单-就是这样。我们继续描述我们所看到的以及我们感兴趣的事物。

ContactFormGroup
  emailFormGroup
  phoneFormGroup
  getValue()
    => [emailFormGroup.getValue(), phoneFormGroup.getValue()]
  isValid()
    => emailFormGroup.isValid() || phoneFormGroup.isValid()

可能值得明确指出次要输入的外观。当经理要求您快速对表单进行第10次编辑时,一切在他脑海中看起来都很简单-就像此伪代码一样。

EmailFormGroup
  getValue()
  isValid()
  isSecondaryEmailVisible()
    => isValid() && !!getValue()

我们可以发现一个奇怪的需求的地方吗...

PhoneFormGroup
  getValue()
  isValid()
  isSecondaryPhoneVisible()
    => isValid() && today !== ‘sunday’

我们在Angular上的表单的一种实现可能看起来像这样。

ContactFormGroup实现(角度)
export class ContactFormGroup {
    emailFormGroup = new EmailFormGroup();
    phoneFormGroup = new PhoneFormGroup();

    changes: Observable<unknown> = merge(this.emailFormGroup.changes, this.phoneFormGroup.changes);

    constructor() {}

    isValid(): boolean {
        return this.emailFormGroup.isValid() || this.phoneFormGroup.isValid();
    }

    getValue() {
        return {
            emails: this.emailFormGroup.getValue(),
            phones: this.phoneFormGroup.getValue(),
        };
    }
}

export class EmailFormGroup {
    emailControl = new FormControl();
    secondaryEmailControl = new FormControl();

    changes: Observable<unknown> = merge(
        this.emailControl.valueChanges,
        this.secondaryEmailControl.valueChanges,
    );

    isValid(): boolean {
        return this.emailControl.valid && !!this.emailControl.value;
    }

    getValue() {
        return {
            primary: this.emailControl.value,
            secondary: this.secondaryEmailControl.value,
        };
    }

    isSecondaryEmailVisible(): boolean {
        return this.isValid();
    }
}


因此,我们得到了三个接口(或类,并不重要)。您应该将这些类放在醒目位置的单独文件中,以便您可以通过简单地了解它来了解界面的移动部分。我们已经确定,提出并强调了有问题的逻辑,现在我们结合了ContactFormGroup各个部分的实现来控制表单的行为。不同用例的需求可以轻松地表示为单独的对象。

这似乎是MVC模式的标准实现,仅此而已。但是我不会忽略实际上根本不尊重的基本事物。关键不是我们从视图中提取了一段代码。关键是我们已经突出显示了易于更改的重要部分,并描述了其行为,从而使其变得简单。


ChA向我们介绍了编写软件的法律。它提供了度量标准,通过这些度量标准,我们可以区分重要部分和次要部分,并正确指导这些部分之间的依赖关系。描述OOP的好处以及通过建模解决问题的方法。

如果您想提高程序的质量,使其变得灵活,在工作中使用OOP,学习如何管理项目中的依赖项,在代码中谈论问题的解决方案而不是关于库的细节,那么我强烈建议阅读Clean Architecture。本书的技巧和原则与任何堆栈和范例都有关。不要害怕对您的任务进行实验。祝好运

PS关于状态管理


理解NA的一个很大障碍是对状态管理库的承诺。实际上,诸如redux / mobx之类的库同时解决了通知组件有关更改的任务。对于某些开发人员来说,没有状态管理器的前端是不可想象的。我相信,无论有没有使用状态管理器,都可以应用ChA的原则。但是,通过专注于状态管理库,您不可避免地会失去一些灵活性。如果从ChA和OOP的角度考虑,那么状态管理的概念通常会消失。没有状态管理的最简单实现是在这里habr.com/en/post/491684

PPS


老实说,我向我的朋友展示了类似界面任务的解决方案-他不满意,并重写了所有内容以用于反应挂钩。在我看来,很大程度上是因为OOP实际上没有在实际项目中使用,并且大多数年轻的前端开发人员对OOP解决方案没有丝毫经验。在面试中,他们有时会询问有关SOLID的问题,但通常只是淘汰候选人。此外,通过审查可以抑制某些团队在PLO领域的发展狂潮。人们整理一个新库通常比阅读一本无聊的书或捍卫他们从组件中提取逻辑的权利要容易得多。请支持OOP活动家:)

All Articles