Clean Code - The Dependency Inversion Principle

Stel je voor dat in de main van de applicatie een e-mail wordt verstuurd op het moment er een exception optreed. De functie die deze mail verstuurd ziet er als volgt uit:

public class Main()
{
  function OnException(Exception exception)
  {
    var mailer = new Mailer();
    mailer.SendExceptionMail(exception);
  }
}

De class main heeft nu direct een dependency met de class Mailer. Nu komt er een nieuwe requirement en die stelt dat in plaats van een mail er een sms moet worden verstuurd afhankelijk van de ingelogde gebruiker. Dit betekent dus dat Main moet worden aangepast.

In andere woorden: Main leunt op implementaties in plaats van abstractions. Wat hier het nadeel van is, is dat bij elke keer dat er een requirement bij komt, Main moet worden aangepast. Beter is om Main te vertellen waar hij het bericht heen moet sturen in plaats dat hij dat zelf uitzoekt:

public class Main()
{
  private readonly IExceptionMessenger _exceptionMessenger;

  public Main (IExceptionMessenger exceptionMessenger)
  {
    _exceptionMessenger = exceptionMessenger;
  }

  function OnException(Exception exception)
  {
    _exceptionMessenger.Send(exception);
  }
}

Wat je ziet is dat nu de dependency is omgedraaid. Main leunt niet langer meer op implementaties (concrete classes) maar op abstractions (interfaces/abstract classes). Dit is het Dependency Inversion Principle.

Het is belangrijk te beseffen dat op bovenstande manier een plugin structuur ontstaat. Er kunnen nu altijd nieuwe implementaties bijkomen zonder dat de Main hoeft te worden aangepast. Andere voorbeelden van plugins zijn bijvoorbeeld ook de UI en de database. De code moet leunen op abstractions en niet op implementaties van bijvoorbeeld een Web framework of een My Sql database. Als dat wel gebeurt en de application moet bijvoorbeeld ook kunnen draaien op een tablet, dan moet je dus hele stukken code gaan kopieren en plakken wat natuurlijk totaal niet wenselijk is.

Reacties

Populaire posts van deze blog

[SQL Server] varchar vs nvarchar

MS Sql 70-461: Chapter 5

[C#] Class serialiseren en deserialiseren