Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ


Choose your language

InfoQ Homepage News Late Architecture with Functional Programming

Late Architecture with Functional Programming

This item in japanese

Many approaches to software architecture assume that the architecture is planned at the beginning. Unfortunately, architecture planned in this way is hard to change later. Functional programming can help achieve loose coupling to the point that advance planning can be kept to a minimum, and architectural decisions can be changed later.

Michael Sperber spoke about software architecture and functional programming at OOP 2023 Digital.

Sperber gave the example of dividing up the system’s code among its building blocks. This is a particularly important kind of architectural decision to work on different building blocks separately, possibly with different teams. One way to do this is to use Domain-Driven Design (DDD) for the coarse-grain building blocks - bounded contexts:

DDD says you should identify bounded contexts via context mapping - at the beginning. However, if you get the boundaries between the contexts wrong, you lose a lot of the benefits. And you will get them wrong, at least slightly - and then it’s hard to move them later.

According to Sperber, functional programming enables late architecture and reduces coupling compared to OOP. In order to defer macroarchitecture decisions, we must always decouple, Sperber argued. Components in functional programming are essentially just data types and functions, and these functions work without mutable state, he said. This makes dependencies explicit and coupling significantly looser than with typical OO components. This in turn enables us to build functionality that is independent of the macroarchitecture, Sperber said.

Sperber made clear that functional programming isn’t "just like OOP only without mutable state". It comes with its own methods and culture for domain modelling, abstraction, and software construction. You can get some of the benefits just by adopting immutability in your OO project. To get all of them, you need to dive deeper, and use a proper functional language, as Sperber explained:

Functional architecture makes extensive use of advanced abstraction, to implement reusable components, and, more importantly, supple domain models that anticipate the future. In exploring and developing these domain models, functional programmers frequently make use of the rich vocabulary provided by mathematics. The resulting abstractions are fundamentally enabled by the advanced abstraction facilities offered by functional languages.

InfoQ interviewed Michael Sperber about how our current toolbox of architectural techniques predisposes us to bad decisions that are hard to undo later, and what to do about this problem.

InfoQ: What are the challenges of defining the macroarchitecture at the start of a project?

Michael Sperber: A popular definition of software architecture is that it’s the decisions that are hard to change later. Doing this at the beginning means doing it when you have the least information. Consequently, there’s a good chance the decisions are wrong.

InfoQ: What makes it so hard to move boundaries between contexts?

Sperber: It seems in the architecture community we have forgotten how to achieve modularity within a bounded context or a monolith, which is why there’s this new term "modulith", implying that a regular monolith is non-modular by default and that its internals are tightly coupled.

InfoQ: So you’re saying we don’t know how to achieve loose coupling within a monolith?

Sperber: Yes. This is because the foundation of OO architecture is programming with mutable state i.e. changing your objects in place. These state changes make for invisible dependencies that are hard to see and that tangle up your building blocks. This does not just affect the functional aspects of a project, but also other quality goals.

InfoQ: Can you give an example?

Sperber: Let’s say you choose parallelism as a tactic to achieve high performance: You need to choose aggregate roots, and protect access to those roots with mutual exclusion. This is tedious work, error-prone, hard to make fast, and increases coupling dramatically.

InfoQ: What’s your advice to architects and developers if they want to improve the way that they take architectural decisions?

Sperber: Even if you can’t use a functional language in your project, play with the basics of functional programming to get a feel for the differences and opportunities there. If you’re new to FP, I recommend the How to Design Programs approach to get you started - or DeinProgramm for German speakers.

There are also two books on software construction with functional programming:

About the Author

Rate this Article