A few days ago while describing the architecture of Excido I wrote that I was ok with “allowing the Web API to reach directly into Entity Framework in order to take advantage of data access service built into Breeze.” This didn’t sit right with me. I suppose I wasn’t as ok with it as I thought.
I was comfortable allowing it (I thought) because of the benefits that Breeze brings to the client side, like change tracking and caching. The client-side programmer part of me really, really wants those benefits. However, the software architect part of me really, really doesn’t like it. By allowing the Web API and Breeze to reach directly into Entity Framework, I’m tightly coupling the architecture from the web browser all the way down to the ORM. While I can’t imagine replacing Breeze or WebAPI or Entity Framework, tightly coupling the three of them in my code makes my code unlikely to be able to adapt to any changes at all. Sure, it’s unlikely that I will be replacing one of the components, but if a new version of one of them comes out with attractive features, it is unlikely that my code will be agile enough to handle the upgrade.
There is also a security issue. Even though the WebAPI is only expecting calls from the BreezeJS client, there’s nothing to stop anyone else from sending requests to the WebAPI. If the WebAPI has access all the way down to the ORM, malicious users could gain that access as well. While there is no pressing security requirements right now, it is entirely reasonable that users will expect their records to be secure.
The Breeze server component does allow me to add code to inspect and cancel requests before they are passed to the ORM. I could use that to apply some security at that point, but then I would be coupling my business code even more tightly to Breeze. I’m more than convinced that there needs loosely coupled business and repository layers between the WebAPI and the ORM.
It turns out that Breeze does allow for this. The part of Breeze that interfaces with Entity Framework is called a ContextProvider. Breeze will allow me to write my own ContextProvider that interfaces with my own business layer instead of Entity Framework. It is possible for me to have the benefits of Breeze on the client side without compromising my architecture on the server side.
Unfortunately, writing my own ContextProvider is not an insignificant task. There are several examples of custom ContextProviders, but there is not a simple tutorial on how to write one. It won’t be impossible, but it won’t be easy.
The software architect part of me wanted to get working on this right away. I started laying out the architecture in my head and taking notes. However, the project owner part of me knows that I should finish my current sprint before rushing off to redesign the architecture. I decided to simply add some new Features to the Product Backlog and agree to have that conversation with myself at a later date.
I wanted to simply add a item to the backlog that said “re-work the architecture” or “add layers between WebAPI and EF”. I’m using the scrum process template in Visual Studio Online and it suggests entering backlog items in terms of “features”. The question I had to ask myself is: “What feature will the software have that requires me re-work the architecture?”
This was a good question to ask. If the new architecture wouldn’t bring any feature to the software, there’s no reason to do it. I came up with the following features:
- Users should only be able to edit their own content.
- Users should not be able to edit the creation date of any content.
These features will require me to write some sort of security into the software. I suppose that I could use the hooks that Breeze gives me to inspect changes before they are made, but as the architect I think I can make the decision to use a more complicated design to achieve flexible security.
I suppose I could add the following feature:
- The software should remain flexible to changing security requirements.
Different project owners will have different opinions as to whether that is a requirement or a feature. Different project owners will also have different opinions as to whether requirements should be allowed in the feature list. I’ve sort of compromised by wording the requirement as a feature.
By adding the above features, it’s now evident that we need to add the following as well:
- Users can log in.
- Each user has unique content that only he can alter.
I also added the following:
- Users can have different roles that give them different capabilities.
- Users in the administrator role can alter any content.