Silicon Valley Code Camp is a little over a week away! If you're in the Bay Area, be sure to carve out some time to stop by. Last year almost 2,500 people attended, and this year looks to be even bigger.
There are tones of interesting people to meet, some famous people speaking, and a HUGE assortment of sessions to choose from on all different development topics. If you have anything to do with technology, there's probably something to interest you.
Silicon Valley Code Camp
October 5 & 6, 2013
http://www.siliconvalley-codecamp.com/
And if you're there, be sure to hunt me down (if you can find me in the crowd). And stop in to one of my sessions:
Clean Code: Homicidal Maniacs Read Code, Too
Session Description
Saturday, October 5th at 1:45 p.m.
Dependency Injection: A Practical Introduction
Session Description
Saturday, October 5th at 3:30 p.m.
I'm looking forward to seeing a bunch of my old friends and making new ones. See you there!
Happy Coding!
Thursday, September 26, 2013
New Pluralsight Course: Design Patterns On-Ramp
My latest course is now available on Pluralight: Design Patterns On-Ramp.
Design Patterns On-Ramp
I'm currently working on my next course: Dependency Injection On-Ramp. And I'm still looking for topics for future courses.
Enjoy the new course, and I'd love to hear your feedback.
Happy Coding!
Design Patterns On-Ramp
You already use Design Patterns but probably don't know it. In this course, we'll take a look at several everyday programming scenarios that are implementations of Design Patterns. Once we start to recognize patterns, we're well on our way to using them effectively. Our goals are to get comfortable with the basic concepts, to see how they are useful, and to discover that design patterns are relevant to all programmers, not just architects and system designers. When we're done, you'll be ready to explore the rich and wonderful world of Design Patterns.This is a great way to get started with Design Patterns. Plus, you get to learn a little about me, including my video game habits and the kind of music I listen to.
I'm currently working on my next course: Dependency Injection On-Ramp. And I'm still looking for topics for future courses.
Enjoy the new course, and I'd love to hear your feedback.
Happy Coding!
Monday, September 23, 2013
Applying the Interface Segregation Principle to a Repository
Repositories appear in many of my example applications. This is because it's a fairly easy problem to describe and understand. Last month, we took a look at whether we really need this in our applications: Do I Really Need a Repository?
My friend, Jim, replied with the following:
A Generic Repository
Before looking at the Interface Segregation Principle, let's update the existing interface to use generic parameters. Here's our original interface from the last article:
This is an example of a CRUD Repository -- where CRUD stands for Create, Read, Update, and Delete. (Another common repository type is CQRS -- Command Query Responsibility Separation -- we'll talk about this in a bit.)
If we add generic parameters to this, we can get this interface to work with more than just Person objects. Everywhere we see "Person", we'll replace with "T", and everywhere we see "string" (which is the type for the primary key), we'll replace with "TKey". Then we just update the method names so that they make sense for any types.
Here's our updated generic repository interface:
This interface will work with any types we have (Customers, Orders, Products, etc.) as well as whatever key types we have (int, string, GUID, etc.).
Now let's look at how we can apply the Interface Segregation Principle to this.
The Interface Segregation Principle
The Interface Segregation Principle is one of the S.O.L.I.D. principles of Object-Oriented Design (specifically, the "I"). Here's what the principle states:
When this repository interface is used in the sample applications, we generally only use the "Read" portions. Because of this, we really should not saddle our client object with the update methods (Create, Update, Delete) since it does not use them.
To apply the Interface Segregation Principle, we just need to segregate out the Read operations into a different interface.
Here's what that could look like:
This way, our application that only does Read operations uses this more granular interface. And it only needs to depend on the methods it actually uses.
If we do need a full CRUD repository, then we can simply inherit from this interface and add the other methods:
Because IRepository inherits IReadOnlyRepository, it includes the GetItems() and GetItem() methods, and then adds the other operations. This lets us be selective about the specific interface, and we only need to depend on the methods we actually use.
A CQRS Repository
But what about Jim's suggestion of having an ILoader and ISaver? This has a simplified set of methods. Here's what those interfaces look like:
We can easily imagine that the Loader would work very similar to our read-only repository. This would handle our "Read" (or "Query") operation. The Saver would handle the operations that update the data (the "Command" operations).
This actually follows the pattern of a CQRS repository. As mentioned above, CQRS stands for Command Query Responsibility Separation. This means that we keep the Command operations (the Saver) separate from the Query operations (the Loader).
What About Implementation?
One thing to notice is that the Saver has a much simpler interface. When we have the CRUD repository, we had separate methods for Create, Update, and Delete operations. With the ISaver interface, we have a single Save() method.
So, how do we know what operations we need to perform on the actual data store: Insert, Update, or Delete? That all depends on how we're storing our data.
One possibility is to only have Insert operations on our data store. We always insert the most recent record into the data store (with a current timestamp). If we have a deleted record, we insert the most recent record with a delete flag set to "true". When pulling data out, we make sure that we're fetching the most current record, but we have the full history in the database. This is fairly easy to implement in a document database. It can also be used with a relational database, however, the pattern isn't quite as common with RDBMS.
If we are using a typical RDBMS data store technique, we actually want to make Insert, Update, or Delete calls as appropriate (along with potentially logging the changes in separate change-tracking tables). But how do we know which operation we need to call on a particular record? That's where things get a bit more complex.
One solution that I've used is to use a business object framework that includes change tracking on the application objects. I've used CSLA.NET very successfully (http://www.cslanet.com/). This is a business object framework that works very well for the types of apps that we often build for companies (get data out of a database, let the user change it, put it back into the database). CSLA includes tons of useful features including change tracking, validation, authorization, and it works on a variety of platforms (web, desktop, mobile).
Using a framework such as this, we simply call "Save" on the business object, and the framework figures out which of the actual update operations to call depending on whether the record is new, changed, or deleted. (As a side note, this is a good example of the Facade design pattern where a complex API is hidden behind a simpler interface.)
Implementing this type of functionality yourself is not trivial, which is why we should look to see if there's an existing implementation that we can take advantage of.
Wrap Up
So, if we determine that we do need a repository (Do I Really Need a Repository?), our job is not necessarily done. We need to consider what type of repository will work best in our situation (CRUD vs. CQRS), and we also need to keep in mind whether we're including more methods in our interface than we actually need. If we find that we are not using all of the methods (or we find that we're using some of the methods in one class and other methods in others), we should think about splitting up our interface so that we have the right level of granularity. This is what the Interface Segregation Principle is all about.
This gives us quite a bit to think about. As always, we need to weigh the options and come up with the best solution for our particular environment.
Happy Coding!
My friend, Jim, replied with the following:
@jeremybytes Scenario 4: Apply the interface segregation principle to repositories and get ILoader and ISaver https://t.co/MLVqeKrQJTThis is a great point, so let's take a closer look at this.
— James R Counts (@jamesrcounts) August 19, 2013
A Generic Repository
Before looking at the Interface Segregation Principle, let's update the existing interface to use generic parameters. Here's our original interface from the last article:
This is an example of a CRUD Repository -- where CRUD stands for Create, Read, Update, and Delete. (Another common repository type is CQRS -- Command Query Responsibility Separation -- we'll talk about this in a bit.)
If we add generic parameters to this, we can get this interface to work with more than just Person objects. Everywhere we see "Person", we'll replace with "T", and everywhere we see "string" (which is the type for the primary key), we'll replace with "TKey". Then we just update the method names so that they make sense for any types.
Here's our updated generic repository interface:
This interface will work with any types we have (Customers, Orders, Products, etc.) as well as whatever key types we have (int, string, GUID, etc.).
Now let's look at how we can apply the Interface Segregation Principle to this.
The Interface Segregation Principle
The Interface Segregation Principle is one of the S.O.L.I.D. principles of Object-Oriented Design (specifically, the "I"). Here's what the principle states:
Clients should not be forced to depend upon methods that they do not use. Interfaces belong to clients, not to hierarchies.What this means is that we should make our interfaces granular so that we only get the methods that we actually need.
When this repository interface is used in the sample applications, we generally only use the "Read" portions. Because of this, we really should not saddle our client object with the update methods (Create, Update, Delete) since it does not use them.
To apply the Interface Segregation Principle, we just need to segregate out the Read operations into a different interface.
Here's what that could look like:
This way, our application that only does Read operations uses this more granular interface. And it only needs to depend on the methods it actually uses.
If we do need a full CRUD repository, then we can simply inherit from this interface and add the other methods:
Because IRepository inherits IReadOnlyRepository, it includes the GetItems() and GetItem() methods, and then adds the other operations. This lets us be selective about the specific interface, and we only need to depend on the methods we actually use.
A CQRS Repository
But what about Jim's suggestion of having an ILoader and ISaver? This has a simplified set of methods. Here's what those interfaces look like:
We can easily imagine that the Loader would work very similar to our read-only repository. This would handle our "Read" (or "Query") operation. The Saver would handle the operations that update the data (the "Command" operations).
This actually follows the pattern of a CQRS repository. As mentioned above, CQRS stands for Command Query Responsibility Separation. This means that we keep the Command operations (the Saver) separate from the Query operations (the Loader).
What About Implementation?
One thing to notice is that the Saver has a much simpler interface. When we have the CRUD repository, we had separate methods for Create, Update, and Delete operations. With the ISaver interface, we have a single Save() method.
So, how do we know what operations we need to perform on the actual data store: Insert, Update, or Delete? That all depends on how we're storing our data.
One possibility is to only have Insert operations on our data store. We always insert the most recent record into the data store (with a current timestamp). If we have a deleted record, we insert the most recent record with a delete flag set to "true". When pulling data out, we make sure that we're fetching the most current record, but we have the full history in the database. This is fairly easy to implement in a document database. It can also be used with a relational database, however, the pattern isn't quite as common with RDBMS.
If we are using a typical RDBMS data store technique, we actually want to make Insert, Update, or Delete calls as appropriate (along with potentially logging the changes in separate change-tracking tables). But how do we know which operation we need to call on a particular record? That's where things get a bit more complex.
One solution that I've used is to use a business object framework that includes change tracking on the application objects. I've used CSLA.NET very successfully (http://www.cslanet.com/). This is a business object framework that works very well for the types of apps that we often build for companies (get data out of a database, let the user change it, put it back into the database). CSLA includes tons of useful features including change tracking, validation, authorization, and it works on a variety of platforms (web, desktop, mobile).
Using a framework such as this, we simply call "Save" on the business object, and the framework figures out which of the actual update operations to call depending on whether the record is new, changed, or deleted. (As a side note, this is a good example of the Facade design pattern where a complex API is hidden behind a simpler interface.)
Implementing this type of functionality yourself is not trivial, which is why we should look to see if there's an existing implementation that we can take advantage of.
Wrap Up
So, if we determine that we do need a repository (Do I Really Need a Repository?), our job is not necessarily done. We need to consider what type of repository will work best in our situation (CRUD vs. CQRS), and we also need to keep in mind whether we're including more methods in our interface than we actually need. If we find that we are not using all of the methods (or we find that we're using some of the methods in one class and other methods in others), we should think about splitting up our interface so that we have the right level of granularity. This is what the Interface Segregation Principle is all about.
This gives us quite a bit to think about. As always, we need to weigh the options and come up with the best solution for our particular environment.
Happy Coding!