80
Object Calisthenics 9 steps to better OO code

Object calisthenics (PyConPL 2016)

Embed Size (px)

Citation preview

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!