Top Banner
Object Calisthenics 9 steps to better OO code
80

Object calisthenics (PyConPL 2016)

Jan 15, 2017

Download

Software

Paweł Lewtak
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Object calisthenics (PyConPL 2016)

ObjectCalisthenics9stepstobetterOOcode

Page 2: Object calisthenics (PyConPL 2016)

Agenda

Learnhowtomakeourcodemore:

readablereusabletestablemaintainable

Page 3: Object calisthenics (PyConPL 2016)

Raiseyouhandifyouknowoneofthefollowing:

DRYKISSSOLIDYAGNIZenofPython

Page 4: Object calisthenics (PyConPL 2016)

Calisthenics

Page 5: Object calisthenics (PyConPL 2016)

Cal•is•then•ics-/ˌkaləsˈTHeniks/

Page 6: Object calisthenics (PyConPL 2016)

"Calisthenicsareexercisesconsistingofavarietyofgrossmotormovements;often

rhythmicalandgenerallywithoutequipmentorapparatus."

Wikipedia

Page 8: Object calisthenics (PyConPL 2016)

WrittenforJava

Page 9: Object calisthenics (PyConPL 2016)

Whybother?

Page 10: Object calisthenics (PyConPL 2016)

Codeisreadmorethanit'swritten

Page 11: Object calisthenics (PyConPL 2016)

Rule#1

Onlyonelevelofindentationpermethod

Page 12: Object calisthenics (PyConPL 2016)

classBoard(object):def__init__(self,data):#Level0self.buf=""foriinrange(10):#Level1forjinrange(10):#Level2self.buf+=data[i][j]

Page 13: Object calisthenics (PyConPL 2016)

classBoard(object):def__init__(self,data):self.buf=""self.collect_rows(data)defcollect_rows(self,data):foriinrange(10):self.collect_row(data[i])defcollect_row(self,row):forjinrange(10):self.buf+=row[j]

Page 14: Object calisthenics (PyConPL 2016)

Benefits

SingleresponsibilityBetternamingShortermethodsReusablemethods

Page 15: Object calisthenics (PyConPL 2016)

Rule#2

Donotuseelsekeyword

Page 16: Object calisthenics (PyConPL 2016)

ifoptions.getCategories()isNone:...eliflen(options.getCategories())==1:...elifSPECIAL_CATEGORYinoptions.getCategories():...elifoptions.getCategories()andoptions.getQuery():...elifoptions.getContentType():...

Page 17: Object calisthenics (PyConPL 2016)

deflogin(self,request):ifrequest.user.is_authenticated():returnredirect("homepage")else:messages.add_message(request,messages.INFO,'Badcredentials')returnredirect("login")

Page 18: Object calisthenics (PyConPL 2016)

deflogin(self,request):ifrequest.user.is_authenticated():returnredirect("homepage")

messages.add_message(request,messages.INFO,'Badcredentials')returnredirect("login")

Page 19: Object calisthenics (PyConPL 2016)
Page 20: Object calisthenics (PyConPL 2016)

Extractcode

Page 21: Object calisthenics (PyConPL 2016)

Defaultvalue

Page 22: Object calisthenics (PyConPL 2016)

Polymorphism

Page 23: Object calisthenics (PyConPL 2016)

Strategypattern

Page 24: Object calisthenics (PyConPL 2016)

Statepattern

Page 25: Object calisthenics (PyConPL 2016)

BenefitsAvoidscodeduplicationLowercomplexityReadability

Page 26: Object calisthenics (PyConPL 2016)

Rule#3

Wrapprimitivetypesifithasbehaviour

Page 27: Object calisthenics (PyConPL 2016)

ValueObjectinDDD

Page 28: Object calisthenics (PyConPL 2016)

classValidator(object):defcheck_date(self,year,month,day):pass

#10thofDecemberor12thofOctober?validator=Validator()validator.check_date(2016,10,12)

Page 29: Object calisthenics (PyConPL 2016)

classValidator(object):defcheck_date(year:Year,month:Month,day:Day)->bool:pass

#Functioncallleavesnodoubt.validator.check_date(Year(2016),Month(10),Day(12))

Page 30: Object calisthenics (PyConPL 2016)

BenefitsEncapsulationTypehintingAttractssimilarbehaviour

Page 31: Object calisthenics (PyConPL 2016)

Rule#4

Onlyonedotperline

Page 32: Object calisthenics (PyConPL 2016)

OK:Fluentinterface

Page 33: Object calisthenics (PyConPL 2016)

classPoem(object):def__init__(self,content):self.content=content

defindent(self,spaces):self.content=""*spaces+self.contentreturnself

defsuffix(self,content):self.content=self.content+"-"+contentreturnself

Poem("RoadNotTravelled").indent(4)\.suffix("RobertFrost").content

Page 34: Object calisthenics (PyConPL 2016)

NotOK:getterchain

Page 35: Object calisthenics (PyConPL 2016)

classCartService(object):defget_token(self):token=self.get_service('auth')\.auth_user('user','password')\.get_result()\.get_token()

returntoken

#1.WhatifNoneisreturnedinsteadofobject?#2.Howaboutexceptionshandling?

Page 36: Object calisthenics (PyConPL 2016)

classLocation(object):def__init__(self):self.current=Piece()

classPiece(object):def__init__(self):self.representation=""

classBoard(object):defboard_representation(self,board):buf=''forfieldinboard:buf+=field.current.representation

returnbuf

Page 37: Object calisthenics (PyConPL 2016)

classLocation(object):def__init__(self):self.current=Piece()defadd_to(self,buffer):returnself.current.add_to(buffer)

classPiece(object):def__init__(self):self.representation=""defadd_to(self,buffer):returnbuffer+self.representation

classBoard(object):defboard_representation(self,board):buf=''forfieldinboard:buf=field.add_to(buf)

returnbuf

Page 38: Object calisthenics (PyConPL 2016)

BenefitsEncapsulationDemeter'slawOpen/ClosedPrinciple

Page 39: Object calisthenics (PyConPL 2016)

Rule#5

Donotabbreviate

Page 40: Object calisthenics (PyConPL 2016)

Whyabbreviate?

Page 41: Object calisthenics (PyConPL 2016)

Toomanyresponsibilities

Page 42: Object calisthenics (PyConPL 2016)

Nametoolong?

Page 43: Object calisthenics (PyConPL 2016)

Split&extract

Page 44: Object calisthenics (PyConPL 2016)

Duplicatedcode?

Page 45: Object calisthenics (PyConPL 2016)

Refactor!

Page 46: Object calisthenics (PyConPL 2016)

BenefitsClearintentionsIndicateunderlyingproblems

Page 47: Object calisthenics (PyConPL 2016)

Rule#6

Keepyourclassessmall

Page 48: Object calisthenics (PyConPL 2016)

Whatissmallclass?15-20linespermethod50linesperclass10classespermodule

Page 49: Object calisthenics (PyConPL 2016)

BenefitsSingleResponsibilitySmallermodules

Page 50: Object calisthenics (PyConPL 2016)

Rule#7

Nomorethan2instancevariableperclass

Page 51: Object calisthenics (PyConPL 2016)

Classshouldhandlesinglevariablestate

Page 52: Object calisthenics (PyConPL 2016)

Insomecasesitmightbetwovariables

Page 53: Object calisthenics (PyConPL 2016)
Page 54: Object calisthenics (PyConPL 2016)

classCartService(object):def__init__(self):self.logger=Logger()self.cart=CartCollection()self.translationService=TranslationService()self.authService=AuthService()self.userService=UserService()

Page 55: Object calisthenics (PyConPL 2016)

BenefitsHighcohesionEncapsulationFewerdependencies

Page 56: Object calisthenics (PyConPL 2016)

Rule#8

Firstclasscollections

Page 57: Object calisthenics (PyConPL 2016)

collectionsmodule

Page 58: Object calisthenics (PyConPL 2016)

BenefitsSingleResponsibility

Page 59: Object calisthenics (PyConPL 2016)

Rule#9

Donotusesetters/getters

Page 60: Object calisthenics (PyConPL 2016)

Accessorsarefine

Page 61: Object calisthenics (PyConPL 2016)

Don'tmakedecisionsoutsideofclass

Page 62: Object calisthenics (PyConPL 2016)

Letclassdoit'sjob

Page 63: Object calisthenics (PyConPL 2016)

Tell,don'task

Page 64: Object calisthenics (PyConPL 2016)

classGame(object):def__init__(self):self.score=0

defset_score(self,score):self.score=score

defget_score(self):returnself.score

#UsageENEMY_DESTROYED_SCORE=10game=Game()game.set_score(game.get_score()+ENEMY_DESTROYED_SCORE)

Page 65: Object calisthenics (PyConPL 2016)

classGame(object):def__init__(self):self.score=0defadd_score(self,score):self.score+=score

#UsageENEMY_DESTROYED_SCORE=10game=Game()game.add_score(ENEMY_DESTROYED_SCORE)

Page 66: Object calisthenics (PyConPL 2016)

BenefitsOpen/ClosedPrinciple

Page 67: Object calisthenics (PyConPL 2016)

Catch'emall!

Page 68: Object calisthenics (PyConPL 2016)

Catch'emall!1. Onlyonelevelofindentationpermethod,2. Donotuseelsekeyword,3. Wrapprimitivetypesifithasbehavior,4. Onlyonedotperline,5. Don’tabbreviate,6. Keepyourentitiessmall,7. Nomorethantwoinstancevariableperclass,8. FirstClassCollections,9. Donotuseaccessors

Page 69: Object calisthenics (PyConPL 2016)

Catch'emall!1. Onlyonelevelofindentationpermethod,2. Donotuseelsekeyword,3. Wrapprimitivetypesifithasbehavior,4. Onlyonedotperline,5. Don’tabbreviate,6. Keepyourentitiessmall,7. Nomorethantwoinstancevariableperclass,8. FirstClassCollections,9. Donotuseaccessors10. ???11. PROFIT!

Page 70: Object calisthenics (PyConPL 2016)

Homework

Page 71: Object calisthenics (PyConPL 2016)

Createnewprojectupto1000lineslong

Page 72: Object calisthenics (PyConPL 2016)

Applypresentedrulesasstrictlyaspossible

Page 73: Object calisthenics (PyConPL 2016)

Drawyourownconculsions

Page 74: Object calisthenics (PyConPL 2016)

Customizetheserules

Page 75: Object calisthenics (PyConPL 2016)

Finalthoughts

Page 76: Object calisthenics (PyConPL 2016)

Thesearenotbestpractices

Page 77: Object calisthenics (PyConPL 2016)

Thesearejustguidelines

Page 78: Object calisthenics (PyConPL 2016)

Usewithcaution!

Page 79: Object calisthenics (PyConPL 2016)

Questions?

Page 80: Object calisthenics (PyConPL 2016)

Thankyou!