This chapter introduction previews the topics and perspective the chapter will cover.
1.1 What is functional programming? · 1.2 The problems with the definition for practical use · 1.3 Problem 1: FP needs side effects · 1.4 Problem 2: FP is good at side effects · 1.5 Problem 3: FP is practical · 1.6 The definition of FP confuses managers · 1.7 We treat functional programming as a set of skills and concepts · 1.8 Distinguishing actions, calculations, and data · 1.9 Functional programmers distinguish code that matters when you call it · 1.10 Functional programmers distinguish inert data from code that does work · 1.11 Functional programmers see actions, calculations, and data · 1.12 Step 1: The user marks a task as completed. · 1.13 Step 2: The client sends a message to the server. · 1.14 Step 3: The server receives the message. · 1.15 Step 4: The server makes a change to its database. · 1.16 Step 5: The server makes a decision of who to notify.** · 1.17 Step 6: The server sends an email notification.** · 1.18 The three categories of code in FP · 1.19 Actions · 1.20 2. Calculations · 1.21 3. Data · 1.23 FP works great for distributed systems, and most software written today is distributed · 1.25 This book is practical for software engineering · 1.26 This book uses real-world scenarios · 1.27 This book focuses on software design · 1.28 This book conveys the richness of FP · 1.29 This book is language agnostic · 1.30 What is functional thinking? · 1.31 Part 1: Distinguishing actions, calculations, and data · 1.32 Part 2: Using first-class abstractions · 1.33 Ground rules for ideas and skills in this book · 1.34 The skills can’t be based on language features · 1.35 2. The skills must have immediate practical benefit · 1.36 3. The skills must apply regardless of your current code situation · 1.37 Conclusion · 1.38 Summary · 1.39 Up next…
This chapter introduction previews a broad tour of functional thinking through real-world examples, stratified design, and timelines.
2.1 Welcome to Toni’s Pizza · 2.2 Part 1: Distinguishing actions, calculations, and data · 2.3 Part 2: Using first-class abstractions · 2.4 Part 1: Distinguishing actions, calculations, and data · 2.5 1. Actions · 2.6 Calculations · 2.7 3. Data · 2.9 A first glimpse of stratified design · 2.11 As applied to a robotic kitchen · 2.12 Timelines visualize distributed systems · 2.13 Multiple timelines can execute in different orderings · 2.15 Toni does a postmortem · 2.16 Cutting the timeline: Making the robots wait for each other · 2.18 Retrospective on coordinating robots · 2.19 Conclusion · 2.20 Summary · 2.21 Up next…
This chapter introduction previews applying the actions, calculations, and data categories to problems and code.
3.1 Actions, calculations, and data · 3.2 Actions, calculations, and data apply to any situation · 3.3 Lessons from our shopping process · 3.4 Applying functional thinking to new code · 3.5 Drawing the coupon email process · 3.6 Implementing the coupon email process · 3.7 Applying functional thinking to existing code · 3.8 Actions spread through code · 3.9 Actions can take many forms · 3.10 Conclusion · 3.11 Summary · 3.12 Up next…
The chapter introduces a planned refactoring of existing software to extract calculations from actions and improve reuse and testability.
4.1 Welcome to MegaMart.com! · 4.2 Calculating free shipping · 4.3 Calculating tax · 4.4 We need to make it more testable · 4.5 We need to make it more reusable · 4.6 Distinguishing actions, calculations, and data · 4.7 Functions have inputs and outputs · 4.8 Testing and reuse relate to inputs and outputs · 4.9 Extracting a calculation from an action · 4.10 Extracting another calculation from an action · 4.11 Let’s see all of our code in one place · 4.12 Conclusion · 4.13 Summary · 4.14 Up next…
The chapter introduces why improving actions means reducing, rather than eliminating, their implicit inputs and outputs.
5.1 Aligning design with business requirements · 5.2 Aligning the function with business requirements · 5.3 Principle: Minimize implicit inputs and outputs · 5.4 Reducing implicit inputs and outputs · 5.5 Giving the code a once-over · 5.6 Categorizing our calculations · 5.7 Principle: Design is about pulling things apart · 5.8 Improving the design by pulling add_item() apart · 5.9 Extracting a copy-on-write pattern · 5.10 Using add_item() · 5.11 Categorizing our calculations · 5.12 Smaller functions and more calculations · 5.13 Conclusion · 5.14 Summary · 5.15 Up next…
Introduces the chapter’s plan to use copy-on-write for arrays, objects, and deeply nested data.
6.1 Can immutability be applied everywhere? · 6.2 Categorizing operations into reads, writes, or both · 6.3 The three steps of the copy-on-write discipline · 6.4 Converting a write to a read with copy-on-write · 6.5 Complete diff from mutating to copy-on-write · 6.6 These copy-on-write operations are generalizable · 6.7 JavaScript arrays at a glance · 6.8 What to do if an operation is a read and a write · 6.9 Splitting a function that does a read and write · 6.10 Returning two values from one function · 6.11 Reads to immutable data structures are calculations · 6.12 Applications have state that changes over time · 6.13 Immutable data structures are fast enough · 6.14 Copy-on-write operations on objects · 6.15 JavaScript objects at a glance · 6.16 Converting nested writes to reads · 6.17 What gets copied? · 6.18 Visualizing shallow copies and structural sharing · 6.19 Conclusion · 6.20 Summary · 6.21 Up next…
The chapter introduces the problem of preserving immutability when copy-on-write code interacts with code that may mutate data.
7.1 Immutability with legacy code · 7.2 Our copy-on-write code has to interact with untrusted code · 7.3 Defensive copying defends the immutable original · 7.4 Implementing defensive copies · 7.5 The rules of defensive copying · 7.6 Wrapping untrusted code · 7.7 Defensive copying you may be familiar with · 7.8 Copy-on-write and defensive copying compared · 7.9 Deep copies are more expensive than shallow copies · 7.10 Implementing deep copy in JavaScript is difficult · 7.11 A dialogue between copy-on-write and defensive copying · 7.12 Conclusion · 7.13 Summary · 7.14 Up next…
The chapter introduces the next part of stratified design, previewing patterns and their relevance to maintenance, testing, and reuse.
9.1 Patterns of stratified design · 9.2 Pattern 2: Abstraction barrier · 9.3 Abstraction barriers hide implementations · 9.4 Ignoring details is symmetrical · 9.5 Swapping the shopping cart’s data structure · 9.6 Re-implementing the shopping cart as an object · 9.7 The abstraction barrier lets us ignore details · 9.8 When to use (and when not to use!) abstraction barriers · 9.9 Pattern 2 Review: Abstraction barrier · 9.10 Our code is more straightforward · 9.11 Pattern 3: Minimal interface · 9.12 Pattern 3 Review: Minimal interface · 9.13 Pattern 4: Comfortable layers · 9.14 Patterns of stratified design · 9.15 What does the graph show us about our code? · 9.16 Code at the top of the graph is easier to change · 9.17 Testing code at the bottom is more important · 9.18 Code at the bottom is more reusable · 9.19 Summary: What the graph shows us about our code · 9.20 Conclusion · 9.21 Summary · 9.22 Up next…
This introduction previews first-class functions and the code smell and refactorings the chapter will teach.
10.1 Code smell: Implicit argument in function name · 10.2 Marketing still needs to coordinate with dev · 10.3 Code smell: Implicit argument in function name · 10.4 Refactoring: Express implicit argument · 10.5 Recognize what is and what isn’t first-class · 10.6 Will field names as strings lead to more bugs? · 10.7 Will first-class fields make the API hard to change? · 10.8 We will use a lot of objects and arrays · 10.9 First-class functions can replace any syntax · 10.10 For loop example: Eating and cleaning up · 10.11 Refactoring: Replace body with callback · 10.12 What is this syntax? · 10.13 Why are we wrapping the code in a function? · 10.14 Conclusion · 10.15 Summary · 10.16 Up next…
The chapter introduces map(), filter(), and reduce() as useful alternatives to for loops over arrays.
12.1 One code smell and two refactorings · 12.2 MegaMart is creating a communications team · 12.3 Deriving map() from examples · 12.4 Functional tool: map() · 12.5 Three ways to pass a function · 12.6 Example: Email addresses of all customers · 12.7 Deriving filter() from examples · 12.8 Functional tool: filter() · 12.9 Example: Customers with zero purchases · 12.10 Deriving reduce() from examples · 12.11 Functional tool: reduce() · 12.12 Example: Concatenating strings · 12.13 Things you can do with reduce() · 12.14 Three functional tools compared · 12.15 Conclusion · 12.16 Summary · 12.17 Up next…
The introduction explains why complex array computations can be expressed as chains of simple functional-tool steps.
13.1 The customer communications team continues · 13.2 Clarifying chains, method 1: Name the steps · 13.3 Clarifying chains, method 2: Naming the callbacks · 13.4 Clarifying chains: Two methods compared · 13.5 Example: Emails of customers who have made one purchase · 13.6 Refactoring existing for loops to functional tools · 13.7 Tip 1: Make data · 13.8 Tip 2: Operate on whole array at once · 13.9 Tip 3: Take many small steps · 13.10 Tip 3: Take many small steps · 13.11 Comparing functional to imperative code · 13.12 Summary of chaining tips · 13.13 Debugging tips for chaining · 13.14 Many other functional tools · 13.15 reduce() for building values · 13.16 Getting creative with data representation · 13.17 Line up those dots · 13.18 Conclusion · 13.19 Summary · 13.20 Up next…
The introduction explains why higher-order tools for object values make immutable updates to deeply nested data less awkward.
14.1 Higher-order functions for values in objects · 14.2 Making the field name explicit · 14.3 Deriving update() · 14.4 Using update() to modify values · 14.5 Refactoring: Replace get, modify, set with update() · 14.6 Functional tool: update() · 14.7 Visualizing values in objects · 14.8 Visualizing nested updates · 14.9 Applying update() to nested data · 14.10 Deriving updateOption() · 14.11 Deriving update2() · 14.12 Visualizing update2() on nested objects · 14.13 Writing incrementSizeByName() four ways · 14.14 Deriving update3() · 14.15 Deriving nestedUpdate() · 14.16 The anatomy of safe recursion · 14.17 Visualizing nestedUpdate() · 14.18 The superpower of recursion · 14.19 Design considerations with deep nesting · 14.20 Abstraction barriers on deeply nested data · 14.21 A summary of our use of higher-order functions · 14.22 Conclusion · 14.23 Summary · 14.24 Up next…
The introduction presents timeline diagrams as a way to see actions over time and reason about bugs, especially in distributed systems.
15.1 There’s a bug! · 15.2 Now we can try to click twice fast · 15.3 The timeline diagram shows what happens over time · 15.4 The two fundamentals of timeline diagrams · 15.5 Two tricky details about the order of actions · 15.6 Drawing the add-to-cart timeline: Step 1 · 15.7 Asynchronous calls require new timelines · 15.8 Different languages, different threading models · 15.9 Building the timeline step-by-step · 15.10 Drawing the add-to-cart timeline: Step 2 · 15.11 Timeline diagrams capture the two kinds of sequential code · 15.12 Timeline diagrams capture the uncertain ordering of parallel code · 15.13 Principles of working with timelines · 15.14 JavaScript’s single-thread · 15.15 JavaScript’s asynchronous queue · 15.16 AJAX and the event queue · 15.17 A complete asynchronous example · 15.18 Simplifying the timeline · 15.19 Reading our finished timeline · 15.20 Simplifying the add-to-cart timeline diagram: Step 3 · 15.21 Review: Drawing the timeline (steps 1–3) · 15.22 Summary: Drawing timeline diagrams · 15.23 Timeline diagrams side-by-side can reveal problems · 15.24 Two slow clicks get the right result · 15.25 Two fast clicks can get the wrong result · 15.26 Timelines that share resources can cause problems · 15.27 Converting a global variable to a local one · 15.28 Converting a global variable to an argument · 15.29 Making our code more reusable · 15.30 Principle: In an asynchronous context, we use a final callback instead of a return value as our explicit output · 15.31 Conclusion · 15.32 Summary · 15.33 Up next…
The introduction explains why timelines sometimes need to share resources safely, while previewing the chapter’s approach.
16.1 Principles of working with timelines · 16.2 The shopping cart still has a bug · 16.3 We need to guarantee the order of the DOM updates · 16.4 Building a queue in JavaScript · 16.5 Principle: Use real-world sharing as inspiration · 16.6 Making the queue reusable · 16.7 Analyzing the timeline · 16.8 Principle: Analyze the timeline diagram to know if there will be problems · 16.9 Making the queue skip · 16.10 Conclusion · 16.11 Summary · 16.12 Up next…
Introduces the need to coordinate timelines even when they do not share an explicit resource.
17.1 Principles of working with timelines · 17.2 There’s a bug! · 17.3 How the code was changed · 17.4 Identify actions: Step 1 · 17.5 Draw each action: Step 2 · 17.6 Simplify the diagram: Step 3 · 17.7 Possible ordering analysis · 17.8 Why this timeline is faster · 17.9 Waiting for both parallel callbacks · 17.10 A concurrency primitive for cutting timelines · 17.11 Using Cut() in our code · 17.12 Uncertain ordering analysis · 17.13 Parallel execution analysis · 17.14 Multiple-click analysis · 17.15 A primitive to call something just once · 17.16 Implicit versus explicit model of time · 17.17 Summary: Manipulating timelines · 17.18 Conclusion · 17.19 Summary · 17.20 Up next…
Introduces reactive and onion architectures as two patterns the chapter will discuss, without explaining how either works.
18.1 Two separate architectural patterns · 18.2 Coupling of causes and effects of changes · 18.3 What is reactive architecture? · 18.4 Tradeoffs of the reactive architecture · 18.5 Cells are first-class state · 18.6 We can make ValueCells reactive · 18.7 We can update shipping icons when the cell changes · 18.8 FormulaCells calculate derived values · 18.9 Mutable state in functional programming · 18.10 How reactive architecture reconfigures systems · 18.11 Decouples effects from their causes · 18.12 Decoupling manages a center of cause and effect · 18.13 Treat series of steps as pipelines · 18.14 Flexibility in your timeline · 18.15 Two separate architectural patterns · 18.16 What is the onion architecture? · 18.17 Review: Actions, calculations, and data · 18.18 Review: Stratified design · 18.19 Traditional layered architecture · 18.20 A functional architecture · 18.21 Facilitating change and reuse · 18.22 Examine the terms used to place the rule in a layer · 18.23 Analyze readability and awkwardness · 18.24 Conclusion · 18.25 Summary · 18.26 Up next…
This chapter introduction closes the book and previews advice on applying functional programming skills and continuing to learn.
19.1 A plan for the chapter · 19.2 We have learned the skills of professionals · 19.3 Big takeaways · 19.4 The ups and downs of skill acquisition · 19.5 Parallel tracks to mastery · 19.6 Sandbox: Start a side project · 19.7 Sandbox: Practice exercises · 19.8 Production: Eliminate a bug today · 19.9 Production: Incrementally improve the design · 19.10 Popular functional languages · 19.11 Functional languages with the most jobs · 19.12 Functional languages by platform · 19.13 Functional languages by learning opportunity · 19.14 Get mathy · 19.15 Further reading · 19.16 Conclusion · 19.17 Summary · 19.18 Up next…
actionAn action is a computation whose observable result depends on when or how it is performed and may involve effects beyond producing a value.
mathematical calculationA calculation is a category of code that deterministically computes a result from its inputs without directly interacting with the outside world.
dataAn inert representation of information that requires interpretation to acquire meaning and can be stored or transmitted.
copy-on-writeA data-management technique that creates a copy before modifying data so the original remains unchanged.
higher-order functionA function that accepts functions as arguments, returns functions as results, or otherwise treats functions as values.
functional, stateless philosophyA programming paradigm that emphasizes composing computations as evaluations of functions while minimizing mutable state and side effects.
concurrency primitiveA synchronization construct that provides a defined operation for coordinating concurrent execution paths or managing shared resources.
implicit inputAn input obtained by a computation from surrounding state or context rather than supplied explicitly as a function argument.
queueA book-specific JavaScript function that creates an encapsulated queue and returns an operation for submitting work to it.
call graphA graph representation in which program entities are connected according to which functions or procedures call which others.
replace body with callbackA refactoring technique that extracts unchanged before-and-after code into a function and supplies the varying body as a callback argument.
straightforward implementationA software implementation pattern that expresses behavior with operations at similar levels of abstraction while omitting irrelevant lower-level details.
implicit outputAn effect of a function that changes external state or performs an observable operation rather than returning the result directly.
defensive copyA technique that copies data intended to be retained so subsequent modifications cannot alter the retained version.
extract function argument refactoringA refactoring technique that converts information encoded implicitly in a function name or surrounding code into an explicit function argument.
immutable collectionData or state whose represented values cannot be modified after creation.
stratified designAn architectural pattern that organizes software into layers ordered from relatively stable foundations to more frequently changing elements.
global variableA variable whose binding is accessible across broad program or module scope rather than being confined to a single function or block.
minimal interfaceA stratified-design pattern in which important business concepts are represented by a small, powerful set of operations from which other operations can be constructed.
implicit argumentA code smell in which a function's name encodes a value that would more appropriately be supplied explicitly as an argument.
lambdaA function expression that has no name and can be defined inline where it is used.
arrayAn indexed JavaScript collection that stores an ordered sequence of values and can change size.
extract subroutineA refactoring technique that moves a block of code into a separately named callable function and replaces the original block with a call to that function.
shallow copyA shallow copy is a copy of a data structure's top-level container that retains references to the nested values rather than copying them recursively.
explicit inputAn input to a function that is supplied directly at the call site through an argument or parameter.
refactoringThe systematic restructuring of existing code without changing its externally observable behavior.
reactive architectureA software architecture pattern centered on asynchronous communication and systems that respond to changing events or conditions.
loopAn iteration construct that repeatedly executes a block while progressing through a sequence or range of values.
interleavingAn ordering formed by combining steps from multiple timelines while preserving the order of steps within each timeline.
cutting timelineA coordination technique that draws a boundary across timelines so actions before it precede actions after it.
recursionA programming technique in which a computation is defined in terms of one or more calls to the same computation.
domain layerThe architectural layer containing domain rules and calculations while remaining independent of external services.
deep copyA deep copy recursively duplicates a data structure and all nested objects and arrays so that no structural parts are shared with the original.
code smellA code smell is a characteristic of source code that may indicate deeper design or maintenance problems.
untrusted codeProgram code whose behavior or data-modification effects cannot be assumed to follow the calling system's safety or immutability rules.
comfortable layerA stratified-design pattern in which abstraction layers are added and shaped to support programmer productivity and software quality rather than abstraction for its own sake.
factoryA function factory is a function that creates and returns other functions, often with a shared behavior or configuration.
validation ruleA rule that specifies behavior or constraints within the problem domain modeled by software.
single-threaded execution modelA single-threaded runtime is an execution environment in which program actions execute on one thread at a time.
static typingA type system that checks and constrains the types of program expressions before execution.
value cellA book-specific reactive container that holds a value and propagates notifications when its value is available or changes.
action spreading ruleA rule stating that action status propagates upward through caller paths in a function call graph.
explicit outputA computation result made directly available through a function's return value or another declared result channel.
DOM updateA modification to the Document Object Model that changes a document's represented content, structure, or presentation.
side effectAn observable interaction with state or the external environment that occurs in addition to producing a computation's return value.
parallelismExecution in which multiple actions may occur simultaneously or without a fixed order relative to one another.
JavaScriptA high-level programming language commonly used for scripting and application development across web and server environments.
sequential processingA sequential action is an action that is ordered to occur in sequence with other actions on the same execution timeline.
structural sharingStructural sharing is a data-structure technique in which multiple versions reuse references to common portions of their representation.
scopeThe region of a program in which a binding can be accessed or referenced.
return valueThe value produced as the result of a function invocation.
distributed systemA software system whose components communicate over a network and may experience delayed, reordered, duplicated, or lost messages.
inline functionA function defined at the place in a program where it is used rather than assigned to a separate name.
ACD perspectiveA functional-programming perspective that classifies computations as actions, calculations, or data.
threading modelA specification of how program execution is divided among threads and how those threads can run concurrently.
linear searchA search algorithm that examines elements sequentially until a matching element is found or the collection is exhausted.
indexingA numeric position identifying an element within an indexed array.
read operationA read operation obtains the current value of data without modifying that data.
shopping cartA collection associated with an online purchase that holds selected items and their quantities before checkout.
write operationA write operation modifies the stored value or state of data.
cart operationA computation that operates on a shopping cart while depending on the cart's structural representation.
event loopA runtime mechanism that repeatedly retrieves queued events or callbacks and invokes them when the call stack is available.
implicit time modelThe representation of time and execution behavior provided implicitly by a programming language or runtime.
accumulatorA function passed to a reduction operation that combines the accumulated result with the current sequence element.
code readabilityThe degree to which source code can be understood by human readers.
complexityA measure of the difficulty of understanding or analyzing a piece of software based on its structure or behavior.
item operationA computation that operates on an item while depending on the item's structural representation.
safe zoneA system region in which code is trusted to preserve the intended data-safety and immutability guarantees.
reuseThe practice of using existing code in multiple places or contexts instead of duplicating its implementation.
These guides are generated from the text of Manning books by Manning's knowledge graph and link to the sections they draw on. The full books are available on liveBook and at manning.com.