SlideShare a Scribd company logo
1 of 120
Download to read offline
by Jon Kruger
 The principles that we will discuss today will help
you write better code in ANY language that you use
 Because you can never completely master object-
oriented programming
 Practice makes perfect, so we’re going to practice
Advanced Object-Oriented/SOLID Principles
Advanced Object-Oriented/SOLID Principles
 A software development technique where you write
automated unit tests before you write your
implementation code
 A technique for ensuring good quality and good
design
 Awesome!
Productivity




Time
Advanced Object-Oriented/SOLID Principles
 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
Advanced Object-Oriented/SOLID Principles
   Definition:

“A method of programming based on a hierarchy of
classes, and well-defined and cooperating objects.”
Advanced Object-Oriented/SOLID Principles
Advanced Object-Oriented/SOLID Principles
OBJECT-ORIENTED PROGRAMMING     PROCEDURAL PROGRAMMING
 Collaboration between          A series of
objects that send and receive   functions, subroutines, or
messages with each other        tasks

 Functionality is grouped by
object                           Functionality is grouped by
                                task
 Objects and their behavior
can be reused                    Functions/subroutines/tasks
                                can be reused
   .NET, Java, Ruby, C++
                                   SQL, VB6
 Objects are a natural way of representing behavior
and properties in code
 Objects are more reusable
 Objects are more maintainable
 Objects are more extensible
 Just because you are using an OO language does
not mean that you are doing object-oriented
programming
 Reuse is good (avoid NIH syndrome)
 The purely object-oriented solution is not always the
best solution
 Don’t be a code hoarder
   Encapsulation
   Inheritance
   Polymorphism
   Hide implementation details from the outside world
   Example: home electrical wiring
public class BankAccount
{
    public decimal Balance { get; set; }
}



It’s true that a BankAccount has a Balance, but this
class does not contain information about the
behaviors of a BankAccount.
public class BankAccount
{
    public decimal Balance { get; set; }

    public void Deposit(decimal amount)
    {
        Balance += amount;
    }

    public void Withdraw(decimal amount)
    {
        Balance -= amount;
    }
}


Sure, we could do it this way, but we are violating
encapsulation by exposing the inner workings of this
class (the Balance property).
public class BankAccount
{
    private decimal _balance;
    public decimal Balance
    {
        get { return _balance; }
    }

    public void Deposit(decimal amount)
    {
        _balance += amount;
    }

    public void Withdraw(decimal amount)
    {
        _balance -= amount;
    }
}

Much better – the inner workings of the class are
hidden from consumers of the class.
public class BankAccount
{
    private decimal _balance;

    public decimal Balance
    {
        get { return _balance; }
    }

    public void Deposit(decimal amount)
    {
        _balance += amount;
    }

    public void Withdraw(decimal amount)
    {
        if (_balance - amount < 0)
            throw new InsufficientFundsException();
        _balance -= amount;
    }
}


Change! Throw an exception if there are insufficient funds during a withdrawal.
public bool Withdraw(BankAccount bankAccount, decimal amount)
{
    bool couldWithdrawMoney;

    // check to see if there is enough money for the withdrawal
    if (bankAccount.Balance >= amount)
    {
        bankAccount.Withdraw(amount);
        couldWithdrawMoney = true;
    }
    else
        couldWithdrawMoney = false;
    return couldWithdrawMoney;
}

Change! You cannot withdraw money if the account is closed.
public bool Withdraw(BankAccount bankAccount, decimal amount)
{
    bool couldWithdrawMoney;

    // check to see if there is enough money for the withdrawal
    // and if the account is open
    if (bankAccount.Balance >= amount &&
        bankAccount.Status == BankAccountStatus.Open)
    {
        bankAccount.Withdraw(amount);
        couldWithdrawMoney = true;
    }
    else
        couldWithdrawMoney = false;
    return couldWithdrawMoney;
}


Change! You cannot withdraw money if the account is closed.

The code in the if statement is a leaky abstraction – the details about whether you
can withdraw money is spread out among the consumers of the BankAccount
instead of being encapsulated inside the BankAccount object.
public class BankAccount
{
    public bool CanWithdraw(decimal amount)
    {
        return Balance >= amount && Status == BankAccountStatus.Open;
    }
}

public bool Withdraw(BankAccount bankAccount, decimal amount)
{
    bool couldWithdrawMoney;

    // no need for a comment anymore, this code says what it does!
    if (bankAccount.CanWithdraw(amount))
    {
        bankAccount.Withdraw(amount);
        couldWithdrawMoney = true;
    }
    else
        couldWithdrawMoney = false;
    return couldWithdrawMoney;
}

The details about whether an amount of money can be withdrawn from a bank account
is now encapsulated inside the BankAccount class.
public class AtmMachine
{
    public void DoSomething(BankAccount bankAccount)
    {
        if (bankAccount.PrimaryAccountHolder.State == “OH”)
        {
            DoSomethingElse(bankAccount);
        }
    }
}




A method of an object may only call methods of:
1) The object itself.
2) An argument of the method.
3) Any object created within the method.
4) Any direct properties/fields of the object.
public class AtmMachine
{
    public void DoSomething(BankAccount bankAccount)
    {
        if (bankAccount.StateWhereAccountIsHeld == “OH”)
        {
            DoSomethingElse(bankAccount);
        }
    }
}

public class BankAccount
{
    public string StateWhereAccountIsHeld
    {
        get { return PrimaryAccountHolder.State; }
    }
}
Advanced Object-Oriented/SOLID Principles
   “Is-a” vs. “Has-a”
   What is the relationship between these objects?

       Customer             PreferredCustomer    CustomerContact
       • string FirstName   • string FirstName   • string FirstName
       • string LastName    • string LastName    • string LastName
       • string Address     • string Address     • string Address
   “Is-a” vs. “Has-a”
   What is the relationship between these objects?

      PreferredCustomer                           CustomerContact
        : Customer                        Has-a   • string FirstName
      • IList<CustomerContact> Contacts           • string LastName
                                                  • string Address

             Is-a

      Customer
      • string FirstName
      • string LastName
      • string Address
PreferredCustomer                                CustomerContact
  : Customer                          Has-a       : Person
• IList<CustomerContact> Contacts

       Is-a

Customer
 : Person

       Is-a

Person
• string FirstName
                              FormatName() will format name
• string LastName
                              as Last Name, First Name.
• string Address
• string FormatName()
PreferredCustomer                                  CustomerContact
  : Customer                           Has-a        : Person
• IList<CustomerContact> Contacts

       Is-a                  Change! We want to format the name for
                             CustomerContact objects as “First Name Last
Customer                     Name” instead of “Last Name, First Name”.
 : Person
                             1. We could change FormatName() to
       Is-a                     FormatName(bool lastNameFirst)
                             2. We could change FormatName() to
Person                          FormatName(INameFormatter formatter)
• string FirstName
• string LastName
                             Either way will force us to change any code
• string Address
                             that calls FormatName() on any class deriving
• string FormatName()
                             from Person!
WHAT’S GOOD ABOUT INHERITANCE       WHAT’S BAD ABOUT INHERITANCE
Enables code reuse                  Tight coupling – changes to
Polymorphism (“one with            the base class can cause all
many forms”)                        derived classes to have to
                                    changes
                                     Deep inheritance hierarchies
                                    are sometimes hard to figure
                                    out
PreferredCustomer                                  CustomerContact
  : Customer                             Has-a      : Person
• IList<CustomerContact> Contacts

       Is-a                  Question:
                             1. Will we ever have code that requires us to use
Customer                        the methods and properties that we put in the
 : Person                       Person class?

       Is-a                         Person person = GetImportantPerson();
                                    return person.FormatName();
Person
• string FirstName
• string LastName
• string Address
• string FormatName()
PreferredCustomer                                    CustomerContact
  : Customer                            Has-a        • string FirstName
• IList<CustomerContact> Contacts                    • string LastName
                                                     • string Address
       Is-a                                          • string FormatName()

Customer                     Employee
• string FirstName           • string FirstName
• string LastName            • string LastName
• string Address             • string FormatName()
• string FormatName()

What do we have now:
1. Our classes are no longer tightly coupled by inheritance, so we can change
   FormatName() on one class without affecting another
2. But we still want to reuse the name formatting code!
Create classes that format names – an object-
oriented solution!
public class FirstNameLastNameNameFormatter
{
    public string FormatName(string firstName, string lastName)
    {
        return firstName + “ “ + lastName;
    }
}

public class LastNameFirstNameNameFormatter
{
    public string FormatName(string firstName, string lastName)
    {
        return lastName + “, “ + firstName;
    }
}
Any class that needs to format names can use the
name formatter objects.
public class Customer
{
    public string FormatName()
    {
        return new FirstNameLastNameNameFormatter()
            .FormatName(FirstName, LastName);
    }
}


This technique is called composition – classes can add
functionality by using functionality in other objects.
module FirstNameLastNameNameFormatter
  def format_name
    return first_name + " " + last_name;
  end
end

class Customer
  include FirstNameLastNameNameFormatter
  attr :first_name, true
  attr :last_name, true
end

customer = Customer.new
customer.first_name = „Jon‟
customer.last_name = „Kruger‟
puts customer.format_name # this line will output: Jon Kruger
 Composition allows you to reuse code without
being tightly coupled to a base class
 Many loosely coupled, small, testable classes that
provide bits of functionality that can be used by
anyone who wants to use them
 Example: going shopping at a grocery store vs.
growing your own food on a farm – at the grocery
store, it’s much easier to change what you get!
public class Fruit
{
    // Return number of pieces of peel that
    // resulted from the peeling activity.
    public int Peel()
    {
        return 1;
    }
}

public class Apple : Fruit
{
}

public class Example1
{
    public static void Main(String[] args)
    {
        Apple apple = new Apple();
        int pieces = apple.Peel();
    }
}
public class Fruit
{
    // Return number of pieces of peel that
    // resulted from the peeling activity.
    public PeelResult Peel()
    {
        return new PeelResult { NumberOfPeels = 1, Success = true };
    }
}

public class Apple : Fruit
{
}

public class Example1
{
    public static void Main(String[] args)
    {
        Apple apple = new Apple();
        int pieces = apple.Peel(); // Compile error!
    }
}
public class Fruit
{
    // Return number of pieces of peel that
    // resulted from the peeling activity.
    public int Peel()
    {
        return 1;
    }
}

public class Apple
{
    private Fruit fruit = new Fruit(); // Composition instead of inheritance
    public int Peel()
    {
        return fruit.Peel();
    }
}

public class Example2
{
    public static void Main(String[] args)
    {
        Apple apple = new Apple();
        int pieces = apple.Peel();
    }
}
public class Fruit
{
    // Return number of pieces of peel that
    // resulted from the peeling activity.
    public PeelResult Peel()
    {
        return new PeelResult { NumberOfPeels = 1, Success = true };
    }
}

public class Apple
{
    private Fruit fruit = new Fruit(); // Composition instead of inheritance
    public int Peel()
    {
        return fruit.Peel().NumberOfPeels; // Changes stop here!
    }
}

public class Example2
{
    public static void Main(String[] args)
    {
        Apple apple = new Apple();
        int pieces = apple.Peel();
    }
}
Advanced Object-Oriented/SOLID Principles
Advanced Object-Oriented/SOLID Principles
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.
Advanced Object-Oriented/SOLID Principles
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 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: 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)
Advanced Object-Oriented/SOLID Principles
  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)
{
    // make sure that the order has products
    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 the order
    _orderSubmissionService.SubmitOrder(order);
}
public void SubmitOrder(Order order)
{
    ValidateOrderHasProducts(order);
    CalculateTax(order);
    CalculateShipping(order);
    SendOrderToOrderSubmissionService(order);
}
public void SubmitOrder(Order order)
          {
              ValidateOrderHasProducts(order);
Small         CalculateTax(order);
              CalculateShipping(order);
Methods   }
              SendOrderToOrderSubmissionService(order);


- After   public void ValidateOrderHasProducts(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);
          }
Advanced Object-Oriented/SOLID Principles
Software entities (classes, modules, methods) should
be open for extension but closed for modification.
Advanced Object-Oriented/SOLID Principles
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)
Advanced Object-Oriented/SOLID Principles
Functions that use references to base classes must be
able to use objects of derived classes without knowing
it.
Advanced Object-Oriented/SOLID Principles
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(); }
    }
}
Advanced Object-Oriented/SOLID Principles
Clients should not be forced to depend on interfaces
that they do not use.
Advanced Object-Oriented/SOLID Principles
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
Advanced Object-Oriented/SOLID Principles
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.
Advanced Object-Oriented/SOLID Principles
 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
Stubs, mocks, and fakes in unit tests are only
possible when we have an interface to implement
   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
   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 CurrentUser { get; set; }
    }
   Use of singletons using “static”

    public class ProductCache
    {
        private static readonly _instance = new ProductCache();
        public static ProductCache Instance
        {
            get { return _instance; }
        }
    }
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);
    }
}
 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!
public class GetProductService : IGetProductService
{
    private IProductRepository _productRepository;

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

    public IList<Product> GetProductById(int id)
    {
        return _productRepository.Get(id);
    }
}
ObjectFactory.Initialize(x =>
{
    x.ForRequestedType<IGetProductService>()
     .TheDefaultIsConcreteType<GetProductService>();
});
ObjectFactory.Initialize(x =>
{
    x.Scan(scan =>
    {
        scan.WithDefaultConventions();
        scan.AssemblyContainingType<IProductRepository>();
    });
});



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


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

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


 InstanceScope.Hybrid means that we will only have
one of these objects per request (web) or thread (in
our tests)
 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
(usually)
Advanced Object-Oriented/SOLID Principles
USE YOUR BRAIN!!!!
   Uncle Bob’s SOLID articles
     http://bit.ly/solid1
   Uncle Bob talking about SOLID on Hanselminutes
     http://bit.ly/solid2
   ALT.NET mailing list
     http://bit.ly/solid4
   This list of links (including these slides)
     http://jonkruger.com/blog/oopsolid

My Info:
email: jon@jonkruger.com
twitter: @jonkruger / blog: http://jonkruger.com/blog
"Draw Five"
Draw Five is a card game where you draw five cards and get points based on the cards that you draw. You can also view the high scores
and save high scores to a database.

When drawing cards
- 5 cards are drawn from a standard 52-card deck (keep in mind that the same card cannot be drawn twice)
- should show the user what cards they drew

When scoring the draw
- face cards = 10
- aces = 15
- numbers = number value

in addition to base score:
- each pair +50
- three of a kind +150
- four of a kind +300
- each spade +1

When showing the high scores
- should show the top 5 scores (name and score)

When saving a high score
- should save the name (entered by the user) and the score
===========================================================================
"Blackjack"
In this simple version of blackjack, you just draw two cards and calculate the score for the two cards (no drawing of extra cards). High
scores are not saved in Blackjack.

When drawing cards
- 5 cards are drawn from a standard 52-card deck (keep in mind that the same card cannot be drawn twice)
- should show the user what cards they drew

When scoring the draw
- face cards = 10
- aces = 11
- numbers = number value
change #1
- Draw Five has 2 Jokers in the deck
- jokers = 20 pts each
- two jokers = 200 pt bonus (in addition to the 20 pts for each Joker)
change #2
- in Draw Five:
   - a "run" of 3 sequential cards is worth 50 pts
   - a "run" of 4 sequential cards is worth 100 pts
   - a "run" of 5 sequential cards is worth 150 pts
   - the order of cards for "runs" is: A,2,3,4,5,6,7,8,9,10,J,Q,K,A
(notice the Ace can be used at either end)
extra credit change
- create an interface that will allow people to write their own
scoring system as a plugin

More Related Content

What's hot

ASP.NET MVC Presentation
ASP.NET MVC PresentationASP.NET MVC Presentation
ASP.NET MVC Presentationivpol
 
JUnit & Mockito, first steps
JUnit & Mockito, first stepsJUnit & Mockito, first steps
JUnit & Mockito, first stepsRenato Primavera
 
Hibernate ppt
Hibernate pptHibernate ppt
Hibernate pptAneega
 
SOLID, DRY, SLAP design principles
SOLID, DRY, SLAP design principlesSOLID, DRY, SLAP design principles
SOLID, DRY, SLAP design principlesSergey Karpushin
 
Spring boot Introduction
Spring boot IntroductionSpring boot Introduction
Spring boot IntroductionJeevesh Pandey
 
Javascript Design Patterns
Javascript Design PatternsJavascript Design Patterns
Javascript Design PatternsLilia Sfaxi
 
Java Spring framework, Dependency Injection, DI, IoC, Inversion of Control
Java Spring framework, Dependency Injection, DI, IoC, Inversion of ControlJava Spring framework, Dependency Injection, DI, IoC, Inversion of Control
Java Spring framework, Dependency Injection, DI, IoC, Inversion of ControlArjun Thakur
 
Java Course 11: Design Patterns
Java Course 11: Design PatternsJava Course 11: Design Patterns
Java Course 11: Design PatternsAnton Keks
 
Introduction to design patterns
Introduction to design patternsIntroduction to design patterns
Introduction to design patternsAmit Kabra
 
Advanced Node.JS Meetup
Advanced Node.JS MeetupAdvanced Node.JS Meetup
Advanced Node.JS MeetupLINAGORA
 
Software Engineering - chp4- design patterns
Software Engineering - chp4- design patternsSoftware Engineering - chp4- design patterns
Software Engineering - chp4- design patternsLilia Sfaxi
 
REST APIs with Spring
REST APIs with SpringREST APIs with Spring
REST APIs with SpringJoshua Long
 

What's hot (20)

Java 8 Lambda and Streams
Java 8 Lambda and StreamsJava 8 Lambda and Streams
Java 8 Lambda and Streams
 
SOLID principles
SOLID principlesSOLID principles
SOLID principles
 
ASP.NET MVC Presentation
ASP.NET MVC PresentationASP.NET MVC Presentation
ASP.NET MVC Presentation
 
JUnit & Mockito, first steps
JUnit & Mockito, first stepsJUnit & Mockito, first steps
JUnit & Mockito, first steps
 
Hibernate ppt
Hibernate pptHibernate ppt
Hibernate ppt
 
SOLID, DRY, SLAP design principles
SOLID, DRY, SLAP design principlesSOLID, DRY, SLAP design principles
SOLID, DRY, SLAP design principles
 
Spring boot Introduction
Spring boot IntroductionSpring boot Introduction
Spring boot Introduction
 
React for Beginners
React for BeginnersReact for Beginners
React for Beginners
 
Javascript Design Patterns
Javascript Design PatternsJavascript Design Patterns
Javascript Design Patterns
 
C#
C#C#
C#
 
Polymorphism in java
Polymorphism in javaPolymorphism in java
Polymorphism in java
 
Java Spring framework, Dependency Injection, DI, IoC, Inversion of Control
Java Spring framework, Dependency Injection, DI, IoC, Inversion of ControlJava Spring framework, Dependency Injection, DI, IoC, Inversion of Control
Java Spring framework, Dependency Injection, DI, IoC, Inversion of Control
 
Java Course 11: Design Patterns
Java Course 11: Design PatternsJava Course 11: Design Patterns
Java Course 11: Design Patterns
 
Introduction to design patterns
Introduction to design patternsIntroduction to design patterns
Introduction to design patterns
 
Advanced Node.JS Meetup
Advanced Node.JS MeetupAdvanced Node.JS Meetup
Advanced Node.JS Meetup
 
Introduction to Spring Boot
Introduction to Spring BootIntroduction to Spring Boot
Introduction to Spring Boot
 
Software Engineering - chp4- design patterns
Software Engineering - chp4- design patternsSoftware Engineering - chp4- design patterns
Software Engineering - chp4- design patterns
 
Design patterns
Design patternsDesign patterns
Design patterns
 
Solid Principles
Solid PrinciplesSolid Principles
Solid Principles
 
REST APIs with Spring
REST APIs with SpringREST APIs with Spring
REST APIs with Spring
 

Viewers also liked

SOLID Design Principles
SOLID Design PrinciplesSOLID Design Principles
SOLID Design PrinciplesAndreas Enbohm
 
S.O.L.I.D. Principles for Software Architects
S.O.L.I.D. Principles for Software ArchitectsS.O.L.I.D. Principles for Software Architects
S.O.L.I.D. Principles for Software ArchitectsRicardo Wilkins
 
"SOLID" Object Oriented Design Principles
"SOLID" Object Oriented Design Principles"SOLID" Object Oriented Design Principles
"SOLID" Object Oriented Design PrinciplesSerhiy Oplakanets
 
Object Oriented Design SOLID Principles
Object Oriented Design SOLID PrinciplesObject Oriented Design SOLID Principles
Object Oriented Design SOLID Principlesrainynovember12
 
SOLID - Principles of Object Oriented Design
SOLID - Principles of Object Oriented DesignSOLID - Principles of Object Oriented Design
SOLID - Principles of Object Oriented DesignRiccardo Cardin
 
Solid principles of oo design
Solid principles of oo designSolid principles of oo design
Solid principles of oo designConfiz
 
Advanced oop laws, principles, idioms
Advanced oop laws, principles, idiomsAdvanced oop laws, principles, idioms
Advanced oop laws, principles, idiomsClint Edmonson
 
Single Responsibility Principle @ Clean Code Alliance Meetup
Single Responsibility Principle @ Clean Code Alliance MeetupSingle Responsibility Principle @ Clean Code Alliance Meetup
Single Responsibility Principle @ Clean Code Alliance MeetupEyal Golan
 
Application Architecture April 2014
Application Architecture April 2014Application Architecture April 2014
Application Architecture April 2014Lars-Erik Kindblad
 
The Single Responsibility Principle
The Single Responsibility PrincipleThe Single Responsibility Principle
The Single Responsibility PrincipleLars-Erik Kindblad
 
Anything Data: Big, Streaming, NoSQL, Cloud, Science ... A Sloppy Travel Guide
Anything Data: Big, Streaming, NoSQL, Cloud, Science ... A Sloppy Travel GuideAnything Data: Big, Streaming, NoSQL, Cloud, Science ... A Sloppy Travel Guide
Anything Data: Big, Streaming, NoSQL, Cloud, Science ... A Sloppy Travel GuideAhmet Akyol
 
Unified Modeling Language (UML), Object-Oriented Programming Concepts & Desig...
Unified Modeling Language (UML), Object-Oriented Programming Concepts & Desig...Unified Modeling Language (UML), Object-Oriented Programming Concepts & Desig...
Unified Modeling Language (UML), Object-Oriented Programming Concepts & Desig...Isuru Perera
 
Open Closed Principle kata
Open Closed Principle kataOpen Closed Principle kata
Open Closed Principle kataPaul Blundell
 
C# OOP Advanced Concepts
C# OOP Advanced ConceptsC# OOP Advanced Concepts
C# OOP Advanced Conceptsagni_agbc
 
SOLID Principles and Design Patterns
SOLID Principles and Design PatternsSOLID Principles and Design Patterns
SOLID Principles and Design PatternsGanesh Samarthyam
 

Viewers also liked (20)

SOLID Design Principles
SOLID Design PrinciplesSOLID Design Principles
SOLID Design Principles
 
S.O.L.I.D. Principles for Software Architects
S.O.L.I.D. Principles for Software ArchitectsS.O.L.I.D. Principles for Software Architects
S.O.L.I.D. Principles for Software Architects
 
"SOLID" Object Oriented Design Principles
"SOLID" Object Oriented Design Principles"SOLID" Object Oriented Design Principles
"SOLID" Object Oriented Design Principles
 
Object Oriented Design SOLID Principles
Object Oriented Design SOLID PrinciplesObject Oriented Design SOLID Principles
Object Oriented Design SOLID Principles
 
SOLID - Principles of Object Oriented Design
SOLID - Principles of Object Oriented DesignSOLID - Principles of Object Oriented Design
SOLID - Principles of Object Oriented Design
 
Solid principles of oo design
Solid principles of oo designSolid principles of oo design
Solid principles of oo design
 
Advance oops concepts
Advance oops conceptsAdvance oops concepts
Advance oops concepts
 
Advanced oop laws, principles, idioms
Advanced oop laws, principles, idiomsAdvanced oop laws, principles, idioms
Advanced oop laws, principles, idioms
 
Introduction to PowerPoint
Introduction to PowerPointIntroduction to PowerPoint
Introduction to PowerPoint
 
Single Responsibility Principle @ Clean Code Alliance Meetup
Single Responsibility Principle @ Clean Code Alliance MeetupSingle Responsibility Principle @ Clean Code Alliance Meetup
Single Responsibility Principle @ Clean Code Alliance Meetup
 
Java inheritance
Java inheritanceJava inheritance
Java inheritance
 
High Level Programming Constructs
High Level Programming ConstructsHigh Level Programming Constructs
High Level Programming Constructs
 
Application Architecture April 2014
Application Architecture April 2014Application Architecture April 2014
Application Architecture April 2014
 
The Single Responsibility Principle
The Single Responsibility PrincipleThe Single Responsibility Principle
The Single Responsibility Principle
 
Anything Data: Big, Streaming, NoSQL, Cloud, Science ... A Sloppy Travel Guide
Anything Data: Big, Streaming, NoSQL, Cloud, Science ... A Sloppy Travel GuideAnything Data: Big, Streaming, NoSQL, Cloud, Science ... A Sloppy Travel Guide
Anything Data: Big, Streaming, NoSQL, Cloud, Science ... A Sloppy Travel Guide
 
Java Inheritance
Java InheritanceJava Inheritance
Java Inheritance
 
Unified Modeling Language (UML), Object-Oriented Programming Concepts & Desig...
Unified Modeling Language (UML), Object-Oriented Programming Concepts & Desig...Unified Modeling Language (UML), Object-Oriented Programming Concepts & Desig...
Unified Modeling Language (UML), Object-Oriented Programming Concepts & Desig...
 
Open Closed Principle kata
Open Closed Principle kataOpen Closed Principle kata
Open Closed Principle kata
 
C# OOP Advanced Concepts
C# OOP Advanced ConceptsC# OOP Advanced Concepts
C# OOP Advanced Concepts
 
SOLID Principles and Design Patterns
SOLID Principles and Design PatternsSOLID Principles and Design Patterns
SOLID Principles and Design Patterns
 

Similar to Advanced Object-Oriented/SOLID Principles

The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)Matthias Noback
 
The quest for global design principles - PHP Benelux 2016
The quest for global design principles - PHP Benelux 2016The quest for global design principles - PHP Benelux 2016
The quest for global design principles - PHP Benelux 2016Matthias Noback
 
Code decoupling from Symfony (and others frameworks) - PHP Conference Brasil ...
Code decoupling from Symfony (and others frameworks) - PHP Conference Brasil ...Code decoupling from Symfony (and others frameworks) - PHP Conference Brasil ...
Code decoupling from Symfony (and others frameworks) - PHP Conference Brasil ...Miguel Gallardo
 
Dutch PHP Conference 2015 - The quest for global design principles
Dutch PHP Conference 2015 - The quest for global design principlesDutch PHP Conference 2015 - The quest for global design principles
Dutch PHP Conference 2015 - The quest for global design principlesMatthias Noback
 
Clean Code: Chapter 3 Function
Clean Code: Chapter 3 FunctionClean Code: Chapter 3 Function
Clean Code: Chapter 3 FunctionKent Huang
 
JavaScript Fundamentals & JQuery
JavaScript Fundamentals & JQueryJavaScript Fundamentals & JQuery
JavaScript Fundamentals & JQueryJamshid Hashimi
 
Reviewing OOP Design patterns
Reviewing OOP Design patternsReviewing OOP Design patterns
Reviewing OOP Design patternsOlivier Bacs
 
Introduction to Domain-Driven Design in Ruby on Rails
Introduction to Domain-Driven Design in Ruby on RailsIntroduction to Domain-Driven Design in Ruby on Rails
Introduction to Domain-Driven Design in Ruby on RailsVisuality
 
fuser interface-development-using-jquery
fuser interface-development-using-jqueryfuser interface-development-using-jquery
fuser interface-development-using-jqueryKostas Mavridis
 
5variables in c#
5variables in c#5variables in c#
5variables in c#Sireesh K
 

Similar to Advanced Object-Oriented/SOLID Principles (20)

The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)
 
The quest for global design principles - PHP Benelux 2016
The quest for global design principles - PHP Benelux 2016The quest for global design principles - PHP Benelux 2016
The quest for global design principles - PHP Benelux 2016
 
Code decoupling from Symfony (and others frameworks) - PHP Conference Brasil ...
Code decoupling from Symfony (and others frameworks) - PHP Conference Brasil ...Code decoupling from Symfony (and others frameworks) - PHP Conference Brasil ...
Code decoupling from Symfony (and others frameworks) - PHP Conference Brasil ...
 
Dutch PHP Conference 2015 - The quest for global design principles
Dutch PHP Conference 2015 - The quest for global design principlesDutch PHP Conference 2015 - The quest for global design principles
Dutch PHP Conference 2015 - The quest for global design principles
 
Refactoring
RefactoringRefactoring
Refactoring
 
Introduction to java and oop
Introduction to java and oopIntroduction to java and oop
Introduction to java and oop
 
Clean Code: Chapter 3 Function
Clean Code: Chapter 3 FunctionClean Code: Chapter 3 Function
Clean Code: Chapter 3 Function
 
JavaScript Fundamentals & JQuery
JavaScript Fundamentals & JQueryJavaScript Fundamentals & JQuery
JavaScript Fundamentals & JQuery
 
About Python
About PythonAbout Python
About Python
 
Design Without Types
Design Without TypesDesign Without Types
Design Without Types
 
11-Classes.ppt
11-Classes.ppt11-Classes.ppt
11-Classes.ppt
 
Minds-on DDD
Minds-on DDDMinds-on DDD
Minds-on DDD
 
Python: Basic Inheritance
Python: Basic InheritancePython: Basic Inheritance
Python: Basic Inheritance
 
S313431 JPA 2.0 Overview
S313431 JPA 2.0 OverviewS313431 JPA 2.0 Overview
S313431 JPA 2.0 Overview
 
Reviewing OOP Design patterns
Reviewing OOP Design patternsReviewing OOP Design patterns
Reviewing OOP Design patterns
 
Introduction to Domain-Driven Design in Ruby on Rails
Introduction to Domain-Driven Design in Ruby on RailsIntroduction to Domain-Driven Design in Ruby on Rails
Introduction to Domain-Driven Design in Ruby on Rails
 
Clean Code 2
Clean Code 2Clean Code 2
Clean Code 2
 
fuser interface-development-using-jquery
fuser interface-development-using-jqueryfuser interface-development-using-jquery
fuser interface-development-using-jquery
 
5variables in c#
5variables in c#5variables in c#
5variables in c#
 
Linq Introduction
Linq IntroductionLinq Introduction
Linq Introduction
 

More from 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
 
Venturing Into The Wild: A .NET Developer's Experience As A Ruby Developer
Venturing Into The Wild: A .NET Developer's Experience As A Ruby DeveloperVenturing Into The Wild: A .NET Developer's Experience As A Ruby Developer
Venturing Into The Wild: A .NET Developer's Experience As A Ruby DeveloperJon Kruger
 
Testable, Object-Oriented JavaScript
Testable, Object-Oriented JavaScriptTestable, Object-Oriented JavaScript
Testable, Object-Oriented JavaScriptJon 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
 
Solid Software Design Principles
Solid Software Design PrinciplesSolid Software Design Principles
Solid Software Design PrinciplesJon Kruger
 

More from Jon Kruger (9)

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
 
Venturing Into The Wild: A .NET Developer's Experience As A Ruby Developer
Venturing Into The Wild: A .NET Developer's Experience As A Ruby DeveloperVenturing Into The Wild: A .NET Developer's Experience As A Ruby Developer
Venturing Into The Wild: A .NET Developer's Experience As A Ruby Developer
 
Testable, Object-Oriented JavaScript
Testable, Object-Oriented JavaScriptTestable, Object-Oriented JavaScript
Testable, Object-Oriented JavaScript
 
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
 
Solid Software Design Principles
Solid Software Design PrinciplesSolid Software Design Principles
Solid Software Design Principles
 

Recently uploaded

Stobox 4: Revolutionizing Investment in Real-World Assets Through Tokenization
Stobox 4: Revolutionizing Investment in Real-World Assets Through TokenizationStobox 4: Revolutionizing Investment in Real-World Assets Through Tokenization
Stobox 4: Revolutionizing Investment in Real-World Assets Through TokenizationStobox
 
How to become a GDSC Lead GDSC MI AOE.pptx
How to become a GDSC Lead GDSC MI AOE.pptxHow to become a GDSC Lead GDSC MI AOE.pptx
How to become a GDSC Lead GDSC MI AOE.pptxKaustubhBhavsar6
 
Trailblazer Community - Flows Workshop (Session 2)
Trailblazer Community - Flows Workshop (Session 2)Trailblazer Community - Flows Workshop (Session 2)
Trailblazer Community - Flows Workshop (Session 2)Muhammad Tiham Siddiqui
 
UiPath Studio Web workshop series - Day 2
UiPath Studio Web workshop series - Day 2UiPath Studio Web workshop series - Day 2
UiPath Studio Web workshop series - Day 2DianaGray10
 
CyberSecurity - Computers In Libraries 2024
CyberSecurity - Computers In Libraries 2024CyberSecurity - Computers In Libraries 2024
CyberSecurity - Computers In Libraries 2024Brian Pichman
 
Webinar: The Art of Prioritizing Your Product Roadmap by AWS Sr PM - Tech
Webinar: The Art of Prioritizing Your Product Roadmap by AWS Sr PM - TechWebinar: The Art of Prioritizing Your Product Roadmap by AWS Sr PM - Tech
Webinar: The Art of Prioritizing Your Product Roadmap by AWS Sr PM - TechProduct School
 
The Zero-ETL Approach: Enhancing Data Agility and Insight
The Zero-ETL Approach: Enhancing Data Agility and InsightThe Zero-ETL Approach: Enhancing Data Agility and Insight
The Zero-ETL Approach: Enhancing Data Agility and InsightSafe Software
 
Technical SEO for Improved Accessibility WTS FEST
Technical SEO for Improved Accessibility  WTS FESTTechnical SEO for Improved Accessibility  WTS FEST
Technical SEO for Improved Accessibility WTS FESTBillieHyde
 
Novo Nordisk's journey in developing an open-source application on Neo4j
Novo Nordisk's journey in developing an open-source application on Neo4jNovo Nordisk's journey in developing an open-source application on Neo4j
Novo Nordisk's journey in developing an open-source application on Neo4jNeo4j
 
Design and Modeling for MySQL SCALE 21X Pasadena, CA Mar 2024
Design and Modeling for MySQL SCALE 21X Pasadena, CA Mar 2024Design and Modeling for MySQL SCALE 21X Pasadena, CA Mar 2024
Design and Modeling for MySQL SCALE 21X Pasadena, CA Mar 2024Alkin Tezuysal
 
Patch notes explaining DISARM Version 1.4 update
Patch notes explaining DISARM Version 1.4 updatePatch notes explaining DISARM Version 1.4 update
Patch notes explaining DISARM Version 1.4 updateadam112203
 
20140402 - Smart house demo kit
20140402 - Smart house demo kit20140402 - Smart house demo kit
20140402 - Smart house demo kitJamie (Taka) Wang
 
Oracle Database 23c Security New Features.pptx
Oracle Database 23c Security New Features.pptxOracle Database 23c Security New Features.pptx
Oracle Database 23c Security New Features.pptxSatishbabu Gunukula
 
Explore the UiPath Community and ways you can benefit on your journey to auto...
Explore the UiPath Community and ways you can benefit on your journey to auto...Explore the UiPath Community and ways you can benefit on your journey to auto...
Explore the UiPath Community and ways you can benefit on your journey to auto...DianaGray10
 
UiPath Studio Web workshop series - Day 4
UiPath Studio Web workshop series - Day 4UiPath Studio Web workshop series - Day 4
UiPath Studio Web workshop series - Day 4DianaGray10
 
Top 10 Squarespace Development Companies
Top 10 Squarespace Development CompaniesTop 10 Squarespace Development Companies
Top 10 Squarespace Development CompaniesTopCSSGallery
 
Automation Ops Series: Session 2 - Governance for UiPath projects
Automation Ops Series: Session 2 - Governance for UiPath projectsAutomation Ops Series: Session 2 - Governance for UiPath projects
Automation Ops Series: Session 2 - Governance for UiPath projectsDianaGray10
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfCheryl Hung
 
SIM INFORMATION SYSTEM: REVOLUTIONIZING DATA MANAGEMENT
SIM INFORMATION SYSTEM: REVOLUTIONIZING DATA MANAGEMENTSIM INFORMATION SYSTEM: REVOLUTIONIZING DATA MANAGEMENT
SIM INFORMATION SYSTEM: REVOLUTIONIZING DATA MANAGEMENTxtailishbaloch
 
Scenario Library et REX Discover industry- and role- based scenarios
Scenario Library et REX Discover industry- and role- based scenariosScenario Library et REX Discover industry- and role- based scenarios
Scenario Library et REX Discover industry- and role- based scenariosErol GIRAUDY
 

Recently uploaded (20)

Stobox 4: Revolutionizing Investment in Real-World Assets Through Tokenization
Stobox 4: Revolutionizing Investment in Real-World Assets Through TokenizationStobox 4: Revolutionizing Investment in Real-World Assets Through Tokenization
Stobox 4: Revolutionizing Investment in Real-World Assets Through Tokenization
 
How to become a GDSC Lead GDSC MI AOE.pptx
How to become a GDSC Lead GDSC MI AOE.pptxHow to become a GDSC Lead GDSC MI AOE.pptx
How to become a GDSC Lead GDSC MI AOE.pptx
 
Trailblazer Community - Flows Workshop (Session 2)
Trailblazer Community - Flows Workshop (Session 2)Trailblazer Community - Flows Workshop (Session 2)
Trailblazer Community - Flows Workshop (Session 2)
 
UiPath Studio Web workshop series - Day 2
UiPath Studio Web workshop series - Day 2UiPath Studio Web workshop series - Day 2
UiPath Studio Web workshop series - Day 2
 
CyberSecurity - Computers In Libraries 2024
CyberSecurity - Computers In Libraries 2024CyberSecurity - Computers In Libraries 2024
CyberSecurity - Computers In Libraries 2024
 
Webinar: The Art of Prioritizing Your Product Roadmap by AWS Sr PM - Tech
Webinar: The Art of Prioritizing Your Product Roadmap by AWS Sr PM - TechWebinar: The Art of Prioritizing Your Product Roadmap by AWS Sr PM - Tech
Webinar: The Art of Prioritizing Your Product Roadmap by AWS Sr PM - Tech
 
The Zero-ETL Approach: Enhancing Data Agility and Insight
The Zero-ETL Approach: Enhancing Data Agility and InsightThe Zero-ETL Approach: Enhancing Data Agility and Insight
The Zero-ETL Approach: Enhancing Data Agility and Insight
 
Technical SEO for Improved Accessibility WTS FEST
Technical SEO for Improved Accessibility  WTS FESTTechnical SEO for Improved Accessibility  WTS FEST
Technical SEO for Improved Accessibility WTS FEST
 
Novo Nordisk's journey in developing an open-source application on Neo4j
Novo Nordisk's journey in developing an open-source application on Neo4jNovo Nordisk's journey in developing an open-source application on Neo4j
Novo Nordisk's journey in developing an open-source application on Neo4j
 
Design and Modeling for MySQL SCALE 21X Pasadena, CA Mar 2024
Design and Modeling for MySQL SCALE 21X Pasadena, CA Mar 2024Design and Modeling for MySQL SCALE 21X Pasadena, CA Mar 2024
Design and Modeling for MySQL SCALE 21X Pasadena, CA Mar 2024
 
Patch notes explaining DISARM Version 1.4 update
Patch notes explaining DISARM Version 1.4 updatePatch notes explaining DISARM Version 1.4 update
Patch notes explaining DISARM Version 1.4 update
 
20140402 - Smart house demo kit
20140402 - Smart house demo kit20140402 - Smart house demo kit
20140402 - Smart house demo kit
 
Oracle Database 23c Security New Features.pptx
Oracle Database 23c Security New Features.pptxOracle Database 23c Security New Features.pptx
Oracle Database 23c Security New Features.pptx
 
Explore the UiPath Community and ways you can benefit on your journey to auto...
Explore the UiPath Community and ways you can benefit on your journey to auto...Explore the UiPath Community and ways you can benefit on your journey to auto...
Explore the UiPath Community and ways you can benefit on your journey to auto...
 
UiPath Studio Web workshop series - Day 4
UiPath Studio Web workshop series - Day 4UiPath Studio Web workshop series - Day 4
UiPath Studio Web workshop series - Day 4
 
Top 10 Squarespace Development Companies
Top 10 Squarespace Development CompaniesTop 10 Squarespace Development Companies
Top 10 Squarespace Development Companies
 
Automation Ops Series: Session 2 - Governance for UiPath projects
Automation Ops Series: Session 2 - Governance for UiPath projectsAutomation Ops Series: Session 2 - Governance for UiPath projects
Automation Ops Series: Session 2 - Governance for UiPath projects
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
 
SIM INFORMATION SYSTEM: REVOLUTIONIZING DATA MANAGEMENT
SIM INFORMATION SYSTEM: REVOLUTIONIZING DATA MANAGEMENTSIM INFORMATION SYSTEM: REVOLUTIONIZING DATA MANAGEMENT
SIM INFORMATION SYSTEM: REVOLUTIONIZING DATA MANAGEMENT
 
Scenario Library et REX Discover industry- and role- based scenarios
Scenario Library et REX Discover industry- and role- based scenariosScenario Library et REX Discover industry- and role- based scenarios
Scenario Library et REX Discover industry- and role- based scenarios
 

Advanced Object-Oriented/SOLID Principles

  • 2.  The principles that we will discuss today will help you write better code in ANY language that you use  Because you can never completely master object- oriented programming  Practice makes perfect, so we’re going to practice
  • 5.  A software development technique where you write automated unit tests before you write your implementation code  A technique for ensuring good quality and good design  Awesome!
  • 8.  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
  • 9. It costs money to develop software  It costs money to fix bugs  It costs money to make changes to software
  • 11. Definition: “A method of programming based on a hierarchy of classes, and well-defined and cooperating objects.”
  • 14. OBJECT-ORIENTED PROGRAMMING PROCEDURAL PROGRAMMING  Collaboration between  A series of objects that send and receive functions, subroutines, or messages with each other tasks  Functionality is grouped by object  Functionality is grouped by task  Objects and their behavior can be reused  Functions/subroutines/tasks can be reused  .NET, Java, Ruby, C++  SQL, VB6
  • 15.  Objects are a natural way of representing behavior and properties in code  Objects are more reusable  Objects are more maintainable  Objects are more extensible
  • 16.  Just because you are using an OO language does not mean that you are doing object-oriented programming  Reuse is good (avoid NIH syndrome)  The purely object-oriented solution is not always the best solution  Don’t be a code hoarder
  • 17. Encapsulation  Inheritance  Polymorphism
  • 18. Hide implementation details from the outside world  Example: home electrical wiring
  • 19. public class BankAccount { public decimal Balance { get; set; } } It’s true that a BankAccount has a Balance, but this class does not contain information about the behaviors of a BankAccount.
  • 20. public class BankAccount { public decimal Balance { get; set; } public void Deposit(decimal amount) { Balance += amount; } public void Withdraw(decimal amount) { Balance -= amount; } } Sure, we could do it this way, but we are violating encapsulation by exposing the inner workings of this class (the Balance property).
  • 21. public class BankAccount { private decimal _balance; public decimal Balance { get { return _balance; } } public void Deposit(decimal amount) { _balance += amount; } public void Withdraw(decimal amount) { _balance -= amount; } } Much better – the inner workings of the class are hidden from consumers of the class.
  • 22. public class BankAccount { private decimal _balance; public decimal Balance { get { return _balance; } } public void Deposit(decimal amount) { _balance += amount; } public void Withdraw(decimal amount) { if (_balance - amount < 0) throw new InsufficientFundsException(); _balance -= amount; } } Change! Throw an exception if there are insufficient funds during a withdrawal.
  • 23. public bool Withdraw(BankAccount bankAccount, decimal amount) { bool couldWithdrawMoney; // check to see if there is enough money for the withdrawal if (bankAccount.Balance >= amount) { bankAccount.Withdraw(amount); couldWithdrawMoney = true; } else couldWithdrawMoney = false; return couldWithdrawMoney; } Change! You cannot withdraw money if the account is closed.
  • 24. public bool Withdraw(BankAccount bankAccount, decimal amount) { bool couldWithdrawMoney; // check to see if there is enough money for the withdrawal // and if the account is open if (bankAccount.Balance >= amount && bankAccount.Status == BankAccountStatus.Open) { bankAccount.Withdraw(amount); couldWithdrawMoney = true; } else couldWithdrawMoney = false; return couldWithdrawMoney; } Change! You cannot withdraw money if the account is closed. The code in the if statement is a leaky abstraction – the details about whether you can withdraw money is spread out among the consumers of the BankAccount instead of being encapsulated inside the BankAccount object.
  • 25. public class BankAccount { public bool CanWithdraw(decimal amount) { return Balance >= amount && Status == BankAccountStatus.Open; } } public bool Withdraw(BankAccount bankAccount, decimal amount) { bool couldWithdrawMoney; // no need for a comment anymore, this code says what it does! if (bankAccount.CanWithdraw(amount)) { bankAccount.Withdraw(amount); couldWithdrawMoney = true; } else couldWithdrawMoney = false; return couldWithdrawMoney; } The details about whether an amount of money can be withdrawn from a bank account is now encapsulated inside the BankAccount class.
  • 26. public class AtmMachine { public void DoSomething(BankAccount bankAccount) { if (bankAccount.PrimaryAccountHolder.State == “OH”) { DoSomethingElse(bankAccount); } } } A method of an object may only call methods of: 1) The object itself. 2) An argument of the method. 3) Any object created within the method. 4) Any direct properties/fields of the object.
  • 27. public class AtmMachine { public void DoSomething(BankAccount bankAccount) { if (bankAccount.StateWhereAccountIsHeld == “OH”) { DoSomethingElse(bankAccount); } } } public class BankAccount { public string StateWhereAccountIsHeld { get { return PrimaryAccountHolder.State; } } }
  • 29. “Is-a” vs. “Has-a”  What is the relationship between these objects? Customer PreferredCustomer CustomerContact • string FirstName • string FirstName • string FirstName • string LastName • string LastName • string LastName • string Address • string Address • string Address
  • 30. “Is-a” vs. “Has-a”  What is the relationship between these objects? PreferredCustomer CustomerContact : Customer Has-a • string FirstName • IList<CustomerContact> Contacts • string LastName • string Address Is-a Customer • string FirstName • string LastName • string Address
  • 31. PreferredCustomer CustomerContact : Customer Has-a : Person • IList<CustomerContact> Contacts Is-a Customer : Person Is-a Person • string FirstName FormatName() will format name • string LastName as Last Name, First Name. • string Address • string FormatName()
  • 32. PreferredCustomer CustomerContact : Customer Has-a : Person • IList<CustomerContact> Contacts Is-a Change! We want to format the name for CustomerContact objects as “First Name Last Customer Name” instead of “Last Name, First Name”. : Person 1. We could change FormatName() to Is-a FormatName(bool lastNameFirst) 2. We could change FormatName() to Person FormatName(INameFormatter formatter) • string FirstName • string LastName Either way will force us to change any code • string Address that calls FormatName() on any class deriving • string FormatName() from Person!
  • 33. WHAT’S GOOD ABOUT INHERITANCE WHAT’S BAD ABOUT INHERITANCE Enables code reuse  Tight coupling – changes to Polymorphism (“one with the base class can cause all many forms”) derived classes to have to changes  Deep inheritance hierarchies are sometimes hard to figure out
  • 34. PreferredCustomer CustomerContact : Customer Has-a : Person • IList<CustomerContact> Contacts Is-a Question: 1. Will we ever have code that requires us to use Customer the methods and properties that we put in the : Person Person class? Is-a Person person = GetImportantPerson(); return person.FormatName(); Person • string FirstName • string LastName • string Address • string FormatName()
  • 35. PreferredCustomer CustomerContact : Customer Has-a • string FirstName • IList<CustomerContact> Contacts • string LastName • string Address Is-a • string FormatName() Customer Employee • string FirstName • string FirstName • string LastName • string LastName • string Address • string FormatName() • string FormatName() What do we have now: 1. Our classes are no longer tightly coupled by inheritance, so we can change FormatName() on one class without affecting another 2. But we still want to reuse the name formatting code!
  • 36. Create classes that format names – an object- oriented solution! public class FirstNameLastNameNameFormatter { public string FormatName(string firstName, string lastName) { return firstName + “ “ + lastName; } } public class LastNameFirstNameNameFormatter { public string FormatName(string firstName, string lastName) { return lastName + “, “ + firstName; } }
  • 37. Any class that needs to format names can use the name formatter objects. public class Customer { public string FormatName() { return new FirstNameLastNameNameFormatter() .FormatName(FirstName, LastName); } } This technique is called composition – classes can add functionality by using functionality in other objects.
  • 38. module FirstNameLastNameNameFormatter def format_name return first_name + " " + last_name; end end class Customer include FirstNameLastNameNameFormatter attr :first_name, true attr :last_name, true end customer = Customer.new customer.first_name = „Jon‟ customer.last_name = „Kruger‟ puts customer.format_name # this line will output: Jon Kruger
  • 39.  Composition allows you to reuse code without being tightly coupled to a base class  Many loosely coupled, small, testable classes that provide bits of functionality that can be used by anyone who wants to use them  Example: going shopping at a grocery store vs. growing your own food on a farm – at the grocery store, it’s much easier to change what you get!
  • 40. public class Fruit { // Return number of pieces of peel that // resulted from the peeling activity. public int Peel() { return 1; } } public class Apple : Fruit { } public class Example1 { public static void Main(String[] args) { Apple apple = new Apple(); int pieces = apple.Peel(); } }
  • 41. public class Fruit { // Return number of pieces of peel that // resulted from the peeling activity. public PeelResult Peel() { return new PeelResult { NumberOfPeels = 1, Success = true }; } } public class Apple : Fruit { } public class Example1 { public static void Main(String[] args) { Apple apple = new Apple(); int pieces = apple.Peel(); // Compile error! } }
  • 42. public class Fruit { // Return number of pieces of peel that // resulted from the peeling activity. public int Peel() { return 1; } } public class Apple { private Fruit fruit = new Fruit(); // Composition instead of inheritance public int Peel() { return fruit.Peel(); } } public class Example2 { public static void Main(String[] args) { Apple apple = new Apple(); int pieces = apple.Peel(); } }
  • 43. public class Fruit { // Return number of pieces of peel that // resulted from the peeling activity. public PeelResult Peel() { return new PeelResult { NumberOfPeels = 1, Success = true }; } } public class Apple { private Fruit fruit = new Fruit(); // Composition instead of inheritance public int Peel() { return fruit.Peel().NumberOfPeels; // Changes stop here! } } public class Example2 { public static void Main(String[] args) { Apple apple = new Apple(); int pieces = apple.Peel(); } }
  • 46. Agile Software Development Principles, Patterns, and Practices, by Robert C. Martin (aka “Uncle Bob” Martin)
  • 47. Clean Code: A Handbook of Agile Software Craftsmanship, by Robert C. Martin (aka “Uncle Bob” Martin)
  • 48. These are guidelines, not hard and fast rules  Use your brain – do what makes sense  Ask why
  • 49. Software should be:  Easy to test  Easy to change  Easy to add features to  Easy != not learning a new way of doing things
  • 50.  Have only as much complexity as you need – have a reason for complexity  “I don’t want to learn this new way” != too complex
  • 51. A class should have one, and only one, reason to change.
  • 53. 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; } }
  • 54. public class Account { private const decimal _minimumRequiredBalance = 10m; 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; } }
  • 55. 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); } }
  • 56. 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); } }
  • 57. UI Business Logic (Domain Model) Data Access Database
  • 58. 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 { ... } }
  • 59. 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) { ... } }
  • 60. 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) { ... } }
  • 61. 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!
  • 62.  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: MVC controller classes, web services
  • 63.  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)
  • 65.  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
  • 66. public void SubmitOrder(Order order) { // make sure that the order has products 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 the order _orderSubmissionService.SubmitOrder(order); }
  • 67. public void SubmitOrder(Order order) { ValidateOrderHasProducts(order); CalculateTax(order); CalculateShipping(order); SendOrderToOrderSubmissionService(order); }
  • 68. public void SubmitOrder(Order order) { ValidateOrderHasProducts(order); Small CalculateTax(order); CalculateShipping(order); Methods } SendOrderToOrderSubmissionService(order); - After public void ValidateOrderHasProducts(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); }
  • 70. Software entities (classes, modules, methods) should be open for extension but closed for modification.
  • 72. 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); } }
  • 73. 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); } }
  • 74.  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
  • 75.  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; } }
  • 76.  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!
  • 77.  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)
  • 79. Functions that use references to base classes must be able to use objects of derived classes without knowing it.
  • 81. 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)?
  • 82. People using derived classes should not encounter unexpected results when using your derived class.
  • 83. 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; } } }
  • 84. 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(); } } }
  • 86. Clients should not be forced to depend on interfaces that they do not use.
  • 88. ASP.NET MembershipProvider class – a very “fat” interface!
  • 89.  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.
  • 90.  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.
  • 91. Why would you want to?  Use common sense
  • 93. 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.
  • 95.  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
  • 96. UI Business Logic (Domain Model) Data Access Database
  • 97. UI Interfaces Business Logic (Domain Model) Interfaces Data Access Database
  • 98.  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.
  • 99.  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
  • 100. Stubs, mocks, and fakes in unit tests are only possible when we have an interface to implement
  • 101. 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
  • 102. Use of “new” public class GetProductService { public IList<Product> GetProductById(int id) { var productRepository = new ProductRepository(); return productRepository.Get(id); } }
  • 103. Use of “static” public class SecurityService { public static User CurrentUser { get; set; } }
  • 104. Use of singletons using “static” public class ProductCache { private static readonly _instance = new ProductCache(); public static ProductCache Instance { get { return _instance; } } }
  • 105. public class ProductRepository : IProductRepository { public Product Get(int id) { ... } } public interface IProductRepository { Product Get(int id); }
  • 106. public class GetProductService : IGetProductService { private IProductRepository _productRepository; public GetProductService( IProductRepository productRepository) { _productRepository = productRepository; } public IList<Product> GetProductById(int id) { return _productRepository.Get(id); } }
  • 107.  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)
  • 108.  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!
  • 109. public class GetProductService : IGetProductService { private IProductRepository _productRepository; public GetProductService( IProductRepository productRepository) { _productRepository = productRepository; } public IList<Product> GetProductById(int id) { return _productRepository.Get(id); } }
  • 110. ObjectFactory.Initialize(x => { x.ForRequestedType<IGetProductService>() .TheDefaultIsConcreteType<GetProductService>(); });
  • 111. ObjectFactory.Initialize(x => { x.Scan(scan => { scan.WithDefaultConventions(); scan.AssemblyContainingType<IProductRepository>(); }); });  Automatically map “ISomething” interface to “Something” class
  • 112. ObjectFactory.Initialize(x => { x.ForRequestedType<IProductRepository>() .TheDefaultIsConcreteType<ProductRepository>() .OnCreation(repository => repository.ConnectionString = ConfigurationManager.AppSettings["MainDB"]); });  We just reduced duplication and complexity by setting this up here!
  • 113. ObjectFactory.Initialize(x => { x.ForRequestedType<IProductCache>() .TheDefaultIsConcreteType<ProductCache>() .AsSingletons(); });  There will only ever be one IProductCache  We don’t violate DIP by having static variables
  • 114. ObjectFactory.Initialize(x => { x.ForRequestedType<ICurrentUser>() .CacheBy(InstanceScope.Hybrid) .TheDefault.Is.ConstructedBy( c => new CurrentUser(Thread.CurrentPrincipal)); });  InstanceScope.Hybrid means that we will only have one of these objects per request (web) or thread (in our tests)  Testing will be easier because we won’t reference Thread.CurrentPrincipal
  • 115. 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 (usually)
  • 118. Uncle Bob’s SOLID articles  http://bit.ly/solid1  Uncle Bob talking about SOLID on Hanselminutes  http://bit.ly/solid2  ALT.NET mailing list  http://bit.ly/solid4  This list of links (including these slides)  http://jonkruger.com/blog/oopsolid My Info: email: jon@jonkruger.com twitter: @jonkruger / blog: http://jonkruger.com/blog
  • 119. "Draw Five" Draw Five is a card game where you draw five cards and get points based on the cards that you draw. You can also view the high scores and save high scores to a database. When drawing cards - 5 cards are drawn from a standard 52-card deck (keep in mind that the same card cannot be drawn twice) - should show the user what cards they drew When scoring the draw - face cards = 10 - aces = 15 - numbers = number value in addition to base score: - each pair +50 - three of a kind +150 - four of a kind +300 - each spade +1 When showing the high scores - should show the top 5 scores (name and score) When saving a high score - should save the name (entered by the user) and the score =========================================================================== "Blackjack" In this simple version of blackjack, you just draw two cards and calculate the score for the two cards (no drawing of extra cards). High scores are not saved in Blackjack. When drawing cards - 5 cards are drawn from a standard 52-card deck (keep in mind that the same card cannot be drawn twice) - should show the user what cards they drew When scoring the draw - face cards = 10 - aces = 11 - numbers = number value
  • 120. change #1 - Draw Five has 2 Jokers in the deck - jokers = 20 pts each - two jokers = 200 pt bonus (in addition to the 20 pts for each Joker) change #2 - in Draw Five: - a "run" of 3 sequential cards is worth 50 pts - a "run" of 4 sequential cards is worth 100 pts - a "run" of 5 sequential cards is worth 150 pts - the order of cards for "runs" is: A,2,3,4,5,6,7,8,9,10,J,Q,K,A (notice the Ace can be used at either end) extra credit change - create an interface that will allow people to write their own scoring system as a plugin

Editor's Notes

  1. We spend all day changing our codeEvery time you change code, you risk adding a bug to the systemThe more code we have to write, the more bugs we risk introducing into the systemAll of this costs money!Therefore, we should do whatever we can to make our code as easy to change as possible.
  2. This is not a talk about testing. But writing unit tests is the best way that you can keep your code maintainable, well-designed, and easy to change.
  3. Your code should be easy for someone other than you to understand – someday someone other than you will probably be maintaining your codeKeep a long term view of things – most apps are supposed to last for many yearsRemove technical debt, don’t create more of itPlease care.http://www.codinghorror.com/blog/archives/000801.html
  4. 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.
  5. -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
  6. Some of the most un-object-oriented code I have ever seen has been in object-oriented languagesRuby Gems – good example of reuse. Open source projects – good example of reuse. But sometimes it’s better to just write something yourself.Use your brain – sometimes non-OO code is good enough (as long as it’s well encapsulated inside a method)- Write your code so that it’s easier for others to reuse it
  7. We can make this change easily without breaking any code that uses this class.
  8. The comment in this code is a code smell – if you need a comment to describe what you’re code is doing, your code should be more descriptive!
  9. Because we used inheritance, changes to the Fruit class are affecting the Example1 class. Example1 is tightly coupled to Fruit in this case.
  10. Instead of having Apple inherit from Fruit, it will compose itself by having an internal Fruit object.
  11. Changes to Fruit affect the Apple class, but nothing that uses the Apple class. We have better encapsulation and less coupling between our objects.
  12. 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
  13. 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
  14. - Imagine trying to use this thing! It can do everything you want, but doing what you want will be difficult.
  15. - What happens if the requirements change and now you can have a joint account that is held by two people?
  16. - Account doesn’t know anything about who holds the account
  17. - Person still has methods and properties dealing with accounts, but now all of the account logic is correctly encapsulated in the Account class
  18. - small, useful Lego blocks instead of oddly-shaped ones
  19. Explain what a domain service is – not a web service
  20. - This is not added complexity – I’m not writing any more code than I did when it was all one class
  21. 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
  22. - 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.
  23. - 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.
  24. - What is this method doing? Even a non-programmer could tell you!
  25. - 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
  26. - We are trying to do 2 things here – find subsets of users, and return user summaries
  27. 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.
  28. - Comments that say “if you want to add another X, you have to add code in these 5 places”
  29. - Probably need a 2DShape and 3DShape base class
  30. - Example – going to a friend’s house and they have the complicated home theater system and you want to watch TV
  31. - 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?
  32. Java: SpringRuby: we don’t need no stinkin’ DI containers!