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 ...
Problem domains are complex enough. The solutions we build should be as simple as possible.
Software development is about running software just as much as it is about gaining insight into a domain.
Maintainability and malleability fundamentally enable the software creation process.
We value software being correct both in the small and in the large.
Software has to be both correct and fast. If software were not fast, computers would be obsolete.
We strive for the values described above. We do so by following this set of principles.
Stop thinking in terms of state and resource management and start thinking in terms of your domain.
→ MoreA pure function transforms immutable values without performing any side effects.
→ MoreReifying concepts as values allows these concepts to be passed around, analyzed and composed. Functions as values, property accessors as values, UI components as values ...
→ MoreWe like to combine small software structures to form larger structures – without cognitive overhead.
→ MoreFunctional software architects try to find models that build on algebraic structures that stood the test of time, such as Monoids, Functors, and Monads.
→ MoreAbstraction is the sharpest weapon of reason. Functional software architects welcome abstraction as a tool for coping with complexity.
→ MoreFunctional 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.
→ MoreMake 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.
→ MoreSoftware 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.
→ MoreModules 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» is a functional design technique that leverages product and sum types to decrease the bug surface of your software.
→ MoreWe follow the principles described above by employing some of the following techniques.
Structure software into functions in the core that are pure and functions in the shell that are impure.
→ MoreFunctional software architecture is best done in proper functional programming languages.
→ MoreType systems allow you to enrich your code with descriptions of properties and requirements, which can be statically checked and enforced.
→ MoreDifferent 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.
→ MoreEffect 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.
→ MoreHandle errors in a way that they can be composed, combined, and passed through different parts of your program predictably.
→ MoreFacebook’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.
→ MoreDenotational 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«Trees that grow» is a method to make models built with algebraic data types more extensible.
→ More«Data types à la carte» is a technique to deal with the dreaded Expression Problem in functional languages.
→ MoreA smart constructor semantically behaves like any ordinary constructor, but it performs some useful computations such as preprocessing, normalization, parsing, or validation.
→ MoreNo (TODO)
TODO