维护大型JavaScript应用程序经验教训 - MathiasSchäfer

栏目: JavaScript · 发布时间: 6年前

内容简介:这是我们从长期维护大型JavaScript应用程序中学到的经验教训。在例如,我们于2012年为贝塔斯曼基金会启动了

这是我们从长期维护大型JavaScript应用程序中学到的经验教训。

我们的机构 ,客户项目通常持续几个月。从第一个客户联系和设计阶段到实施和首次启动,项目大致需要半年时间。但有时我们会在几年内开发和维护特定的软件。

例如,我们于2012年为贝塔斯曼基金会启动了 GED VIZ ,并于2013年发布,每隔几年就会增加新的功能和数据。2016年,我们将核心可视化转变为可重用的库,对其进行了重构。欧洲中央银行(ECB)今天仍在使用流数据可视化引擎。另一个长期存在的项目是 OECD Data Portal 前端:我们在2014年开始实施,我们仍在扩展代码库。

在主要开发阶段之后,我们应用修复并添加新功能。通常,没有重大重构甚至重写的预算。因此,在一些项目中,我坚持使用我在4 - 6年前编写的代码以及当时流行的库堆栈。

小改进而不是大改写

前面提到的两个项目都是相当大的客户端JavaScript应用程序。如今,您发现很少有关于维护现有JavaScript代码库的博客文章。你会发现很多帖子都在用你现在流行的JavaScript框架重写你的前端。

迁移到一组新的库和 工具 是一项重大投资,可能很快得到回报。它可以简化维护。它可以降低变更成本。它允许更快地迭代并更快地实现新功能。它可以减少错误,提高稳健性和性能。最终,这种投资可能会降低总体拥有成本。

但是当客户无法进行此项投资时,我们会寻找如何逐步改进现有代码库的方法。

从长期项目中学习

对于一些Web开发人员来说,坚持使用现有的代码库是一场噩梦。对于他们最近一段时间没有修改过的代码,他们以贬义的方式使用“遗产”这个词。

对我来说,情况恰恰相反。在几年内维护一个项目的代码教会了我更多关于软件开发的知识,而不是多个短暂的,即发即弃的项目。

最重要的是,它让我遇到了我多年前写过的代码。我多年前做出的决定对今天的整个系统产生了影响。我今天做出的决定从长远来看决定了系统的命运。

我常常想知道:今天我会做些什么?有什么需要改进的?像每个开发人员一样,我有时会有破坏一切并从头开始构建它的冲动。

但大多数时候,我对现有代码的问题更加微妙:今天,我会编写相同的逻辑,但结构不同。让我向您展示我在JavaScript代码中发现的主要结构问题。

避免复杂的结构

“复杂”我并不仅仅意味着大。每个非平凡的项目都有很多逻辑。很多案例要考虑和测试。要处理的数据不同。

复杂性来自于交织不同的问题。人们无法完全避免这种情况,但我已经学会先将 问题分开 ,然后以可控的方式将它们带回来。

让我们看看JavaScript中的简单和复杂结构。

函数

最简单的可重用JavaScript代码是一个函数。特别是,一个 纯函数 ,它获取一些输入并产生一个结果(返回值)。该函数显式获取所有必需的数据作为参数。它不会更改输入数据或其他上下文数据。这样的功能易于编写,易于测试,易于记录,易于推理。

编写好的JavaScript不一定需要高级设计模式。首先,它需要技能以巧妙和有益的方式使用最基本的技术:用一些 正确的 函数构建程序。然后将低级函数组合到更高级别的函数。

JavaScript中的函数是完整的值,也称为第一类公民。作为一种多范式语言,JavaScript允许强大的函数式编程模式。在我的职业生涯中,我只是用JavaScript编写了函数式编程的表面,但理解基础知识已经有助于编写更简单的程序。

对象

下一个复杂的结构是一个对象。在最简单的形式中,对象将字符串映射到任意值,没有逻辑。但它也可以包含逻辑:函数在附加到对象时成为方法。

const cat = {
  name: 'Maru',
  meow() {
    window.alert(`${this.name} says MEOW`);
  }
};
cat.meow();

JavaScript中的对象无处不在且功能多样。对象可以用作附加几个处理函数的参数包。对象可以对关联的值进行分组,但也可以构建程序。例如,您可以在一个对象上放置几个类似的函数,并让它们对相同的数据进行操作。

JavaScript中最复杂的结构是一个类。它是物体的蓝图,同时也是这些物体的工厂。它将原型继承与对象的创建混合在一起。它将逻辑(函数)与数据(实例属性)交织在一起。有时在构造函数上有属性,称为“静态”属性。像“singleton”这样的模式会使一个具有更多逻辑的类重载。

类是面向对象语言中常见的工具,但它们需要 设计模式 的知识和对象建模的经验。特别是在JavaScript中,它们很难管理:构建继承链, 对象组合 ,应用mixins,超级调用,处理实例属性,getter和setter,方法绑定,封装等.ECMAScript也没有为常见的OOP概念提供标准解决方案。社区是否就使用类的最佳做法达成一致。

如果具有一个定义的目的(banq:标签),则类是合适的。我学会了避免在类上增加更多的顾虑。例如, 有状态的React组件 通常声明为类。这对特定问题域有意义。它们有一个明确的目的:对属性,状态和两个功能进行分组。该类的核心在于render功能。

我停止用更多,松散相关的逻辑来丰富这些类。值得注意的是,React团队正逐渐从类转向 有状态的函数组件

同样, Angular 中的 组件类 是几个关注点的交集:使用@Component()装饰器应用的元数据字段。基于构造函数的依赖注入。将状态作为实例属性(输入,输出以及自定义公共和私有属性)。这些课程根本不是简单或单一目的。只要它们只包含所需的Angular特定逻辑,它们就是可管理的。

选择结构

多年来,我已经达到了这些指导方针:

  1. 使用最直接,最灵活和多函数的结构:函数。如果可能的话,让它成为一个纯粹的函数。
  2. 如果可能,避免在对象中混合数据和逻辑。
  3. 尽可能避免使用类。如果你使用它们,让他们做一件事。

大多数JavaScript框架都有自己的结构代码方式。在基于组件的UI框架(如React和Angular)中,组件通常是对象或类。选择组合比继承更容易:只需创建一个新的轻量级组件类来分离关注点。

这并不意味着需要坚持使用这些结构来模拟业务逻辑。最好将这个逻辑放入函数中,并将它们与UI框架分开。这允许分别发展框架代码和业务逻辑。

模块,很多

管理JavaScript文件和外部库之间的依赖关系曾经是一团糟。在9elements,我们是CommonJS或AMD模块的早期采用者。后来社区决定使用标准的 ECMAScript 6模块

模块成为JavaScript中必不可少的代码结构。这取决于它们是否带来简单性或复杂性的用法。

我对模块的使用随着时间的推移而改变。我曾经用多个导出创建相当大的文件。或者,单个导出是将一堆常量和函数分组的巨大目标。今天我尝试用一​​个导出或只有几个导出来创建小而扁平的模块。这导致每个函数一个文件,每个类一个文件,依此类推。文件foo.js看起来像这样:

export default function foo(…) {…}

如果您更喜欢命名导出而不是默认导出:

export function foo(…) {…}

这使得单个函数更易于引用并且更易于重用。根据我的经验,许多小文件不会带来很大的成本。它们允许更容易地在代码中导航。此外,特定代码片段的依赖性更有效地声明。

避免创建无类型的对象

JavaScript的最佳功能之一是对象表示法object literal。它允许您使用任意属性快速创建对象。我们已经看到上面的一个例子:

const cat = {
  name: 'Maru',
  meow() {
    window.alert(`${this.name} says MEOW`);
  }
};

JavaScript对象表示法是如此简单和富有表现力,以至于它变成了一种无处不在的独立数据格式:JSON。但是在ECMAScript版本的过程中,对象表示法获得了越来越多超出其原始目的的功能。新的ECMAScript功能,如 Object Rest / Spread, 可以更自由地创建和混合对象。

在小代码库中,动态创建对象是一种生产力功能。然而,在大型代码库中,对象表示法成为一种负担。在我看来,具有任意属性的对象不应该存在于这样的项目中。

问题不在于对象表示法本身。问题是不符合中心类型定义的对象。它们通常是运行时错误的来源:属性可能存在与否,可能具有某种类型。该对象可能具有所有必需的属性,但也更多。通过阅读代码,您无法确定对象在运行时将具有哪些属性。

JavaScript没有类型定义,但有几种方法可以更加可控的方式创建对象。例如,函数可用于创建看起来相似的所有对象。该函数确保所需的属性存在且有效或具有默认值。另一种方法是使用一个创建死简单 值对象

同样,函数可以在运行时检查参数是否可用。它可以明确地检查使用类型typeof,instanceof,Number.isNaN等或隐式使用 duck typing

更彻底的解决方案是使用类型定义(如TypeScript或Flow)来丰富JavaScript。例如,在TypeScript中,首先定义重要数据模型的接口。函数声明其参数的类型和返回值。TypeScript编译器确保仅传递允许的类型 - 假定编译器可以访问所有调用。

强大的代码

这些指南涉及代码的整体结构。多年来,我在大型JavaScript项目中学到了更多的技术和实践。最常见的是影响JavaScript应用程序的健壮性:了解JavaScript程序如何失败以及如何防止它。我在免费的在线书籍中汇编了这些技巧:

强大的客户端JavaScript - 开发人员指南


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Algorithm Design Manual

The Algorithm Design Manual

Steven S Skiena / Springer / 2011-11-14 / GBP 55.07

....The most comprehensive guide to designing practical and efficient algorithms.... Written by a well-known algorithms researcher who received the IEEE Computer Science and Engineering Teaching Aw......一起来看看 《The Algorithm Design Manual》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

html转js在线工具
html转js在线工具

html转js在线工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具