寻找课堂中的隐式沟通
我目前正在用 C++ 重构一个非常有用但设计不佳的类,并且遇到了设计问题:而不是使用方法的参数传递数据,而是通过在类中设置私有状态变量来传递数据。这使得我很难弄清楚数据如何在函数中移动。我周末的任务是尝试尽可能地消除这种传递数据的方式,因为这使得程序很难仅通过方法签名来理解,因为签名只讲述了故事的一部分。我决定
测试方法是否使用私有类级变量进行通信的当前方法如下:
- 编辑方法并使其成为函数而不是方法,这将删除其对类中状态变量的访问。
- 编辑对该方法的所有调用,以便它们调用函数而不是方法。
- 编译一下,看看有没有什么问题。制作要添加到原始类的访问器列表。
- 运行单元测试来看看我是否以非常微妙的方式破坏了任何东西。
有没有更好的方法来做到这一点,也许是一种可以轻松自动化的方法?这种重构是一种众所周知的技术吗?如果我向其他人展示它,我可以引用它吗?
到目前为止,我发现的唯一提到这个问题的是 Coders at Work 通过 < a href="http://en.wikipedia.org/wiki/Object-oriented_programming" rel="nofollow noreferrer">面向对象编程维基百科条目:
“面向对象语言的问题是它们你想要一根香蕉,但你得到的是一只大猩猩拿着香蕉和整个丛林。” - Joe Armstrong
编辑回答 Oli Charlesworth 的一个好问题:
我知道 OOP 的要点有时是通过类的状态变量进行通信。我当前的情况的困难在于,类中当前有 78 个不同的数据成员,其中许多是字符串到其他数据类型的键值对,并且对它们需要初始化的顺序存在未记录的隐式依赖关系。对于一个足够聪明的程序员来说,使用这个类可能会很容易,但目前对我来说非常困难。我认为其中一些数据类型可以抽象为它们自己的类,但在这样做之前,我需要更清楚地了解数据成员如何相互交互。
I am currently refactoring a very useful but poorly designed class in C++, and I'm running into a problem with the design: rather passing data around using arguments to methods, the data is passed around by setting private state variables in the class. This makes it very difficult for me to diagram out how data moves through functions. It's my weekend task to try and remove this style of passing data around as much as possible, as makes the program very impossible to understand from just the method signatures, as the signatures only tell a part of the story. I've decided
My current approach to test if a method communicates using private class-level variables is the following:
- Edit the method and make it a function rather than a method, which removes its access to the state variables in the class.
- Edit all of the calls to the method so that they call the function rather than the method.
- Compile, see if anything breaks. Make a list of accessors to add to the original class.
- Run the unit tests to see if I've broken anything in a very subtle way.
Is there a better way of doing this, perhaps one that can be easily automated? Is this refactoring a well-known technique that I can cite if I show it to other people?
The only mention of this problem that I've found so far is this quote from Coders at Work via the Object-oriented programming Wikipedia entry:
"The problem with object-oriented languages is they've got all this implicit environment that they carry around with them. You wanted a banana but what you got was a gorilla holding the banana and the entire jungle." - Joe Armstrong
Edit in response to a good question from Oli Charlesworth:
I understand that the point of OOP is to sometimes communicate through state variables of the class. The difficulty with my current case is that there are currently 78 different data members in the class, many of which are key-value pairs of strings to other data types, and there are undocumented implicit dependencies on the order in which they need to be initialized. It's possible that given a sufficiently smart programmer working with this class would be easy, but it's currently very difficult for me. I think that several of these data types could be abstracted into their own classes, but before I can do that I need to understand more clearly how the data members interact with each other.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
鉴于问题中的澄清,我的“你确定这不仅仅是你不喜欢其他程序员的风格吗”评论死了;)
就我个人而言,我只是正常重构。也就是说,对于 78 个数据成员和许多相关但不属于自己的类的位,我首先对相关数据进行分组并提取对其起作用的功能。恕我直言,没有必要经历将数据显式传递到现有类中的函数的阶段。只需选择一组相关的数据项,想出一个合适的名称,提取它们并找出它们的使用位置以及如何将功能转移到新类中。
理想情况下,我会开始为主类和新的细分类编写单元测试......
Given the clarification in the question my "are you sure it's not just that you don't like the other programmer's style" comment dies a death ;)
Personally I'd just refactor normally. That is, with 78 data members and lots of bits that are related but not in a class of their own I'd start by grouping the related data and extracting the functionality that works on it. There's no need, IMHO, to go through a stage where you explicitly pass the data into the functions in the existing class. Just pick a group of related data items, come up with a decent name, extract them and work out where they were used and how you need to move functionality into the new class.
Ideally, I'd start writing unit tests for the main class and the new broken out classes as I went along...
一个较小的中间更改是为所有调用者保留该方法,并通过调用该函数来简单地委托它,而不是让该方法的所有调用者都调用该函数。稍后您可以内联方法调用,以便所有调用者都直接调用该函数。
另外,从您的描述来看,您似乎正在通过手动测试来解决这个问题。通过适当的全面单元测试,您将获得更好的成功(更容易重构,降低错误风险),尽管您描述的代码当然很难进行单元测试。尽管如此,还是要努力实现更多的测试自动化。
Instead of making all of the method's callers call the function, a smaller intermediate change would be to leave the method in place for all callers, and have it simply delegate by calling the function. Later you can inline the method call so all callers are directly calling the function.
Also, from your description it sounds like you are approaching this with manual testing. You will have better success (easier refactoring with reduced risk of error) with comprehensive unit tests in place, although of course the code you describe would be hard to unit test. Nevertheless, work toward more test automation.