12 years back when I started my formal classes in computer science, the first thing I learned was “data” “information”. A few days after this, we started conventional programming, where code and data were processed separately. For example, only data can be passed on as functional arguments. It was hard for me to digest the “code which is also information is not treated as data”. I felt strongly that this will increase the complexity of software in the long run.
A system does three things – read, transform (process data), write. In other words – the math (the transform part) and the effect of it in real life (the read / write part). The data transformation is actually a mathematical concept, and through reading and writing we make the mathematics (transformation part) useful for the real world. Bringing the “transform” part completely within the mathematical domain has its own advantage of using mathematics without fear (possible errors) to analyze the system, making the system more intriguing mathematically. The catch is to treat both the elements of transformations, data and functions equally.
Originally, the code was previously larger than the data, so it was possible to send data over the cord. But over time, data becomes huge, sending code to systems over the wire becomes the need, resting the data on the systems intact. With big data, the need of the hour is to treat the code as data, so the code can be taken as an argument to another meta function on a system of huge data expecting an algorithm for transformations.
Roughly speaking, codes are algorithms, algorithms are mathematical functions, in turn functions are actually lookup tables, ie. data. Therefore, all codes or functions are data with this principle. This is exactly the cornerstone of the functional paradigm. Functional programming programs with functions, they process functions and data in the same way. Another principle I love for controlling complexity is that rules should not be complex per se.
Thumb rules rewritten into the functional paradigm:
Read-writing and transformations (algorithms) must be separate.
Use unchangeable variables. Discourages use of deferral statements.
Discuss side effects (input / output or change of any variable on the site), each function should return its expected result ONLY.
Use referring transparent features (sometimes called pure functions) without side effects, ie if x = y, then f (x) and f (y) must be eternal.
Unit testing is a must for every function.
One of the most important design patterns to follow is to use expressions instead of instructions, ie. it must be declarative. Discourage the use of loops as for / while – use recursive statements as shown above to calculate the sum. Tell computers what to do, not how to do it – it reduces errors, especially edge cases.
With the need to control the complexity of the system and the prior design, the design pattern of the functional composition can be made to follow some basic algebraic structures, which in turn become more robust.