# Code review!
Inspire from [google](https://google.github.io/eng-practices/review/reviewer/standard.html)'s guildline.
---
## Session
- The Standard of Code
- Principles
---
## The Standard of Code
本質是讓 codebase 能夠
維持一定的 "`健康度`" 並且是不斷地 "`進步`" 的
The primary purpose of code review is to make sure that the overall code health of our’s code base is **improving** over time.
---
### 主要重點在於「並沒有所謂完美的程式,只有更佳的程式」
---
### Principles
1. 要能給出技術上的建議,而不是個人偏好。
3. 關於軟體設計的部分,必須根據設計的基本原則去權衡考量,而不是基於個人偏好去更動原先的做法。
4. 假使有些部分並沒有前例可以參考時,在不會讓 codebase 變糟前提,應該要 Follow 目前的做法以保持一致性。
[Ref](https://google.github.io/eng-practices/review/reviewer/standard.html)
---
### Resolving Conflicts
- Face-to-face meeting
- Maintainer, tead leader, manager
---
### What to look for in a code review (1/2)
- Design: 整體的設計
- Functionality: 現在,過去,未來
- Complexity: 複雜度,可讀性,over-engineering
- Tests: 在合理的時間允許下,Reviewer 應該要要求寫測試
- Naming: 要能夠清楚表達這是什麼,或者這是在做什麼,以維持可讀性。
- Comment: 這段 Code 為什麼存在,主要是為了達到什麼效果
[Ref](https://tachingchen.com/tw/blog/how-to-do-a-code-review-by-google-2/)
---
### What to look for in a code review (2/2)
- Style: Style guide
- Documentation: 撰寫維護
- Every line: 要能夠理解每行 Code,call out for explaining
- Context: 上下文
- Good things: 有時候如果 Developer 寫得好,也可以留下 Comment 來讚美,因為每次的 Review,其實都可以當作一個 Mentoring 的機會,這也會帶來正面的助益。
[Ref](https://tachingchen.com/tw/blog/how-to-do-a-code-review-by-google-2/)
---
### 1. Naming
#### Before
``` php
$status = $user->status('pending');
```
---
### 1. Naming
#### After
``` php
$isUserPending = $user->isStatus('pending');
```
---
### 2. Naming
#### Before
``` php
return $factory->getTargetClass();
```
---
### 2. Naming
#### After
``` php
return $factory->getTargetClassPath();
```
---
### 3. Extracting
#### Before
``` php
public function setCodeExamples(string $exampleBefore, string $exampleAfter)
{
$this->exampleBefore = file_get_contents(base_path("$exampleBefore.md"));
$this->exampleAfter = file_get_contents(base_path("$exampleAfter.md"));
}
```
---
### 3. Extracting
#### After
``` php
public function setCodeExamples(string $exampleBefore, string $exampleAfter)
{
$this->exampleBefore = $this->getCodeExample($exampleBefore);
$this->exampleAfter = $this->getCodeExample($exampleAfter);
}
private function getCodeExample(string $exampleName): string
{
return file_get_contents(base_path("$exampleName.md"));
}
```
---
### 4. Extracting
#### Before
``` php
User::whereNotNull('subscribed')->where('status', 'active');
```
---
### 4. Extracting
#### After
``` php
User::subscribed();
```
---
### 5. Return Early
#### Before
``` php
public function calculateScore(User $user): int
{
if ($user->inactive) {
$score = 0;
} else {
if ($user->hasBonus) {
$score = $user->score + $this->bonus;
} else {
$score = $user->score;
}
}
return $score;
}
```
---
### 5. Return Early
#### After
``` php
public function calculateScore(User $user): int
{
if ($user->inactive) {
return 0;
}
if ($user->hasBonus) {
return $user->score + $this->bonus;
}
return $user->score;
}
```
---
### 6. Return Early
#### Before
``` php
public function sendInvoice(Invoice $invoice): void
{
if($user->notificationChannel === 'Slack')
{
$this->notifier->slack($invoice);
} else {
$this->notifier->email($invoice);
}
}
```
---
### 6. Return Early
#### After
``` php
public function sendInvoice(Invoice $invoice): bool
{
if($user->notificationChannel === 'Slack')
{
return $this->notifier->slack($invoice);
}
return $this->notifier->email($invoice);
}
```
---
### 7. Use collection
#### Before
``` php
$score = 0;
foreach($this->playedGames as $game) {
$score += $game->score;
}
return $score;
```
---
### 7. Use collection
#### After
``` php
return collect($this->playedGames)
->sum('score');
```
---
### 8. Use collection
#### Before
``` php
$users = [
[ 'id' => 801, 'name' => 'Peter', 'score' => 505, 'active' => true],
[ 'id' => 844, 'name' => 'Mary', 'score' => 704, 'active' => true],
[ 'id' => 542, 'name' => 'Norman', 'score' => 104, 'active' => false],
];
// Requested Result: only active users, sorted by score ["Mary(704)","Peter(505)"]
$users = array_filter($users, fn ($user) => $user['active']);
usort($users, fn($a, $b) => $a['score'] < $b['score']);
$userHighScoreTitles = array_map(fn($user) => $user['name'] . '(' . $user['score'] . ')', $users);
return $userHighScoreTitles;
```
---
### 8. Use collection
#### After
``` php
$users = [
[ 'id' => 801, 'name' => 'Peter', 'score' => 505, 'active' => true],
[ 'id' => 844, 'name' => 'Mary', 'score' => 104, 'active' => true],
[ 'id' => 542, 'name' => 'Norman', 'score' => 104, 'active' => false],
];
// Requested Result: only active users, sorted by score ["Mary(704)","Peter(505)"]
return collect($users)
->filter(fn($user) => $user['active'])
->sortBy('score')
->map(fn($user) => "{$user['name']} ({$user['score']})"
->values()
->toArray();
```
---
### 9. Consistency
#### Before
``` php
class UserController
{
public function find($userId) {}
}
class InvoicesController
{
public function find($user_id) {}
}
```
---
### 9. Consistency
#### After
``` php
class UserController
{
public function find($userId) {}
}
class InvoiceController
{
public function find($userId) {}
}
```
---
### 10. Consistency
#### Before
``` php
class PdfExporter
{
public function handle(Collection $items): void
{
// export items...
}
}
class CsvExporter
{
public function export(Collection $items): void
{
// export items...
}
}
$pdfExport->handle();
$csvExporter->export();
```
---
### 10. Consistency
#### After
``` php
interface Exporter
{
public function export(Collection $items): void;
}
class PdfExporter implements Exporter
{
public function export(Collection $items): void
{
// export items...
}
}
class CsvExporter implements Exporter
{
public function export(Collection $items): void
{
// export items...
}
}
$pdfExport->export();
$csvExporter->export();
```
---
### Reference
- https://google.github.io/eng-practices/review/reviewer/looking-for.html
- https://medium.com/@ryanyang1221/%E8%AE%93-google-%E6%95%99%E4%BD%A0-code-review-be251d4d81b4
- https://tachingchen.com/tw/blog/how-to-do-a-code-review-by-google-1
{"metaMigratedAt":"2023-06-15T13:11:17.951Z","metaMigratedFrom":"YAML","title":"How to do a code review","breaks":true,"description":"View the slide with \"Slide Mode\".","contributors":"[{\"id\":\"73654cf3-8e85-4412-809c-0d74345d349e\",\"add\":10596,\"del\":6355}]"}