SlideShare une entreprise Scribd logo
1  sur  41
Télécharger pour lire hors ligne
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.

Contenu connexe

Tendances

Clean Code II - Dependency Injection
Clean Code II - Dependency InjectionClean Code II - Dependency Injection
Clean Code II - Dependency Injection
Theo Jungeblut
 

Tendances (20)

Support programmation orientée objet c# .net version f8
Support programmation orientée objet c#  .net version f8Support programmation orientée objet c#  .net version f8
Support programmation orientée objet c# .net version f8
 
ドメイン駆動設計 失敗したことと成功したこと
ドメイン駆動設計 失敗したことと成功したことドメイン駆動設計 失敗したことと成功したこと
ドメイン駆動設計 失敗したことと成功したこと
 
コルーチンの使い方
コルーチンの使い方コルーチンの使い方
コルーチンの使い方
 
Jenkinsfileのlintで救える命がある
Jenkinsfileのlintで救える命があるJenkinsfileのlintで救える命がある
Jenkinsfileのlintで救える命がある
 
共変戻り値型って知ってますか?
共変戻り値型って知ってますか?共変戻り値型って知ってますか?
共変戻り値型って知ってますか?
 
The Internals of "Hello World" Program
The Internals of "Hello World" ProgramThe Internals of "Hello World" Program
The Internals of "Hello World" Program
 
Fondamentaux java
Fondamentaux javaFondamentaux java
Fondamentaux java
 
Spectacular Future with clojure.spec
Spectacular Future with clojure.specSpectacular Future with clojure.spec
Spectacular Future with clojure.spec
 
Jenkins 再入門
Jenkins 再入門Jenkins 再入門
Jenkins 再入門
 
Clean code
Clean codeClean code
Clean code
 
Become A Security Master
Become A Security MasterBecome A Security Master
Become A Security Master
 
Clean Code II - Dependency Injection
Clean Code II - Dependency InjectionClean Code II - Dependency Injection
Clean Code II - Dependency Injection
 
[MOPCON 2022] 以 Kotlin Multiplatform 制霸全平台
[MOPCON 2022] 以 Kotlin Multiplatform 制霸全平台[MOPCON 2022] 以 Kotlin Multiplatform 制霸全平台
[MOPCON 2022] 以 Kotlin Multiplatform 制霸全平台
 
xv6のコンテキストスイッチを読む
xv6のコンテキストスイッチを読むxv6のコンテキストスイッチを読む
xv6のコンテキストスイッチを読む
 
コードで学ぶドメイン駆動設計入門
コードで学ぶドメイン駆動設計入門コードで学ぶドメイン駆動設計入門
コードで学ぶドメイン駆動設計入門
 
serviceクラスをやめようサブクラスを使おう
serviceクラスをやめようサブクラスを使おうserviceクラスをやめようサブクラスを使おう
serviceクラスをやめようサブクラスを使おう
 
Spring ioc
Spring iocSpring ioc
Spring ioc
 
PHP版レガシーコード改善に役立つ新パターン #wewlc_jp
PHP版レガシーコード改善に役立つ新パターン #wewlc_jp PHP版レガシーコード改善に役立つ新パターン #wewlc_jp
PHP版レガシーコード改善に役立つ新パターン #wewlc_jp
 
The Art of Unit Testing - Towards a Testable Design
The Art of Unit Testing - Towards a Testable DesignThe Art of Unit Testing - Towards a Testable Design
The Art of Unit Testing - Towards a Testable Design
 
Map
MapMap
Map
 

En vedette

En vedette (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
 

Similaire à PHP 良好實踐 (Best Practice)

JavaScript for PHP developers
JavaScript for PHP developersJavaScript for PHP developers
JavaScript for PHP developers
Stoyan Stefanov
 

Similaire à 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
 
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
 

Plus de Win 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 Report
Win Yu
 
Tpr star tree
Tpr star treeTpr star tree
Tpr star tree
Win 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 operator
Win 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 Search
Win Yu
 

Plus 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
 

Dernier

%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
masabamasaba
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
shinachiaurasa2
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
VictoriaMetrics
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
masabamasaba
 

Dernier (20)

Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
tonesoftg
tonesoftgtonesoftg
tonesoftg
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Harnessing ChatGPT - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT  - Elevating Productivity in Today's Agile EnvironmentHarnessing ChatGPT  - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT - Elevating Productivity in Today's Agile Environment
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 

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