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

CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭するCEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
Yoshifumi Kawai
 
Effective Modern C++ 勉強会#3 Item 15
Effective Modern C++ 勉強会#3 Item 15Effective Modern C++ 勉強会#3 Item 15
Effective Modern C++ 勉強会#3 Item 15
Mitsuru Kariya
 
ドメイン駆動設計 ( DDD ) をやってみよう
ドメイン駆動設計 ( DDD ) をやってみようドメイン駆動設計 ( DDD ) をやってみよう
ドメイン駆動設計 ( DDD ) をやってみよう
増田 亨
 
Route 路由控制
Route 路由控制Route 路由控制
Route 路由控制
Shengyou Fan
 
短期間で新技術を学ぶ技術
短期間で新技術を学ぶ技術短期間で新技術を学ぶ技術
短期間で新技術を学ぶ技術
Takafumi ONAKA
 
オブジェクト指向プログラミングのためのモデリング入門
オブジェクト指向プログラミングのためのモデリング入門オブジェクト指向プログラミングのためのモデリング入門
オブジェクト指向プログラミングのためのモデリング入門
増田 亨
 
C#とILとネイティブと
C#とILとネイティブとC#とILとネイティブと
C#とILとネイティブと
信之 岩永
 
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
DDD x CQRS   更新系と参照系で異なるORMを併用して上手くいった話DDD x CQRS   更新系と参照系で異なるORMを併用して上手くいった話
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
Koichiro Matsuoka
 
Java SE 9の紹介: モジュール・システムを中心に
Java SE 9の紹介: モジュール・システムを中心にJava SE 9の紹介: モジュール・システムを中心に
Java SE 9の紹介: モジュール・システムを中心に
Taku Miyakawa
 
Android カスタムROMの作り方
Android カスタムROMの作り方Android カスタムROMの作り方
Android カスタムROMの作り方
Masahiro Hidaka
 
某S社のddd(メイリオ)
某S社のddd(メイリオ)某S社のddd(メイリオ)
某S社のddd(メイリオ)
kumake
 
Virtual machine and javascript engine
Virtual machine and javascript engineVirtual machine and javascript engine
Virtual machine and javascript engine
Duoyi Wu
 
Rancher/Kubernetes入門ハンズオン資料~第2回さくらとコンテナの夕べ #さくらの夕べ 番外編
 Rancher/Kubernetes入門ハンズオン資料~第2回さくらとコンテナの夕べ #さくらの夕べ 番外編 Rancher/Kubernetes入門ハンズオン資料~第2回さくらとコンテナの夕べ #さくらの夕べ 番外編
Rancher/Kubernetes入門ハンズオン資料~第2回さくらとコンテナの夕べ #さくらの夕べ 番外編
Masahito Zembutsu
 
Goでかんたんソースコードの静的解析
Goでかんたんソースコードの静的解析Goでかんたんソースコードの静的解析
Goでかんたんソースコードの静的解析
Takuya Ueda
 
例外處理實務
例外處理實務例外處理實務
例外處理實務
Jeff Chu
 
ソフトウェア開発における『知の高速道路』
ソフトウェア開発における『知の高速道路』ソフトウェア開発における『知の高速道路』
ソフトウェア開発における『知の高速道路』
Yoshitaka Kawashima
 
実践的な設計って、なんだろう?
実践的な設計って、なんだろう?実践的な設計って、なんだろう?
実践的な設計って、なんだろう?
増田 亨
 
C#で速度を極めるいろは
C#で速度を極めるいろはC#で速度を極めるいろは
C#で速度を極めるいろは
Core Concept Technologies
 
Objective-C のキャストと Swift の型変換を比べてみる #akibaswift
Objective-C のキャストと Swift の型変換を比べてみる #akibaswiftObjective-C のキャストと Swift の型変換を比べてみる #akibaswift
Objective-C のキャストと Swift の型変換を比べてみる #akibaswift
Tomohiro Kumagai
 
GUI アプリケーションにおける MVC
GUI アプリケーションにおける MVCGUI アプリケーションにおける MVC
GUI アプリケーションにおける MVC
Yu Nobuoka
 

What's hot (20)

CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭するCEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
 
Effective Modern C++ 勉強会#3 Item 15
Effective Modern C++ 勉強会#3 Item 15Effective Modern C++ 勉強会#3 Item 15
Effective Modern C++ 勉強会#3 Item 15
 
ドメイン駆動設計 ( DDD ) をやってみよう
ドメイン駆動設計 ( DDD ) をやってみようドメイン駆動設計 ( DDD ) をやってみよう
ドメイン駆動設計 ( DDD ) をやってみよう
 
Route 路由控制
Route 路由控制Route 路由控制
Route 路由控制
 
短期間で新技術を学ぶ技術
短期間で新技術を学ぶ技術短期間で新技術を学ぶ技術
短期間で新技術を学ぶ技術
 
オブジェクト指向プログラミングのためのモデリング入門
オブジェクト指向プログラミングのためのモデリング入門オブジェクト指向プログラミングのためのモデリング入門
オブジェクト指向プログラミングのためのモデリング入門
 
C#とILとネイティブと
C#とILとネイティブとC#とILとネイティブと
C#とILとネイティブと
 
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
DDD x CQRS   更新系と参照系で異なるORMを併用して上手くいった話DDD x CQRS   更新系と参照系で異なるORMを併用して上手くいった話
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
 
Java SE 9の紹介: モジュール・システムを中心に
Java SE 9の紹介: モジュール・システムを中心にJava SE 9の紹介: モジュール・システムを中心に
Java SE 9の紹介: モジュール・システムを中心に
 
Android カスタムROMの作り方
Android カスタムROMの作り方Android カスタムROMの作り方
Android カスタムROMの作り方
 
某S社のddd(メイリオ)
某S社のddd(メイリオ)某S社のddd(メイリオ)
某S社のddd(メイリオ)
 
Virtual machine and javascript engine
Virtual machine and javascript engineVirtual machine and javascript engine
Virtual machine and javascript engine
 
Rancher/Kubernetes入門ハンズオン資料~第2回さくらとコンテナの夕べ #さくらの夕べ 番外編
 Rancher/Kubernetes入門ハンズオン資料~第2回さくらとコンテナの夕べ #さくらの夕べ 番外編 Rancher/Kubernetes入門ハンズオン資料~第2回さくらとコンテナの夕べ #さくらの夕べ 番外編
Rancher/Kubernetes入門ハンズオン資料~第2回さくらとコンテナの夕べ #さくらの夕べ 番外編
 
Goでかんたんソースコードの静的解析
Goでかんたんソースコードの静的解析Goでかんたんソースコードの静的解析
Goでかんたんソースコードの静的解析
 
例外處理實務
例外處理實務例外處理實務
例外處理實務
 
ソフトウェア開発における『知の高速道路』
ソフトウェア開発における『知の高速道路』ソフトウェア開発における『知の高速道路』
ソフトウェア開発における『知の高速道路』
 
実践的な設計って、なんだろう?
実践的な設計って、なんだろう?実践的な設計って、なんだろう?
実践的な設計って、なんだろう?
 
C#で速度を極めるいろは
C#で速度を極めるいろはC#で速度を極めるいろは
C#で速度を極めるいろは
 
Objective-C のキャストと Swift の型変換を比べてみる #akibaswift
Objective-C のキャストと Swift の型変換を比べてみる #akibaswiftObjective-C のキャストと Swift の型変換を比べてみる #akibaswift
Objective-C のキャストと Swift の型変換を比べてみる #akibaswift
 
GUI アプリケーションにおける MVC
GUI アプリケーションにおける MVCGUI アプリケーションにおける MVC
GUI アプリケーションにおける MVC
 

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

top nidhi software solution freedownload
top nidhi software solution freedownloadtop nidhi software solution freedownload
top nidhi software solution freedownload
vrstrong314
 
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
 
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
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
Georgi Kodinov
 
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
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
abdulrafaychaudhry
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
wottaspaceseo
 
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)
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
Fermin Galan
 
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, BetterWebinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
XfilesPro
 
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
 
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume MontevideoVitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke
 
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Globus
 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
Philip Schwarz
 
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
 
Graphic Design Crash Course for beginners
Graphic Design Crash Course for beginnersGraphic Design Crash Course for beginners
Graphic Design Crash Course for beginners
e20449
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
Adele Miller
 
Into the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdfInto the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdf
Ortus Solutions, Corp
 
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus
 
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.ILBeyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Natan Silnitsky
 

Recently uploaded (20)

top nidhi software solution freedownload
top nidhi software solution freedownloadtop nidhi software solution freedownload
top nidhi software solution freedownload
 
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...
 
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...
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
 
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
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
 
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, BetterWebinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
 
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
 
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume MontevideoVitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume Montevideo
 
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...
 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
 
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
 
Graphic Design Crash Course for beginners
Graphic Design Crash Course for beginnersGraphic Design Crash Course for beginners
Graphic Design Crash Course for beginners
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
 
Into the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdfInto the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdf
 
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024
 
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.ILBeyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
 

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