Freigeben über


A C++ Refactoring Trick for "Encapsulate Field"

I was working on some old code that had a structure that looked like this

struct Foo {    bool fOptionEnabled;};

Tons of places in the code would check to see if the option was enabled, and do something based on it. The change I needed to make required that I do some extra work whenever the option was enabled. A good way to do this is to use the "Encapsulate Field" refactoring to reroute access to fOptionEnabled through accessors and then change the set method to be a more domain-specific "EnableOption()" and do all the required work in it.

The problem is that the amount of code affected to do this was very large and I didn't want to do it all at once. Instead I used an intermediate way of turning off just the set access to the variable (at the cost of making the structure a few bytes larger):

struct Foo {private:    bool m_fOptionEnabled;public:    const bool& fOptionEnabled;    Foo() : fOptionEnabled(m_fOptionEnabled) {}};

This change meant that code that read fOptionEnabled continued to compile and work, while code that tried to set it started failing. This let me change all the places that turned the option on to use Foo::EnableOption(). After that I actually went ahead and encapsulated read access to the variable as well, but using this trick means you can work in smaller steps, with fewer changes between passing tests. That is always a good thing when you have to manually refactor code.

Doing refactorings like this definitely makes me appreciate the argument behind Meyer's Uniform Access Principle. In C# this change can be made quite easily by using properties (of course, hiding the implementation like that will upset some people -- they want to see the () so that they know what is going on).

Comments