OO Design

48
OO DESIGN by Oleksii Fedorov

Transcript of OO Design

Page 1: OO Design

OO DESIGNby Oleksii Fedorov

Page 2: OO Design

OBJECT ORIENTED PROGRAMMING

Page 3: OO Design

Most notable features:

Encapsulation (data kept with behaviour and hidden fromclients)Inheritance (subclassing, inheriting all behaviour/data,even private/protected behaviour/data)Polymorphism (ability to substitute instances of one classwith instances of others)

Page 4: OO Design

HOW IMPORTANT THESE FEATURES ARE FOROO DESIGN?

Imagine, that given 100 points you want to distribute thembetween these 3 features, and each number will represent

an importance of corresponding feature.

Page 5: OO Design

Encapsulation Polymorphism Inheritance

80 40 -20

Warning: this is my personal opinion

Page 6: OO Design

80 + 40 - 20 = 100 :)

Page 7: OO Design

INHERITANCE INCREASES COUPLINGSubclass usually depends on some data or/and behaviour of

its superclass. Even worse: usually this is not publicbehaviour/data.

Page 8: OO Design

BUT HOW DOES ONE GO WITHOUTINHERITANCE?

Page 9: OO Design

COMPOSITION AND DELEGATION

Page 10: OO Design

COUPLING

Page 11: OO Design

WHY COUPLING IS BAD?

Page 12: OO Design

Imagine you need to change behaviour of class X.

You will have to change any other piece of code base, thatdirectly depends on this behaviour of class X.

More coupling you have, more changes will have to takeplace, and probably, in totally unrelated parts of codebase.

Page 13: OO Design

Exponentially increases time required for changeInvites bugs

Page 14: OO Design

DEPENDENCY

Page 15: OO Design

HOW DOES ONE DEAL WITH IT?

Page 16: OO Design

DEPENDENCY INVERSION AND DEPENDENCYINJECTION

Page 17: OO Design

class Answer  def rating    RatingCalculator.new.rating_for(comments, upvotes, downvotes)  endend

Page 18: OO Design

AND WHAT THE PROBLEM WITH THIS CODE?

Page 19: OO Design

DEPENDENCY!

Page 20: OO Design

class Answer  def initialize(rating_calculator)    @rating_calculator = rating_calculator  end

  def rating    @rating_calculator.rating_for(comments, upvotes, downvotes)  endend

Page 21: OO Design

NOW YOU CAN HAVE MULTIPLE RATINGCALCULATOR SERVICES AND A/B TEST THEM

EASILY

Page 22: OO Design

COUPLE TO ABSTRACT INTERFACES INSTEADOF REFERENCING FOREIGN

CLASS/MODULE/PACKAGE OF YOUR SYSTEM

Page 23: OO Design

TEST DRIVEN DEVELOPMENT

Page 24: OO Design

HOW IS IT RELATED TO OO DESIGN?

Page 25: OO Design

PROVIDES SHORT FEEDBACK LOOP ON YOURDESIGN

Page 26: OO Design

If you have troubles writing test - your design is wrongIf you don't like how your test look like - your design iswrongIf you have troubles making test green - your design iswrong

Page 27: OO Design

UNIT TESTS AND INTEGRATION TESTS

Page 28: OO Design

INTEGRATION TESTS ARE SCAM!Very slow => bad feedback loopExponential count of paths to test

Page 29: OO Design

UNIT TESTS JUST DOESN'T WORK. ARETHEY?

Page 30: OO Design

Testing in isolation = providing fake objects and/or mocksfor all your dependencies

Mocks and fake objects can make your unit test green, but infact the code is broken, because one of the dependencies

has changed its behaviour or even public interface

Page 31: OO Design

CUT YOUR SYSTEM AT VALUE BOUNDARIES!Instead of method call boundaries.

Page 32: OO Design

ACTOR MODEL

Page 33: OO Design

class RatingCalculator  def rating_for(comments, upvotes, downvotes)    # .. calculate rating somehow ..  endend

Page 34: OO Design

actor RatingCalculator  comments, upvotes, downvotes, outbox = inbox.fetch  # .. calculate rating somehow ..  outbox.send(rating)end

Page 35: OO Design

ALMOST ALWAYS HAS EXACTLY ONE SINGLERESPONSIBILITY

Since it receives message on inbox and doesn't really havemuch space to have multiple responsibilities (and methods)

Page 36: OO Design

EASY TO UNIT TEST WITHOUT FAKE OBJECTSAND MOCKS

Page 37: OO Design

# creating actor, but not starting itrating_actor = RatingCalculator.new

# dependency injection of rating actoranswer_actor = Answer.new(answer_id, rating_actor)answer_actor.start

render_actor = Render.new(answer_actor)render_actor.runexpect(rating_actor.inbox)  .to include([comments, upvotes, downvotes, outbox])

# fake response from rating actoroutbox.send(3.5)expect(render_actor).to render_rating(3.5)

Page 38: OO Design

WHEN THE CODE IS DONE?

Page 39: OO Design

It works!

Page 40: OO Design

It works!It is readable (future me will not curse me for writing thiscode)

Page 41: OO Design

It works!It is readable (future me will not curse me for writing thiscode)It has no duplicationAnd it is as short as possible (while maintaining all of theabove)

Page 42: OO Design

CODE COMMENTS

Page 43: OO Design

BASICALLY A CODE SMELL

Page 44: OO Design

If code needs comment:

It is not readableIt fails to communicate intent

Page 45: OO Design

TO SUM IT UP

Page 46: OO Design

Inheritance is good only in very rare casesCoupling and dependencies are not your friends, takethem under control with dependency inversion &injectionTDD as a shortest feedback cycle for your OO designWrite code in such way, that you would thank yourself forthat in the future

Page 47: OO Design

THAT IS NOT ALL THERE ABOUT OO DESIGNI recommend reading the book "Pragmatic Programmer:

From Journeyman to Master", it is very good one and has alot of references to other good resources

Page 48: OO Design

THANKSQ & A