Rust is not an Oriented-Object Programming language. Despite this, Rust borrows some principles from multiple languages like C++, JavaScript or Haskell. The language can partially use "OOP" and then some design patterns. My first tentative in Rust was to reproduce those patterns as defined by the GoF. Unfortunately, it was an error, and I got a codebase unclear. For this post, let's check how and why using Design-Patterns in Rust can be a good idea or a trap!
Why design patterns in Rust?
In software development, we encounter and resolve many problems. A design pattern is a reusable solution to a problem type. The practice of those helps to solve common problems during application design. They give to your design multiple benefits: clean code, SOLID principle respect and, essentially, a common language.
Initially, the Design Patterns defined by the GoF serve an OOP language. Then, they are not suitable for Rust! We will see when and how we can interpret some of those patterns in a no-OOP language.
I insist on the word "interpret" or "equivalent": Some of those patterns are hard to apply. Furthermore, class diagrams are not always a good representation in Rust. If you want more details about Design Patterns, I created a post about them.
The design patterns defined by the GoF. Their usage in Rust.
At first, I tried several times to apply those design patterns in Rust. It is the case in my project, "street of zombie", a run and gun game in Rust. I designed my objects per "structs" and defined some patterns in my code.
Quickly, I started to re-copy some data in another struct. Then I continued until I reached a milestone where my "structs" are similar to mimic inheritance. I tried to code in Rust as I code in C++: Like an OOP language. I made a classic mistake: The patterns defined by the GoF are not wholly applicable in Rust!
Then, I stopped this style of language and reorganized my code. I started to code as I code in C, then I began to use the traits to complete with some known patterns. Now, my coding style in Rust is different from what I do in Java or C++.
Using the "trait" like a "contract", a standard interface for multiple structs, my code became cleaner and more maintainable! Then, I extracted those patterns from my code and compared them with the "official ones":
- Some of them can be adapted (Composite).
- Some of them are easily reproducible and sometimes easier to implement (Abstract Factory)
- Also, they can be more complex if applied as defined by the GoF. Or even not recommended in Rust (Singleton).
- Or, some of them are unique to Rust!
I will feature (and complete this post) with a few pattern examples in Rust!
Interpretation of Design-Patterns in Rust
Here is a tab about the Design-Patterns in Rust I presented in GrapeProgrammer.com. If I write another post concerning a Design Pattern in Rust, this tab will be updated.
Structural patterns
Name | Description | Post | Usage in Rust |
---|---|---|---|
Composite | Design a tree structure of different components | Usage of "traits" and "dyn" in Box. Adaptable in Rust |
Photo by Barn Images on Unsplash