じぶん対策

日々学んだことをアウトプットして備忘録にしています。

DDD(Domain Driven Design: ドメイン駆動設計)について

参考文献

ドメイン駆動設計の用語と解説(抜粋版)
DDD難民に捧げるDomain-Driven Designのエッセンス
ドメイン駆動設計は何を解決しようとしているのか
クリーンアーキテクチャ完全に理解した   

ドメイン駆動設計とは

  • ひとことでドメイン駆動設計といっても下記のような文脈がある.

そもそもドメインって?

知識、影響、または活動の領域
ソフトウェアが表現する対象のこと。

開発思想としてのDDD

DDDの要点

  • ドメインモデルは、ドメイン知識を深めながら 反復的(iterative) に深化させていく
  • ドメインモデルが、開発者とドメイン知識をもつ人(ユーザ、専門家等)との間の共通言語となるようにする
  • ドメインモデルと実装コードとがきちんと対応付けられるようにする
  • 境界づけられたコンテキストの中のユビキタス言語で話す

境界づけられたコンテキストとは、マイクロサービスの境界をイメージするとわかりやすい。
システムが大規模になると関係者全てで統一してモデルを作るのは困難になる。
一定のコンテキストで分割し、それぞれの中で統一したモデルやユビキタス言語を用いる。
実装面でもモジュールを分割し、複数のコンテキストをまたがる場合はお互いの変更が影響を与えないように設計する。(後述の戦術的設計を参照)

背景

まず、業務をシステムに落とし込む際、以下の手順で行う。
1. 現実の業務を適切に抽象化した分析モデルの作成
2. 1で作成した分析モデルをもとにした設計

しかし、現実には分析モデルには存在しない概念が設計で必要になることが多く、この二つはどんどん乖離していく。(実装上の都合で処理を追加しても要件を満たせてしまうが、ドメインモデルからは遠ざかる)

乖離するとどうなるのか

  • 設計と分析モデルに乖離が大きいとそもそもソフトウェアが正確かどうかも疑わしい。
  • 設計と分析モデルの紐付けが複雑になればなるほどコードを理解するのが難しくなる
  • やがて設計が変更された際に分析モデルとの紐付けを維持できなくなる
  • それぞれの作業で得られる洞察が互いに生かされることはなくなる

特に最後のモデルの改善からソフトウェアに生かすことのできる利益を得るという部分がドメイン駆動設計の目的。以下参照
ドメイン駆動設計は何を解決しようとしているのか

戦術的設計

レイヤードアーキテクチャ

DDD本で言及されている、ドメインを隔離するためのアプリケーションアーキテクチャ。 分析モデル(ドメインモデル)が設計に忠実に反映されているかを確認するためには、ドメインを表現する責務をどこで持つかを明確にしないといけない。
レイヤードアーキテクチャは以下の四層に分かれる。 - UI/プレゼンテーション - アプリケーション - ドメイン - インフラストラクチャ

それぞれの説明は以下 - UI/プレゼンテーション層
ユーザーに情報を表示してユーザーのコマンドを解釈する責務を負う。 - アプリケーション層
ソフトウェア行うことになっている仕事を定義し、表現力豊かなドメインオブジェクトが問題を解決するように導く。やるべき作業を調整するだけで、実際の処理はドメインオブジェクトによって直下のレイヤで実行される共同作業に委譲する。 - ドメイン
ビジネスの概念と、ビジネスが置かれた状況に関する情報、およびビジネスルールを表す責務を負う。ビジネスの状況を反映する状態はここで制御され使用されるが、それを格納するという技術的な詳細は、インフラストラクチャに委譲される。この層がビジネスソフトウェアの核心である。 - インフラストラクチャ
上位のレイヤを支える一般的な技術的機能を提供する。これには、アプリケーションのためのメッセージ送信、ドメインのための永続化、ユーザインタフェースのためのウィジェット描画などがある。インフラストラクチャ層は、ここで示す4層間における相互作用のパターンも、アーキテクチャフレームワークを通じてサポートすることがある。

DDDパターン

そもそもドメインモデリングを提唱しているのはEric Evansの『Domain-Driven Design』という書籍。
この本はよくあるパターン本の一つ。先述したドメイン駆動設計を具体的な実装に落とし込むためのパターン。

基本

  • Ubiquitous Language(ユビキタス言語)パターン
    ドメインを正しく捉えた柔軟で価値の高いソフトウェアを設計するには、チームの共通言語を創造しなければならない。共通言語はユーザ、ドメインの専門家から、設計者、プログラマまで、分析/設計モデルからプログラムコードに至るまで、プロジェクトのすべての関係者、成果物に行き渡っていて、同じ意味で理解されるようなユビキタス(遍在的)な言語である。ドメインモデルがユビキタス言語となるようにし、ドメインモデルを介してプロジェクトが一体となるようにする。
  • Model-Driven Design(モデル駆動設計)パターン
    ユビキタス言語を実現するには、プログラムコードにおいてもドメインモデルが正確に表現されていなければならない。ドメインモデルとプログラムコードとが常にお互いを反映するように保つことで、ドメインモデルの変更がそのままコードの修正を促し、逆にコーディングの中で得られた新たなドメイン知識が即座にドメインモデルに反映されるようになる。このようにモデルとコードを緊密に結びつけるのがモデル駆動設計(MDD)である。MDDを実践するには、開発ツールやオブジェクト指向プログラミング(OOP)のようなプログラミングパラダイムが必要になる。
  • Hands-On Modeler(実践的モデラー)パターン
    もしモデラーがプログラムを書けなかったり、プログラマドメインモデルに興味を示さなかったら、MDDの利点であるモデリングとプログラミングの好循環は生まれない。また、チームのコミュニケーションもそこで停滞してしまう。MDDを通してユビキタス言語を実現するには、モデラーが動くプログラムを書けなければいけないし、同時にプログラマドメインモデルを理解し、修正できなければならない。つまり、チームのすべての開発者は、プログラムを書くモデラーでなければならない。

他にも16パターンが存在する。 まとめは以下のサイトにいい感じに載ってるから確認しておく。
DDD難民に捧げるDomain-Driven Designのエッセンス

まとめ

  • ドメイン駆動設計の目的は実際の業務(ドメイン)をモデル化したものと実装の差を少なくして、モデルの改善とソフトウェアへの反映を容易にすること。
  • そのためにモデルをできる限りソフトウェア上に表現することを目指す。
  • ひとことでドメイン駆動設計といっても下記のような文脈がある.

できる限りドキュメントメンテナンスコストを下げたい [Doxygen] [phpDocumentor]

はじめに(長めの前置き)

大前提として、「コードは必ず変更される」ことはエンジニアであれば理解されていると思います。
経験上、コードを書いて1回切りの「作り捨て」にすることはまずありません。
自分が変更するかもしれませんし、他人が変更することもあるでしょう。
よく「三日後の自分は他人」とも言いますが、そう考えるとほとんどの場合、書いたコードを変更するのは「他人」ということになります。
コードを書く際の判断や選択はこの前提を忘れないようにしましょう。

ソフトウェアというのは複雑なものです。 完璧なソフトウェアというのは存在せず、障害が発生したり、ユーザーからの要望を反映しなければならないことがあります。

コードを理解するとき、その助けとなるのが各種設計書です。
ただ、設計書は往々にして腐ります。
コードはさまざまな要因で変更されますが、それに合わせて設計書を変更するのが手間だからです。

そこで、できるだけ楽をしてドキュメントを作成できれば、設計書のメンテナンスコストを下げることにつながると考え、ツールを使用してアプローチしてみたいと思います。

本記事では、PHPを使用したチーム開発環境を前提として、Doxygenとphpdocumentorを導入してみてその違いを触って理解してみます。

本記事は書いてある通りに実行すれば導入できるような親切な記事ではなく、実際に導入してみたいなと考えた時に必要な情報のみを記載します。

特にサンプルについてはあまり見当たらなかったのでよければ参考にしてください。 詳しい設定等は公式ドキュメントなどを参照してください。

Doxygenのインストール

参考

https://qiita.com/hyt-sasaki/items/8f8312e277d1a4815ab6

Doxygenとは

簡単にいうと、コードに記載されたコメントをもとに、設計書やクラス関係図などのドキュメントを生成してくれるツールです。

公式リンク http://www.doxygen.jp/

今回はDockerを用いたチーム開発を前提として環境構築してみます。

Docker Hubからhytssk/doxygenというイメージをpullしてきます。

docker pull hytssk/doxygen

Doxyfileの作成

DoxygenDoxyfileという設定ファイルを使用します。 下記コマンドを実行して生成します。

docker run --rm -v "${PWD}":/src hytssk/doxygen -g

内容の編集については公式ドキュメントを参照してください。(コメントを読むだけでもある程度わかります。)

参考サイト:

http://www.doxygen.jp/config.html

https://cercopes-z.com/Doxygen/list-config-dxy.html

動作確認用変更箇所

僕が動作確認した際に変更した箇所をメモしておきます。 もっと変えた方がいい箇所があるかもしれないです。

OUTPUT_LANGUAGE = Japanese
EXTRACT_ALL            = YES
WARN_LOGFILE           = "ログファイル名.txt"
INPUT                  = ソースコードのパス
RECURSIVE              = YES
SOURCE_BROWSER         = YES
GENERATE_LATEX         = NO
CALL_GRAPH             = YES
CALLER_GRAPH           = YES

ドキュメント化

ソースコードDoxygen用のコメントを記載した上で使用します。 以下コマンドを実行することでドキュメントが生成されます。

docker run --rm -v "${PWD}":/src hytssk/doxygen Doxyfile

phpDocumentor

phpDocumentorとは

Doxygenと同じくソースコードからドキュメントを生成するツールです。

公式Github

https://github.com/phpDocumentor/phpDocumentor

Dockerイメージ

https://hub.docker.com/r/phpdoc/phpdoc/

参考サイト

https://wand-ta.hatenablog.com/entry/2019/05/18/233631

http://blog.livedoor.jp/haruchaco/archives/1340012.html

実行

まずはDoxygenの時と同じくDocker hubからpullします。

docker pull phpdoc/phpdoc

ドキュメント生成

docker run --rm -v $(pwd):/data phpdoc/phpdoc -d [ソースコードのディレクトリ] -t [出力先のディレクトリ] 

以下のオプションを使用することでクラス図などの図が出力されます。

--setting=graphs.enabled=true

以下のオプションを使用すると出力形式を変更できます。 他にも種類があるようなので公式を参照してください。

--template="clean"

比較

インストールの容易さ

phpdocumentorの方がインストールが簡単だという意見を見かけました。
->まあ今回のようにDocker使うなら大して差はないです。

出力の違い

個人的にはphpDocumentorの方が新しいツールなのもあって出力結果のUIがいい感じだと思う。 DoxygenPHPへの対応が少し弱いのでこの部分でphpDocumentorを選択するのはアリだと思います。 (ちなみにC言語JavaDoxygenを使用したことがあるがその時はいい感じだった。)

サンプル

個人的に作ってるコードをドキュメント化してみました。
簡単なValueObjectのみ作成しているが、Interface,abstractなどを使用してクラス図を確認できるようにしています。
コメントにツール用の記述をすることでさらにドキュメントを充実させることができます。(というかそれが本来の使い方)
ひとまず図を見たい人のためのサンプルだと思ってください。
またサンプルコードが充実したら追記しようかな。

Doxygenのサンプル
https://taiseimiyaji.github.io/doxygen_sample/

phpDocumentorのサンプル
https://taiseimiyaji.github.io/phpDocumentor_sample/

所感

ドキュメントのメンテナンスはコストがかかるしめんどくさいものです。
特に規模が小さい場合、わざわざドキュメントを作ることに後ろ向きになりがちだと思います。
今回紹介したツールを使用すればさほど手間なくドキュメントを作成することができます。

チーム開発の場合は個人の力量に差があることが多く、その差を埋める手助けになればと思います。
また、上級者から初学者への説明の際の資料としても有用だと思いました。

個人的にはこういうめんどくさいなあと感じたことを自動化する瞬間が一番エンジニアであることを実感します。

マイグレーションについて

参考

https://readouble.com/laravel/8.x/ja/migrations.html#column-method-integer

https://tohokuaiki.hateblo.jp/entry/2016/12/26/%E3%80%8CLaravel%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9%E3%80%8D3_%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9

https://onetech.jp/blog/how-to-migration-in-laravel-11913#:~:text=%E3%83%9E%E3%82%A4%E3%82%B0%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AF%E3%80%81Laravel%E3%82%92%E7%94%A8,%E5%8A%B9%E7%8E%87%E3%82%82%E5%90%91%E4%B8%8A%E3%81%97%E3%81%BE%E3%81%99%E3%80%82

マイグレーションとは

Lravel公式には以下の記述があります。

マイグレーションはデータベースのバージョン管理のようなもので、チームがアプリケーションのデータベーススキーマを定義および共有できるようにします。ソース管理から変更を取得した後に、ローカルデータベーススキーマにカラムを手動で追加するようにチームメートに指示する必要があったことを経験していれば、データベースのマイグレーションにより解決される問題に直面していたのです。

マイグレーションとは、「移行」を意味します。 テーブル定義を管理するために実行するコマンドです。 テーブルに変更があった際、チームのメンバーのテーブルを簡単にアップデートが行えます。

Laravelにおけるマイグレーション

マイグレーションファイルの作成

php artisan make:migration ファイル名

上記コマンドを実行すると、database/migrationsの下にマイグレーションファイルが作成されます。

この時のファイル名には、Laravelがマイグレーションの順序を決定できるようにするタイムスタンプを含めて作成されます。

ただし、この時指定するファイル名が既存のものと被るとClass名として被るため、Fatalになって失敗します。

これを回避するために、create_hogehoge_tableみたいな感じで操作名とテーブル名などを含むようにして被ることの無いよう工夫する必要があります。

マイグレーションファイルの編集

先述したartisanコマンドでマイグレーションファイルを作成すると、デフォルトでupdownというメソッドが定義されています。

upメソッドにはデータベース構造の変更を実施する際に実行される内容を記述します。 downメソッドにはupメソッドの操作を元に戻す内容を記述します。

記述後、

php artisan migrate

を実行することでマイグレーションが実行されます。

マイグレーションの取り消し

マイグレーションを行った後、取り消したい場合には以下のコマンドを実行することでロールバックすることができます。

php artisan migrate:rollback
php artisan migrate:reset

また、指定した回数分巻き戻す場合は--stepオプションで巻き戻したい件数を指定しましょう。

全てのデータベースマイグレーションロールバックし、それからmigrateコマンドを実行したい場合は以下のコマンドで対応できます。データベース全体を作り直すために便利なコマンドです。

php artisan migrate:refresh

また、--seedオプションを付けることで全データベースシードを実行できます。

まとめというかメモ

マイグレーションという仕組みを用いることで、チームで開発する際のデータベースの更新の際に生じる問題を解決できます。

詳細なSchemaビルダの使い方は公式ドキュメントに説明を譲るとして、注意しとかないといけないなと感じた箇所をメモしておきます。

  • changeメソッドは存在するカラムを新しいタイプへ変更するか、カラムの属性を変える際に使用します。
  • $table->timestamps();created_atupdated_atの二つのカラムが追加されます。
  • 文中でも一度書きましたが、名前被りには気をつける。
  • migrationはあくまでテーブルの構造なので、中身を作成するのはseederで行う。

所感

Laravelの仕組みを用いることで、チーム開発が捗る部分がとても多いなということを日々実感します。

ただし、Laravelの機能を使用するということはつまり、Laravelに依存するということになります。

クリーンアーキテクチャを意識すると、フレームワークに依存する箇所とそうでない、生のPHPを使用する箇所を分離することになります。 どの部分がLaravelの機能で、どの部分がPHPの機能なのか、しっかり分けられるよう意識しておかないと初学者のうちはごちゃ混ぜになってしまいそうなので気をつけたいと感じました。

RestfulAPIとは

参考

https://lukesilvia.hatenablog.com/entry/20091025/p1 https://qiita.com/NagaokaKenichi/items/0647c30ef596cedf4bf2 https://qiita.com/NagaokaKenichi/items/df4c8455ab527aeacf02 https://qiita.com/NagaokaKenichi/items/0f3a55e422d5cc9f1b9c https://www.sakimura.org/2011/11/1289/ https://qiita.com/mserizawa/items/b833e407d89abd21ee72 https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm

RESTful APIとは

RESTの原則に則って構築されたWeb APIのこと

そもそもWeb APIとは

参考サイトには

厳格な定義はないが、広義にはHTTPプロトコルを用いてネットワーク越しに呼び出すアプリケーション間、システム間のインターフェースのこと。

とあります。

APIは「Application Programming Interface」なので結構広義な言葉ですね。

個人的には

  • Webサービスの画面 ⇨ ユーザー用の出入口(Interface)
  • Web API ⇨ プログラム用の出入口(Interface)

みたいなイメージで理解しています。

RESTとは

Web APIについて調べると避けては通れないのがRESTの概念です。

セットで登場することが多いですがRESTというのはWeb APIのためだけの考え方ではないようです。

RESTはWebのアーキテクチャスタイルです。
アーキテクチャスタイルとは、複数のアーキテクチャに共通するパターンのようなものです。
デザイン(設計)とデザインパターンの関係と抽象度的には近いと思います。

例えば、MVCアーキテクチャスタイルです。具体的なアーキテクチャより抽象度がひとつ高いイメージです。

RESTは、ネットワークシステムのアーキテクチャスタイルです。

ネットワークシステムのアーキテクチャスタイルとして有名なのはクライアント/サーバですが、RESTはこれから派生したものです。 素のクライアント/サーバスタイルにいくつかの制約を加えたものがRESTというアーキテクチャスタイルです。

抽象度のレベル Webにおける例
アーキテクチャスタイル REST
アーキテクチャ ブラウザ,HTTP,URI,HTML
実装 Firefox,IE,Apache

RESTはWeb全体のアーキテクチャスタイルでもあり、個別のWebサービスやWeb APIアーキテクチャスタイルでもあ理ます。

以下、具体的にRESTの内容について見ていきます。

RESTにおける重要な概念の一つにリソースというものがあります。

「リソース指向アーキテクチャ」という概念があり、RESTを語る上で重要なので以下参照先を読んで先に理解しておくとRESTの理解がスムーズそうです。 https://qiita.com/NagaokaKenichi/items/0f3a55e422d5cc9f1b9c

リソースとは、Web上に存在する、名前を持ったありとあらゆる情報のことです。

この名前がWebの場合はURIです。

ただし、1つのリソースは複数のURIを持つことができます。

例えば、

のような二つのURIは同じリソースを指します。 一方は「今日」の情報、一方は「4月25日」の情報を指しているため、それぞれのURIの指す意味は異なります。

このようにURIに別名をつけると、クライアントがリソースにアクセスしやすくなる反面、どれが正式なURIなのかが分かりにくくなってしまう欠点もあります。

RESTの原則について

RESTは主に以下の4つの原則から成り立っています。

ですが原著である以下リンクには特に4つの原則という記述はなかったのでどこから4つの原則になったのか不思議(また調査しておきます)。

https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_1

ちなみにリンク内には以下のようなキーワードで記載があります。

  • Client-Server(クライアント-サーバー)
  • Stateless(ステートレス)
  • Cache(キャッシュ)
  • Uniform Interface(統一インターフェース)
  • Layered System(階層的システム)
  • Code-On-Demand(オンデマンドコード)

一旦、上記のキーワードについては置いておいて、RESTの原則について説明します。
一般的にはRESTの原則とは以下の4つの原則です。

  • アドレス可能性 Addressability

    • 提供するリソースがURIを通して表現できること。全ての情報はURIで表現される一意なアドレスを持っていること。
  • ステートレス性 Stateless

    • HTTPをベースにしたステートレスなクライアント/サーバプロトコルであること。セッション等の状態管理はせず、やり取りされる情報はそれ自体で完結して解釈できること。
      簡単にいうとやり取りするメッセージ内にそれまでのやり取りの情報も含めることでサーバーが状態を持たなくても結果が導き出せること。
  • 接続性 Connectability

    • 情報の内部に、別の情報へのリンクを含めることができること。
  • 統一インターフェース Uniform Interface

    • 情報の操作(取得、作成、更新、削除)は全てHTTPメソッド(HTTPメソッドは8個あるが、主にGET、POST、PUT、DELETE)を利用すること。

RESTful APIのメリット

RESTfulなAPIにすることのメリットについて考えてみます。

いい設計原理への誘導

前述したようにRESTとは、一種の制約です。
つまりこの制約に従う際に苦痛を感じた時、それはWebの自然なアーキテクチャとしての設計が間違っていることを示唆しています。

統一性

RESTに従うことで、統一性が生まれます。その統一性は標準化作業に大きく貢献し、システム間での連携をしやすくします。シンプルかつ一貫性のあるリクエストの標準化が円滑に行えます。

スケーラビリティ

ステートレス性を保つため、負荷に応じて水平方向へスケールしやすいです。

簡単に説明すると、スケーラビリティとは負荷に応じて対応することを指していて、垂直方向はサーバーの処理能力を向上させること、水平方向というのはサーバーの台数を増やすことを指しています。

ステートレス性のおかげで、サーバーが状態を保つことはないため、サーバーを増やす、つまり水平方向へのスケールがしやすいです。

キャッシュ

RESTを通じてHTTPキャッシュを利用することができます。 HTTPキャッシュの要件には「透過性」があり、キャッシュが関与しているいないに関わらず転送される情報が同じになることが意識されています。

利点はサーバーとクライアントの間の通信を減らすことでより効率的に処理できることです。

RESTを用いた設計

リソース指向

RESTfulなAPIやWebアプリケーションの設計はURIの設計が大部分を占めます。

URIごとに何をやるかはHTTPメソッドにて定義されていますし、名前も決められています。

RESTにおいては、「その処理によって得られるリソース」に注目して設計を行います。

これが「リソース指向アーキテクチャ」のことですね。

この辺りは以下参照リンクがとても参考になると思いました。 https://qiita.com/mserizawa/items/b833e407d89abd21ee72

HTTPメソッドに対する正しい設計

HTTPメソッドには、以下のような性質があります。

メソッド 性質
GET,HEAD べき等かつ安全
PUT,DELETE べき等だが安全でない
POST べき等でも安全でもない

べき等とは...ある操作を何回行っても結果が同じこと

基本的にこの性質を逸脱する使い方をしてはいけません。(HTTPメソッドの仕様上、可能だがするべきではない)

ちなみに、リソースの作成については、POSTでもPUTでも行うことができます。 この場合の使い分けは、以下のように考えます。

  • クライアントがリソースのURLを既に知っている場合はPUT
  • サーバーがURLを決定する場合はPOST

POSTの場合、クライアントはリソースのURIを指定できないことから上記の考え方が望ましいです。
PUTの場合はサーバの内部実装を意識しないといけないため、どうしてもサーバとの結合が密になってしまう点に注意が必要です。(URIにどの文字を許すかなどの制限を知っている必要がある)

まとめ

RESTとは、以下の4つの原則から成り立つアーキテクチャスタイルです。

  • アドレス可能性 Addressability
  • ステートレス性 Stateless
  • 接続性 Connectability
  • 統一インターフェース Uniform Interface

他にも、以下のようなキーワードがRESTにおいて重要です。

  • Client-Server(クライアント-サーバー)
  • Stateless(ステートレス)
  • Cache(キャッシュ)
  • Uniform Interface(統一インターフェース)
  • Layered System(階層的システム)
  • Code-On-Demand(オンデマンドコード)

これらRESTの考え方に則ったAPIRESTful APIといいます。

当たり前ですが、RESTに明らかに向いていない場合は他のアーキテクチャスタイルを考えるべきです。

たとえば、他にもSOAPなどのスタイルがあります。
こちらについてもまた調べてみたいと思います。

所感

個人的に今回色々調べる中で、「APIは開発者のためのUIです。」というひとことにかなり納得しました。

ぱっとみて理解できる、想像しやすい、使い易いAPIを設計する上で、RESTの考え方を意識して設計することで理想に近づけるのかなと思いました。
特にどんなリソースに対しても、HTTPメソッドで操作するという統一インタフェースのおかげでどんなサービスでもある程度想像しやすいつくりになると思います。

以前、クリーンアーキテクチャの記事を書いたときに以下のような記述をしました。

  • プログラミングは自由。何でもできる。でも、サービスを作る上では方針をある程度決めておくといろんな事象に対応しやすいし、スムーズに開発できるよね。っていうイメージ。

RESTもまさしくこれに当てはまると思います。 Webをはじめ、さまざまなサービスが統一して一定の制約を守ることで連携しやすい、使いやすいシステムの構築が容易になります。

Laravel Mixについて

参考

https://readouble.com/laravel/6.x/ja/mix.html
https://qiita.com/minato-naka/items/bfc3bbd9a388084e6f17
https://qiita.com/kamykn/items/45fb4690ace32216ca25 https://qiita.com/minato-naka/items/0db285f4a3ba5adb6498 https://goworkship.com/magazine/how-to-webpack/ https://qiita.com/non_cal/items/a8fee0b7ad96e67713eb https://qiita.com/righteous/items/e5448cb2e7e11ab7d477 https://udemy.benesse.co.jp/design/web-design/sass.html http://blog.sakurachiro.com/2017/08/scss_sourcemap/

はじめに

今回の記事はうまくまとまらなかったなと感じていますが、今時点の私の知識ではまとめきれないなと判断しました。
随時更新していきたいと考えています。

Laravelに初めて触った時に僕がつまづいたのはフォルダの多さでした。
この辺りの層の分け方は設計云々も絡んでくると思うので今は触れませんが、 Laravelでは役割ごとにファイルを分けやすい仕組みが用意されていて、その一つがLaravel Mixです。

Laravel Mixとは

以下参考サイトより引用。

Laravel Mixは多くの一般的なCSSJavaScriptプリプロセッサを使用し、Laravelアプリケーションために、構築過程をwebpackでスラスラと定義できるAPIを提供しています。

webpackファイルをよりわかりやすく簡単に書けるように設定ファイルをラップしている。 フロントエンド開発では、webpackというものを使用して開発をするとメリットがあるのですが、設定ファイルが長い。この問題を解決するためのツールがLaravel Mixということらしいです。 ちなみに、Laravelでなくても使用できます。

ざっくりしたイメージ図

そもそもwebpackとは?

https://qiita.com/kamykn/items/45fb4690ace32216ca25 https://qiita.com/minato-naka/items/0db285f4a3ba5adb6498 https://goworkship.com/magazine/how-to-webpack/

ここが一番重要な部分で、webpackがどういうことをしているのかわかればMixはそれのラッパーのようなイメージなのかなと思っています。

webpackとは、主にjsをバンドルするためのモジュールバンドラ。 バンドラ...複数のファイルを1つにまとめて出力してくれるツールのこと。

ちなみに、js以外にもCSSや画像もバンドルできるらしい。

使用することで、

  • ファイルを分割して開発できるため、開発効率や保守性の向上につながる。
  • ファイルを1つにまとめることでリクエストの回数を削減し、パフォーマンスの向上につながる。

webpack.config.jsentry:エントリーポイントファイルoutput:バンドルされたファイル名と出力先パスを書く。

この状態でwebpackコマンドを実行するとbundle.jsが出力される。 あとはこのファイルをhtmlファイルで読み込めば使える。

Laravel Mixのインストール

Laravelをインストールした時点でpackage.jsonが存在しているはずなので、下記コマンドでインストールします。

npm install

このpackage.jsonはNodeの依存パッケージのための構成ファイルです。

Nodeとは、簡単にいうとサーバーサイドでJavaScriptを動かすための仕組みです。 Nodeについては以下を参照するとすんなり理解できるかなと思いました。

https://qiita.com/non_cal/items/a8fee0b7ad96e67713eb

PHPの場合はcomposer.jsonにあたるやつです。

ちなみに、npm installpackage.jsonに基づいてdependencyがインストールされ、実際にインストールされたバージョンがpackage.jsonに書き込まれます。
既にpackage-lock.jsonが存在する場合、基本的にはpackage-lock.jsonに基づいてインストールされます。
package.json内で指定されたバージョンとpackage-lock.jsonに矛盾があればpackage.jsonが優先され、インストールされたバージョンがpackage.jsonに書き込まれます。

package-lock.jsonを優先させたい場合は、npm installの代わりに

npm ci

を実行します。

環境構築の際にこの辺りのパッケージのバージョンでトラブルが発生することが考えられるので基本的にはpackage-lock.jsonが存在する場合はそちらを参照した方がよさそうです。

https://qiita.com/righteous/items/e5448cb2e7e11ab7d477

Laravel Mixの使用

Laraavel Mixは先述した通り、webpack上の設定のためのパッケージなので、

package.jsonファイル上のNPMスクリプトの1つをMixの実行で起動する。

公式サイトにはこんな感じで書かれてますが、要するにnpmコマンドで実行しろってことですね。

npm run dev

のような形で実行します。

以下のように

npm run watch

を実行することで関連ファイルが更新された際に自動で再コンパイルしてくれます。

実際の操作について

先述した通り、webpackの設定ファイルをより簡単に書くための仕組みがLaravel Mixですが、具体的にどう書いてどういう流れで処理されるのか、公式例等を用いて確認していきます。

公式 https://readouble.com/laravel/6.x/ja/mix.html

webpack.mix.jsファイルは全アセットコンパイルのエントリポイントです。 つまり、このファイルに設定を書くことでwebpackの設定が適用されるイメージです。

Mixを用いることで以下のファイルのコンパイルができます。

  • CSS関係

    • Less
    • Sass
    • Stylus
    • PostCSS
    • 平文CSS
  • JavaScript関係

    • ベンダの抽出
    • React
    • バニラJS
    • webpackカスタム設定

聞いたことのないワードもあるのでそれぞれ確認しながら、記述方法を確認します。

また、公式ドキュメントで以下の内容について触れています。

ここからは公式ドキュメントの内容をなぞりながら僕がわからなかったことについて調査したメモ書きになるので読み飛ばしてもらっても大丈夫です。(うまくまとめられなかった)

Less

LessというCSSプリプロセッサがあります。 https://www.tohoho-web.com/ex/less.html CSSをより簡単に書いてメンテナンスしやすくできるもの、といったイメージでしょうか。 Laravel MixではこのLessCSSコンパイルすることができます。

mix.less(元のlessファイル, 出力先)

のように記載することでコンパイルが可能です。

ちなみにLaravelではMixなどでコンパイルされたあとのデータをpublic配下に置きます。
いろんな場所で部品を作ってそれを文字通りMixして出来上がったものをpublicに出力するイメージです。
(初めてLarabelプロジェクトを見た時このフォルダの意味がわからなくて混乱してました。)

以下、公式ドキュメントの例を紹介します。 resources/less/app.lesspublic/css/app.cssコンパイルします。

単一ファイルの場合

mix.less('resources/less/app.less', 'public/css');

複数ファイルの場合

mix.less('resources/less/app.less', 'public/css')
    .less('resources/less/admin.less', 'public/css');

コンパイル後のファイル名を指定したい場合は第二引数に指定すればいいです。

Sass

SassもLessと同じような形でコンパイルすることが可能です。

https://udemy.benesse.co.jp/design/web-design/sass.html

(Sassとscssなにが違うのかよくわかってなかったことがわかった。)

公式のコード例は以下

mix.sass('resources/sass/app.scss', 'public/css');

Stylus

Stylusも同様にコンパイルできるらしい。 Stylusが何かわからないので調べてみます。

https://qiita.com/morishitter/items/b9a2d78c79c3c07de776

Node.js製のCSSプリプロセッサ。 SassとLessのいいとこ取りをしているらしい。

PostCSS

CSS加工ツール

平文CSS

stylesメソッドを使用することで平文のCSSを一つのファイルにまとめることもできます。 mix.styles([ 'public/css/vendor/normalize.css', 'public/css/vendor/videojs.css' ], 'public/css/all.css');

URL処理

Webpackはスタイルシート中のurl()呼び出しをリライトし、最適化します。 画像への相対パスを含むスタイルシートコンパイルする際にURLを書き換えてくれる機能、といったイメージです。 例

.example {
    background: url('../images/example.png');
}

デフォルトでは、パスを解決してexample.pngを見つけて、public/imagesフォルダにコピーします。

勝手に解釈させずに自分で指定したフォルダ構成を適用したい場合は下記のように記述することでurl()リライトを停止できます。

mix.sass('resources/assets/app/app.scss', 'public/css')
   .options({
      processCssUrls: false
   });

ソースマップ

http://blog.sakurachiro.com/2017/08/scss_sourcemap/

使い方

mix.js('resources/assets/js/app.js', 'public/js')
   .sourceMaps();
  • ソースマップとは
    コンパイルする前のファイルを保持したもの。 コンパイルした後のファイルで不具合があった場合にコンパイル前のどの箇所でエラーが出たか特定しやすくなる。

JavaScriptの操作

mix.js('resources/assets/js/app.js', 'public/js');

このように書くことで以下の利点がある。(この辺りはLaravelのバージョンによって異なる?みたい) - ES2015記法 - モジュール - .vueファイルのコンパイル - 開発環境向けに圧縮

バニラJS

スタイルシートのときと同様に、JavaScriptファイルをまとめることができる。

mix.scripts([
    'public/js/admin.js',
    'public/js/dashboard.js'
], 'public/js/all.js');

Browsersyncリロード

Browsersyncとは 自動的にファイルの変更を監視し、手動で再読み込みしなくても変更をブラウザに反映してくれる。 mix.browserSync()メソッドを呼び出し、有効にする。

公式例

mix.browserSync('my-domain.test');

// もしくは

// https://browsersync.io/docs/options
mix.browserSync({
    proxy: 'my-domain.test'
});

npm run watchコマンドにより、webpackの開発サーバを起動します。 PHPファイルを変更すると、すぐにページが再読み込みされ、変更が反映されるのを目にする。

環境変数

.envファイルの中でキーにMIX_をつけることで環境変数をMixへ注入できる。

MIX_SENTRY_DSN_PUBLIC=http://example.com

.envファイルで定義した内容にprocess.envオブジェクトを通してアクセスできるようになる。

process.env.MIX_SENTRY_DSN_PUBLIC

まとめ

今回は公式サイト+αといった形でうまくまとまらなかった部分がありますが、

  • Laravel Mixを使うことでファイルの分割がしやすくなる(というより、分割した後の管理がしやすくなる)
  • 特にスタイルシートやjsについては分割して管理できるとメリットが大きい

ことが掴めたかなと思います。

所感

普段使っている技術について調べていくと、他の技術との関連性や比較をする機会が出てくるので勉強になります。

詳細を追っていくと時間がいくらあっても足りないのでこのくらいで切り上げようと思いました。 実際使ってみてわかったことなどがあれば随時追記していきたいと思います。

cssコンパイル一つとってもさまざまな方法があり、それぞれの長所があるので理解して使うことで長所を最大限活かせるなと感じました。

また、まだまだ知らない技術が多すぎてなかなか網羅的には調べきれていない部分があるのでもう少し局所的にまとめていく方がいいのかな?と悩んでいます。。。 あとはそろそろ手を動かして勉強していけるようになってきた、、、かな?と思ってます。

Mac OSでLogi Optionが読み込まれなくなる問題への対処方法

初めに

今回は完全に個人的なトラブルへの対処についてメモしておこうと思います。
ロジクールファンは多いと思ってるのでよかったら参考にしてください。

PC周りの環境について

学生時代にPCゲームを割とガッツリやっていたのもあって現在もPC周りはゲーミング系が多いです。
写真には写ってませんが足元にWindowsのデスクトップがあったりして、モニタを共有してます。
(デスクトップもパーツやりくりして中学2年生から同じの使ってるので限界を感じている).
バイスはいいものを買おうと思っていろいろ調べた結果毎回ロジクール製品を購入している気がします。

f:id:taisei_miyaji:20220412192729j:plain
現在のPC環境

モニタや机は学生時代に調達した安物なので買い替えたいです。

最近ロジクールのmx keys miniとmx master3 for macを買いました。(写真手前のキーボードとマウス)
必要経費だと自分に言い聞かせてます。
個人的にはPCゲームするならメカニカルの赤軸が好きなんですがタイピング目的ならmx keys miniも悪くないと思ってます。
何より複数台PCを使用していてかつOSが異なる場合はめっちゃいいと思って買いました。
(REALFORCEは値段見て日和ました。)

www.logicool.co.jp

www.logicool.co.jp

本題

ロジクール製品はボタンのカスタマイズなどをLogi Optionsっていう専用ソフトで行うのですが、Macがスリープするとなぜか無効になるんですよね。
無効になるとボタン設定どころかポインタの速度とかも変わってしまう。 めちゃくちゃ不便。
で、以下のページに辿り着きました。

blog.tanebox.com

どうやらプロセスの終了が手っ取り早いみたい。 でも毎回シェル叩くのも面倒だし、ファイルにして叩くのすらめんどくさい。Finderすら開きたくない。 そこでMacのショートカット機能を使用することを思いつきました。 f:id:taisei_miyaji:20220412193559p:plain こんな感じでメニューバーにピン固定しておけば簡単に呼び出せます。
スリープ解除時に自動で実行されるようにできないかなと考えたんですがスリープ時以外にも発生するのでメニューバーがベストだと判断しました。

所感

この不具合たまにならいいんですが頻度めっちゃ多いんですよね。
ハードが好きなだけにソフトのこの辺なんとかしてほしい。
あとLogi Optionの設定がJSONで書けるとめちゃくちゃいいのにな〜と思ったりしてます。(git管理できるし配布しやすいし。)

bash,zshにおける設定ファイルの読み込み順序について

bashzsh

Macユーザーの場合はどちらかを使用している人が多いのではと思います。
MacOS X Catalina以前はbash、以降はzshが標準のシェルです。

以下のサイトによると、

https://kanasys.com/tech/803

MacOS Xは当初tcshであったのがv10.3 Pantherよりbashに変更された

らしいです。

bashは"バッシュ"らしいですが、zshは"ズィーシェル"らしいです。(ゼッシュじゃないんだ、、、)

今回のテーマは設定ファイル

例えば環境構築の際に設定ファイルにパスを通したりします。
その時にの設定ファイルに設定を書いていて、どのように適用されているのか。
なんかzprofileとかzshrcとかいろいろあるけど違いがわからない、、、。
そういった背景から、設定ファイルの仕組みについて理解しておくべきかなと思い調査します。
(前職が組み込み系でLinuxPCを触ってたのでbashrcに書けばいいんやなくらいの理解はありますが詳しいことは知らなかったので)

設定ファイルの違い

起動時に読み込まれるファイルがbashzshでは異なります。 (bashでパス通してもzshじゃ通ってないみたいなことが起きます)

zshrc?zprofile?

設定ファイルには種類があり、それぞれ読み込まれるタイミングが違います。 (僕は全部zshrcに書いておけばいいと思ってました。)

以下の要素でどのファイルが読み込まれるかが変わります。

  • ログインシェルかどうか
  • 対話モードか非対話モードか

ログインシェルとは

例えば、ターミナルウインドウ開いた時に自動的にzshが立ち上がった状態がログインシェルです。 コマンドラインbin/bashbin/zshを実行した場合は非ログインシェルとなります。

対話モードとは

読んで字の如くターミナルで入力できるかどうかです。 例えばシェルスクリプト実行中はターミナル入力できないので非対話モードです。

設定ファイルの読み込み順

設定ファイルごとにglobalとlocalの二種類が存在します。(この定義が公式のものかどうかは調査できてないですが、理解をしやすくなる上で役に立つので便宜上以下の定義をします。)

  • globalは全てのユーザーで有効にしたい設定を記述します。場所は/etc/xxxです。
  • localは特定ユーザーでのみ有効にしたい場合に記述します。場所は~/.xxxxです。(隠しファイルなのでls -aなどじゃないと表示されません)

ログインシェル-対話モードの場合

global→localの順番で読み込まれます。(globalを読み込んだ後にlocalの内容で上書き読み込みされます)
bashの場合はlocalのファイルを一つ読み込んだあとは以降の探索が行われません。
(例えば.bash_profileに設定を記述していて、.profileにも設定を記述していた場合、後者は無視されます。) zshの場合は全て探索されます。 以下表の上から順番に読み込まれます。

bash zsh
/etc/profile /etc/zshenv
~/.bash_profile ~/.zshenv
~/bash_login /etc/zprofile
~/.profile /~/.zprofile
/etc/zshrc
~/.zshrc
/etc/zlogin
~/.zlogin

ちなみに.bashrc.bash_profileの中で読み込まれます。

ログインシェルの終了時には以下の順で読み込まれます。

終了時のみlocal→globalの順で読み込まれる点に注意

bash zsh
~/bash_logout ~/.zlogout
/etc/zlogout

非ログインシェル-対話モード時

bash zsh
~/.bashrc /etc/zshenv
~/.zshenv
/etc/zshrc
~/.zshrc

非ログインシェル-非対話モード時

bash zsh
$BASH_ENV /etc/zshenv
~/.zshenv

まとめ

  • 基本的にはglobal→localの順に読み込まれるが、終了時のみlocal→globalの順。
  • zshのetc/zshenvは影響範囲が大きいことがわかる。
  • どのファイルに何を書くべきかを考える必要がある。
  • 参考サイトにも書いているが、bashzsh両方から読み込まれるファイルを作ってそこにPATHを通すといいかもしれない。
  • .zprofile.bash_profileにはログインシェルに必要な設定のみを記述し、その他設定は.zshrc.bashrcにどんどん書くのがいいかもしれない。

所感

とりあえず.zshrcに書いておけばいいのかと思ってたのですがちゃんと調べると順番とかあってややこしかったです。
エラーの解決策を探っている時にこういう基本的なことが気になったりして勉強するいい機会になっています。
さくさくタスク進んでいる時よりエラーとか出て試行錯誤している時の方が成長しているまである。
それぞれのシェルの違いについてはまた調べようと思います。
ターミナルのカスタマイズも早くやらなきゃと思いつつまだ手を出せていないのでそのうち記事にします。

参考

https://kanasys.com/tech/803
https://qiita.com/muran001/items/7b104d33f5ea3f75353f
https://bacchi.me/linux/bash-settings/
https://qiita.com/dark-space/items/cf25001f89c41341a9fd