メドピア開発者ブログ

集合知により医療を再発明しようと邁進しているヘルステックリーディングカンパニーのエンジニアブログです。PHPからRubyへ絶賛移行中!継続的にアウトプットを出し続けられるようにみんなでがんばりまっす!

GitHub メンションを Slack DM する機能を Serverless Framework で作った話

メドピアマッスル部見習い kenzo0107 です。

今回は GitHub のコミュニケーションを円滑にすべく導入した GitHub 通知の Slack DM 機能になります。

github.com

導入経緯

GitHub.com でイシューコメントやプルリクエスト等でコメントをした、してもらった、時に気づかず放置されてしまうことが度々ありました。

Slack 上で
「あれ、どうなりました?」と聞くと、
「コメントくれてたんですね、すいません、気づきませんでした」と。

この防止策の一環として導入したのが、 GitHub メンションを Slack DM に通知する機能になります。

Slack には既に GitHub アプリあるけど?

Slack には既に GitHub アプリがありますが、個人宛てに DM 通知するには個々が認証する等、一手間あります。

その為、認証等せずとも、GitHub.com 通知を個人宛のメンションとして Slack DM する仕組みが必要と考えました。

新入社員さんに一手間かけてもらうことなく、スムーズに GitHub + Slack のコミュニケーションを体験してもらえるようにしました。

システム構成

f:id:kenzo0107:20190228125632p:plain

  1. mogezo 君が GitHub イシュー or プルリク コメントで hogeko さんへメンション
  2. GitHub Webhook を AWS API Gateway で受け、
  3. Lambda を実行し、
  4. hogeko さんへ Slack DM 通知する

図の点線で囲んだ AWS 内の処理を Serverless Framework で構築しました。

導入手順

以下導入手順の大まかな流れです。

  1. GitHub Webhook 設定
  2. Slack Incoming Webhook URL 発行
  3. serverless framework で API Gateway + Lambda + CloudWatch Logs 構築

GitHub Webhook 設定

Organization の Webhook を作成します。*1

設定項目 内容
Playload URL 仮設定で良いです (ex. https://hoge )。
後ほど設定します。
Content type application/json
Secret 認証の際に必要なパスワード情報です。
適当なランダム値を設定してください。

対象イベントは以下としました。

  • Commit comments
  • Issue comments
  • Pull requests
  • Pull request reviews
  • Pull request review comments

f:id:kenzo0107:20190215182516p:plain

Slack Incoming Webhook 作成

以下リンクから Slack Incoming Webhook URL 作成します。

https://slack.com/services/new/incoming-webhook

Serverless framework で API Gateway + Lambda 構築

事前準備です。

serverless framework プロジェクトを clone します。

git clone https://github.com/medpeer-inc/githubcom2slack
cd githubcom2slack

Nodejs は本プロジェクトでは AWS Lambda 最新の 8.10.0 としています。*2

node -v

v8.10.0

Serverless Framework インストールします。

npm install -g serverless

関連ライブラリをインストールします。

npm install
bundle install -j4 --path vendor/bundle

AWS Access Key ID, AWS Secret Access Key を環境変数設定します。

現状弊社では direnv を利用し設定しています。*3

// direnv インストール
brew install direnv

// 環境変数設定
echo -n 'export AWS_ACCESS_KEY_ID=HOGEFUGA' >> .envrc
echo -n 'export AWS_SECRET_ACCESS_KEY=BUDOUBAR' >> .envrc
direnv allow .

AWS KMS Key 作成

aws kms create-key

{
    "KeyMetadata": {
        "AWSAccountId": "xxxxxxxxxxx",
        "KeyId": "yyyyyyyyyyyyyyyyyyyyyyyy",
        "Arn": "arn:aws:kms:ap-northeast-1:xxxxxxxxxxx:key/yyyyyyyyyyyyyyyyyyyyyyyy",
        "CreationDate": 1549615619.872,
        "Enabled": true,
        "Description": "",
        "KeyUsage": "ENCRYPT_DECRYPT",
        "KeyState": "Enabled",
        "Origin": "AWS_KMS",
        "KeyManager": "CUSTOMER"
    }
}

キーのエイリアス作成

aws kms create-alias \
    --alias-name alias/githubcom2slack \
    --target-key-id yyyyyyyyyyyyyyyyyyyyyyyy

秘密情報の暗号化

今回、秘密情報として扱うのは、以下2 点です。

  • GitHub Webhook Secret
  • Slack Incoming Webhook URL

AWS Lambda コンソール上で暗号化ボタンをポチッと押すのでなく、暗号化した文字列を環境変数として設定します。

GitHub Webhook Secret 暗号化

aws kms encrypt \
  --key-id arn:aws:kms:ap-northeast-1:xxxxxxxxxxx:key/yyyyyyyyyyyyyyyyyyyyyyyy \
  --plaintext "<GITHUB_WEBHOOK_SECRET>" \
  --query 'CiphertextBlob' \
  --output text

Slack Incoming Webhook URL

aws kms encrypt \
  --key-id arn:aws:kms:ap-northeast-1:xxxxxxxxxxx:key/yyyyyyyyyyyyyyyyyyyyyyyy \
  --plaintext "<SLACK_INCONMING_WEBHOOK_URL>" \
  --query 'CiphertextBlob' \
  --output text

<SLACK_INCONMING_WEBHOOK_URL>https:// の後の ドメインからの文字列を指定してください。*4

上記 2 つ生成された値を secrets.yml に設定します。

  • secrets.yml は以下の様になります。
GITHUB_WEBHOOK_SECRET_ENCRYPTED: *****************************
SLACK_INCONMING_WEBHOOK_URL_ENCRYPTED: *********************************
AWS_KMS_KEY_ARN: arn:aws:kms:ap-northeast-1:xxxxxxxxxxx:key/yyyyyyyyyyyyyyyyyyyyyyyy

秘密情報の暗号化

yaml_vault で secrets.yml ファイルを暗号化した secrets.yml.enc をリポジトリで管理します。*5

env \
  AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} \
  AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} \
bundle exec yaml_vault encrypt \
  --cryptor=aws-kms \
  --aws-region=ap-northeast-1 \
  --aws-kms-key-id=alias/githubcom2slack \
  secrets.yml -o secrets.yml.enc

KMS key を利用した暗号化・復号権限を特定 IAM Group に絞ることで、そのグループに属するユーザのみ暗号化・復号が可能になります。

GitHub.com ユーザと Slack ユーザを紐付け

以下 2 つを紐づける為に git2slackNames という hash 値を設定します。

  • GitHub.com ユーザ名
  • Slack ユーザ名
// github username : slack username
const git2slackNames = {
  'kenzo0107': 'kenzo.tanaka',
}

上記の場合、新たにユーザ追加する度にコード修正が必要となります。

もし GitHub.com ユーザ名 と Slack ユーザ名 に命名規則がある場合、以下メソッドで命名規則に沿った変換を実装すると追加の手間がありません。

弊社では命名規則があるので、変換処理をするようにしています。*6

function extractUsernameFromMessage (message) {
  let usernames = []
  let usernameCandidates = message.match(/@[a-zA-Z0-9-]+/g)
  if (!usernameCandidates) {
    return usernames
  }

  for (let i in usernameCandidates) {
    var u = usernameCandidates[i].replace('@', '')
    if (denySlackDmUsers.indexOf(u) > -1) {
      continue
    }
    if (git2slackNames[u]) {
      usernames.push(`@${git2slackNames[u]}`)
    }

    // github username と slack username に命名規則があれば、
    // ここで変換 git --> slack username へ変更するも良し
  }
  return usernames
}

例)命名規則がある場合

  • GitHub.com のアカウント名: medpeer-<firstname>-<lastname>
  • Slack のアカウント名: <firstname>.<lastname>

以下のような変換が可能です。

for (let i in usernameCandidates) {
  ...
  ...
  if (u.match(/^medpeer-/)) {
    usernames.push(`@${u.replace(/medpeer-/, '').replace(/-/, '.')}`)
  }

いざデプロイ

sls deploy -v

GitHub Webhook URL 設定

GitHub Webhook URL が仮設定状態だったので、生成されたエンドポイントを設定します。

sls info

Service Information
service: githubwebhook2slack
stage: production
region: ap-northeast-1
api keys:
  None
endpoints:
  POST - https://xxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/production/webhook
functions:
  githubWebhookListener: githubwebhook2slack-production-githubWebhookListener

上記の例では、 https://xxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/production/webhook がエンドポイントになります。

こちらを仮設定だった Github Webhook URL に設定します。

では、早速試してみましょう!

GitHub.com のプルリクエストでメンションします。

f:id:kenzo0107:20190227143042p:plain

するとすぐに Slack DM 通知がきます。

f:id:kenzo0107:20190227123309p:plain

通知がこないな、という時に

Lambda のログが CloudWatch Logs に流れてますので、ログを確認してください。

そもそもログが出ていないのであれば、 Webhook の設定忘れや URL に誤りがある等チェックしてみてください。

まとめ

弊社では、非エンジニアも GitHub でコミュニケーションしています。

今回の実装によって、コミュニケーションが円滑になったことに加えて、 GitHub 上で明示的にメンションすることが増えた様に思います。

また、 GitHub から API Gateway + Lambda の認証が確立できたことで、 GitHub イベントをトリガーとした AWS リソースの変更に応用する様にもなりました。

こちらについては今後執筆できればと思います。

以上です。 参考になれば幸いです。


(☝︎ ՞ਊ ՞)☝︎是非読者になってください


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

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

https://medpeer.co.jp/recruit/entry/

■開発環境はこちら

https://medpeer.co.jp/recruit/workplace/development.html

*1:リポジトリを絞りたい場合は、個々のリポジトリの Webhook に設定してください。

*2:nodenv でセットアップしています。

*3:特段これでなくてはいけないということではないので、適宜設定してください。

*4:https:// を含めるとエラーになるかと思います。

*5:serverless-secrets-plugin という暗号化する npm 管理可能な package もあるのですが、暗号化時にパスワードを設定する必要があります。そのパスワードの管理をAWS パラメータストアにすると、結局、KMS が必要となり、秘密情報を取得する手間がさらに増えてしまう為、導入経験がある yaml_vault にしました。その他にもあろうかと思いますが、もし良いのあるよ!という場合は是非教えてください!

*6:命名規則がない場合はこの辺りを DB に持たせても良いかもしれません。

MedPeerをrails 5.2へアップデートしてました!🎊

こんにちは、エンジニアの森田です🌴

rails 5.2.0が発表されたのが2018年4月10日🚃

大分遅くなってしまいましたが、2018年10月18日にメドピアが運営する医師専用コミュニティサイト「MedPeer」を、rails 5.1.6からrails 5.2.0にアップグレードしていました🎊

f:id:madogiwa0124:20190105151411p:plain

今回は、アップグレードを行った手順や躓いた部分を今更感もありますが紹介いたします🙌

アップグレードまでの道のり

まずはバージョンアップまでに行ったことの概要を下記にまとめました。

  1. リリースノートとアップグレードガイドを読んで影響を確認
  2. Gemfileのrailsのversionを5.2.0に変更してbundle update
  3. rails app:updateで設定周りを更新
  4. テストを実行し、失敗したor警告が発生した箇所を修正
  5. 社内の検証環境にデプロイして、動作確認
  6. 本番デプロイ
  7. 振り返り会

それぞれについて、実際にやったことを紹介いたします🙇

リリースノートとアップグレードガイドを読んで影響を確認

まずはRails5.2の変更点を知るためにRailsGuideのアップグレードガイドとリリースノートを読みました👀 (私は英語があまり得意ではないので、日本語版もあって非常に助かりました・・・!)

アップグレードガイド

リリースノート

Gemfileのrailsのversionを5.2.0に変更してbundle update

月に1回bundle updateを行っていて、比較的依存Gemのバージョンが上がっている、またマイナーバージョンのアップデートということで影響も少なそうだったので、bundle updateで依存Gemを含めて、アップグレードを行いました。

※月1回のbundle updateの施策については、こちらから👀

speakerdeck.com

rails app:updateで設定周りを更新

次にrails app:updateをとりあえず全てyesで実施して、危なそうな部分を戻す対応を行いました。影響が大きそうだった差分だけ下記に記載しておきます👀

  • bin/railsbin/rakeでspringをロードしないような変更が入っていたので反映しませんでした。
  • active_storagetest_unit関連の設定ファイル追加及び既存ファイルへの更新は、使用していないので反映しませんでした。
  • config/application.rbconfig.load_defaults5.2に変更しました。
  • bootsnapは開発環境のみで動くようにし、本番での使用は一旦様子見しました。

設定ファイル関係はわからないことも多かったのですが、技術顧問の前島さんにレビューしてもらえるので安心・・・🙏

f:id:madogiwa0124:20190105151558p:plain

テストを実行し、失敗したor警告が発生した箇所を修正

とりあえず全体でテストを走らせて落ちた箇所と警告が発生していた部分を修正しました👷
主な修正は下記のようなところでした。

Arelのexistsを使っていた箇所を修正

existsを使っている箇所でDEPRECATION WARNING: Delegating exists to arel is deprecated and will be removed in Rails 6.0.の警告が発生していたため、下記のようにEXISTSではなくNOT INを使って行うように修正しました。

# before
where(Expert.where('users.id = experts.user_id').exists.not)
# after
where.not(id: Expert.select(:user_id)) }

Dangerous query method対応

rails 5.2から下記のようにsqlをハードコーディングするとDangerous query methodの警告が発生するようになりました。

Post.order('RAND()')

MedPeerでは固定の文字列を渡している箇所でのみ発生していたので、Arel.sqlで対応しました。

Post.order(Arel.sql('RAND()'))

テストの無い管理画面に立ち向かう

今回railsのバージョンを上げると同時に管理画面で使っているadministrateというgemのバージョンも大きくあがりました。メドピアでは管理画面ではクリティカルな部分以外でテストコードを書いていません😥
全てを手作業で確認するのは大変なので、今回はRails.application.routesを使ってpathを生成し、各画面遷移時にステータスコード200が返却されることを検証することで、手動テスト前の最低限の品質保証、バージョンアップによるエラーの検知が出来るようにしました🙇

require 'rails_helper'
module AdminRoutingTestHelper
  class << self
    # Admin配下のpath名と、それに合致するcontroller名とaction名を取得
    def admin_routes(actions)
      routes = routes(actions)
      routes.select { |route| route[:name].include?('admin') }
    end

    private

    def routes(actions)
      routes = Rails.application.routes.routes
      routes = routes.map { |route| prepare_route(route) if route.name }.compact
      routes.select { |route| actions.include?(route[:action]) }
    end

    def prepare_route(route)
      { name: route.name, action: route.requirements[:action], controller: route.defaults[:controller] }
    end
  end
end

RSpec.describe '画面に正常に遷移できるか確認' do
  IGNORE_PATH = [
    # 自動テスト対象外のpathを記載 
  ].freeze

  # 前提データが必要な場合は自動テストを行うのが難しいので、一覧と新規に限定
  admin_routes = AdminRoutingTestHelper.admin_routes(['index', 'new'])
  # 対象外のpathを除外
  target_routes = admin_routes.select { |route| IGNORE_PATH.exclude?(route[:name]) }
  url_helper = Rails.application.routes.url_helpers

  # 対象のpathの件数分、遷移しステータスコード200が返ってくることを検証
  target_routes.each do |route|
    describe route[:name] do
      before do
        visit url_helper.url_for(host: Capybara.app_host, controller: route[:controller], action: route[:action])
      end
      it "#{route[:controller]} # #{route[:action]}" do
        expect(page.status_code).to eq 200
      end
    end
  end

社内の検証環境にデプロイして、動作確認

テストのある部分はテストを全て通し、ない部分については先述の仕組みで確認したあと、ディレクターさんにも協力して頂き、業務上クリティカルな箇所について手で検証しました。

今回はマイナーバージョンアップということで、普段使っている本番相当の検証環境にバージョンアップを反映して検証を行いました。

本番デプロイ

通常業務に影響がなさそうという検証が出来たので、2018年10月18日にバージョン対応をmasterブランチにマージし、本番環境にデプロイしました🎊

VersionUp振り返り会

最後にバージョンアップの際に行ったことを整理して、KPTで振り返りを行いました。以下が出てきた内容の抜粋です🙇

Keep

  • 管理画面のテストを最低限ではあるが、自動的に行うことが出来た。

Problem

  • Gemfileで過去に色々な経緯からバージョンが固定されているGemがあり、月1のbundle updateで1年半程更新していないものもあった。railsのバージョンアップによる依存関係の解消時に大きくバージョン上げる必要があったため、検証負荷が高くなってしまった。
  • バージョンアップ用の環境を用意しておらず通常開発と同じ環境でバージョンアップの検証も行っていたため、通常開発業務の検証の際にバージョンアップを切り戻すといった作業が必要でメンテナンス負荷が高く、現状の検証環境のrailsのバージョンを把握しづらかった。

Try

  • Gemfileを読み解く会を開催し、経緯を理解した上で外せるものはバージョン固定を外す。
  • GemfileのVersion固定は、bundle updateのタイミングで見直す等の仕組み化を行う。
  • VersionUpのときは専用の環境を用意する。

Gemfileに記載されているgemがどのように使われているのか、なぜバージョンが固定化されているのかなどを読み解く会をやるといった今後のアクションに繋げることが出てきて、バージョンアップをするだけでなく、その過程で感じた問題等も話せたので振り返りいいのでは?という気持ちになりました🙌

おわりに

大分乗り遅れた感はありますが、今回はMedPeerをrails 5.2にバージョンアップした話でした。 現在6.0に関しても色々と情報が公開されてますが、次回の6.0に関しては乗り遅れずにバージョンアップ出来るように今回の反省を生かしていければと思います!

Railsフロントエンドボイラープレート「medpacker」の紹介

メドピアマッスル部のフロントエンドエンジニア村上(@pipopotamasu)です。

最近筋トレに時間を割かれ、家でコードが書く時間が減ってしまったのが悩みの種です。

今日は最近作ったメドピア用Railsフロントエンドのボイラープレート、「medpacker」を紹介しようと思います。

github.com

medpacker作成の背景

Railsには公式で大きく分けて2つのフロントエンドの環境があります、アセットパイプラインとwebpackerです。 これらはメドピアの既存プロダクトでも使ってきたのですが、プロダクトの規模が大きくなったり、時間が経つにつれて色々な辛みが見えるようになってきました。

アセットパイプライン

  • 最終的にJSやCSSのファイルを1つのファイルに出力するため、プロジェクトが大きくなってくるとファイルサイズが大きくなってしまう(キャッシュが効いてないと読み込みが遅すぎる、開発時のビルドに時間がかかる)
  • ES6+を使いたい場合はwebpack等のBundlerを自前で設定する必要がある(またはbundlerをwrapしているgemを使う必要がある)

webpacker

  • アセットパイプラインの欠点を解消(複数ファイル出力、webpackが設定済み)したのはよいが、webpackの設定がrailsにラップされすぎていてわかりづらい
  • 初期設定だとプロダクションビルドにsource mapがついていたりなど?な設定がある
  • webpack本体のバージョンアップについていけてない(webpackがv4なのに対して、webpackerはwebpack v3依存)

これらの辛みのため新規でRailsプロジェクトを作成する時、今まで通りアセットパイプラインやwebpackerで構築してしまっていいのかという疑問が生じてきました。 またフロントエンド開発をメインで行うのがサーバーサイドエンジニアや外部のフロントエンドエンジニアさんということもあり、プロジェクト間で採用技術や質を標準化するために、またフロントエンドの環境構築の時間短縮のためRailsフロントエンド用のボイラープレートを用意しそれを横展開するのがよいのではないか?

ということで、これらの辛みを克服するためにメドピア用Railsフロントエンド用のボイラープレート「medpacker」を作成しました。

medpackerのコンセプト

medpackerのコンセプトは大きく2つです。

素早く、簡単に導入できる

webpackerのような導入の簡単さを目指し、Railsのアプリケーションテンプレートを使用して設定できるようにしています。これによりrails newをしてから2~3分でフロントエンド環境を構築することができます。

だいたい開発や本番環境で必要なものが初期から設定されている

アプリケーションテンプレートで導入した直後から、webpack・babel・lint・postcss・minify等がすでにセットアップされているため、すぐに開発に着手できるようになっています。

Get started! 実際にmedpackerを導入してみる

それでは実際にmedpackerを導入してみましょう。

STEP1: medpackerをローカルにcloneする

$ git clone https://github.com/medpeer-inc/medpacker.git

STEP2: rails newした直後のrailsプロジェクトを用意する

$ rails new test-project

STEP3: アプリケーションテンプレートを用いて、先ほど作成したプロジェクトにmedpackerを適用する

$ cd test-project
$ bin/rails app:template LOCATION=path/to/medpacker/template.rb

この際いくつかCLIに質問されるので、用途に応じて答えてください。

remove 'app/assets'? y
remove 'test/'? y
need example page? y
Overwrite /Users/yamatomurakami/work/test-project/config/routes.rb? (enter "h" for help) [Ynaqdhm] a

STEP:4 railsを起動する

$ bin/rails s

サーバーを起動し、以下の画面が出たら導入完了です

( ※need example page?にyesで答えないとこのページは表示されません)。

f:id:ec0156hx39:20190122002939p:plain
medpacker_home

medpackerの中身について

作成に至った背景、コンセプトなどはすでに説明した通りです。ここではmedpackerの中身についてみていきます。

webpack

medpackerの核ともいうべきbundlerです。 もちろんフロントエンドのアセットをビルドするために入れてます。 Rails側でビルドしたアセットをHTMLに読み込むためのヘルパーを用意してあり、それを使うことで読み込むことができます。 productionモードでビルドするとCSS, JSがminifyされるようになっています。

webpack-dev-server

webpackでの開発をサポートするツールです。ざっくり以下のような機能があります。

  • JSを変更した時差分のビルドをしてくれる(webpackのwatchと同じ)

  • リロードせずに更新したファイルがブラウザに適用される(Hot module replacement, HMR)

  • 上記のHMRができない場合は自動的にブラウザをリロードし、更新分のアセットを取得する

CSS(SCSS), PostCSS

導入時点で、SCSSとPostCSSの設定がされています。

(※メドピアでは全てのRailsプロジェクトでSCSSを使用しているので、決め打ちで入れてあります)

またPostCSSで初期導入されているプラグインは以下2つです。

  • autoprefixer・・・自動的にベンダープレフィックスをつけてくれるライブラリ
  • postcss-flexbugs-fixes・・・ブラウザが潜在的に持っているflexboxのバグを踏まないように、自動整形してくれるライブラリ

babel

JSを色々なブラウザで読み込めるように(例えば最新の記法が古いブラウザでも読み込めるように)変形/代替してくれるライブラリになります。 導入時点で設定済みなので、IE11とか気にせずにJSを書いても問題ありません。

基本的にメドピアの推奨環境に合わせてありますが、この辺をいじれば対応ブラウザを変えることができます。

lint系

SCSSのlint(stylelint)とJSのlint(eslint)の2つが設定済みです。導入側のプロジェクトのCIに組み込んでおいてください。

Vue.js

medpackerに入れるか迷ったのですが、導入時にVue.jsが初期設定してあります。 個人的にJSライブラリを入れるのは本当に必要になった時に初めて入れればいいと思っているのですが、プロジェクト間での採用技術を統一するために入れてあります(以前とあるプロダクトで外部のエンジニアさんにお手伝いしていただいてた時、社内のほとんどのプロジェクトでVue.jsを使っているにも関わらず、しれっとReactが入っていたことがあったので...)。

工夫したところ

ライブラリアップデート

月1回のペースで、自動的にgemとnpmのアップデートPRがCIで作られるようになっています。 作成後は私がPR内容の確認・マージをしています(この辺は手動です)。 「medpackerを適用しようとしたがバージョンが古い...」というメンテされずに放置されるという事態は避けるようにしています。

アプリケーションテンプレートの使用

より楽にプロジェクトにmedpackerを適用するためにRailsのアプリケーションテンプレートを使用しました。 最初はこの便利機能の存在を知らずに、こちらの方法をメインの適用方法にと考えていました。今考えるととてつもなく使いづらいですね。。。

終わりに

現在メドピアでは3つのプロダクトでmedpackerを使用しています。 使っているうちに出てくる改善点や追加機能などは日々更新していく予定です。

もしこのブログを見た人で「うちではこんなの使ってるよー」とか知見がある人はこっそり教えていただけたらありがたいです。medpackerに取り入れるかもしれません。

またこのmedpackerを作る上でpixivさん、スタディストさんのブログを参考にさせていただきました。本当にありがとうございました。

今日から簡単!Webpacker 完全脱出ガイド - pixiv inside

フロントエンド原理主義者が目論んだ脱webpacker – スタディスト開発ブログ – Medium


(☝︎ ՞ਊ ՞)☝︎是非読者になってください


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

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

https://medpeer.co.jp/recruit/entry/

■開発環境はこちら

https://medpeer.co.jp/recruit/workplace/development.html

エンジニアのスキル底上げを目的として『テックサポート制度』を始めました!

こんにちは!メドピアエンジニアの難波です。

今回はメドピアで先月(2018年12月)から始まったテックサポート制度について紹介させて頂こうと思います。

『テックサポート制度』とは?

『テックサポート制度』とはエンジニアの開発力を底上げしてメドピアの事業開発を加速させることが目的の、1人あたり年間12万円まで開発効率・スキルの向上に関わるサポートを行う制度です。

最近色々な企業で同様の「AWSやGCPを積極的に触ってもらうために年間(月間)○○円まで個人で自由に使える制度を作りました!」という声を聞くようになりましたが、弊社ではAWSやGCPのようないわゆるIaaS以外にもElastic CloudやHerokuなどもOKです。他にもRubyMineやDashのような開発効率促進系ツール、珍しいものだとGo RailsやUdemyのようなオンライン学習サービスについてもサポート対象です。

サポート対象は基本的に社内ドキュメントに記載されているリストにあるものということになっておりますが、現場のエンジニアからCTOやエンジニアマネージャーに要望を挙げて、これは良さそうだねと判断されたものはすぐにリストに追加されるようになっています(まだ始まったばかりの制度なのでどんどんアップデートしています)。

ちなみに一部を抜粋すると現状このようなものが載っています。

実際に使ってみた感想

私の場合は早速以下の2つのツールにテックサポート制度を使いました。

  • Tower
    • 評判の良いGUIのgitクライアント。普段はCUIでgitコマンドを実行するのですが、デザイナの人に勧めることもあるので使い勝手を試してみたかったため
  • Microsoft Azure
    • AWSやGCPはよく使うのですが、Azureはあまり触っていなかったのでこの機会に使ってみることにしました

テックサポート制度が始まってからの印象ですが、普段良さそうなツールを見つけても有料だと「必要になったら改めて……」となりがちなのが「とりあえず試してみるか、サポートされるし。」に変わるのは心理的な障壁をなくす効果という点でとても良いなと感じています。

また自分自身での活用についてだけでなく、同僚(特にまだ経験の浅い人)に対して有料ツールを勧めやすいという効果もありました。経験の浅い人にこそ有料でも便利なツールを積極的に使ってもらうことで成長のきっかけとしていって欲しいのですが、今までは「オススメなんだけどちょっと高いんだよなあ」というように躊躇することがありました。それが「とりあえずテックサポートで試してみてよ」と言えるようになったのは良いですね。

メドピアのエンジニア支援制度

今回のテックサポート制度導入によってメドピアで行っているエンジニア支援の制度やイベントは以下のようになりました。

  • 書籍支援制度
  • イベント(カンファレンス等)参加支援制度
  • 開発合宿
  • ランチLT
  • 輪読会
  • 週次KPT
  • プルリク振り返り会
  • テックサポート制度 <- NEW!!

今後もメドピアではエンジニアがよりパフォーマンスを発揮できる環境づくりに注力していきますので、興味が有る方のご連絡をお待ちしております!


(☝︎ ՞ਊ ՞)☝︎是非読者になってください


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

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

https://medpeer.co.jp/recruit/entry/

■開発環境はこちら

https://medpeer.co.jp/recruit/workplace/development.html

新人エンジニアが開発合宿に参加してみて@湯河原

こんにちは!メドピア10月入社の新米エンジニアの宮原です。 今回のブログでは、メドピアで恒例となっている開発合宿に参加してきましたので、こちらの様子をお届けしたいと思います。

メドピアでは、これまでにも年2〜3回ぐらいのペースで開発合宿を開催しています。湯河原で開発合宿を行うのは、昨年3月以来になります。

tech.medpeer.co.jp tech.medpeer.co.jp

合宿テーマ

開発合宿のテーマは毎回異なり、技術研鑽や技術的負債の解消、他にも新規サービス立ち上げ等を行ったこともあります。過去の開発合宿では新規サービス立ち上げをテーマに実施され、弊社のサービスとして事業化されているものもあります。

合宿に行く前に各自、取り組む内容について宣言してから開発します。今回はこんな感じです。

  • 業務改善ツールの開発
  • メドピア既存サービスへの新機能開発
  • 新技術を使ったサービス開発

取り組み方は自由でチームを組んでも良し。個人でモクモクと取り組むも良し。特に制約は無いので、自身が取り組みたかった開発がしやすいです。 後日、オフィスにて合宿に参加できなかったエンジニアやデザイナーさんたちへ、成果報告LTをすることになりました。

開発合宿向きの旅館「湯河原 おんやど 恵」さん

今回の合宿は湯河原の「おんやど 恵(めぐみ)」さんにお邪魔しました。メドピアでは過去の合宿でも利用させていただいております。こちらの旅館は、SE出身の社長さんが経営されている旅館で、エンジニアに嬉しい「開発合宿プラン」などが用意されています。お隣にコンビニができたこともあり、お酒やお菓子などの補給線が確保されより開発向きになりました。

f:id:nyagato_00_miya:20181212153651p:plain

おんやど恵み 開発合宿プラン

当日は、湯河原駅に直接集合!湯河原駅近くの「トルティーノ」さんでランチをとってから一同、おんやど恵へ向かいます。

f:id:nyagato_00_miya:20181212153942j:plain
総勢15名の参加となりました!

開発の様子

到着後すぐに会議室へ向かいます。各々合宿で取り組むテーマを発表し、いざ開発スタートです。

会議室には、電源タップ、USB充電器、おやつ、ホワイトボード、腰サポートグッズ等、設備も充実。開発スタートから、もくもく作業をする人もいれば、リフレッシュも兼ねて一足先に温泉に浸かりに行く人も。 ※ディスプレイのレンタルプランもあるそうです。

f:id:nyagato_00_miya:20181212154443j:plain
今回のテーマをそれぞれ発表し、いざ開発開始です
f:id:nyagato_00_miya:20181212154251j:plain

基本的に、食事・お風呂・就寝以外の時間は開発タイムです。初日から夜遅くまで開発に没頭するメンバーもいました。

f:id:nyagato_00_miya:20181212154705j:plain
斯く言う私も、モクモクしていました

湯河原ご飯レポート

※美味しそうなご飯の写真が続きます。空腹時の閲覧はご注意ください

f:id:nyagato_00_miya:20181212155007p:plain f:id:nyagato_00_miya:20181212155013p:plain f:id:nyagato_00_miya:20181212155017p:plain

f:id:nyagato_00_miya:20181212155021p:plain
十二庵さんの豆腐プリンは絶品でした

最終日にランチに行った「うおたつ」さんには足湯もありました。 湯河原では、"足湯駆動開発"が大変捗ります。

最終日

2泊3日の楽しい合宿を終え、成果発表を行います。
技術研鑽に務める人もいれば、がっつりと作り込みデモまでする人まで各々の成果が発表されました。今回の合宿では、最も優れた発表には商品が進呈される!とのことで、みんな気合の入った発表が多かった印象です。

f:id:nyagato_00_miya:20181212154900p:plain
合宿の成果が発表されました

画像認識に取り組んでみました

私は、“食品判別AI”を作ってみました。メドピアにはグループ会社からDiet Plusというアプリがリリースされています。ユーザーから送られてきた食べ物の写真を、管理栄養士さんが確認して健康サポートをしてくれます。
そこで、食品の判別は自動化できそうだなと考えていたこともあり、合宿でやってみることにしました。

学習データの加工や、ニューラルネットワークの構築に時間を要しましたがなんとか形にすることができました。 今回は、GCPにVMのインスタンスを立てて、この中でSystemd + Nginx + uWSGI + Flaskのアプリケーションを動かしています。

f:id:nyagato_00_miya:20181212173511p:plain
お寿司が正しく判別された様子。

TensorFlowのサンプルの中に、再学習するサンプルが用意されています。簡単に画像認識を試す場合は、こちらを活用してみてください。
便利なことにTensorFlowでは、dockerイメージが公開されています。こちらを活用することで、めんどうな環境構築を一瞬で終わらせることができます。
(公式から公開されていると安心感がありますね) https://www.tensorflow.org/install/docker

例えば、猫の分類など行ってみましょう。ロシアンブルー、ペルシャ、メインクーン、ベンガルなどの画像を10枚程度集め、それぞれディレクトリに入れます。 こちらのディレクトリを指定して再学習を実行します。

$ cd cats
$ python3 retrain.py --image_dir ~/cats

学習結果を確認するには、label_image.pyを使います。以下のファイルをGithubからダウンロードし、retrain.pyと同じディレクトリに置きます。 https://github.com/tensorflow/tensorflow/raw/master/tensorflow/examples/label_image/label_image.py

以下の様に、再学習で生成された学習データを活用して判定させます。

$ python3 label_image.py \
--graph=~/tmp/output_graph.pb \
--labels=~/tmp/output_labels.txt \
--input_layer=Placeholder \
--output_layer=final_result \
--image=/cats/test/test_cat.jpg

するとどうでしょう、入力した猫の画像から、猫の種類を判別してくれます。学習データが10数枚であれば、ローカル環境で十分学習させることが可能です。
例で述べさせていただいた内容は、公式にチュートリアルとして掲載されています。ぜひ、トライしてみてください。
https://www.tensorflow.org/hub/tutorials/image_retraining

まとめ

開発合宿では、普段の業務でなかなか取り組めないタスクや負債を潰したり、新しい技術に集中して取り組める絶好の機会だと思います。 また、2泊3日という短い時間で成果を出す必要があるので、自身がこの短期間にどこまで出来るかを確認できる良い機会でもあると思います。 以上!2泊3日のメドピア開発合宿@湯河原 おんやど 恵のレポートでした。

追伸

合宿後の発表会で、僭越ながら私が、kenzoさんと同着で表彰されました。 まさかの同着1位ということもあり、2人で商品同等額を山分けさせていただきました。
頂いた賞金は、HHKB 無刻印を買う軍資金にさせていただこうと思っています。


(☝︎ ՞ਊ ՞)☝︎是非読者になってください


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

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

https://medpeer.co.jp/recruit/entry/

■開発環境はこちら

https://medpeer.co.jp/recruit/workplace/development.html

RubyWorld Conference2018にRubyスポンサーとして参加しました

こんにちは。メドピアのRailsエンジニアの小林です。遅くなってしまいましたが、11/1, 11/2に島根県松江市で行われたRubyWorld Conferenceに行ってきたので、レポートをお届けいたします。

2018.rubyworld-conf.org

多くの興味深いセッションが行われましたが、内容はRubyWorld Conferenceの公式YouTubeチャンネル*1から動画で見れるため、本記事では基調講演の大枠のまとめと、ブース出展の様子をお伝え致します。

今回、メドピアは初のブース出展(Rubyスポンサー)でした!そもそもRuby関連のイベントへのブース出展することが初なので、準備に手間取ることを予想して前日入りしました。

f:id:marikokobayashi:20181115235854j:plainf:id:marikokobayashi:20181116000544j:plain
f:id:marikokobayashi:20181115235910j:plainf:id:marikokobayashi:20181116000516j:plainf:id:marikokobayashi:20181116002319j:plain

1日目は開会挨拶と来賓挨拶からスタート。まずは島根県知事代理・松江市市長代理がいらっしゃってのご挨拶。島根県・松江市がRubyを使ったIT企業の支援に力を入れていることが伝わってきます。

Matzの基調講演 The power of the community

  • Rubyのこれまで歩んできた道
  • ピッケル本 (正式名: Programming Ruby: The Pragmatic Programmer's Guide、英語で初めて出版されたRuby本)の出版社のAddison-Wesleyから本を書きたいと連絡が来たときのお話
  • 最初のRubyConfのときのお話
  • Rubyのユーザー数の増加
  • Rubyコミュニティについて
  • Rubyのハイプサイクル
  • 「あきらめない」こと
  • 一歩踏み出すこと
  • Matzの引退とRuby4について(!)

などについて語っていただきました。

特にRubyコミュニティのお話が印象的でした。 もしRubyコミュニティが存在しなかったら、Rubyは今のような形では存在していなかっただろうとMatzはおっしゃいます。

Matzが発案したものではない機能が今ではRubyに欠かせないものとなっていますし、周囲の人がRubyのカンファレンスや勉強会の開催、Rubyの本の執筆等の活動をしたことでRubyは発展してきました。

RubyコミュニティはNiceなコミュニティです。

ですがRubyコミュニティの良いフィードバックをより長く強く維持していくために、Matzは「もう一歩だけ先に行ってほしい」と言っていました。

コンフォートゾーン、居心地が良い環境にいつづけるだけでは進歩がなくなってしまう。

新しいカンファレンスに出てみる、友だちを作ってみる、新しいことを試してみる、他の人を褒める、目を見て握手してみる、アイディアを出し合ってみる。そういったことをしてみて下さい、とのことでした。

「宿題を出します。カンファレンス全体で感じたことをなにかでシェアして下さい。ブログでもTwitterでもFacebookでもMediumでもQiitaでもいいのでシェアして下さい。皆さんにも一歩踏み出していただけたらいいなと思っています。それが未来を良くすると思います」とのことでした。

f:id:marikokobayashi:20181116000215j:plain

メドピアのスポンサーセッション(1日目のお昼)

メドピアのスポンサーセッションは1日目のお昼!CTOの福村が登壇しました。

f:id:marikokobayashi:20181116000247j:plainf:id:marikokobayashi:20181116000328j:plain

発表資料はこちらです。

メドピアの事業紹介、メドピアの働きやすい制度、それからエンジニア発信のしくみである「プルリク振り返り会」と、そこで過去に上がったTipsについて話してくれました。

今メドピアでは数多くのプロジェクトが走っており、PRが上がってきたら同プロジェクトのメンバーがPRをレビューするという体制になっています。

しかしそれだとプロジェクトを横断して全エンジニアが知っておいたほうが良い知識が共有されないので、そのようなPRを振り返って話すのが「プルリク振り返り会」です。この取り組みは他社のエンジニアさんとお話すると「良いね」と言ってもらえることが多いです。

気になるという方は、是非取り入れてみてください。また、取り入れた際は感想を共有してもらえると嬉しいです!

レセプション(懇親会)

1日目の最後にはレセプションがありました。夕食や美味しいお酒とともに、和気あいあいと、島根の学生や各地からの参加者と交流していた弊社メンバーたちでした。 しかし突然の出来事が…!

レセプションの中でTシャツのプレゼント企画を行っていたのですが、弊社参加メンバーの名前が突然壇上から呼ばれ、Tシャツが当たってしまいました!しかもMatzがそれにサインしてくださいました!

喜びと驚きで興奮状態の我々、写真を撮ったりしてはしゃいでいたうちに、近くにいらっしゃったRuby/Railsコミッターの松田さんにお声がけしたところ、松田さんもサインをくださり、そして松田さんがさらに他のRubyコミッターを呼び寄せ、その場にいらっしゃったRubyコミッターによるサインリレーが始まってしまい…

f:id:marikokobayashi:20181116001032j:plainf:id:marikokobayashi:20181116001056j:plain
(弊社メンバー大はしゃぎだったため失礼をしていたら大変申し訳ありません)

…最終的にこのようなTシャツになっていました。Rubyistからしたら完全にお宝ですね。

f:id:marikokobayashi:20181116001418j:plain

今回参加したメドピアメンバーにとって、思い出に残る1日となりました。

Chad Fowler氏基調講演 Don't Stop Moving

2日目のスタートは、RubyConfやRailsConfの共催者、The Passionate Programmer: Creating a Remarkable Career in Software Development (邦題: 情熱プログラマー ソフトウェア開発者の幸せな生き方 )の著者として知られるChad Fowler氏による基調講演でした!

私は彼の著書「情熱プログラマー」は読んだことがあり、感銘を受けた人間の一人ですが、講演を聴くのは初めてなのでわくわくしながら聞きました。

今回は、モチベーションの保ち方や、プログラマーとして生き抜くための戦略について教えてくださいました。

深さと広さ

テクノロジーの仕事をするときは、色々なテクノロジーを広く少しづつ学ぶか、一つのことを深く極めるか、どちらかの戦略を取ると思います。まず、どちらのキャリアを選ぶか決めましょう、という話でした。Chad氏は色々なテクノロジーを広く学ぶ方を選びました。

その道を進んだChad氏は、いろいろな人が新しいテクノロジーを追いかけていることを目の当たりにしますが、「こんな新しいものがいっぱいあるのだ」と驚いてしまったときに、自分のキャリアの中での初心を思い返そうと考えたそうです。

テクノロジーに興味を持ったきっかけとなったビデオゲームである World War Craft のことを思い出してみたら、キャラクター育成の際に最初に「魔術師」「戦士」などを選び、スキルツリーからスキルカテゴリを選んで、どのように育成するかを選んでいました。

それと同じことで、テクノロジーの仕事をするときも、ひとつひとつの細かいことを気にせず、スキルカテゴリを見つけ出すことが大事だとのことです。

1996年頃にメンターの先輩から教わったことがあったそうです。当時は、ディレクトリサービス/UNIX/プログラミング言語という3つのカテゴリを軸に理解すれば、良いキャリアのスタートとなると言われたとのことでした(それぞれのカテゴリについて理解すればその中で具体的に何を選んで学ぶかは重要ではないとのこと)。

2018年の今、同じことを考えた場合、Chad氏が見出した3つのカテゴリは

  • オペレーティングシステム
  • データベース
  • プログラミング言語

とのことです。 さらに、それぞれのカテゴリの中でさらに、3つのカテゴリを見つけると良いとのことです。例えば言語であれば

  • オブジェクト指向言語(Ruby、Pythonなど)
  • Haskell/OCamlのような関数型言語
  • LISP

を挙げていました。これらは、「必要だから学べ」ということではなく、自分の知っている部分と別のカテゴリにおいては考え方の違いを知るのに頭を使うので、実際にはRubyだけで食べていくことができても、 違うカテゴリのものを学ぶことはテクノロジーを広く知るためには役に立つということをおっしゃっていました。

Technology is a fashion

  • ファッションは進化し続けています。全てに付いていくは大変です。テクノロジーもそれと同じ。全部追いかけ回すと全部やらなければいけない、全部最新の流行を理解しないといけないと思うとやる気が無くなってしまう。それよりも自分が安定して取り組めるものにきっちりついていったほうが良いというお話がありました。

自発的な動機づけと外的な動機づけ

  • 外からアメやムチで人を動かそうとしても、結果は出せず、自発的な動機があって初めて結果が出せます。ダニエル・ピンク氏の著書 Drive (邦題: モチベーション3.0 )でも、モチベーションを持つには「自発的であること」「熟練すること」「目標があること」が大事と書かれています。

  • Chad氏も、最初にDave Thomas氏に「情熱プログラマー」を書いてくれと言われた時は、正直大変だなと思ったらしいです。本を書いて有名になりたい気持ちもあったが、それは外的動機づけなのであまり気持ちが乗らなかったとのこと。 しかし、この本を書くことでだれか1人の人間でも幸福にする事ができるかもしれないという自発的なモチベーションを持ったことで、書き上げることができたというお話でした。

「情熱プログラマー」を読んだことでソフトウェア開発者としての生き方を見つめ直したという人も多いのではないでしょうか。その著者自身の執筆のモチベーションのお話を伺ったことで、私ももっと自発的な動機づけをもって物事に取り組もうという気持ちが高まりました。

ブース

ブースでは、弊社のメインサービスである医師向けコミュニティサイト「メドピア」の紹介の他に、子会社Mediplatの遠隔診療サービス「first call」と、同じく子会社FitsPlusの管理栄養士による食事アドバイスアプリ「DietPlus」のご紹介をさせていただいておりました。

f:id:marikokobayashi:20181116002650j:plain

また、PeerWaterというお水とメドベアのステッカー(メドピアの熊キャラクターなので「メドベア」です)を無料で配布していたのですが、ステッカーの評判が良かったですね。ちなみにMatzにも1日目にブースにいらっしゃった時に渡したのですが、気に入っていただけたのか、2日目にもブースに来てくださって数枚持って帰ってくださっていたぐらいです。(メドベアグッズ出したらもしかして需要あるんでしょうか…)

観光

あまり観光の時間は多く取れなかったのですが、前日入りした日には少し松江の空気を味わうことができました。

f:id:marikokobayashi:20181116000111j:plainf:id:marikokobayashi:20181116000015j:plainf:id:marikokobayashi:20181116000032j:plainf:id:marikokobayashi:20181116000052j:plain

初日夕食には美味しいご飯をいただきました。お邪魔したのは「おでん庄助」さん。地元の人にも知られたおでん屋さんです。我々が向かったときはもうすでにメニューの売り切れが多くて「メニューは選べないけど盛り合わせなら出せますよ」とのことでした。

f:id:marikokobayashi:20181116132531j:plainf:id:marikokobayashi:20181116132617j:plain

いただいた盛り合わせはどれも美味しかったです。東京だったらもっと高いであろう夕ご飯が地方価格でしかも美味しい…ワインの種類も豊富に用意されており弊社のワイン大好き社員が感激のあまりワイン講義を初め出すほどでした。

次回以降のRWCなどで松江市観光を検討されている方へ向けたアドバイスを一つ書いておきます。松江市周辺で外食できるお店は全体的に東京より閉まるのが早かったりメニューがなくなるのが早いので、東京の時間感覚で行くとご飯難民になる可能性があります。

この日私達は8時ぐらいからご飯場所を探しましたが、他のお店で「もうご飯がない」と断わられていました。庄助さんで美味しいおでんにありつけたのは運が良かったです。

2日目のアフターパーティには出ずに帰りましたが、初の島根・松江だったメンバーが多かったので、もっとゆっくりすればよかったかもしれないですね。しかしそれはまたいつか機会があるときにリベンジしたいですね。

まとめ

Ruby関連のイベントにスポンサーブースを出すのは初めてで慣れない箇所もありましたが、メドピアを知っていただく機会が増え、多くの方との交流ができたことが嬉しかったです。

個人的な話となりますが、私は地方出身の人間なので、地方のIT産業の活性化には興味があります。

松江の学生は、学生のうちからこのような世界レベルのRubyプログラマーのセッションを自分の地元で聞ける機会に恵まれていて素晴らしいなと思いましたし、島根県・松江市にはこういった取り組みをぜひこれからも続けてほしいと思いました。

弊社としても、今後もこのようなスポンサーの機会がまたあれば良いなと思っております。

f:id:marikokobayashi:20181116002540j:plain

以上、RubyWorld Conference2018のレポートをお届けいたしました!


(☝︎ ՞ਊ ՞)☝︎是非読者になってください


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

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

https://medpeer.co.jp/recruit/entry/

■開発環境はこちら

https://medpeer.co.jp/recruit/workplace/development.html

メドピア に整地部ができたってよ!

はじめに

こんにちは、メドピアの駆け出しエンジニアの川﨑です。

最近我が広島カープが日本シリーズ進出を決めて機嫌が良いのでブログ書きたいと思います。

今回僕がお届けするのは、先月の9月14日 「Rails開発での技術的負債との付き合い方」 をテーマに開催された 「MedBeer」 にて、 Classi株式会社のCTOである佐々木 達也(@sasata299)さんの発表にて紹介された「整地部」がMedPeerでもできたよ!というお話です。

整地部とは?

整地部の定義に関しては、以下にある佐々木 達也さん の興奮する資料が分かりやすいです。

一言で言うと

技術的負債となっているコードを少しずつでも良くしたい人たちの集まり

です。

どんな風に進めたか?

記念すべき第一回は、弊社Railsの技術顧問である前島(@willnet)さんがいらっしゃる水曜日に開催されました。

進め方としては、僕が前々から直したいと思っていた箇所を自分なりに修正したPRを作っていたので、そのPRを元にモブプロで洗練させる形をとりました。

今回の整地対象は?

MedPeerでは製薬企業様から医師の方々へ向けた講演会をWeb上で行えるサービスを展開しており、講演会サービスのTOPページではオススメの講演会をスライドで表示しています。

そのスライドに表示する講演会の情報を抽出するロジックが今回の整地対象となりました。

対象となった理由は以下の通りです。

  • 講演会の情報を抽出するロジックが少し複雑
  • ロジックが書かれているモデルが300行を超え肥大している
  • ActiveRecord のメソッドを使えば良いところが散見される
  • メソッド/変数/定数の名前がわかりにくい

どんなことをしたのか?

前提として

・ロジックが書かれているモデルが300行を超え肥大している

という問題に辛さを感じていたので、以下前島さんの記事を参考にしつつ、対象の処理を単機能として一つのクラスへ切り出す方針で進みました。

tech.medpeer.co.jp

クラスに切り出した後は主に以下のことを行いました。

  • 1メソッドでやるべきでない処理を分けてわかりやすくする
  • メソッド/変数/定数の名前をいい感じにする
  • ActiveRecord のメソッドを使った方が良いところは使うようにする

実例

ここで実際に整地された例を一つご紹介します。

今回クラスへ切り出したコードの中で次のようなメソッドがありました。

  def today_conferences(conferences)
    newly_start_at(conferences.find_all { |c| c.start_at.today? }, TODAY_RECOMMENDATION_COUNT)
  end

  def newly_start_at(conferences, limit) 
    conferences.sort_by(&:start_at)[0..limit] 
  end

このメソッドでやりたいことは次の通りです。

  1. 取得した講演会から当日開催のものだけ抽出
  2. 開催日の昇順ソート
  3. 先頭からlimit取得

やりたいことは実装できていますが辛いですね。

今回は ActiveRecord のメソッド where,order,limit を使って次のように修正を行いました。

  def today_conferences
    conferences.where(start_at: Time.zone.today.all_day)
               .order(:start_at)
               .limit(TODAY_RECOMMENDATION_COUNT)
  end

Rubyの世界でのごちゃごちゃした処理がなくスッキリ書けているので、やりたいことが明確になり可読性が上がったかと思います。

実際やってみた感想

実際やってみて特にデメリットは感じないほど良い活動だったと思います。

メリットはたくさんありましたが、個人的に強く感じたことは次の2点です。

  • レベルが高いエンジニアの方と一緒にモブプロするのすごい勉強になる
  • プロジェクトへ貢献するチャンス(特に僕のような新人エンジニア)

一つ目はそのままの意味で、実装するときの考え方や気をつけることを学べる場にもなると思います。

二つ目についてですが、新人エンジニアは実力的にプロジェクトへ大きく貢献することが難しいと思います。

そういった状況でも、整地部の活動へ積極的に参加することで、技術的負債を作らない方法を学びながらプロジェクトに貢献できる点がメリットだと感じています。

今後はどんな感じで進めて行くのか?

実際に活動してみて割と大きな修正が必要なものが見えてきたこともあり、今後は以下のような方法で活動を進めて行く予定です。

・活動頻度は1回1.5h/隔週
・大きな修正は技術力の高いエンジニアでモブプロ
・新人エンジニアは上記モブプロを見て勉強したり、自分で修正できる箇所があれば整地する(必要であればペアプロ依頼)

また、工夫ではないですが、整地活動をする上でやっておいた方が良いこととして、以下2点を意識すると良いと思いました。

・新人エンジニア場合、余裕があれば事前に自分なりに修正したPRを作っておく
・小さいもので良いので、1つはPRを作るところまで対応する

今後の活動へ向けた気持ち

当然ですが大きな成果が出たりする活動ではないので、地道に続けていくことが重要だと思います。

佐々木 達也さんの発表でもありましたが、小さな修正を続けて成功体験を増やしていくことがとても重要だと感じておりますので、僕自身も積極的に活動へ参加したいと思っております。

おわりに

今回はMedPeerで始まった新たな取り組みについてのご紹介でした。

技術的負債は作らないのが一番ですが、長くシステムを運用していく中で浮き彫りになってくるものもあるかと思います。

技術的負債に目をつぶらず、積極的に立ち向かうチームが社内にできたことそのものがとても素晴らしいことだと感じています。

今後も負債に負けない柔軟で堅牢なシステムを維持するべく整地部は突き進みます!!!


(☝︎ ՞ਊ ՞)☝︎是非読者になってください


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

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

https://medpeer.co.jp/recruit/entry/

■開発環境はこちら

https://medpeer.co.jp/recruit/workplace/development.html