Ben*_*313 36 c c++ refactoring
我本周在工作中一直在研究一些已有10年历史的C代码,在实施了一些修改之后,我去了老板,问他是否需要做其他事情.那是他放下炸弹的时候.我的下一个任务是遍历7000行左右,了解更多代码,并稍微模块化代码.我问他如何将源代码模块化,他说要开始将旧的C代码放入C++类中.
作为一名优秀的工作者,我点头表示赞成,然后回到我的办公桌,我现在坐在那里,想知道世界上如何采用这些代码,并"模块化"它.它已经有20个源文件,每个文件都有自己的用途和功能.此外,还有三个"主要"结构.这些结构中的每一个都有30多个字段,其中许多是其他较小的结构.尝试理解它是一个完全混乱,但程序中几乎每个函数都传递一个指向其中一个结构的指针并大量使用结构.
有没有什么干净的方式让我把它变成课堂?如果可以的话,我决心这样做,我只是不知道如何开始.
小智 35
首先,你很幸运有一个老板认识到代码重构可以成为一个长期的节省成本的策略.
我已经多次这样做了,就是将旧的C代码转换为C++.这些好处可能让您大吃一惊 完成后,最终代码可能是原始大小的一半,并且更易于阅读.此外,您可能会发现一路上棘手的C错误.以下是我将采取的步骤.小步骤很重要,因为在重构大量代码时,不能从A跳到Z. 您必须经历可能永远不会部署的小型中间步骤,但可以在您使用的任何RCS中对其进行验证和标记.
private(是,或受保护),然后隔离访问该字段的代码.最简单,最具侵入性的转换是将代码编写为a friend function.还要考虑将该代码作为一种方法.将代码转换为方法很简单,但您还必须转换所有调用站点.一个不一定比另一个好.const自由使用.从底部向上扫描(调用图的底部,即),您将为代码添加更强的保证,并且您将能够从非mutator中识别mutator.NULL不会重新分配的参数.将引用视为编译时断言,它表示,这是有效对象的别名,并在整个当前作用域中表示相同的对象.char*为std::string.这一步应该是显而易见的.您可能会大大减少代码行.另外,用一行替换10行代码很有趣.有时你可以删除整个函数,其目的是执行C++中标准的C字符串操作.std::vector或std::array.同样,这一步应该是显而易见的.这个转换是从比转化简单得多char到std::string因为接口std::vector和std::array被设计成匹配C数组语法.其中一个好处是可以消除length传递给数组旁边的每个函数的额外变量.malloc/ free到new/delete.此步骤的主要目的是为将来的重构做好准备.仅仅更改C代码malloc,以new不直接获得你多少.此转换允许您向这些结构添加构造函数和析构函数,并使用内置的C++自动内存工具.new/ delete操作std::auto_ptr.此步骤的目的是使您的代码异常安全.throw返回代码(C++允许您在最低级别抛出任何类型).try{} catch(){}在代码中处理错误的位置插入语句.如果不存在处理错误的合适位置,请考虑将语句包装main()在一个try{} catch(){}语句中并记录它.现在退一步看看你有多少改进了代码,而没有将任何内容转换为类.(是的,是的,从技术上讲,你的结构已经是类.)但是你没有触及OO的表面,但设法大大简化并巩固了原始的C代码.
您应该将代码转换为使用类,具有多态性和继承图吗?我拒绝.C代码可能没有适合OO模型的整体设计.请注意,上述每个步骤的目标与将OO原则注入C代码无关.目标是通过实施尽可能多的编译时约束以及通过消除或简化代码来改进现有代码.
最后一步.
考虑添加基准,以便在完成后向老板展示.不仅仅是性能基准.比较代码行,内存使用情况,函数数量等.
小智 20
真的,7000行代码不是很多.对于如此少量的代码,可以按顺序完成重写.但这个代码将如何被调用?大概是调用者期望一个C API?或者这不是图书馆?
无论如何,重写与否,在开始之前,请确保您有一套测试,您可以在现有代码上轻松运行,无需人工干预.然后,在您进行的每个更改中,对新代码运行测试.
ome*_*med 19
这种对C++的看法似乎是随意的,问你的老板他为什么需要这样做,弄清楚你是否可以不那么痛苦地达到同一目标,看看你是否可以用新的不那么痛苦的方式对一个子集进行原型设计,然后去演示你的老板,并建议你按照不那么痛苦的方式.
Rob*_*boy 12
首先,告诉你的老板你没有继续,直到你有:
http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672
在较小程度上:
http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052
其次,没有办法将代码模块化到C++类中.这是一项艰巨的任务,您需要向您的老板传达重构高度重复性代码的复杂性.
它归结为做一个小的改变(提取方法,移动方法等等......)然后进行测试 - 没有这方面的捷径.
我确实感觉到你的痛苦......
我想这里的想法是增加模块化将隔离代码片段,以便促进未来的变化.我们有信心改变一件,因为我们知道它不会影响其他作品.
我看到两个噩梦场景:
然而,也许有一个愉快的媒介.可能存在一些重要且概念上孤立的逻辑,但由于缺乏数据隐藏等目前这些逻辑很脆弱(好的C不会受此影响,但我们没有这个,否则我们会留下好的单独).
拉出一个类来拥有那个逻辑及其数据,包含这个部分可能很有用.用C或C++做它是否更好是值得商榷的.(我的愤世嫉俗者说"我是一名C程序员,很棒的C++学习新东西的机会!")
所以:我认为这是一只可以吃的大象.首先要确定它是否应该被吃掉,糟糕的元素只是没有乐趣,结构良好的C应该被单独留下.第二次找到合适的第一口.我会回应尼尔的评论:如果你没有一个好的自动化测试套件,你就注定要失败.
| 归档时间: |
|
| 查看次数: |
4172 次 |
| 最近记录: |