2019/12/03

今日も酒を飲んでいない。 もう六日目だ。 体と肌の調子がすこぶるよい。 やはり酒は毒だな。

昨日はTaskieeで、自分が実装したいものを洗い出し、アーキテクチャをまとめた。 昨日は疲れ切っていて、新しいアーキテクチャの各コンポーネントを説明する前に寝てしまったので、今日はまずそこから始める。

  • Taskiee-UI: UI
  • Taskiee-Server: タスクやユーザー情報などを管理しAPIを提供するサーバ
  • Taskiee-Writer: ユーザからのタスクの完了や日記、それらに対するリアクションやコメントを受け付け、PersistentなDBに書き込みつつ、Taskiee-Cacheにもデータを流すサーバ
  • Taskiee-Cache: Taskiee-Serverから流れてきたデータを加工し、Redisへ突っ込むサーバ
  • Taskiee-Timeline: ユーザからのリクエストを受け付け、Redis(必要に応じてPersistent DBからも)、Taskiee-Server、Taskiee-Searchからデータを引っ張って来て、ユーザに返すサーバ
  • Taskiee-Search: ユーザの投稿を検索できるサーチサーバ

今日からしばらくかけて、Taskiee-Serverを実装していくこととする。


今日はWindows上にJavaの開発環境を整えるところから始めていく。

まず、Java13のJDKのインストールから始める。

Java界隈のことは何一つ知らないのだが、OracleJavaが有償化であーだこーだみたいな話は風の噂で聞いたことがあるので、とりあえずOracleJavaは使わずOpenJDKをインストールすることとする。

・・・

あああああああ!!! WindowsJava環境整えるの難しすぎる! 何とか動いたが何で動いたのか全然分からないという…。

次にDockerでDBを作って、そこにFlywayでテーブルを作り、アクセスするところまで実装してみる。

・・・

ダメだこりゃ…。 Dockerが全く動かん。 VirtualBoxの起動に失敗しているっぽいんだが、何が原因なのか一つもわからん。 Windows、詰まる所が多すぎてまともに開発できない。 Mac買うか…。

・・・

と思ったんだが、流石にそれで寝てしまうのはムカつくのでDocker Toolboxのバージョンをぐっと下げて1.13.1を使ってみたところ動いた。 もうやだ…。 ホントに何が起きてるかわからん。

とりあえずDockerfileたちをコミットしてから寝る。

おやすみ。

2019/12/02

今日も酒を入れていない。 もう五日間くらいは酒を飲んでいない状態だ。 頭は冴えている。 気持ちも割と上々。 やはり酒は百薬の長であり万病の元であるのだなと思う。 特にメンタル面で酒は目に見えて悪い影響を及ぼしているような気がする。 何にせよ飲まないに越したことはない。

今日は全然進んでいないTaskieeの開発を進めていく。 では、始めよう。


全体の構成をもう一度考え直すべきだと思う。

まず自分が何の機能を実装したいのかを洗い出してみよう。

  • ルーティンワークを管理する仕組み
  • ルーティンワークを達成したことを晒して自己顕示欲を満たす仕組み
  • 今日しなければならないルーティンワークを通知する仕組み

この三つである。 この三つを中心にして、もう少し機能を掘り下げ、アーキテクチャ全体を見直すこととする。

一つ目の「ルーティンワークを管理する仕組み」に関しては今まで考えてきた内容で十分だと思われる(もちろんスキーマの見直しなどは必要だが)。

二つ目の「ルーティンワークを達成したことを晒して自己顕示欲を満たす仕組み」に関しては、SNS的な要素が必要になると思われる。 人のルーティンワークを見たり、人のルーティンワークにリアクションやコメントを残したり、人の日記を見たり、グループ機能があったり、アクセス制御のための機能が必要である。

三つ目の「今日しなければならないルーティンワークを通知する仕組み」に関しては、うーん、これはスマホにもよるし、ブラウザにもよりそうなので色々調べなければならなそうである。


とまあTwitterライクなSNS機能を取り入れたいと考えている。 なので、具体的なアーキテクチャを考え始める前に、Twitterアーキテクチャを学んでみる。

www.youtube.com

ビックリするほど勉強になった。 残念ながら検索機能はあまり詳しく解説されていなかったが、Twitterがどのようにあの膨大なデータ量をさばいているのか少し理解することができた。 まあ速度のためにRedis使いつつ、それとは別にPersistent用のDB作れってだけの話だが…。

というか、Googleの自動翻訳流しながらなら英語も大体理解できることに気付いた…。 自動翻訳がおかしいところも何となく頭の中で補正できるし。 これは毎日仕事中洗脳するかの如くYouTubeに上がってる英語のレッスンを聴き続けてる効果が出てきてるのかもしれない。


上の動画を参考にして(というかほぼそのまま)、アーキテクチャを書き出してみた。

f:id:tac2nd:20191203012540p:plain

こ、これは…! 所謂マイクロサービスアーキテクチャというやつなのでは!

というところで今日はおしまい。 おやすみ。

2019/11/30

今日は朝からブログを書いている。 まだ体調が回復していないので酒を飲んでおらずド素面である。

今日も昨日に引き続きOSSにたまったIssueの解決をしていく。


昨日はWindowsで開発をしようとしたときに、WebpackでWindows特有の煩わしい問題に直面し、その解決に時間を使ったが、そもそも昨日の問題は直接Font-AwesomeSVGを扱わず、そのラッパーライブラリを使えば良いのではと思ったので、今日はそこから始める。

・・・

出来たのでPRを投げた。

github.com


今日はこのくらいにしておこう。

しかし酒が入らないと筆が進まんな…。

ではおやすみ。

2019/11/29

風邪をひいてしまい少し休んでいた。 体調は元通りだが、流石に酒を流し込む気にはなれず今はド素面である。 こういう時にはたまっているIssueを解決していくのが良さそうである。 ということで今日は大人しくOSSコントリビュートしていく。


ということで前にセットアップしたWindows環境でバリバリコミットしていくぞと思ったのだが、思うようにWebpackが動いてくれなくて困っている。 恐らく、/webfonts/hoge.svg のようなファイルに対して、以下の /webfonts\/.*\.(svg)(\?.*$|$)/ がちゃんと引っ掛かってくれないみたいだ。

module: {
  rules: [
    { test: /webfonts\/.*\.(png|svg|jpg)(\?.*$|$)/, ... },
  ],
},

Webpackのソースコードを確かめてみる。

modulerulestest正規表現が含まれているときの処理は以下だと思われる。 これを見る限り普通に正規表現をそのまま適用しているだけである。

https://github.com/webpack/webpack/blob/0d4607c68e04a659fa58499e1332c97d5376368a/lib/rules/RuleSetCompiler.js#L217-L222

       if (condition instanceof RegExp) {
            return {
                matchWhenEmpty: condition.test(""),
                fn: v => condition.test(v)
            };
        }

おそらく、Windowsでのパスの区切り文字は / ではなく \ なので、これが問題なんじゃないかと思われる。 なので上のコードを以下のように変更してみた。

module: {
  rules: [
    { test: /webfonts\\.*\.(png|svg|jpg)(\?.*$|$)/, ... },
  ],
},

動いた。

i 「wdm」: Compiled successfully.

うーん、やはりWindowsで開発するのは色々と辛いな…。

とりあえず修正のPRを出した。

github.com

今日はここまで。

体を休めなければ。

2019/11/26

こんばんは。 今日もプライムリッチを飲んで元気いっぱいである。

では、始める。


今まで、Windowsでの開発はVirtualBoxに立てたLubuntuの仮想マシン上で行っていた。 しかし、うちのPCは結構古くて、いささか動作が重いため、モダンなエディタを開きつつ頻繁にUIの確認が必要となるようなフロントエンドの開発においては、仮想マシンを使うのはかなり無理がある。 そこで、今日はWindows 8.1上に直接開発環境を整えていくこととする。

Windowsであっても、開発中はやはりターミナルやシェルを触る必要が出て来る。 Windowsにもコマンドプロンプトというものがあるみたいだが、シェルコマンドと互換性があるわけではないし、見た目もダサいし、使っていると何故こんなものを使わなくてはいけないんだと悲しくなってしまう。 少なくともzshとtmuxくらいは使えなければ、まともに作業できないし、する気も起きない。

ということで、まずターミナルとシェルの環境を整えていくこととする。 でもまあ、とりあえずMSYS2入れとけばいいんだろ?感あるので、ささっと入れていく。

  1. 公式ページ(https://www.msys2.org/)からEXEファイルをダウンロードして実行
  2. 誘導されるがままに適当にボタンを押していく

完了!滅茶苦茶分かりやすくて好感が持てるゾ。

次にMinttyの見た目を設定していく。

f:id:tac2nd:20191126181449p:plain f:id:tac2nd:20191126181457p:plain

完了!

次にパッケージデータベースとコアのシステムパッケージを更新する。

pacman -Syu

なんかゴチャゴチャ言われる。

f:id:tac2nd:20191126182601p:plain

一度Minntyを閉じて、再度開き、以下のコマンドを入力。

pacman -Su

無事完了!

次に開発に必要な基本的なパッケージをインストールしていく。

pacman -S git emacs zsh tmux

完了!

次にzshをログインシェルに設定する。 MSYS2をインストールしたディレクトリ内の etc/nsswitch.conf を開いて db_shell の項目を以下のように変更する。

# db_shell: cygwin desc ⇒ db_shell: /usr/bin/zsh

次にLinuxMacOS用に使ってきたdotfiles(https://github.com/tacigar/dotfiles)を適用していく。

git clone https://github.com/tacigar/dotfiles.git
cd dotfiles
./bootstrap

完了!

f:id:tac2nd:20191126185257p:plain

ここまででターミナルとシェルの環境の設定は完了した。 次はフロントエンド開発の環境を設定していく。

まずは公式サイト(https://code.visualstudio.com/)からVSCodeのインストール。

f:id:tac2nd:20191126223502p:plain

完了!

次にnpmをインストールしていく。 Nodeを使う場合にはnvmやnodebrewを使うべきだと思うが、npmだけあれば良いような場合、こうしたNode自体のバージョンマネージャが必要なのか否かいまいちよく分かっていないので、今回は直接Nodeの公式サイト(https://nodejs.org/en/)からNodeとnpmをインストールすることとする。

ということで、Node.jsとnpmをWindows用のインストーラからインストールしてみたが、この状態では当然Pathが通っていない。 Windowsで開発するときは本当にこういうところでイライラしてしまう。 仕方がないので .zshenv を編集して以下の行を追加した。

if [ "$(echo $(uname) | cut -c 1-7)" = 'MSYS_NT' ]; then
  export PATH="/c/Program Files/nodejs:$PATH"
fi

ここでGitHubにdotfilesの変更をコミットしようとしたのだが、dotfilesのbootstrapスクリプトで生成されたシンボリックリンクシンボリックリンクとして扱われていないことに今気が付いた。 クソ面倒くさいのだが、MSYS2をインストールしたディレクトリ内の msys2_shell.cmd というファイルを以下のように変更する。

rem set MSYS=winsymlinks:nativestrict ⇒ set MSYS=winsymlinks:nativestrict

その後 msys2_shell.cmd を管理者権限で実行し、再度dotfilesのbootstrapスクリプトを実行することで、dotfiles内のファイルへのシンボリックリンクをホームディレクトリに作成した。

f:id:tac2nd:20191127005951p:plain

完了! 無事にnpmにもPathが通った。

今日はここまでにする。

おやすみなさい。良い夜を。

2019/11/24

また帰って来ることができた。 今は珍しく一滴も酒が体に残っていない状態である。 今のうちにさっさとフロントエンドの開発を始めていく。


以前、滅茶苦茶適当な手書きのワイヤーフレームを描いたが、あれでは流石にどういう機能が必要で、どこに何をどう配置するかなどが一切定まらないので、もう一度考え直すこととする。 ワイヤーフレーム用の良いツールを知らないので、とりあえず今回はdraw.ioで頑張って描いていくこととする。


ちょっとだけできた。 共通のレイアウトを以下に示す。

f:id:tac2nd:20191125002320p:plain

次にカレンダーページを以下に示す。

f:id:tac2nd:20191125002350p:plain

中央に大きいカレンダーを表示し、それぞれのセルにはその日にしなければならないルーティンワークを列挙する。 その下のプロットには各ルーティンワークがどれほどの頻度で行われているかを示すグラフを表示する。 また画面右側には、カレンダー上でフォーカスの当たっている日付に行われるべきルーティンワークと、その日の日記、そしてその日記に対するリアクションを表示する。

今日はここまでとする。 では。

2019/11/21

やあ。 今は茄子と大根と味噌汁と豚の切り落としの唐揚げを作って、プライムリッチとともに胃袋に流し込んでいる最中である。 ちなみに豚の切り落としの唐揚げというのは以下のような料理である。

f:id:tac2nd:20191122120225j:plain

滅茶苦茶体に悪そうである。 肉に対する衣の量が異常に多く大量の油を摂取することができる。 これを味ぽんに生姜とニンニクを溶かした簡単なタレに付けて食べる。 旨すぎるのである。


早速今日も昨日の続きのフロントエンドの作業を進めていく。 と言いたいところだが、一旦その作業はストップし、もう一度テーブルスキーマから見直すこととする。 今日は色々な人たちから刺激を受けて、こういった個人的なプロジェクトでももっと色々吟味しながら開発していかなければ自分のスキル向上には繋がらないなぁと思ったのがその主な動機である。

では、早速テーブルスキーマを再考していく。 全体を考えきってから細かい説明を書き残していくこととする。


できた。

f:id:tac2nd:20191121223142p:plain

Users テーブルは以前に説明したとおりである。 特に説明することはない。

CREATE TABLE IF NOT EXISTS `users` (
  `id` CHAR(36) NOT NULL,
  `name` VARCHAR(255) NOT NULL,
  `display_name` VARCHAR(255) NULL,
  `email` VARCHAR(255) NOT NULL,
  `password` VARCHAR(255) NOT NULL,
  `salt` VARCHAR(45) NOT NULL,
  `is_admin` TINYINT(1) NOT NULL,
  `created_at` DATETIME NOT NULL,
  `updated_at` DATETIME NOT NULL,
  PRIMARY KEY (`id`))
ENGINE = InnoDB

次にルーティンワーク関係のテーブルについて説明する。

以前は週ごとのルーティンワークしか設定出来なかったが、月ごとのルーティンワークを設定したいことも多々あると思われるため、Routines テーブルに継承関係を持たせることにし、共通の設定を Routines テーブルに持たせ、週ごとのルーティンワークの設定を WeeklyRoutines テーブルに、月ごとのルーティンワークの設定を MonthlyRoutines テーブルに持たせることとした。

CREATE TABLE IF NOT EXISTS `routines` (
  `id` CHAR(36) NOT NULL,
  `user_id` CHAR(36) NOT NULL,
  `title` VARCHAR(255) NOT NULL,
  `description` TEXT NULL,
  `status` VARCHAR(16) NOT NULL,
  `start_time` TIME NULL,
  `finish_time` TIME NULL,
  `color` VARCHAR(7) NOT NULL,
  `is_allday` TINYINT(1) NOT NULL,
  `created_at` DATETIME NOT NULL,
  `updated_at` DATETIME NOT NULL,
  PRIMARY KEY (`id`),
  CONSTRAINT `user_id`
    FOREIGN KEY ()
    REFERENCES `users` ()
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB

CREATE TABLE IF NOT EXISTS `weekly_routines` (
  `routine_id` CHAR(36) NOT NULL,
  `do_monday` TINYINT(1) NOT NULL,
  `do_tuesday` TINYINT(1) NOT NULL,
  `do_wednesday` TINYINT(1) NOT NULL,
  `do_thursday` TINYINT(1) NOT NULL,
  `do_friday` TINYINT(1) NOT NULL,
  `do_saturday` TINYINT(1) NOT NULL,
  `do_sunday` TINYINT(1) NOT NULL,
  PRIMARY KEY (`routine_id`),
  CONSTRAINT `routine_id`
    FOREIGN KEY ()
    REFERENCES `routines` ()
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB

CREATE TABLE IF NOT EXISTS `monthly_routines` (
  `routine_id` CHAR(36) NOT NULL,
  `times` INT NOT NULL,
  PRIMARY KEY (`routine_id`),
  CONSTRAINT `routine_id`
    FOREIGN KEY ()
    REFERENCES `routines` ()
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB

RoutineHistories テーブルは以前のものと同じである。 ただし、Routines テーブルの変更履歴を保存するための RoutineEventHistories テーブルは削除することとした。 正直変更履歴を管理し続けるというのは中々厳しいものがあるし、ルーティンワークの条件を変更したい場合は元々の Routines テーブルの行をInactivateして、他の行をInsertするだけでよいと判断したのが主な理由である。

CREATE TABLE IF NOT EXISTS `routine_histories` (
  `routine_id` CHAR(36) NOT NULL,
  `date` DATE NOT NULL,
  `done` TINYINT(1) NULL,
  PRIMARY KEY (`routine_id`, `date`),
  CONSTRAINT `routine_id`
    FOREIGN KEY ()
    REFERENCES `routines` ()
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB

最後に日記関係のテーブルであるが、正直これも前と同じように大した説明は必要ないと思われる。 日記に対するコメントを管理するための DiaryComments テーブルと、日記に対するリアクション(「いいね」的なもの)を管理するための DiaryReactions テーブルを追加したのと、その日記の可視性を管理するための visiblity フィールドを Diaries テーブルに追加したくらいである。

CREATE TABLE IF NOT EXISTS `diaries` (
  `id` CHAR(36) NOT NULL,
  `user_id` CHAR(36) NOT NULL,
  `date` DATE NOT NULL,
  `content` TEXT NOT NULL,
  `visiblity` VARCHAR(16) NOT NULL,
  `created_at` DATETIME NOT NULL,
  `updated_at` DATETIME NOT NULL,
  PRIMARY KEY (`id`),
  CONSTRAINT `user_id`
    FOREIGN KEY ()
    REFERENCES `users` ()
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB

CREATE TABLE IF NOT EXISTS `diary_comments` (
  `id` CHAR(36) NOT NULL,
  `diary_id` CHAR(36) NOT NULL,
  `user_id` CHAR(36) NOT NULL,
  `content` TEXT NOT NULL,
  `created_at` DATETIME NOT NULL,
  `updated_at` DATETIME NOT NULL,
  PRIMARY KEY (`id`),
  CONSTRAINT `diary_id`
    FOREIGN KEY ()
    REFERENCES `diaries` ()
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `user_id`
    FOREIGN KEY ()
    REFERENCES `users` ()
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB

CREATE TABLE IF NOT EXISTS `diary_reactions` (
  `diary_id` CHAR(36) NOT NULL,
  `user_id` CHAR(36) NOT NULL,
  `reaction` VARCHAR(16) NOT NULL,
  PRIMARY KEY (`diary_id`, `user_id`),
  CONSTRAINT `diary_id`
    FOREIGN KEY ()
    REFERENCES `diaries` ()
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `user_id`
    FOREIGN KEY ()
    REFERENCES `users` ()
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB

よし出来上がった! いよいよフロントの開発に取り組める、というところで今日は疲労困憊なのでここまでとする。

続きは明日。