混入带来的一些问题

混入带来的一些问题

1
如何在组件之间共享代码?这是在学习react时,人们最先问的问题,答案一般都是通过组件组合的方式重用代码。你可以定义一个组件,并且使用在其他组件。

为什么混入具有破坏性

在 facebook, react 的使用从只有一些组件到成千上万的组件,这使得我们可以有机会思考下人们是如何使用 react。多亏了声明式的返回和自上而下的数据流,许多团队可以在发布新的功能时处理一堆的问题。

然而不可避免的是随着功能点和代码量的增多,逐渐会有一部分代码变得晦涩难懂。特别是别使用在多个项目中的组件,往往使工程师对修改感到恐惧。这些组件很容易被破坏,对新开发者不友好,有时甚至对于模块的创建者也会感到困惑,诸多这些都由混入引起。

但这并不意味着混入本身是无益的,人们已经成功的在不同语言和模型中使用他们。然而作者任务混入是没有必要且有问题的。

混入会带来隐式的依赖问题

有些时候一个组件依赖于定义在 mixin 中的某个方法,比方说 getClassName(),有时可能会是其他的方法,列如 renderHeader().js 是一种动态语言,因此很困难去增强或是记录这些依赖。

混入破环了普遍性,并且需做安全性的思考,当你重新命名一个状态的键或者方法,你需要去全局搜索下你修改的键出现的频率。你可能会写了一个有状态的组件,而你的同事可能加入了一个混入去读取这个状态。然后过了几个月,你可能想要提升这个状态到父组件,这样可以被一个滑动共享,你会记得去更新这个状态在 mixin 中去读取 prop,要是其他的组件也使用到了这个混入?

这些隐式的依赖使得新成员去贡献代码变得很困难。一个组件的 render 方法可能会引用到一些在类中没有被定义过的方法,这些方法可以被安全的删除?也许他被定义在 mixin 中的一个,但具体是哪一个?需要去查看 mixin 的清单,打开这些文件中的每一个,去寻找这个方法。更糟糕的是,mixin 也可以指定 mixin,这样就会有深层次嵌套查找。

混入没有层级关系,它们是扁平的并且运行在同一个命名空间。

混入引起的名字问题

如果在两个混入函数中有同名的方法,无法同时使用。

在遇到冲突时,你可以重命名其中的一个,然而有意思的是由于重命名的混入方法可能已经被其他组件或 mixin 所引用,那么你就得相应得去处理由这次修改所引起得副作用

假设你有个冲突来自和第三方得库,你不得不使用更复杂得名字避免命名冲突

一旦 mixins 写好,随着时间推移,移除和修改会变得越来越困难,重构得风险也越来越大。

混入还会引起雪球复杂度

一个组件需要状态去跟踪鼠标悬浮。为保持逻辑得复用,你可能抽取 handleMouseEnter(), handleMouseLeave(), 和 isHovering()到 hovermixin 中。下一步,有些人需要实现 tooltip,他们想复用在 hovermixin 中的逻辑,因此他们创建了 TooltipMixin,使用 hovermixin 提供的 isHovering 的函数,来显示是否显示或隐藏。

几个月之后,有人想让 tooltip 可以有方向上的配置,为了避免代码的重复,增加了新的方法 getTooltipOptions()到 TooltipMixin,如果还需要配置 hover delay 的时间,解决这个问题需要在增加 getHoverOption

如果需要支持在单一组件中展示多个 tooltips?你无法定义两个一样的 mixin 在一个组件,如果 tooltip 需要根据 guided tour 自动的展示?

每一个新的需求都会使 mixin 更难于理解,使用同样 mixin 函数的组件随着时间的推移耦合度逐渐增加任何一个新的功能都会相应的增加到使用这个 mixin 的组件中,封装的边界会变得越来越模糊,因为很难去改变和移除这些存在的 mixin,所以只有不断对 mixin 做抽象,直到没有人理解这到底是做什么的

这些问题可以通过声明式的返回,自上而下的数据流和封装过的组件来解决。