はじめに
この記事は完全にポエムです。心の叫びです。
現在、PHPのLaravelで、オープンソースプロジェクト「Exment」を開発しています。
当然GitHubにもソースコードを公開しているのですが、ソースを公開すると、いろんな所が気になって仕方なくなります。
- 自分のスキルはどうなんだろう??
- ソース読んだ人に「こいつスキルねーなwwww」と思われてないかな・・・
- 「分かりづらいわ」と思われてないかな
- この書き方で本当に問題ないのか
などなど。元々超ネガティブなのですが、そんなことがすごく気になってきます。
この記事では、具体的にどんなことが気になって仕方ないのか?
それをまとめて記載することにしました。
完全にとりとめのない話です。
気になって仕方ない箇所
汎用メソッドをどこに書くか
現在、どんな所からも呼び出される汎用メソッドは、Helpers.phpというphpファイルに記載しています。
これはクラスすら持たず、グローバル関数をひたすら量産する記述です。
例えば
- URL結合のurl_join
- マニュアルへのURLを取得するgetManualUrl
- そのリクエスト中だけのセッション(のようなもの)に値をセットするsetRequestSession
などなど。このような関数を大量に作成しています。
//// 一部抜粋
<?php
if (!function_exists('getManualUrl')) {
function getManualUrl($uri = null)
{
// ...
}
}
if (!function_exists('url_join')) {
/**
* Join FilePath.
*/
function url_join(...$pass_array)
{
// ...
}
}
当初は、あらゆる汎用メソッドを大量にここに入れていました。
ですがそのうち、「ここに書きすぎると、重たくなりすぎるんじゃないか??」ということが気になってきます。
あるとあらゆるものをここに書くと、ごっちゃになるんじゃないか??という不安です。
(将来的に5000行ぐらいになりそう)
なので、移行できるものはクラス内に移行することにしました。
例えばModelに関するものは、Modelのインスタンスメソッド、クラスメソッドとして実装するという方法です。
例:CustomView.php
//// 一部抜粋
<?php
namespace Exceedone\Exment\Model;
class CustomView extends ModelBase
{
// custom function --------------------------------------------------
/**
* set laravel-admin grid using custom_view
*/
public function setGrid($grid)
{
// ...
}
/**
* set DataTable using custom_view
* @return list(array, array) headers, bodies
*/
public function getDataTable($datalist, $options = [])
{
// ...
}
/**
* get default view using table
*/
public static function getDefault($tableObj)
{
// ...
}
protected static function createDefaultView($tableObj)
{
// ...
}
}
特定のclassに依存する関数は、このように書いた方が圧倒的に読みやすくなります。最初からこうしろ
が、このように書くと、今度はこんなことが気になってきました。
- 2つ以上のclassに依存する関数はどっちに書けばいいだろう?後で分からなくならないか
- LaravelのModel内にメソッドを実装すると、Modelめっちゃ重くならないか??
- classのインスタンスメソッドで実装した場合、インスタンスそのものがnullになった場合、関数を呼び出せないんじゃないか??(Helperクラスに記載すれば、nullの場合の制御がメソッド内部で出来るけど、インスタンスメソッドの場合、呼び出し側で制御しないといけないからめんどくさい)
などなど。こんなことが気になってきている所です。
特に3番目がけっこう重たいです。グローバル関数として書いていた頃には生じていなかった問題が発生してしまいました。
これの適切な解決方法が、まだ分かっていません。
さらに、例えば機能ごとにHelperクラスを作成することも少し考えました。
例えばファイルを触る「FileHelper」、Web系の「WebHelper」などです。このHelperにstaticメソッドをどんどん追加するイメージです。
ですが、こういったHelperクラスを作っちゃうともうホント訳がわからなくなりそうなので、今現在はやめています。
メソッドを書く順番
これはルール決めすればいいだけの話なのですが、書いていて直面した問題です。
クラス内にメソッドを書く場合、どういった順序で書くのがベストなのか??というところが気になってきました。
メソッド(ならびに近いもの)には、ざっくり以下の種類があると思っています。
- コンストラクタ
- publicでnon static
- publicでstatic
- protectedでnon static
- protectedでstatic
さらにLaravelの場合、こういったものも追加されます。
- Relationをはるための関数(hasMany系)
- DBにアクセスするためのプロパティを増やすための関数(getXXXXAttribute, setXXXXAttribute)
- 既定のEloquentの処理を拡張するための関数(bootとか)
こういった関数を、どういった順番で書くのがベストなんだろう?というのがすごく気になってしまっています。
いま現状では、**「関数の役割」**で固めています。
アクセシビリティに関わらず、関連するメソッドはなるべく固めて書くことで、あとで読みやすくしています。
・・・が、ホントにそれでいいの?ということが気になって仕方ないです。
先輩エンジニアに聞くと、「アクセシビリティで上から書くのがいいんじゃん?」という話だったんですが、好みの問題なのか気になってます。
命名規則ぐちゃぐちゃ問題
ちゃんと明確に、命名規則を決めずにスタートしてしまったのですが(この時点ですでに大問題)、
やっていてひとつ気になる問題が生じました。
基本的にLaravel(PHP)の命名規則は以下と考えています。
- クラス名:パスカルケース(PascalCase)
- メソッド名:キャメルケース(camelCase)
- 定数:CONST_CASE形式
- プロパティ、変数名:キャメルケース(camelCase)
- データベースのテーブル、列名:スネークケース(snake_case)
この中で、下2つに矛盾を感じています。
「LaravelのModelから列の値を取得する」「その値を一時的に変数に代入する」といった処理を行う場合、
$XXXX = CustomTable::find(1)->table_name;
と、このように書くと思いますが、このXXXXをキャメルケースで書くかスネークケースで書くかという問題です。
ルールに従うなら、変数なのでキャメルケース$tableNameになると思います。
が、データベースの値をそのまま代入するだけなのに、わざわざキャメルケースに変換するのって超面倒です。
かといって、今度はスネークケース$table_nameで書くとすると、ソースコード上でここだけスネークケースになります。
ちゃんと読めば、「あ、これはDBの値なんだ」と違いが分かるのですが、ぱっと見だと変数にキャメルケースとスネークケースが混在することになってます。それってちょっと微妙じゃないですか??
最終的に、DBに関係ない値でも、スネークケースで変数やプロパティを書いてしまっています。現にExmentではそうなっちゃっています。
まとめ
こんな感じで、ソースコードを公開すると、色んなことが気になってしまっています。
今回のような内容は、色んな理論がありそうですね。
何かアドバイスあれば教えていただきたいです。