| Forewords |
|
xiii | |
| Preface |
|
xvii | |
| Acknowledgments |
|
xviii | |
| About This Book |
|
xx | |
| About The Author |
|
xxiv | |
| About The Cover Illustration |
|
xxv | |
| Dramatis Personae |
|
xxvi | |
| Part 1 Flexibility |
|
1 | (136) |
|
1 Complexity of object-oriented programming |
|
|
3 | (23) |
|
1.1 OOP design: Classic or classical? |
|
|
4 | (9) |
|
|
|
4 | (2) |
|
|
|
6 | (3) |
|
Explaining each piece of the class diagram |
|
|
9 | (3) |
|
|
|
12 | (1) |
|
1.2 Sources of complexity |
|
|
13 | (13) |
|
Many relations between classes |
|
|
14 | (2) |
|
Unpredictable code behavior |
|
|
16 | (2) |
|
Not trivial data serialization |
|
|
18 | (2) |
|
Complex class hierarchies |
|
|
20 | (6) |
|
2 Separation between code and data |
|
|
26 | (17) |
|
2.1 The two parts of a DOP system |
|
|
27 | (2) |
|
|
|
29 | (2) |
|
|
|
31 | (5) |
|
2.4 DOP systems are easy to understand |
|
|
36 | (2) |
|
2.5 DOP systems are flexible |
|
|
38 | (5) |
|
3 Basic data manipulation |
|
|
43 | (28) |
|
3.1 Designing a data model |
|
|
44 | (4) |
|
3.2 Representing records as maps |
|
|
48 | (6) |
|
3.3 Manipulating data with generic functions |
|
|
54 | (4) |
|
3.4 Calculating search results |
|
|
58 | (7) |
|
3.5 Handling records of different types |
|
|
65 | (6) |
|
|
|
71 | (20) |
|
4.1 Multiple versions of the system data |
|
|
72 | (2) |
|
|
|
74 | (6) |
|
4.3 Implementing structural sharing |
|
|
80 | (2) |
|
|
|
82 | (1) |
|
4.5 The commit phase of a mutation |
|
|
83 | (2) |
|
4.6 Ensuring system state integrity |
|
|
85 | (1) |
|
4.7 Restoring previous states |
|
|
86 | (5) |
|
5 Basic concurrency control |
|
|
91 | (19) |
|
5.1 Optimistic concurrency control |
|
|
92 | (2) |
|
5.2 Reconciliation between concurrent mutations |
|
|
94 | (3) |
|
|
|
97 | (2) |
|
5.4 Structural difference |
|
|
99 | (7) |
|
5.5 Implementing the reconciliation algorithm |
|
|
106 | (4) |
|
|
|
110 | (27) |
|
6.1 The simplicity of data-oriented test cases |
|
|
110 | (2) |
|
6.2 Unit tests for data manipulation code |
|
|
112 | (9) |
|
The tree of function calls |
|
|
113 | (2) |
|
Unit tests for functions down the tree |
|
|
115 | (4) |
|
Unit tests for nodes in the tree |
|
|
119 | (2) |
|
6.3 Unit tests for queries |
|
|
121 | (5) |
|
6.4 Unit tests for mutations |
|
|
126 | (11) |
| Part 2 Scalability |
|
137 | (108) |
|
|
|
141 | (22) |
|
7.1 Data validation in DOP |
|
|
142 | (1) |
|
7.2 JSON Schema in a nutshell |
|
|
143 | (6) |
|
7.3 Schema flexibility and strictness |
|
|
149 | (5) |
|
|
|
154 | (4) |
|
7.5 Details about data validation failures |
|
|
158 | (5) |
|
8 Advanced concurrency control |
|
|
163 | (12) |
|
8.1 The complexity of locks |
|
|
164 | (1) |
|
8.2 Thread-safe counter with atoms |
|
|
165 | (5) |
|
8.3 Thread-safe cache with atoms |
|
|
170 | (2) |
|
8.4 State management with atoms |
|
|
172 | (3) |
|
9 Persistent data structures |
|
|
175 | (13) |
|
9.1 The need for persistent data structures |
|
|
175 | (3) |
|
9.2 The efficiency of persistent data structures |
|
|
178 | (6) |
|
9.3 Persistent data structures libraries |
|
|
184 | (4) |
|
Persistent data structures in Java |
|
|
184 | (2) |
|
Persistent data structures in JavaScript |
|
|
186 | (2) |
|
9.4 Persistent data structures in action |
|
|
188 | (1) |
|
10 Writing queries with persistent data structures |
|
|
188 | (32) |
|
Writing mutations with persistent data structures |
|
|
191 | (1) |
|
Serialization and deserialization |
|
|
192 | (1) |
|
|
|
193 | (4) |
|
|
|
197 | (1) |
|
10.1 Fetching data from the database |
|
|
198 | (6) |
|
10.2 Storing data in the database |
|
|
204 | (3) |
|
10.3 Simple data manipulation |
|
|
207 | (4) |
|
10.4 Advanced data manipulation |
|
|
211 | (9) |
|
|
|
220 | (25) |
|
11.1 Another feature request |
|
|
221 | (1) |
|
11.2 Building the insides like the outsides |
|
|
222 | (3) |
|
11.3 Representing a client request as a map |
|
|
225 | (2) |
|
11.4 Representing a server response as a map |
|
|
227 | (4) |
|
11.5 Passing information forward |
|
|
231 | (3) |
|
11.6 Search result enrichment in action |
|
|
234 | (11) |
| Part 3 Maintainability |
|
245 | (88) |
|
12 Advanced data validation |
|
|
247 | (25) |
|
12.1 Function arguments validation |
|
|
248 | (7) |
|
12.2 Return value validation |
|
|
255 | (2) |
|
12.3 Advanced data validation |
|
|
257 | (3) |
|
12.4 Automatic generation of data model diagrams |
|
|
260 | (2) |
|
12.5 Automatic generation of schema-based unit tests |
|
|
262 | (7) |
|
|
|
269 | (3) |
|
|
|
272 | (23) |
|
13.1 The essence of polymorphism |
|
|
273 | (4) |
|
13.2 Multimethods with single dispatch |
|
|
277 | (4) |
|
13.3 Multimethods with multiple dispatch |
|
|
281 | (5) |
|
13.4 Multimethods with dynamic dispatch |
|
|
286 | (3) |
|
13.5 Integrating multimethods in a production system |
|
|
289 | (6) |
|
14 Advanced data manipulation |
|
|
295 | (16) |
|
14.1 Updating a value in a map with eloquence |
|
|
296 | (3) |
|
14.2 Manipulating nested data |
|
|
299 | (2) |
|
14.3 Using the best tool for the job |
|
|
301 | (4) |
|
|
|
305 | (6) |
|
|
|
311 | (22) |
|
15.1 Determinism in programming |
|
|
312 | (2) |
|
15.2 Reproducibility with numbers and strings |
|
|
314 | (4) |
|
15.3 Reproducibility with any data |
|
|
318 | (3) |
|
|
|
321 | (8) |
|
15.5 Dealing with external data sources |
|
|
329 | (4) |
| Appendix A Principles of data-oriented programming |
|
333 | (31) |
| Appendix B Generic data access in statically-typed languages |
|
364 | (17) |
| Appendix C Data-oriented programming: A link in the chain of programming paradigms |
|
381 | (6) |
| Appendix D Lodash reference |
|
387 | (4) |
| Index |
|
391 | |