Skip to content

Instantly share code, notes, and snippets.

@kimek
Forked from dimabory/dep.md
Created May 3, 2024 07:33
Show Gist options
  • Save kimek/023b472770cd1518470fce1225eb67ed to your computer and use it in GitHub Desktop.
Save kimek/023b472770cd1518470fce1225eb67ed to your computer and use it in GitHub Desktop.
Dependency Elimination Principle

http://qualityisspeed.blogspot.com/2015/04/dependency-elimination-example-primitive-support.html

Primitive Support:

  1. A primitive type (int, string, etc) representing a domain concept (megabytes, phone number, etc).
  2. A helper class that does something meaningful with that primitive (e.g. MegabyteConverter or PhoneNumberParser or FooHelper).

A Simple Example: E-mail Address Validation

public class UserSignup
{
    public void Signup(string emailAddress, string password)
    {
        if (!EmailHelper.IsValidEmail(emailAddress))
            throw new InvalidEmailAddressException(emailAddress);

        // Do your signup magics
    }

}

public class EmailHelper
{
    public static bool IsValidEmail(string emailAddress)
    {
        // do your fancy string magics
    }
}

Sligthly Changed, But Better More Or Less:

public class UserSignup
{
    private IEmailValidator emailValidator;
    
    public UserSignup(IEmailValidator emailValidator) 
    {
        this.emailValidator = emailValidator;
    }
    
    public void Signup(string emailAddress, string password)
    {
        emailValidator.Validate(emailAddress);
        
        // Do your signup magics
    }
 
}
 
public interface IEmailValidator
{
    void Validate(string emailAddress);
}

public class EmailValidator : IEmailValidator
{
    public void Validate(string emailAddress)
    {
        if (!IsValid(emailAddress))
            throw new InvalidEmailAddressException(emailAddress);
    }
    
    private static bool IsValid(string emailAddress)
    {
        // do your fancy string magics
    }
}

There is still a cohesion problem: Email address validation is still a concern of UserSignup, and the validation implementation lives in its own EmailValidator world.

Kill the Primitive:

public class UserSignup
{
    public void Signup(EmailAddress emailAddress, string password)
    {
        // Do your signup magics
    }
 
}
 
public class EmailAddress
{
    private string value;
    
    public EmailAddress(string value)
    {
        if (!IsValid(value))
            throw new InvalidEmailAddressException(value);
            
        this.value = value
    }
    
    public static bool IsValid(string emailAddress)
    {
        // do your fancy string magics
    }
}
  1. We've completely separated the concerns. UserSignup has no validation calls or implementations. It just uses an EmailAddress like it should.
  2. We've improved cohesion. E-maily things live on EmailAddress. UserSignupy things live on UserSignup. No overlap.
  3. EmailAddress validation is now a compile-time concern. You can't make a bad one, so type-checking will guarantee that the thing you pass in is valid.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment