12 Functional design for concurrent systems

 

This chapter covers

  • Splitting the software into isolated components
  • Treating messages as streams of data
  • Transforming reactive streams
  • Using stateful software components
  • Benefits of reactive streams in concurrent and distributed system design

The biggest problem in software development is handling complexity. Software systems tend to grow significantly over time and quickly outgrow original designs. When the features we need implement collide with the design, we must either reimplement significant portions of the system or introduce horrible quick-and-dirty hacks to make things work.

This problem with complexity becomes more evident in software that has different parts executing concurrently—from the simplest interactive user applications to network services and distributed software systems.

A large fraction of the flaws in software development are due to programmers not fully understanding all the possible states their code may execute in. In a multithreaded environment, the lack of understanding and the resulting problems are greatly amplified, almost to the point of panic if you are paying attention.

—John Carmack1 

1 John Carmack, “In-Depth: Functional Programming in C++,” #altdevblogaday, April 30, 2012, reprinted on Gamasutra, http://mng.bz/OAzP.

12.1 The actor model: Thinking in components

12.2 Creating a simple message source

12.3 Modeling reactive streams as monads

12.3.1 Creating a sink to receive messages

12.3.2 Transforming reactive streams

12.3.3 Creating a stream of given values

12.3.4 Joining a stream of streams

12.4 Filtering reactive streams

12.5 Error handling in reactive streams

12.6 Replying to the client

12.7 Creating actors with a mutable state

12.8 Writing distributed systems with actors

Summary