OOD - Object orientated design

Post on 13-Apr-2017

30 views 1 download

Transcript of OOD - Object orientated design

OOD

We want to do our best work.

We want our work to have meaning

We want to have fun along the way

Two major themes being Designand Messages over objects

Design

Failures of OOD might look like failures of coding technique but they are actually failures

of perspective.

Source: Pablo Picasso - Buffalo Art

Design is not an assembly line where similarly trained workers construct identical widgets; it’s a

studio where like-minded artists sculpt custom applications. Design is thus an art, the art of arranging code.

How does Design affect us?

Perspective.

Unfortunately, something will change.

The customers didn’t know what they wanted.

They didn’t say what they meant.

You didn’t understand their needs.

You’ve learned how to do something better.

Even applications that are perfect in every way are not stable.

The application was a huge success, now everyone wants more.

Change is unavoidable. It is ubiquitous, omnipresent, and inevitable.

Source: http://more-sky.com/

Dependency

Object-oriented design is about managing dependencies.

1 class Gear 2 attr_reader :chainring, :cog, :rim, :tire 3 def initialize(chainring, cog, rim, tire) 4 @chainring = chainring 5 @cog = cog 6 @rim = rim 7 @tire = tire 8 end 9 10 def gear_inches 11 ratio * Wheel.new(rim, tire).diameter 12 end 13 # ... 14 end 15 16 Gear.new(52, 11, 26, 1.5).gear_inches

1 class Gear 2 attr_reader :chainring, :cog, :rim, :tire 3 def initialize(chainring, cog, rim, tire) 4 @chainring = chainring 5 @cog = cog 6 @rim = rim 7 @tire = tire 8 end 9 10 def gear_inches 11 ratio * Wheel.new(rim, tire).diameter 12 end 13 # ... 14 end 15 16 Gear.new(52, 11, 26, 1.5).gear_inches

1 class Gear 2 attr_reader :chainring, :cog, :rim, :tire 3 def initialize(chainring, cog, rim, tire) 4 @chainring = chainring 5 @cog = cog 6 @rim = rim 7 @tire = tire 8 end 9 10 def gear_inches 11 ratio * Wheel.new(rim, tire).diameter 12 end 13 # ... 14 end 15 16 Gear.new(52, 11, 26, 1.5).gear_inches

1 class Gear 2 attr_reader :chainring, :cog, :rim, :tire 3 def initialize(chainring, cog, rim, tire) 4 @chainring = chainring 5 @cog = cog 6 @rim = rim 7 @tire = tire 8 end 9 10 def gear_inches 11 ratio * Wheel.new(rim, tire).diameter 12 end 13 # ... 14 end 15 16 Gear.new(52, 11, 26, 1.5).gear_inches

1 class Gear 2 attr_reader :chainring, :cog, :rim, :tire 3 def initialize(chainring, cog, rim, tire) 4 @chainring = chainring 5 @cog = cog 6 @rim = rim 7 @tire = tire 8 end 9 10 def gear_inches 11 ratio * Wheel.new(rim, tire).diameter 12 end 13 # ... 14 end 15 16 Gear.new(52, 11, 26, 1.5).gear_inches

Your goal is to model your application, using classes, such that it does what it is supposed to do right now and is also easy to change later.

1 class Gear 2 attr_reader :chainring, :cog, :rim, :tire 3 def initialize(chainring, cog, rim, tire) 4 @chainring = chainring 5 @cog = cog 6 @rim = rim 7 @tire = tire 8 end 9 10 def gear_inches 11 ratio * Wheel.new(rim, tire).diameter 12 end 13 # ... 14 end 15 16 Gear.new(52, 11, 26, 1.5).gear_inches

Dependency injection

1 class Gear 2 attr_reader :chainring, :cog, :wheel 3 def initialize(chainring, cog, wheel) 4 @chainring = chainring 5 @cog = cog 6 @wheel = wheel 8 end 9 10 def gear_inches 11 ratio * wheel.diameter 12 end 13 # ... 14 end 15 16 Gear.new(52, 11, Wheel.new(26, 1.5)).gear_inches

Dependency aversion

1 class Gear 2 attr_reader :chainring, :cog, :wheel 3 def initialize(chainring, cog, rim, tire) 4 @chainring = chainring 5 @cog = cog 6 @wheel = Wheel.new(rim, tire) 8 end 9 10 def gear_inches 11 ratio * wheel.diameter 12 end 13 # ... 14 end 15 16 Gear.new(52, 11, 26, 1.5).gear_inches

Order Dependency

1 class Gear 2 attr_reader :chainring, :cog, :tire 3 def initialize(args) 4 @chainring = args[:chainring] 5 @cog = args[:cog] 6 @wheel = args[:wheel] 7 end 8 9 def gear_inches 10 ratio * wheel.diameter 11 end 12 # ... 13 end 14 15 Gear.new( 16 :cog => 11, 17 :chainring => 52, 18 :wheel => Wheel.new(26, 1.5)).gear_inches

Is your code too coupled to your tests?

Tools for design

Single Responsibility, Open-Closed, Liskov Substitution, Interface Segregation, and Dependency Inversion. DRY (Don’t Repeat Yourself) Law of Demeter (LoD)

Principles

The so-called Gang of Four (Gof) Skinny models - Service objects

Patterns

Design is more the art of preserving changeability than it is the act of achieving perfection

Virtual World

You will never know less than you know right now.

Keep your code TRUE

Transparent The consequences of change should be obvious in the code that is changing and in distant code that relies upon it Reasonable The cost of any change should be proportional to the benefits the change achieves Usable Existing code should be usable in new and unexpected contextsExemplary The code itself should encourage those who change it to perpetuate these qualities

Challenge - https://gitlab.com/LegendaryRob/WizSys

Example

Sandi Metz“Sandi is the author of Practical Object-

Oriented Design in Ruby, and most recently 99 bottles. She has thirty years of experience working on large object-

oriented applications. She’s spoken about programming, object-oriented design and refactoring at numerous conferences including Agile Alliance

Technical Conference, Craft Conf, Øredev, RailsConf, and RubyConf. She

believes in simple code and straightforward explanations, and is the proud recipient of a Ruby Hero award for her contribution to the Ruby community. She prefers working software, practical solutions and lengthy bicycle trips (not

necessarily in that order). Find out more about Sandi at sandimetz.com.

Why this book?

Design

What are design principlesWhat are design Patterns

When should I design?

How does one design ? OO vs FP

Single Responsibility What belongs to a class?

How do I organize my code?Why does SR matter?

Code IntrospectionHow to write change tolerant codeData vs Behavior

When to design and when to replicate?

Dependencies What is coupling? is it good or bad?

How to inject DependenciesHow to isolate dependencies

Seeing hidden dependencies

Which direction should we interact with them

Interfaces Public vs Private

Responsibilities of interfacesIntention

Context independenceMessages over objects

Developing trust

LoDWhat is this? why is it important

What happens if I break the law?How to avoid violations

Duck TypingUnderstanding the quacks

Trusting ducks by choosing them wiselyFinding hidden ducks

DocumentationSharing Code

Static vs Dynamic Typing

InheritanceWhere to use it?

Drawing up relationshipsWhat happens when you misapply inheritance

Creating abstract classesTemplate Method Pattern

Superclasses and Subclasses