メドピア開発者ブログ

集合知により医療を再発明しようと邁進しているヘルステックカンパニーのエンジニアブログです。読者に有用な情報発信ができるよう心がけたいので応援のほどよろしくお願いします。

毎年恒例の「Swift Quiz」(for Swift 5.8) を公開しました!

Swift Quiz に挑戦してね!

メドピアでアプリ開発を担当している高橋です。

メドピアが iOSDC Japan 2023 にスポンサードする度に毎年恒例で掲載している Swift Quiz の 2023 年度版を公開しました!(メドピアは今年はゴールドスポンサーです!)

今回は Swift 5.8 (Xcode 14.3 相当) 対応になります。社内の iOS エンジニア 3 名にクイズを作成いただきました!

swiftquiz.medpeer.co.jp

今年は例年にも増して難易度が高くなっていると思います・・・🧑‍💻

この辺りは Swift の基礎的な範囲ですが、

ヒント:struct に注目!

少し複雑な例文があったり、

ヒント:lazy は遅延評価

UI についての理解が必要だったりします。

ヒント:iPhone だけじゃないよ!

個人的には Swift 5.8 の特性に着目したこの問題はとてもいい問題だと思っています!

ヒント:Swift 6 を予習している人には簡単かも?

iOS / Swift エンジニアな方もそうでない方も、 ぜひチャレンジしてみてください〜! 👍 👍 👍

swiftquiz.medpeer.co.jp

ちなみに回答後の 𝕏 ツイートボタン押下時に iOSDC トークン が表示されるようになっております🙏

iOSDC Japan 2023 のメドピアセッションも見にきてくださいませ!


是非読者になってください


メドピアでは一緒に働く仲間を募集しています。 ご応募をお待ちしております!

■募集ポジションはこちら

medpeer.co.jp

■エンジニア紹介ページはこちら

engineer.medpeer.co.jp

大規模サービスのデータベースエンジンを MySQLからAurora MySQLへの移行 〜リードレプリカ, DNSを利用した最小ダウンタイム移行方法〜

バックエンドエンジニアの徳富(@yannKazu1)です。先日、メドピアのメインサービスであるmedpeer.jpで使われているデータベースエンジンを、MySQLからAurora MySQLへと移行しました。今回はその移行のプロセスについて詳しくお話しします。

移行したデータベースの簡単なインフラ構成

移行方針

今回移行するデータベースは複数のアプリケーションから参照されており、ダウンタイムによるユーザー影響が大きいため、移行方針の検討の段階で重視したのは、ダウンタイムの最小化でした。これを達成するために、DNSのCNAMEレコードと、Auroraのリードレプリカを活用し、移行させることにしました。

DNSのCNAMEレコードの使用

データベースエンドポイントをアプリケーションに直接記述する代わりに、DNSのCNAMEレコードを利用して間接的に参照するようにしました。これにより、データベースエンドポイントの変更が必要な場合でも、DNSのCNAMEレコードを更新するだけで対応できます。 今回移行したデータベースは複数のアプリケーションで参照されており、すべてのアプリケーションでデータベースホストを手で変更していくのはかなり時間がかかるため、この方法で行うことに決めました。

Auroraをリードレプリカとしての起動

Auroraはリードレプリカとして起動し、必要に応じてプライマリーに昇格させることが可能です。これにより、既存のデータベースと新しいAurora データベースとのデータ同期を保ちつつ、最小限のダウンタイムでデータベースをAuroraに切り替えることができました。

具体的な手順

以下に、具体的な手順を説明します。

①Auroraをリードレプリカとして起動

MySQLのリードレプリカとしてAurora MySQLを起動します。

②CNAMEレコードを作成

データベースエンドポイントを参照するCNAMEレコードを作成し、データベースエンドポイントを参照している全てのアプリケーションをDNS経由に切り替えます。これにより、Auroraに移行後にDNSのエンドポイントを変更するだけで全てのアプリケーションの参照先を切り替えることができ、ダウンタイムが大幅に削減できます。

③既存のRDSを読み取り専用に設定

既存のRDSにread_onlyパラメータを設定し、書き込みを停止します。 書き込みがなくなることで、Auroraレプリカのレプリケーションを追いつかせます。

④Auroraをプライマリーに昇格

リードレプリカとして起動していたAuroraのレプリケーション設定を削除し、フェールオーバーすることでプライマリーに昇格させます。

⑤DNSレコードのエンドポイントをAuroraに変更

DNSレコードの向き先をAuroraのデータベースエンドポイントに変更します。これにより、アプリケーション側で変更を加えることなく、エンドポイントが更新されます。

移行に際して検証したこと

本データベースは多くのアプリケーションが参照するメインデータベースであったため、慎重に検証を行った上で移行を実施しました。特に以下の2点を重視しました。

データベースエンジンの変更による予期せぬエラーの発生

まず、ステージング環境でAurora化を実施し、予期せぬエラーが発生しないかを検証しました。今回AuroraのエンジンはMySQLと互換性のあるバージョンに揃えたので、基本的には問題ないと予想されましたが、確認のためにステージングで検証を行いました。その結果、アプリケーション側の改修は必要ありませんでした。

Auroraのフェールオーバー時の接続切り替えの検証

AuroraとRailsを組み合わせて使用すると、Railsのコネクションプールの仕組み上、フェールオーバー時に新しいライターへのコネクション切り替えが自動的に行われず、リーダー(旧 ライター)にデータの書き込みを行ってしまう事象が知られています。これにより、予期せぬタイミングでデータ更新ができない状況が発生します。

今回、Auroraに移行したデータベースはRails、Go、PHPで書かれた複数のアプリケーションからアクセスを受けており、この問題への対策が必要でした。

対策方法としてはいくつかあることが知られていますが、今回書き込みエラーが発生した際に接続をリセットし、再接続を行うミドルウェアを開発しました。このミドルウェアは、RailsのActionDispatch::ContentSecurityPolicy::Middlewareより先に呼び出されるよう設定しました。

以下に、ミドルウェアの読み込みとそのコードを示します:

module RdsConnectionAdapters
  class Reconnect
    class RdsReadOnlyError < ActiveRecord::ActiveRecordError; end
    CONNECTION_ERROR = ['READ ONLY', '--read-only'].freeze
    CONNECTION_ERROR_REGULAR = /#{CONNECTION_ERROR.map { |w| Regexp.escape(w) }.join('|')}/

    def initialize(app)
      @app = app
    end

    def call(env)
      @app.call(env)
    rescue ActiveRecord::StatementInvalid => e
      raise e unless should_clear_all_connections?(e)

      ActiveRecord::Base.clear_all_connections!
      raise RdsReadOnlyError, 'DBが読み込み専用になっていたため、再接続を行いました'
    end

    private

    def should_clear_all_connections?(e)
      if e.kind_of?(ActiveRecord::StatementInvalid)
        return CONNECTION_ERROR_REGULAR === e.message
      end

      false
    end
  end
end

config/environments/production.rb(ミドルウェアの読み込み)

config.middleware.insert_before ActionDispatch::ContentSecurityPolicy::Middleware,
                                  RdsConnectionAdapters::Reconnect

移行の成果と今後の展望

CNAMEレコードの活用とAuroraレプリカの特性をうまく組み合わせることで、1時間程度のダウンタイムで抑えることができました。 DNSの工夫やAuroraの活用など、新しいアプローチに挑戦することで、予想よりもスムーズな移行が実現できたのは大きな成果です。

この経験から得た学びは、社内で共有し、会社全体の知見向上に努めたいと考えています。


是非読者になってください!


メドピアでは一緒に働く仲間を募集しています。
ご応募をお待ちしております!

■募集ポジションはこちら

medpeer.co.jp

■エンジニア紹介ページはこちら

engineer.medpeer.co.jp

AWS DevDay 2023 Tokyoへの参加レポート〜「セキュリティ/ガバナンス系サービスを使った安全なSandbox環境の作り方」の紹介

はじめに

 今年の4月に新卒で入社したバックエンドエンジニアの冨家(@asahi05020934)です。現在は、全国の医師が経験やナレッジを 「集合知」として共有し合う医師・医学生専用のドクタープラットフォームの開発を行っています。
 新しいAWSのサービスをキャッチアップするときに、触ってみることは効果的です。 「自宅で学ぼう!AWS 初学者向けの勉強方法 6ステップ!」 によると、

勉強したサービスをハンズオンなどを通じて実際に触ってみることで、知識と実践を結びつけて理解することができます。

とあり、アウトプットの重要性が身に沁みます。
 しかし、AWSのサービスを実際に触っていると、想定外のコストが発生し後悔する可能性があります。私も以前使っていないリソースを消し忘れて、月数千円の想定外の費用が発生し後悔したことがあります。
 どのようにすれば、AWSの安全なSandbox環境を作ることができるのか知りたいと思っていたところ、先日 AWS Dev Day 2023 Tokyoというイベントに参加し、セキュリティ/ガバナンス系サービスを使った安全なSandbox環境の作り方というセッションを聞いたので紹介します。

Sandbox環境構築に役立つサービス

 「セキュリティ/ガバナンス系サービスを使った安全なSandbox環境の作り方」では、主にコスト管理系のサービスで「AWS Budgets」「AWS Cost Anomaly Detection」、ガバナンス系のサービスで「AWS Organizations」「AWS IAM Identity Center」、発見的統制のサービスで「Amazon GuardDuty」「AWS CloudTrail」を紹介していました。

表1 AWSのSandbox環境構築に役立つサービス

コスト管理系 ガバナンス系 発見的統制
AWS Budgets AWS Organizations AWS CloudTrail
AWS Cost Anomaly Detection AWS IAM Identity Center Amazon GuardDuty

出典: セキュリティ・ガバナンス系サービス を使った安全な Sandbox 環境の作り方をもとに作成

コスト管理系

AWS Budgets

カスタム予算を設定してコストと使用状況を追跡し、しきい値を超えた場合に E メールまたは SNS 通知でアラートを受信できるサービス
出典: AWS Budgets

  AWS Budgetsには「予測とアクション」という機能があり、「月末ではいくらになるか」を予測してアラートを出してくれます。 これによりコスト面で危険な状態になりそうなとき、より早く気づくことができます。
 私も「このまま使っていけば月末どのくらいかかるんだろう」と不安になることが多いので、月末の金額を予測できるのは便利だと思いました。

AWS Cost Anomaly Detection

高度な Machine Learning テクノロジーを活用して、異常な支出と根本原因を特定できるサービス
出典: AWS Cost Anomaly Detection

 AWS Cost Anomaly Detectionを使用することで、想定外の請求リスクを減らすことができます。
 私も過去にどこでコストが発生しているかよくわからず特定するのに苦労したことがあったので、このサービスを使えばスマートに特定できそうで良いなと思いました!

ガバナンス系

AWS Organizations

複数のアカウントをまとめるサービス
出典: セキュリティ・ガバナンス系サービス を使った安全な Sandbox 環境の作り方

 AWS Organizationsが役に立つ理由は、2つあります。
 1つ目は、SCPが利用できるからです。SCPは、アカウントや組織単位にアタッチするポリシーです。SCPを使いSandbox環境のアカウントでも使用してはいけないサービスをあらかじめ禁止することで、Sandbox環境のアカウント利用者が本番アカウントでも使用できない事を事前に気づくことができます。
 2つ目は、アカウントの閉鎖による不要リソースの削除を行うことができるからです。 リソースを消し忘れる原因の1つは、消して良いリソースと消してはいけないリソースが混ざってしまうことです。そこで、本番環境のアカウントとSandbox環境のアカウントを分け、お試し的な用途はSandbox環境のアカウントを利用し、使わなくなったらSandbox環境のアカウントごと削除することでリソースの消し漏れを防ぐことができます。
 私はこのセッションを聞くまで「リソースの消し漏れを抑制するためにアカウントごと閉鎖してしまう」という発想に至らなかったので、とても斬新な方法だと感じました!

AWS IAM Identity Center

ワークフォースのアイデンティティを安全に作成または接続し、AWSアカウントとアプリケーション全体でそのアクセスを一元管理するサービス
出典: AWS IAM Identity Center

 AWS IAM Identity Centerが役に立つ理由は、3つあります。
 1つ目は、AWS Organizations全体のユーザー管理をAWS IAM Identity Centerでまとめて行うことができるからです。AWS IAM Identity Centerの方にログインをすれば、複数のAWSアカウントに対して、シングルサインオンが可能になります。これにより、IAMユーザーを勝手に作ってID・パスワードをいい加減に使い、インシデントを起こすリスクを減らすことができます。
 2つ目は、AWS CLIとAWS IAM Identity Centerが連携可能だからです。AWS CLIとAWS IAM Identity Centerを連携することで、一時的な認証情報(アクセスキー)を必要に応じて発行することができます。これにより、永続的なアクセスキーを発行することが不要になり、アクセスキーをGitにコミットしてしまったときなどのセキュリティリスクを下げることができます。
 3つ目は、WebAuthn対応のTouch ID / Windows Hello カメラ などの MFA が利用可能だからです。MFAの1つに、TOTPがあります。TOTPとは

ワンタイムパスワード(OTP)の生成手法の標準の一つで、秘密鍵と現在時刻からハッシュ値を求め、これを6桁程度の数値列に変換してパスワードとする方式

です。TOTPは、パスワードの生成・入力する分手間がかかります。そこで、WebAuthn対応のTouch ID / Windows Hello カメラ などの MFAを使うことで、パスワードの生成・入力が不要になり、多要素認証の手間を減らすことができます。
 私は毎回多要素認証する時にすぐにスマホを開けられずに困っているので、WebAuthn対応のTouch IDのような多要素認証が使えるのはとても魅力的に感じました!

発見的統制

AWS CloudTrail

AWS インフラストラクチャ全体のアカウントアクティビティをモニタリングして記録し、ストレージ、分析、および修復アクションをコントロールできるサービス
出典: AWS CloudTrail

 AWS CloudTrailを使うことで、「いつ誰が操作したのか」や「どんな操作をしたのか」ということを追跡することができ、調査をするとき便利です。
 もし、SandBox 環境がハッキングされ侵入されていた場合、作業時刻から不審な操作に気付けるかもしれませんね!

Amazon GuardDuty

悪意のあるアクティビティのために AWS アカウントとワークロードを継続的にモニタリングし、可視化と修復のための詳細なセキュリティ調査結果を提供する脅威検出サービス
出典: Amazon GuardDuty

 Amazon GuardDutyを使うことで、AWS アカウントの脅威を様々な情報ソースから機械学習を使って検知することができます。
 セキュリティ問題は自分の想定外な部分に潜んでいて、私はいつも「本当にこれで問題ないかな」と不安に思っているので、潜在的な脅威の検出に役立てられるAmazon GuardDutyはとても心強いツールだと感じました。

最後に

 以上、「セキュリティ/ガバナンス系サービスを使った安全なSandbox環境の作り方」を紹介してきました。今後はこの話を聞いたことをもとに安全なAWSのSandbox環境を構築して、後悔なくAWSのサービスに触れていきたいと思います。


是非読者になってください!


メドピアでは一緒に働く仲間を募集しています。   ご応募をお待ちしております!

■募集ポジションはこちら

medpeer.co.jp

■エンジニア紹介ページはこちら

engineer.medpeer.co.jp

potatotips主催させていただきました

iOSエンジニアの小林(@imk2o)です。 メドピアでモバイルアプリのテックリーダーをしております。

さる2023年7月21日、弊社でpotatotips #83を主催させていただきました。 以前にもオンラインで主催させていただいたことはあったのですが、オフラインを交えたハイブリッド開催は初めてでした!

弊社のモバイルアプリエンジニア総勢5名がLT登壇しましたので、その内容を紹介させていただきます。

speakerdeck.com speakerdeck.com speakerdeck.com speakerdeck.com speakerdeck.com

発表内容には、実際の業務の中で生じた課題に対する取り組みもありますので、参考になれば幸いです。

ハイブリッド開催の所感

技術系イベントもオフライン開催が復活してきたこともあり、企画当初から社内を会場として実施したいという声があがっていました。 ただ実際のところエンジニアだけで開催準備や当日の進行をするのは難しく、弊社HRチームに協力を仰ぎました。 ここで多忙な中でも快諾いただいたのが、開催成功の一番の要因だったと思います。 この場を借りて、あらためてHRチームには御礼申し上げます🙇‍♂️

また発表に関して、オンライン配信と会場での投影を同時に行うための機材準備についても色々工夫をしてもらいました。

  • 会場発表者を含め、すべての参加者にZoomへ入ってもらう
  • 発表者は投影したいスライドをZoomで画面共有する
  • ホスト用PCを会場のプロジェクターに接続し画面投影
  • 音声は別のマイクで収録し、ホスト用PCと会場スピーカーに接続

とすることで発表者が機材への繋ぎ変えをすることなく、ハイブリッド配信を実現しました。 事前リハーサルでMacと機材の相性問題が起きていたため、その解消と手順の簡略化をも実現したナイスソリューションですね!

LTの後に懇親会をさせていただきましたが、技術的な話から雑談まで色々なお話しをさせてもらい、とても楽しい時間を過ごせました。 エンジニア同士だと、初対面でもすぐ会話できるのが不思議ですよね! 対面でエンジニアの方々とコミュニケーションする機会となったのが、開催して一番よかった理由かなと思いました。

一方でオンライン参加いただいた方にはたくさんの拍手をいただいたものの、こちらのコミュニケーション不足でやや置き去りにしてしまったのかなと反省しております。振り返りをした上で、今後のイベント企画・開催に生かしていきたいと思います。

お知らせ: iOSDCスポンサーセッションに登壇します!

メドピアは今年も iOSDC Japan 2023に協賛しております。 弊社iOSエンジニアの新井がスポンサーセッションに登壇しますのでよろしくお願いいたします!


是非読者になってください


メドピアでは一緒に働く仲間を募集しています。 ご応募をお待ちしております!

■募集ポジションはこちら

medpeer.co.jp

■エンジニア紹介ページはこちら

engineer.medpeer.co.jp

「EM勉強会」をやってみたらすごく良かった話

メドピアでエンジニア/マネージャーをしている濱田 (@yut_h1979) です。

昨年末から半年以上かけて、「EM勉強会」(エンジニアリングマネジメント勉強会) と題したエンジニアリングマネージャーのしごと』の輪読会を実施しました。これがとても良い取り組みになったので、その経緯や内容について共有しようと思います。

目次

1. なぜやろうと思ったのか?

メドピアの組織拡大に伴う課題感

ここ数年でのメドピアの組織拡大に伴い、「マネジメント人材の育成/拡充」が課題であると自分は感じていました。

一定以上の規模に成長した開発組織では、エンジニア個々人の技術力だけではなく事業部との協働なども含めた開発組織の総合力 (生産性) を上げられるような「マネジメント人材」も一定以上必要になってくる、そして現状ではここがボトルネックになっている、という課題感です。

EM学習に最適な書籍との出会い

そんな中、昨年の秋口にエンジニアリングマネージャーのしごとという書籍に出会いました。この書籍は下記の点が素晴らしく、学習に最適であると感じました。

  • これまで自分が学習・経験してきた「EM (エンジニアリングマネジメント) のノウハウ」が、網羅的・体系的に言語化されている
  • EMに関するトピックが、「心構え・姿勢」といった精神論ではなく「メソッド・テクニック・スキル」といった実践論的に書かれている
  • 「他者とのコミュニケーション」「タスクの委譲」「プロジェクトマネジメント」など、マネジメント職でなくても役立つトピックが多く記載されている

さらに、メドピアではテックサポートという学習・スキル向上のための制度があります。そこで「この書籍を使って勉強会をやると良いことが起こりそう!」と感じ、「EM勉強会」を提案・実施するに至りました。

2 . 勉強会の始め方と進め方

勉強会ニーズの把握

「EM勉強会をやると良いことが起こりそう!」と自分が感じていても、それが独りよがりだと意味がありません。そこで、自他部門のEMやメンバーに事前ヒアリングを行い、本勉強会のニーズを探りました。その結果、「おおー良さそう!」「いつからやるの?早くやりたい!」といった反応を頂けたので、「よし、イケる!」という感触を得ることができました。

Slackチャンネルの開設と導入

「EM勉強会」の開始にあたり、まずは勉強会用のSlackチャンネルを作ることにしました。そして全エンジニアが入っているSlackチャンネルにて勉強会用Slackチャンネルの開設と「EM勉強会」の実施日時について案内し、興味あるメンバーに勉強会 and/or Slackチャンネルへの参加を促すようにしました。

読書ペースと進め方の決定

アジャイル開発でもプロジェクト推進でも、「結果の一部から全体を予測する」ことは肝心であると考えます。

そこで、勉強会の第一回では参加者と今後の進め方を相談しつつ、実際にみんなで「読書ペース」を計測しました。その結果、だいたい「15分で5ページ前後 ≒ 30分で10ページ前後」ということが分かったので、そこから次回以降の進行ペースと進め方を決定しました。

  • 一回の範囲:10ページ前後
    • 10数ページの章は1回で読み切る
    • 15ページ超の章は2回に分ける
  • 前半約30分:読書&呟きタイム
    • 黙々会的にその日の範囲を読み進める
    • その中で気になった箇所や意見/感想などをSlackに適宜呟く
  • 後半約30分:深掘り&議論タイム
    • Slackに呟かれた内容をピックアップし、みんなで深掘る

3. 工夫点と留意点

予習不要でハードルを下げる

エンジニアリングマネージャーのしごと』は、300ページ超のボリュームを持つ書籍です。一回に10数ページの進行ペースだと、読み終えるのに「26回」週一開催だと「約7ヶ月」という長丁場になることが分かりました。そこで、参加者が途中で脱落しないようにハードルを極力下げる配慮が必要と考え、事前の予習は不要としました。

内容をSlack上でオープンにする

勉強会はGoogle Meetで実施しましたが、前半30分の呟きと後半30分の深掘りや議論など、勉強会の内容はすべてSlackチャンネル上でオープンにしました。深掘りについてはSlackのスレッド返信で行うようにし、Google Meetのチャットコメントや口頭での意見も極力Slackに転記するようにしました。このようなやり方にした狙いは以下の通りです。

  • ワイワイ盛り上がっている感が出る
  • 欠席者/未参加者も内容を簡単に追える
  • 勉強会後の追加コメントも簡単に行える

「次回予告」で興味を惹く

先述の通り、本勉強会は「26回」、週一開催で「約7ヶ月」という長丁場になります。そこで、次回への期待を持たせて参加継続率を高める目的で、勉強会終了時に「次回予告」を行うようにしました。

「次回予告」のコンテンツは オライリー書籍ページの目次情報 をコピペすれば良いので簡単でした。また、これには「次にどこまで読めば良いかを事前に把握できる」という効果もありました。

4. やってみてどうだったか?

興味ある人が想像以上に多かった

本勉強会を始めるまでは、事前にニーズ把握はしていたものの「果たしてどれくらいの人が参加してくれるだろうか…?」という懸念がありました。しかし蓋を開けてみれば、勉強会には常時10名前後が参加し、勉強会用のSlackチャンネルには30名以上が参加してくれました。勉強会を始めた時期 (2022年後半) のメドピアのエンジニア総数は約80名 なので、割合としてもかなり多くのメンバーが興味を持ってくれたということになります。

もしかしたら、勉強会の内容をSlack上でオープンにしていたことも良かったのかも知れません。実際、最初はSlackチャンネル参加だけしているメンバーから「自分も勉強会に参加したい!」というケースも一定数ありました。

様々な立場からの議論ができた

本勉強会には前職からマネジメント経験のあるメンバーやマネジメント未経験者など、多様なバックグラウンドを持つメンバーが参加しました。そのため、同じトピックでも興味のある部分が異なったり、マネジメントする側でなくマネジメントされる側ならではの意見が出たりなど、様々な立場からの議論ができました。

また、マネジメント経験者からは書籍の内容を補強するような参考情報も随時頂けたりしました。こういった体験は一人で本を読む場合では得られないと思うので、本勉強会は自分を含め参加者にとって非常に有意義な場になったと思います。

事業部メンバーからも反応を頂けた

さらに本勉強会は、エンジニアだけでなく事業部メンバーからも興味を持って頂けました。個人的にも本勉強会を通じて、『エンジニアリングマネージャーのしごと』の内容の一部 (というか半分くらい) は「職種を問わず通用するマネジメントの基礎になり得る」という実感を持ちました。そこで現在は、本書の内容をピックアップした「ビジネス職向けのマネジメント勉強会」を企画中で、近いうちに実施する予定でいます。

最後に、参加したメンバーからの全体感想を抜粋で紹介します。

  • 『エンジニアリングマネージャーのしごと』、めちゃめちゃ良い本だなと思った
  • エンジニアリングマネージャーのいろんな観点を理解できて良かった
  • 本の内容だけでなく、参加者の経験談とか感想とかも聞けたのが良かった
  • 自分の欠席時も、Slackをあとでキャッチアップできて良かった
  • 総じて、一人で本を読むのとは違った体験ができた

5. まとめ

以上、メドピアで実施した「EM勉強会」(エンジニアリングマネジメント勉強会) の取り組みについて共有しました。マネジメントは唯一解が存在しない難しい世界ですが、だからこそこういった勉強会を通じて様々な知見や学びを得るのは意義深いことであると考えます。

本エントリが、マネジメントや勉強会運営に際して何らかの参考になれば幸いです。


是非読者になってください!


メドピアでは一緒に働く仲間を募集しています。 ご応募をお待ちしております!

■募集ポジションはこちら

medpeer.co.jp

■エンジニア紹介ページはこちら

engineer.medpeer.co.jp

RubyKaigi 2023をテーマにした社内LT会に参加しました

今年の4月に新卒で入社したエンジニアの冨家(@asahi05020934)です。
今回は、RubyKaigi 2023をテーマにした社内LT会に参加したので、それについてレポートします。

今回の社内LT会に参加する前

私は、新人研修としてRubyKaigi 2023に参加しました。
皆さんは、どのくらいセッションを理解できましたか?

私は、ほとんど理解できませんでした。
その原因の1つがセッションの内容を理解するために必要な知識が足りていないことだと思いました。
例えば、Power up your REPL life with typesを聞いたとき、
「そもそもこのセッションは何をしようとしているのか?」
ということや
「そもそも型を使うメリットは何なのか?」
ということがセッション中に引っかかって、全然頭に入ってきませんでした。

5月29日の社内LT会

しかし、先日、足りていない知識を少し補えた出来事がありました。
それは、RubyKaigi 2023をテーマにした社内LT会です。
弊社は、カンファレンス等で得た知見を定期的に勉強会や社内LT会で共有しています。
今回の社内LT会は、RubyKaigi 2023をテーマに参加したメンバーが有志で、セッションについて自分なりに調べたことや自作したものを発表しました。

社内LT会の要約

ReDoSの話RubyKaigi 2023レポート

この発表は、ReDoSの概要と対策方法に関する内容でした。

関連するセッション

Make Regexp#match much faster
Eliminating ReDoS with Ruby 3.2

JITの講演を聞いてじっとしていられなくなったのでruby-jit-challengeやってみた

ruby-jit-challengeとは、JITコンパイラ作りを試せるチュートリアルのことです。
この発表は、実際にruby-jit-challengeを試してみたという内容でした。

関連するセッション

Fitting Rust YJIT into CRuby

iseq_compile_pattern_each Hacking Challenge

Findパターンは、Ruby3.0で追加されたパターンマッチ機能の一つです。 この発表は、Findパターンを前方一致から後方一致に改造してみるという内容でした。

関連するセッション

Reading and improving Pattern Matching in Ruby

unloosen を使って Chrome Extension を作ってみた

unloosenとは、ruby.wasmによる Chrome Extension 開発に特化したフレームワークのことです。
この発表は、実際に、unloosenを使ってみてつまづいたところを共有するという内容でした。

関連するセッション

Develop chrome extension with ruby.wasm

型検査なしの型導入のすすめ 〜katakata_irbを添えて〜

この発表は、型の定義方法と型の活用方法に関する発表でした。 詳しい内容は、Railsプロジェクトへの「頑張らない型導入」のすすめに記載しているので、ぜひ読んでみてください。

関連するセッション

Gradual typing for Ruby: comparing RBS and RBI/Sorbet
Let's write RBS!
Parsing RBS

ruby mini_debuggerのコードを読んでみた

mini_debuggerとは、Stan Los(@_st0012)さんがBuild a mini Ruby debugger in under 300 linesで発表されたmini Ruby debuggerのことです。
この発表は、コード量が少ないので、mini_debuggerを読むことは意外と難しくなさそうという内容でした。

関連するセッション

Build a mini Ruby debugger in under 300 lines

DIYインタプリタ

この発表は、インタプリタを作って、プログラミング言語が何をしているのか体験してみたという内容でした。

関連するセッション

The future vision of Ruby Parser
Find and Replace Code based on AST

「演算子 "++"の実装、parse.yへの踏み込み」の講演を聞き、得たこと感じたこと

この発表は、Misaki Shioi(@coe401_)さんのImplementing "++" operator, stepping into parse.yのセッション内容を調べ直して、解説する内容でした。

関連するセッション

Implementing "++" operator, stepping into parse.y

発表を聞いた感想

これら8つのうち、個人的に印象に残った発表が、「型検査なしの型導入のすすめ 〜katakata_irbを添えて〜」でした。
この発表を聞いたことで、型を使うメリットの1つに、コーディング時の補完強化があることを知りました。
そして、改めてPower up your REPL life with typesを見返すと、「このセッションでは、型情報を使用してIRBの自動補完をより正確にしようとしている」ということをなんとなく掴むことができました。
LT会に参加する前は、型を使うメリットやPower up your REPL life with typesでやろうとしていることが全くわからなかったので、雰囲気を掴むことができて今回のLT会に参加して良かったです。

終わりに

今回参加して、LT会にはセッションの内容を理解するために必要な知識を補える可能性があることを知りました。 これからも積極的に参加していきたいです。


是非読者になってください!


メドピアでは一緒に働く仲間を募集しています。   ご応募をお待ちしております!

■募集ポジションはこちら

medpeer.co.jp

■エンジニア紹介ページはこちら

engineer.medpeer.co.jp

2ヶ月半で Nuxt サービスを 3.5 個つくった話

フロントエンドエンジニアの小林和弘です。

去年の 4 月に「Web アプリを 3 つ使ったサービスを 3 ヶ月でつくりたい」という話が降ってきて、無茶を現実にした話をします。

新規サービス「やくばと」で Workspaces のモノレポを使って、医療機関画面、薬局画面、患者画面の 3 つの Nuxt を構築しました。

やくばととは

医療機関、薬局、患者さまの間でやり取りされる医療機関起点の薬局向け処方せん画像事前送信サービスです。処方せんに関する業務負荷を軽減すると共に、患者さまの大きな負担である医療機関、薬局での待ち時間を軽減するということを主な目的としたサービスです。

医療機関、薬局の DX を進め、患者さまの負荷軽減に貢献できる素晴らしいサービスになっています。

開発チームでは医療機関、薬局、患者さまに提供している Web 画面をそれぞれ医療機関システム、薬局システム、患者システムと呼んでいます。

モノレポとは

モノレポとは、ひとつのリポジトリ内で複数プロジェクトを管理するソフトウェアの開発手法を指します。

フロントエンドのモノレポツールでは Lerna が有名です。やくばとでは複雑なビルドフローを組む必要がなかったことと、開発当初は Lerna v4 のメンテナンスが止まっていたことから、技術選定の選択肢からは外していました(やくばと開発中に Nx 社が Lerna のメンテナンスを開始したため、現段階ではモノレポツールとして Lerna は選択肢に入ると思います)。

やくばとでは、yarn の Workspaces を利用してモノレポを実現しています。

「Nuxt サービス 3.5 個」の 0.5

記事のタイトルに書かれている 3.5 個の Nuxt とは何かを説明します。

やくばとでは医療機関システム、薬局システム、患者システムをすべてひとつのリポジトリで管理しているわけではなく、患者システムと薬局システム、患者システムと既存サービスの 2 つのモノレポリポジトリで開発しています。

患者システムは、すでに存在していた既存サービスのリポジトリをモノレポ化してそこに組み込むという形をとっています。既存サービスのフォームコンポーネントなどのコードを、患者システムに流用するために大幅に書き換えています。0.5 はこの既存コードの変更部分を指しています。

ひとつの巨大なフォームコンポーネントを、入力項目ごとにコンポーネント化し、小分けにしたコンポーネントを共通利用するようにしています。作業としては単純ですが、ディレクトリ構造の変更を行っているため、リポジトリ内のほぼ全てのファイルが修正対象になっています。

患者システムは既存サービスのコードを使い回しているので QA テストの工数も大幅削減することができました。

既存リポジトリのモノレポ化 PR

モノレポの設定

モノレポの設定方法は非常に簡単です。

医療機関システムと薬局システムを管理しているモノレポを例に見ていきます。

package.json の設定

モノレポでは package.json をプロジェクトの複数箇所に設置する必要があります。

.
├── package.json
└── packages
    ├── medical
    │   └── package.json
    ├── pharmacy
    │   └── package.json
    └── ui
        └── package.json

まず、プロジェクトルートの package.json の workspaces プロパティにモノレポ対象になるディレクトリパスを指定します。workspaces プロパティには文字列の配列を定義しますが、ワイルドカード * も利用可能なのでやくばとでは下記のように指定しています。

{
  "workspaces": [
    "packages/*"
  ]
}

次に医療機関システム、薬局システム、共通 UI コンポーネントのための package.json を作成していきます。

{
  "name": "@yakubato/medical"
  "dependencies": {
    "@yakubato/ui": "*"
  }
}

{
  "name": "@yakubato/pharmacy"
  "dependencies": {
    "@yakubato/ui": "*"
  }
}

{
  "name": "@yakubato/ui"
}

各 pacakge.json の name プロパティに指定した文字列が package を呼び出すときのネームスペースに使われます。

たとえば、UI の Button コンポーネントを呼び出すとすると、

import Button from '@yakubato/ui/components/atoms/Button.vue'

といった形になります。

yarn workspace コマンド

yarn workspaces を使うと、node_modules のインストールコマンドが変化します。

プロジェクトルートの package.json に Nuxt を追加する場合は、 yarn add nuxt -W といった形で -W オプションをつける必要があります(オプションをつけなかったらエラーログが流れるのですぐに気づけます)。

また、workspaces で指定したディレクトリ配下の package.json に node_modules を追加する場合は、別のコマンドが必要になります。

packages/ui に @storybook/vue を追加する場合は、プロジェクトルートのディレクトリで yarn workspace @yakubato/ui @storybook/vue -D を実行する必要があります。workspace コマンドの第 1 引数に追加したい package.json の name プロパティを指定して、第 2 引数に追加する node_modules を指定します。

モノレポの利点

モノレポの利点はいくつかありますが、やくばとプロジェクトでは下記のような恩恵を受けられました。

  • 設定ファイルの共通化
  • node_modules のアップデートが楽
  • UI コンポーネントの共通利用

設定ファイルの共通化

個別のリポジトリで複数サービスを管理した場合、開発ツールの設定ファイルをそれぞれのリポジトリで管理する必要があります。

モノレポ管理をすると、ひとつのリポジトリで .eslintrc.js, .prettierrc, jest.config.js, stylelint.config.js 等々が一元管理できます。lint のルール変更も 1 ファイル変更するだけで各システムに変更が適応されます。

node_modules のアップデートが楽

node_modules のアップデートには dependabotrenovate といった、PR を自動作成してくれるボットがよく使われると思います。

モノレポ管理をすると、当然ですがリポジトリがひとつなのでこれらの PR 対応が一度で済むことになります。

また、今後発生するであろう Nuxt3 対応も一度で対応できるのも大きいです。

UI コンポーネントの共通利用

やくばとでモノレポを採用した一番の目的は UI コンポーネントの共通利用でした。

デザイナーさんに医療機関システムと薬局システムの UI デザインを共通化していただいた上で、汎用的な Button や Modal コンポーネントを一元管理することで開発工数を大幅に削減しました。

UI の開発工数を抑えるということであれば、UI ライブラリ(Vuetify, Chakra UI, Tailwind UI, etc)を使えばよいのでは? という話なんですが、長期運用で UI ライブラリが負債化するリスクと作成するコンポーネントの数や UI・UX の品質担保を天秤に掛けて、独自 UI コンポーネントの開発という選択をとっています。

UI コンポーネントのみをパッケージ管理できているため、他のプロジェクトでも同じ UI を使いたいという話が出てきたときに、 npm や GitHub Packages でパッケージとして UI を提供できる状態にあるというのもモノレポ管理の良い点です。

各システムの簡略図

やくばとの医療機関システムと薬局システムのモノレポ簡略図

医療機関システムと薬局システムは 2 つの Nuxt と、共通の UI コンポーネント管理を行う Storybook のプロジェクトがひとつの GitHub リポジトリ内で管理されています。

CircleCI 上で 2 つの Nuxt を generate し、生成物を AWS の 各 s3 にデプロイしています。CI 設定が共通化できるのもモノレポの利点です。

患者システムもほぼ同じ構成で、共通 UI コンポーネント管理に Storybook を使っていないくらいの違いしかありません。

患者システムは、Storybook が導入されていない既存サービスをモノレポ化しています。すでに UI が構築されていてテスト済という状態だったので、Storybook の導入を行わないという選択をしています(そもそもスケジュールがタイトでインストールする余裕がなかった)。

まとめ

複数ドメインで Web 画面を管理する必要があるようなサービスの場合、UI コンポーネントを共通化してモノレポ開発すると、初期構築や運用コストが抑えられるといった話でした。

複数の Web 画面を利用しないサービスでも、汎用 UI コンポーネントを切り出しておくとパッケージとして切り離しやすくなるという利点があるので、軽い気持ちでモノレポ構成にしてみるのも面白いかもしれません。


是非読者になってください!


メドピアでは一緒に働く仲間を募集しています。
ご応募をお待ちしております!

■募集ポジションはこちら

medpeer.co.jp

■エンジニア紹介ページはこちら

engineer.medpeer.co.jp