Why go SOLID?

Our main objective as developers should be to keep complexity low, this wasn’t entirely clear to me until I started working on bigger projects. I liked the idea of following SOLID principles to produce cleaner and more readable code but didn’t realize I should have been striving for ways to reduce complexity as much as possible. Which is precisely the reason why SOLID came to be.

Why is complexity the enemy?

We have finite mental resources, there is a limit to how much information we can hold in our minds at one time. If we exceed this limit we have to stop and go back, trying to break the problem down into smaller pieces. Software can get really big, really fast, and it’s our job to understand it. That’s what we get paid for. If anyone could understand code right away then there wouldn’t be much use for software developers. If the solution to understanding a problem is breaking it down into smaller parts, why not write the solution in small pieces right from the start?

Enter SOLID

SOLID principles help us do that, they are a guide to keeping the parts of our solution simple and as de-coupled from one another as possible. This enables us to focus on a small part at a time without having to think about the rest. To help us think this way we can use abstractions. An abstraction is a representation of something. Why use abstractions instead of the object directly? To reduce complexity. It’s easier to think about a car instead of thinking of a collection of wheels, doors, an engine, hydraulics, cooling systems, etc. In this case, the car is an abstraction of all its parts. You know what a car does and how it can help you accomplish what you want, go for food for example. SOLID principles help you keep your abstractions simple, coherent and de-coupled from one another so that you have an easier job working with them.

S – Single Responsibility Principle

Whats easier to think about, a lamp that has a switch to produce light or a lamp that has a clock with a timer to switch on and of at a preset time to produce light? Do you feel how concepts start to stack up in your mind as you think about them? The same thing happens when you have a class, or a method for that matter, that does more than one thing. Instead of being able to focus your mind on just one concept you have to start to juggle your attention between different ones, the abstraction has lost its pure meaning. Going back to our lamp example, if you have a lamp that works with a timer you might be tempted to abstract it away as a whole concept, but in practice, it would be better if you used two abstractions, one for the lamp and one for the timer. Then when you have to maintain the lamp it’s only the lamp you are thinking about, and if you think of a better way to implement a timer in the future, you don’t have to worry about light bulbs.

O – Open Closed Principle

This one is more subtle, the abstraction should maintain it’s meaning but we still should be able to modify it in a way that minimizes errors and re-work.

When a class is coherent and works as intended, and has been tested as such, changing it represents work and risk. On one hand, you have to think what impact the change you are making will have on the clients of the class, and on the other hand, you will have to alter unit tests and re-run them. Having the risk that some unintended side-effect can break part of your code.

A way to minimize these is to leave the working code ‘as-is’ and extend it to incorporate the new functionality, either by composition or inheritance.

If you think this way from the start then the overhead is minimum when a change is required and the risk of breaking something is minimized too.

L – Liskov Substitution Principle

Remember inheritance right? A child object ‘inherits’ some properties from his parent. The idea behind the Liskov principle is that the child object should always respect the idea that a child ‘is-a’ parent in some other form. This allows us to work with class children interchangeably, reducing the complexity of working with them. If you didn’t maintain this ‘is-a’ relationship then a child could grab some of its parent’s meaning and change it to mean something else. When this happens you cannot think of the children of a class as a whole anymore, requiring to check what each of them means. This forces you to keep more concepts in your mind, growing complexity.

For example, if the parent has a functionality to get its color that can be overridden by its children, it makes no sense for a child to use it to represent its shape. If you do that then you could not call getColor on any object of type parent and expect to get its color. Sometimes you will get its color and sometimes its shape, depending on which child you are asking.

I – Interface Segregation Principle

This principle reinforces the idea of keeping the integrity of the abstraction. If you start to implement methods from an interface that you don’t need, with only a ‘throw not implemented exception’, then that abstraction begins to corrupt. A lamp is no longer a lamp, but a lamp with some dead things attached to it. Thus if you have an interface that contains methods that can be used independently of one another you should break it up. This way you can use only the parts that make sense together and leave the unnecessary out.

D – Dependency Inversion Principle

So the lamp needs a timer, there are many ways to go around joining this two together. The worst would be to create a timer inside the lamp and use it, this binds the two permanently and once more you are forced to think of the two when you want to work on any one of them. A good rule of thumb is, if you are using and creating an object in the same place then there is something fishy going on with the abstraction. A better way to solve the problem is to abstract the timer behind a contract that states what the timer can do and then indicate the lamp has a dependency on it. This way you could ‘inject’ the timer into the lamp and keep the parts isolated from one another. The lamp only knows that the timer can be on or off at a given time and work with that. If tomorrow you want to rewrite the timer completely, as long as the contract stays the same, the lamp has nothing to worry about.

.NET Core app on Linux VPS with Direct Admin

I recently made the jump from shared to VPS hosting, been putting it off for some time, fearing a steep learning curve and a lot of wasted time setting and maintaining the server. Up until now, I can say that hasn’t been the case though. The fact that I wanted to switch to HTTPS without having to pay for a certificate, and the promise of .NET core working on Linux where the last incentives I needed to bite the bullet and go for it.

The objective was to serve my blog and my .NET project via HTTPS running side by side on the same server. Below you can find the step by step guide on how I got it working.

Step by step installation

My VPS is running CentOS 7 with DirectAdmin on top of it, I bought a license for it to make my life easier and couldn’t be more happy with it. Setting up HTTPS with Let’s Encrypt and everything else needed to run my domains was extremely easy, even for a Linux newbie like me.

The first step to run a .NET Core app on the server was to install the SDK. An alternative is to publish the apps as self-contained packages, which includes the framework needed to run on their deployment. But this means that for each app you publish you are basically copying the entire framework. As I plan on running multiple Core apps it made more sense to just install the framework once and then deploy against the target framework version directly. This makes the deploys lighter and, being the admin of the server, there was nothing stopping me from going ahead with it. Another plus for setting up your own VPS.

It’s very simple to install, you just follow the steps for your OS that Microsoft has documented so well and you are done.

sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc

sudo sh -c 'echo -e "[packages-microsoft-com-prod]\nname=packages-microsoft-com-prod \nbaseurl=https://packages.microsoft.com/yumrepos/microsoft-rhel7.3-prod\nenabled=1\ngpgcheck=1\ngpgkey=https://packages.microsoft.com/keys/microsoft.asc" > /etc/yum.repos.d/dotnetdev.repo'

sudo yum update
sudo yum install libunwind libicu
sudo yum install dotnet-sdk-2.0.0

export PATH=$PATH:$HOME/dotnet

Next step on the list is setting up Apache as a reverse proxy to forward HTTP calls to the Kestrel web server hosting your app. There are some other options, but because I wanted to run .NET Core apps side by side with, say, WordPress I wanted to keep Apache running. So setting up a reverse proxy on the domain I plan to use to host the Core apps made more sense to me. It’s valuable to mention that you can do this on a domain by domain basis, meaning that Apache will work as a reverse proxy only on the domains (or sub-domains for that matter) that you set it up for. The rest of your domains will work as they did before.

To set up the reverse proxy with DA is once more very easy, just follow their guide and done. The advantage of using a control panel like DA I guess. Adding it to the first box is enough, don’t worry too much about the exact placement inside the <VirtualHost> tag.

 

More detailed info, including how to set up a service to run your app, can be found in the docs by Microsoft.

Once you have .NET Core installed and Apache running as a reverse proxy for your app’s domain it’s just a matter of copying your app files to your desired folder and running the app. This can be done via the .NET Core CLI or by setting up a service as mentioned before. If you want to run some quick test, the CLI will do, if on the other hand, you want to run it permanently then the service is the way to go.

dotnet /pathToYourApp/App.dll

Another resource I used was this guide that did something similar with Debian, you may find it useful.