Successfully reported this slideshow.
Your SlideShare is downloading. ×

Jaap Groeneveld - Software Engineering Principles

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Loading in …3
×

Check these out next

1 of 32 Ad

More Related Content

Similar to Jaap Groeneveld - Software Engineering Principles (20)

Recently uploaded (20)

Advertisement

Jaap Groeneveld - Software Engineering Principles

  1. 1. SoftwareEngineeringPrinciples Softwareengineeringiswhathappenstoprogrammingwhenyouaddtimeand otherprogrammers. JaapGroeneveld-jGroeneveld.de
  2. 2. SoftwareEngineeringdealswiththe challengesof Communicationbetweenpeople Communicationovertime Changingrequirements Tamingcomplexity Cleancodeismoreabouthumansthanits abouttech. 2
  3. 3. Whyinvestincleancode? Minimizestimespendonreadingandunderstanding Easiertogrowinthefuture Lesshuntingforbugs Easieronboarding. =>MessycodeisTechnicaldebt.Youwillpayforitdowntheroad. Messycodehastheuncannyabilitytoslowdownanydeveloperandmakehiswork muchharder 3
  4. 4. 4
  5. 5. BadCodesmells Rigidity.Thesoftwareisdifficulttochange.Asmallchangecausesacascadeof subsequentchanges. Fragility.Thesoftwarebreaksinmanyplacesduetoasinglechange. Immobility.Youcannotreusepartsofthecodeinotherprojectsbecauseofinvolved risksandhigheffort. Opacity.Thecodeishardtounderstand. NeedlessComplexity. NeedlessRepetition. 5
  6. 6. 6
  7. 7. Principles Keepitsimple,stupid(KISS) Youarenʼtgonnaneedit(YAGNI)&PrematureOptimization Don'trepeatyourself(DRY),singlesourceoftruth. Don'tconfusesyntacticandsemanticdry-ness Clearisbetterthanclever. "Short"doesnotmeaneasytoreadandunderstand. Avoid"magic"(unobviousbehavior). Practiceconsistency. Keepthetestsclean. Ifyouletthetestsrot,thenyourcodewillrottoo. Prepareforchange AlwaysaskhowwillthiscodebehaveifXchanges(butkeepYAGNIinmind) 7
  8. 8. CleanCode-Namingguidelines Namesareforhumans Choosedescriptiveandunambiguousnames. Makemeaningfuldistinction. Usepronounceablenames. Usesearchablenames. Replacemagicnumberswithnamedconstants. Avoidencodings.Don'tappendprefixesortypeinformation. 8
  9. 9. CleanCode-Namingguidelines Example d := 12 // elapsed time in days // vs elapsedTimeInDays := 12 9
  10. 10. CleanCode-Explanatoryvariables func doSomething() { defer StartTimer()() // ... } // vs func doSomething() { stopTimer := StartTimer() defer stopTimer() // ... } Yesitsonelinemore... 10
  11. 11. CleanCode-Onewordperconcept Havingaclearterminologyiskeytonotgetconfused. Itsmoreimportanttobeconsistentthentobeperfect. Examples? 11
  12. 12. CleanCode-Functionguidelines Small. Doone"thing".(SRP-SingleResponsibilityPrinciple) Usedescriptivenames. Havenosideeffectsifpossible. Preferfewerarguments. Don'tuseflagarguments.Splitmethodintoseveralindependentmethodsthatcanbe calledfromtheclientwithouttheflag. 12
  13. 13. CleanCode-Commentingguidelines Onlycommentthewhyandonlyifnotobvious Alwaystrytoexplainyourselfincode. Useasexplanationofintent. Useasclarificationofcode. Useaswarningofconsequences. Don'tcommentoutcode.Justremove. 13
  14. 14. StepdownRule Codeshouldbereadfromtoptobottomlikeanarticle. Wewanttoreaditasasetof"paragraphs"eachdescribingthecurrentlevelofabstraction andreferencingdown. Placefunctionsinthedownwarddirection. Declarevariablesclosetotheirusage. Keeplinesshort. Usewhitespacetoassociaterelatedthingsanddisassociateweaklyrelated. SeealsoCohesion... 14
  15. 15. Stepdown-Example package api func CreatePost(w http.ResponseWriter, r *http.Request) { post, err := getPostFromRequest(r) if err != nil {...} err = validatePost(post) if err != nil { ... } err = savePost(post) if err != nil { ... } http.WriteHeader(201) } func getPostFromRequest(r *http.Request) (Post, error) { ... } func validatePost(post Post) error { ... } func savePost(post Post) error { ... } 15
  16. 16. Lineofsight Alignthehappypathtotheleft;youshould quicklybeabletoscandownonecolumntosee theexpectedexecutionflow see src/lineofsight.go https://medium.com/@matryer/line-of-sight-in-code-186dd7cdea88 16
  17. 17. Lineofsight Donʼthidehappypathlogicinsideanestofindentedbraces Exitearlyfromyourfunction Avoidelsereturns;considerflippingtheifstatement Putthehappyreturnstatementastheverylastline Extractfunctionsandmethodstokeepbodiessmallandreadable Ifyouneedbigindentedbodies,considergivingthemtheirownfunction https://medium.com/@matryer/line-of-sight-in-code-186dd7cdea88 17
  18. 18. CleanCode-Dedicatedvaluetypesoverprimitivetype. func getUserData(userID string) {} // vs type UserID string func getUserData(userID UserID) {} Impossibleto"accidentally"assignsomethingelse EasytofindwhereUserIDsareused(searchabilitythroughstaticanalysis) Preventspositionalproblemsinfunctions Allowsaddingfunctionstothetype see typed_primitives.go 18
  19. 19. CleanCode-Avoidimplicitdependency type Processor struct { SomeData []string } func (p *Processor) Init() { p.SomeData = []string{"foo", "bar"} } func (p *Processor) Step() { element := p.SomeData[0] // do something with element } Youhavetoknowthatyouhavetocall Init beforecalling Step ,otherwisetheprogram willcrash. 19
  20. 20. CleanCode-Avoidimplicitdependency func NewProcessor(someData []string) *Processor { return &Processor{ SomeData: someData, } } type Processor struct { SomeData []string } func (p *Processor) Step() { element := p.SomeData[0] // do something with element } See http.Request vs http.NewRequest 20
  21. 21. CleanCode-Avoidimplicitdependency Anotherexample func GetFoo(w http.ResponseWriter, r *http.Request) { dataStore := r.Context().Value("FooDataStore").(FooDataStore) all := dataStore.All() _ = json.NewEncoder(w).Encode(all) } func main() { err := http.ListenAndServe(":8080", http.HandlerFunc(GetFoo)) if err != nil { log.Fatal(err) } } panic:interfaceisnil 21
  22. 22. CleanCode-Avoidimplicitdependency Basicallyifyouhaveto"know"somethingthatmightbeanimplicitdependency func GetFoo(dataStore FooDataStore) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { all := dataStore.All() _ = json.NewEncoder(w).Encode(all) }) } func main() { dataStore = NewFooDataStore() err := http.ListenAndServe(":8080", GetFoo(dataStore)) if err != nil { log.Fatal(err) } } Weenforcecorrectusage 22
  23. 23. SOLIDPrinciples RobertC.Martin SingleResponsibilityPrinciple Open-ClosedPrinciple LiskovSubstitutionPrinciple InterfaceSegregationPrinciple DependencyInversionPrinciple 23
  24. 24. SRP/Separationofconcerns Abstraction,increasemodularity Lessneedtoknow/workonmultiplepartsofthecode(cognitiveload) Easiertochangeimplementations Easiertoisolatebugs Seealsolayerarchitecture,coupling 24
  25. 25. CouplingvsCohesion 25
  26. 26. CouplingvsCohesion Couplingreferstotheinterdependenciesbetweenmodules,whilecohesiondescribes howrelatedthefunctionswithinasinglemoduleare Highcoupling,lowcohesion=> Lowcoupling,highcohesion=> 26
  27. 27. 27
  28. 28. Highcohesion SeeStepdownRule Declarevariablesclosetotheirusage. Dependentfunctionsshouldbeclose. Similarfunctionsshouldbeclose(samefileorsamepackage). SRPishelpful 28
  29. 29. Lowcoupling DependencyinversionPrinciple High-levelmodulesshouldnotdependonlow-levelmodules.Bothshoulddepend onabstractions(e.g.interfaces). InterfaceSegregationPrinciple Thebiggertheinterface,theweakertheabstraction 29
  30. 30. DependencyinjectioninGo Implicitinterfaces DuckTyping Avoidcyclicdependencies 30
  31. 31. DependencyinjectioninGo package cli type DataStore interface { GetData() model.Data } func Run(dataStore DataStore) {} package persistence type FileDataStore struct {} func (s *FileDataStore) GetData() model.Data package main func main() { dataStore := &persistence.FileDataStore{} cli.Run(dataStore) } 31
  32. 32. Literature Lessonslearntfrom“TheCleanCode” RottingdesignBINGO! SixShadesofCoupling TheforgottenrealmofCohesion 32

×