SQLアンチパターン 7章 のメモ
7章 マルチカラムアトリビュート(複数列属性)
この章で目的しているのは、
1つのテーブルの一つの属性が、複数の値を持つことができるようにする事。
具体的な例としては、ユーザーの複数の電話番号や記事に紐づく沢山のタグ等の属性が考えられる。
アンチパターン : 複数の列を定義する
記事に紐づくタグを複数持てるようにするために、その分複数のカラムを定義するのは、
アンチパターンで非常に良くない上に、かなり多くの問題を抱えている。
例えば、記事に紐づくタグを複数持てるようにするために、
tag1, tag2, tag3 このカラムを持ったarticles テーブルを例として考える
CREATE TABLE articles ( id PRIMARY KEY, title VARCHAR, body VARCHAR, tag1 VARCHAR(30), -- 問題のタグ1 タグ名が入る tag2 VARCHAR(30), -- 問題のタグ2 タグ名が入る tag3 VARCHAR(30), -- 問題のタグ3 タグ名が入る );
解決策について
本に載っている例ならば、紹介されている解決策がスマートで非常に良いとは思うが、 ここで例として考えたアンチパターンに紹介された解決策を当てはめても、あまりスマートではない。
よって、ここでの例をターゲットに適切な解決を考える
中間テーブルを使う
このtag1, tag2, tag3がどのようなモノかを考えると、
記事にタグを付けたいが、複数の記事に同一のタグを付けたい場合は、
- 記事は複数のタグを持ち得る
- タグは複数の記事を持ち得る
上記の事から、多 対 多 の関係なので、中間テーブルによる関連付けが良さそう。
CREATE TABLE tags ( id PRIMARY KEY, name VARCHAR(30) );
CREATE TABLE articles_tags ( id PRIMARY KEY, article_id BIGINT UNSIGNED NOT NULL, -- 紐づけたい記事のid tag_id BIGINT UNSIGNED NOT NULL, -- 紐づけたいタグのid FOREIGN KEY (article_id) REFERENCES articles(id), FOREIGN KEY (tag_id) REFERENCES tags(id) ); -- 複合ユニークキーを作って、記事に同じタグを複数付けられないようにする ALTER TABLE articles_tags ADD UNIQUE KEY unique_key_1( article_id, tag_id );
上記のような中間テーブルを用意すれば、
複数の記事に複数のタグを付けられるし、外部キーをきちんと用意しているので検索するのも比較的簡単にできる。
また、中間テーブルにユニークキーを使うことで1つの記事に同じタグを重複使用することを制限できる。
感想
自分の認識としては、テーブルを定義したときにデータの性質を考えて、切り離せるかどうかを考えるようにしている。
データの性質が違う場合は別テーブルとして考えるようにして、安直に中間テーブルを利用してしまうので、
ケースバイケースで適切に選べるようになりたい。
SQLアンチパターン 6章についてメモと感想
6章 ポリモーフィック関連
ポリモーフィック(ポリモーフィズム)
そもそもポリモーフィックとはなにか定義がわからないので調べてみた。
自分の認識としては、
1つの要素が複数の概念に属してもよい状態
を指すと思う。
以下調べた内容の一部
ポリモーフィズム(英: Polymorphism)とは、
プログラミング言語の型システムの性質を表すもので、プログラミング言語の各要素(定数、変数、式、オブジェクト、関数、メソッドなど)についてそれらが複数の型に属することを許すという性質を指す。
ポリモルフィズム、多態性、多相性、多様性とも呼ばれる。
対義語はモノモーフィズム (Monomorphism)、単態性、単相性で、プログラミング言語の各要素が唯一つの型に属するという性質を指す。
ここの説明が非常にわかりやすかった。
複数のテーブルに対して多対一で紐づくテーブルの設計アプローチ|スパイスファクトリー株式会社
近年ではrails系の記事が非常に多い。
【初心者向け】Railsのポリモーフィック関連付けを理解しよう - Qiita
Railsのポリモーフィック関連とはなんなのか - Qiita
アンチパターンのポリモーフィック関連とは
1つのテーブルを複数のテーブルに関連させるような設計の事を指す。
しかし、外部キーが使用できないなどの多くの問題を抱えているので、
あまり良くない手法である。
ただし、Rails等の一部のフレームワークではこの手法で実装が許可されているので、
制御の問題が解消されている為、その場合はフレームワークを使用することでこの設計をある程度は運用することができる。
例えば、
既に存在する、記事(articles)と写真(photos)それぞれにコメント(comments)を新しく付けられるようにしたい場合は、
ポリモーフィック関連を使えば、解決できる。
しかし、このポリモーフィック関連を使った設計では、
外部キーが使用できないので、整合性を保証することができない。
新しく作るコメントテーブル下記のように定義する。
CREATE TABLE comments ( id PRIMARY KEY, parent_type VARCHAR(30), -- 結び付ける親テーブル名が入る articles か photos parent_id INT UNSIGNED NOT NULL, comment TEXT );
このように定義すれば、
parent_typeに、対象となるテーブル名を、
parent_idには、対象となるレコードのidをそれぞれ割り当てることで、紐づけが可能となる。
しかし、記事や写真テーブル以外にも別のテーブルがあれば、保存できてしまうし、
外部キーが使用できないので、アプリケーション側で制御するための処理を実装しないとかなりあいまいで不正確なデータになってしまう。
解決策 その1 交差テーブルを使う
例えば先ほどの例を用いると、
既に存在する、記事(articles)と写真(photos)それぞれにコメント(comments)を新しく付けられるようにしたい場合は、
それぞれに新しく交差テーブルを用意する。
記事とコメントを結び付ける articles_comments テーブルと
写真とコメントを結びつける photos_comments テーブルを作成することで、
外部キーを使用しつつ、1つの記事に対して単一か、複数のコメントなのかを制御したりすることが可能になる。
この解決方は比較的簡単な方だけど、
問題としては、記事と写真に対して同じコメントを付けられてしまう問題がある。
解決策 その2 共通の親テーブルを使う
オブジェクト指向みたいに共通の親テーブルを使用する事でも解決できる。
しかし、交差テーブルと同様の問題が発生する。
先ほどの例を再び用いると、
既に存在する、記事(articles)と写真(photos)それぞれにコメント(comments)を新しく付けられるようにしたい場合は、
共通する親テーブルである 投稿(posts)テーブルを作成。
さらに、記事、写真、コメントの親なのでそれぞれに外部キーであるpost_idを追加する。
この設計を利用する場合は、
記事や、写真を新たに作成する場合でも先に投稿テーブルを作成した後で追加する必要がある。
感想
ポリモーフィックについて、きちんと理解しておらずなんとなくの認識なので、
改めて掘り下げることができたので、以前より理解が進んだとは思う。
ところで、読んだ時のメモや調べたことをブログで公開するのは初めてで、
これは著作権的に良いのかな?
読書感想文ならともかく、あまりに本の内容についてそのままを書きすぎるとダメだった気がしてる...
改めて調べてみて、ダメだった場合はすぐに公開を停止します。
rails 5.2 ActiveStorage を利用するうえでSeed を用意する方法
ActiveStorageをつかって何かしらを実装する際に、そのSeedをどうやって生成するかについてです。
find後のオブジェクトに対してattachするだけ
Active Storage の概要 | Rails ガイド
レコードに結び付ける事自体は上記の公式ドキュメントにも示されている通り、find後にattachするだけで実装できます。
ただし、それをファイルアップロード等ではなくSeed内で明示的にパスを指定して結び付けたいので、
少し手を加える必要があります。
日本語訳はまだ無いようですが、こちらのドキュメントでも説明されてます
Active Storage Overview — Ruby on Rails Guides
attachメソッドの引数で、
io: と filename: を指定することで明示的に指定ができます。
ただし、io: を指定する際は File.openの戻り値を利用する必要があるので注意してください。
File.open('ファイルまでの絶対,あるいは相対パス')
例として、 articlesモデルがあり、そこにvideoとして動画を紐づけたいケースを想定します。
# id 1 のレコードを取得 article = Article.find(1) # modelで指定している、ActiveStorageの紐づけ名は video の場合 article.video.attach(io: File.open('public/test.mp4'), filename: 'test.mp4')
これでSeedでも登録することができます。
はてなでやっていくことにしました
初めまして&お久しぶりです
数年前まで、ロリポップ + WordPress でブログを運営してたのですが、
継続できずにグダグダと更新していませんでした。
そこからアウトプットする癖が全くなくなっていて、これからのエンジニア人生に不安が出てきたので
今年から、再びブログをちゃんと更新していこうと思います。
なぜ、継続できなかったか
これについては、色々振り返って考えてみました。
- 当時はエンジニアとしてあまりに未熟でがむしゃらにインプットし続けてしまった
- ブログ向けに記事をきちんと書こうとしすぎて、途中で疲れてしまった
- 当時の仕事的にも、気持ち的にも余裕がなかった
大まかには上記の3つが大きな要因だと考えており、
それぞれを少し掘り下げて分析してみます。
当時はエンジニアとしてあまりに未熟でがむしゃらにインプットし続けてしまった
当時を思い出すと、高校から上がりたてで全く技術的な事に慣れておらず、
全てが未体験&初体験な為、吸収して仕事についていくので精一杯だったような気がしてます。
その中で、イキってブログをやろうとしたのですがそこまで気力は持ちませんでした...
ただ、そこで踏ん張ってブログを続けてアウトプットしていたら、もう少しはまともなエンジニアに慣れてたのかもしれません。
ブログ向けに記事をきちんと書こうとしすぎて、途中で疲れてしまった
技術的なメモを日常的にとる習慣はあるのですが、それを記事としてブラッシュアップさせる際に、
色々修正してたら疲れて嫌になってしまうようです。
僕だけなのかな?
現在進行形で文章を書いていると、ですます調で良いのか?
普段の口調で書くべきか等の文章を書くスキルが足りてない故に色々迷って、面倒になってしまうのです。
この現象については、基本的には気にしない。
純粋にアウトプットのみを最初の目標として、継続することが出来たら徐々に文章を書くスキルを勉強していく。
このような心構えにしておくことで、やっていけそうな気がしてます。
当時の仕事的にも、気持ち的にも余裕がなかった
単純に仕事についていくので精一杯だった状況 + 初めての一人暮らし
というのが、かなり負担だったと思っています。
初めて一人暮らしすると、様々な体験が得られますが同時にたくさんのミスや手間が発生します。
家事をさぼったツケを土日で支払ったり、光熱費を含む様々な支払い、お金の管理etc...
ただ、今は一人暮らしも慣れてルームシェアしたりもあったので、どこで手を抜いて楽できるのか等の上手い生活ができるようになってきたと思うので、
解決です。
余談ですが、一人暮らしで一番つらいのは家事です。
家事をなるべく自動化するなりしたほうが幸せになれます。
特に洗濯、掃除、皿洗いはクソ疲れる。
これから継続するにはどうすれば良いのか
モチベーションの問題もありますが、これは習慣として取り入れることでなんとかしようと思っています。
そうすると、習慣として定着するまでもモチベーションはどうするのか?というループに陥るので特に深くは考えません。
習慣として定着させるには、なるべく大きな変化として始めるより少しの変化としてどこかに差し込むのが良さそうなので、
朝の情報収集タイムの後にやるようにします。
この情報収集タイムは、午前中の最低30分は技術系ブログを徘徊したり、Twitterで気になるリストを監視したりして
なるべく沢山の情報を得るために使っているのですが、
その後にメモやブックマークをして整理するときに、ついでに記事を書くようにします。
そして公開する。
今の僕の習慣的に、無理せずやれる範囲を考えるとこの辺りに落ち着きました。
夜に作業したり、記事書くのはほんとに難しい...
そんなスタミナがないんです...
今年はアウトプットの年にしたい
去年は知識や、体重含めて様々なインプットをしていたので、
今年はアウトプットを習慣づけて発信していきたいです。
体重もアウトプットしてコミットしたいです(語彙)
これらからよろしくお願いします。
初心者が上達する為の知識[EXVSMBON]
たまには好きなゲームの話がしたい。 というより一緒に楽しめる人が増えてくれることを目的として書きました。 確かにゲーセンに行けば、チンパンは大体いるし、家庭用ではまだプレイしてるプレイヤーは強者が多い感じだし、そもそも今からやろうと思う人がいるのか 怪しいけども、もし初心者or伸び悩んでる人がいるのならば是非参考にしてほしいと思います。 殆どがwikiに書いてあることの焼き直しになりますが...
僕自身は、勝率が45%程度で楽しくやっています。
ゲームを楽しもう!
まずすべてのゲームに言えますが、楽しむことが目的です。 なので、あまりにイライラしたりムカつくのであればその日は出直しましょう。 このゲームは確かに理不尽に強い機体や武装が存在するので、手も足も出ずにストレスが溜まる事もあります。 しかし、それでも愛機と相方で手に入れた勝利の瞬間はとても楽しく心地の良いものですし 人の感性によりますがゲームに楽しさを見出すことから是非始めてください。 ゲロビを当てるのが気持ちがいい、格闘決めるが爽快etc楽しみ方は人それぞれですから! その上で、勝敗を気にしてみてください。今よりももっと楽しくなるはずです。
このゲームはチーム戦
このゲームはチーム戦です(二回目) wikiにも書いてありますが、あくまで2on2のゲームなので相方か自分一人が凄く強くても相手との実力がよほど低くない限り勝てません。 なので、まず一般的な格闘ゲームである "自分 vs 敵" の概念を捨てましょう。
そしてチーム戦なので、勝敗の結果はその時の"自分と相方二人のチームワーク"で決まります。 よくあるのが、負けの原因のなすりつけです。 確かに相方や自分の実力が足りずに足を引っ張ってしまい、負けの原因になるかもしれません。 ですが、そこを責めてもストレスが溜まるばかりで解決には至りません。 まずは自身のプレイの反省からしてみてください。 ちゃんと体力調整できてたか?無駄な攻撃をしてないか?位置取りは? 思い当たる節が、あるのなら反省し改善しようと努力すると共に自分の動きを相方に聞いてみましょう。 聞く相手がいないorオンラインでプレイしているのならリプレイを自分視点と相方視点、敵視点で見なおしてみましょう。 そして、相手がいるのならば同じように相方の評価をしてあげましょう。
一緒にプレイする人との亀裂を少なくすることで、より一層プレイが楽しくなると思います。 オンラインで知らぬ人と決めたコンビネーションや馴染みの友達と阿吽の呼吸で勝利したらお互いに最高の気分になれますから!
wikiを愛読しよう
このゲームは多くの機体とそれぞれが持つたくさんの武装を攻略して勝たなくてはなりません。 なので、ある意味ではこのゲームにおける最も重要な要素は情報です。 wikiにはその殆どが記述されているので、自分が興味のない機体でもさらりと流し読んで機体の得意なことと苦手な事くらいは頭に入れましょう。 そうすれば相手や相方になった機体に合わせて行動ができるので非常に強みになります。
好きな機体を見つけよう
上達の近道、、、 それは、愛機を決めることです。
自分で決めた愛機がwikiではどのように評価されていても気にしないでまずは使い込みましょう。 最低限、武装の特徴と機体に備わっている性能は把握するレベルまでです。 それまでは、じっくりできるCPU戦をおすすめします。 wikiを参考に各武装を使って理解してみてください。 勿論、wikiにあることが絶対に正しい訳ではないので、あくまで"参考"にとどめて実際に使って自分の感性で理解してください。
基礎的なテクニック・セオリーを身につけよう
残念ながら勝てるように、また楽しくなるためには沢山あるテクニックを身につけなければなりません。 wikiの初心者講座でも紹介されているのでそちらを参考に練習してみてください。
また、セオリーについてキチンと覚える必要があります。 覚醒のタイミング、位置取り、前衛と後衛etc... 沢山ありますが、個人的に覚えたほうが上達が早くゲームの理解が進むセオリーを紹介します。
前衛・後衛
このゲームに置いてとても重要な要素になります。 簡潔に言えば"高いコストがステージの中心付近を位置取り、低いコストがその周辺から近い場所を位置取る"という感じです。 位置取り、と聞くと難しく思うかもしれませんが実際に意識してプレイすれば思いの外簡単だと気づけるはずです。 そして、前衛と後衛が入れ替わるタイミングですがコレは初心者が意識するにはあまりに難しすぎるので
"高コストが先落ちしてリスポーンしてきたら一緒に攻め上がる"
"攻め上がった後に撃墜されたら、安全な攻撃以外はせずに逃げに徹する"
"低コストが先に落ちたら、リスポーン後に覚醒を使って攻め立てる"
これを実践してみてください。 相方がそれなりに実力があるならコレでなんとかなるはずです。 これらを実践していくと、様々なシチュエーションに遭遇した時に適切ではない場合が出てきます。 そこに違和感を覚えたりすれば、この考えを元に試行錯誤してみてください。 例でいうと
"高コストが先落ちしたけど、自分も結構危ない体力"
この場合に
"高コストが先落ちしてリスポーンしてきたら一緒に攻め上がる"
これを実践すると、あっという間に自機を撃墜され、コスオバなのでリスポーン後に狙われて勝負を決められてしまいます。 なので、
"高コストの少し後ろでカットを狙う・高コストの体力がある程度減るまで隙の大きい武装を避けて攻撃する"
このような状況判断ができる余裕ができてくれば、プレイしながら臨機応変に対応できるようになり素晴らしいパイロットの仲間入りです!
覚醒のタイミング
コレは本当に難しく、安定した答えが存在しないと言っても良いでしょう。 そのなか初心者が答えを導き出すのは難しいので、タイミングを固定しちゃいます。
覚醒が溜まったらすぐに使う
これはおそらく多大なバッシングを受けますが、初心者のうちは覚醒ゲージの管理やタイミングを図るのは難しいので いっそ使って攻めに転じたほうがダメージにもなるし効果的だと考えるからです。 なにより、"覚醒が溜まった"ということを確認する癖がつくので、管理の訓練になるからです。 勿論、覚醒落ちは避けたいですから死なないように立ちまわる前提です。 覚醒したら攻めなきゃいけないわけではないので、体力を見て逃げるという選択もアリです。
一先ず、この2つのセオリーを実践・学習して身につけて見てください。 これだけでまともな勝負になりますし、意識して考えながらプレイすることで多くの発見が得られると思います。
冷静になる
コレは自分の中で意識してることですが、理不尽にハメ殺しにあったり煽られて所謂"あったまる"状態にならないことです。 あったまってしまうと、冷静な判断力や連携が失われて勝てた勝負も勝てなくなります。 常に冷静に状況を観察して楽しみましょう。 実力差に絶望したり、腹をたてるのではなく関心してその技術を勉強する心持ちでプレイすることで 武装の使い方や、発想をふくらませることができ、近距離や射撃戦においての読み合いで負けづらくなります。 腹をたてると、とたんにストレスがたまりますしゲームが嫌になってしまい上達以前の問題になります。 常勝なぞ、ほとんどのプレイヤーは不可能ですので初心者の方は勝ち負けに意識を向けるのではなく 自分の愛機を自由に動かす事に意識を向けるのをおすすめします。 そうして、自機を自在に動かせるようになってから勝つことを前提とした戦術や武装の使い方を覚えていけばいいと僕は思います。
とりえずプレイし続けよう
どのゲームにもいえますが、積み重ねの経験が大事です。 一回でもいいので機会があればプレイして積み重ねてください。 家庭版がある方は、毎日やってもいいかもしれません。
知識編は以上です。 テクニック等については別の記事で書こうと思います。 ガンダムが好きなら是非プレイしてほしいゲームですし、知らない人もハマってガンダムの世界を知って貰えたら嬉しいです! なにか、意見や指摘、一緒にプレイとかはTwitter(@39mamon)で話しかけてください!
hogehogeという文化について
hogehoge についてもっと説明がほしい!
プログラムでよく見かける"hogehoge"だけど、これについてキチンと初学者に説明したほうがいい気がする... これはプログラムを触る人にとってある種の常識なのだから。 (とはいえ、僕自身もうまく概念を説明できないでいる)
hogehoge という文化について
僕達プログラムを触る人にとって、何かしら技術的な問題に詰まって検索したり、Qiita、個人ブログをみたりしてサンプルコードや具体例、解説を探すことが日常的にあるとおもう。 勿論、初学者や簡単なコーディングをするために情報を集める人も探すだろう。 そしてようやくたどり着いた記事や情報を読んで、インプットしようとすると...
$hogehoge = array(
'piyo' => 5,
'fuga' => 9
);
$fugafuga->save($hogehoge);
このようなコードを見かけることが多々ある。 このサンプルコードを見た人の反応だが、 経験者「ふむふむ、なるほど」 初学者「$hogehoge ってなんだ?」 というおおまかに2つに別れるはずだ。そうであるに違いない。僕はそうだった。
hogehoge って?
日本語的にしっくり来る表現は「アレ」、「ソレ」、「コレ」等の抽象的な表現であると、僕は思う。 実際にプログラムの世界では結構頻繁に使われてる(はず)。 サンプルで示す、適当な変数名やメソッドにファイル名やフォルダ名とか もう名前がつけられるすべてのものに使われる素晴らしい特に意味が存在しない名称(表現)が"hogehoge"。 困ったらhogehogeしとくみたいな。
ちなみに、hogehoge以外にも piyopiyo, fugafuga あたりは亜種としてよく見る。
僕が推すのは imoimo なんかかわいいしね。
hogehoge が引き起こす問題
それは、初学者や察しが悪い人が勘違いをする。 例えば関数の説明をするとして、安直にhogehogeを使うとしよう。
関数の説明
・"function" の後ろにあるのが関数の名前
・()の中にあるのが引数
・引数は関数の内部に値を引き渡せる
function imoimo ( $hoge = null ) {
print($hoge);
}
関数の呼び出し方
・定義した名前を()つけて呼び出す
・()の中に値を渡すことで引数になる
imoimo('kumokumo');
みたいな説明とサンプルコードだとして、経験者は"hogehoge"とかは意味のない名称で自由に設定することができるという暗黙のルールといか知識を知っているので すんなりと頭に入って理解ができると思う。 しかし、初学者ではどうだろうか? まず、この説明文では"$hoge"はそういうものだと、誤解をしてどの関数でも"$hoge = null"を引数に設定するのだな、と誤った解釈をする可能性が非常に高いはずだ。 昔の僕はそうでした。 hogeのルールを理解せずに、とりあえずサンプルと同じようにやってみてソレが定着してしまうと見事に実際のソースコードにhogeを書いてしまう事件になる。
極論かもしれないが...
hogehoge はやめるべき?
しかし、hogehogeはやめるべきではないとも思う。 暗黙のルールさえ理解していれば、コレほどサンプルだと明示的に書かれていることがわかる命名は存在しないと思う。 命名にローマ字で"sample"という変数をつけたとして凄く長い命名になってしまう。"sample_function"、"sample_1"とか分かりづらいし。
面白いのが、誰に言われるわけでもなくいつの間にか"hoge"という概念を理解している点で 少なくとも僕は何度かコードを書くうちに、hogeという概念を理解していた。あぁ、コレには意味が無い命名なんだなって。 だから、多分みんなあえてこのことに深く触れずにシレッとhogeを使ってサンプルを示したり使っているのだと思う。
hogehoge は不思議
結論、僕が話したかったことは
hogehogeについて、初学者にわかるように説明をしてあげたほうが、学習初期においては効率がいいんじゃないのか?
という事です。
理解できると当たり前のことになるほどに便利というかなんというか... 他の業界でもhogehoge的な概念はあるのかちょっと気になる。
みんなもレッツ hogehoge
(追記 2016/08/04) http://togetter.com/li/832718 http://tamezatu.com/hoge-hogehoge-notthrough/ hogeについてやっぱりわからない人も一定数いるみたい。 以外なのは年代によって通じないという話が驚き...