Is there anything wrong with a class with all static methods?

Is there anything wrong with this
pattern? Is this just a matter of
personal choice if the state of a
class is held in fields and properties
or passed around amongst static
methods using arguments?

Speaking from my own personal experience, I’ve worked on 100 KLOC applications which have very very deep object hiearchies, everything inherits and overrides everything else, everything implements half a dozen interfaces, even the interfaces inherit half a dozen interfaces, the system implements every design pattern in the book, etc.

End result: a truly OOP-tastic architecture with so many levels of indirection that it takes hours to debug anything. I recently started a job with a system like this, where the learning curve was described to me as “a brick wall, followed by a mountain”.

Sometimes overzealous OOP results in classes so granular that it actually a net harm.

By contrast, many functional programming languages, even the OO ones like F# and OCaml (and C#!), encourage flat and shallow hiearchy. Libraries in these languages tend to have the following properties:

  • Most objects are POCOs, or have at most one or two levels of inheritance, where the objects aren’t much more than containers for logically related data.
  • Instead of classes calling into each other, you have modules (equivalent to static classes) controlling the interactions between objects.
  • Modules tend to act on a very limited number of data types, and so have a narrow scope. For example, the OCaml List module represents operations on lists, a Customer modules facilitates operations on customers. While modules have more or less the same functionality as instance methods on a class, the key difference with module-based libraries is that modules are much more self-contained, much less granular, and tend to have few if any dependencies on other modules.
  • There’s usually no need to subclass objects override methods since you can pass around functions as first-class objects for specialization.
  • Although C# doesn’t support this functionality, functors provide a means to subclass an specialize modules.

Most big libraries tend to be more wide than deep, for example the Win32 API, PHP libraries, Erlang BIFs, OCaml and Haskell libraries, stored procedures in a database, etc. So this style of programming is battle testing and seems to work well in the real world.

In my opinion, the best designed module-based APIs tend to be easier to work with than the best designed OOP APIs. However, coding style is just as important in API design, so if everyone else on your team is using OOP and someone goes off and implements something in a completely different style, then you should probably ask for a rewrite to more closely match your teams coding standards.

Leave a Comment