Saturday, November 09, 2024

Why the struggle with functional programming?

Slow FP adoption...

Why no widespread adoption even though functional programming exists already now for over sixty years?

Not so long ago I explained this as:

The reason is actually pretty complicated: The strength of FP is much due to its ability to be very strong. This strength in the code weakens the ability of developers to make local changes. Initially, this sounds like something good, yet it creates a new challenge: developers are bound to the constraints of code written by others, and they are not only not happy, they are less productive! You can solve this by bringing your FP to the next level: math. A few companies do this, now a developer is not subject to constraints but to mathematics. If the developer understands the math she/he finds this acceptable.
I am simplifying things a bit here, yet FP, or any language that is strong enough, brings in a whole complexity of technical ownership and people dynamics that does not need to be dealt with with OO. The reality is that FP allows more scaling, but maintaining the stability of people within that scaling is a major challenge.

I want to present this a bit differently here, because the above put too much blame on people. Yes, FP is tricky for teams, yet the root cause is not the teams, the teams just highlight the root cause!

The Design - Features - Tasks trilemma

Let's start with the following trilemma

Design - Features - Tasks

And by trilemma, I mean that you cannot simultaneous set goals to progress all three. (And by task, I mean "effective coding work"). You must specify two of these, and let the third one be determined by the outcome of your work. You can specify design and features, you can specific design and tasks, you can specify features and tasks... but you cannot specify design, features, and tasks before you start working.  To be more concrete: when you focus on architecture before coding, and come up with a design, you are in fact constraining the features that will be implementable with tasks that follow that design. If now you specify additional features, before you start your tasks using the given design, you will likely fail.

Functional programming done seriously "ties" design and tasks together. By which I mean that FP that pushes its higher order design model highly constrains the design. The result is that by construction, a team that pushes its FP design culture, is also a team that is "squeezing themselves" into an over constrained design-features-tasks trilemma. To be specific, an FP team may be imposing design, features and tasks all at the same time, and not understand that this is an over-constrained setup that will most often fail.

There is a solution: Just like I mentioned in that earlier post, you get a around trilemma by splitting one of its terms. Here we split tasks into design tasks and non-design tasks. The approach is then the following:

  1. Given some desired features
  2. Work on design-tasks so that the design can implement the features
  3. Then work on non-design-tasks, that implement the features with the developed design.

From a work triplet perspective, we have:

  1. features & design-tasks -> new-design
  2. features, non-design-tasks -> implemented features

Here, the new-design produced by 1, are used in 2.

However, the challenge is that now we have a two phase work process, and by default teams, especially agile teams, are single phase process. Agile typically asks teams to focus on tasks that deliver MVP features, and therefore agile typically sets people up to fail, as there is no new feature in good FP without new design, and... and teams often struggles to juggle the three needs to progress design, features and tasks within a same agile effort.

TDD helps

Test driven development (TDD) is one way to escape the limits of a one phase agile process. The idea is the following: 

  1. Given some design features
  2. Develop tests for these features, AND extend the design to cover the features.
  3. Then work on non-design-tasks, that implement the tasks, and pass the tests.

However...

Yet there is still a challenge: design changes most often depend on strong opinions. FP depends on design changes. FP depends on strong opinions. Getting teams to gel around strong opinions is often not trivial. And that why I wrote the statement shared above.

All original content copyright James Litsios, 2024.

No comments: