You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

3.9 KiB

Elegant Functional Programming Application Architecture

In this article I will expose you about how to architect your application using function programming paradigm.

It is not tied to any programming language. The principles in this article could probably be used by most programming languages.

Pre

First note that many functional programming languages are not functional. They all provide holes in order to trick the system to be faster. Also for internal use, some advanced feature might be provided.

  1. Type-classes ; this is not something I consider belongs to functional programming.

  2. Clojure Protocols, defmulti ; are not something I would consider belongs to functional programming.

And many other languages features. Let be radical functional programmer.

Radical, means going back to the roots.

So here we go. Functional programming is about manipulating functions with the meaning of mathematical functions not what most programming language call functions. A "function" in C, Clojure, Python, Java, Javascript is not a function in the functional programming sense. OTOH in Haskell it is often a real function, but not always.

So a mathematical function is something that takes a bunch of parameters and return a value (or not, we should allow partial functions unfortunately). And if you provide the same parameter twice the result will always be the same. Also, it should not have any side effect, for example, it should log, emit sounds, … nothing.

Whoa whoa… Give me a minute here. Why would we want to … do nothing at all? Isn't writing an application about doing things? Yes, it is.

Let just say, that, you generally, don't need more than plunging a pure function graph into a context where an interpreter will be able to use and this big pile of pure functions will be used to have side effect. A big ball of pure functions are reproducible, easy to test, easy to analyze and reason about. Easy to expose business logic out of technical detail to access data, etc…

So I will provide a system as radical, and simple as possible that will have a lot of good properties that advanced functional programming methods (like Monad, Monads transformers, Free Monads, Effect systems) are trying to achieve.

The Architecture

The main architecture is based on the Service paradigm. A service will be a sub-application living at runtime, it will depends on other services, and have an internal state.

So in the end your application should look like an acyclic graph of services.

Every service has an init phase, then a living phase, then a stop phase. Every service declare a set of methods to be used and every service will keep an internal implicit state.

Even if this look a lot like Object oriented programming. It is in fact a quite radical functional programming architecture.

(def Interface
  (function-1 [arg-1 arg-2] "a function"))

;; Main implementation of /my-service/
(defservice my-service
  Interface
  [sub-service-1
   sub-service-2
   ,,,
   sub-service-n]
  (init [initial-ctx]
        (let [service-state
              (core/init {:sub-service-1 sub-service-1 ,,,})]
          (into initial-ctx service-state)))

  (function-1 [ctx arg-1 arg-2]
              (core/function-1 ctx arg-1 arg-2)))

;; A test implementation of /my-service/
(defservice my-test-service
  Interface
  [sub-service-1
   sub-service-2
   ,,,
   sub-service-n]
  (init [initial-ctx]
        (let [service-state
              (test/init {:sub-service-1 sub-service-1 ,,,})]
          (into initial-ctx service-state)))

  (function-1 [ctx arg-1 arg-2]
              (test/function-1 ctx arg-1 arg-2)))