この度、株式会社スタメンは、2024年12月05日(木)〜06日(金)の2日間、オンライン & オンサイトで開催される「プロダクトマネージャーカンファレンス 2024(pmconf 2024)」に、Silverスポンサーとして協賛します! カンファレンス情報 名称 :プロダクトマネージャーカンファレンス 2024(pmconf 2024) 開催日時:2024年12月05日(木)〜12月06日(金) 場所 :DAY1(オンライン)、DAY2(オンサイト:東京都大田区羽田空港2丁目7−1羽田エアポートガーデン) 参加方法や詳細については、下記公式サイトをご覧ください。 2024.pmconf.jp 当社スタメンは、企業や組織の業務DX、エンゲージメント向上を支援するクラウド型プラットフォーム「 TUNAG(ツナグ) 」を開発・提供しています。 2017年のサービス提供開始当初から、TUNAGは当社の成長を牽引してきたプロダクトです。 今回初めて、プロダクトマネージャーカンファレンスのスポンサーをさせていただきます。 当日のブース出展はありませんが、弊社からはPMの2名が現地参加します! オンサイト参加の方は、ぜひ現地で交流しましょう! おわりに プロダクトマネージャーカンファレンス 2024の2日間を通して、プロダクトマネジメントに対する学びを深め、よりよりプロダクトづくりに活かしていきたいと思っております。DAY2では、現地参加の皆様とお会いできることを心待ちにしております! 宣伝:直近の事業やプロダクト組織の取り組みもぜひご覧ください! 10→100フェーズを最前線で - デスクレスSaaS TUNAG(ツナグ)のProduct Managerをやる面白さ note.com スタメン技術ロードマップ 2025-2026 note.com 採用情報 スタメンでは、プロダクトマネージャーに限らず、全ての領域でプロダクト職種の採用をしています。 もし興味を持っていただけたら、下記からご応募ください! https://herp.careers/v1/stmn/requisition-groups/8d5d0858-2bda-4167-80f2-2401d8fb1891 herp.careers 参考:エンジニアのカジュアル面談Q&Aから見るスタメンの姿 note.com
はじめまして。TUNAGプロダクト開発部の勝間田です。2024年9月より株式会社スタメンにジョインしました。 2024/10/25 ~ 26で開催された Kaigi on Rails 2024 に当社からは、7名のメンバー(1人写真に入れず。。)で現地参加させていただきました。 Kaigi on Railsは「初学者から上級者までが楽しめるWeb系の技術カンファレンス」をコアコンセプトにしています。 普段Railsを使う中で感じた課題・困難とその解決策がセッションになることが多く、日々の開発に役立つような学びの多いカンファレンスです。 会場の様子 セッション会場は「Hall Red」と「Hall Blue」に分かれており、それぞれが視聴したいセッションを自由に選べる形式でした。 「Sponsor Booth Area」にはさまざまなブースが出展されており、楽しいコンテンツが豊富に用意されていました。 体験を通じて「このプロダクトをこの人数で運営しているのか」「意外とシンプルな構成だな」といった発見や驚きもありました。 また、「わいわい部屋」と「もくもく部屋」が用意されており、一息つきたい時や急な業務対応ができる環境もありました。 フロアマップ スタメンは Silver Sponsor として協賛させていただきました。 スポンサーボード 気になったセッション 約9000個の自動テストの時間を50分から10分に短縮、偽陽性率(Flakyテスト)を1%以下に抑えるまでの道のり speakerdeck.com テスト時間を短縮するためのさまざまな手法が、導入難易度も含めて丁寧に解説されており、とてもありがたい内容でした! 私自身もこの課題に向き合い、紹介された手法をいくつか試した経験があるため、勝手に親近感が湧いてしまいました(笑)。 Flakyテストも確実に減らされており、最終的にテスト時間やCI費用が大幅に改善されていました。 同じような課題に直面した際は、この内容を思い出してみようと思います。 推し活のハイトラフィックに立ち向かうRailsとアーキテクチャ speakerdeck.com ハイトラフィックなイベント物販サービスにおける在庫の確保と決済の対処方法についての内容でした。 具体的には、従来は「商品ID」と「在庫数」を1つのレコードで管理しており、ハイトラフィックな環境では行ロックによるデッドロックが頻発する問題がありました。 これを「1在庫1行」のデータ構造に変更することで、デッドロックを回避する手法が紹介されていました。 当時の状況や実際に起きた問題を、アイデアで解決していくお話が痛快で、とても楽しかったです! Data Migration on Rails speakerdeck.com Railsアプリでのデータマイグレーションについて、代表的な手法とそれぞれのメリット・デメリットをが紹介されていました。 これまで、手法についてあまり深く考えたことはなく、その時々のプロジェクトや状況に応じて選択していたことに気づかされました。 もしチームとして明確な方針が固まっていないのであれば、今回の内容を参考に話してみるのも良さそうです。 また、セッションで紹介されていた maintenance_tasks gemは権限管理や管理画面を提供しているみたいで気になるので今度実際に触ってみようかと思います! アーカイブ動画が公開されたら現地で視聴できなかったセッションも見てみようと思います! 同じくオフライン参戦したエンジニアの感想 まっきー : Kaigi on Railsは初参加だったのですが、実践的な内容のセッションが多くあり、持ち帰れる物の多い充実した2日間でした。 特に印象に残ったセッションは Identifying User Identity です。Railsアプリケーションをそれなりの期間運用しているとどうしてもユーザーモデル周辺が肥大化しがちなのですが、これに対するアプローチとして新たな視点を得ることができました。 また各企業のブースが面白く、お弁当も美味しかったりと、コミュニティとしての素晴らしさを体験することができました。機会があれば運営として参加もしてみたいと思えました。 speakerdeck.com 最後に 今回、個人として初めてオフラインのカンファレンスに参加しました。 福利厚生の一環として、参加費を負担していただき、業務としてこのような機会をいただけたことに感謝しています! Railsエンジニアの方々との交流や会場で感じた雰囲気は、オフラインでしか得られないもので、より一層研鑽への意欲が高まりました。 またカンファレンス開催にあたりご尽力いただいた運営スタッフの皆様に心より感謝申し上げます! 採用情報 スタメンでは、Ruby on Railsエンジニアに限らず全技術領域で、プロダクトを成長させていくエンジニア、デザイナー、プロダクトマネージャーの方を募集しています。 herp.careers
みなさんこんにちは、プロダクト開発部でAndroidアプリを開発している カーキ です。 先週の10月25日に開催された mobile.stmn にて「Composeで敷き詰めるUIをどうやって作るか」というタイトルで発表をしました。登壇した資料自体はSpeakerDeckにも公開をしていますが、せっかくならと思いテックブログでも公開してみることにしました。 導入 タイトルに「敷き詰めるUI」と書いていますが、これは以下の画像のように水平・鉛直方向へ要素が敷き詰められるようなレイアウトを指しています。 敷き詰めるレイアウトの例 このようなレイアウトをJetpack Composeで実現する方法として、2つのレイアウト方法が提供されています。 Lazy〇〇Grid Flow〇〇 Lazy〇〇Gridとは、LazyVerticalGridやLazyHorizontalGridなどに代表されるレイアウトコンポーネントです。またFlow〇〇とは、FlowRowやFlowColumnなどに代表されるレイアウトコンポーネントです。それぞれのレイアウトコンポーネントに関して、以下で基本的な性質から紹介していきます。 Lazy〇〇Gridについて 基本性質 名前の通り Lazy〇〇Grid は格子状のレイアウトを遅延表示することができるレイアウトコンポーネントになります。LazyColumnやLazyRowと同じようにcontentブロック内では、 item や items などのメソッドが利用できます。 主にLazyVerticalGridとLazyHorizontalGridという2つのコンポーネントに分けられ、それぞれ以下のように要素が敷き詰められます。 Lazy〇〇Gridの並び方 LazyVerticalGridは垂直方向へ敷き詰めが行われ鉛直方向にスクロール可能になり、LazyHorizontalGridは鉛直方向へ敷き詰めが行われて垂直方向へのスクロールが行われるため、注意が必要です。 LazyStaggeredGridについて LazyVerticalGrid, LazyHorizontalGridでは、格子状のレイアウトになるため、要素の大きさは均一になります。ただこれらのレイアウトと近縁関係にある LazyStaggeredGrid を利用することで高さもしくは、横幅の大きさを可変なものとしてレイアウト可能になります。 公式ドキュメントより LazyStaggeredGrid の実装例 LazyStaggeredGrid は執筆時点(2024/11/01)で Experimental なレイアウトとなっています。 GridCells LazyHorizontalGridでの格子の敷き詰め方は colums というパラメータによって決まります。(LazyHorizontalGridの場合は rows というパラメータ) columns は GridCells を継承したクラスを要求しており、 compose.foundation では以下の3つのクラスが用意されています。 GridCells.Fixed GridCells.Adaptive GridCells.FixedSize 1. GridCells.Fixed Fixedでは、一列の中に配置する要素の個数を指定することができます。 GridCells.Fixedで指定した場合 指定された個数に従って要素の大きさが決まります。 2. GridCells.Adaptive Adaptiveでは、一列中の要素の幅の最小値を指定することができます。(LazyHorizontalGridの場合は高さの指定になります) GridCells.Adaptiveで指定した場合 指定された幅の最小値に従って表示することの可能な個数分配置されます。指定しているのはあくまで最小値になるため、親のレイアウトの幅が88.dpで、Adaptive(20.dp)と指定した場合は、一列中に4つの要素が配置され、その幅は22.dpとなります 3.GridCells.FixedSize FixedSizeでも、一列中の要素の幅(もしくは高さ)を指定することで配置を指定します。ただAdaptiveと異なっているのは、列中で余った領域に関してはArrangement.Horizontal の指定に従うようになっています。例えば以下の画像では、Arrangement.Horizontalの指定を Arrangement.spaceBy(8.dp) としているため、要素間の間隔を8.dpにするために余剰分に関しては、画面右に寄せられています。 GridCells.FixedSizeで指定した場合 ヘッダーの表示 LazyGridのitemとして、ヘッダー要素を表示させることができます。ただ普通にitemのブロックに要素を入れただけでは、下画像のようにグリッドの要素として組み込まれてしまいます。 item のブロックに単純にヘッダー要素を入れた場合 以下のように span を実装する必要があります。 @Composable fun LazyGridHeaderSample() { LazyVerticalGrid( columns = GridCells.Fixed( 3 ) ) { item( span = { GridItemSpan(maxCurrentLineSpan) } ) { Text(text = "Header" ) } items( 10 ) { index -> ... } } } span に maxCurrentLineSpan で指定すれば、空いているGridのスペース分の領域をコンテンツブロック内で確保することができます。上記のコードで並べた結果が以下のようになります。 GridItemSpanを利用してitem のブロックに単純にヘッダー要素を入れた場合 GridItemSpanを利用することでLazyVerticalGridを利用してヘッダーを表示することができます。 Flowレイアウト 基本性質 Flowレイアウトは 公式のドキュメント では、「ColumnやRowのコンテナのスペースが不足した時に、要素が次の行に流れ込む性質を持ったコンポーネント」と説明されています。次の行に流れ込む性質を持ったColumnやRowと説明されている通り、レイアウト方向に応じてFlowColumnやFlowRowなどが存在します。Flowレイアウトは執筆時点(2024/11/01)で、ExperimentalLayoutApi とされており、試験運用版という扱いになっています。 Flowを使うことで以下のようなタグの表示を実現することができます。 公式ドキュメントよりFlowレイアウトの例 Flowレイアウトでは、上記のタグのように要素を並べていく方向の幅を可変にすることができます。LazyVerticalGridでは基本的に並べる方向の幅は全て均一になります。格子状に並べる上ではLazyGridが適していますが、サイズの異なる要素を順に並べていくのはFlowレイアウトが適しています。 Arrangement Flowレイアウトの敷き詰め方は、 HorizontalArrangement と verticalArrangement という引数に何を渡すかによって決まります。これらのパラメータへの指定によって右寄せ・左寄せ・等間隔など様々な配置方法を指定することができます。 この辺りは 公式のドキュメント が詳しいので説明はそちらに譲ります。 2つの使い分け ここまでLazyGridとFlowレイアウトの性質について紹介してきました。ざっくりそれぞれのレイアウトコンポーネントの特徴をまとめると以下のようになります。 LazyGridは、格子状に要素を敷き詰めるのに適したレイアウトコンポーネント Flowレイアウトは、折り返しを考慮してものを敷き詰めたい時に適したコンポーネント この2つの比べると格子状の場合はLazyGridで、それ以外の場合はFlowを選択するのが良いように感じます。ただLazyVerticalGridはLazyなレイアウトになるので、同一方向のLazyのレイアウトを親や子に持てないなどといった、それぞれ採用判断に影響する差異が存在するので紹介します。 LazyGridが向いているケース スクロール方向と交差する方向のサイズが固定である 表示量が多いなど、遅延して表示したい要件がある Experimental な機能を利用できない Flowレイアウトが向いているケース 要素の大きさがものによって変わる 遅延して表示させる要件がない グリッドの部分のみ背景を変えたい要件がある 「Flowレイアウトが向いているケース」の最後の項目だけより具体的な事例を出していますが、TUNAGの開発中にこのパターンに当たり、Flowレイアウトを採用したという背景があります。 具体的には以下のような画面になります。(該当の画面を抽象化して示しています) 特殊な実装例 こちらの画面では均等に要素を並べるようなUIを想定していたため、LazyVerticalGridの採用を検討していましたが、グリッドの部分のみ背景色を変更することがLazyGridではできません。この画面はスクロールも要求していたので、LazyVerticalGridで実装する場合画面全体をLazyVerticalGridでレイアウトする必要がありました。ただ特定のitemsのブロックの中でのみパディングや背景色の変更を行うことが難しかったため、FlowRowを採用しました。 何か複雑に組み合わせることで、LazyVerticalGridの利用も可能だったかもしれませんが、今後のメンテナンス性も考えると、シンプルな利用で表現することができるFlowRowに寄せることとしました。 LazyGridとFlowレイアウトでは、それぞれ向いているレイアウト方法がありますが、どちらのレイアウト方法でも実現することができるのもまた事実です。基本的にはそれぞれのレイアウトコンポーネントの基本性質にあった方法を取れるのが良いですが、それでも実現することが難しい場合・実装があまりにも複雑になりすぎてしまう場合があります。それぞれのメリット・デメリットのトレードオフを考えて実装されるのが良いかと思います。 まとめ 今回のブログでは、LazyGridとFlowレイアウトの紹介と比較を行いました。 どちらでもできること・どちらかにしかできない表現があるため、それぞれの性質を理解した上で、どちらを利用するのかを要件に沿って選ぶのが良いと思います。 株式会社スタメンでは、チームで議論を深めながらJetpack Composeの利用の幅を広げています。Jetpack Composeが大好きなAndroidエンジニアの方はぜひ一度カジュアル面談からお話を聞いてみてはいかがでしょうか。 herp.careers herp.careers
こんにちは。 この度、株式会社スタメンは、2024年10月25日〜26日の2日間、有明セントラルタワーホール & カンファレンスにて開催される「Kaigi on Rails 2024」に、Silverスポンサーとして協賛します! カンファレンス情報 名称 : Kaigi on Rails 2024 開催日時 : 2024年10月25日(金)〜10月26日(土) 場所 : 有明セントラルタワーホール & カンファレンス + オンライン 参加方法や詳細については、下記公式サイトをご覧ください。 kaigionrails.org 当社スタメンは、企業や組織の業務DX、エンゲージメント向上を支援するクラウド型プラットフォーム「 TUNAG(ツナグ) 」を開発・提供しています。 TUNAGの開発では 2017年のサービス提供開始当初から Ruby on Rails を採択してきました。 リリース当初から、開発を推し進めることができているのは、Rails関連の技術コミュニティの支えがあってこそであり、 昨年 に引き続き 今年も協賛させていただく運びとなりました。 当日のブース出展はありませんが、弊社からはエンジニア、HR含め7名が現地参加します! オフライン参加の方は、ぜひ現地で交流しましょう! おわりに Kaigi on Rails の2日間を通して、Railsエンジニアの皆様だけでなく、様々な技術領域のWebエンジニアの皆様とお会いできることを心待ちにしております! 宣伝:直近の事業やプロダクト組織の取り組みもぜひご覧ください! PIVOT:【日本の労働人口の約半分】飲食・小売・物流…ノンデスクワーカー業界を変える/低い労働生産性 解決のカギは組織エンゲージメントの向上/組織づくりを支援する「TUNAG」とは www.youtube.com スタメン技術ロードマップ 2025-2026 note.com 10→100フェーズを最前線で - デスクレスSaaS TUNAG(ツナグ)のProduct Managerをやる面白さ note.com 採用情報 スタメンでは、Railsエンジニアに限らず、全ての領域でエンジニアを募集しています。 もし興味を持っていただけたら、下記からご応募ください! https://herp.careers/v1/stmn/requisition-groups/8d5d0858-2bda-4167-80f2-2401d8fb1891 herp.careers 参考:エンジニアのカジュアル面談Q&Aから見るスタメンの姿 note.com
TUNAG プロダクト開発部 第2グループの カーキ です。 先週9月11日から13日にわたって開催されたDroidKaigi2024にプロダクト開発部のメンバー4人で参加しました。 参加メンバーでパシャリ📸 今年はサポータースポンサーとしてスタメンもイベントにスポンサードしています。 DroidKaigiスポンサー紹介のスライド DroidKaigi振り返り Workshop Day 初日は JetBrains の方を講師に招いて、Kotlin Multiplatform(以下:KMP)を使ったAndroidアプリ・Webアプリ・デスクトップアプリをビルドするワークショップが開催されました。JetBrains の方に直接質問もできる貴重な機会でした。 ワークショップの様子 ワークショップでは Fleet という JetBrains が KMP のために開発した IDE を利用して行われました。Fleet という IDE は知っていたものの、思った以上にサクサクと開発できて感動しました。ビルド時間が長いなどの問題はありましたが、プレビュー版ゆえのものだと思っておきます🤫 またワークショップでは Compose Multiplatform(以下:CMP) のワークもありました。Android 開発での UI 作成のフレームワークがWebやデスクトップアプリでも全く同じ体験として実現できるのには驚きました。 今回ワークショップに参加をしてみて、KMPとCMP 思ったよりもいけるぞ!と感じました。CMP は一部アルファ版のものもありビルドターゲットによっては、まだ不安はありますが、CMPを使った開発の快適さを感じました。 のぼりの前で📸 2,3 日目のセッション 2日目以降では各ルームでセッションが開催されました。 今年もセッションルームには代々の Android Studio のバージョン名になった動物たちの名前がついていました(カワイイ-) 各ルームのキャラクター 2日間で本当にたくさんのセッションがあり、何を聞きに行くのかも毎回迷ってしまいました。気にはなっていたが渋々見ることができなかったセッションもあるので、それらは公式があげているYouTubeの動画をこれから見ていこうと思っています。 スタメンメンバーが見たセッションの中から印象に残ったセッションをいくつか紹介します。 Androidエンジニア カーキ(自分) 仕組みから理解する!Composeプレビューを様々なバリエーションでスクリーンショットテストしよう 自分が印象に残ったセッションは『 仕組みから理解する!Composeプレビューを様々なバリエーションでスクリーンショットテストしよう 』です。Compose によって作成されたビューはテストがしやすいということは知っていたものの、現状のプロダクトコードには Compose のテストは存在していなかったので、プレビューを利用してどのようなテストが行えるのかが気になっていました。様々なテストツールを利用することで複数プレビューのパターンに対応することができることが段階的に説明されており、中長期的な目線でスクリーンショットテストを導入するかどうかを検討する上での材料になりました。 Androidエンジニア ケンタ PDF Viewer作成の今までとこれから AndroidにおけるPDFビュワーの歴史から細かな実装まで、とても詳細に解説されていて良いセッションでした。 Androidエンジニア ヒビキ たすけて!ViewModel ViewModelの役割や説明を踏まえてよくある誤りから責務の分離がとてもわかりやすかったです。ComposeとViewModelの強い関係性からもこのセッションを聴いて再認識できてよかったです。 CTO 野口 昨年に続き、DroidKaigi 2024に参加し、Android開発のトレンドを肌で感じることができました。特に、Jetpack Composeが十分にデファクトスタンダードになってきている点や、Kotlin Multiplatformの他社導入状況について議論することができました。ビジネス的には競合であったりする会社に属しているエンジニアと会話し、新たなコミュニティに繋がることができたのも技術コミュニティあってのことだと認識しています。スタメンでは今後もより高品質なAndroidアプリ開発を目指していきます。 さいごに 初日のワークショップや、2日目からのセッションはもちろんですが、DroidKaigiには美味しいコーヒーの提供やネイル体験、プリクラなど、参加者が楽しめる仕組みが沢山ありました。 自分は今回のDroidKaigiがオフラインでは2度目の参加になりますが、本当に3日間ずっと充実していました。 セッションで得た情報をそのままにせず、チームで共有をして日々の開発に活かしていくために、チーム内で共有会を開催しようと思っています。 採用情報 株式会社スタメンではAndroid領域に限らず、様々な領域でエンジニアを募集しています。 herp.careers
こんにちは! 株式会社スタメンは、2024年9月11日〜13日の3日間、ベルサール渋谷ガーデンにて開催される「DroidKaigi 2024」に、サポータースポンサーとして協賛します! スタメンは、企業や組織の業務DX、エンゲージメント向上を支援するクラウド型プラットフォーム「 TUNAG(ツナグ) 」の、Android向けアプリケーションを開発・提供しています。 より多くのユーザーが快適にTUNAGをご利用いただくため、当社エンジニア組織ではモバイル先行の開発体制や開発プロセスにシフトしています。 モバイル先行の開発を推し進めることができているのは、Android関連技術コミュニティの支えがあってこそであり、昨年に引き続き今年も協賛させていただく運びとなりました。 参考:これまでのスポンサーやAndroid関連のテックコミュニティでの取り組み DroidKaigi 2023にスポンサーとして参加しました! スタメンが主催で開催しているモバイル開発の勉強会「mobile.stmn」が1周年を迎えました DroidKaigi.collect { @Nagoya } ※会場提供のみ 本カンファレンスへの協賛を通して、これからのAndoridアプリ開発者コミュニティの発展を後押ししていきます! イベントを一緒に盛り上げていきます! カンファレンス概要 開催:2024年9月11日(水)~ 9月13日(金) 場所:東京都渋谷区南平台町16-17 住友不動産渋谷ガーデンタワー 1F・B1 主催:一般社団法人DroidKaigi 詳しくは公式サイトをご覧ください。 2024.droidkaigi.jp 当日のブース出展はありませんが、弊社からはエンジニア4名が現地参加します! オフライン参加の方は、ぜひ現地で交流しましょう! 採用情報 スタメンでは、Andoridエンジニアに限らず、全ての領域でエンジニアを募集しています。もし興味を持っていただけたら、下記からご応募ください! https://herp.careers/v1/stmn/requisition-groups/8d5d0858-2bda-4167-80f2-2401d8fb1891 herp.careers
こんにちは!TUNAG iOSアプリ開発担当のおしん ( @38Punkd )です。 スタメンは今年はシルバースポンサー枠での協賛なのでブース出展はありませんが、 モバイルチームの朝倉( @asashin227 )、プロダクトHRと私の3名で会場に現地参加してきました。 昨年の参加報告はこちら 👇 tech.stmn.co.jp 今回はブースをまわるだけでなく、セッションを聴く時間も多く確保できたので、色々なセッションを聴いて周りました。 その中でも私個人として印象に残ったセッションをピックアップしました。 Day 0 - 前夜祭 8/22 App Clipの魔法: iOSデザイン開発の新時代 by log5 App Clipを使った、アプリデザインの共有方法の紹介がありました。 App Clipとは、iOS 14から搭載された機能で、特定のタスク等を素早く行うためのミニアプリのことです。 完全版のアプリをインストールせずに使用できるので、レストランでの注文などに使われることが多い印象です。 developer.apple.com 本セッションでは、この手軽さを利用してプロトタイピングツールとしての利用を紹介されていました。 新規に実装したUIコンポーネントをApp Clipで表示することで、デザイナーは、実際にiPhone端末上で、そのUIコンポーネントに集中して、触ることができます。 画面より小さい単位のUIに対して特にフィードバックを得やすく、とても斬新なアイデアだと感じました。 fortee.jp Day 1 - 8/23 iOS/iPadOSの多様な「ViewController」の徹底解説と実装例 by haseken iOSのViewを実装する際には必ずどこかしらでお世話になる UIViewController にまつわるお話でした。 UIKitだけでなくMapKit等の他のiOS向けUIフレームワークも合わせると、なんと80種類以上のViewControllerのサブクラスが存在していて驚きました。 私はiOS開発を始めてまだ2年半でまだまだiOS開発の歴史に疎かったので、とても勉強になりました。 fortee.jp Day 2 - 8/24 Swift 6のTyped throwsとSwiftにおけるエラーハンドリングの全体像を学ぶ by koher スタメンもSwift 6への移行準備を進めていますが、Strict Concurrencyへの対応だけでなく、Swift 6から使えるようになる新しい言語機能も、積極的に取り入れていこうと考えています。 その上で、Error型に準拠した型のエラーを投げる「Typed throws」は、どのタイミングで使用すべきか気になっていました。 koherさんのセッションでその疑問が解消されただけでなく、エラーハンドリングの基本的な考え方を学ぶことができました。 早速、今後のモバイルアプリ開発に活かせられそうです! fortee.jp 最後に 今年のiOSDCはSwift 6やクロスプラットフォームの話題が例年より多く感じ、iOS開発の時代の流れを感じました。 LT大会はユニークな発表ばかりで、終始目を丸くして見ていました。 懇親会では、昨年のiOSDCでお会いした方と今年もお会いしてお互いの近況をお話することができ、楽しく過ごすことができました。 昨年とは違った形で参加した今年も、暑い夏に負けないパワーを会場から頂きました!! 運営の皆さま、本当にお疲れ様でした! (LT用のサイリウムを配られ、待てずに点灯させちゃう筆者) 参加メンバーの感想 朝倉( @asashin227 ) 今年もiOSDCに参加できて非常に嬉しく思います。 今年はSwift 6対応やクロスプラットフォームの発表が目につき、直近の弊社の開発状況と似た課題を抱えた方が多い印象を受けました。 普段の開発の割合が多くはないため、必死に食らいつきながら発表を聞いていました。 昨年はブース運営を行なっていましたが、今年はフルで参加できたため久々のお祭り感を存分に楽しむことができました。 また来年、お会いできることを楽しみにしています。 プロダクトHR 個人的には初iOSDC参戦、かつ今回はブース運営がなかったので、純粋に参加者の目線でも楽しむことができました。 私はエンジニアではないので、非エンジニアでも楽しめそうなセッションを選びながら参加していました! 技術的な知見がないとちょっと厳しいかなと思っていたのですが、4ラインのセッションのうち少なくとも1セッションは、技術的な知見の少ない私でも楽しめるものであり、普通に楽しめました。 スポンサー側の体験としても、運営の方が丁寧なコミュニケーションを取ってくださり、事前準備は決して多くありませんでしたが、スムーズに不安なく当日を迎えることができました。 改めてありがとうございました!来年もぜひ参加したいと思います。 採用情報 スタメンでは、iOSエンジニアに限らず、全ての領域でエンジニアを募集しています。もし興味を持っていただけたら、下記からご応募ください! https://herp.careers/v1/stmn/requisition-groups/8d5d0858-2bda-4167-80f2-2401d8fb1891 herp.careers
こんにちは! この度株式会社スタメンは、2024年08月22日-24日の3日間、早稲田大学理工学部西早稲田キャンパスにて開催される「iOSDC Japan 2024」に、シルバースポンサーとして協賛します! スタメンは、企業や組織の業務DX、エンゲージメント向上を支援するクラウド型プラットフォーム「 TUNAG(ツナグ) 」の、iOS向けアプリケーションを開発・提供しています。 より多くのユーザーが快適にTUNAGをご利用いただくため、当社エンジニア組織ではモバイル先行の開発体制や開発プロセスにシフトしています。 モバイル先行の開発を推し進めることができているのはiOS関連技術コミュニティの支えがあってこそであり、 昨年に引き続き 今年も協賛させていただく運びとなりました。 本カンファレンスへの協賛を通して、これからのiOSアプリ開発者コミュニティの発展を後押ししていきます! イベントを一緒に盛り上げていきます! カンファレンス概要 開催:2024年8月22日(木)~ 8月24日(土) 場所:早稲田大学理工学部西早稲田キャンパス+ニコニコ生放送 対象:iOS関連技術およびすべてのソフトウェア技術者 主催:主催: iOSDC Japan 2024 実行委員会 詳しくは公式サイトをご覧ください。 iosdc.jp 当日のブース出展はありませんが、弊社からはモバイルチームの朝倉( @asashin227 )、青木( @38Punkd )、プロダクトHRの3名が現地参加します! オフライン参加の方は、ぜひ現地で交流しましょう! ノベルティについて 創業以来、約8年続いたコーポレートロゴを刷新し、ロゴが新しくなりました。 今回はその新ロゴを印刷したクリアファイルをノベルティとして用意しました。 ぜひ普段のお仕事や、勉強等でご活用いただけると嬉しいです! コーポレートロゴリニューアルの詳細はこちら stmn.co.jp おわりに、チャレンジトークンはこちら! iOSDCの3日間を通して、iOSエンジニアの皆様だけでなく、様々な技術領域のエンジニアの皆様とお会いできることを心待ちにしております! 現地でお会いした際はぜひお話ししましょう! チャレンジトークンは、下記です! #iOSDC_stmn 宣伝:モバイル開発のオフライン勉強会「mobile.stmn」をほぼ各月で定期開催中!次回、9/6(金)の参加者&LT登壇者募集してます! 「mobile.stmn」は、スタメン モバイルアプリエンジニアが主催するモバイルアプリ開発に関する勉強会です。 モバイルネイティブアプリやクロスプラットフォーム開発など、モバイルデバイス向けの開発や周辺の技術を中心に扱っています。 本イベントはオフライン(会場参加)のLT会を開催しています! モバイルアプリエンジニアの方やその領域に興味がある方であれば、どなたでも参加いただけます。 交流会も予定していますので、日頃のアプリ開発のあれこれなどについてお話ししましょう! https://stmn.connpass.com/event/323509/ stmn.connpass.com 採用情報 スタメンでは、iOSエンジニアに限らず、全ての領域でエンジニアを募集しています。もし興味を持っていただけたら、下記からご応募ください! https://herp.careers/v1/stmn/requisition-groups/8d5d0858-2bda-4167-80f2-2401d8fb1891 herp.careers
はじめに 株式会社スタメン、プロダクト開発部モバイルアプリGでAndroidアプリを開発しているカーキ( @khaki_ngy )です。最近は、Google Gemini API ディベロッパーコンペに出すアプリを個人開発しており、賞品のデロリアンを狙っています🤩 スタメンでは名古屋のモバイルアプリ開発メンバーが主体となって mobile.stmn というモバイルアプリ開発のオフラインの勉強会を主催しています。mobile.stmnは隔月で開催しており、前回の開催でちょうど1年が経ちました。 イベントのバナー画像 今回のブログでは、mobile.stmn の1年間の振り返りと今後の展望について紹介をしていきます。 mobile.stmnとは この勉強会は、モバイルアプリ開発に携わる人・関心のある人を対象としたLT会です。社員1名と一般公募4名の計5人がLTを行い、モバイルアプリ開発に関する経験や知見を共有しています。LTのテーマはモバイルアプリ開発に関わることであれば自由です。過去にはモバイルアプリ開発の言語やフレームワーク、CI/CD、開発ツールに関することなど様々な発表がありました。 LT後は懇親会も設け、参加者同士が交流できる場を用意しています。お菓子やドリンクなどを用意し、和気藹々とした雰囲気で交流を楽しんでいます。 イベントの様子 イベントはスタメン名古屋本社のイベントスペースを利用して開催しています。 これまでのイベントについて 過去の登壇内容に関してはこちらのConnpassのイベントページをどうぞ mobile.stmn #1 mobile.stmn #2 mobile.stmn #3 mobile.stmn #4 mobile.stmn #5 mobile.stmn #6 スタメン名古屋本社のイベントスペースは無料で貸し出しも行っており、毎日何かしらのイベントが開催されています。 スタメンイベントスペースの様子 イベントスペースの利用に関心のある方は、こちらの資料もご覧ください。 株式会社スタメン イベントスペース貸し出しについて 開催の背景 mobile.stmnを開始しようとしたきっかけは 名古屋のモバイルアプリ開発を盛り上げたい と思ったからです。 まずmobile.stmnを開始した2023年には名古屋でモバイルアプリ開発に特化した勉強会がほとんど無い状態でした。またちょうどその時期はコロナによって勉強会が中止になっている勉強会も多々ある状況でした。 勉強会は社外の開発者のLTを聞いたり、交流する絶好の機会です。社外の開発者との技術交流などを通じて得た新たな知見を普段の開発に活かしたり、交流によって開発へのモチベーションも得ることができます。自分もオンライン・オフライン問わず様々な勉強会に参加して、学びを業務に活かすことはもちろん、交流という点でも楽しんでいます。 また勉強会をコミュニティとして考えると、地域に活発なコミュニティがあることも重要だと思っています。勉強会という場があることで、モチベーションが上がるだけでなく、同じ技術を学んでいる人が周りにいるんだ!ということも力になると思っています。自分個人の経験としても、学生の時に名古屋のモバイル開発の勉強会に参加をして、たくさんの勇気をもらったという経験が今のエンジニアとしてのキャリアに大きく寄与しています。 1年間開催してきた振り返り 1年間 mobile.stmn を運営してみて、いくつか気付きがあったので紹介していきます。 参加者を集めるのは大変 名古屋でモバイル開発の勉強会を始めて、一番最初に壁にぶつかったのは、参加者集めでした。 名古屋にもモバイル開発に携わるエンジニアの方はいらっしゃいますが、やはり東京や大阪といった大都市圏に比べると数は少なく、イベントの参加者集めには苦労しました。 イベントの初期段階では、他の勉強会に登壇し、自分の主催する勉強会を紹介したり、X(旧Twitter)などのSNSで積極的に情報発信したりするなど、イベントを知ってもらうための活動に力を入れていました。 これらの経験から、イベント告知の重要性を改めて実感しました。 チームでの勉強会の運営 mobile.stmnは自分個人ではなく所属しているモバイルアプリ開発チームの名古屋メンバー全員で運営をしています。 自分がやりたいです!と始めた勉強会ですが、一緒に主催しているチームのメンバー全員で取り組むことができたからこそ、ここまで継続して開催することができたと思っています。 勉強会1回をとっても当日の司会や受付、connpassページの作成、飲食物の購入など様々な準備が必要であり、1人の力で運営することは難しく、ましてや継続していくことは困難です。 きっかけ自体は自分だったものの、運営をチーム全員で取り組むことができたからこそ、ここまで継続できたと思っています。 定期的に登壇の機会を作ることができる このイベントでは、毎回社員がローテーションで登壇し、日頃の業務で得た知見や、新しい技術についての調査結果などを発表しています。発表したいテーマを持ち寄ることもあれば、チームでローテーションを組んで発表の機会を均等に与えることもあります。 この仕組みのおかげで、社員一人ひとりが定期的にプレゼンテーションの機会を得られるようになり、自然と『次は何を発表しようか』と、日々の業務や技術調査の際に発表ネタを探し始めるようになりました。 また、登壇経験が少ないメンバーにとっても、このイベントは貴重な機会となっています。主催イベントということもあり、外部のイベントに比べて参加のハードルが低く、リラックスした雰囲気の中で発表できるため、プレゼンテーションスキル向上のための良いトレーニングの場となっています。 継続は力なり mobile.stmnは、この7月に1周年を迎えました。1年という月日が経ち、リピーターの方も増え、少しずつコミュニティが形成されてきたことを実感しています。 定期的な勉強会を通して、参加者が継続的なつながりを確認する場としても機能していることに気付いてきました。 継続的に交流を行うことのできる場があると、2回目、3回目に参加した時に「前話してたあれどうなったんですか?」という会話など継続的なものとして交流を行うことができます。 技術的なスキルアップはもちろん、同じ目標を持つ仲間と交流することで、開発に対するモチベーションが向上し、日々の業務にも良い影響を与えていると感じています 今後に関して 今後も、隔月で開催しているLT形式のイベントを継続しつつ、新たな試みとしてワークショップ形式のイベントを企画検討中です。名古屋のモバイルアプリ開発コミュニティの拡大を目指し、モバイルアプリ開発に興味のある初心者の方々にも参加しやすい工夫を考えています。 mobile.stmnの次回の開催は、9月6日を予定しています。 次回イベント 下記のコンパスページで募集を開始していますので、参加をお待ちしています。 stmn.connpass.com
こんにちは。 株式会社スタメンです。 今回は RubyKaigi 2024 の参加レポート記事です。 昨年の RubyKaigi 2023 から引き続き、2024年5月15日~17日の3日間、那覇文化芸術劇場なはーとにて開催された、RubyKaigi 2024 にスポンサーとして協賛し、ブース出展をしました。 当社からは、6名のメンバーで現地参戦させていただきました! カンファレンス当日や、ブースの様子をご紹介できればと思います! 今回のスポンサーブースについて RubyKaigi 2024では、Platinumスポンサーとブース出展をさせていただきました。 これまでもテックカンファレンスでブース出展は何度か行なってきましたが、今回は、ノンデスクワーカーの方をメインターゲットとしたデスクレスSaaS『 TUNAG 』で、昨年10月にリリースした新機能『 TUNAG ベネフィット 』の機能の一部をブースコンテンツに用いました。 実際のプロダクトの一部機能を利用し、参加者のみなさまに景品の当たる抽選にトライいただきました。RubyKaigi 2024のために、オーダーしたクッピーラムネが想像以上に好評いただき嬉しかったです。 参加者の皆さまに楽しんでいただけたので、良かったです! Mazさんも遊びに来てくださいました!ありがとうございました!(VP of Engineering 松谷と写真撮影いただきました。) スタメンブースにMatzさん @yukihiro_matz が遊びに来てくれました! TUNAGの抽選機能にもチャレンジしていただきました!ありがとうございます! #rubykaigi pic.twitter.com/H4fssgfGaQ — stmn, inc. Developers (@stmn_eng) 2024年5月16日 RubyKaigi初参戦のエンジニアメンバー感想 スタメンでエンジニアをしている近藤( @sei_kondo97 )です。 今回、初めてRubyKaigiに参加しました。 どのセッションも非常に興味深く感じましたが、特に関心を持っていたのは、Ruby 3.0に導入されたRBSについてです。全てのセッションに参加できたわけではありませんが、2024年はRBSに関する以下のセッションがありました。 Let's use LLMs from Ruby 〜 Refine RBS types using LLM 〜 Community-driven RBS repository Embedding it into Ruby code Good first issues of TypeProf 弊社ではRBSの採用はしておりませんが、型検査によるバグ検出の恩恵は非常に魅力的です。 一方で、Rubyの型に関してはまだコミュニティの方向性が定まっていない部分もあり、現時点で積極的に導入するのは難しいとも感じています。またRubyKaigiを通して、「Rubyに型は必要ない」というネガティブな意見も一定数見受けられ、これも今後の型導入を検討する際の参考になりそうです。 最も面白かったセッションは、 Ruby Committers and the World でした。 例えば、Ruby 3.4からfrozen_string_literalがデフォルトで有効になる対応が開始されますが、この議論も非常に盛り上がっていました。 Immutable String literal in Ruby 3 のようなやり取りがリアルタイムで展開されるのは非常に新鮮な体験であり、私にとってRubyコミュニティをより身近に感じられる時間となりました。 3日間の大盛況だったブースをやり切った翌日はVP of Engineeringの松谷( @uuushiro )の運転のもと、アメリカンビレッジと首里城を観光しました。沖縄を堪能しつつ、社内の参加メンバーともじっくり会話することができ、有意義な時間を過ごしました。 現在は名古屋に戻り、また普段通りに日々の開発に勤しんでいます。今後ますますRubyを盛り上げていけるように、Rubyをメイン言語の1つとしている弊社の TUNAG の成長やOSSへの貢献に励んでいきたいと思います。 最後に 今回はスタメンからもRubyKaigiに初参戦のメンバーが複数いましたが、国籍問わず、 多くのRubyistの方々が来場されており、改めて世界中で長く愛されている言語なのだと肌で感じました。 また、Rubyコミュニティならではの熱量を強く感じることができ、とても良い3日間を過ごすことができました。 毎日、朝早くから、夜遅くまでRubyKaigiがずっと続いているような感覚になり、とても幸せな時間でした。 Rubyを主要言語にプロダクト開発をしている私達にとって、世界中のRuby愛のあるエンジニアの方とお話ができたのはとても貴重な機会でした。開催中、ブースや交流会等でお話しいただいた皆さんありがとうございました! 来年は、ブースのコンテンツや、より多くの国籍の方と一緒に楽しめるよう英語力も磨き上げ、さらに各国の方と交流できるように準備していきたいと思います。 それでは、来年2025年は、松山でぜひお会いしましょう!! 採用情報 スタメンでは、Rubyエンジニアに限らず全技術領域で、プロダクトを成長させていくエンジニア、デザイナー、プロダクトマネージャーの方を募集しています。 もし興味を持っていただけたら、下記からご応募ください! https://herp.careers/v1/stmn/requisition-groups/8d5d0858-2bda-4167-80f2-2401d8fb1891 herp.careers
こんにちは、スタメンで TUNAG の機能開発チームに所属している森( @hisayuki_mori )です。 今回、2023年の11月からスタートした新機能開発においてフロントエンド側の開発を担当しました。 この5ヶ月の間に新しくチャレンジしたことの紹介をします! チャレンジしたことまとめ 背景 詳細 Node.jsを18系から20系にアップデート Reactを17系から18系にアップデート Storybookの8.xをalpha版から導入 Biomeの導入 testing-liblraryの導入(v12)とアップデート(v15) やりきれなかったこと 最後に チャレンジしたことまとめ Node.jsを18系から20系にアップデート Reactを17系から18系にアップデート Storybookの8.xをalpha版から導入 Biomeの導入 testing-liblraryの導入(v12)とアップデート(v15) 振り返るといろいろなことにチャレンジできたなと思います。 それでは、これらを実現できた背景について話していきたいと思います。 背景 TUNAGにはユーザーが見る画面とは別に、管理者のみが見える画面が存在しています。 以前のブログ記事のリプレイスはTUNAGの中の ユーザー画面 と言われる箇所のリプレイスであり、 管理画面 は含まれていませんでした。 そのため、今回ユーザー画面側をリプレイスすることになった背景にある開発効率がよくない課題が管理画面にはそのまま残っていました。 背景についてはこちらの記事を参考にしてください。 tech.stmn.co.jp 今回の新規機能開発では、管理画面の実装ボリュームがそこそこ多かったため、現行のアーキテクチャでの実装を積み上げるのは避けたいと考えました。 せっかくユーザー画面をリプレイスしているので、アーキテクチャを見直すことで古い技術を捨てつつ、社内のスキルセットを合わせていきたいと思っています。 そこで、リプレイスは今はできないですが、今後の新規開発では可能な限りユーザー画面のリプレイス同様の実装に寄せ、切り離しプロジェクトが発足した際に備えたアーキテクチャでの実装を進めることにしました。 以前のブログ記事で、フロントエンドチームがフロントエンドのリプレイスを行っていることが紹介されています。 基本的な技術選定やアーキテクチャはフロントエンドリプレイスに追随しているため、こちらの記事を参照してください。 tech.stmn.co.jp 詳細 ここからは実際にチャレンジしたことの詳細を書いていきます。 Node.jsを18系から20系にアップデート 開発が始まった当初はNode.jsは18系のままでしたが、まずはユーザー画面リプレイスに合わせて 20.9.0 まで上げました。 管理画面はTUNAGのリポジトリに同居していますが、それぞれのディレクトリごとに独自の package.json を保持しています。 そのため、各ディレクトリごとにNode.jsのバージョンも指定できます。 大まかなディレクトリ構成は以下の通りです。 ├ .storybook ├ app │ ├ javascript │ ├ (~~~) │ ├ 新機能の管理画面 👈 今回の実装を配置する場所 │ ├ frontend │ ├ 管理画面 │ | ├ package.json 👈 現行管理画面のpackage.json │ ├ biome.json ├ esbuild.config.mjs ├ package.json 👈 package.jsonはrootに配置 今回の新機能の管理画面用の package.json は、現在の実装の関係でルートに配置する必要があるため、そのようになっています。 新しいディレクトリに実装を始めたため、今回の開発ではどのディレクトリにも属さず現行の制約に縛られることなくNode.jsのバージョンを上げることができました。 開発が落ち着いた現在では、バージョンを 20.12.2 にまで上げており、20.x系の最新版に対応しています。 Reactを17系から18系にアップデート ReactはNode.jsとは異なり、ビルド後のJavaScriptファイルがすべてグローバルにあるReactを参照してしまう課題がありました。 そのため、現在の管理画面では React や React DOM をCDNから呼び出すように変更しました。 これにより、 package.json 側のReactは自由にバージョンを変更できるようになりました。 この課題に関しては機能開発チームではなく別のチームに作業を依頼し、解決してもらいました! Storybookの8.xをalpha版から導入 Storybookを導入するタイミングで、既に 8.0.0-alpha.0 がリリースされていました。 v7の安定版を使用することも考えられましたが、UIコンポーネントを作成する段階であったことや、alpha版であっても最初からv8を導入してv8の仕様に合わせることで、よりスムーズに作業が進められると考えました。 開発が終了する頃には、v8が安定版になっている可能性も考慮しました。 ただし、8.0.0-alpha.6から次のバージョンにアップグレードする際に問題が発生し、一時期バージョンのアップグレードが停滞しました。 その際の原因は次の通りです。 github.com Stroybookのconfigにpluginとして明示的に @vitejs/plugin-react を記述する必要になってました。 import type { StorybookConfig } from '@storybook/react-vite' ; import { mergeConfig } from 'vite' ; import react from "@vitejs/plugin-react" ; import tsconfigPaths from 'vite-tsconfig-paths' ; const config: StorybookConfig = { /** ローカル環境でStorybookを起動するときに使用するViteの設定 */ async viteFinal ( config ) { return mergeConfig ( config , { /** ↓ここに`react()`が必要になった **/ plugins: [ react (), tsconfigPaths () ] , } ); } , docs: { autodocs: true , } , } ; export default config ; 解決後には 8.0.0-rc.2 までバージョンをアップグレードすることができ、その後は定期的に最新版にアップデート出来るようになりました。 現在はDependabotを使用して細かなアップデートを行っています。 StorybookのバージョンがあがるとAddOnのバージョンも上がるため、コマンドで一括で上げてます。 npx storybook@latest upgrade 開発が落ち着いた今では 8.0.9 まで上げてあります! Biome の導入 最初はESLintとPrettierを使っていたのですが、 ESLintとPrettierがともかく遅いからなんとかしたい!! というモチベーションで、すこしでも早くしようと思って導入しました。 LinterやFormatterは husky + lint-staged を使ってコミットのたびに発火するようにしています。 そのため、lintやformatが遅いとコミットのたびにその遅さに付き合わなければなりません。 CI/CDなど、頻繁に発生するプロセスの速度に関しては、このプロジェクトではかなり気にかけたところです。 最初はPrettierをやめてRust製の dprint に変えてみて、これだけでもPrettierより結構早くなったので結構満足してました。 その後にBiomeがメジャーバージョンが上がった事を知って、ESLintと置き換えるために検証したところ・・・ 13秒かかっていたLintが0.24秒になりました!! ESLintに戻ることが難しくなったためLinterはBiomeに移行し、dprintで設定できるフォーマットもBiomeが可能であるため、FormatterもdprintからBiomeに乗り換えました。 Biomeは開発が盛んなため、更新とルールの追加が頻繁に行われています。 なので バージョン上げたタイミングで新しいルールが追加されてLintで引っかかることはよくありました。 基本は全ルールをOnにしており、後から追加のルールや適用が難しいと思われるルールについてはoffにしてます。 ESLintのルールが充実してきたため、最近は少し落ち着いてきました! biomejs.dev importの並び替えや未使用importの自動削除など、機能も増えてきたのでオススメです! testing-liblraryの導入(v12)とアップデート(v15) 管理画面側には testing-liblrary がもともと入っていなかったため新しく導入することにしました。 v13以上はReact17非対応であったため最初はv12からしか入れられませんでしたが、Reactの課題を解決していただいたおかげでtesting-liblraryのバージョンも上げることができv14まで上げられました。 その後にv15へのメジャーアップデートが来たので、既に書いてあったテストを一通り流して特に問題がなかったのでそのままv15までアップデートしました。 まだ新規の範囲が小さいのでテストの量も少ないのもあって、そこまで苦戦することもなくアップデートできたのでよかったです。 やりきれなかったこと 完全な切り離しは今の管理画面の仕様では機能実装と並行で行うのは困難で、 Ruby on RailsにReactを乗せる形での開発 からは完全に抜けることはできなかったです。 そのためNext.jsも入れられませんでしたが、切り離しになった際にNext.jsにスムーズに移行できるような状態には出来たと思います。 また、切り離しのプロジェクトが検討してもらえるところまで持っていけたのは、新しいことの知見以外でチャレンジして得られた成果かなと思います! 最後に ここまで長々と書きましたが、最後まで読んでくださりありがとうございました。 今回やってみたいことを打診できたことや、自分のチームだけでなく垣根を超えて他チームに助けてもらったことが多々ありました。 その上でなりたったチャレンジだと思っているので、協力をしてくださった方々にはとても感謝してます! スタメンでは一緒に働いてくださるエンジニアを絶賛募集中です!! プロダクトに興味を持ってくださった方でも、技術に興味を持ってくださった方でも、ぜひ一度下のリンクを覗いてみてください! herp.careers
株式会社スタメンでiOSエンジニアをしている青木 ( @38Punkd )です。 スタメンは、2024年3月22日~24日の3日間、ベルサール渋谷ファーストにて開催される「 try! Swift Tokyo 2024 」に初めてスポンサーとして協賛し、ブース出展をしました。 今回はカンファレンスやブースの様子をご紹介できればと思います! try! Swift Tokyo 2024、2日目終了。最高のセッションをありがとうございました🥳明日はワークショップの開催です。try! Swift Tokyo 2024, Day 2 has ended. Thank you for the amazing sessions. Tomorrow we have workshops. #tryswift pic.twitter.com/lp9bUzu8gf — try! Swift Tokyo (@tryswiftconf) 2024年3月23日 try! Swift とは? try! Swift は、Swiftとその周辺技術に特化した、 世界規模のカンファレンス です。 毎年、日本を含む世界各地で開催され、世界中のSwiftに関わる開発者が集まり、最新の技術やベストプラクティスについて学び、交流する場となっています。 基調講演・技術セッション・ワークショップ・ハッカソン・スポンサーブースといった内容がベースになっています。 私の肌感ですが、英語話者が3~4割はいたのではと思う程、当日は多くの国籍の方が会場にいらっしゃいました。 ユニークなオープニングと共に始まる 『 SWIFT PUNK 』登場!! 昨年AppleがWWDCで空間コンピュータ Vision Pro を発表して以来、私は Vision Pro を生で見るのは初めてでした。 なのでその感動もありつつ、どこか見覚えのある見た目で現れた御三方を前に、会場は一挙に笑いに包まれました。 個人・企業スポンサー一覧発表の際には、スタメンのロゴをしっかり私のiPhoneに収めました。 スポンサーブース 展示されてあるSwift UIのコードから、プレビュー表示されるとどうなるかを実際にペンで書いて正解数を競うコンテンツや、抽選器を回して賞に応じて景品がいただけるなど、各社様皆、ブースを訪問した方が楽しめるコンテンツが盛りだくさんでした。 弊社社員も大はしゃぎでした。 (左)RevenueCatのぬいぐるみをゲットして喜ぶエンジニア (右)メルカリブースではしゃぐエンジニア スタメンもブース出展はこれまで何度か行なってきましたが、今回は、昨年10月に弊社アプリ 『TUNAG』 でリリースした新機能 『TUNAG ベネフィット』 をブースコンテンツに用いました。 この機能は、様々な企業様の商品をお得に購入できるクーポン券を弊社アプリ上で発行できる機能です。 この機能で抽選もできるようになっています。 ブースに遊びにくださった方には、弊社アプリを実際に触ってもらい、抽選も楽しんでいただきました。 技術セッション 1, 2日目がセッション、3日目がワークショップ形式でした。 TCA(The Composable Architecture) のメンテナーであるBrandonさん( @mbrandonw )、Stephenさん( @stephencelis )による、Swift 6.0から登場したマクロのテストの仕方や、 fastlane のリードメンテナーであるJoshさん( @joshdholtz )による、コード署名を楽しく理解する方法をはじめとする多くのセッションが開催されました。 iOS開発者ならおそらく誰もがご存知の方のセッションを生で聴けるのは、やはり会場でしか得られない経験の一つでした。 その中でも私個人として特に印象が大きかったセッションは、omochimetaruさん( @omochimetaru )の、『Swiftの型推論を学ぼう / Learning Swift's Type Inference』です。 speakerdeck.com 私は普段、iOSアプリ開発をしている中で、コードの可読性やコンパイル速度を向上させるために、型推論を適切に使うよう心がけていました。 しかし、その推論がどのような法則や仕組みによって実現されているのかはコンパイラレベルで調べた事がありませんでした。 そのため、omochimetaruさんの発表内容はどれも私にとって新しく、とても興味深かったです。 📣 try! Swift Tokyo 2024 Session Start 📣 "Swiftの型推論を学ぼう / Learning Swift's Type Inference" 🗣️ by @omochimetaru 👏 #tryswift pic.twitter.com/IfYC6vG9Mp — try! Swift Tokyo (@tryswiftconf) 2024年3月23日 最後に 国籍関係なく、他のエンジニアの方と英語でSwiftやiOS開発のお話ができたのは、またとない貴重な機会でした。 また初めて英語メインでブース対応をしたこともあり、慣れない部分も多かったですが、参加者の皆さんとてもお優しく、たくさん交流する事ができました。 世界の開発者の方々から知見と英気をいただいたので、これからもiOS開発を頑張っていこうと思います! 採用情報 スタメンでは、iOSエンジニアに限らず全技術領域で、プロダクトを成長させていくエキスパートを募集しています。 もし興味を持っていただけたら、下記からご応募ください! herp.careers
こんにちは、株式会社スタメンでiOSエンジニアをしている青木 ( @38Punkd )です。 弊社iOSアプリチームは、開発人数が増えるにつれて、 コンフリクト頻度が増える ことに悩まされていました。 またアプリの機能も増え、機能や画面間の依存関係が複雑になりつつあり、 開発生産性を下げる要因 になっていました。 今回この問題を解消するためにマルチモジュール化を行いましたので、その概要をご紹介できればと思います。 マルチモジュール化とは? アプリのコードを、複数の独立したモジュール(単位)に分割することを指し、アプリの開発や保守を楽にするための手法です。 マルチモジュール化を進めることで、大規模なアプリを複数の小さなモジュールに分割して、それぞれのモジュールで独立して開発・テスト・管理できます。 iOSの場合、後述する プロジェクトファイル の厄介な問題も解消できます。 プロジェクトファイルとは Appleの提供するOS上(iOS, macOS, watchOS, etc..)で動くアプリを開発する時に必要なメタデータが記述されたファイル( project.pbxproj )です。 ソースコードを統合開発環境Xcodeが自動生成したインデックスで紐づけて管理しています。 プロジェクトファイルのソースコード ファイルの追加・移動・削除時などに、このプロジェクトファイルに変更が加わります。 複数人で開発をしていると、ファイル操作を同じタイミングで行うことは良くあるかと思いますが、その際にプロジェクトファイルが、オートマージ不可能なコンフリクトを容易に起こしてしまいます。 自動生成されたメタデータのコンフリクト解消は、中々に辛いものがあります。 遂にマルチモジュール化に踏み切る iOSのマルチモジュール化では、アプリのソースコードを Embedded Framework ないしは Swift Package にしてモジュール化を行います。 今回私たちは、アプリのソースコードをほぼ全て、 Swift Package にしてモジュール化を行いました。 Swift Package は、Apple 標準のパッケージマネージャ Swift Package Manager と同じくして登場した、新しいパッケージの種類です。 Swift Package 内の個々のファイルに対しては、プロジェクトファイルによるインデックス管理下から外れるため、上述したプロジェクトファイルでのコンフリクト頻度が激減します。 私たちのチームでは昨年、パッケージマネージャを Carthage から Swift Package Manager に移行していました。 既にSwift Package Manager を導入済みの環境であれば、アプリのソースコードを Swift Package 化もしやすいと考えました。 マルチモジュール後の構成 レイヤー × 機能 で以下のようにモジュール分割をしました。 (実際にはユーティリティ等の小さめのモジュールもありますが、割愛しています) データベースや外部ライブラリに依存する実装と、アプリの機能を表現する実装は、関心事が違うので、 Data モジュールと Domains モジュールで分けました。 開発は基本的に機能単位で行うことが多いので、Domainsモジュールに存在する各機能は、疎結合でありたいです。 なので、 Module A , Module B , ... というように各機能をさらにモジュール化して分けました(サブモジュール化に相当します)。 よかったこと Swift Package によるマルチモジュール化を行ったことで、コンフリクト頻度が減ったことはもちろん、機能間の依存関係が単一方向になるよう矯正され、より 疎結合・高凝集なコード になりました。 また、既存のコードから関心の分離を行なっていく過程で、責務についての議論をチームで活発に行うことができ、ソースコードへの深い理解につながるという副次的な効果も得られました。 今後の展望 機能毎でモジュールを分けたことで、ビルド直後に、指定の機能にショートカットしてアクセスできる ミニアプリ を作れるようになります。 ビルドターゲットをこのミニアプリにすれば、機能が増えてもビルド速度を高速に保つことが可能です。 今後はミニアプリを各機能毎に作り、開発生産性をさらに高めていければと思います。 最後に try! Swift Tokyo 2024 に出展します! 弊社は、2024年3月22日~24日の3日間、ベルサール渋谷ファーストにて開催される 「 try! Swift Tokyo 2024 」 tryswift.jp に、ゴールドスポンサーとして協賛し、ブース出展を致します。 この3日間を通して、iOSエンジニアの皆様や、他の様々な技術分野の皆様とお会いできることを心よりお待ちしております!! 採用情報 スタメンでは、iOSエンジニアに限らず全技術領域で、プロダクトを成長させていくエキスパートを募集しています。 もし興味を持っていただけたら、下記からご応募ください! herp.careers
はじめに 初期設定 詳細設定 Slack連携とアラートの整備 CircleCIとの連携によるRelease Managementの活用 運用 今後について まとめ はじめに プラットフォーム部 SREチームのショウゴ( @shogo_452 )です。 最近、TUNAGの新たなエラー監視ツールとして「 Sentry 」を導入しました。 本記事では、Railsアプリケーションに対するSentryの導入事例について紹介します。 初期設定 まずは、 sentry-ruby と sentry-rails というGemをインストールします。 Sidekiqを使用している場合は、 sentry-sidekiq も必要です。 gem ' sentry-ruby ' gem ' sentry-rails ' gem ' sentry-sidekiq ' docs.sentry.io docs.sentry.io 次に設定ファイルです。 config/initializers/sentry.rb という設定ファイルを作成し、設定を行います。 この設定まで行えば、基本的なエラーの検知が可能となります。 Sentry .init do |config| config.enabled_environments = %w( production staging ) config.dsn = ' https://xxxxxxx.ingest.sentry.io/xxxxxxx ' config.breadcrumbs_logger = [ :sentry_logger , :active_support_logger , :monotonic_active_support_logger , :http_logger ] config.sample_rate = 1 config.traces_sample_rate = 0.1 config.send_default_pii = true config.environment = Rails .env config.include_local_variables = true end include_local_variables はローカル変数の値の情報を送ることができます、また、 traces_sample_rate はトランザクションのサンプリング率の設定オプションなのですが、 ドキュメント通りに「1」と設定するとサンプリング率100%となり、AWSのNATゲートウェイを使用している環境の場合は、外部通信の通信量が大幅に増え、通信コストが大きく増える可能性があるため注意が必要です。 詳細設定 任意のイベントを送りたい場合は、 capture_message を使用します。levelは、 :fatal , :error , :warning , :log , :info , :debug の6種類が使用できます。 Sentry .capture_message( " Message " , level : :error ) rescueしている箇所で例外の情報を送りたい場合は、 capture_exception を使用します。 begin # Process A rescue StandardError => e Sentry .capture_exception(e) # Process B end set_tags , set_user , set_context などを用いるとデバッグ時に有用な情報を送ることができます。 set_tags は、Sentryの標準のタグに加えてタグ付けをカスタマイズすることができます。 TUNAGでは複数台のステージングの識別のためにタグ付けをしたり、アラームの設定用にbooleanの値でタグ付けしています。 Sentry .set_tags( staging_no : ENV [ ' STAGING_NO ' ]&.to_i) if Rails .env.staging? set_user は、id, username, email, ip_addressの4種類の情報を送ることができ、影響を受けているユーザー数や傾向の分析に役立てれます。 Sentry .set_user( id : current_user.id) set_context は、任意の情報をkey, valueの形式で送ることができ、デバッグに必要になる情報を送る際に便利です。 Sentry .configure_scope do |scope| scope.set_context( ' user_details ' , { user_status : current_user.status, tenant_id : curernt_tenant.id } ) end Slack連携とアラートの整備 Sentryは、Slackとの連携可能でアラートの通知をSlackに送ることができます。 Issue発行のSlack通知例 TUNAGでは、主に下記の4つのアラートを設定しています。 Issueの発行 エラー件数の閾値超過 影響を受けているユーザー数の閾値超過 直近のリリースが原因のエラーの発生 閾値も Critical Conditions と Warning Conditions の2段階で設定できるため、緊急性の判断がしやすいのも特徴的です。 docs.sentry.io CircleCIとの連携によるRelease Managementの活用 Sentryは、CircleCIと連携させることができ、リリース単位でエラーをトラッキングすることができます。 docs.sentry.io 下記がCircleCIのconfigファイルの抜粋です。 jobs : notify-sentry-deploy : executor : deploy environment : SENTRY_ORG : OrganizationName SENTRY_PROJECT : Project Name SENTRY_ENVIRONMENT : Environment steps : - run : name : Create release and notify Sentry of deploy command : | curl -sL https://sentry.io/get-cli/ | bash sentry-cli releases new -p $SENTRY_PROJECT $CIRCLE_SHA1 sentry-cli releases set-commits $CIRCLE_SHA1 --commit "own-repo@$CIRCLE_SHA1" sentry-cli releases finalize $CIRCLE_SHA1 sentry-cli releases deploys $CIRCLE_SHA1 new -e $SENTRY_ENVIRONMENT workflows : deploy_ecs_production : jobs : - build_tunag_production_image : filters : branches : only : main - notify-sentry-deploy : filters : branches : only : main requires : - build_tunag_production_image CirlceCIの環境変数の CIRCLE_SHA1 を用いるようにし、checkoutの時間を省略するようにしました。 この設定により、下図のようにリリース単位でエラーの発生をトラッキングできるようになり、 最新のリリースが原因のエラーが発生した場合のアラートの設定もできるようになりました。 Releases画面の例 運用 運用を開始するにあたり、下記のドキュメントを整備しました。 ドキュメント①:Sentryの運用方針 導入背景 プロジェクトの切り方 Issueのステータスの説明 通知用のSlackチャットルームの命名規則 必須設定のアラート etc. ドキュメント②:プロジェクト個別のIssueのトリアージ手順 分担 新規発行されたIssueのトリアージ アラート対応 etc. また、週1回のSentryデーという日を設けて棚卸しを行うことを始めました。 トリアージ漏れのIssueの処理、Issueのマージ、アラートの閾値の見直しを行っています。 運用を始めたばかりなので、まだ上手く回っていないところもあるため、 今後の改善を模索しています。 今後について Sentryでできることが把握でき、運用方針をまとめることができたため、 今後はTUNAGのフロントエンドや他のプロダクトへの横展開を今後進めていきます。 また、まだまだ活用できていないSentryの機能があるため、それらを活用して効率が良く漏れの無いエラー監視ができる仕組み作りをしていきたいです。 まとめ 本記事では、Railsアプリケーションに対するSentryの導入事例について紹介しました。 最後に、スタメンではエンジニアを募集しています。興味をもっていただけましたら、ぜひ下記からご応募ください。 herp.careers
はじめに 事前の検証作業 MySQL 5.7 ⇒ 8.0の変更点の影響確認 1. 照合順序 2. 暗黙のソート 3. 予約語 アップグレード方法の検討 パラメータグループの作成 パフォーマンス確認 アップグレード済みのステージング環境の運用 k6とDatadogを用いた主要画面のパフォーマンス確認 実行計画の変化の確認 SQLの改善 本番アップグレード作業 振り返りと今後について まとめ はじめに プラットフォーム部 SREチームのショウゴ( @shogo_452 )です。 TUNAGのメインデータベースをAmazon Aurora MySQL v2(MySQL5.7互換)からv3(MySQL8.0互換)にアップグレードしたので、その検証内容などアップグレード完了に至るまでの過程を共有します。 事前の検証作業 MySQL 5.7 ⇒ 8.0の変更点の影響確認 まずは、MySQL 5.7(以下、5.7)からMySQL 8.0(以下、8.0)へのバージョンアップにおける変更点とその影響有無の調査を行いました。 1. 照合順序 照合順序は、文字の並び替えや比較のルールです。 文字コードutf8mb4の照合順序のデフォルトが、8.0でutf8mb4_general_ciからutf8mb4_0900_as_ciに変更になりました。 TUNAGでは、明示的にutf8mb4_general_ciを指定していたため、影響はありませんでした。 各文字セットにはデフォルト照合があります。 たとえば、utf8mb4 および latin1 のデフォルトの照合は、それぞれ utf8mb4_0900_ai_ci および latin1_swedish_ci です。 dev.mysql.com 2. 暗黙のソート 5.7では、GROUP BY句で暗黙的にソートが行われていましたが、8.0からはこの暗黙のソートがなくなったため、ORDER BY句を使う必要があります。 TUNAGでは暗黙のソートに依存している箇所はなかったため、影響はありませんでした。 以前は (MySQL 5.7 以下)、GROUP BY は特定の条件下で暗黙的にソートされていました。 MySQL 8.0 では発生しなくなったため、暗黙的ソートを抑制するために最後に ORDER BY NULL を指定する必要はなくなりました (前述のとおり)。 ただし、クエリー結果は以前の MySQL バージョンとは異なる場合があります。 特定のソート順序を生成するには、ORDER BY 句を指定します。 dev.mysql.com 3. 予約語 8.0では、 新たな予約語 が追加されましたが、 TUNAGで使用しているRailsでは、テーブル名とカラム名をバッククォートでエスケープしてくれるので影響はありませんでした。 dev.mysql.com アップグレード方法の検討 最終的に 「インプレースアップグレード」 を選択しました。 Blue/Greenデプロイ(以下、B/Gデプロイ)も1つの選択肢としてあったのですが、既存のクラスターパラメータグループで binlog_format=MIXED に事前に変更する必要があり、8.0用の新規作成するカスタムパラメータグループで binlog_format=MIXED と設定することとし、今回はB/Gデプロイの選択を見送りました。 パラメータグループの作成 次に8.0用のカスタムパラメータグループの作成です。 まずは、既存の5.7のカスタムパラメータグループのうち、デフォルトの値からカスタムされているパラメータの確認を行いました。 確認の際は、AWS CLIとjqコマンドを用いてデフォルトパラメータグループとカスタムパラメータグループの内容をjsonファイル化し、両ファイルの差分をdiffで確認しました。 この方法を取ることでカスタマイズをしている内容を漏れなく確認することができました。 $ aws rds describe-db-cluster-parameters --db-cluster-parameter-group-name default.aurora-mysql5.7 | jq . > default-cluster-mysql5.7.json $ aws rds describe-db-cluster-parameters --db-cluster-parameter-group-name aurora-cluster-mysql5.7 | jq . > production-cluster-mysql5.7.json $ git diff default-cluster-mysql5.7.json production-cluster-mysql5.7.json $ aws rds describe-db-parameters --db-parameter-group-name default.aurora-mysql5.7 | jq . > default-instance-mysql5.7.json $ aws rds describe-db-parameters --db-parameter-group-name stats-aurora-mysql | jq . > production-instance-mysql5.7.json $ git diff default.aurora-mysql5.7.json production-instance-mysql5.7.json パフォーマンス確認 アップグレード済みのステージング環境の運用 まずは、何台かのステージング環境を8.0にアップグレードした状態で、他のエンジニアメンバーに普段の開発で使ってもらう運用を2週間程度行いました。 これは、普段の開発の中で著しくパフォーマンスが遅くなる画面やAPIを見つけることを狙いました。 k6とDatadogを用いた主要画面のパフォーマンス確認 次に、コアな機能のAPIに対して、関連するレコード数が最多のケースでパフォーマンス確認を行いました。 負荷試験ツールのk6を用いて、検証条件のケースをk6のシナリオに記述、リクエストを実行し、SQLの実行時間や画面の描画時間などの確認をDatadogのAPMを用いて行いました。 この確認の結果、主要なAPIの一部で大幅なパフォーマンスの劣化が起きることが判明しました。 k6.io 実行計画の変化の確認 8.0へのバージョンアップでパフォーマンスが大幅に劣化したSQL(一部省略)が下記となります。 SELECT `table_a`.`id`, -- 省略 FROM `table_a` LEFT OUTER JOIN -- 省略 WHERE -- 省略 AND `table_a`.`id` IN ( SELECT `table_a`.`id` FROM `table_a` LEFT OUTER JOIN -- 省略 WHERE -- 省略 AND ( `table_a`.`id` IN ( SELECT -- 👈 サブクエリ1 `table_b`.`table_a_id` FROM `table_b` WHERE -- 条件1(省略) ) OR `table_a`.`id` IN ( SELECT -- 👈 サブクエリ2 `table_c`.`table_a_id` FROM `table_c` WHERE -- 条件2( 省略) ) OR `table_a`.`id` NOT IN ( SELECT -- 👈 サブクエリ3 `table_c`.`table_a_id` FROM `table_c` WHERE -- 条件3(省略) ) ) ) ORDER BY `table_a`.`id` DESC ; 5.7では、サブクエリ1, 2, 3の部分に対してEXISTS戦略による最適化が適用されていたのですが、 8.0にバージョンアップすると実体化を使用した最適化(materialization)が適用され、実行計画が変わることが分かりました。 サブクエリの最適化状況を確認する場合は、EXPLAIN後にSHOW WARNINGSステートメントで発行できる追加情報もしくはオプティマイザトレースを参照すると確認することができます。 EXPLAIN SELECT * FROM test_table; SHOW WARNINGS; dev.mysql.com SET optimizer_trace= ' enabled=on ' ; EXPLAIN SELECT * FROM test_table; SELECT * FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; dev.mysql.com SQLの改善 パフォーマンス劣化の原因となったSQLについては、様々な対策方法を検討した結果、 最終的にEXISTS句とNOT EXISTS句を明示的に使用するように変更することで、5.7の実行計画を維持できるようになりました。 SELECT `table_a`.`id`, -- 省略 FROM `table_a` LEFT OUTER JOIN -- 省略 WHERE -- 省略 AND `table_a`.`id` IN ( SELECT `table_a`.`id` FROM `table_a` LEFT OUTER JOIN -- 省略 WHERE -- 省略 AND ( EXISTS ( SELECT 1 FROM `table_b` WHERE (`table_a`.`id` = `table_b`.`table_a_id`) AND -- 条件1(省略) ) OR EXISTS ( SELECT 1 FROM `table_c` WHERE (`table_a`.`id` = `table_c`.`table_a_id`) AND -- 条件2(省略) ) OR NOT EXISTS ( SELECT 1 FROM `table_c` WHERE (`table_a`.`id` = `table_c`.`table_a_id`) AND -- 条件3(省略) ) ) ) ORDER BY `table_a`.`id` DESC ; 本番アップグレード作業 本番のアップグレードは、上記のSQL改善を行った上で、ステージング環境で確認した手順で作業を行いました。 アップグレード作業と合わせてCA証明書の更新も行いました。CA証明書は、負荷影響も考慮して既存のrds-ca-2019と同じアルゴリズムが使用されているrds-ca-rsa2048-g1を選択しました。 振り返りと今後について 事前の検証を入念に行ったこともあり、無事に何事もなくバージョンアップ作業を終えることができました。 今回作成した8.0用のパラメーターグループで binlog_format=MIXED を設定したことにより、 今後はB/Gデプロイを利用することができるため、次回はB/Gデプロイを試そうと思っています。 また、メジャーバージョンアップの検証手順が今回確立でき、別のデータベースのAurora PostgreSQL 11.17 から Aurora PostgreSQL 15.4 へのアップグレード作業を控えていたため、 早速手順を流用し先日アップグレードを無事終えました。 まとめ 本記事では、Amazon Aurora MySQL v2(MySQL5.7互換)からv3(MySQL8.0互換)へのアップグレードについて、 検証内容などアップグレード完了に至るまでの過程を紹介しました。 最後に、スタメンではエンジニアを募集しています。興味をもっていただけましたら、ぜひ下記からご応募ください。 herp.careers
こんにちは、エンジニアの @natsuokawai です。 先日開催された Kaigi on Rails 2023 にて、スタメンとしてスポンサーブースを出展しておりました。 遊びに来てくれた皆さんありがとうございました! スタメンのブース その際 Ruby on Rails に関するクイズを出題していたので、本記事ではそれらの解説を簡単にしたいと思います。 問題1 以下のコードを Rails 6.1 以前で実行した時の結果は?(Task は ActiveRecord オブジェクト、id は integer 型のカラムとする) task1 = Task .create( title : " Task 1 " ) task2 = Task .create( title : " Task 2 " ) tasks = Task .where( id : task1.id).merge( Task .where( id : task1.id..task2.id)).pluck(& :title ) 選択肢: ["Task 1"] ["Task 2"] ["Task 1", "Task 2"] [] 解説 正解は 1. ["Task 1"] です! 弊社のサービス TUNAG(ツナグ)の Rails バージョンを 6.1 → 7.0 に上げる際に引っかかったので、今回問題にしてみました。 Rails 6.1 以前では、 relation1.merge(relation2) とした際、relation1 と 2 の条件が AND で結合されたり、relation2 の条件で上書きされたりと、一貫性のない仕様になっていました。 上記コードでは AND で結合されるため 、 tasks を取得する際に発行される SQL は SELECT "tasks".* FROM "tasks" WHERE "tasks"."id" = 1 AND "tasks"."id" BETWEEN 1 AND 2 となり、 Task 1 のみが取得されます。 ちなみに Rails 7.0 以降では常に relation2 の条件で上書きされるように変更されたので、 ["Task 1", "Task 2"] になります。 詳細: Deprecate inconsistent behavior that merging conditions on the same column by kamipo · Pull Request #39328 · rails/rails · GitHub バージョンを上げたときのブログ記事: TUNAG の Rails バージョンが 7.0 になりました - stmn tech blog 問題2 以下のアソシエーションを持つモデルにおいて、正しく動作しないものはどれか? class User < ApplicationRecord belongs_to :company end class Company < ApplicationRecord has_many :users validates :name , presence : true end 選択肢: 1. User.joins(:company).where(company: {name: 'stmn'}).count 2. User.preload(:company).where(company: {name: 'stmn'}).count 3. User.eager_load(:company).where(company: {name: 'stmn'}).count 4. User.includes(:company).where(company: {name: 'stmn'}).count 解説 正解は(正しく動作しないのは) 2. User.preload(:company).where(company: {name: 'stmn'}).count です! N+1 問題の解消でお世話になるメソッドたちについてのクイズでした。 こちらは基礎的な問題だったので、正解者も多かったですね。 実際にコードを実行してクエリを見てみるとわかりやすいですが、1、3、4 は companies を JOIN をしているため、 where メソッドにて companies の絞り込みを行うことができます。 preload は JOIN しないので、companies を参照しようとしてエラーになります。 includes は内部で preload と eager_load を呼び分けるメソッドです。上記のような companies の絞り込みクエリなどがない場合は preload と同じ挙動になります。 参考: activerecord/lib/active_record/relation.rb#L915 activerecord/lib/active_record/relation.rb#L735 問題3 下記のようなコントローラーが定義されているとき、コールバックに定義されたメソッドが実行される順番として正しいものはどれか? class ParentController < ApplicationController before_action :parent_before prepend_before_action :parent_prepend_before end class ChildController < ParentController before_action :child_before prepend_before_action :child_prepend_before end 選択肢: 1. parent_prepend_before → child_prepend_before → child_before → parent_before 2. parent_prepend_before → child_prepend_before → parent_before → child_before 3. child_prepend_before → parent_prepend_before → child_before → parent_before 4. child_prepend_before → parent_prepend_before → parent_before → child_before 解説 正解は 4. child_prepend_before → parent_prepend_before → parent_before → child_before です! コールバックの実行順序に関する問題です。レビューでこんなコードが来たら通さないよねと言われた回数第一位です (それはそう) 継承関係にあるとき、親→子の順でコールバックが実行されます。 また、 prepend_before_action は before_action の配列の先頭にメソッドを追加するので( Array#prepend と同じ)、今回のような場合は親が先に before_action の前に追加し、子がさらにその前に追加します。 参考: actionpack/lib/abstract_controller/callbacks.rb#L171-L175 activesupport/lib/active_support/callbacks.rb#L744 問題4 update! を実行したときのクエリの発行回数は Rails 7.0 以前と 7.1 でそれぞれ何回か?( Post.last で発行されるクエリは考慮しない) class User < ApplicationRecord has_many :posts end class Post < ApplicationRecord belongs_to :user end post = Post .last post.update!( title : " Rails is the best " ) 解説 正解は 「7.0 以前は 2 回、7.1 以降は 1 回」です! こちらもまた Rails バージョンによる差異の問題になります。 optional: true ではない belongs_to 関連が定義されているとき、Rails 7.0 以前は update! のタイミングで関連先のレコードをロードしていました。 7.1 以降では関連先に変更がなければロードしないようになり、クエリの発行回数が減っています。 詳細: Avoid validating `belongs_to` association if it has not changed by fatkodima · Pull Request #46522 · rails/rails · GitHub まとめ Kaigi on Railsのコアコンセプトは 「初学者から上級者までが楽しめるWeb系の技術カンファレンス」ということで、馴染みのあるメソッドを中心に選んでみました。 ブースではこのクイズを起点にして、Rails を始めたばかりの方やコミッターなど幅広い方と盛り上がることができ、とても楽しかったです。 最後に、スタメンではエンジニアを募集しています。Rails 好きな方はもちろん、フロントエンドやモバイルアプリなど各技術領域で募集中なので、ご応募お待ちしております! herp.careers
株式会社スタメンは、2023年10月27日、28日の2日間、浅草橋ヒューリックホールにて開催される「Kaigi on Rails 2023」に、Rubyスポンサーとして協賛し、ブース出展などを通してイベントを盛り上げます。 kaigionrails.org TUNAGの開発では 2017年のサービス提供開始当初から Ruby on Rails を採択してきました。 直近では、 10月6日にリリースされた Rails 7.1 への移行を当日中に完了 するなど、スピード感を持って Rails での開発に取り組んでいます。 本エントリーでは、そんな我々がこの度の Kaigi on Railsに初協賛するにあたって準備を進めている、スポンサーLTや、スポンサーブース、ノベルティ、フライヤーについてをご紹介いたします! スポンサーLTについて スポンサーLTには、Rails 7.1 アップデートの際には主力を担った、プラットフォーム部の河井が登壇いたします。 登壇者:河井 夏生 日時:2023年10月28日 16:40〜(5分) 場所:Hall A 詳細: https://kaigionrails.org/2023/schedule/#day2 スポンサーブースやノベルティ、配布物のご紹介 オフライン会場のスポンサーブースは、 カンファレンスでのブース出展の際 にはお馴染みのスタメンカラーのテーブルクロス、バナースクリーン、のぼり旗。 スタメンメンバーは、黒地に白いスタメンロゴのTシャツが目印です! Rails にまつわるアンケートやクイズを企画しており、ご参加された皆様に楽しんでいただけるようにエンジニアメンバー一丸となって内容を考えています! アンケートかクイズかのいずれかに回答いただけると、もれなくもらえるノベルティ、抽選で当たる豪華ノベルティなども用意する予定です。 6枠のみのRubyスポンサーの一角ということで、気合を入れて準備しているので、当日は是非お立ち寄りください! またスポンサーブースや配布物の共有スペースでは、開発組織についての簡単な紹介しているフライヤー配布する予定です。 おわりに Kaigi on Rails の2日間を通して、Railsエンジニアの皆様だけでなく、様々な技術領域のWebエンジニアの皆様とお会いできることを心待ちにしております! カンファレンス情報 名称 : Kaigi on Rails 2023 開催日時 : 2023年10月27日(金)〜10月28日(土) 場所 : 浅草橋ヒューリックホール&カンファレンス + オンライン 公式サイト: https://kaigionrails.org/2023/ 参加方法や詳細については、 公式サイト をご覧ください。 採用情報 スタメンでは、Railsエンジニアに限らず、全ての領域でエンジニアを募集しています。もし興味を持っていただけたら、下記からご応募ください! herp.careers
こんにちは、スタメンの @natsuokawai です。 今日は Rails World 2023 @アムステルダム の Day 2 ですね。 X(Twitter)のポストを見ていても現地の熱が伝わってきて、私も来年の Rails World にはぜひ参加したいと感じています。 さて、そんな Rails World の開催中、10月5日の日本時間の17時過ぎに、Rails の最新バージョン 7.1 が公開されたことを知ります。 その時点ですでに弊社のサービスTUNAG(ツナグ)も Pre-release バージョンでリリース準備を進めていたところでしたので、発表のタイミングに戸惑いながらも、無事 7.1 に上げることができました。 バージョンを 7.1 に上げたときの Slack 投稿 前回のブログ でもお伝えした 6.1 から 7.0 まで上げる作業には、リリースから500日以上経過した状況で着手し、そこから3週間ほどの時間を要しました。 一方で今回は、正式版リリース後1.5時間で追従することができ、作業にかかった時間は3日ほどと、大幅な時間短縮を実現できています。 これでタイムリーに最新版に追従できている状態になったので、今後は計画的にバージョンアップを行っていきたいです。 常に最新版を使っていれば更新時の差分も少なく、大規模なプロジェクトの必要もなく日々の作業の中で追従しやすくなります。 その分不具合に遭遇するリスクも増えるかもしれませんが、問題の改善や報告を通じて Rails コミュニティにフィードバックすることで、コミュニティへの貢献もしていきたいと思っています。 最後に宣伝をさせてください。 スタメンは今月末の Kaigi on Rails 2023 に Ruby スポンサーとして協賛 しています。 私も現地にいますので、会場でお会いできた際はぜひお話ししましょう! また、スタメンではエンジニアを募集しています。興味を持っていただけましたらぜひ下記からご応募お待ちしております。 herp.careers
こんにちは、CTO室 エンジニアHRチームのがせ( @gasekao96 )です。 スタメンでは、 "Expand your Horizon." をテーマに8月と9月にそれぞれ2週間のエンジニアサマーインターンを実施しました。 インターンには合計8人のメンバーが実際の開発チームに参加。 MacBook Air M2 24GB、32インチ 4Kモニター、各自が希望するマウス/トラックパッド、ハーマンチェアーなどの開発デバイスが貸与され、社員と同じ環境で、そしてプロダクションコード上で開発タスクに取り組みました。 本エントリーでは、プログラムの内容と参加した学生の感想をご紹介します。 インターン初日 初日の出社後は全員集まって自己紹介や、CTO松谷からの事業説明をうけるオリエンテーションを行いました。 事業説明では、 TUNAG ユーザーの解像度を上げてもらうために導入事例動画を交えて紹介がありました。 オリエンテーション後は、”ニューメンバーランチ制度”を利用して、各開発チームメンバーとランチに出かけました。 この制度は1人のニューメンバーに対して2回利用することができます。2回目のニューメンバーランチでは、他の開発チームやビジネスサイドのメンバーとも出かけて、技術や趣味の話で盛り上がっていたようです。 チーム横断で行われたランチの様子 午後からは、いよいよ開発チームとしてのキックオフ。インターン期間の目標設定、チームビルディングや開発環境の構築を行いました。 2日目以降 開発期間 2日目以降はいよいよ、 フロントエンドリプレイス やパフォーマンス改善といったそれぞれの開発タスクに着手し始めます。 開発期間に入ってからは、続々とインターンメンバーによるPRが作成されていました。 メンターからのコードレビューは妥協無しで厳しく行われ、時にはチーム外のメンバーからもレビューをもらう機会があったようです。 インターン期間中、日々の気づきや共有したいトピックがあればTUNAGの日報に投稿してもらっていました。 PR粒度やPR前の自己レビューといったチーム開発をする上での心掛けや、技術課題に詰まった際に前提を見直す/立ち返る、また質問の仕方を工夫するなど、日々の学びがたくさん共有されていました。インターン生だけでなく、スタメンのエンジニアメンバーも改めて自身の振る舞いを見直すいいきっかけになったのではないかと思います。 さらに、日報の中で近隣のおすすめ飲食店をスタメン社員に質問したりと積極的にコミュニケーションを取る姿も見られ、日々投稿へのコメントも盛り上がっていました。 また開発以外では、CEOとの対面1on1や懇親会、部活に所属するメンバーなどの有志によって企画されたゲーム大会などが行われました。 ランチタイムを利用して行われたゲーム大会では、参加せずにご飯を食べながら見守るメンバーも多数。 開発する中では話す機会の少ないビジネスサイドのメンバーや役員メンバーとのコミュニケーションを通じて、スタメンの雰囲気やカルチャーも存分に感じてもらえたようです。 部署を超えてゲームに興じるみなさん インターン最終日 最終日には、オンラインでエンジニアメンバー全員の前での成果発表会が行われ、実装した機能・ページやパフォーマンス改善の成果、得た知見や開発の苦労などを各々のスタイルで発表が行われました。 発表の様子 プロダクトへの理解度やリリースまで完遂する実装速度の速さには、スタメンのエンジニアメンバーから驚きのコメントがたくさん寄せられました。 成果発表後はメンターとフィードバック面談を行い、インターン完走を賞賛するスタカネを鳴らし、全ての工程が終了です。 初日は緊張気味の堅い表情の皆さんでしたが、最終日にはリラックスした表情で過ごしている姿がとても印象的でした。 インターンメンバーからの感想 最後に、インターンメンバーからもらった感想をご紹介します。 フロントエンドリプレイスプログラム 土佐さん: フルタイムのインターンに参加させていただくのは今回が初めてで、時間内に与えられたタスクができるのかとても不安でしたが無事インターンを終えることができました。 メンターの方をはじめ、エンジニアの皆様からは技術的に学ぶことも多く、今後の私の糧にさせていただきたいと思います。 また、ビジネスサイドの社員さんやインターン生と関わることも多く、普段しないような話もたくさんさせていただきました。 2週間という短い期間ではありましたが、社内雰囲気や、社員さんの人となり、また技術的なことなど本当に多くのことを学べ、実りあるインターンとなりました。 この結果にはスタメンの社員さん皆様の協力無くしてはできなかったことだと思います。 改めまして2週間という短い期間でしたがお世話になりました。 (土佐さんは、自身のブログでもインターンについての記事を投稿してくれました。取り組みや、感じた社内の雰囲気についてもかなり深く書いていただいたので、ぜひご一読ください!) ブログ: 株式会社スタメンのインターンシップに参加してきました! フロントエンドリプレイスプログラム 大橋さん: あっという間の2週間でしたが、インターンに参加出来てとてもよかったと感じています。出社する形でのインターン自体あまり経験がなかったのですが、おでんチームを含めた皆さんがあたたかく迎え入れてくれたおかげで、すぐに打ち解けることが出来ました。 今回のインターンのテーマとして、技術面の成長とコミュニケーションということを軸にしていましたが、どちらも学ぶことができました。技術面に関して細かい部分は省きますが、アプリを開発する際の生産効率の上げ方、拡張性、保守性など、実際に運用されているTUNAGの開発に携われたからこその学びが多くありました。コミュニケーションに関しても、懇親会など会社側で用意してくれた企画などもあり、エンジニアサイドに限らず多くの人とコミュニケーションをとることが出来てよかったです。また、CEO、CTOと直接話せる機会もあり、2週間でやれることは全てやれたというのが率直な感想です。最後に、今回のインターンは遠方から参加しましたが、名古屋のグルメなどを堪能できたのもよかったです。 フロントエンドリプレイスプログラム 中村さん: 技術的にも、人としても成長できたインターンになりました。 技術的には、特にフロントエンドのテストに関して大きく成長できました。メンターの方にはかなり丁寧にコードレビューをいただき、それを通してテストケースの網羅性や特定のケースの見落としについての意識が向上しました。インターン参加前はフロントエンドのテストを書いたことがありませんでしたが、インターンを通じて全てのテストケースを網羅する重要性を認識し、その意識が高まりました。 人としての成長として、チームで開発する際の意識が改善されたと思います。初見の人にとって、このPRではどこまでを実装したのか、このコンポーネントは何に使われるかなどを分かりやすく書くことを意識できるといいねといったレビューをいただきました。チームでの時間を増やすためにも、初見の人にとって分かりやすい情報共有を心がけるようになりました。 スタメンさんのインターンに参加して、多くのものを吸収できたと思います。今回身につけたことを今後の開発にどんどん活かしていきたいです。 フロントエンドリプレイスプログラム Kagariさん: 開発しやすいと思ったのと社員の人柄がとても好きだなと感じました。というのも開発の中で疑問に思ったことや改善点を本音でぶつけ合うことができ、制作向上に繋がっていると感じたのと開発以外でも雑談を行ったり冗談を言い合える関係で楽しめたためです。 また私が携わったのはフロントエンドのリプレイスでアーキテクチャやコードの品質周りで深く学べたので参加してよかったと思いました。 パフォーマンス改善プログラム 大石さん: 今回のサマーインターンでは、実際に運用されていて、利益を上げているプロダクトのパフォーマンス・チューニングを体験させていただき、非常に貴重な経験をさせていただきました! 実際にユーザーがいるサービスであるからこそ、表示速度を削った際のインパクトを想像しやすく、「ユーザーのために」とモチベーションが向上していくのを感じました。 これまではサービスやプロダクトを「作っていく」過程を多く経験してきましたが、サービスのフェーズが違えばやることが違うことや、運用フェーズで組織内で行っていることの解像度が高まりました。 また、パフォーマンス・チューニングを行うことで可読性が下がるため、トレードオフの関係になっていることや、その中でもパフォーマンス・チューニングをやってよかったと思えるように、アクセスログなどを用いてデータをもとに意思決定することの大切さに気づくことができました。 ランチや懇親会などで、ビジネス職の方と関わることもでき、スタメンの文化や他業種のことも知ることができました! パフォーマンス改善プログラム 近藤さん: 今までバックエンドを触った経験はなかったのですが、メンターの方に沢山サポートいただき、パフォーマンス改善を行うことができました。 定量的に成果が見えるので、とても楽しい2週間でした。 2週間のプログラムを終えてスタカネを鳴らす様子 採用情報 株式会社スタメンでは、全てのポジションでエンジニアを募集しています。 興味を持っていただけたら、下記のリンクからご応募ください! herp.careers
こんにちは、リファクタリング大好きな ミノ駆動 です。 株式会社スタメン では、企業エンゲージメント構築サービス TUNAG (ツナグ)の技術的負債解消と今後の持続的成長のため、ドメイン駆動設計(DDD)の導入を検討しています。 ところでDDDはとかく理解しづらく、何のためのDDDなんだという議論になりがちです。この記事では、DDDの 真の主人公コアドメイン を中心に、DDDが何を解決するものなのか、 全体像 を改めて整理します。 この記事で扱う内容 DDDが解決したい課題と解決方法の全体像。 この記事では扱わない内容 設計パターンの実例などの実装詳細。 大事な前提 〜利益を得るためのサービス開発 会社でのサービス開発は、趣味や道楽でやるものでしょうか。違いますね。ビジネスとして、企業活動としてサービス開発しています。当たり前の話ですが、利益を得られるように開発しなければなりません。 ドメイン駆動設計は、 継続的に利益向上するための設計手法であり思想 だと考えます。理由を以下に説明します。 DDDが解決したい課題 DDDが解決したい課題は、大きくは以下2つです。 顧客満足度低下による利益減 :「今作ってるもの、本当に顧客に喜ぶものなの…?」と疑問に感じながらの開発が常態化。そしてやっぱり顧客にウケない。顧客離れが起き、稼げなくなる。 開発コスト増大による利益減 :「この機能を実装したら顧客にウケることは間違いないんだ、でも技術的負債があまりにも酷すぎて機能追加が難しすぎる!」……開発生産性が悪化し、リリースまでの時間やコストが増大。折角の利益が膨大な開発コストによって相殺されてしまう。 DDDが目指す世界 上記課題が解決された世界は次のようになるでしょう。 機能性向上 :サービスの 競争優位性 がチームに理解されており、競争優位性を高め続けられている状態。継続的に利益が増大し続けている状態。 変更容易性向上 :技術的負債に苦しめられることがなく、いつでも 迅速に 機能を実装しリリースし続けている状態。 「ドメイン」とは まずこの記事を理解する上でドメインという概念の理解が必要です。 世の中には解決が必要な問題がいろいろあります。「楽しい時間を過ごしたい」「美味しいものを食べたい」「新しい服がほしい」など、いわゆる人の欲求ですね。そうしたいろんな問題の中で、特定の範囲の問題を 問題領域 と呼びます。 次の図における楕円が問題領域の一例です。ここでの問題領域は「楽しい時間を過ごしたい」とします。こうした問題領域のことを ドメイン と呼びます。 問題領域(ドメイン)と解決領域 さて問題に対し、世の中にはさまざまな解決方法が用意されています。この「楽しい時間を過ごしたい」という問題領域には、例えば世の中にはスポーツ観戦や旅行、ゲームなどがあります。こうしたものを、問題領域に対して 解決領域 と呼びます。 問題領域の中にさらに個々の問題領域がある 次の図はX(旧Twitter)の例です。 X(旧Twitter)の問題領域と解決領域(筆者の想像) 「コンテンツを楽しみたい」という全体の大きな問題に対応する解決領域がXだと仮定します。Xには、さらに個々の問題領域があると考えられます。「話題性のあるコンテンツを見たい」「情報収集したい」「TLに流れてくるコンテンツを健全に保ちたい」…。こうした個々の問題領域に対して、Xでは上図の赤四角で示すような機能が用意されています。 どこに開発リソースを投じるか? お金は無限にありません。有限です。 会社のお金も有限です。当然開発予算も有限です。限りある予算の中で、顧客が価値を感じるサービスを作っていかなければなりません。 上で説明したように、サービスには対応する問題領域がいろいろあります。その中でどの領域に投資しますか? 選択と集中 費用対効果を高める 特定の事業分野に経営資源を集中することを 選択と集中 といいます。経営戦略上、 自社が得意とする、差別化可能な、競争優位性のある分野 に集中投資することで費用対効果を高めます。 サービス開発も同様に選択と集中が必要です。不得意な、競争優位性のない分野に開発コストをかけていいものでしょうか…? サービスの魅力が大して高まらないでしょうし、その間にも競合他社に出し抜かれるでしょう。 皆さんも思い浮かべてください。自社サービスにおける、差別化可能な競争優位性のある分野は何でしょうか…?? それが コアドメイン です。 中心的事業領域 コアドメイン コアドメイン はDDDでいの一番で登場する、超重要概念です。DDD序文からの引用です。 DDDを駆動している原則は次の3つだけです。 ・ コアドメイン に集中すること。 ・ドメインの実践者とソフトウェアの実践者による創造的な共同作業を通じて、モデルを探究すること。 ・明示的な境界づけられたコンテキストの内部で、ユビキタス言語を語ること。 コアドメインとは中心的価値を発揮する事業領域のことです。競争優位性があり、他社との差別化が図られます。「その部分がなくなると商売が成り立たなくなってしまう」ぐらい重要な領域です。 コアドメインとは、いわゆる商品の「ウリ」の部分です。昔から営業さんは「うちの商品は◯◯がウリなんですよー」と営業をかけていましたよね。 コアの例 他社さんのコアと思わしき分かりやすい例です( ※あくまで私個人の見解です )。 ハッピーターン:亀田製菓さんのお菓子。粉(ハッピーパウダー)がコアでしょう。粉250%増量タイプも販売されています。 スプラトゥーン:任天堂さんのインクバシャバシャゲーム。インクがコアでしょう。陣地確保、移動経路開拓、高速移動、攻撃、補給、隠匿などあらゆる役割をインクが担っています。インクを中心にゲームのあらゆる要素がデザインされています。 コンビニやECサイトは、皆さん普段から利用されていると思います。商品を見たとき、「この商品の競争優位性は何だろう、何を差別化してるんだろう、何をウリにしているんだろう」と考えてみるのが良いでしょう。 コアドメインの価値を高められない! さて、ソフトウェアではない話が多少混じりましたが、ソフトウェアの話に戻ります。サービス開発では、コアドメインの価値を高めようにも高められない、価値向上を妨害するさまざまな要因があります。 ◆妨害要因1 : そもそもコアドメインが何か分からない そもそも自分たちのサービスのコアドメインが分からない、何が競争優位性なのか分からないといった状況です。 スタートアップ直後は何をやりたいのか明確ですが、サービスが大きくなってくると何が自分たちの強みなのか分からなくなってくる場合がよくあります。こうなると、その場の思いつきで五月雨式に機能が実装されがちになります。顧客のニーズをなかなか満たせず、競争優位性が育ちにくくなり、サービスの価値は低減する一方になります。 ◆妨害要因2 : サブドメインのロジックとの混在、密結合 コアドメイン以外の問題領域をサブドメインと呼びます。サブドメインの分かりやすい例は決済。多くのECサイトには決済機能があります。決済の不具合は重大なインシデントとなるので、決済は慎重に作り込む必要があります。では決済はコアドメインか? といえばそうではなく、どのECサイトにも実装されているもので、決済自体はサービスの競争優位性とはなりません。 ところで現実のサービスでは、サブドメインのロジックとコアドメインのロジック同士が混在したり、密結合になっている、ということが珍しくありません。このような構造では、コアとサブの見分けが難しくなったり、サブのロジックが邪魔でコアのロジックを上手く変更できない、といったことが発生します。 ◆妨害要因3 : コアドメインロジックの散在、低凝集 コアドメインのロジックがソースコード全体のあちこちに散在し、低凝集に陥っているケースです。 コアのロジックを変更しようにもあちこちにバラバラに実装されているために、コアのロジックを探し回り影響範囲を調査するだけで莫大な時間がかかります。 ◆妨害要因4 : DBロジックやViewロジックとの密結合 ドメインのロジックはアプリケーションロジックです。問題領域の問題を解決するルールや概念を実装したものです。以下がその例です。 X(旧Twitter) : リツイートすると、フォロワーのタイムラインにリツイートしたツイートが反映される。 スーパーマリオ:ダッシュしながらジャンプすると、高くジャンプできる。 エクスプレス予約:新幹線の指定席は、乗車日の1ヶ月前から予約可能。 一方で、DBの責務は永続化です。Viewの責務は表示です。ドメインのルールとは関心事も責務も別です。ところがDBロジックやViewのロジックがドメインロジックと密結合になっているケースがあります。こうした密結合はコアドメインのロジック変更を困難にしてしまいます。 列挙したこれらの妨害要因があると、コアドメインの競争優位性を高めようにもなかなか高めることができません。あまりに酷いと商売が成り立たなくなります。 コアドメインの価値を高めるさまざまな手法 上記の妨害要因があるとコアドメインは「汚れている、汚染されている」状態になります。汚れているとは、 コアドメインがサブドメインのロジックで汚れている コアドメインがDBロジックで汚れている といった事象です。 こうした汚れを取り除き、綺麗に清潔に保つことで初めてコアドメインは価値向上の速度を上げることができます。汚れを取り除いたり、綺麗にしたり、コアドメインの価値を高めるさまざまな手法がドメイン駆動設計では解説されています。ドメイン駆動設計は、 コアドメインの価値を高めるために考えられた設計思想であり設計手法 と言えるでしょう。 ◆手法1 : 境界付けられたコンテキスト 問題領域ごとにサブシステムに分割する考え方です(※より正確には、一枚岩モデルだとシステム構造が混乱してしまうため、文脈ごとに特化したモデルを設計し、各特化型モデルの適用可能範囲を定めたものが境界付けられたコンテキストです)。 手前味噌ですが、境界付けられたコンテキストについては下記動画とスライドが分かりやすいでしょう。 www.youtube.com speakerdeck.com (※悲鳴が大音量で流れるのでご視聴には十分注意) クソコード動画「一枚岩モデル」 #AWSDevDay pic.twitter.com/NwfOmXWy6F — ミノ駆動 (@MinoDriven) 2022年11月9日 境界付けられたコンテキストの設計には何がコアで何がサブなのか事業分析が必要です。そしてコアドメインとサブドメインをシステムレベルで分離隔離します。そしてコアドメインの価値を簡潔に説明する ドメインビジョン声明文 を作成し、何がコアであるかを明示します。 こうすることで、以下の利点が生じます。 何がコアで何がサブか、システム構造レベルで見分けがつくようになる。どのロジックが競争優位性を発揮するのか理解できるようになる。 コアがコアロジックだけの純粋な高凝集になり、サブと疎結合になる。 これらのメリットにより、上で挙げた 妨害要因1〜3が解消されるでしょう 。 ◆手法2 : 階層型アーキテクチャ ドメイン関心事や技術関心事など、関心事単位で階層ごとに分離します。次の図はクリーンアーキテクチャの思想でドメイン層を他の関心事から分離したアーキテクチャ図です。 %%{ init: { 'theme': 'base', 'themeVariables': { 'background': '#000000', 'primaryTextColor': '#6360DC' } } }%% graph TD subgraph A["外界"] View層 DB end subgraph B["入出力変換"] Controller層 Infrastructure層 end subgraph C["ユースケース解決"] UseCase層 end subgraph D["ドメインルール解決"] Domain層 end View層 --- Controller層 Controller層 --- UseCase層 DB --- Infrastructure層 Infrastructure層 --- UseCase層 UseCase層 --- Domain層 Infrastructure層 --- Domain層 例えばDBやファイルなどの永続化に関するロジックは、Infrastructure層にてRepository interfaceの実装クラスにカプセル化します。Repositoryは永続化知識のカプセル化に用いられるパターンです(※正確にはオブジェクトのコレクションをエミュレートする仕組みであり、DBやファイルは仕組みの一形態ににすぎない)。 このように隔離することで、コアロジック(上図のDomain層)が他のロジックに汚されずに済みます。これで 妨害要因4が解消されます。 ◆手法3 : Entity, ValueObject, Aggregateなどの設計パターン 上記手法2まで説明した考え方により、コアドメインのロジックを隔離できました。 さて、隔離できたはいいものの、コアドメインのロジックが複雑化し技術的負債になってしまっては開発生産性を出せません。負債化しないよう、適切な関心事単位で疎結合高凝集にします。そこで登場するのがドメイン駆動設計に登場するValueObject、Entity、Aggregateなどの設計パターンです。ここまで来てようやっと見覚えのあるものが登場するんですね。 %%{ init: { 'theme': 'base', 'themeVariables': { 'background': '#000000', 'primaryTextColor': '#6360DC' } } }%% classDiagram namespace Core { class Repository { <<interface>> } class Aggregate class Entity class ValueObject } Repository ..> Aggregate Aggregate --> Entity Aggregate --> ValueObject Entity --> ValueObject これらのパターンを駆使し、変更容易性が向上するよう内部構造を整理していきます。また、ここに挙げた以外にも役立つ設計があるならどんどん使って良い、というのがドメイン駆動設計の見解です。 ここまで紹介した手法1〜3、 コアの邪魔になるものをひたすら分離隔離していくための手法 であることが理解できると思います。 ◆手法4 : 蒸留、深いモデル ここまでの手法は主にコアドメインの技術的負債を解消し、 変更容易性 (ソフトウェア品質特性の一種、なるべくバグを埋め込まずどれだけ素早く正確に変更できるかを示す度合い)を向上させる観点の設計技法です。しかしDDDはこれだけではありません。 DDDではリファクタリングを繰り返し、ドメインモデルを改良することの重要性を説いています。なぜでしょうか。改良を繰り返していくと「 このドメインの問題を解決するには、実はこういう構造のモデルが相応しいんじゃないか!? 」と気付く瞬間が訪れます。それが深いモデルです。 深いモデル とは、深い理解に基づいた本質を表現するモデルとDDDでは説明されます。深いモデルにより 機能性 (ソフトウェア品質特性の一種、顧客ニーズをどれだけ満たすかを示す度合い)の向上が期待できます。深いモデルは一朝一夕に発見または設計できるものではありません。重要なところに焦点を当てて改良を繰り返す、蒸留というプロセスを経る必要があります。 蒸留には、ドメインの深い理解の獲得が必要なので、ドメインすなわち事業課題やその領域のオキテに詳しい人( ドメインエキスパート )との対話が必要です。そして事業内容を理解するためにもユビキタス言語の策定が必要です。 ユビキタス言語 とは、ステークホルダー全員が理解可能な言葉であり、境界付けられたコンテキストごとに意味が一意に定まる言葉です(文脈によって言葉の意味が違うので)。ユビキタス言語は単に「全員が理解できる言葉」ではなく、 目的を表現する言葉 です。DDDの「意図の明白なインターフェース」では次のように説明しています。 クラスと操作には、その効果と 目的 を記述する名前を付け、約束したことを実行する手段には言及しないこと。(中略)こうした名前はユビキタス言語に従っていなければならない。(中略)そうしたインターフェースには、手段ではなく 目的 の観点から語らせなければならない。 (『エリック・エヴァンスのドメイン駆動設計』p.252より引用) この説明から、ユビキタス言語が目的を表現する言葉であることが分かります。そもそもシステムは何らかの目的を達成するために開発される手段であることから考えても不自然ではありません(※ちなみに拙著『良いコード/悪いコードで学ぶ設計入門』では「目的駆動名前設計」と題してユビキタス言語の操り方を解説しています)。 gihyo.jp 目的ベースでユビキタス言語を策定し、目的に着目しやすくなることで良い効果が生まれます。「 この目的を達成するためならば、今の実装や構造にこだわる必要はないよね。もっと良い手段があるのでは!? 」という着想が得られやすくなります。そしてそれが深いモデルの発見や設計に繋がる、と考えることができます。 これは馬車しかなかった時代の自動車のイノベーション話に似ています。「もっと早い馬がほしい」と顧客に言われて馬の肉体構造や馬車の構造を一生懸命分析しても、自動車は生み出されません。現行手段に囚われず、顧客課題と真の目的に向き合い、目的をより満たすものを考え出す姿勢が大事です。 DDDで解決したいこと まとめ 以上、DDDで解決したい課題と、解決手法の全体像を紹介しました。要約すると以下となります。 DDDは、中心的事業領域であるコアドメインの価値を高め、継続的に利益向上していくための設計手法。 DDDは、コアドメインの機能性と変更容易性の向上に貢献する。 境界付けられたコンテキストにより、コアドメインとサブドメインを疎結合にする。 階層型アーキテクチャにより、Domain層とそれ以外の技術層を疎結合にする。 Entity、ValueObject、AggregateなどのパターンによりDomain層内をドメイン概念レベルで高凝集疎結合にし、変更容易性を向上させる。 蒸留プロセスにより繰り返しモデルを改良し、機能性向上に貢献する深いモデルを発見・設計する。 DDDの向き不向き 解説したDDDの特徴を踏まえると、DDDには向き不向きがあることが分かります。 DDDは、以下を満たすものに向いていると言えるでしょう。 事業の主力、競争優位性の発揮対象 長期開発対象 複雑な事業課題を取り扱うもの DDDは、以下には不向きでしょう。設計コストが高くつきます。 サブやオプション的な位置付けのサービスや機能 プロトタイプなど短期開発で終わるもの 取り扱う事業課題が単純で、CRUD程度のシンプルな作りになるもの おまけ 実はあなたもDDDを実践している? 「そうは言ってもDDDの実践は結構大変そうだなぁ」と感じた方がおられるかもしれません。しかし一方で、私たちは日々の生活でDDDを実践していると私は考えます。 人には皆それぞれ 人生のコアドメイン があります。人はそれを 生きがい と呼びます。大好きな趣味や、大切な人との時間、推しのゲーム……それぞれあることでしょう。生きがいは神聖不可侵であり、なんぴとたりとも邪魔は許されません。例えば自分の趣味の大規模イベントや大事な旅行の予定があるとき、アクシデントが発生したり別の用事が突然割り込まれたりすると台無しになってしまいます。台無しにならぬよう健康に気をつけたり、仕事をしっかり片付けて割り込みが入らないようにした経験、皆さんもあると思います。 ちなみに私はフロムソフトウェアさんのゲーム『アーマード・コア6』の発売に備えるために万全の体制で臨みました(下記ツイートは引用)。 今日も1日 #アーマードコア6 #AC6 pic.twitter.com/7069RC9Ulx — 魚遣(うおつか) (@nou_ni_hitomi) 2023年8月22日 生きがいの大切な時間を守るために、邪魔するものを徹底的に除去する。ソフトウェア開発も同様に、競争優位性を発揮するコアドメインを守るために、コア以外の要素を徹底的に分離隔離する、これがドメイン駆動設計なのです。 おわりに 以上の解説のもと、DDDを活用してプロダクトの価値をより高めるべく邁進していきます。 弊社スタメンはTUNAGを中心に右肩上がりの成長を続けています。この成長をより高めるため、私に課せられた責務は非常に重要なものになっております。 2023年12月期 第1四半期決算説明資料 より この勢いで弊社スタメンはさらなる事業拡大を目指し、採用活動をより活性化していきます。現在従業員数は約80名。今の規模の2倍、3倍、5倍とスケールさせていきます。 エンジニア絶賛募集中です。私と一緒に働いてみたい、興味がある方は、ぜひ下記にアクセスしてみてください。 herp.careers