SlideShare a Scribd company logo
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.

More Related Content

What's hot

Interceptors: Into the Core of Pedestal
Interceptors: Into the Core of PedestalInterceptors: Into the Core of Pedestal
Interceptors: Into the Core of Pedestal
Kent Ohashi
 
キメるClojure
キメるClojureキメるClojure
キメるClojure
Yoshitaka Kawashima
 
The art of readable code ( pdf )
The art of readable code ( pdf )The art of readable code ( pdf )
The art of readable code ( pdf )
Jocelyn Hsu
 
運用構築技術者の為のPSプログラミング第2回
運用構築技術者の為のPSプログラミング第2回運用構築技術者の為のPSプログラミング第2回
運用構築技術者の為のPSプログラミング第2回
Shigeharu Yamaoka
 
Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門
Ryosuke Uchitate
 
Laravel Design Patterns
Laravel Design PatternsLaravel Design Patterns
Laravel Design Patterns
Bobby Bouwmann
 
Advanced JavaScript
Advanced JavaScriptAdvanced JavaScript
Advanced JavaScript
Nascenia IT
 
Pipeline oriented programming
Pipeline oriented programmingPipeline oriented programming
Pipeline oriented programming
Scott Wlaschin
 
5. Destructuring | ES6 | Assignment
5. Destructuring | ES6 | Assignment 5. Destructuring | ES6 | Assignment
5. Destructuring | ES6 | Assignment
pcnmtutorials
 
安全なWebアプリケーションの作り方2018
安全なWebアプリケーションの作り方2018安全なWebアプリケーションの作り方2018
安全なWebアプリケーションの作り方2018
Hiroshi Tokumaru
 
Laravel の paginate は一体何をやっているのか
Laravel の paginate は一体何をやっているのかLaravel の paginate は一体何をやっているのか
Laravel の paginate は一体何をやっているのか
Shohei Okada
 
Real Life Clean Architecture
Real Life Clean ArchitectureReal Life Clean Architecture
Real Life Clean Architecture
Mattia Battiston
 
Js: master prototypes
Js: master prototypesJs: master prototypes
Js: master prototypes
Barak Drechsler
 
Domain Modeling Made Functional (DevTernity 2022)
Domain Modeling Made Functional (DevTernity 2022)Domain Modeling Made Functional (DevTernity 2022)
Domain Modeling Made Functional (DevTernity 2022)
Scott Wlaschin
 
Jbatch実践入門 #jdt2015
Jbatch実践入門 #jdt2015Jbatch実践入門 #jdt2015
Jbatch実践入門 #jdt2015
Norito Agetsuma
 
リッチなドメインモデル 名前探し
リッチなドメインモデル 名前探しリッチなドメインモデル 名前探し
リッチなドメインモデル 名前探し
増田 亨
 
Command Bus To Awesome Town
Command Bus To Awesome TownCommand Bus To Awesome Town
Command Bus To Awesome Town
Ross Tuck
 
T119_5年間の試行錯誤で進化したMVPVMパターン
T119_5年間の試行錯誤で進化したMVPVMパターンT119_5年間の試行錯誤で進化したMVPVMパターン
T119_5年間の試行錯誤で進化したMVPVMパターン
伸男 伊藤
 
Domain Driven Design with the F# type System -- F#unctional Londoners 2014
Domain Driven Design with the F# type System -- F#unctional Londoners 2014Domain Driven Design with the F# type System -- F#unctional Londoners 2014
Domain Driven Design with the F# type System -- F#unctional Londoners 2014
Scott Wlaschin
 

What's hot (20)

Interceptors: Into the Core of Pedestal
Interceptors: Into the Core of PedestalInterceptors: Into the Core of Pedestal
Interceptors: Into the Core of Pedestal
 
キメるClojure
キメるClojureキメるClojure
キメるClojure
 
The art of readable code ( pdf )
The art of readable code ( pdf )The art of readable code ( pdf )
The art of readable code ( pdf )
 
Optional in Java 8
Optional in Java 8Optional in Java 8
Optional in Java 8
 
運用構築技術者の為のPSプログラミング第2回
運用構築技術者の為のPSプログラミング第2回運用構築技術者の為のPSプログラミング第2回
運用構築技術者の為のPSプログラミング第2回
 
Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門
 
Laravel Design Patterns
Laravel Design PatternsLaravel Design Patterns
Laravel Design Patterns
 
Advanced JavaScript
Advanced JavaScriptAdvanced JavaScript
Advanced JavaScript
 
Pipeline oriented programming
Pipeline oriented programmingPipeline oriented programming
Pipeline oriented programming
 
5. Destructuring | ES6 | Assignment
5. Destructuring | ES6 | Assignment 5. Destructuring | ES6 | Assignment
5. Destructuring | ES6 | Assignment
 
安全なWebアプリケーションの作り方2018
安全なWebアプリケーションの作り方2018安全なWebアプリケーションの作り方2018
安全なWebアプリケーションの作り方2018
 
Laravel の paginate は一体何をやっているのか
Laravel の paginate は一体何をやっているのかLaravel の paginate は一体何をやっているのか
Laravel の paginate は一体何をやっているのか
 
Real Life Clean Architecture
Real Life Clean ArchitectureReal Life Clean Architecture
Real Life Clean Architecture
 
Js: master prototypes
Js: master prototypesJs: master prototypes
Js: master prototypes
 
Domain Modeling Made Functional (DevTernity 2022)
Domain Modeling Made Functional (DevTernity 2022)Domain Modeling Made Functional (DevTernity 2022)
Domain Modeling Made Functional (DevTernity 2022)
 
Jbatch実践入門 #jdt2015
Jbatch実践入門 #jdt2015Jbatch実践入門 #jdt2015
Jbatch実践入門 #jdt2015
 
リッチなドメインモデル 名前探し
リッチなドメインモデル 名前探しリッチなドメインモデル 名前探し
リッチなドメインモデル 名前探し
 
Command Bus To Awesome Town
Command Bus To Awesome TownCommand Bus To Awesome Town
Command Bus To Awesome Town
 
T119_5年間の試行錯誤で進化したMVPVMパターン
T119_5年間の試行錯誤で進化したMVPVMパターンT119_5年間の試行錯誤で進化したMVPVMパターン
T119_5年間の試行錯誤で進化したMVPVMパターン
 
Domain Driven Design with the F# type System -- F#unctional Londoners 2014
Domain Driven Design with the F# type System -- F#unctional Londoners 2014Domain Driven Design with the F# type System -- F#unctional Londoners 2014
Domain Driven Design with the F# type System -- F#unctional Londoners 2014
 

Viewers also liked

用 Bitbar Tool 寫 Script 自動擷取外幣
用 Bitbar Tool 寫 Script 自動擷取外幣用 Bitbar Tool 寫 Script 自動擷取外幣
用 Bitbar Tool 寫 Script 自動擷取外幣
Win Yu
 
與設計架構當朋友
與設計架構當朋友 與設計架構當朋友
與設計架構當朋友
Win Yu
 
Full Text Search In PostgreSQL
Full Text Search In PostgreSQLFull Text Search In PostgreSQL
Full Text Search In PostgreSQL
Karwin Software Solutions LLC
 
Mooink閱讀功能
Mooink閱讀功能Mooink閱讀功能
Mooink閱讀功能
ecrowdmedia
 
MakerBoard: MT7688 Emulator
MakerBoard: MT7688 EmulatorMakerBoard: MT7688 Emulator
MakerBoard: MT7688 Emulator
Fred 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 - 2018
Brian Solis
 

Viewers also liked (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 to 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.16
Ricardo Signes
 
Oops in php
Oops in phpOops in php
Generating Power with Yield
Generating Power with YieldGenerating Power with Yield
Generating Power with Yield
Jason Myers
 
Adding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsAdding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy Applications
Sam 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 UnCon
Rafael Dohms
 
JavaScript for PHP developers
JavaScript for PHP developersJavaScript for PHP developers
JavaScript for PHP developers
Stoyan Stefanov
 
Symfony2 - extending the console component
Symfony2 - extending the console componentSymfony2 - extending the console component
Symfony2 - extending the console component
Hugo Hamon
 
BEAR DI
BEAR DIBEAR DI
Drupal Development (Part 2)
Drupal Development (Part 2)Drupal Development (Part 2)
Drupal Development (Part 2)
Jeff Eaton
 
Feature flagsareflawed
Feature flagsareflawedFeature flagsareflawed
Feature flagsareflawed
Stephen Young
 
The Origin of Lithium
The Origin of LithiumThe Origin of Lithium
The Origin of Lithium
Nate 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 Better
Stephen Young
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in action
Jace 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 cliente
Leonardo Proietti
 
Taming Command Bus
Taming Command BusTaming Command Bus
Taming Command Bus
Krzysztof Menżyk
 
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
XSolve
 
Micropage in microtime using microframework
Micropage in microtime using microframeworkMicropage in microtime using microframework
Micropage in microtime using microframework
Radek Benkel
 
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
Rafael Dohms
 

Similar to 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
 

More from Win Yu

運用 Cloud Pub/Sub 實作 PIXNET 跨產品動態整合 #modernWeb2018
運用 Cloud Pub/Sub 實作 PIXNET 跨產品動態整合 #modernWeb2018運用 Cloud Pub/Sub 實作 PIXNET 跨產品動態整合 #modernWeb2018
運用 Cloud Pub/Sub 實作 PIXNET 跨產品動態整合 #modernWeb2018
Win Yu
 
AMP Roadshow Taipei
AMP Roadshow TaipeiAMP Roadshow Taipei
AMP Roadshow Taipei
Win Yu
 
Easy to recap AWS reinvent 2017
Easy to recap AWS reinvent 2017Easy to recap AWS reinvent 2017
Easy to recap AWS reinvent 2017
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
 
Pattern Recognition midterm Proposal
Pattern Recognition midterm ProposalPattern Recognition midterm Proposal
Pattern Recognition midterm Proposal
Win 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 classification
Win 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 orthogonality
Win 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 Win
Win 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
 

More from 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
 

Recently uploaded

Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
informapgpstrackings
 
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
Google
 
Cyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdfCyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdf
Cyanic lab
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSage
Globus
 
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Shahin Sheidaei
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
Globus
 
Corporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMSCorporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMS
Tendenci - The Open Source AMS (Association Management Software)
 
RISE with SAP and Journey to the Intelligent Enterprise
RISE with SAP and Journey to the Intelligent EnterpriseRISE with SAP and Journey to the Intelligent Enterprise
RISE with SAP and Journey to the Intelligent Enterprise
Srikant77
 
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdfDominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
AMB-Review
 
Large Language Models and the End of Programming
Large Language Models and the End of ProgrammingLarge Language Models and the End of Programming
Large Language Models and the End of Programming
Matt Welsh
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
Globus
 
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERRORTROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
Tier1 app
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
Max Andersen
 
Using IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New ZealandUsing IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New Zealand
IES VE
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Mind IT Systems
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
rickgrimesss22
 
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Globus
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
NYGGS Automation Suite
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
Ortus Solutions, Corp
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Globus
 

Recently uploaded (20)

Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
 
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
 
Cyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdfCyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdf
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSage
 
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
 
Corporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMSCorporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMS
 
RISE with SAP and Journey to the Intelligent Enterprise
RISE with SAP and Journey to the Intelligent EnterpriseRISE with SAP and Journey to the Intelligent Enterprise
RISE with SAP and Journey to the Intelligent Enterprise
 
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdfDominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
 
Large Language Models and the End of Programming
Large Language Models and the End of ProgrammingLarge Language Models and the End of Programming
Large Language Models and the End of Programming
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
 
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERRORTROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
 
Using IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New ZealandUsing IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New Zealand
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
 
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
 

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