patorashのブログ

方向性はまだない

「現場で役立つシステム設計の原則」読書会 vol.2

間が空いてしまいましたが、第2回目の感想とかです。

前回はこちら。 patorash.hatenablog.com

会社のブログのレポートはこちら。 tech.rhizome-e.com

2章 場合分けのロジックを整理する

感想は箇条書きでメモってました。

  • 区分や種別が条件分岐を生む。区分がロジックを複雑にする。
  • それに対処するために、elseをなくして早期リターンを行うとコードが簡潔になる。これは今もよくやっている。
  • if文の条件をメソッドにして名前を与えると、条件が分かりやすくなる。これもよくやっている。
  • if文同士の関係を疎結合にするというのは、バグが起きにくいし、コードも見やすく、理解しやすくなる。
  • Javaのインターフェースを使っての実装例として分かりやすくてよかった。
  • Rubyだとインターフェースに該当するものがないので、無理やりModuleで作るしかない。呼び出したら例外を発生させるメソッドを定義するとか。
  • Javaの列挙型(enum)は使ったことがないんだけれど、列挙型もクラスとして扱えるというのは知らなかった。
  • 値オブジェクトの次は、区分オブジェクト。業務ロジックとしての区分は頻繁に出てくる。
  • 権限だったり、顧客区分だったり。ここを設計で綺麗にできると、迷いが生じにくそう。
  • 状態遷移のルールを区分オブジェクトにしてしまうという発想はなかった。これもまた条件分岐でやっていたと思うのだが、これならば一目瞭然でわかりやすい。Rubyならば、Setを使って実装するとよさそう。

雑感

よくやっている手法が出てきたので、まぁその辺りはできるようになってるな、うんうんと思いながら読み進めました。早期returnするとコードの階層が浅くなるのでいいですよね。if文の条件も、割と頻繁に出てくる可能性があるので、再利用性が高まるし、なにより条件に名前を付けられるのがわかりやすくなって良いっすね。

インターフェースを使うことで、区分に型を強制できるので、表現力があっていいなと思いました。そして、列挙型を使うことで更に簡潔に…。Rubyには現時点では列挙型がないので羨ましい。これはどうやればRubyで表現できるのか?という話し合いをしたりしました。

状態の遷移先を事前にHashMapに定義しておくのも、なるほどなぁと思いました。こうやってif文を減らしていくのか…。

読めば読むほど、リファクタリングがしたくなる本ですね!しかしなんか読書会の場ではリファクタリングに対して後ろ向きな意見がちらほら出て、やや残念な感じでした。リファクタリングしたらテストし直さないといけなくなるから…と。え、テストがあるからリファクタリングできるんじゃないの?って話したんですが、手動テストし直さないといけなくなるんで、というので、なんかルールが間違ってるんじゃない?ということは言いましたが、他のチームのことなのでこれ以上はとやかくは言えず。日々、リファクタリングに取り組んでほしい!

「現場で役立つシステム設計の原則」読書会 vol.1

最近、社内勉強会で、「現場で役立つシステム設計の原則」読書会をやってます。そして、今年に入ってから会社でテックブログが始まりました。こちらもよろしくおねがいします。

tech.rhizome-e.com

そちらのブログのほうでも、読書会レポートを参加者で交代で書いてます。

しかし、まぁ自分で思ったことはこっちのブログでも書いとこうかなぁと思うので、こっちでも書いときます。

本はこちらです。

1章 小さくまとめて分かりやすくする

感想は箇条書きでメモってました。

  • メソッドへの切り出し、クラスでの切り出しは既によくやっている
  • 切り出すことでテスト可能になり、安心して使うことができる
  • テスト可能になるとリファクタリングが可能になる
  • 値オブジェクトについては、聞いたことはあったが、あまり活用したことがなかった。
  • こんなに小さなクラスでも定義しまうのかという驚きがあった。よく十徳ナイフのようなごちゃごちゃしたクラスを作ってしまうことがあったが、それくらいなら小さいクラスを作ったほうがマシかなと思った。小さいクラスを作ることに罪悪感というか、なんとなくダメみたいな気持ちになってたが、それが払拭された。
  • 型を付けることで、間違いが起きにくくなる。型を活用する安心感をまだあんまり感じたことがなくて、むしろ野暮ったいくらいに思っていたけれど、最近になってようやく理解できるようになってきた。
  • バリューオブジェクトを意識するだけでも、再利用可能なドメインモデルを沢山作ることができて、1つの会社でやっていると、同じようなドメインモデルを活用することが多いから、仕事が捗りそうだなと感じた。
  • ここにきてようやく初めてオブジェクト指向とはなんぞやを理解したように思えた。

雑感

1章を読んだだけで、かなり目から鱗が落ちたような感じでした。俺は全然オブジェクト指向をちゃんと理解できてなかったなと痛感しました。

1章を読んだ後に、試しにJavaScriptをTypeScriptに変えてみようかなと思い、 1つのファイルを修正してみたのですが、型を意識することと、値オブジェクトを意識するようにしたら、「読むだけで意味のわかるコード」になったなと思いました。 もちろん、今までも意味がわかるようにメソッドに切り出して処理に意味のある名前を付けていたのだけれど、中で扱っている値はいわゆるプリミティブな値のままだったので、わちゃわちゃやってるなぁという感じでした。

確実にプログラマとしての腕が上がったな、という気持ちになれたので、この後の章を読んでいくのが楽しみになりました。

読者ハ読ムナ(笑)を読んだ

後輩くんと週に一度、週報を作るときにミーティングしているんだけれど、その時に読んでますって言われた本で、どんな本か聞いたら面白そうだったので私も電子書籍で買ってみた。

あらすじは、「うしおととら」や「からくりサーカス」などで有名な藤田和日郎さんと、その編集担当だった武者さんが、架空の新人アシスタントにアドバイスしていきながら漫画家としてデビューするまで色々とアドバイスをするという話です。

うしおととらにしても、からくりサーカスにしても、大学の近くの漫画食堂で読破したんですが(20年前近くじゃねーの…)、どっちもあんまり内容覚えてない…けれど、からくりサーカスはめっちゃ面白かったという記憶だけある。持っていない漫画のストーリーすぐ忘れてしまう。

話が脱線してしまったんですが、めっちゃ為になりました。

序盤の話

序盤は、まずアシスタントとして藤田さんのスタジオに入ることになるので、そこでルールを教わります。それが「無口禁止」。理由は色々と語られていますが、

  • あなたは新人だからどういう人かわからない
  • あなたも周囲の人のことがわからない
  • コミュニケーションを取って、お互いにどういう人かわかりあいましょう
  • 信頼貯金を作りましょう。話さないと貯まりません
  • 新人は信頼貯金がゼロなので、しっかりわかってもらえるように動きましょう
  • いいヤツじゃないと信頼貯金は貯まらないよ
  • 他人に興味を持ちましょう!

という感じだったと思います。

その話の後くらいに、今度は「映画を一緒に見る」というのがありました。映画を見た後、その映画の評価を点数付きで発表して、その理由をちゃんと言葉にする、というものでした。これも後々の話で出てくる理由も含めて書くと、

  • その人の着眼点がわかるようになる
  • どういうジャンルが好きとかの傾向がわかるようになる
  • ふんわりした理由はダメ。なぜ好きか、嫌いか、ちゃんと理由を考えろ。
  • これは、自分の漫画を客観視するための訓練でもある
  • 漫画のネタのヒントや気付きを貰えることもある
  • 「あの映画の爆発のシーンみたいな感じで描いて」で伝わるようになる

みたいな感じだったかな。

なんかこのあたりの話を読んでいたら、「めちゃめちゃチームビルディングやん」と思って読んでました。特に映画を一緒に見るの件(くだり)は、私が読書会やっているときの狙いと結構似ていたので、違う業界でも似たような手法があるんやなぁと興味深く読みました。

ネームへのダメ出し

新人漫画家なので、連載を狙うべく、アシスタントをしながらネーム(話の下書き)を描いて、編集の武者さんのところに持ち込んでいくわけですが、そこで色々とダメ出しされます。そして、ダメ出しされた内容を元に藤田さんが「武者さんはこう言いたかったんじゃない?」とか「自分のときはこうだった」というアドバイスをくれます。とはいえ、そのネームに対しても藤田さんからのダメ出しもあります。

これも完全にコードレビューと被ってて面白かったんですが、この新人漫画家は武者さんダメ出しされて傷つくんですが、コードレビューでもコードのダメ出しをしているのに人格攻撃をされたと受け取ってしまうことがありますよね。

このあたりについて、藤田さんが「ネームに対する思い入れが強いから傷つく。自分に対するダメ出しだと思ってしまう。でも、ネームに対して言ってるだけよ。もっと良くなってほしいから言ってるの。自分たちが映画を見た後に点数つけてるのと一緒」というふうに言ってます。いやもうホントにその通り…。まぁ必要以上に汚い言葉を使ってレビューする人もいることはあるので、なんとも言えないんですが、それはまぁその人の問題ってことにして…。

他人の批評は素直に受け取りなさいってことと、批評でわからないところがあったら質問しまくれって書いてあって、「素直さは大事よ…」と頷いてました。レビューで人のコードを読むこともあるでしょうし、どういうコードが世間一般で良いコードと言われているかを探求することで、自分のコードを客観的に見られる視点を身に着けないと、レビュー受ける度にグサグサ傷ついてしまう。とはいえ、傷つきたくないからと殻に閉じこもられてしまうと非常にやりづらい。漫画の業界でも、ダメ出しが嫌になって辞めちゃったり、同人誌を描く方に行ったりという話がありました。(※別に同人誌を批判していたわけではないです)

その他のところ

それからもネームや絵にダメ出しされ続けて、言われた通り修正してもまたダメ出しされて…という感じで、なかなか心にくるものがあります。 途中では、同期の漫画家が連載をスタートさせたりしていて、焦りを感じているときもありました。流行のジャンルの漫画を描かないとダメなんじゃないか?とか、知り合いの出版社なら漫画描けるよって誘われたりとか。 しかしまぁそれも本質的なところの「キミは何が描きたいの?どこ(の出版社)で描きたいの?」っていうところに帰結していきます。

何を軸にしてエンジニアとしてやっていくか、という話とか流行の技術に振り回されたりするような話と似ているなぁと思いながら読んでました。そして、「外ではなく内を見つめろ」っていうアドバイスがズーンと突き刺さりますね。自分の価値観・情熱をしっかり持つこと。内省についてまで書かれていて、なんてすごい本だ!と思いました。

どんな業種の新人でも結構当てはまるのでは?

まぁ私はIT業界なもんですから、そういう視点でわりかし藤田先生に感情移入しながら読んでました。 プロを志すのであれば、楽しく面白く心構えを学べる良書だと思いました!

藤田さんや武者さんが話しかけるような形式の本なので、スルスル読めますし、単純に漫画家がデビューするまでの世界の話としての読み物としても面白いですよ!

Hash#digの逆を行うHash#buryを定義するgem buryを作った

先日、新しくgemを作ってリリースしました。

リポジトリはここ。

github.com

Hash#digの逆とは?

Hash#digは、引数に渡されたkeyの配列でHashを掘っていくメソッドです。

hash = { a: { b: { c: 1 } } }
hash.dig(:a, :b, :c) # => 1

今回作ったやつは、それの逆を行います。引数で渡されたkeyの配列のところに値を埋め込みます。

require 'bury'

hash = {}
hash.bury([:a, :b, :c], 1) # => { a: { b: { c: 1 } } }

なお、digは「掘る」という意味なので、埋めるという意味のburyと名付けました。

途中のkeyが重複しても考慮される

途中のkeyが重複したらそれを検知してマージしてます。

require 'bury'

hash = { a: { b: { d: 2 } } }
hash.bury([:a, :b, :c], 1) # => { a: { b: { c: 1, d: 2 } } }

なんで作ったの?

Hashを動的に作りたかったのだけれど、Hashの深いネスト構造を作るのが大変だったので、作った次第です。今やっている作業を楽にするために作った完全に俺得なメソッドですが、もしかしたらこういう再帰的にHashをマージしたい需要はあるかもなぁと思ってgemにしました。

テストはminitestで書いてます。minitestは早くて簡単。

実装ポイント

Hashクラスへのメソッド追加のため、bury以外のメソッドを生やしたくなかったので、再帰的な処理をlambdaにしてメソッド内に閉じ込めました。

bury/bury.rb at 467750a62bc55959b03ad9ab680c109313105a11 · patorash/bury · GitHub

既に改善点が…

会社のTeamsで、こんなのを作ったと書いていたら、mergeメソッドにブロックを渡すとkeyが重複している際の処理が書けますよと教えてもらったので、それを使ってリファクタリングしたい所存。知らんかった…。めちゃ再帰でゴリ押ししてしまった。

docs.ruby-lang.org

しかし、公開するとフィードバックがあるのでありがたい😀

追記

リファクタリングを行い、かなりシンプルなコードになりました。これだけでよかったんか…😇

https://github.com/patorash/bury/blob/v2.0.0/lib/bury.rb

あと、元々のメソッドが破壊的メソッドなのに!マークのないメソッドだったので、非破壊的メソッドと破壊的メソッドを分けて定義しました。これで更に使いやすくなるはず。

2022年の目標

年末年始に読んだ本

年末年始に本を読んでいて、大変面白かったのと参考になった。

最高の体調

たいていのことは20時間で習得できる

科学的に正しい英語勉強法

結構これらの内容がリンクしていて、目標を考えるのによかった。

「最高の体調」で学んだこと

  • パレオ式生活がいい
  • 現代文明から離れる時間を作る
  • 一度にたくさんのことをやらない

「たいていのことは20時間で習得できる」で学んだこと

  • たいていのことは20時間で習得できる
  • しかし、同時に色々手を出していると習得できない。習得するまでは1つに絞れ。
  • 習得したら、次のものに移れ。
  • 学習と練習は違う。
  • 学習だけでは上手になれない。
  • 練習だけではなかなか上手になれない。
  • 練習して、さらに学習すると、上達しやすい。

「科学的に正しい英語勉強法」で学んだこと

  • もっといいものがあると思って他の教材に目移りするから習得できない
  • 英語勉強法というよりは、全ての勉強法について言えることだった
  • インプットはほどほどに、アウトプットを増やせ
  • 苦しんで思い出そうとする努力をしてから答えを見ろ

今年の目標

あれこれ沢山考えるとその数だけ思考にリソースを奪われてしまうので、とりあえず3つに絞る。

  1. 英語をマスターする
  2. Go言語をマスターする
  3. デジタルミニマリストになる

Go言語以外はもう取り組んでいる。とりあえず英語は単語を知らなさすぎるので、勉強中。単語集とか見ている。あと、久々にエンジリッシュに取り組んでいる。継続してマスターしていきたい。英語の問題集も家にあるので、そのあたりをやっていく。単語と文法と熟語をある程度インプットしたら、問題集をガリガリやっていくことにする。

マスターって言っても、どうしたらマスターしたと言えるのか?っていうのを定義しないといけないので、雑にTOEIC600点くらいに設定しておこうか…。TOEIC受けたことがないので、勉強をある程度したら、今年中に1度は受けてみようかなと思う。

デジタルミニマリストの内容と最高の体調の内容は繋がるところがある。

patorash.hatenablog.com

SNSを見る時間が減るといろいろとできる時間が増えたので家事が捗ったんだが、これを勉強の時間に使っていきたい。スマホには、雨音のBGMを流す役割を与えてしまえば、なんとなくスマホが気になりにくくなった。スマホを近くに置かなかったら、SNSの利用時間が激減するので、あとは運動・勉強・家事に時間を割り振っていく。まぁ本を読むのはタブレットになるので、デジタルを手放すのは難しいが、ChromebookからSNSアプリを削除しておけばよさそう。

世の中の流れに疎くなりそうではあるけれど、別にいいかなぁという気持ちになっている。できることを増やすことにフォーカスする。

2021年の振り返り

2022年も始まってもう3週間も経過しているというのに、ここ1ヶ月くらいアウトプットしていなかったので久々にブログ書きます。

年末は、妻と子供達が早めに実家に戻っていたので、数日間の一人暮らし期間があったので、その間に掃除を頑張って、寝室の模様替えをしたり、要らない衣類の整理をしたり、壊れた玩具を精査して処分したり、小型家電を処分したり、まぁ色々とやってました。とりあえずで置いていた物とかがたくさんあって、足の踏み場がなかったところとかが、だいぶ歩けるようになったのでヨシ。

ひとまず、今年の目標とかは既に決めてるんだけれど、まずは振り返ろうと思います。

patorash.hatenablog.com

仕事面

某企画を成功させること

これは、社内ISUCONのことですね。

patorash.hatenablog.com

期末ギリギリではあったけれど、企画を開催することができて、ある程度盛り上がったのでよかったかなと思います。ただ、それからの振り返りを参加メンバーができているのかが分からない…。やっただけになっている感じはあります。高速化のポイントとかについては話したけれど。

後輩氏の育成で得た気付きをアウトプットする

これは「〇月にやったこと」という形でアウトプットして、振り返りをしてました。自分なりに言葉にしていくと、客観視できるところもあってよいです。続けていきたいところなんですが、昨年の途中からあんまりできていません。理由は後述します。

今期目標にしてある例のやつを完成させてリリースする

これはまだ完成していませんね。しかし、後輩氏が育ってきたお陰でだいぶ進んだので、今期には倒したい。マジでいつまでやっとんねんという感じではあるんだけれど、プロジェクトのメンテナンスとかが忙しくてなかなか手を付けられない。ガッとやりたいんだけど。

リモートワーク環境の改善

ほぼ変わってない…。まぁ年末に掃除をして模様替えをしたので、今は多少変わっています。ディスプレイをワイドディスプレイにしました。これは捗る。

家庭面

長男氏が2022年度から小学生の年になるのだけれど、重度知的障害なので、支援学校に就学予定ではありますが、去年はそのために支援学校の見学とか面談とかしてました。コロナ禍ということもあり、学校見学がなくなってしまったり、体験みたいなのもなくなってしまったりと前年と同様慌ただしい一年でした。

次男氏は幼稚園に通い始めたのですが、コロナの影響で最初は休園になったり、なかなか大変でした。夜更かしするから朝に弱くて幼稚園への登園が遅くなりがちなので、今後はそこをなんとか改善していきたいところ…。次男の登園を妻が担当し、長男の登園を私が担当するという形でやってました。

あとはLOVOTをお迎えしたり。初期不良で大変だったりもしたけれど。

patorash.hatenablog.com patorash.hatenablog.com

自身

インプットを貪りたい、とか書いていたけれど、あんまりできてなかったんじゃないかな…。

インプット

読んだ記憶があるのは、これくらい。

  • その仕事、全部やめてみよう
  • 楽々ERDレッスン
  • スモール・リーダーシップ
  • いちばんやさしい教える技術
  • Webサーバ高速化教本
  • ソフトウェア・ファースト
  • みんなでアジャイル

あとは、会社の読書会で取り組んだりした。

  • Effective Ruby
  • プリンシプル オブ プログラミング
  • さわって学ぶクラウドインフラ Docker 基礎からのコンテナ構築
  • 安全なWebアプリケーションの作り方 第2版
ラジオ

ラジオをradikoで聴くようになった。オールナイトニッポン面白い。 地元がAMラジオが綺麗に入らなかったので学生時代にオールナイトニッポンを聞いたことが殆どなかったんだけれど、今はアプリで聴けるんだからいい時代っすねぇ…。

アウトプット

アウトプットは、まぁブログを書いたり、オープンソースにしている自作gemを更新したり、オープンセミナー岡山で登壇したり等。

patorash.hatenablog.com

健康面

これが辛いところで、10月末くらいに背中の右の肩甲骨辺りが痛くなってしまい、適当にストレッチをしていたのですが、どんどん悪化してしまい、右腕が鈍痛を感じたり、ビリビリと痺れはじめました。あまりに辛いので、整形外科に行ってみたら、頚椎ヘルニアの疑いがあるということで、湿布をもらって、やってはダメな姿勢について聞いたりして、気を付けて生活していたのですが、どうにも改善しないので、整体に通い始めました。

肉体的な痛みがあると精神的にも参るので、アウトプットをする気力が激減してしまい、ブログを書けなくなってました。とはいえ、オープンセミナー岡山があったので、なんとかそれだけは仕上げました。

整体に行き始めた当初は週に1~2回くらいのペースで通っていて、最初のほうは痛みはまだ残っていたものの、徐々に和らぎ、現在は日常生活で痛みを感じることはなくなりました。整体凄い。今は隔週で1回通っています。メンテナンス大事ですねぇ…。

健康診断でも、運動不足と体重増加を指摘されたので、最近は昼休みに散歩をしたりしてます。

総括

総括すると、健康と家族が一番大事。痛みは早めに対処したほうがいいですね。

あとは年齢の近い同僚が退職したので、なんだかんだ言っても、だいぶ孤独感ある。仕方ないところですけども。まぁ自分がワイワイできないにしても後輩たちがワイワイできるような環境作りができたらいいなぁと思います。

gem ransacker_translatorをRails7.0対応した

少し前ですが、Rails 7.0がリリースされましたね。弊社のプロダクトもRails 7.0系にアップグレードしていきたい…。しかし、そのためにはRailsに関連するgemのバージョンが対応していなければなりませんよね。はい、ということで、プロダクトで使っている自作gemもRails 7.0に対応していることを保証しなければなりません。やっていくぞ!

というわけで、とりあえず、ransacker_translatorをRails 7.0に対応させました。

rubygems.org

前に、随分放置していたからメンテを始めた、みたいな日記を書いてました。

patorash.hatenablog.com

これ以降も、Ruby 3.0で動くことはCIで検証していたりしましたが、如何せん適当な対応でした。今回は、しっかり対応できたと思います。まぁ新機能とかはないんですけど。

課題だったこと

色々と課題がありました。

  • gem rails に依存していたこと
  • CIにCircleCIを使っていたこと
  • テストが不十分だったこと
  • rspecを使っていたこと

取り組んだこと

依存gemを精査した

railsに依存しているっていうのはあまりに範囲が広すぎるので、依存gemを精査しました。

また、バージョン指定が雑だったので、< 7.1.0, >= 5.0.0というふうに明確にしました。

CircleCIからGitHub Actionsに移行した

CircleCIでもよかったのですが、GitHub Actionsを使う機会がなかったので試しにやってみたところ、めちゃくちゃ簡単だったのでGitHub Actionsに移行しました。GitHub Actionsを導入するためのyamlファイルが準備されているので、後はそれをカスタマイズするだけでした。

すごくいいなと思ったのが、matrixで、いろんな組み合わせでテストができることですね。CircleCIでもできるんですけど、それより簡潔に感じました。 これを使い、Ruby 2.6~3.1までと、Rails 5.0, 5.1, 5,2, 6.0, 6.1, 7.0でテストをするようにしました。

masterブランチでテストが通ったらgemをリリースする設定にしました。これはまた後日、別の記事にでもしようかと思います。

RSpecからMiniTestに移行した

gemのテストをするんだったら、Ruby標準のMiniTestを使うほうがいいかなと常々思っていました。また、gemで作ったヘルパーメソッドのテストの仕方がイマイチわからなかったので、ActionView::TestCaseを使えるMiniTestのほうがやりやすいのでは?と考えたりもしていました。他のgemがMiniTestを使ってどうやってテストしているかを調べました。参考にしたのはよく使っているgem simple_formです。

test_helper.rbを読んでいたら、ActionView::TestCaseをオープンして該当ヘルパーをincludeしていたので、このやり方を採用しました。

simple_form/test_helper.rb at 0f20705fafaec3376d6030171774d1ce0509bfae · heartcombo/simple_form · GitHub

これで、ヘルパーメソッドのテストも簡単に行うことができました😀

また、コントローラー用のConcernを定義しているのですが、それのテストも追加しました。全部のメソッドのテストを書くことができたのでヨシ!👍 これもまたどうやったかの解説を後日書いておこうと思います。

まとめ

テストを追加したことで、リファクタリングすることができました。初回リリースは7年前なので、そもそも当時のRubyのバージョンが古かったので、今どきの書き方にして簡潔になりました。まぁそれだけの期間で私のRuby力も上がっておりますので、スッキリとしました。

あとやっぱりテストが速くなった気がしますし、依存gemがかなり減ったので、その分設定も減り、簡潔になりました。他の自作gemも、実はransacker_translatorから設定をコピーして作ったりしていたと思うので、今後は他のgemもリファクタリングしていこうと思います。