SOLID Principles for Designers
Este artículo también está disponible en español 🇪🇸
In recent years, we have witnessed an increasing convergence between the worlds of design and development. The fact is that until not too long ago, the term “branch” for the average designer referred to a hearty and tasty meal. Fortunately, we designers have adopted some methods and concepts traditionally related to the development field into our workflow, which not only enhances efficiency but also facilitates smoother collaboration with developers.
In this context of convergence, I wanted to write this article to explore how SOLID principles, originally conceived by Robert C. Martin at the beginning of this century as guidelines for quality software development, could provide a methodological framework for designing components of a design system, improving its robustness and scalability. Regardless of the contribution model, it’s crucial for the involved designers to fully understand these concepts. This will enhance communication and collaboration across disciplines and teams.
It’s important to note that this is a very personal perspective based on my experience as a designer, a humble proposal for approaching such a complex and fascinating topic that is very open to different interpretations. With this in mind, let’s explore the SOLID principles and their application in designing components of a Design System.
S — Single Responsibility Principle
The principle is defined as:
“A class should have only one reason to change”
We can interpret this as:
“A component should have a single purpose”
This principle invites us to create very focused and specialized components within our Design System, reducing unnecessary complexities. This greatly facilitates the maintenance and scalability of the components. For example, an inputText component should handle how its different states are displayed, but the form validation logic is not its responsibility. The best practice here is to atomize the components. If you need to create a complex component with multiple behaviors and actions, consider composing it from smaller pieces.
O — Open/Closed Principle
This principle states:
“Software entities should be open for extension, but closed for modification.”
It could be adapted as:
“components should allow configuration without altering their structure.”
In context, this translates to designing components that make use of variants and have their customizable properties parameterized through props
, thus allowing them to extend their use cases. This not only improves robustness but also facilitates the implementation and maintenance of the design system.
For example, a well-designed button component should be able to adapt to different styles, sizes, or states through its props, without hardcoding modifications or creating a new component for each variation.
Although using props
is common in modern design systems, I find it interesting to highlight the flexibility and customization power that Newskit offers with them.
L — Liskov Substitution Principle
This principle says:
“Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it”
In component design, we could understand it as:
“Component’s variants must be able to be replaced with each other without affecting functionality”
This principle pushes us to ensure the consistency of component variants by setting limits on property parameterization. This facilitates maintenance and integration in various contexts.
For example, a button
component with primary
, secondary
, and tertiary
variants should allow an instance of the button
, whether secondary
or tertiary
, to replace an instance of primary
without affecting the UI functionality. This implies that all buttons must have the same configurable parameters and behave consistently when clicked.
If an additional feature is needed in a variant, we need to consider whether it can be implemented so that it’s available in all variants, or if it would be better to create a new and separate component.
I — Interface Segregation Principle
For development, this principle states:
“Clients should not be forced to depend upon interfaces that they do not use”
In context and with a bit of creativity, it would be:
“Create modular components capable of adapting to more specific needs.”
This principle guides us towards decoupling and modularization of components. Instead of a monolithic component with multiple functionalities, it’s preferable to design components that can contain different smaller and specific pieces, combining them as needed. This increases the flexibility of components and greatly reduces the complexity of their maintenance.
Using customizable content slots in components is an excellent way to apply this principle. For example, instead of creating one or several card components with all possible internal variations, we should design a base card with slots for its header, content, and footer.
D — Dependency Inversion Principle
El último de los principios es:
“Depend upon abstractions, not concretes”
This case does not need interpretation.
This principle leads us towards creating more versatile and reusable components. In a Design System, this means designing components that are abstract enough to function in various contexts, without being tied to a specific implementation or overly specific use case.
For example, when designing a card component, instead of creating a multitude of independent components or specific variants like sneakersCard
or featuredOfferCard
, it’s better to create a more generic productCard
component that can adapt to different types of content, allowing the component to be used in multiple scenarios without needing modification.
As you can see, the key to these principles lies in maintaining focus at all times on modularity, flexibility, and coherence when designing components.
Their adoption not only improves the structure of our components but also fosters better communication and understanding between designers and developers. By using a common language and shared principles, we can create a more integrated and efficient workflow.
It’s important to remember that these principles should be understood as guidelines, not inflexible rules. The practical application of SOLID in designing components of a Design System can vary according to the specific needs of each project and team.
I’m sure you’re already applying one or more of these principles when designing components, and if not, I encourage you to consider using this methodological framework to help build a more robust and scalable Design System.
In any case, I’d love to hear opinions on the application of these principles in the design of components within a Design System. I encourage you to share your ideas and experiences in the comments.