søndag den 9. februar 2014

SOLID principles, in layman's terms: Dependency Inversion

Raison d'être: I set out to write about the SOLID software development principles. Specifically, my aim was/is to make these things more understandable to other developers who, much in the way as yours truly, found it troublesome to have to decipher lengthy, complex articles and books on the matter. These principles are for everyone to learn and use, but I found that they were hard to fully grasp; quite possibly because I come from a non-English speaking background. So with this series of articles I'm setting out to try and de-mystify the principles, with only the best intentions in mind. The principles apply to many layers of software development. In my articles, I specifially aim to describe them as they relate to programming. I hope it'll be of use to you. Thank you for stopping by.

This will be a 5 article-series about SOLID. SOLID is all the rage; at least as far as the job-adds I'm reading are concerned; "you are expected to honor the SOLID principles" etc. So what exactly is SOLID about? Plain and simple, it's a set of guide-lines in developing object-oriented systems. They are a group of concepts that have proven themselves valuable for a great many people coding a great many pieces of software. A tale told by your elders in software engineering, if you will, that you will want to pay heed to so you can boast on your CV that you're into the SOLID principles - and you'll be a better developer for knowing them, I promise you that. Heck, you're a better developer for simply _wanting_ to know them!

SOLI[D] - The Dependency Inversion principle
No 5 and last round of our series of articles on the SOLID principles finds us at the Dependency Inversion principle. And as wikipedia says it so well, it [quote] "refers to a specific form of decoupling where conventional dependency relationships established from high-level, policy-setting modules to low-level, dependency modules are inverted (i.e. reversed) for the purpose of rendering high-level modules independent of the low-level module implementation details..[[/quote]. Begging your pardon? Let's try that again, in layman's terms:

The dependency inversion principle means that you'll give your classes the variables they'll need to function, as opposed to letting them declare those variables. Here's first an example of how to not follow the principle:

public class DiskLogLocation
{
    public DiskLogLocation()
    {
    }

    public void LogMessage(string message)
    {
        // do something to log the message here
    }
}

public class Logger
{
    private DiskLogLocation logLocation;

    public Logger()
    {
        logLocation = new DiskLogLocation();
    }

    public void Log(string message)
    {
        logLocation.LogMessage(message);
    }
}


public class Program
{
    private static Logger logger;

    static void Main(string[] args)
    {
        logger = new Logger();
        logger.Log("a log message");
    }
}

In the above basic we have a Program, which instantiates a Logger()-class, which in turn instantiates - "new's up", as some say - a DiskLogLocation object. This does not follow the Depedency Inversion principle, and in a beat I'll explain why. But here's first the right way to do it, if one wishes to follow the SOLID way:

public class DiskLogLocation
{
    public DiskLogLocation()
    {
    }

    public void LogMessage(string message)
    {
        // do something to log the message here
    }
}

public class Logger
{
    private DiskLogLocation logLocation;

    public Logger(DiskLogLocation _logLocation)
    {
        logLocation = _logLocation;
    }

    public void Log(string message)
    {
        logLocation.LogMessage(message);
    }
}


public class Program
{
    private static Logger logger;

    static void Main(string[] args)
    {
        DiskLogLocation diskLogLocation = new DiskLogLocation();
        logger = new Logger(diskLogLocation);
        logger.Log("a log message");
    }
}

The above code varies from the first in as much as we instantiate the DiskLogLocation object in our Main, and pass it on to our Logger-object right there as an argument in the constructor call. That is indeed 'inverted dependency', and that's what this Dependency Inversion principle is all about: Instead of having to depend on the Logger-class to declare and instantiate the DiskLogLocation object, we do it ourselves and simply pass it on. So it follows that instead of depending on our Logger-object to do it, we've "taken the responsibility back - inverted it back to Main()"

That, in a nutshell, is the Dependency Inversion principle. And the reason for wanting to apply it is this, that you'll gain greater control of how your classes are dependent on each other. We want to strive classes having as few dependencies as possible - that is, we want to limit to the extent possible having to 'new stuff up'. Why, because every time we do that, we introduce a dependency that we later cannot alter, as it's hard-wired into the class. But when we ourselves provide the class with the dependencies - in the above case the DiskLogLocation object - it needs, then we have achieved what's popularly referred to as 'loose coupling'; that is, we can easily change things around without having to re-wire a whole bunch of stuff. Well, at least that's the idea.

The above example is - of course - heavily simplified. The Dependency Inversion principle truly comes to the fore when we're dealing with abstractions, but that sentiment is grounded in the other SOLID principles and so I won't go into extending the example with that, rather refer to my other articles on those other principles mentioned.

You'll perhaps have heard of the principle of Dependency Inversion in one of its various guises: Dependency Injection, Inversion of Control, what have you. It's all about the same thing, really, if you understand the basic premise as described in the above, you should be in the clear. If you're wondering how go to from here, there's absolutely no way around researching 'Dependency Injection Containers', or DI Containers for short. A bunch of very clever people have sat down and implemented some equally clever components that takes away all the rough work, so you can invert your dependencies to your heart's content. Some popular ones include Ninject, Castle Windsor, AutoFac; I'll venture to specifically recommend the former, Ninject.

So there you have it, the Dependency Inversion principle; don't let your classes decide which dependencies they need, decide for them and that's all they damn well get. In turn, you offer thoses classes - and your project alike - the possibility to replace those dependencies with something better, should it come along. And in an ever-changing IT climate that's pure gold, the change to adapt quickly to change.


lørdag den 8. februar 2014

SOLID principles, in layman's terms: Open/Closed

Raison d'être: I set out to write about the SOLID software development principles. Specifically, my aim was/is to make these things more understandable to other developers who, much in the way as yours truly, found it troublesome to have to decipher lengthy, complex articles and books on the matter. These principles are for everyone to learn and use, but I found that they were hard to fully grasp; quite possibly because I come from a non-English speaking background. So with this series of articles I'm setting out to try and de-mystify the principles, with only the best intentions in mind. The principles apply to many layers of software development. In my articles, I specifially aim to describe them as they relate to programming. I hope it'll be of use to you. Thank you for stopping by.

This will be a 5 article-series about SOLID. SOLID is all the rage; at least as far as the job-adds I'm reading are concerned; "you are expected to honor the SOLID principles" etc. So what exactly is SOLID about? Plain and simple, it's a set of guide-lines in developing object-oriented systems. They are a group of concepts that have proven themselves valuable for a great many people coding a great many pieces of software. A tale told by your elders in software engineering, if you will, that you will want to pay heed to so you can boast on your CV that you're into the SOLID principles - and you'll be a better developer for knowing them, I promise you that. Heck, you're a better developer for simply _wanting_ to know them!

S[O]LID - The Open/Closed principle

The open/closed principle is the second in the set of principles that make out the SOLID acronym. According to the wikipedia entry, it states that [quote] "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification" [/quote]. What is basically comes down to is this, that you'll want to write your classes in such a way that you won't have to change them once they're done.

And why is this a good thing? Because changes to code is an inheritantly bad thing. Or, to put it differently, if you find yourself having to make changes to your source code when it's gone into production, that's when this principle would come in handy. Why, because source code once it's there and it's been tested, it's been reviewed, it's been released, by then it doesn't lend itself well to changes. Add a feature, tweak a business-rule, and you might find yourself in a situation where something, somewhere breaks, and you could be in a heap of trouble.

So what to do about it? It's easy: program to abstractions (i.e. interfaces or inherit from abstract classes), not implementations. When your variables are interface types, you won't need to specify until run-time which kind of implementation will actually represent the interface type. Consider this basic example:

First here's doing it wrong:

public class Logger
    {
        private DiskLogLocation diskLogLocation;

        public Logger()
        {
            diskLogLocation = new DiskLogLocation(@"c:\logs");
        }

        public void LogMessage(string message)
        {
            diskLogLocation.Log(message);

        }
    }


Above we have a Logger-class, which news up a 'DiskLogLocation', and write a message to it - supposedly to the directory specified in the constructor. The problem with this lies in the fact that we've now limited ourselves to the DiskLogLocation - we haven't fulfilled the open/closed principle, in as much as we cannot easily extend the Logger-class to allow us to log to the event-viewer, for example. Then here's doing it right:


 public class Logger
 {
        // use an interface, and provide an implementation of 
        // this interface at runtime
        private ILogLocation logLocation;

        public Logger()
        {
        }

        public void LogMessage(string message)
        {
            logLocation.Log(message);

        }
 }



In the above, the logLocation acts as a placeholder for which ever implementation of ILogLocation we eventually choose to use (see "As an aside" below on how to do just that). That's basically it - the open/closed principle in a nut-shell. That's - basically - what's meant by "open for extension": that we program to interfaces, not implementations, so that we can pull in whichever code we desire at a later time by simply replacing the interface implementation - for example, an 'EventLogger' class.

There're more ways than one to go about extending a class; the above is just one - but a fine place to start non the less, if I may say so myself. You can do magical stuff with some so-called 'design patterns', for example the strategy pattern, but that's for a different article.

So now you know about the open/closed principle: that you should program to interfaces and thus leave your options open for extention. Easy to learn, difficult to master; it takes some experience, recognizing the internal workings of a class that should be left open for extention. And there's always the risk of going overboard and interfacing to everything, when the business requirements just don't call for it. These discussions can get right religious at times.

______________

As an aside; how do you then, at run-time, specify which implementation will be used? Well one way is to have a method on your utilizing class which offers the possibility of exchanging the implementation with another one. For example, like so:

public class Logger
 {
        private ILogLocation logLocation;

        public Logger()
        {
        }
        
        public void SetLogLocation(ILogLocation _logLocation)
        {
            logLocation = _logLocation;
        }

        public void LogMessage(string message)
        {
            logLocation.Log(message);
        }
 }


Another way is to allow for this in the utilizing class' constructor, like so:

public class Logger
 {
        private readonly ILogLocation logLocation;

        // allow the Logger instantiator to determine which
        // implementation to use
        public Logger(ILogLocation _logLocationDeterminedAtRunTime)
        {
            logLocation = _logLocationDeterminedAtRunTime;          
        }

        public void LogMessage(string message)
        {
            logLocation.Log(message);

        }
 }

Given the above example you might possibly determine which implementing class to use via a configuration file, which you run at your composition root - which is just a fancy way of saying 'where your app starts', typically main() or ApplicationStart() or what have you. You could do this, for a simplistic example:

static void Main(string[] args)
        {
            string logLocationType = ConfigurationSettings.AppSettings.Get("type_of_log_location");
           
            if (logLocationType == "Disk")
            {
                logLocation = new DiskLogLocation(@"c:\logs");
            }

            Logger logger = new Logger(logLocation);
            logger.LogMessage("hello log");

        }

Here we're asking a configuration-setting for know-how on which type of log-location we wish to use, and we instantiate that pass it to the logger on construction. Now you're well on your way to using something fancy called 'Dependency Injection', - which in turn is just a fancy way of saying 'we are giving our classes the variables they need in their constructor*'. A topic for a different article entirely.

*) Usually the case, but not always.

SOLID principles, in layman's terms: Interface Segregation

Raison d'être: I set out to write about the SOLID software development principles. Specifically, my aim was/is to make these things more understandable to other developers who, much in the way as yours truly, found it troublesome to have to decipher lengthy, complex articles and books on the matter. These principles are for everyone to learn and use, but I found that they were hard to fully grasp; quite possibly because I come from a non-English speaking background. So with this series of articles I'm setting out to try and de-mystify the principles, with only the best intentions in mind. The principles apply to many layers of software development. In my articles, I specifially aim to describe them as they relate to programming. I hope it'll be of use to you. Thank you for stopping by.

This will be a 5 article-series about SOLID. SOLID is all the rage; at least as far as the job-adds I'm reading are concerned; "you are expected to honor the SOLID principles" etc. So what exactly is SOLID about? Plain and simple, it's a set of guide-lines in developing object-oriented systems. They are a group of concepts that have proven themselves valuable for a great many people coding a great many pieces of software. A tale told by your elders in software engineering, if you will, that you will want to pay heed to so you can boast on your CV that you're into the SOLID principles - and you'll be a better developer for knowing them, I promise you that. Heck, you're a better developer for simply _wanting_ to know them!

SOL[I]D - The Interface Segregation principle

Round 4 of our series of articles on the SOLID principles brings us to the Interface Segregation. And once more we turn to wikipedia for an official explanation, where it states that, [quote] "that no client should be forced to depend on methods it does not use.[[/quote]. Let's get down and dirty - what's it all about, then?

It's very simple, really: Basically this ones means that if you're implementing interfaces and your implementation doesn't implement all methods of that interface, that's a sign that your interface is bloated and must might benefit from a redesign.

A brief example to the fore. Again, these are very simple examples, solely for the purpose of getting a grasp on the concept. Let's say we've got this interface, that we wish to implement, and two such implementations:

  public interface ILogLocation
    {
        string LogName { get; set; }
        void Log(string message);
        void ChangeLogLocation(string location);
    }

    public class DiskLogLocation : ILogLocation
    {
        public string LogName { get; set; }

        public DiskLogLocation(string _logName)
        {
            LogName = _logName;
        }

        public void Log(string message)
        {
            // do something to log to  a file here
        }

        public void ChangeLogLocation(string location)
        {
            // do something to change to a new log-file path here
        }

    }

    public class EventLogLocation : ILogLocation
    {
        public string LogName { get; set; }

        public EventLogLocation()
        {
              LogName = "WindowsEventLog";
        }

        public void Log(string message)
        {
            // do something to log to the event-viewer here
        }


        public void ChangeLogLocation(string location)
        {
            // we can't change the location of the windows event log, 
            // so we'll simply return
            return;
        }
    }

Above are two implementations of the ILogLocation interface. Both implement the ChangeLogLocation() method, but only our DiskLogLocation-implementation brings something meaningful to the table. This it messy; it's like putting a winter beanie over your summer cap, they're both hats but you needn't wear them both at the same time. Let's say that we have three DiskLogLocations and one EventLogLocation: now, for configuration purposes we may run through them all by adressing them by their interface, that would be a perfectly reasonable thing to do...

var logLocations = new List<ILogLocation>() {
                new DiskLogLocation("DiskWriteLog"),
                new DiskLogLocation("DiskReadLog"),
                new EventLogLocation(),
                new DiskLogLocation("FileCheckLog")
            };

            foreach( var logLocation in logLocations)
            {
                logLocation.ChangeLogLocation(@"c:\" + logLocation.LogName + ".txt");
            }

... so that's what we do in the above, but that leads as you can see to an unncessary call to the ChangeLogLocation() for the EventLogLocation-object. It's unnecessary, it doesn't lead to anything rather the potential of introducing bugs and is to be considered a code smell, and should be generally 'uncalled for' - parden the pun.

So here's what we can do instead:

public interface ILogLocation
{
    string LogName { get; set; }
    void Log(string message);
}

public interface ILogLocationChanger
{
    void ChangeLogLocation(string location);
}

public class DiskLogLocation : ILogLocation,  ILogLocationChanger
{
    public string LogName { get; set; }

    public DiskLogLocation(string _logName)
    {
        LogName = _logName;
    }

    public void Log(string message)
    {
        // do something to log to  a file here
    }

    public void ChangeLogLocation(string location)
    {
        // do something to change to a new log-file path here
    }
}

public class EventLogLocation : ILogLocation
{
    public string LogName { get; set; }

    public EventLogLocation()
    {
        LogName = "WindowsEventLog";
    }

    public void Log(string message)
    {
        // do something to log to the event-viewer here
    }
}

Above we've moved the ChangeLogLocation()-method into its own interface, ILogLocationChanger - which is implemented only the DiskLogLocation implementation. That's a much nicer way of going about it; no unneccesary method implementations ever again! Also, we now have a way of distinguishing the implementations, by way of the abstractions they implement. We could potentially re-use one or more interfaces for other classes.

So there you have it - the Interface Segregation principle, which basically means 'split up your interfaces if you find that you have to implement methods that aren't required for your class, or that you simply return, or throw an exception, from'. Easy!

As an aside, you might ponder the different from this Interface Segregation principle and the Single Responsibility principle; as a reminder, the Single Responsibility principle informs us that a module should carry a single responsibility only. Isn't that about the same thing as this Interface Segregation principle we've just taken on? Well, they're somewhat similar. There's a difference, but I won't go into it. I'll instead refer to StackOverflow user Andreas Hallberg, who I thought penned an explanation superior to anything I could've come up with: (ref: http://stackoverflow.com/questions/8099010/is-interface-segregation-principle-only-a-substitue-for-single-responsibility-pr) [quote]"Take the example of a class whose responsibility is persisting data on e.g. the harddrive. Splitting the class into a read- and a write part would not make practical sense. But some clients should only use the class to read data, some clients only to write data, and some to do both. Applying ISP here with three different interfaces would be a nice solution."[/quote] Great stuff! So we gather that the SR principle is about 'one thing, and one thing only' vs. the IS principle is about 'what we need, and only what we need'. Related principles, both valid, both important.

SOLID principles, in layman's terms: Liskov Substitution

Raison d'être: I set out to write about the SOLID software development principles. Specifically, my aim was/is to make these things more understandable to other developers who, much in the way as yours truly, found it troublesome to have to decipher lengthy, complex articles and books on the matter. These principles are for everyone to learn and use, but I found that they were hard to fully grasp; quite possibly because I come from a non-English speaking background. So with this series of articles I'm setting out to try and de-mystify the principles, with only the best intentions in mind. The principles apply to many layers of software development. In my articles, I specifially aim to describe them as they relate to programming. I hope it'll be of use to you. Thank you for stopping by.

This will be a 5 article-series about SOLID. SOLID is all the rage; at least as far as the job-adds I'm reading are concerned; "you are expected to honor the SOLID principles" etc. So what exactly is SOLID about? Plain and simple, it's a set of guide-lines in developing object-oriented systems. They are a group of concepts that have proven themselves valuable for a great many people coding a great many pieces of software. A tale told by your elders in software engineering, if you will, that you will want to pay heed to so you can boast on your CV that you're into the SOLID principles - and you'll be a better developer for knowing them, I promise you that. Heck, you're a better developer for simply _wanting_ to know them!

SO[L]ID - The Liskov Substitution principle

The Liskov substitution principle is the third in the set of principles that make out the SOLID acronym. According to the wikipedia entry, it states that, [quote] "in a computer program, if S is a subtype of T, then objects of type T may be replaced with objects of type S (i.e., objects of type S may be substituted for objects of type T) without altering any of the desirable properties of that program[/quote]. OK. Cool. But what the heck does that imply, exactly, and why is it important?

It implies that a derived class must be substitutable for its base class. That is to say, whatever methods you define in your base class, you must implement these in all your implementing classes (if you're programming to an interface) or derived classes (if you're programming to an abstraction). You can't, by way of the principle, choose to NOT implement a method, and you mustn't extend your implementation by offering functionality in the implementation that's not available in the base class.

Basically, it's a code of honor: You mustn't 'violate' the base class in your implementations, rather honor it and fulfill its every method.

Alright - so that's the principle. But why is it important? Well, it's important because we would like to always be able to refer to the base class or the interface as opposed to deal with implementations of a base class directly, because this leads us to greater de-coupling in our design, which in turn provides us flexibility, a blessing in systems development (all things being equal!). But if we can't trust our implementations to deliever the same result - albeit in their own unique ways - of our abstraction or interface, that's when we begin to throw ugly if-else lines around. And that's when code becomes bloated, recompilations abound... Ragnarök!

I'll demonstrate by way of example. Please consider the below:

public interface ILogLocation
{
    bool LogVerbose { get; set; }
    void Log(string message);
}

public class DiskLogLocation : ILogLocation
{
    public DiskLogLocation()
    {
    }

    public bool LogVerbose { get; set; }

    public void Log(string message)
    {
        // do something to log to a file here

        if (LogVerbose)
        {
            // do someting to log a heck of lot more log-text here
        }
        else
        {
            // do someting to log not very much log-text here
        }
    }
}

public class EventLogLocation : ILogLocation
{
    public EventLogLocation()
    {
    }

    public bool LogVerbose { get; set; }

    public void Log(string message)
    {
        // do something to log to the event-viewer here

        // notice we don't check the LogVerbose bool here
    }
}

So here we have an interface, ILogLocation, with two different implementations. But only one of the implementations makes use of the LogVerbose boolean. That's our danger-sign: this is a behaviour that alters the design-logic of our interface, which explicitly specifies that boolean and designates it a property, with getter and setter methods, for all intents and purposes because it's meant to be used. But the EventLogLocation-class 'dishonors' the interface in as much it doesn't make use of it all. Wonder if that will come back and haunt us? Let's see below how the implementations might be instantiated:


ConfigurationSettings.AppSettings.type_of_log_location = "eventLog";

private ILogLocation logLocation;

static void Main(string[] args)
{
    string logLocationType = ConfigurationSettings.AppSettings.Get("type_of_log_location");

    switch( logLocationType )
    {
        case "disk":
            logLocation = new DiskLogLocation();
            break;
        case "eventLog":
            logLocation = new EventLogLocation();
            break;
    }

    logLocation.LogVerbose = true;
    logLocation.Log("Hoping to get a lot more text logged");
}

Seems we could land in hot water here; in the above, as we instantiate an ILogLocation implementation by way of a configuration-file. We're setting the LogVerbose property and thus would expect to log a lengthy text with lots of debug hints as Log()-method. But as our configuration file finds us instantiating an EventLogLocation() that's never going to happen!

The Liskov Substitution principle is great for keeping us out of trouble down the road. We'll share our code with others, and they needn't have to know about potential pitfalls like "oh, yeah, there's this thing you need to know about the EventLogLocation's Log()-method...". More importantly, it's a reminder to focus on the code-quality of our implementations, and re-design our interfaces accordingly if we should feel the need to extend or degrade our base-class implementations. That danger lies particularly in altering the behaviour of our base-class, which may for example necessitate ugly type-checks such as the below:

if ( logLocation is EventLogLocation)
{
    // we, the deveoper, know there's no check on the 'LogVerbose' bool
    // on the EventLogLocation implementation
    logLocation.Log("Hoping not so much to get a verbose log");
}
else
{
    logLocation.LogVerbose = true;
    logLocation.Log("Hoping to get a verbose log");
}

In the above we're doing a type-check on the logLocation, and reacting one way if it's this time and another if it's not. Not so good - we've gone beyond having to deal with only a base class or interface representation, and set ourselves up for maintenance problems down the road.

So that's basically what the Liskov Substitution principle holds: Honor the contract as set up by your base class or interface. Don't extend the implementations to hold logic that's not called for, don't skip implementing methods by simple calling a 'return()' or throw an exception from them. If you feel that urge, look into re-designing your 'contract' with the base class or interface instead.

When I was first introduced to it, the Liskov Substitution principle seemed to me to hold little value. "Who does this",  I thought, "who creates a base-class with methods and choose then NOT to implement them - what are they even for, then?" As it turns out, lots of coders. Myself included. It slowly creeps up on you, as various factors such as "you need to finish this project NOW!" or "it'll just be this one time I'm splitting my logic based on this type-check" affect the way you work, and code. But let me assure you it pays dividends down the road, paying attention to it - never more so when you're part of a bigger team, and must be able to trust your colleagues' code, and they yours.