Upgrade to Pro — share decks privately, control downloads, hide ads and more …

プログラミング言語に依存しない、質の高いコードを書く技術

 プログラミング言語に依存しない、質の高いコードを書く技術

PHPカンファレンス沖縄 2021で登壇した内容。

Arakaki Yuji

May 29, 2021
Tweet

More Decks by Arakaki Yuji

Other Decks in Programming

Transcript

  1. プログラミング言語に依存しな
    い、質の高いコードを書く技術
    CBcloud
    株式会社
    新垣 雄志
    (
    あらかき ゆうじ
    )

    View Slide

  2. 自己紹介
    ● 新垣 雄志
    (
    あらかき ゆうじ
    )

    Twitter: @arakaji
    ● 職歴
    ○ 琉球インタラクティブ株式会社
    ○ 株式会社
    Payke

    CBcloud
    株式会社 ←
    NOW

    PHP

    ○ 前職、前前職ともにサーバーサイドで
    PHP
    を使っていた

    CakePHP

    FuelPHP
    ○ 現職ではサーバーサイドは
    Ruby
    を使っている

    View Slide

  3. なぜこのテーマを選んだか?

    PHP
    は前職まではがっつり使っていたが、現職は主に
    Ruby
    で開発をしている
    ● そのため、個人的にいま「
    PHP
    」特有のテーマがみつからなかった
    ● プログラミング言語に依存しないテーマを探した
    ● 現職ではスタートアップあるあるのスピードと成長優先で書かれたプロダクトを引き継
    ぎ、コードの保守性なども改善しながらもプロダクトの成長をさらに加速させるための
    開発をしている最中
    ● 「コードの品質」と「プロダクトの成長速度」をどう両立させていくかがテーマ
    ● そこで出会った名作

    View Slide

  4. 質とスピード

    View Slide

  5. 質とスピード
    ● 和田 卓人
    (@t_wada)
    先生の登壇資料
    ● ソフトウェア開発においてよく言われる「コードの品質を一旦犠牲にしてスピード優先
    で開発する」という言葉に対する誤解を解く内容
    ● コードの品質と開発スピードはトレードオフではない
    ● 品質の高いコードを書くことにより、開発速度が上がる
    ● 質を上げながら開発速度も上げるにはどうすればいいか?ではない
    ● 質を上げることによって開発速度を上げる

    View Slide

  6. View Slide

  7. 次に出てくる疑問
    ● 質の高いコードを書くことが開発速度を上げることに繋がることはわかった。
    ● では「質の高いコードを書く」にはどうすればよいのか ?
    ● 今回はその「プログラミング言語に依存しない質の高いコードを書く技術」について
    の整理・言語化を試みた

    View Slide

  8. ソフトウェアの品質とは?

    View Slide

  9. View Slide

  10. SQuaREのソフトウェア品質モデル
    ● システム及びソフトウェアの多岐にわたるステークホルダ
    (
    利用者、発注者、開発者
    など
    )
    が持つ多様な品質要求を定義し評価するための基準として定義された国際規

    SQuaRE
    シリーズ
    ● 品質モデルでは、品質を構成する上位の要素「品質特性」とこの品質特性をささえ
    る詳細化した下位の要素「品質副特性」を定義している

    View Slide

  11. 保守性の高いコードを書く技術
    ● 今回掘り下げるのは「保守性」
    ● 「意図した保守者によって、製品又は
    システムが修正することができる有効
    性及び効率性の度合い」
    ● 保守性を上げる
    =
    プロダクトの変更
    速度を上げること

    View Slide

  12. モジュール性(modularity)
    ● 「一つの構成要素に対する変更が他の構成要素に与える影響が最小になるように、
    システムまたはコンピュータ・プログラムが別々の構成要素から構成されている度合
    い」
    ● つまり、依存関係やそれによる影響範囲を適切にコントロールしたコードを書くため
    の技術が求められる

    View Slide

  13. SOLID原則

    View Slide

  14. SOLID原則
    SOLID
    原則の目的は、以下のような性質を持つ中
    間レベルのソフトウェア構造を作ること。
    ● 変更につよいこと
    ● 理解しやすいこと
    ● コンポーネントの基盤として、多くのソフトウェ
    アシステムで利用できること

    View Slide

  15. SOLID原則

    S:
    単一責任の原則
    (SRP: Sigle Responsibility Principle)
    ← 着目

    O:
    オープン・クローズドの原則
    (OCP: Open-Closed Principle)

    L:
    リスコフの置換原則
    (LSP: Liskov Substitution Principle)

    I:
    インターフェイス分離の原則
    (ISP: Interface Segregation Principle)

    D:
    依存関係逆転の原則
    (DIP: Dependency Inversion Principle)

    View Slide

  16. 単一責任の法則
    ● 「モジュールを変更する理由はたったひとつだけであるべきである」
    ● ソフトウェアを変更するのは、ユーザーやステークホルダーを満足させるため
    ● この「ユーザーやステークホルダー」が変更する理由になる。
    ● ただし複数のユーザーやステークホルダーがシステムをおなじように変更したいと考
    えることもある。
    ● 変更を望む人たちをひとまとめのグループとして扱いため、そのグループをアクター
    と呼ぶ
    ● 「モジュールはたった一つのアクターに対して責務を負うべきである」

    View Slide

  17. Employeeクラスの例
    ● 給与システムにおける従業員クラスの例

    3
    つのメソッドはそれぞれ別のアクターへ
    の責務を追っている

    calculatePay
    は経理
    (CFO)

    reportHours
    は人事
    (COO)

    save

    DB
    管理者
    (CTO)

    View Slide

  18. 何が問題か?
    ● アクターの異なるメソッドで同じアルゴリズムを共
    有してしまった場合、両方のメソッドに影響が出
    てしまう。
    ● アクターが異なる機能はアルゴリズムが一時的
    に似ていても使われ方が変わるし変更タイミング
    も変わる
    ● アクターが異なるコードは最初からモジュール
    /
    クラスレベルで分離したほうがよい

    View Slide

  19. 再利用性(reusability)
    ● 「一つ以上のシステムに、又は他の資産づくりに、資産を使用することが出来る度合
    い」
    ● 既存コードを再利用することで新たなコードを書く必要をへらし生産性を上げる
    ○ ライブラリ
    ○ フレームワーク

    SaaS
    ● 再利用しやすいコードを自分が書くことでチームメンバー、そして明日の自分の生
    産性をあげる

    View Slide

  20. 再利用性を高めるコードを書くための技術/考え方
    ● ボトムアッププログラミング
    ● 小さいものは美しい
    (Small is Beautiful)
    ● メタプログラミング

    View Slide

  21. ボトムアッププログラミング
    Lisp
    では、プログラムをただプログラミング言語に従って書く
    ことはしない。プログラミング言語を自分の書くプログラムに
    向けて構築するのだ。プログラムを書いているときに、「
    Lisp
    に○△のオペレーターがあればなあ」と思うことがあるかもし
    れない。そうしたらそれを書けばいい。後で、新しいオペ
    レータの使用がプログラムの別の部分のデザインを簡潔に
    まとめることにつながったと気づくだろう。

    View Slide

  22. ボトムアッププログラミング
    ● プログラミング言語を自分たちの開発しているアプリケーションの適する形に変えて
    いくこと
    ● フレームワークやライブラリを使うのはそれと同じ

    Laravel

    CakePHP
    を導入することで
    PHP

    Web
    アプリケーションの開発により適した形に拡張され る

    aws-sdk
    のライブラリを導入することで、
    AWS
    を操作するのに適した形に拡張される
    ● これをもっと小さい単位で、自分たちのアプリケーションコードを書くときにも行う

    View Slide

  23. 連想配列の値取得の例
    連想配列内に指定したキーが存在する場合には
    その値を、存在しない場合には指定したデフォル
    ト値を返す。
    一見シンプルだが以下の様な問題もある。

    false
    と評価される空文字や
    0
    がある場合、
    キー自体はあるのにデフォルト値がかえされ
    てしまう
    ● この差異に以外ときづかず特定ケースでバ
    グを発生させることが多々ある

    View Slide

  24. 連想配列の値取得の例
    ● 非常にシンプルだがより厳密な配列での値を
    取得をするのメソッドを定義する
    ● これによりほんの少しだがバグ発生率やコー
    ド量を削減することができる。
    ● シンプルなので他の人も理解しやすく再利用
    しやすい。
    ● この小さな積み重ねが中長期的な生産性の
    大幅な向上につながっていく

    View Slide

  25. 連想配列の値取得の例
    ● 非常にシンプルだがより厳密な配列での値を
    取得をするのメソッドを定義する
    ● これによりほんの少しだがバグ発生率やコー
    ド量を削減することができる。
    ● シンプルなので他の人も理解しやすく再利用
    しやすい。
    ● この小さな積み重ねが中長期的な生産性の
    大幅な向上につながっていく

    View Slide

  26. 小さいものは美しい
    ● 小さなプログラムはわかりやすい
    ● 小さなプログラムはシステムリソースにやさしい
    ● 小さなプログラムは他のツールとくみあわせしや
    すい
    ○ 再利用性を高める!!

    View Slide

  27. メタプログラミング
    メタプログラミング
    (metaprogramming)
    とはプログラミング技法の一種で、ロジックを直接
    コーディングするのではなく、あるパターンをもったロジックを生成する高位ロジックによっ
    てプログラミングを行う方法、またその高位ロジックを定義する方法のこと
    (from
    wikipedia)
    別の言い方をすると、
    「プログラムを書くプログラムを書くこと」とも言える。

    View Slide

  28. メタプログラミングってPHPで出来る?
    ● メタプログラミングで一級市民的な言語はある

    Lisp

    Ruby

    PHP
    ではどうか?
    ○ マジックメソッドを使うことでメタプログラミングのようなことができる

    View Slide

  29. Driverクラスのtype判別メソッドの定義
    ● 配送ドライバーには複数種類ある
    ○ 軽貨物ドライバー
    (kei_car)
    ○ 一般貨物ドライバー
    (ippan_car)

    Driver
    インスタンスがどのタイプかを判別するた
    めの
    is_hogehoge()
    というメソッドを定義
    ● 問題点

    DRIVER_TYPE
    が増えるたびに同じようなメソッドを再
    定義しないといけない

    View Slide

  30. Driverクラスのtype判別メソッドの定義

    __call
    マジックメソッドは存在しないインスタン
    スメソッドがコールされたときに呼び出される

    __call
    マジックメソッド内で呼び出されたメソッ
    ド名を判別し、より抽象化された
    type
    判別メ
    ソッドを呼び出す
    ● これによって
    DRIVER_TYPES
    の定数に値を
    追加するだけで
    is_hoge
    というメソッドが使え
    るようになる

    View Slide

  31. メタプログラミングのリスク
    ● デバッグが難しい
    ● コードが複雑かつわかりづらくなりがち
    ● 使うことによって得られるメリットとデメリットを天秤にかけて使うかどうか判断したほう
    がよい
    ● もし使うならメタプログラミングの部分ににはバグが入り込まないように厳密にテストを
    することと使い方を説明するドキュメント(コメント
    )
    が必要。

    View Slide

  32. 解析性(analyzability)
    ● 製品若しくはシステムの一つ以上の部分への意図した変更が製品もしくはシステム
    に与える影響を総合評価すること、欠陥もしくは故障の原因を診断すること、または
    修正しなければならない部分を識別することが可能であることについての有効性及
    び効率性の度合い。
    ● つまり「問題が起きたときの発生箇所、影響範囲、原因の特定がしやすいかどうか」

    View Slide

  33. 解析性を高める技術
    ● オブザーバビリティを高めるツールの導入
    ● 適切なログ出力

    View Slide

  34. オブザーバビリティ
    アプリケーション、インフラ、ログなどあらゆ
    るテレメトリーデータを収集、相関、意味付
    け、可視化し、複雑なソフトウェアシステム
    を理解しやすくするための取り組み
    - NewRelic
    - Datadog

    View Slide

  35. NewRelic

    NewRelic

    APM
    、クランド連携、
    agent
    、ログ収集を行うと問題発生時に以下のよう
    なことがワンストップできるようになる。
    ○ エラーレートの可視化
    ○ 発生したエラーのスタックトレースを表示
    ■ どの
    API(
    パス
    )
    を叩かれたのかもわかる
    ○ そのエラーが発生したときのトランザクション中のログを一覧で表示
    ● これによって問題発生箇所、影響範囲、原因が非常に素早く把握することができる

    View Slide

  36. 適切なログ出力

    NewRelic
    で調査しやすくなったとはいえ、適切なログが出力されていないとそこで息
    詰まる。
    ● なにか問題が起きたときに原因調査するための情報があるか?という視点でログ出
    力を行う
    ○ 本来発生しない例外をキャッチした場合、その内容をエラーログに出力する
    ○ 外部連携
    (SaaS
    含む
    )
    をする場合、その
    Request/Response

    INFO
    ログとして出力する

    Web
    アプリケーション場合
    Request
    のログを出力する
    (API
    であれば
    Response
    もログ出力する
    )
    ■ 秘匿情報はマスクするのは前提
    ○ 大きいバッチ処理をする場合経過状況を
    INFO
    ログに出力する

    View Slide

  37. 試験性(testability)
    ● システム、製品または構成要素について試験基準を確立することが出来、その基準
    が満たされているかどうかを決定するために試験を実行することができる有効性及
    び効率性
    ● つまり、「プロダクトの受け入れ条件など決めて、それを満たせているかどうかをテス
    トできるかどうか」

    View Slide

  38. テスト駆動開発(TDD)
    「動作するきれいなコード」を書くためのプログラミングプラクティス
    シンプルなテスト駆動開発のルール
    ● まずはシンプルな自動テストを一つ書く
    ● すべてのテストを走らせ、新しいテストの失敗を確認する
    ● 小さな変更を行う
    ● すべてのテストを走らせ、すべて成功することを確認する
    ● リファクタリングを行って重複を除去する

    View Slide

  39. テストカバレッジ
    ● ソフトウェアコードのうちテストがなされている比率
    (
    網羅率
    )
    ● テストカバレッジが
    100
    %であれば良いかというとそういう訳ではない。
    コードカバレッジは、コードのテストされていない部分を発見するための有用なツールである。ただテ
    スト自体がどれだけ良いかという指標としては、テストカバレッジはほとんど役に立たない。
    カバレッジの数値がほしい理由はわかる。テストが十分かを知りたいのだ。カバレッジの数値が低い
    場合、たとえば
    50%
    以下の場合は、おそらく問題があるだろう。けれど高いカバレッジの数値にはあま
    り意味はない。ダッシュボードの数字に意味がなくなる助けをするだけだ。
    from: https://bliki-ja.github.io/TestCoverage/

    View Slide

  40. 質の良いテストを書く必要がある

    View Slide

  41. 質の良いテストコードを書く技術

    3
    角測量
    ○ 一つのメソッドをテストするとき、
    2
    つ以上の実例を持ってテストをする
    ■ それによってメソッドの実装の一般化が抽出される
    ■ ただテストコードの重複によるテスト実行速度の悪化にもつながるので、テストコードを書くとき
    のフローの中で行うが、実装・テストともに完了したら重複を除去することもある
    ● 欠陥挿入
    ○ プロダクトコードの任意の行の意味合いを変えて、テストが失敗するかどうかを検証する
    ○ もし失敗しない場合は適切にテストが書かれていないこと
    (
    漏れがある
    )
    を示しているのでテストの追
    加・修正が必要だとわかる

    View Slide

  42. 修正性(modifiability)
    ● 欠陥の取り込みも既存の製品品質の低下もなく、有効的に、かつ、効率的に製品ま
    たはシステムを修正することができる。
    ● つまり、バグやパフォーマンスの悪化などを起こさずにどれだけ早く機能の追加・修
    正ができるかどうか

    View Slide

  43. 修正性を高める技術
    ● 他の要素を高めること
    =
    修正性を高めること
    ○ モジュール性
    ○ 再利用性
    ○ 解析性
    ○ 試験性

    View Slide

  44. 質の高いコードを書いて、
    良いソフトウェアを作って、
    売上をあげて
    良い給料を得て
    よりプログラミングを楽しんでいこうな!

    View Slide

  45. 参考書籍
    ● クリーンアーキテクチャ

    On Lisp

    UNIX
    という考え方
    ● テスト駆動開発

    View Slide

  46. 参考資料
    ● 質とスピード〜ソフトウェア開発の典型的な誤解を解く〜
    (2020
    秋バージョン
    )

    https://speakerdeck.com/twada/quality-and-speed-2020-autumn-edition
    ● つながる世界のソフトウェア品質ガイド

    https://www.ipa.go.jp/files/000044964.pdf

    X 25010 : 2013 (ISO / IEC 25020 : 2011 )

    http://kikakurui.com/x25/X25010-2013-01.html
    ● 開発者が知っておくべき
    SOLID
    の原則

    https://postd.cc/solid-principles-every-developer-should-know/
    ● 単一責任の原則
    (Sigle responsibility principle)
    について、もう一度考える

    https://www.ogis-ri.co.jp/otc/hiroba/others/OOcolumn/single-responsibility-principle.html
    ● メタプログラミング

    https://ja.wikipedia.org/wiki/%E3%83%A1%E3%82%BF%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A
    9%E3%83%9F%E3%83%B3%E3%82%B0

    View Slide

  47. 参考資料

    Web
    アプリケーションのログ出力について指針を考えてみた

    https://blog.mmmcorp.co.jp/blog/2018/05/25/web_application_logging/
    ● 「質」のいいユニットテストを書くためのプラクティス

    https://speakerdeck.com/hgsgtk/practices-to-write-better-unit-test
    ● テストカバレッジ

    https://bliki-ja.github.io/TestCoverage/

    View Slide