Xin's Studio.

Clean Code

Word count: 1.6kReading time: 8 min
2023/08/30

Personal Views / Basic Principles

  • [IMO] 编程是一件偏主观的事 is very subjective

    • 比起数学公式它更像是论文 或者 有些人可以写成散文
    • Engineering rather than Science
    • 如果让计算机自己学习,那我们的工作就更像是艺术家 Deep Learning is often considered more of an art than a science because it requires a lot of experimentation and trial-and-error to achieve optimal results.
  • 简单暴力 KISS (Keep it simple, stupid)

    • [IMO]Clarity First,Optimization second. 能让人看懂是最优先, 性能再好都是其次。

    • [IMO] 尽量别用显式的去用Java的多线程,很难不出错。很难debug

      • 为啥要用, 异步 & 性能(利用多核)- 用框架去解决。netty akka erlang exilir
      • 如果你一定要用, 1.把你写的并行代码和其他代码隔离开,单独弄个module。 2 使用ExecutorService。
        ExecutorService abstracts away many of the complexities associated with the lower-level abstractions like raw Thread
    • 任何人都能写出workable的代码,好程序员写出来的是人类能懂的 “Any fool can write code that a computer can understand. Good programmers write code that humans can understand.” — Martin Fowler**

    • 著名的雷神之锤代码 Q_rsqrt https://github.com/id-Software/Quake-III-Arena/blob/master/code/game/q_math.c

    • one of our recent candidate’s code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static int[] transform(int [] array){
int leftIndex = 0;
int rightIndex = array.length -1; // array can be null?

while(leftIndex < rightIndex){

while(array[leftIndex] % 2 == 0 && leftIndex < rightIndex){
leftIndex++;
}
while(array[rightIndex] % 2 != 0 && leftIndex < rightIndex){
rightIndex--;
}

int temp =array[leftIndex];
array[leftIndex] = array[rightIndex];
array[rightIndex] = temp;
}
}

we can do better than this?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

/**
* Transforms the given array by moving all odd numbers to the left side and even numbers to the right side.
*
* @param array The input array to be transformed.
* @return The transformed array.
* @throws IllegalArgumentException If the input array is null.
*/
public static int[] transform(int[] array) {
validateInputArray(array);

int leftIndex = 0;
int rightIndex = array.length - 1;

while (leftIndex < rightIndex) {
leftIndex = findNextOddIndex(array, leftIndex, rightIndex);
rightIndex = findNextEvenIndex(array, rightIndex, leftIndex);
swapElements(array, leftIndex, rightIndex);
}

return array;
}

/**
* Validates the input array to ensure it is not null.
*
* @param array The input array to be validated.
* @throws IllegalArgumentException If the input array is null.
*/
private static void validateInputArray(int[] array) {
if (array == null) {
throw new IllegalArgumentException("Input array cannot be null.");
}
}

/**
* Finds the next odd index in the array starting from the given startIndex.
*
* @param array The input array to search for the next odd index.
* @param startIndex The starting index for searching.
* @param endIndex The ending index for searching.
* @return The next odd index.
*/
private static int findNextOddIndex(int[] array, int startIndex, int endIndex) {
while (startIndex < endIndex && isEven(array[startIndex])) {
startIndex++;
}
return startIndex;
}

/**
* Finds the next even index in the array starting from the given endIndex.
*
* @param array The input array to search for the next even index.
* @param startIndex The starting index for searching.
* @param endIndex The ending index for searching.
* @return The next even index.
*/
private static int findNextEvenIndex(int[] array, int startIndex, int endIndex) {
while (startIndex < endIndex && !isEven(array[startIndex])) {
endIndex--;
}
return endIndex;
}

/**
* Checks if a number is even.
*
* @param number The number to be checked.
* @return {@code true} if the number is even, {@code false} otherwise.
*/
private static boolean isEven(int number) {
return number % 2 == 0;
}

/**
* Swaps the elements at the given indices in the array.
*
* @param array The array in which elements are to be swapped.
* @param leftIndex The index of the left element to be swapped.
* @param rightIndex The index of the right element to be swapped.
*/
private static void swapElements(int[] array, int leftIndex, int rightIndex) {
int temp = array[leftIndex];
array[leftIndex] = array[rightIndex];
array[rightIndex] = temp;
}
  • 快速试错 Rapid Iterative Testing and Evaluation (RITE)

    • 找到问题的根源,在根源上改。 think before you code, don’t make adhoc change or tweak some if condition without much thinking
    • 重复不利于试错 不收敛,程序员最懒惰,工作为了不工作 DRY (Don’t Repeat Yourself) principle
    • 一切都是代码,ut和ft也是代码需要review.”Talk is cheap. Show me the code.” – Linus Torvalds
  • 没有绝对的正确,核心是我们怎么妥协 “There are no solutions, only tradeoffs - Thomas Sowell”

    • 做一个有态度的 reviewer - Having a clear direction helps us converge quickly.
      • code review 包含了主观的偏好 subjective [IMO] objective[FACT]
      • senior 一定是对的吗 I disagree with your disagreement
      • Let’s appeal to rules that all team member respect (We Make Up the Rules as We Go Along)

Replace Conditional with Polymorphis

  • 什么是条件表达
    • if elseif else, switch case
  • 为什么条件表达多了不好
    • 无法一眼看清 nested condition 更差

    • 不好修改, 修改太分散(shotgun surgery 散弹式修改)有时需要在好几个else if里面加同样的代码

    • 方法容易写太长, 这样方法也难复用了

      • how to make it better

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        class Employee {
        int payAmount(RoleType type){
        switch(type){
        case ENGINEER:
        return getMonthlySalary();
        case SALESMAN:
        return getMonthlySalary() + getMonthlyCommission();
        case MANAGER:
        return getMonthlySalary() + getBonus();
        default:
        throw new RuntimeException("Invalid employee role type");
        }
        }

        }

      it works but we can do better:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      abstract class Employee{

      abstract int payAmount();
      }

      class Engineer extends Employee{
      int payAmount(){
      return getMonthlySalary();
      }
      }
      class Salesman extends Employee{
      int payAmount(){
      return getMonthlySalary() + getMonthlyCommission();
      }
      }
      class Manager extends Employee{
      int payAmount(){
      return getMonthlySalary() + getBonus();
      }
      }

Improve Conditional Expression

  • prefer positive checks
    • IsEmpty() NOT IsNotAllEmpty()
    • hasContent() NOT HasNotAnyContent()
  • use gaurd and fail fast
    • [NOT] garbage in , garbage out.
    • throw error and exception, stop return.
  • 每个方法只做一件事,这么多if是不是因为想做的太多
    • 也有可能是level 太多, 把低level的abstract出去,形成一个方法。 比如和persist相关的。和mq相关的
    • 3层最多了 别再多了

Be proactive

Extensive Reading

https://github.com/google/styleguide/tree/gh-pages

https://github.com/alibaba/Alibaba-Java-Coding-Guidelines#naming-conventions

https://github.com/jnguyen095/clean-code/blob/master/Clean.Code.A.Handbook.of.Agile.Software.Craftsmanship.pdf

https://github.com/willykraisler/prueba/blob/master/M.Fowler%20et%20al%20-%20Refactoring%20-%20Improving%20the%20Design%20of%20Existing.pdf

https://github.com/jayphelps/git-blame-someone-else

CATALOG
  1. 1. Personal Views / Basic Principles
  2. 2. Replace Conditional with Polymorphis
  3. 3. Improve Conditional Expression
  4. 4. Be proactive
  5. 5. Extensive Reading