58
Slide 1 © Copyright 2007, Chris Richardson Chris Richardson: Improving Your Application’s Design by Using Real Objects Colorado Software Summit: October 21 – 26, 2007 Improving Your Application’s Design by Using Real Objects Chris Richardson Author of POJOs in Action Chris Richardson Consulting, Inc http://www. chrisrichardson .net

Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

  • Upload
    others

  • View
    3

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

Slide 1

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects

Colorado Software Summit: October 21 – 26, 2007

Improving Your Application’sDesign by Using Real Objects

Chris RichardsonAuthor of POJOs in Action

Chris Richardson Consulting, Inc

http://www.chrisrichardson.net

Page 2: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 2

Colorado Software Summit: October 21 – 26, 2007

About ChrisGrew up in EnglandLive in Oakland, CAOver twenty years ofsoftware developmentexperience

Building object-orientedsoftware since 1986Using Java since 1996Using J2EE since 1999

Author of POJOs in ActionSpeaker at JavaOne,JavaPolis, NFJS, JUGs, ….Chair of the eBIG Java SIGin Oakland (www.ebig.org)Run a consulting andtraining company that helpsorganizations build bettersoftware faster

Page 3: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 3

Colorado Software Summit: October 21 – 26, 2007

Overall presentation goal

Learn how to improve applicationdesign with truly object-oriented

business logic

Page 4: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 4

Colorado Software Summit: October 21 – 26, 2007

Agenda

Where are the real objects?

Overview of the Domain Model pattern

Domain model building blocks

Role of frameworks

Common code smells

Refactoring existing code

Obstacles to OO

Page 5: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 5

Colorado Software Summit: October 21 – 26, 2007

Designing business logicSome enterprise frameworks (e.g.Spring) promote good design practices:

Dependency injection for loose couplingAOP for handling cross cutting concerns

But you must decide how to structureyour business logic:

Domain Model pattern – object-orientedTransaction Script pattern – procedural

Choice of pattern impacts ease of:Development, testing, maintainability, …

Page 6: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 6

Colorado Software Summit: October 21 – 26, 2007

Lots of procedural Java code

Java is an object-oriented language

AND

Object-oriented design is a better way to tacklecomplexity

YET

Many complex enterprise Java applications are writtenin a procedural style

Page 7: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 7

Colorado Software Summit: October 21 – 26, 2007

Example banking application

Page 8: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 8

Colorado Software Summit: October 21 – 26, 2007

Example procedural design

BankingTransaction transfer (fromAccountId , toAccountId , amount )

MoneyTransferService

Account findAccount (accountId )

AccountRepository

txnId

date

BankingTransaction

addTransaction ()

BankingTransactionRepository

accountIdbalanceoverdraftType

Account

State

Behavior

Web Tier

Business Tier Transaction

script

An anemic

domain model

Missing classes

for key concepts

Page 9: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 9

Colorado Software Summit: October 21 – 26, 2007

Example procedural codepublic class MoneyTransferServiceProceduralImpl implements MoneyTransferService {

public BankingTransaction transfer(String fromAccountId, String toAccountId, double amount) throws MoneyTransferException { Account fromAccount = accountDAO.findAccount(fromAccountId); Account toAccount = accountDAO.findAccount(toAccountId); assert amount > 0; double newBalance = fromAccount.getBalance() - amount; switch (fromAccount.getOverdraftPolicy()) { case Account.NEVER: if (newBalance < 0) throw new MoneyTransferException("In sufficient funds"); break; case Account.ALLOWED: Calendar then = Calendar.getInstance(); then.setTime(fromAccount.getDateOpened()); Calendar now = Calendar.getInstance();

double yearsOpened = now.get(Calendar.YEAR) - then.get(Calendar.YEAR); int monthsOpened = now.get(Calendar.MONTH) - then.get(Calendar.MONTH); if (monthsOpened < 0) { yearsOpened--; monthsOpened += 12; } yearsOpened = yearsOpened + (monthsOpened / 12.0); if (yearsOpened < fromAccount.getRequiredYearsOpen() || newBalance < fromAccount.getLimit()) throw new MoneyTransferException("Limit exceeded"); break; default: throw new MoneyTransferException("Unknown overdraft type: " + fromAccount.getOverdraftPolicy());

} fromAccount.setBalance(newBalance); toAccount.setBalance(toAccount.getBalance() + amount); TransferTransaction txn = new TransferTransaction(fromAccount, toAccount, amount, new Date()); bankingTransactionDAO.addTransaction(txn); return txn; }

public class Account {

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

private int id;private double balance;private int overdraftPolicy;private String accountId;private Date dateOpened;private double requiredYearsOpen;private double limit;

Account() {}

public Account(String accountId, double balance, intoverdraftPolicy, Date dateOpened, double requiredYearsOpen,double limit) {….. }

public int getId() {return id;}

public String getAccountId() {return accountId;}

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

public double getBalance() { return balance; }

public int getOverdraftPolicy() { return overdraftPolicy; }

public Date getDateOpened() { return dateOpened; }

public double getRequiredYearsOpen() { return requiredYearsOpen; }

public double getLimit() {return limit; }}

Page 10: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 10

Colorado Software Summit: October 21 – 26, 2007

A seductive programming style

Implementing new functionality is easy

Add a new transaction script

Add code to a new transaction script

No need to do any real design, e.g.

Create new classes

Determine responsibilities

Page 11: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 11

Colorado Software Summit: October 21 – 26, 2007

Unable to handle complexity

Works well for simple business logice.g. the example wasn’t that bad

But with complex business logic:Large transaction scripts: 100s/1000s LOCDifficult/impossible to understand, test, and maintain

What’s worse: business logic has a habit ofgrowing

New requirements Add a few more lines to thetransaction scriptMany new requirements big messSoon or later you end up with unmaintainable code

Page 12: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 12

Colorado Software Summit: October 21 – 26, 2007

Today – rich domain models aregrowing in popularity

POJOsPlain Old Java ObjectsLeverage OO features ofJava

O/R mapping frameworksfor persisting POJOs:

HibernateJava Persistence API…

Spring AOP and AspectJ forhandling cross-cuttingconcerns:

Transaction managementSecurityLoggingAuditing…

Page 13: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 13

Colorado Software Summit: October 21 – 26, 2007

Agenda

Where are the real objects?

Overview of the Domain Model pattern

Domain model building blocks

Role of frameworks

Common code smells

Refactoring existing code

Obstacles to OO

Page 14: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 14

Colorado Software Summit: October 21 – 26, 2007

Using the Domain Model Pattern

Business logic spread amongst a collectionof classes

Many classes correspond to real worldconcepts: Order, Customer, …

Many classes are true objects havingboth:

State – fields

Behavior – methods that act on the state

Page 15: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 15

Colorado Software Summit: October 21 – 26, 2007

Procedural versus OO

Business Tier

Presentation Tier

Data Access Tier

TransactionScripts

(Session Beans)

Data Objects

Business Tier

Domain Model

Presentation Tier

Facade

Data Access Tier

Page 16: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 16

Colorado Software Summit: October 21 – 26, 2007

An example domain model

debit(amount)credit(amount)

balance

Account

amountdate

BankingTransaction

BankingTransaction transfer(fromId, toId, amount)

MoneyTransferService

findAccount(id)

AccountRepository

<<interface>>OverdraftPolicy

NoOverdraftPolicy

limit

LimitedOverdraft

from

to

State + Behavior

Behavior

ExplicitRepresentation

of key concepts

Web Tier

Business Tier

addTransaction(…)

BankingTransactionRepository

Page 17: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

Slide 17

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects

Colorado Software Summit: October 21 – 26, 2007

DEMO

Code Walkthrough

Page 18: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 18

Colorado Software Summit: October 21 – 26, 2007

Benefits of the Domain ModelPattern

Improved maintainabilityThe design reflects realityKey domain classes are represented by classesThe design is more modular

Improved testabilitySmall classes that can be tested in isolation

Improved reusabilityClasses can be used in other applications

Building a domain modelCreates shared understandingDevelops an ubiquitous language

Page 19: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 19

Colorado Software Summit: October 21 – 26, 2007

Quantifiably simpler code

Procedural – few, longer, morecomplex methods

Object-oriented – more, simpler,shorter methods

Page 20: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20

Colorado Software Summit: October 21 – 26, 2007

Drawbacks of the Domain Modelpattern

Requires object-oriented design skills

Requires domain model to betransparently “mappable” to the data

e.g. nice database schema

Ugly schemas and data stored in otherapplications is a challenge

Page 21: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 21

Colorado Software Summit: October 21 – 26, 2007

When to use it

The business logic is reasonablycomplex or you anticipate that it will be

You have the skills to design one

You can use an ORM framework

Page 22: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 22

Colorado Software Summit: October 21 – 26, 2007

Agenda

Where are the real objects?

Overview of the Domain Model pattern

Domain model building blocks

Role of frameworks

Common code smells

Refactoring existing code

Obstacles to OO

Page 23: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 23

Colorado Software Summit: October 21 – 26, 2007

Domain model building blocks

Roles akastereotypes

Benefits of roles:

Guide design

Help name objects

Aid understanding

Roles (fromDomain-DrivenDesign)

Entity Value Object

Aggregate Service

RepositoryFactory

Page 24: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 24

Colorado Software Summit: October 21 – 26, 2007

Entity

Objects with adistinct identity

Typicallycorrespond to realworld concepts

Almost alwayspersistent

public class Account {

private int id;

private double balance;

private OverdraftPolicy overdraftPolicy;

private String accountId;

private CalendarDate dateOpened;

Account() { }

public void debit(double amount) throws MoneyTransferException { assert amount > 0; double originalBalance = balance;

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

}

public void credit(double amount) {

assert amount > 0; balance += amount; }

Page 25: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 25

Colorado Software Summit: October 21 – 26, 2007

Value ObjectsObjects that aredefined by the valuesof their attributesTwo instances withidentical values canbe usedinterchangeablyPart of an entityUsually persistentIdeally immutableOften missing fromprocedural code

public class CalendarDate {

private Date date;

CalendarDate() { }

public CalendarDate(Date date) {

this.date = date; }

public Date getDate() { return date; }

public double getYearsOpen() { Calendar then = Calendar.getInstance(); then.setTime(date);

Calendar now = Calendar.getInstance();

int yearsOpened = now.get(Calendar.YEAR) – then.get(Calendar.YEAR);

int monthsOpened = now.get(Calendar.MONTH) - then.get(Calendar.MONTH); if (monthsOpened < 0) {

yearsOpened--; monthsOpened += 12; }

return yearsOpened + (monthsOpened/12.0);

}

}

Page 26: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 26

Colorado Software Summit: October 21 – 26, 2007

Aggregates

NameserviceArea

Restaurant

updateDeliveryInfo()updateRestaurant()getTotal()...

Order

getExtendedPrice()

quantity

OrderLineItem

nameprice

MenuItem

Address

PaymentInformation

<<interface>>

Coupon

root boundary

A cluster of relatedentities and values

Behaves as a unit

Has a root

Has a boundary

Objects outside theaggregate can onlyreference the root

Deleting the rootremoves everything

Page 27: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 27

Colorado Software Summit: October 21 – 26, 2007

RepositoriesManages a collection ofobjects

Provides methods for:Adding an object

Finding object or objects

Deleting objects

Consists of an interface andan implementation class

Encapsulates databaseaccess mechanism

Keeps the ORM frameworkout of the domain model

Similar to a DAO

public interface AccountRepository {

Account findAccount(String accountId);

void addAccount(Account account);

}

public class HibernateAccountRepository implements AccountRepository {

private HibernateTemplate hibernateTemplate;

public HibernateAccountRepository(HibernateTemplate template) { hibernateTemplate = template;

}

public void addAccount(Account account) {

hibernateTemplate.save(account); }

public Account findAccount(final String accountId) {

return (Account) DataAccessUtils.uniqueResult(hibernateTemplate .findByNamedQueryAndNamedParam( "Account.findAccountByAccountId", "accountId",

accountId)); }

}

Page 28: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 28

Colorado Software Summit: October 21 – 26, 2007

ServicesImplements logic thatcannot be put in a singleentity

Not persistent

Consists of an interface andan implementation class

Service method usually:Invoked (indirectly) bypresentation tier

Invokes one or morerepositories

Invokes one or more entities

Keep them thin

public interface MoneyTransferService {

BankingTransaction transfer(String fromAccountId,

String toAccountId, double amount) throws MoneyTransferException;

}

public class MoneyTransferServiceImpl implements MoneyTransferService{

private final AccountRepository accountRepository;

private final BankingTransactionRepository

bankingTransactionRepository;

public MoneyTransferServiceImpl(AccountRepository accountRepository,

BankingTransactionRepository bankingTransactionRepository) { this.accountRepository = accountRepository; this.bankingTransactionRepository = bankingTransactionRepository; }

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

… }

}

Page 29: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 29

Colorado Software Summit: October 21 – 26, 2007

Factories

Use when a constructor is insufficientEncapsulates complex object creation logic

Handles varying products

Different kinds of factoriesFactory classes

Factory methods

Example: OrderFactoryCreates Order from a shopping cart

Adds line items

Page 30: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 30

Colorado Software Summit: October 21 – 26, 2007

Agenda

Where are the real objects?

Overview of the Domain Model pattern

Domain model building blocks

Role of frameworks

Common code smells

Refactoring existing code

Obstacles to OO

Page 31: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 31

Colorado Software Summit: October 21 – 26, 2007

Use the POJO programmingmodel

Your domain model might outliveinfrastructure frameworks Minimize

dependencies on them

POJO = Plain Old Java Object

Don't implement any infrastructureinterfaces

Don't call infrastructure APIs

No infrastructure framework annotations?

Slide 31

Page 32: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 32

Colorado Software Summit: October 21 – 26, 2007

Use dependency injectionSpring instantiates and wires together

Services, factories and repositories

Dependency injection into entitiesOne option is @Configurable but it’s not POJOHibernate Interceptor+Manual injection is preferable

Benefits:Decouples components from one another and theinfrastructureImproves testability

Slide 32

public AccountServiceImpl(AccountDao accountDao,

BankingTransactionDao bankingTransactionDao) {

this.accountDAO = accountDao;

this.bankingTransactionDAO = bankingTransactionDao;

}

<beans>

<bean id="AccountService"

class="net.chris...domain.AccountServiceImpl">

<constructor-arg ref="accountDao"/>

<constructor-arg ref="bankingTransactionDao"/>

</bean>

</beans>

Page 33: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 33

Colorado Software Summit: October 21 – 26, 2007

Use Aspect-OrientedProgramming

Spring AOP for service-levelcrosscutting concerns:

e.g. transactionmanagement, security,logging, etc.

AspectJ for entity and valueobject crosscutting concerns

e.g. tracking changes tofieldsBut AJC/Load-time weavinghas a cost

BenefitsDecouples code frominfrastructure

Improves modularity

Page 34: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 34

Colorado Software Summit: October 21 – 26, 2007

Use object/relational mapping

Persisting objectswith JDBC is toomuch work

Implement DAOswith Spring ORM

BenefitsLess code

Simpler code

Improved testability

<class name="Account"

table="BANK_ACCOUNT" >

<id name="id" column="ACCOUNT_ID">

<generator class="native" />

</id>

<property name="balance" />

<property name="accountId" />

<property name="dateOpened" />

<many-to-one name="overdraftPolicy" />

</class>

public class HibernateAccountDao

implements AccountDao {

private HibernateTemplate hibernateTemplate;

public HibernateAccountDao(HibernateTemplate

template) {

this.hibernateTemplate = template;

}

public void addAccount(Account account) {

hibernateTemplate.save(account);

}

}

Page 35: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 35

Colorado Software Summit: October 21 – 26, 2007

Agenda

Where are the real objects?

Overview of the Domain Model pattern

Domain model building blocks

Role of frameworks

Common code smells

Refactoring existing code

Obstacles to OO

Page 36: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 36

Colorado Software Summit: October 21 – 26, 2007

Overview of code smells

Code smell = something about thecode that does not seem right

Impacts ease of development andtesting

Some are non-OOD

Some are the consequences of non-OOD

Page 37: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 37

Colorado Software Summit: October 21 – 26, 2007

Long methodMethods should beshortBut business logic isconcentrated in theservices longmethodsLong methods aredifficult to:

Read and understandMaintainTest

Fix:Splitting into smallermethods

public class MoneyTransferServiceProceduralImpl implements MoneyTransferService {

public BankingTransaction transfer(String fromAccountId, String toAccountId, double amount) throws MoneyTransferException { Account fromAccount = accountDAO.findAccount(fromAccountId); Account toAccount = accountDAO.findAccount(toAccountId); assert amount > 0; double newBalance = fromAccount.getBalance() - amount; switch (fromAccount.getOverdraftPolicy()) { case Account.NEVER: if (newBalance < 0) throw new MoneyTransferException("In sufficient funds"); break; case Account.ALLOWED: Calendar then = Calendar.getInstance(); then.setTime(fromAccount.getDateOpened()); Calendar now = Calendar.getInstance();

double yearsOpened = now.get(Calendar.YEAR) - then.get(Calendar.YEAR); int monthsOpened = now.get(Calendar.MONTH) - then.get(Calendar.MONTH); if (monthsOpened < 0) { yearsOpened--; monthsOpened += 12; } yearsOpened = yearsOpened + (monthsOpened / 12.0); if (yearsOpened < fromAccount.getRequiredYearsOpen() || newBalance < fromAccount.getLimit()) throw new MoneyTransferException("Limit exceeded"); break; default: throw new MoneyTransferException("Unknown overdraft type: " + fromAccount.getOverdraftPolicy());

} fromAccount.setBalance(newBalance); toAccount.setBalance(toAccount.getBalance() + amount); TransferTransaction txn = new TransferTransaction(fromAccount, toAccount, amount, new Date()); bankingTransactionDAO.addTransaction(txn); return txn; }

Page 38: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 38

Colorado Software Summit: October 21 – 26, 2007

Feature Envy

Methods that are fartoo interested indata belonging toother classes

Results in:Poor encapsulation

Long methods

Fix by movingmethods to the classthat has the data

public class MoneyTransferServiceProceduralImpl implements MoneyTransferService {

public BankingTransaction transfer(String fromAccountId, String toAccountId, double amount) throwsMoneyTransferException { Account fromAccount = accountDAO.findAccount(fromAccountId); Account toAccount = accountDAO.findAccount(toAccountId); assert amount > 0; double newBalance = fromAccount.getBalance() - amount; switch (fromAccount.getOverdraftPolicy()) { case Account.NEVER: if (newBalance < 0) throw new MoneyTransferException("In sufficient funds"); break; case Account.ALLOWED: Calendar then = Calendar.getInstance(); then.setTime(fromAccount.getDateOpened()); Calendar now = Calendar.getInstance();

double yearsOpened = now.get(Calendar.YEAR) - then.get(Calendar.YEAR); int monthsOpened = now.get(Calendar.MONTH) - then.get(Calendar.MONTH); if (monthsOpened < 0) { yearsOpened--; monthsOpened += 12; } yearsOpened = yearsOpened + (monthsOpened / 12.0); if (yearsOpened < fromAccount.getRequiredYearsOpen() || newBalance < fromAccount.getLimit()) throw new MoneyTransferException("Limit exceeded"); break; default: throw new MoneyTransferException("Unknown overdraft type: " + fromAccount.getOverdraftPolicy());

} fromAccount.setBalance(newBalance); toAccount.setBalance(toAccount.getBalance() + amount); TransferTransaction txn = new TransferTransaction(fromAccount, toAccount, amount, new Date()); bankingTransactionDAO.addTransaction(txn); return txn; }

Page 39: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 39

Colorado Software Summit: October 21 – 26, 2007

Data class

Classes that are justgetters and setters

No business logic -it’s in the service

Leads to:

Feature envy

Fix by movingmethods that act ondata into class

public class Account {

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

private int id;private double balance;private int overdraftPolicy;private String accountId;private Date dateOpened;private double requiredYearsOpen;private double limit;

Account() {}

public Account(String accountId, double balance, int overdraftPolicy, Date dateOpened, double requiredYearsOpen, double limit) {….. }

public int getId() {return id;}

public String getAccountId() {return accountId;}

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

public double getBalance() { return balance; }

public int getOverdraftPolicy() { return overdraftPolicy; }

public Date getDateOpened() { return dateOpened; }

public double getRequiredYearsOpen() { return requiredYearsOpen; }

public double getLimit() {return limit; }}

Page 40: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 40

Colorado Software Summit: October 21 – 26, 2007

Primitive Obsession

Code uses built-intypes instead ofapplicationclassesConsequences:

ReducesunderstandabilityLong methodsCode duplicationAdded complexity

Fix by movingdata and codeinto new class

public class Account { private Date dateOpened;}

public class Account { private Date dateOpened;}

public class MoneyTransferServiceProceduralImpl implementsMoneyTransferService {

public BankingTransaction transfer(String fromAccountId, StringtoAccountId, double amount) throws MoneyTransferException {

Account fromAccount = accountDAO.findAccount(fromAccountId); Account toAccount = accountDAO.findAccount(toAccountId); … Calendar then = Calendar.getInstance();

then.setTime(fromAccount.getDateOpened()); Calendar now = Calendar.getInstance();

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

then.get(Calendar.MONTH); if (monthsOpened < 0) { yearsOpened--; monthsOpened += 12;

} yearsOpened = yearsOpened + (monthsOpened / 12.0); if (yearsOpened < fromAccount.getRequiredYearsOpen()

|| newBalance < fromAccount.getLimit())…}

Page 41: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 41

Colorado Software Summit: October 21 – 26, 2007

Switch StatementsUse of type codes andswitch statements insteadof polymorphism

Key concepts are notrepresented byclassesConsequences:

Longer methodsPoor maintainabilitycaused by code duplicationIncreased code complexity

Fix by introducing classhierarchy and movingeach part of switchstatement into aoverriding method

public class MoneyTransferServiceProceduralImplimplements MoneyTransferService {

public BankingTransaction transfer(StringfromAccountId, String toAccountId,

double amount) throws MoneyTransferException {… switch (fromAccount.getOverdraftPolicy()) { case Account.NEVER:

… break; case Account.ALLOWED: … default:

… } …}

public class Account {

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

Page 42: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 42

Colorado Software Summit: October 21 – 26, 2007

Data clumps

Multiple fields ormethod parametersthat belong together

Consequences:Long methods

Duplication

Fix by:Moving fields intotheir own class

Eliminate resultingFeature Envy

public class Account {

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

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

private int overdraftPolicy;private double requiredYearsOpen;private double limit;

Account() {}

}

Page 43: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 43

Colorado Software Summit: October 21 – 26, 2007

Agenda

Where are the real objects?

Overview of the Domain Model pattern

Domain model building blocks

Role of frameworks

Common code smells

Refactoring existing code

Obstacles to OO

Page 44: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 44

Colorado Software Summit: October 21 – 26, 2007

Transforming procedural code

Inside every procedural design is adomain model just trying to get out

Incrementally transform a proceduraldesign into an OO design

Small, localized changes

Something to do on Monday morning!

Page 45: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 45

Colorado Software Summit: October 21 – 26, 2007

Refactoring to an OO design

Transform aprocedural designto an OO design byapplyingrefactoringsRefactoring:

Restructure thecodeWithout changingbehavior

Essential cleanupsfor decaying code

Page 46: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 46

Colorado Software Summit: October 21 – 26, 2007

Basic refactoringsExtract Method

Eliminates long methods

Move MethodMove a method to adifferent class (field orparameter)Moves method to wherethe data is

Push DownMove a method intosubclassesOptionally leave anabstract method behindPart of eliminatingconditional logic

Page 47: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 47

Colorado Software Summit: October 21 – 26, 2007

Compound refactoringsA sequence of simpler refactoringsCompose method

Apply Extract Method repeatedlyUse to replace long method with more readable shortermethods

Replace Type Code With StrategyDefine GOF Strategy class for each type code

Replace Conditional With PolymorphismTurn into part of a switch statement into an overridingmethod in a subclass

Replace Data Value with ObjectMove field into its own classEliminates Primitive Obsession

Page 48: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

Slide 48

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects

Colorado Software Summit: October 21 – 26, 2007

DEMO

Refactoring procedural code

Page 49: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 49

Colorado Software Summit: October 21 – 26, 2007

Agenda

Where are the real objects?

Overview of the Domain Model pattern

Domain model building blocks

Role of frameworks

Common code smells

Refactoring existing code

Obstacles to good OO design

Slide 49

Page 50: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 50

Colorado Software Summit: October 21 – 26, 2007

Performance tuning changes thedesign

Different web requests

display different objectgraphs

Display project details

Display project forapproval or rejection

Improve performanceby loading objectgraphs using optimizedqueries (e.g. fetch join)

Therefore we needmultiple Dao (andService) methods

Slide 50

getProject(projectId)

ProjectCoordinator

findProject(projectId)

ProjectRepository

getProjectDetails(projectId)

getProjectForReview(projectId)

ProjectCoordinator

findProjectDetails(projectId)

findProjectForReview(projectId)

ProjectRepository

hibernateTemplate.get()

from Project p

inner join fetch p.operations

from Project pinner join fetch p.operations

Inner join fetch p.createdBy

Page 51: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 51

Colorado Software Summit: October 21 – 26, 2007

Untangling what to load fromthe code

Java Data Objects (JDO) has fetch groupsDeclarative specification the object graph thatneeds to be loaded

Flow:Web tier configures fetch groups

Calls ProjectCoordinator.get()

O/RM loads object graph specified by activefetch groups

Look for this feature in JPAimplementations that evolved from JDO

Slide 51

Page 52: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 52

Colorado Software Summit: October 21 – 26, 2007

Web frameworks need JavaBeans

Web frameworks can bind request parametersdirectly to domain objectsEasy creation of domain objectsEasy editing of detached domain objects1. Load object graph from database2. Store object graph in HttpSession3. Bind Http parameters to object's properties4. Reattach object graph and update the database

A lot less codeBut domain objects must be JavaBeans:

Public default constructorJavaBean-style setters

Slide 52

Page 53: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 53

Colorado Software Summit: October 21 – 26, 2007

The trouble with settersPoor encapsulation

Objects are now exposingtheir internal state

No immutable objectsIncreases code complexity

Makes it more error-prone

Developers might bypassbusiness method Bugs,poor design

Slide 53

public class Order {

private Address deliveryAddress;

public void updateDeliveryAddress( Address deliveryAddress) { // validate before changing …}

public Address getAddress() {…}…}

public class Address { private String street1;

private String street2;

public String getStreet1() {...}; public void setStreet1(String street1) {...} …

}

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

Page 54: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 54

Colorado Software Summit: October 21 – 26, 2007

How to cope

Live with it:It's often not that bad

Be vigilant for code bypassing businessmethods

Use DTOsHides domain objects from web tier

But you have to write more code

Encourage the development of betterframeworks

Slide 54

Page 55: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 55

Colorado Software Summit: October 21 – 26, 2007

More on web binding

Web frameworks can bind to propertiesof nested objects, e.g.order.deliveryAddress.street1

But some frameworks require thatintermediate objects to be non-null

This can impact the domain model

Slide 55

Page 56: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 56

Colorado Software Summit: October 21 – 26, 2007

Using ORM frameworksORM frameworks can access private fields

No setters (or getters) required

But require:Default constructorNon-final fieldsid fields

Subtle changes:Collection fields: null emptyEmbedded objects with null fields null reference

Proxy-based lazy loading:Don't access fields outside of instance affects equals()and hashCode()Can affect object identity: this != proxyToSameObjectAsThis

Slide 56

Page 57: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 57

Colorado Software Summit: October 21 – 26, 2007

SummaryA rich domain model:

Organizes the business logic as classeswith state AND behavior

Improves maintainability and testability

Enabled by POJOs and non-invasiveframeworks (mostly)

Emerges from procedural code byincremental refactoring

Use It!

Page 58: Improving Your Application’s Design by Using Real Objects€¦ · Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 20 Colorado Software Summit:

© Copyright 2007, Chris Richardson

Chris Richardson: Improving Your Application’s Design by Using Real Objects Slide 58

Colorado Software Summit: October 21 – 26, 2007

For more informationBuy my book

Send email:

[email protected]

Visit my website:

http://www.chrisrichardson.net

Talk to me about consultingand training