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

12 Tips for Writing Readable Code

12 Tips for Writing Readable Code

Presented at 2022 JavaOne with Ken Fogel

Jeanne Boyarsky

October 20, 2022
Tweet

More Decks by Jeanne Boyarsky

Other Decks in Programming

Transcript

  1. TWELVE TIPS FOR WRITING MORE READABLE JAVA CODE With Jeanne

    Boyarsky & Ken Fogel Slides available after the presentation at https://speakerdeck.com/boyarsky @jeanneboyarsky @omniprof
  2. Who are we Jeanne Boyarsky • Java Champion • Java

    Author • Developer in NYC • @jeanneboyarsky Ken Fogel §Java Champion §JCP Executive Committee Member §Dawson College Research Scholar in Residence §@omniprof @jeanneboyarsky @omniprof
  3. NAMING STUFF IN JAVA Classes, Interfaces, Records, Enums, Methods and

    Variables, oh my. @jeanneboyarsky @omniprof
  4. It’s a bird, it’s a plane, its § A noun

    § Variables, Enum, Interface, Class, Record § A verb § Methods § All capitals § Constants § Not containing a dollar sign $ § Not an abbreviation, except for maybe WTF § In camel case when a phrase @jeanneboyarsky @omniprof
  5. THERE IS NOTHING IN THE REAL WORLD NAMED X, Y,

    OR Z It’s programming and not algebra. @jeanneboyarsky @omniprof
  6. var f = "jeanne"; var l = "boyarsky"; var s

    = f + l; System.out.println(s.length()); @jeanneboyarsky @omniprof
  7. var firstName = "jeanne"; var lastName = "boyarsky"; var fullName

    = firstName + lastName; System.out.println(fullName.length()); @jeanneboyarsky @omniprof
  8. DON’T BE TOO CLEVER, THE PERSON WHO WILL REPLACE YOU

    ONCE YOU LEAVE MUST UNDERSTAND YOUR CODE. There is no award for code that works but which no one can figure out how. @jeanneboyarsky @omniprof
  9. private BigDecimal loanCalculationTooClever(BigDecimal presentValue, BigDecimal annualPercentageRate, BigDecimal numberOfPayments) throws ArithmeticException

    { return presentValue.multiply(annualPercentageRate.divide( new BigDecimal("12"), MathContext.DECIMAL64). divide(BigDecimal.ONE.subtract(BigDecimal.ONE. add(annualPercentageRate.divide(new BigDecimal("12"), MathContext.DECIMAL64)).pow(-numberOfPayments.intValue(), MathContext.DECIMAL64 )), MathContext.DECIMAL64)).setScale(2, RoundingMode.HALF_EVEN); } @jeanneboyarsky @omniprof n rate rate PV PMT - + - ´ = ) 1 ( 1 Clever, compact, and unintelligible
  10. private BigDecimal loanCalculationStepByStep(BigDecimal presentValue, BigDecimal annualPercentageRate, BigDecimal numberOfPayments) throws ArithmeticException

    { var ratePerPayment = annualPercentageRate.divide( new BigDecimal("12"), MathContext.DECIMAL64); var divisor = BigDecimal.ONE.add(ratePerPayment); divisor = divisor.pow(-numberOfPayments.intValueExact(), MathContext.DECIMAL64); divisor = BigDecimal.ONE.subtract(divisor); var result = ratePerPayment.divide(divisor, MathContext.DECIMAL64); result = presentValue.multiply(result); result = result.setScale(2, RoundingMode.HALF_EVEN); return result; } @jeanneboyarsky @omniprof Expressive and intelligible n rate rate PV PMT - + - ´ = ) 1 ( 1
  11. public int weird(int number) { var result=0; var random =

    new Random(); if (number % 2 == 0) { try { while (random.nextInt(3) % 2 != 0) result++; } catch (ArithmeticException e) { result = 0; } } else { result = 1; } return result; } @jeanneboyarsky @omniprof
  12. public int weird(int number) { var result=0; if (number %

    2 != 0) result = 1; else result = silly(result); return result; } @jeanneboyarsky @omniprof
  13. private int silly(int result) { var random = new Random();

    try { while (random.nextInt(3) % 2 != 0) { result++; } } catch (ArithmeticException e) { result = 0; } return result; } @jeanneboyarsky @omniprof
  14. DON’T ABUSE STATIC Do you have a good reason for

    making anything static? Probably not. @jeanneboyarsky @omniprof
  15. @jeanneboyarsky @omniprof public class BadPassLine { private static int Bankroll;

    private static int defaultBank; private static int bet; private static int win = 0; private static int lost = 0; private static int point; public static void main(String[] args){ . . . } public static int gamebegin() { . . . } public static void gamestart(){ . . . } public static int rollingDice(){ . . . } } After 3 Java courses, this is what a student submitted for a PassLine dice game as a warm-up assignment in their 4th Java course with me. Impress me, I said. This student depressed me.
  16. IF IT DON’T FIT THE SCREEN, THEN MAYBE YOUR METHOD

    IS TOO LONG If it doesn’t fit on a screen, then it's too long. No turning the screen to portrait mode or use 6- point text. @jeanneboyarsky @omniprof
  17. 142: int userId = request.getIntParameter("user_id"); 143: int loggedInUserId = SessionFacade.getUserSession().getUserId();

    144: context.put("loggedInUserId", loggedInUserId); 145: context.put("isCurrentUser", userId == loggedInUserId); ... 12: 383: if (canListAllCows() || 384: (canGrantCows() && (userId == loggedInUserId))) { 385: CowsDao dao = DataAccessDriver.newCowsDao(); 386: List<Cow> cows = dao.selectCowsByUser(userId); 387: prepCowsListPage(false, userId, cows); 388: } @jeanneboyarsky @omniprof
  18. THE MAGIC NUMBER FOR A METHOD IS 1, THE NUMBER

    OF TASKS THE METHOD CARRIES OUT You may have many responsibilities in your day-to-day life, but your methods should only have a Single Responsibility. @jeanneboyarsky @omniprof
  19. private static void playGame() { System.out.println(); int bet = 0;

    while (true) { System.out.println("\nYou have $" + currentCash); System.out.println("Insert a bet amount:"); if (reader.hasNextInt()) { bet = reader.nextInt(); if (!(checkIfInvalidBet(bet))) { break; } } else { System.out.println("You can only put whole numbers!"); } } Let’s play How Many Tasks Can You Find In This One Method?
  20. if (bet != 0) { boolean victory; int point =

    0; int total; while (true) { total = roll2Dice(); if (point == 0) { if (total == 7 || total == 11) { victory = true; break; } if (total == 2 || total == 3 || total == 12) { victory = false; break; } point = total; System.out.println("\nThe point is now " +point + "\n"); @jeanneboyarsky @omniprof
  21. } else { if (total == 7) { victory =

    false; break; } if (total == point) { victory = true; break; } } } if (victory) { currentCash += bet; System.out.println(“You have won this round! \n"); } else { currentCash -= bet; System.out.println("Sorry, you lost this round! \n"); } } } @jeanneboyarsky @omniprof
  22. THE STRING CLASS IS FULL OF POORLY AND BADLY NAMED

    METHODS. Use methods from a string whose name your boss could even understand. @jeanneboyarsky @omniprof
  23. if (email.contains("@")) { var startOfString = "^"; var anyChars =

    ".*"; var at = "@"; var regex = startOfString + anyChars + at; System.out.println( email.replaceFirst(regex, "")); } @jeanneboyarsky @omniprof
  24. ROW, ROW, ROW YOUR CODE, GENTLY DOWN THE STREAM Collections

    and for loops should be like water and oil, don’t mix them. @jeanneboyarsky @omniprof
  25. // Pre stream public OptionalInt max(List<Integer> list) { if (list.isEmpty())

    { return OptionalInt.empty(); } Collections.sort(list); int max = list.get(list.size()-1); return(OptionalInt.of(max)); } @jeanneboyarsky @omniprof // Post stream public OptionalInt maxStream(List<Integer> list) { return list.stream().mapToInt(x -> x).max(); }
  26. THE TIME HAS COME TO SAY GOODBYE TO CONCATENATION FOR

    LONG STRINGS. LONG LIVE TEXT BLOCKS! All rise JSON strings!. @jeanneboyarsky @omniprof
  27. public String getJson(String search) { String json = "{" +

    " \"query\": \"%s\"" + " \"start\": \"1\"," + " \"end\": \"10\"" + "}"; return String.format(json, search); } @jeanneboyarsky @omniprof
  28. public String getJson(String search) { Path path = Path.of( ""src/main/resources/query.json");

    String json = null; try { json = Files.readString(path); } catch (IOException e) { throw new UncheckedIOException(e); } return String.format(json, search); } @jeanneboyarsky @omniprof
  29. public String getJson(String search) { String json = """ {

    "query": "%s" "start": "1" "end": "10" }"""; return String.format(json, search); } @jeanneboyarsky @omniprof
  30. THE TRADITIONAL SWITCH IS FROM THE 1950S. TIME TO CODE

    LIKE ITS 2022 Switch expression, Switch statement, Switch pattern matching. It is time to finally say goodbye to fall thru in the absence of a break. @jeanneboyarsky @omniprof
  31. double value = 0; switch (point) { case NORTH: value

    = 12.12; break; case SOUTH: value = 14.14; break; case EAST: value = 16.16; break; case WEST: value = 18.18; break; } The 1950s just called and they want their switch back. @jeanneboyarsky @omniprof
  32. // switch statement switch (point) { case NORTH -> doNorth();

    case SOUTH -> doSouth(); case EAST -> { doEast(); doEastern(); } case WEST -> doWest(); default -> doLost(); }; // switch expression double value = switch (point) { case NORTH -> 12.12; case SOUTH -> 14.14; case EAST -> 16.16; case WEST -> 18.18; default -> 0.0; }; Now’s the time to say goodbye to break. @jeanneboyarsky @omniprof
  33. Object value = 4; switch (value) { case null ->

    System.out.println("null"); case String s -> System.out.println("String"); case Integer i when i > 1 && i < 6 -> System.out.println("Integer"); default -> System.out.println("Something else"); } The future is the Pattern Matching Switch! @jeanneboyarsky @omniprof
  34. public class Book { private String title; private String numPages;

    public Book(String title, String numPages) { super(); this.title = title; this.numPages = numPages; } public String getTitle() { return title; } public String getNumPages() { return numPages; } @jeanneboyarsky @omniprof
  35. public record Book(String title, String numPages) { } Book book

    = new Book( "Breaking and entering", 289); System.out.println(book.title()); System.out.println(book.toString()); @jeanneboyarsky @omniprof
  36. Automatically get • final record • private final instance variables

    • public accessors • constructor taking both fields • equals • hashCode • toString @jeanneboyarsky @omniprof
  37. FOR MORE This deck – on Speakerdeck shortly New Java

    features - https://speakerdeck.com/boyarsky/2022-java17-refactoring New Java features - https://speakerdeck.com/boyarsky/2022-devnexus-java12-17 @jeanneboyarsky @omniprof