A Journey into Extensible Effects in Scala
This article is an introduction to using the Scala
Eff library, which is an implementation of Extensible Effects. This library is now under the Typelevel umbrella, which means it integrates well with popular functional programming libraries in Scala like Cats and Monix. I will not touch on the theoretical side of the concept in this post. Instead, I will be using code snippets to describe how you would introduce it to an existing Scala code base. This should hopefully improve extensibility and maintainability of the code. As part of this, I will demonstrate how to build a purely functional program in Scala using concepts such as
In this blog post, I'm going to provide a very simple explanation for Applicatives (aka "Applicative Functors") just the way I know them. I'm not going to cover the math behind it, or the laws which applicatives must obey.
I've taken a reverse approach compared to many other posts explaining Applicatives: rather than starting with what Applicatives are, I'm going to start with some examples to demonstrate the need for them, then I'll show how Applicatives can be used and at the end, I'll briefly cover how they can be implemented. Continue reading
Author’s note: this isn’t an argument against Futures, there’s nothing wrong with them as such! This article is about good abstraction and proper separation of concerns when using them.
The aims of functional programming are much the same as any other discipline of software engineering: modularity, abstraction, low coupling, high cohesion, and so on. While the techniques and terminology are often new to developers, the goals and benefits are expressible in very familiar language — because it’s all software, and we’re trying to achieve the same thing! (Read SICP for more background on software engineering fundamentals expressed with functional ideas).
Recently, we refactored one of our micro-services in order to apply the Each library. Each is a macro library developed by Thoughtworks that converts native imperative syntax to scalaz‘s monadic expressions. This means that we can write, among other things, asynchronous code with Futures in a plain imperative style.
The micro-service is a Scala application that serves as a RESTful server. It receives requests from browsers. For each of the requests, the micro-service fetches data from other internal RESTful servers, composites these data into one response, and sends the response to browsers.
As previously discussed we’re pretty keen on micro services at REA. Our delivery teams are organised around small, autonomous “squads” that get to choose pretty much any language and technology stack they wish to implement their solutions.
This inevitably leads to a fairly broad church of language use. 🙂
Please don’t use mocks or stubs in tests. While they are seemingly ubiquitous in enterprise development, they have serious drawbacks, and typically mask easily fixable deficiencies in the underlying code.
Even their most ardent defenders concede that mocks and stubs have flaws. These include:
Dependence on fragile implementation details
Mocks and stubs require intimate knowledge of how code interacts with other modules. Even if the implementation is correctly refactored without altering public contracts, these tests will tend to break, and draw your attention away from more productive tasks.
Testing incidental properties with no bearing on correctness
What is the point of this code? This is an essential question to ask, in order to understand it. Tests have a story to tell here, and mocks invariably tell the wrong one. Is the point of makeCoffee() that we made a coffee, or that we opened the fridge to get the milk? When we payShopkeeper(), do we care that we completed a transaction, or that we rummaged though our wallet for change? When mocking tests fail, the poor maintainer is left to reconstruct the real intent from a trail of indirect clues and anecdotes.
Web of lies
It is good practice to write data structures that are correct-by-construction; any constructor or sequence of method calls is guaranteed to leave the data in a meaningful state. Stubs introduce test-only fictions that are stripped of any of the safety latches and guarantees that may have been built in; they introduce fresh sources of error that are not present in the codebase. There is no value in detecting any failure that arises in such a way.
As time goes on, lies beget more lies. It is not unusual for a stubbed input in one place to result in another here, and another there; the fiction leaks and spreads into some kind of evil facsimile of the original code, but with more bulk, complexity and defects.