前言
在前端开发领域,组件开发一直是一个绕不开的话题。
那么在组件开发时,要注意哪些问题?如何开发出易维护且复用性高的组件?
下面就结合面向对象设计原则,和开发中的实践经验,总结一部分组件开发需要注意的几个原则。
原则
1、保持简单 (KISS—Keep It Simple, Stupid,Straightforward)
代码足够简单,也意味着易读、易维护,bug 比较难以隐藏。往往简单的设计越高效和通用(符合奥卡姆剃刀原理)。
如何满足 KISS 原则?
-
不要过度优化。比如加入某些不常用的高级写法,或者使用一些过于底层的函数,位运算等。牺牲了可读性和可维护性。
-
不重复造轮子。尽量使用经过验证和稳定的库和方法。减少维护成本和出错的概率。
-
不要过度设计(YAGNI—You Ain’t Gonna Need It)。在能保证扩展性的前提下,不要提前设计和编写当前用不到的功能。现在用不到的,未来可能也用不到。
如果组件是服务于业务的,就尽量让业务需求驱动,而不要技术驱动。
2、单一职责(SRP—The Single Responsibility Principle)
一个组件负责完成一个职责/功能。
单一职责可以保证组件的粒度,有利于复用和维护。如果职责过多,代码就会臃肿,可读性降低,从而变得难以维护。
比如网站的登录和注册功能,从 UI 看似有很多相似的元素,但内部的验证的逻辑又不尽相同,如果合成一个组件就不符合单一职责。
但是单一职责并没有统一的判断依据,通常要结合组件的使用场景以及业务发展来看。如果起初不能确定,那就尽量保持组件的简单。
如何粗略判断组件是否符合单一职责?
-
组件代码行数、函数个数及属性是否过多。一般判断代码是否超过 200 行,函数个数及属性是否已经超过 10 个。
-
比较难给组件起一个合适的名字,说明组件的职责定义不够清晰。
3、不要重复(DRY—Don’t Repeat Yourself)
不要写重复的逻辑,尽量做好代码的复用性。这也是开发组件的目的之一。
但是如果一味的消除冗余,很容易又违反单一职责原则,使组件内部逻辑复杂、难以维护。
所以在一些情况下,我们可以利用组件化的方式,解决重复问题。
当业务中某块逻辑重复过多且具有明确的功能性倾向,我们就应该考虑将其抽象为组件。
当组件之间存在共同依赖同一部分逻辑时,我们可以把共同依赖的部分提取为新组件,或者在内部转化为共同依赖。
当两个组件都能实现同一功能,且仅因为实现方式或接口不同时,我们需要将其合并,或者在内部解决为依赖关系。不要提供给用户太多选择。
4、共同封闭原则(CCP—The Common-Closure Principle)
将那些会同时修改,或者因为同一个目的发生修改的代码,放到一个组件里。
举个例子,现在有 A、B、C 三个组件,A 和 B 都依赖 C。但是经常 A 的改动就需要改动 C 做一些兼容。
这个时候,就适合将 C 组件直接移到到 A 组件中。
的确这样会违背不要重复的原则,但是当可维护性和可复用性发生冲突时,大多数情况可维护性优先级是更高的。
5、共同复用原则(CRP—The Common Reuse Principle)
一个组件中的类应该一起被复用,相反,如果没有一起被复用,那就不应该放在一个组件。
因此,强烈建议,一个组件一个类。
6、稳定依赖原则(SDP—The Stable-Dependencies Principle)
不稳定的组件应该依赖于更加稳定的组件。
稳定性的衡量
组件不稳定性指标 = (对别的组件依赖个数) / (对别的组件依赖个数 + 别的组件对自己依赖个数)
每个组件的不稳定性指标都应该大于其依赖组件的不稳定性指标。
在实践中通常是越抽象越稳定,越偏实现越不稳定。(这里涉及稳定抽象原则,就不展开了)
举个例子, 就像模版页面 -> 业务组件 -> 基础组件,依赖关系应该指向更加抽象的方向。
7、好莱坞原则(IoC—Inversion of Control, Hollywood Principle)
好莱坞原则就是一句话——“don’t call us, we’ll call you.”。意思是,好莱坞的经纪人们不希望你去联系他们,而是他们会在需要的时候来联系你。
也就是说,所有的组件都是被动的,所有的组件初始化和调用都由容器负责。组件处在一个容器当中,由容器负责管理。
简单讲,就是控制反转,将子组件的创建与管理交给外层容器组件来控制。
8、关注点分离(SoC—Separation of Concerns)
如果一个问题能分解为独立且较小的问题,就是相对较易解决的。
问题太过于复杂,要解决问题需要关注的点太多,人的精力是有限的,不能同时关注到问题的各个方面。
通常实现关注点分离的方式有两种:一种是标准化,另一种就是抽象与包装。
标准化下,每个人只需按照规范开发组件,而不用担心其他的具体实现。
组件化本身就是抽象与包装实现的一种方式。
小结
以上提到的原则,都具有指导意义,但都是理论上的探索,并不是强调组件的开发就必须满足每一个原则。
组件的开发还有很多其他因素需要考虑,比如组件的定位、使用场景以及业务发展、开发和维护成本等等。
所有的原则,最终目的是帮助我们开发出更具复用性,更易维护和扩展的组件。
如果你有自己的一套衡量体系,也欢迎留言分享。