葛のメモ帳

自分で調べたことを忘れないためにメモっておきます

葛のメモ帳

自分で調べたことを忘れないためにメモっておきます


【SQL】アンチパターン6章:ポリモーフィック

おことわり

本記事は自分が理解するために説明を増やして書いています。間違いがあればご指摘ください

目的:複数の親テーブルを参照したい

  • あなたは、ユーザが「Bug」や「Feature Request」「Task」などのチケット管理システムを作ります。
  • どのタイプのチケットにもコメント機能を実装します

とりあえずカラムでTypeを追加するか...

CREATE TABLE Comments (
    comment_id SERIAL PRIMARY KEY,
    issue_type VARCHAR(20) NOT NULL, -- Bugs or Feature Request or Task
    issue_id BIGINT UNSIGNED NOT NULL,
    commen_date DATETIME,
    comment TEXT,
    ...
)

アンチパターン:二重目的の外部キーを使用する

外部キー制約を定義できないですよね
  • FOREGIN KEYを定義できない
クエリ実行
  • どのテーブルにどのタイプがあるかわからないので、全て外部結合(OUTER JOIN)をしなければならない
SELECT *
FROM Comments AS c
    LEFT OUTER JOIN Bugs AS b
        ON b.issue_id = c.isssue_type 
            AND c.issue_type = `Bugs`
    LEFT OUTER JOIN FeatureRequests AS f
        ON f.issue_id = c.issue_type = `FeatureRequests`;

解決作:リレーションシップを単純化する

参照を逆にする
  • 本来あるべき関係が逆さまになっている
交差テーブルの作成

CREATE TABLE BugsComments (
    issue_id BIGINT UNSIGNED NOT NULL,
    comment_id BIGINT UNSIGNED NOT NULL,
    PRIMARY KEY (issue_id, comment_id),
    FOREIGN KEY (issue_id) REFERENCES Bugs(issue_id),
    FOREIGN KEY (comment_id) REFERENCES Comments(comment_id)
);

こうすることで外部キーを張ることができました。

SELECT *
FROM BugComments AS bc
    INNER JOIN Comments AS c
        ON bc.comment_id = c.comment_id
WHERE
    bc.issue_id = 24

ただ同様に全ての項目に対してテーブルを作る必要があります。

共通の親テーブルの作成
CREATE TABLE Issues (
    issue_id SERIAL,
    ...
);

CREATE TABLE Bugs (
    issue_id BIGINT UNSIGNED PRIMARY KEY,
    FOREIGN KEY (issue_id) REFERENCES Issues (issue_id),
    ...
);

最後に

写経すらできていないですが、改めて読み直して整理します・・・

【SQL】アンチパターン2章:ナイーブツリー(素朴な木)

おことわり

自分がわかるように解説記事を書いていきます。間違いがあれば指摘ください

目的:階層構造を格納して、クエリを実行したい

  • あなたは、ニュースサイトの記事に対してコメント機能を実装します。
  • コメントはスレッド形式
  • ディスカッションも可能で、トピック毎に枝分かれする

あなたは思いつきました。

コメントに親コメントを持たせれば再起的にrootコメントまで辿れるやろ

アンチパターン: 常に親のみに依存する

  • データ構造の学習などを経験していれば誰しもがこの方法をまず最初に思いつくと思います。
    • root, branch, leaf, node...
  • 再帰関数を用意してプログラムでは実装できてもSQLではどうでしょうか?
n世代子のコメントを取得...?

いつまでそれ書きますか?

SELECT
FROM Comments c1
    LEFT OUTER JOIN Comments2
        ON c2.parrent_id = c1.comment_id -- 2階層
    LEFT OUTER JOIN Comments3
        ON c3.parrent_id = c2.comment_id -- 3階層
・・・
コメント追加、移動
  • これは容易にできますね。
  • 親のIDに紐づけて登録・更新するだけです
削除
  • ツリー整合性を保つために、ツリー全体の検索して親のすげ替えをしていく必要がありそうですね・・
  • メンテしずらい

解決策:代替ツリーモデル

経路列挙(シンプルだがジェイウォーク)

  • そのノードまでのパスを /2/4/5/5のように保存する方法
  • ジェイウォークになりそうですね

入れ子集合(やや難解)

  • 子孫の集合に関する情報を各ノードに格納する
  • nsleft, nsright
  • これはそこそこ複雑なので今回は割愛します

閉包テーブル(シンプル&フレキシブル)

  • 直接の親子関係だけでなく、ツリー全体のパスを格納する
  • ある意味これも交差テーブルの応用

ツッコミどころの解消

要素の検索
  • コメント4の親の検索は、子孫が4を調べれば良い
  • コメント4の子の検索は、先祖が4を調べれば良い
更新
  • 同じ
追加
  • 親要素を元に追加するだけで良い
削除
  • CommentテーブルとTreePathテーブルの両方を削除しないといけない
  • CASCADEをつければCommentさえ削除しとけば大丈夫

最後に

  • これは自分も知らなかったので勉強になった

【SQL】アンチパターン1章:ジェイウォーク(信号無視)

概要

自分がわかるように解説記事を書いていきます!間違いがあれば遠慮なく指摘ください

目的:複数の値を持つ属性値を保存したい

  • 1対1で紐付くProductテーブルとAccountテーブルがあったとします。
  • そこで追加で依頼が来ました。「プロダクトに登録社員を追加したい」

そこで、「カンマ区切りでとりあえず文字列で保存するか...」としました。

アンチパターン: 区切り文字でリストを保存する

ジェイウォークjaywalkとは、交通規則を無視して道路を横断するという意味

ツッコミどころ

どのアカウントがどのプロダクト持ってるの?

SELECT文で検索することが難しいですよね

Accountテーブルと結合したいのですが

inner joinを書けないですよね

集約クエリかけますか?

COUNT, SUM, AVGどうやって書きましょう

データ更新どうしましょう

select文でデータを取得したのちに、updateでそれを更新するんですか・・・?

バリデーションどうしますか?

文字列で良いなら、bananaとか入っちゃいません?

区切り文字どうしますか?

スペース、カンマ、セミコロン・・・

登録限界数は・・・?

文字列の定義以内です・・・?

解決策:交差テーブルを作ろう!

どのアカウントがどのプロダクト持ってるの?
SELECT p.product_id, p.product_name
FROM Product As p 
    INNER JOIN Account_Product as ap 
        ON p.product_id = ap.product_id
WHERE ap.account_id = 2;
集約クエリ

製品ごとのアカウント数を返す

SELECT ap.product_id, COUNT(*) AS accounts_per_product
FROM Account_Product AS ap
GROUP BY product_id;

アカウント毎の製品数

SELECT ap.account_id, COUNT(*) AS products_per_account
FROM Account_Product AS ap
GROUP BY account_id;

最も関連アカウント数の多い製品

SELECT c.product_id, c.accounts_per_product
FROM(
    SELECT ap.product_id, COUNT(*) AS accounts_per_product
    FROM Account_Product AS ap
    GROUP BY product_id;
) AS c
HAVING c.accounts_per_product = MAX(c.accounts_per_product)
製品のアカウント追加
INSERT INTO Product_Account (
    product_id, account_id
) VALUES (
    456, 34
);

DELETE FROM Product_Account 
WHERE product_id = 456
    AND account_id = 34;
  • MysqlならCASCADEを設定すれば交差テーブルのデータは自動的に削除することができます
バリデーションどうしますか?
  • varcharでなく、intなどを使えば不正な文字は入れることができないです
  • 外部参照を入れることで不正なデータを入れることができなくなります。
区切り文字?

使ってないです!

リストの長さ制限?

リストは存在しません!

最後に

  • 明らかにまずい設計だということはわかると思います
  • ただ、ここまでツッコミを入れることができるか?というと自信がないです
  • ツッコミ力を養いたい

【HHKB】MacでHHKBを使うための設定

HHKBをMacで使うための準備

筆者の環境

Mac用ドライバのインストール

  1. 公式サイトから該当するHHKBのドライバをダウンロードしてください。
  2. ドライバをインストールしてください。

HHKBをPCに接続

有線の場合

  1. USBでPCと繋いでください。
  2. Fn + Tab + 0 を同時押しすると接続されます。

Bluetoothの場合

  1. HHKBの電源ボタンを押してください。
  2. Fn + Q を同時押しすると、ペアリングモードになります。
  3. Fn + Tab + 1 - 4 のいずれかを選択
    • HHKBは同時に4つの端末を登録できます。登録した数字で端末を記憶できます。
  4. Macの設定から、Bluetooth設定画面を開き、ペアリングする。

Karabiner-Elements のインストール

  1. 公式サイトからダウンロードしてインストールしてください。
  2. アプリを開くとMacのセキュリティ関連の設定をするように依頼されるので、誘導に従って許可してください。

Karabiner-Elements のキー配置設定

ドライバーをインストールするだけではキー配列が少しおかしくなってしまっているので、個別に配置していきます。

筆者が確認した問題

HHKBに実際に入力したキー Karabiner-EventViewerで確認したキーイベント
left command left option
right command right option
left Alt(Opt) 日本語 無変換キー
right Alt(Opt) 日本語 変換キー

そのため個別にキー配置を変えました。

筆者はこのように修正しました。

またHHKBにとってFnは高頻度で使うので以下の設定もした方が良いかもしれないです。 UI下のトグルを有効するとFnキー操作ができるようになります。

最後に

  • 高級キーボードだけあって入力はとても心地よいです。
  • HHKB英語配列十字キーは以下のようになっていて、十字キーが使いづらいのがきついですね...

    • Fn + [ =
    • Fn + ; =
    • Fn + ' =
    • Fn + / =

【Vue2 + TypeScript + Vuex3 + Vuetify + Router】今更Vue2のプロジェクトを作る【2023 GW Day 2】

Vue2を振り返る

setup / update

Homebrew

brew update

Node.js

  • nodebrewをhomebrew経由でインストールして管理しています
    • 使うnodeのバージョンでかなり異なる結果になるので気をつける必要がありますが今回は以下を使いました
$ nodebrew ls
v16.20.0

current: v16.20.0
  • nodeのversionが変わっていることを確認します
node -v
v16.20.0

npm update

  • version確認
$ npm -v
9.6.5
  • update
$ npm update -g npm
  • check
$ npm -v
9.6.5

install Vue CLI

npm install -g @vue/cli
$ vue --version
@vue/cli 5.0.8

Create Vue2 Project

  • 今回は以下の構成で作成しました。
$ vue create vue2-project
Vue CLI v5.0.8
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, TS, Router, Vuex, Linter
? Choose a version of Vue.js that you want to start the project with 2.x
? Use class-style component syntax? Yes
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills,
 transpiling JSX)? Yes
? Use history mode for router? (Requires proper server setup for index fallback in 
production) No
? Pick a linter / formatter config: Prettier
? Pick additional lint features: Lint on save
? Where do you prefer placing config for Babel, ESLint, etc.? In package.json
? Save this as a preset for future projects? No
? Pick the package manager to use when installing dependencies: Yarn
Please pick a preset: Manually select features
  • 手動で環境を構築していきます。
? Check the features needed for your project: Babel, TS, Router, Vuex, Linter
  • Bable
    • 新しいバージョンの書き方で書いたJavascritpコードを古いバージョンでも互換して動くように変換するコンパイラツール
    • ECMAScriptとは
  • Vue Router
    • Vue.jsを利用したSPA構築で、ルーティング制御をするための公式プラグイン
    • SPA: シングルページアプリケーション
  • Vuex
    • Vuex は Vue.js アプリケーションのための 状態管理パターン + ライブラリ
  • Linter
    • ソースコードを静的解析し、問題点を指摘、または自動でフォーマットするツールのこと
? Choose a version of Vue.js that you want to start the project with 2.x
  • Vue2を使う
? Use class-style component syntax? Yes
  • 使うのは Class-style componentを使います。

ちなみに...

  • Object Style
    • Vue.extend()を用いた書き方
  • Class Style
    • class MyComponent extends Vueとする書き方
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? Yes
  • VueをTypeScriptかつクラス属性で書くためのツールをインストールする。

  • TypeScriptと一緒にbabelを使用するか?下記オプションが付与される。

    • Babel
      • 古いブラウザ用にJSを下位互換するツール
    • modern mode
      • 下位互換した時にコードが長くなりすぎないよう最適化する
    • polyfills
      • 更新されてなくなってしまったJSライブラリを自動保管する(JSはバージョンが更新される毎にライブラリが一変する)
    • transpiling JSX
      • JSXをトランスパイルする

ちなみに

  • JSX

  • ? Use history mode for router? (Requires proper server setup for index fallback in production) No

    • vue-routerで作成された(SPA)ページのURLは/#/でページ内容を切り分ける。これをハッシュモードという。
    • これに対し、各ページに個別のURLを振り分けるのがhistoryモード。
  • ? Pick a linter / formatter config: Prettier

    • Prettierを使います
  • ? Pick additional lint features: Lint on save

    • 保存時にlintが動く
  • ? Where do you prefer placing config for Babel, ESLint, etc.? In package.json

    • Babel、ESLintなどのconfigファイルをどこにおくか。
    • In package.json・・・nodeの管理ファイルpakage.jsonに書き込む。
  • ? Save this as a preset for future projects? No

    • ここまでの設定を次回プロジェクト立ち上げのために保存しておくかどうか。
  • ? Pick the package manager to use when installing dependencies: Yarn

    • yarnを使う

Vuetify install

vue add vuetify
$ vue add vuetify

📦  Installing vue-cli-plugin-vuetify...

yarn add v1.22.19
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 🔨  Building fresh packages...
success Saved lockfile.
success Saved 5 new dependencies.
info Direct dependencies
└─ vue-cli-plugin-vuetify@2.5.8
info All dependencies
├─ interpret@1.4.0
├─ null-loader@4.0.1
├─ rechoir@0.6.2
├─ shelljs@0.8.5
└─ vue-cli-plugin-vuetify@2.5.8
✨  Done in 2.78s.
✔  Successfully installed plugin: vue-cli-plugin-vuetify

? Choose a preset: Vuetify 2 - Vue CLI (recommended)

🚀  Invoking generator for vue-cli-plugin-vuetify...
📦  Installing additional dependencies...

yarn install v1.22.19
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 🔨  Building fresh packages...
success Saved lockfile.
✨  Done in 3.64s.
⠙  Running completion hooks...
/Users/USERNAME/dev/vue2/vue2-project/src/views/HomeView.vue
  10:9  error  Component name "Home" should always be multi-word  vue/multi-word-component-names

✖ 1 problem (1 error, 0 warnings)
  • コンポーネント名 "Home "は常に複数ワードでなければならない ので以下を変更してください

  • src/views/HomeView.vue

-  name: "Home",
+  name: "HomeView",

最後に

  • モック:Mock Service Worker
  • テストツールなども導入して基本的な構成をしてみたいですね

参考文献

【セットアップ】Macbook Pro M1 の環境構築【2023 GW Day 1】

Macbook Pro M1 の開発する環境構築をする

私がよくする開発環境を構築改めて行なっていこうと思います。

まずはterminal.appを開いてください。

Homebrew

以下のコマンドをterminalに貼り付けてください。

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

brew.sh

install Git Docker Nodebrew Python3

brew install git docker nodebrew python3

nodebrew の path

後ほど以下を.zshrcに追加します

export PATH=$HOME/.nodebrew/current/bin:$PATH

VSCode

.app

アプリのインストールします。公式サイトからインストーラを入手してください。

code.visualstudio.com

codeコマンドの導入

  • VScodeを起動して、F1を入力
  • codeを入力して、コマンドをインストールする

.zsh

zshを使う際に、あると便利な機能を導入していきます。

Gitのブランチ表示

brew install git 実行時に /opt/homebrew/etc/bash_completion.d 配下に以下のファイルが配置してあります。

  • git-completion.bash (Zshには使えないのでこちらは利用しない)
  • git-prompt.sh

Gitの入力補完

ファイルの場所は任意で構いませんが、今回は以下に作成します。

  • ~/.zsh/
: ~/.zsh 
$ mkdir completion
: ~/.zsh 
$ cd completion 
: ~/.zsh/completion 
$ curl -O https://raw.github.com/git/git/master/contrib/completion/git-completion.zsh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:--  0:00:01 --:--:--     0
$ ls ~/.zsh/completion/git-completion.zsh
~/.zsh/completion/git-completion.zsh

オートコンプリーション

以下をターミナルにコピペしてください

brew install zsh-autocomplete

シンタックスハイライト

以下をターミナルにコピペしてください

brew install zsh-syntax-highlighting

.zshrc

# read git script
### sourceコマンドとは、他シェルファイルをカレントシェルで実行するコマンド
source /opt/homebrew/etc/bash_completion.d/git-prompt.sh
source /Users/seconduser/.zsh/completion/git-completion.zsh
source /opt/homebrew/share/zsh-autocomplete/zsh-autocomplete.plugin.zsh
source /opt/homebrew/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh

# Git options
GIT_PS1_SHOWDIRTYSTATE=true
GIT_PS1_SHOWUNTRACKEDFILES=true
GIT_PS1_SHOWSTASHSTATE=true
GIT_PS1_SHOWUPSTREAM=auto

# PATH
export PATH=$HOME/.nodebrew/current/bin:$PATH

# プロンプトの表示設定
setopt PROMPT_SUBST ; PS1='%F{green}%n@%m%f: %F{cyan}%~%f %F{red}$(__git_ps1 "(%s)")%f
\$ '

IntelliJ IDEA Community

javaやkotlinなどのIDEとしてこちらが便利なのでよく利用しています。

IntelliJ IDEA をダウンロード - Java と Kotlin の最先端 IDE

Source Tree

gitはGUIツールで管理した方楽だと思っております。こちらをよく利用しています。

www.sourcetreeapp.com

DBeaver Community

DB管理のGUIアプリです。こちらが使いやすいのでよく利用しています。

dbeaver.io

まとめ

  • 新しいPCを用意したので、個人用にツールを導入していきました。
  • 残念ながら1日過ぎてしまいましたが、頑張って記事を書いて、少しずつ頑張って日々覚えたことを書いていきたいです。

【端書】GitHubを整理しよう

GitHubを整理したい

  • 現状私は学生の頃なんとなく使っていたものをそのままにしている
  • これを社会人としてアピールできるようなレベルのものにしたい
  • GitHubを個人利用の場合はグルーピングできないため名前で整理しよう

現状持っているリポジトリ

命名ルール

  • Learning-XXX: 学習用リポジトリ
  • それ以外とするようにする

ただ作業が手間である

  • 手間である...

作業メモ

作業リスト アカウント URL check
Vue2, Vue3学習 https://github.com/Kuzu99/Learning-Vue
TypeScript学習 https://github.com/Kuzu99/Learning-TypeScript
MozillaDoc学習用 https://github.com/Kuzu99/Learnig-MozillaDoc/settings
ZENN記事用 https://github.com/Kuzu99/zenn
競技プログラミング https://github.com/Kuzu99/Competitive-programming
GitHubプロフィール用 https://github.com/Kuzu99/Kuzu99
GitHubポートフォリオを作りたかったリポジトリ https://github.com/Kuzu99/kuzu99.github.io
スレッドセーフ学習用
VRオンラインスライドショーアプリ
AtCoder
Aize Online Judge用
アルゴリズム勉強用
スピロデザイン
フォレスト
  • ついでにできていなかったBranch protection ruleもやった