Functional Programming Guidelines a la SOLID?

The recent kerfuffle between “Uncle Bob” Martin and Joel Spolsky involves the SOLID Principles,some object-oriented design guidelines that compress into a pleasing acronym.

While there are weaknesses in the mainstream OOP languages, I believe that OOP has a great advantage in that it is teachable. You can start with “objects are nouns, methods are verbs,” draw some class diagrams, and move on to SOLID… all of which could be criticized as overly abstract and ungrounded in the business of turning inputs into outputs, but y’know, darn it, there are teachable principles.

Functional programming fits well with test-driven approaches to development and provides some guidance on concurrency issues. In the Jolt Judges discussions this year, nothing has engendered as much discussion as Haskell and Scala.

But from a pedagogical standpoint, I think that functional programming has a big problem. To the extent that you get anything in terms of principles, it’s mathematical category theory. How do you determine when a function is too big? When should you split a data structure into sub-structures? How can you tell a well-thought-out function from a poorly-thought-out one?

Functional programming needs answers to these types of questions and those answers can’t be of the “once you understand it, you’ll develop a feel for it,” ilk.

9 Comments

  1. Clif Kussmaul says:

    Here’s a simple answer to many of these questions: Unit Tests
    A function is too big when you can’t test all of it easily.
    You should split a data structure when you can’t test all of it easily.
    A well-thought out function has better/clearer/more complete tests.
    Unit testing is relatively easy to teach, even to novices;
    it’s more functions, possibly augmented with coverage analysis.
    And thinking carefully about good test cases is a great match
    for inductive-style functional programming.

    This applies at the micro-level – I think the bigger challenges are macro.

  2. Dan Ciruli says:

    One of my Computer Science professors at Berkeley had a good rule of thumb for how long a function should be: if it doesn’t fit on one screen, it’s too long.

    I certainly violate it sometimes, but it’s not a bad guideline!

  3. John Bender says:

    I’m of the same opinion, where is the definable elegance. People need guidelines for correctness, otherwise what is it?

    If you take it too far though you’ll end up in Zen and the Art of Motorcycle Maintenance.

  4. cashto says:

    I think it’s important to distinguish between guidelines and principles. “No functions longer than a page” is a guideline that applies to OOP as well as FP code, but it’s not a principle like the SOLID principles are. It’s just a handy rule of thumb.

    I think FP lacks SOLID principles chiefly because there’s a lot fewer ways you can write bad FP code. Functions have much simpler contracts than objects; they are easier to use, reuse, and test because of it. Mutable state is especially messy.

    Some of the SOLID principles (such as SRP) still apply in FP, but most of them are there to help you avoid mistakes which are easy to commit in OO programming.

  5. Aaron Davies says:

    speaking as a k/q programmer, i find anything over a line depressingly inelegant

  6. Greg says:

    Functional programming works best when you leverage pre-existing vocabulary and structure — kind of like “design patterns”, only concrete and not useless. If you can work out an applicative functor or a monoid instance for a given datatype, that opens up a working language and library of techniques that other people can understand.

    This also means you want to take advantage of “standard” functions like map, fold, filter, etc instead of writing the functions out in tail-recursive worker/wrapper style.

  7. noah healy says:

    Well a bit tongue in cheek but a la Paul Graham and co the answers to your questions are:
    A function is too big if you can see a way to make it shorter.
    Data structures should never be split the ideal number of data structures per program is 1 including the program.
    You can identify a well thought out function because it conforms to both of the above rules.

  8. logicalmind says:

    Why do you need unit tests if your functional program is provably correct? I mean provable in terms of a mathematical proof. Unit tests are for testing code that you cannot reason about mathematically, like OO programs.