B-Teck!

お仕事からゲームまで幅広く

【雑記】だめでした

近況

4~6月期の目標立てるような状態でもないのですが、なんか投げっぱなしもあれなのでとりあえず現状報告の記事を書きました。
うちの会社も世間の流れに漏れず在宅勤務になっているんですが、通勤の辛さがなくなるのはいいですね。
仕事の辛さは無くなりませんが。
直近で恩師、というか尊敬していた一緒に仕事のしたことある人が二人も辞めてしまうという現実を目の当たりにし、打ちひしがれています。
一緒に働きたいと思ってる人がバシバシ辞めていくので、寂しさがあります。もちろん辞める人だけがそうであるわけではないですけど。

ここからだめだったはなしです。

【雑記】前に進むしかないという話 - B-Teck!
これで言ってた案件がどう考えても終わらない分量だったので突き抜けて今月もやってます。
だいぶメンタルがやられている中でヘビーな要件を設計・実装に一人で落とし込んでおり、正直先週あたりは記憶がおぼろげです。
なんとか実現の光が見えてきたのですが、そのためには後2週間でほぼ実装しきらねばならず、苦しい。
5月頭の連休は休める予定なのでいっぱい寝たいです。

【雑記】2020年の目標 その1 - B-Teck!
年末から始めてたよさげな生活習慣(運動・睡眠・食事・水分摂取等)はことごとく破壊され、歩数とtogglによるトラッキングのみ継続しています。
とはいえ毎日8000歩も歩いていると在宅勤務でもだいぶマシですね。

色々と息苦しい昨今ですが、4月末までなんとか走りきりたいと思いますので、またお会いしましょう。

【MySQL/Docker】docker-composeでMySQL5.7のイメージを作成して接続する備忘録

参考にした記事

本記事はこれらの記事を参考に自分でDBを構築してみた作業メモとなります。
不明点があれば、下記の記事をご覧いただくことで解決するかもしれません。

環境

macOS Mojave 10.14.6  
Docker version 19.03.5, build 633a0ea  
docker-compose version 1.25.4, build 8d51620a  

最終的なプロジェクトのディレクトリ構成例(MySQLの場合)

今回は下記のようなプロジェクトを作成することを目標とします

sample-project/
             ├ docker/
             |       └ mysql/
             |              ├ conf.d/
             |              |       └ my.cnf
             |              ├ initdb.d/
             |              |       ├ data.csv
             |              |       ├ import.sh
             |              |       └ ddl.sql
             |              └ Dockerfile
             └ docker-compose.yml            

インストール

  • docker for macをインストール
$ brew cask install docker
$ brew install docker-compose

Dockerfileを作成する

Dockerfileにimageの内容を記述することでそのとおりのimageが作成される
MySQL 5.7のimageを作成するには下記のように記載する

FROM mysql:5.7
RUN touch /var/log/mysql/mysqld.log # 指定の場所にログを記録するファイルを作る

docker-compose.ymlを作成する

プロジェクト内に含んでいるServiceのportやvolumeなどの設定を行うことができる。

version: '3.3'
services:
  db:
    build: ./docker/mysql
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_DATABASE: sampledb
      MYSQL_USER: user
      MYSQL_PASSWORD: password
      MYSQL_ROOT_PASSWORD: mysql
    ports:
      - "3314:3306"
    volumes:
      - ./docker/mysql/initdb.d:/docker-entrypoint-initdb.d
      - ./docker/mysql/conf.d:/etc/mysql/conf.d
      - ./log/mysql:/var/log/mysql

my.cnf(MySQLの設定ファイル)を作成する

[mysqld]
character-set-server=utf8mb4                # mysqlサーバー側が使用する文字コード
explicit-defaults-for-timestamp=1          # テーブルにTimeStamp型のカラムをもつ場合、推奨
general-log=1                              # 実行したクエリの全ての履歴を記録
general-log-file=/var/log/mysql/mysqld.log  # ログの出力先

[client]
default-character-set=utf8mb4               # mysqlのクライアント側が使用する文字コード

initdb.d配下配置したスクリプトでDBの初期化を行う

https://hub.docker.com/_/mysql/

Initializing a fresh instance When a container is started for the first time, a new database with the specified name will be created and initialized with the provided configuration variables. Furthermore, it will execute files with extensions .sh, .sql and .sql.gz that are found in /docker-entrypoint-initdb.d. Files will be executed in alphabetical order. You can easily populate your mysql services by mounting a SQL dump into that directory and provide custom images with contributed data.

公式イメージは /docker-entrypoint-initdb.dに.sqlや.shを置いておけば初回起動時に実行 してくれる。
今回はdocker-compose.ymlのvolumeに ./docker/mysql/initdb.d:/docker-entrypoint-initdb.d を記載しているので、 /docker/mysql/initdb.d にリソースを配置する。

初期化処理でテーブル作成

  • 初期化用のDDLを配置
mysql/initdb.d/
            └ ddl.sql
  • ddl.sql
CREATE TABLE users (
    name VARCHAR(32) NOT NULL,
    email VARCHAR(32) NOT NULL
);

初期化処理でテストデータimport

  • 読み込み対象のcsv等と、それをimportする.shを配置
mysql/initdb.d/
            ├ data.csv
            └ import.sh
  • data.csv
exam taro,xxxx@mail.co.jp
  • import.sh
mysql -uroot -pmysql --local-infile sampledb -e "LOAD DATA LOCAL INFILE '/docker-entrypoint-initdb.d/data.csv' INTO TABLE users FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\n'"

プロジェクトのルートでdocker-composeコマンドを実行

今回の場合は sample-project/ 配下で実行します。

$ docker-compose up # コンテナを作成しスタートする
$ docker-compose ps # コンテナの状態を確認

各種コマンドメモ

  • up
    docker-compose.ymlで定義したサービスを開始または再起動する
  • run
    service名を指定して特定のサービスのコンテナと依存するコンテナを起動する
  • start
    既に作成済みのコンテナを再起動する
  • stop
    サービスを停止させる
  • down
    コンテナの停止、削除、さらにネットワーク、記憶領域を全て削除
  • ps
    存在するコンテナのリストを表示する

起動したMySQLに接続

コンテナ内からDBにアクセスできることを確認

$ docker exec -it sample-project_db_1 bash # sample-project_db_1コンテナでコマンドを実行
# mysql -u user -ppassword sampledb # 作成したmysqlにログイン
mysql> show tables; # テーブルが作られているか確認する
mysql> select * from users; # 仕込んだデータが入っているか確認する

ホスト名 ポートを指定してログイン

  • docker-compose ps でIP、portを確認
$ docker-compose ps
       Name                   Command            State            Ports         
--------------------------------------------------------------------------------
sample-project_db_1   docker-entrypoint.sh       Up      0.0.0.0:3314->3306/tcp,
                      mysqld                             33060/tcp              
  • 確認したIP, portをそれぞれhost、portに指定してログイン
$ mysql --host 0.0.0.0 --port 3314 -u user -ppassword

IntelliJやSQL Clientから接続する

GUI環境から接続する際には、ターミナル上で確認したhost名ではなく 127.0.0.1 を指定して接続する必要があるよう f:id:beatdjam:20200305114734p:plain

【本/DDD】 わかる! ドメイン駆動設計~もちこちゃんの大冒険~読書メモ

booth.pm

こちらの本を読みました。
ストーリー仕立てでドメイン駆動設計の戦略的な部分を平易に説明してくれる良本で、DDDの用語にとっつきづらさを感じていた自分にはちょうどよい内容でした。
戦術的な部分については一切書かれていないので注意。
次は「ドメイン駆動設計入門 ボトムアップでわかる! ドメイン駆動設計の基本」を読んで、戦術的な部分を抑えてみようかなと思ってます。

ドメイン駆動設計入門 ボトムアップでわかる!ドメイン駆動設計の基本

ドメイン駆動設計入門 ボトムアップでわかる!ドメイン駆動設計の基本

  • 作者:成瀬 允宣
  • 発売日: 2020/02/13
  • メディア: 単行本(ソフトカバー)

以下読書メモです

DDDってなに?

DDDとは

  • DDD = Domain Driven Design(ドメイン駆動設計)のこと
  • ドメイン駆動設計はソフトウェア開発手法であり、ソフトウェアモデルを設計する指針となる手法・理論・概念

DDDでは何をする?

  • 開発者とドメインエキスパートが協力してドメインを反映したモデル(ドメインモデル)を作り上げる
    • ドメインとはソフトウェアを適用する対象領域 ソフトウェアを通して表現したいなんらかの業務など
    • ドメインエキスパートとはドメインに対して知識を持っている人 業務の流れ/業務知識/既存設計/営業視点/実際の業務/運用の歴史など

ドメインを反映したモデル

  • ドメインを反映したモデルとは、ドメインを構成する物・概念・振る舞い・関係性を表現したもの 業務を構成するタスクがどのような関係性を持ち、どのような役割・振る舞いを期待されて存在しているか
  • DDDを効果的に行い、現実世界を適切に表したモデルを作るにはプロジェクトが下記のように進んでいると望ましい
    • 開発がイテレーティブである
    • 開発者とドメインエキスパートが密接に関わっている

DDDをすべき理由

  • ドメインエキスパートと開発者が相互に連携しモデルを作り上げることで、全員が業務・ソフトウェアを理解した状態を作り出せる

DDDの要素

  • DDDを構成する要素として、戦略的設計と戦術的設計がある
    • 戦略的設計
      • ユビキタス言語などの考え方や概念についてのもの
    • 戦術的設計
      • エンティティ・値オブジェクトなどの技術的手法
  • 戦術的設計だけを適用してもそれなりにメリットは得られるが、戦略的設計を行った上で戦術的設計を適用することがDDDの本旨

ユビキタス言語ってなに?

ユビキタス言語とは/ユビキタス言語を見つけるには

  • ドメインエキスパート・開発者間で共通となる、ドメインやその要素・振る舞いや関連性などを一意に表すための言葉
  • 関連する人間が同じものを同じ言葉で表すことが大事
    • そうでないものは徐々に排除し、置き換えていく

変化し続けるユビキタス言語

  • ユビキタス言語はソフトウェアの成長とともに常に変化しうるものであり、用語集的なものを用いると陳腐化しやすい
    • ので、ソフトウェアのコメントなどにできると良い

ユビキタス言語の適用範囲

  • 同じものを同じ言葉で話すことで認識の齟齬が減り、手戻りや修正、そもそもの認識の違いなどと言ったリスクが回避しやすくなる
  • プロジェクトの中での会話・ドキュメント・ソースコードなど、あらゆる範囲で同じ言葉を用いる

ユビキタス言語とドメインモデル

  • ドメインモデルはユビキタス言語で表されなければならない
  • つまり、ドメインモデル及びその実装についてユビキタス言語で定義できる状態になっていなければならない

ユビキタス言語の確立

  • 既に存在していたりするフレーズなどを収集する
    • 現在のドキュメントに存在するフレーズ 同じ存在を表しているもの/現象だけがあるもの/概念だけがあるもの
    • ドメインエキスパートが用いる言葉・単語
    • それらの振る舞いを表す言葉
  • 収集した言葉をチーム内で議論し、1つの言葉に収束させていく

ドメインモデル

ドメインモデルとは

  • ドメインを反映した概念的なモデル
  • チーム内での名前・関係性・振る舞いの概念を規定する
  • コードで表現されたドメインモデルが成果物であり、設計である状態を維持することがドメイン駆動設計

ドメインモデル貧血症

  • ドメインモデルが値を保持するだけのオブジェクトとなっていたり、ドメインモデルに振る舞いが規定されていない状態
  • ユビキタス言語に基づいてドメインの振る舞い・意図を実装したものこそがドメインオブジェクト

境界づけられたコンテキストって?

ドメインとは

  • 何らかの業務を表す領域のようなもの
  • 殆どのソフトウェアのドメインは複数のサブドメインの集合体である
    • サブドメインの種類
      • そのドメインを表すのに必要不可欠なコアドメイン
      • 業務にロックインしている、独自の機能、領域を表す支援サブドメイン
      • 十分に汎化され、なくても成り立つ、代替可能である汎用サブドメイン

境界づけられたコンテキストとは

  • ユビキタス言語やドメインの概念は、特定のコンテキストの中でのみ通用する概念である
  • サブドメイン単位であることもあれば、サブドメイン内で担当チームごとにコンテキストの境界が存在することもある
  • 解決したい問題に対して適切なサイズの境界付けを行うことで、チーム内が一つの概念を扱う形に統率できる

コンテキストマップ

コンテキストマップとは

  • 複数の境界付けられたコンテキストとその関係性を描いたもの
  • 境界付けられたコンテキスト自体の名前をユビキタス言語から取る

コンテキストマップの役割

  • ありのままの現状を表現する
  • それぞれのコンテキストの関係性、振る舞いについて、チーム内に共有と理解をもたらすもの

コンテキストマップを活用する

境界づけられたコンテキストの関係性のパターン

  • 共有カーネル
    • 2つのチーム間でコンテキストをやり取りをするための、ドメインモデルのサブセット
    • 自分たちのコンテキストと共有カーネルだけを意識すれば良くなる
  • 顧客/供給者の開発チーム
    • 2つのチームで開発しているシステムに相互の関係があり、片方が完全に依存している場合に適用できるパターン
      • 上流を供給者、下流を顧客と見立てて顧客と供給者という関係で定義する
      • 上流が下流の要望に答えるメリットがない場合はこのパターンの適用が難しい
    • 下流が要件を洗い出し、上流へ伝える
    • 上流は下流に対して要件を満たす適切なインターフェースを提供する
  • 順応者
    • 2つのチームで開発しているシステムに相互の関係があり、顧客と供給者の関係を築けない場合のパターン
    • 下流のチームが順応者として上流チームの提供するドメインモデルに従い開発するパターン
    • 上流のコンテキストに合わせた開発を行うため下流の負荷は高くなるが、開発を進めることは出来る
    • 順応者として振る舞えるほどコンテキストが単純でない場合、後述の腐敗防止層のパターンを用いることも出来る
  • 腐敗防止層
    • 境界づけられたコンテキスト間の変換にかかるコストが高い場合に、変換用のレイヤを用意するパターン
    • レイヤを持つことで独自のユビキタス言語、ドメインモデルを保つ
  • 別々の道
    • 要件を整理した結果コンテキスト間の関係が薄かった場合に、それらの関係を切り離して独立したドメインモデルとすること
  • 公開ホストサービス
    • 多くのコンテキストと関連する場合、個別に変換するレイヤを設けず、プロトコルとインターフェースを定義・公開するパターン
    • 1対他の共有カーネルのようなもの?
  • 公表された言語
    • 公開ホストサービスが提供するプロトコルとして利用する言語
    • 独自にプロトコルを生み出すのではなく、一般的に広く利用されているxmlやjsonなどを介すことで問題を簡単にする
  • 巨大な泥団子(巨大なコンテキスト)
    • 既存のシステムがドメインで整理されておらず、分割も難しい場合に一つのコンテキストとして隔離してしまうこと
    • 巨大なコンテキストの整理を一旦諦めて、腐敗防止層などを用意して腐敗が溶け込まないようにする