【发布时间】:2011-04-12 13:14:55
【问题描述】:
应该使用哪些措施来识别代码过度抽象且难以理解,以及应该采取哪些措施来减少过度抽象?
【问题讨论】:
标签: abstraction
应该使用哪些措施来识别代码过度抽象且难以理解,以及应该采取哪些措施来减少过度抽象?
【问题讨论】:
标签: abstraction
我完全同意@ArnisLapsa 写的:
"Simplicity over complexity, complexity over complicatedness"
还有那个
an abstraction is used to "de-level" those, from complicated to complex
(从复杂到简单)
另外,正如@MartinHemmings 所说,一个好的抽象是非常主观的,因为我们的想法并不相同。事实上,我们的思维方式会随着时间而改变。所以有些人觉得简单的东西在别人看来可能很复杂,甚至随着经验的增加变得更简单。例如。一元操作对于函数式程序员来说是微不足道的,但对其他人来说可能会严重混淆。同样,具有可变对象相互通信的设计对于某些人来说可能很自然,而对其他人来说则无法跟踪。
话虽如此,我想添加几个指标。请注意,这适用于代码库中使用的抽象,而不是“范式抽象”,例如一切都是函数或一切都被设计为对象。所以:
【讨论】:
下载 Magento 并查看代码,阅读其中的一些文档并查看其 ERD:http://www.magentocommerce.com/wiki/_media/doc/magento---sample_database_diagram.png?cache=cache
我不是在开玩笑,这太抽象了.. 试图取悦每个人并覆盖每个基础是一个糟糕的想法,并且会让每个人的生活都变得非常困难。
【讨论】:
我会给出一个会得到很多反对票的答案!
如果代码是用 OO 语言编写的……它必然是过度抽象的。语言越纯,问题就越严重。
应该非常谨慎地使用抽象。如果有疑问,请始终使用具体的数据结构。 (以后可以随时抽象,这比反抽象容易:)
您必须非常确定您在当前上下文中具有正确的抽象,并且您必须非常确定该概念能够经受住变化的考验。抽象在代码和编码器的性能上都付出了高昂的代价。
对过度抽象的一些弱测试:如果数据结构是产品类型(C 中的结构)并且程序员已经为每个字段编写了 get 和 set 方法,他们完全没有提供任何真正的抽象,禁用运算符,如C 增量,没有目的,根本不理解结构字段名称已经是产品的抽象表示。复制和叠加界面不是一个好主意。
对产品案例的一个很好的测试是是否存在需要维护的任何数据不变量。例如,一对表示有理数的整数几乎就足够了,几乎不需要任何抽象,因为所有对都是有效的,除非分母为零。然而,出于性能原因,人们可能会选择保持不变量,通常要求分母大于零,并且分子和分母互质。为了确保不变量,产品表示被封装:由构造函数保护的初始值和受约束以保持不变量的方法。
要修复代码,我推荐以下步骤:
记录抽象维护的表示不变量
如果找不到强不变量,请删除抽象(方法)
使用直接访问数据的方法重写代码。
此过程仅适用于低级抽象,即类对小值的抽象。
更高层次的过度抽象更难处理。理想情况下,您会反复重构代码,检查每个步骤后它是否继续工作。然而,这将是困难的,有时需要进行重大重写,而不是改进。除非抽象离基础太远以至于无法继续维护它,否则它可能不值得。
【讨论】:
“简单大于复杂,复杂大于复杂”
所以 - 只有当您将复杂性“降低”到复杂性时,抽象某些东西才有好处。这样做的原因可能各不相同:更好的模块化、更好的封装等。
识别过度抽象是一个先有鸡还是先有蛋的问题。为了减少过度抽象,您需要了解代码行背后的实际原因。这包括理解特定抽象本身的想法(与将其称为缺乏理解的抽象原因相反)。这还不够——您需要知道一个更好、更简单的解决方案来证明它过于抽象。
如果您正在寻找可以代替您执行此操作的工具 - 不要再看了,只有头脑才能可靠地判断。
【讨论】:
我个人会说“理想的抽象级别是什么?”是一个主观问题。
我不喜欢为每个原子操作使用新行的代码,但我也不喜欢在一行中包含 10 个嵌套操作。
我喜欢使用递归函数,但我不喜欢仅仅为了递归而使用递归。
我喜欢泛型,但我不喜欢(嵌套)泛型函数,例如为每种预期的特定类型使用不同的代码...
这是个人意见和常识的问题。这能回答你的问题吗?
【讨论】: