I'm not just talking about different styles here, I'll give you an example. For our plugin development we use the repository pattern so the following type of code is used quite often:
public class AccountRepository { IOrganizationService _service; public AccountRepository(IOrganizationService service) { _service = service; } /*...*/ }
This is somewhat fine, although the 1 to 1 mapping between entities and repository classes isn't ideal, but it works well for us so far. Unfortunately some of the developers don't fully understand what the repository pattern really is and what it should and shouldn't know of/know how to do. Recently I spotted that the following code was checked in some time back:
public class AccountRepository { IOrganizationService _service; Entity Account { get; set; } public AccountRepository(IOrganizationService service) { _service = service; Account = null; } public AccountRepository(IOrganizationService service, Entity Account) { _service = service; this.Account = Account; } /*...*/ }
The problem this introduces is that my repository is now aware of an account record/entity. This immediately points the finger at the code breaking SRP (Single Responsibility Principle).
Let's refresh our memory on what a repository pattern is. Put simply, the repository should act as a data layer or mediator between our business logic, domain objects and our data source. It should know how to take a query and provide a resulting set of domain objects. It might also be able to add and remove objects, or even update objects. To perform these operations it should be aware of how to connect to the data source, how to map the result of a query to domain objects and it should make that list of objects available to the caller. In some instances you may move the "data mapping" logic out into its own classes, but in Dynamics CRM the Organization Service already provides you with Entity objects (or strongly typed objects if you prefer) so you may not need a separate data mapping abstraction.
Let's refresh our memory on what a repository pattern is. Put simply, the repository should act as a data layer or mediator between our business logic, domain objects and our data source. It should know how to take a query and provide a resulting set of domain objects. It might also be able to add and remove objects, or even update objects. To perform these operations it should be aware of how to connect to the data source, how to map the result of a query to domain objects and it should make that list of objects available to the caller. In some instances you may move the "data mapping" logic out into its own classes, but in Dynamics CRM the Organization Service already provides you with Entity objects (or strongly typed objects if you prefer) so you may not need a separate data mapping abstraction.
So, what do I do? Refactor a load of methods I didn't develop and spend half a day fixing other peoples code? Send out a tip (yet another one!) saying why this is bad and look like Mr Grumpy (yet again!)? Or do I ignore it and hope it goes away in time...
Decisions decisions!
What decision did you make? I tend to look to try and improve the codebase I'm working on as I'm working on it. Roughly speaking I try and follow the Boy Scout Principle.
ReplyDeleteFor my part I've found that tips (however nicely presented) can be received well and can be received badly based on the attitude of the people you're working with. However, more often than not it seems tips are ignored - quite often ignored!
In this particular instance I had to leave the code as it was. When I unraveled the underlying logic removing the reference to the account entity would have taken more time that I had.
ReplyDeleteAlso, when I found out what dev had made the change I decided not to comment. This particular person hadn't responded so well to another tip I had given him previously and got quite code defensive, so I decided against.
I don't work on that project any more, but out of curiosity I took a quick peek at the code. That repository I blogged about above deteriorated even more... it's now a 611 lines of code repository (just for the account entity)... and some of the functions in the repository return a completely different entity type to account...
On the plus side, my new team are hell bent about clean code so it's the first time in a long while that the project has been incredibly satisfying from that perspective!