Torihaji's Growth Diary

Little by little, no hurry.

初心者が達人に学ぶDB設計を読んだら達人になれるのか

はじめに

みなさんこんにちは. torihaziです。

今回はこちらの書籍を読んだので、そのアウトプット会になります。

達人に学ぶDB設計 徹底指南書 | ミック | 工学 | Kindleストア | Amazon

前回に引き続き、このデータベース周りは理解が大変でした。

本当に疲れました......

それではl .. t.. g....

よかったこと

稼働させるDBサーバのハードウェアに関する説明があった

どういうことかというと、物理設計に関する記述があったということです。

物理設計とはDBMSを稼働させる実際のハードウェアのサイズ(容量)を決める設計フェーズのことです。

前に読了したSQLドリルには今回のようなハードウェアに関する記述はそこまでなかったのに対し、

本書籍は 1章の1節を丸ごと物理設計の説明に充てられています。

もちろん、実際に扱った経験がないので「そうなんだ」程度の知識でしかありませんが

全く知らない人と比べたらあるほうだと思います。

初めて使うようになった時に「そういえばこういうものあったよな」という引き出しができるので

全く勉強していない人に比べたら有利だと思います。

DB設計のアンチパターンが掲載されている

アンチパターンとは文字通り「やらないほうがいい設計、手法」のことです。

著者がこれまで遭遇してきたものから様々なパターンが取り上げられています。

実務でDB設計を行っている人間による説明なので、詳細に説明がされています。

ただこちらも私は実務で扱ったことがないので、

本当に使えるようになっているかは不安です。

しかし、「聞いたことはある」状態ではあるので他の初心者に比べたら

多少有利であるはずです。

読んでいて一番ありそうだなと思ったのが、「サイクリックな一意キー」ですね。

昨今の人口減少に起因する市町村合併によって日本各地で起きているはずです。

悪かったこと

今回に関してはありませんでした。

ともかく私のレベルがまだまだ書籍に追いついていないなと思いました。

アンチパターンについては

将来自分がやってしまった時に見返すと思います。

DB設計について悩むようなことがあったら繰り返し読み返して

吸収していきたいと思います。

学んだこと

バックアップの種類

バックアップには3つの種類があります。

フルバックアップ、差分バックアップ増分バックアップ

それぞれに使用する場面や用途に違いがあります。

フルバックアップは字の如く、全体のバックアップを取得します。

現時点におけるDBMSを丸々複製して保存するようなイメージです。

スナップショットともいいます。

長所としてはスナップショットを取ることができることです。

短所としては、以下があります。

  • バックアップにかかる時間が長い。
  • ハードウェアにかかる負荷が大きい
  • システムを停止させる必要があること

これだけ長所短所の量に差があるといい所ないのではと思いますが、

フルバックアップ単体で使うことはあまりないそうです。

後述する増分、差分バックアップと併用する形です。

増分バックアップは「増えた分だけバックアップ」で

バックアップ量は一番少なく済むけど、元に戻すのが大変で

差分バックアップは「前フルバックアップからの差分をバックアップ」で

バックアップ量は増分より多いが、元に戻すのは増分に比べたら楽

というものになります。

イメージは下記です。

これが差分バックアップ

これが増分バックアップ

これを見れば違いは一目瞭然ですね。

増分は少なそうだけど、それぞれ繋げて復元することが大変そうだし、

差分は増分に比べたら多いけど、1回で済みそうです。

一般的にバックアップの方式は

となります。要件によって使い分けることが大事、だそうです。

関連実体

難しい日本語です。

この用語はエンティティ間に多対多の関連があるときに使用されるものです。

中間テーブル、Junction テーブルなどとも呼ばれます。

学生テーブルと講義テーブルを次のように定義します

学生コード 学生名
0001 a
0002 b
0003 c
講義コード 講義名
001 線形代数
002 力学
003 流体力学

ここで学生の講義登録状況を表してみると

学生コード 学生名 講義コード (FK)
0001 a 001
0001 a 002
0001 a 003
0002 b 002
0003 c 001

となり一見良さそうですが、これでは講義を登録しない学生はこのテーブルに登録できません。

この問題を解決するために人口的に次のテーブルを作成します。

学生コード 講義コード
0001 001
0001 001
0001 002
0002 002

こうすれば講義が未登録な学生も学生テーブルに登録することができます。

難しかったこと

第二正規系にするにあたって、一方の主キーに部分関数従属しているカラムの見極め方に

苦戦していましたが、この記事を書いている間に理解しました。

そもそも主キーを誤解していたようです。

主キーとはそのカラムの値を指定すれば必ず1行を特定できるというもの。

おそらくこの理解で大丈夫なはずです。

つまづいたらまた戻ってくることにします。

終わりに

いかがだったでしょうか。

このHappinessChainをやってきて

一番しんどかったと思います。

どこまで理解したらゴールと言えるのだろうか

とくに正規形の箇所は正直不安です。

関数従属は理解しましたが、エンティティの定義、抽出ができるかどうか。

とりあえず何度もやって身につけていきたいと思います。

皆さんも頑張ってください。

僕も頑張ります。

初心者である私が書籍"スッキリわかるSQL"にゴリ押された件

はじめに

みなさんこんにちは、torihaziです

今日はタイトルの本を読んでみたので、そのアウトプット回です

個人的には 最後の概念設計あたりが山場でしたね。

それではltg

スッキリわかるSQL入門 第3版 ドリル256問付き! (スッキリわかる入門シリーズ) | 中山 清喬, 飯田 理恵子, 株式会社フレアリンク |本 | 通販 | Amazon

どんな本だったか 1言で!!

圧倒的物量で知識定着をゴリ押される書籍

よかったこと

問題量が豊富

書籍タイトルにもありますが、巻末に256問の問題があります。

簡単なSELECT から 副問い合わせ、複数テーブル間の結合問題まで嫌になるくらいあります。

ちなみに僕は心が折れかけました。( ´ ▽ ` )

ただ やり切れば自信はつくと思います。

事実、取り組む前は CASE WHEN~COALESCEなどはおろか書き方もまともに知らない状態でしたが、

何度も出てくるのでもう使い方は覚えることができました。

あとは INSERT INTOUPDATEのあとは SET か VALUESなのかとかそう言うものもですね。

これだけやれば、身につくというかこびりついて離れなくなります。

私はこのような学習本は"知識のつらつら述べるだけでなく演習量があるか"どうかも重要であると考えています。

そのためこの点については本書籍はとてもよかったと思います。

手を動かして試せるdokoQLがあること

dokoQLは本書籍の発行会社が提供しているオンラインのSQL学習用webサービスのことです。

書籍で扱っているテーブルが実際に同サービス上で用意されており、それに対してSQLも実行することができます。

そのため、自分で考えたSQLを実行して学習を進めることができます。

悪かったこと

問題の解答に少し誤植がある

問題演習をやっている間に気づいたのですが、解答に誤植がありました。

経験者ならわかるかもしれませんが、初心者にとっては

こう言う書き方もあるのね。参考になります。

となってしまいます。そこから調べることで更なる学力向上となりますが

うーんと思ってしまいました。

dokoQLにSQL実行上限があること

dokoQLには巻末の問題に対応するテーブルも用意されているので、

それらに対してもSQLを実行可能です。

ただSQL実行上限が100回です。

もちろんリセットは可能なのですが、指定した回までリセットというものではなく全リセットです。

初期テーブルからINSERTUPDATEのような更新処理をしながら作り上げていくので

途中で上限に達してしまった時は台パンしたくなりました。

特にINSERTが20個ほどあった最終問題の時は応えました。

学んだこと

意外と数があったSQLの関数たち

私は去年、他スクールさんでSQLについてはみたことがあったので完全初見ではありませんでした。

しかし文中で何度も触れていますが、CASE WHENなどは知りませんでした。

CASE WHENについては書き方が2通りあり、使い分けは下記になります。

  • CASE カラム名 WHEN 条件式 THEN 値 ->条件が 同値比較(a=b)のもの
  • CASE WHEN 条件式 THEN 値 ->条件が数値比較 (a>=bなど)のもの

また非NULL時の値を表現する際に使用するCOALESCEは面食らいました。

COALESCEはCOALESCE(カラムa,'カラムaがnullだったときに表示する値')の形で使用します。

これから機会があれば積極的に使っていきたいと思います。

エイリアスのas は省略可能

テーブル間の結合において出てくるテーブル名のエイリアス(tableA as hoge)が省略可能であったことです.

dokoQLは1回あたりのSQL文の文字列上限が200文字であったのでよく使いました。

これについては解答をみて知りましたが、誤植かと思いました。

難しかったこと

概念設計におけるエンティティの抽出方法について

冒頭においても触れていますが、エンティティの抽出方法が難しかったと思います。

今もあまり理解できているとは思えません。

現実世界の物体、事象をどのようにSQLで扱えるようにデータ化するかを設計するフェーズだと思いますが、うーんという状況です。

この後に読むことになっているDB設計の書籍で理解できたらいいなと思っています。

巻末問題の問題文の日本語

SQL以前の問題です。

1問あたりの文章が長く、条件の抽出に苦労しました。

私は1度に全てSQLを作り切ろうとしてしまうので

段階を踏んで、1条件ずつクリアするやり方をしていったほうが良いと感じました。

終わりに

いかがだったでしょうか。

初心者である方にとっては良書であると思います。

書籍自体は分厚く心が萎えてしまう方も多いと思うので

電子書籍を試してみるのもありかと思います。

1つずつクリアしていったら見える景色は必ずいいものになります。

さーっと読み進めるだけでわかったつもりになるのは危険です!

絶対に一番起きてほしくないときにそのつけが回ってきます。

手を動かして学習するすることをマストしてください!

萎えたら僕にDMください。松岡修造みたいに励ましてあげます。

何度も言いますが、辛いですけど強くなれます。

頑張ってください。

僕も頑張ります。

初心者がDocker で 使い捨て PostgreサーバとPostgreクライアントを作る

はじめに

みなさん、こんにちは torihaziです。

今回はタイトルのことをやっていきます。

現在学習しているもの(youtube)がPosgreSQLになるのですが、

ローカルに色々入れて。。。をやるというものでした。

そうなるとローカルが汚れるので、そんならDockerで全部作ったるということで今に至ります。

復習も兼ねていい勉強になるかと思います。

なおDocker初心者ですので、「そんな使い方するか、はげ」という方は見なかったことにしてください。

あと見切り発車中です。

それではltg

自身の環境について

  • Apple M2
  • Ventura 13.4
  • Docker version 24.0.7, build afdd53b

まず何がいるか

構成図はこんな感じです。

緑の方は Docker hubからpostgresql のimageをそのまま持ってくれば良さそうです。

青の方は postgre-client(psqlが使える)を入れた alipine? ubuntu? を作れば良さそうです。

そのため

  • docker-compose.yml どっちも使わずに一旦作れました。
  • Dockerfile (青用) どっちも使わずに一旦作れました。

を作ればいけそうですね。多分。

やってみる

方針としては

  1. docker network createでネットワーク作成
  2. docker run ~~で dbサーバのコンテナ起動
  3. docker run ~~でdbクライアントのコンテナ起動
  4. docker-compose.ymlでも作ってみる

です。

ネットワークの作成

以下の構成図を目指して作成します。(冒頭に示した図は誤りです)

コンテナ間の通信はbridgeを通じて行うということを理解できていませんでした。

1. 現時点におけるネットワークを調べる

docker network lsで現時点におけるネットワークを調べます。

特に何もしていない場合は次の3つが表示されるはずです。

# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
55d109cc26dc   bridge    bridge    local
90e6df847268   host      host      local
7b13fcb3161b   none      null      local

2. psql-testの作成

docker network create [作成するネットワーク名]でネットワークを作成します。

その後docker network lsで作成されているか確認します。

# docker network create psql-test
wh394twjseiorgu90jthi4oetgioer(英数字の羅列)
# docker network ls
NETWORK ID     NAME        DRIVER    SCOPE
55d109cc26dc   bridge      bridge    local
90e6df847268   host        host      local
7b13fcb3161b   none        null      local
e39c513a77c7   psql-test   bridge    local <= 追加されている

あとはこのpsql-testに作成したdockerコンテナを組み込む(アサイン)するだけです。

この時点で下記のようになっています。

DBサーバコンテナ作成

ここからは単純です。docker run ~~コマンドを叩くだけです。

まずは緑色のDBサーバ用のコンテナを立ち上げます。

長いです。

# docker run --name postgre-db -h postgre-db --network psql-test -e POSTGRES_PASSWORD=postgres -d postgres:16-alpine
3j4oigjewr09gjweirg049q5jgreog(数字の羅列)

1つずつ分解します。

  • docker run : Dockerコンテナを実行する
  • --name postgre-db : postgre-dbという名前のコンテナを作る
  • -h postgre-db : postgre-dbという名前をコンテナ内のホスト名として設定する
  • --network psql-test : 作成したコンテナをpsql-testというネットワークに組み込む
  • -e POSTGRES_PASSWORD=postgres : 環境変数として 設定
  • -d : デタッチモードで起動(バックグラウンドで起動) <- 入力できなくなるので設定する方が無難
  • postgres:16-alpine : Dockerhubから好きなイメージ名を指定(軽いということでalpineに)

作成できたか確認してみます。

# docker container ls
CONTAINER ID   IMAGE                COMMAND                   CREATED         STATUS         PORTS      NAMES
8ca1bea34e14   postgres:16-alpine   "docker-entrypoint.s…"   8 minutes ago   Up 7 minutes   5432/tcp   postgre-db

ネットワークにも組み込まれているか確認します。

# docker network inspect psql-test
[
    {
        "Name": "psql-test",
        "Id": "e39c513a77c7d3793aeade008d1bbfef5333e10021c7e5a0025b194f58181ff1",
        "Created": "2024-02-17T01:37:42.311064131Z",
        "Scope": "local",
        "Driver": "bridge",
  ・・・・・・・・・・
        "Containers": { <= このネットワークに組み込まれているコンテナちゃんたち一覧
            "8ca1bea34e142d28a102251f04403075dfa421193ddbd297e1a0328aa1988f6b": {
                "Name": "postgre-db", <= 組み込まれちゃってるコンテナ
                "EndpointID": "bd142fd32f9999c88f4667f8114d410bc0f54e3af74868183bd4e30dce5effab",
                "MacAddress": "02:42:ac:15:00:02",
                "IPv4Address": "172.21.0.2/16",
                "IPv6Address": ""
            }
        },
 ・・・・・・・

OKですね。これで次の状態になりました。

DBクライアントコンテナ作成

やることはDBサーバの時とほぼ同じです。

方法1 1発でpostgreサーバに入る

## 1発で postgreのプロンプトになります。
#  docker container run --rm --name=postgre-client --network psql-test -it postgres:16-alpine psql -h postgre-db -U postgres -p 5432 postgres
Password for user postgres:  <= パスワードを入力(自分のものに従うなら "postgres")
psql (16.2)
Type "help" for help.

postgres=# 

方法2 bashを挟んでそこからpsqlコマンドでpostgreサーバに入る(今回こっち)

## 一旦bashを立ち上げてからpsqlで入ります。
#  docker container run --rm --name=postgre-client --network psql-test -it postgres:16-alpine bash

どちらかを実行することで次の結果になります。

今回はbashを挟んで行います。

理由は次のことを試したかったからです。

  • psql コマンド本当にあるのか
4819d14d4750:/# which psql
/usr/local/bin/psql
  • DBサーバのホストpingが通るのか
4819d14d4750:/# ping -c 3 postgre-db
PING postgre-db (172.21.0.2): 56 data bytes
64 bytes from 172.21.0.2: seq=0 ttl=64 time=0.148 ms
64 bytes from 172.21.0.2: seq=1 ttl=64 time=0.257 ms
64 bytes from 172.21.0.2: seq=2 ttl=64 time=0.335 ms

--- postgre-db ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.148/0.246/0.335 ms
  • /etc/hostsにdbサーバの情報はあるのか
4819d14d4750:/# cat /etc/hosts
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.21.0.3      4819d14d4750

ないですね。postgre-dbの情報はどこに載っているのでしょうか。

勝手にdockerのDNSで名前解決されることは理解していますが、どこに載っているのでしょうか。

わかる人いたら教えてください。

とりあえず無事繋がるのでよしとします。

最後にpsqlコマンド(クライアントからサーバに繋ぐためのコマンド)で接続します。

4819d14d4750:/# psql -h postgre-db -U postgres
Password for user postgres:  <= ここも変えてなければ postgres
psql (16.2)
Type "help" for help.

postgres=# 

無事接続できましたね。

ちなみにクライアント側でexitで抜けると --rmを設定しているので

出たらコンテナも削除されるはずです。

起動しているときに他ターミナルで確認します。

# docker container ls -a
CONTAINER ID   IMAGE                COMMAND                   CREATED         STATUS         PORTS      NAMES
1088051238b6   postgres:16-alpine   "docker-entrypoint.s…"   5 seconds ago   Up 5 seconds   5432/tcp   postgre-client
001fdbdbc239   postgres:16-alpine   "docker-entrypoint.s…"   5 minutes ago   Up 4 minutes   5432/tcp   postgre-db

上のやつですね。

クライアントから抜けます。

1088051238b6:/# exit
exit

# docker container ls -a
CONTAINER ID   IMAGE                COMMAND                   CREATED         STATUS         PORTS      NAMES
001fdbdbc239   postgres:16-alpine   "docker-entrypoint.s…"   5 minutes ago   Up 5 minutes   5432/tcp   postgre-db

きちんと使い捨てのものができました!

見切り発車終点です。。。

docker-compose.yml

ごめんなさい。事切れました。次回作で作ります。

終わりに

いかがだったでしょうか。

コンテナのデータ永続化とかそういうものまではできていませんが

一旦これで十分だと思います。

ymlファイルについては盛大にサボりましたが、一旦これにて終了です。

コンテナのデータ永続化についてもymlのものとまとめてやります。

疲れました。

しかしネットワークについては理解が深まりました。

やっぱりテキストのものをやるだけではなく、自分でこうするにはどうしたら。。。

という流れでテキスト見直してあーだこーだしたほうが習得が早いです。

さてこれからインプット動画視聴です。

みなさんも勉強頑張ってください。

僕も頑張ります。

今回の課題を通じて感じたこと ruby編

はじめに

みなさん、こんにちは torihaziです。

今日は何かのtipsというわけではなく振り返り回になります。

数回のコードレビューを通じて感じた自身の課題や習得したことを

つらつら書いていこうと思います。

それではltg

レビューを受けて

同じことを何度も書いている

こういうことをDRYともいうらしいですね。

Don't Repeat Yourself.

同じものを何度も書くな、という考え方です。

私はコードが書けたら嬉しさのあまりそのままPR投げてしまうので

終了したら少し時間をおいて見直してみることが大事だと感じました。

elseを書きがち

現職でシェルスクリプトを書いているためか、

去年を通じて学んだPHPでそう書くことが多かったためか

ことあるごとに if ~~ else ~~ endとelseを書いてしまいがちでした。

しかし、rubyでは raise ~~ unless ~~と書くことが可能です。

rubyに限らず、if のネストは最小限にして早期リターンすることを肝に銘じておこうと思いました。

if 条件式
   trueの処理
else
   raise 'falseです'
end
raise 'falseです' unless  条件式

trueの処理

1つの処理にまとめがちで何をする処理なのかわかりにくい

これはrubocopに怒られたことになります。

def ~ endの間の行数があまりに多いとダメなようです。

例えば 何かを買う処理を書こうとした時、私は次のようにして書いていました。

# arrayには買いたいものが入っている配列です。
def buy(name, num)
    if array.include?(name) && num >= 1
       arrayから1つ値を削除する
       所持金が 買いたいものの値段分減った
       売上が値段分増えた
   else
      raise '買えなかったよ'
   end
end

この時最初のifで買えるかの判定をしていますが、ぱっと見何をしているかわかりません。

そのため新しくbuy?メソッドを作りその後unlessを使用して次のように書き換えました。

これが正解かどうかはわかりませんが、わかりやすくなったと思います。

def buy?(name, num) <= true or falseを返す関数
   array.include?(name) && num >= 1
end

def buy (name, num)
    raise '買えなかったよ' unless buy?(name, num)

    arrayから1つ値を削除する
    所持金が 買いたいものの値段分減った
    売上が値段分増えた
end

今後は

  • 行数をなるべく少なく
  • 他人が見てもわかりやすく
  • 1つの大きなものを作らず
  • 複数の小さなものを組み合わせて

コーディングを進めていくことが必要だと感じました。

習得したこと

配列やハッシュを扱う課題であったため、少し前に比べたらレベルが上がったと思います。

ジムバッジ1つか2つはもらえたのではないでしょうか。

Array#each

配列の各要素を1つずつ取り出し、ブロック内の処理を評価することができるメソッドです。

評価した後は配列を返しません。ただ処理をするだけです。

[1, 2, 3].each do |i|
  puts i
end
#=> 1
#   2
#   3

Array#map

配列の各要素を1つずつ取り出し、ブロック内の処理を実行します。

そしてそのそれぞれの処理結果を要素とする新しい配列を返します。ここがeachと違うポイントです。

そのためここからさらに Array#firstやArrayselectを使用することもできます。

new_array = [1, 2, 3].map {|n| n * 3 }  
p new_array 
# => [3, 6, 9]

Array#select

配列の各要素を1つずつ取り出し、ブロック内の処理を実行します。

この時ブロック内の処理は 条件式を記載します。

selectはこの条件式がtrueとなった要素のみを各要素とする新しい配列を返します。

even_array = [1,2,3,4,5].select { |num| num.even? } 
p even_array
 # => [2, 4]

Array#uniq

与えた配列の中から重複している要素を削除し、その削除後の結果を新しい配列としてを返します。

duplicated_array = [1, 3, 2, 2, 3].uniq 
p duplicated_array
# => [1, 3, 2]

Array#delete_if

配列の各要素を1つずつ取り出し、ブロック内の処理を実行します。

この時、ブロック内の処理は条件式を記載します。

delete_ifはこの条件式がtrueとなった要素のみ削除し、残った要素から構成される新しい配列を返します。

a = [0, 1, 2, 3, 4, 5].delete_if{|x| x % 2 == 0}
p a 
#=> [1, 3, 5]

Array#any?

配列の各要素を1つずつ取り出し、ブロック内の処理を実行します。

この時、ブロック内の処理は条件式を記載します。

any?は条件式が要素全てでfalseとなった場合、falseを返します。

一方で途中でtrueが出た場合はそこでtrueを返し、処理を終了します。

p [1, 2, 3].any? {|v| v > 3 }   # => false

Array#first

今回は first(n)を使用しました。

firstは作用する配列の最初の要素(indexが0)を返します。

first(n)とすると最初からn個分取り出して、取得結果から構成される配列を返します。

ary =  [0, 1, 2]
p ary.first(0)
p ary.first(1)
p ary.first(2)

# => []
#    [0]
#    [0, 1]

Array#size

配列の要素数を返します。

p [1, nil, 3, nil].size    
#=> 4

Object#eql?

作用させるオブジェクトの値と判別すべき値を同値であるか判断し、ture かfalseを返します。

p("foo".equal?("bar")) #=> false
p("foo".equal?("foo")) #=> false

p(4.equal?(4)) #=> true
p(4.equal?(4.0)) #=> false

Object#object_id

作用させたオブジェクトが持つ一意な整数を返します。 ただこちらについてはいつか痛い目を見るような気がします。 便利そうだと思って使っては見ましたが、どうなることやらです。

p "ruby".object_id #=> 60
p "ruby".object_id #=> 80

p [].object_id #=> 100
p [].object_id #=> 120

p :ruby.object_id #=> 710428
p :ruby.object_id #=> 710428

Numeric#positive?

作用させた値が正の数であるか判別し、trueかfalseで返します。

1.positive?    # => true
0.positive?    # => false
-1.positive?   # => false

Object#dup

作用させたオブジェクトの複製を返します。

これについてはあまり理解できていません。

同じインスタンスを作りたいが、別物として作りたかったので使用しました。

浅いコピーと深いコピーという概念があるようです。

いつか痛い目見ると思います。

その時はまた戻って来たいと思います。

array  = ["red","blue","yellow"]    

p array.object_id

d = array.dup
c = array.clone
p d.object_id
p c.object_id

# =>60
80
100

終わりに

初めて数回にわたるコードレビューというものをgithubを通じてしていただきました。

前スクールでは先生の方に恥ずかしくて見せることができず終わってしまったので

今回できてよかったと思います。

ただ動くだけではダメなようです。

難しいです。

ベタな表現ですが、最適化されたような気がします。

今後も受けっぱなしで終わりにせず、どこがダメでどこがよかったのか

毎度言語化してうやむやにしないようにしていきたいと思います。

その際、メソッドの説明(コードは一旦別)はマニュアルの丸パクリではなく

自分の言葉で説明することを絶対としていきます。

みなさんも頑張ってみてください。

僕も頑張ります。

HappinessChain Eufoliaへ入ったきっかけとそれまでの私について

はじめに

みなさん、こんにちは。 torihaziです。

現在、私はHappiness Chainというプログラミングスクールに通っています。

そして最近、そのスクールの中で さらに厳しいとされる Euforiaに入会しました。

今日は

  • なぜプログラミングを学ぼうと思ったのか
  • なぜスクールに通い出したのか
  • なぜHappiness Chain 、Eufoliaに入ったのか

そのあたりについてつらつら書いていこうと思います。

それでは ltg..

あなた誰ですか。

お前誰だという方に向けて自己紹介です。

わたくし、torihazi(トリハジ)という名前で

XなりQiitaなりをやっている インフラエンジニア25歳です。

IT未経験の状態からいろいろガチャガチャ勉強してここまできました。

頑張って勉強して、資格は LPIC lv2や AWS SAA などを持っています。

ちなみにスクールは社会人になって2個目です(ハシゴしてきました。)

なぜプログラミングを学びたいと思った?

それは 次の理由からです。

  1. 将来に対する漠然とした不安感
  2. 手に職をつけたかった
  3. 稼げると聞いた
  4. できたらかっこいいと思った

将来に対する漠然とした不安感

これは新卒で会社に入ってすぐに思いました。

この会社で稼げるのか、強くなれるのか、本当に大丈夫なのかと。

最初の1年ははこのままじゃまずいと思い、いろいろ勉強しました。

インフラ周りを触ることが多かったので、LPICAWSGCP など

片っ端から勉強しました。(もちろん最初はLinux?の状態からでした)

そして努力した結果、資格は取得できました。(LPIC lv2,AWS SAAなど)

それでも何か足りない。何か違う

そんな状況でした。なんやかんやそのまま勉強を続け、

その何かを具現化できないまま足掻いた結果が次の考えにつながります。

歌って踊れるようにならないと

「やっぱりエンジニアってコード書いて何か作る人でしょ」

「資格だけ取ってもダメじゃね?」

「インフラだけ頑張ってもねぇ」

という考えが私の中にありました。

「1年もインフラ触ってない人間が何たわけたことを」と思うかもしれませんが

プログラミングは偉大だという考えが私の中にはありました。

何より稼げるとよく聞くし、かっこいいし、手に職だし。

そのためプログラミングどうしてもやりたいという謎の執着がありました。

ただある程度インフラを勉強してインフラも知っておかないといけないことは理解していました。

そのような葛藤の末、

「プログラミングもできてインフラもできればいいじゃん」

という考えに至り、プログラミングを学ぶ決意をしました。

これが会社入って8ヶ月したくらいの時です。

なぜスクールに通ったの?

それは次の理由からです。

  1. 独学には限界があった。
  2. どうやればいいかわからなかった。
  3. エラーに詰まるとどうしようもなかった

ネットで調べるとよく出てくる理由3選そのまんまです。

自分だけはいけると思いましたが、ダメでした。

1つ目のスクール入会

某スクールに約100万を学費ローン組んで入会しました。

今後アツいプログラミング言語などは調べてもわからなかったので

エージェントさんのいう通りにPHPという言語を選択し、学習をしました。

学習の流れとしては

  • 週に1度、講師の方との講義
  • 講師の方が指定する資料をもとに自習
  • 必要に応じて質問

という形でした。

とてもいい先生だったと思います。

比較対象こそないので説得力はありませんが、

話しやすく、「授業だけで終わるような講義にはしません」と

いうことでとても安心したのを覚えています。

学習途中にエラーでつまづいて辞めたくなる時もありました。

しかし払っているお金の額も額だったしフォローもあったので

9ヶ月ほどの間学習を継続し、ポートフォリオ作成までやり抜くことができました。

そのポートフォリオがXに載っている例のアレです。

やり抜いた後の違和感

正直ポートフォリオまでやり抜いた後の私は天狗になっていました。

エージェントさんからも「優秀ですね」と言われたこともあり、自信に満ち溢れていました。

未経験の割にここまでできたらすごいのではないかと思っていました。

ただこんなんでいいのかと思っていたことも事実です。

それに現実はそこまで甘くはありませんでした。

転職先の企業様も自身の第1希望のところはありませんでした。

Xを見渡せば上には上がいたしその人とこれから勝負をするとなると

確実に勝負にならないなと思ってもいました。

せっかく1年くらい頑張ったのにダメだったかとかなり凹んだことを覚えています。

(ちなみにこの後胃潰瘍もどきになりました😃 )

HappinessChainとの出会い

現在通っているスクール Happiness ChainはX(旧Twitter)で見つけました。

いつものように学習の積み上げをしていたときに

ふと流れてきて「なんかすごそう」と思って想って覗いて見たことがきっかけです。

前スクールで学んで5,6ヶ月くらいの時だったと思います。

正直この時からこっちにすればよかったなと思ってはいました。

もっと早く見つけていればと。(まぁ無理だったと思うのでこれ以上は言いません)

それに100万途中で捨てて切り替えるわけには行かないと思ってもいました。

ポートフォリオまで作りきったらやってみようかなくらいの気持ちでした。

転職できた後、開発エンジニアしながら通おうかなと思っていました。


ただ結局この1ヶ月後くらいに入会を決めました。2023年12月18日です。

転職サポートさんも打ち切って、PHPも諦めました。

入会金を払ってMacbook air M2 19万ほど1括購入して。

我ながら今思うと、「貯金しといてよかったな」です( ´ ▽ ` )

実際に入ってみて。

驚きました。

Reactがすごい、Goがすごいなどということは正直まだわかりません。

しかし自分のポートフォリオとは

比べ物にならないくらいのことをみなさんやっています。

実際、現に開発エンジニアとして働かれている方も入るほどのスクールです。

また「これさえやっとけば強くなれる」という確立されたロードマップもあるので

「これやっとかなくて平気かな」と迷うこともありません。

私はまだまだこのロードマップの最初ですが、これから頑張りたいと思います。

ちなみに私はGoコースです。気になる人は来年の私を楽しみにしててください。

Euforia にはなんで入ったの

もっと刺激が欲しかったからです。高いお金払ってでも。

あとは自分の直感です。

入れば多分もっとすごくなれるという直感がありました。

また完全自習型は前スクールさんでやり抜いたので、ただ自分のペースで

やり抜く分にはできる自信がありました。

ただそうなると 甘えが出ます。

私は弱いのですぐサボります。実際辞めようと思えば辞めれます。

あー無理だった、ダメだったけどいい経験だったで解約すればすぐ辞めれます。

それで困るの将来の自分なんです。

もちろん分かってはいます。でもダメなんです。

伴走者というかそれ以上の存在が欲しかったんです。

導いてくれる存在がいたらいろいろ刺激になるじゃないですか。

それにEuforiaには他の方もいます。

動機はなんであれ、その方もいればさらに刺激になるじゃないですか。

だから入りました。自分の直感を信じて。

本格的な活動は3月からのようなので楽しみですね。

終わりに

いかがだったでしょうか。

未経験から転職するのは難しいことだと思います。

失敗することもあると思います。

ただ無駄な経験ではなかったと思います。私はそう思っています。

お金はかなりかかりましたが良い勉強になりました。

これから取り返していきたいと思います。

みなさんも慣れない環境に飛び込むことは不安だと思いますが

とりあえず入ってみる、とりあえずはじめてみることが大事だと思います。

きっと将来変わりますよ。頑張ってください。

僕も頑張って変えて見せます。

happiness-chain.com

Ruby Hashのキーにシンボルで書いた整数を使用したら SyntaxErrorが出た件について

はじめに

みなさん、こんにちは torihaziです

現在、rubyの課題をあれこれやっています。

その際に タイトルのことが出たのでその経緯を記載していこうと思います。

それではltg

結論

Ruby Hashのキーにシンボルで書いた整数({1: value})は使えない。

もし書くなら {整数 => 値}として書く

事象

問題となったコードは下記です。

SCORE_MAPPING = {
  -4: 'コンドル',
  -3: 'アルバトロス',
  -2: 'イーグル',
  -1: 'バーディ',
  0: 'パー',
  1: 'ボギー'
}

これを含んだコードを実行すると

syntax error, unexpected ':', expecting => (SyntaxError)
    -4: 'コンドル',

と出ました。

解決

  SCORE_MAPPING = {
    -4 => 'コンドル',
    -3 => 'アルバトロス',
    -2 => 'イーグル',
    -1 => 'バーディ',
    0 => 'パー',
    1 => 'ボギー'
  }

teratail.com

こちらの記事で解決しました。

結論は ダメだからだそうです。

どこか公式リファレンスに載っていないのでしょうか。

終わりに

いかがだったでしょうか。

まだしっくりきていません。

公式リファレンスに何か載っていたらいいのですが。。

見つけたら更新したいと思います。

ruby初心者がoptparseを使ってみた結果

はじめに

みなさん、こんにちは。torihaziです。

ruby初めてようやく1週間くらいが経ったと思います。

今回は コマンドライン引数を受けとることができるライブラリ

optparseを使っていきたいと思います!

それでは ltg

optparse

コマンドライン引数を受け取ることができると書きました。

それはどのようなものかというと

ruby test.rb -a testのようにこの-a testの部分を受け取ることができると言うことです。

使い方

マニュアル

マニュアルにも記載がある通り、optparseの基本的な使い方は

  1. OptionParser オブジェクト opt を生成する。
  2. オプションを取り扱うブロックを opt に登録する。
  3. opt.parse(ARGV) でコマンドラインを実際に parse する。

になります。

1. OptionParser オブジェクトを生成する

require `optparse`
opt = OptionParser.new

この書き方は初心者の私であっても慣れてきました。

組み込みライブラリでない標準ライブラリを組み込むためのrequire

そこからOptionParserをオブジェクト化するためのnewです。

これにより変数optにOptionParserオブジェクトが代入されます。

2. オプションを取り扱うブロックをoptに登録する

require `optparse`
opt = OptionParser.new

# ここから #
opt.on('-a') {|v| p v }
opt.on('-b') {|v| p v }

ここではonメソッドを使用します。

onメソッドの書き方は

opt.on('オプションの設定', 入力値の型指定[Integerなど], '説明`・・)

オプションの設定は-aなどが基本です。

-aの後に何か必須で受け取りたいなら -a valとします。

任意で受け取りたい場合は -a [val]とします。([]は [のみでもいいです)

onメソッドによって入力値であるオプションが登録されます。

ここでは登録されるだけです。

ブロック内の処理を実行するには後述するparseをする必要があります。

嘘だと思う方は試しに実行してみてください。

下記は ruby main.rb -a test -b numとした実行結果です。何も出ません。

require 'optparse'
opt = OptionParser.new

opt.on('-a test') {|v| p v }
opt.on('-b num') {|v| p v }

# 出力結果
# なし

3.opt.parse(ARGV)でコマンドラインを実際にparseする

parseするとはどう言うことかというと解析して実行できるようになると言うことです。

これにより -a testの testが受け取ることができるようになります。

require `optparse`
opt = OptionParser.new

opt.on('-a') {|v| p v }
opt.on('-b') {|v| p v }

# ここから #
opt.parse(ARGV)

# 引数を使うメイン処理の記載
puts ARGV

これを実行すると次のように帰ってきます。

# ruby Main.rb -a test -b num
"test"
"num"
["-a", "test", "-b", "num"]

そのため、引数を受け取り何か別の変数に代入するためには

ブロック内で処理を記述すれば良いことが分かります。

下記のように記述します。

require 'optparse'
opt = OptionParser.new
options = {}

opt.on('-a val') {|v| options[:a] = v}
opt.on('-b num') {|v| options[:b] = v}

opt.parse(ARGV)
p options

# 実行結果
#ruby Main.rb -a test -b num
# {:a=>"test", :b=>"num"}

以上の記述で、コマンドラインのオプションを解析して引数の値を受け取ることができるようになります。

まとめ

なんだかよくわからないと言う人は

  1. opt.onで引数を登録して
  2. opt.parseすれば
  3. その引数を使えるようになる

とだけでも理解しておいてください。

応用編

この度、カレンダーを作成してみました。

ご参考ください。

# frozen_string_literal: true

require 'optparse'
require 'date'

opt = OptionParser.new

options = { month: Date.today.month }

# 引数の受け取り
opt.on('-m [month]', Integer) {|month|
  if month >= 1 && month <= 12
    options[:month] = month
  else
    puts "#{month} is neither a month number (1..12) nor a name"
    exit
  end
}

begin
  opt.parse!(ARGV)
rescue ArgumentError => e
  puts 'Only integers between 1 and 12'
  exit
end

# データの用意
year = Date.today.year
header = Date.new(year, options[:month]).strftime('%-m月 %Y')
start_day = Date.new(year, options[:month], 1)
end_day = Date.new(year, options[:month], -1)
wdays = %w[月 火 水 木 金 土 日]
wday = start_day.wday

# カレンダー出力
puts header.center(20)
puts wdays.join(' ')
print '   ' * (start_day.wday - 1)

(1..end_day.day).each do |date|
  print format('%2s', date.to_s)
  print ' '
  puts '' if (wday % 7).zero?
  wday += 1
end

puts

実行結果は下記です。ターミナルではずれずに出ています。

root@1e049359c7de:/com/practice_ruby/practice_calendar# ruby calendar.rb -m 2
      2月 2024       
月 火 水 木 金 土 日
          1  2  3  4 
 5  6  7  8  9 10 11 
12 13 14 15 16 17 18 
19 20 21 22 23 24 25 
26 27 28 29 

終わりに

いかがだったでしょうか。

個人的に onでは登録しかされないと言うことが理解に苦しみました。

ただいろいろ触っていくうちに

だんだんと理解できるようになりました。

わからないことが多いことは辛いですが、

乗り越えれば楽しいことが増えます。

頑張ってください。

僕も頑張ります。