克服“以后修复”的坏习惯

时间:2009-07-20 22:37:17

标签: c++ code-reuse modularity

当我从头开始编写代码时,我养成了在一个函数中快速编写所有内容的坏习惯,整个时间都在考虑“我将在以后更加模块化”。然后,当后来出现时,我有一个工作产品,任何修复它的尝试都意味着创建函数并且必须弄清楚我需要通过什么。

它变得最糟糕,因为当你的项目几乎完成时重新设计类变得非常困难。例如,我通常在开始编写代码之前做一些计划,然后当我的项目完成时,我意识到我可以使类更加模块化和/或我可以使用继承。基本上,我认为我没有做足够的计划,而且我不会获得超过一级的抽象。

所以最后,我坚持使用一个具有大型main函数,一个类和一些辅助函数的程序。不用说,它不是非常可重复使用。

有没有人遇到同样的问题并有任何提示可以解决这个问题?我想到的一件事是用pseduocode编写main函数(没有太多细节,但足以看到他们需要什么对象和函数)。基本上是一种自上而下的方法。

这是个好主意吗?还有其他建议吗?

9 个答案:

答案 0 :(得分:12)

我在事先没有大的设计阶段即时编写内容时采取完全相反的方法。也就是说,我使用虚构的对象和方法编写主要功能,然后创建所有内容的骨架,然后返回并使其工作。这确保了模块化设计,并且高级代码非常易于理解。如果有的话,缺点是代码变得过于模块化,因为编写doFoo()而不是实现foo内联是很诱人的。

答案 1 :(得分:5)

“首先我们养成习惯,然后才能养成我们。”

这似乎适用于好习惯和坏习惯。听起来像一个坏人已经掌握了你。

练习更加模块化,直到它“只是我做事的方式。”

答案 2 :(得分:3)

是的,解决方案很简单,虽然需要时间来适应它。 从来没有声称会有一个“后来”,你坐下来,只是做重构。相反,继续向代码(或测试)添加功能,并在此阶段执行小的增量重构。 “后来”基本上是“永远”,但隐藏在你每次都在做新事物的阶段。

答案 3 :(得分:2)

我的经验法则是,任何超过20 LoC的东西都应该是干净的。 IME的每个项目都代表着一些从未打算在生产代码中出现的“仅仅是一个概念验证”。由于这似乎是不可避免的,即使是20行概念验证代码也应该清楚,因为它们最终可能成为一个大项目的基础之一。

我的方法是自上而下的。我写了

while( obj = get_next_obj(data) ) {
  wibble(obj);
  fumble(obj);
  process( filter(obj) );
}

并且稍后才开始编写所有这些函数。 (通常它们是inline并进入未命名的命名空间。有时它们会变成单行,然后我可能会在以后消除它们。)

这样我也避免了对算法的评论:函数名称足够解释。

答案 4 :(得分:1)

我发现TDD Red-Green-Refactor纪律创造了奇迹。

答案 5 :(得分:0)

你几乎已经确定了这个问题。没有足够的计划。 花一些时间分析您将要开发的解决方案,将其细分为多个功能,确定如何最好地实现它们并尝试分离应用程序的各个层(UI,业务逻辑,数据访问层等) )。

尽可能早地考虑OOP和重构。一切都建好后,它比做它便宜很多。

答案 6 :(得分:0)

最低限度地编写main函数,几乎没有任何内容。在大多数gui程序,sdl游戏程序,open gl或任何具有任何类型用户界面的任何东西中,主要功能应该只是一个事件循环。它必须是,或者总是有很长一段时间,计算机似乎没有响应,操作系统认为可能会关闭它,因为它没有响应消息。

一旦你获得主循环,快速锁定它,只是修改bug修复,而不是新功能。这可能最终将问题转移到另一个函数,但无论如何,在基于事件的应用程序中具有monilithic函数是相当困难的。你总是需要一百万个小事件处理程序。

也许你有一个单一的课程。我做到了。主要处理它的方法是尝试保持依赖关系的心理或物理映射,并注意哪里有... ...说,穿孔,裂缝,其中一组函数没有明确依赖于任何共享状态或变量与班上的其他功能。在那里,您可以将该功能集关闭到一个新类中。如果它真的是一个庞大的阶级,并且真的很纠结,我会称之为代码味道。考虑重新设计这样一个不那么庞大且相互依存的东西。

你可以做的另一件事就是你正在编码,注意当一个函数增长到一个不再适合单个屏幕的大小时,它可能太大了,并且在那时开始思考如何打破它分成多个较小的函数。

答案 7 :(得分:0)

如果你有很好的工具,那么重构就不那么可怕了。我看到你将你的问题标记为“C ++”,但任何语言都是如此。获取一个IDE,其中提取和重命名方法,提取变量等很容易,然后学习如何有效地使用该IDE。然后,Stefano Borini提到的“小的,渐进的重构”将不那么令人生畏。

答案 8 :(得分:0)

您的方法并不一定是坏的 - 早期更多的模块化设计最终可能会过度工程化。

你需要重构 - 这是生活中的事实。问题是什么时候?太晚了,重构太重要了,太冒险了。太早了,它可能是过度工程化的。而且,随着时间的推移,你将需要再次重构。这只是软件自然生命周期的一部分。

诀窍很快就会重构,但不会太快。经常,但不是太频繁。多久和多久?这就是为什么它是一门艺术,而不是一门科学:)