Functional programming concepts that can be used in any language for simplicity and automated tests
I want to share my recent insights after studying a few different functional languages. If you find yourself with some or all of those questions, this is an article for you to read.
1- When should I create a new function?
2- How can I write simple functions that are easily testable?
3- How can my code increase in size without increase in complexity?
Now let's see this example "ideal code":
jsonPath = getJsonPath()
now = getDate()
config = getConfig(jsonPath, now)
news = getNews(config)
config = updateConfig(config, now, news)
news = updateNews(news)
errors = postNews(news)
saveConfig(jsonPath, config)
showErrors(errors)
Notice that there are a few important points:
1- The emphasis of the code is on WHAT is being done, not how. The how is deferred to the functions, but the "orchestrator" doesn't know about how, just knows about what.
2- There is a separation between functions that:
A) Retrieve/obtain data: getJsonPath, getDate, getConfig, getNews
B) Transform data (or calculations): updateConfig, updateNews
C) Generate side effects: postNews, saveConfig, showErrors
3- There is no especial functional resources like currying, high order functions, etc.
The concept of orchestrator is interesting and depends on the context of the code being invoked. Whenever a event starts a code execution, or a controller from MVC pattern is called, or a "main" function starts, we have an orchestrator that should focus on the what, not the how.
Ideally all the functions should be testable, either using mocking or dependency injection, but none of the orchestrators should be tested.
Intensive side effect code like the UI rendering is very hard to test and is the main exception to this rule.
I know this is very simple, but by following these simple rules I could answer all the questions in the beginning of this post:
1- I use a new function whenever I had to get data, transform data (or calculations over data), or generate a side effect.
2- I write functions that have one of those 3 responsibilities and even better a single of these responsibilities. Ideally a function does a single data loading or transformation or side effect.
3- By having the orchestrators simplified by focusing on WHAT, and functions simplified by focusing on a single task, the code doesn't increase in complexity as it increases in size.
It was hard for me to understand the most important development principle: single responsibility. But once I grasped the distinction between data load, transformations, and effects it was easy to apply this principle to my code and start creating more testable functions.
In OO we should apply same ideas. Each method of the object should respect the single responsibility principle and the orchestrator can use the object methods in a similar way.
Good luck with your coding!
Comments
Post a Comment