i Cubed Systems Engineering blog 株式会社アイキューブドシステムズの製品開発メンバーが、日頃のCLOMO開発の様子などを紹介します。 2023-12-15T17:00:32+09:00 clomo-dev Hatena::Blog hatenablog://blog/26006613534031960 スクラムを使って理想のチームを作る hatenablog://entry/6801883189066402353 2023-12-15T17:00:32+09:00 2024-01-31T14:56:24+09:00 はじめに アイキューブドシステムズでCLOMOのサーバーサイドを担当している Kakuno です。 前回のブログでCSEサーバーチームについての紹介がありました。 tech.i3-systems.com こちらの記事にもあるように、CSEサーバーチームでは既存のバグ修正や改善をメインに行っており、スクラムを用いてサイクル(スプリント)を繰り返す手法を用いています。 今回はCSEサーバーチームがスクラムを組むうえでどのような点で工夫が必要なのかをお伝えします。 スクラムとは スクラムとはアジャイル開発の一手法で、プロジェクトを短いスプリント(通常2〜4週間)に分割して進めることで柔軟性を高めます… <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/r/rani-i3/20240131/20240131143422.png" width="1200" height="630" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <h2 id="はじめに">はじめに</h2> <p>アイキューブドシステムズでCLOMOのサーバーサイドを担当している <a href="https://www.linkedin.com/in/tetsuhiro-kakuno-078862100/">Kakuno</a> です。</p> <p>前回のブログでCSEサーバーチームについての紹介がありました。<br/> <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftech.i3-systems.com%2Fentry%2F2023%2F11%2F17%2F163328" title="CSEサーバーチームについて - i Cubed Systems Engineering blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://tech.i3-systems.com/entry/2023/11/17/163328">tech.i3-systems.com</a></cite></p> <p>こちらの記事にもあるように、CSEサーバーチームでは既存のバグ修正や改善をメインに行っており、スクラムを用いてサイクル(スプリント)を繰り返す手法を用いています。<br/> 今回はCSEサーバーチームがスクラムを組むうえでどのような点で工夫が必要なのかをお伝えします。</p> <h2 id="スクラムとは">スクラムとは</h2> <p>スクラムとはアジャイル開発の一手法で、プロジェクトを短いスプリント(通常2〜4週間)に分割して進めることで柔軟性を高めます。スクラムチームは自己組織化し、定期的にミーティング(デイリースクラム)で進捗と調整を行います。スクラムは透明性・検証・適応を重視し、効果的な製品開発を目指します。<br/> 以下では一般的なスクラムの仕組みの説明とCSEサーバーチームのスクラムのルーティンの説明をします。</p> <h3 id="スプリント">スプリント</h3> <p>CSEサーバーチームではスプリント期間は長すぎず短すぎない2週間にしています。この期間で成果物を完成させるのがゴールです。</p> <h3 id="バックログ">バックログ</h3> <p>優先度順に並べられた課題の一覧がバックログです。<br/> バグ修正の課題は日々増えるので、適切に並び替えをしていきます。</p> <h3 id="スプリントプランニング">スプリントプランニング</h3> <p>スプリントプランニングでは、2週間のスプリントの中で何をやるのかという計画を立てていきます。基本的にはバックログの優先順位に応じてどこまでやり切るかを決めていきます。</p> <h3 id="デイリースクラム">デイリースクラム</h3> <p>毎朝10:00にデイリースクラムとして朝会議をしています。</p> <ul> <li>昨日やったこと</li> <li>今日やること</li> <li>困っていること</li> </ul> <p>3つを報告して各々のタスクと状況を確認します。</p> <h3 id="スプリントレビュー">スプリントレビュー</h3> <p>2週間のスプリントで完成したものを発表する会がスプリントレビューです。<br/> ここではエンジニアだけでなく様々な関係者が参加し、成果物をレビューしてもらいます。<br/> 成果物をデモすることで、フィードバックをもらう事が狙いです。</p> <h3 id="ふりかえり">ふりかえり</h3> <p>スプリントの内容を振り返る場です。<br/> 振り返りでは主に良かったこと、悪かったことを話し合い、このチームとしてやってみたいこと(StartDoing)とやめるべきこと(StopDoing)を決めます。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/0262677a8b6fb580169b5d221" alt="スクラム" /></p> <h2 id="CSEサーバーチームのスクラム">CSEサーバーチームのスクラム</h2> <p>ここまでは一般的なスクラムの説明になります。これらを参考にしつつ、CSEサーバーチームでは繰り返しの中で出てきた改善点を取り込み、より良いスクラムを目指しています。<br/> 今回はこの中からデイリースクラムとふりかえりで工夫している点を説明します。</p> <h3 id="デイリースクラムの工夫">デイリースクラムの工夫</h3> <p>デイリースクラムでは<strong>見える化</strong>を行う事を意識しています。<br/> 見える化とは、スクラムボードを用いてチームのタスクや進捗状況を明確に表示し共有することです。これにより、誰がどの課題に取り組んでいて、それはどのような進捗度なのかを明確にします。</p> <p>また、<strong>新しいことをはじめずに終わらせることをはじめる</strong>、という事も意識しています。<br/> 自分の担当課題が終わり手が空くと、スプリントに入っていない新しい課題に着手してしまいがちですが、他の人の課題を手伝う、レビューを進めるなど<strong>今のレーンにある課題を右へ流すこと</strong>を意識しています。</p> <p>各レーンには<strong>最大制限数</strong>を設けており、<strong>それを超えた際には警告が出る</strong>ようにしています。これにより滞留している課題をわかりやすくし、<strong>全ての課題を完了にまで持っていくというゴール</strong>をチームとして共通認識で持ち心がけるようにいています。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/81c0780ece643eb0df6d4ae03" alt="JIRAボード" /></p> <h3 id="ふりかえりの工夫">ふりかえりの工夫</h3> <p>スクラムの一般的な振り返りでは主に良かったこと、悪かったことを話し合い、このチームとしてやってみたいこと(StartDoing)とやめるべきこと(StopDoing)を決めます。<br/> CSEサーバーチームでは、これに加えてそのスプリントのクライテリア(指標)をもとにスプリントの評価を行っています。</p> <p>クライテリアとしてQCD(Quality, Cost, Delivery)に分類分けし、チームが達成すべきものを以下のように定義しています。<br/> CSEサーバーチームと密接に関わるCSチームやQAチームとのやりとりも指標として取り入れています。</p> <h4 id="Quality">Quality</h4> <ul> <li>設計書の質</li> <li>バグ件数</li> </ul> <p>設計書の質を上げることでQA検証時にバグ発見をしやすくし、またQA検証でバグが見つかった件数に応じて採点をしています。</p> <h4 id="Cost">Cost</h4> <ul> <li>チームのベロシティ</li> <li>効率的な開発</li> </ul> <p>SP(ストーリーポイント)を評価に用いてはいけない、という定説はありますが、CSEチームでは部分的に評価に取りいれています。チームとして達成すべきSPを定義し、それに達しているか評価をしています。また余計な会議などが行われていないかもチェックしています。</p> <h4 id="Delivery">Delivery</h4> <ul> <li>マイルストーン</li> <li>優先度対応</li> </ul> <p>様々なマイルストーンを適切に守れているかを基準としています。開発や検証はもちろん、CSチームと連携してマニュアルサイトの修正などのマイルストーンも定義しています。<br/> また、課題によっては優先度を高く設定してあるものもあり、それが早くデプロイ出来たかという観点も入れています。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/0262677a8b6fb580169b5d223" alt="クライテリア" /></p> <p>また、長期的なクライテリアのチーム達成率を分析することによって、チームとしてどのような問題を抱えているのかを分析することも出来ます。例えば直近のチームの状態を見てみるとCostが安定していない傾向にあります。これはCSEサーバーメンバーに入れ替わりがあり、稼働が安定しない事が原因です。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/81c0780ece643eb0df6d4ae04" alt="チームのチャート" /></p> <h2 id="まとめ">まとめ</h2> <p>CSEサーバーチームではチームとして成長する事を意識しており、様々な話し合いのもとスクラムを改善しています。しかしながら、課題としてまだ以下のような点が残っています。</p> <ul> <li>組織の壁を超えたチームづくりが出来ていない</li> <li>高頻度でデプロイする仕組み作りがまだ出来てない</li> <li>1日以内で開発が終わるような規模まで課題を細かく分割出来ていない</li> </ul> <p>これらの課題を解決することにより、より良いスクラムを用いてユーザーにより早くバグ修正を届けられるチームを引き続き目指していきます。</p> <p><a href="https://www.i3-systems.com/new-graduates/">新卒採用</a><br/> <a href="https://www.i3-systems.com/careers/">キャリア採用</a></p> clomo-dev 新入社員が感じた4つのこと hatenablog://entry/6801883189062188592 2023-12-08T16:33:43+09:00 2023-12-11T11:58:46+09:00 2023年にアイキューブドシステムズに新卒で入社したIshizaka-Kといいます。 現在弊社では週一回の出社となっており、新卒研修も同様にリモートと出社のハイブリッドでした。今回は、こうしたリモート前提での新卒研修で気づいたことや、在宅と出社での違いを書いていきたいと思います。 記事を通して会社の雰囲気をお伝えできればと思います。 研修中の一日の流れ 在宅時 在宅では自由な時間が本当に多くて、のんびりと仕事できました。 ご飯を食べるついでに掃除できたり、仕事終わりでそのまま趣味の時間にはいれたり、仕事と家事や趣味を両立することができて働きやすかったです。 仕事に関しては集中力が落ちやすいので… <p>2023年にアイキューブドシステムズに新卒で入社した<a href="https://github.com/Ishizaka-K">Ishizaka-K</a>といいます。</p> <p>現在弊社では週一回の出社となっており、新卒研修も同様にリモートと出社のハイブリッドでした。今回は、こうしたリモート前提での新卒研修で気づいたことや、在宅と出社での違いを書いていきたいと思います。<br/> 記事を通して会社の雰囲気をお伝えできればと思います。</p> <h2 id="研修中の一日の流れ">研修中の一日の流れ</h2> <h3 id="在宅時">在宅時</h3> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/81c0780ece643eb0df6d4ae00" alt="在宅時円グラフ.png" /></p> <p>在宅では自由な時間が本当に多くて、のんびりと仕事できました。<br/> ご飯を食べるついでに掃除できたり、仕事終わりでそのまま趣味の時間にはいれたり、仕事と家事や趣味を両立することができて働きやすかったです。<br/> 仕事に関しては集中力が落ちやすいので、仕事の30分前に趣味のコーディングをして集中力を高めてから仕事にとりかかることで朝から集中して作業できました。また、家では誘惑が多かったり集中力が途切れたりするので、お昼のごはん休憩とは別に1時間程度休憩をはさむことがよくありました。チャット等で中抜けする旨を伝えることで休憩を入れられるので、疲れたときは休憩をはさみ業務中の作業効率を上げるようにしてました。 </p> <p>入社前は「人の目がない分、さぼったりしそうだな」と思っていたのですが、自分にとっては在宅が性に合っていたようで、むしろ楽しくなって長めに働いてしまうことのほうがよくありました。</p> <h3 id="出社時">出社時</h3> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/0262677a8b6fb580169b5d21e" alt="出社時円グラフ.png" /></p> <p>出社時はなんといってもコミュニケーションがとりやすかったです。<br/> 疑問や感じたことを上長にすぐ相談できたり、同期と話し合ったりできたので、悩んで手が止まるということがほぼ起こりませんでした。特に同期とは、出社したときに研修の進捗や勉強会の相談などいろいろ雑談できて、研修中の不安解消の大きな助けになりました。<br/> オフィスが天神という繁華街にあることもあり、お昼休憩のランチにはいろんなお店を回ったり、仕事後には同期との遊びやご飯に行ったりと出社時ならではの楽しみもありました。</p> <h2 id="研修の流れ">研修の流れ</h2> <p>研修は大まかに、全体研修→部門研修→配属後研修というような流れでした。<br/> 研修の詳細な内容やスケジュールといったところは下記の記事にて書いてあるので、そちらを参照いただけると幸いです。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftech.i3-systems.com%2Fentry%2F2023%2F04%2F11%2F132419" title="新卒社員がサーバーサイドに配属されるまでの話 - i Cubed Systems Engineering blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://tech.i3-systems.com/entry/2023/04/11/132419">tech.i3-systems.com</a></cite></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftech.i3-systems.com%2Fentry%2F2023%2F07%2F03%2F135756" title="モバイルに配属された新卒社員の研修と仕事内容 - i Cubed Systems Engineering blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://tech.i3-systems.com/entry/2023/07/03/135756">tech.i3-systems.com</a></cite></p> <h2 id="研修を通して感じたこと">研修を通して感じたこと</h2> <p>研修を通して感じたことは下の4つです。</p> <ul> <li>学習の楽しさ</li> <li>めちゃくちゃ自由</li> <li>解るまで判らない</li> <li>自分は何をするべきなのか?</li> </ul> <h3 id="学習の楽しさ">学習の楽しさ</h3> <p>研修中に何よりも感じたことが学習の楽しさです。<br/> 私はトライ&エラーでいろいろ試してみることが好きで、プログラミングはまさにそれを繰り返すことができるので楽しく研修を受けることができました。<br/> 会社においても、テックイベントについての情報を教えてくれたり、書籍の貸し出し・購入など、業務関係のみならず学習を奨励している雰囲気を感じました。社内で「こんなことやってます」と話すと、上長や先輩方にそれに付随する技術や知識について教えてもらえました。どんどん知っていけてスキルアップしている実感があり、学習がますます楽しくなりました。</p> <p>なかでも、とある勉強会でMDMを実際につくってみたことが印象に残ってます。<br/> MDMとはデバイスを管理する仕組みやツールのことで、勉強会ではAndroidとiOSのデバイスを管理できる簡易なシステムを作りました。<br/> この勉強会を通して基本的なMDMの構造や、プラットフォームによるMDMの違いを学ぶことができました。これから関わっていく技術について詳しく知ることができ、学習するごとにわくわくしたことを覚えてます。<br/> 今では個人的に趣味でMDMをやってみて勉強もしているのですが、そのときの楽しさが原動力になっているように感じます。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/81c0780ece643eb0df6d4ae01" alt="勉強" /></p> <h3 id="めちゃくちゃ自由">めちゃくちゃ自由</h3> <p>業務環境がめちゃくちゃ自由です。 自分は朝が弱く、早起きや決まった時間に起きるというのが苦手で、フレキシブルに働けるのが本当に助かってます。<br/> お昼寝で中抜けしたり、早く起きたから早めに始めたり、自由に働けるので良いコンディションで気持ちよく業務に臨めるので助かってます。</p> <p>また、timesという自由に呟けるチャットスペースがあるのですが、そこでは仕事の話から今日行くお昼の話まで役職の隔たりなく雑談できます。自分は上の役職の方と話すときは恐縮してしまって自分から話しかけたりできないので、こうしたチャットスペースは本当に助かりました。<br/> 何となくした呟きで上長から技術的な知識を教えてもらえてモチベーションが上がったり、オフィス周辺で開催してるイベント情報を教えてもらって遊びに行ったり、個人的にtimesはお気に入りの場所です。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/81c0780ece643eb0df6d4ae02" alt="MicrosoftTeamsChat" /></p> <h3 id="解るまで判らない">解るまで判らない</h3> <p>これは自分でアプリケーションを作成する研修で感じたことです。<br/> アプリケーションを作っていて、「何がわからないのかわからない」といったことが多くありました。それは資料に従って開発しているときにはあまり感じなかったことだったので、本当に困ったのを覚えてます。「何を質問すればいいのかわからない。しかしアプリはエラーを吐いていてどこかしら間違っていることは分かる。検索してみても有効性の高い情報は得られない。」といった感じでした。<br/> そのエラーの原因はクラスの引数を間違えているという単純なものでしたが、この問題の本質は使っているクラスや関数を理解できていないことだと感じました。</p> <p>これまではエラー文をコピペして検索して、同様の症状を扱った記事や資料を見て、対応策を真似ていました。それでうまくいっていたので、エラーについて理解できていないのに分かったつもりでいたのだなと痛感しました。自分でクラスやフローを図で書いてみて、整理して理解へ落とし込むことの重要性を感じることができました。</p> <p>エラーについてある程度理解できて、そこで初めて対応策や対処方法を判断することができるのだと学びました。</p> <h3 id="自分は何をするべきなのか">自分は何をするべきなのか?</h3> <p>研修が一通り終わり、他部署の同期と話す機会がありました。今どんなことをやってるかとか、これからどんなことをやっていきたいかといった他愛もない話をしたのですが、そのときに「自分は研修中、目先のことに集中しすぎてたな」と感じました。</p> <p>研修期間中はやることや作業内容が明確で、職場に慣れる・業務ができるようになるという明確な目標もありました。研修を通して職場の雰囲気にも慣れましたし、業務に必要な知識も得ることができたと思います。</p> <p>しかしそれでいいのかな?と感じました。<br/> 研修中は「指示された行動をとって、自身のスキルを上げること」といった自分の市場価値の向上を中心としてとらえていました。しかし実際の業務においては、当たり前ですが会社があって・お客様がいて・コストが決まっていて・チームで動く必要性があります。そのためには「指示された行動について考えて、会社の価値を上げること」といった会社の市場価値の向上を中心として、そのうえで自分は何をするべきなのかを考えなければならないと思います。</p> <p>目先の業務のみならず、会社において自分は何をするべきなのかといった俯瞰的な視点を持つ必要性を感じました。</p> <h2 id="まとめ">まとめ</h2> <p>今回は新卒の研修内容と、研修を受けた感想の話をしましたがいかがだったでしょうか。<br/> まだまだ未熟ですが、少しでも早く1人前になりメンバーに頼られる存在になりたいです。</p> <p>最後に、興味のある方はご応募をお待ちしております。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.i3-systems.com%2Fnew-graduates%2F" title="新卒採用|株式会社アイキューブドシステムズ" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.i3-systems.com/new-graduates/">www.i3-systems.com</a></cite></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.i3-systems.com%2Fcareers%2F" title="採用情報|株式会社アイキューブドシステムズ" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.i3-systems.com/careers/">www.i3-systems.com</a></cite></p> <p>外部の就活サイトでも弊社が載っておりますので、そちらもご覧いただけると幸いです。</p> Kent-i3 社内ハッカソンの成功を求めて【i Cubed Mini ShipIt!】 hatenablog://entry/6801883189059439759 2023-11-21T15:55:09+09:00 2023-12-15T20:41:09+09:00 i Cubed Mini ShipIt! を開催しました! サーバーサイド担当のMisaki-i3です。 アイキューブドシステムズの製品開発運用本部では、不定期に社内ハッカソンを開催しています。 『i Cubed Mini ShipIt!』というイベント名称はAtlassianのShipItをリスペクトしたものです。 2018年秋に第1回を開催し、2019年夏に第2回、2019年冬に第3回が行われました。 2020年以降はCOVID-19の流行により開催を断念。 そして2023年夏、2年半振りとなる i Cubed Mini ShipIt! が実現しました。 第4回の会場となったのは、今年春に… <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/M/MisakiShiote-i3/20231117/20231117093342.png" width="1200" height="630" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <h2 id="i-Cubed-Mini-ShipIt-を開催しました">i Cubed Mini ShipIt! を開催しました!</h2> <p>サーバーサイド担当のMisaki-i3です。<br/> アイキューブドシステムズの製品開発運用本部では、不定期に社内ハッカソンを開催しています。<br/> 『i Cubed Mini ShipIt!』というイベント名称は<a href="https://www.atlassian.com/ja/company/shipit">AtlassianのShipIt</a>をリスペクトしたものです。</p> <p>2018年秋に第1回を開催し、2019年夏に第2回、2019年冬に第3回が行われました。<br/> 2020年以降はCOVID-19の流行により開催を断念。<br/> そして2023年夏、2年半振りとなる i Cubed Mini ShipIt! が実現しました。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/0262677a8b6fb580169b5d212" alt="会場の様子" /></p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/0262677a8b6fb580169b5d214" alt="作業中の様子" /></p> <p>第4回の会場となったのは、今年春に生まれ変わったばかりのミーナ天神、その最上階にあるレンタルオフィス『The Company』です。<br/> 天神地下街直結で、弊社福岡オフィスからも歩いて数分の好立地。同じフロアにカフェのテナントも入っており、ランチ懇親会ではそちらのフードメニューが並びました。</p> <p>早速、イベントの内容の話に移りましょう。<br/> 今回は、これまでの3回とは大きく異なる特徴がいくつかありました。</p> <ul> <li>前回までは<strong>ほとんどが数年以上の経験者</strong>であったのに対し、今回は<strong>開発歴1〜2年のメンバーが大幅に増えている</strong></li> <li>総勢35名(うち5名はオンライン)という<strong>過去最多の参加者数</strong>であった</li> <li>前回までは個人参加が基本だったが、今回は運営によって分けられた<strong>チームでの参加</strong>だった</li> <li>発表準備を含む作業時間が<strong>過去最短の4時間</strong>だった</li> </ul> <p>前回からの3年近い期間に開発部の規模も大きくなっており、前回にはいなかったメンバーが多くいます。彼らのほとんどはハッカソンへの参加自体もはじめてのこと。<br/> 運営にとっても参加者にとっても手探りの部分が多いイベントとなりました。</p> <p>結果からいって、期待した効果が概ね発揮された1日になったと思います。<br/> 作業中の雰囲気やランチ懇親会の和やかさからは、イベントが多くの参加者に心地よい刺激と前向きな反省を与えたことを感じられました。<br/> かくいう私は開発歴1〜2年メンバーの一人で、初参加という立場だったのですが、いくつもの興味深い経験ができました。</p> <h2 id="社内ハッカソンの成功を求めて">社内ハッカソンの成功を求めて</h2> <p>多くのIT企業が社内ハッカソンを組織の成長の手段として評価しており、有名企業の技術ブログを探せば多くの関連記事を見つけられます。<br/> その一方で、短時間で成果物を生み出すという前提にハードルの高さを感じて躊躇している組織もあるのではないでしょうか。</p> <p>例えば、参加前日までの私はこのような不安を抱いていました。</p> <ul> <li>一定の経験を持つエンジニア以外は、「予想通り、何もできなかったね。分かっていた通り、もっと勉強しなきゃね」で終わってしまわないか?</li> <li>一日限りの「楽しかった」、「気分転換になった」で終わってしまわないか?</li> </ul> <p>この不安は的中しませんでした。ただし、それはイベントの方針や運用方式が適切に選択されていたおかげだと感じます。</p> <p>この記事では、社内ハッカソンだからこそ得られる経験や求められる意義、個人参加とチーム参加の違いなどを探り、組織のためのハッカソンの成功の鍵を見つけたいと思います。</p> <p>本イベントをふりかえるにあたって、イベントの運営メンバーや前回までの i Cubed Mini ShipIt! を経験しているメンバーに取材を行いました。<br/> 若手の立場である私のふりかえりを併せ、様々な視点から分析できるよい機会でした。<br/> 本イベントの進行順序もご紹介しますので、社内ハッカソンの開催方法が分からないという方のお役に立てると思います。</p> <h2 id="i-Cubed-Mini-ShipIt-進行詳細">i Cubed Mini ShipIt! 進行詳細</h2> <p>今回は予め課題決定までを済ませておき、開催当日は実作業から開始しました。</p> <table> <thead> <tr> <th> フェーズ </th> <th> 第4回 i Cubed Mini ShipIt! での内容 </th> </tr> </thead> <tbody> <tr> <td> 課題候補作成 </td> <td> ・社内から改善したい業務や作りたいツールの案を募り、課題候補とする<br>・今回は業務改善やプロダクトの改良に繋がる課題に限った<br />・0→1ではない課題も候補に上がった(自社プロダクトのボトルネック改善等) </td> </tr> <tr> <td> チーム分け </td> <td> ・社員番号順のメンバーを8チームに剰余で振り分け(1,9,17,24番目がチームA)<br>・チーム内のメンバーのキャリアを偏らせず、スキルや担当分野はランダムになることを期待 </td> </tr> <tr> <td> 課題決定 </td> <td> ・課題候補の中から各チームでどの課題を選択するか当日までに決定する<br>・必要であれば課題の当事者にヒアリングを行う </td> </tr> <tr> <td> 実作業 </td> <td> ・決定した課題に取り組む<br>・作業時間は4時間 (i Cubed Mini ShipIt! としては史上最短) </td> </tr> <tr> <td> 懇親会 </td> <td> ・ランチ懇親会 </td> </tr> <tr> <td> 成果物発表 </td> <td> ・成果物の発表<br>・各チーム5分 </td> </tr> <tr> <td> 投票・総括 </td> <td> ・参加者全員による投票を行い、順位を決定<br>・運営の代表がイベントの総括を行った </td> </tr> </tbody> </table> <p>もちろんこれは一例であり、課題の決定を当日の作業に含む方式や、実作業の途中で中間発表を挟む方式など、開催意図に合わせて様々なアレンジが考えられます。</p> <p>実作業の時間が4時間という設定は、参加者が「短すぎる」と感じる時間でした。この点に関する参加者からのフィードバックは後ほど紹介しますので、ご参考になさってください。<br/> 過去の開催では、第1回が14時間(2日間)、第2回が6時間、第3回が7.5時間の設定でした。</p> <h2 id="i-Cubed-Mini-ShipIt-で運営が意図したこと期待したこと">i Cubed Mini ShipIt! で運営が意図したこと、期待したこと</h2> <p>イベントの開催やスケジュール設定に関して運営の意図を伺いました。<br/> ハッカソンという形式に共通することだけでなく、マネジメントの観点で参加者の様子から何を受け取ろうとしていたのかも聞けました。</p> <h3 id="なぜハッカソンなのか">なぜハッカソンなのか</h3> <ul> <li><strong>多様な能力と自己決定力</strong>が問われる <ul> <li>解決したい課題の選択、要件定義から実装、プレゼン準備まで</li> <li>時間以外の<u>制限が無さすぎる</u>中で、全てを自律的に進行しようとする能力</li> </ul> </li> <li>自然と高い集中力を発揮できる <ul> <li>時間にゆとりがない状況</li> <li>不完全でも発表の時が来てしまう<u>強い締め切り感</u></li> </ul> </li> <li>定められた時間内でゴールへ辿り着くための<strong>計画力と対応力</strong>があらわになる <ul> <li>時間配分をどのように決定していくか</li> <li>締め切りの延長ができない中、エラーやトラブルにどう対処するか</li> </ul> </li> </ul> <h3 id="フルリモート中は開催が無かったがオフライン開催にこだわりがある">(フルリモート中は開催が無かったが)オフライン開催にこだわりがある?</h3> <ul> <li>そもそも、2020年時点では数十名規模のオンラインミーティングという発想もなければ、ツールもなかった……</li> <li>作業場所をともにすることで一体感を得られる <ul> <li>他の人・チームの様子が目に入ること、聞こえてくること</li> <li><u>競争心やプレッシャー</u>が、モチベーションと集中力に寄与</li> </ul> </li> <li>各々の成果物という目標をともにすることから、<strong>明確な共同体の意識</strong>を覚える <ul> <li>普段は仕事内容もスケジュールも異なっており、オフラインイベントほど意識しにくい</li> </ul> </li> <li>懇親会ができる</li> </ul> <p>オンライン参加は十分に可能であることを補足しておきます。オンライン開催のハッカソンも存在します。<br/> 今回のイベントでも、成果物に対する投票ではオンラインのチームが最も得票しました。<br/> 一方で、会場側の空気は感じにくく、お祭り感は少なかったとの声がオンライン参加者からありました。</p> <h3 id="チームメンバーの割り振りの意図">チームメンバーの割り振りの意図</h3> <ul> <li>役割を考慮したチームでないから発生する<strong>挑戦とキャッチアップ</strong> <ul> <li>各人が<u>『いつもの役割』に収まることなく</u>、チームに不足している役割を見つけてキャッチアップしていく</li> <li>普段なら触れようとも考えない領域にチャレンジできる機会</li> </ul> </li> <li>普段接点の少ないエンジニア同士が<strong>協力</strong>する体験の機会に <ul> <li>互いの<u>スキル交換</u></li> <li>経験の多いエンジニアと経験の浅いエンジニアの相互刺激</li> </ul> </li> <li>新しい<strong>個性の発見</strong> <ul> <li>誰がオーナーシップを持つのか?</li> <li>共同作業の中でどのような振る舞いを見せるか?</li> </ul> </li> </ul> <p>(個人参加とチーム参加の違いについては次章で扱います!)</p> <h3 id="イベントや参加者に何を期待していた">イベントや参加者に何を期待していた?</h3> <ul> <li>メンバーの<strong>自主性・個性</strong>の発見 <ul> <li>どのように成果物に貢献しようとしたか > 良い成果物ができたか</li> <li>役割を果たすため工夫や努力を試みたか > 役割を果たせたか</li> </ul> </li> <li>メンバー同士のコミュニケーションと相互理解の促進</li> <li>普段の業務や自学の日々で担当領域に定まりがちな視野を、ハッカソンの参加によってストレッチしてもらう</li> </ul> <hr /> <p>以上のように、様々な角度から組織力の分析や教育のための期待が込められていました。<br/> ハッカソンの独特なルールと競技性が、普段の業務や勉強会とは異なる観点を与えていることも分かります。<br/> これは私の感想になりますが、このようにまとめてみて初めて、ハッカソンの難しさとやりがいは「時間制限があること」ではなく「時間以外の制限がないこと」にあるのだと気付かされました。</p> <h2 id="チーム参加ならではの特徴優位性">チーム参加ならではの特徴・優位性</h2> <p>私は個人参加を経験したことがないので、前回までの i Cubed Mini ShipIt! に参加した経験のあるメンバーにも取材を行いました。指導者寄りの視点も多く伺えています! 特に、若手社員に参加した意義を感じてもらいたいという配慮はどのメンバーにも共通しておりました。教育の観点は項を分けてご紹介しています。</p> <h3 id="個人参加とチーム参加の対比">個人参加とチーム参加の対比</h3> <ul> <li><span style="color:#1DAAAA">個人では、</span>頭の中の不完全な設計から直接実装に入ることができた<br><span style="color:#AB511D">チームでは、</span>実装の前に設計を共有する必要があった <ul> <li>時間の制限もあり、素早く適切にアイデアや設計を共有し合う努力が重要</li> <li>認識が共有できたことを確認するフェーズを経て、ようやく実装に入れる</li> </ul> </li> <li><span style="color:#1DAAAA">個人では、</span>設計・実装・発表準備まで独力でやりきらなければならない<br><span style="color:#AB511D">チームでは、</span>自分の不得意分野に関してはチームメンバーに任せたりサポートを頼んだりできる <ul> <li>もちろん、不得意分野を強いられる経験も面白いものである</li> </ul> </li> <li><span style="color:#1DAAAA">個人では、</span>一人の知識や先入観の範囲を出ることが難しい<br><span style="color:#AB511D">チームでは、</span>自分の思いもよらないこと、考慮できていないことにメンバーが気付いてくれた</li> <li><span style="color:#1DAAAA">個人では、</span>自身のスキルと興味のままに技術的な挑戦を取り入れられた<br><span style="color:#AB511D">チームでは、</span>課題解決の方法をチームが遂行できる複雑度に調整することに重きが置かれた <ul> <li>技術的な挑戦の優先度を下げ、作業時間に見合うまで要件を間引いていった</li> </ul> </li> <li><span style="color:#1DAAAA">個人では、</span>競技性や技術的な挑戦の楽しみが大きかった<br><span style="color:#AB511D">チームでは、</span>アイデアを出し合い協調する楽しさが大きかった <ul> <li>コミュニケーション・協力・教育に意義を求められる</li> </ul> </li> <li><span style="color:#1DAAAA">個人では、</span>みな黙々と作業に集中していて静かだった<br><span style="color:#AB511D">チームでは、</span>会話が盛んで終始賑やかな雰囲気だった <ul> <li>他チームが近すぎると自チームの議論の障害になることも</li> </ul> </li> </ul> <h3 id="チーム参加と教育">チーム参加と教育</h3> <ul> <li>若手社員の教育になるようなテーマ、体験をさせられた <ul> <li>プロジェクトの進行を経験できる</li> <li>要件定義を、他メンバーの補助付きで担当してもらう</li> </ul> </li> <li>教育を念頭においた進行の工夫を行った <ul> <li>研修段階の新入社員にも楽しいと思ってもらうため、配属予定の分野に絡む課題を選択した</li> <li>モデル設計を進める様子や考え方を共有する</li> </ul> </li> <li>中堅層以上のエンジニアも課題の進行から多くの反省点や改善点を見出せた</li> <li>若手層のエンジニアも、自分より日の浅いエンジニアのサポートを意識させられた</li> </ul> <p>経験の長いメンバーが自然と教育を意識した行動を取ったのは確かですが、終始経験の浅いメンバーの面倒を見つつ成長を促す……とはいきません。今回は作業時間が極めて短時間であったこともあり、経験者もかつてない切迫感を覚えていたそうです。<br/> 「当日に思いつきで発した提案が成果物の完成度を落としちゃった」と反省するベテランもいました。<br/> 冷静にチームをリードしているように見えた中堅・ベテラン層も、しっかり慌てていたのだなと親近感が湧きました!<br/> ハッカソンの緊張感や焦燥感はキャリアを問わないようです。キャリアによる熱量の格差が生まれないことは強い魅力ですね。</p> <h2 id="反省と今後">反省と今後</h2> <p>i Cubed Mini ShipIt! には、改善されるべき点もありました。最後の章に進む前に、しっかりふりかえっておこうと思います。</p> <h3 id="適切な時間制限">適切な時間制限</h3> <p>参加者への取材で特に聞かれたのが、時間の短さに起因する問題です。<br/> 短時間であるおかげで普段とは質の異なる集中力が発揮でき、時間への挑戦を強く意識できる面はあるものの、今回はそれを差し引いても無視できない不完全燃焼感があるようでした。</p> <ul> <li>成果物の完成に到達できず、フラストレーションが残った <ul> <li>エンジニアとして、最低ラインであっても『完成』と言える成果物を用意したい気持ちが強い</li> <li>前回までは時間があったので、一人でもある程度やりきることを目指せた</li> </ul> </li> <li>課題の解決方法の選択や課題そのものがインパクトの弱い内容に留まってしまう <ul> <li>時間内にできそうなシンプルな課題やコストの低い課題解決方法を選択する</li> <li>大きそうな課題もあるが、そもそも実装まで辿り着くことを期待されていない</li> </ul> </li> <li>最低限の要件を満たすことも危うく感じられ、挑戦の要素を取り入れることには踏み出せなかった <ul> <li>あるチームでは、同時進行で2通りの課題解決方法を実践することに挑戦したが、とても間に合わなかった</li> </ul> </li> </ul> <p>参加者がそれぞれのベストを尽くしたであろうことは各チームの発表から感じられましたが、動く成果物を用意できたチームが僅かであったことは事実です。<br/> だから次はもっと時間を取りましょう――で終わってはもったいないので、他にできる工夫がないか探ってみます。</p> <h3 id="短い作業時間でも課題を達成してもらうための工夫">短い作業時間でも課題を達成してもらうための工夫</h3> <p>例えば、経験の浅いメンバーが多いという条件が明らかなとき、課題候補の収集フェーズからある程度運営が手を加えることはできなかったでしょうか。</p> <p>運営や経験のあるメンバーを中心に課題を精査して厳選したり、要件の調整をしたり、大きく漠然とした課題の分割をしたりします。<br/> 各チームが課題を選択する際の判断材料を増やせますし、漠然としていたために早々に検討対象から外されてしまうような課題にも光が当たり、よりチームに合った課題の選択を実現できるかもしれません。</p> <p>あるいは、各チームが課題を選択してから当日までの期間に、チーム内での共通認識の作成を推奨するのも良いかもしれません。</p> <p>課題の認識・成果物の最低ライン・課題に関するアイデアを共有してもらえば、当日は共通認識という土台に支えられ、スムーズに要件や挑戦要素の絞り込みに入れます。<br/> 設計を急ぐ経験者についていくだけで必死だった若手も、土台があれば話に遅れにくくなります。そうなると、思いついた工夫やひらめきを表明しやすくなることも期待できそうです。</p> <p>私が思いついたのはこの2つです。きっと複数人で知恵を絞れば、短時間開催のデメリットを劇的に解消するような工夫も生まれうるでしょう。<br/> そのような工夫を生み出すにも、ハッカソンの運営、あるいは参加の経験は欠かせないと思います。</p> <p>経験とフィードバックを受け止め、次に活かせる資産に昇華することができれば、少なくともその点において『成功』を得られたと言ってよいはずです。</p> <h3 id="イベントの企画準備">イベントの企画・準備</h3> <p>「もうちょっと事前準備をしっかりしておけばよかった〜!」とは、運営チームの一人の談です。</p> <p>いち参加者の私としては、イベントはごくごくスムーズに進行しているように見えたし、トラブルもほとんどなかった(※わずかにはあった)と感じていたので、反省点として一番に挙げられたのが事前準備であったのは意外でした。</p> <p>具体的に、何を「しっかり」しておけなかったのでしょう。</p> <ul> <li>ハッカソンの必要条件を満たすだけの企画に留まった</li> <li>会場選定の際に候補会場の下見を行えなかった</li> <li>ひとつひとつの決定を急がねばならず、検討を深められなかった</li> </ul> <p>イベントにより高い価値を与えたり、様々なリスクを最小化するための準備のことのようです。</p> <p>実は本イベントは数週間前に開催が決定したものであったため、開催準備も前回までより少ない時間で進められたそうです。<br/> プラスアルファの企画を用意するには、時間の不足が過ぎたのでしょう。</p> <p>企画に関しては、単に「楽しい企画を足したかった」というものではなく、価値の最大化のためにできる企画がないかを十分に検討したかったというニュアンスです。<br/> 価値ある要素を足したからといって、そのイベント全体の価値が足し算で高まるわけではないので注意が必要です。</p> <p>角度を変えれば、開催条件を絞りさえすれば手早く用意できたとも言えます。<br/> 手早さには過去3回の開催経験がものをいったことでしょう。<br/> イベントの進め方だけでなく、イベントの準備の進め方も、前回までの様式を踏襲するだけでいいのです。チーム制という新様式の用意に時間を割くことができます。</p> <p>様々な会場を利用したことがあれば、下見を省ける候補になるでしょうし、過去の会場選定時の資料が存在するだけでも0から探すより効率的なのは明らかです。<br/> 社内ハッカソンに限らず、様々なイベントの開催実績を積み重ねていけば、急に時間を与えられても「このスケジュールならあれができるかも」と当たりをつけて、余裕を持って開催準備に取り掛かれるでしょう。</p> <p>過去の開催経験は、それだけで資産になるようです。</p> <h2 id="社内ハッカソンの成功の鍵">社内ハッカソンの成功の鍵</h2> <p>ここまで、様々な角度から社内ハッカソンをふりかえってきました。<br/> i Cubed Mini ShipIt! への参加、ブログ執筆のための取材、ブログの執筆を通して、「成功の鍵はこれだ!」と断言できるものが見つかりました。</p> <p><br></p> <p><strong>「ふりかえりが大事!!」</strong></p> <p><br></p> <p>イベントによって私たちが得た経験や成長に、私たちは気付けていない可能性があります!</p> <p>私が今回の経験の価値を心から実感できたのは、イベントの当日ではなく、ブログ執筆のための取材中でした。<br/> 作業直後に行われた懇親会での雑談も、イベントの締めの総括もふりかえりの役割を担っていましたし、取材前にもハッカソンの意義や役割を調べて知識を深めたつもりでいました。<br/> しかし、それらから価値を思い知るには、少し没入度が足りなかったのでしょう。</p> <p>『取材』という、イベントのふりかえりをメインテーマにした時間を取ることが必要だったと考えます。<br/> 同じ場にいた者同士で経験を共有し、考察を交換しあったとき、私は「これは私が経験したことだ!」と実感や重みを感じることができたのです。<br/> ここだけ見ると、少々間抜けな感想……ですが、似たような経験のあるエンジニアはいるのではないでしょうか?</p> <p>また、時間を取ったのが開催直後でなかったことも、ふりかえりの密度の高さに良い影響を与えていそうです。<br/> 確信はないものの、通常業務のリズムに帰って記憶も新鮮でなくなってきた頃が、冷静に分析するのに適している時期かもしれません。</p> <p>改めて――。<br/> 組織が経験のないイベント開催に二の足を踏む主な理由は「うちのチームでも効果があるの?」という点かと思います。<br/> 私にはそれに答えられるだけの経験がありませんが、少なくとも「効果があるかどうかを確かめた経験」は組織の資産になると考えています。</p> <p>もしイベントの中で効果を感じられなくても、参加者に達成感や満足感を与えられなくても、必ず反省点は得られるはずです。<br/> それは組織の弱点を示唆する重要な情報である可能性もあります。</p> <p>社内ハッカソンの成功の要件を1つに絞るなら、得られた反省を手がかりにして、組織に必要な改善や挑戦を発見することだと私は考えます。<br/> 成功の鍵は適切なふりかえりの実施です。</p> <p>もし当日に失敗の空気が漂ったら……想像するだけでおそろしいですが、それはむしろ、たくさんの改善と挑戦が見つかる、大成功の予兆なのです。</p> <hr /> <h2 id="We-Are-Hiring">We Are Hiring!</h2> <p>挑戦を楽しもう!</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.i3-systems.com%2Fnew-graduates%2F" title="新卒採用|株式会社アイキューブドシステムズ" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.i3-systems.com/new-graduates/">www.i3-systems.com</a></cite> <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.i3-systems.com%2Fcareers%2F" title="採用情報|株式会社アイキューブドシステムズ" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.i3-systems.com/careers/">www.i3-systems.com</a></cite></p> MisakiShiote-i3 CSEサーバーチームについて hatenablog://entry/820878482941261906 2023-11-17T16:33:28+09:00 2023-11-17T16:33:28+09:00 はじめに こんにちは!アイキューブドシステムズでCLOMOのサーバーサイドを担当しているyuriKIM-i3です。この記事では私が所属しているCSEサーバーチームではどのようなことをやっているかついてご紹介します。 他のCSEチームについては以下の記事を参考にしてください! tech.i3-systems.com CSEサーバーチームとは? CSEは「CLOMO Sustained Engineering」の略で弊社のサービスCLOMOのバグ修正や改善を担当しています。 CSEサーバーチームではRuby on Railsをメインにして、バックエンドに関する改修をしています。 やっていること C… <h2 id="はじめに">はじめに</h2> <p>こんにちは!アイキューブドシステムズでCLOMOのサーバーサイドを担当している<a href="https://github.com/yuriKIM-i3">yuriKIM-i3</a>です。この記事では私が所属しているCSEサーバーチームではどのようなことをやっているかついてご紹介します。 他のCSEチームについては以下の記事を参考にしてください! <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftech.i3-systems.com%2Fentry%2F2023%2F06%2F26%2F114358" title="CSE iOSチームの紹介 - i Cubed Systems Engineering blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://tech.i3-systems.com/entry/2023/06/26/114358">tech.i3-systems.com</a></cite></p> <h2 id="CSEサーバーチームとは">CSEサーバーチームとは?</h2> <p>CSEは「CLOMO Sustained Engineering」の略で弊社のサービス<a href="https://www.i3-systems.com/">CLOMO</a>のバグ修正や改善を担当しています。 CSEサーバーチームではRuby on Railsをメインにして、バックエンドに関する改修をしています。</p> <h2 id="やっていること">やっていること</h2> <h3 id="CLOMOの不具合対応や改善">CLOMOの不具合対応や改善</h3> <p>前述の通り、CLOMOの不具合対応や改善はCSEサーバーチームのメインの仕事です。その中でもお客様にとって早く解決してほしい内容をピックアップし優先的に実施することを目標にしています。 そしてチームでは主にRuby on Railsを扱っていますが、不具合や改善の内容によっては<a href="https://www.mongodb.com/ja-jp">MongoDB</a>や<a href="https://ja.vuejs.org/">Vue.js</a>を触ることもあります。</p> <h3 id="お客様からのお問い合わせ対応">お客様からのお問い合わせ対応</h3> <p>弊社ではお客様からのお問い合わせは主にカスタマーサクセス部で対応をしています。ですが、内容によっては技術的な調査が必要な場合はCSEチームにエスカレーション調査を依頼します。エスカレーション業務の具体的な内容については下の記事をご参考にしてください!(その記事を作成した当時はプラットフォーム運用部の業務でしたが2023年11月現在、私たちCSEチームが担当しています。) <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftech.i3-systems.com%2Fentry%2F2021%2F06%2F25%2F104219" title="CLOMOサービスのエスカレーション業務についてのご紹介 - i Cubed Systems Engineering blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://tech.i3-systems.com/entry/2021/06/25/104219">tech.i3-systems.com</a></cite></p> <h3 id="コードレビュー">コードレビュー</h3> <p>改修したコードに対してチームのみんながレビューをします。 コードレビューを通して作成したコードが実際にきちんと動作しているか、こういう風に書いたらもっと良いコードになるのではないかなど様々な工夫を重ねてコードを完成していきます。 私の前職でコードレビューは1人の先輩しかしていなかったです。なので、今のようにたくさんの人からレビューを頂くことは様々な意見を聞き成長にもつながっていく感じがします。</p> <h3 id="スプリント振り返り">スプリント振り返り</h3> <p>CSEサーバーチームでは2週間単位のスプリントで開発を進めています。1スプリントが終わったら、チーム内でそのスプリントで思った「うまく行った点、改善すべき点」について話し合います。うまくいった点には助けてもらったことを表彰したり、やって良かったことはこれからも続けていきましょう!などを作成し、改善すべき点には自身で経験した失敗談や注意事項を共有し再発防止に努めています。 私は改善すべき点に仕事を進めている中で悩んでいたことを挙げたことがありました。その時、チーム員から励ましの言葉を沢山頂きました。今のような3人以上のチームで働くことは初めてだったので、悩み事について皆んなから意見を聞いたのは良い経験でした。</p> <h2 id="最後に">最後に</h2> <p>以上でCSEサーバーチームについての紹介でした。この記事を読んで「私も一緒にお仕事したい!」と思ったら、ぜひ下記のリンクでご応募してください!</p> <ul> <li><a href="https://www.i3-systems.com/new-graduates/">新卒採用</a></li> <li><a href="https://www.i3-systems.com/careers/">キャリア採用</a></li> </ul> yuri-i3 Kaigi on Rails 2023 に参加してブース出展をした思い出と反省 hatenablog://entry/6801883189054597266 2023-10-31T15:35:49+09:00 2023-10-31T15:35:49+09:00 株式会社アイキューブドシステムズは、Kaigi on Rails 2023 にゴールドスポンサーとして協賛し、現地でMDM体験ブースを出し、2日間盛り上げさせていただきました。この記事では会社としてKaigi on Rails 2023 にどのような思いで参加して、どのような取り組みをおこなってきたかを中心に共有できればと思います。 <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/0262677a8b6fb580169b5d217" alt="" /></p> <p>こんにちは、サーバーサイドエンジニアの <a href="https://github.com/YusukeIwaki">@YusukeIwaki</a> です。 個人開発活動の延長で<a href="https://speakerdeck.com/yusukeiwaki/kaigionrails2023pub">登壇</a>しつつ、株式会社アイキューブドシステムズの会社として、Kaigi on Rails 2023 にゴールドスポンサーとして協賛し、現地でMDM<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup> 体験ブースを出し、2日間盛り上げさせていただきました。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/0262677a8b6fb580169b5d21a" alt="" /></p> <p>エンジニアの登壇については、 <a href="https://yusukeiwaki.hatenablog.com/entry/2023/10/30/Kaigi_on_Rails_2023__retrospect">個人ブログで何かを書いている</a>ので、そちらに任せるとして、この記事では会社としてKaigi on Rails 2023 にどのような思いで参加して、どのような取り組みをおこなってきたかを中心に共有できればと思います。</p> <h2 id="エンジニアが主体でブース出展することを決めた">エンジニアが主体でブース出展することを決めた</h2> <p>そもそも協賛するだけではなく、なぜブース出展をしたいと思ったか、から書いていきます。</p> <h3 id="表向きの理由は人材採用">表向きの理由は&quot;人材採用&quot;</h3> <p>我々の会社は、実は10年以上もRails一筋でMDMサーバーを開発し続けています。しかしながら、あまりそこを採用観点で有利にはアピールできていません。</p> <p>10年以上もRailsを使っていることは、現実的にはいわゆる「技術的な負債」も多くありますので、イケイケなベンチャー企業でサービスを作っていくのとは根本的に異なることをやらないといけません。分かる人にはわかると思いますが、そんな事情はほぼほぼ採用関係者には伝わりません。</p> <p>Kaigi on Railsのように、Railsにゆかりのあるエンジニアだけが全国から集まるカンファレンスは、我々のような複雑で深みのあるサービスを知ってもらうには格好の場で、そこでプレゼンスを向上することができれば、人材採用観点では確実にプラスになります。</p> <p>また、個人的に2年前、去年、とKaigi on Railsに参加して、志の高いプログラミングスクールの卒業生・卒業予定の方々も多く参加されていることも事前情報としては知っていました。この層の方々にはぜひうちの会社を知ってもらいたい、そんな思いでブースを出そうと決めたのでした。</p> <p>・・・ただ、これは実は上司を説得するための理由です(笑)</p> <h3 id="真の理由はお祭り作り">真の理由は&quot;お祭り作り&quot;</h3> <p>Kaigi on Railsは今年で3年目で、東京での現地開催は今年が初めて。RubyKaigiなどと比較するとまだ歴史は浅く、「Kaigi on Railsといえばコレ」のような"型"がまだない、言い換えると自分たちで"型"を作り上げていくことができる貴重なフェーズにあるカンファレンスでした。</p> <p>昨年のKaigi on Rails 2022にオンラインブースに参加していた際に感じた雰囲気として、なんとなく不完全燃焼感が漂っており、ここは来年2023現地開催すると絶対楽しいことができるぞ、という謎の確信を持っていました(笑)</p> <p>また、アイキューブドシステムズは福岡に本社のある会社のため、エンジニアメンバーの多くは福岡に住んでいます。そのため、東京開催のカンファレンスでお祭りを作る側になる、ということはそれだけで(若手エンジニアにとっては特に)貴重な経験になります。</p> <p>書き出すと次々溢れ出す思いが止まらないくらい、とにかくKaigi on Rails 2023を、エンジニアである我々が盛り上げないといけないという使命感があり、ブースを出すことにしたのでした。</p> <p>このように直感半分で行動しちゃった面もありますが、結果的に大きくは外れてなかったと思います。</p> <h2 id="基本的な準備">基本的な準備</h2> <p>弊社の開発メンバーがこれまでブースを出展した経験はほとんどなく、社内にノウハウはありませんでした。RubyKaigiやDroidKaigiに参加したメンバーで集まって「何があれば盛り上がりそうか」「何が不可欠か」など持ち寄るところからのスタートでした。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/0262677a8b6fb580169b5d21b" alt="" /></p> <ul> <li>お菓子で釣りたくないよね <ul> <li>でも製品説明ばっかりやってて楽しいブースってあった?</li> </ul> </li> <li>Tシャツとかノベルティを充実させたいよね <ul> <li>でもTシャツもらったの、着る? 置いてるだけで着てなくない?</li> </ul> </li> </ul> <p>などなど、右往左往するところから始まりましたが、最終的には非常にオーソドックスなところに着地し、下記のものを用意してブース出展に臨みました。</p> <ul> <li>来訪者に配るもの <ul> <li>チラシ</li> <li>シール</li> <li>ノベルティ3点(ケース、水筒、モバイルバッテリー)</li> </ul> </li> <li>ブースのデザインや印象づけに必要なもの <ul> <li>スタッフが着るポロシャツ</li> <li>ブースの背景の幕</li> <li>テーブルクロス</li> </ul> </li> </ul> <h2 id="お祭りアイテム-フラッシュ暗算アプリ">お祭りアイテム: フラッシュ暗算アプリ</h2> <p>ブースを出展しても、ノベルティを並べて淡々とCLOMO MDMの製品説明をするのでは、お祭りとして盛り上がるはずはありません。盛り上げるための"必殺アイテム"を用意する必要があります。</p> <p>とはいえ、初めてのブース出展ということもあってそこに大量の予算💰を投じることは難しかったので、自分たちで"必殺アイテム"を作ることにしました。</p> <p>MDMの機能性(遠隔インストール、遠隔設定、専用端末化など)がほどほどにアピールできて、なんか人が寄ってくるもの、・・・そう、 <strong>クイズ</strong> です。</p> <p>ブース企画のメンバーからは既成のクイズアプリを使う提案が出てきていたものの、これではメンバーがお祭りを作る感触に乏しいと感じ、却下。自分たちの手でクイズのアプリを作ることにしました。</p> <p>たまたま新人教育目的で<a href="https://play.google.com/store/apps/details?id=com.okudate.flashapp">フラッシュ暗算のアプリ</a>を作っていたものがあったので、それを魔改造してMDMの機能とアピールができる機能性を持たせることにしました。</p> <table> <thead> <tr> <th style="text-align:right;"> </th> <th> 改造前 </th> <th> 改造後 </th> </tr> </thead> <tbody> <tr> <td style="text-align:right;"> <strong>答えの入力</strong> </td> <td> キーボードで入力 </td> <td> 音声入力できるようにした。(ブースの前で誰かが答えを叫んでいたら、別の誰かが気になって寄ってくるだろう作戦w) </td> </tr> <tr> <td style="text-align:right;"> <strong>次の問題へ進む操作</strong> </td> <td> ボタンで「次に進む」「もう一度トライ」いずれかを選択 </td> <td> 自動で1回目は再トライ、2回目は次の問題に遷移するようにした(デジタルサイネージ・専用端末っぽさを醸し出すため) </td> </tr> <tr> <td style="text-align:right;"> <strong>設定値の変更</strong> </td> <td> 設定画面でポチポチ </td> <td> Managed Configuration に対応してMDMから設定値を書き換えられるようにした(デバイス無操作で設定値を書き換えることができる機能性のデモのため) </td> </tr> </tbody> </table> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/0262677a8b6fb580169b5d215" alt="" /></p> <p>若手エンジニアの勉強目的でもちょうど良く一石二鳥・・・・と私は思っていたものの、若手にとっては少し難しかったのか進捗が思わしくなく、本番の2週間前に私が突貫で仕上げることとなりました。ここはお祭りを自らの手で作っている感をみんなが得るためにも、もっと計画的に作って仕上げるべきだったと反省しています。</p> <p>とはいえで、全然想像もしていなかったこととして、フラッシュ暗算(そろばん)が得意な方が複数名いらっしゃって、<strong>3桁の足し算をサクサクと正解されている姿</strong>は本当にカッコよかった。めちゃくちゃ刺激になりました。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/0262677a8b6fb580169b5d218" alt="" /></p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/0262677a8b6fb580169b5d219" alt="" /></p> <h2 id="ブースで説明する内容は基本アドリブで">ブースで説明する内容は、基本アドリブで</h2> <p>初めてのブース出展なので、基本的な説明シナリオを用意しよう、という動きも当初はありました。ただ、あえて最後まで確定させずに当日を迎えました。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/0262677a8b6fb580169b5d21c" alt="" /></p> <p>エンジニア相手のブースの説明は営業活動とは異なり、多少たどたどしくても説明が下手でも、それをフォローする雰囲気がそこにあれば逆にチームワークあるなーと感じ取ってもらてプラスになります。</p> <p>また、ブース来訪者が何を説明したら楽しむか感じ取り、臨機応変に説明内容を切り替えるという能力も、普段の開発ではほとんど使わないので、いい機会になると考えました。</p> <p>・・・というのを本当に説明なく本番迎えたので、私以外のブースメンバーにとってはただただ不安で自信を失うだけになってしまったかもしれません...。せめて「アドリブで行くよ!頑張ろう!」くらいの宣言はしておくべきでした。反省。</p> <p>ただ、アドリブである程度いくという方針自体はそんなに間違っていなかったかなと思います。</p> <h2 id="さああとは楽しむぞ">さあ、あとは楽しむぞ!</h2> <p>準備は頑張ったので、あとはKaigi on Railsの現地で、参加者の皆さまと一緒に楽しみ、場を盛り上げるのみです。</p> <p>1日目には(福岡には無い)成城石井のデザートを、2日目にはローソンのフルーツをみんなで食べたりもしながら、協力してやりきりました。</p> <p>正直なところ、「フラッシュ暗算、思ったより地味だったな・・・」、というのが最大の反省としてあります(苦笑)</p> <p>ただ、ブースを訪れてくれた方々にMDMの世界を知ってもらったり、我々がRailsを使っている理由を説明する側としても再認識するなど、お互いにとって"地味な刺激"にはなったように感じています。</p> <h2 id="みんなありがとうまた来年">みんなありがとう、また来年!</h2> <p>今回、初めてのブース出展としては、場を盛り上げる一員として頑張れたとブース企画メンバー全員が感じでいるでしょうし、今回の取り組みは本当に成功に終わりました。</p> <p>また来年もぜひ機会があればKaigi on Rails 2024で出展をして場を盛り上げる役に立ちたいと考えています。</p> <p>Kaigi on Rails 2023の運営の皆さま・参加された皆さまには本当にお世話になりました。どうもありがとうございました。また来年もどうぞよろしくお願いいたします。</p> <h2 id="We-are-hiring">We are hiring!</h2> <p>私たちは、Ruby on Railsを活用しながら、CLOMO MDMの製品開発を通じて共に成長していける仲間を募集しています。</p> <p>Kaigi on Railsをきっかけに、ちょっと話を聞いてみたいなと思った方がもしいましたら、専用のカジュアル面談フォームを用意しましたのでぜひこちらからお申し込みください。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fherp.careers%2Fv1%2Fi3systems%2Fa4PBXIh36z87" title="【A001】Kaigi on Rails 参加者用: サーバーサイドエンジニア向けカジュアル面談フォーム - 株式会社アイキューブドシステムズ" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://herp.careers/v1/i3systems/a4PBXIh36z87">herp.careers</a></cite></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.i3-systems.com%2Fcareers%2F" title="採用情報|株式会社アイキューブドシステムズ" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.i3-systems.com/careers/">www.i3-systems.com</a></cite></p> <div class="footnotes"> <hr/> <ol> <li id="fn:1"> Mobile Device Management(モバイルデバイス管理)の略です。株式会社アイキューブドシステムズは、<a href="https://www.i3-systems.com/clomo">CLOMO MDM</a>というMDMのサービスを提供しています。<a href="#fnref:1" rev="footnote">&#8617;</a></li> </ol> </div> clomo-dev 品質とは誰かにとっての価値である hatenablog://entry/820878482972660953 2023-10-23T08:41:16+09:00 2023-10-23T08:41:16+09:00 はじめまして、アイキューブドシステムズにおける CLOMO の製品検証を担う部門、QA を担当している林田です。 私が QA に配属されて早2年半が経ちました。まだまだ多くの課題は残っているものの、少しずつプロセスや組織体制が確立されたと感じる、今日この頃。 ここらで一旦、QA という組織をどのように考えてきたか、どういう仕組みを整えてきたか、過去を振り返りつつ、備忘録として筆を取りたいと思います。 今後何回かに渡り、QA に関するブログを記載していきます。 組織を考えるにあたって いきなり QA でやってきたことをつらつらと書き始めてもなんですので、まずは、どういう組織にしていくか、どういう… <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hayashida-i3/20231004/20231004144220.png" width="1200" height="630" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <p>はじめまして、アイキューブドシステムズにおける CLOMO の製品検証を担う部門、QA を担当している林田です。</p> <p>私が QA に配属されて早2年半が経ちました。まだまだ多くの課題は残っているものの、少しずつプロセスや組織体制が確立されたと感じる、今日この頃。</p> <p>ここらで一旦、QA という組織をどのように考えてきたか、どういう仕組みを整えてきたか、過去を振り返りつつ、備忘録として筆を取りたいと思います。</p> <p>今後何回かに渡り、QA に関するブログを記載していきます。</p> <h2 id="組織を考えるにあたって">組織を考えるにあたって</h2> <p>いきなり QA でやってきたことをつらつらと書き始めてもなんですので、まずは、どういう組織にしていくか、どういう事を考えていたかをお伝えしたいと思います。</p> <p>最初に考えたのは、この組織において、また弊社製品において、どういった部分にフォーカスするべきか、そのために何を考えないといけないか、でした。</p> <p>まず「ソフトウェアテスト」について、ありきたりに wiki で検索したところ、</p> <ul> <li>規定した品質目標に到達すること</li> <li>目標とした品質には、規定した試験項目にすべて合格すること</li> <li>テスト対象の品質に対する信頼を積み重ねて、所定のレベルにあることの確証</li> <li>故意・欠陥の発見、それによる不十分なソフトウェア品質リスクレベルの低減</li> <li>意思決定のための情報提供(テスト対象の品質レベル等)</li> </ul> <p>など、様々な部分に「品質」という言葉が出てきました。そこでまず最初に考察したのは</p> <p><strong>「品質とは何か?」</strong></p> <p><strong>「大事にすべき品質のポイントは何か?」</strong></p> <p>についてでした。</p> <h2 id="品質保証と品質管理">品質保証と品質管理</h2> <p>製品を作る立場の方々がこぞって大事だと言う「品質」という言葉。</p> <p>この「品質」とはいったい何のことでしょう。</p> <p><br/></p> <p>例えば、高級カフェで注文したサンドイッチが出てきたとしましょう。しかし、パンの一部が少し焦げているように見えました。顧客は料理の品質に不満を感じるかもしれません。</p> <p>別の日、同じ顧客が通りで安いクレープを買いました。しかし、クレープの中に少し硬い部分があったとします。それでも、顧客はあまり気にせずに楽しんで食べたと思われます。</p> <p>つまり、<strong>品質とは顧客が支払う「対価」に対する「価値」のことであり、「満足度」でもあります。したがって品質は相対的なものと考えることもできます。</strong></p> <p>※ ちなみに、タイトルの回収にもなりますが、ジェラルド・ワインバーグは著書「Quality Software Management, Volume 1」 で「品質とは誰かにとっての価値である」と書いています。</p> <p>そして、品質は顧客が決定するもので、生産者が決めることはできません。</p> <p><br/></p> <p>自分たちで決めることができないものを、しかし企業としてどこまで考えるべきなのでしょう。</p> <p>ここで必要となるのが、品質保証や品質管理です。</p> <p><br/></p> <p>私が所属する QA とは「quality assurance」、品質保証という意味です。</p> <p>検索するとだいたい「Q&amp;A」が出てきてしまい、「品質保証」としての在り方・考え方についての情報はあまり見つからなかったりするものです。</p> <p>この QA とは、『顧客に対して製品の性能や機能を保証すること』を指す言葉です。ソフトウェア業界においてこの言葉は、テストの実施、所謂検証業務を実施し、不具合や問題が発生しないことに責任を負う部門として概ね認識されています。</p> <p>品質を保証するためには、どの程度の品質なら合格かという基準も持たなければなりません。QA には合格基準を定義したり、どのような検査で合否判定するかというプロセスを決めることも含まれています。</p> <p>しかし、あくまで、品質は判定しません。前述のとおり、品質を決めるのは顧客であるからです。</p> <p><br/></p> <p>もうひとつ、QC という似た言葉もあり、これは「quality control」、品質管理という意味です。</p> <p>QC は『製品やサービスの品質目標を設定し、それを実現するための取り組み』を指す言葉です。同時に、高品質な製品やサービスを効率よく低コストで製造・構築するための視点も求められます。</p> <table> <thead> <tr> <th> </th> <th> 品質保証 </th> <th> 品質管理 </th> </tr> </thead> <tbody> <tr> <td> <strong>意味</strong> </td> <td> 製品の性能や機能を保証すること </td> <td> 製品やサービスの品質目標を設定し、それを実現するための取り組み </td> </tr> <tr> <td> <strong>責任</strong> </td> <td> 製品の不具合や問題に対し </td> <td> 顧客の満足度向上に対し </td> </tr> <tr> <td> <strong>時間軸</strong> </td> <td> 企画から販売後まで </td> <td> 製品完成前まで </td> </tr> <tr> <td> <strong>範囲</strong> </td> <td> すべての製品・機能について </td> <td> 顧客にとって重要な部分まで </td> </tr> </tbody> </table> <p>品質を保証する、品質を管理する。</p> <p>似たような言葉ではありますが、品質保証は『製品を使う顧客に対して責任を負う』ことに対し、品質管理は『顧客の要求を満足させる品質をもった製品を作り出し提供する』ことと考えています。</p> <p><br/></p> <p>ちなみに、私が QA に所属する前には、ここでいう「品質管理」の部門に属していました。</p> <p>やっていたことは似たようなものなのですが、「顧客にとって大きな問題の起こらない製品改修、機能追加であるか」「顧客が分かりやすい、使いやすい UI/UX であるか」「改修箇所以外にも、顧客が良く利用する機能に問題は生じていないか」など、顧客にとって大事な要素のみ検査する部門でした。</p> <p><br/></p> <p>QA に属するにあたっては、この品質管理でやってきた「品質は顧客に寄り添うこと」や、「顧客に品質が高いと思わせること」などを取り入れていくことが軸になると考えました。</p> <h2 id="当たり前品質と魅力的品質">当たり前品質と魅力的品質</h2> <p>品質を考える場合、もうひとつの軸として「当たり前品質」と「魅力的品質」があります。</p> <p><br/></p> <p>当たり前品質とは、その名のとおり「あって当たり前」の品質のことです。例えばゲームにおいて操作どおりにスムーズに動作すること、不具合やバグでプレイが妨げられないことなど、当たり前に求められるものです。</p> <p>対して、魅力的品質とは、高まることでユーザーの満足につながる一方、不十分でも不満に思われない品質のことです。こちらも同様にゲームで例えるなら、キャラクターの背景、グラフィック、素晴らしい BGM、他にもネームバリューのある声優や作家が関わっていることなどが挙げられます。魅力的品質は、なかったからといってすぐに不満に繋がることはありませんが、この品質が高まることによって、より一層の満足度向上が見込めることとなります。</p> <p><strong>参考</strong>:当たり前品質と魅力的品質は、東京理科大学の狩野名誉教授が1980年代に提唱した「狩野モデル」の一部である。狩野モデルでは魅力的品質と当たり前品質を含め、品質を以下の5種類に分類して定義している <br/></p> <p><strong>当たり前品質</strong> 充足されても当たり前としか受け取られない反面、不充足であるとユーザーの不満につながる品質 <br/></p> <p><strong>魅力的品質</strong> 充足されるとユーザーの満足度を高められる反面、仮に不充足でもユーザーの不満にはつながらない品質 <br/></p> <p><strong>一元的品質</strong> 充足されるとユーザーの満足度を高められるが、不充足であると不満につながる品質 <br/></p> <p><strong>無関心品質</strong> 充足されても不充足でもユーザーの満足度に影響しない品質 <br/></p> <p><strong>逆品質</strong> 充足されるとかえってユーザーの満足度を下げ、ない方がユーザーの満足につながる品質</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/5c1b569ef5e5ac60eed7c9d01" alt="" /></p> <h2 id="目指すべき品質目標">目指すべき品質目標</h2> <p>「不具合はゼロにはならない」</p> <p>これは、かなり昔に読んだ文献に登場していた言葉で(文献は失念してしまいました・・)、とても印象に残っているものです。</p> <p>私はこの言葉を「不具合をゼロにすることを目的としてはならない」という意味で解釈しています。</p> <ul> <li>当たり前品質を向上させること</li> <li>魅力的品質を向上させること</li> </ul> <p>これらは当然のことですが、ただし、完璧を求めてはいけない。</p> <p>何かしら定義を明確にし、より多くの顧客にとって、充足してかつ満足いただけるライン。まずはそこを目指していこうと考えました。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/5c1b569ef5e5ac60eed7c9d00" alt="" /></p> <p>次回は、当たり前品質の向上について、どういう施策を考えてきたかお伝えしたいと思います。</p> <p>新卒採用  <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.i3-systems.com%2Fnew-graduates%2F" title="新卒採用|株式会社アイキューブドシステムズ" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.i3-systems.com/new-graduates/">www.i3-systems.com</a></cite></p> <p>キャリア採用 <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.i3-systems.com%2Fcareers%2F" title="採用情報|株式会社アイキューブドシステムズ" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.i3-systems.com/careers/">www.i3-systems.com</a></cite></p> hayashida-i3 Kaigi on Rails 2023 に株式会社アイキューブドシステムズのエンジニア1名が登壇します hatenablog://entry/820878482974535956 2023-10-12T16:41:25+09:00 2023-10-12T19:26:52+09:00 Kaigi on Rails 2023 にて、株式会社アイキューブドシステムズのサーバーサイドエンジニア @YusukeIwaki が登壇します。Playwrightというブラウザ自動操作のライブラリをRubyにポーティングしているエンジニアによるお話です。 <p>2023年10月27日〜28日 の2日間で、浅草橋で開催される Kaigi on Rails 2023 にて、株式会社アイキューブドシステムズのサーバーサイドエンジニア <a href="https://github.com/YusukeIwaki">@YusukeIwaki</a>が登壇します。</p> <table> <thead> <tr> <th> 日時 </th> <th> タイトル </th> </tr> </thead> <tbody> <tr> <td> 10/28(土) 11:05-11:35 </td> <td> E2E testing on Rails 2023 <a href="https://kaigionrails.org/2023/talks/YusukeIwaki/">https://kaigionrails.org/2023/talks/YusukeIwaki/</a> </td> </tr> </tbody> </table> <p>アイキューブドシステムズは <a href="https://www.i3-systems.com/">CLOMO MDM</a> というサービスを開発・運用している会社なのですが、<a href="https://tech.i3-systems.com/entry/2021/10/22/kaigi-on-rails-2021">2年前</a>と同様に、今回もMDMとは関係のない内容をお伝えします。個人の開発で Playwrightというブラウザ自動操作のライブラリをRubyにポーティングしているエンジニアによるお話です。</p> <p>Playwrightといえば、最近Ruby on Railsのシステムテストに取り込まれて、少し話題になりました。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Frails%2Frails%2Fpull%2F48950" title="Add support for Playwright as a driver for system tests by yuki24 · Pull Request #48950 · rails/rails" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://github.com/rails/rails/pull/48950">github.com</a></cite></p> <p>どんな話が聞けるか、ご期待ください!</p> <p>また、先日もお伝えしていたように、株式会社アイキューブドシステムズはゴールドスポンサーとして、Kaigi on Rails 2023イベントブースを出展します。 MDMを身近に体験できるコンテンツを用意していますので、みなさん東京の浅草橋でお会いしましょう!</p> <h2 id="We-are-hiring">We are hiring!</h2> <p>私たちは、Ruby on Railsを最大限活用しながら、CLOMO MDMの製品開発を通じて共に成長していける仲間を募集しています。</p> <p>Kaigi on Railsのブースでは、エンジニア4人が交代で誰かしら居ますので、ちょっと話を聞いてみたいなという方は、お気軽にブースにお立ち寄りください。</p> <p>また、カジュアル面談・エントリーも、下記のページから随時受け付けています。では、Kaigi on Rails 2023を盛り上げていきましょう!</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fherp.careers%2Fv1%2Fi3systems%2Fa4PBXIh36z87" title="【A001】Kaigi on Rails 参加者用: サーバーサイドエンジニア向けカジュアル面談フォーム - 株式会社アイキューブドシステムズ" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://herp.careers/v1/i3systems/a4PBXIh36z87">herp.careers</a></cite></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.i3-systems.com%2Fcareers%2F" title="採用情報|株式会社アイキューブドシステムズ" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.i3-systems.com/careers/">www.i3-systems.com</a></cite></p> clomo-dev 【Ruby】図解・定数の探索経路で迷わなくなるために hatenablog://entry/820878482972413570 2023-10-03T12:00:57+09:00 2023-10-03T12:00:57+09:00 本記事では、はじめに定数探索を習得する上で必要な観点をざっくりお伝えし、のちの章で個々を掘り下げていく構成とする。 この記事だけで定数探索のポイントを1から10まで習得できることを目指し、できるだけ多くの混乱しやすいポイントに対応できるよう心がけた。 文量に見合う情報量となっているだろうから、お付き合いいただきたい。 <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/M/MisakiShiote-i3/20231003/20231003115752.png" width="1200" height="630" loading="lazy" title="" class="hatena-fotolife" itemprop="image"><ul class="table-of-contents"> <li><a href="#まえがき">まえがき</a><ul> <li><a href="#対象レベル">対象レベル</a></li> <li><a href="#注意">注意</a></li> </ul> </li> <li><a href="#準備運動-2つの前提知識">準備運動 2つの前提知識</a><ul> <li><a href="#メソッド呼び出しのような暗黙的なレシーバの補完selfは行われない">メソッド呼び出しのような、暗黙的なレシーバの補完(self.)は行われない</a><ul> <li><a href="#なぜ-C2newconst-が-C2-を返すような気がしたか">なぜ C2.new.const が 'C2' を返すような気がしたか</a></li> <li><a href="#定数呼び出しは暗黙の-self-が補われない">定数呼び出しは暗黙の self. が補われない</a></li> </ul> </li> <li><a href="#ダブルコロンの記法">ダブルコロンの記法</a></li> </ul> </li> <li><a href="#定数探索の概要">定数探索の概要</a></li> <li><a href="#探索経路1-クラスモジュールのネストを辿る探索">探索経路(1) クラス・モジュールのネストを辿る探索</a><ul> <li><a href="#クラスモジュールのネストとは">クラス・モジュールのネストとは</a></li> <li><a href="#Modulenesting-メソッド">Module.nesting メソッド</a></li> <li><a href="#ネストを辿る探索の経路--Modulenesting">ネストを辿る探索の経路 = Module.nesting</a></li> </ul> </li> <li><a href="#探索経路2-継承チェーンを辿る探索">探索経路(2) 継承チェーンを辿る探索</a></li> <li><a href="#定数の参照の記述">定数の参照の記述</a></li> <li><a href="#参照の記述と探索経路1-定数名のみ記述記述箇所からの探索">参照の記述と探索経路(1) 定数名のみ記述・記述箇所からの探索</a></li> <li><a href="#参照の記述と探索経路2-ダブルコロン演算子を用い記述指定オブジェクトからの探索">参照の記述と探索経路(2) ダブルコロン演算子を用い記述・指定オブジェクトからの探索</a><ul> <li><a href="#Object-まで探索されると何が困るのか">Object まで探索されると何が困るのか</a></li> </ul> </li> <li><a href="#あとがき">あとがき</a></li> <li><a href="#Ruby-Gold-対策-xxx_eval-のスコープと定数定義">(Ruby Gold 対策) xxx_eval のスコープと定数定義</a></li> <li><a href="#Ruby-Gold-対策-試験中のメモの取り方">(Ruby Gold 対策) 試験中のメモの取り方</a></li> <li><a href="#定数探索の練習確認">定数探索の練習・確認</a><ul> <li><a href="#練習1-ネストと継承の基本">練習1 ネストと継承の基本</a></li> <li><a href="#練習2-特異クラス">練習2 特異クラス</a></li> <li><a href="#練習3-深いネスト">練習3 深いネスト</a></li> <li><a href="#練習4-モジュールのinclude">練習4 モジュールのinclude</a></li> </ul> </li> </ul> <p>執筆: <a href="https://github.com/MisakiShiote-i3">Misaki-i3</a></p> <h2 id="まえがき">まえがき</h2> <p><a href="https://tech.i3-systems.com/entry/2023/06/23/173914">前回の記事</a>でクラス・モジュールの継承チェーンを学び、メソッドの探索経路を攻略した私は、「これで定数も読めるようになった」と安心していた。それはもちろん勘違いであった。<br/> 模擬試験サイトの点数に勘違いを突きつけられると、私はさっさと書籍とWebを徘徊する仕事に戻った。<br/> 定数の挙動と私の解釈の辻褄が合うまでに、私は定数の探索がメソッドのそれよりも奇妙であることを確信できていた。</p> <p>本記事では、はじめに定数探索を習得する上で必要な観点をざっくりお伝えし、のちの章で個々を掘り下げていく構成とする。</p> <p>この記事だけで定数探索のポイントを1から10まで習得できることを目指し、できるだけ多くの混乱しやすいポイントに対応できるよう心がけた。<br/> 文量に見合う情報量となっているだろうから、お付き合いいただきたい。</p> <p>それにしても謎なのが、各所の解答・解説に頻出する『定数の参照はレキシカルに決まるので答えは○○』という、何も明らかにならない説明だ。『レキシカルに決まる』という慣用句でもあるのか? 今でも得心は行っていない。 もし同じ思いをした方がご覧であれば、本記事ではこの言葉を用いずに説明しきるので、よくよく安心してほしい。</p> <h3 id="対象レベル">対象レベル</h3> <p>前回に引き続き、この記事は入門書を開いたばかりの初心者向きではないが、Rubyの入門書を一周した初心者には十分理解できるものと思う。</p> <p>Ruby Goldの合格を目指している学習者には、ぜひ理解しておいてもらいたい内容である。定数参照がボーナス問題になると、かなり余裕ができるはずだ。</p> <p>今回、メソッドの探索経路の詳細な知識は不要であるが、クラス・モジュールの継承チェーンの理解は必須となる。<br/> 本記事では継承チェーンの解説は行わないため、自信のない方は前回の記事から必要な部分を補いながら読み進めてもらいたい。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftech.i3-systems.com%2Fentry%2F2023%2F06%2F23%2F173914" title="【Ruby】図解・継承チェーンとメソッド探索経路で迷わなくなるために - i Cubed Systems Engineering blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://tech.i3-systems.com/entry/2023/06/23/173914">tech.i3-systems.com</a></cite></p> <h3 id="注意">注意</h3> <p>今回はRubyの定数探索に限定した解説となる。<br/> 他の言語にも当てはめられるものではないので注意していただきたい。</p> <p>Rubyのフレームワークを利用した場合も同様で、例えばRuby on Railsには独自の定数探索経路が追加されているため、正しく参照先を特定するためにはRuby on Railsの理解が重要となる。</p> <h2 id="準備運動-2つの前提知識">準備運動 2つの前提知識</h2> <p>探索経路の解説をスムーズに理解していただくため、以下の2点を前提知識として確認されたい。</p> <ol> <li>メソッド呼び出しのような、暗黙的なレシーバの補完(<code>self.</code>)は行われない</li> <li>ダブルコロンの記法</li> </ol> <h3 id="メソッド呼び出しのような暗黙的なレシーバの補完selfは行われない">メソッド呼び出しのような、暗黙的なレシーバの補完(<code>self.</code>)は行われない</h3> <p>メソッド呼び出しをよく練習した人ほど、レシーバを記述していない呼び出しを見ると、反射的に頭の中で <code>self.</code> を補完してしまうかもしれない。<br/> (そのような思い込みがない方は、本項を読み飛ばしていただいて問題ない)</p> <p>ここを勘違いしたままであると、次のコードにおいて、 <code>C2.new.const</code> が <code>'C2'</code> を返すような気がしてしまう。</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synPreProc">class</span> <span class="synType">C1</span> <span class="synType">FOO</span> = <span class="synSpecial">'</span><span class="synConstant">C1</span><span class="synSpecial">'</span> <span class="synPreProc">def</span> <span class="synIdentifier">const</span> <span class="synType">FOO</span> <span class="synPreProc">end</span> <span class="synPreProc">end</span> <span class="synPreProc">class</span> <span class="synType">C2</span> &lt; <span class="synType">C1</span> <span class="synType">FOO</span> = <span class="synSpecial">'</span><span class="synConstant">C2</span><span class="synSpecial">'</span> <span class="synPreProc">end</span> <span class="synType">C2</span>.new.const <span class="synComment"># 'C1'</span> </pre> <p>これを見て「なぜ <code>'C1'</code> を返すのか」が分からない場合は、まず「なぜ <code>'C2'</code> が返す気がしたか」を明確にしよう。</p> <h4 id="なぜ-C2newconst-が-C2-を返すような気がしたか">なぜ <code>C2.new.const</code> が <code>'C2'</code> を返すような気がしたか</h4> <p>もし先のサンプルが、メソッド <code>foo</code> のサンプルだったとすると……</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synPreProc">class</span> <span class="synType">C1</span> <span class="synPreProc">def</span> <span class="synIdentifier">foo</span> { <span class="synSpecial">'</span><span class="synConstant">C1</span><span class="synSpecial">'</span> }; <span class="synPreProc">end</span> <span class="synPreProc">def</span> <span class="synIdentifier">const</span> foo <span class="synComment"># self.foo と同じ</span> <span class="synPreProc">end</span> <span class="synPreProc">end</span> <span class="synPreProc">class</span> <span class="synType">C2</span> &lt; <span class="synType">C1</span> <span class="synPreProc">def</span> <span class="synIdentifier">foo</span> { <span class="synSpecial">'</span><span class="synConstant">C2</span><span class="synSpecial">'</span> }; <span class="synPreProc">end</span> <span class="synPreProc">end</span> <span class="synType">C2</span>.new.const <span class="synComment"># 'C2'</span> </pre> <p>このときは、たしかに <code>C2.new.const</code> は <code>'C2'</code> を返す。</p> <p>これは、レシーバの記述を省略して呼び出された <code>foo</code> が、暗黙的にカレントオブジェクトをレシーバとして補うためだ。(<code>self.foo</code> と同等)<br/> サンプルでは <code>C2.new</code> がレシーバであるから、<code>C2.new</code> のインスタンスメソッド <code>foo</code> を実行する。</p> <p>この仕組みがメソッド呼び出しのポリモーフィックな挙動を実現している。</p> <h4 id="定数呼び出しは暗黙の-self-が補われない">定数呼び出しは暗黙の <code>self.</code> が補われない</h4> <p>元のサンプルに戻ろう。</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synPreProc">class</span> <span class="synType">C1</span> <span class="synType">FOO</span> = <span class="synSpecial">'</span><span class="synConstant">C1</span><span class="synSpecial">'</span> <span class="synPreProc">def</span> <span class="synIdentifier">const</span> <span class="synType">FOO</span> <span class="synComment"># self.FOO ではない</span> <span class="synPreProc">end</span> <span class="synPreProc">end</span> <span class="synPreProc">class</span> <span class="synType">C2</span> &lt; <span class="synType">C1</span> <span class="synType">FOO</span> = <span class="synSpecial">'</span><span class="synConstant">C2</span><span class="synSpecial">'</span> <span class="synPreProc">end</span> <span class="synType">C2</span>.new.const <span class="synComment"># 'C1'</span> </pre> <p>コメントのとおり、定数には暗黙のレシーバ <code>self.</code> が補われない。<br/> そのためこのときの <code>FOO</code> は、記述箇所である C1クラスの <code>FOO</code> を見つけ、<code>'C1'</code> を返す。</p> <p>ちなみに私は、「 <strong><code>FOO</code> は自分がインスタンスメソッド中にいることに気付いていない</strong>」とイメージしている。<br/> <code>FOO</code> から見た景色が次のようであると想像してみると、この <code>FOO</code> が <code>'C1'</code> を返すことに違和感はないはずだ。</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synPreProc">class</span> <span class="synType">C1</span> <span class="synType">FOO</span> = <span class="synSpecial">'</span><span class="synConstant">C1</span><span class="synSpecial">'</span> <span class="synType">FOO</span> <span class="synPreProc">end</span> </pre> <h3 id="ダブルコロンの記法">ダブルコロンの記法</h3> <p>メソッド呼び出しのドット(<code>.</code>)と同じイメージで考えてよい。<br/> <code>呼び出す側::呼ばれる側</code> の関係で、チェーンもできる。</p> <ul> <li>ダブルコロン(<code>::</code>)を用いて、探索の始点となるオブジェクトを指定できる(<code>Sample::CONST</code>)</li> <li>左辺を省略(<code>::CONST</code>)すると、左辺をトップレベルとみなす(<code>Object::CONST</code>)</li> <li>チェーンして使える(<code>Object::Sample::CONST</code>)</li> </ul> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/0262677a8b6fb580169b5d205" alt="ダブルコロンの記法のイメージ" /></p> <p>ちなみに……</p> <ul> <li>ダブルコロンは、ドット(<code>.</code>)の役割も包含している(エイリアスではない)</li> <li>メソッドを呼び出せる(<code>Sample::class</code>, <code>'str'::reverse</code>)</li> <li>ドット(<code>.</code>)で定数は呼び出せない</li> </ul> <p>重要な前提を共有できたところで、いよいよ本題だ。</p> <h2 id="定数探索の概要">定数探索の概要</h2> <p>定数の探索経路は1種類ではない。また、呼び出し方によって探索経路を選択することができる。</p> <p>定数の探索経路は、大きく2つある。</p> <ol> <li>クラス・モジュールのネスト(入れ子)を辿る探索</li> <li>継承チェーンを辿る探索</li> </ol> <p>定数の参照の記述もまた、大きく2つに分けられる。</p> <ol> <li>定数名のみを記述する</li> <li>ダブルコロン(<code>::</code>)演算子を用いてオブジェクトを指定し記述する</li> </ol> <p>最後に、参照の記述と探索経路は、次のような関係になる。</p> <ol> <li>定数名のみ記述・記述箇所からの探索 <ul> <li>クラス・モジュールのネストを辿る探索を行う</li> <li>次に、継承チェーンを辿る探索を行う</li> </ul> </li> <li>ダブルコロン演算子を用い記述・指定オブジェクトからの探索 <ul> <li>継承チェーンを(<strong>Objectクラスの手前まで</strong>)辿る探索を行う</li> </ul> </li> </ol> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/0262677a8b6fb580169b5d206" alt="定数探索のイメージ図" /></p> <p>この時点で、定数の探索は奇妙で易しくないということが分かったかもしれない。(特に米印のあたり)<br/> しかし理解が進めば、その奇妙さにも歴史的経緯があり、いたずらなものではないと気付ける。</p> <h2 id="探索経路1-クラスモジュールのネストを辿る探索">探索経路(1) クラス・モジュールのネストを辿る探索</h2> <h3 id="クラスモジュールのネストとは">クラス・モジュールのネストとは</h3> <p>ネストの理解は十分であるだろうか。探索経路の基準となるものだ。</p> <ul> <li><code>module</code> キーワードや <code>class</code> キーワードによる定義を入れ子(ネスト)にできる</li> <li>外部からネストの内側のオブジェクトを参照したい場合は、外側のオブジェクトを経由して参照する</li> <li>ネストの内側からでも、外側のクラス・モジュールを呼び出したり定義したりできる</li> <li>ネストは継承関係を<strong>表さない</strong></li> </ul> <p>ネストを利用した定義の例を用意した。<br/> ダブルコロンの記法の復習も兼ねて、自身の理解と異なる結果が生じていないかを確認してほしい。</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synPreProc">module</span> <span class="synType">M1</span> <span class="synComment"># M1</span> <span class="synPreProc">class</span> <span class="synType">C1</span> <span class="synComment"># M1::C1</span> <span class="synPreProc">class</span> <span class="synType">C2</span> <span class="synComment"># M1::C1::C2</span> <span class="synPreProc">end</span> <span class="synPreProc">end</span> <span class="synPreProc">end</span> <span class="synPreProc">class</span> <span class="synType">C1</span> <span class="synComment"># C1</span> <span class="synPreProc">end</span> <span class="synPreProc">class</span> <span class="synType">M1</span>::<span class="synType">C1</span> <span class="synComment"># M1::C1</span> <span class="synPreProc">class</span> <span class="synType">C2</span> <span class="synComment"># M1::C1::C2</span> <span class="synPreProc">end</span> <span class="synPreProc">class</span> ::<span class="synType">C1</span> <span class="synComment"># C1</span> <span class="synPreProc">end</span> <span class="synPreProc">class</span> ::<span class="synType">M1</span>::<span class="synType">C1</span> <span class="synComment"># M1::C1</span> <span class="synPreProc">end</span> <span class="synPreProc">end</span> </pre> <p><code>M1::C1</code> と <code>C1</code> は別物であることを押さえておくように。<br/> 後半は少々イレギュラーな書き方をしているが、難しく考えず、素直に読めばきっと大丈夫。</p> <h3 id="Modulenesting-メソッド"><code>Module.nesting</code> メソッド</h3> <p><code>Module.nesting</code> は、クラス・モジュールのネストの状態を確認するためのメソッドだ。</p> <p>このメソッドの返す配列の内容が、そのまま探索経路となる。<br/> このメソッドは、呼び出した箇所(記述箇所)のネストの状態を、クラス・モジュールの配列にして返してくれる。<br/> 現在のクラス→ひとつ外側のクラス→もうひとつ外側のクラス……と、内側から外側の順に並んでいる。</p> <p>ネストの説明に使ったサンプルの各所で <code>Module.nesting</code> を呼んでみた。</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink>p <span class="synType">Module</span>.nesting <span class="synComment"># []</span> <span class="synPreProc">module</span> <span class="synType">M1</span> p <span class="synType">Module</span>.nesting <span class="synComment"># [M1]</span> <span class="synPreProc">class</span> <span class="synType">C1</span> p <span class="synType">Module</span>.nesting <span class="synComment"># [M1::C1, M1]</span> <span class="synPreProc">class</span> <span class="synType">C2</span> p <span class="synType">Module</span>.nesting <span class="synComment"># [M1::C1::C2, M1::C1, M1]</span> <span class="synPreProc">end</span> <span class="synPreProc">end</span> <span class="synPreProc">end</span> <span class="synPreProc">class</span> <span class="synType">C1</span> p <span class="synType">Module</span>.nesting <span class="synComment"># [C1]</span> <span class="synPreProc">end</span> <span class="synPreProc">class</span> <span class="synType">M1</span>::<span class="synType">C1</span> p <span class="synType">Module</span>.nesting <span class="synComment"># [M1::C1]</span> <span class="synPreProc">class</span> <span class="synType">C2</span> p <span class="synType">Module</span>.nesting <span class="synComment"># [M1::C1::C2, M1::C1]</span> <span class="synPreProc">end</span> <span class="synPreProc">class</span> ::<span class="synType">C1</span> p <span class="synType">Module</span>.nesting <span class="synComment"># [C1, M1::C1]</span> <span class="synPreProc">end</span> <span class="synPreProc">class</span> ::<span class="synType">M1</span>::<span class="synType">C1</span> p <span class="synType">Module</span>.nesting <span class="synComment"># [M1::C1, M1::C1]</span> <span class="synPreProc">end</span> <span class="synPreProc">end</span> </pre> <p>すべての結果に違和感がないかをよく確認してほしい。<br/> 違和感があればネストの説明に戻って、納得行くまで往復することを強く勧める。<br/> 特に、ふたつの <code>M1::C1::C2</code> クラス内の <code>Module.nesting</code> の違いに気付き、「確かにこの結果になる」と確信できること。</p> <p>頭の中で <code>Module.nesting</code> の返り値を求められるようになったなら完璧だ。</p> <h3 id="ネストを辿る探索の経路--Modulenesting">ネストを辿る探索の経路 = <code>Module.nesting</code></h3> <p>先程述べた通り、この配列の並びがそのまま探索経路となる。</p> <p><code>Module.nesting</code> の返り値が <code>[M1::C1::C2, M1::C1, M1]</code> である箇所なら、<br/> 探索経路は <code>M1::C1::C2</code> → <code>M1::C1</code> → <code>M1</code> となる。</p> <p>ここで生じるべき疑問は、「例えば <code>M1::C1</code> を探す段になったとき、これの superclass の定数は見つかるのか?」というものだ。<br/> 見つからない、が答えである。<strong>ネストを辿る探索の最中に、継承チェーンを辿る探索は発生しない。</strong></p> <p><code>[M1::C1::C2, M1::C1, M1]</code> なら、<code>M1::C1::C2</code> → <code>M1::C1</code> → <code>M1</code> のみなのだ。</p> <p>継承チェーンが絡まないことを確認するサンプルを用意した。</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synPreProc">class</span> <span class="synType">Parent</span> <span class="synType">CONST</span> = <span class="synSpecial">'</span><span class="synConstant">Parent</span><span class="synSpecial">'</span> <span class="synPreProc">end</span> <span class="synPreProc">class</span> <span class="synType">C1</span> &lt; <span class="synType">Parent</span> <span class="synPreProc">class</span> <span class="synType">C2</span> p <span class="synType">Module</span>.nesting <span class="synComment"># [C1::C2, C1]</span> <span class="synComment"># p CONST # NameError</span> <span class="synPreProc">end</span> <span class="synPreProc">end</span> </pre> <p>ネストを辿る探索経路に <code>C1</code> クラスが存在するが、そのスーパークラスである <code>Parent</code> までは探しに行かないため、定数の呼び出しで <code>NameError</code> が発生している。</p> <p>上のサンプルをイメージ化すると、このような感じ。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/0262677a8b6fb580169b5d207" alt="ネストを辿る探索経路のイメージ" /></p> <p>ネストと <code>Module.nesting</code> だけ分かれば、ネストを辿る探索は攻略完了!<br/> くれぐれも、深読みしすぎて探索経路を勝手に増やすことのないよう!</p> <h2 id="探索経路2-継承チェーンを辿る探索">探索経路(2) 継承チェーンを辿る探索</h2> <p>これは文字通りの意味しかなく、継承チェーンがそのまま探索経路となっている。<br/> 継承チェーンに関しては理解されているものとして進むので、新しく説明できることは実はない。</p> <p>継承チェーンのおさらい(メソッド探索の記事で使用した図)</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/0262677a8b6fb580169b5d208" alt="継承チェーンの図解" /></p> <p>メソッドの探索と同様、この図の青色(superclass)の矢印を追うだけでよい。<br/> もちろん、水色(singleton_class)の矢印を通ることはない。クラスとその特異クラスは継承関係ではないためだ。</p> <p>概要の章では確か、場合によって継承チェーンを<strong>どこまで辿るかが異なる</strong>かのような説明を見かけたが……それはのちの章で扱う。</p> <h2 id="定数の参照の記述">定数の参照の記述</h2> <p>繰り返しになるが、定数の参照の記述は、大きく2つに分けられる。</p> <ol> <li>定数名のみを記述</li> <li>ダブルコロン(<code>::</code>)演算子を用いて記述</li> </ol> <p>様々な記述の例</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synType">CONST</span> = <span class="synSpecial">'</span><span class="synConstant">トップレベル</span><span class="synSpecial">'</span> <span class="synPreProc">class</span> <span class="synType">Sample</span> <span class="synType">CONST</span> = <span class="synSpecial">'</span><span class="synConstant">Sampleクラス</span><span class="synSpecial">'</span> puts <span class="synType">CONST</span> <span class="synComment"># Sampleクラス</span> puts ::<span class="synType">CONST</span> <span class="synComment"># トップレベル</span> puts ::<span class="synType">Sample</span>::<span class="synType">CONST</span> <span class="synComment"># Sampleクラス</span> <span class="synPreProc">end</span> puts <span class="synType">CONST</span> <span class="synComment"># トップレベル</span> puts <span class="synType">Sample</span>::<span class="synType">CONST</span> <span class="synComment"># Sampleクラス</span> puts ::<span class="synType">Sample</span>::<span class="synType">CONST</span> <span class="synComment"># Sampleクラス</span> </pre> <p><code>puts CONST</code> で呼び出されているところが定数のみの記述だ。<br/> 他はダブルコロン演算子を用いた記述で、探索の始点となるオブジェクトを指定している。</p> <p><code>puts Sample::CONST</code> と <code>puts ::Sample::CONST</code> の違いにも注目してみてほしい。<br/> <code>CONST</code> にとっては、どちらもダブルコロン演算子を用いた記述で、探索の始点は <code>Sample</code> クラスである。<br/> 違いがあるのはダブルコロンの左辺だ。 <code>Sample</code> か <code>::Sample</code> かという違いが存在している。ということは <code>Sample</code> を見つけるまでの探索経路は異なる。</p> <p>つまり、今回の例では同じ <code>Sample</code> を取得できているものの、場合によっては別のオブジェクトが取得されている可能性がある。</p> <p>Ruby のライブラリを始めとした既存のコードを読み解く機会には、このことを忘れないようにしたい。</p> <p>さて、探索の種類と記述の種類を学び終えたら、あとは組み合わせるだけだ!</p> <h2 id="参照の記述と探索経路1-定数名のみ記述記述箇所からの探索">参照の記述と探索経路(1) 定数名のみ記述・記述箇所からの探索</h2> <p>定数名のみを記述した場合の探索経路は次のようになる。</p> <ul> <li>クラス・モジュールのネストを辿る探索を行う</li> <li>次に、継承チェーンを辿る探索を行う</li> </ul> <p>非常に喜ばしいことに、これ以上説明すべきことが何もない。<br/> 例題で確認してみよう。</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synPreProc">module</span> <span class="synType">M1</span> <span class="synPreProc">module</span> <span class="synType">M2</span> <span class="synType">FOO</span> <span class="synPreProc">end</span> <span class="synPreProc">end</span> </pre> <p>定数名のみで呼び出されている <code>FOO</code> がある。この探索経路はどうなるだろう?</p> <ul> <li>クラス・モジュールのネストを辿る探索 <ul> <li><code>FOO</code> の箇所に <code>Module.nesting</code> があったとき、返り値はなにか?</li> </ul> </li> <li>継承チェーンを辿る探索 <ul> <li><code>FOO</code> が記述されている <code>M1::M2</code> の継承チェーンは?</li> </ul> </li> </ul> <p>答えは以下のようになる。</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synPreProc">module</span> <span class="synType">M1</span> <span class="synPreProc">module</span> <span class="synType">M2</span> p <span class="synType">Module</span>.nesting <span class="synComment"># [M1::M2, M1]</span> <span class="synType">FOO</span> <span class="synComment"># (1) M1::M2 → M1 (2) M1::M2 → Object → Kernel → BasicObject</span> <span class="synPreProc">end</span> <span class="synPreProc">end</span> </pre> <p>よって、<code>FOO</code> の探索経路は、<br/> ( <code>M1::M2</code> → <code>M1</code> ) → ( <code>M1::M2</code> → <code>Object</code> → <code>Kernel</code> → <code>BasicObject</code> )<br/> となる。</p> <p><code>Module.nesting</code> を攻略したあなたには、拍子抜けするほど簡単なのではないだろうか。<br/> 記事の最後にもいくつかのサンプルを用意しているので、まだ不安という方もそちらで練習していただける。<br/> いまのところは、次へ進もう。</p> <h2 id="参照の記述と探索経路2-ダブルコロン演算子を用い記述指定オブジェクトからの探索">参照の記述と探索経路(2) ダブルコロン演算子を用い記述・指定オブジェクトからの探索</h2> <p>ダブルコロン演算子を用い記述した場合の探索経路は次のようになる。</p> <ul> <li>継承チェーンを(<strong>Objectクラスの手前まで</strong>)辿る探索を行う</li> </ul> <p>書いてあるとおり、継承チェーンを辿る探索は <code>Object</code> の手前までしか行われない。<br/> 例で確認してみる。</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synPreProc">module</span> <span class="synType">M1</span> <span class="synPreProc">module</span> <span class="synType">M2</span> ::<span class="synType">M1</span>::<span class="synType">M2</span>::<span class="synType">FOO</span> <span class="synPreProc">end</span> <span class="synPreProc">end</span> </pre> <p>ひとつ前のサンプルと同じ構造にしているので、 <code>M1::M2</code> モジュールの継承チェーンは <code>M1::M2 → Object → Kernel → BasicObject</code> となっていることを覚えていると思う。<br/> しかし、 探索経路には <code>Object</code> 以降が含まれない。</p> <p>よって、 <code>::M1::M2::FOO</code> の探索経路は<br/> ( <code>M1::M2</code> )<br/> となる。</p> <h3 id="Object-まで探索されると何が困るのか">Object まで探索されると何が困るのか</h3> <p>「定数名だけのときと、ダブルコロンを使うとき、 <code>Object</code> まで行かないのはどっちだっけ?」<br/> 答えはダブルコロンを使うときだが、暗記する必要はない。<br/> 事の経緯を知れば、すぐに思い出せるようになる。</p> <p>ダブルコロン演算子を用い記述する方の定数探索も、かつては <code>Object</code> とその先まで探索されていた。しかし、利便性に難があった。</p> <p>次のリンクは、ダブルコロンの記法を用いて指定オブジェクトからの探索を行うとき、トップレベルまで探索されてしまうことのデメリットを指摘するチケットである。</p> <p><a href="https://bugs.ruby-lang.org/issues/11547">Feature #11547: remove top-level constant lookup - Ruby master - Ruby Issue Tracking System</a></p> <p>要約すると、「呼び出そうとした定数が指定オブジェクトの配下になかったとき、Object まで探索されると意図しない定数を参照してしまいやすくなり、不便である」という内容である。<br/> (起票された2015年には、探索の結果トップレベルの定数を取得した場合に warning が出力されるだけであった)</p> <p>あえてオブジェクトを指定して定数を呼び出そうとするときは、トップレベルを探索する意図はないことの方が多い。その意図を持って利用するケースがあるとしても、そうでない多くの開発者の被るデメリットのほうが大きいと考えられる。<br/> そして今の実装に変更された。</p> <p>規則が一貫していることは重要だが、実用に配慮する柔軟性もかけがえのないものなのだろう。</p> <p>ここまでで、定数の探索経路の解説は完了だ。<br/> 終わってみれば簡単だった……か?</p> <h2 id="あとがき">あとがき</h2> <p>記事は続くが、想定より長くなってしまったのであとがきを繰り上げることにした。</p> <p>私が定数の探索経路を学んでいるとき、見つけられる既存の解説では十分に理解できなかった。<br/> 分かった気になって、実行してみて間違いに気付き、資料に戻って誤解に気づいて、分かった気になり、以下繰り返し。</p> <p>この記事では何が何でも『一読で』『誤解なく』『分かってもらう』つもりで執筆しているが、残念ながら既に誤解を与えている可能性は低くないだろうと覚悟している。</p> <p>記事中にあるサンプルを実行したり、「ここに定義を追加したらどんな影響があるだろう」とアレンジしてみたりしてほしい。</p> <p>Ruby Goldの模擬問題を解き、模擬試験サイトの点数に勘違いを突きつけられ、また記事を読み返しに戻ってきてほしい。</p> <hr /> <p>弊社では採用活動を実施しています。<br/> アウトプットの盛んな社内で、ともに技術の追求を楽しんでいける仲間をお待ちしております。</p> <p>新卒採用:<a href="https://www.i3-systems.com/new-graduates/">https://www.i3-systems.com/new-graduates/</a><br/> キャリア採用:<a href="https://www.i3-systems.com/careers/">https://www.i3-systems.com/careers/</a></p> <hr /> <p>以降は、Ruby Goldの受験を目指す向けの追加情報と、定数探索を確認・練習するためのサンプルを記載している。</p> <h2 id="Ruby-Gold-対策-xxx_eval-のスコープと定数定義">(Ruby Gold 対策) xxx_eval のスコープと定数定義</h2> <p>メタプログラミングの領域となるが、Ruby Gold の出題範囲であるため、資格取得を目指す人は押さえておくべきだ。</p> <ul> <li>xxx_evalに渡すブロックはクラス・モジュールのスコープに入らない</li> <li>ただし、テキストでコードを与えた場合は、class・moduleキーワード等でオープンしたとき相当の処理がされるためスコープに入る</li> <li>スコープに入っているかは <code>Module.nesting</code> で確認できる</li> </ul> <p><code>xxx_eval</code> とスコープを確認する例</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synPreProc">class</span> <span class="synType">C</span> p <span class="synType">Module</span>.nesting <span class="synComment"># [C]</span> <span class="synPreProc">end</span> <span class="synType">C</span>.class_eval <span class="synStatement">do</span> p <span class="synType">Module</span>.nesting <span class="synComment"># []</span> <span class="synStatement">end</span> <span class="synType">C</span>.class_eval(&lt;&lt;~<span class="synSpecial">CODE</span>) <span class="synConstant"> p Module.nesting # [C]</span> <span class="synSpecial">CODE</span> <span class="synType">C</span>.instance_eval(&lt;&lt;~<span class="synSpecial">CODE</span>) <span class="synConstant"> p Module.nesting # [#&lt;Class:C&gt;] instance_evalは特異クラス</span> <span class="synSpecial">CODE</span> </pre> <p>実際に定義した場合の例</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synPreProc">class</span> <span class="synType">C</span>; <span class="synPreProc">end</span> <span class="synType">C</span>.class_eval <span class="synStatement">do</span> <span class="synType">FOO</span> = <span class="synSpecial">'</span><span class="synConstant">C</span><span class="synSpecial">'</span> <span class="synComment"># Cの定数のつもりが、Objectの定数として定義されている</span> <span class="synStatement">end</span> <span class="synType">C</span>.const_defined?(<span class="synConstant">:FOO</span>) <span class="synComment"># true 継承チェーンの探索のときにようやく見つかる</span> <span class="synType">C</span>.const_defined?(<span class="synConstant">:FOO</span>, <span class="synConstant">false</span>) <span class="synComment"># false 継承チェーンを辿らない設定にすると、見つからない</span> <span class="synType">C</span>.class_eval(&lt;&lt;~<span class="synSpecial">CODE</span>) <span class="synConstant"> FOO = 'C' # Cに定義されている</span> <span class="synSpecial">CODE</span> <span class="synType">C</span>.const_defined?(<span class="synConstant">:FOO</span>, <span class="synConstant">false</span>) <span class="synComment"># true Cに定義できている</span> </pre> <h2 id="Ruby-Gold-対策-試験中のメモの取り方">(Ruby Gold 対策) 試験中のメモの取り方</h2> <p>定数探索の問題は、定数名のみを記述したときの探索がほとんどなので、それを前提にする。</p> <ol> <li>問題文の中で定数定義(<code>CONST = 'XXX'</code>)を見かけたら、対応表に追加しよう</li> <li>呼び出しコードにたどり着いたら、定数探索の(1)と(2)を作ろう</li> <li>探索経路が導けたら、その時点での対応表を見ながら探索しよう</li> </ol> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synPreProc">module</span> <span class="synType">M1</span> <span class="synType">FOO</span> = <span class="synSpecial">'</span><span class="synConstant">M1</span><span class="synSpecial">'</span> <span class="synComment"># 追加! M1/FOO/'M1'</span> <span class="synPreProc">end</span> <span class="synPreProc">class</span> <span class="synType">C1</span> <span class="synPreProc">include</span> <span class="synType">M1</span> <span class="synPreProc">class</span> &lt;&lt; <span class="synConstant">self</span> <span class="synPreProc">def</span> <span class="synIdentifier">foo</span> p <span class="synType">FOO</span> <span class="synComment"># 探索経路 (1) #&lt;Class:C1&gt; → C1 (2) #&lt;Class:C1&gt; → Object以降</span> <span class="synPreProc">end</span> <span class="synPreProc">end</span> <span class="synPreProc">end</span> <span class="synComment"># C1.foo # 探索! 誰も持っていない ==&gt; NameError</span> <span class="synPreProc">class</span> <span class="synType">C1</span> <span class="synType">FOO</span> = <span class="synSpecial">'</span><span class="synConstant">C1</span><span class="synSpecial">'</span> <span class="synComment"># 追加! C1/FOO/'C1'</span> <span class="synPreProc">end</span> <span class="synType">C1</span>.foo <span class="synComment"># 探索! (1)の C1 が持っていた ==&gt; 'C1'</span> <span class="synPreProc">class</span> &lt;&lt; <span class="synType">C1</span> <span class="synType">FOO</span> = <span class="synSpecial">'</span><span class="synConstant">特異C1</span><span class="synSpecial">'</span> <span class="synComment"># 追加! 特異C1/FOO/'特異C1'</span> <span class="synPreProc">end</span> <span class="synType">C1</span>.foo <span class="synComment"># 探索! (1)の #&lt;Class:C1&gt; が持っていた ==&gt; '特異C1'</span> </pre> <h2 id="定数探索の練習確認">定数探索の練習・確認</h2> <h3 id="練習1-ネストと継承の基本">練習1 ネストと継承の基本</h3> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synPreProc">module</span> <span class="synType">M1</span> <span class="synPreProc">class</span> ::<span class="synType">C1</span> <span class="synType">Module</span>.nesting <span class="synComment"># [C1, M1]</span> <span class="synType">FOO</span> <span class="synComment"># (1) C1 → M1 (2) C1 → Object以降</span> <span class="synPreProc">end</span> <span class="synPreProc">end</span> <span class="synPreProc">class</span> <span class="synType">C1</span> <span class="synType">Module</span>.nesting <span class="synComment"># [C1]</span> <span class="synType">FOO</span> <span class="synComment"># (1) C1 (2) C1 → Object以降</span> <span class="synPreProc">end</span> <span class="synPreProc">class</span> <span class="synType">C2</span> &lt; <span class="synType">C1</span> <span class="synType">Module</span>.nesting <span class="synComment"># [C2]</span> <span class="synType">FOO</span> <span class="synComment"># (1) C2 (2) C2 → C1 → Object以降</span> <span class="synPreProc">end</span> </pre> <h3 id="練習2-特異クラス">練習2 特異クラス</h3> <p>(クラスと特異クラスに継承関係はないからね、ということ)</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synPreProc">class</span> <span class="synType">C1</span> <span class="synPreProc">end</span> <span class="synPreProc">class</span> &lt;&lt; <span class="synType">C1</span> <span class="synPreProc">def</span> <span class="synIdentifier">foo</span> <span class="synType">Module</span>.nesting <span class="synComment"># [#&lt;Class:C1&gt;, C1]</span> <span class="synType">FOO</span> <span class="synComment"># (1) #&lt;Class:C1&gt; (2) #&lt;Class:C1&gt; → Object以降</span> <span class="synPreProc">end</span> <span class="synPreProc">end</span> <span class="synComment"># C1.foo # (1) #&lt;Class:C1&gt; (2) #&lt;Class:C1&gt; → Object以降 ==&gt; NameError</span> <span class="synPreProc">class</span> <span class="synType">C1</span> <span class="synType">FOO</span> = <span class="synSpecial">'</span><span class="synConstant">C1</span><span class="synSpecial">'</span> <span class="synPreProc">end</span> <span class="synComment"># C1.foo # (1) #&lt;Class:C1&gt; (2) #&lt;Class:C1&gt; → Object以降 ==&gt; NameError</span> <span class="synPreProc">class</span> &lt;&lt; <span class="synType">C1</span> <span class="synType">FOO</span> = <span class="synSpecial">'</span><span class="synConstant">特異C1</span><span class="synSpecial">'</span> <span class="synPreProc">end</span> <span class="synType">C1</span>.foo <span class="synComment"># (1) #&lt;Class:C1&gt; (2) #&lt;Class:C1&gt; → Object以降 ==&gt; '特異C1'</span> </pre> <h3 id="練習3-深いネスト">練習3 深いネスト</h3> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synPreProc">module</span> <span class="synType">M1</span> <span class="synPreProc">class</span> <span class="synType">C1</span> <span class="synType">Module</span>.nesting <span class="synComment"># [M1::C1, M1]</span> <span class="synPreProc">end</span> <span class="synPreProc">end</span> <span class="synPreProc">module</span> <span class="synType">M1</span>::<span class="synType">C1</span>::<span class="synType">M2</span> <span class="synPreProc">class</span> <span class="synType">C2</span> <span class="synType">Module</span>.nesting <span class="synComment"># [M1::C1::M2::C2, M1::C1::M2]</span> <span class="synType">FOO</span> = <span class="synSpecial">'</span><span class="synConstant">M1::C1::M2::C2</span><span class="synSpecial">'</span> <span class="synPreProc">end</span> <span class="synPreProc">end</span> <span class="synPreProc">class</span> <span class="synType">C2</span> <span class="synType">Module</span>.nesting <span class="synComment"># [C2]</span> <span class="synType">FOO</span> = <span class="synSpecial">'</span><span class="synConstant">C2</span><span class="synSpecial">'</span> <span class="synPreProc">end</span> <span class="synPreProc">module</span> <span class="synType">M1</span> <span class="synPreProc">module</span> <span class="synType">C1</span>::<span class="synType">M2</span> <span class="synType">Module</span>.nesting <span class="synComment"># [M1::C1::M2, M1]</span> <span class="synPreProc">class</span> <span class="synType">C2</span> <span class="synType">Module</span>.nesting <span class="synComment"># [M1::C1::M2::C2, M1::C1::M2, M1]</span> <span class="synType">FOO</span> <span class="synComment"># (1) M1::C1::M2::C2 → M1::C1::M2 → M1 (2) M1::C1::M2::C2 → Object以降 ==&gt; 'M1::C1::M2::C2'</span> <span class="synPreProc">end</span> <span class="synPreProc">end</span> <span class="synPreProc">end</span> </pre> <h3 id="練習4-モジュールのinclude">練習4 モジュールのinclude</h3> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synPreProc">module</span> <span class="synType">M1</span> <span class="synType">FOO</span> = <span class="synSpecial">'</span><span class="synConstant">M1</span><span class="synSpecial">'</span> <span class="synPreProc">class</span> ::<span class="synType">C1</span> <span class="synType">Module</span>.nesting <span class="synComment"># [C1, M1]</span> <span class="synType">FOO</span> <span class="synComment"># (1) C1 → M1 (2) C1 → Object以降 ==&gt; 'M1'</span> <span class="synPreProc">end</span> <span class="synPreProc">end</span> <span class="synPreProc">class</span> <span class="synType">C2</span> &lt; <span class="synType">C1</span> <span class="synType">Module</span>.nesting <span class="synComment"># [C2]</span> <span class="synComment"># FOO # (1) C2 (2) C2 → C1 → Object以降 ==&gt; NameError</span> <span class="synPreProc">include</span> <span class="synType">M1</span> <span class="synType">FOO</span> <span class="synComment"># (1) C2 (2) C2 → M1 → C1 → Object以降 ==&gt; 'M1'</span> <span class="synPreProc">end</span> </pre> MisakiShiote-i3 新卒エンジニアがDroidKaigi 2023に参加してみて hatenablog://entry/6801883189053859182 2023-09-21T17:00:00+09:00 2023-11-01T21:52:32+09:00 こんにちは、株式会社アイキューブドシステムズでモバイルアプリを担当しているKajihara-3です。私は2023年に新卒で入社し、現在はAndroidチームで開発を行っています。 今回、09/14~9/16に開催されたDroidKaigi 2023に参加してきました。私はAndroid開発を始めてからまだ間もないですが、それでも得るものはたくさんありました。Androidエンジニアとの交流やモダンな技術についてのセッションにより、多大な刺激を受けて開発のモチベーションとなりました。このブログでは、カンファレンスに参加し、セッションの聴講などをする中で得られたことについて紹介します。 Droid… <p>こんにちは、株式会社アイキューブドシステムズでモバイルアプリを担当している<a href="https://github.com/Kajihara-i3">Kajihara-3</a>です。私は2023年に新卒で入社し、現在はAndroidチームで開発を行っています。</p> <p>今回、09/14~9/16に開催されたDroidKaigi 2023に参加してきました。私はAndroid開発を始めてからまだ間もないですが、それでも得るものはたくさんありました。Androidエンジニアとの交流やモダンな技術についてのセッションにより、多大な刺激を受けて開発のモチベーションとなりました。このブログでは、カンファレンスに参加し、セッションの聴講などをする中で得られたことについて紹介します。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/0262677a8b6fb580169b5d20d" alt="" /></p> <h2 id="DroidKaigi-2023の概要">DroidKaigi 2023の概要</h2> <p><a href="https://2023.droidkaigi.jp/">DroidKaigi 2023</a>は、09/14~09/16の3日間、ベルサール渋谷ガーデンにて開催されました。DroidKaigiは、エンジニアが主役のAndroidカンファレンスで、Android技術情報の共有とコミュニケーションを目的として様々なセッションや交流の場が用意されています。</p> <p>1日目、2日目はセッションの聴講、スポンサーブースの出展が主になります。セッションではAndroidや開発に関するテーマが幅広く扱われており、興味のある内容のセッションを自由に選択して聴講することができます。</p> <p>3日目は、Android開発を進めるための自己学習型コンテンツであるコードラボを進めながら、キャリア・パネルトークに参加したり、キャリア相談会やMeet Upに参加したりと、自由な雰囲気で会場を回ることができます。</p> <p>カンファレンス全体を通して交流に重きが置かれており、スポンサーブースやMeet Up、アフターパーティなど様々な場面で参加者同士で交流を深めることができます。</p> <h2 id="印象に残ったセッションをピックアップ">印象に残ったセッションをピックアップ</h2> <p>今回参加してきたセッションは、弊社が取り組んでいるようなAndroid Enterpriseに関するものから、Jetpack Compose、 Material design3(以降、Material 3)など、Androidに関する幅広いセッションがありました。 今回は数あるセッションの中でも、印象に残ったセッションをピックアップして、簡単に内容をまとめてみます。</p> <h3 id="ビジネス向けアプリを開発するときに知っておくべきAndroid-Enterpriseの世界まとめ">「ビジネス向けアプリを開発するときに知っておくべきAndroid Enterpriseの世界まとめ」</h3> <p>Android Enterpriseは、Androidプラットフォームのビジネス利用を支えるために、Googleが主導している取り組みのことです。 弊社のプロダクトであるCLOMO MDMは、企業や組織におけるモバイルデバイス運用をより効率的かつ安全にするためのサービスですが、AndroidにおけるMDMの実装や機能セットは、Android Enterpriseとして標準化されています。 そんなMDMで使える特別な機能に、Managed ConfigurationsとConnected Appsがあります。</p> <p>これらの機能を使うと、アプリにリモートで設定を配布したり、アプリが仕事用プロファイルと個人用プロファイルの間で通信を行ったりできます。 カンファレンス後、個人的にManaged Configurationsを実装してみて、面白い機能だと感じました。</p> <h3 id="Jetpack-Compose-の-Side-effect-を使いこなす">Jetpack Compose の Side-effect を使いこなす</h3> <p>Side-effectとは、関数や操作などが結果を返すなどの、主となる効果以外の効果のことです(副作用の例:グローバル変数の変更や、I/O操作など)。Jetpack ComposeにおけるSide-effectとは、コンポーズ可能な関数の範囲外で発生するアプリの状態の変化を指します。このセッションでは、Side-effectをうまく扱うためのAPIの紹介がされました。</p> <p>Side-effectによってテストやデバッグに影響が出るため、Composable関数は副作用がないようにするのが理想です。しかし、副作用が必要になる場面もあります。そのため、状況に応じて各APIを使いこなせるようになるのが重要なポイントでした。</p> <h3 id="Material-3-やめました">Material 3 やめました</h3> <p>Material 3のDesign Tokensには、Reference Token, System Token, およびComponent Tokenという3つのTokenがあります。Design Tokensは色やフォントといったスタイルの値を定義するためのもので、この中のSystem Tokenで色を扱うのが辛いため、独自のシステムを作ろうといった話でした。</p> <p>実際には、Material 3のメカニズムは利用しつつ、一部Token内の設定をカスタムしたり削ったりしてデザインシステムとコンポーネントを実装して独自にシステムを作っており、Tokenのおすすめの初期設定を共有されていました。このセッションはかなり人気で、会場がほぼ満席となっていました。</p> <hr /> <p>他にもAndroid開発に関わることが幅広くセッションで紹介されていました。感想としては、まだまだ使い慣れていない技術やあまり知らない技術もあり、知識を得るだけでなく使えるようにする必要があると感じました。</p> <h2 id="アフターパーティやMeet-Up">アフターパーティやMeet Up</h2> <p>ここからは交流の場についてです。</p> <p>1日目の終わりにはアフターパーティが開催されました。ここでは広い会場を自由に回りながら、一般参加者だけでなくスピーカー、スポンサーの方とも好きに交流することができます。自分の知らない意外な業界にもAndroidが使用されていたり、他社の職場の雰囲気や取り組みについて知ることができたりと、エンジニアとの会話では新たな発見がたくさんありました。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/0262677a8b6fb580169b5d20f" alt="" /></p> <p>他にも、昼食やおやつの時間にはMeet Upが開催され、いろんな方とお話する機会があります。Meet Upでは、新人エンジニア、キャリアプラン、子育てと仕事、マネジメント・チーム開発といった様々なテーマをもとに集まって話をすることができます。このMeet Upのおかげで、意気投合して仲良くなった人もできました。特に、(社内など)自分の所属するコミュニティ外にいる、異なるバックグラウンドや観点を持つ人との話はかなり新鮮で、参考になることがたくさんありました。</p> <h2 id="参加して良かったこと">参加して良かったこと</h2> <h3 id="現地でエンジニアと交流できる">現地でエンジニアと交流できる</h3> <p>先ほども述べたように、Meet Upやアフターパーティでは他の方と話をする機会がありました。特定のテーマについて集まったメンバーの中でグループを作り、食事をしながら会話ができるためアイスブレイクもしやすかったです。若手エンジニアだけでなく、さまざまなキャリアを持った方や外国籍の方など多様性のある参加者の中から交流を行ったため、多大な刺激を受けることができました。</p> <h3 id="オフィスアワーにより質疑応答や会話ができる">オフィスアワーにより、質疑応答や会話ができる</h3> <p>セッション終了後はオフィスアワーという時間があり、この間にセッションのスピーカーに直接質問をぶつけたり感想を伝えたりすることができます。セッション中の厳かな雰囲気で手を挙げるような形式ではなかったため、気軽に質問やそれに関連した話をすることができました。質問がなくとも会話をしてセッションの理解を深められるオフィスアワーは、オフラインでのみ参加できます。</p> <h3 id="翻訳レシーバーがある">翻訳レシーバーがある</h3> <p>英語を日本語に、日本語を英語に翻訳してくれるレシーバーが会場で配布されており、これを利用すれば言語を気にすることなくリアルタイムにセッションを聴講することができます。ただし、スライドは翻訳に対応していないので注意が必要です。</p> <h2 id="課題に感じたところ">課題に感じたところ</h2> <h3 id="セッション時間だけで内容の理解を完結できない">セッション時間だけで内容の理解を完結できない</h3> <p>セッションによってはスライドが詰め込まれており、一度に全てを理解するのは難しいと感じることがありました。コードの解説をスライドで行っているセッションもあるため、現地では大まかな概要を理解し、詳細は後で確認する方が良いと感じました。私はAndroid開発に携わって半年も経っておらず、勉強不足な部分もあると痛感したため、もっとAndroid開発に打ち込みたいと感じました。</p> <h3 id="学んだことを会社に活かしていく方法">学んだことを会社に活かしていく方法</h3> <p>様々な技術についてセッションがありましたが、そういった内容全てを開発現場に還元し、活かせるわけではありません。とはいえ、活かせる部分を探し、どうしたら活かせるかを試行錯誤して学んだことを身に付けていくのは重要だと考えました。</p> <h2 id="まとめ">まとめ</h2> <p>今回のことは、現地に参加する意義のあるカンファレンス出張だったと確信しています。ただ参加して終わりではなく、業務や開発に活かせるよう取り組んでいきたいです。</p> <p>最後に、弊社では採用活動を実施しています。興味のある方はご応募ください。</p> <ul> <li>[新卒採用]:<a href="https://www.i3-systems.com/new-graduates/">https://www.i3-systems.com/new-graduates/</a></li> <li>[キャリア採用]:<a href="https://www.i3-systems.com/careers/">https://www.i3-systems.com/careers/</a></li> </ul> kajihara-i3 アイキューブドシステムズはKaigi on Rails 2023にゴールドスポンサーとして協賛&ブース出展します! hatenablog://entry/820878482963327749 2023-08-31T14:59:59+09:00 2023-08-31T15:03:01+09:00 2023年10月27日〜28日 の2日間で開催される Kaigi on Rails 2023 にて、株式会社アイキューブドシステムズはゴールドスポンサーとして協賛します! 今年のKaigi on Railsは初のオフライン開催ですので、これまで以上に場を盛り上げていきたいという思いから、スポンサーブースの出展もあわせて行います。 <p>2023年10月27日〜28日 の2日間で開催される Kaigi on Rails 2023 にて、株式会社アイキューブドシステムズはゴールドスポンサーとして協賛します!</p> <p>今年のKaigi on Railsは初の現地開催ですので、これまで以上に場を盛り上げていきたいという思いから、スポンサーブースの出展もあわせて行います。</p> <p><a href="https://kaigionrails.org/2023/sponsors/"><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/5c1b569ef5e5ac60eed7c9d03" alt="" /></a></p> <p><a href="https://kaigionrails.org/2023/sponsors/">https://kaigionrails.org/2023/sponsors/</a></p> <p>弊社のエンジニア1名が登壇予定なのと、スポンサーブースの詳細については、続報にてお伝えしたいと思います。</p> <h2 id="We-are-hiring">We are hiring!</h2> <p>私たちは、Ruby on Railsを最大限活用しながら、CLOMO MDMの製品開発を通じて共に成長していける仲間を募集しています。</p> <p>Kaigi on Railsのブースでは、エンジニア4人が交代で誰かしら居ますので、ちょっと話を聞いてみたいなという方は、お気軽にブースにお立ち寄りください。</p> <p>また、カジュアル面談・エントリーも、下記のページから随時受け付けています。 <a href="https://www.i3-systems.com/careers/">https://www.i3-systems.com/careers/</a></p> <p>では、Kaigi on Rails 2023を盛り上げていきましょう!</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.i3-systems.com%2Fnew-graduates%2F" title="新卒採用|株式会社アイキューブドシステムズ" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.i3-systems.com/new-graduates/">www.i3-systems.com</a></cite></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.i3-systems.com%2Fcareers%2F" title="採用情報|株式会社アイキューブドシステムズ" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.i3-systems.com/careers/">www.i3-systems.com</a></cite></p> iwaki-i3 新入社員のオンボーディング hatenablog://entry/820878482939329588 2023-08-29T15:55:18+09:00 2023-08-29T15:55:18+09:00 はじめに 新入社員のオンボーディング アイキューブドシステムズでCLOMOのサーバーサイドを担当している Kakuno です。 4月になり、弊社に新入社員が入社致しました。私は新入社員のオンボーディングを担当しています。今回のブログでは、どのように新入社員を迎え入れ、チームにフィットさせるのかというオンボーディングの準備を紹介したいと思います。 なお、過去にどんなオンボーディングを行ったかはこちらの過去のブログを御覧ください 新卒社員がサーバーサイドに配属されるまでの話 新卒でいきなりリモートワークってどんな感じなの?と気になる方へ 1. 受け入れ準備 ハードウェアとソフトウェアの用意 新入社… <h2 id="はじめに">はじめに</h2> <p><figure class="figure-image figure-image-fotolife" title="新入社員のオンボーディング"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/c/clomo-dev/20230612/20230612105925.jpg" alt="&#x65B0;&#x5165;&#x793E;&#x54E1;&#x306E;&#x30AA;&#x30F3;&#x30DC;&#x30FC;&#x30C7;&#x30A3;&#x30F3;&#x30B0;" width="1200" height="630" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>新入社員のオンボーディング</figcaption></figure> アイキューブドシステムズでCLOMOのサーバーサイドを担当している <a href="https://www.linkedin.com/in/tetsuhiro-kakuno-078862100/">Kakuno</a> です。</p> <p>4月になり、弊社に新入社員が入社致しました。私は新入社員のオンボーディングを担当しています。今回のブログでは、どのように新入社員を迎え入れ、チームにフィットさせるのかというオンボーディングの準備を紹介したいと思います。</p> <p>なお、過去にどんなオンボーディングを行ったかはこちらの過去のブログを御覧ください</p> <p><a href="https://tech.i3-systems.com/entry/2023/04/11/132419">新卒社員がサーバーサイドに配属されるまでの話</a></p> <p><a href="https://tech.i3-systems.com/entry/2021/11/25/102622">新卒でいきなりリモートワークってどんな感じなの?と気になる方へ</a></p> <h2 id="1-受け入れ準備">1. 受け入れ準備</h2> <h3 id="ハードウェアとソフトウェアの用意">ハードウェアとソフトウェアの用意</h3> <p>新入社員に必要なハードウェアとソフトウェアを用意し、業務を開始するためのインフラストラクチャを整えます。弊社のエンジニアには基本的にMacBookProを支給しています。 また業務に必要な有償エディタなども購入ができます。</p> <h3 id="リモートワークに必要な物の用意">リモートワークに必要な物の用意</h3> <p>さらに必要に応じてリモートワークに関する物品のレンタル/購入が出来ます。 4Kディスプレイ/高級チェアは会社で管理しているものがあるのでレンタルが出来ます。 それ以外の物品については申請を出してもらいAmazonビジネスアカウント経由で購入して自宅に届けています。例えば、高品質なヘッドセットマイクやWebカメラの購入ができます。 <a href="https://github.com/MiyazakiTakayuki">MiyazakiTakayuki</a>さんが自宅の環境について紹介しています。</p> <p><a href="https://tech.i3-systems.com/entry/2022/03/28/140520">使ってみないとわからない!新卒3人が福利厚生を利用してみた</a></p> <h2 id="2-教育訓練">2. 教育・訓練</h2> <h3 id="基本的な業務知識の提供">基本的な業務知識の提供</h3> <p>新入社員が担当する予定の業務に関する基本的な知識を提供します。これには、業界の規制、顧客のニーズ、および企業の戦略的目標などが含まれます。 ここは部署に限らず、全新入社員を対象として、CLOMOの基礎知識、ビジネス基礎、ロジカルシンキングなどの研修が含まれます。</p> <h3 id="開発プロセスとシステムのトレーニング">開発プロセスとシステムのトレーニング</h3> <p>エンジニアに向けて、CLOMO Developer’s Quick Start Guideというドキュメントを用意しており、自主的に学習が出来るようにしています。 CLOMO Developer’s Quick Start Guideでは、開発プロセスなどシステム開発に関するトレーニングを提供します。このトレーニングには、gitの基礎知識、サーバーサイド開発の基礎知識、モバイル開発の基礎知識が含まれます。 ここについてはこちらの過去のブログをご覧ください。</p> <p><a href="https://tech.i3-systems.com/entry/2021/03/18/154142">CLOMOの開発スタートガイド作成までの道のり</a></p> <h2 id="3-チームの統合">3. チームの統合</h2> <h3 id="チームビルディングイベントの開催">チームビルディングイベントの開催</h3> <p>新入社員を受け入れるチームによるビルディングイベントを開催し、メンバー間の信頼関係を築きます。これにより、新入社員はより効果的にチームに参加できるような手伝いになります。 弊社では現在(2023年5月)週1出社を原則とし、様々なメンバーとのコミュニケーションを取っています。また業務外イベントも行っており、直近では任意参加のOUTDOORイベント(植物園ピクニック)が開催されました。</p> <h3 id="メンターシップの提供">メンターシップの提供</h3> <p>新入社員に対して、経験豊富な社員をメンターとして割り当て、業務上のアドバイスや質問に答えるサポートを提供します。これにより、新入社員はより迅速に組織に溶け込むことができます。 1:1でメンターシップを割り当てています。毎日夕会という30分程度の相談会を用意し、ささいな疑問の解消や相談も出来るように環境を整えています。</p> <h2 id="4-パフォーマンス管理">4. パフォーマンス管理</h2> <h3 id="目標の設定とフィードバック">目標の設定とフィードバック</h3> <p>新入社員と管理者は、新入社員の目標設定を共同で行います。そして、定期的なフィードバックを通じて、新入社員が目標に向かって進捗しているかどうかを確認し、必要に応じて業務内容を調整します。 育成計画を立てており、1年後にどのような姿であるべきかの理想の姿を見据えています。</p> <h3 id="成果評価">成果評価</h3> <p>新入社員の成果を評価し、業績に基づいてフィードバックを提供します。これにより、新入社員は業務内容を改善するための行動を取ることができます。 四半期毎に進捗状況の確認を行い、目標に対しての達成度の確認とコメント・アドバイスをしていきます。</p> <h2 id="5-オンボーディングプログラムの改善">5. オンボーディングプログラムの改善</h2> <h3 id="フィードバックの収集と分析プログラムの改善">フィードバックの収集と分析、プログラムの改善</h3> <p>新入社員、メンターからのフィードバックを収集し、プログラムの改善に役立てます。フィードバックを分析し、オンボーディングプログラムを改善します。 今年は前年度のオンボーディングからの改善点として、研修終了後も希望に応じて発展的な勉強(例えばUI/UXやデザインやフロントまわりの基礎知識)のコンテンツを取り入れる予定です。</p> <h2 id="まとめ">まとめ</h2> <p>企業が適切なオンボーディングを実施することで、新入社員は早期に生産的なメンバーとなることができます。</p> <p>オンボーディングプログラムを改善するためには、フィードバックの収集と分析が重要です。新入社員、メンター、および担当者からのフィードバックを収集し、改善点を見つけ、改善することが必要です。</p> <p>最後に、新入社員のオンボーディングプログラムは、企業の成功に欠かせない重要なプロセスであるため、計画と実施にあたっては、その重要性を理解し、真剣に取り組むことが求められます。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.i3-systems.com%2Fnew-graduates%2F" title="新卒採用|株式会社アイキューブドシステムズ" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.i3-systems.com/new-graduates/">www.i3-systems.com</a></cite> <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.i3-systems.com%2Fcareers%2F" title="採用情報|株式会社アイキューブドシステムズ" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.i3-systems.com/careers/">www.i3-systems.com</a></cite></p> clomo-dev 社内のMicrosoft Teamsチャットに OpenAIを使ったチャットボットを導入してみた hatenablog://entry/820878482942108457 2023-08-01T20:17:41+09:00 2023-08-01T20:17:41+09:00 サーバーサイドエンジニアの@YusukeIwakiです。 巷ではChatGPTがすっかり賑わっていますね。多くの会社でチャットボットが導入されているのを横目に見て、私たちの開発組織でも Azure OpenAI Service を使ってボットを作ってみました。 世の中のブログ記事を見ると、「こんなボット作ったよ(ドヤ)」という部分については比較的多く共有されているいっぽうで、「これを作るまでにはこんな苦労があったよ」という部分については積極的には発信されていない印象があります。 この記事では、後者の部分をしっかり伝えられるよう心がけて書いてみました。 導入したもの ともあれ最初に最終成果物を見… <p>サーバーサイドエンジニアの<a href="https://github.com/YusukeIwaki">@YusukeIwaki</a>です。</p> <p>巷ではChatGPTがすっかり賑わっていますね。多くの会社でチャットボットが導入されているのを横目に見て、私たちの開発組織でも Azure OpenAI Service を使ってボットを作ってみました。</p> <p>世の中のブログ記事を見ると、「こんなボット作ったよ(ドヤ)」という部分については比較的多く共有されているいっぽうで、「これを作るまでにはこんな苦労があったよ」という部分については積極的には発信されていない印象があります。</p> <p>この記事では、後者の部分をしっかり伝えられるよう心がけて書いてみました。</p> <h2 id="導入したもの">導入したもの</h2> <p>ともあれ最初に最終成果物を見てもらったほうがイメージが付きやすいので、紹介しちゃいます。</p> <p>Azure OpenAI Serviceをバックエンドにしたチャットボットで、構成自体はありきたりです。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_b49e20c0a3b26bb7e22f76e26d4bb61a.png" alt="" /></p> <p>1点工夫したところがあって、会社のチャットツールであるMicrosoft Teamsの<strong>会話スレッドごとに、ボットの文脈を切り替えられる</strong>ようにしています。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_ae3a88052880aede6f4ccb932fea61bd.png" alt="" /></p> <p>こうすることで、ある人がカスタマーサポートの文言をAIに書かせている傍らで、別の人がAppleのMDMの仕様をAIに聞くなど、自然なやりとりを実現できています。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_a3b5476659caa40382a8f5b8cc46d47f.png" alt="" /></p> <h2 id="この構成に至るまでの試行錯誤">この構成に至るまでの試行錯誤</h2> <p>ここからが本題です。組織のみんなが積極的に使うようになった現在のチャットボットに至るまでの試行錯誤を、できる限り紹介していきます。</p> <h3 id="Phase1-プライベートメッセージでチャットボットと話せる">Phase1: プライベートメッセージでチャットボットと話せる</h3> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_89eaa4c9b2139a4f0c78bb5fd7459cf0.png" alt="" /></p> <p>最初期は、スレッドで会話する機能がありませんでした。</p> <p>Teamsチャット欄でボットに話しかけると、返ってくる方式です。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_602a1b961dea5d9303702c98eeb5e952.png" alt="" /></p> <p><strong>この構成で発生した問題点</strong></p> <p>想像に難くないですが、他の人がボットとどんな会話をしているのかわからないので、「うまい使い方がわからない」という問題が普通に発生しました。</p> <p>この頃はまだ部内ではなく一部の興味ある人達だけで使っていましたが、それでもこのような問題があらわになったことから、個別チャットボットでは全体共有すると絶対に活用できない確信がありました(苦笑)</p> <p><strong>次の一手</strong></p> <p>まずはスレッド上で会話できるようにしました。</p> <h3 id="Phase2-スレッド上でチャットボットにメンションして会話できるようにする">Phase2: スレッド上でチャットボットにメンションして会話できるようにする</h3> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_142586e66282a052a6b474d0faf4cb90.png" alt="" /></p> <p>これは簡単そうに見えて、Microsoft Teamsでは非常に<del>難しい</del>面倒な作業でした。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fzenn.dev%2Fyusukeiwaki%2Farticles%2Fb6ae7bf77a81eb%23%25E4%25BC%259A%25E7%25A4%25BE%25E3%2581%25AE%25E3%2581%25BF%25E3%2582%2593%25E3%2581%25AA%25E3%2581%258C%25E3%2582%25B9%25E3%2583%25AC%25E3%2583%2583%25E3%2583%2589%25E3%2583%25A1%25E3%2583%2583%25E3%2582%25BB%25E3%2583%25BC%25E3%2582%25B8%25E4%25B8%258A%25E3%2581%25A7%25E4%25BD%25BF%25E3%2581%2588%25E3%2582%258B%25E3%2582%2588%25E3%2581%2586%25E3%2581%25AB%25E3%2581%2599%25E3%2582%258B%25E3%2581%25AB%25E3%2581%25AF%253F" title="Microsoft Teamsで(Bot frameworkを使わずに)ボットを作るには" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://zenn.dev/yusukeiwaki/articles/b6ae7bf77a81eb#%E4%BC%9A%E7%A4%BE%E3%81%AE%E3%81%BF%E3%82%93%E3%81%AA%E3%81%8C%E3%82%B9%E3%83%AC%E3%83%83%E3%83%89%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E4%B8%8A%E3%81%A7%E4%BD%BF%E3%81%88%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%99%E3%82%8B%E3%81%AB%E3%81%AF%3F">zenn.dev</a></cite></p> <p>実装の詳しくはこちらを参照されてください。リファレンスをあちこち読み漁って、組織内部用Teamsアプリのようなものを作って、情シス(Teams管理者)に承諾してもらう必要があります。</p> <p>ここまで来ると、他人の活用事例が見えるようになります。Open AIで学習データ利用されることから、業務知識は食わせてはならない!などいくつかの注意点を組織内で共有の上、みんなで使い始めてみました。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_bd8a5ea6f01a3a5bff90b070b5151e31.png" alt="" /></p> <p>こんな感じで活用するメンバーが現れ始めました。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_021ed51164ade844158667fc40a10718.png" alt="" /></p> <p><strong>この構成で発生した問題点</strong></p> <p>Phase1の個別チャットボットのときにも起きていたのですが、「話しかけたのに回答が返ってこない」というのをみんな気にし始めました。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_8cd59190bd3afd6183611e2d77d7869b.png" alt="" /></p> <p><strong>次の一手</strong></p> <p>Azure App Serviceのコールドスタート問題は、どうも無料プランだと酷いらしいということが(なんとなく)わかり、課金を開始することにしました。<del>ビバ札束解決。</del></p> <p>あとは、質問内容を受け付けたよ、ってのをわかるようにするようにしました。</p> <h3 id="Phase3-質問内容を即時で返してOpenAIからのレスポンス契機でアップデートをかける">Phase3: 質問内容を即時で返して、OpenAIからのレスポンス契機でアップデートをかける</h3> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_e93298539f1a9b892d1425b25811995d.png" alt="" /></p> <p>Azure BotのBot ConnectorAPIには、</p> <ul> <li>会話(スレッドへの返信)を投稿するAPI <ul> <li><code>POST /v3/conversations/{conversationId}/activities</code> )</li> </ul> </li> <li>投稿内容を上書きするAPI <ul> <li><code>PUT /v3/conversations/{conversationId}/activities/{activityId}</code></li> </ul> </li> </ul> <p>の2つが存在します。</p> <p>従来はPOST /activitiesのみを使用していましたが、これを改善して、</p> <ul> <li>まずは POST /activitiesでProcessing...である旨の返信をして</li> <li>次にPUT /activities/{activityId} で質問に対する回答をする</li> </ul> <p>という<strong>二段階の投稿を行うことで、"無視されてる感"の軽減</strong>を実現しました。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_2662b01f6a4b4b5bf3768baca7ed15ae.png" alt="" /></p> <p>(参考) Bot Connector APIリファレンス <a href="https://learn.microsoft.com/ja-jp/azure/bot-service/rest-api/bot-framework-rest-connector-api-reference?view=azure-bot-service-4.0#send-to-conversation">https://learn.microsoft.com/ja-jp/azure/bot-service/rest-api/bot-framework-rest-connector-api-reference?view=azure-bot-service-4.0#send-to-conversation</a></p> <p>ちなみに、このPhaseではOpenAIのStreaming APIも試しました。 比較的リアルタイムに返信が得られる一方で、べつにそこまで要らない(ボットの実装コードがやや読みづらくなる割に、得られる恩恵が少ない)という感じだったので、結局Streaming API採用には至りませんでした。</p> <p><strong>この構成での問題</strong></p> <p>もともと存在していた問題ですが、<strong>業務の知識を含んでないか、気軽に質問がしづらい</strong>という点です。社内だけでなくパートナーの皆さんにも使ってもらいたいという声は出てきて、セキュリティの担保が急務となってきました。</p> <p><strong>次の一手</strong></p> <p>ちょうどこのあたりで、Azure OpenAI Serviceの審査が通りました。Azure OpenAI Serviceにはデータを学習利用する旨のポリシーは存在していないので、バックエンドサービスをAzure OpenAI APIからAzure OpenAI Serviceへ切り替えることにしました。</p> <h3 id="Phase4-OpenAI-APIからAzure-OpenAI-Serviceへの切り替え簡易的な認証">Phase4: OpenAI APIからAzure OpenAI Serviceへの切り替え+簡易的な認証</h3> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_37a012bbbf7da18d30b4ea3a6cc1e875.png" alt="" /></p> <p>OpenAI APIを、審査が通ったAzure OpenAI Serviceへと切り替えました。</p> <p>Azure OpenAI Serviceは、機能が限られているうえに、APIの入力データ構造が本家OpenAI APIとほぼ同じなので、移行自体は非常に簡単でした。</p> <ul> <li><a href="https://platform.openai.com/docs/api-reference">https://platform.openai.com/docs/api-reference</a> <ul> <li><code>POST https://api.openai.com/v1/completions</code></li> </ul> </li> <li><a href="https://learn.microsoft.com/ja-jp/azure/cognitive-services/openai/reference">https://learn.microsoft.com/ja-jp/azure/cognitive-services/openai/reference</a> <ul> <li><code>POST https://YOUR_RESOURCE_NAME.openai.azure.com/openai/deployments/YOUR_DEPLOYMENT_NAME/completions</code></li> </ul> </li> </ul> <p>これにより、多少は安心して使ってもらえるようになりました。 ただ、さすがにセキュリティ的な観点から、どこの誰でもインストールして使える状態というのはまずいので、使用可能なメンバーをTeamsチームごとに制限することにしました。</p> <p>誰かが勝手にTeamsアプリを追加してしまっても、予め許可したチームでなければ固定のメッセージを返すようにしたり、</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_4e3a11d83ae0836e533bee41ad1dfe7b.png" alt="" /></p> <p>チームへの許可はしていても、想定外のメンバーが質問してきた場合には固定のメッセージを返すようにしたり。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_e997878f4917527b9f8dcfe17dcc917a.png" alt="" /></p> <p>ともあれ、ここまでやったところで、ある程度安心してみんなに使えるようになったので、堂々の周知をしました。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_ab68dff6afa3f5c8cf343ace12bb978b.png" alt="" /></p> <p><strong>この構成での問題</strong></p> <p>ここまでくると、だいぶみんなに使ってもらえるようにはなりましたが、<strong>本家のChatGPTと全然使用感が違う</strong>といった声もでてきました。何が問題だったかというと、文脈を一切考慮していなかったという点です。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_cb5f55287b64ebbe6c91938af63b857e.png" alt="" /></p> <p>これまでの使い方は、いわば「一問一答」で、質問文で与えられた字面だけをみてそれっぽい回答が返ってくるというものでした。これを実際に使いこなすには利用者側がそれなりの工夫が必要な状況でした。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_afccbaccc0961c832d22eb0725f8e818.png" alt="" /></p> <p>もっと自然に会話したいと思うのは当然です。</p> <p><strong>次の一手</strong></p> <p>会話履歴を保存して、文脈をいちいち入力せずともAIと自然な会話ができるようにする。</p> <h3 id="Phase5-一問一答からの脱却">Phase5: 一問一答からの脱却!</h3> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_7c04856972d3e643e48ef25bd57fba54.png" alt="" /></p> <ul> <li>キャッチコピーを3つ考えてください</li> <li>あと2つ考えてください</li> </ul> <p>のように連続する質問を与えた際、「あと2つ」は文脈的に「キャッチコピーの4個目と5個目」を求めていることをAIにわかってもらう必要があります。これはどうすればよいのでしょうか。</p> <p>実は、OpenAI APIがそのような文脈を与えての補完をサポートしています。APIリファレンスをよく読んでみると、messageは複数指定できるようになっており、しかもroleというパラメータで誰の発言かを区別できるようになっています。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_fb74bcf0bbcf026eaf207a96038a5e66.png" alt="" /></p> <p>これを利用して、先の例では2回目の発言時に、Teams上の会話履歴を含めて渡すようにしました。</p> <pre class="code" data-lang="" data-unlink>{ &#34;role&#34;: &#34;system&#34;, &#34;content&#34;: &#34;あなたは優秀なアウトドア雑誌の記者です。&#34;}, { &#34;role&#34;: &#34;user&#34;, &#34;content&#34;: &#34;キャッチコピーを3つ考えてください。&#34;}, { &#34;role&#34;: &#34;assistant&#34;, &#34;content&#34;: &#34;1. xxxxx\n 2. xxxx\n 3. xxxxx&#34;}, { &#34;role&#34;: &#34;user&#34;, &#34;content&#34;: &#34;あと2つ考えてください。&#34;},</pre> <p>こうすることで、とても自然な質問回答を得ることができるようになります。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_0a39e1214e18b1fc3ba57229875300cb.png" alt="" /></p> <p>ただ、会話履歴をどこからどこまで渡したいかは指定できたほうが便利そうと直感的に思い、2つのマジックワードで囲まれた区間のみ会話履歴を一緒に渡すような実装にしました。マジックワードはいちいち覚えてられないので、質問回答の末尾にガイドとして表示するようにしたのも工夫ポイントです。</p> <p><strong>デフォルト状態では、一問一答モード</strong>で、このようなガイド表示。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_9e683781cd4af6f344462b16b80e6472.png" alt="" /></p> <p><strong><code>@ChatBot あなたは.+です</code> という正規表現にひっかかる発言をしたときに、会話履歴も合わせて質問</strong>するモードへ変更。そのときにはこのようなガイド表示。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_3fa5d99ebb14bbc009cf79c078243bc6.png" alt="" /></p> <p><strong><code>@ChatBot reset</code> と打つことで、会話履歴を消去</strong>し、デフォルトの状態に戻る。</p> <p>チャットのUXてきには超ダサいものの、実使用においては意外とこれで必要十分で、この会話履歴機能を付けてからは特に社外のパートナーのエンジニアも含めて一気に使われるようになりました。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_590e7840d541ee89e844b245c9cd7be5.png" alt="" /></p> <p><strong>この構成での問題点</strong></p> <p>チャットボットとして使えるものにはなりました。ただ、そもそものところで <code>@ChatGPT</code> という名前はいけません。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fopenai.com%2Fbrand" title="Brand guidelines" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://openai.com/brand">openai.com</a></cite></p> <p>2023年4月に公開されたOpenAIのガイドラインにも、勝手に"GPT"とか名前を付けるなと明記されています。</p> <p>社内向けアプリケーションであるとか関係なくダメなことをやってしまっています。</p> <p><strong>次の一手</strong></p> <p>ボットのリネーム。</p> <p>これはAzure Bot Serviceのコンソールから簡単にできるものではなく、</p> <ul> <li>チャットボットのアプリケーションのマニフェストで名前を修正</li> <li>再度アプリをビルド、組織内Teamsアプリとしてアップロード</li> <li>情シス(Teams管理者)による再承認</li> </ul> <p>までをやって、ようやくチャットボットのリネームができます。</p> <h3 id="Phase6-ボット名をOpenAIのカイドラインに遵守する形にリネーム">Phase6: ボット名をOpenAIのカイドラインに遵守する形にリネーム</h3> <p>と、ここまで書いたところで、まだ現在(2023/6/14)でも対応が完了していません...。早くやらなきゃ・・・💦</p> <h2 id="まとめ">まとめ</h2> <p>アイキューブドシステムズのエンジニア組織で実際に運用されている、Azure OpenAI Serviceをベースとしたチャットボットについて、その変遷を中心に紹介してみました。</p> <p>アリものを使って導入しておしまいではなく、継続的な改善を重ねてきたことで、チャット初心者でも新卒メンバーでも自然に使いこなすことができるようなものになりました。</p> <p>本当は活用事例をもっと紹介してソースコードも公開したかったのですが、機密情報を取り除くのが地味に大変で、間に合っていないので、またの機会に紹介したいと思います。</p> <h3 id="We-are-hiring">We are hiring!</h3> <p>アイキューブドシステムズでは、このように「継続的な改善」ができる/楽しめるメンバーを大募集中です。カジュアル面談もやっていますので、興味のある方はぜひ応募されてください。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.i3-systems.com%2Fcareers%2F" title="採用情報|株式会社アイキューブドシステムズ" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.i3-systems.com/careers/">www.i3-systems.com</a></cite></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.i3-systems.com%2Fnew-graduates%2F" title="新卒採用|株式会社アイキューブドシステムズ" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.i3-systems.com/new-graduates/">www.i3-systems.com</a></cite></p> iwaki-i3 モバイルに配属された新卒社員の研修と仕事内容 hatenablog://entry/820878482937308054 2023-07-03T13:57:56+09:00 2023-07-03T13:57:56+09:00 今回はモバイルに配属となった22卒のMAKKUPOUNとayano-i3がモバイル開発チームに配属されるまでの研修内容、配属後の仕事内容についてご紹介します。 iOS研修 初めまして、22卒のMAKKUPOUNです。香港出身です。アソシエイトモバイルエンジニア担当させていただいています。iOS関係の不具合とプロジェクトの業務を務めています。実はこの会社で働く前も銀行でバック・フォアオフィスの正社員として働いていましたが、プログラミングと関係ありませんでした。それに、日本に旅行したことありますが、生活したこともなく、日本語も全然上手ではなく、日本に行くことは前から不安を感じていました。幸い、弊社… <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/ayano-i3/20230608/20230608112000.png" width="1200" height="630" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <p>今回はモバイルに配属となった22卒の<a href="https://github.com/MAKKUPOUN">MAKKUPOUN</a>と<a href="https://github.com/ayano-i3">ayano-i3</a>がモバイル開発チームに配属されるまでの研修内容、配属後の仕事内容についてご紹介します。</p> <h2 id="iOS研修">iOS研修</h2> <p>初めまして、22卒の<a href="https://github.com/MAKKUPOUN">MAKKUPOUN</a>です。香港出身です。アソシエイトモバイルエンジニア担当させていただいています。iOS関係の不具合とプロジェクトの業務を務めています。実はこの会社で働く前も銀行でバック・フォアオフィスの正社員として働いていましたが、プログラミングと関係ありませんでした。それに、日本に旅行したことありますが、生活したこともなく、日本語も全然上手ではなく、日本に行くことは前から不安を感じていました。幸い、弊社の方がいろいろサポートいただきました。</p> <p>大学の専攻は応用数学です。情報系専攻ではないですが、大学のプロジェクトや課題にPythonを使っていました。現在担当しているモバイル作業のプログラミングと関係なかったですが、特に複雑なモデルを解析するときに、数学でプログラミングがすごく役立つと感じました。そのときに、プログラミングに興味を持ちました。これもITの仕事を探すきっかけになりました。</p> <p>新卒として弊社に入り、最初の3ヶ月くらいは研修を受けていました。主にサーバーとiOSモバイルの研修でした。私はiOSモバイル側に興味持っていたので、C#とXamarinの知識を習得しながら、自分で簡単なアプリを作成しました。</p> <p>最初に一番苦しいことは環境構築とアプリ開発ツールの使い方です。特にXcodeに触ったことは全然なかったので、プロジェクトをビルドするときに、エラーを解消するのにすごく時間がかかりました。エラーメッセージを読んで苦しんでいたことはありますが、エラーの内容と原因を理解し、解決方法を学びました。ネットでドキュメントを読み、自分で試しつつ、UIやFirebaseなどの利用方法を学びました。</p> <p>研修の最後に自分が好きなように、簡単なアプリを作成しました。まだ簡単な構成のアプリでしたが、やりがいがあるとすごく感じました。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_b22cd8dd4859a37d3c9464234022722c.png" width="500"></p> <h3 id="iOSチーム配属後">iOSチーム配属後</h3> <p>研修が終わった後に、不具合の課題に関わる仕事をずっとしていました。最初はMDM AgentとS-Browserアプリの不具合を解消していました。初めて製品のコードを触った時に、アプリのコードの構成や機能などすごく複雑だと思っていました。利用されているコードの場所さえ知らなかった状態で、不具合の原因を推測し、突き止めるように頑張りました。大変でしたが、新しい課題を解決するたびに、新しいコードの知識を学びました。コードの知識だけではなく、論理的思考も鍛えました。それに、OSバージョンにより、コードを改修しないといけないこともよくあります。プログラミングは進化し続けて、もっと学びたいと思います。</p> <p>そして、他のアプリの課題やプロジェクトもやらせていただきました。XamarinとC# だけではなく、Objective-Cも勉強しながら、アプリの課題を解決しました。それぞれのアプリは構成と機能も違うし、利用されている言語も全部同じではないので、苦しんだことはありますが、いろいろ学べて嬉しいです。今Objective-Cより、Swiftを使ってる人が多いかもしれませんが、どのプログラミング言語もメリットとデメリットがあるし、お互い共通点もあるので、Objective-Cを勉強するのも同様に重要だと考えております。</p> <h2 id="Android研修">Android研修</h2> <p> こんにちは、製品開発運用本部 製品開発課に所属している22卒の<a href="https://github.com/ayano-i3">ayano-i3</a>です。大学では幼児教育を専攻しており、開発経験はなく趣味程度でプログラミングを勉強していました。現在はMDM Agent for Androidアプリを担当しています。</p> <h3 id="研修の流れ">研修の流れ</h3> <p>部署配属後新卒メンバー全員ではじめにサーバーサイド研修、iOS研修を受けた後にAndroid研修を受けました。サーバーサイドの研修内容については<a href="https://tech.i3-systems.com/entry/2023/04/11/132419">こちら</a>の記事をご覧ください。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftech.i3-systems.com%2Fentry%2F2023%2F04%2F11%2F132419" title="新卒社員がサーバーサイドに配属されるまでの話 - i Cubed Systems Engineering blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://tech.i3-systems.com/entry/2023/04/11/132419">tech.i3-systems.com</a></cite></p> <p>サーバーサイド研修、iOS研修終了後、自分たちで興味を持った方を選び、配属希望面談を経て配属先が決定します。</p> <p>私はAndroidに興味があったので、面談でそのことを伝えAndroid研修を受けさせてもらいました。Android研修ではAndroidアプリ開発の基礎とKotlinの勉強を行いました。<a href="https://developer.android.com/courses/android-basics-kotlin/course">Android Basics in Kotlin</a>のコードラボを進め、分からないところがあったらその都度質問をするという流れで進めていきました。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_8443f1016cba1f7a0146bab6ebe1b1e4.png" alt="" /></p> <p>私は研修を通して計18個のアプリを作成しました。研修の最後には自分で考えた好きなアプリを作成し、成果発表を行いました。</p> <h3 id="成果発表">成果発表</h3> <p>研修の最後には成果発表があり、そこで全体に向けて研修で学んだことを発表します。私は簡単なルーレットアプリをAndroid研修の6日目から4日間ほどかけて作成しました。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_b91185021b83217798610bd2c8b67427.png" width="200"></p> <p><br> 作成にあたり、実装方法が分からないところや、こんな機能追加したいけど、実現可能なのかなど知識が足りず苦戦するところがありました。 </br></p> <p>しかし、毎日”夕会”という1日の勉強内容を共有する時間を作ってもらっていたため、分からなかったところはその場で相談し、改善のアドバイスをもらうことができました。</p> <p>研修を初めてすぐに自分で考えたアプリを作成するというのは難しいことだとは思いますが、実装したい機能を先に決め、それに向けてどうしたらできるようになるのかを調べ、考える事により実践的に学ぶことができました。</p> <p>また、簡単ではありますが、アプリが完成することにより達成感とアプリづくりの楽しさも感じることができました。</p> <h3 id="研修中の働き方について">研修中の働き方について</h3> <p>弊社ではリモートワークを採用しており、研修も全てリモートで行われていました。現在は週1出社へ変更となり、新卒研修は出社とリモートのハイブリットで行われています。リモートワークについては「<a href="https://tech.i3-systems.com/entry/2021/11/25/102622">新卒でいきなりリモートワークってどんな感じなの?と気になる方へ</a>」の記事をご覧ください。 <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftech.i3-systems.com%2Fentry%2F2021%2F11%2F25%2F102622" title="新卒でいきなりリモートワークってどんな感じなの?と気になる方へ - i Cubed Systems Engineering blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://tech.i3-systems.com/entry/2021/11/25/102622">tech.i3-systems.com</a></cite></p> <p>対面ではないので、質問がしにくそうと考える方もいるかも知れません。雑談がてら、ちょっとした質問をするのは難しいですが、私はリモートワークのほうが質問がしやすいと感じています。</p> <p>対面の場合、今忙しそうだからもう少し時間を置いてから質問しに行こうとタイミングを見計らうことが多いと思います。しかし、リモートワークの場合だと自分が質問したい時にチャットを送り、受け取った相手も自分が都合のいいタイミングで返信をすることができるので、質問しやすいと感じます。チャットベースだと質問するのが難しい内容や、時間がかかりそうな場合はTeamsやGoogle Meetを使って画面共有をしながら教えてもらうこともあります。</p> <h3 id="Androidチーム配属後">Androidチーム配属後</h3> <p>Andoridチーム配属後は実務に入るための準備として<a href="https://androidenterprise.exceedlms.com/student/catalog">Android Enterprise Academy</a>で、Android Enterpriseの基礎・専門用語を学びました。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_a2082592579383a38444d1c253dfc1a7.png" width="200"></p> <p><br> その後、MDM Agent for Androidアプリの内部的な処理をコードを追いながらアプリについての知識を身につけ、簡単な不具合修正を行いました。 </br></p> <p>Agent for Androidアプリを初めて実際に触ってみた時は、どこにその処理がかかれてるのかを探すことも理解することも時間がかかりました。研修で行っていたコードラボは簡単なアプリの作成だったため、Agent for Androidアプリは複雑に感じ処理を追うだけでも難しかったです。</p> <p>しかし、不具合修正・機能追加などの課題を通して、自分が入れた処理がアプリに反映されているのを見ると、とても嬉しく、また他の課題にも挑戦してみたいという気持ちになりました。</p> <p>現在は新規プロジェクトに参加したり、不具合の修正を行ったり、お客様からのお問い合わせの調査を行っています。他のチームに比べて、Androidチームは人数が少ないですが、分からないところがあった時は先輩社員が優しくとても丁寧に教えてくださるので、開発未経験の私でも日々少しずつではありますが、知識と技術を身につけていくことができています。</p> <h2 id="まとめ">まとめ</h2> <p>今回は、私たちがモバイル開発チームに配属前研修と配属後の仕事内容をご紹介しました。今後もモバイル開発に未経験のことを挑戦し続け、尽力し、過去の自分を超えたいと考えています。学ぶべきこともたくさんありますが、一歩一歩踏み出して、焦らずに進めていきたいと思います。</p> <p>ご興味がありましたらお気軽にお問い合わせください。</p> <ul> <li>新卒採用 <ul> <li><a href="https://www.i3-systems.com/new-graduates/">https://www.i3-systems.com/new-graduates/</a></li> </ul> </li> <li>キャリア採用 <ul> <li><a href="https://www.i3-systems.com/careers/">https://www.i3-systems.com/careers/</a></li> </ul> </li> </ul> ayano-i3 CSE iOSチームの紹介 hatenablog://entry/820878482937406462 2023-06-26T11:43:58+09:00 2023-06-26T11:43:58+09:00 はじめに アイキューブドシステムズでiOSアプリ開発を担当しているhuong-i3です。 2022年6月に入社しました。入社研修後6ヶ月Xamarin iOS Coreチームに配属していました。初めてのチーム開発記事を書いたのでよければご覧ください。 2022年12月末にCSE iOSチームに参画することになりました。今回、CSE iOSチームを紹介したいと思います。 CSE iOSチーム CSEはCLOMO Sustained Engineeringの略であり、小規模の修正や要望対応、障害対応を行うチームです。運用中のアプリのメンテナンス、CS(Customer Success)チーム経由で… <div style="text-align: center"> <img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_8ec183dc78b7e8f11ea81f4b6da913a1.png" alt="" width="300" height=""> </div> <h2 id="はじめに">はじめに</h2> <p>アイキューブドシステムズでiOSアプリ開発を担当している<a href="https://github.com/huong-i3">huong-i3</a>です。</p> <p>2022年6月に入社しました。入社研修後6ヶ月Xamarin iOS Coreチームに配属していました。<a href="https://tech.i3-systems.com/entry/2022/12/27/102935">初めてのチーム開発</a>記事を書いたのでよければご覧ください。</p> <p>2022年12月末にCSE iOSチームに参画することになりました。今回、CSE iOSチームを紹介したいと思います。</p> <h2 id="CSE-iOSチーム">CSE iOSチーム</h2> <p>CSEはCLOMO Sustained Engineeringの略であり、小規模の修正や要望対応、障害対応を行うチームです。運用中のアプリのメンテナンス、CS(Customer Success)チーム経由でのお客さんからの問い合わせの対応、必要に応じて新規機能開発などを担当します。 CSE iOSの他にサーバー、Androidチームがあります。</p> <h2 id="CSE-iOSチームのメンバー">CSE iOSチームのメンバー</h2> <p>メンバー数は外部委託メンバーと含めて11名です。日本国籍以外にフィリピン、香港、中国、ベトナムの外国籍の人がおり、多様性のあるチームだと思います。</p> <h2 id="CSE-iOSチームの活動">CSE iOSチームの活動</h2> <h3 id="お客さんからのお問い合わせ対応">お客さんからのお問い合わせ対応</h3> <p>問い合わせの内容により、iOSアプリのみの対応をしても良い課題と、サーバー側と連携した対応が必要な課題があります。問い合わせの内容を追加で確認する必要があるとき、CSチーム経由でお客さんに確認していただきます。</p> <p>問い合わせの内容はさまざまです。仕様確認やデータの調査、また調査した結果で不具合との判断になった場合、不具合の起票をしてもらい、原因調査、修正など行います。</p> <p>課題を管理するJIRAでのコメントやTeamsのチャットで連絡をとります。週3回エスカレーション朝会があり、サーバー、Android、iOS、CSチームの代理者が参加し、重要な共有をするようにしています。 エスカレーション課題は社内用語であり、お客さんから優先度が高い問い合わせを意味します。</p> <p>お客さんの営業に影響する可能性があるので、問い合わせが届いたら優先して対応します。</p> <h3 id="QAチームや開発チームが発見した不具合の対応">QAチームや開発チームが発見した不具合の対応</h3> <p>リリースする前にQAチーム(Quality Assurance、検証部隊)がアプリの検証を行い、発生した不具合を報告してくれます。リリース予定と合わせて課題に優先度をつけて対応します。</p> <p>新しいiOSバージョンが公開される前に、動作確認が行われます。不具合が発見されたらCSEで修正します。</p> <h3 id="メンテナンス改修">メンテナンス・改修</h3> <p>開発用ツールのXcode, Visual Studioや言語、フレームワークなどのバージョンアップが出たときに検討、対応します。</p> <p>セキュリティ・品質を固めるため、必要に応じて新しい技術を適用する改修も行います。</p> <h2 id="プロジェクトの紹介">プロジェクトの紹介</h2> <p>CSE for iOSチームは担当するプロジェクトを紹介します。</p> <h3 id="担当するアプリ">担当するアプリ</h3> <ul> <li>CLOMO MDM (<a href="https://www.i3-systems.com">https://www.i3-systems.com</a>): iOSモバイルアプリとMacOSデスクトップアプリがあります。</li> <li>SECURED APPs (<a href="https://www.i3-systems.com/securedapps">https://www.i3-systems.com/securedapps</a>) :5つのアプリ</li> </ul> <p>担当するアプリが多い印象があるかもしれませんが、オーバーすることがないようにリリース予定と合わせてメンバーの課題を調整します。</p> <h3 id="使用している言語プラットフォームツール">使用している言語、プラットフォーム、ツール</h3> <ul> <li>言語:Objective-C, Swift, Xamarin.iOS C#</li> <li>IDE:Xcode, Visual Studio</li> <li>管理ツール:GitHub, Jira-Confluence</li> </ul> <h2 id="おまけわたしの1日を紹介">(おまけ)わたしの1日を紹介</h2> <p>フルフレックスタイム制なので6:00~22:00以内で会議の時間と合わせて勤務時間8時間に調整すれば、開始・休憩・終了時間は自由に取れます。2023年6月現在、原則週1日出社です。(例外あり)</p> <ul> <li><p><strong>10:00</strong>: 作業開始、メール、チャットと課題状況確認</p></li> <li><p><strong>10:30</strong>: CSE iOS朝会</p> <p> 毎日10~30分程度でQAチームの代理者からの検証状態など共有し、CSE iOSチーム内で課題状況の共有、問題の相談を行います。</p></li> <li><p><strong>11:00</strong>: 課題対応</p> <p> JIRAでアサインされる課題を優先度順で対応します。質問や相談事項があった時、随時にチームズのチャットや通話で連絡をとります。</p></li> <li><p><strong>12:00</strong>: 休憩</p> <p> 休憩を長くとってヨガスタジオに通ったり、冬に日光浴したりしに行ってきます。</p></li> <li><p><strong>14:00</strong>: 課題対応継続</p></li> <li><p><strong>15:00</strong>: エンジニアブログ書こう会</p> <p> 週1回、1時間程度でエンジニアブログを書く予定の人が集まり、ブログを書きます。参加が任意ですが、1時間ブログに集中できて書き方などについての相談も受けてくれますのでおすすめです。</p></li> </ul> <ul> <li><p><strong>17:00</strong>: オフィストレーニング</p> <p> 週1~2回、15分と30分バージョンがあります。<a href="https://tech.i3-systems.com/entry/2022/12/26/153838">在宅ワークによる運動不足解消のための取り組み</a>記事が公開されているので良ければご覧ください。</p></li> <li><p><strong>17:15</strong>: 課題対応継続</p></li> <li><p><strong>19:50</strong>: 日々報入力、1日の振り返り</p></li> <li><p><strong>20:00</strong>: 終了</p></li> </ul> <p>他にもさまざまなテーマで盛んに社内勉強会やイベントが開催されています。</p> <h2 id="おわりに">おわりに</h2> <p>関わるアプリとプラットフォームが多様にあるので、慣れるまで時間がかかるかもしれませんが、勉強できるものも多くあり、毎日楽しめます。</p> <p>一緒にコーディングを楽しむ仲間を探しています。興味のある方ぜひご応募お待ちしています。</p> <ul> <li>新卒採用:<a href="https://www.i3-systems.com/new-graduates/">https://www.i3-systems.com/new-graduates/</a></li> <li>キャリア採用:<a href="https://www.i3-systems.com/careers/">https://www.i3-systems.com/careers/</a></li> </ul> huong-i3 【Ruby】図解・継承チェーンとメソッド探索経路で迷わなくなるために hatenablog://entry/820878482937995227 2023-06-23T17:39:14+09:00 2023-06-23T17:39:14+09:00 執筆: Misaki-i3 まえがき メソッド探索経路を理解するためには、特異クラス・特異メソッド・クラスメソッドという、名前からして特殊そうな概念の把握が必要らしい。 それはそれは難解で恐ろしかろうと私は信じ、Ruby Silverをやりすごせる程度の理解に甘んじて、詳細な仕組みの整理を後回しにしてきた。 Ruby Goldの資格取得のためにいよいよ逃げられなくなり、震える足を踏み出して、何やら様子がおかしいと気付いた。 『特異クラス』は、『クラス』とほとんど変わらなかった。大きな違いは「何をインスタンスとみなしているか」だったのだ。 『特異メソッド・クラスメソッド』に至っては『インスタンス… <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/M/MisakiShiote-i3/20230602/20230602182021.png" width="1200" height="630" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span> 執筆: <a href="https://github.com/MisakiShiote-i3">Misaki-i3</a></p> <h2 id="まえがき">まえがき</h2> <p>メソッド探索経路を理解するためには、特異クラス・特異メソッド・クラスメソッドという、名前からして特殊そうな概念の把握が必要らしい。<br/> それはそれは難解で恐ろしかろうと私は信じ、Ruby Silverをやりすごせる程度の理解に甘んじて、詳細な仕組みの整理を後回しにしてきた。<br/> Ruby Goldの資格取得のためにいよいよ逃げられなくなり、震える足を踏み出して、何やら様子がおかしいと気付いた。</p> <p>『特異クラス』は、『クラス』とほとんど変わらなかった。大きな違いは「<strong>何をインスタンスとみなしているか</strong>」だったのだ。<br/> 『特異メソッド・クラスメソッド』に至っては『インスタンスメソッド』そのものだった。</p> <h3 id="対象レベル">対象レベル</h3> <p>この記事は、上の私の気付きを見て「当たり前のことだ」と感じられる方にとっては有意義でない。また、入門書を開いたばかりの初心者向きでもない。<br/> Rubyの入門書を一周した初心者には十分理解できるものと思う。<br/> 探り探り実装をこなしている中級者や、Ruby Goldの合格を目指している学習者にも役立てていただけると期待している。</p> <h3 id="注意">注意</h3> <p>クラスと継承の話をするには、以下のような概念を区別しなければならない。</p> <ul> <li>Class</li> <li>Classのインスタンス(=クラス)</li> <li>クラスのインスタンス(=Classのインスタンスのインスタンス)</li> </ul> <p>私の説明能力では、どうしても「クラス(=Classのインスタンス)のインスタンスの特異クラス」といった混沌が量産されてしまう。<br/> よって、この場に限り、『Classのインスタンス(=クラス)』のことを『クラスオブジェクト』と記述したい。<br/> おそらく、これは公式な用語ではない。</p> <p>また、記事の内容はRubyに限定した話であり、オブジェクト指向プログラミングの実現方法は言語によって異なることをご留意いただきたい。</p> <h2 id="準備運動-クラスオブジェクト">準備運動 クラスオブジェクト</h2> <h3 id="クラスはオブジェクト">クラスはオブジェクト</h3> <p>少なくともRubyにおいては、クラスオブジェクトはただのオブジェクトだ。<br/> 文字列がStringクラスのインスタンスオブジェクトであるように、クラスオブジェクトはClassクラスのインスタンスオブジェクトである。</p> <p>知ってのとおり、classキーワードでクラス定義を実行すると、クラス名の定数でクラスオブジェクトを呼び出せるようになる。<br/> これは、classキーワードがクラスオブジェクトを作成した際、指定された識別子と<strong>同名の定数にクラスオブジェクトの参照を代入する</strong>ためだ。<br/> classキーワードをClass.newに置き換えると簡単に理解できる。</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synPreProc">class</span> <span class="synType">Sample1</span>; <span class="synPreProc">end</span> <span class="synComment"># =&gt; nil</span> <span class="synType">Sample1</span> <span class="synComment"># =&gt; Sample1</span> <span class="synType">Sample2</span> = <span class="synType">Class</span>.new <span class="synStatement">do</span>; <span class="synStatement">end</span> <span class="synComment"># =&gt; Sample2</span> <span class="synType">Sample2</span> <span class="synComment"># =&gt; Sample2</span> </pre> <p>定数は単なる入れ物だ。クラスオブジェクトの参照さえ入っていれば、samやらhogeやらの変数からでも問題なく呼び出せる。</p> <h3 id="クラス名は定数名にすぎない">クラス名は定数名にすぎない?</h3> <p>「classキーワードに与えた識別子が定数名にすぎないのなら、なぜクラスオブジェクトを参照した際、クラス名(<code>Sample1</code>や<code>Sample2</code>)を返せたのか?」</p> <p>その答えは次のとおりだ。</p> <ul> <li><strong>定数に代入されるまで</strong>は、クラスオブジェクトは<strong>無名</strong>である</li> <li><strong>はじめて定数に代入されたとき</strong>、クラスオブジェクトはその<strong>定数名をクラス名として記憶</strong>する</li> </ul> <p>次のコードで、クラスオブジェクトが自分の名前を記憶するタイミングを検証した。</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink>sample3 = <span class="synType">Class</span>.new <span class="synComment"># =&gt; #&lt;Class:0x000000010743faa0&gt;</span> sample3 <span class="synComment"># =&gt; #&lt;Class:0x000000010743faa0&gt;</span> <span class="synType">Sample3</span> = sample3 <span class="synComment"># =&gt; Sample3</span> sample3 <span class="synComment"># =&gt; Sample3</span> <span class="synType">Sample3</span> == sample3 <span class="synComment"># =&gt; true</span> </pre> <p>(ちなみに) クラスオブジェクトを定数に代入→remove_constで定数を削除→同名の定数に別のクラスオブジェクトを代入→remove_constで……<br/> という処理を続けると、複数のクラスオブジェクトが同じ名前を名乗るという状態が実現できた。</p> <h2 id="Rubyの継承チェーンの全体像">Rubyの継承チェーンの全体像</h2> <p>クラスオブジェクトを中心とした継承関係を(できるだけ見やすく)図にまとめた。<br/> 白い四角は全てクラスオブジェクトだと考えてほしい。ClassもModuleも、特異クラス(<code>#</code>付きのもの)も、みなクラスオブジェクトだ。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_dfb12c4b2f123b9847d95c68898ee212.png" alt="継承チェーンの全体像" /></p> <p>注釈のとおり、すべてを暗記する必要はない。</p> <p>まずは2点だけ押さえておこう。</p> <ol> <li>基本は『クラスオブジェクトたち > Object > BaseObject』</li> <li>クラスメソッドの利用時には、特異クラスやClassが継承チェーンに絡んでくる</li> </ol> <p>モジュールについてはあとで説明するので、今は考えなくてよい。<br/> (気になる人のために結論だけ先に言っておくと、クラスに読み込まれたときだけメソッド探索経路にモジュールが追加される)</p> <h2 id="特異クラス特異メソッドクラスメソッドとは結局">特異クラス・特異メソッド・クラスメソッドとは結局……</h2> <p>『特異メソッド』と『クラスメソッド』という言葉が、「インスタンスメソッドではない、特別なものがあるらしい」という思い込みの源である</p> <h3 id="クラスと特異クラス">クラスと特異クラス</h3> <p>まずは『クラス』と『特異クラス』がどれだけ違うのかを確かめたい。</p> <p>結論はすでにまえがきに書いてしまった。</p> <blockquote><p>『特異クラス』は、『クラス』とほとんど変わらなかった。大きな違いは「<strong>何をインスタンスとみなしているか</strong>」だ。</p></blockquote> <p>具体的な違いを次の表に示す</p> <table> <thead> <tr> <th> </th> <th> クラス </th> <th> 特異クラス</th> </tr> </thead> <tbody> <tr> <td> インスタンスとみなすもの </td> <td> 自分がnewしたオブジェクト </td> <td> 特定のオブジェクト </td> </tr> <tr> <td> インスタンスとの関係<br />(呼び出し方) </td> <td> インスタンス.class </td> <td> インスタンス.singleton_class </td> </tr> </tbody> </table> <p>(ちなみに: instance_of?メソッドは、クラス.newで作られたインスタンスとクラスの関係判定にしか使えない)</p> <h3 id="特異メソッドとクラスメソッド">特異メソッドとクラスメソッド</h3> <p>まえがきに書いたもの繰り返す。</p> <blockquote><p>『特異メソッド・クラスメソッド』に至っては『インスタンスメソッド』そのものだった。</p></blockquote> <ul> <li>特異メソッドは、オブジェクトの特異クラスのインスタンスメソッドの別名</li> <li>クラスメソッドは、クラスオブジェクトの特異クラスのインスタンスメソッドの別名</li> </ul> <p>オブジェクトのメソッドを呼び出す命令を与えると、<br/> 特異クラスのインスタンスメソッド<u>(=特異メソッド)</u>から探索を開始する。<br/> <u>クラス</u>オブジェクトのメソッドを呼び出す命令を与えると、<br/> 特異クラスのインスタンスメソッド<u>(=特異メソッド =クラスメソッド)</u>から探索を開始する。</p> <p>ほぼ同じだな、と感じていただけただろうか。</p> <h3 id="特異クラスへのインスタンスメソッド定義">特異クラスへのインスタンスメソッド定義</h3> <p>これまでの理解を前提に、特異メソッドを定義するコードを見てみよう。<br/> 1) オブジェクトの特異クラスをオープンし、インスタンスメソッドを定義する</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synPreProc">class</span> &lt;&lt; <span class="synType">A</span> <span class="synPreProc">def</span> <span class="synIdentifier">method_open</span>; <span class="synPreProc">end</span> <span class="synPreProc">end</span> </pre> <p>2) defキーワードで、オブジェクトを指定して定義する</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synPreProc">def</span> <span class="synType">A</span>.<span class="synIdentifier">method_def</span>; <span class="synPreProc">end</span> </pre> <p>3) オブジェクトにdefine_singleton_methodで定義する</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synType">A</span>.define_singleton_method(<span class="synConstant">:method_meta</span>) {} </pre> <p>これらをclassキーワードによる定義内で行うと、見慣れた「クラスメソッド定義」となる。</p> <pre class="code lang-ruby" data-lang="ruby" data-unlink><span class="synPreProc">class</span> <span class="synType">A</span> <span class="synConstant">self</span> <span class="synComment"># A</span> <span class="synPreProc">class</span> &lt;&lt; <span class="synConstant">self</span> <span class="synPreProc">def</span> <span class="synIdentifier">method_open</span>; <span class="synPreProc">end</span> <span class="synPreProc">end</span> <span class="synPreProc">def</span> <span class="synConstant">self</span>.<span class="synIdentifier">method_def</span>; <span class="synPreProc">end</span> <span class="synPreProc">end</span> </pre> <p><code>class &lt;&lt; オブジェクト</code> や <code>def オブジェクト.</code>は特異クラスにアクセスするための大事な文法だ。「クラスメソッドを定義するやつ」という不十分な理解になっている場合は覚え直しておきたい。</p> <h2 id="メソッド探索経路">メソッド探索経路</h2> <p>ここからは教科書どおりの説明を繰り返すだけで十分だろうと思う。</p> <ol> <li>メソッド探索の開始地点は特異クラス<br />(※特異クラスにprependされたモジュールがある場合を除く。モジュールについては後述)</li> <li>特異クラスにメソッドが見つからなければ、探索経路を辿る</li> <li>最後まで見つからなければmethod_missingメソッドを呼び出す</li> </ol> <h3 id="クラスオブジェクトでないオブジェクトの場合">クラスオブジェクトでないオブジェクトの場合</h3> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_dd4492c45d532b065cd2348991bd29cb.png" alt="" /></p> <p>(オブジェクトaのことをインスタンスとみなしているのは、特異クラスaとクラスA)</p> <h3 id="クラスオブジェクトの場合">クラスオブジェクトの場合</h3> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_327f0ceab367dbfcf637ea011beac7f9.png" alt="" /></p> <p>(オブジェクトBのことをインスタンスとみなしているのは、特異クラスBとClass)</p> <h3 id="覚えておくべき経路">覚えておくべき経路</h3> <p>次の図に示す範囲は最低限覚えておきたい。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_676d073805b77a437add463221b1deb7.png" alt="" /></p> <h2 id="探索経路にモジュールを追加する">探索経路にモジュールを追加する</h2> <p>モジュールは、インスタンスから呼び出されるためのインスタンスメソッドを定義しておくものだ。つまり、クラスオブジェクトと基本は同じである。</p> <p>クラスと特異クラスの章で使った表に、モジュールの列を追加してみるとこうなる。</p> <table> <thead> <tr> <th> </th> <th> クラス </th> <th> 特異クラス </th> <th> モジュール </th> </tr> </thead> <tbody> <tr> <td> インスタンスとみなすもの </td> <td> 自分がnewしたオブジェクト </td> <td> 特定のオブジェクト </td> <td> 自分を読み込んだクラス<br />にとってのインスタンス </td> </tr> <tr> <td> インスタンスとの関係<br />(呼び出し方) </td> <td> インスタンス.class </td> <td> インスタンス.singleton_class </td> <td> - </td> </tr> </tbody> </table> <p>モジュールはクラスオブジェクトに読み込ませて使うものだ。もちろん、特異クラスにも読み込ませることは可能だ。<br/> クラスオブジェクトに読み込まれたモジュールは、クラスオブジェクトのインスタンスのメソッド探索経路に追加される。</p> <p>追加される位置は、読み込みに使うメソッドによって異なる。</p> <table> <thead> <tr> <th> メソッド </th> <th> </th> </tr> </thead> <tbody> <tr> <td> include </td> <td> クラスの後に追加する </td> </tr> <tr> <td> prepend </td> <td> クラスの前に追加する </td> </tr> <tr> <td> extend </td> <td> クラスの特異クラスの後に追加する </td> </tr> </tbody> </table> <p>extendメソッドを使うと、モジュールのメソッドをクラスメソッドとして追加できる。<br/> これは特異クラスでincludeメソッドを使って読み込むのと同じ動作だ。<br/> 「特異クラスをオープンする記述が省略できるよ!」というだけのものなので、怖がらないでほしい。</p> <p><u>includeやprependを2度以上記述したときの順番は、「<strong>新しい方が手前だ</strong>」と暗記するとよい。</u><br/> (※ <code>include M1, M2</code>のように1度に複数渡した場合は、第一引数側が手前になる)</p> <p>モジュールが探索経路に追加された状態を図にした。 <img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_d21f090abff548a7f977f0d10d92c0a5.png" alt="" /></p> <h2 id="まとめ">まとめ</h2> <p>『特異クラス』は、『クラス』とほとんど変わらなかった。大きな違いは「<strong>何をインスタンスとみなしているか</strong>」だったのだ。<br/> 『特異メソッド・クラスメソッド』に至っては『インスタンスメソッド』そのものだった。</p> <p>まえがきの繰り返しだ。<br/> 私が勝手に敵を大きく見積もっていたために遠回りをしてしまっただけとも言える。<br/> しかし、これから学習や試験対策を行う人々が自分と同じ遠回りをするのはもったいないので、私なりに継承チェーンと探索経路の整理と図解を行った。</p> <h2 id="あとがき">あとがき</h2> <p>「さき言うといてくれ」と呟きながら学習しています。<br/> 複数の参考書を行き来しながら、Webページをブラウザのタブに詰め込みながら、ようやく結び目が解ける情報にたどり着いて視界が開けたとき、「そうならそうと、さき言うてといてくれ」と怒ったふりをしています。</p> <p>参考書やWebページにある解説にも、筆者らの経験した「さき言うといてくれ」の気持ちが込められているはずなのです。<br/> 「あの内容を自分ならこんな説明で――」「あの記事に自分ならこんな注釈を――」<br/> 私が1冊の入門書から受け取りきれなかった穴を少しずつ埋めていけたのは、様々な人が「自分なら」をアウトプットしてくれたおかげであることは疑う余地もありません。</p> <p>弊社では開発部をはじめ、各部門の有志による勉強会が頻繁に開催されています。<br/> 発表資料は社員の経験と学習の成果! ときには発表者の「さき言うといてくれ」を感じます。</p> <p>私も誰かの役に立つことを期待して、アウトプットをこそこそ積ませてもらおうと思います。</p> <p>また、弊社では採用活動を実施しています。<br/> アウトプットの盛んな社内で、ともに技術の追求を楽しんでいける仲間をお待ちしております。</p> <p>新卒採用:<a href="https://www.i3-systems.com/new-graduates/">https://www.i3-systems.com/new-graduates/</a><br/> キャリア採用:<a href="https://www.i3-systems.com/careers/">https://www.i3-systems.com/careers/</a></p> MisakiShiote-i3 中途採用されたわたしの一ヶ月の旅 hatenablog://entry/4207575160647423163 2023-06-22T19:08:54+09:00 2023-06-22T19:08:54+09:00 こんにちは、モバイルアプリエンジニアを担当しているdate-i3です。 今回は、中途入社してからモバイルアプリエンジニアとして実際の業務に参加するまでの流れをお話しします。 わたしは前職でJavaを使ったWebシステム開発をしていました。そのためiOS開発については知識も経験もゼロという状態で入社しましたが、そんな人が現場に入るまでどのようなことをするのか知ってもらえたら幸いです。 サーバーサイドエンジニアの中途入社の流れについては、中途入社した私が開発現場に入るまでに受けた教育プランで紹介しています。 製品開発運用本部について知る 入社前に会社についてある程度のことは調べていたのですが、実際… <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/d/date-i3/20230531/20230531152648.png" width="1200" height="630" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span>こんにちは、モバイルアプリエンジニアを担当している<a href="https://github.com/date-i3">date-i3</a>です。</p> <p>今回は、中途入社してからモバイルアプリエンジニアとして実際の業務に参加するまでの流れをお話しします。 わたしは前職でJavaを使ったWebシステム開発をしていました。そのためiOS開発については知識も経験もゼロという状態で入社しましたが、そんな人が現場に入るまでどのようなことをするのか知ってもらえたら幸いです。</p> <p>サーバーサイドエンジニアの中途入社の流れについては、<a href="https://tech.i3-systems.com/entry/2022/10/31/132654">中途入社した私が開発現場に入るまでに受けた教育プラン</a>で紹介しています。</p> <h2 id="製品開発運用本部について知る">製品開発運用本部について知る</h2> <p>入社前に会社についてある程度のことは調べていたのですが、実際の組織の運用については全く分かりませんでした。 そんなわたしの配属先は製品開発運用本部というところ。名前が長いからか、PDOとみんな呼んでいます。</p> <p>研修のはじめは製品開発運用本部について、いろいろ説明会が開催されました。 仕事につかうツール(Teams、GitHub)の開発内ルール、日々の作業内容の報告の仕方、環境構築、部門長の自己紹介、製品開発運用本部の各グループの仕事内容の紹介、などなど、、、</p> <p>最初の数日は説明会で一日が終わります。 説明会の担当が部長1人だけだったので、1対1で説明を受けました。仲良く雑談タイムもあるのでそんなに緊張しないです。</p> <h2 id="製品について知る">製品について知る</h2> <p>自社製品についての理解も大事です。わたしはモバイルサイドエンジニアとして入社したので、うち何のアプリ作っているんだろう、、?の状態では困ります。 カスタマーサクセス部が出しているセミナー動画を見て製品について学びます。しかし手元に端末がなかったため、動画を眺めて知識を深めていきました。 このときに実際に製品に触ることができたらもっとよかったのに、、、 手を動かしたいタイプのわたしは、動画を見るばかりの時間にすこーーーし眠気を覚えることも。</p> <p>そんなこともあろうかと!説明の合間にちょっとリフレッシュしたくなったときは、オフィストレーニングを活用しましょう!詳しくは <a href="https://tech.i3-systems.com/entry/2022/12/26/153838">在宅ワークによる運動不足解消のための取り組み</a>で紹介しています。</p> <p>モバイル側のアプリだけでなくサーバー側のアプリについても説明があります。あの時は、へ〜こんなものがあるんだ〜(わかってない)となっていましたが、今ではわかるのでもう一度チャンスが欲しい、、、</p> <h2 id="iOSについて知る">iOSについて知る</h2> <p>いよいよ実践演習です。まずは環境構築。ローカル環境でアプリが動かせるように、ドキュメントを見ながらXcode、Visual Studio を入れて、ソースを落として、ビルドして、、、。エラーが出ても大丈夫!エラー対処のドキュメントが残っているからそれを見るもよし、先輩に丸投げしてもよし!</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_5cdf4d6d28e87ee0f2c1d2034a46c41c.png" alt="" /></p> <h2 id="Xamarinについて知る">Xamarinについて知る</h2> <p>お次はXamarin研修です。簡単なアプリを作ってC#の文法やiOS開発について学びます。アプリのライフサイクルとは何ぞや、の状態のわたしでしたが、先輩社員さんが優しく教えてくれました。何か困ったらすぐ質問していました。もちろん、ちゃんと自分で調べてから質問してましたよ、、?ただ今となれば、このときに調べる能力をもう少しつけていたら今そこまで困らなかったかなと思います。 Xamarin(C#) なのか、はたまたApple なのか。そのためにも、Xamarin開発について学びたかったなと思います。 (現場に入ってからXamarin開発についての勉強会がありました!)</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_3290f2819b6e17b8fefbaf69750ba388.png" alt="" /></p> <h2 id="業務について知る">業務について知る</h2> <p>研修の仕上げとして、最後にiOSアプリの調査課題を3つほど取り組んでいきます。Apple に起因するものなのか、ソースコードが原因なのか、切り分けて調査するので一番実務に近い研修になっています。 ソースコードの調査はどこかに答えがあるのでまだ楽ですが、iOSの仕様を調査することは難しかったです。公式ドキュメントは英語なので読解力が求められます。(Google翻訳に頼ると謎の日本語が完成します) また、検索ワードも工夫する必要がありました。例えば「ダークモード iOS」のように単純に調べると、ダークモードのやり方が出てきて実際どのように実装するのかはなかなか出てきません。情報収集力が必要です。</p> <h2 id="研修終了">研修終了</h2> <p>1ヶ月ほどの研修期間を終えると、ついに実務作業へ入ります。しかしご安心ください、いきなり難しい課題を任せられることはありません。簡単な課題からやっていき、文法、iOSの仕様を学びながら徐々にできることを増やしていく感じです。 最初のうちは研修時と変わらず先輩を質問攻めしていましたが、先輩方の態度は変わらず優しく答えていただきました。 入社してそろそろ1年になるわたしですが、なんとアプリのライフサイクルとは何かなんとなく答えることができるところまで成長しています。</p> <h2 id="まとめ">まとめ</h2> <p>今回は中途入社してから業務に参加するまで、モバイルアプリエンジニアの流れを簡単にお話ししました。 教育プランの見直しは随時行われるため、変わっている部分もあるかもしれませんが参考になれば嬉しいです。</p> <p>最後に、弊社では採用活動を実施しています。皆さまのご応募をお待ちしております。</p> <p>新卒採用:<a href="https://www.i3-systems.com/new-graduates/">https://www.i3-systems.com/new-graduates/</a> <br> キャリア採用:<a href="https://www.i3-systems.com/careers/">https://www.i3-systems.com/careers/</a></p> date-i3 RubyKaigi 2023に現地参加にして良かったこと hatenablog://entry/820878482941354918 2023-05-18T20:50:51+09:00 2023-11-01T21:48:28+09:00 RubyKaigiに参加してきた様子をお届けします。 <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_27e61145232ce28de0005c799df6f284.jpg" alt="" /></p> <p>はじめまして、アイキューブドシステムズでサーバーサイドのエンジニアとして働いている<a href="https://github.com/imamura3i">imamura</a>です。</p> <p>アイキューブドシステムズがGold Sponsorとして協賛させていただいた<a href="https://rubykaigi.org/2023/about/">RubyKaigi 2023</a>にエンジニア4人で現地参加してきました!舞台は長野県松本市です。</p> <p>周りを見渡せば、高い山々に囲まれていて、自然を間近に感じられる素敵なところでした。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_585fab99382105e44c37ae9f9be132a7.jpeg" alt="" /></p> <p>感想も交えて参加前の準備や現地参加の魅力、セッションについて共有したいと思います。</p> <ul> <li>参加前にした方が良いこと</li> <li>現地参加のメリット <ul> <li>コミュニケーションの大切さを再認識できる</li> <li>興味を引く宣伝方法や採用戦略について考えるきっかけができる</li> <li>美味しいものを食べられる</li> </ul> </li> <li>印象に残ったセッション</li> </ul> <h2 id="参加前にした方が良いこと">参加前にした方が良いこと</h2> <p>参加を検討される方は学びに貪欲な方だと思います。その学びや経験を最大化するために必要だと感じたことを2つ挙げます。</p> <p><strong>1. セッション内容の予習</strong><br /> 専門性の高いセッションが多いので、背景知識がないとついていけなくなる可能性があります。セッションの概要はイベントのWebサイトで事前に公開されるため、タイトルや概要を確認し、知らない用語を調べるなどして背景知識を整えておくことで、理解がスムーズに進むと思います。</p> <p><strong>2. 英語力向上</strong><br /> セッションは日本語と英語、半々くらいでした。興味のあるセッションが英語の場合、しっかり聞き取って理解を深めるためにもリスニング力は必要です。また、スライドは見た限り全て英語で書かれていたため、リーディング力も必要だと思いました。 さらに、スピーキング力も高めることでRubyKaigiに参加している外国籍のRubyistの方々ともコミュニケーションを取ることができ、より有意義な時間を過ごせると思います。</p> <h2 id="現地参加のメリット">現地参加のメリット</h2> <h3 id="コミュニケーションの大切さを再認識できる">コミュニケーションの大切さを再認識できる</h3> <p>弊社は、コロナの感染拡大が落ち着いてきた頃にフルリモートワークから原則週1出社(例外あり)に変わりました。フルリモートワークよりも質問をするハードルが下がり、一人で悩み込んで時間をかけすぎてしまうことが減りました。また、雑談をする機会が増えて、社内のコミュニケーションが円滑になったと実感しています。</p> <p>RubyKaigiでも、Official PartyやAfter Party、ブース訪問でコミュニケーションの機会がありました。ブース訪問では、 どんなプロダクトを作っているか、社内コミュニケーションツールは何か、Rubyのバージョンアップ時の苦労話など、情報交換を活発に行いました。自社の成長につながる新たなアイデアや知見を得ることができました。</p> <p>今回のイベントでますますコミュニケーションの大切さを再認識できました。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_cfb53d95f57f8b719bc07df50583d4bb.jpg" alt="" /></p> <div style="text-align: center;"> Official Partyの様子 </div> <h3 id="興味を引く宣伝方法や採用戦略について考えるきっかけができる">興味を引く宣伝方法や採用戦略について考えるきっかけができる</h3> <p>RubyKaigiに参加して印象に残っている会社を紹介しようと思います。<br /> 株式会社ZOZOさんがノベルティで配布していたZOZOMATは、上に足を置いて、スマホで簡単に足の3Dサイズが計測でき、さらに適切な靴選びが可能になるという画期的なものです。技術力をアピールし、自社で得られるエンジニアスキルをイメージしやすくすることで、会社にマッチしたエンジニアの応募増加を狙っていると思いました。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_a313ad129c9e07d3aaff668e7f7ae82c.jpg" alt="" /></p> <p>また、セッション前にPRしているある会社のCMは非常にインパクトがあり、記憶に残るものだったので、今後CM製作をすることがあれば、参考したいと思いました。</p> <p>ブースでは、ステッカーやTシャツ、お菓子などの様々なノベルティが配られていたので、どのような狙いでそのノベルティを製作しているか考える機会になりました。 会社のロゴ入りTシャツを配布している会社は、イベント後もTシャツを着ることによる継続的周知を狙っているかもしれません。 また、食べ物を用意している会社は、食べ物でたくさんの人を集めて、興味深いブース出展で印象を残す戦略かもしれません。 戦略はそれぞれですが、興味・関心の獲得、周知のために何が必要かを考えるきっかけになる非常に良い機会でした。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_0340fc7635e652337557c393b7f9fca8.jpg" alt="" /></p> <h3 id="美味しいものが食べられる">美味しいものが食べられる</h3> <h5 id="お弁当の紹介">お弁当の紹介</h5> <p>初現地参加のため、勝手が分からず、お昼ご飯はどうするべきか迷っていましたが、全日程でお弁当が用意されていて、外に食べに行く必要はありませんでした。</p> <p>4種類ほどから選ぶことができました。写真のお弁当は、ベジタリアンの方も食べれるように用意されていたもので、野菜だけでもお米が進みました。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_85a8671e487e80ffe6f1895b8a53b3ad.jpeg" alt="" /></p> <h5 id="After-Party">After Party</h5> <p>立食形式で、色々な方々とコミュニケーションを取って楽しみました。Official Partyで知り合えた方と再会し、話が弾みました。このような出会いは本当に大切にしたいです。 食べ物は唐揚げ・焼き鳥・たこ焼き・馬刺し・鹿肉など、どれをとっても絶品でした。松本市に行かれる方はぜひ行ってみてください。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fmatsumoto-yokocho.jp%2F" title="松本つなぐ横丁|長野県最大級の飲み歩き横丁です!|居酒屋文化を信州から世界に!" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://matsumoto-yokocho.jp/">matsumoto-yokocho.jp</a></cite></p> <h2 id="印象に残ったセッション">印象に残ったセッション</h2> <p>そもそもどんなセッションがあるのか気になる方のために、参考までに今回参加して印象に残ったセッションを紹介します。</p> <h3 id="Introduction-of-new-features-for-VS-Code-debugging"><a href="https://rubykaigi.org/2023/presentations/ono-max.html#day2">Introduction of new features for VS Code debugging</a></h3> <p>VS Codeのデバッグのための2つの新機能Trace InspectorとDebug Visualizerの紹介です。<br /></p> <p>詳しくは上のリンクに飛んでいただけますと幸いですが、これらの新機能により、様々なメリットがあると思いました。 例えば、コードデバッグとトラブルシューティングです。 プログラムが期待通りに動作せず、特に複雑なデータ構造の場合、デバッグが難しくなることがあります。Debug Visualizerは、変数の内容やデータ構造を視覚化するため、問題を素早く特定しやすくします。例えば、配列やハッシュの中身をグラフやテーブルとして表示することで、データの変化やパターンを把握しやすくなります。</p> <p>その他にもコードレビューやドキュメント作成などにも活用できそうです。</p> <h3 id="Eliminating-ReDoS-with-Ruby-32"><a href="https://rubykaigi.org/2023/presentations/lmt_swallow.html#day2">Eliminating ReDoS with Ruby 3.2</a></h3> <p>Ruby3.2では正規表現のマッチングに修正が入り、ReDosの脆弱性がほぼほぼ解決されたという内容です。<br /> ReDosとは、正規表現の分岐処理の際にバックトラックが増えてしまう脆弱性を利用した攻撃のことです。セッションでは、実際に入力値に対して条件分岐が走り、指数関数的に検索時間が増えることで起こるReDos脆弱性のケーススタディを見ることができました。 セキュリティや安定性、パフォーマンス、信頼性、保守性、コード品質の向上を期待でき、嬉しいことづくしだと思い、興味が湧きました。</p> <h2 id="感想">感想</h2> <p>セッション内容・交流・食べ物・景色など全てのことを楽しむことができる現地参加は最高でした。<br /> Rubyを作っている方とお会いできたり、社外のエンジニアの方との繋がりも作ることができて、とても有意義な時間を過ごせました。 大いに刺激を得て、新たな知識や今後のブース出展のヒントも得られたので、会社に持ち帰って今後に活かしたいと思います。</p> <p>来年は沖縄で開催されます。 興味ある方はぜひRubyKaigiに現地参加してみてはいかがでしょうか!</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_4c3e73bb00d955a66471e4de7f5dc8ce.jpg" alt="" /></p> <h2 id="最後に">最後に</h2> <p>株式会社アイキューブドシステムズでは、一緒に成長していける仲間を募集しています。</p> <p>また、カジュアル面談・エントリーも、下記のページから随時受け付けています。</p> <p>新卒採用  <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.i3-systems.com%2Fnew-graduates%2F" title="新卒採用|株式会社アイキューブドシステムズ" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.i3-systems.com/new-graduates/">www.i3-systems.com</a></cite></p> <p>キャリア採用 <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.i3-systems.com%2Fcareers%2F" title="採用情報|株式会社アイキューブドシステムズ" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.i3-systems.com/careers/">www.i3-systems.com</a></cite></p> imamura-i3 Play Integrity APIへの移行 hatenablog://entry/4207112889986105692 2023-05-08T12:36:07+09:00 2023-05-08T12:36:07+09:00 はじめに アイキューブドシステムズで製品開発運用本部の製品開発部に所属している kazuya-oota です。 Google から提供されているSafetyNet Attestation APIの廃止により、CLOMOが提供するAndroid向けの機能の一つが将来的に利用不可となることがわかりました。 SafetyNet Attestation APIには後継となるPlay Integrity APIがリリースされています。今回の記事はこのSafetyNet Attestation API からPlay Integrity APIの移行についてご紹介します。 SafetyNet Attesta… <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_1d15331e8e3082db15fa7638c988f0eb.png" alt="" /></p> <h2 id="はじめに">はじめに</h2> <p>アイキューブドシステムズで製品開発運用本部の製品開発部に所属している <a href="https://github.com/kazuya-oota">kazuya-oota</a> です。 Google から提供されているSafetyNet Attestation APIの廃止により、CLOMOが提供するAndroid向けの機能の一つが将来的に利用不可となることがわかりました。 SafetyNet Attestation APIには後継となるPlay Integrity APIがリリースされています。今回の記事はこのSafetyNet Attestation API からPlay Integrity APIの移行についてご紹介します。</p> <h2 id="SafetyNet-Attestation-APIって何">SafetyNet Attestation APIって何?</h2> <p><a href="https://developer.android.com/training/safetynet/attestation?hl=ja">SafetyNet Attestation API</a> は Googleから無料で提供されているAPIです。このAPIはアプリが動作しているAndroid デバイスをアプリの開発者が評価することができ、チートやアプリの改ざんといった不正利用の防止に利用します。 これは単純なルート化をチェックする機能ではありません。複数の情報からデバイスの完全性を判断するものです。</p> <p>この<a href="https://developer.android.com/training/safetynet/attestation?hl=ja#overview">フロー</a>は以下のようになっています。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_e4ebcd34af3d65b4e37c5af3a6d3317c.png" alt="" /></p> <ol> <li>サーバーまたはアプリでNonce<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>を生成して、アプリはSafetyNet Attestation API を呼び出す。</li> <li>SafetyNet Attestation サービスは、アプリの実行環境を評価し、Google のサーバーに評価結果をリクエストする。</li> <li>Google のサーバーは、評価結果を SafetyNet Attestation サービスに送信する。</li> <li>アプリはSafetyNet Attestation サービスからの検証情報<sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup>を取得する。</li> <li>アプリはサーバーにSafetyNet Attestation APIの検証情報(とNonce)を送信する。</li> <li>サーバーは受信した検証情報を解析して不正判断をする。また、その検証結果をアプリに送信する。 この1.のAPI呼び出しには、Google Cloud Projectから発行されたAPIキーが必要になります。 詳しい手順は<a href="https://developer.android.com/training/safetynet/attestation?hl=ja#obtain-api-key">API キーを取得する</a>にあります。 ・・・ですが、既に(2023年1月以降)新規開発者の登録は終了しています。</li> </ol> <p>SafetyNet Attestation APIの検証情報は以下のようなJSON形式のデータです。 これらの具体的な内容は<a href="https://developer.android.com/training/safetynet/attestation?hl=ja#use-response-server">SafetyNet Attestation APIの検証情報</a>で説明されています。</p> <pre class="code" data-lang="" data-unlink>{ &#34;timestampMs&#34;: 9860437986543, &#34;nonce&#34;: &#34;R2Rra24fVm5xa2Mg&#34;, &#34;apkPackageName&#34;: &#34;com.package.name.of.requesting.app&#34;, &#34;apkCertificateDigestSha256&#34;: [&#34;base64 encoded, SHA-256 hash of the certificate used to sign requesting app&#34;], &#34;ctsProfileMatch&#34;: true, &#34;basicIntegrity&#34;: true, }</pre> <p>また、SafetyNet Attestation はサポート終了が発表されており、ロードマップは以下のようになっています。 サポートの終了についての詳細は<a href="https://developer.android.com/training/safetynet/deprecation-timeline">Discontinuing the SafetyNet Attestation API</a>で説明されています。</p> <table> <thead> <tr> <th> 年月日 </th> <th> 内容 </th> </tr> </thead> <tbody> <tr> <td> 2022年6月 </td> <td> SafetyNetAttestation API 終了が発表。 </td> </tr> <tr> <td> 2022年11月 </td> <td> deprecationInformation フィールド追加<br>開発者向けの非推奨の情報が含まれます。 </td> </tr> <tr> <td> 2023年1月 </td> <td> 新規登録終了<br>2023年1月31日以降、新規開発者の登録が終了。 </td> </tr> <tr> <td> 2023年6月 </td> <td> <strong>移行期限</strong><br>本番アプリがPlay Integrity APIに移行している場合は、引き続きSafetyNet Attestation APIは利用可能。 </td> </tr> <tr> <td> 2024年6月 </td> <td> SafetyNet Attestation APIはすべてのバージョンのアプリで利用不可。 </td> </tr> </tbody> </table> <h2 id="Play-Integrity-APIへの移行">Play Integrity APIへの移行</h2> <p>先に述べたSafetyNet Attestation API は Play Integrity APIに統合されました。 Play Integrity APIでは3つの項目を検証をすることができます。</p> <ul> <li>正規のアプリ <ul> <li>Google Play にアップロードされた改変されていないアプリかどうかを判断します。</li> </ul> </li> <li>正規の Play インストール <ul> <li>現在のユーザー アカウントにライセンスが付与されているかどうか(つまりユーザーが Google Play でアプリまたはゲームのインストールや支払いを行ったかどうか)を判断します。</li> </ul> </li> <li>正規の Android デバイス <ul> <li>Google Play 開発者サービスを搭載した正規の Android デバイスかどうかを示します。</li> </ul> </li> </ul> <p>SafetyNet Attestation APIを利用している場合は、Play Integrity APIへの移行は簡単です。 これはPlay Integrity APIを使用するアプリがGoogle Playで公開されたパブリックなアプリか、公開されていないプライベートなアプリかで有効化する方法が異なります。</p> <ul> <li>Google Play で公開されている場合 <ul> <li>Google Play Console から設定します。これは [設定] > [アプリの完全性] の [Integrity API]タブから行います。</li> </ul> </li> <li>Google Play で公開されていない場合 <ul> <li>Google Cloud ProjectのAPIを有効化することが利用可能になります。<a href="https://developer.android.com/google/play/integrity/setup?hl=ja#apps-exclusively-distributed-outside-google-play">Google Play 以外で独占配信されているアプリ</a>または<a href="https://developer.android.com/google/play/integrity/setup?hl=ja#sdks">Play Integrity API を使用する SDK</a>に手順があります。</li> </ul> </li> </ul> <p>Play Integrity API の<a href="https://developer.android.com/google/play/integrity/overview?hl=ja#api-usage">フロー</a>はSafetyNet Attestation APIからほとんど変わりはありません。 <img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_8334fd961215783757b4b616504db3f0.png" alt="" /></p> <ol> <li>サーバーまたはアプリでNonceを生成して、アプリはPlay Integrity API を呼び出す。</li> <li>アプリはPlay Integrity APIから検証情報(token)<sup id="fnref:3"><a href="#fn:3" rel="footnote">3</a></sup>を取得する。</li> <li>アプリはサーバーにPlay Integrity APIの検証情報(とNonce)を送信する。</li> <li>サーバーはGoogle Playサーバーまたは自身のサーバーで検証情報を復号する。</li> <li>サーバーは受信した検証情報を解析して不正判断をする。また、その検証結果をアプリに送信する。</li> </ol> <p>Play Integrity APIでは検証情報が暗号化される変更がありました。 サーバーはこれを復号する必要があり、これには2つの方法が提供されています。</p> <ul> <li>自前のサーバーで復号する方法</li> <li>Google サーバーに復号を任せる方法(Googleの推奨方法)</li> </ul> <p>自前のサーバーで復号する方法を使用する場合にはGoogle Playでアプリが公開されていることが条件です。どちらを選ぶかはサービスに依存すると思いますが、両方を試してから決定するとよいでしょう。</p> <p>復号した検証情報は、ペイロードと呼ぶJSON形式のデータが含まれます。 これらは<a href="https://developer.android.com/google/play/integrity/verdict?hl=ja#returned-payload-format">返されるペイロードの形式</a>に詳細が解説されています。</p> <pre class="code" data-lang="" data-unlink>{ requestDetails: { ... } appIntegrity: { ... } deviceIntegrity: { ... } accountDetails: { ... } }</pre> <p>それぞれのフィールドには以下のような情報が含まれます。</p> <ul> <li>requestDetailsはAPIのリクエストに指定した情報が含まれます。</li> <li>appIntegrityはパッケージに関する情報が含まれます。</li> <li>deviceIntegrityはデバイスがアプリの完全性の強度が含まれます。</li> <li>accountDetailsはアプリのライセンスまたは利用資格のステータスが含まれます。</li> </ul> <h2 id="検証情報のマッピング">検証情報のマッピング</h2> <p>SafetyNet Attestation APIとPlay Integrity APIの検証情報に含まれるJSONデータの構造は全て異なります。 そのため、SafetyNet Attestation APIの検証情報とPlay Integrity APIの検証情報の対比にはそれぞれに対応するパラメータが何かを明確にしてマッピングする必要があります。</p> <p>これは<a href="https://developer.android.com/google/play/integrity/migrate?hl=ja#api-response-mapping">API レスポンスのマッピング</a>に詳しく解説されています。 <img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_3735f9bca45c58618f119f7245e8c274.png" alt="" /></p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_b35e6169df7837d1c7270ced0f2b61a2.png" alt="" /></p> <p>例えば、SafetyNet Attestation APIで判断できた最も強度の高いデバイスのペイロードは以下のようになります。</p> <ul> <li>ctsProfileMatch = true</li> <li>basicIntegrity = true</li> <li>evaluationType に HARDWARE_BACKEDを含む</li> </ul> <p>これをPlay Integrity APIで同じ判断をするには以下のようになります。</p> <ul> <li>deviceIntegrityに MEETS_STRONG_INTEGRITY, MEETS_DEVICE_INTEGRITY,MEETS_BASIC_INTEGRITYを含む</li> </ul> <p>これらのマッピングはすべて表に載っているため、サービスの実装に合わせた改修を行うこととなります。</p> <p>デバイスの完全性判定は、Google PlayからPlay Integrity APIを有効化している場合に追加のオプションが設定できます。SafetyNet Attestation APIの実装と完全に合わせるにはこれが必要な場合があり、先程の例に挙げたマッピングを行うためにはGoogle Play Consoleから設定する必要があります。 <img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_58ca05b3faaa1d4b08c59db594f73d1f.png" alt="" /></p> <p>オプションの説明は以下の通りになります。</p> <ul> <li>MEETS_STRONG_INTEGRITY <ul> <li>MEETS_DEVICE_INTEGRITYに加えてKey Attestation(鍵構成証明)を利用する。</li> </ul> </li> <li>MEETS_BASIC_INTEGRITY <ul> <li>基本的なシステム完全性チェックに合格したデバイスで動作しているがAndroid の互換性要件を満たしておらず、Google Play 開発者サービスの実行を承認されていない可能性がある。</li> </ul> </li> </ul> <h2 id="移行にあたって">移行にあたって</h2> <p>Play Integrity APIへの移行にあたって、発生したトラブルなどを紹介します。</p> <h3 id="互換性要件を満たしたデバイスでペイロードがおかしい問題">互換性要件を満たしたデバイスでペイロードがおかしい問題</h3> <ul> <li>事象 Pixel 5a(Android 11)で確認時に、異常なペイロードがPlay Integrity APIから取得できてしまう。 デバイス完全性(deviceRecognitionVerdict)が空、アプリ情報(appIntegrity)にpackageNameやその他も無く、評価するためのペイロードが十分ではない。 デバイス側はPlay Integrity APIのAPIの呼び出しでエラーなどは発生していない。</li> <li>解決 Google Play 開発者サービス、Google Playのアップデートを実施で解決。Play Integrity APIにはこれらのパッケージが影響することがわかった。</li> </ul> <p>個人利用のデバイスで定期的にアプリなどをアップデートしている場合は発生しないが、デバイスのファクトリーリセット直後などでGMSに関連するパッケージが更新されていないと問題が発生することがわかりました。 ただし、これはデバイスに依存するようでPixel 6(Android 13)などでは発生しませんでした。</p> <h3 id="バージョンの古いアプリとの共存">バージョンの古いアプリとの共存</h3> <p>Androidやモバイルの宿命ではありますが、デバイスごとにアプリのバージョンが異なるという問題が発生します。 すべてのユーザーに常に最新バージョンのアプリを利用してもらうことは難しく、インストールされたAndroidデバイスごとにバージョンが異なるといったことが起きます。</p> <p>この問題を解決するための方法としては、アプリ自身にバージョンチェック機能をもたせます。</p> <ul> <li>アプリ起動時に外部サーバーと通信してバージョンチェックをする。</li> <li>バージョンチェックに失敗すると起動フローを中止し、ユーザーに更新を促す。</li> <li>バージョンチェックに成功すると起動する。</li> </ul> <p>この機能は全てのアプリで機能するとは限りません。なぜなら、これらはアプリを利用するにはユーザーが明示的に起動する必要があるためです。</p> <p>バージョンチェック機能を持たない、初期設定後はバックグラウンドで動作する、SafetyNet Attestation APIの検証が必須機能ではない、などの場合にはアプリのアップデートを強制することができません。 今回対応を行ったアプリはこちらにあたるため、SafetyNet Attestation APIとPlay Integrity APIの共存が必要になりました。</p> <p>アプリの特性にもよりますが、可能な限りアプリはアップデートを強制することがよいでしょう。それが難しい場合にはSafetyNet Attestation APIが完全に終了する2024年6月までにユーザーにアップデートをしてもらえるよう適切にアナウンスする必要があります。</p> <h2 id="最後に">最後に</h2> <p>Googleのシステムの進化により、APIが統合されたことでこの対応を行いました。 単純な切り替えができると考えていましたが、実際に動かすことで見つかる課題も多くありました。</p> <p>当社では、システム開発を通じて、問題を自らで調べ、考え、周りと協調して解決できる人材を募集しています。 カジュアル面談・エントリーは以下で随時受け付けています。</p> <ul> <li>新卒採用 <ul> <li><a href="https://www.i3-systems.com/new-graduates/">https://www.i3-systems.com/new-graduates/</a></li> </ul> </li> <li>キャリア採用 <ul> <li><a href="https://www.i3-systems.com/careers/">https://www.i3-systems.com/careers/</a></li> </ul> </li> </ul> <div class="footnotes"> <hr/> <ol> <li id="fn:1"> 検証ごとに生成する一意の値。(<a href="https://developer.android.com/training/safetynet/attestation?hl=ja#obtain-nonce">詳細</a>)<a href="#fnref:1" rev="footnote">&#8617;</a></li> <li id="fn:2"> <a href="https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-signature-36">JWS</a>で表現されるデータであり、暗号化されていない。<a href="#fnref:2" rev="footnote">&#8617;</a></li> <li id="fn:3"> <a href="https://datatracker.ietf.org/doc/html/rfc7516">JWE</a>で表現されるデータで、暗号化されている。<a href="#fnref:3" rev="footnote">&#8617;</a></li> </ol> </div> oota-i3 松本出身のエンジニアがrubykaigiに合わせて松本のお店を紹介するエントリ hatenablog://entry/4207112889984675937 2023-05-01T11:44:54+09:00 2023-05-01T13:16:12+09:00 祝 rubykaigi2023 in Matsumoto こんにちは。アイキューブドシステムズ所属、パソコンに詳しい人の市川です。 当社で開発しているCLOMOはサーバサイドテクノロジスタックとして長らくrubyを使っているため、rubykaigiの動向については毎年注視しておりますが、2023年の開催はリベンジの松本になったという大変うれしい知らせが飛びこんできました! ご存じとは思いますが、一度2020年に一度松本開催が決まっていたのですが、例のやつで中止(まあ、オリンピックも開催しなかったくらいですし)・・・。その後のオンサイト開催も三重になったりで、松本にはもう来ないのかなあ・・・など… <h1 id="祝-rubykaigi2023-in-Matsumoto">祝 rubykaigi2023 in Matsumoto</h1> <p>こんにちは。アイキューブドシステムズ所属、パソコンに詳しい人の市川です。 当社で開発しているCLOMOはサーバサイドテクノロジスタックとして長らくrubyを使っているため、rubykaigiの動向については毎年注視しておりますが、2023年の開催はリベンジの松本になったという大変うれしい知らせが飛びこんできました!</p> <p>ご存じとは思いますが、一度2020年に一度松本開催が決まっていたのですが、例のやつで中止(まあ、オリンピックも開催しなかったくらいですし)・・・。その後のオンサイト開催も三重になったりで、松本にはもう来ないのかなあ・・・などと思っていたところだったので、この松本開催は非常にうれしかったですね。</p> <p>私、今でこそ福岡に拠点を構える会社に勤務しておりますが、生まれも育ちも長野県松本市(ちなみに当社で長野県出身は私しかいない)。高校を卒業するまで松本におりましたが、住んでいたことからいい街だな、と思っていましたのでたくさんのrubyistに松本のご紹介をいろいろしようかなと思い筆を取りました。</p> <p>各社様から、松本のお店紹介のblogのエントリが出ているのを拝見して、私も住民だった目線から、松本のいろいろなお店をご紹介したいと思います。</p> <h1 id="そば">そば</h1> <p>実は住んでいたころから、店で蕎麦を食べる機会などほとんどなかったので、行ったことがほぼないんです。だいたいそばといえば家で母親が茹でて作ってる、っていう。なんで、松本に滞在する人で調理器具が使える環境(AirBnBとか)であれば、ぜひスーパーで「古城そば」を購入して茹でてください。うちの実家ではこれ一択でした。茹ですぎないように注意さえすれば、東京などで下手な店でそば食べるより数段上のそばが食べられます。 多分どこのスーパーでも扱いあると思います。駅近くであれば、デリシアがバスターミナルビルの地下にあるのでそこに売っていると思います。会場近くであればイオンモール松本のイオンでも売っているかと。</p> <p>デリシア松本駅前店</p> <iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3218.384374800962!2d137.96417987503435!3d36.23015569962673!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x601d0e8c777fa6c9%3A0xee0421f5c60c87e0!2sDELiCiA%20Matsumoto%20Ekimae!5e0!3m2!1sen!2sjp!4v1681442650062!5m2!1sen!2sjp" width="400" height="300" style="border:0;" allowfullscreen="" loading="lazy" referrerpolicy="no-referrer-when-downgrade"></iframe> <p>イオンモール松本</p> <iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d1609.1213718692445!2d137.97724549123848!3d36.233596824864115!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x601d0e951f5a319d%3A0xc3cba583b5317f2b!2sAeon%20Style%20Matsumoto!5e0!3m2!1sen!2sjp!4v1681442611088!5m2!1sen!2sjp" width="400" height="300" style="border:0;" allowfullscreen="" loading="lazy" referrerpolicy="no-referrer-when-downgrade"></iframe> <p>なんとメーカーさんのHPが公開されてますね!</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fkumagaiseimen.jp%2F" title="熊谷製麺" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://kumagaiseimen.jp/">kumagaiseimen.jp</a></cite></p> <p>お土産にもいいとは思いますが、そもそもお土産用のそばとは違い、生麺でスーパーでも冷蔵コーナーに売っているので難しいかも。</p> <p>お店でということであれば、小木曽製粉所で十分かと思います。大盛りまで追加料金なしの500円。 だいたいそばってのは、もりもり食べるものだと思ってて、東京とかの白いそばがざるにうすーく張り付いているのを見ると、悲しくなります。小木曽製粉所も十分おいしいです。前述イオンモールのフードコードに入っているのと、松本駅出てすぐのところにもお店あります。</p> <div><strong><a target="_blank" href="https://tabelog.com/nagano/A2002/A200201/20018212/">小木曽製粉所 松本駅前店</a> </strong><br> <script src="https://tabelog.com/badge/google_badge?escape=false&rcd=20018212" type="text/javascript" charset="utf-8"></script> </div> <p><p style="color:#444444; font-size:12px;"></p> <p>市内であれば観光ガイドなどでよく紹介されていると聞いたことあるのはもとき、とか女鳥羽そばですかね。両方とも行ったことないんでわかりません笑 リンクだけ貼っときますね。</p> <div><strong><a target="_blank" href="https://tabelog.com/nagano/A2002/A200201/20000047/">もとき 開智店</a></strong><br> <script src="https://tabelog.com/badge/google_badge?escape=false&rcd=20000047" type="text/javascript" charset="utf-8"></script> </div> <p style="color:#444444; font-size:12px;"> <strong>関連ランキング:</strong><a href="https://tabelog.com/rstLst/soba/">そば(蕎麦)</a> | <a href="https://tabelog.com/nagano/A2002/A200201/R3207/rstLst/">北松本駅</a></p> <div><strong><a target="_blank" href="https://tabelog.com/nagano/A2002/A200201/20000104/">女鳥羽そば</a></strong><br> <script src="https://tabelog.com/badge/google_badge?escape=false&rcd=20000104" type="text/javascript" charset="utf-8"></script> </div> <p style="color:#444444; font-size:12px;"> <strong>関連ランキング:</strong><a href="https://tabelog.com/rstLst/soba/">そば(蕎麦)</a> | <a href="https://tabelog.com/nagano/A2002/A200201/R9297/rstLst/">松本駅</a></p> <p>もし足を伸ばせるのであれば、安曇野市になりますがあさ川というお店がおすすめです。多分お昼ちょうどとかだと売り切れてるかなと思いますが。庭があり、秋には庭の散策も楽しめます。</p> <div><strong><a target="_blank" href="https://tabelog.com/nagano/A2005/A200501/20000817/">そば処 時遊庵 あさかわ</a></strong><br> <script src="https://tabelog.com/badge/google_badge?escape=false&rcd=20000817" type="text/javascript" charset="utf-8"></script> </div> <p style="color:#444444; font-size:12px;"> <strong>関連ランキング:</strong><a href="https://tabelog.com/rstLst/soba/">そば(蕎麦)</a> | <a href="https://tabelog.com/nagano/A2005/A200501/R9047/rstLst/">穂高駅</a>、<a href="https://tabelog.com/nagano/A2005/A200501/R465/rstLst/">有明駅</a>、<a href="https://tabelog.com/nagano/A2005/A200501/R304/rstLst/">安曇追分駅</a></p> <h1 id="甘味">甘味</h1> <p>頭を使ったら糖分を補給しましょう。</p> <h2 id="ケーキ">ケーキ</h2> <h3 id="マサムラ">マサムラ</h3> <p>松本でケーキといえば(あくまで個人的)マサムラ一択です。今でも帰省したら必ずここのシュークリームを1回は食べます。</p> <div><strong><a target="_blank" href="https://tabelog.com/nagano/A2002/A200201/20000074/">マサムラ</a></strong><br> <script src="https://tabelog.com/badge/google_badge?escape=false&rcd=20000074" type="text/javascript" charset="utf-8"></script> </div> <p style="color:#444444; font-size:12px;"> <strong>関連ランキング:</strong><a href="https://tabelog.com/rstLst/cake/">ケーキ</a> | <a href="https://tabelog.com/nagano/A2002/A200201/R9297/rstLst/">松本駅</a>、<a href="https://tabelog.com/nagano/A2002/A200201/R7571/rstLst/">西松本駅</a>、<a href="https://tabelog.com/nagano/A2002/A200201/R3207/rstLst/">北松本駅</a></p> <p>マサムラはとにかく生クリームが美味しいんです。濃厚すぎなくて割といくらでも入る感じ。今でもここの生クリーム超えるものに出会ってないです(ノスタルジー補正や地元びいきはあると思います)。で、スイス風シュークリームが大量の生クリームを安く食べられるので、これを買ってます。でも一般的にはベビーシューの方がよく売れているみたい。うちの母親はモンブランが好きです。モンブランも結構中生クリームぎっしりですね。</p> <p>スイス風 <img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_7055f21c5a5eecac1a6b1e1327473c41.png" alt="スイス風シュークリーム" /></p> <p>モンブラン <img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_1eee6b5b347814bec396a6133e1a4ed7.png" alt="" /></p> <p>本店だと、喫茶スペースもあるのでイートイン可能です。本店は会場から徒歩圏ですね。 ホテルなどで食べても大丈夫ということであれば、持ち帰りがいいかと思います。大きめのスーパーならあります。先ほどあげたバスターミナルビルの地下やイオンモールにも持ち帰り用で販売ブースあります。</p> <p>マサムラはお土産として天守石垣サブレをお薦めしておきます。非常においしいです。が、結構高いので、職場のお土産にするのは少し躊躇してしまう・・・。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_a0ffdd734007cc46f04f172807dd67dc.png" alt="" /></p> <p>このレトロ感漂う包装紙が好きです。昔から変わらないんですよね。</p> <p>このサブレはこの間銀座のアンテナショップ行ったら売ってたんで食べてみて気に入ったらぜひアンテナショップでもご購入ください。</p> <h3 id="5HORN">5HORN</h3> <p>ラグジュアリーなイメージもあって若干近寄り難い5HORN。地元では有名です。マサムラばっか食べてたのと、高級感あるのでなかなか機会なく・・・。 上高地五千尺ホテルの経営だったかと思います。昔は家の近くにも個別のお店あったはずなんですけど、今はなくなっちゃいましたね。松本パルコか松本駅ビルに入っています。多分両方ともイートインあったと思います。</p> <p><figure class="figure-image figure-image-fotolife" title="5HORN"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/i/ichikawa-i3/20230501/20230501111618.png" width="1200" height="676" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>5HORN</figcaption></figure></p> <div><strong><a target="_blank" href="https://tabelog.com/nagano/A2002/A200201/20000388/">5HORN Dining</a></strong><br> <script src="https://tabelog.com/badge/google_badge?escape=false&rcd=20000388" type="text/javascript" charset="utf-8"></script> </div> <p style="color:#444444; font-size:12px;"> <strong>関連ランキング:</strong><a href="https://tabelog.com/rstLst/cake/">ケーキ</a> | <a href="https://tabelog.com/nagano/A2002/A200201/R9297/rstLst/">松本駅</a>、<a href="https://tabelog.com/nagano/A2002/A200201/R7571/rstLst/">西松本駅</a>、<a href="https://tabelog.com/nagano/A2002/A200201/R3207/rstLst/">北松本駅</a></p> <h2 id="バームクーヘン">バームクーヘン</h2> <h3 id="てまりや">てまりや</h3> <p>私が住んでいた時にはなかったんですが、結構かわいらしくおいしかったんでご紹介です。 松本は松本手まり、というまりが有名なんですが、それをモチーフにしたバームクーヘンを販売しています。 <figure class="figure-image figure-image-fotolife" title="てまりや"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/i/ichikawa-i3/20230501/20230501111828.png" width="1200" height="619" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>てまりや</figcaption></figure></p> <div><strong><a target="_blank" href="https://tabelog.com/nagano/A2002/A200201/20017408/">信州バームクーヘン工房 てまりや</a></strong><br> <script src="https://tabelog.com/badge/google_badge?escape=false&rcd=20017408" type="text/javascript" charset="utf-8"></script> </div> <p style="color:#444444; font-size:12px;"> <strong>関連ランキング:</strong><a href="https://tabelog.com/rstLst/SC020199/">洋菓子</a> | <a href="https://tabelog.com/nagano/A2002/A200201/R9297/rstLst/">松本駅</a>、<a href="https://tabelog.com/nagano/A2002/A200201/R3207/rstLst/">北松本駅</a>、<a href="https://tabelog.com/nagano/A2002/A200201/R7571/rstLst/">西松本駅</a></p> <p>買ってすぐ食べるもよし、お土産にもよしです。</p> <h2 id="パン">パン</h2> <h3 id="小松パン店">小松パン店</h3> <p>昔っからやってるパン屋なんですけど、ここの牛乳パンはいつのまにか全国区になったようで、予約しないと買えない状況のようです。牛乳パンってのは、普通にスーパーとかでも売ってるし全国のものかと思ってたんですがどうも長野県発祥?なのかな?小松のパン屋の牛乳パンはその某両区的なバタークリームの量です。運がよければ食べられるかもしれません。チャレンジしてください。</p> <p><figure class="figure-image figure-image-fotolife" title="小松の牛乳パン"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/i/ichikawa-i3/20230501/20230501113117.png" width="1200" height="786" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>小松の牛乳パン</figcaption></figure></p> <div><strong><a target="_blank" href="https://tabelog.com/nagano/A2002/A200201/20002131/">小松パン店</a></strong><br> <script src="https://tabelog.com/badge/google_badge?escape=false&rcd=20002131" type="text/javascript" charset="utf-8"></script> </div> <p style="color:#444444; font-size:12px;"> <strong>関連ランキング:</strong><a href="https://tabelog.com/rstLst/SC0101/">パン</a> | <a href="https://tabelog.com/nagano/A2002/A200201/R9297/rstLst/">松本駅</a>、<a href="https://tabelog.com/nagano/A2002/A200201/R3207/rstLst/">北松本駅</a></p> <h1 id="たべるお店">たべるお店</h1> <p>レストランなど、そこそこ行ってるお店をご紹介します。 ただ、久しぶりに色々調べてみたら、コロナのせいで閉店してるところが多く、悲しい気持ちになりました。</p> <h2 id="居酒屋">居酒屋</h2> <h3 id="しづか">しづか</h3> <p>地元のものが多いので、とりあえず行けばいろいろローカルのものが食べられる居酒屋さんです。 場所もわりと中心地に近いので行きやすいですね。</p> <div><strong><a target="_blank" href="https://tabelog.com/nagano/A2002/A200201/20002702/">しづか</a></strong><br> <script src="https://tabelog.com/badge/google_badge?escape=false&rcd=20002702" type="text/javascript" charset="utf-8"></script> </div> <p style="color:#444444; font-size:12px;"> <strong>関連ランキング:</strong><a href="https://tabelog.com/rstLst/izakaya/">居酒屋</a> | <a href="https://tabelog.com/nagano/A2002/A200201/R9297/rstLst/">松本駅</a></p> <p>長野県で有名なあの虫とか、あの虫とか食べられます。</p> <h3 id="鳥じん">鳥じん</h3> <p>うちの妹が松本で働いていた時によく行っていた店で私も何回か伺いました。結構おいしかったです。席数がカウンターのみ6席しかないので、rubyistの宴には使いづらいかな・・・</p> <div><strong><a target="_blank" href="https://tabelog.com/nagano/A2002/A200201/20003234/">鳥じん</a></strong><br> <script src="https://tabelog.com/badge/google_badge?escape=false&rcd=20003234" type="text/javascript" charset="utf-8"></script> </div> <p style="color:#444444; font-size:12px;"> <strong>関連ランキング:</strong><a href="https://tabelog.com/rstLst/yakitori/">焼き鳥</a> | <a href="https://tabelog.com/nagano/A2002/A200201/R9297/rstLst/">松本駅</a>、<a href="https://tabelog.com/nagano/A2002/A200201/R7571/rstLst/">西松本駅</a>、<a href="https://tabelog.com/nagano/A2002/A200201/R3207/rstLst/">北松本駅</a></p> <h2 id="バー">バー</h2> <h3 id="BRORA">BRORA</h3> <p>松本はバーの街として売り出しているようで、結構今街中にバーが多いです。(昔はそんなことなかったはずなんですが・・・売り出そうというわけでもなさそうだしどういうムーブメントでこうなったのかいまいち把握できてません) 帰省したときに行ったBRORAはバーカウンターが一枚板のとてつもないテーブルで圧倒されます。オーセンティックなバーでお酒の種類も揃っているので飲みたいものはあるんじゃないでしょうか。</p> <div><strong><a target="_blank" href="https://tabelog.com/nagano/A2002/A200201/20010947/">ブローラ</a></strong><br> <script src="https://tabelog.com/badge/google_badge?escape=false&rcd=20010947" type="text/javascript" charset="utf-8"></script> </div> <p style="color:#444444; font-size:12px;"> <strong>関連ランキング:</strong><a href="https://tabelog.com/rstLst/BC0101/">バー</a> | <a href="https://tabelog.com/nagano/A2002/A200201/R9297/rstLst/">松本駅</a>、<a href="https://tabelog.com/nagano/A2002/A200201/R7571/rstLst/">西松本駅</a>、<a href="https://tabelog.com/nagano/A2002/A200201/R3207/rstLst/">北松本駅</a></p> <h2 id="スパゲティ">スパゲティ</h2> <p>何気におすすめの店がいくつか・・・</p> <h3 id="翁堂">翁堂</h3> <p>松本駅前に親戚が店を出していて、その関係でこちらのお店にはよく言ってました。今はビルの都合で規模縮小してしまいましたが、雰囲気がすごくいいんですよね。あとスパゲティがおいしい。確か150円くらいプラスで大盛りとかにできるんですけど、その量が暴力的笑 たくさん食べたい時にぜひどうぞ。おすすめは和風イタリアンです。</p> <p><figure class="figure-image figure-image-fotolife" title="翁堂 和風イタリアン"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/i/ichikawa-i3/20230501/20230501113357.png" width="1200" height="1057" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>翁堂 和風イタリアン</figcaption></figure></p> <div><strong><a target="_blank" href="https://tabelog.com/nagano/A2002/A200201/20008598/">翁堂 駅前店</a></strong><br> <script src="https://tabelog.com/badge/google_badge?escape=false&rcd=20008598" type="text/javascript" charset="utf-8"></script> </div> <p style="color:#444444; font-size:12px;"> <strong>関連ランキング:</strong><a href="https://tabelog.com/rstLst/kissaten/">喫茶店</a> | <a href="https://tabelog.com/nagano/A2002/A200201/R9297/rstLst/">松本駅</a>、<a href="https://tabelog.com/nagano/A2002/A200201/R7571/rstLst/">西松本駅</a>、<a href="https://tabelog.com/nagano/A2002/A200201/R3207/rstLst/">北松本駅</a></p> <h3 id="どんぐり">どんぐり</h3> <p>市内では有名な洋食のお店ですが、確かここもナポリタンが有名だったと思います。上の翁堂に頻繁に行っていたのですごく行っていたというわけではないのですが。白線流しのロケなどに使われた店でTOKIOの長瀬くんや酒井美紀のサインが飾ってあったと思います。今もあるのかな?</p> <div><strong><a target="_blank" href="https://tabelog.com/nagano/A2002/A200201/20000428/">どんぐり</a></strong><br> <script src="https://tabelog.com/badge/google_badge?escape=false&rcd=20000428" type="text/javascript" charset="utf-8"></script> </div> <p style="color:#444444; font-size:12px;"> <strong>関連ランキング:</strong><a href="https://tabelog.com/rstLst/RC980401/">弁当</a> | <a href="https://tabelog.com/nagano/A2002/A200201/R9297/rstLst/">松本駅</a>、<a href="https://tabelog.com/nagano/A2002/A200201/R7571/rstLst/">西松本駅</a>、<a href="https://tabelog.com/nagano/A2002/A200201/R3207/rstLst/">北松本駅</a></p> <h3 id="キッチンヤマナミ">キッチンヤマナミ</h3> <p>その昔は松本駅前の公園通りにお店があって、めちゃ好きだったんですが、オーナーがご高齢か何かで閉店。一時期松本駅前の地下に間借りしてやられていたようですが、そこもなくなり、もう食べられないのかなあと思っていたのですが、数年前に安曇野の方に開かれたとのことで、私も一度行って堪能してきました。 名古屋のあんかけパスタ系かな?と思いますが、甘いソースなんですよね。好みは正直分かれるところだと思います。私はノスタルジーで行ってるだけなので、すごくおすすめではないですが、もし足を伸ばすことが可能であればご検討ください。今行かれる人も多分懐かしさを追っていく人が多いのではないかなあ。</p> <p><figure class="figure-image figure-image-fotolife" title="ヤマナミ風(これは多分昔の店舗での写真)"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/i/ichikawa-i3/20230501/20230501113607.png" width="1200" height="776" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>ヤマナミ風(これは多分昔の店舗での写真)</figcaption></figure></p> <div><strong><a target="_blank" href="https://tabelog.com/nagano/A2005/A200501/20022156/">キッチン ヤマナミ</a></strong><br> <script src="https://tabelog.com/badge/google_badge?escape=false&rcd=20022156" type="text/javascript" charset="utf-8"></script> </div> <p style="color:#444444; font-size:12px;"> <strong>関連ランキング:</strong><a href="https://tabelog.com/rstLst/pasta/">パスタ</a> | <a href="https://tabelog.com/nagano/A2005/A200501/R304/rstLst/">安曇追分駅</a>、<a href="https://tabelog.com/nagano/A2005/A200502/R9039/rstLst/">細野駅</a>、<a href="https://tabelog.com/nagano/A2005/A200501/R465/rstLst/">有明駅</a></p> <h2 id="ラーメン">ラーメン</h2> <h3 id="テンホウ">テンホウ</h3> <p>発祥は松本ではないようなのですが、店舗がいっぱいあって今でも帰省のときに行ってたりします。タンタンメンがおいしくてよく食べてるんですけど、いわゆるタンタンメンではなく、そこまで辛くはないです。ただコクがあっておいしい。学生の頃はタンタンメンとソフトクリームのセットが480円とかで食べられました。今はもうちょっと高いと思いますが。 月に2回かな?ある餃子の日だとぎょうざ半額です。 会場から徒歩でいけるところにあったお店は残念ながら今なくなってしまっていますが、ちょっといけばあるのでもし見かけたらどうぞ。</p> <p><figure class="figure-image figure-image-fotolife" title="テンホウのタンタンメン"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/i/ichikawa-i3/20230501/20230501114318.png" width="1200" height="753" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>テンホウのタンタンメン</figcaption></figure></p> <div><strong><a target="_blank" href="https://tabelog.com/nagano/A2002/A200201/20016074/">テンホウ 追分店</a></strong><br> <script src="https://tabelog.com/badge/google_badge?escape=false&rcd=20016074" type="text/javascript" charset="utf-8"></script> </div> <p style="color:#444444; font-size:12px;"> <strong>関連ランキング:</strong><a href="https://tabelog.com/rstLst/MC0101/">ラーメン</a> | <a href="https://tabelog.com/nagano/A2002/A200201/R3207/rstLst/">北松本駅</a>、<a href="https://tabelog.com/nagano/A2002/A200201/R9297/rstLst/">松本駅</a>、<a href="https://tabelog.com/nagano/A2002/A200201/R4711/rstLst/">島内駅</a></p> <p>距離的には桐が一番近いのかなあ・・・</p> <h3 id="大石家">大石家</h3> <p>家ついてますが、家系ではないです。ビュアな醤油ラーメン。チャーシューがやたら乗ってておいしいです。家族で結構行ってました。歩いて行ったりするにはややつらいところではありますが、車など出せたらぜひどうぞ。</p> <div><strong><a target="_blank" href="https://tabelog.com/nagano/A2002/A200201/20000225/">大石家 松本店</a></strong><br> <script src="https://tabelog.com/badge/google_badge?escape=false&rcd=20000225" type="text/javascript" charset="utf-8"></script> </div> <p style="color:#444444; font-size:12px;"> <strong>関連ランキング:</strong><a href="https://tabelog.com/rstLst/MC0101/">ラーメン</a> | <a href="https://tabelog.com/nagano/A2002/A200201/R9697/rstLst/">南松本駅</a>、<a href="https://tabelog.com/nagano/A2002/A200201/R11045/rstLst/">平田駅</a></p> <h2 id="その他">その他</h2> <h3 id="たけしや">たけしや</h3> <p>中学の時にめっちゃはやりました笑 やきそば、という料理のはずなんですけど麺がやたらと太くて硬くて、味が濃くて結構油が強いです。焼きそば食べにたけしやにいく、というよりもたけしやを食べにいく、みたいな感じではないかと。好きな人はすごく好きな味だと思います。油そばとは全然違うんですが、油そば好きな人なら多分すきなんじゃないかなと思います。でもよく考えたらテイクアウト1回しか食べたことないな。私の口にはあまり合いませんでしたが、流行ってたってことは好きな人が多いし、人気店なのは間違い無いです。</p> <p><figure class="figure-image figure-image-fotolife" title="たけしや"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/i/ichikawa-i3/20230501/20230501114050.png" width="1200" height="877" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>たけしや</figcaption></figure></p> <div><strong><a target="_blank" href="https://tabelog.com/nagano/A2002/A200201/20001590/">たけしや</a></strong><br> <script src="https://tabelog.com/badge/google_badge?escape=false&rcd=20001590" type="text/javascript" charset="utf-8"></script> </div> <p style="color:#444444; font-size:12px;"> <strong>関連ランキング:</strong><a href="https://tabelog.com/rstLst/RC012402/">焼きそば</a> | <a href="https://tabelog.com/nagano/A2002/A200201/R3207/rstLst/">北松本駅</a>、<a href="https://tabelog.com/nagano/A2002/A200201/R9297/rstLst/">松本駅</a></p> <h3 id="かき船">かき船</h3> <p>すいません、行ったことはないんですが、もう私が子供の頃から全く同じ佇まいでそこに存在しているお店。うちの母親が銀行員の時によく食べに行っていたというので、多分外観はそのころからもかわってないんじゃないでしょうか。お堀の上にあるので、川床みたいな雰囲気なのかも。カツ丼がおいしいらしいです。</p> <p><figure class="figure-image figure-image-fotolife" title="かき船の外観。子供心に敷居の高さを感じた"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/i/ichikawa-i3/20230501/20230501114145.png" width="1200" height="860" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>かき船の外観。子供心に敷居の高さを感じた</figcaption></figure></p> <div><strong><a target="_blank" href="https://tabelog.com/nagano/A2002/A200201/20006461/">かき船</a></strong><br> <script src="https://tabelog.com/badge/google_badge?escape=false&rcd=20006461" type="text/javascript" charset="utf-8"></script> </div> <p style="color:#444444; font-size:12px;"> <strong>関連ランキング:</strong><a href="https://tabelog.com/rstLst/tonkatsu/">とんかつ</a> | <a href="https://tabelog.com/nagano/A2002/A200201/R3207/rstLst/">北松本駅</a>、<a href="https://tabelog.com/nagano/A2002/A200201/R9297/rstLst/">松本駅</a>、<a href="https://tabelog.com/nagano/A2002/A200201/R7571/rstLst/">西松本駅</a></p> <h3 id="メーヤウ">メーヤウ</h3> <p>カレーのお店。まあまあお値段しますが、結構おいしいです。早稲田に同名のお店があるんですけど、同じなのかな。ここはよく聞く人気店ですね。</p> <div><strong><a target="_blank" href="https://tabelog.com/nagano/A2002/A200201/20000052/">松本メーヤウ 桐店</a></strong><br> <script src="https://tabelog.com/badge/google_badge?escape=false&rcd=20000052" type="text/javascript" charset="utf-8"></script> </div> <p style="color:#444444; font-size:12px;"> <strong>関連ランキング:</strong><a href="https://tabelog.com/rstLst/RC1201/">カレー</a> | <a href="https://tabelog.com/nagano/A2002/A200201/R3207/rstLst/">北松本駅</a></p> <h3 id="桑原冷凍機工業所">桑原冷凍機工業所</h3> <p>多分会期中にはやってませんが笑 製氷機の会社?なのかな?私の中ではクワハラというアイスキャンデー屋さんです。松本でアイスキャンデーというと大体2派に分かれて、松本の中心地の方にあるスギヤかこのクワハラか、です。私は家から近いこのクワハラの方に行ってました。いちご、あすき、ミルクで1本40円?だったような気がします。今は値段あがってますかね。夏季限定です。夏に帰省すると必ず食べてます。</p> <p>うちの母など、これを下の方から食べてます。曰く「棒を上にして凍らせてるから、下の方が味が濃い。」</p> <p><figure class="figure-image figure-image-fotolife" title="クワハラのアイスキャンデー"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/i/ichikawa-i3/20230501/20230501113745.png" width="1200" height="444" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>クワハラのアイスキャンデー</figcaption></figure></p> <div><strong><a target="_blank" href="https://tabelog.com/nagano/A2002/A200201/20011524/">桑原冷凍機工業所</a></strong><br> <script src="https://tabelog.com/badge/google_badge?escape=false&rcd=20011524" type="text/javascript" charset="utf-8"></script> </div> <p style="color:#444444; font-size:12px;"> <strong>関連ランキング:</strong><a href="https://tabelog.com/rstLst/SC0228/">ジェラート・アイスクリーム</a> | <a href="https://tabelog.com/nagano/A2002/A200201/R9297/rstLst/">松本駅</a>、<a href="https://tabelog.com/nagano/A2002/A200201/R7571/rstLst/">西松本駅</a>、<a href="https://tabelog.com/nagano/A2002/A200201/R3207/rstLst/">北松本駅</a></p> <h1 id="まとめ">まとめ</h1> <p>完全に自分が好きで紹介したい店を紹介しただけになってしまいましたが、観光ガイドにはあまりないようなお店であればいいな、と思ってます。地元民目線で選んでますので、皆様の旅のお供に訪問をぜひご検討いただき、松本を満喫してもらえたらうれしいです。</p> ichikawa-i3 育休中のエンジニアが感じたこと hatenablog://entry/4207112889980524694 2023-04-28T11:49:14+09:00 2023-04-28T11:49:14+09:00 はじめに こんにちは、サーバーサイドエンジニアのM-Yamashita01です。 今回は、パパエンジニアとなった私が育児休業を取得した話です。 私の子供は2022年6月に産まれる予定でしたが、1ヶ月早く低出生体重児として産まれました。急遽産まれることを想定した仕事への対応や、慣れない育児への準備、仕事との兼ね合いをどうやって行ったかをこの記事で伝えます。 子供が産まれる前〜現在に至るまでの期間 まずは育休の話をする前に、どのくらいの時期に何があったのか全体感を伝えます。 時期 何があった? 2022年初め 出産予定日がわかる 2022年5月 子供が産まれる。子供は入院へ 2022年6月 子供が… <h1 id="はじめに">はじめに</h1> <p>こんにちは、サーバーサイドエンジニアの<a href="https://github.com/M-Yamashita01">M-Yamashita01</a>です。</p> <p>今回は、パパエンジニアとなった私が育児休業を取得した話です。<br/> 私の子供は2022年6月に産まれる予定でしたが、1ヶ月早く低出生体重児として産まれました。急遽産まれることを想定した仕事への対応や、慣れない育児への準備、仕事との兼ね合いをどうやって行ったかをこの記事で伝えます。</p> <h1 id="子供が産まれる前現在に至るまでの期間">子供が産まれる前〜現在に至るまでの期間</h1> <p>まずは育休の話をする前に、どのくらいの時期に何があったのか全体感を伝えます。</p> <table> <thead> <tr> <th>時期</th> <th>何があった?</th> </tr> </thead> <tbody> <tr> <td>2022年初め</td> <td>出産予定日がわかる</td> </tr> <tr> <td>2022年5月</td> <td>子供が産まれる。子供は入院へ</td> </tr> <tr> <td>2022年6月</td> <td>子供が退院し、妻の実家へ</td> </tr> <tr> <td>2022年8月1日</td> <td>妻と子供がアパートへ。育休開始</td> </tr> <tr> <td>2022年10月1日</td> <td>育休終了、仕事復帰</td> </tr> </tbody> </table> <h1 id="なぜ育休取得を">なぜ育休取得を?</h1> <p>以前から育児にとても興味があり、妻と一緒に子育てをしたいと思っていました。育児はわからないことだらけで不安もありましたが、子供と遊んだり世話をすることが好きだったので、育休を取得しようと思いました。<br/> また弊社では、男性エンジニアで育休を半年ほど取得されている方がいます。加えて別部署でも育休を取得されている方がいます。男性の育休取得の前例があることも、後押しとなりました。</p> <h1 id="育休取得前の準備">育休取得前の準備</h1> <h2 id="子供が産まれることの連絡休みなどの相談">子供が産まれることの連絡、休みなどの相談</h2> <p>出産予定日が分かった時点で、すぐに上司に連絡しました。その際に育休を取得したいことを伝えました。育休を取るにあたり、取得タイミングと期間を決める必要があります。それらを決めるにあたって、子供の成長具合や生活リズムなどを妻と何度も相談しました。その結果、子供が3ヶ月程度になる8月から2ヶ月間、育休を取得することにしました。</p> <p>また、出産日が前倒しになったり、突発的な出来事が起こることを考え、数時間の休みや全休を突発的に取得する可能性があることを事前に連絡しました。</p> <p>今思い返せば、この相談をしていたことで、子供が産まれる日や通院などで休みを気にせずに済んだと思います。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_85f062ede7101a8bd09214ae19e7c170.png" alt="" width="400" height=""></p> <h2 id="仕事の引き継ぎ">仕事の引き継ぎ</h2> <p>育休取得の1〜2週間前付近から、私のタスクを洗い出し始めました。そのタスクの中から、私ができる範囲はここまでという部分を対応し、残りを別の方に引き継ぎしました。あらかじめ余裕を持って引き継ぎをしていたおかげで、育休期間中に困ることはあまりありませんでした。</p> <h2 id="子供が産まれてから育休までの間">子供が産まれてから育休までの間</h2> <p>子供の退院後、妻と子供が育休開始前まで妻の実家で過ごしていたので、週の半ばや週末に妻の実家に通いました。妻の実家が私のアパートの近くであったため、在宅勤務での仕事終了後、すぐに向かうことができました。子供を持つ家庭での在宅勤務の良さはここにもあると思います。<br/> また、定期的に通って育児をしていたこともあり、育児休業中に何もできない・分からないということがあまりなかったと思います。</p> <h1 id="育休復帰後">育休復帰後</h1> <p>10月から復帰し、仕事を再開しました。若干の浦島太郎気分はありましたが、仕事の引き継ぎをしていたおかげで、スムーズに業務を始められました。</p> <p>以前と変わったことしては、時間の使い方です。子供が産まれる前までは、キリがいいところまであと少しあと少しと仕事をし続けており、メリハリがあまりない生活となっていました。子供が産まれたことで、子供の生活リズムをメインに考え、基本的に定時で今日の仕事を終えるようにリズムを変えました。そのおかげで、時間の大切さを考えるようになり、今まで以上に効率を考えた仕事をするようになりました。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_84b4a2e0b0ca2ff28401a90e14ce33ed.png" alt="" width="400" height=""></p> <h1 id="育休を取ったことについてどうだった">育休を取ったことについてどうだった?</h1> <p>取得してすごくよかったと感じています。仕事は私ではなくても回りますし、どうにかなりますが、子供にとっては私と妻しかいません。そのため、育休により子供の成長やちょっとした変化を、仕事を気にせずにしっかりと見ることができたと思っています。<br/> また、私の生活リズムを見直す機会にもなり、どうやったら育児と仕事を両立できるかを考える機会にもなると考えています。</p> <p>育休取得するかどうか迷っている方、ぜひ取得してみてください。大変な部分、慣れない部分も出てきますが、今しかできない、見れないことがたくさんあります。</p> <p>この記事が誰かの次の一歩に繋がれば嬉しいです。</p> <h1 id="最後に">最後に</h1> <p>弊社では採用活動を実施しています。家庭と仕事を両立させて働ける環境を用意しております。</p> <p>皆さまのご応募をお待ちしております。</p> <p>新卒採用:<a href="https://www.i3-systems.com/new-graduates/">https://www.i3-systems.com/new-graduates/</a><br/> キャリア採用:<a href="https://www.i3-systems.com/careers/">https://www.i3-systems.com/careers/</a></p> yamashita-i3 アイキューブドシステムズは『RubyKaigi 2023』に Gold スポンサーとして協賛します! hatenablog://entry/4207112889970118082 2023-04-14T00:17:16+09:00 2023-04-28T10:25:54+09:00 こんにちは!Imamuraです。 アイキューブドシステムズは、Rubyを活用してWeb開発を行っております💎 この度、私たちはRubyコミュニティーの発展を支援するため、5/11(木), 12(金), 13(土)の 3 日間に渡り開催されるRubyKaigi 2023にGoldスポンサーとして協賛することが決定しました。 ところで、皆さん、RubyKaigi はご存知でしょうか。 RubyKaigiは、プログラミング言語Rubyに関する国際カンファレンスです。 Rubyのコア開発者が集まり、Rubyの未来と最新技術を議論する世界最大の場として重要な役割を担っています。 rubykaigi.or… <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/i/imamura-i3/20230413/20230413184034.png" width="1200" height="835" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span>こんにちは!<a href="https://github.com/imamura3i">Imamura</a>です。</p> <p>アイキューブドシステムズは、Rubyを活用してWeb開発を行っております💎 </br> この度、私たちはRubyコミュニティーの発展を支援するため、5/11(木), 12(金), 13(土)の 3 日間に渡り開催されるRubyKaigi 2023にGoldスポンサーとして協賛することが決定しました。</p> <p>ところで、皆さん、RubyKaigi はご存知でしょうか。 RubyKaigiは、プログラミング言語Rubyに関する国際カンファレンスです。 Rubyのコア開発者が集まり、Rubyの未来と最新技術を議論する世界最大の場として重要な役割を担っています。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Frubykaigi.org%2F2023%2Fsponsors%2F" title="Sponsors" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://rubykaigi.org/2023/sponsors/">rubykaigi.org</a></cite></p> <p>私たちのスポンサーシップは、RubyKaigiの開催やプログラムの充実に貢献し、Rubyコミュニティーの成長を支援します。 Rubyコミュニティーがより活発になることにより、多様なアイデアが生まれることを期待しています。 </br> そして、これからもよりRubyを活用した開発者が増加することを促進することを目的として、積極的に関与していきたいと思っています。</p> <p>そんなRubyKaigiも今年で17回目を迎え、舞台は、長野県松本市です。</p> <p>アイキューブドシステムズからも4名が現地で参加します。 </br> 私たちは、今年最大のRubyistの集いで多くの参加者とリアルなコミュニケーションを取れることを楽しみにしています。</p> <p>都合で参加できない方もおられるでしょう。 安心してください! </br> もちろん、そんな方はオンラインで参加し、チャットでわいわい楽しむことができます。</p> <p>こちらから、RubyKaigi 2023への参加を申し込むことができます。 <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fti.to%2Frubykaigi%2F2023" title="RubyKaigi 2023" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://ti.to/rubykaigi/2023">ti.to</a></cite> それでは、RubyKaigi 2023 で会いましょう!</p> <h2 id="We-are-looking-for-new-members">We are looking for new members</h2> <p>私たちは、CLOMO MDMの製品開発を通じて、共に成長していける仲間を募集しています。</p> <p>また、カジュアル面談・エントリーも、下記のページから随時受け付けています。 <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.i3-systems.com%2Fcareers" title="採用情報|株式会社アイキューブドシステムズ" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.i3-systems.com/careers">www.i3-systems.com</a></cite></p> imamura-i3 新卒社員がサーバーサイドに配属されるまでの話 hatenablog://entry/4207112889959350453 2023-04-11T13:24:19+09:00 2023-04-11T13:24:19+09:00 新卒社員がサーバーサイドに配属されるまでの話 こんにちは、アイキューブドシステムズのmatsuoi3です。私は、2022年4月に新卒で入社し、執筆時点(2022年12月)でサーバーサイド配属から3ヶ月が経ちました。そこで、今回は、私が入社してから現在までどのようなことをやったのかについて話していきたいと思います。 サーバーサイド配属まで ここでは、入社後から行った研修について順に述べていきます。入社から半年間は以下の時系列で研修を行いました。 新卒全体研修 4月からの1ヶ月間は全部署の新卒メンバーで研修を行います。ビジネスマナーやロジカルシンキングといった新卒おなじみの研修のほか、製品研修やグ… <h1 id="新卒社員がサーバーサイドに配属されるまでの話">新卒社員がサーバーサイドに配属されるまでの話</h1> <p>こんにちは、アイキューブドシステムズの<a href="https://github.com/matsuoi3">matsuoi3</a>です。私は、2022年4月に新卒で入社し、執筆時点(2022年12月)でサーバーサイド配属から3ヶ月が経ちました。そこで、今回は、私が入社してから現在までどのようなことをやったのかについて話していきたいと思います。</p> <h2 id="サーバーサイド配属まで">サーバーサイド配属まで</h2> <p>ここでは、入社後から行った研修について順に述べていきます。入社から半年間は以下の時系列で研修を行いました。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_6a22c913a94e7898e0d1a26610db1a6a.png" alt="" /></p> <h3 id="新卒全体研修">新卒全体研修</h3> <p>4月からの1ヶ月間は全部署の新卒メンバーで研修を行います。ビジネスマナーやロジカルシンキングといった新卒おなじみの研修のほか、製品研修やグループワークもありました。製品の知識を学んだり、新卒のメンバーとコミュニケーションもとれたので充実した研修でした。</p> <h3 id="サーバー研修1モバイル研修">サーバー研修1・モバイル研修</h3> <p>5月から約1ヶ月半はサーバー・モバイル両方の研修を行い、研修後どちらの配属になるかの希望を出します。</p> <p>サーバー研修では<a href="https://railstutorial.jp/">Ruby on Rails チュートリアル</a>でツイートアプリを、モバイル研修ではiOSの To Doアプリ作成を行いました。サーバーとモバイル両方の研修ができるので、しっかり比較して配属の希望を出すことができました。私はサーバーの方で希望を出しました。</p> <h3 id="サーバー研修2">サーバー研修2</h3> <p>希望調査から7月末までの1ヶ月半は、再びサーバーので研修を行いました。最初は<a href="https://railstutorial.jp/">Ruby on Rails チュートリアル</a>の続きを行い、その後(1ヶ月くらい)は自作アプリの設計・作成を行いました。</p> <p>アプリ作成は、チュートリアルのようにお手本がないので、エラーが発生して画面が動かなくなったり、動いたとしても想定した挙動と違ったりといったことがありました。こういった業務の実装で陥りそうな経験ができたので良かったです。また、環境構築は弊社の開発環境と同じ<a href="https://docs.docker.com/desktop/install/mac-install/">Docker</a>で行なっていたので、後のMDM研修やサーバーサイド配属後の業務にスムーズに着手できました。</p> <h3 id="MDM研修">MDM研修</h3> <p>8月から1ヶ月間は、MDM研修を行いました。研修では弊社の製品の開発環境構築をし、ログを読み取ってMDMコマンドを実装しました。</p> <p>コマンド実装にあたって、基本設計書の作成、GitHubを用いたプルリクエストの作成、コードレビュー依頼とレビューを受けての修正、コンフリクトの解消といったサーバー配属後の開発の流れを経験することができました。MDM研修に関してはこちらのブログでも記載されているので、こちらもご覧いただけると幸いです。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftech.i3-systems.com%2Fentry%2F2022%2F10%2F31%2F132654" title="中途入社した私が開発現場に入るまでに受けた教育プラン - i Cubed Systems Engineering blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://tech.i3-systems.com/entry/2022/10/31/132654">tech.i3-systems.com</a></cite></p> <h2 id="サーバーサイド配属後">サーバーサイド配属後</h2> <p>MDM研修終了後は、ついにサーバーサイド配属です。製品の不具合改修を行うチームに配属となりました。ここからは、チーム内で行っていることを話していきたいと思います。</p> <p>私のチームでは毎日10時に朝会を行っています。朝会では、課題の現況共有や担当する課題の相談を行なっています。朝会以外でも、Teamsに自分の課題のスレッドがあるので、そこでも課題の共有ができます。そのため、自分の課題が煮詰まったとしても、溜めこまずに課題をこなすことができます。 また、ここ最近はじまったことですが、詰まっているときに、2,3人でミーティングを行うようになりました。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_7b7defb9aac58bcda0d1d5ec1efa6b82.png" alt="" /></p> <p>ミーティングを行うことで、どの側面から問題を見ているのか、どうやって不具合の箇所を調べるのかといった部分も勉強になりました。弊社では現状リモートワークが多くなってますので、どうしても他の人がどうやっているかという部分が見れなくなってしまいます。そんな中、こういう形で他の人が作業している部分が見れる機会が増えるのはいいなと思います。</p> <h2 id="まとめ">まとめ</h2> <p>今回は私がサーバーサイドに配属されるまでの話をしました。配属されて3ヶ月が経ちますが、いまだに新しい発見ばかりで、非常に有意義な生活が送れています。まだ、未熟な状態ですが、少しでも早く1人前になりメンバーに頼られる存在になりたいです。</p> <p>最後に、興味のある方はご応募をお待ちしております。 <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.i3-systems.com%2Fnew-graduates%2F" title="新卒採用|株式会社アイキューブドシステムズ" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.i3-systems.com/new-graduates/">www.i3-systems.com</a></cite></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.i3-systems.com%2Fcareers%2F" title="採用情報|株式会社アイキューブドシステムズ" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.i3-systems.com/careers/">www.i3-systems.com</a></cite></p> <p>外部の就活サイトでも弊社が載っておりますので、そちらもご覧いただけると幸いです。</p> matsuo-i3 アイキューブドシステムズの社員教育への取り組みを紹介します hatenablog://entry/4207112889948586853 2023-03-24T11:52:33+09:00 2023-03-24T11:52:33+09:00 みなさん、こんにちは。アイキューブドシステムズでモバイルアプリの開発を担当している tafuji-i3 です。業務でカジュアル面談を担当することがあるのですが、「もし入社した場合に、実務に入る前にトレーニングを受けることはできますか?」という質問を受けることがあります。 今回の記事では、アイキューブドシステムズの社員教育について、当社の社員が書いた記事を紹介しながら、簡単に説明をしていきたいと思います。 入社後の教育プラン スキルアップの支援環境 学ぶことができる環境づくり 入社後の教育プラン アイキューブドシステムズに興味を持っていただいた方で、「仮に入社したとして、業務にキャッチアップして… <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/tafuji-i3/20221227/20221227114825.png" width="1200" height="630" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span> みなさん、こんにちは。アイキューブドシステムズでモバイルアプリの開発を担当している <a href="https://github.com/tafuji-i3">tafuji-i3</a> です。業務でカジュアル面談を担当することがあるのですが、「もし入社した場合に、実務に入る前にトレーニングを受けることはできますか?」という質問を受けることがあります。</p> <p>今回の記事では、アイキューブドシステムズの社員教育について、当社の社員が書いた記事を紹介しながら、簡単に説明をしていきたいと思います。</p> <ul> <li>入社後の教育プラン</li> <li>スキルアップの支援環境</li> <li>学ぶことができる環境づくり</li> </ul> <h2 id="入社後の教育プラン">入社後の教育プラン</h2> <p>アイキューブドシステムズに興味を持っていただいた方で、「仮に入社したとして、業務にキャッチアップしていくことができるのか?」と考える人がいるかもしれません。</p> <p>当社では、新卒・中途の両方の社員向けに教育プランが用意されています。ここでは、それぞれの教育プランについて簡単にご紹介したいと思います。また、リモートワークは初めてというかたのために、リモートワークで実務にうまくはいっていくことができるのかについての記事も紹介したいと思います。</p> <h3 id="新卒採用の場合">新卒採用の場合</h3> <p>新卒で入社した場合は、サーバーサイドか、モバイルサイドか、どちらのエンジニアとして仕事をしたいのか判断がつかないかもしれません。また、エンジニアとしての業務経験もなく、実務でどんなことをやっているのかも想像できないかもしれません。</p> <p>そんな疑問や不安を抱える新卒社員のために、当社ではモバイル・サーバー、さらに QA・PMO までの業務を一通り経験できる教育プランが用意されています。</p> <p>新卒で入社した社員が取り組んだ教育プランの内容の詳細は、以下の記事をご覧ください。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftech.i3-systems.com%2Fentry%2F2020%2F09%2F30%2F151314" title="アイキューブドシステムズの新米エンジニアが配属後3ヶ月を振り返りながら新卒研修を紹介 - i Cubed Systems Engineering blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://tech.i3-systems.com/entry/2020/09/30/151314">tech.i3-systems.com</a></cite></p> <h3 id="中途採用の場合">中途採用の場合</h3> <p>中途採用で入社する場合、特定のチーム(サーバー・モバイルなど)に配属が決まっています。当社では中途入社の方向けの教育プランも用意されています。この教育を受け、チームメンバーと一緒に活動していくことで、開発メンバーとしてスキルを高めていくことができます。</p> <p>以下は、サーバーサイドチームに中途採用で配属された社員が書いた記事です。中途採用で入社したときにうけた教育プランの内容について書かれています。興味をもたれたかたは、ぜひご覧ください。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftech.i3-systems.com%2Fentry%2F2022%2F10%2F31%2F132654" title="中途入社した私が開発現場に入るまでに受けた教育プラン - i Cubed Systems Engineering blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://tech.i3-systems.com/entry/2022/10/31/132654">tech.i3-systems.com</a></cite></p> <h3 id="OJT">OJT</h3> <p>新卒・中途ともに入社後のトレーニングを受けた後は、チームに配属され、OJT でトレーニングと実務を行っていきます。チームの中で製品について学び、経験を積んでいくことになります。</p> <p>以下は、OJT で初めてチーム開発を経験した社員の記事です。ご一読いただき、参考にしていただければ幸いです。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftech.i3-systems.com%2Fentry%2F2022%2F12%2F27%2F102935" title="初めてのチーム開発 - i Cubed Systems Engineering blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://tech.i3-systems.com/entry/2022/12/27/102935">tech.i3-systems.com</a></cite></p> <h3 id="リモートワーク">リモートワーク</h3> <p>「新卒・中途のどちらの場合でも、教育プランが提供されているのは分かった。でも、リモートワークという働き方で、トレーニングから OJT までスムーズに取り組んでいくことが、本当にできるの?」と思った人もいるかもしれません。新卒・中途ともに、入社直後からリモートという環境で働いている社員はたくさんいます。</p> <p>新卒入社後、リモートワーク環境で研修を受け、チームに配属された社員の体験談が、以下の記事に書かれています。ぜひご一読ください。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftech.i3-systems.com%2Fentry%2F2021%2F11%2F25%2F102622" title="新卒でいきなりリモートワークってどんな感じなの?と気になる方へ - i Cubed Systems Engineering blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://tech.i3-systems.com/entry/2021/11/25/102622">tech.i3-systems.com</a></cite></p> <p>また、中途で入社された社員のリモートワークの様子は、以下の記事に書かれています。ぜひこの記事もご一読ください。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftech.i3-systems.com%2Fentry%2F2020%2F07%2F23%2F%25E8%25BB%25A2%25E8%2581%25B7%25E3%2581%2597%25E3%2581%259F%25E3%2582%2589%25E3%2583%25AA%25E3%2583%25A2%25E3%2583%25BC%25E3%2583%2588%25E3%2583%25AF%25E3%2583%25BC%25E3%2582%25AB%25E3%2583%25BC%25E3%2581%25A0%25E3%2581%25A3%25E3%2581%259F%25E4%25BB%25B6" title="転職したらリモートワーカーだった件 - i Cubed Systems Engineering blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://tech.i3-systems.com/entry/2020/07/23/%E8%BB%A2%E8%81%B7%E3%81%97%E3%81%9F%E3%82%89%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AB%E3%83%BC%E3%81%A0%E3%81%A3%E3%81%9F%E4%BB%B6">tech.i3-systems.com</a></cite></p> <h2 id="スキルアップの支援環境">スキルアップの支援環境</h2> <p>入社直後のトレーニングと OJT だけではなく、アイキューブドシステムズは社員が継続的にスキルアップできる環境も提供しています。主な取り組みは、以下の通りです。</p> <ul> <li>社内勉強会</li> <li>オンライン学習サイト</li> <li>英語への取り組み</li> </ul> <h3 id="社内勉強会">社内勉強会</h3> <p>アイキューブドシステムズの社内勉強会の歴史は長いです。勉強会のスタイルも変化しており、過去のランチを食べながら勉強会を行うスタイルから、現在は業務時間の中で定期的に勉強会を開催するスタイルに変わりました。</p> <p>社内勉強会は、エンジニアの部署だけで開催されているのではありません。当社では、管理部門、カスタマーサクセス部門でも開催されており、社員はどの部門の勉強会にも参加することができます。</p> <p>社内勉強会の詳しい様子は以下の記事を参考にしてください。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftech.i3-systems.com%2Fentry%2F2020%2F10%2F12%2F142550" title="開催実績 100 回以上の社内勉強会の様子を紹介 - i Cubed Systems Engineering blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://tech.i3-systems.com/entry/2020/10/12/142550">tech.i3-systems.com</a></cite></p> <h3 id="オンライン学習サイト">オンライン学習サイト</h3> <p>社内勉強会だけでは、エンジニアが必要とするトレーニングを提供することはできないことがあります。例えば、「業務では使っていない新しいプログラミング言語を学びたい」、「財務・会計の知識を深めて、会社の数字を理解できるようになりたい」、「リーダーシップ、コミュニケーションスキル、問題解決能力などのソフトスキルを学びたい」といった要望に応えるトレーニングすべてを社内勉強会で提要していくことは難しいです。</p> <p>そこで、当社はオンライン学習サイトと契約しており、希望者はそのサービスを利用して様々なコンテンツを学習することができます。このサイトを活用することで、当社のエンジニアは自身の長期的なキャリアプランに必要とされるスキルを自由に学ぶことができます。</p> <p>当社のエンジニアがオンライン学習サイトを利用して感じたことは、以下の記事に記載されています。興味をもたれたかたは、ご参照ください。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftech.i3-systems.com%2Fentry%2F2022%2F03%2F28%2F140520" title="使ってみないとわからない!新卒3人が福利厚生を利用してみた - i Cubed Systems Engineering blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://tech.i3-systems.com/entry/2022/03/28/140520">tech.i3-systems.com</a></cite></p> <h3 id="英語への取り組み">英語への取り組み</h3> <p>エンジニアの業務の中で避けて通ることができないものの一つに、英語を使って仕事をすることがあるでしょう。例えば、英語の仕様書を読むことや、外部ベンダーと英語でやり取をすることなどがあります。アイキューブドシステムズでは、社員の英語のスキルを高めるための取り組みが行われています。</p> <p>一つ目の取り組みは、英語勉強会です。定期的な英語の勉強会や、英語でコミュニケーションする、English Power Lunch がランチタイムに開催されています。これらの取り組みの詳しい様子は、以下の記事をご参照ください。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftech.i3-systems.com%2Fentry%2F2021%2F04%2F02%2F125700" title="英語への取り組み - i Cubed Systems Engineering blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://tech.i3-systems.com/entry/2021/04/02/125700">tech.i3-systems.com</a></cite></p> <p>二つ目の取り組みは、「TOEIC 社内受験制度」です。自分の英語力がどれくらいのレベルなのか、自分にどのスキルが不足しているのかを知ることができるように、年に2回オンラインでTOEIC Listening &amp; Reading IP テストが開催されてます。希望者は、無償でこのテストを受けることができます。当社の社員が、この制度を使った感想は、<a href="https://tech.i3-systems.com/entry/2022/03/28/140520#%E5%88%B6%E5%BA%A6">この記事</a>に記載されています。もしよかったら、ご一読ください。</p> <h2 id="学ぶことができる環境づくり">学ぶことができる環境づくり</h2> <p>入社後の教育プランや社内勉強会、英語の勉強会などは、社員が自ら考えて取り組んできた活動です。ここであげた活動だけにとどまることなく、当社では社員が学ぶことができる環境を作るためのカイゼン活動を定期的に実施しています。</p> <p>その中のひとつに「CLOMO の開発スタートガイド」の作成という活動があります。このガイドが出来上がる前は、トレーニングは、1対1の説明会形式で行なわれていましたが、新入社員へのトレーニング内容にばらつきが生じることがありました。また、開発メンバーの増加にともない、開発メンバーへのオンボーディング対応時間が増加の一途をたどっていました。</p> <p>このような課題を解決するために、「CLOMO の開発スタートガイド」が作成され、ここで作成されたコンテンツが教育のトレーニングに利用されています。この取り組みが実際に役に立ったと当社の社員が以下の記事を書いています。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftech.i3-systems.com%2Fentry%2F2022%2F12%2F20%2F214325" title="新人エンジニア、ドキュメントめっちゃつくる。 - i Cubed Systems Engineering blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://tech.i3-systems.com/entry/2022/12/20/214325">tech.i3-systems.com</a></cite></p> <p>チームメンバーが学ぶことができる環境を社員自らが考え作っていくことができる当社の文化を感じ取っていただけるのではないでしょうか。</p> <p>なお、「CLOMO の開発スタートガイド」の作成までの経緯や取り組み内容についての詳細は、以下の記事をご参照ください。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftech.i3-systems.com%2Fentry%2F2021%2F03%2F18%2F154142" title="CLOMOの開発スタートガイド作成までの道のり - i Cubed Systems Engineering blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://tech.i3-systems.com/entry/2021/03/18/154142">tech.i3-systems.com</a></cite></p> <h2 id="おわりに">おわりに</h2> <p>アイキューブドシステムズは、入社してから業務に取り組むまで、業務に取り組みながらキャリアパスに沿ってスキルを高めていくための仕組みがあることを理解していただけたのではないかと思います。</p> <p>また、新しく入った仲間が、後からチームにジョインする人がスムーズに業務に取り掛かることができるためにドキュメントを自発的に作成し、学ぶことができる環境を自ら作っている様子も理解していただけたのではないかと思います。</p> <p>私たちは、CLOMO MDM の製品開発を通じて、共に成長していける仲間を募集しています。 カジュアル面談・エントリーを、下記のページから随時受け付けています。</p> <ul> <li><a href="https://www.i3-systems.com/new-graduates/">新卒採用</a></li> <li><a href="https://www.i3-systems.com/careers/">キャリア採用</a></li> </ul> tafuji-i3 Kibanaコンテストを開催しました! hatenablog://entry/4207112889945574875 2022-12-28T13:36:38+09:00 2022-12-28T13:36:38+09:00 こんにちは!プラットフォーム運用部のchiwata-i3です。 今回は、社内でKibanaをより活用していくためにコンテストを実施しましたので、ご紹介します。 コンテスト開催の経緯 弊社では、各種ログをElasticsearchに集積し、Kibanaで可視化しています。 しかし、実際はログの検索や、プラットフォーム運用部がダッシュボードを使っている程度で、あまり活用できていませんでした。 そこで、Elasticsearch株式会社さまからダッシュボードを活用するためのコンテストのご提案をいただき、共同でKibanaの活用コンテストを実施しました。 しかも、豪華賞品を頂けるとのこと!! そこで、… <p>こんにちは!プラットフォーム運用部の<a href="https://github.com/chiwata-i3">chiwata-i3</a>です。</p> <p>今回は、社内でKibanaをより活用していくためにコンテストを実施しましたので、ご紹介します。</p> <h3 id="コンテスト開催の経緯">コンテスト開催の経緯</h3> <p>弊社では、各種ログをElasticsearchに集積し、Kibanaで可視化しています。 しかし、実際はログの検索や、プラットフォーム運用部がダッシュボードを使っている程度で、あまり活用できていませんでした。</p> <p>そこで、Elasticsearch株式会社さまからダッシュボードを活用するためのコンテストのご提案をいただき、共同でKibanaの活用コンテストを実施しました。 しかも、豪華賞品を頂けるとのこと!!</p> <p>そこで、コンテストを企画し、10/14(金)に開催しました。</p> <h3 id="Kibanaとは">Kibanaとは?</h3> <p>Elasticsearchサーチでインデックスされた各種データを、検索・可視化するツールです。</p> <p>例えば、下の図では、リリース候補環境のレスポンスコードを集計し、可視化しています。 <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/c/chiwata-i3/20221216/20221216151056.png" width="1200" height="441" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <p>詳細はElasticsearch社さまのページをご確認ください。 <a href="https://www.elastic.co/jp/what-is/kibana">https://www.elastic.co/jp/what-is/kibana</a></p> <h3 id="コンテストの目的">コンテストの目的</h3> <p>現状、データの蓄積や検索のみに使っているKibanaの使い方をみんなで試し、 開発・検証の効率・生産性アップにつながるようなデータの可視化、監視に挑戦することを目標に開催しました。</p> <p>また、みんなでKibanaの活用に挑戦する時間を作ることで、Kibanaの使い方&amp;できることを知り、コンテスト後もより一層データを活用していくことができると考えました。</p> <h3 id="参加者">参加者</h3> <p>福岡オフィスで9名+オンラインで2名+(プラットフォーム運用部から運営2名)が参加しました。 新卒からベテランまで幅広い層のエンジニアが揃いました。</p> <p>また、Elasticsearch株式会社さまから福岡オフィスに2名来社いただき、途中3名のオンラインでのサポートもいただきながら、コンテスト中の相談に乗っていただきました!</p> <h3 id="当日の様子">当日の様子</h3> <p>当日は会議室で相談/質問をしながら進めました。 オンライン組も質問しやすいようにZoomで相談を受け付けながら進めました。 <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/c/chiwata-i3/20221221/20221221101522.jpg" width="1200" height="900" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <h3 id="発表会の様子">発表会の様子</h3> <p>1日の最後にみなさんが作ったKibanaのダッシュボードを見せていただきました。 みなさん、数時間で作ったとは思えないほどのものを作られていて、開発・検証の効率・生産性アップにつながるさまざまなアイディアを形にされていました! <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/c/chiwata-i3/20221221/20221221101620.jpg" width="1200" height="900" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <h3 id="まとめ">まとめ</h3> <p>みなさんが積極的に参加してくださり、さまざまなKibanaの活用方法を考え、実行に移してくださったことで、 今後の業務の効率化につながり、また他にデータがみたい時でも、どのようにしたら見やすく表示できるかを学ぶことができたと思います。 とても良い取り組みだったと思うので、是非また開催したいです!</p> <p>最後に、弊社では採用活動を実施しています。 皆様のご応募をお待ちしております。</p> <p>・新卒採用:<a href="https://www.i3-systems.com/new-graduates/">https://www.i3-systems.com/new-graduates/</a></p> <p>・キャリア採用:<a href="https://www.i3-systems.com/careers/">https://www.i3-systems.com/careers/</a></p> chiwata-i3 初めてのチーム開発 hatenablog://entry/4207112889944787203 2022-12-27T10:29:35+09:00 2022-12-27T10:29:35+09:00 はじめに アイキューブドシステムズでXamarin iOSアプリ開発を担当しているhuong-i3です。 2022年6月に入社しました。入社前に独自勉強し、個人アプリを作ったレベルですが、入社後初めてチーム開発することになりました。 今回アイキューブドシステムズでチーム開発して体験したGitの使い方やチームの動き方について話したいと思います。 プロジェクトの概要 入社後、1ヶ月の研修が終わった後にOJTとしてプロジェクトに入りました。 開発対象アプリはiOS版とAndroid版が存在します。開発効率の向上、アプリの品質を上げるため、Xamarinを採用し、Xamarin.iOSから開発していま… <h2 id="はじめに">はじめに</h2> <p>アイキューブドシステムズでXamarin iOSアプリ開発を担当している<a href="https://github.com/huong-i3">huong-i3</a>です。</p> <p>2022年6月に入社しました。入社前に独自勉強し、個人アプリを作ったレベルですが、入社後初めてチーム開発することになりました。</p> <p>今回アイキューブドシステムズでチーム開発して体験したGitの使い方やチームの動き方について話したいと思います。</p> <h2 id="プロジェクトの概要">プロジェクトの概要</h2> <p>入社後、1ヶ月の研修が終わった後にOJTとしてプロジェクトに入りました。</p> <p>開発対象アプリはiOS版とAndroid版が存在します。開発効率の向上、アプリの品質を上げるため、Xamarinを採用し、Xamarin.iOSから開発しています。</p> <p>Xamarin は .NET を使用して、iOS、Android、Windows 向けのアプリケーションをビルドするためのオープンソースのプラットフォームです。Xamarin.iOSを使用すると、C#言語とVisual Studio for MacやVisual StudioのIDEでネイティブのiOSアプリケーションを作成することができます。</p> <p>私が参加した時点はプロジェクトが進行中の状態で、チームメンバーは私を含めて7名でした。</p> <h3 id="プロジェクトの動き方">プロジェクトの動き方</h3> <p>アジャイルフレームワークのスクラム(Scrum)を利用してプロジェクトを進めます。1スプリントが2週間です。毎日チーム内ミーティングがあり、隔週の金曜日にスプリントレビューとスプリントプランニングを行います。</p> <p>チーム内ミーティングは各メンバーが担当している課題の状況を共有します。実装の品質を高めるため、課題対応が終わったら、クローズする前に担当者がチームの前で動作確認し、漏れがないかチームで最後の確認をします。 スプリントレビューは終わったスプリントの生産性、起こった問題や改善できたことをまとめて共有します。 スプリントプランニングは次のスプリントで各メンバーの対応する課題を決めます。 フルリモートなので、もちろんTeamsで通常にやりとりしていますが、ミーティングで顔合わせて「一緒に仕事をしている」と共感できると思います。</p> <p>課題はJIRA、資料はConfluence、コードはGitHubで管理されます。</p> <h3 id="プロジェクトの環境構築">プロジェクトの環境構築</h3> <p>チーム開発なので、同じコードを共通して、同じ設定、同じ動きをすることが大切です。</p> <p>プロジェクトの範囲が広く、またMacbookのみ開発するメンバーとWindows+Macbook組み合わせ開発するメンバーがいます。既に環境構築ガイドがあり、よくあるエラーが記載するトラブルシューティング資料があって助かりました。</p> <h2 id="チーム開発で初めての体験">チーム開発で初めての体験</h2> <h3 id="マージコンフリクト">マージコンフリクト</h3> <p>初課題を作業して、ワクワクしながらプルリクエストを出したとたん、GitHubの自動チェックで「This branch has conflicts that must be solved」(このブランチには解決しなければならない競合があります)とのエラー。 自分が一生懸命コードを書いている間に他のメンバーも同じく頑張っているので、同じ箇所のコードが修正されたエラーです。一つずつ確認してどうすれば良いか決めて修正するしかありません。一人開発はこういう競合対応がありませんでした。</p> <p>開発課題対応フローを紹介します。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_da493733ed327375732ae914350965ad.png" alt="" /></p> <p>Squash and mergeは、プルリクエスト(PR)を一つのコミットにまとめるので、メインのブランチから見やすくなります。</p> <p>競合を対応するとき、Gitコマンドを使うと難しくて、GUIのあるツールを使う方が楽だとアドバイスしてもらい、Sourcetreeを使うことにしました。画面でコードの変更が確認できるので、わかりやすいです。</p> <h3 id="余計なコードをコミット">余計なコードをコミット</h3> <p>GitHubにアップロードしたくないファイルは.gitignoreで定義されますが、開発中時々IDEが自動生成したファイルを意識がなくコミットしてしまい、プルリクエストしたら「不要なファイルを消してくだい」との指摘を受けました。個人開発の時は気にせず全てコミットしていました。</p> <p>共通コードベースなので気をつけないと不要なファイルがどんどん増えてしまいますね。プルリクエストを出すとき、自己レビューしてGitHubに不要なファイルやコードをアップしてないかもう一度確認するようにしました。</p> <h3 id="テストコード">テストコード</h3> <p>本プロジェクトはxUnitという単体テストフレームワークを使っています。テストケースを書くのに時間がかかりますが、毎回修正が入る時自動で一括検証できるので、品質を確保できるし、開発者としても安心してコーディングできます。</p> <p>上手くテストコードを書けるようにUdemyでオンラインコースを受ける予定です。</p> <h3 id="プロジェクトの構成">プロジェクトの構成</h3> <p>本プロジェクトは前のプロジェクトから継承して構成を改修されています。アーキテクチャや他のアプリにも共有できる機能の共通化も配慮しながらやっていきます。 クリーンアーキテクチャとMVVMの組み合わせでより依存性を減らしてテスタビリティ(テスト容易性)を向上することを期待しています。 その代わりコードの量は増えてしまうため、理解して上手く使えるまで時間がかかりそうです。私の場合、コードを書く場所を間違えたり、考えすぎて余計なコードを書いたりしたことがあります。プルリクエストのレビューで指摘と説明をしてもらって理解した上で修正しました。</p> <p>アーキテクチャの本だけ読むより読みながら実際のコードを理解する方が積極的に勉強できます。</p> <h2 id="おわりに">おわりに</h2> <p>一人でコツコツ調べてコーディングするより、チームでもっと大きなプロジェクトの開発ができ、悩んでいる課題について相談できる仲間がいて嬉しいです。 さらに、話したオンラインコースや参考書籍は会社側の負担で利用できます。</p> <p>一緒にコーディングを楽しむ仲間を探しています。興味のある方ぜひ一度面談をしてみてください。</p> <ul> <li><p>新卒採用:<a href="https://www.i3-systems.com/new-graduates/">https://www.i3-systems.com/new-graduates/</a></p></li> <li><p>キャリア採用:<a href="https://www.i3-systems.com/careers/">https://www.i3-systems.com/careers/</a></p></li> </ul> huong-i3 在宅ワークによる運動不足解消のための取り組み hatenablog://entry/4207112889944722855 2022-12-26T15:38:38+09:00 2022-12-27T11:28:46+09:00 はじめまして、モバイルサイドエンジニアを担当しているdate-i3です。 2022年6月に入社し、実際の業務に慣れてきた今日この頃。作業内容は不具合の調査や改修と、毎日パソコンとにらめっこしています。 前職もエンジニアをしていた私は、毎日眼精疲労と肩こり、時々頭痛といった不調に悩まされていました。 今も完全にこれらの不調がなくなったというわけではありませんが、以前よりもましになったと感じています。 個人的に運動習慣を作ったというのもあるでしょうが、オフィストレーニングも改善に役立っているのではないかと思います。 弊社では社員の健康維持・促進のために体を動かす時間を設けています。それが「オフィス… <p>はじめまして、モバイルサイドエンジニアを担当している<a href="https://github.com/date-i3">date-i3</a>です。</p> <p>2022年6月に入社し、実際の業務に慣れてきた今日この頃。作業内容は不具合の調査や改修と、毎日パソコンとにらめっこしています。</p> <p>前職もエンジニアをしていた私は、毎日眼精疲労と肩こり、時々頭痛といった不調に悩まされていました。 今も完全にこれらの不調がなくなったというわけではありませんが、以前よりもましになったと感じています。 個人的に運動習慣を作ったというのもあるでしょうが、オフィストレーニングも改善に役立っているのではないかと思います。</p> <p>弊社では社員の健康維持・促進のために体を動かす時間を設けています。それが「オフィストレーニング」です。 今回はその「オフィストレーニング」について紹介していこうと思います。</p> <h2 id="オフィストレーニングとは">オフィストレーニングとは</h2> <p>オフィストレーニングとは、毎週1〜2日あるインストラクターの先生と一緒に体を動かす時間です。 15分のショートトレーニングと、30分のトレーニングに分かれており、業務時間内で実施されているため仕事の合間のリフレッシュや運動不足解消に役立ちます。</p> <p>例えば11月は次のようなテーマで実施されました。</p> <p>〇15分ストレッチ・エクササイズ<br> 11/8(火) 代謝UP!体を温めるストレッチ&amp;エクササイズ<br> 11/15(火) 眼精疲労、頭痛解消!疲労回復のためのセルフマッサージとストレッチ<br> 11/22(火) 運動不足解消ちょいきつトレーニング<br> 11/29(火) ボディメイクエクササイズ!腹筋、背中、腕トレ!汗をかいて爽快リフレッシュ!</p> <p>〇30分ストレッチ・エクササイズ<br> 11/4(金) 冷え、むくみ解消!簡単ストレッチと簡単エクササイズ<br> 11/18(金) 肩こり、腰痛の予防、改善ストレッチ!<br></p> <p>参加は強制ではないため、自分が参加したい!不調を治したい!と思ったテーマのみ参加できます。 わたしは基本毎回参加しています。 インストラクターの先生と参加者が見れるため、家の中ですがみんなで一緒に取り組んでいる感覚になり楽しいです。 まるでオンラインジム!(通ったことがないので想像です)</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/d/date-i3/20221216/20221216124227.png" width="1200" height="671" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <h2 id="リモートワークでより運動不足に">リモートワークでより運動不足に…</h2> <p>弊社は現在も原則リモートワークです。 そう、基本椅子の上にいるだけで毎日の歩数は1桁です。「通勤」という唯一の運動がなくなってしまった今、運動の習慣はほとんど0になってしまいました。</p> <p>リモートワークには自由に時間が使えるというメリットもありますが、私のような引きこもりには運動不足になるというデメリットもあったのです。 運動不足になると肩こりや腰痛がより悪化するとか…。</p> <p>ですが運動不足という問題も、オフィストレーニングに参加すれば一発解決です。 ちょいきつトレーニングという名目で、呼吸が乱れるほどの運動も実施されています。(個人差あり)</p> <p>しかも仕事の合間に取り組めるので、業務に詰まっているときなどはいい気分転換になります。たかが15分の運動ですが、15分だらだら詰まっている部分を悩むよりかは有意義な時間を過ごせると思っています。 一旦頭がリセットされるので、新しい観点に気付けます。</p> <h2 id="継続して取り組んだ結果">継続して取り組んだ結果</h2> <p>前述しましたがわたしは極度の引きこもりです。運動習慣は通勤時の自転車と徒歩のみでした。</p> <p>しかしオフィストレーニングに参加するようになり、運動やストレッチの楽しさを知った今は自発的に毎日30分~1時間の運動時間を取り入れるようになりました。</p> <p>このまま不調を緩和させて、仕事のパフォーマンスを上げて良い結果を出したいです。</p> <p>最後に、弊社では採用活動を実施しています。 皆様のご応募をお待ちしております。<br> - 新卒採用:<a href="https://www.i3-systems.com/new-graduates/">https://www.i3-systems.com/new-graduates/</a><br> - キャリア採用:<a href="https://www.i3-systems.com/careers/">https://www.i3-systems.com/careers/</a></p> date-i3 Capture The Flagを社内で紹介した話 hatenablog://entry/4207112889944645039 2022-12-23T10:03:29+09:00 2022-12-27T11:06:35+09:00 アイキューブドシステムズで製品開発運用本部に所属している nakano-i3 です。 弊社では、定期的に社内勉強会を開催しており、社員それぞれが持つ知識・スキルをチーム全体・社内全体に対して共有すること、知識や技術力の向上を目的としております。以前であればエンジニアが社内勉強会を主催し、エンジニア以外の社員が参加することもありましたが、近年はカスタマーサポート部門や経理部門が主催する勉強会にエンジニアが参加することもあります。 今回は、エンジニア主催の社内勉強会でCapture The Flag(以降、CTF)について紹介する機会がありましたので、弊社のエンジニアブログでも紹介したいと思います… <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_375bce2076eea49943bc9dae9b34a35d.jpg" alt="Capture The Flagを社内で紹介した話" /></p> <p>アイキューブドシステムズで製品開発運用本部に所属している <a href="https://github.com/nakano-i3">nakano-i3</a> です。</p> <p>弊社では、定期的に社内勉強会を開催しており、社員それぞれが持つ知識・スキルをチーム全体・社内全体に対して共有すること、知識や技術力の向上を目的としております。以前であればエンジニアが社内勉強会を主催し、エンジニア以外の社員が参加することもありましたが、近年はカスタマーサポート部門や経理部門が主催する勉強会にエンジニアが参加することもあります。</p> <p>今回は、エンジニア主催の社内勉強会でCapture The Flag(以降、CTF)について紹介する機会がありましたので、弊社のエンジニアブログでも紹介したいと思います。</p> <h2 id="なぜ社内勉強会で紹介しようと考えたか">なぜ社内勉強会で紹介しようと考えたか</h2> <p>サイバーセキュリティについて学ぶにはネットワーク、サーバ、OS、アプリケーションなど幅広い知識や技術が求められておりますが、幅広い知識や技術を学ぶのに何から始めて良いか分からず五里霧中となっておりました。何か良い方法がないかと探していた時にCTFというものがあることを知り、体験してみることにしました。 <img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_a8b846515b4cbb239ea07f7a63711141.png" alt="CTFを知る" /></p> <p>体験してみて感じたことは、CTFを進めることでゲーム感覚で系統立てて学べそうだなと思い、これを社内で紹介しつつ自分の学びに繋げたいなと思い社内勉強会で紹介することにしました。</p> <h2 id="Capture-The-Flagとは">Capture The Flagとは</h2> <p>CTFは、コンピュータやセキュリティの知識・技術を競う競技となります。出題内容からFLAG(フラッグ)と呼ばれる答えを探すことから、「Capture」(獲得する)、「The Flag」(フラグ)で、Capture The Flag(略称:CTF)と名付けられています。</p> <h2 id="CTFには大会がある">CTFには大会がある</h2> <p>コンピュータや情報セキュリティーに関係した国際的なイベントのDEFCON(デフコン)の中で講演をはじめ、CTFの大会なども行われています。日本ではSECCON(セクコン)などが開催されており、学生向けのCTFコンテストなども開催されております。</p> <p>CTFの大会はチーム戦となっており、DEFCON CTF 2022の参加ブログなどから企業のチームや社会人と学生の混成チームなど世界各国から多数のチームが参加された様です。</p> <h5 id="CTF大会の一例">CTF大会の一例</h5> <ul> <li><a href="https://defcon.org/">DEFCON</a></li> <li><a href="https://www.seccon.jp/2022/">SECCON</a></li> <li><a href="https://linecorp.com/ja/pr/news/ja/2022/4147">LINE CTF</a></li> <li><a href="https://scan.netsecurity.ne.jp/article/2022/11/01/48416.html">NEC Security Skills Challenge for Students 2022(学生向け) </a> <img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_11c8532f99d2821d2052fcf1cbde2cf7.png" alt="CTF大会イメージ" /></li> </ul> <h2 id="CTFについて学ぶ方法">CTFについて学ぶ方法</h2> <p>弊社の社内勉強会では、これまで話してきたCTFの説明に加えて、CTFを学ぶ方法についてconnpassで公開されている社外勉強会や書籍の紹介を行いました。また、先に紹介したSECCONでは、SECCON BEGINNERSというCTF未経験者向け勉強会も開催されておりますので、SECCON BEGINNERSの紹介も行いました。</p> <h5 id="社内勉強会の様子">社内勉強会の様子</h5> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_a9cfb43c417aa89fd1a78c85904914ec.png" alt="社内勉強会の様子" /></p> <h5 id="社外勉強会の一例">社外勉強会の一例</h5> <ul> <li><a href="https://west-sec.connpass.com/">WEST-SEC</a></li> <li><a href="https://zeroctf.connpass.com/">ゼロから始めるCTF</a></li> <li><a href="https://www.seccon.jp/2022/beginners/about-seccon-beginners.html">SECCON BEGINNERS</a> <img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_b1637414cd6a92939cd9d31cff85bc3a.png" alt="勉強会" /></li> </ul> <h5 id="書籍">書籍</h5> <ul> <li><a href="https://www.amazon.co.jp/%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%E3%82%B3%E3%83%B3%E3%83%86%E3%82%B9%E3%83%88%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8%E3%83%96%E3%83%83%E3%82%AF-CTF%E3%81%A7%E5%AD%A6%E3%81%BC%E3%81%86-%E6%83%85%E5%A0%B1%E3%82%92%E5%AE%88%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E6%88%A6%E3%81%84%E6%96%B9-%E7%A2%93%E4%BA%95-%E5%88%A9%E5%AE%A3/dp/4839956480/">セキュリティコンテストチャレンジブック</a></li> <li><a href="https://www.amazon.co.jp/%E8%A9%B3%E8%A7%A3%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%E3%82%B3%E3%83%B3%E3%83%86%E3%82%B9%E3%83%88-CTF%E3%81%A7%E5%AD%A6%E3%81%B6%E8%84%86%E5%BC%B1%E6%80%A7%E6%94%BB%E7%95%A5%E3%81%AE%E6%8A%80%E8%A1%93-%E6%A2%85%E5%86%85-%E7%BF%BC/dp/4839973490/">詳解セキュリティコンテスト</a></li> <li><a href="https://www.amazon.co.jp/%E5%85%A5%E9%96%80%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%E3%82%B3%E3%83%B3%E3%83%86%E3%82%B9%E3%83%88%E3%83%BC%E3%83%BCCTF%E3%82%92%E8%A7%A3%E3%81%8D%E3%81%AA%E3%81%8C%E3%82%89%E5%AD%A6%E3%81%B6%E5%AE%9F%E6%88%A6%E6%8A%80%E8%A1%93-%E4%B8%AD%E5%B3%B6-%E6%98%8E%E6%97%A5%E9%A6%99/dp/4297131803">入門セキュリティコンテスト</a> <img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_87110dbf5050e990ad2493a428a4db4e.png" alt="書籍" /></li> </ul> <h2 id="CTFの種類">CTFの種類</h2> <p>CTFには、大きく分けてクイズ形式と攻防戦形式の二つの形式があります。</p> <p>一つ目のクイズ形式(Jeopardy形式)は、コンピュータやセキュリティに関する出題を解く形式、二つ目の攻防戦形式(Attack&amp;Defence形式)は、各チームに与えられたサーバーを守りながら他のチームのサーバを攻撃するといったものとなります。クイズ形式・攻防戦形式の中から、今回の社内勉強会ではクイズ形式のCTFにフォーカスして説明を行いました。</p> <h2 id="クイズ形式のCTFで出題されるジャンル">クイズ形式のCTFで出題されるジャンル</h2> <p>クイズ形式のCTFでは、次のようなジャンルが出題されます。</p> <table> <thead> <tr> <th> ジャンル </th> <th> 出題内容 </th> </tr> </thead> <tbody> <tr> <td> Reversing <br>(リバーシング)</td> <td> 実行ファイルを解析する問題 </td> </tr> <tr> <td> Pwn<br>(ポウン・パウン)</td> <td> サーバプログラムが持つ脆弱性を突く問題 </td> </tr> <tr> <td> Web </td> <td> Webに関する問題。Webアプリケーションが持つ脆弱性を突く問題が多い。 </td> </tr> <tr> <td> Crypto<br>(クリプト)</td> <td> 暗号を解読する問題 </td> </tr> <tr> <td> Network </td> <td> ネットワークの通信を解析する問題 </td> </tr> <tr> <td> Forensics<br>(フォレンジック)</td> <td> 与えられたファイルを解析する問題 </td> </tr> <tr> <td> Steganography<br>(ステガノグラフィー)</td> <td> あるデータに隠蔽されたデータを探す問題 </td> </tr> <tr> <td> PPC<br>(Professional Programming and Coding)</td> <td> プログラミングを使って解く問題 </td> </tr> <tr> <td> Recon<br>(リーコン)</td> <td> ある特定の人物を調査する問題 </td> </tr> <tr> <td> Misc<br>(ミスク)</td> <td> 上記のジャンルに当てはまらないコンピュータの雑学、練習問題 </td> </tr> </tbody> </table> <h2 id="CTFを体験してみよう">CTFを体験してみよう</h2> <p>CTFについて学ぶ方法に加えて、常設しているCTFがインターネット上に色々とありますので、そちらでも学ぶこともできます。調べていく内に以下の2つの常設CTFがブログなどでよく紹介されております。CTF初心者向けの常設CTFが「CpawCTF」、難しいのが「ksnctf」の様で、私も実際に試してみましたが「ksnctf」は出題内容が難しく、解答することができませんでした。</p> <p><strong>初心者向け:</strong><a href="https://ctf.cpaw.site/index.php">CpawCTF</a><br> <strong>中級者以上向け:</strong><a href="https://ksnctf.sweetduet.info/">ksnctf</a></p> <p>弊社の社内勉強会でもCTFを体験してみようということで、「CpawCTF」からQ6、Q8、Q9の問題に挑戦してもらいました。</p> <ul> <li>Q6.[Crypto] Classical Cipher</li> <li>Q8.[Misc] Can you open this file ?</li> <li>Q9.[Web] HTML Page</li> </ul> <p><strong>CTFの体験の様子</strong> <img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_dcc1f641fa9a1c9061577a7656e146a0.png" alt="CTFの体験の様子" /></p> <p>体験された方からは「楽しかったよ」といった言葉や「こっちのやり方もあるよ」など知識共有も行われ、社内勉強会を開催して良かったなと感じております。</p> <h2 id="まとめ">まとめ</h2> <p>本記事の冒頭でも説明しましたが、情報セキュリティと言ってもネットワーク、サーバ、OS、アプリケーションなど幅広い知識や技術が求められております。幅広い知識や技術を学ぶのに何か良い方法をと探して出会ったのがCTFでした。</p> <p>CTFの色々な出題を解答していくために、ネットで調べたり社内エンジニアに質問したりして「あー、そうやるのか」、「このコマンド使うのか」と気づきになることも学びと考えております。</p> <p>たとえば、「CpawCTF」のQ7は、あるファイル種類を調べ実行する出題内容となっており、私が利用しているPCではファイルの種類を調べることができても、実行時にエラーとなり実行できませんでした。エラーメッセージをネットで検索して「どうしてできないのか」「どうやったらできるのか」を知ることができましたが、それも一つの学びと思います。</p> <h2 id="最後に">最後に</h2> <p>今回の記事では、CTFを社内勉強会で紹介したことについて触れましたが、弊社ではtafuji-i3が書いたブログの様に社内勉強会で自分の興味があることを紹介したりすることができます。</p> <p><strong>開催実績 100 回以上の社内勉強会の様子を紹介:</strong><a href="https://tech.i3-systems.com/entry/2020/10/12/142550">https://tech.i3-systems.com/entry/2020/10/12/142550</a></p> <p>CTFやサイバーセキュリティの知識・技術が豊富な方に入社いただいて、社内勉強会を開催してもらえると嬉しいなと思っております。弊社ではエンジニアを含めて採用活動を実施しており、PSIRT経験者などセキュリティエンジニアを始め、CTF得意です!という方など皆さまのご応募をお待ちしております。</p> <p><strong>新卒採用:</strong><a href="https://www.i3-systems.com/new-graduates/">https://www.i3-systems.com/new-graduates/</a><br> <strong>キャリア採用:</strong><a href="https://www.i3-systems.com/careers/">https://www.i3-systems.com/careers/</a></p> nakano-i3 コード品質を確保するためのチェック項目 hatenablog://entry/4207112889941765104 2022-12-21T14:02:05+09:00 2022-12-22T09:06:31+09:00 はじめに アイキューブドシステムズでCLOMOのサーバーサイドを担当している Kakuno です。 今回は弊社のコード品質を確保するための、チェック項目の仕組みついて紹介したいと思います。 チェック項目とは 実装したコードはプルリクエストの時にメンバーのレビューなどで見直しをすることがあると思います。この時、熟練者であれば的確な指摘が出来ますが、レビュワーによって指摘内容が異なる、指摘を見落としてしまうなど様々な要因でコード指摘が的確に出来ないことがあると思います。そこで、弊社ではツールを用いて色んな角度からコードの見直しをしています。 Lintツールによる見直し 以前に、静的解析ツールの導入… <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/c/clomo-dev/20221205/20221205165649.png" width="1200" height="630" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <h2 id="はじめに">はじめに</h2> <p>アイキューブドシステムズでCLOMOのサーバーサイドを担当している <a href="https://www.linkedin.com/in/tetsuhiro-kakuno-078862100/">Kakuno</a> です。 今回は弊社のコード品質を確保するための、チェック項目の仕組みついて紹介したいと思います。</p> <h2 id="チェック項目とは">チェック項目とは</h2> <p>実装したコードはプルリクエストの時にメンバーのレビューなどで見直しをすることがあると思います。この時、熟練者であれば的確な指摘が出来ますが、レビュワーによって指摘内容が異なる、指摘を見落としてしまうなど様々な要因でコード指摘が的確に出来ないことがあると思います。そこで、弊社ではツールを用いて色んな角度からコードの見直しをしています。</p> <h2 id="Lintツールによる見直し">Lintツールによる見直し</h2> <p>以前に、<a href="https://tech.i3-systems.com/entry/2020/08/11/%E3%83%8F%E3%83%83%E3%83%94%E3%83%BC%E3%81%AA%E9%96%8B%E7%99%BA%E3%83%A9%E3%82%A4%E3%83%95%E3%82%92%E9%81%8E%E3%81%94%E3%81%99%E3%81%9F%E3%82%81%E3%81%AB%E9%9D%99%E7%9A%84%E8%A7%A3%E6%9E%90%E3%83%84">静的解析ツールの導入</a>で紹介したのですが、弊社では静的解析ツール(Lintツール)を用いてコード指摘を行っています。これらは会社内のルールを制定して、それに違反しているものをプルリクエストで指摘する形をとっています。 <img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_75ad5fdfff34ad615ada781b1c0183ea.png" alt="" /></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftech.i3-systems.com%2Fentry%2F2020%2F08%2F11%2F%25E3%2583%258F%25E3%2583%2583%25E3%2583%2594%25E3%2583%25BC%25E3%2581%25AA%25E9%2596%258B%25E7%2599%25BA%25E3%2583%25A9%25E3%2582%25A4%25E3%2583%2595%25E3%2582%2592%25E9%2581%258E%25E3%2581%2594%25E3%2581%2599%25E3%2581%259F%25E3%2582%2581%25E3%2581%25AB%25E9%259D%2599%25E7%259A%2584%25E8%25A7%25A3%25E6%259E%2590%25E3%2583%2584" title="ハッピーな開発ライフを過ごすために静的解析ツールを本格導入した - i Cubed Systems Engineering blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://tech.i3-systems.com/entry/2020/08/11/%E3%83%8F%E3%83%83%E3%83%94%E3%83%BC%E3%81%AA%E9%96%8B%E7%99%BA%E3%83%A9%E3%82%A4%E3%83%95%E3%82%92%E9%81%8E%E3%81%94%E3%81%99%E3%81%9F%E3%82%81%E3%81%AB%E9%9D%99%E7%9A%84%E8%A7%A3%E6%9E%90%E3%83%84">tech.i3-systems.com</a></cite></p> <h3 id="RuboCop">RuboCop</h3> <p>RuboCopではRubyに対するコードの見直しを行います。 弊社内で策定したRuby on Railsのコーディングルールに従い、怪しいコードがある場合は適宜レビューコメントとして指摘してくれます。 <img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_b7b46109a4f1384abf17b026029450d8.png" alt="" /></p> <h3 id="ESLint">ESLint</h3> <p>ESLintではJavaScriptに対するコードの見直しを行います。 こちらも弊社内で策定したコーディングルールに従い、怪しいコードがある場合は適宜レビューコメントとして指摘してくれます。 <img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_96cd251f389be28c9b105bbeaba08c06.png" alt="" /></p> <h2 id="Snykによる見直し">Snykによる見直し</h2> <p>弊社ではSnykを試験的に導入しています。 その中でSnyk Codeというツールを用いて、脆弱性があるコードの見直しを行っています。 <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fsnyk.io%2Fproduct%2Fsnyk-code%2F" title="Code Security &amp; Code Quality Scanning | Snyk Code" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://snyk.io/product/snyk-code/">snyk.io</a></cite></p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_87d05145022adec81b7bfc20b9dc3ca8.png" alt="" /> セキュリティ上詳細はお見せできませんが、例えば<strong>Use of Hardcoded Credeintials</strong>はセキュリティ情報がハードコーディングされているという指摘をしてくれています。 現在は定期的なミーティングを行い、このような指摘を一つ一つチェックしていきコードの見直しを行っています。SnykではIDEやCI/CDとの連携も可能ですので今後検討しています。</p> <h2 id="最後に">最後に</h2> <p>このように色んな角度からコードを見直すことで、意図しないバグの混入や脆弱性への対応を行っています。また見直すことで自分の書いたコードはどのような欠点があったのか、等自身のコーディングスキルを見直すきっかけにもなります。今後もこのような改善を積極的に行っていきたいと思っています。</p> <p>私たちは、CLOMO MDMの製品開発を通じて、共に成長していける仲間を募集しています。 また、カジュアル面談・エントリーも、下記のページから随時受け付けています。 <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.i3-systems.com%2Fcareers%2F" title="採用情報|株式会社アイキューブドシステムズ" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.i3-systems.com/careers/">www.i3-systems.com</a></cite></p> clomo-dev 新人エンジニア、ドキュメントめっちゃつくる。 hatenablog://entry/4207112889937087683 2022-12-20T21:43:25+09:00 2022-12-20T21:45:34+09:00 この記事におけるドキュメントとは CLOMOのサーバーサイドを担当しているMisaki-i3です。 入社してから10ヶ月が経過し、業務を通じて製品に貢献できている自覚も得られるようになってきました。 さまざまな課題に取り組む中、あらゆる場面でその重要性を感じさせたのが、調べたことや理解したことをドキュメントに出力しておくことです。 システム開発におけるドキュメントといえば、マニュアル・仕様書・設計書・報告書等を指すようですが、この記事では、調査記録・開発メモ・学習ノート等を含む文書全般のことを指します。逆に、仕様書や設計書作成には触れません。 弊社のドキュメント管理はAtlassianのCon… <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/M/MisakiShiote-i3/20221116/20221116161029.png" width="1200" height="630" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <h2 id="この記事におけるドキュメントとは">この記事におけるドキュメントとは</h2> <p>CLOMOのサーバーサイドを担当している<a href="https://github.com/MisakiShiote-i3">Misaki-i3</a>です。<br/> 入社してから10ヶ月が経過し、業務を通じて製品に貢献できている自覚も得られるようになってきました。</p> <p>さまざまな課題に取り組む中、あらゆる場面でその重要性を感じさせたのが、調べたことや理解したことをドキュメントに出力しておくことです。</p> <p>システム開発におけるドキュメントといえば、マニュアル・仕様書・設計書・報告書等を指すようですが、この記事では、調査記録・開発メモ・学習ノート等を含む文書全般のことを指します。逆に、仕様書や設計書作成には触れません。</p> <p>弊社のドキュメント管理はAtlassianのConfluenceで行っています。<br/> 多くの類似サービスと同様、容易に文書の装飾や図表の挿入ができ、ページを増やしても紙は減らず、ページを削除してもゴミが出ません。<br/> アカウントごとにパーソナルスペースがあるため、いくつページを作っても共有スペースを乱しませんし、1−2行だけ書いたきり使わなかった、メモ帳として利用したあと削除したなどという行為も気兼ねなくできます。</p> <p>このハードルの低さも前提におき、私の経験に基づいた、作業の効率化に寄与するドキュメント作成についていくつか紹介します。</p> <h2 id="頭の中のメモリを開放する---開発効率を上げる">頭の中のメモリを開放する - 開発効率を上げる</h2> <p>コードを読み解く作業などでは、脳の一時記憶領域を大量に使います。<br/> ロジックの理解に苦戦しながら、そもそもなんのために調査をしているのか、何を見つけたくて処理を追っているのかといった目的も忘れられません。コードを読む途中で新たな仮説が立てば、次に調べるべきものとして記憶に留めておくことになります。</p> <p>これらの一時記憶のうち、必要になったら思い出せばよいものはすべてドキュメントに書き出してしまいます。<br/> 空いた領域はロジックの理解につぎ込み、調査に対する集中を確保する目的です。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_e3bab7467f807dbcd8f75119df67a59d.png" alt="パンクするサーバー" /></p> <p>もう少しでAが終わるから、次はBを検証しようかな。ところがAの調査中に有力な情報や手がかりが見つかり、少し脱線した隙にBのことを忘れてしまった。</p> <p>このようなケースは頻繁にあります。(ありませんか? すごい)<br/> 「何か忘れている気がするなあ」ともやもやしながら別の作業に着手し、あるときBに関連するコードを見て思い出すことになるのでしょう。</p> <p>問題は、そのような経験を何度も繰り返すと、何も忘れていない場合も「どうせ何か忘れているのだろうから思い出さなきゃなあ」と考えてしまうようになります。(私はなるのです)<br/> 常にもやもやし続け、思い出すことは不可能なため長く継続します。<br/> このもやもやにメモリを食われるのは非常にもったいないことです。</p> <p>これを解決する術はもちろん、次にやること、次に検証したい仮説も、思いついた時点でドキュメントに書き留めておくことです。<br/> 書き留める作業が大きな負担に感じてしまう場合を除き、「頭の片隅に残しておく」という大きな負担は避けるに限ります。</p> <h2 id="質問しようと思ったとき質問はすでに終わっているのだ---質問の質を上げる">質問しようと思ったとき、質問はすでに終わっているのだ - 質問の質を上げる</h2> <p>新人エンジニア 質問、と検索すると、様々な質問の失敗例を見つけられます。<br/> それら失敗の原因の多くは、「情報が整理できていないため」のようです。</p> <p>「ここでエラーが出てしまったんです……<br/>  AAAを確かめようと思ってBBBを見たら<br/>  多分CCCあたりにDDDがあって……<br/>  あ、あったのはDDDじゃなくてEEEでした。<br/>  あ、そっか、BBBを見たのはAAAのついでにFFFを確かめようとしたときでした。<br/>  あ、FFFのときってことは、<br/>  あっ、勘違いでした、大丈夫です……」</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_ee30fcf49cda2c47636e37c47cba55e0.png" alt="リモコンをたくさん抱える人" /></p> <p>良い質問をするためには、自分の持つ情報を整理し、俯瞰し、取捨選択して提供する能力が必要になります。<br/> 質問経験の乏しい初心者が情報の取捨選択を行うのは難しいものの、情報を整理し俯瞰することは比較的取り組みやすいと思います。<br/> そのために、作業中に取ったアクション・得られた情報は、リアルタイムにドキュメント上に出力しておきましょう。</p> <p>何を知りたくて、何を期待して、何を試し、何が分かったか・何が期待はずれだったかを記録しておきます。<br/> 質問をする際にはそこから選び取ります。</p> <p>調査中のメモをどれだけ詳細に書くかはまちまちで構わないと考えていますが、最低限、質問や途中報告のときに使うかもしれない情報は記録しておきます。<br/> 丁寧にまとめあげる必要はありません。必要に迫られたとき整理する程度で良いと考えます。</p> <h2 id="自分に向けての報告書を持っておく---報告のハードルを下げる">自分に向けての報告書を持っておく - 報告のハードルを下げる</h2> <p>弊社では、システムの解決すべき課題は扱いやすい大きさに分割され、AtlassianのJiraというサービス上でチケットとして管理されています。<br/> 本項では、チケット管理されているうちの一件を指して「課題」と呼びます。</p> <p>さて、私が課題に着手するほとんどの場合、「調査資料」として一つのドキュメントを課題に紐付けます。<br/> 前項までに紹介した作業中の記録とは異なり、調査資料としてのドキュメントは報告書のような形式で記述します。<br/> (いまのところチームとして運用を定義しているわけではないため、内容は柔軟に変更します)</p> <p>入社当初は手探りで作成していた調査資料も、半年後には形式が定まってきました。</p> <ol> <li>主なリンク集(課題・関連ドキュメント)</li> <li>課題の概要</li> <li>課題のゴール(要件・期待される動作)</li> <li>分かっていること</li> <li>分からないこと・これから調査すべきこと</li> </ol> <p>ここを対象課題への取り組みの拠点と定め、やや外向きな言葉遣いで記述していきます。<br/> 自分に向けてとは言いつつ、「課題のことをすっかり忘れてしまってもいいようにまとめておくぞ」という心持ちで作成しているため、実質は第三者のエンジニアへ向けるものと同じ基準と言えましょう。</p> <p>この資料のメリットは、(なんのひねりもありませんが、)この調査資料の内容をそのまま各所への報告・相談に転用できることです。<br/> チームの朝会での報告、課題チケットに対する報告、もちろん質問時に概要を伝えたい際にも、この資料をベースに内容を作成します。<br/> コピペで十分な場面も少なくありません。</p> <p>報告が必要なときになってまとめはじめるのでは時間のロスが避けられません。もし作業中の記録もよく取っていなかったとあれば、思い出すことと言語化することを同時にこなしていかなければならずハイコストです。<br/> この資料だけは記憶の新鮮なうちに少しずつ更新し、現況に近い状態を維持しておくよう努めます。</p> <p>口頭でのコミュニケーションに優れている自信のない人ほど、円滑なコミュニケーションのための道具としてドキュメントを作成する習慣づけをしてみてはいかがでしょうか。</p> <h2 id="全てのドキュメントに感謝を---組織の資産としてのドキュメント">全てのドキュメントに感謝を - 組織の資産としてのドキュメント</h2> <p>フレームワークや単体テストの基礎もおぼつかない初心者でありながら、順調に基礎を固めていくことがかなった要因は、先輩方の知識と手解き、そして組織内外にあまたあるドキュメントのおかげです。</p> <p>新入社員のオンボーディング効率化を目的に作成されたスタートガイドは、まさしくon boardするだけで無駄なく開始地点に導いてくれるものです。2年目になっても3年目になってもたびたび参照することになるであろう確信があります。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftech.i3-systems.com%2Fentry%2F2021%2F03%2F18%2F154142" title="CLOMOの開発スタートガイド作成までの道のり - i Cubed Systems Engineering blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://tech.i3-systems.com/entry/2021/03/18/154142">tech.i3-systems.com</a></cite></p> <p>実務として課題に取り組むさなかにも、多くの既存のドキュメントが仕様理解や不具合調査の近道となってくれました。</p> <p><img src="https://i3hackmd.blob.core.windows.net/i3-hackmd-production/upload_8a136b6265438c697ea9684e7dba40b4.png" alt="おじぎする猫" /></p> <p>これから作成されるドキュメント達も将来の課題解決に役立てられるはずです。<br/> 上に挙げたスタートガイドはいまだ進化の途上であり、この夏には開発部全体でドキュメント改善を議論する場を持ちました。<br/> 私が過去の調査記録をありがたく利用させていただいているように、私の調査記録や学習ノートも組織の資産として残り、今後の開発に貢献するものとなればと望みます。</p> <p>スタートガイドのようなマニュアルをいちから作るのは、たいへん時間がかかります。<br/> しかし仕様の調査記録や学習ノートを少し外向けに整理して残すだけならば、多くの人にとってそう難しいことではないはずです。</p> <p>特に新人エンジニアだからこそ残せる資料もあるでしょう。<br/> 豊富な経験を持つエンジニアだと、メモを取る間もなく通り過ぎるような典型的な処理も、私はひとつひとつ拾わなければ不安が大きい。<br/> つまり、珍しくもない典型的な処理やライブラリの使い方をわざわざ調べる新人エンジニアは、経験則で突破できる経験者よりも、ドキュメントを残すという貢献のチャンスに恵まれていると考えます。やった!</p> <h2 id="リモートワークとドキュメント文化">リモートワークとドキュメント文化</h2> <p>近年、リモートワークが急速に普及し、テキストによる非同期コミュニケーションの検証と最適化が促進されることとなりました。<br/> 会議を除く会話のほとんどがチャットに置き換わり、コミュニケーションの非同期性が高まります。この環境におけるドキュメントの意義はこれまで述べたとおりです。</p> <p>ただ、ドキュメント文化を推奨する声は2020年より前から存在しています。多くの組織がドキュメントを軽視していたわけでもないでしょう。<br/> リモートワークがドキュメントの価値を高めたというより、リモートワークがもたらした、テキストベースの非同期コミュニケーションがドキュメントのハードルを大きく下げたというほうが正しそうです。<br/> この追い風を受けきって、成功体験の蓄積と文化の醸成を加速させたいところです。</p> <h2 id="まとめ">まとめ</h2> <p>情報をドキュメントにまとめる作業は、それだけで頭の中の整理に役立ちます。<br/> また、言語化・取捨選択・並べ替えなど論理的思考の訓練にもなります。ともすれば苦手な口頭でのコミュニケーションにもその成果が現れてくれるのではと期待しています。</p> <p>この記事を通して、ドキュメント作成に対する意識や期待に変わりはあったでしょうか。<br/> 自分のため、チームのため、将来の組織のための意義深さを感じられましたら幸いです。</p> <p>ここまでお付き合いいただきまして、どうもありがとうございました。<br/> (さて、時間のあるときにブログ執筆の記録をドキュメント化しよう)</p> <p>弊社では採用活動を実施しています。<br/> 皆様のご応募をお待ちしております。</p> <ul> <li>2023年度新卒採用:<a href="https://www.i3-systems.com/new-graduates/">https://www.i3-systems.com/new-graduates/</a></li> <li>キャリア採用:<a href="https://www.i3-systems.com/careers/">https://www.i3-systems.com/careers/</a></li> </ul> MisakiShiote-i3 フロントエンドの単体テストで実感したメリット hatenablog://entry/4207112889930699594 2022-12-15T11:02:17+09:00 2022-12-15T11:02:59+09:00 アイキューブドシステムズでフロントエンドの開発を担当しているMiyazakiTakayukiです。本記事ではフロントエンドの単体テストで実感したメリットをご紹介します。 フロントエンドの単体テスト導入を検討している方の参考になれば幸いです。 フロントエンドの単体テストを導入した経緯 弊社の製品のCLOMO PANELは従来、フロントエンド・バックエンド共にRuby on Railsのみで構成されていました。現在、以下の構成へ置き換えるプロジェクトを進めており、CLOMO PANELの一部はすでに置き換わっています。 バックエンド Ruby on Rails API フロントエンド Nuxt.j… <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/miyazaki-i3/20221025/20221025164645.png" width="1004" height="591" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <p>アイキューブドシステムズでフロントエンドの開発を担当している<a href="https://github.com/MiyazakiTakayuki">MiyazakiTakayuki</a>です。本記事ではフロントエンドの単体テストで実感したメリットをご紹介します。</p> <p>フロントエンドの単体テスト導入を検討している方の参考になれば幸いです。</p> <h2 id="フロントエンドの単体テストを導入した経緯">フロントエンドの単体テストを導入した経緯</h2> <p>弊社の製品のCLOMO PANELは従来、フロントエンド・バックエンド共にRuby on Railsのみで構成されていました。現在、以下の構成へ置き換えるプロジェクトを進めており、CLOMO PANELの一部はすでに置き換わっています。</p> <ul> <li>バックエンド <ul> <li>Ruby on Rails API</li> </ul> </li> <li>フロントエンド <ul> <li>Nuxt.js</li> </ul> </li> </ul> <p>Nuxt.jsでフロントエンドの開発を始めた当初はスナップショットテストのみで実装する方針でした。スナップショットテストとはレンダリングされたHTMLの変更を検知し、予期せずにUIが変更されていないかを確かめるテストです。しかし、実装した画面が増えてくるにつれ以下の課題が出てきました。</p> <ul> <li>リファクタリングがやりにくい</li> <li>依存関係のあるライブラリ・フレームワークのバージョンアップの際のデグレを把握できない</li> </ul> <p>リファクタリングはリファクタリング対象の挙動が変化しないように注意して行う必要があります。意図せず挙動を変化させてしまった場合、デグレが発生する可能性があります。単体テストが実装されていない場合は、このデグレを恐れてリファクタリングに着手するハードルが上がってしまいます。</p> <p>ライブラリ・フレームワークのバージョンアップでは、使用しているAPIの廃止や仕様変更に対応する必要があります。この対応が漏れるとデグレが発生してしまいます。規模が大きくなるにつれ、ライブラリ・フレームワークのバージョンアップによるデグレを把握することは大変になります。</p> <p>このような課題を解決するためにフロントエンドの単体テストを導入することとなりました。</p> <h2 id="どのようなテストを実装したのか">どのようなテストを実装したのか</h2> <p>Nuxt.jsでの単体テストは、多くがコンポーネントのテストになりました。ここでは、どのようなテストを行ったかを簡単にご紹介します。Vue.jsに関する内容になるので<a href="https://v3.ja.vuejs.org/guide/component-basics.html">コンポーネントの基本|Vue.js</a>をご一読いただければ理解がしやすいと思います。</p> <p>コンポーネントに対するテストの実装は、<a href="https://v1.test-utils.vuejs.org/ja/guides/#%E4%B8%80%E8%88%AC%E7%9A%84%E3%81%AA%E3%83%92%E3%83%B3%E3%83%88">ガイド|Vue Test Utils</a>の記載に従い、入力(input)を与えたときの出力(output)が正しいかという観点でテストを実装していきました。入力には次のようなものがあります。</p> <ul> <li><code>props</code></li> <li>ユーザーの操作</li> <li>子コンポーネントのイベント</li> </ul> <p>対して出力には次のようなものがあります。</p> <ul> <li>画面の変化(HTML CSS)</li> <li>Eventの発行</li> <li>子コンポーネントに渡す<code>props</code></li> </ul> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/miyazaki-i3/20221025/20221025144845.png" width="1200" height="921" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <p>コンポーネントの単体テストはテストフレームワークの<a href="https://jestjs.io/ja/">Jest</a>に加え、<a href="https://v1.test-utils.vuejs.org/ja/">Vue Test Utils</a>というVue公式のテストライブラリを使用しました。具体的には以下のようなテストを実装しています。</p> <p><strong>削除ボタンを押下した場合、削除確認ダイアログが表示されているか</strong></p> <pre class="code lang-typescript" data-lang="typescript" data-unlink>it<span class="synStatement">(</span><span class="synConstant">'「削除」ボタンををクリックしたとき、削除確認ダイアログが表示されること'</span><span class="synStatement">,</span> <span class="synStatement">async</span> <span class="synStatement">()</span> <span class="synStatement">=&gt;</span> <span class="synIdentifier">{</span> <span class="synStatement">await</span> wrapper.find<span class="synStatement">(</span><span class="synConstant">'[data-testid=&quot;deleteButton&quot;]'</span><span class="synStatement">)</span>.trigger<span class="synStatement">(</span><span class="synConstant">'click'</span><span class="synStatement">)</span> expect<span class="synStatement">(</span>wrapper.find<span class="synStatement">(</span><span class="synConstant">'[data-testid=&quot;deleteConfirmDialog&quot;]'</span><span class="synStatement">))</span>.isVisible<span class="synStatement">())</span>.toBeTruthy<span class="synStatement">()</span> <span class="synIdentifier">}</span><span class="synStatement">)</span> </pre> <p><strong>バリデーションエラーが発生した場合、submitボタンに<code>disabled</code>属性が付与されているか</strong></p> <pre class="code lang-typescript" data-lang="typescript" data-unlink>it<span class="synStatement">(</span><span class="synConstant">'文字数制限以上の文字を入力した場合、「保存」ボタンに disabled 属性が付与されていること'</span><span class="synStatement">,</span> <span class="synStatement">async</span> <span class="synStatement">()</span> <span class="synStatement">=&gt;</span> <span class="synIdentifier">{</span>   <span class="synStatement">await</span> wrapper.find<span class="synStatement">(</span><span class="synConstant">'[data-testid=&quot;input-name&quot;]'</span><span class="synStatement">))</span>.setValue<span class="synStatement">(</span><span class="synConstant">'a'</span>.repeat<span class="synStatement">(</span><span class="synConstant">256</span><span class="synStatement">))</span>   expect<span class="synStatement">(</span>wrapper.find<span class="synStatement">(</span><span class="synConstant">'[data-testid=&quot;submitButton&quot;]'</span><span class="synStatement">)</span>.attributes<span class="synStatement">(</span><span class="synConstant">'disabled'</span><span class="synStatement">))</span>.toBeTruthy<span class="synStatement">()</span> <span class="synIdentifier">}</span><span class="synStatement">)</span> </pre> <p><strong>inputの値を変更した場合、正しい引数でイベントを発行しているか</strong></p> <pre class="code lang-typescript" data-lang="typescript" data-unlink>it<span class="synStatement">(</span><span class="synConstant">'「名前」を変更したとき、イベントが発行されること'</span><span class="synStatement">,</span> <span class="synStatement">async</span> <span class="synStatement">()</span> <span class="synStatement">=&gt;</span> <span class="synIdentifier">{</span> <span class="synStatement">await</span> wrapper.find<span class="synStatement">(</span><span class="synConstant">'[data-testid=&quot;input-name&quot;]'</span><span class="synStatement">)</span>.setValue<span class="synStatement">(</span><span class="synConstant">'名前'</span><span class="synStatement">)</span> expect<span class="synStatement">(</span>wrapper.emitted<span class="synStatement">(</span><span class="synConstant">'update:name'</span><span class="synStatement">))</span>.toEqual<span class="synStatement">(</span><span class="synIdentifier">[[</span><span class="synConstant">'名前'</span><span class="synIdentifier">]]</span><span class="synStatement">)</span> <span class="synIdentifier">}</span><span class="synStatement">)</span> </pre> <p><strong>子コンポーネントの<code>props</code>に正しい値を渡しているか</strong></p> <pre class="code lang-typescript" data-lang="typescript" data-unlink>it<span class="synStatement">(</span><span class="synConstant">'子コンポーネントの props に正しい値を渡していること'</span><span class="synStatement">,</span> <span class="synStatement">async</span> <span class="synStatement">()</span> <span class="synStatement">=&gt;</span> <span class="synIdentifier">{</span> expect<span class="synStatement">(</span>wrapper.find<span class="synStatement">(</span><span class="synConstant">'[data-testid=&quot;childComponent&quot;]'</span><span class="synStatement">)</span>.props<span class="synStatement">(</span><span class="synConstant">'name'</span><span class="synStatement">))</span>.toBe<span class="synStatement">(</span><span class="synConstant">'名前'</span><span class="synStatement">)</span> <span class="synIdentifier">}</span><span class="synStatement">)</span> </pre> <p>単体テストを導入してから約8か月間経過した現在ではテストケース数は5000件を超えてきました。 <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/miyazaki-i3/20221025/20221025144808.png" width="688" height="160" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <h2 id="実感したメリット">実感したメリット</h2> <p>単体テストにはメリットとデメリットが存在します。デメリットとしては単体テストを書く工数やテストコードのメンテナンスコストがなどがあげられると思います。まだまだ単体テストを運用しはじめてから約8か月と短い期間ですが、すでにデメリットを超えるメリットを実感しています。 実感したメリットの中から以下の3つを抜粋してご紹介します。</p> <ul> <li>リファクタリングがやりやすくなる</li> <li>実装のミスに早く気づける</li> <li>共通コンポーネントの仕様変更が行いやすくなる</li> </ul> <h3 id="リファクタリングがやりやすくなる">リファクタリングがやりやすくなる</h3> <p>1つ目は、リファクタリングがやりやすくなることです。これは単体テストを始めた理由の1つでもありました。単体テストがあるのとないのとではリファクタリングのやりやすさは雲泥の差だと思っています。</p> <p>実際にリファクタリングを行った例をご紹介します。 フロントエンドの開発を進めて実装した画面数が増えてくると複数のコンポーネントでロジックの重複が起こるようになってきました。そこで、重複したロジックを再利用可能な共通関数として切り出すことになりました。</p> <p>関数の切り出しを行った際、切り出し元コンポーネントの単体テストがしっかりと実装してあったため、手作業で動作を確認する必要はありませんでした。単体テストの実装を確認したのみです。今回の作業では共通関数化したものの数がそこそこ多かったので、単体テストがなかった場合は目視での確認になり、それなりに大変だったと思います。また、目視での確認は漏れが発生する可能性もあります。</p> <p>単体テストを実装していれば確認作業に時間がかからず、確認漏れが発生することもありません。リファクタリングのやりやすさが格段に違います。</p> <h3 id="実装のミスに早く気づける">実装のミスに早く気づける</h3> <p>2つ目は、実装のミスに早く気づけることです。 私たちのプロジェクトでは新規に画面を実装した際、同時に単体テストを実装しています。この単体テスト実装時に考慮漏れなどのミスに気づくことがあります。</p> <p>単体テストでは実装をできる限り細かい単位に区切ってテストを行っていきます。その細かい範囲でテストデータを準備していると考慮漏れに気づきやすくなります。また、意図せず他の箇所に影響を与えていた場合などにテストが失敗して気づくことができます。</p> <p>単体テスト実装の段階で実装ミスや考慮漏れに気づけることはとても大きなメリットだと思っています。実装の段階で不具合に気づかずそのまま進めて社内検証やリリース後に実装ミスや考慮漏れが発覚すると不具合となり、不具合原因の調査や修正の対応への工数が発生してしまいます。単体テスト実装時にミスに気づけることで不具合対応工数の発生を未然に防げているという考え方もできると思います。</p> <h3 id="共通コンポーネントの仕様変更が行いやすくなる">共通コンポーネントの仕様変更が行いやすくなる</h3> <p>3つ目は、共通コンポーネントの仕様変更が行いやすくなることです。 Nuxt.jsでは共通コンポーネントを組み合わせて画面を実装します。共通コンポーネントはさまざまな画面で利用されることとなります。使用される画面が増えれば増えるほど影響範囲が大きくなり共通コンポーネントを変更することはリスクが大きくなっていきます。しかし、さまざまな理由で仕様変更をする必要が出てくることがあります。</p> <p>共通コンポーネントの仕様変更も単体テストを実装していることで行いやすくなりました。仕様変更によって共通コンポーネントの使い方が変わった場合に単体テストが失敗して影響範囲を教えてくれるためです。</p> <p>Vue.jsやReactなどコンポーネントベースの開発を行うフレームワークでは単体テストによる恩恵を受けやすいと思いました。</p> <h2 id="キャッチアップとしての単体テスト実装">キャッチアップとしての単体テスト実装</h2> <p>単体テストは上記のメリット以外にもキャッチアップとしてとても効果的だと感じました。</p> <p>私は2021年に新卒として入社して現在2年目です。新卒としての研修(<a href="https://tech.i3-systems.com/entry/2021/11/25/102622">以前の記事</a>で新卒の研修について紹介しています!)が終わった後、開発チームへの配属のために今後どのようなことをやっていきたいか希望を聞かれる機会がありました。研修中にフロントエンドの技術について興味を持っていたため、フロントエンドチームへの配属を希望し、希望通りに配属していただけることになりました。</p> <p>私がフロントエンドチームへ配属されるタイミングとフロントエンドの単体テストを導入するタイミングがちょうど被っていたため、キャッチアップもかねて単体テスト未実装画面の実装を私が担当することとなりました。</p> <p>今振り返るとこの単体テストの実装がキャッチアップとしてとても良かったと思っています。キャッチアップでは主にシステム全体像の把握や動いているシステムの確認、ソースコードの理解などを行っていくことが多いと思います。単体テストを実装することで、システムの確認、ソースコードの理解をより深く行えたと思います。</p> <h3 id="ソースコードの理解">ソースコードの理解</h3> <p>単体テストはテスト対象の関数やコンポーネントの仕様を理解していないと実装できません。 何が渡されて何が返却されるかを理解する必要があります。そのため、実際に動かしてみたり、さまざまな入力パターンを試してみたりしました。単体テストを実装するために試行錯誤を繰り返していくうちにソースコードが理解できるようになりました。ただソースコードを読むだけの場合よりも、必然的に理解が深くなったと思います。</p> <h3 id="コンポーネントの分割基準の理解">コンポーネントの分割基準の理解</h3> <p>コンポーネントをどのように分けていくかはチームやプロジェクトの方針で決まっている部分でもあるのでキャッチアップの段階で理解しておきたいところです。この理解にも単体テストが役に立ちました。</p> <p>コンポーネントの単体テストでは対象のコンポーネントの責務を理解する必要があります。例えば、<code>props</code>で値を受け取って表示する子コンポーネントがあり、その親コンポーネントを対象とします。対象のコンポーネントの責務は、子コンポーネントに<code>props</code>に値を渡すところまでです。 単体テストでは「子コンポーネントに渡している<code>props</code>の値が正しいか」ということをテストします。 もし、「子コンポーネントの表示が正しいか」ということをテストしていた場合、子コンポーネントで<code>props</code>の値を表示せずに内部で扱うように修正すると、親コンポーネントの単体テストも修正する必要が出てきます。このように、単体テストでは責務を理解することが重要です。</p> <p>私もコンポーネントの責務を意識しながら単体テストを実装しました。コンポーネントの責務を理解していくことでコンポーネントの役割がわかるようになり、どのような役割でコンポーネントが分割されているかが理解できました。</p> <h2 id="おわりに">おわりに</h2> <p>フロントエンドの単体テストを導入し、どのようなテストを行い、どのようなメリットを実感したかをご紹介しました。私自身まだまだ単体テストについて理解が足りていない部分も多々あるのでさらに勉強して、単体テストでユーザーや開発者などこの製品に関わるすべての人が幸せになれることを目指して頑張ろうと思っています!</p> <p>最後に、弊社では採用活動を実施しています。 皆様のご応募をお待ちしております。 <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.i3-systems.com%2Fcareers%2F" title="採用情報|株式会社アイキューブドシステムズ" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.i3-systems.com/careers/">www.i3-systems.com</a></cite></p> miyazaki-i3