- You are still happily using inheritance,
if/elsecollections, have methods that are hundreds of lines long etc. You possibly haven’t heard of TDD or DI. There’s a very good chance that, if this is the case, you’ll likely never see this post as you likely do not read blogs by other developers.
- You do read around, you are aware of why inheritance,
switch, deeply nested and long code blocks are frowned upon by the well-informed. You are at least aware of TDD, even if you haven’t quite started using it yet. Also, you are likely aware of the growing excitement around functional languages and perhaps look on with envy at some of their features. If this is you, you possibly already use SHOF’s without knowing it.
So what is SHOF? It’s an acronym created by Mike Hadlow, and it stands for Static Higher Order Functions. Higher Order Functions (HOFs) are defined on wikipedia as being those that have at least one parameter that is another function. The problem here is that everything else is then a first order function. That doesn’t give much scope for defining good use of static methods, eg avoiding side effects. A better definition is needed. So a method is a SHOF if:
- It is static. The S is there for a reason!
- It must have no direct side effects:
- It must take at least one parameter
- It must return a value; it must not be a
- It must not define any
- It must not access any fields or properties
- It must not directly access any non-private method directly
- All private methods directly accessed must must return a value; they must not be
- All other interactions with methods must be via injecting them through
Func<>(and if really necessary,
Looking through the above list, you are possibly asking yourself the question “how can my code have any use if it contains only SHOFs and so can have no side affects?” Alternatively, you may be thinking that SHOFs will be limited to simple helper methods that manipulate their parameter values to derive a return value. The key addressing both of these concerns lies in the term “direct side effects”. A SHOF may just be a first-order function with no side effects; it can also be a HOF though: other methods may be invoked by the SHOF. Consider the following simple C# SHOF:
T SomeFunc(Func<T> x) => x();
SomeFunc meets all of the above requirements, so it’s definitely a SHOF. There is no requirement that
x be one though. The key here is that functionality is injected into the SHOF via
Action<> callbacks. Just with using interfaces, the specific behaviour is then decoupled from the calling code. That specific behaviour may (and, to make a useful program, at times must) have side effects.
For an example of how SHOF’s can be used to write real code, take a read of Mike’s blog post, C#: Program Entirely With Static Methods.