We finished last post with this funny situation: the abstraction that represents Facebook depends on our Domain Model.

It was a bit obvious that what we needed was not only system abstractions for Facebook, Twitter and the like but Bounded Contexts. We need to acknowledge the fact that these domains are not part of our model, even though we depend on them. We need to make this explicit.
The Facebook API doesn’t have the same concept of User as we do, and neither does Twitter. Someone has to translate from Profiles to Users. We identified the UserRepository as the best candidate for that.
The hugest advantage of this is proper dependency management. If you remember our last post, we had a circular dependency between system abstractions and our model. It was something like this:
But, by isolating message parsing from the user creation, we remove that red line. Facebook doesn’t create Users anymore, therefore it doesn’t depend on AllSocialNetworks/UserRepository. Will fall in a situation closer to this:
Now UserRepository will have access to everything it needs to create valid instances of User –and all it needs are objects returned by the system abstractions. The circular dependency problem is solved.
While moving this translation away from the system abstractions we learned that our situation was much worse than we first thought. The challenge looked simple, transform this:

Into this:
But indirect coupling among those classes was so strong that even with multiple levels of tests the effort to migrate all system abstractions to this structure is still in progress.
The Repository class is currently in a weird situation. It was already a very good candidate to be renamed to something else or, even better, split in two or more. After all those changes, though, that class is just too far away from whatever a Repository should be. This will probably be the next major refactoring that we have to do in this system.
But that’s another story, that maybe will be told another day…
Conclusion
In this example we went from this:

To this:
We sent from seven to thirteen classes. From two to four major packages/modules. Did this really help or we just went nuts on abstraction explosion?
All metrics I have gathered up to this point are positive. I am not talking about abstract metrics like cyclomatic complexity, efferent coupling and etc. –those are useful but won’t tell much without context. What tells me if those changes helped or not is how they impact the behaviour of the development team.
We went from a couple of fat and overdependent classes to many small classes with limited responsibility. This design is not suitable for all scenarios but it is what works well with most Object-Oriented models. If you consider that we are always adding more integration points -it’s an integration project after all- the extra flexibility and explicit concepts are really welcome to the system.
People in the team are more comfortable with the new model, it is easier to talk to the business and understand what they want done. It is also easier for newcomers to understand what the system is about and how to change it –how to map the vocabulary used in story narratives to classes and objects.
Looking at Subversion logs, we can see that commits tend to be contained into a given module. That means fewer conflicts to resolve and less contention –i.e. no or few God classes. In the end of the day this means that developers waste less time waiting for someone else to finish working with a given class and in rework.
On the bad side, making this refactoring while still delivering user stories is messy. It is really important to remember people frequently that we should not patch the old classes, but take the chance to advance towards the new model.
Unfortunately we were not pro-active enough to start refactoring and cleaning the code before having issues with circular dependencies and while playing a story one usually feels much more pressure to just fix the symptom than to solve the root cause.




Thanks for posting this series. It really helps when you can see how code evolves naturally/logically to become more well designed.
I think that you’ll get into a situation where UserRepository will be a mess and it will be responsible for the majority of the bugs.
I have a proposal: since the application is a kind of aggregation of several other applications, I suggest that the fact that the application User should also be related to several other users. So, you have a UberUser and normal User for each of the aggregated other applications.
Nevertheless, UserRepository should be split in several classes, each implementing only one responsibility.
Besides diagrams, could you show us some code?
Thanks for sharing, Phillip!