Learning Design Patterns: A Summary
What I learned from reading this awesome book and why you should read it too!
In programming, a "pattern" describes a general, reusable solution to a common occurring problem. As a software developer, it is important to understand when to apply these patterns; because using them arbitrarily can cause more harm than good to your software.
This weekend, I read a book called "Learning Patterns" by Lydia Hallie and Addy Osmani. It is a great book for any level of developer to learn about various design patterns, when to use it, and its pros and cons. It also includes web performance optimization techniques.
In this article, let me share a snippet of the goodness of this book, which would hopefully entice you to get a copy yourself.
The Patterns
Before reading the book, I recommend understanding a bit about React and how it works because the entire book uses examples with React code and focuses on React-specific patterns.
You can read my React Cheat Sheet for Beginners for a quick overview, or read the book's chapter covering the basics of React.
Now, let's look at some patterns!
1. Singleton
The Singleton is a single global instance that is accessible throughout the application. In React apps, this pattern makes it easy for managing states and accessing them globally.
However, Singletons are considered an anti-pattern in JavaScript and should be avoided. Because unlike Java, C++ or C#, we can directly create an object in JavaScript to implement a similar pattern without actually creating a Singleton class.
Some disadvantages of this pattern:
- Having global variables can potentially cause overwrites and unexpected behavior
- Difficult to test since we cannot create a new instance, we must test the value based on any previous tests' modification
- In React apps, there are already state management libraries such as Redux, which makes the Singleton pattern quite redundant
2. Provider
The Provider pattern is commonly seen in React. Passing props from one component to another is just very tedious as the app gets more complex. This is known as prop drilling.
One example React has implemented to overcome this challenge is the React Context API. It allows data to be accessible from any component in the component tree.
For example, you may need to check whether a user is logged in throughout your app. So you need to wrap all your elements inside some kind of AuthProvider
so that any components in this Provider can access its prop.
We first create a Context
object like this:
export const AuthContext = React.createContext();
Then, we can have a Provider
with a prop we want to be accessible everywhere in our app. Here we have a user
state that the AuthProvider
will provide to the rest of the components.
export const AuthProvider = ({ children }) => {
const [user, setUser] = useState(null);
useEffect(() => {
app.auth().onAuthStateChanged(setUser);
}, []);
return (
<AuthContext.Provider value={{ user }}>{children}</AuthContext.Provider>
);
Now we just need to wrap it around all our elements.
function App() {
return (
<AuthProvider>
<Router>
<Nav />
<Switch>
<Route path="/signin" component={SignIn} />
</Switch>
</div>
</Router>
</AuthProvider>
);
}
And now our app components can access user
anywhere like this:
const { user } = useContext(AuthContext);
For more details on React Context API, feel free to read about useContext hook here or how to set up authentication in this article.
3. Hooks
Hooks in React has become one of the most powerful features to write cleaner and more efficient code. It is not exactly a design pattern, but ever since its release, it has replaced many traditional patterns. According to the official React website, Hooks achieves the following:
- Allow you to reuse stateful logic without changing your component hierarchy
- Let you split one component into smaller functions based on what pieces are related (such as setting up a subscription or fetching data)
- Let you use more of React’s features without classes
Before Hooks, class components are the only way to handle state and lifecycle methods in React. As the app grew, it becomes increasingly complex to have to refactor functional to class components or have many duplicate lifecycle methods.
To learn more about React Hooks at a deeper level, please check out my A Look at React Hooks series, where I cover 8 commonly used Hooks in detail.
4. Container
Our next pattern is the Container pattern. It is quite an overlooked pattern if you are not familiar with React. The purpose of implementing this pattern is to separate the app's view components (only UI) from the functional components that deals with application logic.
The 2 types of components are:
- Presentational component - simply about displaying data to user
- Container component - cares about what data is shown to user
For example, the logic for fetching data from an API will be in a Container component while the Presentational component will get the data to display it in a readable format.
This pattern is advantageous as it enforces the separation of concerns. It makes it easy for developers to test and to make changes to the view or the logic whenever needed.
5. Factory
As its name suggests, the factory pattern is about using factory functions to create objects over and over again, without the new
keyword.
Take a look at the example below:
// Factory function
const createShape = ({numberOfSides, color}) =>({
numberOfSides,
color
})
// create objects from factory
const square = createShape({
numberOfSides: 4,
color: "red"
})
const hexagon = createShape({
numberOfSides: 6,
color: "yellow"
})
This pattern is useful for when you need to create complex, configurable objects that share some properties. The downside is that in JavaScript, it may be more memory efficient to create new instances rather than objects.
Conclusion
As a developer, studying some patterns can be beneficial to your problem-solving and software design principles because patterns are tried and tested solutions to common problems in software design.
Unfortunately, this is all I have for this article before it turns into an essay. This is just the tip of the iceberg in terms of what this book contains. I highly recommend reading it yourself to learn more patterns in detail.
Thanks for reading, hope this article has inspired you to read the book yourself. Feel free to go to patterns.dev to download the book for free. Do share with me which patterns do you encounter or use most in the comments below. Cheers!
Reference
- Learning Patterns by Lydia Hallie and Addy Osmani