良い睡眠のためにやっていること

最近、 @kuluna と話しているときに、なぜそんなにポケスリのスコアが良いのか、と聞かれた。 見返してみると、確かに大体80点代〜90点くらいを推移しており、💯の時もあった。

新卒でSEになった頃は22時23時の残業は当たり前で、眠りに着くのは午前2時頃だった。 始業が8時半だったので7時起きだとギリギリで、いつもリポDを片手に駅まで走っていたと記憶がある。 その頃は睡眠トラッキングなどなかったのでスコアも何もないが、きっと酷い数字だったのだろうと思う😇

事業会社に転職して慢性的な長時間残業がなくなり、始業も10時になった。 『スタンフォード式 最高の睡眠』を何気なく手に取り、睡眠のために色々気を使うようになった。 そして、コロナ禍リモートワークにより通勤がなくなった。 そんな3段階の変化があったように思う。

現在気をつけているのは、

  • コーヒーは遅くても18時まで
  • 退勤したらジョギング or 散歩
  • 睡眠の90分前の入浴を意識
  • 22時以降は固形物を食べない
  • 0時を過ぎたら寝室へ向かう
  • ポケモンGOプラスプラスのボタンを押したらそのまま布団に入る
  • スマホはデスクの充電器に置き、寝室に持ち込まない
  • 起きたらスマホを取りに行き、そのまま起きる(サイクルを固定する)

あとは、ブレインスリープのマットレス、枕、布団を一式揃えた。 プラシーボかも知れないが、寝起きは良くなったように感じている。

元々睡眠時間が長い方で、朝活をしていた時もあったが続かなかった。 子どもができたらこんなに眠れないのはわかっているので、今はできるだけ健康を維持したい。

npx で command not found になるとき

適当な Nuxt.js のプロジェクトを作ろうとしたら何故か command not found に。 キャッシュを消すことで解消した。

$ npx create-nuxt-app hello
sh: create-nuxt-app: command not found

$ which npx
/opt/homebrew/bin/npx

$ npx -v
9.4.0

$ npx clear-npx-cache
Need to install the following packages:
  clear-npx-cache@1.0.1
Ok to proceed? (y) y

$ npx create-nuxt-app hello
Need to install the following packages:
  create-nuxt-app@5.0.0
Ok to proceed? (y)

macのメニューバーに今日の残り分数を表示する

少し前に、『1440分の使い方』という本を読んで感銘を受けた。

www.amazon.co.jp

そこでふと思いつきで、Macbook のメニューバーに1日の残り分数を出してみた。

xbar

メニューバーのカスタマイズというと SwiftBar というのがあったのだけど、開発が止まったらしい。 後継として xbar というのがあったので、それを使ってみることにした。

github.com

最近仕事でよく使っているGo言語もサポートしているので、ここでも使ってみることにした。

Code

unixtimeで差分を計算して表示するコードを書いた。 さっと適当に書いたものなので厳密ではないかもしれないが、ここでは許容した。

package main

import (
    "fmt"
    "time"
)

func main() {
    // 今日 23:59:59 の unixtime を取得する
    t := time.Now()
    loc, _ := time.LoadLocation("Asia/Tokyo")
    // NOTE: 常に今日の 23:59:59 にすることで閏年を考慮しなくて済む
    dt := time.Date(t.Year(), t.Month(), t.Day(), 23, 59, 59, 0, loc)
    lastUnixTimeToday := dt.Unix()

    // 現在の unixtime を取得する
    currentUnixTime := time.Now().Unix()

    // 差分を計算
    diff := lastUnixTimeToday - currentUnixTime

    // 残り分数として表示
    fmt.Println(diff/60)
}

設定

$ go build main.go
$ mv ./main ~/Library/Application\ Support/xbar/plugins/file.1s.cgo

完成

f:id:suzusin:20220106141640g:plain
countdown

初めてのドメインモデリングから得た学び

この記事は、ドメイン駆動設計(DDD) Advent Calendar 2021  22日目の記事です。

こんにちは、 @suzushin54 です。 Showcase Gig という会社で、O:der Table というモバイルオーダーのプロダクトを開発しています。

プロダクトや会社の紹介については、以下の記事をご覧いただければと思います。

note.com

現在の仕事で幸運にもドメインモデリングをする機会に恵まれました。これまで書籍を読んだりイベントに参加するなどして学習はしていたもの、初めての経験でした。

今回は会社のブログではないので、用語などを一般化した上で個人的な感想や反省、工夫を残していこうと思います。

環境

メンバー

6~7名の比較的よくあるプロダクトチームです。

ドメインエキスパートの招聘

PdMとManager, そしてカスタマーサポートの方にも参加してもらいました。この3名は日頃、同じチームとして活動しているわけではないのですが、スクラムのセレモニーなどには適宜参加してもらっています。業界やプロダクトに対する造詣が深く、まさにドメインエキスパートと言える存在です。

事前準備

はじめに、チーム内での認識を合わせることを目指しました。

今回、ドメイン駆動設計の経験者はいませんでしたが、DDD本を読んだことがあり知識はある人、増田さんの現場で役立つシステム設計の原則の社内輪読会に参加していた人、なんとなく聞いたことがある人、まったく知らない人、などなど、認識のレベルもバラバラでした。

とはいえ、これまた諸般の事情により、あまり時間がありません。今回はみんなで、松岡さんのドメイン駆動設計 モデリング/実装ガイドの輪読を行い、ドメインモデリングに入る最低限として以下の認識を合わせました。

  • そもそも DDD とは何か
  • なぜ今回採用したのか
  • どのようなメリットがある手法で、今後何を期待しているのか
  • ドメインモデルとは、ドメインモデリングとは

booth.pm

※ 話としては前後しますが、プロジェクトの見積の都合でユースケースは既に一覧化していました。

ドメインモデリングの実施

ドメインモデリングはオンラインホワイトボードツールの miro で行いました。日頃からレトロスペクティブなどで使い慣れていたので、ここでの戸惑いはありませんでした。

一方で、実際にやってみてから気づくことが多々ありました。

やっぱりデータモデリングと混同する

これはあるあるかと思います。事前に違いとして、以下を確認していました。

しかし実際にクラス図のような図を前にすると、こういう属性があって、こういうデータができて...ということをエンジニアは考えがちなのだと実感しました。

従来のソフトウェア開発の経験から来る副作用のようなものですが、注意していれば気づくこともできるので、その都度修正していきました。

ドメインモデルの種類?

ここはまだあまり考えが纏まっていないのですが、モデルを洗い出していると静的なモデルと、そうではないモデルがあるように感じました。例えば、店舗モデルや商品モデルなど、実体があるものは前者のイメージで、注文モデルや会計モデルは後者です。前者の種類のモデルが状態を保つと若干の違和感があります(有効/無効などは当然あるのですが)。

また、元となるデータがあって、それが一時的に有効になっているようなモデルも表現に悩みました。例えば、焼肉が食べ放題のお店にいろんな料理の掲載された「メニュー」があるとします。この「メニュー」を元に120分間の食べ放題がスタートすると、「有効となったメニュー」のようなモデルが生まれたりするのですが、こういったところはまだ洗練されていない感覚があります。

貧血不可避なモデル

ひととおりモデルが出揃ったタイミングで振る舞いを書き出そうとしたのですが、結果としてここでは不要だったかもしれません。というのも、実際に書いてみた振る舞いも実装の段階になると「なんか違う」ということが多かったです。振る舞いとして書いたけどドメインイベントなのではないか。このモデルが振る舞いとして持つには集約を見直さなければならない、などなど。

また、これまで私たちが触っていたシステムはトランザクションスクリプトになっていることが多かったので、ドメインモデルの振る舞いをイメージするのは想像以上に難しかったです。実際に実装フェーズに入ってから出てきた振る舞いも多く、ある程度で切り上げて試行錯誤のサイクルを回す方が効率的でした。

Tips的なもの

付箋や吹き出しのルールを決めないと無秩序になる

意外にこれは大事だなと思いました。

あれこれ書き込んでもらうことは議論を促進させるためにも歓迎すべきことですが、各々が好きな色で「(単なる)メモ」、「疑問点」、「ドメインエキスパートの見解」、「現行システムの仕様」などを書き出すと、あとで整理するときに消して良いのか残すべきなのか、はたまた既に解決した疑問なのかなどがわかりづらくなりました。

あらかじめ凡例と雛形を用意しておくと書き込む心理的な障壁も下げられて良さそうです。

早めにドメインモデルを実装する

環境にも寄りますが、基本的にドメインモデル( Entity, Value Object ) の実装はそれだけで完結できます。画面やEndpointを用意する必要がなく他の開発作業とは切り離して実行できるので、試行錯誤のサイクルを回しやすいと感じました。

おわりに

初めての経験でしたが、当たり前のことながら、やってみてわかることがたくさんありました。また実装に入った時に結構詰まってしまう感覚があったので、次回からはロバストネス図を描いてみることにしました。新しい学びがあったら、こちらも記録していきます。

これからも試行錯誤を繰り返し、良いドメインモデリングができるように励んでいこうと思います!

M1 ProのマシンでFlutter開発環境を準備する

11月にNew MBPを手に入れてFlutter開発環境を整えたものの、Kernel Panic発生により入院、初期化となりました😇

MBPが帰ってきたので再整備しようとしたところエラーが起きたのでメモ📝

Flutter

公式を参考にSDKを入手します。

https://docs.flutter.dev/get-started/install/macos

flutter doctor で確認

$ flutter doctor

  ╔════════════════════════════════════════════════════════════════════════════╗
  ║                 Welcome to Flutter! - https://flutter.dev                  ║
  ║                                                                            ║
  ║ The Flutter tool uses Google Analytics to anonymously report feature usage ║
  ║ statistics and basic crash reports. This data is used to help improve      ║
  ║ Flutter tools over time.                                                   ║
  ║                                                                            ║
  ║ Flutter tool analytics are not sent on the very first run. To disable      ║
  ║ reporting, type 'flutter config --no-analytics'. To display the current    ║
  ║ setting, type 'flutter config'. If you opt out of analytics, an opt-out    ║
  ║ event will be sent, and then no further information will be sent by the    ║
  ║ Flutter tool.                                                              ║
  ║                                                                            ║
  ║ By downloading the Flutter SDK, you agree to the Google Terms of Service.  ║
  ║ Note: The Google Privacy Policy describes how data is handled in this      ║
  ║ service.                                                                   ║
  ║                                                                            ║
  ║ Moreover, Flutter includes the Dart SDK, which may send usage metrics and  ║
  ║ crash reports to Google.                                                   ║
  ║                                                                            ║
  ║ Read about data we send with crash reports:                                ║
  ║ https://flutter.dev/docs/reference/crash-reporting                         ║
  ║                                                                            ║
  ║ See Google's privacy policy:                                               ║
  ║ https://policies.google.com/privacy                                        ║
  ╚════════════════════════════════════════════════════════════════════════════╝


Running "flutter pub get" in flutter_tools...                    1,952ms
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 2.8.1, on macOS 12.1 21C52 darwin-arm, locale en-JP)
[!] Android toolchain - develop for Android devices (Android SDK version 32.0.0)
    ✗ cmdline-tools component is missing
      Run `path/to/sdkmanager --install "cmdline-tools;latest"`
      See https://developer.android.com/studio/command-line for more details.
    ✗ Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/macos#android-setup for more details.
[✗] Xcode - develop for iOS and macOS
    ✗ Xcode installation is incomplete; a full installation is necessary for iOS development.
      Download at: https://developer.apple.com/xcode/download/
      Or install Xcode via the App Store.
      Once installed, run:
        sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
        sudo xcodebuild -runFirstLaunch
    ✗ CocoaPods not installed.
        CocoaPods is used to retrieve the iOS and macOS platform side's plugin code that responds to your plugin usage on the Dart side.
        Without CocoaPods, plugins will not work on iOS or macOS.
        For more info, see https://flutter.dev/platform-plugins
      To install see https://guides.cocoapods.org/using/getting-started.html#installation for instructions.
[✓] Chrome - develop for the web
[✓] Android Studio (version 2020.3)
[☠] IntelliJ IDEA Ultimate Edition (the doctor check crashed)
    ✗ Due to an error, the doctor check did not complete. If the error message below is not helpful, please let us know about this issue at
      https://github.com/flutter/flutter/issues.
    ✗ FormatException: Unexpected extension byte (at offset 5)
[✓] VS Code (version 1.63.0)
[✓] Connected device (1 available)

! Doctor found issues in 3 categories.

何やらいろいろ出ています。

Android Studio & toolchain

こちらも普通に公式からDL. ARM版が用意されている。

android-studio-2020.3.1.26-mac_arm.dmg

Download Android Studio and SDK tools  |  Android Developers

f:id:suzusin:20211219120854p:plain

11月に試した時はRC版でないとSDKのDLがされなかった記憶がありますが、12月時点では大丈夫そうです。

f:id:suzusin:20211219121200p:plain
android-studio-welcome

Android toolchain

コマンドラインからインストールできるようですが、今回はポチポチ入れてみました。

More Actions から、 SDK Manager を選択。 Android SDK Command-line Tools にチェックを入れてインストールします。

f:id:suzusin:20211219121343p:plain
android-sdk

再度 flutter doctor を実行すると、 licenses not accepted の表示に変わりました。

[!] Android toolchain - develop for Android devices (Android SDK version 32.0.0)
    ! Some Android licenses not accepted.  To resolve this, run: flutter doctor --android-licenses

ここは指示どおりに flutter doctor --android-licenses を実行。

[✓] Android toolchain - develop for Android devices (Android SDK version 32.0.0)

Xcodeは AppStore からインストールしていました。 残った cocoapodsCocoaPods Guides - Getting Started を参照せよとのこと。そして公式の指示どおりにインストール。

sudo gem install cocoapods

再度 flutter doctor を実行。ここまでで、この状態。

$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 2.8.1, on macOS 12.1 21C52 darwin-arm, locale en-JP)
[✓] Android toolchain - develop for Android devices (Android SDK version 32.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 13.2.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2020.3)
[☠] IntelliJ IDEA Ultimate Edition (the doctor check crashed)
    ✗ Due to an error, the doctor check did not complete. If the error message below is not helpful, please let us know about this issue at
      https://github.com/flutter/flutter/issues.
    ✗ FormatException: Unexpected extension byte (at offset 5)
[✓] VS Code (version 1.63.0)
[✓] Connected device (1 available)

IntelliJ IDEA

IntelliJは普段使いしているので、別途インストール済みでしたが、これが何やら怒られています。 既にIssueが上がっていました。まだ直っていない様子。

github.com

IntelliJ 2021.2 だと動くというコメントがありました。手元の IntelliJ は 2021.3 だったので、一時的にDowngradeすることにしました。

https://www.jetbrains.com/toolbox-app/ から Toolbox を手に入れると、過去のバージョンを簡単に入手できます。

f:id:suzusin:20211219122707p:plain

2021.2 をインストールして、再度 flutter doctor を実行。

$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 2.8.1, on macOS 12.1 21C52 darwin-arm, locale en-JP)
[✓] Android toolchain - develop for Android devices (Android SDK version 32.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 13.2.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2020.3)
[✓] IntelliJ IDEA Ultimate Edition (version 2021.2.3)
[✓] IntelliJ IDEA Ultimate Edition (version 2021.2.3)
[✓] VS Code (version 1.63.0)
[✓] Connected device (1 available)

• No issues found!

無事、環境を復活させることができました。

git subtree のコミット履歴は順番どおりになる

たまたま git subtree を使う機会があったのでメモです。 説明を読むと理論上は時系列が考慮されるように思えましたが、念のため検証したところ、ちゃんとコミットした順番に並ぶことが確認できました。

2つの Git Repositoryを作りました。

  1. subtree-foo
  2. subtree-bar

そして、 foo, bar と交互に commit しています。

f:id:suzusin:20210603004115p:plain
subtree-commits

コミットログの先頭の数字が通し番号になっていて、これが実際の作業順です。

ここで、subtree として foo に bar を追加します。

$ git remote add subtree-bar https://github.com/suzushin54/subtree-bar.git

$ git subtree add --prefix=subtree-bar subtree-bar master
git fetch subtree-bar master
remote: Enumerating objects: 6, done.
remote: Counting objects: 100% (6/6), done.
remote: Total 6 (delta 1), reused 6 (delta 1), pack-reused 0
Unpacking objects: 100% (6/6), 447 bytes | 149.00 KiB/s, done.
From https://github.com/suzushin54/subtree-bar
 * branch            master     -> FETCH_HEAD
 * [new branch]      master     -> subtree-bar/master
Added dir 'subtree-bar'

$ git log --oneline
2a8292d (HEAD -> master) Add 'subtree-bar/' from commit '5f80d93e873e67467ffc7b0b405c90a8b2413223'
5f80d93 (subtree-bar/master) 4. second commit in bar
c07738d (origin/master) 3. second commit in foo
7702b0a 2. first commit in bar
226cc4e 1. first commit in foo

ちゃんと、1〜4の順番に並ぶことが確認できました。


ついでに、順番を入れ替えたり、foo の Repository から bar のファイルを更新したりしてみました。

それでも特に変わったことはなく、マージコミットが作られる、コンフリクトが発生したら普段どおり解消してコミットする、という通常の開発時における操作で対応できることを確認できました。

$ git log --oneline
23dae13 (HEAD -> master, origin/master) Merge commit '341fc6e882d31032c07e28785c03541cef699af9'
341fc6e (subtree-bar/master) 10. fifth commit in bar
14f9102 9. fifth commit in foo
9c48859 Merge commit 'c04367496b48f971f6a2ce540f3fad2eadbce74c'
04ef6bd 8. fourth commit in foo
c043674 7. fourth commit in bar
04b27d3 Merge commit '7687befaf4b8dbf5ed68b5668bb1996f1acaf51a'
7687bef 6. third commit in bar
6b824b3 5. third commit in foo
2a8292d Add 'subtree-bar/' from commit '5f80d93e873e67467ffc7b0b405c90a8b2413223'
5f80d93 4. second commit in bar
c07738d 3. second commit in foo
7702b0a 2. first commit in bar
226cc4e 1. first commit in foo

ADR を導入して意思決定を残そうという話をした

開発部門の月例会にて、意思決定を残そうという話をしました。

現職で最初の頃に困っていたのは、過去に「なぜその決定をしたのか」がわからないことでした。 これは単に当時の関係者が退職しているかどうか、というだけの話ではなく、「過去の自分が関わっていたとしても決定事項以外は忘れやすい」、「意思決定の記録が残っていれば、後々の追加開発や不具合修正のタイミングで議論の土台になる」という思いのもとです。

今後も人が入れ替わったり、機会があれば話したいと思い、Google Slideに残しておくことにしました。

内部的な情報を除外し、一部文言を修正しています。 ちなみに月例会は バーチャルSNS cluster(クラスター) を用いることが多いため、見やすさを考慮して1枚の内容は少なくしています。

docs.google.com

社内ではさっそくその後、各チームで Confluence や GitHub の Repository に ADR が作られており、良い雰囲気です 🙌

具体的な成果やさらなる学びがあれば、また記載していこうと思います。