SlideShare ist ein Scribd-Unternehmen logo
1 von 82
by Jon Kruger
   Definition:

“A method of programming based on a hierarchy of
classes, and well-defined and cooperating objects.”

 The SOLID principles are principles of object-
oriented class design
   Your code is going to change
   Make your code more reusable (DRY)
   Testability
   Make our lives easier!
 Fewer bugs – it costs money to find bugs, fix
bugs, and clean up the mess created by bugs.
 More flexibility – since code will need to change, it
should be easy to change
   It costs money to develop software
   It costs money to fix bugs
   It costs money to make changes to software
Agile Software
Development
Principles, Patterns, and
Practices,
by Robert C. Martin (aka
“Uncle Bob” Martin)
Clean Code: A Handbook of
Agile Software Craftsmanship,
by Robert C. Martin (aka
“Uncle Bob” Martin)
   These are guidelines, not hard and fast rules
   Use your brain – do what makes sense
   Ask why
   Software should be:
     Easy to test
     Easy to change
     Easy to add features to
   Easy != not learning a new way of doing things
 Have only as much complexity as you need – have a
reason for complexity
 “I don’t want to learn this new way” != too complex
A class should have one, and only one, reason to
change.
public class Person
{
    private const decimal _minimumRequiredBalance = 10m;

    public string Name { get; set; }
    public decimal Balance { get; set; }

    public decimal AvailableFunds
    {
        get { return Balance - _minimumRequiredBalance; }
    }

    public void DeductFromBalanceBy(decimal amountToDeduct)
    {
        if (amountToDeduct > Balance)
            throw new InvalidOperationException(“Insufficient funds.”);

        Balance -= amountToDeduct;
    }
}
public class Account
{
    private const decimal _minimumRequiredBalance = 10m;

    public decimal Balance { get; set; }
    public IList<Person> AccountHolders { get; set; }

    public decimal AvailableFunds
    {
        get { return Balance - _minimumRequiredBalance; }
    }

    public void DeductFromBalanceBy(decimal amountToDeduct)
    {
        if (amountToDeduct > Balance)
            throw new InvalidOperationException(“Insufficient funds.”);

        Balance -= amountToDeduct;
    }
}
public class Person
{
    public string Name { get; set; }
    public Account Account { get; set; }

    public decimal AvailableFunds
    {
        get { return Account.AvailableFunds; }
    }

    public decimal AccountBalance
    {
        get { return Account.Balance; }
    }

    public void DeductFromBalanceBy(decimal amountToDeduct)
    {
        Account.DeductFromBalanceBy(amountToDeduct);
    }
}
public class OrderProcessingModule {
               public void Process(OrderStatusMessage orderStatusMessage) {
                // Get the connection string from configuration
SRP             string connectionString = ConfigurationManager.ConnectionStrings["Main"].ConnectionString;

                      Order order = null;
Violation -           using (SqlConnection connection = new SqlConnection(connectionString)) {

Spaghetti               // go get some data from the database
                        order = fetchData(orderStatusMessage, connection);
                      }
Code                  // Apply the changes to the Order from the OrderStatusMessage
                      updateTheOrder(order);

                      // International orders have a unique set of business rules
                      if (order.IsInternational)
                        processInternationalOrder(order);

                      // We need to treat larger orders in a special manner
                      else if (order.LineItems.Count > 10)
                        processLargeDomesticOrder(order);

                      // Smaller domestic orders
                      else
                        processRegularDomesticOrder(order);

                      // Ship the order if it's ready
                      if (order.IsReadyToShip()) {
                        ShippingGateway gateway = new ShippingGateway();

                       // Transform the Order object into a Shipment
                       ShipmentMessage message = createShipmentMessageForOrder(order);
                       gateway.SendShipment(message);
                  }
              }
UI

Business Logic (Domain Model)

        Data Access

            Database
public class OrderService
{
    public Order Get(int orderId) { ... }
    public Order Save(Order order) { ... }
    public Order SubmitOrder(Order order) { ... }
    public Order GetOrderByName(string name) { ... }
    public void CancelOrder(int orderId) { ... }
    public void ProcessOrderReturn(int orderId) { ... }
    public IList<Order> GetAllOrders { ... }
    public IList<Order> GetShippedOrders { ... }
    public void ShipOrder { ... }
}
Fill out the XML doc comments for the class – be
wary of words like if, and, but, except, when, etc.

/// <summary>
/// Gets, saves, and submits orders.
/// </summary>
public class OrderService
{
    public Order Get(int orderId) { ... }
    public Order Save(Order order) { ... }
    public Order SubmitOrder(Order order) { ... }
}
Domain services should have a verb in the class
name
public class GetOrderService
{
    public Order Get(int orderId) { ... }
}

public class SaveOrderService
{
    public Order Save(Order order) { ... }
}

public class SubmitOrderService
{
    public Order SubmitOrder(Order order) { ... }
}
   We want it to be easy to reuse code
   Big classes are more difficult to change
   Big classes are harder to read

Smaller classes and smaller methods will give you
more flexibility, and you don’t have to write much
extra code (if any) to do it!
 The violating class is not going to be reused and
other classes don’t depend on it
 The violating class does not have private fields that
store values that the class uses
 Your common sense says so
 Example: ASP.NET MVC controller classes, web
services
 Don’t code for situations that you won’t ever need
 Don’t create unneeded complexity
 However, more class files != more complicated
 Remember, this is supposed to make your lives
easier! (but not easier to be lazy)
 You can always refactor later (if you write tests)
  A method should have one purpose (reason to
change)
 Easier to read and write, which means you are less
likely to write bugs
 Write out the steps of a method using plain English
method names
public void SubmitOrder(Order order)
{
    // validate order
    if (order.Products.Count == 0)
    {
        throw new InvalidOperationException(
            "Select a product.");
    }

    // calculate tax
    order.Tax = order.Subtotal * 1.0675;

    // calculate shipping
    if (order.Subtotal < 25)
         order.ShippingCharges = 5;
    else
         order.ShippingCharges = 10;

    // submit order
    _orderSubmissionService.SubmitOrder(order);
}
public void SubmitOrder(Order order)
{
    ValidateOrder(order);
    CalculateTax(order);
    CalculateShipping(order);
    SendOrderToOrderSubmissionService(order);
}
public void SubmitOrder(Order order)
          {
              ValidateOrder(order);
Small         CalculateTax(order);
              CalculateShipping(order);
Methods   }
              SendOrderToOrderSubmissionService(order);


- After   public void ValidateOrder(Order order)
          {
              if (order.Products.Count == 0)
                  throw new InvalidOperationException("Select a product.");
          }

          public void CalculateTax(Order order)
          {
              order.Tax = order.Subtotal * 1.0675;
          }

          public void CalculateShipping(Order order)
          {
              if (order.Subtotal < 25)
                  order.ShippingCharges = 5;
              else
                  order.ShippingCharges = 10;
          }

          public void SendOrderToOrderSubmissionService(Order order)
          {
              _orderSubmissionService.SubmitOrder(order);
          }
Software entities (classes, modules, methods) should
be open for extension but closed for modification.
public class GetUserService
{
    public IList<UserSummary> FindUsers(UserSearchType type)
    {
        IList<User> users;
        switch (type)
        {
             case UserSearchType.AllUsers:
                 // load the “users” variable here
                 break;
             case UserSearchType.AllActiveUsers:
                 // load the “users” variable here
                 break;
             case UserSearchType.ActiveUsersThatCanEditQuotes:
                 // load the “users” variable here
                 break;
        }
        return ConvertToUserSummaries(users);
    }
}
public interface IUserQuery
{
    IList<User> FilterUsers(IList<User> allUsers);
}

public class GetUserService
{
    public IList<UserSummary> FindUsers(IUserQuery query)
    {
        IList<User> users = query.FilterUsers(GetAllUsers());
        return ConvertToUserSummaries(users);
    }
}
 Anytime you change code, you have the potential to
break it
 Sometimes you can’t change libraries (e.g. code that
isn’t yours)
 May have to change code in many different places
to add support for a certain type of situation
 When the number of options in the if or switch
statement is unlikely to change (e.g. switch on enum)
public void UpdateFontStyle (Paragraph paragraph)
{
    switch (IsBoldCheckBox.CheckState)
    {
        case CheckState.Checked:
            paragraph.IsBold = true;
            break;
        case CheckState.Unchecked:
            paragraph.IsBold = false;
            break;
        case CheckState.Indeterminate:
            break;
    }
}
  Use if/switch if the number of cases is unlikely to
change
 Use strategy pattern when the number of cases are
likely to change
 Always use common sense!
 Don’t code for situations that you won’t ever need
 Don’t create unneeded complexity
 However, more class files != more complicated
 Remember, this is supposed to make your lives
easier!
 You can always refactor later (if you write tests)
Functions that use references to base classes must be
able to use objects of derived classes without knowing
it.
public class Product
{
    public string Name { get; set; }
    public string Author { get; set; }
}

public class Book : Product    {}

public class Movie : Product    {}



If someone had a Product object (which was actually
a Movie) and asked for the Author, what should it do
(a Movie doesn’t have an Author)?
People using derived classes should not encounter
unexpected results when using your derived class.
public class MyList<T> : IList<T>
{
    private readonly List<T> _innerList = new List<T>();

    public void Add(T item)
    {
        if (_innerList.Contains(item))
            return;
        _innerList.Add(item);
    }

    public int Count
    {
        get { return _innerList.Count; }
    }
}
Throw exceptions for cases that you can’t support (still
not recommended)
public class Rectangle : Shape
{
    public double Width { get; set; }
    public double Height { get; set; }
    public override double Area
    {
        get { return Width * Height; }
    }
}

public class Cube : Shape
{
    public override double Area
    {
        get { throw new NotSupportedException(); }
    }
}
Clients should not be forced to depend on interfaces
that they do not use.
ASP.NET
MembershipProvider
class – a very “fat”
interface!
 If you implement an interface or derive from a base
class and you have to throw an exception in a method
because you don’t support it, the interface is probably
too big.
 Single Responsibility Principle for interfaces/base
classes
 If your interface has members that are not used by
some inheritors, those inheritors may be affected by
changes in the interface, even though the methods
that they use did not change.
   Why would you want to?
   Use common sense
High level modules should not depend on low level
modules. Both should depend on abstractions.

Abstractions should not depend on details. Details
should depend on abstractions.
 Two classes are “tightly coupled” if they are linked
together and are dependent on each other
 Tightly coupled classes can not work independent of
each other
 Makes changing one class difficult because it could
launch a wave of changes through tightly coupled
classes
UI

Business Logic (Domain Model)

        Data Access

            Database
UI
           Interfaces

Business Logic (Domain Model)
           Interfaces

        Data Access

            Database
 Each layer should not know anything about the
details of how the other layers work.
 Example: your domain model should not know how
data access is done – it shouldn’t know if you’re using
stored procedures, an ORM, etc.
 Tight coupling is bad – if your business layer
contains code related to data access, changes to how
data access is done will affect business logic
 Harder to test because you have to deal with
implementation details of something you’re not trying
to test
How do you know that your code is working?
How do you know that your code will continue to
work after you change it?
   Unit tests:
     Tests a small unit of functionality
     Mock or “fake out” external dependencies (e.g. databases)
     Run fast

   Integration tests:
     Test the whole system working together
     Can run slow
     Can be brittle
Stubs, mocks, and fakes in unit tests are only
possible when we have an interface to implement

The main reason for the Dependency Inversion
Principle is to help us write unit tests.
public class ProductRepository : IProductRepository
{
    public Product Get(int id) { ... }
}

public interface IProductRepository
{
    Product Get(int id);
}
public class GetProductService : IGetProductService
{
    private IProductRepository _productRepository;

    public GetProductService(
        IProductRepository productRepository)
    {
        _productRepository = productRepository;
    }

    public IList<Product> GetProductById(int id)
    {
        return _productRepository.Get(id);
    }
}
   Use of “new”

    public class GetProductService
    {
        public IList<Product> GetProductById(int id)
        {
            var productRepository = new ProductRepository();
            return productRepository.Get(id);
        }
    }
   Use of “static”

    public class SecurityService
    {
        public static User GetCurrentUser()
        {
            // do something
        }
    }
   Use of singletons using “static”

    public class ProductCache
    {
        private static readonly _instance = new ProductCache();
        public static ProductCache Instance
        {
            get { return _instance; }
        }
    }
public class GetProductService : IGetProductService
{
    private IProductRepository _productRepository;

    public GetProductService(
        IProductRepository productRepository)
    {
        _productRepository = productRepository;
    }

    public IList<Product> GetProductById(int id)
    {
        return _productRepository.Get(id);
    }
}


Problem: How do we create these objects?
 Creates objects that are ready for you to use
 Knows how to create objects and their
dependencies
 Knows how to initialize objects when they are
created (if necessary)
 Popular .NET choices:
   StructureMap, Ninject
 Other .NET choices:
   Unity, Castle Windsor, Autofac, Spring .NET
 Java
   Spring
 Ruby
   We don’t need no stinkin’ DI containers!
ObjectFactory.Initialize(x =>
{
    x.For<IGetProductService>().Use<GetProductService>();
});
ObjectFactory.Initialize(x =>
{
    x.Scan(scan =>
    {
        scan.WithDefaultConventions();
        scan.AssemblyContainingType<IProductRepository>();
    });
});



 Automatically map “ISomething” interface to
“Something” class
ObjectFactory.Initialize(x =>
{
    x.For<IProductRepository>()
     .Use<ProductRepository>()
     .OnCreation(repository =>
         repository.ConnectionString =
         ConfigurationManager.AppSettings["MainDB"]);
});


 We just reduced duplication and complexity by
setting this up here!
ObjectFactory.Initialize(x =>
{
    x.ForSingletonOf<IProductCache>().Use<ProductCache>();
});




   There will only ever be one IProductCache
   We don’t violate DIP by having static variables
ObjectFactory.Initialize(x =>
{
    x.For<ICurrentUser>()
     .Use(c => new CurrentUser(Thread.CurrentPrincipal));
});




Testing will be easier because we won’t reference
Thread.CurrentPrincipal
   Don’t “new” up anything that is a dependency
       Don’t new up classes that you want to create a fake for in a test
       Do new up entity objects
       Do new up value types (e.g. string, DateTime, etc.)
       Do new up .NET Framework types (e.g. SqlConnection)
  Entity objects should not have dependencies
  If you have to have static variables, isolate them
behind the DI container (e.g. example in previous
slide)
 Use ObjectFactory.GetInstance() to create objects
when you can’t take them in as constructor
parameters
 Don’t use the DI container when writing unit tests
USE YOUR BRAIN!!!!
   Uncle Bob’s SOLID articles
     http://bit.ly/solid1
   Uncle Bob talking about SOLID on Hanselminutes
     http://bit.ly/solid2
   My slides
     http://bit.ly/solid3
   ALT.NET mailing list
     http://bit.ly/solid4

My Info:
email: jon@jonkruger.com
twitter: @jonkruger / blog: http://jonkruger.com/blog
TDD training: http://tddbootcamp.com

Weitere ähnliche Inhalte

Was ist angesagt?

Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...go_oh
 
Developing application for Windows Phone 7 in TDD
Developing application for Windows Phone 7 in TDDDeveloping application for Windows Phone 7 in TDD
Developing application for Windows Phone 7 in TDDMichele Capra
 
Design Patterns in PHP5
Design Patterns in PHP5 Design Patterns in PHP5
Design Patterns in PHP5 Wildan Maulana
 
Backbone js
Backbone jsBackbone js
Backbone jsrstankov
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Railsrstankov
 
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and JasmineRails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and JasmineRaimonds Simanovskis
 
Design Patterns Reconsidered
Design Patterns ReconsideredDesign Patterns Reconsidered
Design Patterns ReconsideredAlex Miller
 
Powerful JavaScript Tips and Best Practices
Powerful JavaScript Tips and Best PracticesPowerful JavaScript Tips and Best Practices
Powerful JavaScript Tips and Best PracticesDragos Ionita
 
Java Script Promise
Java Script PromiseJava Script Promise
Java Script PromiseAlok Guha
 
Understanding Asynchronous JavaScript
Understanding Asynchronous JavaScriptUnderstanding Asynchronous JavaScript
Understanding Asynchronous JavaScriptjnewmanux
 
Art of Javascript
Art of JavascriptArt of Javascript
Art of JavascriptTarek Yehia
 
FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6Dmitry Soshnikov
 
Hacking hhvm
Hacking hhvmHacking hhvm
Hacking hhvmwajrcs
 
Node.js in action
Node.js in actionNode.js in action
Node.js in actionSimon Su
 
Building a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing StrategiesBuilding a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing StrategiesCiaranMcNulty
 

Was ist angesagt? (20)

Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...
 
Developing application for Windows Phone 7 in TDD
Developing application for Windows Phone 7 in TDDDeveloping application for Windows Phone 7 in TDD
Developing application for Windows Phone 7 in TDD
 
The IoC Hydra
The IoC HydraThe IoC Hydra
The IoC Hydra
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript Promises
 
Design Patterns in PHP5
Design Patterns in PHP5 Design Patterns in PHP5
Design Patterns in PHP5
 
Backbone js
Backbone jsBackbone js
Backbone js
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Rails
 
Why ruby
Why rubyWhy ruby
Why ruby
 
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and JasmineRails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
 
SOLID Principles
SOLID PrinciplesSOLID Principles
SOLID Principles
 
Design Patterns Reconsidered
Design Patterns ReconsideredDesign Patterns Reconsidered
Design Patterns Reconsidered
 
Powerful JavaScript Tips and Best Practices
Powerful JavaScript Tips and Best PracticesPowerful JavaScript Tips and Best Practices
Powerful JavaScript Tips and Best Practices
 
Java Script Promise
Java Script PromiseJava Script Promise
Java Script Promise
 
Understanding Asynchronous JavaScript
Understanding Asynchronous JavaScriptUnderstanding Asynchronous JavaScript
Understanding Asynchronous JavaScript
 
Art of Javascript
Art of JavascriptArt of Javascript
Art of Javascript
 
Rails on Oracle 2011
Rails on Oracle 2011Rails on Oracle 2011
Rails on Oracle 2011
 
FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6
 
Hacking hhvm
Hacking hhvmHacking hhvm
Hacking hhvm
 
Node.js in action
Node.js in actionNode.js in action
Node.js in action
 
Building a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing StrategiesBuilding a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing Strategies
 

Andere mochten auch

software design principles
software design principlessoftware design principles
software design principlesCristal Ngo
 
Presentation on SOLID design principles
Presentation on SOLID design principlesPresentation on SOLID design principles
Presentation on SOLID design principlesKostadin Golev
 
SOLID Design Principles
SOLID Design PrinciplesSOLID Design Principles
SOLID Design PrinciplesAndreas Enbohm
 
SOLID Principles and Design Patterns
SOLID Principles and Design PatternsSOLID Principles and Design Patterns
SOLID Principles and Design PatternsGanesh Samarthyam
 
Are You a SOLID Coder?
Are You a SOLID Coder?Are You a SOLID Coder?
Are You a SOLID Coder?Steve Green
 
SOLID Design Principles
SOLID Design PrinciplesSOLID Design Principles
SOLID Design PrinciplesSamuel Breed
 
Introduction to SOLID Principles
Introduction to SOLID PrinciplesIntroduction to SOLID Principles
Introduction to SOLID PrinciplesGanesh Samarthyam
 
Geecon09: SOLID Design Principles
Geecon09: SOLID Design PrinciplesGeecon09: SOLID Design Principles
Geecon09: SOLID Design PrinciplesBruno Bossola
 
Solid principles of oo design
Solid principles of oo designSolid principles of oo design
Solid principles of oo designConfiz
 
SOLID - Principles of Object Oriented Design
SOLID - Principles of Object Oriented DesignSOLID - Principles of Object Oriented Design
SOLID - Principles of Object Oriented DesignRiccardo Cardin
 

Andere mochten auch (15)

SOLID principles
SOLID principlesSOLID principles
SOLID principles
 
software design principles
software design principlessoftware design principles
software design principles
 
SOLID Principles
SOLID PrinciplesSOLID Principles
SOLID Principles
 
Presentation on SOLID design principles
Presentation on SOLID design principlesPresentation on SOLID design principles
Presentation on SOLID design principles
 
SOLID Design Principles
SOLID Design PrinciplesSOLID Design Principles
SOLID Design Principles
 
SOLID Principles and Design Patterns
SOLID Principles and Design PatternsSOLID Principles and Design Patterns
SOLID Principles and Design Patterns
 
SOLID Principles
SOLID PrinciplesSOLID Principles
SOLID Principles
 
Are You a SOLID Coder?
Are You a SOLID Coder?Are You a SOLID Coder?
Are You a SOLID Coder?
 
SOLID Design Principles
SOLID Design PrinciplesSOLID Design Principles
SOLID Design Principles
 
SOLID principles
SOLID principlesSOLID principles
SOLID principles
 
Introduction to SOLID Principles
Introduction to SOLID PrinciplesIntroduction to SOLID Principles
Introduction to SOLID Principles
 
Geecon09: SOLID Design Principles
Geecon09: SOLID Design PrinciplesGeecon09: SOLID Design Principles
Geecon09: SOLID Design Principles
 
SOLID Principles part 2
SOLID Principles part 2SOLID Principles part 2
SOLID Principles part 2
 
Solid principles of oo design
Solid principles of oo designSolid principles of oo design
Solid principles of oo design
 
SOLID - Principles of Object Oriented Design
SOLID - Principles of Object Oriented DesignSOLID - Principles of Object Oriented Design
SOLID - Principles of Object Oriented Design
 

Ähnlich wie Solid Software Design Principles

SOLID - Not Just a State of Matter, It's Principles for OO Propriety
SOLID - Not Just a State of Matter, It's Principles for OO ProprietySOLID - Not Just a State of Matter, It's Principles for OO Propriety
SOLID - Not Just a State of Matter, It's Principles for OO ProprietyChris Weldon
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For BeginnersJonathan Wage
 
The uniform interface is 42
The uniform interface is 42The uniform interface is 42
The uniform interface is 42Yevhen Bobrov
 
That’s My App - Running in Your Background - Draining Your Battery
That’s My App - Running in Your Background - Draining Your BatteryThat’s My App - Running in Your Background - Draining Your Battery
That’s My App - Running in Your Background - Draining Your BatteryMichael Galpin
 
CDI e as ideias pro futuro do VRaptor
CDI e as ideias pro futuro do VRaptorCDI e as ideias pro futuro do VRaptor
CDI e as ideias pro futuro do VRaptorCaelum
 
Real Life Clean Architecture
Real Life Clean ArchitectureReal Life Clean Architecture
Real Life Clean ArchitectureMattia Battiston
 
Combatendo code smells em Java
Combatendo code smells em Java Combatendo code smells em Java
Combatendo code smells em Java Emmanuel Neri
 
比XML更好用的Java Annotation
比XML更好用的Java Annotation比XML更好用的Java Annotation
比XML更好用的Java Annotationjavatwo2011
 
Imagine a world without mocks
Imagine a world without mocksImagine a world without mocks
Imagine a world without mockskenbot
 
Pragmatic Functional Refactoring with Java 8
Pragmatic Functional Refactoring with Java 8Pragmatic Functional Refactoring with Java 8
Pragmatic Functional Refactoring with Java 8Codemotion
 
Advanced #2 networking
Advanced #2   networkingAdvanced #2   networking
Advanced #2 networkingVitali Pekelis
 
May 2010 - RestEasy
May 2010 - RestEasyMay 2010 - RestEasy
May 2010 - RestEasyJBug Italy
 
TDC2017 | São Paulo - Trilha Android How we figured out we had a SRE team at ...
TDC2017 | São Paulo - Trilha Android How we figured out we had a SRE team at ...TDC2017 | São Paulo - Trilha Android How we figured out we had a SRE team at ...
TDC2017 | São Paulo - Trilha Android How we figured out we had a SRE team at ...tdc-globalcode
 

Ähnlich wie Solid Software Design Principles (20)

SOLID - Not Just a State of Matter, It's Principles for OO Propriety
SOLID - Not Just a State of Matter, It's Principles for OO ProprietySOLID - Not Just a State of Matter, It's Principles for OO Propriety
SOLID - Not Just a State of Matter, It's Principles for OO Propriety
 
Nancy + rest mow2012
Nancy + rest   mow2012Nancy + rest   mow2012
Nancy + rest mow2012
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
SOLID
SOLIDSOLID
SOLID
 
The uniform interface is 42
The uniform interface is 42The uniform interface is 42
The uniform interface is 42
 
That’s My App - Running in Your Background - Draining Your Battery
That’s My App - Running in Your Background - Draining Your BatteryThat’s My App - Running in Your Background - Draining Your Battery
That’s My App - Running in Your Background - Draining Your Battery
 
CDI e as ideias pro futuro do VRaptor
CDI e as ideias pro futuro do VRaptorCDI e as ideias pro futuro do VRaptor
CDI e as ideias pro futuro do VRaptor
 
Real Life Clean Architecture
Real Life Clean ArchitectureReal Life Clean Architecture
Real Life Clean Architecture
 
Combatendo code smells em Java
Combatendo code smells em Java Combatendo code smells em Java
Combatendo code smells em Java
 
Bot builder v4 HOL
Bot builder v4 HOLBot builder v4 HOL
Bot builder v4 HOL
 
比XML更好用的Java Annotation
比XML更好用的Java Annotation比XML更好用的Java Annotation
比XML更好用的Java Annotation
 
Imagine a world without mocks
Imagine a world without mocksImagine a world without mocks
Imagine a world without mocks
 
Pragmatic Functional Refactoring with Java 8
Pragmatic Functional Refactoring with Java 8Pragmatic Functional Refactoring with Java 8
Pragmatic Functional Refactoring with Java 8
 
JDK Power Tools
JDK Power ToolsJDK Power Tools
JDK Power Tools
 
SOLID Principles
SOLID PrinciplesSOLID Principles
SOLID Principles
 
RESTEasy
RESTEasyRESTEasy
RESTEasy
 
Advanced #2 networking
Advanced #2   networkingAdvanced #2   networking
Advanced #2 networking
 
May 2010 - RestEasy
May 2010 - RestEasyMay 2010 - RestEasy
May 2010 - RestEasy
 
TDC2017 | São Paulo - Trilha Android How we figured out we had a SRE team at ...
TDC2017 | São Paulo - Trilha Android How we figured out we had a SRE team at ...TDC2017 | São Paulo - Trilha Android How we figured out we had a SRE team at ...
TDC2017 | São Paulo - Trilha Android How we figured out we had a SRE team at ...
 
Gwt and Xtend
Gwt and XtendGwt and Xtend
Gwt and Xtend
 

Mehr von Jon Kruger

The Business of You: 10 Steps To Run Your Career Like a Business
The Business of You: 10 Steps To Run Your Career Like a BusinessThe Business of You: 10 Steps To Run Your Career Like a Business
The Business of You: 10 Steps To Run Your Career Like a BusinessJon Kruger
 
Developing an Automated Testing Strategy
Developing an Automated Testing StrategyDeveloping an Automated Testing Strategy
Developing an Automated Testing StrategyJon Kruger
 
A Whole Team Approach To Testing
A Whole Team Approach To TestingA Whole Team Approach To Testing
A Whole Team Approach To TestingJon Kruger
 
An ATDD Case Study
An ATDD Case StudyAn ATDD Case Study
An ATDD Case StudyJon Kruger
 
Productivity Boosters for .NET Developers
Productivity Boosters for .NET DevelopersProductivity Boosters for .NET Developers
Productivity Boosters for .NET DevelopersJon Kruger
 
Test-Driven Development In Action
Test-Driven Development In ActionTest-Driven Development In Action
Test-Driven Development In ActionJon Kruger
 
Advanced Object-Oriented/SOLID Principles
Advanced Object-Oriented/SOLID PrinciplesAdvanced Object-Oriented/SOLID Principles
Advanced Object-Oriented/SOLID PrinciplesJon Kruger
 

Mehr von Jon Kruger (7)

The Business of You: 10 Steps To Run Your Career Like a Business
The Business of You: 10 Steps To Run Your Career Like a BusinessThe Business of You: 10 Steps To Run Your Career Like a Business
The Business of You: 10 Steps To Run Your Career Like a Business
 
Developing an Automated Testing Strategy
Developing an Automated Testing StrategyDeveloping an Automated Testing Strategy
Developing an Automated Testing Strategy
 
A Whole Team Approach To Testing
A Whole Team Approach To TestingA Whole Team Approach To Testing
A Whole Team Approach To Testing
 
An ATDD Case Study
An ATDD Case StudyAn ATDD Case Study
An ATDD Case Study
 
Productivity Boosters for .NET Developers
Productivity Boosters for .NET DevelopersProductivity Boosters for .NET Developers
Productivity Boosters for .NET Developers
 
Test-Driven Development In Action
Test-Driven Development In ActionTest-Driven Development In Action
Test-Driven Development In Action
 
Advanced Object-Oriented/SOLID Principles
Advanced Object-Oriented/SOLID PrinciplesAdvanced Object-Oriented/SOLID Principles
Advanced Object-Oriented/SOLID Principles
 

Kürzlich hochgeladen

Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGSujit Pal
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 

Kürzlich hochgeladen (20)

Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAG
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 

Solid Software Design Principles

  • 2. Definition: “A method of programming based on a hierarchy of classes, and well-defined and cooperating objects.”  The SOLID principles are principles of object- oriented class design
  • 3.
  • 4.
  • 5. Your code is going to change  Make your code more reusable (DRY)  Testability  Make our lives easier!
  • 6.  Fewer bugs – it costs money to find bugs, fix bugs, and clean up the mess created by bugs.  More flexibility – since code will need to change, it should be easy to change
  • 7.
  • 8. It costs money to develop software  It costs money to fix bugs  It costs money to make changes to software
  • 9. Agile Software Development Principles, Patterns, and Practices, by Robert C. Martin (aka “Uncle Bob” Martin)
  • 10. Clean Code: A Handbook of Agile Software Craftsmanship, by Robert C. Martin (aka “Uncle Bob” Martin)
  • 11. These are guidelines, not hard and fast rules  Use your brain – do what makes sense  Ask why
  • 12. Software should be:  Easy to test  Easy to change  Easy to add features to  Easy != not learning a new way of doing things
  • 13.  Have only as much complexity as you need – have a reason for complexity  “I don’t want to learn this new way” != too complex
  • 14. A class should have one, and only one, reason to change.
  • 15.
  • 16. public class Person { private const decimal _minimumRequiredBalance = 10m; public string Name { get; set; } public decimal Balance { get; set; } public decimal AvailableFunds { get { return Balance - _minimumRequiredBalance; } } public void DeductFromBalanceBy(decimal amountToDeduct) { if (amountToDeduct > Balance) throw new InvalidOperationException(“Insufficient funds.”); Balance -= amountToDeduct; } }
  • 17. public class Account { private const decimal _minimumRequiredBalance = 10m; public decimal Balance { get; set; } public IList<Person> AccountHolders { get; set; } public decimal AvailableFunds { get { return Balance - _minimumRequiredBalance; } } public void DeductFromBalanceBy(decimal amountToDeduct) { if (amountToDeduct > Balance) throw new InvalidOperationException(“Insufficient funds.”); Balance -= amountToDeduct; } }
  • 18. public class Person { public string Name { get; set; } public Account Account { get; set; } public decimal AvailableFunds { get { return Account.AvailableFunds; } } public decimal AccountBalance { get { return Account.Balance; } } public void DeductFromBalanceBy(decimal amountToDeduct) { Account.DeductFromBalanceBy(amountToDeduct); } }
  • 19. public class OrderProcessingModule { public void Process(OrderStatusMessage orderStatusMessage) { // Get the connection string from configuration SRP string connectionString = ConfigurationManager.ConnectionStrings["Main"].ConnectionString; Order order = null; Violation - using (SqlConnection connection = new SqlConnection(connectionString)) { Spaghetti // go get some data from the database order = fetchData(orderStatusMessage, connection); } Code // Apply the changes to the Order from the OrderStatusMessage updateTheOrder(order); // International orders have a unique set of business rules if (order.IsInternational) processInternationalOrder(order); // We need to treat larger orders in a special manner else if (order.LineItems.Count > 10) processLargeDomesticOrder(order); // Smaller domestic orders else processRegularDomesticOrder(order); // Ship the order if it's ready if (order.IsReadyToShip()) { ShippingGateway gateway = new ShippingGateway(); // Transform the Order object into a Shipment ShipmentMessage message = createShipmentMessageForOrder(order); gateway.SendShipment(message); } }
  • 20. UI Business Logic (Domain Model) Data Access Database
  • 21. public class OrderService { public Order Get(int orderId) { ... } public Order Save(Order order) { ... } public Order SubmitOrder(Order order) { ... } public Order GetOrderByName(string name) { ... } public void CancelOrder(int orderId) { ... } public void ProcessOrderReturn(int orderId) { ... } public IList<Order> GetAllOrders { ... } public IList<Order> GetShippedOrders { ... } public void ShipOrder { ... } }
  • 22. Fill out the XML doc comments for the class – be wary of words like if, and, but, except, when, etc. /// <summary> /// Gets, saves, and submits orders. /// </summary> public class OrderService { public Order Get(int orderId) { ... } public Order Save(Order order) { ... } public Order SubmitOrder(Order order) { ... } }
  • 23. Domain services should have a verb in the class name public class GetOrderService { public Order Get(int orderId) { ... } } public class SaveOrderService { public Order Save(Order order) { ... } } public class SubmitOrderService { public Order SubmitOrder(Order order) { ... } }
  • 24. We want it to be easy to reuse code  Big classes are more difficult to change  Big classes are harder to read Smaller classes and smaller methods will give you more flexibility, and you don’t have to write much extra code (if any) to do it!
  • 25.  The violating class is not going to be reused and other classes don’t depend on it  The violating class does not have private fields that store values that the class uses  Your common sense says so  Example: ASP.NET MVC controller classes, web services
  • 26.  Don’t code for situations that you won’t ever need  Don’t create unneeded complexity  However, more class files != more complicated  Remember, this is supposed to make your lives easier! (but not easier to be lazy)  You can always refactor later (if you write tests)
  • 27.
  • 28.  A method should have one purpose (reason to change)  Easier to read and write, which means you are less likely to write bugs  Write out the steps of a method using plain English method names
  • 29. public void SubmitOrder(Order order) { // validate order if (order.Products.Count == 0) { throw new InvalidOperationException( "Select a product."); } // calculate tax order.Tax = order.Subtotal * 1.0675; // calculate shipping if (order.Subtotal < 25) order.ShippingCharges = 5; else order.ShippingCharges = 10; // submit order _orderSubmissionService.SubmitOrder(order); }
  • 30. public void SubmitOrder(Order order) { ValidateOrder(order); CalculateTax(order); CalculateShipping(order); SendOrderToOrderSubmissionService(order); }
  • 31. public void SubmitOrder(Order order) { ValidateOrder(order); Small CalculateTax(order); CalculateShipping(order); Methods } SendOrderToOrderSubmissionService(order); - After public void ValidateOrder(Order order) { if (order.Products.Count == 0) throw new InvalidOperationException("Select a product."); } public void CalculateTax(Order order) { order.Tax = order.Subtotal * 1.0675; } public void CalculateShipping(Order order) { if (order.Subtotal < 25) order.ShippingCharges = 5; else order.ShippingCharges = 10; } public void SendOrderToOrderSubmissionService(Order order) { _orderSubmissionService.SubmitOrder(order); }
  • 32.
  • 33. Software entities (classes, modules, methods) should be open for extension but closed for modification.
  • 34.
  • 35. public class GetUserService { public IList<UserSummary> FindUsers(UserSearchType type) { IList<User> users; switch (type) { case UserSearchType.AllUsers: // load the “users” variable here break; case UserSearchType.AllActiveUsers: // load the “users” variable here break; case UserSearchType.ActiveUsersThatCanEditQuotes: // load the “users” variable here break; } return ConvertToUserSummaries(users); } }
  • 36. public interface IUserQuery { IList<User> FilterUsers(IList<User> allUsers); } public class GetUserService { public IList<UserSummary> FindUsers(IUserQuery query) { IList<User> users = query.FilterUsers(GetAllUsers()); return ConvertToUserSummaries(users); } }
  • 37.  Anytime you change code, you have the potential to break it  Sometimes you can’t change libraries (e.g. code that isn’t yours)  May have to change code in many different places to add support for a certain type of situation
  • 38.  When the number of options in the if or switch statement is unlikely to change (e.g. switch on enum) public void UpdateFontStyle (Paragraph paragraph) { switch (IsBoldCheckBox.CheckState) { case CheckState.Checked: paragraph.IsBold = true; break; case CheckState.Unchecked: paragraph.IsBold = false; break; case CheckState.Indeterminate: break; } }
  • 39.  Use if/switch if the number of cases is unlikely to change  Use strategy pattern when the number of cases are likely to change  Always use common sense!
  • 40.  Don’t code for situations that you won’t ever need  Don’t create unneeded complexity  However, more class files != more complicated  Remember, this is supposed to make your lives easier!  You can always refactor later (if you write tests)
  • 41.
  • 42. Functions that use references to base classes must be able to use objects of derived classes without knowing it.
  • 43.
  • 44. public class Product { public string Name { get; set; } public string Author { get; set; } } public class Book : Product {} public class Movie : Product {} If someone had a Product object (which was actually a Movie) and asked for the Author, what should it do (a Movie doesn’t have an Author)?
  • 45. People using derived classes should not encounter unexpected results when using your derived class.
  • 46. public class MyList<T> : IList<T> { private readonly List<T> _innerList = new List<T>(); public void Add(T item) { if (_innerList.Contains(item)) return; _innerList.Add(item); } public int Count { get { return _innerList.Count; } } }
  • 47. Throw exceptions for cases that you can’t support (still not recommended) public class Rectangle : Shape { public double Width { get; set; } public double Height { get; set; } public override double Area { get { return Width * Height; } } } public class Cube : Shape { public override double Area { get { throw new NotSupportedException(); } } }
  • 48.
  • 49. Clients should not be forced to depend on interfaces that they do not use.
  • 50.
  • 51. ASP.NET MembershipProvider class – a very “fat” interface!
  • 52.  If you implement an interface or derive from a base class and you have to throw an exception in a method because you don’t support it, the interface is probably too big.
  • 53.  Single Responsibility Principle for interfaces/base classes  If your interface has members that are not used by some inheritors, those inheritors may be affected by changes in the interface, even though the methods that they use did not change.
  • 54. Why would you want to?  Use common sense
  • 55.
  • 56. High level modules should not depend on low level modules. Both should depend on abstractions. Abstractions should not depend on details. Details should depend on abstractions.
  • 57.
  • 58.  Two classes are “tightly coupled” if they are linked together and are dependent on each other  Tightly coupled classes can not work independent of each other  Makes changing one class difficult because it could launch a wave of changes through tightly coupled classes
  • 59. UI Business Logic (Domain Model) Data Access Database
  • 60. UI Interfaces Business Logic (Domain Model) Interfaces Data Access Database
  • 61.  Each layer should not know anything about the details of how the other layers work.  Example: your domain model should not know how data access is done – it shouldn’t know if you’re using stored procedures, an ORM, etc.
  • 62.  Tight coupling is bad – if your business layer contains code related to data access, changes to how data access is done will affect business logic  Harder to test because you have to deal with implementation details of something you’re not trying to test
  • 63. How do you know that your code is working? How do you know that your code will continue to work after you change it?
  • 64. Unit tests:  Tests a small unit of functionality  Mock or “fake out” external dependencies (e.g. databases)  Run fast  Integration tests:  Test the whole system working together  Can run slow  Can be brittle
  • 65. Stubs, mocks, and fakes in unit tests are only possible when we have an interface to implement The main reason for the Dependency Inversion Principle is to help us write unit tests.
  • 66. public class ProductRepository : IProductRepository { public Product Get(int id) { ... } } public interface IProductRepository { Product Get(int id); }
  • 67. public class GetProductService : IGetProductService { private IProductRepository _productRepository; public GetProductService( IProductRepository productRepository) { _productRepository = productRepository; } public IList<Product> GetProductById(int id) { return _productRepository.Get(id); } }
  • 68. Use of “new” public class GetProductService { public IList<Product> GetProductById(int id) { var productRepository = new ProductRepository(); return productRepository.Get(id); } }
  • 69. Use of “static” public class SecurityService { public static User GetCurrentUser() { // do something } }
  • 70. Use of singletons using “static” public class ProductCache { private static readonly _instance = new ProductCache(); public static ProductCache Instance { get { return _instance; } } }
  • 71. public class GetProductService : IGetProductService { private IProductRepository _productRepository; public GetProductService( IProductRepository productRepository) { _productRepository = productRepository; } public IList<Product> GetProductById(int id) { return _productRepository.Get(id); } } Problem: How do we create these objects?
  • 72.  Creates objects that are ready for you to use  Knows how to create objects and their dependencies  Knows how to initialize objects when they are created (if necessary)
  • 73.  Popular .NET choices:  StructureMap, Ninject  Other .NET choices:  Unity, Castle Windsor, Autofac, Spring .NET  Java  Spring  Ruby  We don’t need no stinkin’ DI containers!
  • 74. ObjectFactory.Initialize(x => { x.For<IGetProductService>().Use<GetProductService>(); });
  • 75. ObjectFactory.Initialize(x => { x.Scan(scan => { scan.WithDefaultConventions(); scan.AssemblyContainingType<IProductRepository>(); }); });  Automatically map “ISomething” interface to “Something” class
  • 76. ObjectFactory.Initialize(x => { x.For<IProductRepository>() .Use<ProductRepository>() .OnCreation(repository => repository.ConnectionString = ConfigurationManager.AppSettings["MainDB"]); });  We just reduced duplication and complexity by setting this up here!
  • 77. ObjectFactory.Initialize(x => { x.ForSingletonOf<IProductCache>().Use<ProductCache>(); });  There will only ever be one IProductCache  We don’t violate DIP by having static variables
  • 78. ObjectFactory.Initialize(x => { x.For<ICurrentUser>() .Use(c => new CurrentUser(Thread.CurrentPrincipal)); }); Testing will be easier because we won’t reference Thread.CurrentPrincipal
  • 79. Don’t “new” up anything that is a dependency  Don’t new up classes that you want to create a fake for in a test  Do new up entity objects  Do new up value types (e.g. string, DateTime, etc.)  Do new up .NET Framework types (e.g. SqlConnection)  Entity objects should not have dependencies  If you have to have static variables, isolate them behind the DI container (e.g. example in previous slide)  Use ObjectFactory.GetInstance() to create objects when you can’t take them in as constructor parameters  Don’t use the DI container when writing unit tests
  • 80.
  • 82. Uncle Bob’s SOLID articles  http://bit.ly/solid1  Uncle Bob talking about SOLID on Hanselminutes  http://bit.ly/solid2  My slides  http://bit.ly/solid3  ALT.NET mailing list  http://bit.ly/solid4 My Info: email: jon@jonkruger.com twitter: @jonkruger / blog: http://jonkruger.com/blog TDD training: http://tddbootcamp.com

Hinweis der Redaktion

  1. Each of these Legos have a very specific purpose and a way to interact with each other. Using these simple blocks, you can create amazing Lego structures.
  2. -Imagine if some of our Lego blocks were missing the pins on the top, some were very weird shapes, some couldn’t attach anything to the bottom, some were glued together, etc. – if would be really hard to build different things with them or change what we were building
  3. DRY – if you write less code, you will write less bugs (and you have to do less work)Good software design and testing go hand in hand – testable code is usually well designed code (and vice versa)
  4. I will try to explain situations where (I think) you can not follow these principlesThe goal is to make software development easier. This DOES NOT mean that you shouldn’t follow these principles just because you don’t understand it or don’t know how to do it. Try to understand why you are doing things the way you are doing it. Do what makes sense to you – but make sure you do your homework and make sure you are doing the right thingDon’t just do something because someone says you should – learn why you should do it that way (they could be wrong)You should be able to explain why you made a decision – not “Microsoft told me to do it” or “someone says this is the right way to do it” or “this is how we’ve always done it in the past” Have seen projects that took these principles to extremes, or added unnecessary complexity without knowing why they were doing it, and the project suffered or failed because of it
  5. If you’re not willing to use a technology because you’re not willing to learn something new, that is a big problem not saying that you need to spend all of your time outside of work learning new stuff be open to change and new ideas
  6. - Imagine trying to use this thing! It can do everything you want, but doing what you want will be difficult.
  7. - What happens if the requirements change and now you can have a joint account that is held by two people?
  8. - Person still has methods and properties dealing with accounts, but now all of the account logic is correctly encapsulated in the Account class
  9. - small, useful Lego blocks instead of oddly-shaped ones
  10. Explain what a domain service is – not a web service
  11. - This is not added complexity – I’m not writing any more code than I did when it was all one class
  12. Big classes are harder to read, write, change, or testBig classes often mean tight coupling, so it’s difficult to change one part of the class without affecting the other parts of it
  13. - Common sense – go with your gut – don’t sit there for half an hour trying to figure out if a class violates SRP. If you can’t make a decision, just leave it how it is, you can come back and refactor later if you need to.
  14. - What is this method doing? You can figure it out, but you have to read it carefully and figure out what’s going on, even for this simple example.
  15. - What is this method doing? Even a non-programmer could tell you!
  16. - When you’re writing a one line method, it’s a lot easier because you can concentrate on what that one line is supposed to do… you don’t have to think about the overall flow and logic of what you’re trying to do overall
  17. - We are trying to do 2 things here – find subsets of users, and return user summaries
  18. Now the IUserQuery is responsible for filtering the users, and the FindUsers() method is only responsible for return user summaries for a list of users We can reuse the IUserQuery in other places, and now we don’t have to modify GetUserService.FindUsers() in order to create a new type of query.
  19. - Comments that say “if you want to add another X, you have to add code in these 5 places”
  20. - Probably need a 2DShape and 3DShape base class
  21. - Example – going to a friend’s house and they have the complicated home theater system and you want to watch TV
  22. - example: I want to test my validation code. I just want to test the validation logic, so why should I have to actually save something to the database to do this?
  23. Java: SpringRuby: we don’t need no stinkin’ DI containers!