當每個你看到的程式,執行結果都與你想得差不多,你會察覺到你正工作在 Clean Code 上

你是否經常遇到一些惱人或在維護時連自己都看不懂的程式碼呢?程式碼不僅是寫給機器看,更是為寫給人看。

程式碼的可讀性很重要,是日後維護的關鍵,以下介紹幾個簡單的規則,幫助寫出更乾淨的程式碼:

Any fool can write code that a computer can understand. Good programmers write code that humans can understand - Martin Fowler


1. 有意義的命名

不使用 $x $y 之類的變數名稱,沒人知道是什麼意思

// Bad
foreach ($x as $y) {...}

// Good
foreach ($people as $person) {...}

讓數字變得有意義

// Bad
$users = $userRepository->fetchByType(1);

// Good
$users = $userRepository->fetchByType(User::TYPE_ADMIN);


2. 不使用縮寫

寫程式常常會用縮寫代表的意義,可能為了讓變數名稱看起來更簡短,或者減少打字的時間!?
但這都是不需要的,縮寫會導致程式碼可讀性更差,讓意義變得更模糊,就把完整名稱打出來吧!

// Bad
class Trnsltr {...}

// Good
class Translator {...}

像一些很常見的縮寫,一看就知道代表什麼意思,就不用把完整名稱打出來了

// Bad
echo $userIdentification;

// Good
echo $userId;


3. 不必要的變數宣告

有時候加上不必要的變數反而會造成混亂,更加難以閱讀

// Bad
class User
{
...

public function isPremium(): bool
{
if ($this->type === static::TYPE_PREMIUM) {
$result = true;
} else {
$result = false;
}

return $result;
}
}

// Good
class User
{
...

public function isPremium(): bool
{
if ($this->type === static::TYPE_PREMIUM) {
return true;
} else {
return false;
}
}
}

// Best
class User
{
...

public function isPremium(): bool
{
return $this->type === static::TYPE_PREMIUM;
}
}


4. 盡量讓名稱保持在兩個字詞以下

過長的方法名稱描述也代表這個方法做了過多的事情,讓程式碼保持簡單,做的事情只有一件事

// Bad
class Post
{
public funciton saveAndUploadPost() {...}
}

// Good
class Post
{
public funciton savePost() {...}
public funciton uploadPost() {...}
}

// Best
class Post
{
public funciton save() {...}
public funciton upload() {...}
}

名稱太長有時候也可以考慮抽成 class

// Bad
function isShopOpen($day) {...}

// Good
class Shop
{
public function isOpen($day) {...}
}

有相同類型的對象描述,可以抽成 Entity

// Bad
$userName;
$userPhone;
$userEmail;

// Good
class User
{
public $name;
public $phone;
public $email;
}

但還是要看情況,有時候為了完整描述做的一件事情這樣做是更好的

$posts = $postRepository->fetchAllByIdAndDate($id, $date);


5. 盡量保持一層縮排

過多層數的縮排會影響閱讀,也會產生所謂的波動拳程式碼,利用 Early Return,或者 PHP Array Functions 或者 Collections 去處理,增加可讀性

Early Return,可以利用 Type Hint 除去檢查類型的程式碼,再利用 array 把相關的邏輯封裝,並且不用 else

// Bad
class Shop
{
public function isOpen($day): bool
{
if ($day) {
if (is_string($day)) {
$day = strtolower($day);
if ($day === 'friday') {
return true;
} elseif ($day === 'saturday') {
return true;
} elseif ($day === 'sunday') {
return true;
} else {
return false;
}
} else {
return false;
}
} else {
throw new Exception('$day is empty');
}
}
}

// Good
class Shop
{
public function isOpen(string $day): bool
{
if (empty($day)) {
throw new Exception('$day is empty');
}

$day = strtolower($day);
if ($day === 'friday') {
return true;
} elseif ($day === 'saturday') {
return true;
} elseif ($day === 'sunday') {
return true;
} else {
return false;
}
}
}

// Best
class Shop
{
public function isOpen(string $day): bool
{
if (empty($day)) {
throw new Exception('$day is empty');
}

$openDays = ['friday', 'saturday', 'sunday'];

return in_array(strtolower($day), $openDays);
}
}

多利用 PHP Array Functions 來處理問題,也可以增加可讀性

// Bad
class Posts
{
...

public function filterBy($type): array
{
$filtered = [];
foreach ($this->posts as $post) {
if ($post->isPublished) {
if ($post->type === $type) {
$filtered[] = $post;
}
}
}

return $filtered;
}
}

// Good
class Posts
{
...

public function filterBy($type): array
{
return array_filter($this->posts, function (Post $post) use ($type) {
return $post->isPublished && $post->type === $type;
});
}
}


總結

以上簡單整理了一些常常出現並且可以改進的地方,程式碼是死的,人是活的,規則沒有一定,多與其他人討論,多接觸不一樣的想法,程式碼可以更靈活、乾淨

如果有什麼問題歡迎指出或討論


References