今の現場では比較的、いわゆるモダンな環境で開発をしていることもあり、非常に勉強になります。
今の現場に入る前に10年近くはPHPをやっていますが、まだまだ知らないこと(といいますか新しいことがふえてきます)、つかいこなせてないことがあるなあという感じです。
直近1年ぐらいで使い方まで含めて頻繁につかいそうなものなどを。
Contents
アーキテクチャに関して
ものすごく単純にいってしまうとディレクトリの構造分けなのですが、MVCとかDDDとかいろいろな概念がありますよね・・こういってしまうと身も蓋もないですが、現場の事情によってどこまでもとめるか、もとめられるかがかわってくるので、それを無視して過度にこだわらないほうが良いと思います。
ポイントとしては以下のような点でしょうか。
- 過度に複雑すぎないか
- 目的のリソースがすぐに探せるか
- 工数削減に役立っているか
- ルールとしてわかりやすいか
今の現場ではざっくりと以下のようにわけてますが大変わかりやすく理想的だと思います。
大まかなデザインパターン
DDDが何たるものか、など設計思想に関する深いところはわからないのですが、現在の現場では大きくいかのように判断して考えています。
Controller・・エントリーポイントのみ
UseCase・・Transacion単位。基本的にビジネスロジックの集合体。_invokeメソッドで呼び出す。
Serivce・・再利用可能なビジネスロジック。基本的にTransactionを貼らない
これ以外のこまかいパーツに関しては以下で。
命名
自分があまり意識できていない部分でした。
コーディングでは多少考えていたのですが、ディレクトリ構造などでも流用できます。
Controllerではメソッドをindex 、 show 、 create 、 store 、 edit 、 update 、 destroyのみにする。(これで分けられない場合、基本的にControllerを複数の名詞でわける)
UserCaseに関してもディレクトリを名詞で深くわけ、実際のファイルに関してはindex 、 show 、 create 、 store 、 edit 、 update 、 destroyのみにする。などすると何をやっているかがすごくわかりやすいです。
インフラ、外部サービス周りに関して
テストコードについてよく知らなかったときは、自動テスト完備なんて都市伝説だと思っていたんですよね。
まずデータベースをどうするのかということと外部サービスとの連携をどうするのかというところがネックになっていたので・・
結果として以下のような対象方法をとれば可能です。
S3
- localstackなどの環境を使う(実際にあがっているCSVを見たい時などに使います。)
API
- DI化して、ローカル、ステージング以降の環境をわけるなど。
- テストコード時はMock化してきめうちの値を返すなど。(ただMockは限界があるので、APIがかえってくるまでの暫定的な対応)
状態再現
10ヶ所以上の現場で仕事をしてきましたが、大体どの現場でも重要になるのが
- 状態の再現(ようは投入すべき前提データの用意)
- 状態の追跡(ログなどをいかにあつめるか)
- エラー時の情報収集(エラーハンドリング)
ですね。
ここで状態の再現に関しては明確な解があり、
migration+seederかと思います。
これがあるとないとで開発効率が全然ちがいますね・・・今の現場ではそれらをしっかりやっているので(テストケースごとにseederを用意している)、開発がめちゃくちゃ楽です。
昔はローカルで開発サーバーみたいなのを作って、データを適当に探して、そこでテストしてましったっけ・・ようやっとたなと思ってます。
個人的には深い技術選定よりもここらへんをしっかりやるほうが工数の削減につながるのでは・・・と思います。
コーディングに関して
型の意識
当たり前かもしれませんが、今までが比較的緩い現場でそだったので、復習の意味もこめて
- 型決め必須、タイプヒンティング必須、
- 意味ある変数はenum化
- 連想配列をできるだけつかわず、Object化
- forceFillやcreate,fillableなど型を意識しないものは禁止
- 2重イコール禁止、empty禁止
規約ツール導入
細かい規約とか人がいちいち指摘するの大変ですよね・・・スペースのちょっとした指摘とかいちいち指摘されると気分害する人もいるし・・・(汗) 私なんかも細かい指摘をするのはちょっと気後れしちゃうほうです。
第一段階としてエディタで気づけるようにしておくのはmustだと思いますが、徹底したい場合に自動化した方が絶対良いです。
今の現場ではreviewdogというツールをつかっています。
徹底したい場合には、エラーが出たらそもそもマージできないなど仕組み化をする必要があります
ValueObjectの活用
DDDの思想の一部だと思いますが、
品番、コード値、伝票番号などプロジェクト内で仕様が決まっている値などはstringで定義するのではなくValueObjectとして定義しましょう。
こうすることで、下記の様なメリットがあります。
- これらの値の担保をすることができる
- コードが仕様書がわりになる
構造をわかりやすく。過度に抽象化しない。
若干、テーマが抽象的なのですが個人的に少し目から鱗でした。
抽象的なクラスや変数をつかうと可読性がおちます。引数や戻り値も少ない方がいい・・と思っていますが、内部を隠蔽してしまってわかりにくくなるため、ずらずらかくほうが親切で丁寧ということもあります。
nullがらみ対策
コードの節約において多分No1の貢献度でしょう。私は大好き(汗)
callback系
一番の使いどことしてはCSVダウンロードやS3へのアップロードなどInとOutで共通処理があり、内部の処理自体が動的になる場合、引数が関数になるため、callbackが使われることが多いと思います。
これだけかくとわかりにくいですが・・・(汗)
継承とIFの違い
継承に関しては子供と親で文字通り継承関係がないといけないですが、IFは単純にメソッド名と引数と戻り値の統一だけです。
全く関連がないけど戻り値を統一したいときなどにIFが使えます。
ここからはもう少し細かいネタを・・
メソッドチェーン系
再認識すべきネタですかね。数年前に書いた記事で今でもそれほど変わってないかな・・という気がします。
あえて付け加えるとするとそのモデルが持っている属性的なメソッド(伝票番号モデルからのgetCode())やfirstWhereぐらいでしょうか・・
macro
コレクションのカスタマイズや登録です。転置という処理(縦横の変換)は明細系の処理でよくでてきますが、これを登録しておき、使っていくという手法です。
こんなことができるのか・・と驚嘆しました。
chunk
大量のデータを取得してぐるぐるする場合など。今までは自分だったらgroupByをつかっていることが多かった気がします。
chunkは少しずつメモリにわけてとる手法でして、大量のデータを取得する際にメモリを節約しながらデータを取得する際に向いています。その分、スピードはあまり速くないようです。
他にcursorなんかもあります。
Laravel の取得系メソッド cursor() や chunk() を徹底比較する
trait
継承関係をつくるほどではないけど、複数のModelに似たようなメソッドをつかいたいときなどです。
PHPは基本、多重継承ができず親は1つですので、その場合、この考え方が必要になってきます。
あまりガンガン使うのは問題ですが、ちょっとした際に使えるとコード量が節約できます。
firstOrNew
超ピンポイントですが、新規と更新時の処理を共通化できるという点で使い所が多いです。
Laravel firstOrCreate と firstOrNewの違いと、create、newしたか判定する方法
プロモーション
コード節約への貢献度がとにかく高いので積極的に活用しましょう。
まとまりないですが、一旦ここら辺で。