Quantcast
Channel: メドピア開発者ブログ
Viewing all 211 articles
Browse latest View live

メドピアはRubyKaigi 2022にRubyスポンサーとして(今年も)協賛します

$
0
0

皆さんこんにちは!春から社会人大学生をやっているサーバサイドエンジニアの福本(@terry_i_)です。

開催がいよいよ来週に迫っているRubyKaigi2022ですが、メドピアは今年も(Ruby)スポンサーとして協賛することになりました。ちなみに、RubyKaigiで弊社がスポンサーを行うのは、今回で5回目です。

tech.medpeer.co.jp

私自身、RubyKaigiに初めて現地参加する予定なので大変楽しみにしております!というわけで、参加に向けて気持ちを高めていきたい思いもあり、今回のRubyKaigiでメドピアが行うスポンサー内容をご紹介できればと思います。

概要

大枠の内容としては、現地でのブース出展を行いまして、以下のコンテンツをお届けする予定です。

  1. 「Rubyistは健康か?」実態調査
  2. かわいい、使えるノベルティたちの配布
  3. あなたは解けるか!?『RubyQUIZ』を実施

スッとイメージできるものから「もっとよく知りたい」ものまでありますので、以降で詳しく説明します。

1. 「Rubyistは健康か?」実態調査

在宅勤務も普及している昨今なので、開発者の皆さんの中には

「ずっと!!!!!座りっぱなし!!!」
「生活が!!!!!不規則!!!!」

といった、不健康を地で行く状態になっている方も(私も含めて)いらっしゃるかと思います。

私たちはヘルステックカンパニーとして、その実態を調査し開発者として何かサービスやソリューションの提供できれば良いな〜と思いました。

というわけで、当日参加されるRubyistの皆さんに健康調査アンケートを実施します。こんな感じ↓であれこれ聞いてみたいと思いますので、皆さまぜひワイワイ楽しみながらご協力頂ければと思います。

アンケートボードのイメージ

2. かわいい、使えるノベルティたち

カンファレンスといえば…な、ノベルティをRubyKaigiでも配布します!

メドピアのキャラクターがあしらわれた、実用的なものを提供する予定です。以下、現時点で完成しているノベルティになります。

当日はブースまで遊びに来て、ぜひ持って帰ってください。

3. あなたは解けるか!?『RubyQUIZ』

現地に参加する天才エンジニア達からのRubyに関するクイズを出題し、ブースに来場された方に配布するリーフレットに掲載する予定です。空き時間にワイワイお楽しみください。

現時点でのリーフレットのドラフト

ちなみに、私も一部挑戦してみましたが、フツーに悩んでしまう問題があり「Rubyなんもわからん…」となりました。同じ気持ちになりたい方はオススメです。

RubyKaigi 予習会

また、RubyKaigiの参加に向けて、社内で「RubyKaigi 予習会」なるものを実施しました。以下の記事で開催の模様を記載しております。

www.wantedly.com

概要としては、RubyKaigiのポイントとなるテーマに関する勉強や、単純にセッションに参加するにあたっての事前勉強などを解説したものになります。

  1. RubyKaigi参加の準備方法
  2. RubyKaigiのトークテーマの分類
  3. Rubyの基礎
  4. JIT
  5. 並行性(Fiber, Ractor)

また、予習会のドキュメントも公開してくれているのですが、内容をMatzさんがTweetして取り上げてくれていました!ありがとうございます!

まとめ

今回の内容は以上です。Rubyistで現地に来られるみなさんと現地でお会いできるのを楽しみにしております!


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

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

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

■開発環境はこちら

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


Vapor(Serverside Swift) + Nuxt.js + Cloud Run でホームページを手作りする

$
0
0

こんにちは。モバイルアプリを開発しています。髙橋です。 ホームページも作るのが好きなので、仕事の隙間時間で iOSDC Japan 2022 で同僚の出演を応援する意味で、 Swift のクイズサイトを作って Cloud Run で公開してみました。

メドピアは今週末いよいよ開催となる iOSDC Japan 2022 を PLATINUM SPONSOR として協賛させていただいております。

作ったホームページ

「Swift Quiz for 5.6 | メドピア」

👉 http://swiftquiz.medpeer.co.jp

正解数 6 問以上になると、正解が増えていくごとに演出が変わるので、全問正解できるまでトライしてみてください👍

  • iOSDC 向けなので、一時期 Serverside Swift に妙にハマったのもあり、せっかくなので Swift をバックエンドにしたホームページにしてみました。
  • iOSDC で配布しているメドピアのチラシには、毎年 Swift Quiz が掲載されているので「せっかくならウェブサービスにしましょう」と同僚らをそそのかしてクイズ問題をいっぱい作ってもらいました。

基礎知識

Nuxt.js とは

https://nuxtjs.org/ja/

  • JavaScript な Frontend Application Framework です。いい加減に言うと、Next.js とか jQuery みたいなやつです。
  • Nuxt 3 リリースが近いようですが、今回は Nuxt 2 で作りました。TypeScript を適宜使っていますが、解説が複雑化するので今回の Tips では JavaScript で解説しています。
  • メドピアは Vue.js 推しなので選択しました。Vue Fes 2022にも同僚がスタッフとして参加します。

Vapor とは

https://vapor.codes

  • Swift 製の Web Application Framework です。いい加減に言うと、Express とか Rails とか Amon2 みたいなやつです。
  • Serverside Swift だと今はこれ一択という感じかもです。
  • メドピアは Rails で基本的にプロダクトを作っているので、空気を読まない感じでやってみました。

Cloud Run とは

https://cloud.google.com/run

  • Fully Managed IaaS です。いい加減に言うと、 AWS App Runner みたいなやつです。
  • 最近 GCP を個人開発だったり Android アプリの開発業務で自分的によく使っているので選択しました。
  • これもメドピアは AWS で以下略

Tips

ポイントをまとめました。

[Swift/Vapor] Vapor で Nuxt.js で SSG したサイトを配信する

Vapor で HTML ページを配信する場合、Leaf テンプレートエンジンを使って SSR するチュートリアルはよく見かけるのですが、Nuxt.js で SSG したサイトを配信する例を見たことがなかったのでご紹介です。

私は Flash を作って育ってきたので、ウェブサイトは SPA であってほしいし、HTML を表示するにあたって SSR ではない方が好きなので、Vapor の公式では紹介されていないこんな構成にしました。その理由についてつらつら語る前職時代に登壇した動画も参考になるかもしれません(この時一番太っていて黒歴史)。

セットアップ

インストールは Vapor 公式のチュートリアルをご確認ください。https://docs.vapor.codes/getting-started/hello-world/

まずは vapor newするとき、 Fluent (ORM) 使うか?Leaf (Template Engine) 使うか?の質問に Leaf の部分だけ no とします。データベースを使いたい場合は Fluent を試してみてください。

次に Public配下にアクセスできるように、FileMiddlewareを使います。configure.swiftで、おそらくコメントアウトされているので戻してあげれば大丈夫です。

configure.swift
import Vapor

publicfuncconfigure(_ app:Application) throws {
    app.middleware.use(FileMiddleware(publicDirectory:app.directory.publicDirectory))
    try routes(app)
}

root リクエストが来たら Publicフォルダの index.htmlを表示するように route.swiftでルーティングします。

route.swift
import Vapor

funcroutes(_ app:Application) throws {
    app.get { req ->EventLoopFuture<View>inreturn req.view.render(app.directory.publicDirectory +"index.html")
    }
}

さらに、Scheme の設定で、ワーキングディレクトリを指定します。 Package.swiftがあるディレクトリを指定してあげれば大丈夫です。

ワーキングディレクトリを指定する

あとはこの Publicフォルダに、Nuxt.js の generatedフォルダを指定し、SSG すれば完了です。

nuxt.config.jsgenerateで vapor のプロジェクトくフォルダの Publicを指定します。

nuxt.config.js
export default {
  target:'static',
  generate: {
    dir:'vaporproj/Public'
  }
}

Nuxt.js のソースフォルダと、Vapor の Package.swiftが同階層にある場合、Xcode で Package.swiftを開くと(Nuxt.js のソースコードも読み込もうとするので、特に node_modulesフォルダの影響だと思うのですが)、Xcode ビルド時ハングアップしてしまうかもしれません。(自分の M1 MacBook Air では厳しい印象でした)

Nuxt.js のコードは Visual Studio Code、Vapor のコードは Xcodeで書く感じにしました。

これで nuxt generateしたファイルが Vapor 経由で localhost:8080で見られるようになると思います。

[Swift/Vapor] POST 通信を受け取って JSON を返す

ここ Serverside Swift ならでは感があっていいなと思ったポイントなんですが、Codableみたいな感じの型でデコードして、レスポンスで returnするだけで、そのまま JSON レスポンスが作られました。

Contentを使用します。

route.swift
import Vapor

funcroutes(_ app:Application) throws {
    // ... 省略
    app.post("greeting") { req ->Resultinletmessage=try req.content.decode([UserMessage].self)
        // ... 普通はこの間で DB に問い合わせたりなんかやるreturn Result(message:"Hello \(message.name)")
    }
}

structUserMessage:Content {
    letname:String
}

structResult:Content {
    letmessage:String
}

Terminal から POSTしてみてレスポンスを確認します

% curl -X POST -H "Content-Type: application/json" -d '{"name":"medpeer"}]' http://localhost:8080/greeting

GETも JSON を返すだけなら同様です。これ Swift を普段書いている人間からすると、ちょっと気持ちいい感じがします。

[JavaScript/Nuxt.js] Syntax Highlight する

syntax highlighted

prismjsを使用しました。

https://github.com/PrismJS/prism

~/plugins/prism.jsで以下を作成し

~/plugins/prism.js
import Prism from 'prismjs'import'prismjs/themes/prism-tomorrow.css'import'prismjs/plugins/toolbar/prism-toolbar'import'prismjs/plugins/toolbar/prism-toolbar.css'import'prismjs/plugins/show-language/prism-show-language'import'prismjs/components/prism-swift'exportdefault Prism

nuxt.config.jsで読み込みます。

nuxt.config.js
  ...  
  plugins: [{src: '@/plugins/prism.js'}]}

適当に VueComponentを作って、

~/components/HighlightedCode.vue
<template>
  <div class="prism">
    <pre class="language-swift"><code v-html="content"></code></pre>
  </div>
</template>

<script>
import Vue from 'vue'import Prism from "@/plugins/prism"exportdefault Vue.extend({
  props: {
    content: {
      type: String,
      required: true,
      default: "",
    },
  },
  mounted() {
    Prism.highlightAll()
  }})
</script>

宣言すれば OK です。

~/pages/index.vue
<HighlightedCode :content="code"></HighlightedCode>

テーマが色々あったり、コードをコピーできる機能とかオプションも色々あったり、対応している言語が本当にたくさんあって、本当至れり尽くせりですごいです。

[JavaScript/Nuxt.js] パーティクルを舞わせる

particles.vueを使用しました。tsparticlesVueComponentです。

https://github.com/matteobruni/tsparticles

~/plugins/particles.js
import Vue from 'vue'import Particles from "particles.vue";

Vue.use(Particles)
nuxt.config.js
  ...  
  plugins: [{ src: '@/plugins/prism.js'},
    { src: '@/plugins/particles.js'}]}

設定ファイル particles.jsonを作っておきます。

~/static/particles.json
{"autoPlay": true,
  "background": {},
  "fullScreen": {"enable": true,
    "zIndex": -1},
  "interactivity": {"detectsOn": "window"
  },
  "emitters": [{"position": {"x": 30,
        "y": -30},
      "rate": {"quantity": 5,
        "delay": 0.25}},
    {"position": {"x": 70,
        "y": -30},
      "rate": {"quantity": 5,
        "delay": 0.25}}],
  "particles": {"move": {"decay": 0.01,
      "direction": "top",
      "enable": true,
      "gravity": {"enable": true},
      "outModes": {"top": "none",
        "default": "destroy"
      },
      "speed": {"min": 5,
        "max": 10}},
    "number": {"value": 10},
    "opacity": {"value": 1},
    "rotate": {"value": {"min": 0,
        "max": 360},
      "direction": "random",
      "animation": {"enable": true,
        "speed": 10}},
    "size": {"value": 8},
    "wobble": {"distance": 30,
      "enable": true,
      "speed": {"min": -10,
        "max": 10}},
    "shape": {"type": ["image",
        "image"
      ],
      "options": {"image": [{"src": "/images/confettie1.svg",
            "width": 30,
            "height": 27,
            "particles": {"size": {"value": 16}}},
          {"src": "/images/confettie2.svg",
            "width": 15,
            "height": 15,
            "particles": {"size": {"value": 12}}}]}}}}

あとは読み込むだけで OK です。

~/pages/index.vue
<template>
  <Particles
        id="tsparticles"
        :particlesInit="particlesInit"
        url="/particles.json"
        />
</template>

<script>
import Vue from 'vue'import Particles from "@/plugins/particles"import{ loadFull } from "tsparticles";

exportdefault Vue.extend({
  methods: {
    async particlesInit(engine) {
      await loadFull(engine)
    }}})
</script>

こちらも至れり尽くせり系なので、ほんとうに素晴らしいです。

[Infrastructure] Cloud Run にデプロイする

公式にも Swift / Vapor プロジェクトのデプロイの記載がなかったので、ざっと手順をまとめました。

  1. Google Cloud SDKツール をインストール
  2. 初期化 gcloud initして Google Cloud SDK を使えるようにする
  3. プロジェクトを設定: gcloud config set project {PROJECT_ID}
  4. 確認: gcloud config list
  5. デプロイしたいディレクトリに移動 cd ${VAPOR_PROJECT}
    • Vapor の初期化をしたタイミングで Dockerfileとかができているので、これを確認して、問題なければそのまま使って OK
  6. gcloud builds submit --tag gcr.io/{PROJECT_ID}/{IMAGE_NAME} --timeout=1200s Vapor はビルドにちょっと時間かかるので --timeout=1200sまたは 20mをつけるのが良さげ
  7. gcloud run deploy --image gcr.io/{PROJECT_ID}/{IMAGE_NAME} --platform managedでデプロイする
  8. ロケーションを選択し(asia-northeast1など)、Allow unauthenticated invocations = yして公開。(コンソール側で public アクセス権限を削除すればアクセスできないようにできます)

一旦これでサービスが公開されるので、ドメインの設定を行えば期待通りの表示ができるかと思います。

その他 Tips・かんそう

  • CSS 久しぶりに書くと色々進化していて素晴らしいです。
    • 上下センターも display: flex;してサイズ決めるだけなので楽ですね。
    • position: sticky;は感動しました。 
  • 画面デザインのスケッチを作るとき、 Figma コミュニティの Confettie プラグインと Code Highlighter が活躍しました。
  • Vapor で gzipも、以下の一行足すだけです。
  • FileMiddlewareCache-Controlの機能を持たないので、静的なファイルは実際はやはり CDN に逃すと良さそうです。
    • この辺りは開発コミュニティ(Discord)のやりとりが参考になりました。
  • Lighthouse は、アニメーションを利用したり HIG に合わせた配色などにしたため、 ALL 100 点とはいきませんでしたが、 service-workerを使い(単にオフライン表示しか対応していませんが) PWA 対応バッジもついたので、フロントエンド側の開発も満足です。

おわりに

某トークン用→ #Healthtech

RubyKaigi 2022 セッションレポート Day 1

$
0
0

バックエンドエンジニアの田中悠大(@ytnk531)です。 RubyKaigi 2022で三重県に来ています。1日目(9/8)に聞いたセッションについて、簡単に紹介させていただきます。

Ruby meets WebAssembly

Ruby meets WebAssembly - RubyKaigi 2022

RubyのWebAssembly (WASM) 対応についての発表でした。WebAssemblyの基礎から、WASM対応のテクニカルな難しさまで、非常にわかりやすく丁寧に説明されており、聴きごたえのある素晴らしい発表でした。 特にデモがおもしろく、思わずスゴイ!とうなってしまうものばかりでした。

RubyのWASM対応にあたっては、ExceptionやFiberで利用する特殊な制御をWASM上で再現するのに特に苦労されたそうです。Asyncifyという技術を使うことで、うまく解決できたそうです。

パフォーマンスについてはCRubyの半分くらい、mrubyと同等くらいだそうで、十分実用ができそうですね。WASMで書かれたRubyインタプリタの容量は数十MBで少し大きのですが、圧縮すれば数MBになるそうです。より小さくするためのアイディアがいくつかあるそうなので、今後にも期待が持てますね。

Building a Lightweight IR and Backend for YJIT

Building a Lightweight IR and Backend for YJIT - RubyKaigi 2022

Ruby 3.1から利用できるようになったYJITを拡張するために、YJIT IRというIR(中間表現)を導入するお話でした。

現状のYJITは、YARV命令列からx86-64用のアセンブラを生成し、そこからマシンコードを生成しています。このため、M1 Macなどで使われるARM64のCPUでは動作しません。 ARM64でも動くようにするために、直接ARM64のアセンブラを生成するのではなく、中間表現を生成するアプローチをとったそうです。

従来はYARV命令列→x86-64マシンコードとコンパイルしていたのですが今後は、YARV命令列→中間表現(YJIT IR)→x86-64マシンコード or ARM64マシンコードとコンパイルしていくようになります。

RISC-Vなど他のアーキテクチャへの対応も展望に入れているそうで、その時の手間を少なくすることなども見据えて中間表現を導入することにしたようです。

発表の中では、中間表現の設計や、最適化の方法について詳細が語られました。ARM64とx86-64の違いをうまく吸収するのがすごく難しそうでした。

最終的にARM64対応ができたが、まだちょっとバグがあるとのことです。今後はYJIT IRの最適化をやってスピードアップを目指していくようです。

Adding Type Signatures into Ruby Docs

Adding Type Signatures into Ruby Docs - RubyKaigi 2022

rubyapi.orgをメンテナンスしているColbyさんの発表でした。rubyapi.orgでは、Rubyのドキュメントを見やすい形で公開していて、より仕様をわかりやすくするためにRBSの型注釈を利用したというお話でした。

RDocには、Call Sequenceという場所に呼び出しと返り値を記述できるのですが、厳密なフォーマットの定めはありません。Call Sequenceをより正確にわかりやすくするために、RBSを用いて自動生成できるようにしたという内容でした。せっかく型情報があるのだから、ドキュメントからもみれるようにしよう、ということですね。 それだけでなく、RBSの出力も読みやすく工夫したそうです。

RDocとRBSの型情報が組み合わされば仕様の把握がしやすくなるので、Rubyがより使いやすくなりそうです。

Towards Ruby 4 JIT

Towards Ruby 4 JIT - RubyKaigi 2022

Ruby 4に向けたJITの取り組みの紹介と、最適化の余地についてのお話でした。主な話題は下記の4つでした。

  • MJIT, YJITの仕組みの説明
  • MJITをモンキーパッチできるインターフェースの説明
  • JITのベンチマークの仕方の説明
  • JITの最適化の余地

RubyにはMJITとYJITという、2つのJITコンパイラが実装されています。MJITはYARV命令列からC言語を生成して、gccをコンパイルしてマシンコードを生成します。対して、YJITはYARV命令例からx86-84のアセンブラを生成してマシンコードを得ます。

MJITでJITコンパイルを実行するモジュールはRubyで書かれていて、このモジュールをモンキーパッチすることでJITの動作を変更できるそうです。 だからみんなもJITを改良してRubyを速くしようぜ!ということのようです。

JITを改良したら、それがどのくらい良いか測定したいよねということで、yji-benchの紹介もありました。

今後の目論見として、Ruby 4はJavaScriptくらい速くしたい、とのことでした。そのためのJITによる最適化の余地と課題の説明がありました。

ざっくりまとめると、みんなもJITコンパイラ書こうな!といった内容でした。

おわりに

1日目だけでも、非常に興味深い発表ばかりでした。2日以降も気になったセッションがあればレポートを投稿する予定です。


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

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

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

■開発環境はこちら

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

RubyKaigi 2022 セッションレポート Day 2

$
0
0

バックエンドエンジニアの田中悠大(@ytnk531)です。 RubyKaigi 2022で三重県に来ています。2日目(9/9)に聴いたセッションについて、簡単に紹介させていただきます。

ruby/debug - The best investment for your productivity

ruby/debug - The best investment for your productivity - RubyKaigi 2022

Rubyのデバッグツールであるruby/debugを紹介する発表でした。

ある調査によると、Rubyプログラムのデバッグにはbinding.pryを使っている開発者が多いようなのですが、ruby/debugを使ってもっと効率よくデバッグしよう、という趣旨でした。

ruby/debugはデバッグに役立つ機能を3つ提供しています。

  • Step-debugging
    デバッグ対象のコードを実行中に停止して、1行ずつ実行できる機能。定義されている変数や呼び出せるメソッドを確認したり、任意のコード片を実行したりできる。
  • Frame navigation
    デバッガで止めているコードの呼び出し元をたどる機能。呼び出し元やそのさらに元の実行コンテキスト(フレーム)切り替えることができる。
  • Breakpoint commands
    コードの実行を止める位置(ブレークポイント)を、コマンドで指定できる機能。ソースコードの編集せずに、メソッド名や行番号によってブレークポイントを設置できる。

さらに、便利な機能としてScriptable breakpointの紹介もありました。ブレークポイントに到達した際に、実行したいデバッグコマンドを指定できる機能です。変数の確認など、毎回実行したいコードを予め書いておいて自動的させることで、デバッグの手間を減らすことができます。

# doを使うと、指定したデバッガのコマンドを実行してプログラムの実行を再開します
binding.b do: 'watch @a'

# preを使うと、指定したデバッガのコマンドを実行してプログラムの実行を停止します
binding.b pre: 'p bar()'

READMEに詳しい説明があります。

ruby/debugはVSCode拡張も提供しているので、手軽に利用できるようです。ruby/debugには便利な機能がつまっているので、使いこなして効率的なデバッグを行えば、開発スピードをかなり上げられそうだと感じました。

Implementing Object Shapes in CRuby

Implementing Object Shapes in CRuby - RubyKaigi 2022

主にインスタンス変数へのアクセスの高速化を目的として実装が進められている、Object Shapeの仕組みと実装の詳細について解説する発表でした。

Rubyはインスタンス変数を配列に格納しています。同時に、各インスタンスはインスタンス変数名とその変数が格納されている配列のインデックスの組み合わせを保持しています。インスタンス変数にアクセスする際は、この組み合わせをたどって配列のインデックスを探し、得られたインデックスを使ってインスタンス変数の配列にアクセスします。

この挙動を実現するために、Rubyではクラスのインスタンス変数の定義が変更されていないかなどの確認するつくりになっており、計算コストの面で改善の余地があるそうです。Object Shapeは、この問題を解決してより効率的にインスタンス変数へのアクセスを行えるようにするアイディアです。

Object Shapeには、オブジェクトのプロパティが記録されています。プロパティというのは、保持しているインスタンス変数とそれがfrozenであるかどうかです。

Object Shapeはプロパティが変わるたびに新しく生成されます。その際、もとのObject ShapeのIDを保持していて、親のObject Shapeを辿れるようになっています。この親子関係によって、ツリー構造が作られます。Object Shapeはインデックスを持っていませんが、インスタンス変数の数はIDと対応しているので、Object Shapeのツリーを辿ることによって、所望のインスタンス変数が追加されたShapeのID-1がインデックスとして利用できます。

Object Shapeは、同じプロパティを持つインスタンス間であれば共有されます。また、キャッシュすることによりアクセスを高速化できます。

今の所、Object Shapeを利用した実装によるパフォーマンス向上は数%とあまり大きくないそうです。JITと組み合わせることにより高速化が見込まれるようで、今後の進展に大きな期待が持てそうです。

Method-based JIT compilation by transpiling to Julia

Method-based JIT compilation by transpiling to Julia - RubyKaigi 2022

高速なRubyプログラムを書くために、RubyをJuliaに変換するトランスパイラを作ったというお話でした。 こちらに発表資料があります。

Rubyではメソッドの再定義が可能ですが、この性質によりメソッド実行のたびにメソッドが再定義されていないか確認する必要があります。この挙動はデータ分析など特定のシチュエーションでは特に使わないことが多いため、メソッドを再定義できなくなる代わりに速くするような方法を考えたそうです。

PythonにはnumbaというJITコンパイラがあります。numbaは特定のオプションを与えると、メソッドを再定義できなくなる代わりに極力CPUの命令だけで計算するような高速なマシンコードを生成できます。このようなマシンコードを得る方法を考えたところ、numbaとマシンコードの生成方法はJuliaのアーキテクチャに近いので、RubyをJuliaにトランスパイルしてみよう、と考えたそうです。

Juliaへのトランスパイルにあたっては、RubyのコードをASTに変換し、それをJuliaの文法でフォーマットし直します。Ruby上の配列や一部の型は、そのままだとJuliaでは動かないので、RubyのリテラルをJuliaで扱える形にするメソッドをJulia側に実装したそうです。

Juliaへのトランスパイルで生成されたマシンコードは、期待通り少ない命令で高速に実行することができたそうです。(特定のケースでは遅い、という話をしていた気がするのですが、詳細を失念してしまいました)。

高速に動作させるために、一度他の言語に変換して実行する、という非常にワイルドな解決方法でとても興味深い内容でした。実際にかなり高速化しているのもすごいです。

おわりに

2日目も非常に興味深い発表ばかりでした。最終日も気になったセッションがあればレポートを投稿する予定です。


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

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

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

■開発環境はこちら

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

iOSDC Japan 2022参加レポート

$
0
0

iOSエンジニアの島です。 iOSDC Japan 2022にオフライン参加したので参加レポートを書きたいと思います。

会場

iOSDCへの参加は二度目ですが、オフラインでの参加は今回が初めてです。 スポンサーブースがたくさん(19あったみたいです)あってとても活気がありました!

人がたくさんいるな〜と思っていたのですが、コロナ前から参加している方からするとこれでも以前の6割くらいらしく、オンライン参加だけの方も結構いたんじゃないでしょうか。

ノベルティコーナーには各スポンサーのノベルティが置かれていました、久々に歩いて汗をかいたのでうちわとタオルがありがたかった... ノベルティボックスに入っていたものが主ですが、自由に置いて行っても良いとのことだったので持って行ったメドベアのステッカーとカードを置いていきました。

盛り付け中

セッション

いくつか聞いたセッションを紹介したいと思います。

UIKit ベースの大規模なプロジェクトへの SwiftUI 導入 @kuritatu18

fortee.jp

弊社でもUIKitベースのアプリにSwiftUIの導入を順次行なっている最中なので参考になるかと思い聞いてみました。
すごく共感できる内容で、自分としてもそんなに間違ったことしてなかったなと安堵しました。

特にスモールスタートするべきというのは大事で、UIKitの動作を置き換えきれない部分やバージョンによって未対応な機能があったりと、落とし穴がまだまだあるので(特にiOS13をサポートしている場合)ここは慎重に進める必要がありそうです。

余談ですがMOTではフォントを独自の呼び名で使い分けてる件がおしゃれでいいなと思いました。

即時通知を導入する際に考えるべきこと @aomathwift

fortee.jp

集中モードや通知要約など既存のPush通知が見られづらくなっているなか、ユーザーにとって重要な通知を確実に届ける方法として、iOS15以降から使えるinterruption leveltime-sensitiveにするというのを紹介されていました。

こういった機能はちゃんとルール決めをしておかないとなんでも対象にした挙句ユーザーに設定で表示されないようにされてしまう懸念がありますが、Push通知を新設する際のルールをフローチャート化して運用しているそうです。

モバイルアプリの行動ログの「仕込み」を快適にする @yujif_

fortee.jp

ログを取得して利用状況の分析をするというのはいろんなアプリやサービスでされていそうですが、そのログを収集する際の仕組みづくりについてのセッションでした。

Markdownでログの仕様を記述するとSwiftのコードが生成されて、あとはログの送信箇所に実装するだけという仕組みを作っていて、ログの仕様がgitで管理できてかつ仕様と実装の乖離がないというのは体験としてすごくよさそう。 ログが本当に送られているのかをチェックできる機能も紹介されていて、非常に参考になりました。

まとめ

オフラインでの参加は初めてということもあって浮き足ってしまい、あまり集中してセッションに望めなかったところはありますが、後ほどアーカイブでしっかり見ようと思います。

正直なところセッションの内容を頭に入れることを考えるならオンラインの方が適しているように思えますが、オフラインだと各企業やスピーカーの方々がイベントを盛り上げようとしている熱量が伝わってきて、とても刺激的でした。

私も弊社の取り組みとしてSwift Quizを作成し、一部はパンフレットにも記載されています。全問はサーバーサイドSwiftで書かれたWebページで公開しており、こちらに答えや解説を載せています。 まだチャレンジされていない方はぜひチャレンジ&結果のシェアをお願いします!

サーバーサイドSwiftにご興味のある方は今回のWebページについてこちらの記事で解説されていますので読んでみてくださいね。


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

■募集ポジションはこちら https://medpeer.co.jp/recruit/entry/

■開発環境はこちら https://medpeer.co.jp/recruit/workplace/development.html

RubyKaigi 2022 感想戦を開催しました!

$
0
0

こんにちは、バックエンドエンジニアをやっている吉野です。

9月の 8, 9, 10日に三重県で開催された RubyKaigi 2022 に現地で参加してきました。
現地参加はもちろん、RubyKaigi 自体に初参加だった私は Rubyist たちの熱量の高さ、レベルの高さにひたすら圧倒された 3 日間でした。すごかった。

さて、そんな RubyKaigi に関して、MedPeer では感想戦として技術アドバイザーの Matz こと、まつもとゆきひろさんによる解説・コメントをいただく会を開催いたしました!

この記事では、その感想戦の様子をお伝えします。

感想戦の様子

Matz さんによるコメント

Matz さんより RubyKaigi に参加しての感想や、各セッションについての解説・コメントをいただきました。

ここではその一部を簡単にご紹介しようと思います。

オフライン開催について

  • 2 年半ぶりにオフラインカンファレンスに参加
  • オフラインコミュニケーションは情報の密度が高い
  • カンファレンスの醍醐味はオフラインコミュニケーション
  • 雑談からうまれるものもある
  • 三重のご飯が美味しかった

2019 年以来、3 年ぶりにオフライン開催された今回の RubyKaigi。
やはりオフラインならではの良さがあるようです。

参加者からはこんなコメントがありました。

みなさん久しぶりのオフラインイベントを堪能しているようでした。
一方でオンラインの更なる発展を望む声も聞こえてきました。

- わいわい
- RubyKaigi 参加しましたノ
- 久しぶりすぎてオフラインでどう振る舞うか忘れてました
- 久しぶりのオフラインだと人疲れ、コミュニケーション疲れはしそう
- 今後は VR に可能性はありそうですよね
- バーチャル廊下(雑談スペース)、もっと発展してオフラインに近づいてほしい

Ruby meets WebAssembly

  • WebAssembly について、当初はマイナープラットフォームのサポート程度に認識していた
  • そのため、@kateinoigakukun さんから「マージしたい」と言われた際に気楽に「いいよ」と答えていた
  • WebAssembly がメディアに取り上げられてバズったときには「みんなそんなに WebAssembly に期待していたの?」と驚いた
  • これまでにも Opalなどを利用してブラウザで Ruby を動かすことも可能だったが、いくつかの機能制限があった
  • 一方、Ruby WASM では機能制限がない Ruby を再現できている
    • クックパッドさんが Ruby WASM を使用して提供していたクイズを通して Opal との違いを感じた

参加者のコメント

- WebAssembly!
- これかな https://www.publickey1.jp/blog/22/rubywebassemblywasiwebassemblyruby.html
- WebAssemblyはゲームチェンジャーっておっしゃってましたねkateiさん

クックパッドさん提供のクイズは多くの人が挑戦したようですが、その難易度の高さに苦戦していたようですね。
ちなみに私が 4 問目で止まっていることは秘密です。。。Ruby なにもわからない

- クイズやった!
- めっちゃ難しかった
- 難しかったです
- 中のソースコードを読む方に興味が行ってしまった...
- 同じく16で止まってます
- 10問目で詰みました

Building a Lightweight IR and Backend for YJIT

  • Maxime さんのチームが作る PR はとても良い
    • 「大きすぎるから分けて」といったこともなく、ほぼ完璧なものが来る
  • YJIT が AMD64 しかサポートしていない
  • Apple の Rosetta 2 はよくできているものの、JIT コンパイラは流石に動かない
  • YJIT IR という中間表現を導入し、マージされたので ARM64 の CPU を搭載した Mac でも動くようになった!

こちらの話題では登壇者のレベルの高さに感嘆の声が上がっていました。
YJIT についてよくわかっていない私も、Ruby の生みの親をして「完璧な PR」と言わしめるすごさはわかりました。すごい。

- Maxime すごい人なんだな...(すごい
- すご
- すげぇ
- 天才だ

他にも多くのセッションについてコメントをいただきましたが、書ききれないため割愛させていただきます!

質疑応答

今回は時間の関係で 1 つしか質疑応答できませんでしたが、参加者からの質問に Matz さんにお答えいただきました!

Question

  • WASM の活用について、 gem 依存をなくす前提で活用した方が良いのか、必要な gem のみダウンロードできるような機構が提供される方向なのか、など今後の展望プランはあるでしょうか?

Answer

  • 現在は gem を使えないが、「Ruby で書かれた gem は使えるようにしていく」といった話が出ていることは聞いている
  • 最終的な目指すところは把握していない

おわりに

今回は Matz さんに RubyKaigi のセッションをおさらいする形で解説いただきました。
セッション内容の細かい解説から、コミッター内での裏話まで非常にタメになるお話が満載でした。
それにしても、現地参加できるだけでも貴重な体験なのにその上 Matz さんの解説を聞けるなんて恵まれすぎているのでは?と改めて感じています。

Matz さん、どうもありがとうございました!!


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

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

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

■開発環境はこちら

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

DroidKaigi 2022にプラチナスポンサーとして協賛します!

$
0
0

こんにちは。Androidエンジニアの伊藤です。 DroidKaigiまで 1週間となりましたね。 弊社はDroidKaigi 2022にプラチナスポンサー✨として協賛します!
メドピアからはオリジナルクイズとして、「DroidQuiz」の出題と会場ブースの出展を予定しています。 エンジニアによるセッション登壇も行います!今回はその一部をご紹介します!

DroidQuizの一部紹介

DroidKaigi 2022当日からAndroidやKotlinに関する DroidQuizを8問Webで公開する予定で、その一部を紹介します。

DroidQuiz

いかがでしょうか?

他にも問題があるので当日挑戦してみてください! またクイズに答えてTwitterでシェアしていただくと、グッズがもらえるのでぜひ弊社のブースに立ち寄ってください 🎊

弊社Androidエンジニア登壇の紹介

弊社Androidエンジニアの@Tahia910が 社内でのモバイルアクセシビリティ推進について発表します。 droidkaigi.jp

是非ご興味のある方はご覧になってください!


メドピアでは一緒に働く仲間を募集しています。
弊社ではモバイルエンジニアがJetpack Composeの勉強会を行ったり参加したり積極性を持ったエンジニアが多いです。
ご応募をお待ちしております!

■募集ポジションはこちら
https://medpeer.co.jp/recruit/entry/

■開発環境はこちら https://medpeer.co.jp/recruit/workplace/development.html

Vue Fes Japan Online 2022にスポンサーとして協賛します!

$
0
0

こんにちは、メドピアでフロントエンドのテックリーダーを務めている小林和弘です。
待ちに待ったVue Fes Japan Online 2022の開催が来週に迫っています。 2019年は台風、2020年以降は新型コロナウィルス感染症によって中止となったVue Fes Japan。2022年、満を持してオンラインカンファレンスとしてVue Fes Japanが開催されるということで、私たちもとても楽しみにしています!

メドピアもVue Fes Japan Online 2022にプラチナスポンサーとして協賛していまして、スポンサーセッションとして、『メドピアのサービスにおけるテスト戦略の過去と未来』をテーマに私がお話しさせていただくことになりました。
(個人的にもスポンサーさせてもらっています)

今回は私が登壇するセッションの概要を簡単にご紹介します!

セッションの概要

私は、2019年10月にメドピアへ入社したのですが、入社した当初は、フロントエンドチームの一員として、横断的に事業部全体の開発に携わっていました。
その後の組織改編で、各事業部にフロントエンドエンジニアを配置することになり、そこで薬局と患者さんを繋ぐかかりつけ薬局化支援サービス「kakari」の開発を担当し、今は「kakari」にあわせて、かかりつけクリニック支援サービス「kakari for Clinic」というサービスの開発、運用を担当しています。

※「kakari」とは…
2019年6月に薬局向けのかかりつけ薬局化支援サービスとしてリリース ※「kakari for Clinic」とは…
2020年9月にかかりつけクリニック支援サービスとしてリリース

今回のスポンサーセッションでは、私が日々開発に携わっている「kakari」において、フロントエンドのテスト戦略をどのように立て、実行しているのかについて『メドピアのサービスにおけるテスト戦略の過去と未来』と題してお話します。

スポンサーセッションは11:00〜です。 ぜひご興味のある方はご覧になってください!


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


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

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

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

■開発環境はこちら

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


DroidKaigi 2022 参加レポート

$
0
0

Androidエンジニアの池上です。 メドピアがプラチナスポンサーとして協賛しているDroidKaigi 2022が10月05日~10月07日の3日間で行われました。 私はDay1とDay2にオフライン参加してきましたのでその内容をご紹介したいと思います。

会場の様子

Day1とDay2は東京ドームシティのプリズムホールで開催されました。 とても広い会場の中で、多くの企業がブースを出展しておりとても盛り上がっていました!! 私はオフラインでの参加は初めてでしたが、Androidに関心のある・携わっている人たちがたくさんいることを改めて実感することができてとても感動しました。

会場ではスタンプラリーが実施されており、楽しみながらさまざまな企業のブースを回ることができます。

瞬く間にスタンプラリーを制覇するVPoE

メドピアブース

メドピアのブースでは『Androidエンジニアは健康か?』の内容でアンケートを行いました。 座っている時間が1日平均7時間以下かどうか、などの健康に関する質問をDay1とDay2で合計6問用意しました。 設問の枠からシールがはみ出てしまうほど多くの方に参加いただき大変嬉しく思います!

ちなみに結果は以下のようになりました。

Day1

健康への意識は持ちつつもなかなか行動に移せていない・・・という結果に

Day2

週2回30分以上運動している方が半分近くいらっしゃいました!
Day1の結果だけだとAndroidエンジニアの健康が心配になってしまうところでしたが一安心ですね笑

スポンサーセッション

Day1のセッションが全て終了した後に協賛企業によるスポンサーセッションが行われました。 ルールは「時間は3分間・内容は自由」だけであり、運営の方たちも各企業がなにを発表するのか事前に知らなかったようです。 短い時間でも印象に残るような趣向を凝らしたセッションの連続で会場も大盛り上がりでした! メドピアではDroidKaigiに向けて作成した『Droid Quiz』の紹介を行いました。

ガチガチに緊張しているAndroidエンジニア

AndroidとKotlinに関するクイズが計8問ありますので興味のある方は下記から挑戦してみてください!

droidquiz.medpeer.co.jp

セッション

いくつか聞いたセッションをご紹介したいと思います。

2022年ヘルスケアアプリのつくり方

droidkaigi.jp

Google I/O 2022で発表されたHealth Connectをどう導入していくかの知見を共有していただきました。

Health Connectでは、今まで別のアプリで管理していた体重や歩数などの健康・フィットネスに関するデータをまとめて管理できるようになるようです。 今後Health Connectを使用するユーザーが増えていくようであれば、健康に関するデータを扱うアプリでは導入が必須になるような印象を受けました。

また、Google FitとHealth Connectの比較も紹介いただきました。 弊社のヘルスケアアプリではGoogle Fitを使用しているものもあるため、今後の対応をどう進めていくかを考える上でとても勉強になりました。

Why Projects Succeed: Lessons Learned from the Android OS

droidkaigi.jp Androidのこれまでの歴史を振り返りながらどうしたらプロダクトが成功するのか考えるセッションでした。

まずAndroidの歴史が非常に興味深かったです。
Android OSは最初デジタルカメラ用のOSとしてデザインされたことを始めて知りました! 他にも「Android端末の販売台数がガラケーを追い越したのはいつか」などAndroidのこれまでのお話をさまざまな角度から聞くことができました。

「What Can We Learn From Android?」として現代のプロダクトに活かせるエッセンスもいくつか紹介されています。

Crunch times happen ... but death marches shouldn't

胸に刻みたい言葉だ笑

実例から学ぶJetpack Composeのパフォーマンス改善

droidkaigi.jp Jetpack Composeで実装する際にパフォーマンス面で気をつけることを実例を交えながら紹介いただきました。

弊社のアプリでも新画面などから徐々にJetpack Composeへの移行を進めています。 Composeへ移行するにあたり、Recycler Viewと組み合わせた時のパフォーマンスなどに不安を感じていたのでとても参考になりました。Layout InspectorでRecomposeの回数確認できるのはとても便利そうでした。

個人的には「早すぎる最適化を避ける」というのが一番刺さりました。 パフォーマンスのことを考えすぎて、可読性がさがったり実装が遅くなっては元も子もないので、パフォーマンスの問題に直面してから最適化を検討するようにしていきたいです。

終わりに

現地参加・ブースの運営・スポンサーセッションなど初めてづくしのDroidKaigi 2022で、非常に有意義な体験をさせていただきました。 オフライン参加することで、DroidKaigiスタッフ・スピーカー・各企業の方達のイベント、そしてAndroidを盛り上げようする情熱がひしひしと伝わってきました。来年もオフラインで開催されるようであれば、是非現地参加しようと思います!!


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

■募集ポジションはこちら https://medpeer.co.jp/recruit/entry/

■開発環境はこちら https://medpeer.co.jp/recruit/workplace/development.html

Fluent Bit で ECS コンテナログから特定ログを抽出する

$
0
0

SREチームの左サイドバック @kenzo0107です。

今回は ECS コンテナログから特定のリクエストによるログを抽出し、 Athena でクエリ捜査できる様にした話です。

コンテナログから特定リクエストによるログを抽出する目的

以下への一助としたい為に実装しました。

  • アプリケーションの改善となるデータの集計
  • 問題発生時の調査

コンテナログはどのように出力されるか

ECS コンテナログを JSON 形式で出力すると以下の様になります。

{"source":"stdout",
    "log":"{\"method\":\"GET\",\"path\":\"/sre/boshuchu\",\"format\":\"html\",\"controller\":\"SRE::BoshuchuController\",\"action\":\"show\",\"status\":200,\"duration\":11.07,\"view\":0.73,\"level\":\"INFO\",\"user_id\":null,\"ip\":null,\"referer\":null,\"user_agent\":null,\"time\":\"2022-09-29T01:14:40+00:00\",\"params\":{}}",
    "container_id": "596d27e777c54922a63fa0d11716ee26-265927825",
    "container_name": "web",
    "ecs_cluster": "main",
    "ecs_task_arn": "arn:aws:ecs:ap-northeast-1:123456789012:task/sre-love/h1a2p3p4y5l6i7f8e9s0r1e2",
    "ecs_task_definition": "sre-love:123"
}

上記例では log キーに logrageで JSON フォーマットされた Rails ログが含まれています。

参考: タスク定義の例 - Amazon Elastic Container Service

上記ログを特に整形せず、Athena でクエリ実行すると log キーに JSON 形式の文字列が表示されます。1

Athena でクエリ実行した際の log キー : lograge で JSON フォーマットされた Rails ログ

このログにアプリケーションからキーを仕込み、そのキーが存在する場合を特定ログと見做すことができます。

また、この JSON の個々のキーで検索できる様にすることで先述の目的が達成できそうです。

lograge で JSON フォーマットした Rails ログの個々のキーを Athena でクエリ実行できる様にした Glue テーブル

構成

  1. ログ配信は Fluent Bit コンテナに委譲
  2. 特定ログは Kinesis Firehose に配信
  3. コンテナログは CloudWatch Logs に配信2
  4. Glue Crawler で S3 に保管されるログをクローリングし Glue テーブル作成
  5. Athena から Glue テーブルに対しクエリ実行

Kinesis Firehose 等のリソースの構築は Terraform Cloud Private Registryを利用し手間を省力化しています。

Fluent Bit の処理の流れ

  1. 全コンテナログは CloudWatch Logs に output
  2. Stream Processor で Rails コンテナログのストリームを作成
  3. 上記ストリームを Parser や Filter で整形し Kinesis Firehose に output

以下に Fluent Bit の実装内容をまとめています。3

github.com

トピック

テスト実施方法

実は本ブログのメインはこちらになります。
皆様に聞いてみたかったのが設定ファイルのテスト実施方法についてです。
まずは皆様に聞く前に自身の手の内を見せたいと思います。

概要は以下になります。

  1. テスト用 Fluent Bit コンテナを起動
  2. テストデータを HTTP Plugin で Input
  3. 出力されたデータが想定通りか確認

テストは GitHub Actionsで実施してみました。 テスト実施に当たって工夫点を以下にまとめます。

INPUT は HTTP Plugin を採用する

http Input pluginを使用することで Fluent Bit を HTTP 経由で複数の任意のタグ付けしたログを POST できる様になります。

テスト用 Fluent Bit では設定ファイルをラップし http input plugin を設定しています。

test/test.conf#L1-L4

[INPUT]
    Name http

@include extra.conf

.github/workflows/test_fluentbit.yml#L50-L59

- name: run fluentbit for testing
        run:>
          docker run --rm -d
          --name fluentbit
          ...
          -v $(pwd)/test/test.conf:/fluent-bit/etc/test.conf
          test-fluentbit:latest
          /fluent-bit/bin/fluent-bit -c /fluent-bit/etc/test.conf

他 Plugin との比較

  • dummy input pluginは、テスト毎に conf ファイルを読み込ませ直す必要があり、 fluentbit を起動する必要があり、実行時間が掛かります。複数の dummy データを流すことも可能ですが、結果の判定のしにくさがありました。
  • tail input pluginは、 上記同様、テスト毎に conf ファイルを読み込ませる必要があります。
  • tcp input pluginは、外部からタグ指定できません。

テスト用に output.conf を上書き

商用環境で利用する output.conf を使用すると GitHub Actions 上のテスト時には Kinesis Firehose への接続ができずエラーとなる為、 テスト用に output.confで上書きしエラーを回避しています。4

test/output.conf

[OUTPUT]
    Name file
    Match *
    Path /tmp/

[OUTPUT]
    Name stdout
    Match *

.github/workflows/test_fluentbit.yml#L56

run: |
          docker run --rm -d \
          -v $(pwd)/docker/fluentbit/test/output.conf:/fluent-bit/etc/output.conf \
          test-fluentbit:latest \

file output pluginを利用しているのは、整形後のログをファイルとして出力し結果比較に利用します。

GitHub Actions 上で docker run で起動したコンテナにアクセスする為に network 作成

GitHub Actions 上で docker runで起動したコンテナは 127.0.0.1 ではアクセスできません。 その為、 docker network を作成しその network 上から curlimages/curl:latest経由で curl を fluentbit コンテナに対し実行しています。

.github/workflows/test_fluentbit.yml#L45-L70

- name: fluentbit コンテナへ外部から http 経由でアクセスすべく、docker network を作成
        run: docker network create actions

      - name: run fluentbit for testing
        run:>
          docker run --rm -d
          --name fluentbit
          --network actions
          ...
          test-fluentbit:latest
          /fluent-bit/bin/fluent-bit -c /fluent-bit/etc/test.conf

      # NOTE: http://fluentbit:9880/web-firelens-dummy に対して curl することで #       tag=web-firelens-dummy を付与したログを fluentbit に POST できる。- name: fluentbit コンテナへ Rails コンテナログを http 経由で POST する
        run:>
          docker run --rm
          --network actions
          --link fluentbit:fluentbit
          -v $(pwd)/docker/fluentbit/test/web_container.log:/tmp/web_container.log
          curlimages/curl:latest -v -d @/tmp/web_container.log -XPOST -H "content-type: application/json"
          http://fluentbit:9880/web-firelens-dummy

expect filter plugin で対象ログが取得できているかチェック

expect filter pluginを使用しコンテナログから抽出したJSONフォーマットされたRailsログを expect で個々のキー値を検証します。
action exitでいずれかのチェックで失敗した場合、異常終了となります。

test/test.conf#L6-L26

[FILTER]
    name expect
    match eventlog

    key_val_eq method GET
    key_val_eq path /sre/boshuchu
    ...

    action exit

fluentbit が意図した振る舞いをしているかは出力するログファイルの内容を照合する

expect filter plugin は、抽出対象のログが取得できているかについて、キー単位でチェックが可能ですが、 「ログが配信されない」が正解の場合のテストには向きません。

以下は通常のコンテナログが改変されずにログ出力されるかのテストです。

 # NOTE: http://fluentbit:9880/web-firelens-dummy に対して curl することで #       tag=web-firelens-dummy を付与したログを fluentbit に POST できる。- name: fluentbit コンテナへ Rails コンテナログを http 経由で POST する
        run:>
          docker run --rm
          ...
          curlimages/curl:latest -v -d @/tmp/web_container.log -XPOST -H "content-type: application/json"
          http://fluentbit:9880/web-firelens-dummy
      - name:コンテナログファイルが生成されるまで待機する。生成されない場合、テスト失敗となる
        # NOTE: web-firelens-dummy タグでリクエストすると web_firelens_dummy というファイル名で生成されるrun: while [ ! -e /tmp/web_firelens_dummy ]; do sleep 1; done
      - name: Rails コンテナログが改変されず出力されること。実値と予測値が一致しない場合、テスト失敗とし異常終了する
        # NOTE: fluentbit 経由で出力されるログの JSON のキーは毎回順不同な為、 `--sort-keys` でキーを昇順にソートしています。run: |
          diff -q \
          <(sed 's|web_firelens_dummy: ||g' /tmp/web_firelens_dummy | jq -r --sort-keys '.[1]') \
          <(cat ./docker/fluentbit/test/web_container.log | jq --sort-keys .)

timestamp は変更されてしまう為、 ログ {"source":"stdout","log": ...}の内、第二要素の log キーを比較対象としています。
比較時に json は毎回順不同になる為、 --sort-keysでキーを昇順 (a→z) に並べています。 5

run: |
          diff -q \
          <(sed 's|web_firelens_dummy: ||g' /tmp/web_firelens_dummy | jq -r --sort-keys '.[1]') \
          <(cat ./docker/fluentbit/test/web_container.log | jq --sort-keys .)

fluentbit の構文チェック

- name: fluentbit 設定ファイル構文チェック
        run:>
          docker run --rm
          -e DELIVERY_STREAM_WEB_LOG=dummy
          test-fluentbit:latest
          /fluent-bit/bin/fluent-bit -c /fluent-bit/etc/extra.conf --dry-run

設定ファイルの構文チェックを実施しています。

設定に問題がない場合は以下の様に正常終了します。

Fluent Bit v1.9.8
* Copyright (C) 2015-2022 The Fluent Bit Authors
* Fluent Bit is a CNCF sub-project under the umbrella of Fluentd
* https://fluentbit.io

configuration test is successful

不正な構文がある場合は異常終了します。

総評

元々、ngx_mruby で SSL 証明書の動的読み込みシステム構築した際に Nginx の挙動をテストした方法をヒントに Fluent Bit のテストを実装してみました。

本当に皆さんどのようなテストをしているのか気になってます。コメントいただけると嬉しいです 😭

今回は lograge で JSON フォーマットされた Rails のコンテナログが対象でしたが、 同様の方式で他 F/W でもアプリケーションログ専用の Glue テーブルを管理しています。

また、DB にログを蓄積しているプロジェクトもありましたが、 Fluent Bit でログを S3 保存することで DB のコストを削減できた例もあります。

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


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


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

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

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

■開発環境はこちら

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


  1. Kinesis Firehose で JSON → Parquet 変換、 S3 保存し、Glue Crawler で生成した Glue テーブルを想定しています。

  2. CloudWatch Logs へコンテナログを配信することでタスク起動失敗時のログ調査が直ちにできる様に配慮しました。Kinesis Firehose はログが一定 byte (最大 128 MB)、もしくは、一定時間 (最大 15分間) S3 にログ配信しない様、バッファすることが可能です。バッファサイズを小さくし、ログレコードのサイズが小さくなると意図せぬコスト増となる可能性があります。弊社では、コスト抑制する意図から極力バッファの最大値を採用している関係で直ちに Glue テーブルに反映されないデメリットがあります。
    参考: https://docs.aws.amazon.com/ja_jp/firehose/latest/dev/limits.html
    プロジェクトの特性によってコンテナログを CloudWatch Logs でなく Kinesis Firehose に配信し、コスト削減を実施している場合もあります。

  3. 実装意図をできる限り commit ログにまとめましたので参考にしていただけますと幸いです。

  4. GitHub Actions で試用できる Kinesis Firehose コンテナの様なものがあればより実際の構成に近く利用したかったのですが、現状はなさそう。

  5. 可読性が悪く、シェル芸飛び出てきたのでつらみが増してる箇所です。皆さんどんなテストしてるのか知りたいと思ったのはまさにこの時でした 😅

Vue Fes Japan Online 2022にPlatinumスポンサーとして参加しました!

$
0
0

サーバーサイドエンジニアの栗崎です。

医師専用コミュニティサイト『MedPeer』サービスの開発を担当しています。

2022年10月16日にVue Fes Japan Online 2022が開催されました。メドピアはPlatinumスポンサーとして参加しました。

私は、今年に入り、業務の中でフロントエンドを開発する機会が増え、Vue.jsに対する興味が増し、初めてVue Fes Japanに参加しました。

さらに今回、個人スポンサーにもなってみました!

メドピアでは私を含め4名のメンバーが個人スポンサーをしました。

カンファレンス中はSlackチャンネルを作り、わいわい感想を言いながら視聴しました!

Platinumスポンサーとして

YouTube Liveで配信されるオンライン形式の開催でしたが、カンファレンス中、上で「メドピアトラック」を開設させていただきました。

個人スポンサー向けのギフトボックスには、メドピアからのノベルティとしてマスクケース、ステッカー、綿棒の3点をお届けしました!

スポンサーセッションでは、フロントエンドのテックリーダーの小林が『メドピアのサービスにおけるテスト戦略の過去と未来』を発表しました。

www.slideshare.net

  • RailsとVueを使ったアーキテクチャ構成でコンポーネントを確認する方法の課題への共感の声

  • StoryBookを破棄した意思決定への賞賛、反省を生かし別ProjectではStorybookを使ったコンポーネント開発を行った運用の見直しへの賞賛の声

  • CIツール *1を使いStoryファイルの追加強制する運用を模倣したい声

など多くの反応がTwitter上で見受けられました。

また、プレゼンテーションの幕間に30秒の新しい動画CMも放映されました。

これを機に、メドピアのエンジニアにおけるテックイシュー「つくるのは、ヘルステックのプラットフォーム。」とともに会社の存在をより多くの方に知っていただけたかなと思います!

カンファレンス中のようす

今回は計41セッションが行われていました。

タイムテーブル上は3つのトラックにわかれていて、それぞれ視聴したものを専用Slackチャンネルでコメントしあいました。

―話題その1ー

Slackで話題に挙がっていたことのひとつは、「Evan You に聞こう」で、小林の質問が取り上げられたことです。

このセッションではTwitter上のハッシュタグ「#vuefes_qa」のツイートから、Vue.jsのクリエイターである Evan You氏に質問をするセッションでした。

視聴者の皆さんも気になる質問を取り上げていただけました。

ちなみにEvan氏の回答は、VueとNuxtそれぞれのタイムラインで動いているため影響はないとのことでした。

―話題その2ー

オンラインで3トラックの配信ということもあり、各セッションどれを聞くか悩みながら、参加メンバー各々で気になるものに参加しました。

既に、アーカイブ動画も公開されましたので、見れなかったセッションや、もう一度聞いてみたいセッションなどがたくさんあるので、後日見てみたいと思います。

印象的だったこと

今回のカンファレンスを通して、私が印象的だったのは、「Vue2からVue3への移行」のお話でした。

現在私が開発しているサービスでもVue3への移行が課題で何か良いノウハウがないかなと楽しみにしていました。

参加したセッションは「Vue2 Vue3 マイグレーション 令和最新 最強」と「施策を止めるな!Vue2からVue3への移行」のセッションです。

1つ目のセッションでは、まず一人でVue3化を一気に進めたことに驚きました!

Vue2からVue3への移行戦略で、正規表現で一括置換したり、OptionsAPIからCompositionAPIへの書き換えをツール *2を作って行うなど、自分のチームでは行っていない方法で、バージョンアップ作業を進めており、勉強になりました。

移行のコストや、変更点が多く大変ですが、バージョンアップ後の期待が更に高まり、移行を進めていきたいと強く思いました!

2つ目のセッションでは、開発手法が似ていて、ビジネス施策を止めずにVueのバージョンアップを行っていかなければならない背景などがとても共感できました😭

スクラムイベントでVue3化を発言し、チームを巻き込みバージョンアップを推進する行動など大変参考になりました。

プロジェクト規模や使用ライブラリなど完全に模倣できる訳ではないですが、今後移行作業を進める上で通るであろう課題を事前に知ることができました。

バージョンアップのリリース時と並行して行っていたメイン施策をVue2で実装していた際にエラーが起こった注意点のお話も、私たちのプロジェクトでも起こりうる問題であるため、知見になりました。

まとめ

今回のVue Fes Japan Online 2022に初めて参加し、サーバサイドエンジニアの私でもとても楽しむことができました!

冒頭Evan You氏がVue.jsは導入ハードルの低く、学習曲線が緩やかで即戦力になれるとおっしゃっていました。

まさに私もサーバサイド開発を行いつつ、フロントエンドの一部でVue.jsを使い、フロントエンド開発を実際に行い、Vue.jsの導入ハードルの低さを体感し、Vue.jsにのめり込んでいます。

3年越しの開催でオンライン配信のなか、全セッションが時間通り円滑に行われ、Vue.js 日本ユーザーグループを初めとしたVueのコミュニティを生で観られたのも印象的でした!

メドピアチームとして、今後もVueコミュニティに貢献できるよう積極的に活動していきます!


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

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

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

■開発環境はこちら

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

メドピアは今年もKaigi on Rails 2022 に協賛します!

$
0
0

三国志クイズ全国ランカーのVPoEの平川@arihhです。

2022年10月21日(金),22日(土)の2日間で、初学者から上級者まで楽しめるWeb系の技術カンファレンス「Kaigi on Rails 2022」が開催されます。 メドピアは今年、ゴールドスポンサーで協賛を行います!

今年も会を盛り上げるべく、カンファレンスの概要から、エンジニアが楽しみにしているセッションなどもご紹介します!

Kaigi on Rails 2022とは

Kaigi on Railsは、2020年からオンラインで毎年開催されています。 コアコンセプトは 「初学者から上級者までが楽しめるWeb系の技術カンファレンス」 とされています。 Railsを中心としたカンファレンスではありますが、広くWebに関すること全般(例えばフロントエンドやプロトコルなど)についてもカバーされるため、難易度や専門性が高い技術カンファレンスよりも参加する心理的なハードルが低いのが特徴です。

Kaigi on Rails 2022 公式HP より一部引用

メドピアは今回で3回目の協賛です。Kaigi on Railsが始まって以来、連続協賛中です!

気になるセッションについて

現在出ているタイムテーブル(Day1Day2)の中で、特に気になるセッションについてエンジニアに聞いてみました。 以下に紹介するのは一部ですが、すでに視聴予定のメンバーはタイムテーブルを見て予習中のようです。

内藤さん「モジュラモノリスの事例を聴きたい。(Packwerk gem が良さそう)」

モノリシックRailsアプリケーションをモジュラモノリスへ移行しているnoteの事例 by Hiroya Shimamotokaigionrails.org

千葉さん「今携わっているサービスでも「状態管理」を頑張っているので、個人的に注目しています!」

7つの入金外部サービスと連携して分かった実践的な”状態管理”設計パターン3選 by Shohei Mitanikaigionrails.org

当日は、Kaigi on Rails専用の社内Slackチャンネルでも、感想コメントでワイワイしながら参加したいと思います!

Kaigi on Rails専用社内チャンネルはすでにワイワイしています


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

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

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

■開発環境はこちら

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

Web Designing 2022 年 12 月号でフロントエンド開発におけるインタビューが掲載されました

$
0
0

ウェブ制作出身でソフトウェアエンジニアの髙橋です。

2022年10月18日発売の「Web Designing 2022 年 12 月号」で、フロントエンドの実装時 React/Vue.js など SPA フレームワークを選択する理由について、計8ページに渡るインタビュー「制作者・制作会社は今こそ!React、Vue.jsに舵を切れ」を掲載いただきました。

現在発売中のWeb Designing12月号では、「Web構築最前線」と題して、React、Vue.js、Angular、Next.jsなど、今注目のWeb制作技術について特集しています。各技術がどんな場面で求められ、どう使いこなすべきかを一挙紹介です。気になるコーナーがあれば、以下より本誌をチェックしてみてください。
●マイナビブックス https://bit.ly/3fY3FPn
●Amazon https://amzn.to/3RZn0gM
●定期購読 https://bit.ly/3CqMjSU

Web Designing 2022 年 12 月号

先日開催された iOS エンジニアのカンファレンス、「iOSDC Japan 2022」向けに Vue.js (Nuxt) で制作した「Swift Quiz」の紹介もしていただいております。同僚の iOSDC 参加レポートがありますのでよければこちらもご覧ください。

ちなみに、先日公開した Android エンジニアのカンファレンス「DroidKaigi 2022」向けに制作した「Droid Quiz」も Vue.js (Nuxt) で制作しました。同僚の Droid Kaigi 参加レポートもご覧ください。後者は Vuetify.jsを使用するなど、より Vue.js コミュニティの恩恵を受けて制作されています。

当社は直近も Vue.js のカンファレンス「Vue Fes Japan Online 2022」でプラチナスポンサードを行うなど、Vue.js コミュニティを応援しております。こちらも同僚の Vue Fes 参加レポートがございますのでよかったらご覧ください。

--

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

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

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

■開発環境はこちら

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

Kaigi on Rails 2022 参加レポート

$
0
0

サーバーサイドエンジニアの千葉です。

メドピアがゴールドスポンサーで協賛している技術カンファレンス「Kaigi on Rails 2022」が10月21日と22日の2日間で開催されました。私自身も2日間通してオンライン参加してきたので、聞いたセッションの中からいくつか簡単に紹介したいと思います。

Kaigi on Railsグッズもおしゃれでいい感じ

RBSとSteepで始める型のあるRails開発とその運用

静的型解析を導入したRailsアプリケーションでの運用事例やメンテナンスコストを下げるための工夫、発生した課題についての発表です。

「RBSから受ける恩恵>RBSを導入するコスト」を実現するために、以下のような取り組みをプロジェクトで行っているとのことです。普段の開発で行うことをRBSにも導入する感じですね。

  • ドキュメントを整備することで学習コストを抑える
  • 自動更新・スクリプトを活用することで手作業を減らす
  • CIを活用し不正な状態が入らないように管理する(steep checkが通る、RBSが最新である等)

静的型解析を実際のアプリケーションに導入・運用していくには課題点がいくつか残っているそうですが、バグを検知する仕組みの1つとしてマイクロサービスへの導入を検討してみても良さそうと感じました。

今後はuntypedを減らす取り組みを行っていきたいとのことでしたので、それらで得られた知見もぜひ聞いてみたいですね。

youtu.be

kaigionrails.org

7つの入金外部サービスと連携して分かった実践的な”状態管理”設計パターン3選

外部サービスと連携した際の「状態管理」の設計パターンについての発表です。

外部サービスを使用することで実装コストは低くなる一方、複数システム間の「状態管理」の難易度は上がってしまいます。このセッションではテーブル設計上での要件や不整合が発生するケース、不整合が発生した場合の監視・リカバリ方法について、3つのパターン(リアルタイム型・事前予約型・完全非同期型)を踏まえながら解説してくださっています。

DBトランザクションやエラー検知・リカバリ方法といったパターン毎に抑えるべきポイントや実際のテーブル設計例を挙げていただいたことで、外部サービスをあまり利用したことがない人でも実装イメージがつきやすいと感じるセッションでした。

3つのパターンのうち、事前予約型の「状態管理」を理解していれば他の2パターンはその応用であるという点も面白いですね。

youtu.be

kaigionrails.org

森羅万象に「いいね」するためのデータ構造

似ているけど少し異なる「いいね機能」を実装するにあたり、失敗したデータ設計や開発中の悩み・苦しみ、それらを解決していくリファクタリングの道筋についてのセッションです。

リファクタリング前は商品・トピック・クチコミなどそれぞれで「いいねテーブル」を作成していましたが、ポリモーフィック関連を用いたリファクタリングを行ったことで変更に耐えられるデータ構造になったそうです。リファクタリングに伴うデータの移行手順についても解説されており、より実践的な内容だと感じました。

リファクタリングに取り組む予定があるプロジェクトに参画中の方は特に有意義なセッションだったのではないでしょうか。

youtu.be

kaigionrails.org

歴史あるプロジェクトのとある技術的負債を隙間プロジェクトの 210 PullRequests で倒しきった話

巨大な技術的負債解消への取り組み方、変更リスクとコストを下げた方法についての発表です。(個人的にタイトルで一番気になっていたセッションです。)

具体的には、7年間育った歴史あるRailsアプリに開発初期から存在していたオレオレフレームワーク「Crud Controller」を撃退した方法を以下の4つのポイントに絞って解説してくださっています。

  • スクリプト化
  • 変更リスクの軽減
  • チーム戦
  • モチベーションの維持

Crud Controllerとは

  • includeするとクラスメソッドcrud_controllerが生える
  • アクションメソッドをよしなに定義してくれる
  • search_one、scopeなどよしなにメソッドが生える
  • メソッドをオーバーライドしてレスポンスをカスタマイズできる

Crud Controllerのデメリット

  • コールバックの順序に依存が発生し、バグが生まれやすい
  • メタプロで可読性が低く、学習コストが高い
  • メソッドのオーバーライド等により、認知コストが高い

技術的負債を抱えているプロダクトは多いと思うので、それらを打倒するための計画やモチベーションの維持方法など参考になったという方も多いセッションだったのではないでしょうか。

youtu.be

kaigionrails.org

とりあえず抑えておきたい、Railsでの「テストの内容」の考えかた

テストコードを書く上で抑えておきたいテストで扱うべき「内容」に関しての発表です。

具体的には、テストケースを作成するためのノウハウ「テスト技法」の内の「同値分割法」と「境界値分析」について例題を踏まえながら解説してくださっています。

自身もどこまでテストを書くべきなのか分からなくなるタイミングがあるため、非常にためになるセッションでした。「同値分割法」と「境界値分析」は取り入れやすい技法であるため、日頃から頭に入れておくと良さそうですね。

youtu.be

kaigionrails.org

終わりに

Kaigi on Railsのコアコンセプトが「初学者から上級者までが楽しめるWeb系の技術カンファレンス」 ということもあり、比較的参加しやすいカンファレンスだと感じました。発表者・参加者からもRailsに対する熱量が伝わってくるイベントでもあり、ぜひ来年も参加したいと思いました。「カンファレンス参加はハードルが高そう、、、難しそう、、、」と思っている方でもぜひ積極的に参加してみてください。


メドピアでは一緒に働く仲間を募集しています。

ご応募をお待ちしております!

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

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

■開発環境はこちら

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

メドピアはRubyWorld Conference 2022にスポンサーとして協賛します!

$
0
0

今まで買ったラズパイの台数を覚えていないVPoEの平川(@arihh)です。

2022年11月10日(木)〜11月11日(金)の2日間にわたって、島根県立産業交流会館「くにびきメッセ」で開催されるRubyWorld Conference 2022。メドピアは今年もRubyスポンサーとして協賛します!

私も会場に伺う予定ですが、当日の各講演の様子はRubyWorld Conference公式YouTubeチャンネルでもライブ配信されるとのこと(参加登録不要・参加費無料)。 会場に行けないメンバーはYouTube視聴で参加する予定です!RubyWorld Conference専用の社内Slackチャンネルで、感想コメントを共有しながら、ワイワイと楽しみたいと思います。

RubyWorld Conferenceとは

RubyWorld Conferenceは、プログラミング言語「Ruby」の国内最大のビジネスカンファレンスです。Rubyに深いゆかりのある島根県松江市で毎年開催され、Rubyに関する最新技術の発信や先進的な利用事例の紹介や、開発者教育の状況などがさまざまなセッションを通じて発信されます。

RubyWorld Conference 2022 公式HPより一部引用

メドピアは2018年から毎年協賛しており、5年連続の協賛です!

開催実行委員会 委員長で、基調講演に登壇される「まつもとゆきひろ:Matz(@yukihiro_matz)」さんには、2020年からメドピアの技術アドバイザリーを務めていただいています。

メドピアもセッションに登壇します!

DAY2のスポンサーセッションでは、私、平川が『Rubyとともに歩んだメドピアとこれから』をテーマにお話させていただきます。

メドピアは2016年にPHPからRubyに移行を進め、現在はRuby on RailsでのWebアプリケーション開発を行っています。 メドピアとRubyの歩みを振り返りつつ、組織の変更についてのお話などをしていこうと思います。

RubyWorld Conference 2022 Day2 プログラム

スポンサーセッションは11:40〜です。 ご興味のある方はぜひご覧になってください!

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

■募集ポジションはこちら https://medpeer.co.jp/recruit/entry/

■開発環境はこちら https://medpeer.co.jp/recruit/workplace/development.html


Kotlin Fest 2022 参加レポート

$
0
0

どうも、Androidエンジニアのティフェン(@tahia910)です。

12月10日に「Kotlinを愛でる」をビジョンにしたテックカンファレンス「Kotlin Fest」がオンラインで開催されました。 1日2 trackで、Kotlinへの愛を感じるセッションを見ながら、Kotlinファン同士で交流や知見の共有が出来る楽しいイベントです。

弊社は今年もひよこスポンサーとして協賛しました!

そして私含めて弊社Androidエンジニア数人も参加させていただきましたので、 今回は皆さんの注目したセッションをご紹介出来ればと思います。

ノベルティがたくさん床に置いてある。メドぴあ株式会社からの物(マスク、綿棒、ウェットティッシュ、ステッカー)とチラシは上に置いてある。
参加者はノベルティをたくさんいただけます!

みんなの推し

新しいKotlinのコンパイラK2についてや、どうして作り直すことに至ったのか、などについて紹介いただきました。
K2はパフォーマンスの改善に力を入れているようで、FrontendでもIR(Intermediate Representation)を使用することでこれを実現しているみたいです。 現段階でシングルスレッドでもおよそ2倍程度はやくなるようです。すごいですね!
作り直すに至った経緯としては、既存のFrontendのコードに対してコンパイラ・IDE・third partyのIDEが依存しており、リファクタリングが困難であったことが背景としてあるようでした。
一方で今の状態が完全に悪いわけではなく、この状態でやってきたからこそ無事にKotlin1.7までリリースすることができた、とも話されていました。

普段はあまり知ることができないコンパイラの内部について丁寧に説明いただける貴重なセッションでした。
私自身コンパイラについてはあまり理解できていなかったのですが、今回のセッションをきっかけにもう少し踏み込んで理解してみようと思うようになりました!
ちなみにK2はまだAlphaですが、-Xuse-k2 で有効にすることができますので、みなさんも試してみてはいかがでしょうか!?


  • 伊藤さん(@y2kit_1127)にはなんと3つのセッションも選んでいただきました!

1.「Kotlin/NativeのNew Memory Managerに移行しよう

Kotlin Multiplatform Mobileの Old Memory ManagerのKotlin/NativeにおけるKotlin coroutinesや並列、非同期処理の課題やNew Memory Managerでの改善点について、ご紹介いただけました。
Kotlin Multiplatfrom Mobileは個人的にとても興味があり試聴してみました。以前C++言語を用いたアプリケーション開発を経験したことがありますが、MulchThreadな処理上でもstd::atomicなどあり、Old Memory Managerではその方式に似たようなライブラリがあるなっと思いました。New Memory Managerではメモリーリークを起こしづらい点やfreeze()による開発者体験を下げるようなコードが排除されているなど、メリットが大きいですね。
今後なにかしらでKotlin Multiplatformにふれていけたらと思います!

2.「型だけでバグを減らそう!Kotlinの型パワーをつかった実践タイプセーフエンジニアリング

Kotlinの型機能を使ってコンパイルで検出できる実装ミスを増やしアプリケーションの品質を高める方法を説明しております。
色々なパターンで実装ミスやバグなどを紹介していただけました。
コンパイル時の実装のミスに気づきバグ減らせるのは品質面など良くなりそうですし、開発者体験が良くなりそうだと思いました。
個人的には「sealed class を使ってデータの不整合型が起こり得ない型を定義する」はよく使う実装の一つで、 AndroidでもJetpack Composeに渡すUIの状態などもsealed classを使って定義していました。
改めてなぜsealed classを使うのか?というのが意識していけそうだと思いました!

3.「もう迷わないCoroutines〜suspend funとChannelとFlow〜

kotlin Coroutinesについて、suspend function、Flow、Channel、の使い分けなど?BroadcastChannelとMutableSharedFlowのどちらを使ったらいいかなどご紹介いただけました。
普段CoroutinesをAndroid開発でも、Flowやsuspend functionを主に使用しておりますが、使用箇所含めChannelの使い所など改めて勉強になりました。
絶賛プロダクトでもRxとCoroutinesが混同しているため、同じようにRxからCoroutinesの置き換えていきたい気持ちが強まりました!


言語機能の良くない使い方をご紹介いただき、とても考えさせられるセッションでした。
個人的に一番刺さったところは、スコープ関数の深いネストを避けるためのコツです。 一部を別途プライベート関数か拡張に書き換えたことだけで、処理が圧倒的に読みやすくなりました。。!よく見かける問題ですし、もう衝撃的でした。
他にもデフォルト値の必要性や決め方、data classやsealed classを書く時の罠などもご説明いただき、とても参考になりました。
是非もう一度チームメンバーと一緒に見たいセッションです。

おわりに

様々な方面でKotlinの面白さが伝わる一日でした。 おかげさまで同僚と共に楽しく勉強させていただきました。

もし来年オフライン開催となりましたら是非現地でまた参加してみたいと思いました。

それまではKotlinの成長を温かく見守りましょう。


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


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

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

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

■開発環境はこちら

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

Vue3 に向けて取り組み続けていること

$
0
0

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

Vue Fes Japan Online 2022 でお話したことを少し掘り下げようと思います。

薬局のかかりつけ化支援サービス kakariの Vue3 対応の方針についてのお話です。

Vue2 の LTS 終了まであと 1 年なので「もう Vue3 対応が終わっているよ」というサービスも多いかと思いますが、kakari はこういう方針でやってるよというお話をします)

Vue3 の障壁

kakari では開発初期から、class ベースで Vue の SFC(Single File Component)を書くことができる vue-property-decoratorというライブラリが導入されていました。

このライブラリは開発があまり活発ではなく、Vue3 への対応が行われるか怪しい状況にあり、Vue2 から Vue3 へ migration するときの大きな障壁になっています。

GitHub に Vue3 化の issueは立っていますし、Vue3 対応のブランチも作成されていましたが、開発はあまり進んでいないようでした。

vue-property-decorator の元となっている、Vue のコミュニティ内で管理されている vue-class-componentも同様の状況です。

vuex、vue-router も Vue3 化に伴い、メジャーバージョンアップする必要があります。

当然、Vue3 の Breaking Changesにも対応しなければなりません。

Vue2 の抑制

kakari で取り組んだのは、Vue2 の依存のコードを増やさないことでした。

Vue3 対応のコードが書ける各種ライブラリのアップデートと導入を進めました。

vue-property-decorator

class ベースのコンポーネントをこれ以上増やさないように、@vue/composition-api の v1.0.0-beta.21 を 2020/12/08 に導入しています。

2020/12/08 に package.json に追加された @vue/composition-api v1.0.0-beta.21 のキャプチャ

RC 版を待たずに導入したのは今思えばリスキーな選択でしたが、v1.0.0-beta.1 のリリースが 2020/07/01 で 5 ヶ月間ですごい熱量で bugfix が行われていたので「まあ大丈夫だろう」と楽観的に導入を決定しています。

導入時点で class ベースで書かれたコンポーネントは 134 ファイル存在していましたが、導入してしまえばこの 134 ファイルが増えることはないので、黙々と composition-api に書き換えれば Vue3 の migration に着実に近づきます。

なお現在では composition-api が同梱された vue v2.7.x を利用しているので、@vue/composition-api はプロジェクトからは削除されています。

vuex

composition-api 導入後、Vuex3 での state 管理をやめ、composition-api を利用して state 管理を composable に切り出すようにしました。

state を reactive で管理して、state を更新する関数(Vuex だと actions に相当します)を返却する Object を用意しています。

言葉だと説明がしづらいので、雑なサンプルコードを用意しました。

composable のサンプルコード

コンポーネント間での state 参照は provide を使って大元の親コンポーネントから composable の Object を子コンポーネントに流して、子コンポーネント側は inject で Object を受け取るようにしています。

v3.ja.vuejs.org

composable の導入は 2021/06/15 で、この時点で Vuex3 の modules は 20 ファイルありましたが、導入後は Vue3 対応で migration が必要な Vuex3 の modules が増えることはありません。

現在では pinia(Vuex5)を導入しているので、composable での state 管理をやめて、新規の Store は pinia で作成しています。

既存の Vuex3 の modules も pinia に置き換えている最中です。

vue-router

vue-router は v3.6.0から v4 の useRoute、useRouterに対応した composables を提供してくれています。

v3.6.0 にアップデートして、コンポーネント内で Vue インスタンスの $route、$router にアクセスしている部分を useRoute、useRouter に置き換えてしまえば、Vue3 アップデートによる vue-router の修正はほぼ行わなくてよくなります。

kakari では vue-router v3.6.0 を導入して、$route、$router の参照をすべて置き換えました。

安全な migration

Vue Fes Japan Online 2022 では kakari のテスト戦略についてお話しました。

安全な Vue3 への migration が実施できるように E2E の自動テストを導入したというお話をしましたが、それ以外の取り組みとして不足していたコンポーネントのユニットテストを追加・編集してから composition-api へ migration を行っていました。

vue-class-component で Vuex を呼び出す独自の decorator が書かれていたので Vuex の mutation、action、getter が想定したタイミングで呼び出されているかということを確認するユニットテストを中心に書きました。

コンポーネントのみの Jest のカバレッジを、Vue Fes Japan Online 2022 が開催された 2022/10/01 時点と 2022/12/20 時点で比較すると下記のようになっています。各セクションが概ね 8 ~ 14% ほど改善していることがわかります。

Jest のカバレッジ比較

2022/10/16 時点で class ベースコンポーネントは 39 ファイルありましたが、2022/12/16 に class ベースコンポーネントはすべて composition-api に置き換えが完了しています。 努力の甲斐あってか、composition-api の migration で大きな事故は起こっていません。

vue-property-decorator を削除した PR

進捗を出す方法

Vue3 のマイグレーションはビジネス的なインパクトが(見た目上)小さいので対応が後手後手になりがちです。

kakari でも運用・新規開発・お問い合わせ対応の合間をみて Vue3 の対応を進めていますが、ただ闇雲に進めていては進捗やモチベーションが下がる一方です。その対策として、Vue3 で必要な対応をすべて洗い出して TODO リストを作成しています。

どのような修正が必要で、さらにどのファイルに修正が必要なのかをリストアップしています。

Vue3 対応の親 issue
vue-property-decorator の削除対応の issue

そして、各ファイルの修正工数と 1 週間で使えそうなリソースからざっくりとロードマップを作成しました。

Vue3 対応のロードマップ

前述した Vue2 の抑制対応を行って、Vue2 の LTS 終了までにやらなければいけないタスクが確定した(これ以上増えない)状態にしないと、新規追加されたコンポーネントや Store を TODO に追加してロードマップを引き直すという不毛なタスクが発生します。

まずは前述した各ライブラリのアップデートと導入、チーム内での共有を行うことをオススメします。

現状の進捗

残りのタスクは

  • Vuex3 → pinia
  • node_modules のコンポーネントのアップデート
  • Breaking Changes の対応

になっています。

Vuex3 → pinia

Vuex3 の pinia の置き換えは骨が折れますが、安全な migration ができそうな見立てがついています。

まず Vuex3 の modules のユニットテストを作成して、そのテストを pinia のテストに流用するという方法をとっています。

テストファイルの修正差分は 10% 、それも state の参照を $state に変更、dispatch を store のメソッド参照に置き換えるといった軽微なものです。ちょっとしたテストファイルの修正だけで、pinia の store の動作保証ができてしまいます。

実行するコンポーネント側のテストは、vue-property-decorator を composition-api に置き換える際に Vuex3 の mutation や action や getter を呼び出している部分のユニットテストを網羅的に書いていたことが功を奏して、ほぼ修正不要な状態になっています。

vuex3 のテストを pinia のテストに転用したときのコミット

node_modules のコンポーネントのアップデート

kakari では UI ライブラリは使っていなかったので node_modules で呼び出している Vue コンポーネントの影響範囲は抑えられてます。

唯一、Drag & Drop を実現するコンポーネントとして Vue.Draggableを利用していますが、こちらは Vue3 バージョンがすでにリリースされていました。

利用しているコンポーネントがメンテナンスされずに Vue3 バージョンが出ていなかった場合は、同じ機能を持つ他のコンポーネントを利用するか、自前でコンポーネントを作成する必要があります。

Breaking Changes の対応

公式の Vue3 Migration Guide には Breaking Changesがリストアップされています。

数は多いですが、対応が必要なものを調べてフィルターしてあげるとそんなにタスク量は多くなかったりします。

kakari では

が対応が必要なタスクでした。

Vue3 対応、そろそろはじめませんか?

Vue2 の LTS 終了は避けようのない未来です。

まずは Vue3 対応のコードを書くことからはじめてみませんか?


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


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

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

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

■開発環境はこちら

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

FigJam (Figma) でチーム目標達成のためのマンダラートワークショップを開催しました

$
0
0

モバイルアプリサービスの開発を担当している髙橋です。

最近読んだ本で「解像度を上げる」という本が良かったので、そこに記述のあったマンダラートを使ったワークショップを開いてみました。(本にはマンダラート自体の解説はありません、念の為)

エンジニアだけでサービスは作れないし運用できないしビジネス成長は難しいと思っているので、エンジニア以外のチームメンバーも集めてファシリテートしてやってみたという話です。

期待効果・効能

とにかくアイデアを出したい時とか、チームの情報共有の量や質(解像度)を上げたいとき、今後の方針を考えていきたいときに使ってみると役に立つかもと思います。

マンダラートとは

今回使用するワークシートのことです。特殊なルールがある 9x9 のマトリックスです。大谷翔平さんが高校時代使用していたことで話題になりました。

リモートでの実施なのでこちらの Figma コミュニティーの FigJam ファイルと FigJam を使って実施しました。

ワークシートの埋め方

  1. 「テーマ」にワークショップのテーマを予め決めて入力しておく
    • 例:「サービスが業界ナンバーワンになる」「売上が XX 円達成する」「〇〇な技術に載せ替える」「最強のエンジニア」など
  2. メインテーマの周りのマスに「関連するキーワード」を書く
    • 例:「サービスが業界ナンバーワンになる」なら「①ユーザーが集まってくる」「②話題になる」「③解決できない課題が無い状態」「④みんなが使える」など
  3. そのキーワードを外周にコピーし、さらにそのキーワードに関連するキーワード書いていく
    • 例:「①ユーザーが集まってくる」なら「宣伝頑張る」「覚えやすい名前」「ポイントがもらえる」とか

例えばこんな感じです。 賛否両論のありそうな図ができました。

チームワークショップ進め方例 (1hours + α 想定)

  1. 予めワークショップテーマは決めておいて、参加者分のワークシートを作成する
  2. 配られたワークシートの「要素」を相談して8つ入れる (10min.)
    • 普遍的な内容だとより良いかも
    • 見える範囲が広い役職の高い人に決めてもらうでも OK
    • 時短のために予め決めておいても良いかも(で、会のキックオフ時に齟齬ないかを確認する)
  3. 各々がワークシート外周部分にキーワードを入れていく (20min. 下記図1)
    • おバカなアイデアも全然 OK
    • できるだけ各々頑張って埋める
  4. 各々がワークシートに何を入れたか特に重要だと思ったアイデアを各々が発表する (時間は参加人数・チーム分け次第だが、各 3min 想定)
  5. 全員のワークシートをマージして、関連しそうなキーワードをまとめたり、重要だと思ったものにはスタンプをつけてもらう (5min. 下記図 2)
  6. まとめた状態にしたワークシートについてまとめコメントを数名に言ってもらう (10min.)

様子

FigJam の左上でタイマーをかけつつ集中できそうな音楽を流せる

各々が入力している状態

それぞれのアイデアをマージした状態

ワークショップ後の活用方法

  1. チケット化できそうであれば、記載された内容をチケット化して具体的にアクションにできるようにする
    • 優先度はチームや PM で判断する
  2. 他の人が書いた内容で、わからないキーワードがあれば、ググったり質問したり、そういうものが多ければシニアメンバーがフォローアップする
  3. 半年〜一年後とかにこれを振り返ってみるとよかったりするかも

その他注意事項

  • ブレストなので出した意見はなんでも神だし、否定はしてはいけない
  • 参加者はなるべく頑張って埋める
  • 新しいことじゃなくて、すでにチームも周知だと思っているアイデアや事実も書く

実施してみて

  1. 各々のメンバーの解像度がざっくりわかるので、リモートワークでありがちな情報の非対称性になっている部分が少しわかった
    • 役職の高いメンバーが見ている部分、または灯台下暗しになっている部分もわかる
    • 特にエンジニアが見えている部分とビジネスメンバーが見えている部分はかなり違うので、チーム各々が感じる課題が交換できた
  2. ファシリテーターに慣れがある程度必要そう
  3. 参加メンバーが業界経験が浅すぎたり、あまりにも新人だったりするとうまくいかないことがありそう。ある程度仕事をしたことがあるメンバー同士がおすすめかも

参考

終わりに

よかったら試してみてください!


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


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

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

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

■開発環境はこちら

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

スギサポwalkへのJetPack Compose導入の取り組み

$
0
0

こんにちは。Androidエンジニアの伊藤です。 スギサポwalkという歩数計アプリの開発を担当しており今回は Jetpack Composeを導入したので、この取り組みについて書いていきます!

Jetpack Composeとは

Jetpack ComposeはAndroidの新しいUIツールキットです。 宣言的UIとも呼ばれ、状態をUIとして表示するという仕組みです。 AndroidでUI開発を簡素化して、直感的なAPIにより良い開発体験が得られます。

また、数多くのAndroidのプロダクトで利用されています。

なぜ導入しようと思ったのか

主に以下の点によるメリットが大きいと考え、導入しようと考えました。

  • 宣言的UIによりAndroidViewよりも状態管理がしやすくメンテナンス性も上がることが期待できる。
  • AndroidViewと比べると再描画の際の再計算コストが小さく、パフォーマンスの向上が期待できる。
  • Jetpack Composeのコンポーネントは使い回しがしやすく開発コストが少しでもさげられそう。
  • Preview機能によりUI開発体験が以前よりも飛躍しそう。
  • Googleからも推奨されアップデートも沢山行われている。
  • フルCompose実装が難しい場合ComposeとAndroidViewを組み合わせて使える。

どのように導入していったのか?

まずは、Jetpack Composeを入門するにあたり弊社Android、iOSエンジニアが集まってPathWayを受講しました。 その後、スギサポwalkでは導入にあたり、導入障壁となる問題の解決と導入方針を決めました。

問題の解決

導入にあたり、以下の問題がありました。

  • Kotlin , AGP(Android Gradle Plugin)のVersionが古い

当初はKotlinのVersionが1.4、AGPが3.6.3で構成されており、StableなComposeが導入できませんでした。 そのため、KotlinとAGPを最新に更新する必要が出てきました。

  • アーキテクチャがMVPで構成されている

Composeは状態管理手法として、UDFアーキテクチャパターンが推奨されていますが、 スギサポwalkのアーキテクチャはMVP(Model-View-Presenter)で構築されています。
MVPでもUDFパターンを扱う事はできそうですが、ViewとPresenterはFragmentなどと密接に繋がっていて、後々の実装で障壁なりそうでした。 そのため、Composeを導入する画面はPresenterからAndroid Architecture ComponentのViewModelに置き換えていく作業を加えていくことにしました。

プロダクトへの導入方針

  • 影響箇所の少ないデバッグ画面や新規機能を開発する場合は積極的にComposeでUIを作っていく。
  • リソースの関係上、全ての既存画面のリプレイスは問題がない限りは行わない。
  • 既存のStyleやThemeに沿ったボタンやテキスト、Appbarなどはコンポーネント化していく。

実際に導入した箇所の説明

スギサポwalkでは、昨年12月頃から連続ログインボーナスという機能を導入しました。 ダウンロード後7日間の間で日付に応じて、マイルが付与されるお得な機能になります! ダウンロードして使ってもらえると嬉しいです😄play.google.com

apps.apple.com

連続ログインボーナス

連続ログインボーナスの画面は以下のような画面です!

連続ログインボーナス

画面構成について

画面の構成については以下のようなイメージです。 スギサポwalkは多種多様なモーダル画面が表示されています。
元々は、Activity → Fragment →XML(binding).
のような構成だったため、その構成に則ってXML部分をComposeに置き換えたような形になります。

コードでは以下になります。

   override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        super.onCreateView(inflater, container, savedInstanceState)
        return ComposeView(requireContext()).apply {
            setContent {
                setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
                AppCompatTheme {
                    LoginBonusViewScreen(
                        onCloseClick = {
                            // close event 
                        },
                        data = LoginBonusData()
                    )
                }
            }
        }
    }

今回実装した画面では状態とロジックが単純なため Composeに UIロジックとUI 要素を保有しています。

レイアウトについて

レイアウトについてざっくりとですが以下のようなイメージです。

Compose Node

Dialogがあり、Boxがあります。 その下にマイルの情報、連続ログインの情報やCloseButtonを表示するColumnStarAnimationを表示するLayerがあり重ねています。 マイルの情報、連続ログインの情報を表示するColumnの下には各種コンテンツを構成する要素が並んでいます。

工夫した点

工夫した点はStarのAnimationです。 StarのAnimationはAndroidViewの方で実装されていたObjectAnimatorを利用したImageViewだったのですが、 ComposeのAnimationでは再現が難しく、AndroidViewの実装をComposeに組み込むことで再現しました。

@Composablefun StarAnimation(modifier: Modifier = Modifier) {
    val ticks = remember { mutableStateOf(0) }
    val isStart = remember { mutableStateOf(false) }
    ObserveLifecycleEvent { event ->when (event) {
            Lifecycle.Event.ON_RESUME -> {
                isStart.value = true
            }
            Lifecycle.Event.ON_PAUSE -> {
                isStart.value = false
            }
            else->Unit
        }
    }

    LaunchedEffect(isStart.value) {
        while (isStart.value) {
            delay(ANIMATION_DELAY)
            ticks.value += 1
        }
    }
    AndroidView(
        modifier = modifier.fillMaxSize(),
        factory = { context ->
            StarAnimationView(context).apply {
                val params = FrameLayout.LayoutParams(
                    FrameLayout.LayoutParams.WRAP_CONTENT,
                    FrameLayout.LayoutParams.WRAP_CONTENT
                )
                params.gravity = Gravity.CENTER
                layoutParams = params
            }
        },
        update = { view ->if (ticks.value>0) {
                view.startStarAnimation()
            }
        }
    )
}

内容としては、0.25秒ごとにFrameLayoutに対して、AnimationするStarのImageViewを追加するというものでした。(Viewがインフレートされた後にAnimationを開始)

AnimationするImageViewの内容とライフサイクルは以下です。

  • Animation時間は2.5秒
  • 画面の中心から上下ランダムにTranslationX & Yの値を変化させていく。
  • Scale & Alpha値を徐々に大きくしていく。
  • Animation終了時に親のViewからRemoveする。

以下にStarAnimationViewはクラスを作成しました。

class StarAnimationView : FrameLayout {

    constructor(context: Context) : super(context) {
        init(context, null, 0)
    }
    // Animation ViewをFrameLayoutにaddしanimationを開始、終了したら、removeするfun startStarAnimation() {
      val star = addStarView(context, this)
      val winAnim = starAnim(context, star)
      winAnim.doOnEnd { this.removeView(star) }
      winAnim.start()
    }

改善点

  • Lottie Animationで実装すれば、ロジック的にはもう少し簡素化できた。
  • メモリーやCPU使用率には大きな問題は無かったが、AndroidViewが高頻度でrecomposesされ 内部でもViewがインフレートされるため、フルComposeにすればパフォーマンスの向上が期待できそう。

実際に導入してよかったこと

  • 開発体験が向上した。
  • UIのUnitTestができるようになった。
  • Previewのインタラクティブモードが使いやすい。
  • LazyColumnやLazyRowによりRecyclerViewの時よりもコードが簡潔になった。

今後の課題

  • Composable設計ルールの制定
    Atomicデザインに則りパーツ単位でUIデザインを設計していく。
  • 脱MVP
    新規の機能や影響範囲からCompose化していく予定のため、徐々に脱MVP化してViewModel+UDFのような形にしていきます。
  • 脱Rx
    現状のRest APIとの通信結果はRxのSingleなどでデータフローを作っているが、ComposeはCoroutine Flowなどと相性が良いため、置き換えていきたい。
  • VRT(Visual Regression Testing)の導入を検討
    頻繁にUIが変わる画面など、プロダクトの方向性により導入を検討していく。

いかがだったでしょうか。 まだまだ、弊社では他プロダクトでもJetpackComposeの導入を実行中です。 新たな知見など出てきたら、また発信していきます!


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


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

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

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

■開発環境はこちら

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

メドピアはRubyKaigi 2023にPlatinum Sponsorとして協賛します!

$
0
0

皆さんこんにちは!サーバーサイドエンジニアの千葉です。

今回、メドピアは2023/5/11から2023/5/13に開催されるRubyKaigi 2023にPlatinum Sponsorとして協賛することになりました!スポンサー協賛としては今回で6回目になります。また、弊社は昨年よりも大所帯の30名超で参加する予定です。

この記事を書いている現時点でも、交通やホテル、出展ブース企画等の準備が着々と進行しており、修学旅行(※ あくまで業務です)のようなワクワク感があり、今から楽しみです。

RubyKaigi 2023概要

rubykaigi.org

昨年のRubyKaigiの様子

この機会に、メドピアの昨年のRubyKaigiを振り返っていきます。

RubyKaigi 2022

昨年のRubyKaigiは2022/9/8から2022/9/10に三重で開催されました。

たくさんの方が出展ブースに訪れてくださり、Rubyistの健康チェックを行うことができました。(Rubyistの皆さん、運動しましょう!笑)

たくさんの方がブースに来てくださいました!

tech.medpeer.co.jp

tech.medpeer.co.jp

RubyKaigi 2022感想戦

メドピアでは、技術アドバイザーであるMatzことまつもとゆきひろさんによる解説・コメントをいただく会を開催しました。

Matz自身からRubyKaigiの振り返りを聞くことができる環境に感謝です。

Matzを交えた感想戦の様子

tech.medpeer.co.jp

After RubyKaigi 2022

RubyKaigi 2022スポンサー企業の株式会社ZOZO、メドピア株式会社、ファインディ株式会社3社合同で行うAfter RubyKaigiイベントに参加しました。

このイベントでは、RubyKaigiで発表された内容を活用した事例や、スポンサーとして参加した感想をディスカッションし、RubyKaigi後の貴重な交流の場となりました。

弊社からはVPoEの平川とリードエンジニアの草分が登壇

engineer.medpeer.co.jp

最後に

開催まではまだ時間がありますが、今から楽しみですね。

皆さんが楽しめるような企画を用意しておきますので、当日オフライン参加する方はメドピア出展ブースでお待ちしております。

みんなでRubyKaigi 2023を盛り上げていきましょう!


メドピアでは一緒に働く仲間を募集しています。

ご応募をお待ちしております!

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

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

■開発環境はこちら

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

Viewing all 211 articles
Browse latest View live