patorashのブログ

方向性はまだない

長男に家の1階全部を水浸しにされた話

先週の日曜日の早朝に、長男に1階全部を水浸しにされました。

長男は知的障害児で現在小学校2年生で支援学校に通っています。 水遊びが好きで、家でも目を離すとすぐに水道を出しっぱなしにして大変です。それのせいと、大きくなってきたのと、ある意味で知恵がついてきたので鍵をかけてもどこかから台になるものを持ってきて軽々と開けてしまうため、親としては気が抜けません。 困っていたので、リフォームを敢行しました。リフォームの話はまた別の機会にしようと思うのですが、今回の件と関係しているので、とりあえず対策としてキッチンに鍵をつけて入りにくいようにしたということだけ伝えておきます。

基本的に、寝る前には、お風呂の鍵とキッチンの鍵をかけるようにしていたのですが、この日に限ってはなぜかキッチンの鍵をかけ忘れていました。 普段は私が長男と一緒に寝るようにしているのですが、時々夜中に起きて癇癪を起こしたりすることがあるのですが、この日も起きてしまいました。私もうっすらと目が覚めたのですが、妻のいる寝室に行ったみたいだったので、まぁそれならいいかと見過ごしてそのまま寝てしまいました。

その後、遠くから「ピピピピピピ…」という音が聞こえてきて「これは冷蔵庫が開けっ放しになっている音だ!」と気付き、ガバッと起きてすぐに1階に降りたのですが(寝室は2階)、そこはもう全部が水浸しとなり、長男はマットの上で泣いていました。案の定、冷蔵庫は空いており、キッチンの蛇口が引っ張れるタイプなのですが、それがシンクを超えた状態で水が出続けていました…。まさか1階全てが水浸しになっているなんて想像もしていなかったので、軽くパニックになりましたが、ひとまず水道を止め、冷蔵庫を閉めたのに、まだ音が鳴っている…。確認すると、食洗機が水漏れしているというエラーを出していました…。水がシンク下の収納のところに一杯に入っており、そこから食洗機側に流れ込んだようでした。絶望です。

まずは長男をどうにかしないといけないので、2階の寝室に連れていったら、泣き疲れたのか、すぐに寝てしまいました。本人は気楽なものです…。

この時点で朝6時半くらいで、妻を起こして二人で水をなんとかするために作業を開始。ぐしょ濡れになった衣類は洗濯かごに入り切らないし水をたっぷり吸っているので、とりあえず風呂場へ移動させ、洗面所あたりはの水は風呂に流し、リビングの水は庭に捨てるようにしました。ひたすらバスタオルに吸わせてバケツに絞り、を繰り返し、二人ともクタクタになりながら全部を片付け終わったのはお昼すぎでした。8割くらいは昼前に終わってたけれど、そこからの残りをやる気力・体力がなかなか出ませんでした。

当然ですが、床においてあった全てのものが濡れてしまいました。本やオモチャなど、使い物にならなくなったものが結構ありました。長男の学校用カバンもぐしょ濡れ。次男の幼稚園用カバンもぐしょ濡れ。たまたまいい天気の日だったので、ウッドデッキに広げて干せました。

数週間前にお風呂のシャワーを洗面所に向かって出されて洗面所が水浸しになったことがあったり、以前にも水を出しっぱなしにされたりしたこともあったせいもあり、私と妻の感想は「不幸中の幸いで、日曜日だったからよかった」でした。もし、平日だったら、仕事を休んで対応しないと床が浸水しすぎて剥がれてくるかもしれなかったですし、子どもたちも学校に行けないし(カバンが使えないから)、大混乱していたことでしょう。いやー、おさるのジョージに出てくる黄色い帽子のおじさんばりによく訓練されている…。

リフォームして油断していたというのもあるかと思うのですが、もう本当に知的障害児の育児は気が抜けません。話せないから言葉が通じないし、怒っても理解はできないでただ癇癪を起こして暴れるだけ。まぁ一応、怒られたら止めるのだけれど、私達がいなくなった隙をみてすぐにやってやろうとするので、それがもう本当に腹が立ちます。ダメ、を理解しているわけではないので、どうやったら本当にダメなことをわかってもらえるのか…。

今までの子育ての中で一番の大事件だったんじゃないかなぁと思います。マジで疲れました。もう二度とやりたくないです。こういうの、なんか保険とか使えないかなぁ…。片付けちゃったから証拠がもうないんだけれど。あ、食洗機は壊れたままです。使えないと、本当に不便です。

rom-rb(rom-sql)でマイグレーションをロールバックする

Hanami v2.0を試そうとしているのだけれど、まだHanami v2系にはHanami Modelがリリースされておらず、rom-rbを直接使うことが推奨されている状態なので、rom-rbを使ってDBのマイグレーションを行っていたのですが、これロールバックはどうするんだろうか?と思って調べていました。しかし、ロールバックについての情報は見つからない…。

rom-rbでDBを使うためのgem rom-sqlでは、sequelを使っているので、sequelのほうの情報を見てみました。

sequel/migration.rdoc at master · jeremyevans/sequel · GitHub

running migrationのところを確認すると、-Mロールバックになると書いてあったので、ロールバックの仕組みはある…。

今一度、rom-sqlのほうのコードを確認してみようと思い立ち、rake taskのコードを確認したところ、rake db:migrate[version]でいけることが分かりました。

rom-sql/migration_tasks.rake at 596fea491ace84ae1aea12599879f84cb0ce5b64 · rom-rb/rom-sql · GitHub

こんな感じ。指定したバージョンまで戻るので、明示的にrollbackと書くことがないので、ググってもなかなかヒットしないわけですね。

bundle exec rake db:migrate[20230405151448]
# zshの場合
bundle exec rake db:migrate\[20230405151448\]

というかdescに書いてあるやん…。

$ bundle exec rake -T
rake db:clean                           # Perform migration down (removes all tables)
rake db:create_migration[name,version]  # Create a migration (parameters: NAME, VERSION)
rake db:migrate[version]                # Migrate the database (options [version_number])]
rake db:reset                           # Perform migration reset (full erase and migration up)
rake environment                        # Load the app environment
rake spec                               # Run RSpec code examples

Hanami v2.1で登場するHanami Modelの場合はこの辺りをサポートしてもらえると嬉しい。

Railsで作ってたアプリをSinatraで作り直した

何年も前に社内向けにシンプルなアプリをRailsで作っていたのだけれど、長いことメンテナンスできずにいた。 Rubyのバージョンも古いし、Railsのバージョンも古かったので、バージョンアップをしないとなぁと思っていたのだけれど、やったところでまた数年後に同じ思いをすることになりそうだなぁ…と思ったので、もっとバージョンアップのしやすいSinatraに書き換えることにした。

実はSinatraを試したことくらいはあったけれど、ちゃんとデプロイまでしたことはなかったので、よい経験になった。

作ったもの

シンプルなWebAPIを作った。JSONを返すだけ。

使ったgem

ハマったところ

CORSをするための設定

CORSをするときに、Bearer認証を使っていたため、Authorizationヘッダーを追加しているのでpreflight requestが発生するようになり、エラーが発生していた。

Before
# app.rb
require 'sinatra'
require 'sinatra/activerecord'
require 'sinatra/contrib'
require "sinatra/cors"
require 'rack/bearer_auth'

use Rack::BearerAuth::Middleware do
  match path: "/api/v1/foos", via: [:all] do |token|
    AccessToken.exists?(token: token)
  end
end

set :database_file, 'config/database.yml'
set :allow_origin, '*'
set :allow_methods, 'GET'
set :allow_headers, 'content-type,if-modified-since'
set :allow_credentials, true

# 略
After

調査をした結果、以下の修正が必要だった。

# app.rb
require 'sinatra'
require 'sinatra/activerecord'
require 'sinatra/contrib'
require "sinatra/cors"
require 'rack/bearer_auth'

use Rack::BearerAuth::Middleware do
  match path: "/api/v1/foos", via: [:get] do |token| # <= via: [:get]に変更してoptionsの場合を対象外に変更
    AccessToken.exists?(token: token)
  end
end

set :database_file, 'config/database.yml'
set :allow_origin, '*'
set :allow_methods, 'GET,OPTIONS' # <= OPTIONSを追加
set :allow_headers, 'content-type,if-modified-since,authorization' # <= authorizationを追加
set :allow_credentials, true

# 略

これでCORSできるようになった!

最初のCORSの設定を行ったとき、当初はBearer認証を実装してない状態だったのでシンプルなCORSでpreflight requestが発生していなかったので気づかなかった。 Bearer認証を実装したときには、CORSを試さずに単にREST Clientで試して問題なかったので、気づかなかった。 普通にデプロイ後に一応手動テストを行ったらCORSに失敗して非常に焦った…😅

pumaコマンドでsinatraの起動

pumaコマンドで起動する場合、config.ruファイルが必要。

# config.ru
require './app'
run Sinatra::Application

ホットリロードの導入

単にpumaで起動した場合、ファイルを修正しても反映されないので、一旦pumaを止めてまた起動しなければならない。

bundle exec puma

rerunを使うことで、ファイルを修正したらホットリロードされるようになる。

bundle exec rerun puma

修正が即反映されてとっても捗る。

まとめ

これでRailsアプリを1つメンテナンスしなくて済むようになったのでよかった。Sinatraならメンテ不要というわけでもないけれど、まぁ基本的にbundle updateだけで済みそうでしょう。

久々にブログを書いたけれど、やっぱりメモ的な内容でもいいからアウトプットしていかないとなぁ〜と思った。管理職になってからコードを書く量がめちゃ減っているので頑張っていきたい。

スキーマ駆動開発は依存関係逆転の原則を適用したものだと気づいた

ここ最近、チーム内で設計力強化のためにクリーンアーキテクチャ読書会をしているのだけれど、そこで気づいたことがあるのでメモとして残しておく。

18章の境界の解剖学を読んでいた際に、クライアントとサービスの図があったのだが、下位レベルのクライアントから上位レベルのサービスへの呼び出しとなっていた。しかし、ここでサービスのインターフェースを挟むことで、上位レベルのクライアントから下位レベルのサービスへの流れとなっていた。

このサービスのインターフェースこそが、Swagger Editor等で作るWebAPIのスキーマであり、バックエンドはこのスキーマをインターフェースとして捉えてこれをimplementする形で実装する。フロントエンドは、WebAPIのスキーマをインターフェースとして呼び出すことを前提として作れば、フロントエンドとバックエンドは疎結合となる。

スキーマ駆動開発はフロントエンドとバックエンドを疎結合にして実装できる、とは以前から認識していたのだけれど、依存関係逆転の原則を適用したものだとは本を読むまで気づいてなかったので、気づいたときはすごく嬉しかったというか、ワクワクした。

一回読んだだけだと全然よくわかってなかったんだけれど、色々見えるようになってきてから読むと、また気づきがあるなと思えた。

2022年9月に取り組んだこと

とりあえず、前回の記事からほぼ1ヶ月くらい経過しました。前回の記事では、昇進して課長になったよという話を書きました。

patorash.hatenablog.com

この1ヶ月で取り組んだことをざっと書いていこうかなと思います。

  1. 独自にOKRの導入
  2. スプリントのふりかえりのフォーマットを変更した
  3. 1on1の資料のフォーマットを変更した
  4. 朝会・夕会のフォーマットを変更した
  5. Yammerで日報を開始した
  6. 開発チームのメンバーに求めるものを定義した
  7. 曜日毎に取り組む作業を変更するルールを定義した
  8. レビューはモブレビューするようにルールを定義した
  9. PRのマージはPRを行った人が行うようルールを定義した
  10. コードのメソッドにドキュメントを書くようルールを定義した
  11. gitのコミットにプレフィックスをつけるようルールを定義した
  12. 読書会の主催を前チームの後輩氏に引き継いだ
  13. クリーンアーキテクチャ読書会をチームの一部のメンバーで始めた
  14. 個人の目標の確認をしやすいようにMS Listsで公開した
  15. AWSの勉強に取り組みやすいように情報を整理し、MS Listsで公開した。進捗も確認できるようにした
  16. New Relicの勉強会に参加。その後、遅い処理の見つけ方、RedMineへの報告の仕方を指示した
  17. 某システムの設計の開始。設計に入る前に改めて全体像の把握や疑問点の洗い出しなどを行った
  18. 自分のPCに現行システムの開発環境のセットアップを行った
  19. 管理職になったので、管理職会議や週次報告、お金に関わるところの確認・承認などなど
  20. 前チームで作っていた製品のコードレビューや、相談にのったり等。

うーん、結構やった感あるな…。

この中から、今回はコミュニケーションに関わるところの変更について書いていこうと思います。

フォーマット変更系

スプリントのふりかえり

最初はとりあえず見てみようかなと思って、観察していたのですが、もともとのスプリントのふりかえりのフォーマットが

  • 良かったこと
  • 悪かったこと

になっていました。悪かったことはなんか言い出しにくそうだし、良かったことは「別にないなぁ…」となりがち。

そこで、以下の記事を参考にして変更しました。

ihcomega.hatenadiary.com

  • 聞いてほしいこと
  • お礼したいこと
  • 自慢したいこと
  • 続けたいこと
  • 変えたい・なんとかしたいこと

順番はこのようにしています。これは、気分一致効果を狙ったもので、ポジティブな気持ちになってから、変えたい・なんとかしたいことに向き合ってほしいからです。

また、ふりかえりのレジュメは数日前から公開しておき、事前に記入してもらうようにしました。当日に聞くと、よく喋る人しか言わないので、じっくり考えたい人もいるのでそうしています。このフォーマットに変えてからまだ2回しか行えていませんが、以前に比べたらお礼や自慢したいことでコミュニケーションが取れたり、問題提起に関しても多く出てくるようになったかと思います。

また、今回のスプリントどうだった?というよりは、OKRの達成度に変化あったか?という視点でふりかえりを行い、次のスプリントゴールを定義するときに、OKRの達成度を上げるための取り組みを意識するようにできたかなと思います。

1on1の資料のフォーマットを変更した

こちらも、部門目標・個人目標を意識したフォーマットに変えました。といっても、ほとんど、とある本の丸パクリです。

  • 前回のスプリントでよかったことを3つ以上あげる
  • 次のスプリントで、こうできたら最高だなと思うことを3つ以上あげる
  • 前回のスプリントでの反省点を3つあげる
  • ネクストアクションと、そのネクストアクションの始めの一歩を考える

「重要だけれど緊急ではないこと」が個人目標に設定されていることが殆どなので、それを意識して取り組んでもらえるようにしました。私はこの本の中に出てきた「仮決め・仮行動」という考え方がすごく気に入りまして、「とりあえずこう仮決めしといて、とりあえず取り組んでみようや」というノリのおかげで重要だけれど緊急ではないことにサクッと取り組めるんじゃないかなと考えたので、丸パクリしているところです。もちろん、このフォーマットも仮決めです!しっくりこなければやめます。

あとさっき書いた気分一致効果もこの本で紹介されていたものになります。まず悪かったことから…とならないように振り返ることの大事さが書かれていてよかったです。

ネクストアクションを書いてもらい、さらにそのネクストアクションを行うための始めの一歩を書くようにしてもらってます。始めの一歩が次の行動を自然と起こすキッカケになるので、これもこの本を参考にしました。

朝会・夕会のフォーマットを変更した

朝会・夕会はデイリースクラムなので、目的は何をやってたかの報告ではなく、「スプリントゴールへの道を阻害するものを早く検出すること」なので、そういう視点で書いてもらうようにお願いしています。お願いしていますが、今の所そこまで出てきてません…。まぁ時々出てきているので、問題はないかなと思いつつ…。

Yammerで日報の運用を開始した

日報は、前も行われていたのですが、夕会の作業報告用であり、Teamsで行われていました。 しかし、これではその日の夕会でしか使えないので勿体ないと感じていました。

そこで、Yammerに日報コミュニティを作り、そこに個人を示すハッシュタグ付きで投稿してもらうようにしました(ちなみにTeamsはハッシュタグ使えません!)ハッシュタグ #名字日報 をつけることでハッシュタグをクリックしたらその人の日報だけに絞り込まれるようにしてあります。

これで、私は週次報告する際に個人ごとの活動を確認するのに便利だし、各メンバーは1on1等で、このスプリントで取り組んできたことをふりかえるのに便利、というわけです。

そして、フォーマットをYWTを改良したYWTKにしています。

  • Y: やったこと
  • W: わかったこと
  • T: 次にやること
  • K: 気になること

気になることは、なにかしら新しい情報や、面白そうな話題等について自由に書いてもらってます。障害があったときには、Aは対応したが、Bのほうは大丈夫だろうか?とかも。

朝会が始まる前に、Teamsで「前日の日報を確認してリアクションお願いします」と自動で流すようにしています。気になること・わかったことを共有してもらえるので、他の人の参考にもなったり、やったことの中で躓いた点などがあれば他のメンバーから「こうしたらいいんじゃないか?」とコメントがついたり、いいねなどのリアクションが付いたりしますし、実際の朝会の際に日報で書いていた件を話題に上げたり等、以前より確実にコミュニケーションが活発になったと思います👍

まとめ

という感じで、コミュニケーション設計でやりたかったことは1ヶ月でザーッとやることができたかなと思ってます。一気に色々と変えたので、大丈夫かな?と心配なところはあったのですが、「意図が伝わったしどれも大事だなと思ったので特に嫌だなと思ったりとかはない」、「どこに書けばいいかわからなかったのでまぁいいやと思って何もしてなかったことがあったが、ここに書けばいいのか、と書くところができたのはよかった」などのポジティブフィードバックを貰えたので、今の所よかったかなと思います。

運用を続けて、メンバーの成長と会社への貢献がガッチリ組み合わさっていけたらいいなぁと思います。

オマケ

うちのチームでメンバー募集しておりますので、RubyRailsアプリの開発・運用・保守や、AWSでの運用・保守に興味のある方はのほうまでご連絡いただけると助かります🙏 運用・保守の関係で、できれば岡山の方が望ましいですが、基本開発メンバーはリモートなので、岡山県外の方でも募集中です。

株式会社 リゾーム | システム開発(保守運用担当):岡山本社勤務 | IT/Web業界の求人・中途採用情報に強い転職サイトGreen(グリーン)

株式会社 リゾーム | システム開発(開発者):基本リモート勤務 | IT/Web業界の求人・中途採用情報に強い転職サイトGreen(グリーン)

開発だけでなく、システム管理系も募集しています。こちらもよろしくお願いします🙏

株式会社 リゾーム | システム管理(社内SE・情報システム)(岡山) | IT/Web業界の求人・中途採用情報に強い転職サイトGreen(グリーン)

株式会社リゾームで昇進しました(2回目)

うちの会社は期首が9月で、今期で昇進した。世間では退職エントリーとか入社エントリーが多いから、自分は昇進エントリーを書く。(2回目)

なお、1回目はこちら。3年前ですね。

patorash.hatenablog.com

課長に昇進した

うちの会社ではキャリアとしてマネジメント職と専門職がある。前期までは専門職だったが、今期からはマネジメント職になる。マネジメント職になった経緯は、まぁ正直なところ横滑り的な感じではある。昨年、このポジションにいたカズさんこと id:tech-kazuhisa が退職したことで、傍から見ていた感じではあるが、チームが一気に硬直化してしまったように思えた。カズさんの存在の大きさがよくわかった1年だと感じた。

まぁそんなこんなで日々の雑談タイムや読書会などで彼らの話を聞いていると、色んな不安や不満の話が出てきたりするのだけれど、当時の自分は、違うチームのリーダーだったし、かといってこのままだとマズイなぁというのはヒシヒシと感じていた。 「こうなったら、私が課長やるかー」という気持ちになってきたので、打診したところ、じゃあ来期から課長で!ということになったのだった。

マネジメント職の職責

マネジメント職の職責としては、

  • 組織の上位方針に沿って部門目標を立てる
  • 部門目標を達成するための計画を立てる
  • 計画を遂行するための指揮を取る
  • 部門メンバーの様々なサポートを行う
  • 他部門との調整を行う
  • お金の関わる辺りのやりくり

あたりだろうか?当たり前だけれど、専門職とは求められるものは随分異なる。今までよりも、より成果を求められるので、チームをいかに強くしていくかにかかっていると思う。

課長になってやっていくこと

さきほど、チームをいかに強くしていくかにかかっていると書いたばかりだが、今期はそこはそこまで重要なポイントとは思っていない。 まずは差し当たっての不満・不安を解消していくことだと考えている。その要は部門目標である。

部門目標・個人目標を明確に

期が変わる1ヶ月前に、今期の体制が発表されるため、8月はまだ課長ではないものの、今期の課長として部門目標を立てたり、それを達成するための計画作成、そして部門メンバーの個々の目標作成などについてミーティングを重ねた。なにせ、雑談や読書会で一緒に話したりはしているものの、違うチームから来た人間が課長になるので、現場の感覚と一致していない目標を立てられたら白けるだろうと思ったので、自分が考えた叩き台の目標と計画を事前に説明し、現場の意見をもらいながら修正して現実的なところに落とし込んだ。しかしそれでもかなりアグレッシブな目標にしてある。

成果の定量

開発部門は目標をなかなか定量化しづらいのだが、達成基準として、

  • 期日を設定し、前倒しで開発できたら評価に加点
  • ○名が運用・保守に参加できる技能を習得する
  • 既存システムの改善ポイントを見つける毎に評価に加点

など、加点ポイントを多く盛り込んだ。 開発だと、大概のことが「業務なのだから、やって当たり前」とされてしまい、せっかく改善ポイントを見つけても、やるのは発見した本人になるし、やったところで当たり前だから評価のポイントにはならない。だったら見つけてもあまりやりたくない、という負のスパイラルを生みがち。 その人の職位にもよるけれど、そのあたりは評価されて然るべきと思ったので、まずはそのスパイラルを断ち切りたい。

定量化されていれば、それ以上の成果を出せた場合はアピールしやすいし、途中経過が芳しくなければ、ふりかえりで対策を練ることができる。加点を狙って動けるようにするのが目的。一見、評価気にしすぎじゃない?と思われるかもしれないけれど、評価の高くなる成果は組織にとって良いことなのである。しょうもないことを評価するようにしているわけではない。

コミュニケーション設計

コミュニケーションはコロナ禍になってから更に希薄になっていると思うのだけれど、もうちょい活発になってほしいなぁと考えている。かといって、なんでもいいから雑談しろってのは無理があるので、コミュニケーション設計していくからねという話はした。

まぁ簡単に書くと日報を書こうってことと、他のメンバーの日報に、できればなにかしらリアクションしましょうってあたり。 日報には他の目的もあって、1on1の際に何をやってきたかを蓄積できるので、より振り返りしやすくなる。

あまりコミュニケーションが薄いと、チームワークが発揮されにくい。逆にいえば、コミュニケーションを増やせば自ずとチームワークが発揮されるようになるはずなので、コミュニケーションを取らないと達成できない形の目標を作ったりもした(もちろん両者同意の上で)。

管理職としての決意

部門目標を達成することは大事だけれど、やはり現場で働くメンバーが楽しくやりがいを感じて仕事できるようにすること、そして、給与面での待遇改善が、管理職としての重要な役割だと思う。体制としては上司と部下であるけれど、本質は役割の違いでしかないと思う。だから、そこを気にして発言できないようなことにはしたくない。心理的安全性のある関係を作りつつ、チームワークを発揮して成果を出して、その成果はしっかりアピールして、メンバーが昇進・昇給できるようにやっていく所存です。

頑張るぞー!

ActiveRecordでテーブルコメントを参照する

小ネタです。migrationの際にテーブルコメントを追加する情報は検索すればいくらでもヒットするんですが、ActiveRecordでテーブルコメントを参照する方法はなかなかヒットしなかったので、メモしときます。

環境情報

方法

ヒットしたのはAPI Dockのこれ。 apidock.com

ConnectionAdaptersのメソッドです。引数にテーブル名を渡します。 モデルから直で取れるメソッドはなさそうでした。

connection = ApplicationRecord::connection
connection.table_comment(:users) # usersテーブルのテーブルコメント取得

User.table_nameみたいに、User.table_commentで取れてほしいなぁ〜。