Skip to content

いまさら!PHPお作法入門

公開日:

東京都渋谷区千駄ヶ谷ピクシブ株式会社で開催された『pixiv SUMMER BOOT CAMP 2017』でレギュラーセッション(20分)として発表しました。

Download PDF

スライドテキスト

Page 1

いまさら! お作法入門

Modern...? PHP manners guide

pixiv SUMMER BOOT CAMP 2017東京都渋谷区千駄ヶ谷 #pixiv_BOOTCAMP

Page 2

Page 3

講義資料です

Page 4

このスライドはWebで公開します(メモはとらなくても良いです、の意味)

Page 5

お前誰よ

  • うさみけんた (@tadsan) / Zonu.EXE
  • GitHub/Packagistでは id: zonuexe
  • 2012年11月にピクシブ株式会社に入社
  • Emacs Lisper, PHPer
  • 入社前は自宅警備をしながらRuby書いてた
  • Qiitaに記事を書いたり変なコメントしてるよ

Page 6

おぼえてほしいこと

Page 7

コードは動けばええんや

😄

Page 8

反論?

Page 9

最高のコードは動くコード

コードの美しさはユーザーに見えない

汚ないコードでも、動けばユーザーにとっては最大の価値を生み出す

Page 10

最高のコードは動くコード

コードの美しさはユーザーに見えない

汚ないコードでも、動けばユーザーにとっては最大の価値を生み出す

Page 11

全ての物事には一長一短がある

読めないコードはメンテできない

機能拡張しにくい

ある日とつぜん動かなくなる

仕様変更に追従困難

Page 12

動けばの前提が崩れたコードは価値が大暴落

Page 13

まとめると

ソースコードの美醜は現在のプログラムの価値とは関係ない

ただし美しくないコードは将来の可能性を閉ざしかねない

Page 14

リーダブルそのために「読める」コードの追求とお作法の共有が必要

Page 15

今回は大仰な設計の話ではなく、単にコーディングルールの共有をします

Page 16

PSR?

Page 17

その話はあとで

Page 18

<?phpからはじめよ

ファイル先頭は必ず<?phpを書きます

必要ならnamespaceとuseを書きます

include_once 必要なければ書きません

そのあとクラス定義(だけ)を書きます

ファイル最後に ?> は書きません

Page 19

namespaceは必要か?

namespaceを利用すべきかは、プロジェクトごとの事情に強く依存します

pixiv-libでは原則として利用しません

テストコード(tests/)でだけ使ってる

pixiv.git内のプロジェクト単位では、利用されることもあります

Page 20

もしもnamespaceがなかったら

User_Commonのような擬似名前空間

namespaceとuseの解決は少し面倒

要はクラス名とファイル名の解決ができればオートローディングできます

User_Common → User/Common.php

Page 21

require/include_onceは最低限だけ

クラスローダーを登録することで、自動ローディングできる (遅延評価)

1ファイルにつき1クラスを定義する

関数定義などは基本的には初期化ファイルから読み込みます

(composer.jsonのautoload.files)

Page 22

?> を書かない理由

省略可能、書くメリットが皆無

PHPは <?php 〜 ?> の範囲外に書かれた文字列を出力します不随意にコード中に変な文字が混入したとき、文法エラーにもならず出力されかねないリスクがあります

Page 23

クラス定義

クラスの概要を一行で要約すること一行で説明が不可能なら、クラスが持つ責任は明らかに多すぎます

クラス継承は慎重に設計してください個人的な経験では継承よりも委譲やinterfaceの方がうまくいきます

Page 24

PHPDocの構造

/*** 概要(summary, 要約) ↓ 下は空行** 説明文(description)。クラスの説明を書きます。* ここには何行書いてもいいです。** 説明不足よりも能弁を尊べ。** @see https://zonuexe.github.io/phpDocumentor2-ja/references/phpdoc/basic-syntax.html*/final class Foo_BarModel implements ModelInterface{// ...

Page 25

クラスとPHPDoc

Page 26

メソッド定義

メソッドの概要を一行で要約し、引数と返り値の型をデザインします一行で説明できないメソッドはその存在の軸が容易に揺らいでいく複数の型の値を返すメソッドは機能が多すぎ、利用側が煩雑になる

Page 27

メソッドとPHPDoc

Page 28

http://nico.ms/kn1774

Page 29

これだけ覚えて帰ってね

タグ名

意味

@param引数を定義@param int $n1

@return返り値を定義@return int[]

@var変数/プロパティを定義@var int

@propertyマジックプロパティを定義@property int $id

Page 30

PHPDocの型

  • 「PHPの型」か「クラス名」を書く
  • 基本的な型
  • string, int, bool, float, array,

resource, null, true, false

  • 擬似型
  • callable, void(返り値を返さない)

https://zonuexe.github.io/phpDocumentor2-ja/references/phpdoc/types.html

Page 31

PHPDocの型

  • 複合型
  • 「intまたは文字列」 int|string
  • 値が並んだ配列
  • 「intが並んだ配列」 int[]

https://zonuexe.github.io/phpDocumentor2-ja/references/phpdoc/types.html

Page 32

なんでPHPなのにわざわざ型を書くの

Page 33

バグるのと型書くのどっちがええねん

😎

Page 34

PHPは動的プログラミング言語

静的型解析器(コンパイラ)は一般に実行前(コンパイル時)に変数や関数の型を特定するPHPのVM(インタプリタ)は、変数や関数の型は基本的に特定せず、実行時に動的型解析する

Page 35

PHPの多くのバグは実行時まで遅延する

Page 36

要は動かさないとわからない

Page 37

動かさなくてもバグを検出できるうれしみは大きい

Page 38

引数一覧で型を表示するところ

Page 39

型がめったくそなの叱ってくれ

Page 40

ループの話をしよう

Page 41

PHPのfor文は原則禁止

Page 42

PHPの配列は歯抜けになる

Page 43

foreachなら大丈夫

Page 44

引数一覧で型を表示するところ

Page 45

ループの中で補完が利かない

Page 46

きちんと型をつけ直す

Page 47

ループの中でも補完が利くよ

Page 48

PSR

PHP Standards Recommendations

PHP標準勧告

Page 49

PHP-FIG

PHP Framework Interop Group PHPフレームワーク相互運用グループ

Page 50

フレームワークやCMSを開発する組織の寄合

Page 51

2017年8月現在のメンバー

CakePHP, Composer, concrete5, Contao Open Source CMS, Drupal, eZ Publish, Horde, IBM i Toolkit, Icicle, Jackalope, Joomla, Lithium,Magento, PEAR, Phalcon, Phing, phpBB,phpDocumentor, PHPixie, Pimcore, PPI Framework, PrestaShop, PyroCMS, ReactPHP,Revive Adserver, Sculpin, SilverStripe, Slim,Stash, Stormpath PHP SDK, SugarCRM,Symfony, Neos and Flow, Wikibase and Semantic MediaWiki, Yii framework, Zend Framework 2,Zikula

http://www.php-fig.org/members/

Page 52

相互運用??

Page 53

Page 54

Page 55

Page 56

ばらばらに作ってたのを仕様化して相互に利用しやすくしようぜ!……みたいな人類の夢

Page 57

みんな仲良く



Page 58

PSR-0 Autoloading Standard

クラス名とファイルを一致させる規則

ベンダー名を名前空間のトップにする

\と_をDIRECTORY_SEPARATORに置換

2014年にPSR-4に置換されて廃止

Page 59

PSR-1 Basic Coding Standard

PHPコードは<?php … ?>または<?= … ?>

文字コードはUTF-8(BOMなし)

クラスや定義のファイルは分けて、副作用のある処理とは分割する

クラス名はStudlyCaps(UpperCamlCase)、メソッド名はlowerCamelCase、プロパティ名は規定しないけど一貫せよ

Page 60

PSR-2 Coding Style Guide

具体的なコーディングスタイルガイドPSRに準拠したライブラリが必ず遵守しなければいけないルールではなく、プロジェクトごとにガイドラインを決めるための叩き台↑ここ誤解してるひとが意外と多い

Page 61

クラスや関数など定義の{は改行

final class Hoge implements Fizz{function hoge($a, $b){return $a + $b;}}function foo(){

Page 62

そのほかの文の{は改行しない

$is_hoge = hoge();if ($is_hoge) {foo();} elseif (piyo($a)) {bar();}foreach ($values as $i => $v) {$values[$i] = piyopiyo($v);}

Page 63

演算子などは、きっちり空白

$str = "もじれつ";$str2 = $str . "!";

$n = 2;$m = 5;return foo($n, $m) * 2;

Page 64

PSR-4 Autoloading Standard

クラス名とファイルを一致させる規則

ベンダー名を名前空間のトップにする

\と_をDIRECTORY_SEPARATORに置換

サブ名前空間とベースディレクトリの概念が導入

Page 65

わしのPSRは17まであるぞ

Page 66

さて

Page 67

ルールは破るためにある

😎

Page 68

所詮はフレームワーク開発者どもの間の規則

😎

Page 69

プライベートなプロジェクトがPSRに厳密に従っても得られるものは乏しい

Page 70

プライベートなプロジェクトがPSRに厳密に従っても得られるものは乏しい

Page 71

厳密に

Page 72

都合のいいところだけ持ってくればいい

😊

Page 73

規則とは理想的には自分たちの足を撃ち抜かないためにある

Page 74

実態に即しない規則は改正すべし

Page 75

よく聞く例

PSR-2を魔改造カスタマイズ

インデントはスペースではなくタブ

{ の改行位置が気に入らないので統一

要はコード内で統一感があれば良い

Page 76

pixivの例

PSR-1, PSR-2はそのまま採用

行の長さの規制だけ緩めてる

PSR-0, PSR-4は採用しない

相互運用されないアプリケーションコードなどはvendorは厳密に意識しなくても別に問題が起こらない

Page 77

クラスのオートロード

PSR-0, PSR-4の規約通りに配置するだけで、Composerがいい感じにロードできる

まあ文字列マッチしてるだけなので、ベンダー名とか省略しても実際動く

そもそもローダーを自作してもいい

Page 78

まとめ

Page 79

まとめ

(これに限らず)ルールやお作法は、われわれ人類が自爆しないための鎖

ルールが作られた背景には事情があるので、それを共有していくのが重要

「どうしてこうなってるの」と感じたら質問していこう