This summer at Dialexa I was given multiple opportunities to do software design.
Design is hard—anybody who tells you differently is lying. When you are designing algorithms, frameworks or even a simple piece of code, you never have all of the requirements, and you have to design code that will be able to adapt to support these currently undefined requirements.
One piece of code I designed for my team at Dialexa was a GenericUpdate utility. In my context, update means ‘create, delete, or update in database.’ The trick is that the update needed to not only update the entity that was passed in to the function but also update all children entities.
Before I wrote GenericUpdate we would have separate update classes for each of our 50+ entities. Each class would explicitly select which entities needed to be updated and determine which entities where children. When we needed to add a new table to the database (and thus another entity) we would have to create a new update class for that entity. Maintaining 50+ unique classes to update entities was an impossible task that created multiple bugs in our project.
My task was to implemented a GenericUpdate utility that would take any entity and figure out how to save it properly. Saving the parent entity was easy, we already had a Repository factory that would manage the different update commands. The trick was determining which properties represented children and which properties represented primitive fields.
Reflection couldn’t work. It simply wasn’t possible to have some sort of naming scheme or attribute on the property to represent an “IsChild” status.
The solution was for all entities to implement a GetChildren function. This function would allow the entity to specifically enumerate which children needed to be updated. A default implementation was provided in the Abstract parent class, and any sub-class that wanted to claim children would implement a single function to claim it’s children.
The GenericUpdate was able to call this GetChildren function, and then recursively GenericUpdate again on each of the children. My code replaced thousands of lines of code that were needlessly duplicated with a well-defined utility function for claiming children.