I have been falling into a pattern lately where I have been defining routines that rely on an interface defined by a function that is specified as a parameter to the routine. (The language is C#, but this can be applied to any language with first-class functions.)
For example, I have an API that exposes CRUD operations against a backing store. In the case of a GET operation on a particular resource, I can generalize the routine into:
- get the resource we are looking for
- return a not found response if resource does not exist
- return the resource if found
What I ended up doing is defining a routine that accepts a delegate function for finding the resource. It's this delegate that defines the interface contract.
This happens to work well for my situation because the information required to locate the resource can vary. In my case, it's looking up data in a database by keys, but the type and number of keys can vary. I can capture these in a closure in the calling routine and satisfy the delegate function interface. For example:
// Locate a simple record that only has one key
public SimpleRecord GetSimpleRecord(int recordID) {
return getResource(repository => repository.SimpleRecords.Find(recordID));
}
// Locate a complex record that has many keys
public ComplexRecord GetComplexRecord(int recordID, int userID, string token) {
return getResource(repository => repository.ComplexRecords.Find(recordID, userID, token));
}
This work, but seems like is a mix of OOP and functional style programming. If I need more than one delegate passed, it starts to get a bit messy. Some routines that I need everywhere I ended up defining as abstract methods that all sub-classes need to implement. So I have a hybrid.
Does this type of technique have a name or pattern that I'm missing? Should the delegates be implemented in a defined class interface that gets passed to the caller?
UPDATE with more concrete example:
I'm trying to adhere to the DRY principal. I'm talking about controllers in a C# Web API application. Each and every request has some commonality which I have implemented in a base controller class:
- Handle all exceptions by returning the correct HTTP status code, (404 for resources that are not found, 201 for created resources, etc.)
- Map database entities to-and-from data transport objects that the client deals with
I want to express what to do in this base class, and delegate how to the concreate class. The how ends up being implemented by delegate functions. I may need to get a person from the database, by first name and last name, or a purchase order, by an integer id. In both cases, if the resource is not found, a 404 must be returned. One returns a person, one a purchase order. How to look them up and how to map the data to a client object differs.
The base function may look like this:
T getResource<T> (Func<IRepository, T> find) {
T data = find(getRepository());
if (data == null) {
throw new DataNotFoundException();
}
return data;
}
Now, in the person controller and purchase order controller, I don't have to repeat the logic of what do to when the resource is not found--just implement the find delegate. (This is a simple example without mapping, adding, removing or other details that differ resource to resource).
public Person Get(string first, string last) {
return getResource<Person>(repository => repository.People.Find(first, last));
}
public PurchaseOrder Get(int id) {
return getResource<PurchaseOrder>(repository => repository.POs.Find(id));
}
Note how the closures above neatly deal with varying number and types of parameters for finding things, but satisfy the interface defined by the delegate find function. Is this possible to do with standard class interfaces?
(And this question is not about the repository. That is resolved with dependency injection and is implemented with Entity Framework.)