Vapor Trail

明るく楽しく元気よく

初めてOSSにプルリク送って感じたこと

経緯

npxコマンドでNuxt.js + Vuetifyのプロジェクトテンプレートが簡単に作れるのだけど、初期テンプレートにあるVuetifyのロゴの解像度が低くてぼやけているのが気になって、「これなら自分でも直せそうだな」と思ったので修正してみることにした。

はじめてのプルリク

仕事では相談してわからないことをアドバイスしてもらったりされたことはあるが、プルリクを送ってコードレビューをしてもらった経験はない。

とりあえずリポジトリをフォークして、Qiitaの記事とか過去のクローズされたプルリクのやり取りとか見ながら、ブランチ切って・コード修正・テスト修正・コミット・プッシュして、見様見真似でプルリクを送った。
qiita.com

拒否されたらどうしようとか、これであってるのかなとか結構不安だったが、2度のレビューの後無事マージされた。

学び

  • 知らないツールに触れた
    AVAなんてテストフレームワーク知らなかったし、commitlintなんてものがあるなんて知らなかった。自分が触れることのないツールを使う機会を得て学びになった。

  • レビュワーの人の英語がいいなと思った

Can we change the file name more readable?
ファイル名をわかりやすく(リーダブルに)変えることはできないだろうか?

Can you ~ ? ではなく、 Can we ~ ? としていて主語を「あなた」ではなく「私たち」としている部分に、OSSってこういうことなんだなぁと感じさせられた。

blog.cybozu.io

issue/PRの発行には、いくつかコツがあります。第一にプロジェクトの中の多くの人が嬉しくなることをアピールしましょう。たとえば単に「このバグが直らないと弊社のシステムが止まるんです!」とみなさんの都合をまくしたてるよりも、コミュニティの中のみんなが遭遇しうる問題だという言い方のほうが反応してもらえる可能性が高いでしょう。

この記事の中にも書かれているように、自分の視点だけではなくコミュニティにとって良いことかという視点が重要なんだなと気付かされました。 普段何気なく打っている、npm installとかcomposer installとかが動くのは誰かがメンテしてくれているおかげなんですよね。

Laravelのコードで学ぶSOLIDの原則

Laravelのコードで学ぶSOLIDの原則

たまたま観た動画が、before-after形式でコードサンプルが書かれてあってわかりやすかったのでまとめる。
原題は「SOLIDの設計原則を用いてより良い開発者になるには」

SOLIDの原則とは?

詳しくは割愛
postd.cc

単一責任の原則

動画内でのコードは、Controller内でバリデーションとDBへの保存を行っている。

<?php
    public function store(Request $request, User $user)
    {
        $validateData = $request->validate([
            // バリデーションルール
        ]);

        $user->name = $request->name;
        $user->mail = $request->mail;
        $user->password = bcrypt($request->password);
        $user->save();

        return response()->json(['user' => $user], 201);
    }

Controllerの主な役割は入力(Request)を受けとり出力(Response)すること。
Controller内でバリデーションロジックを書いたり、Eloquentを使用して保存・更新している場合、Controllerは責務を負いすぎている。

<?php
    public function store(StoreUserRequest $request, UserRepository $userRepository)
    {
        $user = $userRepository->create($request);
        return response()->json(['user' => $user], 201);
    }

LaravelはFormRequestがあるのでFormRequestにバリデーションロジックを書くこと。
ユーザの保存はRepository層を挟んでDBへのアクセスを隠蔽すること。

開放・閉鎖原則

よくあるコード。
支払い方法のタイプを受けとり、typeに応じて支払い方法を変えるというもの。
Requestを受け取っているということは、あるController内に書かれたメソッドなのだと思う。

<?php
    public function pay(Request $request)
    {
        $payment = new Payment();

        // typeによって分ける
        if ($request->type === 'credit') {
            $payment->payWithCredit();
        } elseif ($request->type === 'paypal') {
            $payment->payWithPaypal();
        }
        // ...
    }
<?php
class Payment
{
    public function payWithCredit()
    {

    };

    public function payWithPaypal()
    {

    };
    //...
}

支払い方法が増えるたびに、payメソッド内にif文を追加し、Paymentクラス内に新しい支払い方法に応じた支払いロジックを追加しなければならない。

<?php
interface PayableInterface
{
    public function pay();
}

class PaypalPayment implements PayableInterface
{
    public function pay()
    {
        // implements
    }
}

class CreditPayment implements PayableInterface
{
    public function pay()
    {
        // implements
    }
}

class PaymentFactory
{
    public function initializePayment($type)
    {
        if ($type === 'credit') {
            return new CreditrCardPayment();
        } elseif ($type === 'paypal') {
            return new PaypelPayment();
        }
    }
}
<?php
    public function pay(Request $request)
    {
        $paymentFacory = new PaymentFactory();
        $payment = $paymentFacory->initializePayment($request->type);
        $payment->pay();
    }

支払い方法ごとにクラスを分割し、支払い方法が増えるたびにPaymentクラスのコードが長くなることがなくなった。
各クラスはPayableInterfaceをimplementsすることで、payメソッドを実装することを強制している。
またファクトリパターンを使うことで、利用者が実装の詳細を知る必要がなくなるとともに、新しい支払い方法が増えてもpayメソッドを変更する必要がなくなり変更箇所を一箇所に留めることができる。

リスコフの置換原則

よくあるアヒルクラスの例。
ゴム製のおもちゃのアヒルは飛べないので、派生型(RubberDuckクラス)は基底型(Duckクラス)と置換可能ではないので、リスコフの置換原則に違反している。
Duckクラスを継承するのではなく、各ふるまいをクラス化し、implementsすればよい。

scrapbox.io

chapter1 · kyamashiro/head-first-design-pattern Wiki · GitHub

インタフェース分離の原則

購読しているユーザに通知を送るコードの例。

<?php
class Subscriber extends Model
{
    public function subscribe()
    {

    }

    public function unsubscribe()
    {

    }

    public function getNotifyEmail()
    {

    }
}

class Notifications
{
    public function send(Subscriber $subscriber, $message)
    {
        Mail::to($subscriber->getNotifyEmail())->queue();
    }
}

Notificationsクラスのsendメソッドは使う必要のないSubscriberクラスのsubscribeメソッドやunsubscribeメソッドも使用できる。

<?php
interface NotifiableInterface
{
    public function getNotifyEmail();
}

class Notifications
{
    public function send(NotifiableInterface $subscriber, $message)
    {
        Mail::to($subscriber->getNotifyEmail())->queue();
    }
}

NotifiableInterfaceをタイプヒントに与えることで、NotificationsクラスのsendメソッドはgetNotifyEmailメソッドのみを使用する。

 依存性逆転の原則

<?php
    public function index(User $user)
    {
        $users = $user->where('created_at', '>=', Carbon::yesterday())->get();
        return response()->json(compact('users'), 200);
    }

ControllerでEloquentを使用して値を取得したりしている場合、単一責任の原則にも違反しているし、依存性逆転の原則にも違反している。

<?php
    public function index(UserRepositoryInterface $user)
    {
        $users = $user->getAfterDate(Carbon::yesterday());
        return response()->json(compact('users'), 200);
    }

/users のGETリクエストをController内でEloquentで取得して返す部分はDBに依存しないように、Repository層を作ってUserRepositoryInterfaceをタイプヒントに指定して抽象に依存するようにしている。
UserRepositoryInterfaceに依存するようにすることで、UserRepositoryInterfaceをimplementsしているクラスであればEloquentを使用していようとMongoDBを使用していようとDBを意識しないで$userを使用することができる。

SOLIDの原則にとらわれるな

  • SOLIDの原則はあくまでprinciplesであってrulesではない
  • SOLIDの原則のために過剰な分割をすることは避けよ
  • SOLIDの原則を達成しようとするのではなくメンテナビリティ(拡張・修正のしやすさ)を得るためにSOLIDの原則を使え

カナヅチを持つとすべてがクギに見えるように、SOLIDの原則を知るとついついなんでも当てはめて使いたくなっちゃいますが、あくまで原則であると。SOLIDは原則であって目的ではないと。
実際SOLIDの原則を当てはめるとクラスやファイルが増えてしまいますが、大した規模のアプリでないのならわざわざ分割しないでControllerでEloquentを使用したり、ロジックベタ書きをしてもいいと思う。
しかし、その時は後で必要になったときに分割しようと思うのだけど、それがなされないままどんどん条件分岐が増えてしまうパターンが経験上多い・・・。
「後でやろう」は大体やらないのだから、最初から愚直にちゃんと分割していくべきかなと思う。ユニットテスト書きやすいし。
ファイルやクラスが増えるとかえって複雑になるだろへの反論はこのスライド見ればいいと思います。

『1兆ドルコーチ』を読んだ

 以前から思っていたのだけれど、マネジメントされるではなくマネジメントする側にならないと給料が上がらないと思うので、そういうスキルについて知るために読んだ。

人がすべて

どんな会社の成功を支えるのも、人だ。マネジャーのいちばん大事な仕事は、部下が仕事で実力を発揮し、成長し、発展できるように手を貸すことだ。

3つの柱

  1. 支援
    ツールや情報、トレーニングやコーチングを提供すること。実力を発揮し、成長できるように手助けする。

  2. 敬意
    一人ひとりのキャリア目標を理解し、彼らの選択を尊重する。そして、キャリア目標を達成できるように手助けをする。

  3. 信頼
    自由に仕事に取り組ませ、決定をくださせること。部下の成功を信じること。

コーチン

「優れたコーチは選手をどうやってよくするかを、夜も眠らずに考える。選手がもっと力を出せるような環境を作ることに喜びを感じる。コーチというものは、絵に的確に筆を入れようとする画家に似ている。コーチが描くのは人間関係だ。普通の人は、他人をよくする方法を考えるのに時間をかけたりしない。だが、コーチはそれをやる。」


コーチは教える相手がどれだけ自己認識できているかを知る必要がある。コーチは相手の強味と弱味を知るだけでなく、相手が自身の強味と弱味をどれだけ認識しているかを知らなくてはならないのだ。

 自分自身、大学生のときに就活で自己分析した内容を先輩に見てもらったら、「自己認識が歪んでいる」と言われたことがある。つまり、自分はこういう人間だと言語化したら全然違うと言われたのだ。
 自分の能力、強みや弱みを的確に認識するということは難しいことだ。強みや弱みというものは他人と相対的に比較しないと見えてこないものだと思う。もし世界中に自分一人しか存在しないとしたら、自分の背が高いのか、それとも低いのか認識することはできない。何をするにしても現状を正しく認識することは最も大事なことの一つだと思う。地図で例えるなら現在地がずれているようなもので、現在地がズレたまま目的地にきちんとたどり着くことは難しいだろう。優れたコーチングはこの認識のズレを修正し、正しい目的地に到達することを手助けしてくれるのだろう。

相手としっかりと向き合うこと

ビルはコーチングのセッションで、いつもじっくり耳を傾けてくれた。うわのそらでスマホのメールをチェックしたり、腕時計をちらっと見たり、窓の外に目をやったりすることは決してなかった。

 これは実は何よりも重要なことだと思う。「自分の話本当に聞いてくれているのかな?」「話して意味があるのかな」「この人に話しても無駄だな」という疑念が生じると正直に自分のことを話す気を一気に失くさせる。

話を聞く

「発見や洞察を促すような質問をしょっちゅうする人は、最高の聞き手だと相手に思われる。」


自分から多くの質問をして、相手の状況を多面的に理解しようとする。そうすることで、用意された質問(や答え)に囚われずに、問題の核心を明らかにすることができるのだ。


誰かの話に耳を傾けると、相手は大事にされていると感じる。...従業員の話を聞く、声をかけるといった「ありきたりの何でもないこと」が、すぐれたリーダーシップの重要な側面だという。そうした行動は従業員に「自分は尊重されていて、目に見えない名も無き存在ではなく、チームワークの一端を担っていると感じ」させることができるからだ。


「リーダーの敬意のこもった問いかけ」に効果があるのは、相手の「有能感」(自分は試されていて、それに応えることができるという感覚)、「関係性」(他者とつながっている)、「自立性」(自分が状況をコントロールし、選択しているという感覚)を高めるからだという。

 コーチングというと相手を指導する、的確なアドバイスをするというイメージを持ちがちだが、相手から話を引き出す、相手に何かを促すということは、的はずれなアドバイスよりも重要。

「人を大切にするには、人に関心を持たなくてはならない」

君の家族はどうしている?何が君を駆り立てているのか?まず絆を築き、その理解をもとに仕事にかかるのが、ビルのやり方だった。


ビルは人を大切にした。どんな人にも敬意を持って接し、名前を覚え、温かい言葉をかけた。彼らの家族のことを気にかけ、言葉より行動でそれを示した。


友人がケガや病気をしたり、なにか助けが必要になったら、何を置いても駆けつけるんだと、ビルは教えてくれた。それがやるべきことだと。ビルはそうした。とにかく駆けつけるんだ。

 相手のことを知るといろいろな行動や意思決定の理由が見えてくる。仕事のパフォーマンスが悪い人の背景には、子どもが産まれたばかりで、おまけにパートナーの体調が悪くて大変な状況があるのかもしれない。「そんなことは仕事に関係ない」と言うのは簡単かもしれないが、自分はそういう事を言う人にはなりたくない。「信頼できる人」というのは困っているときに見捨てない人・・・だと思うから。ただし上辺だけの話を聞くだけではダメで踏み込んだ話をしないといけないと書かれている。相手とのあっぴろげな会話をするには自分のことも曝け出さないといけない。
 また、友人や家族をないがしろにしないで大事にするというのは簡単なことではない。ついつい、あともう少しと残業してしまったり、忙しいからと理由をつけて何かを断ってしまう。そういう行動の積み重ねが大きな亀裂を生み出してしまう。

人に興味を持つには

ビルはおそらく私たちの知るなかで最も「人間好き」な人だった。では、もともとあまり外交的でない人はどうすればいいのか?練習だ。

 自分は他人にあまり興味がない。名前を覚えるのが苦手だし雑談をするのも得意ではない。自分と波長が合う人と話すことはできるが、そうではない人と話すのは正直気が進まない。でもそれではいけない。アドビCEOだったBruce Chizenはビルのやり方を真似て克服したと書かれている。

  1. まずは人の名前を覚えるようにした。
  2. エレベータで乗り合わせた人に話しかけ、調子はどう、何に取り組んでいるのと尋ねた。
  3. カフェテリアでは思い切って初めての人たちと食事をした。

 こうした努力が徐々に実を結び、彼が開発者を会話に引き入れようとする姿を見て、エンジニアのリーダーたちが彼に一目置くようになったという。

「人間関係を築くことは、僕にとって自然にできることじゃなかったが、努力した」とブルースは言う。「さいわい、次第に無理なくできるようになる。」