“易于维护的主要特征是局部性:局部性是源代码的一种特性,它使程序员能够通过查看源代码的一小部分来理解它。” - 理查德·加布里埃尔
行为局部性是指:
代码单元的行为应该尽可能地通过仅查看该代码单元来显而易见
LoB 原则是对来自 理查德·加布里埃尔 的引述的一个简单规范性表述。在尽可能的情况下,以及在与其他关注点保持平衡的情况下,开发人员应该努力使代码元素的行为在检查时一目了然。
考虑两种在 HTML 中实现 AJAX 请求的不同方式,第一种是在 htmx 中
<button hx-get="/clicked">Click Me</button>
第二种是在 jQuery 中
$("#d1").on("click", function(){
$.ajax({
/* AJAX options... */
});
});
<button id="d1">Click Me</button>
在前者中,button
元素的行为在检查时一目了然,满足了 LoB 原则。
在后者中,button
元素的行为分散在多个文件中。很难在没有完全了解代码库的情况下确切地知道按钮的作用。这种“远距离的怪异行为”是维护问题的一个来源,并且阻碍了开发人员对代码库的理解。
htmx 示例展示了良好的行为局部性,而 jQuery 示例则表现出糟糕的行为局部性。
对行为局部性的一种常见反对意见是,它将实现细节内联到代码单元中,使代码单元变得不那么抽象,更容易出错。但是,重要的是要区分内联某些行为的实现和内联某些行为的调用(或声明)。
考虑大多数编程语言中的函数:函数的声明与其在调用站点上的使用之间存在区别。一个好的函数会抽象化它的实现细节,但也以一种显而易见的方式被调用,没有任何远距离的怪异行为。
提高元素行为的清晰度,在其他条件不变的情况下,是一件好事,但最终由最终用户开发人员,特别是框架开发人员来使 LoB 尽可能地简单易懂。
LoB 经常会与其他软件开发原则发生冲突。两个重要的原则分别是:
软件开发人员通常努力避免代码或数据中的冗余。这被称为“保持 DRY”,即不要重复自己。就像其他软件设计原则一样,这本身就是一件好事。例如,htmx 允许你将许多属性放置在 DOM 中的父元素上,避免在子元素上重复这些属性。这违反了 LoB,有利于 DRY,开发人员需要谨慎地权衡这样的取舍。
请注意,行为离影响它的代码单元越远,违反 LoB 的程度就越严重。如果它位于代码单元的几行内,这比它距离代码单元一页远时要轻微,而比它位于一个单独的文件中时要轻微。
没有严格的规定,而是在软件开发中必须进行的主观权衡。
关注点分离是一种将计算机程序分成不同部分的设计原则,以便每个部分都解决一个单独的关注点。一个典型的例子是将 HTML、CSS 和 JavaScript 分开。同样,就其本身而言,这可能是一件好事。内联样式 最近变得越来越普遍,但仍然有强烈的理由支持这方面的 SoC。
请注意,然而,SoC 与 LoB 相冲突。通过调整 CSS 文件,元素的外观和在一定程度上,行为都会发生巨大变化,而这种巨大变化来自哪里并不明显。工具可以在一定程度上提供帮助,但仍然存在“远距离的怪异行为”。
再说一次,这并不是要完全否定 SoC,只是说在考虑如何构建代码时,必须进行主观的权衡。内联样式最近变得越来越普遍,这表明 SoC 在开发人员中正在失去一些支持。
LoB 是一种主观的软件设计原则,它可以帮助使代码库更人性化,更易于维护。它必须与其他设计原则进行权衡,并且要考虑代码单元所处的系统的限制,但只要在实际情况下,遵守这一原则将会提高软件的可维护性、质量和可持续性。