酒と開発の日々

飲酒大好き駆け出しエンジニアのブログ

composition される final クラスを mock してテストを書きたい

お久しぶりです。ぐーどらです。

ここ数日個人的な困りごととして、掲題の悩みを抱えていました。

テストするために Interface 切り、コンストラクタの引数を Interface にすることも考えました。 しかし今回はテスト対象のクラスがコンポジションするべきはmockするクラスであることを明示したい状況であったため、Interfaceを切る方針も却下しました。 結果的にTwitterで声をかけていただいた、局所的なrequireでクラスをオーバーライドすることでテストを通すことにしたので覚書にしようと思います。

Compositional.php
final class Compositional
{
  // doSomething
}

TestTargetCalss.php
final class TestTarget
{
  public function construct(private readonly Compositional $conpositional) {
  }
}

CompositionalClassも別の箇所から呼び出されるようなパッケージだし、final取るのも、TestTargetの引数をInterfaceにするのも違うよなあ…と苦慮していたのですが、同じ名前空間・同じクラス名でオーバーライドするというのは目からウロコでした。 早速やってみることに。

$ tree
.
├── Packages
│   └── SomePackage
│       ├── Compositional.php
│       └── TestTarget.php
└── tests
    ├── Overrides
    │   └── Compositional.php
    └── Packages
        └── TestTargetTest.php


composer.json
    "autoload-dev": {
        "psr-4": {
            "Tests\\": "tests/"
        },

TestTargetTest.php
require (__DIR__ . '/../Overrides/Compositional.php')

public function test_finalClassMockTest()

このようなディレクトリ構成とautoloaderの外にstubファイルとして配置することで、本番環境でも動作しないことを担保できるようにしました。

しかし一つだけ問題が… 定義する名前空間が同一であるため、PhpStormで警告が出てきました。 ぐぬぬ。許せぬ。

ここで妙案が。拡張子変えてしまえば良いのでは?と思いつき、tests/Overrides/Compositional.phptests/Overrides/Compositional.php.stub に変更してみました。 こうすることでPhpStormでの警告も消え、無事にテストもmock出来るようになりました。

@mpywさんありがとうございました! どうやったらこんな解決方法思いつくんや…

他にこんな方法知ってるぜって方いらっしゃいましたらぜひ教えて下さい。

apt installが失敗したので、少しapt updateに関して調べてみた

結論

  • apt update/var/lib/apt/lists配下にpackage information cacheとしてdeb~形式のファイルを格納する。
  • apt upadte直後でもapt installが失敗することがある。
  • そうなった場合の対処法はsudo rm -rf /var/lib/apt/lists/*をしてキャッシュファイルを消してからapt updateを行う。

事の発端

何もしてないのにCircleCIが壊れた!

これは今週の平日、いつものように作業を作業をしていたのですが、唐突にCircleCIのテストが通らなくなりました。エラーを見てみるとapt updateapt installをしているところでコケている様子。

#!/bin/bash -eo pipefail
sudo apt update && sudo apt install -y

(中略)

E: Could not open file /var/lib/apt/lists/deb.debian.org_debian_dists_buster-updates_main_binary-amd64_Packages.diff_Index - open (2: No such file or directory)
E: Could not open file /var/lib/apt/lists/deb.debian.org_debian_dists_stretch-backports_main_binary-amd64_Packages.diff_Index - open (2: No such file or directory)

なんぞ…?

調べてみた

当該のエラーでググると稀に発生するようです。

github.com

とりあえず上記ページを見つけ、どうやらsudo rm -rf /var/lib/apt/lists/* && sudo apt updateすれば良さそうだということはわかってきました。ですが今ひとつ納得行かなかったので、少しapt updateについて調べてみました。

itsfoss.com

karoten512.hatenablog.com

上記2記事を読み、apt updateを行うと~.debというpackage informationキャッシュを/var/lib/apt/lists配下に引っ張ってくると理解しました。

再度結論

apt install/var/lib/apt/lists/配下のdebファイルで失敗する場合、sudo rm -rf /var/lib/apt/lists/* && sudo apt updateしてからsudo apt install

正しいものを正しく作る塾の設計コース第2回のまとめ

設計コース2回めを受けてからだいぶ時間が空いてしまいましが、2回めの内容のまとめと自分なりのメモを取っていたので、噛み砕き反芻するための記事とします。また、3回めを受けた後にまとめているので、3回目の内容を含みながらの考察になります。自分のためにまとめたので、本文はですます調ではなくなってしまって読みにくいと思いますが、ご容赦願います。

設計コースでの参考にする書籍3冊の設計アプローチ

設計コースでは下記3冊の内容に触れながらコースが進められる。

第2回の最初の内容では上記3冊の設計アプローチについての説明があった。

ソフトウェアシステムアーキテクチャ構築の原理
特定の設計アプローチを取り扱っているわけではなく、設計における課題を体系的に整理し、様々なアプローチを列挙している本。故に、最初から最後まで通して読む本ではなく、必要になった時に適宜どのようなアプローチがあるのか参照してゆく本。

エリック・エヴァンスのドメイン駆動設計
ソフトウェアの成長に重きを置いて振り切っている内容の本。アプリケーション全体を作る場合はエヴァンス本だけでは作れない。

オブジェクト指向入門 第2版 原則・コンセプト
作者がカテゴライズマニアを自称しており、書き方にもそれが出ている本。正確性と拡張性が重要視され、それを念頭に置いて読むことがポイントとなる。正確性と拡張性を実現するためにオブジェクト指向を使い、型・クラス・モジュールを一致させるべきと主張している。

考察

おそらく俯瞰するスキルを活用し、インプットの効果を上げることを狙いとしている部分。

設計の関心事(ユーザーインターフェースとデータベースの扱い)

アプリケーションの実現にはユーザーインターフェースとデータベースは必要な要素。
しかし、SSAでは様々な要素のうちの1つでしか無いし、DDDとOOSCではソフトウェアの中核の周りにある、周辺的で従属的な関心ごととして扱われている。
UIやDBは設計の中心課題ではない。

考察

ここは講師の増田さんの経験知からくる特徴的な部分。ここの考えが合わないとこの設計コースでの内容が入ってこなくなるかつ、重要な部分であるため記載されていると考えられる。

設計コースの3回目の内容と繋がっているのもこのスライドの部分で、3回目ではエヴァンス本の1章の内容を扱った。1章のp12には次のような内容が出てくる。

そこで、自動テストフレームワークを使って、非常にシンプルなプロトタイプを作成した。インフラストラクチャ部分は全て省いた。したがって、永続化もなければ、ユーザーインターフェース(UI)もない。これでふるまいだけに集中することができるようになった。その後、ほんの数日のうちに、簡単なプローブシミュレーションを実演することができた。

このようにエヴァンス本では、明確にUIやデータベースを使わずにソフトウェアの構築を始めている。

要点の見極め方

  • まとめの段落(書き始め、もしくは最後の段落)から読み始めると理解が進みやすい。
  • 一覧項目は最初がもっとも基本的で重要。順不同ではなく、均一ではない。
  • 何度も登場する言葉が重要な関心ごとであり、作者が伝えたいこと。

論文や論理的な文章ほどそうなっている。

考察

効率的な文章の読み方についてまとめられたスライド。
DDDやOOSCは厚い本なので、意識的に実践し効率的に読んでいきたい。

3冊をつなぐ軸

  1. 望ましい品質
  2. ソフトウェア変更の背景と動機
  3. 変更を容易にする設計技法
  4. 変更を重視する開発プロセス

1.望ましい品質

  • SSA28章 変更容易性
    • あらゆるシステムが経験する避けようのない変更に柔軟であり、そういう柔軟性を提供するコストに釣り合うシステムの能力
  • DDD 進化を続けるソフトウェア
    • (まえがき)いずれも役に立ったが、企業の継続的な要求をみたすべく進化し続けるソフトウェアをつくりだせたプロジェクトは一つだけ
    • (最後の段落)成長するにつれて我々の進路をふさぐことなく、新しい機械を生み出し所有者にとって価値を付け加え続けるソフトウェア
  • OOSC 拡張性
    • (1.2.3拡張性)使用の変更に対するソフトウェア製品の適応のしやすさ

考察

設計コースにおける前提、最も大切な品質特性は発展性の論拠となる箇所。
3冊とも異なる切り口で変更容易性、発展性を論じている。

変更容易性が無ければソフトウェアは次第に使われなくなる経験と実感があり、納得する。そもそも変更や発展できるからこそ「ソフトウェア」と呼ばれるのではないだろうか。

2.ソフトウェア変更の背景と動機

  • SSA:製品管理(PdM)
    • (28.2関心事の1.製品管理)顧客のニーズと事情がもたらす機会と脅威が、ソフトウェアのすべての変更の文脈と方向性を提供する。(ビジネスがソフトウェア変更の文脈と方向性を決める)
  • DDD:事業活動そのもの
    • (まえがき)複雑なのはユーザーの活動やビジネス。これがソフトウェアの中心的な側面。設計を成功させ、変更や拡張を容易で安全にするために、この中心的側面を体系的に扱う。
  • OOSC:外界の世界の変化
    • (1.3ソフトウェアの保守)まっとうな保守作業は修正であり、外界の世界の変化を反映させること。

事業の知識をもとにして設計判断をしてゆく

考察

事業の目的、目標、方針があり、それらをソフトウェアがサポートするため、ビジネスを中心とすることはごく自然なことだと感じられる。ソフトウェア側の都合がビジネス側に影響を及ぼすことはあってはならないと思う。

3.変更を容易にする設計技法

考察

3冊とも変更を容易にするためにオブジェクト指向に注目している。

DDDでは確かにオブジェクト指向について具体的に論じられている箇所は無いと思うが、例えば下記の箇所

1章 知識豊富な設計 オーバーブッキングのルールは、ポリシーである。ポリシーとは、ストラテジーとして知られている設計パターンの別名だ(Gamma 他 1995)

この箇所で出てきている"ストラテジー"は明らかにGoFデザインパターンのストラテジーパターンを指している。目次からも読み取れる。

SSA:変更を閉じ込める設計原則

  • カプセル化
    • OOPの基本的概念のひとつ。OOSCではカプセル化ではなく、型とクラスの関係で説明している。データと関連する操作のセットを一つの入れ物にまとめる。
  • 関心事の分離
    • 関心事の分離の具体的な切り口は、SSAでは何かに特定していない。オブジェクト指向プログラミングでは、入出力と計算・判断ロジックの分離が基本。型やカプセル化と強く関係する。
  • 機能的凝集
    • 機能を入出力と考えると、手続き的な凝集。機能を値の種類ごとの計算・判断ロジックの集合と考えるとオブジェクト指向プログラミングの凝集。
  • 単一の定義ポイント

考察

こちらのブログ記事を設計コース用にまとめてもらったようなスライド。

masuda220.hatenablog.com

カプセル化とデータ抽象の違いを理解できていない。

4.変更を重視する開発プロセス

  • SSA:選択肢のひとつとしてアジャイル
    • (28.2.6変更の対価を払う時期)前払いと後払いの両極端の間でバランスを取る
  • DDD:アジャイルにおける設計の重要性
    • 開発者が括弧とした設計原則を持っていないと、理解も変更も難しい、アジャイルとは正反対のソフトウェアを作り出してしまう。XP(エクストリームプログラミング)は設計に関する鋭いセンスを持った開発者に適している。
  • OOSC:一貫した方法論(オブジェクト指向)を適用する
    • ライフサイクル全体(分析・設計・実装・保守)に適用し、作業感の隔たりを最小に。

考察

アジャイルやXPについての知識が不足していると感じたスライド。アジャイルソフトウェア開発の奥義を借りることが出来たので、DDDの後に読む。

このスライドの後にウォーターフォールアジャイルなアプローチとの比較のスライドがあった。
ウォーターフォールはシステマチックな面は良いが、現代では費用対効果が悪くなりすぎると増田さんは主張されていた。
しかしそれと同時にアジャイルなアプローチならうまくいくのかというとそんなことはなく、高い設計スキルが必要になってくるという話もあった。
経験として設計スキルは大切であると感じていた部分を言語化してもらえたと感じた。

まとめ

設計アプローチの選択がテーマの回だった。設計の重要な関心事はビジネスであり、UIやDBではないという部分が際立った回だと思う。

大きくまとめると、ソフトウェアの発展性を重視して、ビジネスを主軸にソフトウェアを組み立て、オブジェクト指向で変更を容易にするというアプローチをしている。そのために必要になるのが設計スキル。

どの内容もとても大切な内容だったが、概要の部分が多かった。しかしこの内容を念頭に置いてDDDやOOSCなどを読み込んでいけば、格段に知識の吸収力が良くなると思う。
次回は第4回だが、その前に第3回の内容もまとめたいと思う。

正しいものを正しく塾 設計コースに参加しました

めちゃくちゃお久しぶりです、ぐーどらです。

新しい環境に身を置き、半年以上経過していることに驚いています。

今回の記事は正しいものを正しく作る塾の設計コースの初回に参加してきたので、内容のまとめと自分なりの解釈を記事にしたいと思います。(アウトプットは主体的に学ぶために大切という話がまさに塾の内容にもありました。)

主体的に設計スキルを学ぶ

現場で役立つ実践的な設計スキルを学ぶには当然ですが、学びと実践が大切であるという話が最初にありました。 また、コースを受けるにあたりラーニング・パターンが紹介されました。特に下記2点は設計活動にも酷似しているパターンとして紹介されました。

また、このセクションの最後のスライドでは設計を学ぶコツというスライドが有り、"形式知は正解でなく手がかり"と書かれていました。この部分に関しての自分なりの解釈は、形式知はかならずしも現実の正解とは限らず、実践が不可能の場合もある。実際に実験などを経て自分の経験から来る正解を見つけるべきという主張だと解釈しました。

設計スキル 三つの伸びしろ

まず最初に下記のスキルが書かれたスライドがありました。

  • 俯瞰するスキル
    • 全体を見渡す
    • ランドマーク(特徴や目印)を見つける
  • つながりで考えるスキル
    • つながりの有無・強弱・濃淡・方向を考える
  • 軸を中心に組み立てるスキル
    • 軸から周辺に広げる
    • 軸を強化してから周辺を広げる

設計を学び、実践する際はこの3つのスキルを意識し実践せよとスライドに書かれていました。 自分なりの解釈を書き出すと下記のようになるかと思います。

俯瞰するスキル

全体を眺め、中でも大切な部分や特徴的な部分や要素を見つけ出す能力。

つながりで考えるスキル

要素同士がどのように関連するかを考える能力。

軸を中心に組み立てる

大切な部分や大切な要素から組み立て始め、理解をまず深める。その後周囲に取り掛かる能力。

正直なところつながりで考えるスキルに関してはあまりピンときていません。

良い設計

ソフトウェアの品質特性として、スライドでは下記3つが挙げられました。

  • 合目的性
    • 対象業務、画面、データ、外部インターフェース
  • 稼働性
    • セキュリティ、処理性能、可用性、運用・監視
  • 発展性
    • 設計品質

最も大切な品質は発展性であるとスライド内で明示され、また講師である増田氏のブログ記事でも、下記のように主張されています。

masuda220.hatenablog.com

講義の中では、合目的性や可動性を突き詰めても発展性は向上しない。逆に発展性を担保できれば合目的性や稼働性を改善してゆくことができるというお話もされていました。個人的にはとても納得のゆく話で、下記のスライドの中でも共通している主張がされていると感じました。

speakerdeck.com

最後に

今回自分がこのコースに参加を決めた理由はいくつかあるのですが、やはり一番はコードを書く時の迷いを払いたいという思いが一番強いと思っています。

今まで私はプログラミングを学ぶ際、師事をうけるような機会がありませんでした。前職や現職でもアーキテクトのような存在がおらず、コードを書くための判断基準が常に曖昧なままコードを書き続けていました。

講師の増田氏の書籍やブログ記事は以前より拝読していました。主張されていることはいずれも納得のゆくものばかりで、この塾の講師をされると知ったときすぐに申し込みをしました。

この塾を通じて、設計に対する身体知を少しでも多く獲得し、コードを書く時の迷いが軽減することを願ってやみません。

気軽にデータベースを作って壊せるdocker-composeを作りました

みなさんこんにちは。寒いですね。

というわけで、タイトル通りなんですが、簡単にデータを突っ込んで壊すためのdocker-composeを作りました。

https://github.com/cranch-crown/container_db

READMEにちょろっと書いたんですが、ORDER BY カラム IS NULL ASCなんて記述を見かけ、動作はわかったけど、逆にDESCしたらどうなるんだろう?とかを感じ、気軽にデータを入れて壊すデータベースがほしいなという思いをリポジトリ化してみました。

まだまだSQLなんもわからんな人なので、僕と同じようにこういうときのサブクエリどうなるん?とか感じている人は使ってください。

短いですが、こんなところで。

PHPerKaigiと自分

皆さんおはこんばんにちは。ぐーどらです。

1週間ほど前、遂にスギ花粉の天気予報が始まり、花粉の痒みに苦しめられてます。

はじめ

僕は昨年1月に異業種からエンジニアに転職しました。そんな知り合いがほとんどいない状態で昨年PHPerKaigiに参加し、今年はより一層楽しむことができました。PHPerKaigiに参加された全員の方のおかげで楽しめたと思っています。

なので今回の記事は、自分なりの恩送りとして(恩送りがわからない方はこちらの記事をどうぞ)、まだカンファレンスや勉強会に参加されたことが無い方が「PHPerKaigi面白そう!」「勉強会参加してみたい」なんて思っててくれればいいなあと思いながらブログを書いてます。

PHPerKaigi 2019に参加したこととその後

冒頭でも触れたとおり、僕は一年前に異業種から転職しました。そんな中、たまたまイベントで知り合った人からPHPerKaigi2019というカンファレンスがあるから行ってみないかと誘われました。

正直なところ、初めは気が進みませんでした。チケットは有料だし、知り合いもその人以外にはあまりいないし…という状態でした。

なので昨年は、「お付き合いを優先」という後ろ向きなモチベーションで参加したのが正直なところです。

しかし実際に参加してみると、とても楽しく参加できた自分がいました。

技術的に興味をそそられるセッショントーク(発表)、悩みを共有出来るIRT、セッションのQ&Aとは別に登壇された人に質問することが出来るAsk The Speakerの場などが提供されていて、気がつくと色々なものを持ち帰ろうと夢中になっている自分がいました。

楽しめた要因はそれだけではなく

  • 休憩スペースや無料ドリンクの提供があり、会場の居心地が良い
  • PHPerチャレンジ、PHPer茶会、名札など、参加者同士の交流が発生しやすい状況、企画

などの要因があったと思います。

PHPerKaigi 2019にしたことで、なんの実績も無い自分がイベントに参加することへの心理的なハードルはかなり下がりました。

その後、様々なイベントやカンファレンスに参加するようになりました。

今年のPHPerKaigi

そして季節が巡り、今年のPHPerKaigiも参加してきました。今年は昨年よりも楽しめた実感がありました。

PHPerKaigiは他のカンファレンスと比較して、圧倒的に楽しいカンファレンスだと感じます。もちろん他のカンファレンスもとても楽しいのですが、実行委員長の@tomzohさんがクロージングで話していた同窓会のような雰囲気を味わえたということが、一層楽しく感じられた要因じゃないかと思います。

企画の面でも去年より面白くなっていて、自分のTwitterアイコンが印刷されたトレーディングカードノベルティになっていました。交換するだけで話題になりそうで、当日の会場はめちゃくちゃいい雰囲気でした。なぜ数日前にチケットを買わなかったのか後悔しました。

あとはやはりPHPerKaigi 2019以降、色々な勉強会に参加した結果、たくさんのPHPerの人と知り合えたことが今年のPHPerKaigiでの楽しさになったのかなと思います。

今年も楽しいPHPerKaigiを本当にありがとうございました!!

勉強会参加のススメ

ここまで読んでくださった方もありがとうございます。

最後は、ここまで読んでくださった方の中でカンファレンスや勉強会に出られたことが無い方へ向けです。

初めてコミュニティに参加することはとても尻込みしますよね。わかります。

しかし、あなたが少しでも技術に興味があったり、悩み事を抱えているならば、コミュニティの人はその思いを雑に扱ったりはしません。きっと僕の時と同じように知恵を貸してくれます。

この記事が少しでも勉強会参加のきっかけになれば幸いです。

…え?どの勉強会に出たらいいかわからない?それではとっておきの勉強会ともくもく会をご紹介します。

どちらも僕が運営に参加させて頂いています。ぐーどらさんの記事読みました!なんて声をかけてもらえたらめちゃくちゃ嬉しいです!

それではどこかの勉強会でお会いしましょう。

CentOS8のVagrantイメージではすんなり共有ディレクトリが使えなかったという話

みなさんおはこんばんにちは。ぐーどらです。昨日突然の腹痛と頭痛と熱により、本日突然な休みをゲットしてしまい、せっかくだからReactでHello Worldしてやろう!と思い立ったぐーどらです。休め

modprobe vboxguest failed

さて、CentOS8がリリースされてから随分日が経ちましたが、しっかり情報はゲットしていました。折角なんで気分新しく、新品の仮想マシン上でコーディングしたいなあという欲望に駆られ、CentOS8のイメージを使ったVagrantマシンの作成を始めました。そこで出てくる下記のエラー。

VirtualBox Guest Additions: Look at /var/log/vboxadd-setup.log to find out what
went wrong
modprobe vboxguest failed
The log file /var/log/vboxadd-setup.log may contain further information.
An error occurred during installation of VirtualBox Guest Additions 6.0.12. Some functionality may not work as intended.
In most cases it is OK that the "Window System drivers" installation failed.
Redirecting to /bin/systemctl start vboxadd.service
Job for vboxadd.service failed because the control process exited with error code.
See "systemctl status vboxadd.service" and "journalctl -xe" for details.

ほう…どうやらGuest Additionsが機能していない模様…仮想マシンで共有ディレクトリが使えなくなるのは痛すぎるので、早速エラーに書かれているvboxadd-setup.logを確認します。

$ cat /var/log/vboxadd-setup.log
Building the main Guest Additions 6.0.12 module for kernel 4.18.0-80.el8.x86_64.
Error building the module.  Build output follows.
make V=1 CONFIG_MODULE_SIG= -C /lib/modules/4.18.0-80.el8.x86_64/build M=/tmp/vbox.0 SRCROOT=/tmp/vbox.0 -j1 modules
Makefile:958: *** "Cannot generate ORC metadata for CONFIG_UNWINDER_ORC=y, please install libelf-dev, libelf-devel or elfutils-libelf-devel".  Stop.
make: *** [/tmp/vbox.0/Makefile-footer.gmk:111: vboxguest] Error 2
Could not find the X.Org or XFree86 Window System, skipping.
modprobe vboxguest failed

ふむふむ。どうやら前提ライブラリがなにか足りていないようですね。というわけで、please install 以下にかかれているライブラリのインストールを試みます。結局CentOS8ではelfutils-libelf-develのみインストールが可能でした。

インストール後にvagrant reloadをすると、[default] No Virtualbox Guest Additions installation found.が出ましたが、正常に起動します。それ以降は正常に起動がおこなえるようになります。

まとめ

CentOS8のVagrantイメージでvbguestを使いたいときはdnf install elfutils-libelf-devel