SlideShare a Scribd company logo
1 of 68
Download to read offline
Improving Application Design
with a Rich Domain Model
  Chris Ri h d
  Ch i Richardson

  Author of POJOs in Action
  Chris Richardson Consulting, Inc

  http://www.chrisrichardson.net
     p //
3/1/2009                                                                  Slide 1
              Copyright (c) 2007 Chris Richardson. All rights reserved.
Overall presentation g
        p            goal



Learn how to improve application
   design by using truly object-
       g    y    g     y   j
      oriented business logic



3/1/2009                                                               2
           Copyright (c) 2007 Chris Richardson. All rights reserved.
About Chris

                                                     Grew up in England
                                                     Live in Oakland, CA
                                                     Over twenty years of software
                                                     development experience
                                                               Building object-oriented
                                                               software since 1986
                                                               Using Java since 1996
                                                               Using J2EE since 1999
                                                     Author of POJOs in Action
                                                     Speaker at JavaOne, JavaPolis,
                                                     NFJS, JUGs, ….
                                                     Chair of the eBIG Java SIG in
                                                     Oakland (www.ebig.org)
                                                     Run a consulting and training
                                                     company that helps
                                                     organizations build better
                                                     software faster

3/1/2009                                                                                  3
           Copyright (c) 2007 Chris Richardson. All rights reserved.
Agenda
 g

   Where are the real objects?
   Wh          th       l bj t ?
   Overview of the Domain Model pattern
   Domain model building blocks
   Role of frameworks
   Obstacles to OO
   Eliminating common code smells
   Refactoring existing code


3/1/2009                                                                 4
             Copyright (c) 2007 Chris Richardson. All rights reserved.
Objects in LISP (
  j             (1987-1993)
                          )
  (defclass Account ()
    ((account-id :accessor account-id :initarg :account-id)
                                                                                                State
     (balance :accessor account-balance :initarg :balance))
                                                                                                  +
  )

                                                                                               Behavior
  (defmethod debit ((Account account) amount)
   (decf (account-balance account) amount))

  (defmethod credit ((Account account) amount)
   (incf (account balance account) amount))
         (account-balance


      CL-USER 5 > (setq a (make-instance 'account :account-id quot;abc123quot; :balance 10.0))
      #<ACCOUNT 200C05AF>

      CL-USER 6 > (describe a)

      #<ACCOUNT 200C05AF> is an ACCOUNT
      ACCOUNT-ID   quot;abc123quot;
      BALANCE    10.0

      CL-USER
      CL USER 7 > (debit a 5)
      5.0

      CL-USER 8 > (describe a)

      #<ACCOUNT 200C05AF> is an ACCOUNT
      ACCOUNT-ID
      ACCOUNT ID   quot; b 123quot;
                   quot;abc123quot;
      BALANCE    5.0


3/1/2009                                                                                                  5
                                   Copyright (c) 2007 Chris Richardson. All rights reserved.
Objects in C++ (
  j            (1993-1996)
                         )
  #ifndef ACCOUNT_H_
  #define ACCOUNT_H_

  class Account {
  public:
              Account(char* account_id, double balance);
              void debit(double amount);
              void credit(double amount);
              double getBalance();
  private:
              char* account_id;
                                                                                               State
              double balance;
  };
                                                                                                 +
  #endif /*ACCOUNT_H_*/
                                                                                              Behavior
     #include quot;Account.hquot;
     #incl de quot;Acco nt hquot;

     Account::Account(char* account_id, double balance) {
        …
     }
     void Account::debit (double amount) {
                 balance -= amount;
                 bl
     }

     void Account::credit(double amount) {
                 balance += amount;
     }

     double Account::getBalance() { return balance; }


3/1/2009                                                                                                 6
                                  Copyright (c) 2007 Chris Richardson. All rights reserved.
Objects in Java (
  j             (1996-1999)
                          )
     public class Account {

      private int id;

      private double balance;

      private OverdraftPolicy overdraftPolicy;

                                                                                                   State
      private String accountId;

                                                                                                     +
      private CalendarDate dateOpened;

                                                                                                  Behavior
      Account() {
      }

      p
      public void debit(double amount) {
                       (               )
        assert amount > 0;
        double originalBalance = balance;
        double newBalance = balance - amount;
        overdraftPolicy.beforeDebitCheck(this, originalBalance,
                                            newBalance);
        balance = newBalance;
        overdraftPolicy.afterDebitAction(this, originalBalance, newBalance);
            d ftP li     ft D bitA ti (thi       i i lB l          Bl     )
      }

      public void credit(double amount) {
        assert amount > 0;
        balance += amount;
      }




3/1/2009                                                                                                     7
                                      Copyright (c) 2007 Chris Richardson. All rights reserved.
EJB objects (
      j     (1999- ?)
                    )

    Applications were still built
     pp
            from objects

   But those objects were very
            different …



3/1/2009                                                                 8
             Copyright (c) 2007 Chris Richardson. All rights reserved.
Example Banking UI
    p         g




3/1/2009                                                               9
           Copyright (c) 2007 Chris Richardson. All rights reserved.
Example p
    p procedural design
                     g




3/1/2009                                                               10
           Copyright (c) 2007 Chris Richardson. All rights reserved.
Example p
    p procedural code
public class MoneyTransferServiceProceduralImpl implements MoneyTransferService {                     public class Account {

p
public BankingTransaction transfer(String fromAccountId, String toAccountId,
             g                    (     g               ,     g            ,                           p
                                                                                                       public static final int NEVER = 1;
                                                                                                                                        ;
    double amount) {                                                                                   public static final int ALLOWED = 2;
  Account fromAccount = accountDAO.findAccount(fromAccountId);
  Account toAccount = accountDAO.findAccount(toAccountId);                                            private   int id;
  assert amount > 0;                                                                                  private   double balance;
  double newBalance = fromAccount.getBalance() - amount;                                              private   int overdraftPolicy;
  switch (fromAccount.getOverdraftPolicy()) {                                                         private   String accountId;

                                                                      Behavior                                                                         State
  case Account.NEVER:                                                                                 private   Date dateOpened;
    if (newBalance < 0)                                                                               private   double requiredYearsOpen;
      throw new MoneyTransferException(quot;In sufficient fundsquot;);                                        private   double limit;
    break;
  case Account.ALLOWED:                                                                               Account() {}
    Calendar then = Calendar.getInstance();
    then.setTime(fromAccount.getDateOpened());
    Calendar now = Calendar.getInstance();                                                            public Account(String accountId, double balance, int
                                                                                                      overdraftPolicy,
      double yearsOpened = now.get(Calendar.YEAR) - then.get(Calendar.YEAR);                                           Date dateOpened, double requiredYearsOpen,
      int monthsOpened = now.get(Calendar.MONTH) - then.get(Calendar.MONTH);                          double limit)
      if (monthsOpened < 0) {                                                                          {….. }
        yearsOpened--;
              O     d
        monthsOpened += 12;                                                                           public int getId() {return id;}
      }
      yearsOpened = yearsOpened + (monthsOpened / 12.0);                                              public String getAccountId() {return accountId;}
      if (yearsOpened < fromAccount.getRequiredYearsOpen()
          || newBalance < fromAccount.getLimit())                                                     public void setBalance(double balance) { this.balance = balance; }
        throw new MoneyTransferException(quot;Limit exceededquot;);
      break;                                                                                          public double getBalance() { return balance; }
     default:
      throw new MoneyTransferException(quot;Unknown overdraft type: quot;
                 MoneyTransferException( Unknown                                                      public int getOverdraftPolicy() { return overdraftPolicy; }
          + fromAccount.getOverdraftPolicy());
                                                                                                      public Date getDateOpened() {     return dateOpened; }
     }
     fromAccount.setBalance(newBalance);                                                              public double getRequiredYearsOpen() {
     toAccount.setBalance(toAccount.getBalance() + amount);                                               return requiredYearsOpen; }
     TransferTransaction txn = new TransferTransaction(fromAccount, toAccount,
        amount, new Date());                                                                          public double getLimit() {return limit; }
     bankingTransactionDAO.addTransaction(txn);                                                       }
     return txn;
 }




3/1/2009                                                                                                                                                             11
                                                         Copyright (c) 2007 Chris Richardson. All rights reserved.
Why write code like this?
  y
    EJB made writing object-oriented code
    difficult/impossible
    diffi lt/i      ibl
    Implementing new functionality is easy
           Add a new transaction script
                             i      i
           Add code to a new transaction script
    Manipulating relational data is easier
    Distribution is easier
    No
    N need to do any real design, e.g.
           dt d            ld i
           Create new classes
           Determine responsibilities

3/1/2009                                                                          12
                      Copyright (c) 2007 Chris Richardson. All rights reserved.
Unable to handle complexity
                    p     y
    Works well for simple business logic
           E.g.
           E g the example wasn’t that bad
                           wasn t
    But with complex business logic:
           Large transaction scripts: 100s/1000s LOC
           Difficult/impossible to understand, test, and
           maintain
    What s
    What’s worse: business logic has a habit
    of growing
           New requirements ⇒ Add a few more lines
           to the transaction script
           Many new requirements ⇒ big mess
           Soon or later you end up with
           unmaintainable code

3/1/2009                                                                          13
                      Copyright (c) 2007 Chris Richardson. All rights reserved.
The legacy of EJB
      gy
           Java is an object-oriented language

                                        AND

  Object-oriented design is a better way to tackle
                     complexity

                                          YET

   Many complex enterprise Java applications are
            written in a procedural style


3/1/2009                                                                        14
                    Copyright (c) 2007 Chris Richardson. All rights reserved.
Today – rich domain models are
growing in popularity

    POJOs
           Plain Old Java Objects
           Leverage OO features of Java
    O/R mapping frameworks for
    persisting POJOs:
           Hibernate
           Java Persistence API
           …
    Spring AOP and A
    Si            d AspectJ f
                           tJ for
    handling cross-cutting
    concerns:
           Transaction management
           Security
           S     it
           Logging
           Auditing
           …



3/1/2009                                                                                15
                            Copyright (c) 2007 Chris Richardson. All rights reserved.
Agenda
 g

   Where are the real objects?
   Overview of the Domain Model
   pattern
   Domain model building blocks
   Role of frameworks
   Obstacles to OO
   Eliminating common code smells
              g
   Refactoring existing code


3/1/2009                                                                  16
              Copyright (c) 2007 Chris Richardson. All rights reserved.
Using the Domain Model Pattern
    g

   Business logic spread amongst a
   Bi        li          d      t
   collection of classes
   Many classes correspond to real world
   concepts: Order, Customer, …
   Many classes are true objects having
   both:
           State – fields
           Behavior – methods that act on the state



3/1/2009                                                                          17
                      Copyright (c) 2007 Chris Richardson. All rights reserved.
Procedural versus OO
                Presentation Tier
                                                                                                Presentation Tier


Business Tier

                                                                       Business Tier
Transaction
  Scripts
                                                                         Facade
 (Session
  Beans)
                                                                         Domain Model




     Data
    Objects




                                                                                                Data Access Tier
                Data Access Tier




   3/1/2009                                                                                                         18
                                    Copyright (c) 2007 Chris Richardson. All rights reserved.
An example domain model
       p
                                                Web Tier

                           Behavior
     Business Tier


                                        MoneyTransferService


                           BankingTransaction transfer(fromId, toId, amount)




                                                        from
                                                                       Account
                                     Banking                                                        Account
      BankingTransaction
                                   Transaction                                                     Repository
          Repository
                                                                   balance
                                                         to
                                 amount                                                           findAccount(id)
      addTransaction(…)                                            debit(amount)
                                 date
                                                                   credit(amount)




                                                                                                      Explicit
                                                                 <<interface>>
                                                                 OverdraftPolicy
                                                                                                   Representation
                      State +
                                                                                                       of key
                      Behavior                                                        Limited
                                                                                                     conceptst
                                                          NoOverdraft                Overdraft
                                                            Policy
                                                                                  limit




3/1/2009                                                                                                            19
                                      Copyright (c) 2007 Chris Richardson. All rights reserved.
DEMO

Code Walkthrough




 3/1/2009                                                                20
             Copyright (c) 2007 Chris Richardson. All rights reserved.
Benefits of the Domain Model
Pattern
    Improved maintainability
           The design reflects reality
           Key domain classes are represented by
           classes
           The design is more modular
    Improved testability
           Small classes that can be tested in isolation
    Improved reusability
           Classes can be used in other applications
    Building a domain model
           Creates shared understanding
           Develops an ubiquitous language
                 p        q          gg

3/1/2009                                                                          21
                      Copyright (c) 2007 Chris Richardson. All rights reserved.
Q
Quantifiably simpler code
           y    p

    Procedural – few longer more
                 few, longer,                                          Object-oriented more, simpler
                                                                       Object oriented – more simpler,
          complex methods                                                      shorter methods




3/1/2009                                                                                                 22
                          Copyright (c) 2007 Chris Richardson. All rights reserved.
Drawbacks of the Domain Model
p
pattern

    Requires object-oriented design skills
    Works best if domain model is
    transparently “mappable” to the data
           E.g. nice database schema
           Ugly schemas and data stored in other
           applications is a challenge
               l              h ll




3/1/2009                                                                        23
                    Copyright (c) 2007 Chris Richardson. All rights reserved.
When to use it
    The business logic is reasonably
    complex or you anticipate that it will
    be
    You have the skills to design one
    You can either:
           Use an ORM framework
           Invest in writing a data access
           framework



3/1/2009                                                                         24
                     Copyright (c) 2007 Chris Richardson. All rights reserved.
Agenda
 g

   Where are the real objects?
   Wh         th      l bj t ?
   Overview of the Domain Model pattern
   Domain model building blocks
   Role of frameworks
   Obstacles to OO
   Eliminating common code smells
   Refactoring existing code


3/1/2009                                                                 25
             Copyright (c) 2007 Chris Richardson. All rights reserved.
Domain model building blocks
                    g

                                                     Roles aka
                                                     stereotypes
                                                     Benefits of roles:
                                                               Guide design
                                                               Help name
                                                               objects
                                                                bj t
                                                               Aid understanding
                                                     Roles (from
                                                     Domain-Driven
                                                     Design)

3/1/2009                                                                      26
           Copyright (c) 2007 Chris Richardson. All rights reserved.
Entity
     y

   Objects with a                           public class Account {


   distinct identity                         private int id;


   Typically correspond
                                             private double balance;



   to real world
                                             private OverdraftPolicy overdraftPolicy;

                                             private String accountId;
   concepts                                  private CalendarDate dateOpened;

   Almost always                             Account() {

   persistent
                                             }

                                             public void debit(double amount) {

   Encapsulate state and                       assert amount > 0;
                                               double originalBalance = balance;

   behavior                                    double newBalance = balance - amount;
                                               overdraftPolicy.beforeDebitCheck(this, originalBalance, newBalance);
                                               balance = newBalance;

   Often modal ⇒ call                          overdraftPolicy.afterDebitAction(this, originalBalance, newBalance);
                                             }

   methods in a                              public void credit(double amount) {

   particular order                            assert amount > 0;
                                               balance += amount;
                                             }




3/1/2009                                                                                                   27
                 Copyright (c) 2007 Chris Richardson. All rights reserved.
Value Objects
        j
 Objects that are
                                                 public class CalendarDate {


 defined by the values                               private Date date;


 of their attributes                                 CalendarDate() {
                                                     }

 Two instances with                                  public CalendarDate(Date date) {

 identical values can be
                                                       this.date = date;
                                                     }

 used i t
     d interchangeably
             h       bl                              public Date getDate() {
                                                       return date;
 Two flavors                                         }

      Persistent – parts of                          public double getYearsOpen() {
                                                      Calendar then = Calendar.getInstance();
      entities                                        then.setTime(date);
                                                      then setTime(date);
                                                      Calendar now = Calendar.getInstance();
      Transient – intermediate
      values                                             int yearsOpened = now.get(Calendar.YEAR) –
                                                                           then.get(Calendar.YEAR);

 Ideally immutable                                       int monthsOpened = now.get(Calendar.MONTH) -
                                                                          then.get(Calendar.MONTH);

 Often missing from
 Oft       ii   f
                                                         if (monthsOpened < 0) {
                                                           yearsOpened--;

 procedural code –
                                                           monthsOpened += 12;
                                                         }

 Primitive Obsession                                     return yearsOpened + (monthsOpened/12.0);


 code smell                                          }

                                                 }




3/1/2009                                                                                                28
                     Copyright (c) 2007 Chris Richardson. All rights reserved.
More examples of Value Objects
               p               j
                                                                                       public class User {
public class User {
                                                                                         private int id;
 private String firstName;
                                                                                         private PersonName name;
 p
 private String lastName;
              g          ;
                                                                                         private UserId login;
 private String login;
                                                                                         private Password password;
 private String password;
                                                                                         …
 …
                                                                                       }
}




                                              public class Password implements Serializable {

                                               private String passwordString;

    public class PersonName {                 public Password(String passwordString) {
     private String firstName;                   this.passwordString = passwordString == null ? null : passwordString.trim();
     private String lastName;                  }

     PersonName() {                            …
     }                                         @Override
                                               public String t St i () {
                                                  bli St i   toString()
     public PersonName(String firstName,         return new ToStringBuilder(this).append(quot;passwordquot;, quot;****quot;).toString();
               String lastName) {              }
       this.firstName = firstName;
       this.lastName = lastName;
     }




       3/1/2009                                                                                                        29
                                           Copyright (c) 2007 Chris Richardson. All rights reserved.
Aggregates
 gg g

                                                     A cluster of related
                                                     entities and values
                                                     Behaves as a unit
                                                     Has
                                                     H a root  t
                                                     Has a boundary
                                                     Objects outside the
                                                     aggregate can only
                                                     reference the root
                                                     Deleting the root
                                                     removes
                                                     everything


3/1/2009                                                               30
           Copyright (c) 2007 Chris Richardson. All rights reserved.
Repositories
  p
                                                        public interface AccountRepository {
    Manages a collection of
    objects                                                  Account findAccount(String accountId);

                                                             void addAccount(Account account);
    Provides methods for:                               }
           Adding an object
           Finding object or objects
           Deleting objects                             public class HibernateAccountRepository implements AccountRepository {


    Consists of an interface                                private HibernateTemplate hibernateTemplate;

    and an implementation                                   public HibernateAccountRepository(HibernateTemplate template) {
                                                              hibernateTemplate = template;
    class
     l                                                      }

    Encapsulates database                                   public void addAccount(Account account) {
                                                              hibernateTemplate.save(account);
    access mechanism                                        }

    Keeps the ORM                                           public Account findAccount(final String accountId) {
                                                              return (Account) DataAccessUtils.uniqueResult(hibernateTemplate
    framework out of the                                         .findByNamedQueryAndNamedParam(

    domain model
                                                                     quot;Account.findAccountByAccountIdquot;, quot;accountIdquot;,
                                                                     accountId));
                                                            }
    Similar to a DAO                                    }




3/1/2009                                                                                                               31
                            Copyright (c) 2007 Chris Richardson. All rights reserved.
Services
                                                       public interface MoneyTransferService {
    Implements logic that                                   BankingTransaction transfer(String fromAccountId,
    cannot be put in a single                                    String toAccountId, double amount);

    entity                                             }


    Not persistent
         p
    Consists of an interface                           public class MoneyTransferServiceImpl implements MoneyTransferService
                                                       {
    and an implementation                                  private final AccountRepository accountRepository;
    class                                                  private final BankingTransactionRepository

    Service method usually:                                           bankingTransactionRepository;

                                                           public MoneyTransferServiceImpl(AccountRepository accountRepository,
           Invoked (indirectly) by                            BankingTransactionRepository bankingTransactionRepository) {
           presentation tier                                 this.accountRepository = accountRepository;
                                                             this.bankingTransactionRepository = bankingTransactionRepository;
           Invokes one or more                             }

           repositories                                    public BankingTransaction transfer(String fromAccountId,
                                                              String toAccountId, double amount) {
           Invokes one or more                               …
           entities                                        }


    Keep them thin                                     }




3/1/2009                                                                                                              32
                           Copyright (c) 2007 Chris Richardson. All rights reserved.
Factories
    Use when a constructor is insufficient
           Encapsulates complex object creation
           E      l          l   bj         i
           logic
           Handles varying products
    Different kinds of factories
           Factory classes
           Factory methods
    Example: OrderFactory
        p               y
           Creates Order from a shopping cart
           Adds line items

3/1/2009                                                                        33
                    Copyright (c) 2007 Chris Richardson. All rights reserved.
Agenda
 g

   Where are the real objects?
   Wh         th      l bj t ?
   Overview of the Domain Model pattern
   Domain model building blocks
   Role of frameworks
   Obstacles to OO
   Eliminating common code smells
   Refactoring existing code


3/1/2009                                                                 34
             Copyright (c) 2007 Chris Richardson. All rights reserved.
Use the POJO programming model
             pg        g
    Your domain model might outlive
    infrastructure frameworks ⇒ Minimize
    dependencies on them
    POJO = Plain Old Java Object
    Don't implement any infrastructure
    interfaces
    Don't call infrastructure APIs
    No infrastructure framework
    annotations?

3/1/2009                                                                  Slide 35
              Copyright (c) 2007 Chris Richardson. All rights reserved.
Use dependency injection
      p      yj
  Spring instantiates and wires together components:
        Services, factories and repositories
        S   i     fti         d      it i
  Dependency injection into entities
        One option is @Configurable but it’s not POJO
        Use Hibernate Interceptor + manual injection instead?
  Benefits:
        Decouples components from one another and the
        infrastructure
        Improves testability
                                                                                 <beans>

                                                                                <bean id=quot;accountServicequot;
                                                                                  class=quot;net.chris...domain.AccountServiceImplquot;>
public AccountServiceImpl(AccountDao accountDao,                                  <constructor-arg ref=quot;accountDaoquot;/>
                                                                                  <constructor-arg ref=quot;bankingTransactionDaoquot;/>
   BankingTransactionDao bankingTransactionDao) {
                                                                                </bean>
  this.accountDAO = accountDao;
  this.bankingTransactionDAO = bankingTransactionDao;                           …
}                                                                               </beans>




 3/1/2009                                                                                             Slide 36
                               Copyright (c) 2007 Chris Richardson. All rights reserved.
Use Aspect-Oriented Programming
      p                g      g

 Spring AOP for service-level
 crosscutting concerns:
      E.g. transaction
      management, security,
      logging etc.
 AspectJ for entity and value
 object crosscutting concerns
      E.g. tracking changes to
      fields
      But AJC/Load-time weaving
      has a cost
 Benefits
      Decouples code from
      infrastructure
      Improves modularity



3/1/2009                                                                         37
                     Copyright (c) 2007 Chris Richardson. All rights reserved.
Use object/relational mapping
       j   /             pp g

   Persisting objects
            g   j                                              <class name=quot;Accountquot;
                                                                      table BANK_ACCOUNT
                                                                      table=quot;BANK ACCOUNTquot; >

   with JDBC is usually
                                                                    <id name=quot;idquot; column=quot;ACCOUNT_IDquot;>
                                                                       <generator class=quot;nativequot; />
                                                                    </id>
   too much work                                                    <property name=quot;balancequot; />
                                                                    <property name=quot;accountIdquot; />

   Implement DAOs
                                                                    <property name=quot;dateOpenedquot; />
                                                                    <many-to-one name=quot;overdraftPolicyquot; />
                                                                </class>
   with Spring ORM
   Benefits                                            public class HibernateAccountDao
                                                         implements AccountDao {
                                                        private HibernateTemplate hibernateTemplate;
           Less code                                     public HibernateAccountDao(HibernateTemplate
                                                                                      template) {
           Simpler code
           Si   l    d                                     this.hibernateTemplate = template;
                                                         }

           Improved testability                          public void addAccount(Account account) {
                                                           hibernateTemplate.save(account);
                                                         }
                                                       …
                                                       }

3/1/2009                                                                               Slide 38
                       Copyright (c) 2007 Chris Richardson. All rights reserved.
Agenda
 g
    Where are the real objects?
    Overview of the Domain Model
    pattern
    Domain model building blocks
    Role of frameworks
    Obstacles to good OO design
    Eliminating common code smells
    Refactoring existing code

3/1/2009                                                                  Slide 39
              Copyright (c) 2007 Chris Richardson. All rights reserved.
Web frameworks need Java Beans
    Web frameworks can bind request
    parameters directly to domain objects
    Easy creation of domain objects
    Easy editing of detached domain objects
     asy ed    g o de ac ed do a objec s
    1.     Load object graph from database
    2.     Store object graph in HttpSession
    3.
    3      Bind Http parameters to object's properties
    4.     Reattach object graph and update the database
    A lot less code
    But domain objects must be JavaBeans:
           Public default constructor
           JavaBean-style setters
           Ja aBean st le sette s

3/1/2009                                                                           Slide 40
                       Copyright (c) 2007 Chris Richardson. All rights reserved.
The trouble with setters
                                                                     public class Address {
    Poor encapsulation                                                 private String street1;
                                                                       private String street2;
           Objects are now exposing                                      public String getStreet1() {...};
           their internal state                                          public void setStreet1(String street1) {...}
                                                                         …
    No immutable objects                                             }

           Increases code complexity                                     public class Order {

           Makes it more error-prone                                     private Address deliveryAddress;

    Developers might b
    D    l      i ht bypass                                              public void updateDeliveryAddress(
                                                                            Address deliveryAddress) {
    business method ⇒ Bugs,                                                // validate before changing

    p
    poor design
             g
                                                                           …
                                                                         }

                                                                         public Address getAddress() {…}
                                                                         …
                                                                         }


                                                                  order.getAddress().setStreet1(quot;Bad!quot;);



3/1/2009                                                                                   Slide 41
                        Copyright (c) 2007 Chris Richardson. All rights reserved.
How to cope
         p
    Live with it:
           It's often not that bad
           But be vigilant for code bypassing
           business methods
           bi           th d
    Use DTOs
           Hides domain objects from web tier
           But you have to write more code
    Encourage the development of better
    frameworks

3/1/2009                                                                         Slide 42
                     Copyright (c) 2007 Chris Richardson. All rights reserved.
More on web binding
                   g
      Web frameworks can bind to
      properties of nested objects, e.g.
      order.deliveryAddress.street1
      But some frameworks require that
      intermediate objects to be non-null
      This can impact the domain model




3/1/2009                                                                     Slide 43
                 Copyright (c) 2007 Chris Richardson. All rights reserved.
Using ORM frameworks
     g
      ORM frameworks can access private fields
           No setters (or g
                      ( getters) required ☺
                               )q
      But require:
           Default constructor
           Non-final fields
           id fields
      Subtle changes:
           Collection fields: null ⇒ empty
                                       py
           Embedded objects with null fields ⇒ null reference
           Objects sometimes require equals()/hashCode()
      Proxy-based lazy loading:
           Don't access fields outside of instance ⇒ affects
           equals() and hashCode()
           Can affect object identity: this !=
           proxyToSameObjectAsThis

3/1/2009                                                                            Slide 44
                        Copyright (c) 2007 Chris Richardson. All rights reserved.
Performance tuning changes the
design
    g
    Different web requests                                               DisplayProject            DisplayProject
                                                                            Details                  ForReview

    display different object                                               Controller                Controller




    graphs
           Display project details
                                                                       ProjectCoordinator

                                                                       getProject(projectId)

           Display project for
           approval or rejection                                        ProjectRepository

    Improve performance                                                                                 hibernateTemplate.get()
                                                                      findProject(projectId)


    by loading object
    graphs using optimized
    queries (e.g. fetch                                                ProjectCoordinator


    join)                                                        getProjectDetails(projectId)
                                                                 getProjectForReview(projectId)


    Therefore we need
    multiple Dao (and
                                                                                                            from Project p
                                                                        ProjectRepository
                                                                                                            inner join fetch p.operations



    Service) methods
                                                                 findProjectDetails(projectId)
                                                                 findProjectForReview(projectId)
                                                                                                            from Project p
                                                                                                            inner join fetch p.operations
                                                                                                            Inner join fetch p.createdBy




3/1/2009                                                                                                                     Slide 45
                       Copyright (c) 2007 Chris Richardson. All rights reserved.
Untangling what to load from the
code
    Java Data Objects (JDO) has fetch
    groups
           Declarative specification of the object graph
           to load
           Fields and related objects
    Flow:
           Web tier
           W b ti configures f t h groups
                        fi     fetch
           Calls ProjectCoordinator.get()
           O/RM loads object graph specified by active
           fetch groups
    Look for this feature in JPA
    implementations th t evolved f
    i  l      t ti    that     l d from JDO
3/1/2009                                                                          Slide 46
                      Copyright (c) 2007 Chris Richardson. All rights reserved.
Agenda
 g

   Where are the real objects?
   Wh         th      l bj t ?
   Overview of the Domain Model pattern
   Domain model building blocks
   Role of frameworks
   Obstacles to OO
   Eliminating common code smells
   Refactoring existing code


3/1/2009                                                                 47
             Copyright (c) 2007 Chris Richardson. All rights reserved.
Overview of code smells
    Code smell = something
    about the code that does not
    seem right
    Impacts ease of
    development and testing
    Some are non-OOD
    Some are the consequences
    of non-OOD


3/1/2009                                                                  48
              Copyright (c) 2007 Chris Richardson. All rights reserved.
Refactoring – the cure for stinky
code

    Refactoring:
           Systematic way to
           restructure the
           code
           Without changing
           behavior
           bh i
    Essential
    cleanups for
    decaying code


3/1/2009                                                                         49
                     Copyright (c) 2007 Chris Richardson. All rights reserved.
Basic refactorings
                g

                                                     Extract Method
                                                               Eliminates long methods
                                                     Move Method
                                                               Move a method to a
                                                               different class (field or
                                                               parameter)
                                                               Moves method to where
                                                               the data is
                                                     Push Down
                                                               Move a method into
                                                               subclasses
                                                               Optionally leave an
                                                               abstract method behind
                                                               Part of eliminating
                                                               conditional logic
                                                     …


3/1/2009                                                                                50
           Copyright (c) 2007 Chris Richardson. All rights reserved.
Compound refactorings
   p               g
    A sequence of simpler refactorings
    Compose method
           Apply Extract Method repeatedly
           Use to replace long method with more readable
           shorter methods
    Replace Type Code With Strategy
           Define GOF Strategy class for each type code
    Replace C diti
    Rl      Conditional With P l
                      l      Polymorphism
                                     hi
           Turn into part of a switch statement into an
           overriding method in a subclass
    Replace D
    Rl      Data Value with Object
                 Vl     i h Obj
           Move field into it’s own class
           Eliminates Primitive Obsession


3/1/2009                                                                           51
                       Copyright (c) 2007 Chris Richardson. All rights reserved.
Long method
   g
 Methods should be
 short                                           p
                                                 public class MoneyTransferServiceProceduralImpl implements MoneyTransferService {
                                                                  y                           p    p            y

                                                 public BankingTransaction transfer(String fromAccountId, String toAccountId,
                                                     double amount) {


 But business logic is                             Account fromAccount = accountDAO.findAccount(fromAccountId);
                                                   Account toAccount = accountDAO.findAccount(toAccountId);
                                                   assert amount > 0;


 concentrated in the
                                                   double newBalance = fromAccount.getBalance() - amount;
                                                   switch (fromAccount.getOverdraftPolicy()) {
                                                   case Account.NEVER:


 services ⇒ long
                                                     if (newBalance < 0)
                                                       throw new MoneyTransferException(quot;In sufficient fundsquot;);
                                                                 MoneyTransferException( In            funds );
                                                     break;


 methods
                                                   case Account.ALLOWED:
                                                     Calendar then = Calendar.getInstance();
                                                     then.setTime(fromAccount.getDateOpened());
                                                     Calendar now = Calendar.getInstance();


 Long methods are                                      double yearsOpened = now.get(Calendar.YEAR) - then.get(Calendar.YEAR);
                                                       int monthsOpened = now.get(Calendar.MONTH) - then.get(Calendar.MONTH);



 difficult to:
                                                       if (monthsOpened < 0) {
                                                         yearsOpened--;
                                                         monthsOpened + 12
                                                              th O    d += 12;
                                                       }


      Read and understand
                                                       yearsOpened = yearsOpened + (monthsOpened / 12.0);
                                                       if (yearsOpened < fromAccount.getRequiredYearsOpen()
                                                           || newBalance < fromAccount.getLimit())
                                                         throw new MoneyTransferException(quot;Limit exceededquot;);

      Maintain                                         break;
                                                      default:
                                                       throw new MoneyTransferException(quot;Unknown overdraft type: quot;

      Test
                                                           + fromAccount.getOverdraftPolicy());

                                                      }



 Fix:
                                                      fromAccount.setBalance(newBalance);
                                                      toAccount.setBalance(toAccount.getBalance() + amount);
                                                      TransferTransaction txn = new TransferTransaction(fromAccount, toAccount,
                                                         amount, new Date());


      Splitting into smaller
                                                      bankingTransactionDAO.addTransaction(txn);
                                                      return txn;
                                                  }

      methods


3/1/2009                                                                                                                             52
                      Copyright (c) 2007 Chris Richardson. All rights reserved.
Compose Method Refactoring
         p                     g
                                                                                        public class MoneyTransferServiceProceduralImpl implements
                                                                                        MoneyTransferService {
public class MoneyTransferServiceProceduralImpl
                                                                                        public BankingTransaction transfer(String fromAccountId, String
implements MoneyTransferService {
                                                                                                  toAccountId,
                                                                                                  toAccountId double amount) {
                                                                                           Account fromAccount =
public BankingTransaction transfer(String fromAccountId,
                                                                                                   accountDAO.findAccount(fromAccountId);
   String toAccountId, double amount) {
                                                                                           Account toAccount = accountDAO.findAccount(toAccountId);
    Account fromAccount =
                                                                                           assert amount > 0;
            accountDAO.findAccount(fromAccountId);
                                                                                           debit(fromAccount, amount);
    Account toAccount =
                                                                                           credit(toAccount, amount);
             accountDAO.findAccount(toAccountId);
                                                                                           TransferTransaction txn = new
                                                                   Extract
                                                                   Et    t
    double newBalance = fromAccount getBalance() –
                            fromAccount.getBalance()
                                                                                                       TransferTransaction(fromAccount, toAccount,
                               amount;
                                                                   Method                     amount, new Date());
    switch (fromAccount.getOverdraftPolicy()) {
                                                                                           bankingTransactionDAO.addTransaction(txn);
    case Account.NEVER:
                                                                                           return txn;
      …
                                                                                         }
     break;
    default:
                                                                                         public void debit(Account fromAccount, double amount) {
     …
                                                                                          double newBalance = fromAccount.getBalance() –
  }
                                                                                                               amount;
   fromAccount.setBalance(newBalance);
                                                                                          switch (fromAccount.getOverdraftPolicy()) {
   toAccount.setBalance(toAccount.getBalance() +
                                                                                          case Account.NEVER:
                            amount);
                                                                                           …
   TransferTransaction txn = new
                                                                                            break;
         TransferTransaction(fromAccount, toAccount,
                                                                                          default:
                               amount,
                               amount new Date());
                                                                                            …
  bankingTransactionDAO.addTransaction(txn);
                                                                                          }
   return txn;
                                                                                          fromAccount.setBalance(newBalance);
}
                                                                                        }

                                                                                        public void credit(Account toAccount, double amount) {
                                                                                          toAccount.setBalance(toAccount.getBalance() +
                                                                                                                  amount);
                                                                                        }



       3/1/2009                                                                                                                               53
                                                  Copyright (c) 2007 Chris Richardson. All rights reserved.
Feature Envy
           y
                                               public class MoneyTransferServiceProceduralImpl implements MoneyTransferService {

                                               public BankingTransaction transfer(String fromAccountId, String toAccountId, double
                                               amount) {

    Methods that are                             Account fromAccount = accountDAO.findAccount(fromAccountId);
                                                 Account toAccount = accountDAO.findAccount(toAccountId);
                                                 assert amount > 0;


    far too interested
                                                 double newBalance = fromAccount.getBalance() - amount;
                                                 switch (fromAccount.getOverdraftPolicy()) {
                                                 case Account.NEVER:


    in data belonging
                                                   if (newBalance < 0)
                                                     throw new MoneyTransferException(quot;In sufficient fundsquot;);
                                                   break;
                                                 case Account.ALLOWED:

    to th
    t other classes
               l                                   Calendar then = C l d
                                                   C l d th        Calendar.getInstance();
                                                                                tI t      ()
                                                   then.setTime(fromAccount.getDateOpened());
                                                   Calendar now = Calendar.getInstance();



    Results in:
                                                     double yearsOpened = now.get(Calendar.YEAR) - then.get(Calendar.YEAR);
                                                     int monthsOpened = now.get(Calendar.MONTH) - then.get(Calendar.MONTH);
                                                     if (monthsOpened < 0) {
                                                       yearsOpened--;

           Poor encapsulation                          monthsOpened += 12;
                                                     }
                                                     yearsOpened = yearsOpened + (monthsOpened / 12.0);


           Long methods
                                                     if (yearsOpened < fromAccount.getRequiredYearsOpen()
                                                         || newBalance < fromAccount.getLimit())
                                                       throw new MoneyTransferException(quot;Limit exceededquot;);
                                                     break;


    Fix by moving
                                                    default:
                                                     throw new MoneyTransferException(quot;Unknown overdraft type: quot;
                                                         + fromAccount.getOverdraftPolicy());


    methods to the
       th d t th                                    }
                                                    fromAccount.setBalance(newBalance);


    class that has the
                                                    toAccount.setBalance(toAccount.getBalance() + amount);
                                                    TransferTransaction txn = new TransferTransaction(fromAccount, toAccount,
                                                       amount, new Date());
                                                    bankingTransactionDAO.addTransaction(txn);


    data
                                                    return txn;
                                                }




3/1/2009                                                                                                                             54
                      Copyright (c) 2007 Chris Richardson. All rights reserved.
Data class
                                                 public class Account {

                                                 public static final int NEVER = 1;

    Classes that are                             public static final int ALLOWED = 2;

                                                 private   int id;

    just getters and                             private   double balance;
                                                 private   int overdraftPolicy;
                                                 private   String accountId;

    setters                                      private   Date dateOpened;
                                                 private   double requiredYearsOpen;
                                                 p
                                                 private   double limit;
                                                                       ;

    No business logic -                          Account() {}



    it’s in the service                          public Account(String accountId, double balance, int overdraftPolicy,
                                                                 Date dateOpened, double requiredYearsOpen, double limit)
                                                  {….. }

    Leads to:                                    public int getId() {return id;}


           Feature envy                          public String getAccountId() {return accountId;}

                                                 public void setBalance(double balance) { this.balance = balance; }


    Fix by moving
         y       g                               public double getBalance() { return balance; }



    methods that act
                                                 public int getOverdraftPolicy() { return overdraftPolicy; }

                                                 public Date getDateOpened() {     return dateOpened; }

    on data into class                           public double getRequiredYearsOpen() {       return requiredYearsOpen; }

                                                 public double getLimit() {return limit; }
                                                 }




3/1/2009                                                                                                                    55
                      Copyright (c) 2007 Chris Richardson. All rights reserved.
Move Method refactoring
                               g
                                                                                                               public class MoneyTransferServiceProceduralImpl implements
                                                                                                                         MoneyTransferService {
public class MoneyTransferServiceProceduralImpl implements MoneyTransferService {
                                                                                                               public BankingTransaction transfer(String fromAccountId, String
public BankingTransaction transfer(String fromAccountId, String toAccountId, double
                                                                                                                         toAccountId,
                                                                                                                         toAccountId double amount) {
amount) {
  Account fromAccount = accountDAO.findAccount(fromAccountId);
                                                                                                                  Account fromAccount =
  Account toAccount = accountDAO.findAccount(toAccountId);
                                                                                                                          accountDAO.findAccount(fromAccountId);
  assert amount > 0;
  double newBalance = fromAccount.getBalance() - amount;
                                                                                                                  Account toAccount = accountDAO.findAccount(toAccountId);
  switch (fromAccount.getOverdraftPolicy()) {
                                                                                                                  assert amount > 0;
  case Account.NEVER:
    if (newBalance < 0)
                                                                                                                  fromAccount.debit(amount);
      throw new MoneyTransferException(quot;In sufficient fundsquot;);
                                                                                                                  toAccount.credit(amount);
    break;
  case Account.ALLOWED:
                                                                                                                  TransferTransaction txn = new
    Calendar then = Calendar.getInstance();
                                                                                                                              TransferTransaction(fromAccount, toAccount,
    then.setTime(fromAccount.getDateOpened());
    Calendar now = Calendar.getInstance();
                                                                                                                     amount, new Date());
                                                                                                                  bankingTransactionDAO.addTransaction(txn);
      double yearsOpened = now.get(Calendar.YEAR) - then.get(Calendar.YEAR);
      int monthsOpened = now.get(Calendar.MONTH) - then.get(Calendar.MONTH);
                                                                                                                  return txn;
      if (monthsOpened < 0) {
                                                                                                                }
        yearsOpened--;
        monthsOpened += 12;
      }
      yea sOpe ed
      yearsOpened = yearsOpened + (monthsOpened / 12.0);
                      yea sOpe ed    ( o t sOpe ed      0);
      if (yearsOpened < fromAccount.getRequiredYearsOpen()
          || newBalance < fromAccount.getLimit())
        throw new MoneyTransferException(quot;Limit exceededquot;);
                                                                                                               public class Account {
      break;
                                                                                                                 public void debit(fAccount fromAccount, double amount) {
     default:
      throw new MoneyTransferException(quot;Unknown overdraft type: quot;
                                                                                                                   double newBalance = getBalance() – amount;
          + fromAccount.getOverdraftPolicy());
                                                                                                                   switch (getOverdraftPolicy()) {
     }
                                                                                                                    ….
     fromAccount.setBalance(newBalance);
                                                                                                                   }
     toAccount.setBalance(toAccount.getBalance()
     toAccount setBalance(toAccount getBalance() + amount);
     TransferTransaction txn = new TransferTransaction(fromAccount, toAccount,
                                                                                                                  setBalance(newBalance);
        amount, new Date());
                                                                                                               }
     bankingTransactionDAO.addTransaction(txn);
     return txn;
 }
                                                                                                               public void credit(Account toAccount, double amount) {
                                                                                                                 setBalance(getBalance() + amount);
                                                                                                               }
Extract and move feature envy
code into data class

         3/1/2009                                                                                                                                                    56
                                                                         Copyright (c) 2007 Chris Richardson. All rights reserved.
Primitive Obsession
                                          public class Account {
   Code uses built-                         private Date dateOpened;
                                          }
   in types instead
       yp
   of application
                                          public class Account {
                                            private Date dateOpened;

   classes
                                          }

                                          public class MoneyTransferServiceProceduralImpl

   Consequences:
          q                                         implements MoneyTransferService {

                                          public BankingTransaction transfer(String f
                                                                         f          fromAccountId,
           Reduces                                                           String toAccountId,
                                                                             double amount) {
           understandability                Account fromAccount = accountDAO.findAccount(fromAccountId);
                                            Account toAccount = accountDAO.findAccount(toAccountId);
           Long methods                     …
                                              Calendar then = Calendar.getInstance();
           Code duplication
           C d d li ti                        then.setTime(fromAccount.getDateOpened());
                                              th      tTi   (f    A        t   tD t O      d())
                                              Calendar now = Calendar.getInstance();

           Added                               double yearsOpened = now.get(Calendar.YEAR) -
           complexity                                                      then.get(Calendar.YEAR);
                                               int monthsOpened = now.get(Calendar.MONTH) –

   Fix by moving
                                                                         then.get(Calendar.MONTH);
                                               if (monthsOpened < 0) {

   data and code
                                                 yearsOpened--;
                                                 monthsOpened += 12;
                                               }
   into new class                              yearsOpened = yearsOpened + (monthsOpened / 12.0);
                                               if (yearsOpened < fromAccount.getRequiredYearsOpen()
                                                   || newBalance < fromAccount.getLimit())
                                          …
                                          }




3/1/2009                                                                                                   57
                         Copyright (c) 2007 Chris Richardson. All rights reserved.
Replace Data Value with Object
   p                       j
                                                                                     public class CalendateDate {
                                                                                       private Date dateOpened;
public class Account {                                                                 Date getDateOpened( return dateOpened; }
  private Date dateOpened;                                                           }
}


                                                                                     public class Account {
                                                                                      private CalendateDate dateOpened;


                                         Move Method                                  public double getYearsOpen() {

                                                                                          Calendar then = Calendar.getInstance();
                                                                                          then.setTime(dateOpened.getDateOpened());
  public class Account {
                                                                                          Calendar now = Calendar.getInstance();
    private CalendateDate dateOpened;

                                                                                          double yearsOpened = now.get(Calendar.YEAR) -
      public double getYearsOpen() {
                                                                                                                   then.get(Calendar.YEAR);
        return dateOpened.getYearsOpened();
                                                                                          int monthsOpened = now.get(Calendar.MONTH) –
      }
                                                                                                                  then.get(Calendar.MONTH);
                                                                                          if (monthsOpened < 0) {
                                                                                            yearsOpened--;
  public class CalendateDate {
                                                                                            monthsOpened += 12;
    private Date dateOpened;
                                                                                          }
                                                                                          yearsOpened = yearsOpened +
      public double getYearsOpen() {
                                                                                                         (monthsOpened / 12.0);
                                                                                          return yearsOpened;
                                                                                             t        O    d
          Calendar then = Calendar.getInstance();
                                                                                     }
          yearsOpened = yearsOpened +
                          (monthsOpened / 12.0);
          return yearsOpened;
      }

  }




  3/1/2009                                                                                                                              58
                                                Copyright (c) 2007 Chris Richardson. All rights reserved.
Switch Statements
  Use of type codes and                              public class Account {
  switch statements instead                          p
                                                     public static final int NEVER = 1;
                                                                                      ;
  of polymorphism                                    public static final int ALLOWED = 2;
  Key concepts are                                   private int overdraftPolicy ;
                                                     …
  represented by type codes
  instead of classes
                                                public class MoneyTransferServiceProceduralImpl
  Consequences:
  C                                             implements MoneyTransferService {
       Longer methods
                                                public BankingTransaction transfer(String
       Poor maintainability caused
                                                                   fromAccountId, String toAccountId,
       by code duplication
                                                                   double amount) {
       Increased code complexity                …
  Fix by introducing class                         switch (fromAccount.getOverdraftPolicy()) {
                                                   case Account.NEVER:
  hierarchy and moving                               …
  each part of switch                                break;
  statement into a                                 case Account ALLOWED:
                                                        Account.ALLOWED:
  overriding method                                  …
                                                   default:
                                                …
                                                   }
                                                  …
                                                }



3/1/2009                                                                                          59
                          Copyright (c) 2007 Chris Richardson. All rights reserved.
Replace Type Code with Strategy
        p      yp                  gy
public class Account {

public static final int NEVER = 1;
public static final int ALLOWED = 2;
                                                   public class MoneyTransferServiceProceduralImpl … {
private OverdraftPolicy overdraftPolicy;
…                                                  public BankingTransaction transfer(String fromAccountId,
                                                                                      String toAccountId,
                                                                                      double amount) {
                                                                                                     )
                                                      …
                                                     switch (fromAccount.getOverdraftPolicy().getTypeCode())
                                                     {
                                                      case Account.NEVER:
                                                         …
                                                        break;
                                                        b   k
                                                      case Account.ALLOWED:
                                                        …
                                                      default:
                                                   …
                                                      }
                                                     …
                                                   }




      3/1/2009                                                                                           60
                                           Copyright (c) 2007 Chris Richardson. All rights reserved.
Replace Conditional with
Polymorphism
   y    p
    Extract/Move   public class MoneyTransferServiceProceduralImpl … {

    Method         public BankingTransaction transfer( ) {
                                             transfer(…)
                     …
                     fromAccount.getOverdraftPolicy().beforeDebitCheck(…);
                     …
                   }




                                    Push Down
                                    & simplify




3/1/2009                                                                           61
                       Copyright (c) 2007 Chris Richardson. All rights reserved.
Data clumps
         p

    Multiple fields or                            public class A
                                                    bli l      Account {
                                                                     t
    method
    parameters that                                public static final int NEVER = 1;
                                                   public static final int ALLOWED = 2;
    belong together
    Consequences:                                 private          int id;
                                                  private          double balance;
           Long methods                           private          String accountId;
           Duplication
           D li ti                                private          Date dateOpened;

    Fix by:                                       private int overdraftPolicy;
           Moving fields into                     private double requiredYearsOpen;
           their
           th i own class
                      l                           private double limit;

           Eliminate resulting                    Account() {}
           Feature Envy
                                                  }


3/1/2009                                                                               62
                       Copyright (c) 2007 Chris Richardson. All rights reserved.
Extract Class
              public class Account {

              public static final int NEVER = 1;
              public static final int ALLOWED = 2;

              private   int id;
Move Field    private   double balance;
              private   String accountId;
              private   Date dateOpened;

              private OverdraftPolicy overdraftPolicy;

              Account() {}

              }
              pub c c ass O e d a t o cy
              public class OverdraftPolicy {

              private int overdraftPolicy;
              private double requiredYearsOpen;
              p
              private double limit;
                                  ;
              …

   3/1/2009                                                                             63
                            Copyright (c) 2007 Chris Richardson. All rights reserved.
Agenda
 g
    Where are the real objects?
    Overview of the Domain Model
    pattern
    Domain model building blocks
    Role of frameworks
    Obstacles to OO
    Eliminating common code smells
    Refactoring existing code

3/1/2009                                                                  64
              Copyright (c) 2007 Chris Richardson. All rights reserved.
Transforming p
           g procedural code
    Inside every procedural design is a
    domain model just trying to get out
    Incrementally transform a procedural
    design into an OO design
           Small, localized changes
           Something to do on Monday morning!




3/1/2009                                                                        65
                    Copyright (c) 2007 Chris Richardson. All rights reserved.
DEMO

Refactoring procedural code




 3/1/2009                                                                  66
               Copyright (c) 2007 Chris Richardson. All rights reserved.
Summary
      y
A rich domain model:
  Organizes the business logic as
  classes with state AND behavior
  Improves maintainability and
  I             i t i bilit    d
  testability
  Enabled by POJOs and non invasive
                          non-invasive
  frameworks (mostly)
  Emerges from procedural code by
  incremental refactoring
   Use it – starting monday!
3/1/2009                                                                 67
             Copyright (c) 2007 Chris Richardson. All rights reserved.
For more information

                                                     Buy my book ☺

                                                     Send email:

                                           chris@chrisrichardson.net

                                                     Visit my website:

                                           http://www.chrisrichardson.
                                               net

                                                     Talk to me about
                                                     consulting and training
                                                              g            g


3/1/2009                                                                       68
           Copyright (c) 2007 Chris Richardson. All rights reserved.

More Related Content

What's hot

Spark Summit East 2015 Advanced Devops Student Slides
Spark Summit East 2015 Advanced Devops Student SlidesSpark Summit East 2015 Advanced Devops Student Slides
Spark Summit East 2015 Advanced Devops Student SlidesDatabricks
 
Intelligent, Automatic Restarts for Unhealthy Kafka Consumers on Kubernetes w...
Intelligent, Automatic Restarts for Unhealthy Kafka Consumers on Kubernetes w...Intelligent, Automatic Restarts for Unhealthy Kafka Consumers on Kubernetes w...
Intelligent, Automatic Restarts for Unhealthy Kafka Consumers on Kubernetes w...HostedbyConfluent
 
Almost Perfect Service Discovery and Failover with ProxySQL and Orchestrator
Almost Perfect Service Discovery and Failover with ProxySQL and OrchestratorAlmost Perfect Service Discovery and Failover with ProxySQL and Orchestrator
Almost Perfect Service Discovery and Failover with ProxySQL and OrchestratorJean-François Gagné
 
Inside Flutter: Widgets, Elements, and RenderObjects
Inside Flutter: Widgets, Elements, and RenderObjectsInside Flutter: Widgets, Elements, and RenderObjects
Inside Flutter: Widgets, Elements, and RenderObjectsHansol Lee
 
Domain driven design and model driven development
Domain driven design and model driven developmentDomain driven design and model driven development
Domain driven design and model driven developmentDmitry Geyzersky
 
From framework coupled code to #microservices through #DDD /by @codelytv
From framework coupled code to #microservices through #DDD /by @codelytvFrom framework coupled code to #microservices through #DDD /by @codelytv
From framework coupled code to #microservices through #DDD /by @codelytvCodelyTV
 
Introducing Domain Driven Design - codemash
Introducing Domain Driven Design - codemashIntroducing Domain Driven Design - codemash
Introducing Domain Driven Design - codemashSteven Smith
 
RocksDB compaction
RocksDB compactionRocksDB compaction
RocksDB compactionMIJIN AN
 
Flutter State Management - Moti Bartov, Tikal
Flutter State Management - Moti Bartov, TikalFlutter State Management - Moti Bartov, Tikal
Flutter State Management - Moti Bartov, TikalDroidConTLV
 
PostgreSQL Tutorial For Beginners | Edureka
PostgreSQL Tutorial For Beginners | EdurekaPostgreSQL Tutorial For Beginners | Edureka
PostgreSQL Tutorial For Beginners | EdurekaEdureka!
 
Introduction to the Disruptor
Introduction to the DisruptorIntroduction to the Disruptor
Introduction to the DisruptorTrisha Gee
 
Le Domain Driven Design, comment bien démarrer ?
Le Domain Driven Design, comment bien démarrer ?Le Domain Driven Design, comment bien démarrer ?
Le Domain Driven Design, comment bien démarrer ?Maxime Sanglan-Charlier
 
Tech Talk: RocksDB Slides by Dhruba Borthakur & Haobo Xu of Facebook
Tech Talk: RocksDB Slides by Dhruba Borthakur & Haobo Xu of FacebookTech Talk: RocksDB Slides by Dhruba Borthakur & Haobo Xu of Facebook
Tech Talk: RocksDB Slides by Dhruba Borthakur & Haobo Xu of FacebookThe Hive
 
Outrageous Performance: RageDB's Experience with the Seastar Framework
Outrageous Performance: RageDB's Experience with the Seastar FrameworkOutrageous Performance: RageDB's Experience with the Seastar Framework
Outrageous Performance: RageDB's Experience with the Seastar FrameworkScyllaDB
 

What's hot (20)

Spark Summit East 2015 Advanced Devops Student Slides
Spark Summit East 2015 Advanced Devops Student SlidesSpark Summit East 2015 Advanced Devops Student Slides
Spark Summit East 2015 Advanced Devops Student Slides
 
Intelligent, Automatic Restarts for Unhealthy Kafka Consumers on Kubernetes w...
Intelligent, Automatic Restarts for Unhealthy Kafka Consumers on Kubernetes w...Intelligent, Automatic Restarts for Unhealthy Kafka Consumers on Kubernetes w...
Intelligent, Automatic Restarts for Unhealthy Kafka Consumers on Kubernetes w...
 
Almost Perfect Service Discovery and Failover with ProxySQL and Orchestrator
Almost Perfect Service Discovery and Failover with ProxySQL and OrchestratorAlmost Perfect Service Discovery and Failover with ProxySQL and Orchestrator
Almost Perfect Service Discovery and Failover with ProxySQL and Orchestrator
 
Inside Flutter: Widgets, Elements, and RenderObjects
Inside Flutter: Widgets, Elements, and RenderObjectsInside Flutter: Widgets, Elements, and RenderObjects
Inside Flutter: Widgets, Elements, and RenderObjects
 
Domain driven design and model driven development
Domain driven design and model driven developmentDomain driven design and model driven development
Domain driven design and model driven development
 
From framework coupled code to #microservices through #DDD /by @codelytv
From framework coupled code to #microservices through #DDD /by @codelytvFrom framework coupled code to #microservices through #DDD /by @codelytv
From framework coupled code to #microservices through #DDD /by @codelytv
 
Introducing Domain Driven Design - codemash
Introducing Domain Driven Design - codemashIntroducing Domain Driven Design - codemash
Introducing Domain Driven Design - codemash
 
Pro Postgres 9
Pro Postgres 9Pro Postgres 9
Pro Postgres 9
 
Sql Antipatterns Strike Back
Sql Antipatterns Strike BackSql Antipatterns Strike Back
Sql Antipatterns Strike Back
 
RocksDB compaction
RocksDB compactionRocksDB compaction
RocksDB compaction
 
Flutter State Management - Moti Bartov, Tikal
Flutter State Management - Moti Bartov, TikalFlutter State Management - Moti Bartov, Tikal
Flutter State Management - Moti Bartov, Tikal
 
PostgreSQL Tutorial For Beginners | Edureka
PostgreSQL Tutorial For Beginners | EdurekaPostgreSQL Tutorial For Beginners | Edureka
PostgreSQL Tutorial For Beginners | Edureka
 
Flutter
FlutterFlutter
Flutter
 
Introduction to the Disruptor
Introduction to the DisruptorIntroduction to the Disruptor
Introduction to the Disruptor
 
Le Domain Driven Design, comment bien démarrer ?
Le Domain Driven Design, comment bien démarrer ?Le Domain Driven Design, comment bien démarrer ?
Le Domain Driven Design, comment bien démarrer ?
 
TypeScript intro
TypeScript introTypeScript intro
TypeScript intro
 
Tech Talk: RocksDB Slides by Dhruba Borthakur & Haobo Xu of Facebook
Tech Talk: RocksDB Slides by Dhruba Borthakur & Haobo Xu of FacebookTech Talk: RocksDB Slides by Dhruba Borthakur & Haobo Xu of Facebook
Tech Talk: RocksDB Slides by Dhruba Borthakur & Haobo Xu of Facebook
 
Introducing ELK
Introducing ELKIntroducing ELK
Introducing ELK
 
Outrageous Performance: RageDB's Experience with the Seastar Framework
Outrageous Performance: RageDB's Experience with the Seastar FrameworkOutrageous Performance: RageDB's Experience with the Seastar Framework
Outrageous Performance: RageDB's Experience with the Seastar Framework
 
Clean code
Clean codeClean code
Clean code
 

Viewers also liked

Applying Domain-Driven Design to craft Rich Domain Models
Applying Domain-Driven Design to craft Rich Domain ModelsApplying Domain-Driven Design to craft Rich Domain Models
Applying Domain-Driven Design to craft Rich Domain ModelsAlexander van Trijffel
 
Improving application design with a rich domain model (springone 2007)
Improving application design with a rich domain model (springone 2007)Improving application design with a rich domain model (springone 2007)
Improving application design with a rich domain model (springone 2007)Chris Richardson
 
Handling Eventual Consistency in JVM Microservices with Event Sourcing (javao...
Handling Eventual Consistency in JVM Microservices with Event Sourcing (javao...Handling Eventual Consistency in JVM Microservices with Event Sourcing (javao...
Handling Eventual Consistency in JVM Microservices with Event Sourcing (javao...Chris Richardson
 
Domain model example
Domain model exampleDomain model example
Domain model exampleHeba Fathy
 
A pattern language for microservices (#gluecon #gluecon2016)
A pattern language for microservices (#gluecon #gluecon2016)A pattern language for microservices (#gluecon #gluecon2016)
A pattern language for microservices (#gluecon #gluecon2016)Chris Richardson
 
Microservices + Events + Docker = A Perfect Trio (dockercon)
Microservices + Events + Docker = A Perfect Trio (dockercon)Microservices + Events + Docker = A Perfect Trio (dockercon)
Microservices + Events + Docker = A Perfect Trio (dockercon)Chris Richardson
 
Developing microservices with aggregates (SpringOne platform, #s1p)
Developing microservices with aggregates (SpringOne platform, #s1p)Developing microservices with aggregates (SpringOne platform, #s1p)
Developing microservices with aggregates (SpringOne platform, #s1p)Chris Richardson
 
Developing microservices with aggregates (devnexus2017)
Developing microservices with aggregates (devnexus2017)Developing microservices with aggregates (devnexus2017)
Developing microservices with aggregates (devnexus2017)Chris Richardson
 
Agile Modeling In Color (Agile China 2009)
Agile Modeling In Color (Agile China 2009)Agile Modeling In Color (Agile China 2009)
Agile Modeling In Color (Agile China 2009)Vernon Stinebaker
 
Static and Dynamic Behavior
Static and Dynamic BehaviorStatic and Dynamic Behavior
Static and Dynamic Behavioradil raja
 
Road to database automation - Database source control
Road to database automation - Database source controlRoad to database automation - Database source control
Road to database automation - Database source controlEduardo Piairo
 
Road to database automation: database source control
Road to database automation: database source controlRoad to database automation: database source control
Road to database automation: database source controlEduardo Piairo
 
Delivering changes for applications and databases
Delivering changes for applications and databasesDelivering changes for applications and databases
Delivering changes for applications and databasesEduardo Piairo
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven DesignNader Albert
 
Why your business needs a strategic narrative
Why your business needs a strategic narrativeWhy your business needs a strategic narrative
Why your business needs a strategic narrativeSeyi Fabode
 
An Architectural Model for Adapting Domain-Specific AOM Applications
An Architectural Model for Adapting Domain-Specific AOM ApplicationsAn Architectural Model for Adapting Domain-Specific AOM Applications
An Architectural Model for Adapting Domain-Specific AOM Applicationseduardomg23
 
Transactions and Concurrency Control Patterns
Transactions and Concurrency Control PatternsTransactions and Concurrency Control Patterns
Transactions and Concurrency Control PatternsVlad Mihalcea
 

Viewers also liked (20)

Applying Domain-Driven Design to craft Rich Domain Models
Applying Domain-Driven Design to craft Rich Domain ModelsApplying Domain-Driven Design to craft Rich Domain Models
Applying Domain-Driven Design to craft Rich Domain Models
 
Improving application design with a rich domain model (springone 2007)
Improving application design with a rich domain model (springone 2007)Improving application design with a rich domain model (springone 2007)
Improving application design with a rich domain model (springone 2007)
 
Handling Eventual Consistency in JVM Microservices with Event Sourcing (javao...
Handling Eventual Consistency in JVM Microservices with Event Sourcing (javao...Handling Eventual Consistency in JVM Microservices with Event Sourcing (javao...
Handling Eventual Consistency in JVM Microservices with Event Sourcing (javao...
 
Domain model example
Domain model exampleDomain model example
Domain model example
 
A pattern language for microservices (#gluecon #gluecon2016)
A pattern language for microservices (#gluecon #gluecon2016)A pattern language for microservices (#gluecon #gluecon2016)
A pattern language for microservices (#gluecon #gluecon2016)
 
Microservices + Events + Docker = A Perfect Trio (dockercon)
Microservices + Events + Docker = A Perfect Trio (dockercon)Microservices + Events + Docker = A Perfect Trio (dockercon)
Microservices + Events + Docker = A Perfect Trio (dockercon)
 
Developing microservices with aggregates (SpringOne platform, #s1p)
Developing microservices with aggregates (SpringOne platform, #s1p)Developing microservices with aggregates (SpringOne platform, #s1p)
Developing microservices with aggregates (SpringOne platform, #s1p)
 
Developing microservices with aggregates (devnexus2017)
Developing microservices with aggregates (devnexus2017)Developing microservices with aggregates (devnexus2017)
Developing microservices with aggregates (devnexus2017)
 
Mut zur Fachlichkeit
Mut zur FachlichkeitMut zur Fachlichkeit
Mut zur Fachlichkeit
 
Agile Modeling In Color (Agile China 2009)
Agile Modeling In Color (Agile China 2009)Agile Modeling In Color (Agile China 2009)
Agile Modeling In Color (Agile China 2009)
 
Linq tools
Linq toolsLinq tools
Linq tools
 
Static and Dynamic Behavior
Static and Dynamic BehaviorStatic and Dynamic Behavior
Static and Dynamic Behavior
 
List 2
List 2List 2
List 2
 
Road to database automation - Database source control
Road to database automation - Database source controlRoad to database automation - Database source control
Road to database automation - Database source control
 
Road to database automation: database source control
Road to database automation: database source controlRoad to database automation: database source control
Road to database automation: database source control
 
Delivering changes for applications and databases
Delivering changes for applications and databasesDelivering changes for applications and databases
Delivering changes for applications and databases
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven Design
 
Why your business needs a strategic narrative
Why your business needs a strategic narrativeWhy your business needs a strategic narrative
Why your business needs a strategic narrative
 
An Architectural Model for Adapting Domain-Specific AOM Applications
An Architectural Model for Adapting Domain-Specific AOM ApplicationsAn Architectural Model for Adapting Domain-Specific AOM Applications
An Architectural Model for Adapting Domain-Specific AOM Applications
 
Transactions and Concurrency Control Patterns
Transactions and Concurrency Control PatternsTransactions and Concurrency Control Patterns
Transactions and Concurrency Control Patterns
 

Similar to Building Rich Domain Models

CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...
CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...
CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...Chris Richardson
 
Overview of Grails Object Relational Mapping (GORM)
Overview of Grails Object Relational Mapping (GORM)Overview of Grails Object Relational Mapping (GORM)
Overview of Grails Object Relational Mapping (GORM)Chris Richardson
 
Evolving a Clean, Pragmatic Architecture at JBCNConf 2019
Evolving a Clean, Pragmatic Architecture at JBCNConf 2019Evolving a Clean, Pragmatic Architecture at JBCNConf 2019
Evolving a Clean, Pragmatic Architecture at JBCNConf 2019Victor Rentea
 
AppSync in real world - pitfalls, unexpected benefits & lessons learnt
AppSync in real world - pitfalls, unexpected benefits & lessons learntAppSync in real world - pitfalls, unexpected benefits & lessons learnt
AppSync in real world - pitfalls, unexpected benefits & lessons learntAWS User Group Bengaluru
 
Qiaoling Liu, Lead Data Scientist, CareerBuilder at MLconf ATL 2017
Qiaoling Liu, Lead Data Scientist, CareerBuilder at MLconf ATL 2017Qiaoling Liu, Lead Data Scientist, CareerBuilder at MLconf ATL 2017
Qiaoling Liu, Lead Data Scientist, CareerBuilder at MLconf ATL 2017MLconf
 
A Journey with React
A Journey with ReactA Journey with React
A Journey with ReactFITC
 
AWS Neptune - A Fast and reliable Graph Database Built for the Cloud
AWS Neptune - A Fast and reliable Graph Database Built for the CloudAWS Neptune - A Fast and reliable Graph Database Built for the Cloud
AWS Neptune - A Fast and reliable Graph Database Built for the CloudAmazon Web Services
 
Introduction to OO, Java and Eclipse/WebSphere
Introduction to OO, Java and Eclipse/WebSphereIntroduction to OO, Java and Eclipse/WebSphere
Introduction to OO, Java and Eclipse/WebSphereeLink Business Innovations
 
Supercharging Applications with GraphQL and AWS AppSync
Supercharging Applications with GraphQL and AWS AppSyncSupercharging Applications with GraphQL and AWS AppSync
Supercharging Applications with GraphQL and AWS AppSyncAmazon Web Services
 
C#7, 7.1, 7.2, 7.3 e C# 8
C#7, 7.1, 7.2, 7.3 e C# 8C#7, 7.1, 7.2, 7.3 e C# 8
C#7, 7.1, 7.2, 7.3 e C# 8Giovanni Bassi
 
MongoDB and Web Scrapping with the Gyes Platform
MongoDB and Web Scrapping with the Gyes PlatformMongoDB and Web Scrapping with the Gyes Platform
MongoDB and Web Scrapping with the Gyes PlatformMongoDB
 
Executing a Large Scale Migration to AWS (ENT337-R2) - AWS re:Invent 2018
Executing a Large Scale Migration to AWS (ENT337-R2) - AWS re:Invent 2018Executing a Large Scale Migration to AWS (ENT337-R2) - AWS re:Invent 2018
Executing a Large Scale Migration to AWS (ENT337-R2) - AWS re:Invent 2018Amazon Web Services
 
Developing and Deploying Java applications on the Amazon Elastic Compute Clou...
Developing and Deploying Java applications on the Amazon Elastic Compute Clou...Developing and Deploying Java applications on the Amazon Elastic Compute Clou...
Developing and Deploying Java applications on the Amazon Elastic Compute Clou...Chris Richardson
 
Vertical slice architecture
Vertical slice architectureVertical slice architecture
Vertical slice architectureGermán Küber
 
Sustainable Agile Development
Sustainable Agile DevelopmentSustainable Agile Development
Sustainable Agile DevelopmentGabriele Lana
 
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8tdc-globalcode
 
Dublin Ireland Spark Meetup October 15, 2015
Dublin Ireland Spark Meetup October 15, 2015Dublin Ireland Spark Meetup October 15, 2015
Dublin Ireland Spark Meetup October 15, 2015eddiebaggott
 
What's new in DWR version 3
What's new in DWR version 3What's new in DWR version 3
What's new in DWR version 3Joe Walker
 
Advanced Container Automation, Security, and Monitoring - AWS Summit Sydney 2018
Advanced Container Automation, Security, and Monitoring - AWS Summit Sydney 2018Advanced Container Automation, Security, and Monitoring - AWS Summit Sydney 2018
Advanced Container Automation, Security, and Monitoring - AWS Summit Sydney 2018Amazon Web Services
 

Similar to Building Rich Domain Models (20)

CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...
CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...
CommunityOneEast 09 - Dynamic Languages: the next big thing for the JVM or an...
 
Overview of Grails Object Relational Mapping (GORM)
Overview of Grails Object Relational Mapping (GORM)Overview of Grails Object Relational Mapping (GORM)
Overview of Grails Object Relational Mapping (GORM)
 
Evolving a Clean, Pragmatic Architecture at JBCNConf 2019
Evolving a Clean, Pragmatic Architecture at JBCNConf 2019Evolving a Clean, Pragmatic Architecture at JBCNConf 2019
Evolving a Clean, Pragmatic Architecture at JBCNConf 2019
 
AppSync in real world - pitfalls, unexpected benefits & lessons learnt
AppSync in real world - pitfalls, unexpected benefits & lessons learntAppSync in real world - pitfalls, unexpected benefits & lessons learnt
AppSync in real world - pitfalls, unexpected benefits & lessons learnt
 
Qiaoling Liu, Lead Data Scientist, CareerBuilder at MLconf ATL 2017
Qiaoling Liu, Lead Data Scientist, CareerBuilder at MLconf ATL 2017Qiaoling Liu, Lead Data Scientist, CareerBuilder at MLconf ATL 2017
Qiaoling Liu, Lead Data Scientist, CareerBuilder at MLconf ATL 2017
 
A Journey with React
A Journey with ReactA Journey with React
A Journey with React
 
AWS Neptune - A Fast and reliable Graph Database Built for the Cloud
AWS Neptune - A Fast and reliable Graph Database Built for the CloudAWS Neptune - A Fast and reliable Graph Database Built for the Cloud
AWS Neptune - A Fast and reliable Graph Database Built for the Cloud
 
Introduction to OO, Java and Eclipse/WebSphere
Introduction to OO, Java and Eclipse/WebSphereIntroduction to OO, Java and Eclipse/WebSphere
Introduction to OO, Java and Eclipse/WebSphere
 
Supercharging Applications with GraphQL and AWS AppSync
Supercharging Applications with GraphQL and AWS AppSyncSupercharging Applications with GraphQL and AWS AppSync
Supercharging Applications with GraphQL and AWS AppSync
 
C#7, 7.1, 7.2, 7.3 e C# 8
C#7, 7.1, 7.2, 7.3 e C# 8C#7, 7.1, 7.2, 7.3 e C# 8
C#7, 7.1, 7.2, 7.3 e C# 8
 
MongoDB and Web Scrapping with the Gyes Platform
MongoDB and Web Scrapping with the Gyes PlatformMongoDB and Web Scrapping with the Gyes Platform
MongoDB and Web Scrapping with the Gyes Platform
 
Executing a Large Scale Migration to AWS (ENT337-R2) - AWS re:Invent 2018
Executing a Large Scale Migration to AWS (ENT337-R2) - AWS re:Invent 2018Executing a Large Scale Migration to AWS (ENT337-R2) - AWS re:Invent 2018
Executing a Large Scale Migration to AWS (ENT337-R2) - AWS re:Invent 2018
 
Data Binding in qooxdoo
Data Binding in qooxdooData Binding in qooxdoo
Data Binding in qooxdoo
 
Developing and Deploying Java applications on the Amazon Elastic Compute Clou...
Developing and Deploying Java applications on the Amazon Elastic Compute Clou...Developing and Deploying Java applications on the Amazon Elastic Compute Clou...
Developing and Deploying Java applications on the Amazon Elastic Compute Clou...
 
Vertical slice architecture
Vertical slice architectureVertical slice architecture
Vertical slice architecture
 
Sustainable Agile Development
Sustainable Agile DevelopmentSustainable Agile Development
Sustainable Agile Development
 
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
 
Dublin Ireland Spark Meetup October 15, 2015
Dublin Ireland Spark Meetup October 15, 2015Dublin Ireland Spark Meetup October 15, 2015
Dublin Ireland Spark Meetup October 15, 2015
 
What's new in DWR version 3
What's new in DWR version 3What's new in DWR version 3
What's new in DWR version 3
 
Advanced Container Automation, Security, and Monitoring - AWS Summit Sydney 2018
Advanced Container Automation, Security, and Monitoring - AWS Summit Sydney 2018Advanced Container Automation, Security, and Monitoring - AWS Summit Sydney 2018
Advanced Container Automation, Security, and Monitoring - AWS Summit Sydney 2018
 

More from Chris Richardson

The microservice architecture: what, why, when and how?
The microservice architecture: what, why, when and how?The microservice architecture: what, why, when and how?
The microservice architecture: what, why, when and how?Chris Richardson
 
More the merrier: a microservices anti-pattern
More the merrier: a microservices anti-patternMore the merrier: a microservices anti-pattern
More the merrier: a microservices anti-patternChris Richardson
 
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...Chris Richardson
 
Dark Energy, Dark Matter and the Microservices Patterns?!
Dark Energy, Dark Matter and the Microservices Patterns?!Dark Energy, Dark Matter and the Microservices Patterns?!
Dark Energy, Dark Matter and the Microservices Patterns?!Chris Richardson
 
Dark energy, dark matter and microservice architecture collaboration patterns
Dark energy, dark matter and microservice architecture collaboration patternsDark energy, dark matter and microservice architecture collaboration patterns
Dark energy, dark matter and microservice architecture collaboration patternsChris Richardson
 
Scenarios_and_Architecture_SkillsMatter_April_2022.pdf
Scenarios_and_Architecture_SkillsMatter_April_2022.pdfScenarios_and_Architecture_SkillsMatter_April_2022.pdf
Scenarios_and_Architecture_SkillsMatter_April_2022.pdfChris Richardson
 
Using patterns and pattern languages to make better architectural decisions
Using patterns and pattern languages to make better architectural decisions Using patterns and pattern languages to make better architectural decisions
Using patterns and pattern languages to make better architectural decisions Chris Richardson
 
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...Chris Richardson
 
Events to the rescue: solving distributed data problems in a microservice arc...
Events to the rescue: solving distributed data problems in a microservice arc...Events to the rescue: solving distributed data problems in a microservice arc...
Events to the rescue: solving distributed data problems in a microservice arc...Chris Richardson
 
A pattern language for microservices - June 2021
A pattern language for microservices - June 2021 A pattern language for microservices - June 2021
A pattern language for microservices - June 2021 Chris Richardson
 
QConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
QConPlus 2021: Minimizing Design Time Coupling in a Microservice ArchitectureQConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
QConPlus 2021: Minimizing Design Time Coupling in a Microservice ArchitectureChris Richardson
 
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...Chris Richardson
 
Designing loosely coupled services
Designing loosely coupled servicesDesigning loosely coupled services
Designing loosely coupled servicesChris Richardson
 
Microservices - an architecture that enables DevOps (T Systems DevOps day)
Microservices - an architecture that enables DevOps (T Systems DevOps day)Microservices - an architecture that enables DevOps (T Systems DevOps day)
Microservices - an architecture that enables DevOps (T Systems DevOps day)Chris Richardson
 
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...Chris Richardson
 
Decompose your monolith: Six principles for refactoring a monolith to microse...
Decompose your monolith: Six principles for refactoring a monolith to microse...Decompose your monolith: Six principles for refactoring a monolith to microse...
Decompose your monolith: Six principles for refactoring a monolith to microse...Chris Richardson
 
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...Chris Richardson
 
Overview of the Eventuate Tram Customers and Orders application
Overview of the Eventuate Tram Customers and Orders applicationOverview of the Eventuate Tram Customers and Orders application
Overview of the Eventuate Tram Customers and Orders applicationChris Richardson
 
An overview of the Eventuate Platform
An overview of the Eventuate PlatformAn overview of the Eventuate Platform
An overview of the Eventuate PlatformChris Richardson
 
#DevNexus202 Decompose your monolith
#DevNexus202 Decompose your monolith#DevNexus202 Decompose your monolith
#DevNexus202 Decompose your monolithChris Richardson
 

More from Chris Richardson (20)

The microservice architecture: what, why, when and how?
The microservice architecture: what, why, when and how?The microservice architecture: what, why, when and how?
The microservice architecture: what, why, when and how?
 
More the merrier: a microservices anti-pattern
More the merrier: a microservices anti-patternMore the merrier: a microservices anti-pattern
More the merrier: a microservices anti-pattern
 
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
 
Dark Energy, Dark Matter and the Microservices Patterns?!
Dark Energy, Dark Matter and the Microservices Patterns?!Dark Energy, Dark Matter and the Microservices Patterns?!
Dark Energy, Dark Matter and the Microservices Patterns?!
 
Dark energy, dark matter and microservice architecture collaboration patterns
Dark energy, dark matter and microservice architecture collaboration patternsDark energy, dark matter and microservice architecture collaboration patterns
Dark energy, dark matter and microservice architecture collaboration patterns
 
Scenarios_and_Architecture_SkillsMatter_April_2022.pdf
Scenarios_and_Architecture_SkillsMatter_April_2022.pdfScenarios_and_Architecture_SkillsMatter_April_2022.pdf
Scenarios_and_Architecture_SkillsMatter_April_2022.pdf
 
Using patterns and pattern languages to make better architectural decisions
Using patterns and pattern languages to make better architectural decisions Using patterns and pattern languages to make better architectural decisions
Using patterns and pattern languages to make better architectural decisions
 
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
 
Events to the rescue: solving distributed data problems in a microservice arc...
Events to the rescue: solving distributed data problems in a microservice arc...Events to the rescue: solving distributed data problems in a microservice arc...
Events to the rescue: solving distributed data problems in a microservice arc...
 
A pattern language for microservices - June 2021
A pattern language for microservices - June 2021 A pattern language for microservices - June 2021
A pattern language for microservices - June 2021
 
QConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
QConPlus 2021: Minimizing Design Time Coupling in a Microservice ArchitectureQConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
QConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
 
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
 
Designing loosely coupled services
Designing loosely coupled servicesDesigning loosely coupled services
Designing loosely coupled services
 
Microservices - an architecture that enables DevOps (T Systems DevOps day)
Microservices - an architecture that enables DevOps (T Systems DevOps day)Microservices - an architecture that enables DevOps (T Systems DevOps day)
Microservices - an architecture that enables DevOps (T Systems DevOps day)
 
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
 
Decompose your monolith: Six principles for refactoring a monolith to microse...
Decompose your monolith: Six principles for refactoring a monolith to microse...Decompose your monolith: Six principles for refactoring a monolith to microse...
Decompose your monolith: Six principles for refactoring a monolith to microse...
 
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
 
Overview of the Eventuate Tram Customers and Orders application
Overview of the Eventuate Tram Customers and Orders applicationOverview of the Eventuate Tram Customers and Orders application
Overview of the Eventuate Tram Customers and Orders application
 
An overview of the Eventuate Platform
An overview of the Eventuate PlatformAn overview of the Eventuate Platform
An overview of the Eventuate Platform
 
#DevNexus202 Decompose your monolith
#DevNexus202 Decompose your monolith#DevNexus202 Decompose your monolith
#DevNexus202 Decompose your monolith
 

Recently uploaded

Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsRoshan Dwivedi
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 

Recently uploaded (20)

Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 

Building Rich Domain Models

  • 1. Improving Application Design with a Rich Domain Model Chris Ri h d Ch i Richardson Author of POJOs in Action Chris Richardson Consulting, Inc http://www.chrisrichardson.net p // 3/1/2009 Slide 1 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 2. Overall presentation g p goal Learn how to improve application design by using truly object- g y g y j oriented business logic 3/1/2009 2 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 3. About Chris Grew up in England Live in Oakland, CA Over twenty years of software development experience Building object-oriented software since 1986 Using Java since 1996 Using J2EE since 1999 Author of POJOs in Action Speaker at JavaOne, JavaPolis, NFJS, JUGs, …. Chair of the eBIG Java SIG in Oakland (www.ebig.org) Run a consulting and training company that helps organizations build better software faster 3/1/2009 3 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 4. Agenda g Where are the real objects? Wh th l bj t ? Overview of the Domain Model pattern Domain model building blocks Role of frameworks Obstacles to OO Eliminating common code smells Refactoring existing code 3/1/2009 4 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 5. Objects in LISP ( j (1987-1993) ) (defclass Account () ((account-id :accessor account-id :initarg :account-id) State (balance :accessor account-balance :initarg :balance)) + ) Behavior (defmethod debit ((Account account) amount) (decf (account-balance account) amount)) (defmethod credit ((Account account) amount) (incf (account balance account) amount)) (account-balance CL-USER 5 > (setq a (make-instance 'account :account-id quot;abc123quot; :balance 10.0)) #<ACCOUNT 200C05AF> CL-USER 6 > (describe a) #<ACCOUNT 200C05AF> is an ACCOUNT ACCOUNT-ID quot;abc123quot; BALANCE 10.0 CL-USER CL USER 7 > (debit a 5) 5.0 CL-USER 8 > (describe a) #<ACCOUNT 200C05AF> is an ACCOUNT ACCOUNT-ID ACCOUNT ID quot; b 123quot; quot;abc123quot; BALANCE 5.0 3/1/2009 5 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 6. Objects in C++ ( j (1993-1996) ) #ifndef ACCOUNT_H_ #define ACCOUNT_H_ class Account { public: Account(char* account_id, double balance); void debit(double amount); void credit(double amount); double getBalance(); private: char* account_id; State double balance; }; + #endif /*ACCOUNT_H_*/ Behavior #include quot;Account.hquot; #incl de quot;Acco nt hquot; Account::Account(char* account_id, double balance) { … } void Account::debit (double amount) { balance -= amount; bl } void Account::credit(double amount) { balance += amount; } double Account::getBalance() { return balance; } 3/1/2009 6 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 7. Objects in Java ( j (1996-1999) ) public class Account { private int id; private double balance; private OverdraftPolicy overdraftPolicy; State private String accountId; + private CalendarDate dateOpened; Behavior Account() { } p public void debit(double amount) { ( ) assert amount > 0; double originalBalance = balance; double newBalance = balance - amount; overdraftPolicy.beforeDebitCheck(this, originalBalance, newBalance); balance = newBalance; overdraftPolicy.afterDebitAction(this, originalBalance, newBalance); d ftP li ft D bitA ti (thi i i lB l Bl ) } public void credit(double amount) { assert amount > 0; balance += amount; } 3/1/2009 7 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 8. EJB objects ( j (1999- ?) ) Applications were still built pp from objects But those objects were very different … 3/1/2009 8 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 9. Example Banking UI p g 3/1/2009 9 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 10. Example p p procedural design g 3/1/2009 10 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 11. Example p p procedural code public class MoneyTransferServiceProceduralImpl implements MoneyTransferService { public class Account { p public BankingTransaction transfer(String fromAccountId, String toAccountId, g ( g , g , p public static final int NEVER = 1; ; double amount) { public static final int ALLOWED = 2; Account fromAccount = accountDAO.findAccount(fromAccountId); Account toAccount = accountDAO.findAccount(toAccountId); private int id; assert amount > 0; private double balance; double newBalance = fromAccount.getBalance() - amount; private int overdraftPolicy; switch (fromAccount.getOverdraftPolicy()) { private String accountId; Behavior State case Account.NEVER: private Date dateOpened; if (newBalance < 0) private double requiredYearsOpen; throw new MoneyTransferException(quot;In sufficient fundsquot;); private double limit; break; case Account.ALLOWED: Account() {} Calendar then = Calendar.getInstance(); then.setTime(fromAccount.getDateOpened()); Calendar now = Calendar.getInstance(); public Account(String accountId, double balance, int overdraftPolicy, double yearsOpened = now.get(Calendar.YEAR) - then.get(Calendar.YEAR); Date dateOpened, double requiredYearsOpen, int monthsOpened = now.get(Calendar.MONTH) - then.get(Calendar.MONTH); double limit) if (monthsOpened < 0) { {….. } yearsOpened--; O d monthsOpened += 12; public int getId() {return id;} } yearsOpened = yearsOpened + (monthsOpened / 12.0); public String getAccountId() {return accountId;} if (yearsOpened < fromAccount.getRequiredYearsOpen() || newBalance < fromAccount.getLimit()) public void setBalance(double balance) { this.balance = balance; } throw new MoneyTransferException(quot;Limit exceededquot;); break; public double getBalance() { return balance; } default: throw new MoneyTransferException(quot;Unknown overdraft type: quot; MoneyTransferException( Unknown public int getOverdraftPolicy() { return overdraftPolicy; } + fromAccount.getOverdraftPolicy()); public Date getDateOpened() { return dateOpened; } } fromAccount.setBalance(newBalance); public double getRequiredYearsOpen() { toAccount.setBalance(toAccount.getBalance() + amount); return requiredYearsOpen; } TransferTransaction txn = new TransferTransaction(fromAccount, toAccount, amount, new Date()); public double getLimit() {return limit; } bankingTransactionDAO.addTransaction(txn); } return txn; } 3/1/2009 11 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 12. Why write code like this? y EJB made writing object-oriented code difficult/impossible diffi lt/i ibl Implementing new functionality is easy Add a new transaction script i i Add code to a new transaction script Manipulating relational data is easier Distribution is easier No N need to do any real design, e.g. dt d ld i Create new classes Determine responsibilities 3/1/2009 12 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 13. Unable to handle complexity p y Works well for simple business logic E.g. E g the example wasn’t that bad wasn t But with complex business logic: Large transaction scripts: 100s/1000s LOC Difficult/impossible to understand, test, and maintain What s What’s worse: business logic has a habit of growing New requirements ⇒ Add a few more lines to the transaction script Many new requirements ⇒ big mess Soon or later you end up with unmaintainable code 3/1/2009 13 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 14. The legacy of EJB gy Java is an object-oriented language AND Object-oriented design is a better way to tackle complexity YET Many complex enterprise Java applications are written in a procedural style 3/1/2009 14 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 15. Today – rich domain models are growing in popularity POJOs Plain Old Java Objects Leverage OO features of Java O/R mapping frameworks for persisting POJOs: Hibernate Java Persistence API … Spring AOP and A Si d AspectJ f tJ for handling cross-cutting concerns: Transaction management Security S it Logging Auditing … 3/1/2009 15 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 16. Agenda g Where are the real objects? Overview of the Domain Model pattern Domain model building blocks Role of frameworks Obstacles to OO Eliminating common code smells g Refactoring existing code 3/1/2009 16 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 17. Using the Domain Model Pattern g Business logic spread amongst a Bi li d t collection of classes Many classes correspond to real world concepts: Order, Customer, … Many classes are true objects having both: State – fields Behavior – methods that act on the state 3/1/2009 17 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 18. Procedural versus OO Presentation Tier Presentation Tier Business Tier Business Tier Transaction Scripts Facade (Session Beans) Domain Model Data Objects Data Access Tier Data Access Tier 3/1/2009 18 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 19. An example domain model p Web Tier Behavior Business Tier MoneyTransferService BankingTransaction transfer(fromId, toId, amount) from Account Banking Account BankingTransaction Transaction Repository Repository balance to amount findAccount(id) addTransaction(…) debit(amount) date credit(amount) Explicit <<interface>> OverdraftPolicy Representation State + of key Behavior Limited conceptst NoOverdraft Overdraft Policy limit 3/1/2009 19 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 20. DEMO Code Walkthrough 3/1/2009 20 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 21. Benefits of the Domain Model Pattern Improved maintainability The design reflects reality Key domain classes are represented by classes The design is more modular Improved testability Small classes that can be tested in isolation Improved reusability Classes can be used in other applications Building a domain model Creates shared understanding Develops an ubiquitous language p q gg 3/1/2009 21 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 22. Q Quantifiably simpler code y p Procedural – few longer more few, longer, Object-oriented more, simpler Object oriented – more simpler, complex methods shorter methods 3/1/2009 22 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 23. Drawbacks of the Domain Model p pattern Requires object-oriented design skills Works best if domain model is transparently “mappable” to the data E.g. nice database schema Ugly schemas and data stored in other applications is a challenge l h ll 3/1/2009 23 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 24. When to use it The business logic is reasonably complex or you anticipate that it will be You have the skills to design one You can either: Use an ORM framework Invest in writing a data access framework 3/1/2009 24 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 25. Agenda g Where are the real objects? Wh th l bj t ? Overview of the Domain Model pattern Domain model building blocks Role of frameworks Obstacles to OO Eliminating common code smells Refactoring existing code 3/1/2009 25 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 26. Domain model building blocks g Roles aka stereotypes Benefits of roles: Guide design Help name objects bj t Aid understanding Roles (from Domain-Driven Design) 3/1/2009 26 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 27. Entity y Objects with a public class Account { distinct identity private int id; Typically correspond private double balance; to real world private OverdraftPolicy overdraftPolicy; private String accountId; concepts private CalendarDate dateOpened; Almost always Account() { persistent } public void debit(double amount) { Encapsulate state and assert amount > 0; double originalBalance = balance; behavior double newBalance = balance - amount; overdraftPolicy.beforeDebitCheck(this, originalBalance, newBalance); balance = newBalance; Often modal ⇒ call overdraftPolicy.afterDebitAction(this, originalBalance, newBalance); } methods in a public void credit(double amount) { particular order assert amount > 0; balance += amount; } 3/1/2009 27 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 28. Value Objects j Objects that are public class CalendarDate { defined by the values private Date date; of their attributes CalendarDate() { } Two instances with public CalendarDate(Date date) { identical values can be this.date = date; } used i t d interchangeably h bl public Date getDate() { return date; Two flavors } Persistent – parts of public double getYearsOpen() { Calendar then = Calendar.getInstance(); entities then.setTime(date); then setTime(date); Calendar now = Calendar.getInstance(); Transient – intermediate values int yearsOpened = now.get(Calendar.YEAR) – then.get(Calendar.YEAR); Ideally immutable int monthsOpened = now.get(Calendar.MONTH) - then.get(Calendar.MONTH); Often missing from Oft ii f if (monthsOpened < 0) { yearsOpened--; procedural code – monthsOpened += 12; } Primitive Obsession return yearsOpened + (monthsOpened/12.0); code smell } } 3/1/2009 28 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 29. More examples of Value Objects p j public class User { public class User { private int id; private String firstName; private PersonName name; p private String lastName; g ; private UserId login; private String login; private Password password; private String password; … … } } public class Password implements Serializable { private String passwordString; public class PersonName { public Password(String passwordString) { private String firstName; this.passwordString = passwordString == null ? null : passwordString.trim(); private String lastName; } PersonName() { … } @Override public String t St i () { bli St i toString() public PersonName(String firstName, return new ToStringBuilder(this).append(quot;passwordquot;, quot;****quot;).toString(); String lastName) { } this.firstName = firstName; this.lastName = lastName; } 3/1/2009 29 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 30. Aggregates gg g A cluster of related entities and values Behaves as a unit Has H a root t Has a boundary Objects outside the aggregate can only reference the root Deleting the root removes everything 3/1/2009 30 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 31. Repositories p public interface AccountRepository { Manages a collection of objects Account findAccount(String accountId); void addAccount(Account account); Provides methods for: } Adding an object Finding object or objects Deleting objects public class HibernateAccountRepository implements AccountRepository { Consists of an interface private HibernateTemplate hibernateTemplate; and an implementation public HibernateAccountRepository(HibernateTemplate template) { hibernateTemplate = template; class l } Encapsulates database public void addAccount(Account account) { hibernateTemplate.save(account); access mechanism } Keeps the ORM public Account findAccount(final String accountId) { return (Account) DataAccessUtils.uniqueResult(hibernateTemplate framework out of the .findByNamedQueryAndNamedParam( domain model quot;Account.findAccountByAccountIdquot;, quot;accountIdquot;, accountId)); } Similar to a DAO } 3/1/2009 31 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 32. Services public interface MoneyTransferService { Implements logic that BankingTransaction transfer(String fromAccountId, cannot be put in a single String toAccountId, double amount); entity } Not persistent p Consists of an interface public class MoneyTransferServiceImpl implements MoneyTransferService { and an implementation private final AccountRepository accountRepository; class private final BankingTransactionRepository Service method usually: bankingTransactionRepository; public MoneyTransferServiceImpl(AccountRepository accountRepository, Invoked (indirectly) by BankingTransactionRepository bankingTransactionRepository) { presentation tier this.accountRepository = accountRepository; this.bankingTransactionRepository = bankingTransactionRepository; Invokes one or more } repositories public BankingTransaction transfer(String fromAccountId, String toAccountId, double amount) { Invokes one or more … entities } Keep them thin } 3/1/2009 32 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 33. Factories Use when a constructor is insufficient Encapsulates complex object creation E l l bj i logic Handles varying products Different kinds of factories Factory classes Factory methods Example: OrderFactory p y Creates Order from a shopping cart Adds line items 3/1/2009 33 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 34. Agenda g Where are the real objects? Wh th l bj t ? Overview of the Domain Model pattern Domain model building blocks Role of frameworks Obstacles to OO Eliminating common code smells Refactoring existing code 3/1/2009 34 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 35. Use the POJO programming model pg g Your domain model might outlive infrastructure frameworks ⇒ Minimize dependencies on them POJO = Plain Old Java Object Don't implement any infrastructure interfaces Don't call infrastructure APIs No infrastructure framework annotations? 3/1/2009 Slide 35 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 36. Use dependency injection p yj Spring instantiates and wires together components: Services, factories and repositories S i fti d it i Dependency injection into entities One option is @Configurable but it’s not POJO Use Hibernate Interceptor + manual injection instead? Benefits: Decouples components from one another and the infrastructure Improves testability <beans> <bean id=quot;accountServicequot; class=quot;net.chris...domain.AccountServiceImplquot;> public AccountServiceImpl(AccountDao accountDao, <constructor-arg ref=quot;accountDaoquot;/> <constructor-arg ref=quot;bankingTransactionDaoquot;/> BankingTransactionDao bankingTransactionDao) { </bean> this.accountDAO = accountDao; this.bankingTransactionDAO = bankingTransactionDao; … } </beans> 3/1/2009 Slide 36 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 37. Use Aspect-Oriented Programming p g g Spring AOP for service-level crosscutting concerns: E.g. transaction management, security, logging etc. AspectJ for entity and value object crosscutting concerns E.g. tracking changes to fields But AJC/Load-time weaving has a cost Benefits Decouples code from infrastructure Improves modularity 3/1/2009 37 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 38. Use object/relational mapping j / pp g Persisting objects g j <class name=quot;Accountquot; table BANK_ACCOUNT table=quot;BANK ACCOUNTquot; > with JDBC is usually <id name=quot;idquot; column=quot;ACCOUNT_IDquot;> <generator class=quot;nativequot; /> </id> too much work <property name=quot;balancequot; /> <property name=quot;accountIdquot; /> Implement DAOs <property name=quot;dateOpenedquot; /> <many-to-one name=quot;overdraftPolicyquot; /> </class> with Spring ORM Benefits public class HibernateAccountDao implements AccountDao { private HibernateTemplate hibernateTemplate; Less code public HibernateAccountDao(HibernateTemplate template) { Simpler code Si l d this.hibernateTemplate = template; } Improved testability public void addAccount(Account account) { hibernateTemplate.save(account); } … } 3/1/2009 Slide 38 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 39. Agenda g Where are the real objects? Overview of the Domain Model pattern Domain model building blocks Role of frameworks Obstacles to good OO design Eliminating common code smells Refactoring existing code 3/1/2009 Slide 39 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 40. Web frameworks need Java Beans Web frameworks can bind request parameters directly to domain objects Easy creation of domain objects Easy editing of detached domain objects asy ed g o de ac ed do a objec s 1. Load object graph from database 2. Store object graph in HttpSession 3. 3 Bind Http parameters to object's properties 4. Reattach object graph and update the database A lot less code But domain objects must be JavaBeans: Public default constructor JavaBean-style setters Ja aBean st le sette s 3/1/2009 Slide 40 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 41. The trouble with setters public class Address { Poor encapsulation private String street1; private String street2; Objects are now exposing public String getStreet1() {...}; their internal state public void setStreet1(String street1) {...} … No immutable objects } Increases code complexity public class Order { Makes it more error-prone private Address deliveryAddress; Developers might b D l i ht bypass public void updateDeliveryAddress( Address deliveryAddress) { business method ⇒ Bugs, // validate before changing p poor design g … } public Address getAddress() {…} … } order.getAddress().setStreet1(quot;Bad!quot;); 3/1/2009 Slide 41 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 42. How to cope p Live with it: It's often not that bad But be vigilant for code bypassing business methods bi th d Use DTOs Hides domain objects from web tier But you have to write more code Encourage the development of better frameworks 3/1/2009 Slide 42 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 43. More on web binding g Web frameworks can bind to properties of nested objects, e.g. order.deliveryAddress.street1 But some frameworks require that intermediate objects to be non-null This can impact the domain model 3/1/2009 Slide 43 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 44. Using ORM frameworks g ORM frameworks can access private fields No setters (or g ( getters) required ☺ )q But require: Default constructor Non-final fields id fields Subtle changes: Collection fields: null ⇒ empty py Embedded objects with null fields ⇒ null reference Objects sometimes require equals()/hashCode() Proxy-based lazy loading: Don't access fields outside of instance ⇒ affects equals() and hashCode() Can affect object identity: this != proxyToSameObjectAsThis 3/1/2009 Slide 44 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 45. Performance tuning changes the design g Different web requests DisplayProject DisplayProject Details ForReview display different object Controller Controller graphs Display project details ProjectCoordinator getProject(projectId) Display project for approval or rejection ProjectRepository Improve performance hibernateTemplate.get() findProject(projectId) by loading object graphs using optimized queries (e.g. fetch ProjectCoordinator join) getProjectDetails(projectId) getProjectForReview(projectId) Therefore we need multiple Dao (and from Project p ProjectRepository inner join fetch p.operations Service) methods findProjectDetails(projectId) findProjectForReview(projectId) from Project p inner join fetch p.operations Inner join fetch p.createdBy 3/1/2009 Slide 45 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 46. Untangling what to load from the code Java Data Objects (JDO) has fetch groups Declarative specification of the object graph to load Fields and related objects Flow: Web tier W b ti configures f t h groups fi fetch Calls ProjectCoordinator.get() O/RM loads object graph specified by active fetch groups Look for this feature in JPA implementations th t evolved f i l t ti that l d from JDO 3/1/2009 Slide 46 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 47. Agenda g Where are the real objects? Wh th l bj t ? Overview of the Domain Model pattern Domain model building blocks Role of frameworks Obstacles to OO Eliminating common code smells Refactoring existing code 3/1/2009 47 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 48. Overview of code smells Code smell = something about the code that does not seem right Impacts ease of development and testing Some are non-OOD Some are the consequences of non-OOD 3/1/2009 48 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 49. Refactoring – the cure for stinky code Refactoring: Systematic way to restructure the code Without changing behavior bh i Essential cleanups for decaying code 3/1/2009 49 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 50. Basic refactorings g Extract Method Eliminates long methods Move Method Move a method to a different class (field or parameter) Moves method to where the data is Push Down Move a method into subclasses Optionally leave an abstract method behind Part of eliminating conditional logic … 3/1/2009 50 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 51. Compound refactorings p g A sequence of simpler refactorings Compose method Apply Extract Method repeatedly Use to replace long method with more readable shorter methods Replace Type Code With Strategy Define GOF Strategy class for each type code Replace C diti Rl Conditional With P l l Polymorphism hi Turn into part of a switch statement into an overriding method in a subclass Replace D Rl Data Value with Object Vl i h Obj Move field into it’s own class Eliminates Primitive Obsession 3/1/2009 51 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 52. Long method g Methods should be short p public class MoneyTransferServiceProceduralImpl implements MoneyTransferService { y p p y public BankingTransaction transfer(String fromAccountId, String toAccountId, double amount) { But business logic is Account fromAccount = accountDAO.findAccount(fromAccountId); Account toAccount = accountDAO.findAccount(toAccountId); assert amount > 0; concentrated in the double newBalance = fromAccount.getBalance() - amount; switch (fromAccount.getOverdraftPolicy()) { case Account.NEVER: services ⇒ long if (newBalance < 0) throw new MoneyTransferException(quot;In sufficient fundsquot;); MoneyTransferException( In funds ); break; methods case Account.ALLOWED: Calendar then = Calendar.getInstance(); then.setTime(fromAccount.getDateOpened()); Calendar now = Calendar.getInstance(); Long methods are double yearsOpened = now.get(Calendar.YEAR) - then.get(Calendar.YEAR); int monthsOpened = now.get(Calendar.MONTH) - then.get(Calendar.MONTH); difficult to: if (monthsOpened < 0) { yearsOpened--; monthsOpened + 12 th O d += 12; } Read and understand yearsOpened = yearsOpened + (monthsOpened / 12.0); if (yearsOpened < fromAccount.getRequiredYearsOpen() || newBalance < fromAccount.getLimit()) throw new MoneyTransferException(quot;Limit exceededquot;); Maintain break; default: throw new MoneyTransferException(quot;Unknown overdraft type: quot; Test + fromAccount.getOverdraftPolicy()); } Fix: fromAccount.setBalance(newBalance); toAccount.setBalance(toAccount.getBalance() + amount); TransferTransaction txn = new TransferTransaction(fromAccount, toAccount, amount, new Date()); Splitting into smaller bankingTransactionDAO.addTransaction(txn); return txn; } methods 3/1/2009 52 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 53. Compose Method Refactoring p g public class MoneyTransferServiceProceduralImpl implements MoneyTransferService { public class MoneyTransferServiceProceduralImpl public BankingTransaction transfer(String fromAccountId, String implements MoneyTransferService { toAccountId, toAccountId double amount) { Account fromAccount = public BankingTransaction transfer(String fromAccountId, accountDAO.findAccount(fromAccountId); String toAccountId, double amount) { Account toAccount = accountDAO.findAccount(toAccountId); Account fromAccount = assert amount > 0; accountDAO.findAccount(fromAccountId); debit(fromAccount, amount); Account toAccount = credit(toAccount, amount); accountDAO.findAccount(toAccountId); TransferTransaction txn = new Extract Et t double newBalance = fromAccount getBalance() – fromAccount.getBalance() TransferTransaction(fromAccount, toAccount, amount; Method amount, new Date()); switch (fromAccount.getOverdraftPolicy()) { bankingTransactionDAO.addTransaction(txn); case Account.NEVER: return txn; … } break; default: public void debit(Account fromAccount, double amount) { … double newBalance = fromAccount.getBalance() – } amount; fromAccount.setBalance(newBalance); switch (fromAccount.getOverdraftPolicy()) { toAccount.setBalance(toAccount.getBalance() + case Account.NEVER: amount); … TransferTransaction txn = new break; TransferTransaction(fromAccount, toAccount, default: amount, amount new Date()); … bankingTransactionDAO.addTransaction(txn); } return txn; fromAccount.setBalance(newBalance); } } public void credit(Account toAccount, double amount) { toAccount.setBalance(toAccount.getBalance() + amount); } 3/1/2009 53 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 54. Feature Envy y public class MoneyTransferServiceProceduralImpl implements MoneyTransferService { public BankingTransaction transfer(String fromAccountId, String toAccountId, double amount) { Methods that are Account fromAccount = accountDAO.findAccount(fromAccountId); Account toAccount = accountDAO.findAccount(toAccountId); assert amount > 0; far too interested double newBalance = fromAccount.getBalance() - amount; switch (fromAccount.getOverdraftPolicy()) { case Account.NEVER: in data belonging if (newBalance < 0) throw new MoneyTransferException(quot;In sufficient fundsquot;); break; case Account.ALLOWED: to th t other classes l Calendar then = C l d C l d th Calendar.getInstance(); tI t () then.setTime(fromAccount.getDateOpened()); Calendar now = Calendar.getInstance(); Results in: double yearsOpened = now.get(Calendar.YEAR) - then.get(Calendar.YEAR); int monthsOpened = now.get(Calendar.MONTH) - then.get(Calendar.MONTH); if (monthsOpened < 0) { yearsOpened--; Poor encapsulation monthsOpened += 12; } yearsOpened = yearsOpened + (monthsOpened / 12.0); Long methods if (yearsOpened < fromAccount.getRequiredYearsOpen() || newBalance < fromAccount.getLimit()) throw new MoneyTransferException(quot;Limit exceededquot;); break; Fix by moving default: throw new MoneyTransferException(quot;Unknown overdraft type: quot; + fromAccount.getOverdraftPolicy()); methods to the th d t th } fromAccount.setBalance(newBalance); class that has the toAccount.setBalance(toAccount.getBalance() + amount); TransferTransaction txn = new TransferTransaction(fromAccount, toAccount, amount, new Date()); bankingTransactionDAO.addTransaction(txn); data return txn; } 3/1/2009 54 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 55. Data class public class Account { public static final int NEVER = 1; Classes that are public static final int ALLOWED = 2; private int id; just getters and private double balance; private int overdraftPolicy; private String accountId; setters private Date dateOpened; private double requiredYearsOpen; p private double limit; ; No business logic - Account() {} it’s in the service public Account(String accountId, double balance, int overdraftPolicy, Date dateOpened, double requiredYearsOpen, double limit) {….. } Leads to: public int getId() {return id;} Feature envy public String getAccountId() {return accountId;} public void setBalance(double balance) { this.balance = balance; } Fix by moving y g public double getBalance() { return balance; } methods that act public int getOverdraftPolicy() { return overdraftPolicy; } public Date getDateOpened() { return dateOpened; } on data into class public double getRequiredYearsOpen() { return requiredYearsOpen; } public double getLimit() {return limit; } } 3/1/2009 55 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 56. Move Method refactoring g public class MoneyTransferServiceProceduralImpl implements MoneyTransferService { public class MoneyTransferServiceProceduralImpl implements MoneyTransferService { public BankingTransaction transfer(String fromAccountId, String public BankingTransaction transfer(String fromAccountId, String toAccountId, double toAccountId, toAccountId double amount) { amount) { Account fromAccount = accountDAO.findAccount(fromAccountId); Account fromAccount = Account toAccount = accountDAO.findAccount(toAccountId); accountDAO.findAccount(fromAccountId); assert amount > 0; double newBalance = fromAccount.getBalance() - amount; Account toAccount = accountDAO.findAccount(toAccountId); switch (fromAccount.getOverdraftPolicy()) { assert amount > 0; case Account.NEVER: if (newBalance < 0) fromAccount.debit(amount); throw new MoneyTransferException(quot;In sufficient fundsquot;); toAccount.credit(amount); break; case Account.ALLOWED: TransferTransaction txn = new Calendar then = Calendar.getInstance(); TransferTransaction(fromAccount, toAccount, then.setTime(fromAccount.getDateOpened()); Calendar now = Calendar.getInstance(); amount, new Date()); bankingTransactionDAO.addTransaction(txn); double yearsOpened = now.get(Calendar.YEAR) - then.get(Calendar.YEAR); int monthsOpened = now.get(Calendar.MONTH) - then.get(Calendar.MONTH); return txn; if (monthsOpened < 0) { } yearsOpened--; monthsOpened += 12; } yea sOpe ed yearsOpened = yearsOpened + (monthsOpened / 12.0); yea sOpe ed ( o t sOpe ed 0); if (yearsOpened < fromAccount.getRequiredYearsOpen() || newBalance < fromAccount.getLimit()) throw new MoneyTransferException(quot;Limit exceededquot;); public class Account { break; public void debit(fAccount fromAccount, double amount) { default: throw new MoneyTransferException(quot;Unknown overdraft type: quot; double newBalance = getBalance() – amount; + fromAccount.getOverdraftPolicy()); switch (getOverdraftPolicy()) { } …. fromAccount.setBalance(newBalance); } toAccount.setBalance(toAccount.getBalance() toAccount setBalance(toAccount getBalance() + amount); TransferTransaction txn = new TransferTransaction(fromAccount, toAccount, setBalance(newBalance); amount, new Date()); } bankingTransactionDAO.addTransaction(txn); return txn; } public void credit(Account toAccount, double amount) { setBalance(getBalance() + amount); } Extract and move feature envy code into data class 3/1/2009 56 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 57. Primitive Obsession public class Account { Code uses built- private Date dateOpened; } in types instead yp of application public class Account { private Date dateOpened; classes } public class MoneyTransferServiceProceduralImpl Consequences: q implements MoneyTransferService { public BankingTransaction transfer(String f f fromAccountId, Reduces String toAccountId, double amount) { understandability Account fromAccount = accountDAO.findAccount(fromAccountId); Account toAccount = accountDAO.findAccount(toAccountId); Long methods … Calendar then = Calendar.getInstance(); Code duplication C d d li ti then.setTime(fromAccount.getDateOpened()); th tTi (f A t tD t O d()) Calendar now = Calendar.getInstance(); Added double yearsOpened = now.get(Calendar.YEAR) - complexity then.get(Calendar.YEAR); int monthsOpened = now.get(Calendar.MONTH) – Fix by moving then.get(Calendar.MONTH); if (monthsOpened < 0) { data and code yearsOpened--; monthsOpened += 12; } into new class yearsOpened = yearsOpened + (monthsOpened / 12.0); if (yearsOpened < fromAccount.getRequiredYearsOpen() || newBalance < fromAccount.getLimit()) … } 3/1/2009 57 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 58. Replace Data Value with Object p j public class CalendateDate { private Date dateOpened; public class Account { Date getDateOpened( return dateOpened; } private Date dateOpened; } } public class Account { private CalendateDate dateOpened; Move Method public double getYearsOpen() { Calendar then = Calendar.getInstance(); then.setTime(dateOpened.getDateOpened()); public class Account { Calendar now = Calendar.getInstance(); private CalendateDate dateOpened; double yearsOpened = now.get(Calendar.YEAR) - public double getYearsOpen() { then.get(Calendar.YEAR); return dateOpened.getYearsOpened(); int monthsOpened = now.get(Calendar.MONTH) – } then.get(Calendar.MONTH); if (monthsOpened < 0) { yearsOpened--; public class CalendateDate { monthsOpened += 12; private Date dateOpened; } yearsOpened = yearsOpened + public double getYearsOpen() { (monthsOpened / 12.0); return yearsOpened; t O d Calendar then = Calendar.getInstance(); } yearsOpened = yearsOpened + (monthsOpened / 12.0); return yearsOpened; } } 3/1/2009 58 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 59. Switch Statements Use of type codes and public class Account { switch statements instead p public static final int NEVER = 1; ; of polymorphism public static final int ALLOWED = 2; Key concepts are private int overdraftPolicy ; … represented by type codes instead of classes public class MoneyTransferServiceProceduralImpl Consequences: C implements MoneyTransferService { Longer methods public BankingTransaction transfer(String Poor maintainability caused fromAccountId, String toAccountId, by code duplication double amount) { Increased code complexity … Fix by introducing class switch (fromAccount.getOverdraftPolicy()) { case Account.NEVER: hierarchy and moving … each part of switch break; statement into a case Account ALLOWED: Account.ALLOWED: overriding method … default: … } … } 3/1/2009 59 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 60. Replace Type Code with Strategy p yp gy public class Account { public static final int NEVER = 1; public static final int ALLOWED = 2; public class MoneyTransferServiceProceduralImpl … { private OverdraftPolicy overdraftPolicy; … public BankingTransaction transfer(String fromAccountId, String toAccountId, double amount) { ) … switch (fromAccount.getOverdraftPolicy().getTypeCode()) { case Account.NEVER: … break; b k case Account.ALLOWED: … default: … } … } 3/1/2009 60 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 61. Replace Conditional with Polymorphism y p Extract/Move public class MoneyTransferServiceProceduralImpl … { Method public BankingTransaction transfer( ) { transfer(…) … fromAccount.getOverdraftPolicy().beforeDebitCheck(…); … } Push Down & simplify 3/1/2009 61 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 62. Data clumps p Multiple fields or public class A bli l Account { t method parameters that public static final int NEVER = 1; public static final int ALLOWED = 2; belong together Consequences: private int id; private double balance; Long methods private String accountId; Duplication D li ti private Date dateOpened; Fix by: private int overdraftPolicy; Moving fields into private double requiredYearsOpen; their th i own class l private double limit; Eliminate resulting Account() {} Feature Envy } 3/1/2009 62 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 63. Extract Class public class Account { public static final int NEVER = 1; public static final int ALLOWED = 2; private int id; Move Field private double balance; private String accountId; private Date dateOpened; private OverdraftPolicy overdraftPolicy; Account() {} } pub c c ass O e d a t o cy public class OverdraftPolicy { private int overdraftPolicy; private double requiredYearsOpen; p private double limit; ; … 3/1/2009 63 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 64. Agenda g Where are the real objects? Overview of the Domain Model pattern Domain model building blocks Role of frameworks Obstacles to OO Eliminating common code smells Refactoring existing code 3/1/2009 64 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 65. Transforming p g procedural code Inside every procedural design is a domain model just trying to get out Incrementally transform a procedural design into an OO design Small, localized changes Something to do on Monday morning! 3/1/2009 65 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 66. DEMO Refactoring procedural code 3/1/2009 66 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 67. Summary y A rich domain model: Organizes the business logic as classes with state AND behavior Improves maintainability and I i t i bilit d testability Enabled by POJOs and non invasive non-invasive frameworks (mostly) Emerges from procedural code by incremental refactoring Use it – starting monday! 3/1/2009 67 Copyright (c) 2007 Chris Richardson. All rights reserved.
  • 68. For more information Buy my book ☺ Send email: chris@chrisrichardson.net Visit my website: http://www.chrisrichardson. net Talk to me about consulting and training g g 3/1/2009 68 Copyright (c) 2007 Chris Richardson. All rights reserved.