SlideShare una empresa de Scribd logo
1 de 41
Descargar para leer sin conexión
PHP
PIXNET 踢克⼤⼩事分享
PIXNET @ Win 17/11/10
kylinyu.win
良好實踐
前傳
實戰
服⽤警告
✤ 我們不談 Framework 的⼯具
✤ 程式碼皆為範例⽰意,切勿直接複製套⽤
✤ Coding Style 為 PIXNET Platform 的風格
Naming 名詞單複數
// 複數名詞 ResultSet / Collection
$users = User::search(1);
// 單數名詞 Row
$article = BlogArticle::find(1);
變數提煉
foreach ($employees as $employee) {
$expectedSalary = $employee->calculateExpectedSalary();
$experience = $employee->getExperience();
$githubLink = $employee->getGithubLink();
$data = [
$expectedSalary,
$experience,
$githubLink
];
render($data);
}
✤ 當有進⼀步運⽤需求時
變數提煉
foreach ($employees as $employee) {
$expectedSalary = $employee->calculateExpectedSalary();
$experience = $employee->getExperience();
$githubLink = $employee->getGithubLink();
$data = [
$expectedSalary,
$experience,
$githubLink
];
render($data);
}
foreach ($employees as $employee) {
render([
$employee->calculateExpectedSalary()
$employee->getExperience(),
$employee->getGithubLink(),
]);
}
✤ 當有進⼀步運⽤需求時
✤ 但,只有賦值就不建議提煉
變數提煉
foreach ($employees as $employee) {
render([
$employee->calculateExpectedSalary()
$employee->getExperience(),
$employee->getGithubLink(),
]);
}
$bouns = 1.25;
foreach ($employees as $employee) {
$expectedSalary = $employee->calculateExpectedSalary() * $bouns;
render([
$expectedSalary,
$employee->getExperience(),
$employee->getGithubLink(),
]);
}
✤ 當有進⼀步運⽤需求時
✤ 假設要後處理(額外運算)
變數提煉
✤ 特殊語意不易理解的時候
$user = User::find(1);
if (!$user->friends->friends_feeds['12345']->friends_comments->count()) {
echo 'No comments.'
}
變數提煉
✤ 特殊語意不易理解的時候
$user = User::find(1);
$friends_comments_count = $user->friends->friends_feeds['12345']->friends_comments->count();
if (!$friends_comments_count) {
echo 'No comments.'
}
$user = User::find(1);
if (!$user->friends->friends_feeds['12345']->friends_comments->count()) {
echo 'No comments.'
}
常數提煉
class CardAuthor
{
// ....
public function checkAdmin()
{
return (2 === $this->role);
}
}
✤ 物件的限制特性
常數提煉
class CardAuthor
{
// ....
public function checkAdmin()
{
return (2 === $this->role);
}
}
class CardAuthor
{
// ....
const ROLE_GENERAL = 0; // ⼀一般作者
const ROLE_EDITOR = 1; // 內容管理理員
const ROLE_ADMIN = 2; // 者總管理理員
public function checkAdmin()
{
return (self::ROLE_EDITOR === $this->role);
}
}
✤ 物件的限制特性
✤ 跟著類別⾛,語易化更佳
變/常數提煉
$member = Member::find(1);
if (5 < $member->day_logs) {
throw new Exception('該名員⼯工超時⼯工作!!');
}
✤ 特殊⽤意的參數都建議提煉
➡ 能被改就⽤變數 ($variable)
➡ 不能被改就⽤常數 (constant)
$member = Member::find(1);
if (5 < $member->day_logs) {
throw new Exception('該名員⼯工超時⼯工作!!');
}
$workdays_per_week_limit = 5;
if ($workdays_per_week_limit < $member->day_logs) {
throw new Exception('該名員⼯工超時⼯工作!!');
}
變/常數提煉 ✤ 特殊⽤意的參數都建議提煉
➡ 能被改就⽤變數 ($variable)
➡ 不能被改就⽤常數 (constant)
函式 - ⾸則要務 − 簡短
public function checkAlbumStatus()
{
if ('ok' === $this->album->status) {
return true;
}
return false;
}
函式 - ⾸則要務 − 簡短
public function checkAlbumStatus()
{
if ('ok' === $this->album->status) {
return true;
}
return false;
}
public function checkAlbumStatus()
{
$album_status = $this->album->status;
return ('ok' === $album_status) ? true : false;
}
…
函式 - ⾸則要務 − 簡短
public function checkAlbumStatus()
{
$is_ok = ('ok' === $this->album->status);
return $is_ok;
}
…
函式 - ⾸則要務 − 簡短
public function checkAlbumStatus()
{
$is_ok = ('ok' === $this->album->status);
return $is_ok;
}
…
public function checkAlbumStatus()
{
return ('ok' === $this->album->status);
}
✤ set 設定某個 property
✤ get 設定某個 property
✤ is/has 通常判斷式 boolean
✤ check 做某種條件檢查 boolean, void
✤ filter 過濾, input/output 不⾒見見得⼀一樣 mixed
✤ validate 驗證器資料是否符合預期 boolean, void, throw exception
函式 - 動詞起⼿式
✤ can
✤ should
函式 - 動詞起⼿式
/**
* getUser 取得使⽤用者
*
* @param int $id
* @return UserRow
*/
function getUser($id)
{
// implement
}
/**
* setAge 設定使⽤用者年年齡
*
* @param UserRow
* @return boolean
*/
function setAge($user)
{
// implement
}
/**
* isAdmin 判斷是否為管理理者
*
* @param UserRow
* @return boolean
*/
function isAdmin($user)
{
// implement
}
/**
* checkLogin 檢查免費的時效
*
* @return void
*/
function checkFreeExpired()
{
// implement
}
set
get is
check
函式 - 動詞起⼿式
/**
* validateCSRFToken 檢查 CSTF Token
*
* @thorw Exception
* @return void
*/
function validateCSRFToken()
{
if (...) {
throw new Exception("Don't Hack Me.");
}
// return true; //(optional)
}
<?php
class UserPreference
{
const SERVICE_WHITE_LIST = [
'PIXNET',
'STYLEME',
'PIXWALLET'
];
/**
* filterRegisterService 過濾註冊服務類別
*
* @param string $service
* @return string
*/
public function filterRegisterService($service)
{
if (in_array($service, self::SERVICE_WHITE_LIST)) {
return $service;
}
return "kylinyu.win";
}
}
filter
validate
函式 - 只做⼀件事
- 難以組成
- 難以測試
- 難以理解
當⼀個函式
做超過⼀件事的時候...
函式 - 只做⼀件事
- 難以組成
- 難以測試
- 難以理解
- 容易測試
- 容易重構
- 結構清晰
當⼀個函式
做超過⼀件事的時候...
當⼀個函式
拆分到只剩⼀個功能時...
函式 - 只做⼀件事
function createArticle($title, $is_draft = true)
{
if ($is_draft) {
touch('./temp/' . $title);
} else {
touch('./article/' . $title);
}
}
✤ 不⽤ Flag 做參數
函式 - 只做⼀件事
function createArticle($title, $is_draft = true)
{
if ($is_draft) {
touch('./temp/' . $title);
} else {
touch('./article/' . $title);
}
}
function createArticle($title)
{
touch('./temp/' . $title);
}
function createDraftArticle($title)
{
touch('./article/' . $title);
}
✤ 不⽤ Flag 做參數
能⾒度Visibility
class User
{
public $name;
public function __construct($name)
{
$this->name = $name;
}
}
$user = new User('Win Yu');
echo 'User name: ' . $user->name;
// User name: Win Yu
✤ 沒必要對外開放的就不要開 public
✤ 使⽤類別時只要看 public 成員就好
能⾒度Visibility
class User
{
public $name;
public function __construct($name)
{
$this->name = $name;
}
}
$user = new User('Win Yu');
echo 'User name: ' . $user->name;
// User name: Win Yu
class User
{
private $name;
public function __construct($name)
{
$this->name = $name;
}
public function getName()
{
return $this->name;
}
}
$user = new User('Win Yu');
echo 'User name: ' . $user->getName();
// User name: John Doe
✤ 沒必要對外開放的就不要開 public
✤ 使⽤類別時只要看 public 成員就好
封裝條件句
if ('active' === $user->status) {
// do something
}
✤ 更清楚的語意
封裝條件句
if ('active' === $user->status) {
// do something
}
if ($user->isActive()) {
// do something
}
class User {
// ...
public function isActive()
{
return ('active' === $this->status);
}
}
✤ 更清楚的語意
Guard Clause 原則
//define('DEBUG_ENV', true);
/**
* markByENV 根據 env 做標記
*
* @return string
*/
function markByENV()
{
$user = User::find($user_id);
if (DEBUG_ENV) {
$user->mark('staging');
$message = "標記 {$user->name} staging";
} else {
$user->mark('production');
$message = "標記 {$user->name} production";
}
return $message;
}
✤ Early return
✤ 減少巢狀 loop
Guard Clause 原則
//define('DEBUG_ENV', true);
/**
* markByENV 根據 env 做標記
*
* @return string
*/
function markByENV()
{
$user = User::find($user_id);
if (DEBUG_ENV) {
$user->mark('staging');
$message = "標記 {$user->name} staging";
} else {
$user->mark('production');
$message = "標記 {$user->name} production";
}
return $message;
}
//define('DEBUG_ENV', true);
/**
* markByENV 根據 env 做標記
*
* @return sting
*/
function markByENV()
{
$user = User::find($user_id);
if (DEBUG_ENV) {
$user->mark('staging');
return "標記 {$user->name} staging";
}
$user->mark('production');
return "標記 {$user->name} production";
}
✤ Early return
✤ 減少巢狀 loop
Type Hint
function enableEpaper($user)
{
if ($user instanceof UserRow) {
//
}
}
✤ PHP7 可⽤強型別檢查
Type Hint
function enableEpaper($user)
{
if ($user instanceof UserRow) {
//
}
}
function enableEpaper(UserRow $user)
{
//
}
✤ PHP7 可⽤強型別檢查
查表法
/**
* getFruitByColor ⽤用顏⾊色取得⽔水果名稱
*
* @param string $color
* @return string
*/
function getFruitByColor($color)
{
if ('紅⾊色' === $color) {
return '蘋果';
} elseif ('綠⾊色' === $color) {
return '芭樂';
} elseif ('紫⾊色' === $color) {
return '葡萄';
}
return $color;
}
✤ 簡化 if/else 可讀性更⾼
查表法
/**
* getFruitByColor ⽤用顏⾊色取得⽔水果名稱
*
* @param string $color
* @return string
*/
function getFruitByColor($color)
{
if ('紅⾊色' === $color) {
return '蘋果';
} elseif ('綠⾊色' === $color) {
return '芭樂';
} elseif ('紫⾊色' === $color) {
return '葡萄';
}
return $color;
}
✤ 簡化 if/else 可讀性更⾼
/**
* getFruitByColor ⽤用顏⾊色取得⽔水果名稱
*
* @param string $color
* @return string
*/
function getFruitByColor($color)
{
$fruit_map = [
'紅⾊色' => '蘋果',
'綠⾊色' => '芭樂',
'紫⾊色' => '葡萄',
];
return isset($fruit_map[$color]) ?
$fruit_map[$color] : color;
}
查表法
/**
* getFruitByColor ⽤用顏⾊色取得⽔水果名稱
*
* @param string $color
* @return string
*/
function getFruitByColor($color)
{
if ('紅⾊色' === $color) {
return '蘋果';
} elseif ('綠⾊色' === $color) {
return '芭樂';
} elseif ('紫⾊色' === $color) {
return '葡萄';
}
return $color;
}
✤ 簡化 if/else 可讀性更⾼
/**
* getFruitByColor ⽤用顏⾊色取得⽔水果名稱
*
* @param string $color
* @return string
*/
function getFruitByColor($color)
{
$fruit_map = [
'紅⾊色' => '蘋果',
'綠⾊色' => '芭樂',
'紫⾊色' => '葡萄',
];
return isset($fruit_map[$color]) ?
$fruit_map[$color] : color;
}
return $fruit_map[$color] ?? $color;
PHP 7
避免⽤ switch/case
⽽是⽤多型
class Airplane
{
// ...
public function getCruisingAltitude()
{
switch ($this->type) {
case '777':
return $this->getMaxAltitude() - $this->getPassengerCount();
case 'Air Force One':
return $this->getMaxAltitude();
case 'Cessna':
return $this->getMaxAltitude() - $this->getFuelExpenditure();
}
}
}
✤ ⼀個函式做多件事
✤ 等同任由後者隨意增加邏輯於
case 中
interface Airplane
{
// ...
public function getCruisingAltitude();
}
class Boeing777 implements Airplane
{
// ...
public function getCruisingAltitude()
{
return $this->getMaxAltitude() -
$this->getPassengerCount();
}
}
class AirForceOne implements Airplane
{
// ...
public function getCruisingAltitude()
{
return $this->getMaxAltitude();
}
}
class Cessna implements Airplane
{
// ...
public function getCruisingAltitude()
{
return $this->getMaxAltitude() -
$this->getFuelExpenditure();
}
}
避免⽤ switch/case
⽽是⽤多型
Practice and Practice
✤ 反覆練習
✤ 藉由 Code Review 互相提醒
✤ 不斷思考,何以更為精練
✤ 勿矯枉過正,良好的可讀性優先
See more
✤ 無瑕程式碼的彩虹七式
✤ https://www.slideshare.net/kylinfish/clean-code-72688451
✤ Clean Code PHP
✤ https://github.com/php-cpm/clean-code-php
✤ PHP The Right Way
✤ https://laravel-china.github.io/php-the-right-way
kylinyu.win
Thanks you.

Más contenido relacionado

La actualidad más candente

Road From Hex. Architecture to Event Sourcing
Road From Hex. Architecture to Event SourcingRoad From Hex. Architecture to Event Sourcing
Road From Hex. Architecture to Event SourcingCarlos Buenosvinos
 
The Secrets of Hexagonal Architecture
The Secrets of Hexagonal ArchitectureThe Secrets of Hexagonal Architecture
The Secrets of Hexagonal ArchitectureNicolas Carlo
 
You code sucks, let's fix it
You code sucks, let's fix itYou code sucks, let's fix it
You code sucks, let's fix itRafael Dohms
 
Keep your code clean
Keep your code cleanKeep your code clean
Keep your code cleanmacrochen
 
[Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang)
[Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang) [Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang)
[Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang) Johnny Sung
 
Golang basics for Java developers - Part 1
Golang basics for Java developers - Part 1Golang basics for Java developers - Part 1
Golang basics for Java developers - Part 1Robert Stern
 
Using Xcore with Xtext
Using Xcore with XtextUsing Xcore with Xtext
Using Xcore with XtextHolger Schill
 
關於SQL Injection的那些奇技淫巧
關於SQL Injection的那些奇技淫巧關於SQL Injection的那些奇技淫巧
關於SQL Injection的那些奇技淫巧Orange Tsai
 
The aggregate is dead! Long live the aggregate! - SpringIO.pdf
The aggregate is dead! Long live the aggregate! - SpringIO.pdfThe aggregate is dead! Long live the aggregate! - SpringIO.pdf
The aggregate is dead! Long live the aggregate! - SpringIO.pdfSara Pellegrini
 
Clean architecture with ddd layering in php
Clean architecture with ddd layering in phpClean architecture with ddd layering in php
Clean architecture with ddd layering in phpLeonardo Proietti
 
Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented ProgrammingScott Wlaschin
 
Rust Programming Language
Rust Programming LanguageRust Programming Language
Rust Programming LanguageJaeju Kim
 
Clean code and Code Smells
Clean code and Code SmellsClean code and Code Smells
Clean code and Code SmellsMario Sangiorgio
 
One App, Many Clients: Converting an APEX Application to Multi-Tenant
One App, Many Clients: Converting an APEX Application to Multi-TenantOne App, Many Clients: Converting an APEX Application to Multi-Tenant
One App, Many Clients: Converting an APEX Application to Multi-TenantJeffrey Kemp
 
Design functional solutions in Java, a practical example
Design functional solutions in Java, a practical exampleDesign functional solutions in Java, a practical example
Design functional solutions in Java, a practical exampleMarian Wamsiedel
 

La actualidad más candente (20)

Clean code
Clean codeClean code
Clean code
 
Road From Hex. Architecture to Event Sourcing
Road From Hex. Architecture to Event SourcingRoad From Hex. Architecture to Event Sourcing
Road From Hex. Architecture to Event Sourcing
 
The Secrets of Hexagonal Architecture
The Secrets of Hexagonal ArchitectureThe Secrets of Hexagonal Architecture
The Secrets of Hexagonal Architecture
 
You code sucks, let's fix it
You code sucks, let's fix itYou code sucks, let's fix it
You code sucks, let's fix it
 
Keep your code clean
Keep your code cleanKeep your code clean
Keep your code clean
 
[Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang)
[Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang) [Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang)
[Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang)
 
Golang basics for Java developers - Part 1
Golang basics for Java developers - Part 1Golang basics for Java developers - Part 1
Golang basics for Java developers - Part 1
 
Clean coding-practices
Clean coding-practicesClean coding-practices
Clean coding-practices
 
Using Xcore with Xtext
Using Xcore with XtextUsing Xcore with Xtext
Using Xcore with Xtext
 
Separation of concerns - DPC12
Separation of concerns - DPC12Separation of concerns - DPC12
Separation of concerns - DPC12
 
關於SQL Injection的那些奇技淫巧
關於SQL Injection的那些奇技淫巧關於SQL Injection的那些奇技淫巧
關於SQL Injection的那些奇技淫巧
 
Hexagonal architecture in PHP
Hexagonal architecture in PHPHexagonal architecture in PHP
Hexagonal architecture in PHP
 
Clean code
Clean codeClean code
Clean code
 
The aggregate is dead! Long live the aggregate! - SpringIO.pdf
The aggregate is dead! Long live the aggregate! - SpringIO.pdfThe aggregate is dead! Long live the aggregate! - SpringIO.pdf
The aggregate is dead! Long live the aggregate! - SpringIO.pdf
 
Clean architecture with ddd layering in php
Clean architecture with ddd layering in phpClean architecture with ddd layering in php
Clean architecture with ddd layering in php
 
Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented Programming
 
Rust Programming Language
Rust Programming LanguageRust Programming Language
Rust Programming Language
 
Clean code and Code Smells
Clean code and Code SmellsClean code and Code Smells
Clean code and Code Smells
 
One App, Many Clients: Converting an APEX Application to Multi-Tenant
One App, Many Clients: Converting an APEX Application to Multi-TenantOne App, Many Clients: Converting an APEX Application to Multi-Tenant
One App, Many Clients: Converting an APEX Application to Multi-Tenant
 
Design functional solutions in Java, a practical example
Design functional solutions in Java, a practical exampleDesign functional solutions in Java, a practical example
Design functional solutions in Java, a practical example
 

Destacado

用 Bitbar Tool 寫 Script 自動擷取外幣
用 Bitbar Tool 寫 Script 自動擷取外幣用 Bitbar Tool 寫 Script 自動擷取外幣
用 Bitbar Tool 寫 Script 自動擷取外幣Win Yu
 
與設計架構當朋友
與設計架構當朋友 與設計架構當朋友
與設計架構當朋友 Win Yu
 
Mooink閱讀功能
Mooink閱讀功能Mooink閱讀功能
Mooink閱讀功能ecrowdmedia
 
MakerBoard: MT7688 Emulator
MakerBoard: MT7688 EmulatorMakerBoard: MT7688 Emulator
MakerBoard: MT7688 EmulatorFred Chien
 
HITCON駭客戰隊與CTF經驗分享
HITCON駭客戰隊與CTF經驗分享HITCON駭客戰隊與CTF經驗分享
HITCON駭客戰隊與CTF經驗分享Alan Lee
 
聊天機器人:一個沒有小編的世界
聊天機器人:一個沒有小編的世界聊天機器人:一個沒有小編的世界
聊天機器人:一個沒有小編的世界佳新 陳
 
容器驅動開發 - .NET Conf 2017 @ 台中
容器驅動開發 - .NET Conf 2017 @ 台中容器驅動開發 - .NET Conf 2017 @ 台中
容器驅動開發 - .NET Conf 2017 @ 台中Andrew Wu
 
時代在變 Docker 要會:台北 Docker 一日入門篇
時代在變 Docker 要會:台北 Docker 一日入門篇時代在變 Docker 要會:台北 Docker 一日入門篇
時代在變 Docker 要會:台北 Docker 一日入門篇Philip Zheng
 
容器與資料科學應用
容器與資料科學應用容器與資料科學應用
容器與資料科學應用Philip Zheng
 
2016 ModernWeb 分享 - 恰如其分 MySQL 程式設計 (修)
2016 ModernWeb 分享 - 恰如其分 MySQL 程式設計 (修)2016 ModernWeb 分享 - 恰如其分 MySQL 程式設計 (修)
2016 ModernWeb 分享 - 恰如其分 MySQL 程式設計 (修)Win Yu
 
企業導入容器經驗分享與開源技能培養
企業導入容器經驗分享與開源技能培養企業導入容器經驗分享與開源技能培養
企業導入容器經驗分享與開源技能培養Philip Zheng
 
容器與IoT端點應用
容器與IoT端點應用容器與IoT端點應用
容器與IoT端點應用Philip Zheng
 
容器與 Gitlab CI 應用
容器與 Gitlab CI 應用容器與 Gitlab CI 應用
容器與 Gitlab CI 應用Philip Zheng
 
Docker 進階實務班
Docker 進階實務班Docker 進階實務班
Docker 進階實務班Philip Zheng
 
API Token 入門
API Token 入門API Token 入門
API Token 入門Andrew Wu
 
大型 Web Application 轉移到 微服務的經驗分享
大型 Web Application 轉移到微服務的經驗分享大型 Web Application 轉移到微服務的經驗分享
大型 Web Application 轉移到 微服務的經驗分享Andrew Wu
 
Continuous Delivery - 敏捷開發的最後一哩路
Continuous Delivery - 敏捷開發的最後一哩路Continuous Delivery - 敏捷開發的最後一哩路
Continuous Delivery - 敏捷開發的最後一哩路Miles Chou
 
[系列活動] 一天搞懂對話機器人
[系列活動] 一天搞懂對話機器人[系列活動] 一天搞懂對話機器人
[系列活動] 一天搞懂對話機器人台灣資料科學年會
 
26 Disruptive & Technology Trends 2016 - 2018
26 Disruptive & Technology Trends 2016 - 201826 Disruptive & Technology Trends 2016 - 2018
26 Disruptive & Technology Trends 2016 - 2018Brian Solis
 

Destacado (20)

用 Bitbar Tool 寫 Script 自動擷取外幣
用 Bitbar Tool 寫 Script 自動擷取外幣用 Bitbar Tool 寫 Script 自動擷取外幣
用 Bitbar Tool 寫 Script 自動擷取外幣
 
與設計架構當朋友
與設計架構當朋友 與設計架構當朋友
與設計架構當朋友
 
Full Text Search In PostgreSQL
Full Text Search In PostgreSQLFull Text Search In PostgreSQL
Full Text Search In PostgreSQL
 
Mooink閱讀功能
Mooink閱讀功能Mooink閱讀功能
Mooink閱讀功能
 
MakerBoard: MT7688 Emulator
MakerBoard: MT7688 EmulatorMakerBoard: MT7688 Emulator
MakerBoard: MT7688 Emulator
 
HITCON駭客戰隊與CTF經驗分享
HITCON駭客戰隊與CTF經驗分享HITCON駭客戰隊與CTF經驗分享
HITCON駭客戰隊與CTF經驗分享
 
聊天機器人:一個沒有小編的世界
聊天機器人:一個沒有小編的世界聊天機器人:一個沒有小編的世界
聊天機器人:一個沒有小編的世界
 
容器驅動開發 - .NET Conf 2017 @ 台中
容器驅動開發 - .NET Conf 2017 @ 台中容器驅動開發 - .NET Conf 2017 @ 台中
容器驅動開發 - .NET Conf 2017 @ 台中
 
時代在變 Docker 要會:台北 Docker 一日入門篇
時代在變 Docker 要會:台北 Docker 一日入門篇時代在變 Docker 要會:台北 Docker 一日入門篇
時代在變 Docker 要會:台北 Docker 一日入門篇
 
容器與資料科學應用
容器與資料科學應用容器與資料科學應用
容器與資料科學應用
 
2016 ModernWeb 分享 - 恰如其分 MySQL 程式設計 (修)
2016 ModernWeb 分享 - 恰如其分 MySQL 程式設計 (修)2016 ModernWeb 分享 - 恰如其分 MySQL 程式設計 (修)
2016 ModernWeb 分享 - 恰如其分 MySQL 程式設計 (修)
 
企業導入容器經驗分享與開源技能培養
企業導入容器經驗分享與開源技能培養企業導入容器經驗分享與開源技能培養
企業導入容器經驗分享與開源技能培養
 
容器與IoT端點應用
容器與IoT端點應用容器與IoT端點應用
容器與IoT端點應用
 
容器與 Gitlab CI 應用
容器與 Gitlab CI 應用容器與 Gitlab CI 應用
容器與 Gitlab CI 應用
 
Docker 進階實務班
Docker 進階實務班Docker 進階實務班
Docker 進階實務班
 
API Token 入門
API Token 入門API Token 入門
API Token 入門
 
大型 Web Application 轉移到 微服務的經驗分享
大型 Web Application 轉移到微服務的經驗分享大型 Web Application 轉移到微服務的經驗分享
大型 Web Application 轉移到 微服務的經驗分享
 
Continuous Delivery - 敏捷開發的最後一哩路
Continuous Delivery - 敏捷開發的最後一哩路Continuous Delivery - 敏捷開發的最後一哩路
Continuous Delivery - 敏捷開發的最後一哩路
 
[系列活動] 一天搞懂對話機器人
[系列活動] 一天搞懂對話機器人[系列活動] 一天搞懂對話機器人
[系列活動] 一天搞懂對話機器人
 
26 Disruptive & Technology Trends 2016 - 2018
26 Disruptive & Technology Trends 2016 - 201826 Disruptive & Technology Trends 2016 - 2018
26 Disruptive & Technology Trends 2016 - 2018
 

Similar a PHP 良好實踐 (Best Practice)

PHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くためにPHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くためにYuya Takeyama
 
What's New in Perl? v5.10 - v5.16
What's New in Perl?  v5.10 - v5.16What's New in Perl?  v5.10 - v5.16
What's New in Perl? v5.10 - v5.16Ricardo Signes
 
Generating Power with Yield
Generating Power with YieldGenerating Power with Yield
Generating Power with YieldJason Myers
 
Adding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsAdding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsSam Hennessy
 
Code moi une RH! (PHP tour 2017)
Code moi une RH! (PHP tour 2017)Code moi une RH! (PHP tour 2017)
Code moi une RH! (PHP tour 2017)Arnaud Langlade
 
Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConRafael Dohms
 
JavaScript for PHP developers
JavaScript for PHP developersJavaScript for PHP developers
JavaScript for PHP developersStoyan Stefanov
 
Symfony2 - extending the console component
Symfony2 - extending the console componentSymfony2 - extending the console component
Symfony2 - extending the console componentHugo Hamon
 
Drupal Development (Part 2)
Drupal Development (Part 2)Drupal Development (Part 2)
Drupal Development (Part 2)Jeff Eaton
 
Feature flagsareflawed
Feature flagsareflawedFeature flagsareflawed
Feature flagsareflawedStephen Young
 
The Origin of Lithium
The Origin of LithiumThe Origin of Lithium
The Origin of LithiumNate Abele
 
Feature Flags Are Flawed: Let's Make Them Better
Feature Flags Are Flawed: Let's Make Them BetterFeature Flags Are Flawed: Let's Make Them Better
Feature Flags Are Flawed: Let's Make Them BetterStephen Young
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in actionJace Ju
 
Symfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteSymfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteLeonardo Proietti
 
PHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolvePHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolveXSolve
 
Micropage in microtime using microframework
Micropage in microtime using microframeworkMicropage in microtime using microframework
Micropage in microtime using microframeworkRadek Benkel
 

Similar a PHP 良好實踐 (Best Practice) (20)

PHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くためにPHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くために
 
What's New in Perl? v5.10 - v5.16
What's New in Perl?  v5.10 - v5.16What's New in Perl?  v5.10 - v5.16
What's New in Perl? v5.10 - v5.16
 
Oops in php
Oops in phpOops in php
Oops in php
 
Generating Power with Yield
Generating Power with YieldGenerating Power with Yield
Generating Power with Yield
 
Adding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsAdding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy Applications
 
Code moi une RH! (PHP tour 2017)
Code moi une RH! (PHP tour 2017)Code moi une RH! (PHP tour 2017)
Code moi une RH! (PHP tour 2017)
 
Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnCon
 
JavaScript for PHP developers
JavaScript for PHP developersJavaScript for PHP developers
JavaScript for PHP developers
 
Symfony2 - extending the console component
Symfony2 - extending the console componentSymfony2 - extending the console component
Symfony2 - extending the console component
 
BEAR DI
BEAR DIBEAR DI
BEAR DI
 
Drupal Development (Part 2)
Drupal Development (Part 2)Drupal Development (Part 2)
Drupal Development (Part 2)
 
Feature flagsareflawed
Feature flagsareflawedFeature flagsareflawed
Feature flagsareflawed
 
The Origin of Lithium
The Origin of LithiumThe Origin of Lithium
The Origin of Lithium
 
Feature Flags Are Flawed: Let's Make Them Better
Feature Flags Are Flawed: Let's Make Them BetterFeature Flags Are Flawed: Let's Make Them Better
Feature Flags Are Flawed: Let's Make Them Better
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in action
 
Symfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteSymfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il cliente
 
Taming Command Bus
Taming Command BusTaming Command Bus
Taming Command Bus
 
PHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolvePHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolve
 
Micropage in microtime using microframework
Micropage in microtime using microframeworkMicropage in microtime using microframework
Micropage in microtime using microframework
 
Perl Web Client
Perl Web ClientPerl Web Client
Perl Web Client
 

Más de Win Yu

運用 Cloud Pub/Sub 實作 PIXNET 跨產品動態整合 #modernWeb2018
運用 Cloud Pub/Sub 實作 PIXNET 跨產品動態整合 #modernWeb2018運用 Cloud Pub/Sub 實作 PIXNET 跨產品動態整合 #modernWeb2018
運用 Cloud Pub/Sub 實作 PIXNET 跨產品動態整合 #modernWeb2018Win Yu
 
AMP Roadshow Taipei
AMP Roadshow TaipeiAMP Roadshow Taipei
AMP Roadshow TaipeiWin Yu
 
Easy to recap AWS reinvent 2017
Easy to recap AWS reinvent 2017Easy to recap AWS reinvent 2017
Easy to recap AWS reinvent 2017Win Yu
 
Video Face Recognition , Pattern Recognition Final Report
Video Face Recognition , Pattern Recognition Final ReportVideo Face Recognition , Pattern Recognition Final Report
Video Face Recognition , Pattern Recognition Final ReportWin Yu
 
Pattern Recognition midterm Proposal
Pattern Recognition midterm ProposalPattern Recognition midterm Proposal
Pattern Recognition midterm ProposalWin Yu
 
A rank based ensemble classifier for image classification
A rank based ensemble classifier for image classificationA rank based ensemble classifier for image classification
A rank based ensemble classifier for image classificationWin Yu
 
Hybrid clustering based 3 d face modeling upon non-perfect orthogonality
Hybrid clustering based 3 d face modeling upon non-perfect orthogonalityHybrid clustering based 3 d face modeling upon non-perfect orthogonality
Hybrid clustering based 3 d face modeling upon non-perfect orthogonalityWin Yu
 
MSR-Bing Image Retrieval Challenge ,written by Win
MSR-Bing Image Retrieval Challenge ,written by WinMSR-Bing Image Retrieval Challenge ,written by Win
MSR-Bing Image Retrieval Challenge ,written by WinWin Yu
 
Tpr star tree
Tpr star treeTpr star tree
Tpr star treeWin Yu
 
A completed modeling of local binary pattern operator
A completed modeling of local binary pattern operatorA completed modeling of local binary pattern operator
A completed modeling of local binary pattern operatorWin Yu
 
Recognition of Partially Occluded Face Using Gradientface and Local Binary Pa...
Recognition of Partially Occluded Face Using Gradientface and Local Binary Pa...Recognition of Partially Occluded Face Using Gradientface and Local Binary Pa...
Recognition of Partially Occluded Face Using Gradientface and Local Binary Pa...Win Yu
 
Bundling Features for Large Scale Partial-Duplicate Web Image Search
Bundling Features for Large Scale Partial-Duplicate Web Image SearchBundling Features for Large Scale Partial-Duplicate Web Image Search
Bundling Features for Large Scale Partial-Duplicate Web Image SearchWin Yu
 

Más de Win Yu (12)

運用 Cloud Pub/Sub 實作 PIXNET 跨產品動態整合 #modernWeb2018
運用 Cloud Pub/Sub 實作 PIXNET 跨產品動態整合 #modernWeb2018運用 Cloud Pub/Sub 實作 PIXNET 跨產品動態整合 #modernWeb2018
運用 Cloud Pub/Sub 實作 PIXNET 跨產品動態整合 #modernWeb2018
 
AMP Roadshow Taipei
AMP Roadshow TaipeiAMP Roadshow Taipei
AMP Roadshow Taipei
 
Easy to recap AWS reinvent 2017
Easy to recap AWS reinvent 2017Easy to recap AWS reinvent 2017
Easy to recap AWS reinvent 2017
 
Video Face Recognition , Pattern Recognition Final Report
Video Face Recognition , Pattern Recognition Final ReportVideo Face Recognition , Pattern Recognition Final Report
Video Face Recognition , Pattern Recognition Final Report
 
Pattern Recognition midterm Proposal
Pattern Recognition midterm ProposalPattern Recognition midterm Proposal
Pattern Recognition midterm Proposal
 
A rank based ensemble classifier for image classification
A rank based ensemble classifier for image classificationA rank based ensemble classifier for image classification
A rank based ensemble classifier for image classification
 
Hybrid clustering based 3 d face modeling upon non-perfect orthogonality
Hybrid clustering based 3 d face modeling upon non-perfect orthogonalityHybrid clustering based 3 d face modeling upon non-perfect orthogonality
Hybrid clustering based 3 d face modeling upon non-perfect orthogonality
 
MSR-Bing Image Retrieval Challenge ,written by Win
MSR-Bing Image Retrieval Challenge ,written by WinMSR-Bing Image Retrieval Challenge ,written by Win
MSR-Bing Image Retrieval Challenge ,written by Win
 
Tpr star tree
Tpr star treeTpr star tree
Tpr star tree
 
A completed modeling of local binary pattern operator
A completed modeling of local binary pattern operatorA completed modeling of local binary pattern operator
A completed modeling of local binary pattern operator
 
Recognition of Partially Occluded Face Using Gradientface and Local Binary Pa...
Recognition of Partially Occluded Face Using Gradientface and Local Binary Pa...Recognition of Partially Occluded Face Using Gradientface and Local Binary Pa...
Recognition of Partially Occluded Face Using Gradientface and Local Binary Pa...
 
Bundling Features for Large Scale Partial-Duplicate Web Image Search
Bundling Features for Large Scale Partial-Duplicate Web Image SearchBundling Features for Large Scale Partial-Duplicate Web Image Search
Bundling Features for Large Scale Partial-Duplicate Web Image Search
 

Último

Mobile App Development process | Expert Tips
Mobile App Development process | Expert TipsMobile App Development process | Expert Tips
Mobile App Development process | Expert Tipsmichealwillson701
 
User Experience Designer | Kaylee Miller Resume
User Experience Designer | Kaylee Miller ResumeUser Experience Designer | Kaylee Miller Resume
User Experience Designer | Kaylee Miller ResumeKaylee Miller
 
Practical Advice for FDA’s 510(k) Requirements.pdf
Practical Advice for FDA’s 510(k) Requirements.pdfPractical Advice for FDA’s 510(k) Requirements.pdf
Practical Advice for FDA’s 510(k) Requirements.pdfICS
 
BusinessGPT - SECURITY AND GOVERNANCE FOR GENERATIVE AI.pptx
BusinessGPT  - SECURITY AND GOVERNANCE  FOR GENERATIVE AI.pptxBusinessGPT  - SECURITY AND GOVERNANCE  FOR GENERATIVE AI.pptx
BusinessGPT - SECURITY AND GOVERNANCE FOR GENERATIVE AI.pptxAGATSoftware
 
Building Generative AI-infused apps: what's possible and how to start
Building Generative AI-infused apps: what's possible and how to startBuilding Generative AI-infused apps: what's possible and how to start
Building Generative AI-infused apps: what's possible and how to startMaxim Salnikov
 
Leveling Up your Branding and Mastering MERN: Fullstack WebDev
Leveling Up your Branding and Mastering MERN: Fullstack WebDevLeveling Up your Branding and Mastering MERN: Fullstack WebDev
Leveling Up your Branding and Mastering MERN: Fullstack WebDevpmgdscunsri
 
VuNet software organisation powerpoint deck
VuNet software organisation powerpoint deckVuNet software organisation powerpoint deck
VuNet software organisation powerpoint deckNaval Singh
 
Einstein Copilot Conversational AI for your CRM.pdf
Einstein Copilot Conversational AI for your CRM.pdfEinstein Copilot Conversational AI for your CRM.pdf
Einstein Copilot Conversational AI for your CRM.pdfCloudMetic
 
Enterprise Content Managements Solutions
Enterprise Content Managements SolutionsEnterprise Content Managements Solutions
Enterprise Content Managements SolutionsIQBG inc
 
MUT4SLX: Extensions for Mutation Testing of Stateflow Models
MUT4SLX: Extensions for Mutation Testing of Stateflow ModelsMUT4SLX: Extensions for Mutation Testing of Stateflow Models
MUT4SLX: Extensions for Mutation Testing of Stateflow ModelsUniversity of Antwerp
 
8 Steps to Build a LangChain RAG Chatbot.
8 Steps to Build a LangChain RAG Chatbot.8 Steps to Build a LangChain RAG Chatbot.
8 Steps to Build a LangChain RAG Chatbot.Ritesh Kanjee
 
Unlocking AI: Navigating Open Source vs. Commercial Frontiers
Unlocking AI:Navigating Open Source vs. Commercial FrontiersUnlocking AI:Navigating Open Source vs. Commercial Frontiers
Unlocking AI: Navigating Open Source vs. Commercial FrontiersRaphaël Semeteys
 
Large Scale Architecture -- The Unreasonable Effectiveness of Simplicity
Large Scale Architecture -- The Unreasonable Effectiveness of SimplicityLarge Scale Architecture -- The Unreasonable Effectiveness of Simplicity
Large Scale Architecture -- The Unreasonable Effectiveness of SimplicityRandy Shoup
 
Telebu Social -Whatsapp Business API : Mastering Omnichannel Business Communi...
Telebu Social -Whatsapp Business API : Mastering Omnichannel Business Communi...Telebu Social -Whatsapp Business API : Mastering Omnichannel Business Communi...
Telebu Social -Whatsapp Business API : Mastering Omnichannel Business Communi...telebusocialmarketin
 
MinionLabs_Mr. Gokul Srinivas_Young Entrepreneur
MinionLabs_Mr. Gokul Srinivas_Young EntrepreneurMinionLabs_Mr. Gokul Srinivas_Young Entrepreneur
MinionLabs_Mr. Gokul Srinivas_Young EntrepreneurPriyadarshini T
 
If your code could speak, what would it tell you? Let GitHub Copilot Chat hel...
If your code could speak, what would it tell you? Let GitHub Copilot Chat hel...If your code could speak, what would it tell you? Let GitHub Copilot Chat hel...
If your code could speak, what would it tell you? Let GitHub Copilot Chat hel...Maxim Salnikov
 
Technical improvements. Reasons. Methods. Estimations. CJ
Technical improvements.  Reasons. Methods. Estimations. CJTechnical improvements.  Reasons. Methods. Estimations. CJ
Technical improvements. Reasons. Methods. Estimations. CJpolinaucc
 
BATbern52 Swisscom's Journey into Data Mesh
BATbern52 Swisscom's Journey into Data MeshBATbern52 Swisscom's Journey into Data Mesh
BATbern52 Swisscom's Journey into Data MeshBATbern
 
Boost Efficiency: Sabre API Integration Made Easy
Boost Efficiency: Sabre API Integration Made EasyBoost Efficiency: Sabre API Integration Made Easy
Boost Efficiency: Sabre API Integration Made Easymichealwillson701
 

Último (20)

Mobile App Development process | Expert Tips
Mobile App Development process | Expert TipsMobile App Development process | Expert Tips
Mobile App Development process | Expert Tips
 
User Experience Designer | Kaylee Miller Resume
User Experience Designer | Kaylee Miller ResumeUser Experience Designer | Kaylee Miller Resume
User Experience Designer | Kaylee Miller Resume
 
Practical Advice for FDA’s 510(k) Requirements.pdf
Practical Advice for FDA’s 510(k) Requirements.pdfPractical Advice for FDA’s 510(k) Requirements.pdf
Practical Advice for FDA’s 510(k) Requirements.pdf
 
BusinessGPT - SECURITY AND GOVERNANCE FOR GENERATIVE AI.pptx
BusinessGPT  - SECURITY AND GOVERNANCE  FOR GENERATIVE AI.pptxBusinessGPT  - SECURITY AND GOVERNANCE  FOR GENERATIVE AI.pptx
BusinessGPT - SECURITY AND GOVERNANCE FOR GENERATIVE AI.pptx
 
Building Generative AI-infused apps: what's possible and how to start
Building Generative AI-infused apps: what's possible and how to startBuilding Generative AI-infused apps: what's possible and how to start
Building Generative AI-infused apps: what's possible and how to start
 
Leveling Up your Branding and Mastering MERN: Fullstack WebDev
Leveling Up your Branding and Mastering MERN: Fullstack WebDevLeveling Up your Branding and Mastering MERN: Fullstack WebDev
Leveling Up your Branding and Mastering MERN: Fullstack WebDev
 
VuNet software organisation powerpoint deck
VuNet software organisation powerpoint deckVuNet software organisation powerpoint deck
VuNet software organisation powerpoint deck
 
Einstein Copilot Conversational AI for your CRM.pdf
Einstein Copilot Conversational AI for your CRM.pdfEinstein Copilot Conversational AI for your CRM.pdf
Einstein Copilot Conversational AI for your CRM.pdf
 
20140812 - OBD2 Solution
20140812 - OBD2 Solution20140812 - OBD2 Solution
20140812 - OBD2 Solution
 
Enterprise Content Managements Solutions
Enterprise Content Managements SolutionsEnterprise Content Managements Solutions
Enterprise Content Managements Solutions
 
MUT4SLX: Extensions for Mutation Testing of Stateflow Models
MUT4SLX: Extensions for Mutation Testing of Stateflow ModelsMUT4SLX: Extensions for Mutation Testing of Stateflow Models
MUT4SLX: Extensions for Mutation Testing of Stateflow Models
 
8 Steps to Build a LangChain RAG Chatbot.
8 Steps to Build a LangChain RAG Chatbot.8 Steps to Build a LangChain RAG Chatbot.
8 Steps to Build a LangChain RAG Chatbot.
 
Unlocking AI: Navigating Open Source vs. Commercial Frontiers
Unlocking AI:Navigating Open Source vs. Commercial FrontiersUnlocking AI:Navigating Open Source vs. Commercial Frontiers
Unlocking AI: Navigating Open Source vs. Commercial Frontiers
 
Large Scale Architecture -- The Unreasonable Effectiveness of Simplicity
Large Scale Architecture -- The Unreasonable Effectiveness of SimplicityLarge Scale Architecture -- The Unreasonable Effectiveness of Simplicity
Large Scale Architecture -- The Unreasonable Effectiveness of Simplicity
 
Telebu Social -Whatsapp Business API : Mastering Omnichannel Business Communi...
Telebu Social -Whatsapp Business API : Mastering Omnichannel Business Communi...Telebu Social -Whatsapp Business API : Mastering Omnichannel Business Communi...
Telebu Social -Whatsapp Business API : Mastering Omnichannel Business Communi...
 
MinionLabs_Mr. Gokul Srinivas_Young Entrepreneur
MinionLabs_Mr. Gokul Srinivas_Young EntrepreneurMinionLabs_Mr. Gokul Srinivas_Young Entrepreneur
MinionLabs_Mr. Gokul Srinivas_Young Entrepreneur
 
If your code could speak, what would it tell you? Let GitHub Copilot Chat hel...
If your code could speak, what would it tell you? Let GitHub Copilot Chat hel...If your code could speak, what would it tell you? Let GitHub Copilot Chat hel...
If your code could speak, what would it tell you? Let GitHub Copilot Chat hel...
 
Technical improvements. Reasons. Methods. Estimations. CJ
Technical improvements.  Reasons. Methods. Estimations. CJTechnical improvements.  Reasons. Methods. Estimations. CJ
Technical improvements. Reasons. Methods. Estimations. CJ
 
BATbern52 Swisscom's Journey into Data Mesh
BATbern52 Swisscom's Journey into Data MeshBATbern52 Swisscom's Journey into Data Mesh
BATbern52 Swisscom's Journey into Data Mesh
 
Boost Efficiency: Sabre API Integration Made Easy
Boost Efficiency: Sabre API Integration Made EasyBoost Efficiency: Sabre API Integration Made Easy
Boost Efficiency: Sabre API Integration Made Easy
 

PHP 良好實踐 (Best Practice)

  • 1. PHP PIXNET 踢克⼤⼩事分享 PIXNET @ Win 17/11/10 kylinyu.win 良好實踐
  • 4. 服⽤警告 ✤ 我們不談 Framework 的⼯具 ✤ 程式碼皆為範例⽰意,切勿直接複製套⽤ ✤ Coding Style 為 PIXNET Platform 的風格
  • 5. Naming 名詞單複數 // 複數名詞 ResultSet / Collection $users = User::search(1); // 單數名詞 Row $article = BlogArticle::find(1);
  • 6. 變數提煉 foreach ($employees as $employee) { $expectedSalary = $employee->calculateExpectedSalary(); $experience = $employee->getExperience(); $githubLink = $employee->getGithubLink(); $data = [ $expectedSalary, $experience, $githubLink ]; render($data); } ✤ 當有進⼀步運⽤需求時
  • 7. 變數提煉 foreach ($employees as $employee) { $expectedSalary = $employee->calculateExpectedSalary(); $experience = $employee->getExperience(); $githubLink = $employee->getGithubLink(); $data = [ $expectedSalary, $experience, $githubLink ]; render($data); } foreach ($employees as $employee) { render([ $employee->calculateExpectedSalary() $employee->getExperience(), $employee->getGithubLink(), ]); } ✤ 當有進⼀步運⽤需求時 ✤ 但,只有賦值就不建議提煉
  • 8. 變數提煉 foreach ($employees as $employee) { render([ $employee->calculateExpectedSalary() $employee->getExperience(), $employee->getGithubLink(), ]); } $bouns = 1.25; foreach ($employees as $employee) { $expectedSalary = $employee->calculateExpectedSalary() * $bouns; render([ $expectedSalary, $employee->getExperience(), $employee->getGithubLink(), ]); } ✤ 當有進⼀步運⽤需求時 ✤ 假設要後處理(額外運算)
  • 9. 變數提煉 ✤ 特殊語意不易理解的時候 $user = User::find(1); if (!$user->friends->friends_feeds['12345']->friends_comments->count()) { echo 'No comments.' }
  • 10. 變數提煉 ✤ 特殊語意不易理解的時候 $user = User::find(1); $friends_comments_count = $user->friends->friends_feeds['12345']->friends_comments->count(); if (!$friends_comments_count) { echo 'No comments.' } $user = User::find(1); if (!$user->friends->friends_feeds['12345']->friends_comments->count()) { echo 'No comments.' }
  • 11. 常數提煉 class CardAuthor { // .... public function checkAdmin() { return (2 === $this->role); } } ✤ 物件的限制特性
  • 12. 常數提煉 class CardAuthor { // .... public function checkAdmin() { return (2 === $this->role); } } class CardAuthor { // .... const ROLE_GENERAL = 0; // ⼀一般作者 const ROLE_EDITOR = 1; // 內容管理理員 const ROLE_ADMIN = 2; // 者總管理理員 public function checkAdmin() { return (self::ROLE_EDITOR === $this->role); } } ✤ 物件的限制特性 ✤ 跟著類別⾛,語易化更佳
  • 13. 變/常數提煉 $member = Member::find(1); if (5 < $member->day_logs) { throw new Exception('該名員⼯工超時⼯工作!!'); } ✤ 特殊⽤意的參數都建議提煉 ➡ 能被改就⽤變數 ($variable) ➡ 不能被改就⽤常數 (constant)
  • 14. $member = Member::find(1); if (5 < $member->day_logs) { throw new Exception('該名員⼯工超時⼯工作!!'); } $workdays_per_week_limit = 5; if ($workdays_per_week_limit < $member->day_logs) { throw new Exception('該名員⼯工超時⼯工作!!'); } 變/常數提煉 ✤ 特殊⽤意的參數都建議提煉 ➡ 能被改就⽤變數 ($variable) ➡ 不能被改就⽤常數 (constant)
  • 15. 函式 - ⾸則要務 − 簡短 public function checkAlbumStatus() { if ('ok' === $this->album->status) { return true; } return false; }
  • 16. 函式 - ⾸則要務 − 簡短 public function checkAlbumStatus() { if ('ok' === $this->album->status) { return true; } return false; } public function checkAlbumStatus() { $album_status = $this->album->status; return ('ok' === $album_status) ? true : false; } …
  • 17. 函式 - ⾸則要務 − 簡短 public function checkAlbumStatus() { $is_ok = ('ok' === $this->album->status); return $is_ok; } …
  • 18. 函式 - ⾸則要務 − 簡短 public function checkAlbumStatus() { $is_ok = ('ok' === $this->album->status); return $is_ok; } … public function checkAlbumStatus() { return ('ok' === $this->album->status); }
  • 19. ✤ set 設定某個 property ✤ get 設定某個 property ✤ is/has 通常判斷式 boolean ✤ check 做某種條件檢查 boolean, void ✤ filter 過濾, input/output 不⾒見見得⼀一樣 mixed ✤ validate 驗證器資料是否符合預期 boolean, void, throw exception 函式 - 動詞起⼿式 ✤ can ✤ should
  • 20. 函式 - 動詞起⼿式 /** * getUser 取得使⽤用者 * * @param int $id * @return UserRow */ function getUser($id) { // implement } /** * setAge 設定使⽤用者年年齡 * * @param UserRow * @return boolean */ function setAge($user) { // implement } /** * isAdmin 判斷是否為管理理者 * * @param UserRow * @return boolean */ function isAdmin($user) { // implement } /** * checkLogin 檢查免費的時效 * * @return void */ function checkFreeExpired() { // implement } set get is check
  • 21. 函式 - 動詞起⼿式 /** * validateCSRFToken 檢查 CSTF Token * * @thorw Exception * @return void */ function validateCSRFToken() { if (...) { throw new Exception("Don't Hack Me."); } // return true; //(optional) } <?php class UserPreference { const SERVICE_WHITE_LIST = [ 'PIXNET', 'STYLEME', 'PIXWALLET' ]; /** * filterRegisterService 過濾註冊服務類別 * * @param string $service * @return string */ public function filterRegisterService($service) { if (in_array($service, self::SERVICE_WHITE_LIST)) { return $service; } return "kylinyu.win"; } } filter validate
  • 22. 函式 - 只做⼀件事 - 難以組成 - 難以測試 - 難以理解 當⼀個函式 做超過⼀件事的時候...
  • 23. 函式 - 只做⼀件事 - 難以組成 - 難以測試 - 難以理解 - 容易測試 - 容易重構 - 結構清晰 當⼀個函式 做超過⼀件事的時候... 當⼀個函式 拆分到只剩⼀個功能時...
  • 24. 函式 - 只做⼀件事 function createArticle($title, $is_draft = true) { if ($is_draft) { touch('./temp/' . $title); } else { touch('./article/' . $title); } } ✤ 不⽤ Flag 做參數
  • 25. 函式 - 只做⼀件事 function createArticle($title, $is_draft = true) { if ($is_draft) { touch('./temp/' . $title); } else { touch('./article/' . $title); } } function createArticle($title) { touch('./temp/' . $title); } function createDraftArticle($title) { touch('./article/' . $title); } ✤ 不⽤ Flag 做參數
  • 26. 能⾒度Visibility class User { public $name; public function __construct($name) { $this->name = $name; } } $user = new User('Win Yu'); echo 'User name: ' . $user->name; // User name: Win Yu ✤ 沒必要對外開放的就不要開 public ✤ 使⽤類別時只要看 public 成員就好
  • 27. 能⾒度Visibility class User { public $name; public function __construct($name) { $this->name = $name; } } $user = new User('Win Yu'); echo 'User name: ' . $user->name; // User name: Win Yu class User { private $name; public function __construct($name) { $this->name = $name; } public function getName() { return $this->name; } } $user = new User('Win Yu'); echo 'User name: ' . $user->getName(); // User name: John Doe ✤ 沒必要對外開放的就不要開 public ✤ 使⽤類別時只要看 public 成員就好
  • 28. 封裝條件句 if ('active' === $user->status) { // do something } ✤ 更清楚的語意
  • 29. 封裝條件句 if ('active' === $user->status) { // do something } if ($user->isActive()) { // do something } class User { // ... public function isActive() { return ('active' === $this->status); } } ✤ 更清楚的語意
  • 30. Guard Clause 原則 //define('DEBUG_ENV', true); /** * markByENV 根據 env 做標記 * * @return string */ function markByENV() { $user = User::find($user_id); if (DEBUG_ENV) { $user->mark('staging'); $message = "標記 {$user->name} staging"; } else { $user->mark('production'); $message = "標記 {$user->name} production"; } return $message; } ✤ Early return ✤ 減少巢狀 loop
  • 31. Guard Clause 原則 //define('DEBUG_ENV', true); /** * markByENV 根據 env 做標記 * * @return string */ function markByENV() { $user = User::find($user_id); if (DEBUG_ENV) { $user->mark('staging'); $message = "標記 {$user->name} staging"; } else { $user->mark('production'); $message = "標記 {$user->name} production"; } return $message; } //define('DEBUG_ENV', true); /** * markByENV 根據 env 做標記 * * @return sting */ function markByENV() { $user = User::find($user_id); if (DEBUG_ENV) { $user->mark('staging'); return "標記 {$user->name} staging"; } $user->mark('production'); return "標記 {$user->name} production"; } ✤ Early return ✤ 減少巢狀 loop
  • 32. Type Hint function enableEpaper($user) { if ($user instanceof UserRow) { // } } ✤ PHP7 可⽤強型別檢查
  • 33. Type Hint function enableEpaper($user) { if ($user instanceof UserRow) { // } } function enableEpaper(UserRow $user) { // } ✤ PHP7 可⽤強型別檢查
  • 34. 查表法 /** * getFruitByColor ⽤用顏⾊色取得⽔水果名稱 * * @param string $color * @return string */ function getFruitByColor($color) { if ('紅⾊色' === $color) { return '蘋果'; } elseif ('綠⾊色' === $color) { return '芭樂'; } elseif ('紫⾊色' === $color) { return '葡萄'; } return $color; } ✤ 簡化 if/else 可讀性更⾼
  • 35. 查表法 /** * getFruitByColor ⽤用顏⾊色取得⽔水果名稱 * * @param string $color * @return string */ function getFruitByColor($color) { if ('紅⾊色' === $color) { return '蘋果'; } elseif ('綠⾊色' === $color) { return '芭樂'; } elseif ('紫⾊色' === $color) { return '葡萄'; } return $color; } ✤ 簡化 if/else 可讀性更⾼ /** * getFruitByColor ⽤用顏⾊色取得⽔水果名稱 * * @param string $color * @return string */ function getFruitByColor($color) { $fruit_map = [ '紅⾊色' => '蘋果', '綠⾊色' => '芭樂', '紫⾊色' => '葡萄', ]; return isset($fruit_map[$color]) ? $fruit_map[$color] : color; }
  • 36. 查表法 /** * getFruitByColor ⽤用顏⾊色取得⽔水果名稱 * * @param string $color * @return string */ function getFruitByColor($color) { if ('紅⾊色' === $color) { return '蘋果'; } elseif ('綠⾊色' === $color) { return '芭樂'; } elseif ('紫⾊色' === $color) { return '葡萄'; } return $color; } ✤ 簡化 if/else 可讀性更⾼ /** * getFruitByColor ⽤用顏⾊色取得⽔水果名稱 * * @param string $color * @return string */ function getFruitByColor($color) { $fruit_map = [ '紅⾊色' => '蘋果', '綠⾊色' => '芭樂', '紫⾊色' => '葡萄', ]; return isset($fruit_map[$color]) ? $fruit_map[$color] : color; } return $fruit_map[$color] ?? $color; PHP 7
  • 37. 避免⽤ switch/case ⽽是⽤多型 class Airplane { // ... public function getCruisingAltitude() { switch ($this->type) { case '777': return $this->getMaxAltitude() - $this->getPassengerCount(); case 'Air Force One': return $this->getMaxAltitude(); case 'Cessna': return $this->getMaxAltitude() - $this->getFuelExpenditure(); } } } ✤ ⼀個函式做多件事 ✤ 等同任由後者隨意增加邏輯於 case 中
  • 38. interface Airplane { // ... public function getCruisingAltitude(); } class Boeing777 implements Airplane { // ... public function getCruisingAltitude() { return $this->getMaxAltitude() - $this->getPassengerCount(); } } class AirForceOne implements Airplane { // ... public function getCruisingAltitude() { return $this->getMaxAltitude(); } } class Cessna implements Airplane { // ... public function getCruisingAltitude() { return $this->getMaxAltitude() - $this->getFuelExpenditure(); } } 避免⽤ switch/case ⽽是⽤多型
  • 39. Practice and Practice ✤ 反覆練習 ✤ 藉由 Code Review 互相提醒 ✤ 不斷思考,何以更為精練 ✤ 勿矯枉過正,良好的可讀性優先
  • 40. See more ✤ 無瑕程式碼的彩虹七式 ✤ https://www.slideshare.net/kylinfish/clean-code-72688451 ✤ Clean Code PHP ✤ https://github.com/php-cpm/clean-code-php ✤ PHP The Right Way ✤ https://laravel-china.github.io/php-the-right-way