建築士がプログラマーのごとく働かねばならぬとしたら
If architects had to work like programmers...
上記サイトの翻訳です。
ソフトウェア開発という行為が、いかに複雑で困難なことかを説明する時のために残しておく。
全プログラマが泣ける内容になっております。
建築士様、 家を一つ設計施行してくださいな。まだ何が必要か具体的なことはわからないので、そこはよきに計らう方向で。 寝室の数は、2から45までの間。寝室の追加と削除は簡単に出来るようにしといて下さいね。青写真が出来次第あたしが何が気に入ったかを最終判断します。それぞれの青写真について明細書を付けるのをお忘れなく。後で気に入ったのをピックアップできるように。 完成後の家の費用は、今住んでいる家よりも安上がりでないと駄目なことを留意してくださいな。それでいて、今の家の欠陥(あたしが歩くたびにキッチンの床がきしむとか、壁の断熱がなってないとか)が全て修正されている必要があるのは言うまでありません。設計の際には、保守費用も最低になるよう工夫するのもお忘れなく。当然ですがそれにはアルミやビニールやサイディングのような高品質の部材が必要になるでしょう(アルミが使えない場合は、その理由を委細もらさず説明すること)。施行においては最新のデザインと素材を惜しまないように。モデルルームにひけをとらないように。ただし、キッチンには1952年ギブソン製の冷蔵庫を含め、今あるものが全て無理なく収まるようにすること。正しく家を設計するにあたって、当然ですが私の子供たち、義理の家族達に詳細にインタビューするように。そうそう、家に関しては一家言お持ちの姑をお忘れなく。一年に一度も来るんですからね。 選択肢は入念に吟味すること。ただし、最終決定権は当然あたしにあります。ささいなことであたしを患わせないこと。建築士様の仕事は、全体計画をたてて大枠を提示すること。例えばカーペットの色とかは委細。ところで私のダンナは青が好き。 資材調達に関しては心配ご無用。建築士様の第一優先は詳細設計と仕様固めですから。ただし、あたしが計画を承認ししだい、48時間以内に棟上げ完了すること。 あたしの家を設計する際には、いつかはあたしが家を別の誰かに売りに出すことを忘れないこと。将来の買主が誰になっても魅力的なものにすること。計画を仕上げる前に、近所の潜在顧客の了承もとりつけておくこと。 あたしのご近所の新築物件の視察は済ませておいた方がいいわ。あたしも多いに感銘を受けたし。あたしの家に必要なものもたくさんあったし。たとえば25mプールとか。建築士様なら、費用負担を一円も増やさずに出来るわよね。 必要な青写真はすべて取り揃えておくこと。本番デザインは必要ないわ。施工業者の入札に使うだけだから。ただし、設計変更による追加費用は、すべて建築士様の責任だということは念を押しておきます。 建築士様にとってこれほど魅力的なプロジェクトもそうはないでしょう!最新の技術と部材を使って、自由に設計できるんですから。滅多にない機会ですよ。アイディアと完成済みの設計をもって今すぐご連絡下さいませ。 追伸: ダンナはあたしの指示をあまり気に入ってないみたい。建築士様なら、丸く納められるわよね。あたしもいろいろ試してみたのだけどどうもうまく行かなくって。丸く納められないなら、他の建築士を探すことにするわ。 追々伸: もしかして、あたしが必要なのは家じゃなくてトレーラーハウスかも。そう思うならその旨すぐにご連絡を。
ドメイン駆動設計をざっくり把握したい②
前回の続き。
DDDの戦術的設計をざっくりまとめる。
戦術的設計
レイヤ化アーキテクチャ
アーキテクチャパターンの一つで、下位層から順番にインフラストラクチャ層、ドメイン層、アプリケーション層、UI層に分離される。
原則として下位層にしか依存してはいけない。
- ユーザインタフェース層
- 顧客への情報表示や、顧客のコマンドを解釈する責務
- アプリケーション層
- ドメイン層
- ソフトウェアの価値を生み出すビジネスロジックを表現する責務
- インフラストラクチャ層
- 上位層を支える一般的な技術機能(永続化やメッセージング)を提供する責務
依存関係逆転の原則(DIP)
「上位のモジュールは下位のモジュールに依存してはならない。どちらのモジュールも抽象に依存すべきである。
抽象は、実装の詳細に依存すべきではない。実装の詳細が、抽象に依存すべきである。」
- DDDにおけるDIP
インフラストラクチャ層のコンポーネントは、ドメイン層が定義するインターフェースに依存するべきである。
具体的には、インターフェースIRepository
をドメイン層に実装し、具象暮らすRepository
をインフラストラクチャ層に実装する。
エンティティ
一意なモノを表現する概念のことで、実装時は一意に特定するポイントとなる属性や振る舞いだけに注目することが重要。
ビジネスロジックを内包した一般的なクラス群の呼称、getterとsetterしかないドメインモデル貧血症というアンチパターンに注意する。
ドメインサービス
とあるドメインにおいてのサービスは、そのドメインに特化したタスクをこなす、ステートレスな操作のこと。
集約
集約とは、エンティティのまとまりを表し、整合性を保ちながらデータを更新する単位のこと。
責務は、エンティティ群の生成/読み込み/変更/保存等のライフサイクル管理。
ファクトリ
ファクトリとは、集約を生成する責務をもつ概念のこと。
特定の集約にて、別のエンティティ(集約も含む)を生成することが多い。
リポジトリ
リポジトリとは、エンティティから構成される集約の保存と取得の責務をもつ概念のこと。
依存関係逆転の原則
の説明にあるように、リポジトリのインターフェースは、集約と同じドメイン層のパッケージに配置。
リポジトリの具象クラスはインフラストラクチャ層に配置する。
アプリケーション
ここでいうアプリケーションとは、
ドメインモデル、ユーザーインターフェース、アプリケーションサービス、インフラストラクチャのコンポーネント全体を指す。
ユーザーインターフェース
JavaのSpringや.NETのASP.NETなどのWAFがこの層に属する。
ドメインモデルのユーザーインターフェースへのレンダリングは、DTOを用いることが多い(当然他の方法もある)。
アプリケーションサービスが集約インスタンスを取得し、それをDTOにレンダリングする。
ドメインモデルに依存するかどうかはケースバイケース。
アプリケーションサービス
アプリケーションサービスとは、ドメインモデルの調整を行う責務をもつコンポーネント。
ユーザーインターフェースとドメインモデルの橋渡し役となるので、それぞれの層の依存関係を調整するのが大切。
インフラストラクチャ
インフラストラクチャは、アプリケーション全体の技術的機能を提供する責務をもつ。
DIPをい、アプリケーション内のあらゆるクライアントは抽象に依存するようにし疎結合化を図る。
ドメイン駆動設計をざっくり把握したい①
DDDをざっくりまとめておく必要があったので、メモがてらまとめる。
前提
「ソフトウェア開発とは、恐ろしく複雑である」
という事実を真正面から向き合うための方法論。
全プログラマが泣いた建築士がプログラマーのごとく働かねばならぬとしたらという秀逸な例え。
デジタルサービスを事業としている会社にとって「ソフトウェアは事業そのもの」
といえる。
経営がソフトウェアを理解するのも大事だし、開発者が経営を理解するのも大事。
それがそのまま対象ドメインでの競争力になる。
DDDとは
DDD(ドメイン駆動設計)とは、Domain Driven Design の略でソフトウェア開発手法です。
GoFのようなデザインパターンではなく、ソフトウェア設計の概念です。
DDDの登場人物
DDD導入メリット(事業)
開発費用がコスト
から事業投資
へ置き換わる。
- 開発者とドメインエキスパートが共通言語(ユビキタス言語)を用いて視点を揃えることにより、ワンチームであたかも顧客が開発するようにソフトウェアを開発できる
- ドメインエキスパートですら理解が浅い業務ドメインの知識を、チームで共有し開発者視点も含め検討することにより、顧客の理想を超えるソフトウェアを開発できる
- 対象ドメインの複雑さを
ドメインモデル
というDDDの概念を用いて緩和する事ができる - DDDは、
設計がコードであり、且つコードが設計である
と表現されるように、開発時の翻訳コストが減り、実装時の課題を設計段階で気づくことが出来る - DDDは、アジャイル開発が前提なので、イテレーティブでインクリメンタルな開発を行うことが出来る
DDD導入メリット(人物)
各人の望むことが手に入る可能性が高まる。
- 開発者
- 適切で正しいソフトウェア開発手法を用いて、スキルアップしながら楽しく開発したい
- シニア開発者
- 開発者とドメインエキスパートの距離を縮め、事業価値を向上させたい
- ドメインエキスパート
- 開発者とコミュニケーションをスムーズに行い、顧客に喜ばれるソフトウェアを開発したい
- マネージャー
- 開発者が業務知識を得て、ドメインエキスパートが開発力を理解し、協力して結果を出してほしい
DDD導入メリット(具体例)
- 従来
- ドメインエキスパートが話す言葉と開発者の言葉が違い、実装内容にズレが生じる
- 1つの大きなシステムのため、実装(プログラム)が肥大化する
- 処理主体のトランザクションスクリプトでは、変更を入れる際のリスクと工数が肥大化する
1つの大きなシステムのため、DB(永続化層)が肥大化する
DDD
- ドメインエキスパートと開発者で共通言語(ユビキタス言語)で会話したとおりに実装できる
- ドメインとコンテキストを適切に分割することで、業務知識ごとに機能を分離することが出来る
- 業務知識を抽象化した
ドメインモデル
を用い開発を行うため、見通しがよく変化に強くなる - ドメインとコンテキストを適切に分割することで、永続化ストレージ(RDB/NoSQL等)を適切に分離することが出来る
DDD用語集
PHPとnginxとMySQLをdocker-composeでミニマム構築
ちょっとPHP
触ってみたくなったのでnginx
とMySQL
なWebアプリケーションをdocker-compose
で構築してみる。
PHPの環境構築
PHPの実行環境をnginxで構築する場合、PHP-FPMを使いやり取りを行うらしい。
nginx と PHP-FPM の仕組みをちゃんと理解しながら PHP の実行環境を構築する - Qiita
php.ini
ファイルが↓
[Date] date.timezone = "Asia/Tokyo" [mbstring] mbstring.internal_encoding = "UTF-8" mbstring.language = "Japanese"
Dockerfile
が↓
FROM php:fpm-alpine COPY php.ini /usr/local/etc/php/ RUN docker-php-ext-install mysqli pdo pdo_mysql mbstring
nginxの環境構築
nginxのパラメータは正直ググりながら適当にやったら動いたという代物笑。
本格的に使うときにちゃんと調べる。
server { listen 80; server_name _; root /var/www/html; index index.php index.html; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; location / { try_files $uri $uri/ /index.php$is_args$args; } location ~ \.php$ { fastcgi_pass php:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }
index.php
何を表示しようかと思ったけど、とりまDBに接続できてればよいかという発想で書いた。
<?php printf("%s\n", date("Y/m/d H:i:s")); $db = new mysqli("php-db", "root", "zaqroot", "test"); if ($db->connect_errno) { echo $db->connect_errno . " : " . $db->connect_error; exit(); } $arr = $db->query("SELECT * FROM hoge"); while ($val = $arr->fetch_assoc()) { var_dump($val); } $db->close() ?>
docker-compose
肝心のdocker-compose
ファイルがこちら。
MySQL
はlatest
を使ってます。
version: '3' services: nginx: image: nginx:alpine container_name: php-nginx ports: - 8000:80 volumes: - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf - ./www/html:/var/www/html depends_on: - php php: build: ./php container_name: php-app ports: - 9000:9000 volumes: - ./www/html:/var/www/html depends_on: - db db: image: mysql:latest container_name: php-db ports: - 13306:3306 command: --default-authentication-plugin=mysql_native_password restart: always environment: - "MYSQL_USER=root" - "MYSQL_ROOT_PASSWORD=zaqroot" - "TZ=Asia/Tokyo" volumes: - ./mysql/data:/var/lib/mysql
出来たものがこちら
GitHub - yuki-toida/php-tutorial
感想
全然わからないが、なんとなくPHP
を生のまま書くのは死ねる気がする。
一旦Laravel
使ってみてからじゃないと評価できなそう。
というわけで次回はLaravel
使う。
ライブ動画配信システムの構成図書いてみた
全部GCP
で、
ストリーミングサーバはWowza Streaming Engine
アプリケーションサーバはElixir/Phoenix
とりあえずザックリ全体像だけ
誰かの役に立てればいいなと
Cloud Storage FUSEを使ってGCSをGCEにマウントする
Cloud Storage FUSE とは
GCSを、Linux または OS X システム上でファイル システムとしてマウントするためのGoogle謹製OSS。
Cloud Storage FUSE | Cloud Storage | Google Cloud
インストール
gcsfuse/installing.md at master · GoogleCloudPlatform/gcsfuse · GitHub
export GCSFUSE_REPO=gcsfuse-`lsb_release -c -s` echo "deb http://packages.cloud.google.com/apt $GCSFUSE_REPO main" | sudo tee /etc/apt/sources.list.d/gcsfuse.list curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - sudo apt-get update sudo apt-get install gcsfuse
マウントする
GCSのバケット名を bucket-vod
とするとし、マウント元を/home/bucket-vod
とすると、
sudo mkdir /home/bucket-vod sudo gcsfuse -o nonempty bucket-vod /home/bucket-vod
これで、/home/bucket-vod
が bucket-vod
にマウントされる。
GCE起動時にgcsfuseを実行する
GCEのカスタムメタデータに startup-script
に同じコマンドをを仕込む。
これで、サーバー再起動等行っても正常にマウントされる。
sudo gcsfuse -o nonempty bucket-vod /home/bucket-vod
GCE で Wowza Streaming Server をつくる② GPUアクセラレーション編
前回の続き。
この記事ではGPUをGCEで使えるようにする設定を行う。
NVIDIA Driver をダウンロードする
Nvidiaの公式サイトから下記画像の沿ってドロップダウンを選択しダウンロードする。
- Tesla
- K-Series
- Tesla K80
- Linux 64-bit
GCEでNVIDIA Driver を使うためのセットアップ
Set up NVIDIA NVENC accelerated encoding on Debian
この辺を参考にしつつ、ウルトラググりながら依存ライブラリをインストールする。
sudo apt-get update sudo apt-get upgrade sudo apt-get install build-essential sudo apt-get install linux-headers-$(uname -r) sudo apt-get install dkms
blacklist.conf
にblacklist nouveau
を追加する。
vimで編集します。
sudo vim /etc/modprobe.d/blacklist.conf
ここで忘れずにGCE再起動。
NVIDIA Driver をGCEにアップロードしインストールする
GCEインスタンス名をwowza
とし、ドライバをNVIDIA-Linux-x86_64-396.26.run
とすると、
下記SCPコマンドでアップロード可能。
gcloud compute scp ./NVIDIA-Linux-x86_64-396.26.run wowza:~/
GCEターミナル内でドライバを実行権限をつけてインストールする。
chmod +x NVIDIA-Linux-x86_64-396.26.run sudo ./NVIDIA-Linux-x86_64-396.26.run
動作確認
nvidia-smi
コマンドでGPUの使用状況が取得できれば正常にインストール完了。
一筋縄ではいかなかったので、ググラビリティが試されるかも。