Tuesday, October 2, 2012

Least-Concept-Method

Often when writing code a developer will use member overloading to provide an alternate convenient call interface on a class. Assuming the developer has at-least a passing interest in quality, they will try and stay DRY. To this end, one of the method overloads will contain the core 'work' for the member, whilst overloads will perform only simple tasks, and then hand-off to the core method to do the real work. But which overload is the best for the core?

I like to use a least-concept method for the core. By this I select a set of parameter(s) that are

  1. Not native types, or simple constants.
  2. Don't require the method to navigate deeply into the parameter(s) (one-level in is ideal).
Why not native types? 
Often I've seen code that uses a core method that extracts the most-basic, or native data from more complex objects, and implements the core with this. For example, say I have a CountLines() method that needs a file, the developer may go for the most basic CountLines(string fileName) style. This approach has the benefit of being flexible for the caller, but it sacrifices clarity. The next developer has to know that what I really mean is the full path to the file, not just its file name. You could argue the parameter is badly named (and I'd agree), but I still would prefer a stronger type. C# is a typed language, a better idea would be to leverage it. In this case I would go for a CountLines(FileInfo file) method.

Why not the most complex object as a parameter?
Sometimes you need to implement a method that takes a complex object, particularly when implementing an interface (plug-in), but the method only uses a small part of the complex object. Lets say you're implementing a RejectIfTooBusy(HttpApplication context) method. You want to reject if the current request is from a set of black-listed hosts. The context has the data you need via context.Request.Url.Host, but to reach this you need to check for nulls along the way. Rather than having this parameter conversion code in your main implementation, I prefer to pull out a core RejectIfTooBusy(Uri whoReqested) method, and have this overload called by the first. By separating out the core member, it becomes clearer that all I'm checking is the request url. It can also be useful to split a complex object, to highlight the bits that the method really uses.

No comments:

Post a Comment

A short list of C# coding issues.

Injecting services into entities It been bugging me for a while now that to use services in a entity can be a bit of pain. It usually starts...