
Enterprise Architecture Patterns
Topics:
Table of Contents
Introduction
Introduction
Lukas Ruebbelke discusses the outline and scope of the course. Exercises can be completed using the GitHub repository or through code examples on stackblitz.com.Repo Logistics
Lukas opens the Github repository and explains where to find the solutions to each exercise.Why It's Called Enterprise Patterns
Lukas explains how the scope of the course relates to enterprise development. Reducing the complexity of code makes large-scale applications easier to build and maintain.
Complexity
Managing State Complexity
Lukas explains that managing complexity includes the proper handling of state, code volume, and flow of control. Any application with a shared mutable state can be difficult to test or share code across multiple components.Dependency Injection
Lukas explains that local, or micro, complexity is addressed at the component level. In order for component code to be testable, it should avoid hidden state and adhere to the single responsibility principle. The first step to fixing issues with hidden state is utilizing dependency injection.Extract to Method
Lukas uses the extract-to-method technique to address issues with flow control. When a method's logic becomes too complex or breaks the single responsibility principle, the code can be split into separate, reusable functions.Separation of Concerns Q&A
Lukas answers a student question about how far a developer should go when splitting up logic and how to determine which methods to test.Reducing Complexity Exercise
Students are instructed to refactor the home service until all unit tests pass.Reducing Complexity Solution
Lukas live codes the solution to the Reducing Complexity exercise.
Object Oriented Programming
TypeScript vs Vanilla JavaScript
Lukas demonstrates why TypeScript makes it easier for developers to communicate the intention of code. Prior to ECMAScript 6, class-like objects could only be created through prototypes. ECMAScript 6 introduced native classes in JavaScript and TypeScript adds strict typing to those classes.Feature Complexity
Lukas describes the process of writing code as the continuous use of nouns, verbs, conditions, and iterators. Any programmatic task can be summarized in terms of these four concepts.Object Modeling as Nouns
Lukas explains the programming concepts around the object models within an application. Classes are the blueprint for models. Interfaces define a contract that classes must follow.Defining & Typing Objects
Lukas creates two custom types and uses them to strongly type an Object. When an Object is strongly typed, IDEs are able to offer type-checking and code hinting.Defining State
Lukas demonstrates that modeling data objects in an application makes it easier to define and maintain state. Composing the state objects from existing data types makes the functionality in the component or application more clear.Object Modeling Q&A
Lukas answers questions about why it was necessary to create a BaseEntity class, why the string type was used for for the id, and strategies for abstracting the data modeling outside the home component.Object Modeling Exercise
Students are instructed to create an object to represent a client project and implements an interface. An initialState object should also be created and implement a ProjectState interface.Object Modeling Solution
Lukas live codes the solution to the Object Modeling exercise.Methods as Verbs
Lukas creates a ClientStore object. The methods within the ClientStore are the actions for that store.Adding Methods
Lukas refactors the ClientStore object to include the ClientsState object rather than the individual clients array and currentClient properties. The use of array notation is also explained in this segment.Adding Methods Exercise
Students are instructed to create a ProjectStore class with a constructor, state property, and the methods getState and select. The class should be instantiated with the initialState object and the select method should be called to retrieve the projects collection.Adding Methods Solution
Lukas live codes the solution to the Adding Methods exercise.
Decisions & Conditionals
Managing Flow Control
Lukas explains that flow control in an application is managed through conditions. When a certain condition is true, the corresponding action is fired.Reducers
Lukas demonstrates how reducers are used to manage state changes. A series of conditions are checked with a case statement to determine which action's method should be called. String-based action names should be replaced with constant variables to reduce code duplication.Reducer Exercise
Students are instructed to create a reducer function that accepts a state and an action parameter. A switch statement should evaluate the action type and call the appropriate method.Reducer Solution
Lukas live codes the solution to the Reducer exercise.
Collections & Iterators
Higher Order Functions
Lukas demonstrates why higher order functions like forEach more succinctly iterate over collections of data. Other useful higher order functions are filter, map, and reduce.Immutability
Lukas explains how to use immutable methods to create new items, update existing items, or delete an item within an array. Each of these immutable operations returns a new array and avoids a shared mutable state. This segment also discusses how to use the Object.freeze method.Immutable CRUD Methods Practice
Lukas demonstrates how to refactor the reducer methods using immutable operations. The concat method is be used for creating a new project. The map and assign methods are be used for updating projects. The filter method is used for deleting a project.Immutability Q&A
Lukas answers questions about the Object.assign method and how to extract common CRUD operations for better reusability.Immutable Store Practice
Lukas implements an immutable store by adding a dispatch method that accepts an action and calls the reducer method with the state and the action.Four Elements of Programming Recap
Lukas reviews how the four elements of programming have been used to build a light-weight state management module. The code is using the same architecture patterns as other state management libraries like Redux or NgRx.
Time Management in Applications
Observable Streams
Lukas explains how to manage time, or asynchronicity, in applications. Observable streams encapsulate functionality, transport data asynchronously, and transform the data reliably.Streaming Values Over Time
Lukas compares observables and streaming values with promises. A promise is effective when managing a single asynchronous event. Observables coordinate multiple asynchronous events since streaming values are emitted over time.Observables Demonstration
Lukas demonstrates a basic observable example from the macro application. Data outputted from the stream is passed directly into the subscribe method. The data can be transformed before reaching the subscribe method by using the pipe method.Observables Exercise
Students are instructed to capture the searchControl output into a queryString. The data should also be mapped to uppercase letters and reversed.Observables Solution
Lukas live codes the solution to the Observables exercise.Observables Q&A
Lukas answers questions about IDE theme configurations, promises vs. observables, and if data should be transformed on the server or client in an asynchronous call.Preserving State & Merging Streams
Lukas discusses how to preserve state within a stream. The scan method behaves like the reduce method by continually updating an initial value. The scan method can also receive a partially applied function for cases when multiple streams are being merged.Mapping to Functions
Lukas explains in more detail how partially applied functions are passed into the stream and called at a later time. The mapTo method passes the property and value that should be applied to the position property once it enters the stream.Sequencing Streams with switchMap
Lukas demonstrates how the switchMap method is used to switch to another stream. The takeUntil method allows the stream to receive data until a desired observable is emitted.Communication with Subjects
Lukas explains how communication messages are sent and received between subjects in an application. A subject's asObservable method returns a stream and any observer subscribed to the stream will receive updates when an event is emitted.Observables Examples and Q&A
Lukas answers questions about currying, partially applied functions, and Redux vs. Observables.
Distributed Complexity
Simulating User Actions
Lukas discusses how user interactions can be simulated by manually dispatching actions. A properly decoupled system is not dependent on what triggers an action. It subscribes to a stream and waits for an action to be emitted.Dynamic Actions & Real World Benefits
Lukas demonstrates some real world examples of distributed complexity. Abstracting the state from an application allows two distinct instances of the application to share a synchronous stream of data through the use of web sockets.