How Xamarin devs violate SOLID
We all know how to create mobile applications. As professionals we aim to make them not only eye-candy but scalable, fast and secure as well. Meantime as lazy professionals, we do not like to reinvent the wheel. Yes, I’m talking about patterns and principles. One of the most important abbreviations in modern apps development is SOLID, which stands for 5 basic app development principles.
We all know about SOLID. All those ducks and circles with rectangles. But what about the real world? How do Xamarin devs violate SOLID?
A class should have one, and only one, reason to change.
You may find SRP violation in nearly every ViewModel. The view model is an abstraction of the view exposing public properties and commands. And that is it. No routing. No communication with backend. No caching. No error handling. Just properties and triggers (i.e. commands).
So what can we do? Well, let’s just split the responsibilities! There is a life outside the MVVM. It is not necessary to get rid of bindings and viewmodels at all, but you may try to use VIPER-like approach. Our popular frameworks work great with a ViewModel-first approach, so it is quite easy to create separate models with strict responsibilities.
The Open-Closed Principle
Software entities (classes, modules, functions, etc) should be open for extension, but closed for modification.
Everything is clear about inheritance and you know how to implement area calculator (or a part of the drawing app) for sure, so let’s not focus on that aspect of OCP at all.
The tricky part of OCP is in the code base organization, i.e. modules. Have you ever developed a list with complex cells? Usually, we just create a monstrous
DataTemplate in Page’s XAML and handle all the logic in Page’s ViewModel. Shame on us!
There is such a nice answer on SE about OCP:
The OCP is typically sloganized as “a component should be open to extensions and closed to modifications by consumers”. Basically, if a consumer of a component wants to add functionality to the component they should be able to extend the old component into a new one with the additional functionality, but they should not be able to change the old component.
So what should we do with our cells? Create components! You may use the same VIPER module as a starting point and adopt it for your solution.
The Liskov Substitution Principle
Child classes should never break the parent class’ type definitions.
Each time you do
throw new Exception(…); in the derived class, you probably violate this principle.
Each time you do not call base method implementation you do the same.
Pre- or post- conditions changed? Violation.
Where do we do that? Usually in service models, but it is even easier to violate LSP when you do platform-specific code.
What should we do? Try not to use inheritance for code reuse! It is easy if you try. Composition to the rescue. However sometimes it is impossible or makes no sense, so just be smart and use a checklist like that.
The Interface Segregation Principle
No client should be forced to depend on methods it does not use.
We love to violate this principle in the communication layer. Let’s say we have an abstract Twitter app with the following
I think you’ve got the idea. Sometimes you may find user’s likes here, or even
Logout() method, etc.
This interface may be used on user’s profile pages, and profile editing pages, and on a pages with user’s posts. Will we have a single screen that uses all those methods? Barely.
What should we do? Split the interface!
The Dependency Inversion Principle
1. High-level modules should not depend on low-level modules. Both should depend on abstractions.
2. Abstractions should not depend upon details. Details should depend upon abstractions.
Fortunately, this principle violation is kindly rare. We all use DI-frameworks and in case if you use VIPER-like modules you should not face any problems with DIP.
SOLID is great, but do not lose your head in blind acceptance. Always know why and what you are doing.