Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Clean Code

Nico Krijnen
September 20, 2022

Clean Code

Clean Code is the foundation of healthy software and a happy development teams. Yet few developers have had the opportunity to properly learn this.

Nico Krijnen

September 20, 2022
Tweet

More Decks by Nico Krijnen

Other Decks in Programming

Transcript

  1. Code = Communication “Any fool can write code that a

    computer can understand. 
 Good programmers write code that humans can understand.” —Refactoring, Martin Fowler with Kent Beck, 1996
  2. SDO Performance Organizational performance Industry (control) Enterprise (control) CULTURE OF

    PSYCHOLOGICAL SAFETY Burnout Construct Control variable Second-order construct Common goal for team or organization Predictive relationship Mixed results Negative predictive relationship Continuous delivery Loosely coupled architecture Monitoring Deployment automation HEAVYWEIGHT CHANGE PROCESS CODE MAINTAINABILITY Trunk-based development CLEAR CHANGE PROCESS Continuous integration Automated testing Cloud - DISASTER RECOVERY TESTING - - - Availability Software delivery performance
  3. SDO Performance Burnout Continuous delivery Loosely coupled architecture Monitoring Deployment

    automation CODE MAINTAINABILITY Trunk-based development Continuous integration Automated testing Cloud DISASTER RECOVERY TESTING - - Availability Software delivery performance
  4. 10x more time reading “Indeed, the ratio of time spent

    reading versus writing is well over 10 to 1. We are constantly reading old code as part of the effort to write new code. ... [Therefore,] making it easy to read makes it easier to write.” ― Robert C. Martin, Clean Code: A Handbook of Agile Software Craftsmanship
  5. Code that is easy to change • Easy to read

    and understand intention • Version control
  6. Code that is easy to change • Easy to read

    and understand intention • Version control • Automated tests
  7. Code that is easy to change • Easy to read

    and understand intention • Version control • Automated tests Safety net }
  8. Clean Code • Polite • Self-explaining • Code without surprises

    Robert C. Martin – Uncle Bob Daniel Terhorst-North
  9. SOLID • Single-responsibility principle • Open–closed principle • Liskov substitution

    principle • Interface segregation principle • Dependency inversion principle Robert C. Martin – Uncle Bob
  10. CUPID – for joyful coding • Composable • Unix philosophy

    • Predictable • Idiomatic • Domain-based https://dannorth.net/2022/02/10/cupid-for-joyful-coding/ Daniel Terhorst-North
  11. CUPID – Composable Plays well with others • Small surface

    area • Intention-revealing • Minimal dependencies Daniel Terhorst-North
  12. CUPID – Unix philosophy Does one thing well • A

    simple, consistent model • Single purpose vs. single responsibility Daniel Terhorst-North
  13. CUPID – Predictable Does what you expect • Behaves as

    expected • Deterministic • Observable Daniel Terhorst-North
  14. CUPID – Domain-based The solution domain models the problem domain

    
 in language and structure • Domain-based language • Domain-based structure • Domain-based boundaries Daniel Terhorst-North
  15. CUPID – for joyful coding • Composable • Unix philosophy

    • Predictable • Idiomatic • Domain-based https://dannorth.net/2022/02/10/cupid-for-joyful-coding/ Daniel Terhorst-North
  16. Absolutely gorgeous Code is not done until it: 1. Works

    2. Communicates 3. No duplicates 4. Fewest methods and classes Fred George Kent Beck
  17. Test Driven Development • TDD helps code design • Intention

    = captured and re-enforced by tests • Tests make code safer and easier to change Kent Beck
  18. Domain-Driven Design Keep systems as simple as possible 
 to

    solve real problems for your domain. Eric Evans
  19. What if you have no tests? "There is only one

    way to eat an elephant: a bite at a time." understandlegacycode.com “Legacy Code is code without tests” Michael Feathers: Working Effectively with Legacy Code
  20. void printOwing() { printBanner(); // Print details. System.out.println("name: " +

    name); System.out.println("amount: " + getOutstanding()); } void printOwing() { printBanner(); printDetails(getOutstanding()); } void printDetails(double outstanding) { System.out.println("name: " + name); System.out.println("amount: " + outstanding); } vs
  21. var d; // elapsed time in days var elapsedTimeInDays; var

    daysSinceCreation; var daysSinceModification; vs
  22. vs if (age >= 18) { ... } else {

    ... } boolean isOldEnoughToBuyAlcohol = age >= 18; if (isOldEnoughToBuyAlcohol) { ... } else { ... } if (isOldEnoughToBuyAlcohol(age)) { ... } else { ... } public boolean isOldEnoughToBuyAlcohol(int age) { return age >= 18; } vs
  23. public boolean checkPasswordStrength(String password) { boolean isNotBlank = password !=

    null && !password.isBlank(); if (isNotBlank) { boolean hasSpecialChar = password.chars().anyMatch(Character::isLetterOrDigit); if (hasSpecialChar) { boolean longEnough = password.length() >= 10; if (longEnough) { return true; } else { throw new IllegalArgumentException("Must be at least 10 characters"); } } else { throw new IllegalArgumentException("Must contain at least one special character"); } } else { throw new IllegalArgumentException("Password must not be blank"); } } public void checkPasswordStrength(String password) { if (password == null || password.isBlank()) throw new IllegalArgumentException("Password must not be blank"); if (password.chars().noneMatch(Character::isLetterOrDigit)) throw new IllegalArgumentException("Must contain at least one special character"); if (password.length() < 10) throw new IllegalArgumentException("Must be at least 10 characters"); } vs
  24. public void checkPasswordStrength(String password) { checkNotBlank(password); checkHasSpecialCharacter(password); checkHasMinimumLength(password); } private

    void checkNotBlank(String password) { if (password == null || password.isBlank()) throw new IllegalArgumentException("Password must not be blank"); } private void checkHasSpecialCharacter(String password) { if (password.chars().noneMatch(Character::isLetterOrDigit)) throw new IllegalArgumentException("Must contain at least one special character"); } private void checkHasMinimumLength(String password) { if (password.length() < 10) throw new IllegalArgumentException("Must be at least 10 characters"); } public void checkPasswordStrength(String password) { if (password == null || password.isBlank()) throw new IllegalArgumentException("Password must not be blank"); if (password.chars().noneMatch(Character::isLetterOrDigit)) { throw new IllegalArgumentException("Must contain at least one special character"); } if (password.length() < 10) { throw new IllegalArgumentException("Must be at least 10 characters"); } } vs
  25. class Password { private final String password; public Password(String password)

    { this.password = password; checkNotBlank(); checkHasSpecialCharacter(); checkHasMinimumLength(); } private void checkNotBlank() { if (password == null || password.isBlank()) throw new IllegalArgumentException("Password must not be blank"); } private void checkHasSpecialCharacter() { if (password.chars().noneMatch(Character::isLetterOrDigit)) throw new IllegalArgumentException("Must contain at least one special character"); } private void checkHasMinimumLength() { if (password.length() < 10) throw new IllegalArgumentException("Must be at least 10 characters"); } ... }
  26. 2000 classes 25 lines per class 1 to 3 lines

    per method <2 cyclomatic complexity vs 100 classes 500 lines per class 5 - 80+ cyclomatic complexity
  27. Business / Time pressure? • The need to go fast

    is real! • 'Slower but steady' requires discipline.
  28. Lack of support? • How do you build understanding from

    business stakeholders • Hard to explain the need for refactoring. [don't] • Easy to explain the need for quality. [do] • You will fall when you run too fast. You may make the finish, but you won't be able to run the next race.
  29. # developers doubles every 5 years At any point in

    time, 
 50% of developers 
 have less than 5 years experience
  30. Convince your business 16 Accelerate: State of DevOps 2019 |

    How Do We C SOFTWARE DEVELOPMENT SOFTWARE DEPLOYMENT SERVICE OPERAT Lead Time Change Fail Availability Deployment Frequency Time to Restore FOUR KEY METRICS The first four metrics that capture the effectiveness of the development and delivery process can be summarized in terms of throughput and stability. We measure the throughput of the so ware delivery process using lead time of code changes from check-in to release along with deployment fr Stability is measured using time to r the time it takes from detecting a us impacting incident to having it rem and change fail rate, a measure of t of the release process. PERFORMANCE METRICS # of Tests
  31. Master the fundamentals Learn Framework / Library Use Learn Cloud

    landscape Use Learn Clean code Use Learn Use Switch programming language Switch programming language
  32. Learn & Practice = Experience • TDD / BDD •

    Refactoring • Absolutely gorgeous • Version control • DDD
  33. Helpful tooling • IDE / IntelliJ (hints + safe refactoring)

    • SonarLint / SonarQube • ArchUnit • Checkstyle • PMD, FindBugs, SpotBugs
  34. Helpful tooling • IDE / IntelliJ (hints + safe refactoring)

    • SonarLint / SonarQube • ArchUnit • Checkstyle • PMD, FindBugs, SpotBugs 😀 🙅
  35. Learning angles • Read books, watch talks • Follow training

    • Form group, do katas • Practice on side projects https://tinyurl.com/luminis-clean-code
  36. Clean Code is written over time • First focus on

    making it work • Spend time to make it communicate • Your understanding of a codebase will grow • Any time you see or touch code, make it fit your latest insights
  37. Clean as-you-code • Refactor in your task cycle • Boy/girl

    scout rule 
 "Always leave the campground cleaner than you found it." • Code rub