
This book was conceived as a comprehensive guide to reactive systems, which will help to understand and design them. Therefore, it discusses not only the manifest of reactive programming, but also the reasons that led to its appearance. The main body of the book is a collection of design patterns that embody many aspects of the reactive architecture. This provides references to in-depth material for further study. And although the presented templates are a single whole, their list is not complete - it cannot be such. However, the general information contained in the book will allow the reader to identify, isolate and develop new templates, if necessary.
Who is this book for?
The book was created for all who are interested in the implementation of jet systems.
- It covers the architecture of such systems and the philosophy behind it, providing designers with a list of characteristics that reactive applications and their components should have, and describing the possibilities of using various templates.
- Practicing programmers will appreciate a detailed discussion of the tasks that each of the templates solves, the steps to apply them (illustrated with full source code), and instructions for porting and adapting the template to different scenarios.
- Students who wish to deepen their knowledge (for example, after watching a course of lectures on the principles of reactive programming), will be able to get acquainted with how the reactive principles were derived, and continue their study using references to other literature.
The book does not require prior acquaintance with jet systems, it is based on well-known general principles of development and refers to the experience of solving certain problems inherent in distributed applications. In some cases, you may need a basic understanding of functional programming — that part of it that is related to immutable values ​​and pure functions, but we have bypassed category theory.
The need for reactive design patterns
Many of the above solutions and most of the source problems are not new. The separation of the architecture of different components of the program is one of the tasks of computer science since its inception and has been discussed in technical literature since the publication of the famous book Design Patterns 1. As computers penetrated everyday life, programming began to receive well-deserved attention from society and turned from art practiced by scientists, and later by young fanatics in garages, into a mass applied craft. The growth of the total number of computer systems installed over the past two decades led to the formalization of design, and at the same time determined a set of recommended methods and expanded the number of developed areas. In 2003, the book “Enterprise Application Integration Templates” 2 was published, which considers the exchange of messages between components and defines the patterns of interaction and message processing, which, for example, are implemented in the Apache Camel project. The next step was called service-oriented architecture (SOA).
')
As you read through this chapter, you will encounter elements of the previous stages, such as services and focus on message passing. In this regard, a natural question arises: what can this book offer that has not been discussed in detail earlier in other publications? Particularly interesting is the comparison with the definition of SOA, which is given in Arnon Rotem-Gal-Oz's book SOA Patterns (SOA Patterns. - Manning, 2012): “Service-Oriented Architecture (SOA) is a design style for building interoperable systems loosely coupled, generic and autonomous components called “services”. Each service uses to provide processes and behavior contracts consisting of messages that can be detected at specified addresses (endpoints). The behavior of the service is determined by the rules that are defined outside of it. Contracts and messages are used by external components, called service consumers. ”
This definition refers to the high-level architecture of the application, as indicated by the requirement of generalization of the structure of services. This is because the SOA methodology approaches the problem in terms of business requirements and an abstract software architecture, which, no doubt, is useful. But, as we have already argued, for technical reasons, services are becoming smaller and require that manual simulation of the exchange of messages, which is the basis of the basic system, replaces such abstractions as synchronous blocking network interaction.
Complexity management
Increasing the level of abstraction proved to be the most effective way to improve the productivity of programmers. Opening up access to internal details may seem like a step backwards, since abstraction usually involves hiding complexities from view. However, one should not forget that complexity is of two types:
• integral, inherent in the subject area;
• side, created solely by the decision.
Returning to the example of using a traditional transactional database as a repository for joint editing of documents, it can be said, ACID transactions are trying to hide the complexity present in the area of ​​network computing systems, but they introduce additional complexity, requiring the programmer to solve the problems with performance and scaling.
Adequate solution leaves the inherent complexity of the domain, allowing you to cope with it as required by the specific situation, and does not burden the user with side problems that are the result of the inconsistency of the chosen abstraction and internal implementation.
This means that as your understanding of the subject area evolves (for example, you may see the need for distributed computing at a lower level than before), you have to revise the existing abstractions in terms of integral coverage and add-on side complexity. The result will be the application of solutions that may affect the choice of characteristics that need abstraction and pull out. One example of this is the design of reactive services, which makes obsolete concepts such as synchronous, strictly coordinated linking of components. The corresponding reduction in the level of abstraction is compensated by the definition of new abstractions and patterns, which is akin to shifting building blocks on top of the re-planned foundation.
A new foundation is a messaging orientation, and to build a large-scale application on top of it, you need the right tools. The templates discussed in Part III are a combination of comfortable time-tested techniques, such as the “fuse” pattern, and recent concepts arising from the use of the actor model. But the design pattern is not just a description of the prototype of the solution, it is characterized by a problem that is solved with its help, and this is more important. Thus, the main objective of this book is to discuss reactive design patterns in the light of the four principles of the reactive programming manifest.
Making programming models closer to the real world
A final comment about reactive programming refers to areas that have already been covered in previous sections. You already know that the desire to create autonomous software instances that provide fast and reliable services to their users has led to the creation of an architecture that underlies encapsulated, independently executed computing modules. The compartments separated by bulkheads form isolated spaces for services that interact exclusively with messages made in a high-level language.
These architectural restrictions were taken from the real world and from our society: people also cooperate to work on something large-scale - each person performs a separate task independently, communicating with colleagues in a high-level language. This allows you to visualize abstract software concepts using familiar, familiar images. Design can begin with the question: “How would I do it using the example of a human team?” Software development has been an extremely young area compared to the organization of work in society over the last millennium, but we can use the knowledge already acquired to facilitate the task of partitioning systems modules compatible with the principles of distributed autonomous implementation.
Of course, one should not abuse anthropomorphism: terminology such as master / slave (literally “master / slave”) gradually disappears from everyday life, since its interpretation does not always take the technical context into account. But even the responsible use of such metaphors can give piquancy to potentially boring work: for example, the component responsible for saving journal entries to disk can be called Scribe (Russian clerk). The implementation of this class will give you the feeling that you are creating a small robot that will execute your commands and with whom you can play a little - someone calls this occupation writing tests, pronouncing this phrase with a sour face. Reactive programming allows you to look at it from the other side and realize: it's fun!
»More information about the book can be found on
the publisher's website.»
Table of Contents»
ExcerptFor Habrozhiteley a 20% discount on the coupon -
Reactive Design Patterns