楽々ERDレッスン
『楽々ERDレッスン』(翔泳社)を読みました!
データベース設計の本です📖
目次
1.使用書籍
2.DB設計総論
2-1. 正規化
DB設計において、One Fact in One Place というのが要点になります。
簡単にいうと、重複を排除して、1つのデータの置き場所を1箇所に整理するような感じです。
これを実現するために正規化という手法があります。
2-2. 正規化の手順(例)
商品の伝票を例にした正規化の手順の例です。
- 項目と値を全て列挙
- 繰り返し部分の切り出し
- 従属性の追加
- 冗長性の排除
例えばはじめに項目を伝票番号、日付、顧客名、商品名1、単価1、数量1、金額1、合計金額
と列挙し、値を全て書き出します。
次に商品名1、商品名2、…
など、繰り返すものを切り出します。
従属性の追加とは、商品ごとに単価が決まっている場合、商品名と単価をくっつけることです。
冗長性の排除とは、金額、合計金額は自明であるため削除するといったことです。
また、レコードの中身とは関係なくレコードの存在を表現するために、IDを定義することがあります。
- IDの割り付け
- ERDで表現
伝票ID、顧客ID、商品IDを定義し、ERD(Entity Relationship Diagram)という図で表現するという流れですが、詳しくは今後勉強です🙂
2-3. キー
キーとは、膨大なデータの中からあるデータを特定するための識別子です。
キーの定義の善し悪しでデータベース設計のクオリティが大きく左右されるそうです🤨
一般的には以下のようなものがあります。
キー | 役割 |
---|---|
主キー (primary key) |
・候補キーの中から何らかの意味的に選択された、インスタンスを特定可能な識別子 |
ユニークキー | ・エンティティ内のインスタンスをそれぞれに特定可能な識別子 ・実装上はユニークインデックス |
候補キー | ・エンティティ(箱)内のインスタンスをそれぞれに特定可能な識別子の「すべて」 ・実装上はインデックス |
外部キー (foreign key) |
・エンティティをまたがってのインスタンス同士の関係 ・参照整合性制約 |
3.DB設計の手順
DB設計の手順は以下のとおりです。
- 大まかにブロック分けを行う(業務単位か部門単位)
- それぞれのブロックごとにイベント系を洗い出す
- イベント系に対する正規化を行って、リソース系を洗い出す
- リソース系に対する分類の洗い出しを行って、リソース系の正規化を行う
- ブロック間でリソース系の統合を行い、さらに正規化を行う
- 導出系の整理をして、最終的な正規化を行う
4.感想など
この本とってもわかりやすいです。
最低限SQLの基礎を知っている方向けの本でしたが、語彙が豊富で表現が面白く、知的で、小説を読んでいるようでした!(わたしの語彙力が残念で申し訳ありません)
頭の良い人にやさしく教えてもらっている気分になれるのでおすすめです💪笑
SQLの基本
本日は SQL について勉強します!
データベースについては以前実務でFileMakerを使っていたので、単語が全く分からないわけではないため、テーブルとかの用語は解説を割愛いたします🙇♀️
目次
1.SQLとは
SQL(Structured Query Language)とは、データベースを操作するための言語のことです。
以前PostgreSQLというものを学習しましたが、だいぶ忘れています😗笑
SQLには ISO(国際標準化機構)で定められた標準規格があるそうで、ISO に準拠した SQL を標準SQLと言います。
2.SQLの分類
SQLは、定義
、操作
、制御
の3つに分類されます。
2-1. DDL(Data Definition Language)
DDLはデータ定義言語です。以下のようなコマンドがあります。
コマンド | 機能 |
---|---|
CREATE | データベースやテーブルなどを作成する |
DROP | データベースやテーブルなどを削除する |
ALTER | データベースやテーブルなどの構成を変更する |
削除はDELETE
ではないのですね…😐
DELETE
は次に出てくるので間違えないように注意ですね!
2-2. DML(Data Manipulation Language)
DMLはデータ操作言語です。以下のようなコマンドがあります。
コマンド | 機能 |
---|---|
SELECT | テーブルから行を検索する |
INSERT | テーブルに新規行を登録する |
UPDATE | テーブルの行を更新する |
DELETE | テーブルの行を削除する |
2-3. DCL(Data Control Language)
DCLはデータ制御言語です。以下のようなコマンドがあります。
コマンド | 機能 |
---|---|
COMMIT | データベースに対して行った変更を確定する |
ROLLBACK | データベースに対して行った変更を取り消す |
GRANT | ユーザーに操作の権限を与える |
REVOKE | ユーザーから操作の権限を奪う |
3.SQLの書き方
SQLの書き方にはルールがあります。
4.操作方法(sqlite3)
わたしのmacbookには sqlite3 がインストールされているので、これを使って操作をしてみます!
(いつかの勉強会でいつの間にかインストールしてたようです笑)
4-1. 接続
データベースに接続します。データベースが無い場合、新規作成になります。
今回はtest
という名前のデータベースを作成します!
$ sqlite3 test.sqlite3
4-2. CREATE
テーブルの新規作成をします。
文章で説明するとものすごくわかりにくいと思うので、実際に作ったもの載せます😂
途中で改行を入れたとしても、先程のルールのとおり、SQL文の最後はセミコロン;
です。
なのでキャプチャは6行に分かれていますが、SQL文としては1文です👀
CREATE TABLE
のあとにテーブル名shopping_list
を書き、その後に括弧( )
の中に列名、データ型、制約の3セットが並んでいます。
列名はid
、name
、price
、note
の4つがあります。
データ型は以下のように設定できます💡
データ型 | 意味 |
---|---|
INTEGER | 整数(小数は入らない) |
CHAR | 固定長文字列 指定した最大長に満たない場合は後ろを半角スペースで埋める |
VARCHAR | 可変長文字列 指定した最大長に満たない場合は何もしない |
DATE | 日付(年月日) |
VARCHAR
はTEXT
でも良いみたいですが、VARCHAR
だと最大長がマルチバイト文字に対応するとか、TEXT
だと最大長はバイト数で決まるとか違いがあるそうです。
今はどっちでも良いかな…?
制約がNOT NULL
の場合、必ずデータが格納されていないといけないという意味になり、無記入ではエラーになります🧐
最後の PRIMARY KEY は、特定のデータを指定するときの主キーになります。
そのため、主キーは重複してはいけません。
例えば「ラーメン」という商品を2つ登録するとしても、1つめのラーメンと2つめのラーメンを見分けるために異なる主キーを使います。
ここではid
を主キーとしています✨
4-3. トランザクション
データベースにおけるトランザクション(transaction)とは、簡単に言うとデータベースの複数の操作を一括で更新することです。
先程作った空のテーブルにデータを入れていきます💪💪
BEGIN TRANSACTION;
でトランザクションを開始します。
その後INSERT
などでデータを触ったら、最後にCOMMIT;
で変更を一括で反映させます。
トランザクションの終了はEND TRANSACTION;
です👏
もし途中で間違えたら、COMMIT
ではなくROLLBACK
を使って変更を破棄します💡
なんとなく感覚的にわかりやすいです〜🐾
4-4. INSERT
トランザクションを行って、INSERT
で2行追加しました!
最後にCOMMIT;
を行った時点で、データベースに反映されます。
DB Browser for SQLiteというソフトをインストールしているので、視覚的に確認することができます!
4-5. SELECT
SELECT
は検索コマンドです。
今作ったtest.sqlite3
にはほとんどデータが格納されていませんが、実際データベースは多大なデータを格納します。
この中から検索する時に使うため、重宝されるコマンドみたいです🎉
*
を使うと全てを表示してくれるみたいですね〜!
4-6. DELETE
DELETE
は行を削除するコマンドです。
先程追加したorange
の行を削除します。
ブラウザで、行が消えているのが確認できます😶
4-7. UPDATE
UPDATE
は行を更新するコマンドです。
単価を1.08倍にしました😊
Rubyでwcコマンドを作った
lsコマンドに続き、Rubyでwcコマンドを作りました〜!
課題なのでカンニング防止のためコードは公開できないのですが、学んだことまとめます💪
目次
1.wcコマンドとは
wcコマンドは、指定したファイルの行数・単語数・バイト数を表示してくれるコマンドです🌱
上記のとおり、fileA
は7行、6単語、43バイトであることがわかります✨
7行で6単語というのは、最後に空白行があるからです。ややこしくてすみません笑
なお、macのwcコマンドのソースコードはこちらです。
2.wcコマンド成果
複数のコマンドライン引数に対応しました🎉
オプションは-l
、-w
、-c
に対応しました。
標準入力にも対応👏
3.学んだこと
3-1. コマンドライン引数
lsコマンドでもコマンドライン引数は扱いましたが、なんとなくで出来てしまっていました💦
wcコマンドはそうはいかなかったので、以前よりは扱えるようになったと思います。
RubyにはARGV
という、コマンドライン引数を配列にしたものがあります。
例えば$ wc file1 file2
ならARGV = ["file1", "file2"]
となります。
3-2. 標準入力
Rubyには標準入力を扱うための変数があることがわかりました!
$stdin
でもSTDIN
でもどちらでも良いそうです。
配列のARGV
と違って変数
なので、それ自体が値を持っているのではないことや、標準入力が代入されるということが注意点でした。
3-3. マルチバイト文字の単語数
これが一番苦戦したのですが、マルチバイト文字を含むファイルを指定すると単語数がずれてしまうことがありました…😭
単語数というのは、wcコマンドにおいては空白文字で区切られた文字列の数と定義されています。
man wc
に書いてありました👀
A word is defined as a string of characters delimited by white space characters.
White space characters are the set of characters for which the iswspace(3) function returns true.
そしてこの空白文字の定義はiswspace関数が true であることなんです。
更に、iswspace関数が true を返す値というのは以下のとおりです。
- 空白' '
- 改頁 \f
- 改行 \n
- 復帰 \r
- 水平タブ \t
- 垂直タブ \v
ここまでは良いのですが、これらとマルチバイト文字が何の関係があるかというと、マルチバイト文字はバイト文字に変換すると、ノーブレークスペースというのが含まれていることがあるそうです😳
例えば「配列」の配
の字にノーブレークスペースが含まれます。
text = "配 列" text.bytes { |b| print "0x" + b.to_s(16) + " "} #=> 0xe9 0x85 0x8d 0x20 0xe5 0x88 0x97
配 列
という文字列に対して、空白で区切った文字列の数を単語数とすると、2単語ですよね🙂
でもこれオリジナルのwcコマンドだと3
が返ってくるんです…😖
配
をバイト文字にすると0xe9 0x85 0x8d
で、このうちの0x85
が iswspace 関数で true になってしまうからです。
このような目に見えないスペースをノーブレークスペースと言うそうです。
0x20
は普通の半角スペースで、改行は0xa0
になります。
ノーブレークスペースをカウントするために、マルチバイト文字をバイト文字列に変換し、ノーブレークスペースの数だけ単語数を増やすことになりました。
バイト文字列というのがよくわかっていなかったのですが、先頭の0x
は共通みたいです😶
bytes
メソッドで文字列をバイトの数値に変換できるので、それを更に16進数に変換し、0x
に続けます。
UTF-8 とかの文字コード?もぼんやりとしか分かっていないので、難しかったです〜〜💀💀💀
分かりやすいサイトとかあったら教えてほしいです…。
Rubyの配列コピーの種類
Rubyの配列コピーについて試したので記録です🙌
目次
1. 配列のコピーの種類
配列をコピーすると同じ要素を参照するのか?他方の要素の変更の影響を受けるのか?というのが曖昧だったので、動作を試してみました!
オブジェクトIDはそのままだと桁が大きく読みづらいので、10000で割った余りの数で比較しています。
結果的には以下のような違いがあるみたいでした⛱
コピーの種類 | 配列のID | 要素のID | 要素の変更の影響 |
---|---|---|---|
浅いコピー | 異なる | 同じ | 受けない |
深いコピー | 異なる | 異なる | 受けない |
代入 ( a = b ) | 同じ | 同じ | 受ける |
2.浅いコピー
2-1. コード
org = ["あいうえお", "abcde", "12345"] puts "org = #{org} (元の配列)" puts "配列 org ID:#{org.object_id % 10000}" puts "要素 org[0] ID:#{org[0].object_id % 10000}" # shallow copy shal = org.dup puts "shal = #{shal} (浅いコピー)" puts "配列 shal ID:#{shal.object_id % 10000}" puts "要素 shal[0] ID:#{shal[0].object_id % 10000}" org[0] = "アイウエオ" puts "org[0]の値を \"#{org[0]}\" に変更" shal[1] = "ABCDE" puts "shal[1]の値を \"#{shal[1]}\" に変更" puts "org = #{org}" puts "shal = #{shal}" puts "配列 org ID:#{org.object_id % 10000}" puts "配列 shal ID:#{shal.object_id % 10000}" puts "要素 org[0] ID:#{org[0].object_id % 10000}" puts "要素 shal[0] ID:#{shal[0].object_id % 10000}" puts "要素 org[1] ID:#{org[1].object_id % 10000}" puts "要素 shal[1] ID:#{shal[1].object_id % 10000}" puts "要素 org[2] ID:#{org[2].object_id % 10000}" puts "要素 shal[2] ID:#{shal[2].object_id % 10000}"
2-2. 結果
3.深いコピー
3-1. コード
org = ["あいうえお", "abcde", "12345"] puts "org = #{org} (元の配列)" # deep copy deep = Marshal.load(Marshal.dump(org)) puts "deep = #{deep} (深いコピー)" puts "配列 org ID:#{org.object_id % 10000}" puts "配列 deep ID:#{deep.object_id % 10000}" puts "要素 org[0] ID:#{org[0].object_id % 10000}" puts "要素 deep[0] ID:#{deep[0].object_id % 10000}" puts "要素 org[1] ID:#{org[1].object_id % 10000}" puts "要素 deep[1] ID:#{deep[1].object_id % 10000}" puts "要素 org[2] ID:#{org[2].object_id % 10000}" puts "要素 deep[2] ID:#{deep[2].object_id % 10000}"
3-2. 結果
4.代入
4-1. コード
org = ["あいうえお", "abcde", "12345"] puts "org = #{org} (元の配列)" # substitution sub = org puts "sub = #{sub} (代入)" puts "配列 org ID:#{org.object_id % 10000}" puts "配列 sub ID:#{sub.object_id % 10000}" org[0] = "アイウエオ" puts "org[0]の値を \"#{org[0]}\" に変更" sub[1] = "ABCDE" puts "sub[1]の値を \"#{sub[1]}\" に変更" puts "org = #{org}" puts "sub = #{sub}" puts "配列 org ID:#{org.object_id % 10000}" puts "配列 sub ID:#{sub.object_id % 10000}" puts "要素 org[0] ID:#{org[0].object_id % 10000}" puts "要素 sub[0] ID:#{sub[0].object_id % 10000}" puts "要素 org[1] ID:#{org[1].object_id % 10000}" puts "要素 sub[1] ID:#{sub[1].object_id % 10000}" puts "要素 org[2] ID:#{org[2].object_id % 10000}" puts "要素 sub[2] ID:#{sub[2].object_id % 10000}"
4-2. 結果
Rubyでlsコマンド作成
久しぶりの投稿ですが、勉強してなかったわけではありません!!笑
Rubyでlsコマンドを作っていました。
ようやくできたので、学んだことなど記録します〜😊
目次
1.経緯
フィヨルドブートキャンプの課題で、 ls コマンドを作ることになりました。
ls コマンドは、ターミナルで使えるLinuxのコマンドのひとつで、今いるディレクトリに入っているファイルを一覧で表示するコマンドです💡
ちなみに他の方も課題で作るため、作成したコードは公開できません💦
2.成果
オプションなしのls
に加え、-a
、-r
、-l
オプションに対応しました💡
macのlsコマンドと比較して、以下のとおり同じ出力になりました🎉🎉
ls (オプションなし)
ls -a
ls -r
ls -l
ls -arl (オプション同時実行)
3.新しく学んだこと
これを作るのに学んだことは沢山ありますが、主なものを紹介します!
3-1. オプションのつけかた
optparse
というものを使いました。
参考サイト多すぎて紹介しきれないのですが、正直言って未経験者にとって本気で参考になったサイトってひとつも無かったような…😭
いろんなサイトの情報をかいつまんで自分なりに解釈して、どのサイトにも見かけなかった方法で作ってしまいました。使い方が合ってるのかわかりませんが、実行できたのでとりあえず結果オーライです💪笑
3-2. クラス定義、メソッド定義
今まではクラス定義やメソッド定義は概念として「こういうのがあるのかー」程度に知っていたのですが、実際にどういった場面で使うのか全然分かりませんでした!
最初はクラスもメソッドも定義せずにベタ打ちで書き始めて、複雑になってきた頃にようやくメソッドを定義しました。
実際のところ、クラスを定義する過程って「こういうオブジェクトを作りたい」→「クラス定義する(クラスメソッドも定義する)」→「クラスからオブジェクトを作る」という感じでした。分かりづらい…??🤨
クラスを定義しないとmainクラスのオブジェクトになってしまうので、不都合が出てきてしまいます。
このあたりもうちょっと学習してちゃんと説明できるようになりたいです!!
3-3. リファレンスマニュアル
gem を使っていないので、配列を作ったりファイルの情報を取得したりという細かいことは、ほとんどリファレンスマニュアルを見ながらできました🎉
3-4. その他
わからないところを時間掛けて調べて試して、95%くらい自力で考えて作ってみたので、だいぶ進歩したな!と感じています✨
他の方にいただいたアドバイスは「クラスを作って最後にオブジェクトを呼び出せばいける」ということと「mapメソッドが便利」ということだけでしたが、これが無ければかなり厳しかったですー!
アドバイスありがとうございました!
いきなり完成形を目指すのは難しいので、まず手始めに簡単なところから作っていったり、部分的に別ファイルに作って動作検証したりしたのが良かったです。
構造がイメージできればそんな手間かける必要ないのですが…😖
次はwc
コマンドの作成にかかります!🙌
Git-it
今回はGithubのお勉強ということで、Git-itをやってみます!
目次
- 1.Git-itインストール
- 2.Git-it開始
- 2-1. Gitをインストールして設定をする
- 2-2. ローカルのrepositoryを作成
- 2-3. ステータスを確認して、コンテンツを追加してcommitをする
- 2-4. GitHubのアカウントを作成
- 2-5. ローカルのrepositoryをGitHub.comのrepositoryに接続
- 2-6. オープンソースのrepositoryをforkしてcloneする
- 2-7. 新機能・修正のためにbranchを作成
- 2-8. Collaboratorを追加して作業を同期する
- 2-9. 修正をGitHub.comと同期するためにpushとpullを行う
- 2-10. Pull requestを作成
- 2-11. Branchをmergeしてdelete(削除)する
1.Git-itインストール
Git-itのアプリは以下のページからダウンロードできます。Macの方はGit-it-darwin-x64
です😊
インストールしたアプリを開くと、スタート画面が出てきます。
11ステップに分けて学べるみたいですね👀
言語は日本語に設定できます✨
2.Git-it開始
GET STARTED!
から開始します。
ちなみに私は既にGitのインストールとGithubのアカウント作成は済んでいるので、終わっているところは飛ばしながらやっていきます。
2-1. Gitをインストールして設定をする
既に終わっているので飛ばします〜!
参考記事:Git入門 part1 / Gitの基本
2-2. ローカルのrepositoryを作成
ローカルリポジトリを作成します。
hello-world
という名前のディレクトリを作成し、プロジェクトを初期化して新しいGitインスタンスを作成します。
このあたりも既に学習済みなのでさくさく進めていきます💪
2-3. ステータスを確認して、コンテンツを追加してcommitをする
作成したリポジトリの中にテキストファイルを作成します。
readme.txt
というファイルを作成し、Hello
とだけ書きます✋
status
コマンドでファイルに変更が加わっていることを確認したら、add
コマンドでコミットをライブラリに追加し、commit
コマンドでコミットします💡
更に、readme.txt
に2行目(World!
)を追加します。
diff
コマンドで最後にコミットした内容と現在の内容を照らし合わせ、差分を確認できます👀
差分を確認したら、先程と同様にコミットします✨
2-4. GitHubのアカウントを作成
Githubのアカウントは持っているのですが、以下のコマンドでGitにGithubのユーザー名を登録できるようなので、やってみます!
$ git config --global user.username ユーザー名
登録できました!
2-5. ローカルのrepositoryをGitHub.comのrepositoryに接続
Githubにログインして、新規リポジトリを作成します。
このとき、ローカルリポジトリのhello-world
と同じ名前を指定します💪💪
ローカルリポジトリ側の操作で、リモートリポジトリ(Github)に Push します。
リモートリポジトリにorigin
という名前をつけ、master
ブランチに Push です😇
参考記事:Git入門 part2 / リポジトリの共有, 変更履歴の統合
2-6. オープンソースのrepositoryをforkしてcloneする
今度はリポジトリのフォーク(fork)をやってみます!
フォークとは、対象のリポジトリのコピーをリモートリポジトリ(Github)のひとつとして使うようにすることです。
この時点ではGithub上でリポジトリの複製をしているだけで、ローカルリポジトリには対象のリポジトリはありません🙁
ここでは、以下のリポジトリをフォークします!
右上のFork
ボタンを押します👆
読み込みのアニメーションが現れたあと、フォーク完了です🎉
次に、フォークしたリポジトリをローカルリポジトリにクローンします。
このとき、ローカルリポジトリ(hello-world
ディレクトリ)にいる場合は外に出ます👣
以下のコマンドでリポジトリをクローンすることができます。
$ git clone GithubのURL
また、元々のリポジトリ(フォーク元)に変更が加わった場合に簡単に Pull できるように、元々のリポジトリに名前をつけておきます。
名前はなんでも良いのですが、upstream
という名前をつけることが多いみたいです🙂
2-7. 新機能・修正のためにbranchを作成
ブランチについては学習済みのため、割愛します〜!
参考記事:Git入門 part3 / ブランチ
GitHubの機能として、gh-pages
という名前のブランチにあるファイルを、自動的に静的なWebサイトとしてホストしてくれるそうです。
今回フォークしたプロジェクトはWebサイトを作るためのものなので、メインブランチの名前はmaster
ではなくgh-pages
です😶
また、このようなサイトのURLは以下のようになっています。
http://githubusername.github.io/repositoryname
早速ブランチを作成しますが、その前に今どこのブランチにいるのかをstatus
コマンドで確認しておきます。
gh-pages
という名前のブランチにいることが分かりましたね!!Webサイトを作るためのメインブランチです。
新しくadd-mistyrinth
という名前のブランチを作成し、チェックアウトします。
クローンしたpatchwork
内にある既存のcontributors
という名前のディレクトリ内に、新しくadd-mistyrinth.txt
というファイルを作成します。
中身はmistyrinth
というユーザー名のみ記入しました🙃
このテキストファイルをadd
とcommit
コマンドによりコミットします。
最後にこの変更をGitHub上の自分のリポジトリにPushします!
一連の流れは以下のとおりです☀️
2-8. Collaboratorを追加して作業を同期する
GitHub上で、他の人のリポジトリにアクセスして編集する権限を持つ人をコラボレーター(Collaborators)と言います。
コラボレーターはSetting
タブから簡単に追加できます😊
追加したら相手に通知がいき、承認されればコラボレーターになっていただけます!
2-9. 修正をGitHub.comと同期するためにpushとpullを行う
同じプロジェクトで他の人もファイルに修正を加えている場合などに、ファイルを pull することで、最新の状態を取り込むことができます⛱
参考記事:Git入門 part2 / リポジトリの共有, 変更履歴の統合
何も変更がされていなければ、Already up to date.
と表示されます✨
2-10. Pull requestを作成
フォークしたリポジトリに変更や修正を加えたら、変更元のリポジトリの所有者に対して、自分が行った変更や修正を元のリポジトリにも反映してもらえるよう、プルリクエストを送ることができます。
参考記事:Git入門 part5 / Pull Request
元のリポジトリにプルリクエストを送ります!
変更箇所は以下のとおりでしたね〜🙃
相手がチェックして問題が無ければプルリクエストがマージされます💡
2-11. Branchをmergeしてdelete(削除)する
プルリクエストがマージされたら、作業用のブランチは不要になりますね。
整理のため、変更を自分のフォークバージョンにもアップデートします。
まず、自分のローカルリポジトリのメインブランチgh-pages
にマージします🙌
その後不要になったブランチadd-mistyrinth
は削除し、リモートリポジトリに push します😊
これにより、Github上のadd-mistyrinth
ブランチも削除され、ブランチはメインブランチの1本だけになります🎉
また、フォーク元のリポジトリ(upstream
)の変更を Pull すると、最新にアップデートされてます。
他のユーザーさんたちもGit-itやってますね笑
Git-itは以上です〜!🧚♀️
Git入門 part5 / Pull Request
本日はサルでもわかるGit入門 プルリクエスト編です!
目次
1.プルリクエスト
本日学習するプルリクエストとは、Githubなどで利用できる機能で、ローカルリポジトリでの変更を他の開発者に通知する機能です💡
チームで開発をする時に、作業内容をレビュー担当者・マージ担当者などの関係者に通知し、確認してもらうといった使い方ができます😊
自分で作った成果品を、客先に納品する前に上司に確認してもらうようなイメージですね。
プルリクエストの利用により、最終的にマージされるソースコードの品質を高くすることができます。
プルリクエストは一覧で表示され、未完了のプルリクエストを漏れなく確認できます。
プルリクエスト上では、担当者同士でコメントのやりとりをして議論できます。更に、対象のブランチにプッシュされたコミットは、自動的にプルリクエスト上に反映されます。
プロセス | 開発者 | レビュー・マージ担当者 |
---|---|---|
1 | 作業対象のソースを clone または pull | |
2 | 作業用ブランチを作成 | |
3 | 開発作業(機能追加や改修) | |
4 | push | |
5 | プルリクエストを作成 | |
6 | プルリクエストから変更を確認しレビュー | |
7-1 | 修正が必要なら開発者にフィードバック (プロセス3へ戻る) |
|
7-2 | 修正が不要ならマージ | |
7-3 | プルリクエスト自体が不要ならクローズ |
2.チュートリアル
早速チュートリアルに入ります🙂
JavaScriptで配列だけが準備されている状態のソースコードに、リストの内容をソートする処理を追加するという内容です。
BacklogとGitHubが選択できるので、Githubでやってみます!
2-1. サンプルリポジトリの準備
まずはGithubにログインし、新規リポジトリを作成します。
作成したリポジトリの中に、以下のようなjsファイルを作成します。
2-2. 開発ブランチでの修正
次に、作業するためのブランチを作成します💪
add-sort-func
というブランチを作成し、切り替えます。
ブランチを切り替えたら、先程作成したjsファイルを修正します🖋
コメントを追加してコミットします。
2-3. プルリクエストの作成
リポジトリのトップに戻ると、直近 Push されたブランチが表示されるので、Compare & pull request
を実行します💡
実行すると、次のような画面が表示されます。スクロールして画像2枚に分かれています🙂
上のほうにbase: master
←compare: add-sort-func
と書かれていますね😶
これは、base
がプルリクエストをマージする対象のブランチ、compare
がプルリクエストをマージしてもらうブランチを指しています。
更に2枚目のキャプチャは、base
に対してcompare
を比較し、10行追加されていることが分かりますね✨
次はCreate pull request
ボタンを押します。
これで他の担当者にレビューしてもらうことができるようになりました!🎉
2-4. レビューとマージ
プルリクエストが作成されたら、今度はレビュー担当者がFiles changed
タブから変更内容を確認します。
修正してほしい箇所があった場合、該当行の左端にある+
からコメントを追加することができます😳便利〜!
自作自演になってしまいますが、修正指示がきたので修正し、再度コミットを行います。
2-5. 画面上でマージ
レビュー担当者は、再度レビューした結果、問題が無ければマージします👌
Merge pull request
を押すと、以下のようにコメントを書くことができます。
コメントは「修正ありがとうございました」などなんでもOKです😊
コメントを書いてConfirm merge
を押すと、マージされます😆✨
3.マージできない場合は?
3-1. 競合の発生
練習のため、別の開発者との競合が発生して、マージできない状況を作ってみます🙁
開発者Aが先程の等価演算子==
を使用し、開発者Bが厳密等価演算子===
を使うとします。
条件は先程と同じなので、再度新規リポジトリを作成してmaster
ブランチにjsファイルを作成します🖋
開発者Aが作業するためのadd-sort-func1
というブランチと、開発者Bが作業するためのadd-sort-func2
というブランチを作成します。
add-sort-func1
には、等価演算子==
を使ってコードを書き足します。
先程のチュートリアルと同様に、Compare & pull request
からプルリクエストを作成し、修正が無いものとしてマージします!
続いて、ブランチをadd-sort-func2
に切り替えて、厳密等価演算子===
を使ってコードを書き足します。
今度はPull requests
メニューからNew pull request
ボタンを押して、プルリクエストを作成します。
base: master
のままcompare: add-sort-func2
を選択すると、自動マージができないと言われました🤨
競合が発生しているからですね〜!
そのままConfirm pull request
を行い、プルリクエストの作成を実行すると、コンフリクトがあると言われます。
Insights
のNetwork
から、ブランチの様子を見ることができます。
3-2. 競合の解決
この競合を解決するには、Resolve conflicts
ボタンを押します🙂すると競合箇所が表示されます!!
今回の場合は厳密等価演算子===
を使用するように競合を解決して、Commit merge
ボタンを押します。
あとは通常通りにマージしていき、完了です👏✨
以上です〜!