Functional declarative design (FDD) is a practical, end-to-end methodology for designing applications in statically typed functional languages. It supplies a reasoning framework—comparable in scope to object-oriented design—for turning requirements and domain models into architecture, abstractions, patterns, and code structures while controlling accidental complexity. section 1.0 section 1.6
Its central aim is declarative thinking: describe what the system should achieve through functional abstractions rather than organize behavior around imperative updates or object-oriented structure. This does not erase general design concerns; modularity, interfaces, inversion of control, low coupling, cohesion, requirements work, and architecture remain important ways to divide a difficult system into understandable parts. section 1.6 section 2.3
A typical FDD design cycle works from broad decisions toward implementation:
- Collect and organize requirements, using questions, user scenarios, mind maps, or use case diagrams where they help investigate the domain. section 2.3 section 1.3
- Start with a high-level function or problem-to-solution boundary, then separate the architecture into subsystems before writing detailed code. section 2.1.3
- Return to diagrams and architectural decisions iteratively as requirements, risks, and implementation details become clearer. section 2.1.3
- Hide diverse native or low-level interfaces behind abstractions so application code stays concise, testable, and less coupled to device-specific details. section 1.3
Layering gives those decisions a structural home. FDD distinguishes application concerns such as configuration and logging; service interfaces; persistence abstractions; presentation; a domain-model layer expressed with data types and DSLs; and interoperability for communication details. The domain-model layer is intended to be completely pure, while persistence can be pure or impure depending on its abstraction level. section 2.2.1
Mapping through nested structure
A small functional example illustrates the style of abstraction FDD relies on. Mapping `length` across a list of names produces lengths; when each name becomes optional, mapping twice—once for the list and once for `Maybe`—preserves missing values without manually recursing through either structure. Recognizing shared properties such as `Functor` replaces special-purpose traversal with reusable operations. section 1.3.3
FDD is not presented as the only possible functional design philosophy. Its value is a consistent vocabulary and baseline for making conscious trade-offs across applications ranging from command-line tools and web services to critical software, games, business systems, and reactive simulators. It seeks designs that reduce risk and maintenance cost without pretending that essential domain complexity can simply be removed. section 2.0 section 1.0 section 1.3
Figure 2.8 Iterative architecture design process in FDD
Use the iterative architecture design process diagram to connect requirements, high-level structure, implementation descent, and revision loops. section 2.1.3
