SOLID Principles are well-known Object-Oriented Design (OOD)principles summarized by Uncle Bob (Robert C. Martin). The word SOLID comes from the initials of the five principles it refers to, including Single responsibility principle, Open-closed principle, Liskov substitution principle, Interface segregation principle and Dependency inversion principle. Those principles are closely related to each other, and can be a great guidance in practice.
Here is a widely used summary of SOLID principles from Uncle Bob:
In this chapter, we will walk through them and find out how those principles can help form a design that smells nice.
But before we proceed, I want to mention that a few of the reasons why those principles exist might be related to the age in which they were raised, the languages and their building or distributing process people were working with, and even computing resources. When being applied to JavaScript and TypeScript projects nowadays, some of the details may not be necessary. Think more about what problems those principles want to prevent people from getting into, rather than the literal descriptions of how a principle should be followed.
The single responsibility principle declares that a class should have one, and only one reason to change. And the definition of the world reason in this sentence is important.
Consider a Command
class that is designed to work with both command-line interface and graphical user interface:
class Command { environment: Environment; print(items: ListItem[]) { let stdout = this.environment.stdout; stdout.write('Items: '); for (let item of items) { stdout.write(item.text + ' '); } } render(items: ListItem[]) { let element = <List items={items}></List>; this.environment.render(element); } execute() { } }
To make this actually work, execute
method would need to handle both the command execution and result displaying:
class Command { .. execute() { let items = ...; if (this.environment.type === 'cli') { this.print(items); } else { this.render(items); } } }
In this example, there are two reasons for changes:
Those reasons lead to changes in different dimensions and violate the single responsibility principle. This might result in a messy situation over time. A better solution is to have those two responsibilities separated and managed by the CommandEnvironment
:
Does this look familiar to you? Because it is a variant of the Visitor Pattern. Now it is the environment that executes a specific command and handles its result based on a concrete environment class.
You might be thinking, doesn't CommandResult
violate the single responsibility principle by having the abilities to display content in a different environment? Yes, and no. When the axis of this reason is set to displaying content, it does not; but if the axis is set to displaying in a specific environment, it does. But take the overall structure into consideration, the result of a command is expected to be an output that can adapt to a different environment. And thus the reason is one-dimensional and confirms the principle.
3.141.37.10