A place for everything, everything in its place - dworld.pl - everything on place and...Define roles...

106
A place for everything, everything in its place Benjamin Franklin

Transcript of A place for everything, everything in its place - dworld.pl - everything on place and...Define roles...

A place for everything, everything in its place

Benjamin Franklin

● I create software – holistic approach● Technology (Java, Java EE) and Craftsmanship● Design, architecture, usability● Exploration of methodologies and best practices

● I work as a trainer and consultant● Java technologies● Software engineering

● Community● Leader of Lublin Java Users Group● Blogger, speaker, publisher...

What do I do

● Challenges of software● Domain Driven Design

● introduction● advanced topics

● Technical and architecturalaspects of implementation

● When to use DDD● Beyond DDD

Agenda

Business software● No sophisticated stuff

● nothing like Fast Fourier Transform● Just simple operations...

● just multiplied by 1000:)● synergy of simple components● continuously changing

● We need a structure for dozens ofsimple elements

●You read code and understand nothing● You can't see any rules or process

●You don't know how to translatebusiness requirements to code

●You change code and nothing works●Now it's Your problem:)

Symptoms

Complexity● Essential

● inherent and unavoidable● depends on problem

● Accidental● caused by chosen approach ● depends on solution

The Second Law of Thermodynamics

Entropy does not diminish

Cowards solutionCowards solution;)

What would You change...if You start everything from the beginning?

XML

Annotations

New server

New versionof the serverSOA Dynamic language

Another webframework;)

Insanity: doing the same thing over and over again and expecting different results

Where is the problem?

Data access layer

Logic layer

Presentation layer

It's all about the model● Model needs care● Model is a heart of the system

● reason why creating it● main value● advantage factor

● Modelling is the toughest part● weak model leads to failure

*it's not truth for all system, it's just DDD perspective

Unstructured design

Just adding new features – with no care about model

● big ball of mud● chaos and anarchy● costs in long term

What model IS NOT

Database is not a model● just data structure – very technical● no behavior● static – we can't see whats going on● created to early – later we need to hack

What model IS FOR● continous knowledge gathering

● about rules● about dynamics

● common (client … developer) understanding of domain● vocabulary● jargon

What model IS

Real model● description and simplification for current needs● no unimportant stuff – avoid mental overload ● knowledge base - rules and behavior

●General concept● technology and platform independent

●Set of design and analysis techniques● focus on domain logic layer● complexity reduction● extension-ability and changeability

●Pragmatic approach to OOD and OOA

Domain Driven Design

DDD IS NOT A SILVER BULLET

EVANS IS NOT A SAVIOR

„There is technically nothing new or revolutionary in DDD, there is only a guide to a better way of thinking.”

Casey Charlton

●Focus on behavioral model

●Common (Ubiquitous) Language

●Strategic modeling● Core Domain● Contexts

●Domain Layer – OOD● Data and rules● Roles that implicate responsibility

● Responsibility Driven Design● GRASP● SOLID

DDD – Mental shift

Language of the model

If domain expert don't understand model than something is really wrong

Problems with models

●No model● just add features (somewhere;)

●Model at the beginning, but no maintenance● useless, inadequate documents

●Distinct jargon leads to need of translation● translation leads to errors and misunderstandings

●Pure analytical model – fails fast● unimplementable models are useless● "I've done my job, I don't care how You will implement it"

Solution: Ubiquitous language

● Model must be bind to code● modeling in right paradigm – there is no pure

modeling support for procedural paradigm● OOD techniques used by annalists● building blocks...

● Modeler must code● coding is not low-skilled job● result: creating implementable models

● Coder must fell responsibility for the model

“Good picture is worth more than 1000 words”

●Not only UML●Use any form that supports common understanding

and communication● Client specific diagrams● Sketch● System metaphor...

System metaphor● Software design tend to be abstract

● hard to grasp● Organize design around metaphor

● absorb vocabulary● Find metaphor in real world that

describes your system● loose, easy do understand● large scale structure

Domain Model Analysis

Domain ModelDesign

+ == Domain Logic Layer

Effort reduction

How to bind model and code?● Responsibility Driven Design

● Define roles that objects can play● Roles determines responsibility

● Separate logic in layers

Layers

User interface

Infrastructure

Application logic

Domain logic

Thin layer - just coordinates and delegatesto domain

Heart of the system – model of the businessconcepts and rules

Technical capabilities - may exist as a few layers(persistence, messages, etc)

Presentation – can be very sophisticated;do not underestimate

Building Blocks of Domain Layer

●Entities (not anemic)●Value Objects●Aggregates●Services (business)●Policies and Specifications●Business events

●Factories●Repositories

Entities● Object that need to be distinguished

● even if attributes are the same● some ID

● Not only data● Also behavior (business responsibility)

● characteristic● essential

Value Objects● Just description of some characteristic● No distinction – no identity

● VOs are the same if their attributes are the same● Typical usage:

● attributes of call between objects● Usually immutable - because has no identity

● therefore can be reusable – we don't care which instance is being used

● Usually no need to persist● if You have search criteria => You can create an instance

Power of VOs● Expression of business concepts

● adds conceptual power● more meaningful than just String

● May contain useful methods (instead of utils)● validation● constructor may validate input

● Examples● color, point (source, destination)● address*, phone number● money

Candidates for VO● Strings with format limitations

● zip code● name

● Numbers with limitations● percentage● quantity

● Business object's arguments/returns● money – composed: amount + currency

– maybe can be exchanged?● address

– can be valid only for specific time period?

Services● Business Services

● Sometimes it just isn't a thing● OO is not always proper approach● OO is not always possible (human factor)

● When can not find natural "home" in Entity/VO● Operation without state

● Defined in terms of other Building Block● Should not strip Entity/VO of all their

responsibilities

Aggregate● Cluster of objects (Entity/VOs)

● inner objects can reference each other inside● boundary with one root

● Outer entity is Aggregate root● controls access - encapsulation

● Unit of data change

Encapsulation is virtue

human.getDigestionSystem().getPeritoneum().getStomach().

add(new Sausage(2));

human.getDigestionSystem().getPeritoneum().getStomach().

add(new Sausage(2));

human.eat(new Sausage(2));

public void eat(Food f){ if (! iLike(f))

thow new IDontLikeItException(f); this.digestionSystem.swallow(f);}

human.eat(new Sausage(2));

public void eat(Food f){ if (! iLike(f))

thow new IDontLikeItException(f); this.digestionSystem.swallow(f);}

@Entitypublic class Order{

@Id private OrderId id;@OneToMany private List<OrderItem> items = new ArrayList<OrderItem>();private BigDecimal sum = new BigDecimal(0);//.... status, createDate, rebatePolicy, productRepository,...

public void add(ProductId id, int quantity){Product p = productRepository.load(id);OrderItem oi = orderItemFactory.build(p, quantity, rebatePolicy);items.add(oi);sum = sum.add(oi.getCost());

}

public void submit(){if (status != Status.NEW)

throw new InvalidStateException();status = Status.IN_PROGRESS;createDate = new Date();eventsManager.handle(orderEventsFactory.orderSubmitted(this));

}

public Iterator<OrderItem> getOrderItems(){return items.iterator();

}}

@Entitypublic class Order{

@Id private OrderId id;@OneToMany private List<OrderItem> items = new ArrayList<OrderItem>();private BigDecimal sum = new BigDecimal(0);//.... status, createDate, rebatePolicy, productRepository,...

public void add(ProductId id, int quantity){Product p = productRepository.load(id);OrderItem oi = orderItemFactory.build(p, quantity, rebatePolicy);items.add(oi);sum = sum.add(oi.getCost());

}

public void submit(){if (status != Status.NEW)

throw new InvalidStateException();status = Status.IN_PROGRESS;createDate = new Date();eventsManager.handle(orderEventsFactory.orderSubmitted(this));

}

public Iterator<OrderItem> getOrderItems(){return items.iterator();

}}

Builder Design Pattern

Director Builder

●Use factory when creation of Entity/Aggregate is complicated●Factory prevents from invalid Domain Object

● if “raw material” is invalid than factory vetoes●Options

● add factory method to closely related objects● if creating VO consider Singleton

●Architectural aspects● when creating ORM Entities (out of IoC containter control)● than inject dependencies manually in factory method

Factory

Repository

●Storage abstraction of objects (Entity/Aggregate) of some type●Encapsulates DB access

● decoupling domain and technical stuff●Retrieves objects by

● identity● business criteria (in business Use Cases)● don't use it as a finder (use separate service)

AOP Transactions

Application Service

OrdersRepository InvoicesRepository

OrmOrdersRepositoryImpl OrmInvoicesRepositoryImpl

Persistence Unit + Transactions Manager

Application Service Transaction Proxy

Policy● Process as a Domain Object

● makes it explicit● extends Ubiquitous Language

● Simply: Strategy Design Pattern● Useful when there is more than one way to

carry out a process● if process variations can be covered

by common interface● to choose process is to choose strategy

public class Order{ //FIXME: change to BigDecimal private double totalCost;

private TaxPolicy taxPolicy; private RebatePolicy rebatePolicy;

public void submit(){ totalCost-=rebatePolicy.calculateRebate(this); totalCost-=taxPolicy.calculateTax(this);

... }}

<<interface>>TaxPolicy

calculateTax(order)

PolishTaxPolicy UKTaxPolicy

Policy example

IoC Container

Policy injection

getOrderFactory

return OrderFactory

OrderFactory

PolishTaxPolicy

setTaxPolicy

@Componentpublic class OrderFactory{ private TaxPolicy taxPolicy; private RebatePolicy rebatePolicy;

@Autowired public OrderFactory(TaxPolicy tp, RebatePolicy rp){ this.taxPolicy = tp; this.rebatePolicy=rp; } public Order createOrder(...){ Order o = new Order(...);

… o.setTaxPolicy(taxPolicy);

o.setRebatePolicy(rebatePolicy); }}

@Component(„taxPolicy”)public class PolishTaxPolicy implements TaxPolicy{ ...}

<bean id="taxPolicy" class="x.y.PolishTaxPolicy">

@Configurationpublic class PolicyFactories{

@Beanpublic TaxPolicy taxPolicy() {

return ... ;}

}

Policy – common patternChange classic thinking

● noun – class● verb - method

Activity is an object● method is just a signal to execute it

Unleash OO techniques● polymorphic execution● re-usability

Extension and Testability● Extension without modification● Strategy implies high cohesion

● Single policy can be tested● Aggregate can be tested using policy stub/mock

Aggregate

<<interface>>Strategy

ConcreteBusiness Impl

Stub/MockTest Impl

Test

Test

Events● Business Event is a signal from Aggregate● Aggregate is highly decoupled

● does not know about receiver type● does not know how many receivers are interested in

@Entitypublic class Order{

public void submit(){if (status != Status.NEW)

throw new InvalidStateException();status = Status.IN_PROGRESS;createDate = new Date();

eventsManager.handle(orderEventsFactory.orderSubmitted(this));}

}

@Entitypublic class Order{

public void submit(){if (status != Status.NEW)

throw new InvalidStateException();status = Status.IN_PROGRESS;createDate = new Date();

eventsManager.handle(orderEventsFactory.orderSubmitted(this));}

}

What are Events for?● Decouple additional behavior

● adding new behavior without domain modification● strong form of Inversion of Control

● Collect state change (if we need to keep track of entity changes history) – Events Sourcing● events can signalize change

● Asynchronous invocation● When fast response is needed● Distributed DDD...

Specification● Model of rules● Makes rules explicit● Can be used for Entity/Aggregate validation or

selection

public interface InvoiceSpecyfication{public Collection<InvoiceProblem> check(Invoice i)

}

public interface InvoiceSpecyfication{public Collection<InvoiceProblem> check(Invoice i)

}

public class CombinedInvoiceSpecyfication implements InvoiceSpecyfication{

private List<InvoiceCriterion> criteria;

public Iterable<InvoiceProblem> check(Invoice i){Collection<InvoiceProblem> result = new ...;for (InvoiceCriterion criterion : criteria){

String problem = criterion.validate(i);if (problem != null){

result.add(new InvoiceProblem(problem));if (criterion.isCritical())

break;return result;

}}}}

public class CombinedInvoiceSpecyfication implements InvoiceSpecyfication{

private List<InvoiceCriterion> criteria;

public Iterable<InvoiceProblem> check(Invoice i){Collection<InvoiceProblem> result = new ...;for (InvoiceCriterion criterion : criteria){

String problem = criterion.validate(i);if (problem != null){

result.add(new InvoiceProblem(problem));if (criterion.isCritical())

break;return result;

}}}}

public interface InvoiceCriterion{public String validate(Invoice i);public boolean isCritical();

}

public interface InvoiceCriterion{public String validate(Invoice i);public boolean isCritical();

}

Domain Layer (Business Logic)

Aggregate

Entity(Aggregate root)

Entity

ValueObject

business methods

Delegate

LoadSave

BusinessService

<<interface>>Policy

(Strategy Design Pattern)

Application Layer (Application Services, Use Case Agents)

PolicyImpl1 PolicyImpl2

Building Blocks - cooperation

<<interface>>Repository

Factory

Event

Generate

Create

Delegate

Delegate

Comparison to procedural approach

PROCEDURE orderService(o:TOrder); BEGIN...END;

TOrder = RECORD id: integer;

...END;

memory.reset();

Strategic design

●Distillation of Domains●Defining Bounded Contexts●Introduce Anti-corruption Layer

You can't do everything perfect● Not enough knowledge● Not enough skilled people● Not enough time● Not enough money● Not enough time● Not enough money● Not enough time● Not enough money● Not enough time

Welcome to the real world, Neo

Focus on core domainCore Domain● Reason why we create system● Main business features (give advantage to the client)● Focus intellectual effort – invest time and best people

Supporting Domain● Additional features – not critical● Lower quality is acceptable● Can be rewritten (someday - sure;)

Generic Domain● Very specific (invoicing, math calculations)● Buy/use working solution and integrate with it

Core Domain Strategies● Write Domain Vision Statement

● what brings value?● Keep it small● Invest the best people

● Fame for implementing "sexy" business features

Context

When distinct models are combined, we are introubles

● difficult to understand● unreliable● buggy

Grand Unified Theory

Common anti-pattern● one, big, corporate model● meaningless● one word in different contexts mean different thing

– responsibility– behavior– structure

Bounded Context● When system grow up – complexity is too high

● can't look at the level of individual objects● Define context where model applies● Context is encapsulated

● communicates with outer word via interface● inner business model is hermetic● therefore it can evolve -changes don't spread

through whole system

Contexts Strategies● Common Core Context can be defined

● Shared Kernel

● Decouple distinct Domain Contexts● Core (business)● Generic (Math stuff etc)

Anti-corruption Layer

Anti-corruption Strategies

Our brand newshiny nice system

Ugly legacysystem

Anti-corruptionLayer

FacadeAdapterService

Technical aspects of DDD impl.

Main rule

Platform, framework or technical architecture should not influence arena of domain model

Useful techniques already discussed

● ORM - aggregates● Inversion of Control

● Dependency Injection - policies● Events● Aspect Oriented Programming – transactions (also

security) over application layer that impact Repositories

● Design Patterns● Policy, Specification, Anti-corruption Layer

Command-query Separation Paradigm

● Method should play one of the following roles● command – executes some logic● query – return data

● Multiple query should not affect the answer● Eliminates side effect

●Class level violation

●System level violation● Add an Order and return list of all orders

● it's GUI functionality● but server API should offer 2 methods

private int x;public int incrementAndReturn(){ x++; return x;}

private int x;public int incrementAndReturn(){ x++; return x;}

Sample violation of CqS

(G)UI

Business Logic

Application Logic

Command

Facade

ORM + JDBC

Query

DTO

Repository/DAO

Command-query Responsibility Segregation

Data provider/Finder viaService

CqRS Characteristic● Processing C and Q is often asymmetrical

● Should be scaled separately● Is it worth to apply in CRUD systems?

(G)UI

Business Logic

Application Logic

Command

Data provider/Finder

Query

DTO

Repository/DAO

DB 1DB 2

Event(asynch)

Events Bus+ Event handlersChange

CqRS – Distributed DDD and scalability

public class SearchDocumentsQuery implements Serializable{private Status status;private Date epiryDate;private String[] titleWords;private String[] contentWords;//Getters and setters/constructor

}

public class SearchDocumentsQuery implements Serializable{private Status status;private Date epiryDate;private String[] titleWords;private String[] contentWords;//Getters and setters/constructor

}

public class DocumentQueries /*implements SomeInterface*/{public List<Document> search(SearchDocumentsQuery query){

//ORM return entities – simple case }

public List<DocumentDTO> search(SearchDocumentsQuery query){//SQL return UseCase relevant Data Transfer Object

}}

public class DocumentQueries /*implements SomeInterface*/{public List<Document> search(SearchDocumentsQuery query){

//ORM return entities – simple case }

public List<DocumentDTO> search(SearchDocumentsQuery query){//SQL return UseCase relevant Data Transfer Object

}}

Query – sample impl.

public class SearchDocumentsQuery implements Serializable{private Status status;private Date epiryDate;private String[] titleWords;private String[] contentWords;//ONLY getters

public SearchDocumentsQuery expired(){

status = Status.ACTIVE;expiryDate = new Date();return this;

}

public SearchDocumentsQuery contains(String phrase){String[] words = phrase.split(" ");titleWords = words;contentWords = words;return this;

}}

public class SearchDocumentsQuery implements Serializable{private Status status;private Date epiryDate;private String[] titleWords;private String[] contentWords;//ONLY getters

public SearchDocumentsQuery expired(){

status = Status.ACTIVE;expiryDate = new Date();return this;

}

public SearchDocumentsQuery contains(String phrase){String[] words = phrase.split(" ");titleWords = words;contentWords = words;return this;

}}

Query a'la DSL

public class OrderProductCommand implelents Serializable{ private int productId; private int quantity; //getters and constructor}

public class OrderProductCommand implelents Serializable{ private int productId; private int quantity; //getters and constructor}

public class Basket /*implements SomeInterface*/{ private Order order; public void add(AddProductCommand cmd){ Product prod = productRepository.get(cmd.getProductId()); order.add(prod, cmd.getQuantity()); }

public void submit(SubmitOrderCommand cmd){ order.submit(cmd.getPayment(), cmd.getAddressInfo());

orderRepository.save(order);eventsManager.orderSubmitted(new OrderSubmittedEvent(order));

}}

public class Basket /*implements SomeInterface*/{ private Order order; public void add(AddProductCommand cmd){ Product prod = productRepository.get(cmd.getProductId()); order.add(prod, cmd.getQuantity()); }

public void submit(SubmitOrderCommand cmd){ order.submit(cmd.getPayment(), cmd.getAddressInfo());

orderRepository.save(order);eventsManager.orderSubmitted(new OrderSubmittedEvent(order));

}}

Command – classic impl.

public class OrderProductCommand extends Command{...}public class OrderProductCommand extends Command{...}

public interface Handler<T> { void handleMessage(T message) throws Exception; }

public interface Handler<T> { void handleMessage(T message) throws Exception; }

Command – handlers based impl.

public class AddProductHandler implements Handler<AddProductCommand>{

private ProductRepository repository; public void handleMessage(AddProductCommand message) { //... }}

public class AddProductHandler implements Handler<AddProductCommand>{

private ProductRepository repository; public void handleMessage(AddProductCommand message) { //... }}

public class CommandBus{public void handle(Command cmd)

Collection<Handler<?>> matchedHandlers = handlers.get(message.getClass());

for (Handler handler : matchedHandlers){//prepare environment (transactions, security,//inject current user, etc)handler.handleMessage(cmd);

}//may generate message

}}

public class CommandBus{public void handle(Command cmd)

Collection<Handler<?>> matchedHandlers = handlers.get(message.getClass());

for (Handler handler : matchedHandlers){//prepare environment (transactions, security,//inject current user, etc)handler.handleMessage(cmd);

}//may generate message

}}

Event Sourcing● If state of Aggregate at any given time is

needed to be rebuild● not the same as Logs

● "Inner" events● represents current state of Aggregate● events are stored in persistence layer● Aggregate can be recreated to given state (point in

time) by rebuilding information from relevant events.

Temporal Object PatternAlternative to Event Sourcing●whole state of Aggregate version persisted●newest version is always available – no computation

source: http://mbartyzel.blogspot.com/2008/10/wzorce-projektowe-temporal-object.html

Is DDD right for me?● Aspects of personality● Aspects of business domain itself● Aspects of project nature

C o n s t r u c t o r W r i t e r

Sometimes it's all about just collecting data(with nice GUI)

DDD Prerequisites● Domain is not trivial● Team has experience and interest in OOP/OOD● You have access to domain experts● You have an iterative process

Beyond DDD

Advanced data models● Model Archetype – analytical “design pattern”

● standard● "model component" that can be taken off the shelf,

customized, and instantiated in your own models● adaptable – can be trimmed to fit actual

requirements● extensible – can be extended to fit new

requirements● Catalog of models:

● Company structure and relationships, customers, products, inventory, orders, scientific stuff (laboratory),...

How to model People and Organizations?

Person

Employee

User

Client

Inheritance is not a good idea to model roles:P

Company

Party

source: Enterprise Patterns and MDA: Building Better Software with Archetype Patterns and UML By Jim Arlow, Ila Neustadt

General Idea

source: Enterprise Patterns and MDA: Building Better Software with Archetype Patterns and UML By Jim Arlow, Ila Neustadt

Example

source: Enterprise Patterns and MDA: Building Better Software with Archetype Patterns and UML By Jim Arlow, Ila Neustadt

Model

source: Enterprise Patterns and MDA: Building Better Software with Archetype Patterns and UML By Jim Arlow, Ila Neustadt

Details of Party

source: Enterprise Patterns and MDA: Building Better Software with Archetype Patterns and UML By Jim Arlow, Ila Neustadt

Person is a Party

source: Enterprise Patterns and MDA: Building Better Software with Archetype Patterns and UML By Jim Arlow, Ila Neustadt

Organization is a Party

source: Enterprise Patterns and MDA: Building Better Software with Archetype Patterns and UML By Jim Arlow, Ila Neustadt

Customer is a Party

source: Enterprise Patterns and MDA: Building Better Software with Archetype Patterns and UML By Jim Arlow, Ila Neustadt

Customer is a different story...

source: Enterprise Patterns and MDA: Building Better Software with Archetype Patterns and UML By Jim Arlow, Ila Neustadt

Behavior Driven Development● Agile software development technique● Encourages collaboration between

● developers, QA● non-technical or business participants

● BDD focuses on exposing internal logic (typically business rules) to review by stakeholders.

● Native language in combination with the ubiquitous language of DDD● describe the purpose and benefit of the code

Data Context Interaction● New programming paradigm

● needs dynamic language syntax (mixins, traits)● Trygve Reenskaug

● co-inventor of Object Oriented● inventor of MVC

● Mainstream OO languages● are not Object Oriented● they are rather Class Oriented

Use Case flow and global algorithm

Classes

Classes

Classes

Classes

Classes

Data● core● basically dumb● may contain basic

responsibility

Interactions● business

responsibility● operates on data

Context● Whole Use Case● or just few steps● adds meaning to

the data

Full working Objects● makes sense only in context● methods implies by current role

DDD summary● No rocket science● “Just” rational usage of OOA and OOD● Pragmatic approach to complexity of business

logic● Most important things:

● Ubiquitous Language● Strategic Design

● Building Block are not the most important thing:P

Code should mean somethingDan Bergh Johnsson

Sławomir Sobótka

Dziękuję za uwagę

więcej...

http://[email protected]

Photo credits● http://www.norcalblogs.com/commission/images/house-of-cards.jpg

● http://nirmukta.com/wp-content/uploads/2009/08/complexity.jpg

● http://www.basicbonsai.com/wp-content/uploads/2009/11/brazilian_rain_tree.jpg

● http://i659.photobucket.com/albums/uu312/mlee4elbow/prof_chaos02.jpg

● http://a.images.blip.tv/Unclephilms-puppetTest1168.jpg

● http://www.individual-i.org/images/logo-3sizes.jpg

● https://star-cosmos.com/starcomsos_blog/wp-content/uploads/2009/08/human-body.jpg

● http://media.photobucket.com/image/train%20wreck/wgman21/train_wreck.jpg

● http://englishrussia.com/images/mig_factory/1.jpg

● http://upload.wikimedia.org/wikipedia/commons/thumb/b/b7/2000_core-repository02_hg.jpg/600px-2000_core-repository02_hg.jpg

● http://www.alacera.com/images/model_city_3d.jpg

● http://www.faqs.org/photo-dict/photofiles/list/5558/7276chess_pawn.jpg

● http://www.shoemoney.com/images/nuke.jpg

● http://www.dzieci.legnica.pl/grafikacms/niejadek250.jpg

● http://fineartamerica.com/images-medium/conwy-castle-and-the-telford-suspension-bridge-north-wales-mal-bray.jpg

● http://fandomania.com/wp-content/uploads/2008/05/terminator.jpg

● http://www.directortom.com/storage/square%20peg.jpg?__SQUARESPACE_CACHEVERSION=1223602138853

● http://dontsqueezethejj.com/blog/wp-content/uploads/2008/07/macgyver.jpg

● http://www.wilsonsalmanac.com/images2/shakespeare9.jpg

● http://arnoldit.com/wordpress/wp-content/uploads/2008/10/mismatch.jpg

● http://images1.wikia.nocookie.net/matrix/images/thumb/3/32/Neo.jpg/300px-Neo.jpg

● http://i69.photobucket.com/albums/i71/nynja24me/guns/M-67handgrenade.jpg

● http://www.travelooce.com/pics/sunset_sailing.jpg