Sunday, June 9, 2013

Encapsulating collections

I'm working on a protein energy landscape exploration program written in C++.

In the program each explorer can react to its environment in several ways: stopping the simulation, changing its search parameters or jumping to a more favorable spot.
An explorer knows about its environment through its sensors and then evaluates a series of conditions to know what to do next. There are conditions for each kind of action to happen.

Our code was suffering from a case of primitive obsession in the form of using raw STL collections for the conditions and sensors. That meant that there was a bunch of code that dealt with those concepts that was spread all over the place, particularly in the explorer's creation code.

On Friday I tried to improve the code applying the Encapsulate Collection refactoring.
I combined this refactoring with the use of the factory method pattern.

I'm happy with the results. Now the collection-handling code that was spread all over, has been attracted by the newly generated collections-like classes (ExitConditions, JumpingConditions and Sensors). Moreover, I've been able to give that functionality proper names to improve its readability and also to remove a bunch of getters that were bothering me and a class that didn't make sense anymore.

Regarding the refactoring process, it was pretty easy to introduce ExitConditions and JumpingConditions in tiny steps staying in green most of the time.

The real challenge was to introduce Sensors because the sensors related code was being used in many places, mainly for building conditions and reporting sensor values.
I tried to refactor it in tiny steps but got to a point where I got stucked. So I decided to plow ahead (I always had the possibility of using SVN to go back to where I started) and see. Well, three hours were gone before I could run the tests again...

While in the end all tests were green, I'm not proud of how I did it. I spent too much time in red and it could have easily gone badly.

Even though I'm sure I need more practice with this refactoring technique, I think it's always going to be very difficult to apply it when the problem has already spread too much.

In that case, I think that I have two options: a reactive one, learning more powerful large scale refactoring techniques like Mikado method; or, better a preemptive one, not letting the problem spread by applying the Encapsulate Collection refactoring more often.

As Xavi Gost said once:
Encapsulate in objects your collections you must.
A couple of days after writing this post I realized that I could merge JumpingConditions and ExitConditions classes in just one: Conditions.
This has simplified the code further.

No comments:

Post a Comment