やる気がストロングZERO

やる気のストロングスタイル

やっぱり正規化をベースにしたテーブル設計しか勝たん

テーブル設計は正規化を基本にして設計する手法しか成功しない気がしてる。

DBやテーブル設計系の書籍を読むとどれにも「正規化」による設計手法が書かれているけど、現場ではなぜかあまり正規化に重きをおいた設計が行われていない場合が多かった。

先人の経験から「教科書通りにいけば理想的だが、現実はなかなかそうは行かない」という事なのかと思っていたが、結局はどれもあまりうまくはいっていないように見えた。

個人プロジェクトは正規化をベースに設計したテーブルで開発を行っているが、とてもうまくいっている。 テーブル設計はやはり正規化を基本にして行うべきだと、改めて思ったので書いてみる。

  • 正規化とは?
  • 正規化を使わない設計手法とは?
    • エクセル表現がそのままテーブルとして定義されている
    • データ取得・保存がシンプルになるようにテーブル分割を避ける
    • 1テーブルにデータがまとまっていれば、データ内容の把握がしやすい
    • コード(ロジック)側の都合に合わせる
    • パフォーマンスを心配する
  • まとめ:不整合が発生するようなテーブル設計をするとずっと苦しむことになる

正規化とは?

テーブルからデータの重複を排除し整合性を保持してデータを扱えるようにするための手法。

続きを読む

GoでもRubyのirbみたいにREPLを使いたい

Rubyirbとか、rails_consoleが便利なので、Goでもそういうの出来ないか探したら作ってくれてた。

motemen.hatenablog.com

インストールして、使いたいメソッドがあるパッケージをimportして使えば普通に使えた。

「実行したい処理のコードはあるけど、外部から実行するためのインターフェースがない」みたいなときに使えそう。

以下の感じで実行できた。

$ gore # 起動(このシェルの環境変数は内部からも参照できる)

gore > :import github.com/mixmaru/my_contracts/domains/contracts/application_service@v0.0.2 # 必要なメソッドが定義されてるパッケージをインポート

gore > app := application_service.NewUserApplicationService() # 構造体インスタンス化
# 返り値を表示してくれる
&application_service.UserApplicationService{                                                                                                
  userRepository: &repositories.UserRepository{                                                                                             
    BaseRepository: &repositories.BaseRepository{},                                                                                         
  },                                                                                                                                        
}

gore > app.RegisterUserIndividual("コンソールたろう") # メソッドの実行
# 返り値を表示してくれる
data_transfer_objects.UserIndividualDto{                                                                                                    
  Name:    "コンソールたろう",                                                                                                              
  Type:    "individual",
  BaseDto: data_transfer_objects.BaseDto{
    Id:        2,
    CreatedAt: 2020-09-27 13:15:26 Etc/UTC,
    UpdatedAt: 2020-09-27 13:15:26 Etc/UTC,
  },
}

※補足

importは「v1.0.11」のようなタグがあればその最新を、なければmaster(もしくはデフォルトブランチ?)の最新をとってくるっぽい。

PostgreSQLでのトランザクション分離レベルの使い分けを考えた

標準としてのトランザクション分離レベルは一応把握してたけど、MySQLPostgreSQLとか、実装によって結構事情が異なっててそのあたりあまり理解できてなかったのでPostgreSQLにおいてのトランザクション分離レベルを学び直した。

※参考にしたのはこのあたり

postgeSQLのトランザクション分離レベルについて
www.postgresql.jp

www.postgresqlinternals.org

トランザクションで発生する問題(ダーティーリードやファントムリードの具体的なサンプルなど)
postd.cc

  • 結論「どういう時にどうすればいいか?」
    • 「基本的にはデフォルト(read committed)指定で良い」について
    • 「不整合が起こる可能性がある場合にrepeatable readを明示的に指定する」について
    • 「repeatable readを明示的に指定する場合、クエリ実行失敗に備えての再実行処理を組み込む事を検討する」について
  • (補足)for updateについて

結論「どういう時にどうすればいいか?」

色々学び直した結果、PostgreSQLでは「どういう時にどうすればいいか?」を検討したので書く。

続きを読む

GROUP BYでまとめてそのLASTやFIRSTを取りたい場合のsqlの書き方(window関数を使う)

以下のような有効期間テーブルから、、

id ユーザーid 有効期間from 有効期間to
1 1 2020-6-1 2020-7-1
2 1 2020-7-1 2020-8-1
3 2 2020-5-1 2020-6-1
4 2 2020-6-1 2020-7-1

以下のようなデータ(ユーザー毎に最新の有効期間のレコード)を取得したい

id ユーザーid 有効期間from 有効期間to
2 1 2020-7-1 2020-8-1
4 2 2020-6-1 2020-7-1

window関数を使えればこんな感じ

WITH tmp_t AS (
    SELECT *, row_number() over (partition by ユーザーid order by 有効期間to DESC) AS row_num FROM 有効期間テーブル
)
SELECT * FROM tmp_t
WHERE row_num = 1
;

DDDのメリットを勘違いしてた件

僕はDDDで「俺が考える最強の契約管理システムを作る」というのをやってみている。
もう100回を超えた。

www.youtube.com

目的としては、外部からあれこれ言われず自分が思う通りに実装を進めて、自分だけの責任で躓いて、自分で「良い・悪い」を体験する事である。 アーキテクチャとしてはDDDを意識している。

  • 着手当初思っていたこと =>すぐに実装速度があがってくる
  • 着手中感じたこと => 全然実装速度があがってこない
  • 新規開発のステージではDDDはコスト感を感じやすい
  • 何に実装時間(コスト)がかかっているか? => レイヤー分割
  • なんのためにレイヤー分割するのか? => コアドメインを依存から守るため
  • レイヤー分割するメリットは?
    • 不必要な依存を持ち込まないようにする
    • 仕様変更にも追従しやすい
  • 実装速度に差が出てくるのはもう少し先の話。

着手当初思っていたこと =>すぐに実装速度があがってくる

DDDで実装すると、最初は手数が多い分実装スピード遅いが、次第に実装スピードが上がっていき「Railsのドキュメントに愚直に沿った開発」よりも早く完成させることができると思っていた。

続きを読む

娘が生まれたメモ

8/26(水)に娘が生まれたのでメモ

本当は9/4くらいが予定日だったのだが、奥さんが病院に定期検査にいったらそのまま入院することになった。
コロナの状況下なので僕は入院している病院に入ることができず、入院したら次あえるのは出産して退院するとき。
主にLineで状況のやり取りしてたけど、本人が陣痛等やなんか出産準備のあれこれをやってると連絡をすることができず、僕から見ると急に連絡が途絶える感じになって、まぁ大丈夫だとは思いながらも不安だった。

続きを読む

brew upgradeしたらrailsが起動しなくなったので対応したメモ

久々にbrew upgradeを実行したらopensslのなんかが読み込めなかっただかなんだか言われて、railsが起動しなくなった。

bundleもbrewも「ほしいライブラリを便利にインストールしてくれるツール」くらいの認識であまりどういう動きをしているか認識してなくて対応にちょっと苦労したのでメモ。
※あまり内部を意識せずに使えるツールなので、どういうものなのかすぐ忘れてしまう。。

  • 作業ログ
  • 調べたこと
  • まとめ

作業ログ

  • brew gradeした。その後railsで使っているgemの一つが[opensslが読み込めない]とかいうエラーを出して起動できなくなった。
  • よくわかってないまま、bundle installを実行して(エラー無く終了)再度railsを起動しようとしたが同じ状況
続きを読む