読者です 読者をやめる 読者になる 読者になる

5年モノのサービスに1ヶ月で Sass(SCSS) を導入したお話

皆さんこんにちは、メディカルサービス部エンジニアの中村です。
好きなブキはスプラチャージャーワカメです。

先日、5年程稼働しているサービスへ Sass(SCSS) を導入したのでその技術的知見を共有させていただきます。

f:id:yuzurunakamura:20160128143430p:plain

なお、Sass は現在 SCSS Syntax が主流の為、CSS プリプロセッサについては Sass, ファイルタイプについては SCSS と表記します。

状況と経緯

メドピア株式会社では、医師限定サービス MedPeer を運営しています。
MedPeer サービス内ではさらに、薬剤評価掲示版、症例検討会、症例相談、ディスカッションなど、機能の異なる約10種のサービスを提供しております。

2011年頃、MedPeer サービスは現在稼働している Web アプリケーションフレームワークに移行しました。
長らく運用されてきたサービスのフロントエンドは、外注や様々な経緯を経て以下のような問題を抱えておりました。

  • Bootstrap v2.0.2 のまま。しかし bootstrap.css が大量に書き換えられておりバージョン追従不可
  • DOM が Grid system に沿っていない
  • bootstrap.css に一部でしか使われていないスタイルが大量に定義、さらに個別サービス用 CSS にも重複したスタイル定義
  • CSS 構文エラーが大量に存在する
  • HTML テンプレート内の style 要素に直書き
  • !important の嵐。そして !important をオーバーライドする為、別箇所でさらに !important の嵐...

要するに、長年運用されてきたサービスによくある技術的負債が積もった状態でした。

HTML テンプレートの DOM を見直したい、CSS も見直したい、UI も見直したい。しかし量が多い。
やりたいことは幾つもありましたが、問題を切り分け、Bootstrap3 に対応した新しい HTML テンプレートへの移行を少しずつ進めつつ、サイトデザインやボタン類に利用されている CSS 部分を、既存のこんがらがった bootstrap.css や他 CSS からサルベージし、新規に CSS を構成し直すことにしました。

そして、折角なのでこのタイミングで Sass へ移行する舵取りを行いました。
CSS をスクラッチで大量に書き換える必要がある為、CSS プリプロセッサを導入してもっと楽で管理しやすい形で書きたいよねというのが動機でした。

Bootstrap は v4 から less から Sass になったことと、デザイナからゆくゆくは Compass Helper Functions も使いたいとの要望を考慮に入れ、less ではなくSass 導入を決めました。

Sass 導入プラン

導入プランとして、以下の3案がありました。

1. *.css をすべて *.scss に一括置換し、リポジトリから CSS はすべて無くす。

1.は、リポジトリから一括で CSS を排除するプランです。
CSS はそのままでも SCSS Syntax として読み込み可能なので 、機械的に一括置換し後々 SCSS を整理していこうというプランです。

しかし、既存コードの中には CSS 構文エラーやブラウザハック系の CSS が含まれており、置換後の SCSS から生成した CSS が当初の CSS と異なるケースがありました。
さらに、機械的に構文エラーを修正すると、適用されていなかったスタイルが適用されるようになり、思わぬ所でデザイン崩れが発生する可能性もありました。
構文エラーの種類によってはブラウザ側で許容し適用してくれていた箇所もあり、これもまた当初のデザインと異なる可能性が否定できません。

一括置換しただけではスタイル定義重複などの煩雑な構成が解決されないことからも、このプランは見送りとなりました。

2. CSS をすべて SCSS に手動で全部一度に書き換える。エンジニアとデザイナは死ぬ。

2.も、リポジトリから一括で CSS を排除するプランです。 HTML も CSS も問題があるから両方全部直したい!というよくあるプランですが、一度に複数のことをやろうとすると大抵破綻します。 他の開発案件も当然ありますし、作業量が膨大になることからこのプランも見送りとなりました。

1, 2共に E2E テストを併用した HTML, CSS 同時改修も検討したのですが、この記事の執筆時点で MedPeer のリポジトリには、HTML テンプレートが451ファイル・53701行、CSS が123ファイル・47294行があり、ユーザの属性ごとに出し分けするコンテンツも多く存在する為、一度に行うのは困難だと判断しました。

3. 移行期間中、一時的に CSS と SCSS が混在することを許容し、各サービス単位で徐々に移行する。

最終的には無難なプランでの導入となりました。

CSS と SCSS がリポジトリ上に混在することで、SCSS から生成された CSS を別の人が直接編集し、SCSS と CSS の整合性が取れなくなる懸念がありますが、SCSS から生成する際には compressed されたワンライナーCSS にすることで、誰が見ても生成された CSS と分かるようにしています。
最初の段階で共通 CSS はすべて SCSS にしておき、新規ページも原則 SCSS で作成することで、徐々に CSS を減らしていきます。

CSSリポジトリから無くすのが最終目標になります。

Sass 導入

導入プランも決まった所でいよいよ Sass 導入です。
導入に際して以下を実施しました。

  • Node.js, gulp 環境の構築
  • コーディングスタイルガイドの策定
  • scss-lint の導入
  • Browsersync の導入

Node.js, gulp 環境の構築

Sass 導入にあたって、デザイナでも簡単に環境構築できる環境が必要です。
極力 $ npm install 一発で済むように package.json に gulp も含め管理するようにしました。 global でなく local にインストールした gulp を使うようにしておくことで、環境差異をできるだけ少なくしています。

local の gulp 実行は、package.json"scripts" に以下のように記述するとOKです。

  "scripts": {
    "start": "gulp default",
    "gulp": "gulp",
    "scss": "gulp scss",
    "scss-lint": "gulp scss-lint"
  },

上記の場合、 $ npm startgulp default が実行されます。

コーディングスタイルガイドの策定

社内には PHP のコーディングスタイルガイドはあったのですが、CSS に関してはありませんでした。 過去の技術的負債はサービス開発全体に於けるコーディング流儀が統一されていなかったことにも要因がありますので、この問題にも対応しなければなりません。

ちょうど弊社の凄腕フロントエンドエンジニアがスタイルガイド策定準備を進めていてくれたので、このタイミングで社内公開を行いました。
あくまで社内向けスタイルガイドの為この記事では公開しませんが、概ね以下の著名なスタイルガイドを継承したものになります。

しかし、コーディングスタイルガイドを策定したからといって、すべてのコードがスタイルガイドに従ったものになるとは限りません。

scss-lint の導入

すべてのコードをスタイルガイドに合わせるべく、 scss-lint も併せて導入しました。

  • 後で導入すると、既存コードの修正は放置されがち
  • 早い段階で一定のフォーマットに整えておき、後程の新たな技術的負債を防ぎたかった
  • 過去に既存リポジトリPHP CodeSniffer と PHP Mess Detector の導入を試みたが、なかなか徹底されず頓挫してしまった
    • 一方、当初からCircle CIと共に導入した別プロジェクトでは問題なくlint活動が行われていた

などが主な動機です。

SCSS の lint ツールは幾つかありましたが、コード内で特定箇所のみルールの除外が可能だった為 Ruby 実装ではありますが scss-lint にしました。
できれば Node.js だけで完結したかったのですが、Node.js 実装の lint ツールは現時点ではルールの除外ができなかったり、CLI 出力やオプション設定などで総合的に満足いくものが現状ありませんでした。

gulp-scss-lint と併用し、gulp watchで *.scss 変更時に自動で lint 警告を gulp log に流すことで lint の徹底を行っています。

GitHub - brigade/scss-lint: Configurable tool for writing clean and consistent SCSSgithub.com github.com

インデントやシングル/ダブルクォートなど、細かいフォーマットを指摘は lint ツールに任せた方が角が立たずオススメです。
前述のスタイルガイドは .scss-lint.yml に反映し、自然とスタイルガイドに沿ったコーディングになるようにしています。

また、 csscomb も適宜利用し、自動での修正もサポートしています。
PropertySortOrder などの修正は面倒ですからね。

Browsersyrc の導入

このタイミングで以前から個人的に使っていた Browsersync も配布しました。
大量に SCSS を書き換える際に抜群の効果を発揮します。

Browsersync については以前こんな記事を書きました。

tech.medpeer.co.jp

Browsersync 利用時の WebFont の Cross-Origin Resource Sharing 設定

defalut では Browsersync は localhost:3000 で動作します。
その為、CDN に WebFont を置いている場合には Cross-Origin Resource Sharing policy( CORS 設定) の為に読み込みが行われません。

とはいえ、CloudFront や S3 の CORS 設定に localhost:3000 を許可してしまうのはセキュリティ上好ましくありません。
そこで今回は、Browsersync 用の hosts を追加し、CORS 設定で許可することで WebFont も読み込み可能にしました。

127.0.0.1 browsersync.example.com
browserSync({
  host: 'browsersync.example.com',
  open: 'external',
});

(個人的な話) Vim

個人的に Vim 上でも scss-lint を実行するようにしました。

Vim での Syntax Check Plugin は Syntastic が著名ですが、同期実行の為 Vim が固まりがちなのが課題でした。
vim-watchdogs は非同期実行の為、この懸念がありませんのでこのタイミングで乗り換えました。

おおよそ以下のような設定を書くことで、指定の .scss-lint.yml を読み込んで実行が可能です。

let g:quickrun_config = {
  \ 'watchdogs_checker/_': {
  \   'hook/time/enable': 0,
  \   'hook/back_window/enable_exit' : 1
  \ },
  \ 'scss/watchdogs_checker': {
  \   'type': 'watchdogs_checker/scss-lint',
  \   'cmdopt': '-c $HOME/.config/.scss-lint.yml'
  \ }
  \}

let g:watchdogs_check_BufWritePost_enable = 1
let g:watchdogs_check_CursorHold_enable = 1
let g:watchdogs_check_BufWritePost_enable_on_wq = 0
call watchdogs#setup(g:quickrun_config)

詳しくは vim-watchdogs/README.md を参照してください。

また、CSScomb も vim-csscomb を利用することで :CSScomb で実行可能にしています。

社内周知と公開

さてさて、上記のような環境を用意しましたが、突然「使ってください!!!!」といっても、Sass 経験のないエンジニアや Terminal に慣れてないデザイナにはとっつきにくいかもしれません。

メリットを上手く説明し、納得して使ってもらう普及活動が必要です。
恐らく、新しい環境を導入する際に、最も重要で、最も難しいポイントです。

どうやって周知するか悩んでおりましたが、ちょうど弊社では月一でピザを食べつつ LT を行う、通称ピザ会を開催しているので、この時に Sass と開発環境の説明を行いつつ、社内公開を行いました。

なお、突然 LT で「merge しろ!!」「使ってくれ!!」 といっても「何言ってんだこいつ」となるかなと思ったので、関係者ほぼ全員に事前に承認ラリーを行いました。

tech.medpeer.co.jp

マイクロソフトVisual Studio Code をイベント中にライブで GitHub に公開したように、その場で Pull Request に LGTM を貰いカッコ良く公開したかったのですが、カッコ良くは行かなかったのが反省点です。

とはいえコレで Sass 環境の配布が完了しました。

まとめ

以上の流れで MedPeer では Sass 導入を実施しました。 Slack を眺めて振り返ってみたところ、大体1ヶ月程度で導入まで漕ぎ着けることができました。 導入しようと決めてからは、あれこれ決めることが多かったのですが、思ったよりすんなり進められた印象です。
今後は Sass 移行を進めつつパーシャルファイルに分け、modularize を進めていくことになりますが、CSSに比べ格段に書きやすいので以前より開発が進めやすくなったと実感しています。

Sass 導入を検討されている方の参考になれば幸いです。

Golang(Go言語)を採用して、たった二人で基盤となるAPIゲートウェイを開発した話

はじめに

初めまして、気がつけば先月の25日で入社1年目を迎えた、
技術部 & Sake部部長@shinofara(篠原)です。
1月頃からGo言語(Golang ばかり触りすぎて、PHPをたまに触ると; を忘れて怒られます。
困ったものです....

今回は、僕も含めた2名で進めてきた、弊社初の Go言語(Golang プロダクトについてのお話をしたいと思います。
少し長いですが、お付き合いいただければとてもうれしいです!

※関係無いですが、gopher君可愛いです。

f:id:shinofara:20151209165705p:plain

Go言語のロゴ、マスコットは2009年にRenée French(http://reneefrench.blogspot.jp/)さんによって作成・公表されました。 これらはCreative Commons Attribution 3.0 Unported License(http://creativecommons.org/licenses/by/3.0/)で保護されています。 ライセンスの全文はhttps://golang.org/doc/gopher/README をご覧ください。

さて、本題に入りたいと思います。

先月末、2015年11月25日に JSON RPC API ゲートウェイ のリリースを行いました。
(と言っても社内限定利用ですが)
開発には Go言語(Golang を採用しています。
アプリ開発を除くと、PHP以外で開発した弊社初のプロダクトになります。

当記事では、MedPeer × Go言語(Golang での開発に関して
下記の三点にフォーカスしてお話していきたいと思います。

  1. Go言語(Golang でのゲートウェイ開発が始まった経緯
  2. どのような体制・環境でゲートウェイの開発を行ったか
  3. 今後どうして行きたいか

なぜ Go言語(Golang でのプロダクト開発が始まったのか

ゲートウェイ作成の背景

弊社のサービスは、良くも悪くもモノリシック として、今まで提供してきました。 モノリシック でもスケールさせ続ける事は可能ですが、以下の様な問題が発生しやすくなります。

  1. 小さい機能ひとつのデプロイだとしても、アプリケーション全体に影響を与える事が考えられます。
  2. ソースコードの肥大化に伴い、複雑性も高まってしまう為、修正の影響範囲が特定し辛くなると考えられます。

などなど、モノリシック から マイクロサービス にしていく事に関しては、様々なTech Blogなどで公開されておりますので、今回は省略させていただきます。

マイクロサービス については、最近 株式会社FiNCがslideshareに公開した、以下のスライドがわかりやすいかと思います。

引用元:株式会社FiNC, slideshare)

そして、弊社でマイクロサービス 化を実現する為に、クライアントの認証と、APIへのアクセス制御を考慮した結果ゲートウェイの開発を行う事となりました。

実際に作成したゲートウェイの簡単な図を載せておきます。

f:id:shinofara:20151210155610p:plain

PHPカンパニーが、Go言語(Golang)導入をどの様に決定したのか

今回開発する事になったゲートウェイの開発初期段階に、以下の事を考えた結果、
Go言語(Golang でやってみようという事になりました。

  • 求められている事は何なのか?
  • 求められている事に一番最適な言語は何なのか?

最後の方は勢いだったかもしれません。

全てをお話する事はできませんが、掻い摘みますと 以下の内容になります。

なぜGo言語(Golang)なのか?

  1. 静的型付け言語である事
    コンパイル時に、型の不整合に起因するバグを捕捉する事ができます。
    それ故に開発サイクルの後でバグ修正する多くのコスト、またはその場所で起こる多くのバグのコストを取り除く事ができるからです。 メリットは分かるのですが、やはり動的型付け言語経験者からすると、煩わしかったりもします。
    ですが、 Go言語(Golang には、型推論があるおかげで、静的型付けで型の恩恵を受けながら違和感無く開発できますので、とても親しみやすいです。

  2. 大抵の必要な物は、標準ライブラリに含まれている
    Go言語(Golang は十分な標準ライブラリが潤沢ですので、言語自体をインストールするだけで大抵の事が可能になります。

  3. 本番環境でGo言語を動かす為に必要な物は何一つ準備しなくてよい コンパイルする手間は発生してしまいますが、コンパイル後のバイナリを実行するだけでアプリケーションを立ち上げる事ができます。
    本番構築に関しては後述しますが、環境構築をとてもシンプルに保てると思いました。

Golangにする事で発生するデメリットは何なのか

  • 不慣れな言語に対する学習コスト
    Golangで実戦経験0の状態で着手した事も有りますが、どんな言語でも学習コストは発生してしまいます。
  • 依存管理が課題
    公式では、ベンダー管理が未サポート(1.5 からvendorを使ったコンパイルをサポートはしているが、管理に関してはまだです)
    今後この辺りが公式サポートされるのかは要観察です。

ゲートウェイのインフラ周辺、利用したライブラリや、技術について

今回は深くは説明することが出来ませんので、使っている環境、技術などをさっと紹介したいと思います。
詳細に関しては、またお話させていただければと思います。

言語

もちろん Go言語,Golang 1.5
開発初期は 1.4 でしたが、vendorサポート など恩恵を受けたい機能追加がありましたので、早い段階から1.5 を使い始めました。

開発環境

go の開発自体はmacでも問題無くできるのですが、mysql や関係するサービス環境を誰が作っても再現できるようにする為に、docker-compose を使って確認を行っています。

docker 実行環境は docker-machine を使って立ち上げています。

開発支援

開発時には以下のコマンドを使ってコーディングスタイルなどの統一化を行う様にしています。

依存管理

良くなかった事でも書きましたが、まだ公式では依存するパッケージのバージョン管理方法に関しては、未サポートなので、実行タイミングや、実行者、環境によってパッケージのバージョンが変わってしまう問題が発生してしまいます。

その為、弊社ではGoogleの公式ドキュメントで推奨と書かれている GO15VENDOREXPERIMENTの使い方 を参考にして、バージョンの固定とvendorを使ったコンパイルを実現する事で、誰がコンパイルしても同じ結果を得られる状態にしています。

  • バージョン管理は、PHPcomposerrubybundler に似た、glideを使ってvendorのバージョン管理しています。
  • vendorを使ったコンパイルは、バージョン 1.5サポートされた設定 を使って、GOPATH よりvendor/... を優先して参照させるようにしています。

現在の所、特に問題なく使えてるため、最近はオススメっす!といろいろな場所で話をしています。

マイグレーション

Go言語で作成された、goose を使ってスキーマ管理とマイグレーションを行っています。
使って見た感想としては、とてもシンプルで使い勝手がよく現時点では満足しています。

バリデーション

バリデーションには、gojsonschemaを採用しています。 ゲートウェイ開発では、Request/Responseのスキーマ定義をJSON-Schemaを採用していますので、gojsonschema を使う事で、ドキュメントとバリデーションの設定が同時に変更できるというメリットを得ることができています。

ユニットテスト

Go言語(Golang で標準に用意されているtestパッケージのtestingを使っています。
assert とか無く不便かな?と思ってましたが、特に不便なく使えています。

CI(継続的インテグレーションツール

CIツールは、Github Enterprise と連携可能な CircleCI Enterprise を利用しています。

クラウドCircleCI では、golang 1.5 のサポートが開始しているのですが、
エンタープライズ版では 1.4 の為、cricle.yml を以下の様に記述しています。

※サポートを今か今かと楽しみに待っています!!(切実

machine:
  environment:
    GO15VENDOREXPERIMENT: 1
    GOROOT: "/home/ubuntu/.go"
    GOPATH: "/home/ubuntu/go"
    PATH: "/home/ubuntu/.go/bin:$PATH"

dependencies:
  cache_directories:
    - "/home/ubuntu/.go"
  pre:
    - if [[ ! -e /home/ubuntu/.go/bin/go ]]; then cd /home/ubuntu; curl https://storage.googleapis.com/golang/go1.5.2.linux-amd64.tar.gz | tar -xz; mv go .go; fi
  override:
    - mkdir -p $HOME/go/src/path/to/organization
    - ln -s $HOME/$CIRCLE_PROJECT_REPONAME $HOME/go/src/path/to/organization

test:
  override:
    - |
      cd $HOME/go/src/go/src/path/to/organization/$CIRCLE_PROJECT_REPONAME;
      go vet $(go list ./...|grep -v vendor);
    - |
      cd $HOME/go/src/go/src/path/to/organization/$CIRCLE_PROJECT_REPONAME;
      go test $(go list ./...|grep -v vendor);

一覧がGreenだと嬉しいですね! f:id:shinofara:20151204172353p:plain

テスト結果はこんな感じです。

f:id:shinofara:20151204172358p:plain

フレームワーク

使用しておりません。 この辺りに関しては、次回お話できればと思います。

本番環境構築

ゲートウェイの本番環境は、AWS上に構築しています。
構築に利用した技術は、以下の2点です。

Goの場合は本番環境にGo言語自体の実行環境は不要ですが、Nginx などいくつか必要なパッケージがありますので、それらの構成管理として利用しています。
また、terraformはvpc全体のインフラ構成を管理する為に利用しています。
どちらもなれるまでは大変でしたが、なれてみると一昔前の構築にものすごく時間がかかっていた時代は何だったのか!と思いました。

開発からデプロイの簡単な流れ

今回は各工程の深掘りは出来ないですが、よくある図で表してみました。

f:id:shinofara:20151209022708j:plain

今後どうして行きたいか

弊社での Go言語(Golang を使ったプロジェクトはリリースで終わりではありません、ここからが本当の意味でのスタートとなります。

今後は、更に踏み込んだ技術のお話などをブログで公開していく予定です。 例えば開発現場についてとか、フレームワークを使わずに、どの様に開発をしたかなど

もし、弊社のプロダクトや、Go言語(Golang に関して少しでも興味がありましたら、ぜひ一緒に働きましょう! 気軽にお声がけくだされば、ランチとかでも大丈夫です!!

ついにHealth 2.0が日本上陸 - 新しいHealthTechの発展の場

こんにちは、@fukumuraです。

メドピアでCTOをやってます。よろしくお願いします。

はじめに

ここは技術ブログですが、 本日は技術の話はせずに「Health 2.0」の話を中心に 来週11/4-5に日本で初開催する「Health 2.0 ASIA-JAPAN」の話もしたいと思います。

Health 2.0とは

皆様、Health 2.0という言葉を聞いたことがありますでしょうか? (2.0は少し古い感じはしますよね、、、でもヘルスケア業界はまだ2.0の段階です)

Health 2.0とは、米国サンフランシスコを拠点に2007年に生まれたHealthTechのカンファレンスです。 新しいHealthTechの発展のために、大企業からHealthTech系のスタートアップやベンチャー企業、VCなどさまざまなプレイヤーが集まり、出会い、 化学反応を起こす場となるべく、世界各国で開催されています。

Health 2.0 Annualカンファレンス

米国で開催されるAnnualカンファレンスは、 今や参加者2000名を超えるイベントとなっています。

f:id:akinorifukumura:20151027113941p:plain

今年2015/10/5-7の3日間、米国サンノゼで開催されたカンファレンスには、 弊社メンバーも参加してきました。 先日その報告会が社内で行われ、いろいろなヘルステックの最新サービスが発表されました。 その中でも私が個人的に面白いなと思ったサービスが有りましたので3つだけご紹介させていただきます。

FirstDerm

www.firstderm.com

サービスの特徴はスマホで撮影した画像で医師からセカンドオピニオンが得られるというサービスです。 患者側アプリと医師側アプリを開発し、患者と医師をつないでいます。 主に皮膚科系を中心に展開していて、患者側はレスポンス速度を買い、 医師側はレスポンス速度で報酬を得るというビジネスモデルです。 技術的なハードルは高くなさそうですが、 日本では、まだまだ遠隔診療の領域なのでビジネス化という点でハードルが高いです。 しかしながら、患者と医師がWin-Winになっている非常に面白いサービスで、 今後もウォッチしていきたいです。

Tyto Care

tytocare.com

遠隔に必要な情報が取得できるデバイスを作り、遠隔診療ができるようにしたサービスです。 実際にデバイスをつくってしまうところがすごいですが、 さらにそこで得たデータはクラウドに蓄積し、病院との連携プラットフォームになっているようです。 また、スマートフォンとデバイスを連携させて確定診断までできるとのことで、 こちらも日本では遠隔診療の壁がまだ高いのですが将来的にはここまでできると日本医療も変わってきそうです。 Web出身の私としてはデバイスまで作りきってしまうTyto careのエンジニアに憧れと嫉妬を感じてしまいます。

athena health

www.athenahealth.com

1997年創業時からクラウド型EHRシステムを開発・提供していて、売上は700億円を超えている会社です。 課金は会員医師に入る医療費の数%としていて、まさに実医療に踏み込んでいる素晴らしいサービスとなっています。

Health 2.0 ASIA-JAPAN のセッション

さらに、来週から開催されるHealth 2.0 ASIA-JAPANでデモやピッチ等で参加されるサービスを3つほどご紹介したいと思います。

Steth IO

www.stethio.com

こちらは、スマホを胸にあてるだけで心拍の様子がわかるというもので 医療機器などが整っていない国でも容易に利用が可能になります。 医師の聴診器を使った音の判断+グラフ描画による視覚の判断、 これらのデータを蓄積して分析することでの予防や発見につなげることができるなど 技術的にもいろいろ夢が広がりそうです。 AppleのWatchOS2より心拍数が取れるようになったので、今後いろいろ出てきそうですね。

BaseHealth

www.basehealth.com

遺伝子データや臨床データを収集し、Fitbitなどのデバイスからも情報を収集することで 患者の予防にまで踏み込んだサービスを提供しています。 予防ができるようになると医療費も削減されるので 今後の日本もこのような予防医療が発展していくようにしていきたいです。

BirdsView

http://www.birdsview.jp/

救急車と病院のマッチングをし、搬送を最適化するシステムを提供しているサービスです。 各地で地域全体をひとつの医療システムとしていく地域医療連携の代表例です。

最後に

いかがでしたでしょうか?

海外では活発に医療関連のサービスが開発されていますが、 日本も遠隔医療の環境がすこしずつ変化しており、同じ様な世界がくると感じています。

医療情報の開発をする上で、ガイドライン*1は欠かせませんが、 実はすごいボリュームがあり、 現状では気軽に開発できるような環境ではないかもしれません。

しかし、本カンファレンスはHealthTech業界の情報のハブとなり イノベーションとコラボレーションを加速させる場に少しでもなればと願っております。

f:id:akinorifukumura:20151027114116p:plain

そんな雰囲気を味わいたい方がいたら、 来月日本で初開催する「Health 2.0 ASIA-JAPAN」に是非ご参加ください。

共同創業者のMattew Holt氏とIndu Subaiya氏も来日して、世界のヘルステックの最新トレンドを語ってくれますし、 米国ではとても有名な患者SNS、PatientsLikeMeのRishi Bhalerao氏もスピーカーで参加されます。

皆様奮ってご参加下さい!

www.health2conjapan.com

Zenhack(禅ハック)で最優秀賞いただきました&ハッカソンのススメ

こんにちは、メドピアデザイナーの松村です。
最近行き詰まることが多かったので座禅を組んで己に向き合いたい…と思ってZenhackに参加したら最優秀賞いただきましたやったー٩( ᐛ )و

Zenhackとは?

”禅 と IT で世界の課題に挑む”という壮大なコンセプトのもと由緒ある臨済宗建長寺派大本山建長寺に泊まり込みで行われるハッカソンです。すごい。 www.zenhack.jp

当日の様子と成果物イメージは以下からどうぞ。実況まとめありがたい! togetter.com hacklog.jp

私はハッカソンに何度か参加していますが、表彰されると承認欲求の満たされ方がすごいのでフラストレーションの溜まってるエンジニアさんやデザイナーさんにおすすめです。この快感を多くの方に味わって頂きたいので、僭越ながらまだハッカソンに参加されたことのない方に向けて、ハッカソンのススメ的なものを綴ってみます。

ハッカソンのススメ

ハッカソンて何ぞい?とよく聞かれますが、基本的には技術でお題に応える大喜利だと捉えています。ネタに走るもよし、ガチガチのビジネスプランを携えて挑むもよし。楽しみ方は人それぞれです。自分が一番楽しい!と思うことで勝負しましょう。(えらそう)

楽しむ

イデア出しの段階では俺はこれを作りたいんだーー!というのを思いつくまま紙にぶつけます。

こんなかんじ f:id:umeccco:20150708122557j:plain

お題に沿うのも大事ですが、内容を理解しないまま要素だけ貼り付けると薄っぺらくなるので基本的には自分の持ち味を活かすのが大事かなと思います。

尚このときに出すアイデアはチームビルディングのときに淘汰されることが多いので、一人でもやるよという気概のない方はあとでフラストレーションの溜まらないようにこの段階で持てるネタを出し切りましょう。

協力を求める

イデアを出し切ったら次は仲間探しです。

ボーっとしてるとどんどん人が売り切れいくので恥ずかしがらずにナンパしましょう。スーパーのタイムセールの状況が近いです。

この時大事なのがお互いのアイデアに共感できるか、それを一緒に作りたいか、というビジョンの共有です。これがないと実際手を動かしはじめたときにえらいことになります(過去にチームビルディングが上手く行かず途中でリタイアした悲しい思い出)。今回は本当に良いチームに恵まれました。ありがたい。

キョロキョロする

ハッカソンには普段は会えない人がひょっこり参加されてたりします。今回だと電波少年の土屋Pとかカヤックの岩渕さんとかぐるなびのフロントエンドエンジニアさんとかホームズの中の人とか錚々たる面々です。そんな方々と肩を並べて一夜を共に過ごせる…たまらないですね!

トラブルはつきもの

ハッカソンあるあるとしてWi-fi環境の不具合があります。状況を運営に相談したら慌てず騒がずSOYJOYでも食べて休憩しましょう。スケジュールどおり進まない?あるあるです。(今回はスケジュールどおり進んでてさすがカマコンバレーだなーと思いました)

また、出会ったばかりの人と2日間一緒に過ごすのですから、チームメンバーと険悪になる瞬間もあります。でも仕方ないじゃない。人間だもの。とりあえず目の前の自分の作業を終わらせて、それからお茶でも淹れて話し合いましょう。

プレゼンが上手くいかなかった?これは事前準備あるのみです。プレゼン環境を確認した上で3回は通しで練習すべきだなと痛感しました。(プレゼンほんとにやりなおしたい…orz)

讃える

人のアイデアや技術力に嫉妬することも多々ありますが素直にすごい!あんなの思いつかなかった!くやしい!と声に出して讃えることでより楽しくなります。あと人の能力を認めることで人間的に成長できる気がします。

というわけで少しはハッカソンの楽しさが伝わったでしょうか。 ハッカソンに参加する人はものを作りたくてウズウズしてる人たちばかりなので、今ここにない出会い的なものを求めている人は是非参加してみていただきたいです。

ハッカソン情報の収集は以下のサイトが便利です。

www.doorkeeper.jp connpass.com

後日談

頂いた賞金はチームで山分けしたのち会社へのお土産に鳩サブレーの一番大きいサイズを買って帰りました。めちゃくちゃ重かったです。f:id:umeccco:20150708124608j:plain 中に入っていた小分けの袋にも禅の思想を感じて、鎌倉はすごいところだな〜と思いました。 f:id:umeccco:20150708124723j:plain

SOYJOYもたくさん届いて社員一同ハッピーです!大塚製薬さんありがとうございます! f:id:umeccco:20150713151158j:plain f:id:umeccco:20150713151203j:plain

お知らせ

メドピアでは2015年11月4-5日にHealth2.0というイベントを開催します。 ハッカソンの開催はありませんが、医療に関わる様々な情報が集まる場ですので 興味のある方は是非お立ち寄りください!(事前申込制ですが、申込開始は今しばらくお待ちください!) health2.medpeer.co.jp

LaravelとLumenのパフォーマンスを比較してみた

こんにちは。エンジニアの尾澤です。

先日、酒井がLaravel5.0:FormRequestを使ったValidationというエントリでLaravelのTipsをご紹介しましたが、今回は、そのLaravelと同じコミュニティで開発している別の軽量フレームワークであるLumenとパフォーマンスの比較をしてみたいと思います。バージョンは5.1を使用します。

Lumenのベンチマークとしては、公式サイトで他の軽量フレームワークであるSilexとSlim 3との比較が紹介されていますが、相互にコードの移植性が高いLaravelとの比較がなかったので、調べてみました。

LaravelとLumenの機能面での比較はこちらのエントリーによくまとめられていますので、参考にしてください。

検証環境

検証には、同じくLaravelコミュニティが提供しているVagrant環境であるHomesteadを使用しました。なお、HomesteadはHHVMをサポートしていますが、今回は使用していません。

検証マシンのスペックは以下の通りです。ちなみにメドピアでは、エンジニア・デザイナの全員にMacbook Proを支給していますので、開発作業は快適です(ง ˙ω˙)ว☆

MacBook Pro (Retina, 14-inch, Mid 2014)
Processor 2.8GHz Intel Core i5
Memory 16GB 1600MHz DDR3
Storage 500GB Flash Storage

検証環境には、それぞれのフレームワークで同じ仕様のアプリケーションを実装しました。アプリケーションはシンプルに、GETリクエストに対して常に同じ内容のテキストをレスポンスとして返します。テキストはJSONフォーマットで、Homestead内のMySQLから取得したデータを使用します。LaravelとLumenでは多少書き方は変わるところもありますが、クラス構成やロジックは同じです。フレームワークの以下の機能を利用しました。

  • Routing
  • Controllers
  • Service Providers
  • Eloquent ORM

速度の比較

速度の比較にはApache Benchを使用しました。接続数100で1000リクエストを発行して、1リクエストあたりのレスポンスタイムを比較してみます。

まずはLaravelから。

user:homestead mymac$ ab -n 1000 -c 100 http://laravel.app/sample

〜中略〜

Concurrency Level:      100
Time taken for tests:   113.675 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      12632114 bytes
HTML transferred:       11679000 bytes
Requests per second:    8.80 [#/sec] (mean)
Time per request:       11367.500 [ms] (mean)
Time per request:       113.675 [ms] (mean, across all concurrent requests)
Transfer rate:          108.52 [Kbytes/sec] received

〜後略〜

Time per requestを確認すると、1リクエストあたり113.675 msかかってることが分かります。

Laravelの検証にあたってはphp artisan optimizeコマンドによるコード最適化を行っていません。最適化による速度の改善については別の機会に書きたいと思います。

次にLumen。

user:homestead mymac$ ab -n 1000 -c 100 http://lumen.app/sample

〜中略〜

Concurrency Level:      100
Time taken for tests:   30.072 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      11840000 bytes
HTML transferred:       11679000 bytes
Requests per second:    33.25 [#/sec] (mean)
Time per request:       3007.196 [ms] (mean)
Time per request:       30.072 [ms] (mean, across all concurrent requests)
Transfer rate:          384.49 [Kbytes/sec] received

〜後略〜

Lumenでは、1リクエストあたり30.072 msでした。Laravelの113.675 msと比較すると3.78倍も速いという結果になりました!こんなに差が出ると思わなかったのでビックリ。

負荷の比較

それでは、サーバの負荷についてはどうでしょう?いくら速くてもリソース消費が著しければ意味がないですからね。Apache Benchを実行している状態で、vagrantインスタンスの負荷をvmstatコマンドで記録し、gnuplotでグラフ化してみました。

Laravelの負荷 f:id:o205:20150708185806p:plain

Lumenの負荷 f:id:o205:20150708185818p:plain

CPU負荷のグラフを比較すると、Lumenの負荷の方が軽いことが分かります。vmstatの実測値からアイドリング率を平均すると、Laravelが9.0%、Lumenが31.4%でしたので、LumenのCPU負荷はLaravelの75.4%ということになります。だいぶCPUに優しいですね!

メモリ負荷については若干Lumenの方が少ないように見えますが、空きメモリ量の実測値を平均すると、Laravelが879MB、Lumenが897MBで、ほとんど変わらないですね。誤差の範囲といってもよさそうです。フレームワーク自体の消費メモリに優劣ありませんでした。

サイズの比較

Laravelのサイズ

vagrant@homestead:~$ du -sk laravel/vendor/laravel/framework/
3416    laravel/vendor/laravel/framework/

Lumenのサイズ

vagrant@homestead:~$ du -sk lumen/vendor/lumen/vendor/illuminate/ lumen/vendor/laravel/lumen-framework/
2588    illuminate
292     laravel/lumen-framework/

フレームワークそのもののサイズはどうでしょう?composerで取得したコアライブラリの容量を比較してみたところ、Laravelが3416 KB、Lumenが292 KB 2880KBで、LumenのサイズはLaravelの8.5% 84.3%という結果になりました。かなり減量されていますね!自分も、せめて80%くらいにまでダイエットしたいところです…。 軽量というには減量具合が中途半端ですね。自分の場合、それくらいダイエットできればBMI値が人並みになるんですが…。

Lumenのサイズに依存パッケージの分が含まれていないというご指摘をいただきました。illuminateパッケージのサイズを加味して計算して修正しました。

まとめ

以上の検証結果をまとめると、以下のような結論になりました。

f:id:o205:20150715113430p:plain

  • LumenはLaravelの約4倍速い
  • LumenはLaravelの約75%CPUに優しい
  • LumenはLaravelと同じくらいメモリを消費する
  • LumenはLaravelの約10% 約85%の大きさ

Lumenは拡張性や機能に制限がありますが、その範囲で要求を満たせるものであれば、フルスタックのLaravelではなくLumenを使ってみるという選択肢もありかもしれませんね。

今回使用したソースコードは、https://github.com/medpeer-inc/benchmark-laravel-lumenに置いてありますので、ぜひ参考にしてみてください。

社内LT紹介!

こんにちは。メドピアエンジニアの西澤です。梅雨らしい雨の日が続いていますが皆様いかがお過ごしですか?

今日はメドピアで不定期(ほぼ月1回)で実施しているLightning Talk大会を紹介します。Lightning Talkについてはこちらをご参照下さい。

ライトニングトークとは - はてなキーワード

実際は5分に制限する事もなく、ドラもドラ娘も置かずに実施しているわけですが(^^;)

弊社はオフィス内にオープンなミーティングスペース(セントラルパーク)があり、LTをやるにも適しています。(私のお気に入りのスペースの1つです。) f:id:ikuheinishizawa:20150701181504j:plain

何枚かLT中の写真も。 f:id:ikuheinishizawa:20150701181506j:plain ピザをつまみながら。 f:id:ikuheinishizawa:20150701181509j:plain

これまで発表されたテーマは以下のようなものがあります。(本当はもっとあります!)機会があればこのブログでも紹介出来ればと思っています。

  • Go into Golang(Go言語入門)
  • SwiftでUIKit Dynamics
  • Research Kitを触ってみた
  • (元・某ベンチャーCTOによる)シード期の開発現場について
  • (入社直後のメンバーによる)自身のエンジニアキャリア披露

等等・・・

元々このLT大会、個々のエンジニアが持っているスキルや興味を気楽に皆で共有し、研鑽する事を目的に始まりました。 実際やってみると、興味の幅が広がったり、自分が手を付けられていなかった分野を学べたり、業務で役に立ったり、なかなか良い手応えがあります。また、オープンスペースのおかげもあり、エンジニア以外の社員も少し覗いて行ったり出来るので、交流の場にもなっている、と良いな。

今はエンジニアが技術中心の話題で発表していますがいずれ、ディレクターだったり社外の方も交えて開催出来たらと思っています。

それでは、雨にも負けず楽しく夏を迎えましょう!

メドピア株式会社 エンジニア 西澤

Laravel5.0:FormRequestを使ったValidation

はじめまして。 メドピアエンジニアの酒井です。

まだ使い始めてそんなに経っていませんが、Laravelの小ネタを紹介したいと思います。

Laravel5.0で導入されたFormRequestを使用して Controllerをスッキリさせる方法です。

Laravelを触ったのは5.0が始めてですが。

実際に見てみる

まず、最初に通常のValidationの書き方はこんな感じです。

<?php

use App\Http\Requests\Request;

Class SampleController extends Controller
{
    public function getIndex(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'name' => 'required',
            'email' => 'required|email'
        ]);
        if ($validator->fails()) {
        }
    }
}

見ても分かるようにContollerに記述していくとForm項目が増えるにつれ、 Controllerに大量のValidation設定を記述する事になります。

次にFormRequestを使用したControllerです。

<?php

use App\Http\Requests\SampleRequest;

Class SampleController extends Controller
{
    public function getIndex(SampleRequest $request)
    {
    }
}

すっきりしましたね!

FormRequestって何?

Laravel5.0から導入されたValidation処理を含んだRequestクラスとなります。

詳しくはこちら

リクエストをdispatchした際、Controllerメソッドの依存関係を解決した後に validate()が実行されるようになっています。

つまり、FormRequestを使用するとControllerメソッドの実行前に Validationの実行が完了している事になります。

FormRequestの使い方

<?php

use App\Http\Requests\Request;

Class SampleRequest extends Request
{
    //認証ユーザーが権限あるかチェックする
    public function authorize() {
        return true;
    }

    //Validationの設定
    public function rules() {
        return [
            'name' => 'required',
            'email' => 'required|email'
        ]
    }

    //エラー文言の設定
    public function messages() {
        return [
            'name.required' => 'The :attribute field is required.',
            'email.required' => 'The :attribute field is required.',
            'email.email' => 'The :attribute must be a valid email address.',
        ];
    }
}

public function authorize()

権限チェックする必要ない場合もこれを指定しないとエラーとなりますので 必ず記述するようにします。

あとはviewに以下のように記述すれば、Form画面にエラーを出力できるようになります。

@if (count($errors) > 0)
    @foreach ($errors->all() as $error)
        {{ $error }}
    @endforeach
@endif

エラー時のリダイレクト先は特に指定がなければ、前画面(Form画面)になります。

頻度の高いValidationルール

rule 内容
alpha 英字チェック
alpha_num 英数字チェック
between:min,max 最小値と最大値チェック
email メールアドレスチェック
numeric 数字チェック
regex 正規表現によるチェック ※1
required 入力値の存在チェック
same:field 指定されたフィールドとの同値チェック

詳しくはこちら

※1 regexで「|」を使用する場合はrulesの指定を配列にしないと動作しません。

<?php
    public function rules() {
        return [
            'sort' => ['regex:/^(desc)|(asc)$/']
        ]
    }
}

これでしばらくハマりました。。。

まとめ

Illuminate\Foundation\Http\FormRequestを見ると リダイレクト先やエラー時の挙動を変更できるようになっているので、 Validation関連のだいたいの事はFormRequestで行えると思います。

ControllerがValidation設定ばかりになってきたら、 FormRequestの利用を検討してみるのもいいかもしれませんね。