Functional Software Architecture

Functional programming in the large

Functional Software Architecturerefers to methods of construction and structure of large and long-lived software projects that are implemented in functional languages and released to real users, typically in industry.

We strive for ...

Simplicity

Problem domains are complex enough. The solutions we build should be as simple as possible.

Domain Insight

Software development is about running software just as much as it is about gaining insight into a domain.

Maintainability

Maintainability and malleability fundamentally enable the software creation process.

Correctness

We value software being correct both in the small and in the large.

Performance

Software has to be both correct and fast. If software were not fast, computers would be obsolete.

Principles

We strive for the values described above. We do so by following this set of principles.

Immutability

Stop thinking in terms of state and resource management and start thinking in terms of your domain.

→ More

Pure Functions

A pure function transforms immutable values without performing any side effects.

→ More

Everything as a Value

Reifying concepts as values allows these concepts to be passed around, analyzed and composed. Functions as values, property accessors as values, UI components as values ...

→ More

Composition and Closure

We like to combine small software structures to form larger structures – without cognitive overhead.

→ More

Algebraic Modelling

Functional software architects try to find models that build on algebraic structures that stood the test of time, such as Monoids, Functors, and Monads.

→ More

Airtight Abstractions

Abstraction is the sharpest weapon of reason. Functional software architects welcome abstraction as a tool for coping with complexity.

→ More

Architecture as Code

Functional Software Architecture allows many architectural decisions to be expressed in code. We may still use diagrams and descriptions as supporting documentation, but the source of truth is always to be found in the code.

→ More

Decoupled by Default

Make the communication channels between building blocks as wide as neccessary and as narrow as possible. Build tools with affordances toward low coupling and high cohesion.

→ More

Late Decision Making

Software design is usually performed under uncertainty. Instead of trying to make the right decisions up front, we want to design our systems in such a way that it is easy to change our minds later in the process. This shifts our focus from making decisions to making decisions possible.

→ More

Modularization

Modules hide difficult decisions behind simple interfaces. While modularization is not an exclusive feature of functional architectures, functional abstractions allow for simpler interfaces and therefore allow to hide more decisions, leading to more malleable designs overall.

→ More

Make Illegal States Unrepresentable

«Make illegal states unrepresentable» is a functional design technique that leverages product and sum types to decrease the bug surface of your software.

→ More

Patterns, Tools, and Techniques

We follow the principles described above by employing some of the following techniques.

Functional Core, Imperative Shell

Structure software into functions in the core that are pure and functions in the shell that are impure.

→ More

Zipper

TODO

→ More

Continuations

TODO

→ More

Use of functional programming languages

Functional software architecture is best done in proper functional programming languages.

→ More

Expressive static type systems

Type systems allow you to enrich your code with descriptions of properties and requirements, which can be statically checked and enforced.

→ More

Event Sourcing

TODO

→ More

Bidirectional Data Transformations

Different components of a system may need the same information but may have different demands on its structure. We employ bidirectional data transformations with functional optics to simplify conversions from one representation to the next.

→ More

Embedded Domain-Specific Languages

TODO

→ More

Composable Effects

Effect systems allow us to deal with effects by making them explicit. Effect systems also allow effectful code to be run in a pure environment, which makes our code better testable.

→ More

Composable Error Handling

Handle errors in a way that they can be composed, combined, and passed through different parts of your program predictably.

→ More

Composable GUI libraries

Facebook’s React popularized the component model of user interface programming. Functional programming languages allow to improve on that model by treating components as composable first-class user interfaces. Functional UI libraries provide a set of primitive components and a set of UI combinators, which let you build sophisticated graphical user interfaces without cognitive overhead.

→ More

Property-based testing

TODO

→ More

Formal Verification

TODO

→ More

Denotational Design

Denotational Design is a software design methodology which tries to extract the essence of a domain’s problem and describe it formally in machine-checkable code. Denotational design affords software designers to be absolutely precise in what they want to achieve before they talk about how they plan to achieve it. Denotational Design informs both the use and the implementation of a unit of software without coupling them. Denotational Design is therefore a methodology to build airtight abstraction barriers.

→ More

Parse, don’t validate

«Parse, don’t validate» is a simple mnemonic for type-driven design.

→ More

Trees that grow

«Trees that grow» is a method to make models built with algebraic data types more extensible.

→ More

Data types à la carte

«Data types à la carte» is a technique to deal with the dreaded Expression Problem in functional languages.

→ More

Smart constructor

A smart constructor semantically behaves like any ordinary constructor, but it performs some useful computations such as preprocessing, normalization, parsing, or validation.

→ More

Correctness by Construction

TODO

→ More

Frequently Asked Questions

Is there a class of domains where Functional Software Architecture works exceptionally well? Is there a class of domains where Functional Software Architecture fails?

No (TODO)

External systems usually don't follow FSA principles. How do you interface with them?

TODO