5

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.)

4

3 Answers 3

1

I immediately think of two patterns that can be of use for your case.

Template method pattern

Everything that is the same for all concrete implementations resides in a single abstract class. All that is more concrete is delegated to subclasses. If I were you, I would first try this one.

Builder pattern

If you need more flexibility, e.g. if using the Template Method Pattern you would have to create a broad hierarchy of abstract classes, you may benefit from the builder pattern. Turning imperative code into a more descriptional object is exactly what you obtain with this pattern. All that remains for client applications is then to create and pass a concrete description of what you want to CRUD from the backing store.

0

You might have more indirection than you need. For example:

public SimpleRecord GetSimpleRecord(int recordID) {
   return getResource(repository => repository.SimpleRecords.Find(recordID));
}

could simply be:

public SimpleRecord GetSimpleRecord(int recordID) {
   return repository.SimpleRecords.Find(recordID);
}

Assuming that Repository fulfills an interface contract like IRepository, you can simply inject a repository that draws from the correct data source.

public class DataAccess
{
    IRepository repository;

    public DataAccess(IRepository repository)
    {
        this.repository = repository;
    }

    public SimpleRecord Find(int recordID)
    {
        // etc.
    }
}
2
  • I used a simple example in the post, but think about a case like an UPDATE to a resource: the code needs to find the resource (delegate), and map the changed properties to the found resource (delegate). Can this be accomplished with interfaces given the varying parameters required for different resources?
    – Jeremyx
    Nov 19, 2013 at 20:57
  • It sounds like you want to write a repository without having to hard-code the table and field names. You can do that, but it's turtles all the way down; you have to specify that information eventually, and the way you're abstracting it, you'll be doing it in magic strings, and not strongly-typed objects. Nov 19, 2013 at 21:13
0

Why not just use assert-like function?

public T Exists<T>(T val) where T : class
{
    if (val == null)
        throw new DataNotFoundException();
    return val;
}

And then use it:

public Person Get(string first, string last) {
   return Exists(repository.People.Find(first, last));
}

But this probably applies only for your simple example. But we don't know how complex your requirements are if you don't describe your complex cases. I think you are approaching this problem from bad side. While C# has few functional properties, it is not a functional language. Trying to solve problems in functional way is never going to look nicely.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.