セーフィー株式会社のブログ - TECH PLAY

TECH PLAY

セーフィー株式会社

セーフィー株式会社 の技術ブログ

256

この記事は Safie Engineers' Blog! Advent Calendar 10日目の記事です 「社内プチ表彰式」の写真 はじめに みなさんこんにちは。法務部 知財グループの永島です。 セーフィーでは、2022年に知財部門を立ち上げて以来、20件以上の特許が登録されています。 今回は、その中の1件について、上記表彰に応募したところ無事に受賞できましたので、お話いたします。 はじめに 地方発明表彰とは 受賞内容 どんな発明? 本件特許に込めた想い 「社内プチ表彰式」の様子 おわりに 地方発明表彰とは 地方発明表彰は、公益社団法人 発明協会が大正10年から開始した歴史ある表彰で、全国を8地方(北海道・東北・関東・中部・近畿・中国・四国・九州)に分け、各地方から生まれた優れた発明等を表彰するものです。 地方発明表彰の詳細(発明協会Webページ) https://koueki.jiii.or.jp/hyosho/chihatsu/chihatsu.html イメージとしては、「特許の甲子園」みたいな感じです。ただ、その地方大会とはいえ、特にセーフィーが応募する関東ブロックは激戦区で、例年、名だたる大企業が多数応募してきます。そこに、セーフィーのような数年前に上場したばかりのスタートアップが如何に切り込めるか・・・初応募は、まさに挑戦でした。 受賞内容 令和6年度 関東地方発明表彰 「発明奨励賞」   【発明名称】映像解析により人の滞留を検知するシステム  【特許番号】特許第7279241号  【受賞者】谷野 香菜 橋本 貴博 鬼城 渉 藤澤 真之 大友 裕明       柏木 直諒 松田 一輝 沖 総一朗 小嶋 幸恵 単に特許が取れただけでなく、それを第三者機関に評価してもらった結果、大企業と肩を並べて受賞者に名を連ねることができたという事実は、それだけで誇れることであり、会社にとって大きな自信となった筈です。 どんな発明? 特許第7279241号(以下、本件特許)は、 Safie One に搭載された AI-App人数カウント の1つである「立ち入り検知」に関するものです。 その概要については過去に こちらの記事でも紹介済み ですが、もう少し詳しく説明します。 近年、店舗のカメラで撮影した映像を現場のDX に活用する試みがあり、その中で本件特許が生まれました。 ざっくり言うと、上図に示したようなシステムにおいて、人の滞留を見える化するための技術です。 ポイントは、予め検知エリアおいて人の滞留を検知するための条件:①人数②滞留時間を設定しておき、実際にカメラで撮影した映像において①②の条件が満たされた場合に、そのタイミングを出力する(サムネイル表示/タイムライン上にオブジェクト表示)というものです。 利用シーンとしては、例えばレジ待ちが長くなっているシーンを可視化することにより、店員のシフトや接客方法を改善するのに役立ちます。また、例えば売場で特に混雑しているシーンを可視化することにより、売場のレイアウトや商品のラインナップを再考するのにも役立ちます。この様に現場のDXが進めば、店舗側の機会ロスが減り、お客様の満足度向上に繋がります。 さらには、店舗の省人化が図られることにより、日本の大きな課題である働き手不足の解消にも貢献することができます。 本件特許に込めた想い 近年、世の中では監視カメラの用途を現場DXに広げようとする動きが一部見受けられるようになってきたものの、まだ思うようには進んでいません。 その主な要因は、「記録された膨大な映像データの中から、見るべきシーンを特定するのが大変」という点にあり、これが映像データを利活用するうえで大きな壁となっています。 これを克服すべく、AIによる映像解析等に頼る企業もありますが、AIの精度を実用に足るまで上げるのは難しい場合が多く、AIを作るためのコストや時間も馬鹿にならないため、AIの社会実装はなかなか上手くいっていない、というのが現実です。 本件特許は、その様な現実を理解したうえで、多くの発明者が共に現場で議論を重ね、人が考えたロジックをシステムに組み込むことにより、映像データを利活用するための壁を突破しよう、という想いが込められています。 「社内プチ表彰式」の様子 発明協会の表彰式には参加できませんでしたが、その代わりに社内でプチ表彰式を行いました。 当日は、受賞者、森本CTOが参加し、表彰状の授与やスピーチ等で盛り上がりました! 表彰状授与の様子 受賞者の谷野さんのコメント 一言では語り尽くせないくらい困難なプロジェクトでした。当初は「Safie One」が売れるかどうか不安もありましたが、多くの方に選ばれる商品となり、大変嬉しく思っています。 今回の受賞は、チーム全員が一丸となって努力を重ねた結果が実を結んだものです。この成果を手にできたことを心から誇りに思います。 これからも機能改善を重ね、賢くなるカメラである「Safie One」をさらに進化させていきたいです。 森本CTOのコメント これまで、売れない商品に悩まされることも多く、まさに可能性を模索していた時期に「Safie One」は生まれました。これは、チームのやりきる力が生み出した成果です。 今回の受賞は、私たちの努力が評価された結果だと感じており、大きな喜びと誇りを感じています。また、このような表彰への応募は社会的な意義を広げ、セーフィーの認知度を高め、新たな可能性を切り開く大切な取り組みであると確信しています。 今後も、私たちはさらなる高みを目指し、果敢に挑戦し続けます。 おわりに セーフィーでは、上場後に知財活動が本格化しましたが、そこから1年目で種蒔き(出願)⇒2年目で収穫(登録)⇒3年目で外部評価(表彰)と、着実に進化してきました。 これは何といっても、現場で新しい技術がちゃんと生まれていたからです。特にSaaS系の業界においては、大して新しい技術は生まれていないだろう・・・と当事者含め思い込みがちですが、そうではないことが証明できたと思います。 今後もセーフィーは、地道な開発活動を通してイノベーションの現実解を見出し、日本の新たな未来を切り開いていきたいと考えています。 セーフィーではエンジニアを積極的に採用しています。 興味がある方は是非下記サイトを一度覗いてみてください。 https://safie.co.jp/teams/engineering/
この記事は Safie Engineers' Blog! Advent Calendar 9日目の記事です。 あいさつ こんにちは!セーフィーの井上と申します! 2023年11月に入社し、エンジニアリングオフィスの一員として日々業務に取り組んでいます。 今回はセーフィーの「エンジニアリングオフィス」という部署は一体何をしているのか、皆様への紹介も兼ねて取り組んでいることについてお伝えさせていただきます! あいさつ エンジニアリングオフィスとは? エンジニアリングオフィスのミッション ミッション達成するためには 取り組み内容 テックブランディング向上施策 テックブログ 次のステップへ 開発本部アイデアソン 2024年の進化過程 社内認知の向上と参加者の拡大 第3回での大きな進展 2024年の活動を通して得られた成果 社内認知向上が一定の成果を達成 オンボーディング・ネットワーキング構築の取り組みとして採用 まとめ 終わりに エンジニアリングオフィスとは? エンジニアリングオフィスは、取締役CTO・VPoE、各部室長や各部署と密に連携し、最高のプロダクトをつくるため、エンジニア組織拡大に伴い中長期の組織成長戦略を策定・実行しており、さらなる事業成長を見据え組織の強化を推進しています。 エンジニアリングオフィス発足に至った理由として、弊社のVPoEの谷口が記事を掲載しておりますので、こちらも是非ご覧ください! engineers.safie.link エンジニアリングオフィスのミッション セーフィーはVisionとして「映像から未来をつくる」を掲げています。 このVisionを実現するためには、中長期の戦略を実行できる組織へと常にアップデートし続ける必要があります。 セーフィーが掲げるVisionを実現するべく、エンジニアリングオフィスはプロダクトと人・組織の両輪を支えるために下記ミッションを設定しました。 エンジニア組織の未来を追求し、未来に起きるであろう課題も見通した解決エンジンとなる そのためには「ありたい姿」「こういう組織を作らなきゃいけないよね」というゴールを定め、目標への道筋を明確にすることが重要となります。 ミッション達成するためには ミッションを達成するべく、エンジニアリングオフィスではバックキャスティングの考え方を採用しています。 業務に着手するときは、始めに将来どういう姿になっていたいか・ありたい姿(ゴール)は何なのかを定義します。その後、現状の自分達の立ち位置を確認することで「ありたい姿と現状のギャップ(課題)」を確認します。こうして課題を明確にし、次に何をするべきかの道筋を明確にすることで、ゴールまでの道筋を迷うことなく進むことが出来ます。 取り組み内容 上記を踏まえた上で、実際どのように組織開発に臨んでいるのか?ということを、自分が担当している業務から3つピックアップしてご紹介いたします。 テックブランディング向上施策 まず、自分が担当している業務の1つとして「テックブランディング向上施策」があります。端的に説明しますと、社外のエンジニアからの認知を高める施策を担当しています。 じゃあイベントに参加したりブログを沢山出して社外にアピールしよう!そしたら認知あがるじゃん! ・・・等と、とりあえず目の前のタスクに掛かる前に、まずはバックキャスティングの基本である ・ゴール(あるべき姿・数年後どうなっていたいか) ・課題(あるべき姿と現状のギャップ) ・何をするべきなのか を腰を据えて定義しました。 ゴールを定義した後、そのゴールを達成できるよう道筋を明確にするため中長期計画を立て、ロードマップを策定しました。 ロードマップについて要約すると、以下のようになります。 FY24:社内認知が向上している FY25:社外認知が向上している FY26:セーフィーの組織文化が社内外に浸透している このテックブランディング向上施策の1つにテックブログがありますので、次項ではテックブログを例に具体的に何をしていたかを説明します。 テックブログ 上項で策定したロードマップにおいて、FY24は【社内認知が向上している】ことを目指しています。 テックブログは、世間にセーフィーの活動内容や取り組みを認知頂ける手段として最たるものだと自分は考えています。 しかしながら、そもそも活動内容や取り組みを執筆頂ける方がいないと、テックブログ自体が成り立ちません。 また、「情報を発信する重要性」が浸透していないと執筆して頂ける方も増えていきません。 そのため、上項で策定したロードマップに則り2024年の取り組みとして【社内認知の向上】に努めました。 例えば・・・ 開発本部全体会議にてテックブログの成果報告や成功事例の共有をすることで、テックブログがどの程度見られていてどのような反響があるのかをフィードバック テック系イベントの記事執筆例 Mobile Dev Japan #3 イベントを共同開催した話 - Safie Engineers' Blog! Findy さん主催のイベント「TechBrew in 東京 ~モバイルアプリの技術的負債に向き合う~」にて発表してきました - Safie Engineers' Blog! DroidKaigi 2024に参加してきました! - Safie Engineers' Blog! 勉強会や社内の取り組みをブログで展開して頂けるよう積極的にアピール 取り組み紹介記事の記事執筆例 AWS Startersに参加しました - Safie Engineers' Blog! We held our first English event at Safie, Safie English School! - Safie Engineers' Blog! 開発本部(エンジニア向け)社内アイデアソン始めました - Safie Engineers' Blog! スクラムチームの振り返りに Sailboat Retrospective を導入してみた - Safie Engineers' Blog! 執筆プロセスを改善して、より簡単に書けるプロセスを構築する等の運営プロセスの改善(進行中) 上記以外にも取り組んだ施策はありますが、こういった施策を実施した結果、2023年と比較して自ら執筆される方が増加し、記事執筆のご提案もご快諾頂ける文化が出来上がりました。 また、「この技術の裏側を記事にしたらウケそう」「この知見を是非外部に広めたい」等と記事ネタの提案も頂けるようにもなりました。 今回のアドベントカレンダーについても、「アドカレやります!!」と社内告知した際、皆様が積極的に立候補されたことにより、早い段階で全枠を埋めることが出来ました。 その他にも、他部署の方から「執筆したい」というお声もあがるようになりました。以下の記事は営業本部の松本さんに執筆頂いた記事です。 engineers.safie.link 上記のように、中長期のロードマップ計画に則り、施策を実施し続けた事で社内認知を向上させることができました。 次のステップへ 社内認知を上げるための活動を続け、執筆にご協力頂ける方が増えたことにより記事発信数が増加、テックブログ自体の露出が高まり社外認知も向上しました。 例えば、セーフィーがイベントブースに出展した際、ご訪問頂いた方々から「テックブログ見たことあるよ」等のお声がけを頂く機会が着実に増えています。 このように、ロードマップの各年度の計画が次の計画に繋がるよう設計していくことにより、理想の姿へ一歩一歩進むことができるようになります。 開発本部アイデアソン エンジニアリングオフィスでは、社内ネットワーキングの強化や、エンジニアのナレッジの向上を目的とした取り組みも行っています。 その一環として2024年にスタートしたのが開発本部アイデアソンです。 第1回開発本部アイデアソンの記事はこちら engineers.safie.link ここでも勿論バックキャスティングの考え方で企画・運営を進めています。 この開発本部アイデアソンの目指すべき姿として、以下を定義しました。 セーフィーの企画会議を通過し、正式なプロダクトとして稼働するアイデアを生み出せる場 上述した目指すべき姿を達成するためには、定期的に開催・都度アップデートを行い、業務時間を割いてでも参加する意義のあるイベントにしなくてはなりません。 そのための第一歩としてテックブログ項と同様、こちらもまずは社内認知を高める所からスタートしています。 いくら価値があるとアピールしても、参加者がいなければ開催はできません。 2024年の進化過程 社内認知の向上と参加者の拡大 アイデアソン開始当初はあまり興味を持たれておらず、参加者が少ない状態でのスタートとなりました。 しかし、「楽しかった」「学びが多かった」という好意的な反応や参加者の声が各グループ内で広まりました。 直近のアイデアソンでは、定員上限に近い人数が参加するほどになりました。 第3回での大きな進展 第3回アイデアソンでは、あるアイデアを正式な企画として実現したいという声が上がり、参加者たちによる企画会議に提案するためのチームが立ち上がりました。 この動きは、アイデアソンの目的である「正式なプロダクトとして実現可能なアイデアを生む」に直結しうる成果ともいえます。 2024年の活動を通して得られた成果 社内認知向上が一定の成果を達成 第3回まで開発本部アイデアソンを高頻度で開催したことにより、取り組み内容等の社内認知が向上しました。 「面白そうだから・学びがあるから参加してみたい」という声が他部署からも多く寄せられるようにもなり、社内認知の向上を達成できました オンボーディング・ネットワーキング構築の取り組みとして採用 開発本部アイデアソンは、部・グループを跨いだネットワーキングの向上に効果があると評価を社内で頂きました。結果、新入社員のオンボーディングコンテンツの一環として正式に組み込まれるようになりました。 今後は新入社員と既存社員を混成した人数で計画を組むことを意識し、より円滑なコミュニケーションを早期に構築することを狙っていきます。 上記の通り、2024年では認知向上やアイデアソンに参加することの有用性を証明することができました。 2025年からは、アイデアソンの目指すべき姿に到達できるように、より洗練されたアイデアや提案資料を生むことができるよう更にブラッシュアップを行います。 例えば、企画会議に提案できる資料のアウトプットやプレゼンの内容を充実させるためのレビュー会を実施したり・・・ アイデアがより実現可能で説得力のある形に仕上がるよう様々な施策を実施し、参加者全員に実りのある体験ができる場へとアップデートを行っていく予定です。 まとめ セーフィーはここ数年で事業・組織が大きくなったことで、組織のあるべき姿を中長期を見据えて戦略的に構築するフェーズに入りました。 個人個人の開発生産性を高めて成長を促すだけに留まらず、組織としての成長が重要になってきます。 組織を成長させ続け、新しい技術に挑戦できる組織にアップデートし続けるには、エンジニアリングオフィスが重要視しているバックキャスティングの考え方が活きてきます。 目指すべき姿は何か。現状と理想の姿のギャップ(課題)は何があるのか。実現するためには何をするべきなのか。 ・・・という事を押さえる事で、組織開発を実践できるようになります。 終わりに 本記事では、エンジニアリングオフィスについてご紹介させていただきました。 エンジニアリングオフィスでは、エンジニア組織の組織開発を牽引して中長期の組織戦略立案から実行を推進するメンバーを募集しています! open.talentio.com カジュアル面談から受け付けておりますので、気軽に応募いただければと思います!皆様のご応募、心よりお待ちしております! 最後までお読みいただき、ありがとうございました。
この記事は Safie Engineers' Blog! Advent Calendar 8日目の記事です はじめに こんにちは、第1開発部でサーバーサイドエンジニアをしている坂上(さかうえ)です。今回は2024年新卒エンジニア研修における成果発表と、その後についてお伝えします。 はじめに 研修の成果発表 サービス運用 運用方針 運用開始後 ナレッジ共有会 最後に 研修の成果発表 我々24新卒エンジニアは、エンジニア研修として「社内課題を解決するプロダクト開発」というテーマについて取り組みました。自身の体験や社員の方々へのユーザーインタビューを経て、異才ランチ(社員同士のランチ代を補助する制度)のマッチングをサポートするisai connectというプロダクトを開発しました。 プロダクトの詳細や、それまでの経緯に関する詳細は、今までの記事をご覧ください。 新卒研修の紹介とチーム開発前にやったこと 2024年新卒エンジニア研修-アジャイル開発編 2024年新卒エンジニア研修-isai connectについて 2024年新卒エンジニア研修-isai connect開発のアウトプット_サーバーサイド 2024年新卒エンジニア研修-フロントエンド開発編 2024年新卒エンジニア研修-インフラ構築編 2024年新卒エンジニア研修-isai connect開発のアウトプット_デバイス編 2024年新卒エンジニア研修-新卒研修の成果発表とその後 ←本記事 研修の成果であるisai connectの成果発表は、2つに分けて行いました。 1つ目は、セーフィー社員全体に向けた発表です。 2024年新卒エンジニアがisai connectを作ったというインパクトを残し、認知してもらうことが主な目的でした。isai connectが解決する課題とターゲットの説明やサービス方針を伝え、より多くのユーザーに使ってもらえるような発表をしました。 2つ目は、開発本部に向けた発表です。 isai connectの開発の中でも以下の3つの内容に絞り、より詳細に説明しました。 ・2024年新卒エンジニアチームとしての開発の進め方 ・isai connectに実装した機能に対する技術的に工夫したポイント ・研修を通して成長した点と今後の意気込み 2つの発表を振り返ると、改めて発表の難しさを実感しました。研修内容が非常に充実していた一方で、限られた時間の中でその内容を効果的に伝えるためには、発表の目的を明確に設定し、それを達成するために内容を厳選する必要がありました。この整理や意思決定には時間を要し、難しさを感じました。 また、発表では、直感的に理解しやすい工夫としてスライドだけでなく、動画も活用しました。その結果、多くの社員に興味を持ってもらい、「興味が湧いた」「使ってみたい」といった前向きな感想をいただくことができました。 こうした声をいただけたことで、今回の発表で設定した目的を達成できたと感じ、とても満足しています。 この経験を通じて、限られた時間で効果的に見せる大切さを改めて学ぶことができました。 以降の章ではサービス運用と研修後の勉強会について説明します。 サービス運用 運用方針 isai connectを実際にセーフィーで使ってもらうために、サービス方針を定めました。 この運用方針で進めるにあたって、配属先であるグループの上長に許可をもらう形で、業務として運用していく形としました。 主な業務内容としては、以下5つです。 isai connect定例ミーティング 隔週30分 議題 サービスの利用状況確認 各自の取り組んだことの進捗確認 相談事項の確認 新規機能開発 ユーザーからの要望や開発メンバーからのアイデアを元に、新規機能についてSlackで開発メンバーと共有し、実装すべきとなった場合にチケットとして発行する バグ修正のチケットの優先順位を加味して、実装していく バグ修正 発生したバグやユーザーからあった要望、そして新たに開発したい機能をチケットとしてまとめ、スクラムマスターが優先順位づけを行ったものを、上から処理していく 主当番 2週間ごとに交代制 お問い合わせ対応 Slackの専用チャンネルを設け、isai connectの利用者からの不具合の報告や要望の一次対応をする 副当番 2週間ごとに交代制 主当番のお問い合わせ対応の補佐 従業員名簿更新作業(※月の最初の週の場合) セーフィーの社員名簿が月初に新しくなるに伴い、更新作業を行う 定期リリース作業(※月の最後の週の場合) 2週間で実装した内容をリリースする 運用開始後 サービス運用を開始すると実際に使用したユーザーから感想を多数いただきました。 isai connectがなければ、関わりがなかったであろう人とランチにいく良い機会になりました 誘いがきた時に、自己紹介が見れるので、事前知識があって嬉しいです さらに、この機能があったらもっと良いなというフィードバックまでいただくことができました。 日程調整の機能までついていたら、さらに手軽になる 誘う時に、誘われる側が異才ランチに行きたい気持ちがあるかどうか、わかるとより誘いやすい 一方、それと同時に以下のような障害対応にも追われました。 isai connectのアカウント作成時に利用規約に同意しようとすると画面が真っ白になってしまう 異才ランチが成立した時に、作成したSlackグループDMの文言が間違っている デバイスの電源を常につけておくと、フリーズしてしまう このように、実装の不備に加え、実際に運用することで初めてわかるような想定以上の不具合に追われ、配属先の業務と並行して対応を行いました。サービス運用を継続しながら引き続き改善を続けています。 また、2024年新卒エンジニアに運用の感想を聞いたところ、ポジティブな意見としては以下のような声がありました。 いろんな方から使ったよと言ってもらえて嬉しい 自分が開発した機能が、他の人に使われている様子が見れて、達成感がある 一方、今後の改善点としては以下のような声がありました。 本業務の合間にまとまった時間を取るのが難しい 開発中には出てこなかった問題が浮き彫りになる 研修時に担当していた分野以外のチケットを取りたかったが、運用となるとハードルが上がってしまう 運用開始から5ヶ月が経とうとしていますが、月に10件弱の異才ランチの実施がisai connectを通じて行われています。 今後は、本来の目的である価値を発揮するために、これまでの運用で得られたフィードバックや障害対応を活かし、更なる機能改善と安定性向上に注力していきます。また、運用を担うチーム体制の見直しを行い、各メンバーが無理なく役割を果たせるよう、業務の分担や支援体制を整えていきます。 ナレッジ共有会 無事にエンジニア研修を終えた後、配属先での実務が本格的に始まりました。研修を通じて築いた2024年新卒エンジニアのつながりを活用するため、私たちからの提案で「ナレッジ共有会」を隔週で開催しております。配属先で学んだ知識や経験を共有して、早く新しい環境に適応し、エンジニアとして成長することが目的です。 この会では、各回で2人の発表者が発表資料を準備し、1人15分ずつ、合計30分間のプレゼンテーションを隔週で行っています。テーマは配属先で得た知見や学びを中心とし、実務で役立つ技術的な内容から、業務効率化の工夫や課題解決のアプローチまで幅広く設定しています。 ナレッジ共有会は、新卒エンジニア同士のつながりを強化するだけでなく、他のメンバーの知識や経験から刺激を受け、新しいアイデアを得る場としても機能しています。今後もこの取り組みを継続し、互いに支え合いながら成長していきます。 最後に 2024年新卒エンジニアのメンバーは、多様なバックグラウンドを持つ仲間が集まりました。その中で、意見が食い違ったり、進め方がなかなか決まらなかったりと、数多くの困難にも直面しました。しかし、チームで協力しながら乗り越え、一つのプロダクトとして形にすることができたことに大きな達成感を感じています。同時に、isai connectをさらに成長させ、多くの方々に価値を届けられるサービスへと進化させていきたいという思いも抱いています。 また、このプロジェクトを通じて築いた仲間とのつながりを大切にし、互いに切磋琢磨しながら成長を続けていきたいと思っています。これからも挑戦を重ね、セーフィーの一員としてさらなる価値を創出していきます。
この記事は Safie Engineers' Blog! Advent Calendar 7日目の記事です はじめに こんにちは。第4開発部でデバイスエンジニアをしている集路(しゅうじ)です。 今回は2024年新卒エンジニア研修におけるデバイス分野の開発についてお話しします。 はじめに セーフィーでの2024年新卒エンジニア研修と作ったプロダクトの紹介 開発したデバイスの概要 デバイス機能の決定まで 開発上の苦労・工夫点 今後の展望 最後に セーフィーでの2024年新卒エンジニア研修と作ったプロダクトの紹介 セーフィーでは全体研修後、約3ヶ月のエンジニア研修があり、エンジニアとしての基礎を学びつつ、社内課題を解決するプロダクトを開発しました。 課題選定から開発言語、体制まで全て自分たちで決める形式で、私たちは「isai connect」を開発しました。これは、他部署の方とランチに行くと会社がランチ代を負担してくれる「異才ランチ」制度をより活用し、活発化を図るためのプロダクトです。 詳しくは以下の記事でご覧ください。 新卒研修の紹介とチーム開発前にやったこと 2024年新卒エンジニア研修-アジャイル開発編 2024年新卒エンジニア研修-isai connectについて 2024年新卒エンジニア研修-isai connect開発のアウトプット_サーバーサイド 2024年新卒エンジニア研修-フロントエンド開発編 2024年新卒エンジニア研修-インフラ構築編 2024年新卒エンジニア研修-isai connect開発のアウトプット_デバイス編 ←本記事 2024年新卒エンジニア研修-新卒研修の成果発表とその後 セーフィーではカメラを扱っていることもあり、新卒エンジニア研修でも組み込み開発の領域も体験するため、 RaspberryPi とカメラを用いるという条件がありました。 我々の開発したプロダクト「isai connect」では、Webの開発が主であり、どのようにしてデバイスをサービスに結びつけるのか、など苦労した点も多くありました。開発したデバイスの概要や、その紆余曲折についてご紹介します。 開発したデバイスの概要 まず、開発したデバイス「Receipt Sender」の概要・機能について説明します。 このデバイスでは、名前の通りレシートの画像を個人のSlackに送信します。ランチから帰ってきた人がすぐにレシートを送信できるよう、オフィスの出入口付近2か所に設置しています。 異才ランチ後の経費精算では、経費申請の際にレシートの画像を登録する必要があります。その際、入力の都合上PCでの申請が便利なため、一度手持ちのスマートフォン等でレシートの写真を撮り、Slack等で自分宛てに共有している人が複数いました。この手順をもっと手軽に行えないか、ということで生まれたのがこの「Receipt Sender」です。 Receipt Senderを利用したレシート送信は以下のような流れです。 1. 顔認証ログイン 2. レシート撮影 3. レシート送信 以下で Receipt Sender の利用方法をご紹介します。 ~利用方法~ 1. 「始める」ボタンから顔認証を実施 2. 本人であることを確認し、「レシートの撮影に進む」ボタンからレシート画像を撮影 3. 撮影した画像を確認し、「DMに送信する」ボタンからSlackへ送信 4. Slackに画像が届いていることを確認 デバイス機能の決定まで デバイスの具体的な機能や活用方法には悩みました。どのようなプロダクトを作っていきたいかのアイデア出しの時点においても、デバイスをどう活用するのか?を念頭に置いて考える必要があり、なかなかアイデアが定まらない一因となっていました。 アイデアが固まり、デバイスの用途は「レシート送信から経費申請までの手間を減らす」ものを作ると決まりました。当初の計画では、経費精算サービスと連携して、レシートの送信から申請までをスムーズに行えるよう整備することを考えました。 しかし、いざ社内で相談してみると、サービスとの連携はNGという結果に…。経費に関係し、セキュリティ面も考えての結果だったため、当初より範囲を小さくして開発することとなりました。そこで、ランチから帰ってきてすぐにレシートの送信ができるだけでも申請の手間が減ると考え、その機能を作成しました。 ただレシートを送信する機能だけではなく、デバイスとして設置する価値を高めたほうがよいとのご指摘もありました。どのように活用するかを考えた結果、トップページにおいて累計・月間それぞれのコネクト数を表示し、どの程度使われているのかを知ることができるように工夫しました。 これにより、isai connect の状況を社員の方が簡単に見れるようになり、興味を持っていただくきっかけを作ることができたのではないかと考えています。 開発上の苦労・工夫点 今回のデバイス開発では、実装の手軽さから Python を選択しました。GUIの作成は tkinter を使用しています。 2台のカメラの制御 図のように、Receipt Sender では、顔認証用のカメラ(市販のUSB-Webカメラ)と、レシート撮影用のカメラ(RaspberryPi用カメラモジュール)の2台のカメラを同時に使用しています。 1つのアプリ内でこれらのカメラを別々で動作させる際、顔認証用のカメラ映像は映らないがレシート撮影用のカメラ映像は映る…などの問題が生じました。 各カメラの映像を扱うのに、顔認証用ではOpenCV、レシート撮影用では picamera2 および libcamera と別々のライブラリを使用しており、複雑化していた点も要因の一つでした。 最終的には、カメラ毎にスレッドを割り当てて処理することで解決しました。 顔認証 顔認証の機能を実装するにあたり、2023年度の新卒エンジニア研修で開発された「librarian」の顔認証用APIを利用させてもらうことにしました。顔認証の実装となると大きく時間もかかるため、23卒の先輩方に利用させてほしい旨お伝えしたところ快く許諾してくださいました。 結果として、先輩から我々へと新卒エンジニア研修の成果が繋がる非常に良い要素だったのではないかと思っています。 一方、顔認証の部分では、複数人で連続で利用する際、操作している人ではなくその前に操作した人として認証されてしまう不具合もありました。下図に示す通り、顔認証画面からの画面遷移時にその時点でのカメラ画像が保持されたままになっており、再度顔認証画面を開いた際に保持された画像が一瞬表示されてしまうことが原因でした。 この不具合に対し、顔認証の処理を走らせる間隔を調整してみるなど様々試しながら修正を行いました。時間はかかってしまったものの、最終的には顔認証画面遷移時に明示的に認証情報をリセットすることで解決しました。 専用のケース作成 社内に設置するにあたり、RaspberryPi本体を隠しつつレシート撮影用カメラを固定するケースが市販で存在しなかったため、プラ板を用いて自作しました。本体に合う大きさに切って張り合わせるだけの単純な作業ではありましたが、ぴったり合うものを作成でき、むき出しのまま置くことを防げています。 今後の展望 今後は、常時稼働していることを活かし、利用されていないときは社内への周知事項を表示させるデジタルサイネージのような機能を開発することを考えています。また、このデバイスの価値を最大限高めるには、やはり経費申請をより簡単に行えるよう改善していく必要があると思っております。 最後に 私自身、チーム開発の経験がなく、プログラミングも研究で扱った程度(しかもFortranのみ)といった状態でした。技術的な不安が多くある中、必死に勉強しながら同期のメンバーや先輩の社員の皆様にもご協力いただき、最終的にはデバイスの開発部分の多くを実装することができました。デバイス以外にもフロント分野に挑戦することもでき、未経験でも多くの経験を積める有意義な研修であったと感じています。
この記事は Safie Engineers' Blog! Advent Calendar 6日目の記事です。 はじめに  こんにちは。第2開発部でフロントエンドエンジニアをしている東條です。今回は、2024年新卒エンジニア研修におけるインフラ分野の開発についてお話ししたいと思います。 はじめに セーフィーでの2024年新卒エンジニア研修と作ったプロダクトの紹介 導入 定期実行について バージョン更新とメンテナンスについて バージョンが更新されているのかどうかが判断できない バージョン更新中にアクセスするとエラーになる Slackへの通知が確認できない 感想 セーフィーでの2024年新卒エンジニア研修と作ったプロダクトの紹介  セーフィーでは全体研修後、約3ヶ月のエンジニア研修があり、エンジニアとしての基礎を学びつつ、社内課題を解決するプロダクトを開発しました。課題選定から開発言語、体制まで全て自分たちで決める形式で、私たちは「isai connect」を開発しました。これは、他部署の方とランチに行くと会社がランチ代を負担してくれる「異才ランチ」制度をより活用し、活発化を図るためのプロダクトです。詳しくは以下の記事でご覧ください。 新卒研修の紹介とチーム開発前にやったこと 2024年新卒エンジニア研修-アジャイル開発編 2024年新卒エンジニア研修-isai connectについて 2024年新卒エンジニア研修-isai connect開発のアウトプット_サーバーサイド 2024年新卒エンジニア研修-フロントエンド開発編 2024年新卒エンジニア研修-インフラ構築編 ←本記事 2024年新卒エンジニア研修-isai connect開発のアウトプット_デバイス編 2024年新卒エンジニア研修-新卒研修の成果発表とその後 導入  今回、個人としてはじめて IaC( Infrastructure as a Code ) によるインフラ構築を体験しました。使用したツールは Terraform です。そもそも記法やどんな仕組みで動いているのかも知らなかったため、他のインターン生がインターンのときに書いていたコードや公式のチュートリアルのコードとにらめっこしながら概要を把握していきました。  最終的な全体構成としては、 フロントエンドアプリ S3 にビルドしたファイル群を配置 CloudFront から配信 APIサーバー ECS Fargate でコンテナを立ち上げ DB Aurora MySQL のようになっています。 AWS のインフラ構成図  最初は Single AZ で組んでいたのですが、インフラの構築をしている時期にたまたま AWS の方が入門者向けにハンズオン形式で講義してくださる貴重な機会があり( https://engineers.safie.link/entry/safie_aws_starters_report )、そのなかで Multi AZ 構造をとることで可用性を担保できると教えていただいたので早速取り入れました。  余談ですが、AWS の DB 系の Multi AZ 構成では Writer (書き込み専用)と Reader (読み取り専用)が別れていて完全な2台構成になっていないということを初めて知りました。書き込みが複数の AZ で発生すると一貫性が崩れるので当たり前といえば当たり前ですが賢いですね。Writer が死ぬと Reader のうち1台が Writer に昇格するのは動物の生存本能みたいでとても合理的でおもしろい仕組みだと感じました。  この記事内では、インフラの構築および運用の中で工夫した点や苦労した点についていくつか紹介させていただきたいと思います。 定期実行について  24新卒チーム内で機能開発を進めていく中で、実際にコネクトしてお誘いのメッセージをおくったはいいものの返事をくれなかったときはどうすればいいのかという問題が浮き彫りになりました。ここで、3日経ったところで自動でキャンセルする機能の開発を行うことになりました。API のサーバーの機能的には、定期的に DB を見てコネクトの作成日から3日経っているかを判定してキャンセル処理をすればよいのですが、本番環境で定期実行をどうするかに結構悩みました。  最初思い浮かんだのは cron スケジュールですが、そもそも Fargate では Linux 自体を起動しているわけではなく Python:3.11-slim のイメージを起動していますし、今後オートスケーリングなどをした場合は無駄に複数回処理を回すことになりバグが発生する可能性もあり却下しました。  そこで、AWS のサービス自体でなんとかできないかと色々調べ回った結果2つ選択肢の目星をつけました。 Lambda を使用して Aurora MySQL を直接操作する Event Bridge Scheduler で ECS タスクを定期実行する  最終的には EventBridge Scheduler で ECS タスクを定期実行する方針で決めました。理由としては、学習コストが少ないことです。これは、チーム内のスケジュール的な問題ではありますが、この定期実行のタスクに取り掛かったのが最終のスプリントであったため、学習コストを抑えて短期で実行可能な状態まで持っていく必要がありました。  実際の実装としては単純なもので、API サーバーで定期実行用の API エンドポイントを用意して定期実行 ECS の中では curl イメージを使用してただその API を叩いています。このような実装にした理由は、開発において API サーバーとキャンセル機構が分離すると保守性が下がってしまうためです。 バージョン更新とメンテナンスについて  今回のインフラ構築では、アプリケーションの特性上アクセス頻度が高くないことと、集中した開発が研修中だけであることから、AWS のコストを抑えるためステージング環境を用意せず本番環境のみの構成としています。その中で困ったことが3点ありました。 バージョンが更新されているのかどうかが判断できない バージョン更新中にアクセスするとエラーになる Slack への通知が確認できない  それぞれどのように解決したかをご紹介します。 バージョンが更新されているのかどうかが判断できない  これはステージング環境があっても起こることだとは思うのですが、イメージやファイルをあげてアップデートしてもそれが反映されているのか、エラーで反映されていないのか、が判断できませんでした。フロントエンドだとデザインの修正や機能の修正が目に見えるのである程度問題はないのですが、とくにサーバーサイドのバグ修正や DB のスキーマ修正などは API を叩くまでは判断できないためデプロイ時に判断できる仕組みが必要でした。  対策としては、ビルド時にバージョンを入れ込む仕組みを導入しました。デプロイする際に CI で自動で付与していたバージョン( vx.x.x )を指定してビルド&デプロイすることで外部から簡単にバージョンを確認できるようにしました。  具体的には、フロントエンドではビルドするコマンドにバージョンを渡すことで meta タグにバージョンが埋め込まれるようにしました。バックエンドではイメージのビルド時に Dockerfile で環境変数を ARG と ENV を用いて固定することで Swagger UI に表示し、それぞれバージョンの表示を実現しています。以下画像は v1.6.0 状態を確認した際のものです。 フロントエンド バックエンド  このあたりはまだデプロイを含めて自動化できていないため、今後の課題として CI/CD を充実させたいです。 バージョン更新中にアクセスするとエラーになる  フロントエンドのアプリケーションはキャッシュを削除しない限り以前のバージョンが配信されますし、バックエンドも更新をかけて新しいコンテナが起動してから置き換わるのでそれぞれがエラーを吐くことはないのですが、デプロイ自体のラグが発生するためフロントエンドで叩いていた API が新しいパラメータを要求するようになっていたり、逆も然りが置きます。  そこで対策としてメンテナンス期間を導入しました。想像つきやすいのは銀行系のアプリなどである「◯月◯日◯時から◯時はメンテナンスのため一部機能がご利用できない可能性があります」だと思います。AWS の ALB に固定 503 Service Unavailable エラーを返すルールをメンテナンス中のみ追加し、フロントエンド側は 503 Error を返却されたときにメンテナンスページを開くように実装することでデプロイ中の数分間のみサービスを停止しています。 メンテナンス中に表示される画面 Slackへの通知が確認できない  本番環境の API を叩くと実際に DM が届いてしまうので、Slack からのアクションを確認できないという問題が発生しました。プレリリース前の開発中はテスト用の Slack チャンネルを作成することで実際に DM を飛ばすことなく確認できたのですが、本番環境ではそうはいかないので代替案を考える必要がありました。  色々考えた結果、最終本番環境に Slack App のテスト環境を作りました。具体的には、Slack App を開発検証用に DM 権限を制限した状態で作成し、図のように開発検証用の Slack App には本番環境のテスト用エンドポイントを指定、テスト用エンドポイントへのリクエストボディをそのままテスト用チャンネルに送信するように実装しました。こうすることでテスト用チャンネルに送られてきたリクエストボディをローカル環境で立ち上げている API サーバーに送信することができます。これによりで Slack のアクションを確認することが可能になりました。(ただし、参考として ngrok などを使ってローカル環境で Slack App 自体をモックすることは可能なようです) Slack通知のテスト環境概念図 感想  今こうして振り返るとこんな感じに構築していたらもっと楽だったかもしれない、今ならこうするといった反省点が山盛りではあるのですが、個人開発でも触ってこなかったインフラの分野についてチーム開発を通して試行錯誤しながら触れることができたのは良い経験だと考えています。また、新卒でのチーム開発を通して配属されたあとも未だに一緒にお昼ごはんを食べているくらい仲が良くなったので、何かあったときに気軽に相談できる仲間を社内に作れたという点はとても重要でした。
この記事は Safie Engineers' Blog! Advent Calendar  5日目の記事です。 自己紹介 こんにちは。セーフィー株式会社 開発本部所属の佐々木 大翔(ささき ひろと)と申します。今回は、我々が行った2024年度新卒エンジニア研修における、フロントエンド開発についてお話ししたいと思います。 自己紹介 エンジニア研修と開発したプロダクトについて 活動内容 画面定義 画面実装 使用技術 工夫した点 テストコード実装 テスト方針 テストツール 気をつけたこと・学んだこと 試行錯誤した部分 改善例 トップ画面の改善 プログレスバーの追加 アプリのフロントエンド開発をしてみて エンジニア研修と開発したプロダクトについて セーフィーでは全体研修後、約3ヶ月のエンジニア研修があり、エンジニアとしての基礎を学びつつ、社内課題を解決するプロダクトを開発しました。課題選定から開発言語、体制まで全て自分たちで決める形式で、私たちは「isai connect」を開発しました。これは、他部署の方とランチに行くと会社がランチ代を負担してくれる「異才ランチ」制度をより活用し、活発化を図るためのプロダクトです。詳しくは以下の記事でご覧ください。 新卒研修の紹介とチーム開発前にやったこと 2024年新卒エンジニア研修-アジャイル開発編 2024年新卒エンジニア研修-isai connectについて 2024年新卒エンジニア研修-isai connect開発のアウトプット_サーバーサイド 2024年新卒エンジニア研修-フロントエンド開発編 ←本記事 2024年新卒エンジニア研修-インフラ構築編 2024年新卒エンジニア研修-isai connect開発のアウトプット_デバイス編 2024年新卒エンジニア研修-新卒研修の成果発表とその後 活動内容 今回のフロントエンド開発で行ったことは以下の通りです。 画面定義 実装 テストコード実装 以上の工程について、それぞれ説明していきます。 画面定義 ここでは、Figmaを用いてアプリ内のページ遷移や各ページのレイアウト、UI・UXデザインを定義した画面仕様書の作成を行いました。 フロントエンド開発の担当者は決まっていたものの、画面仕様書を作成した際にはチームメンバー全員で確認を行うなどして、チーム内できちんと合意をとった上で画面定義を行いました。 また、我々の開発はアジャイル開発をベースにしていたので、スプリントごとに画面定義を行いました。アジャイル開発については こちらの記事 をご覧ください。 isai-connect-画面デザイン 画面実装 制作した画面仕様書をもとに、コーディングを行いました。 使用技術 今回の実装で使用したものは、以下の通りとなっております。 プログラミング言語・・・TypeScript フレームワーク・・・React ビルドツール・・・Vite UIライブラリ・・・Material UI コード整形関連ツール・・・ESlint, Prettier 基本的に、ドキュメント量が豊富であり、サポートが現在も継続的に行われているツールを採用しました。また、実際にセーフィーで活用されている言語やツールを用いることで、配属後の学習コストを下げる狙いもありました。 工夫した点 Figmaで定義したフォントサイズやコンポーネントが画面上に反映されやすくなるよう、Figmaの設定に忠実に倣って、Material UIのコンポーネントのテーマを定義しました。 例えば、上の画像に定義されている黄色の「デフォルトボタン」では、ColorにSecondary、VariantにContainedが定義されています。 isai-connect-ボタンデザイン isai-connect-デザイン設定 この設定をコード上では以下のように定義しました。これによりコンポーネントに”color=’Secondary’”、”variant=’contained’”というような形で変数を指定するだけで、この黄色のボタンをFigmaの定義通りに表現することができます。 components : { MuiButton : { variants : [ { props : { size : "small" } , style : { fontSize : 10 } } , { props : { size : "medium" } , style : { fontSize : 16 } } , { props : { size : "large" } , style : { fontSize : 24 } } ] } } palette: { text: { primary: "#333" }, primary: { main: "#FFAD36", contrastText: "#fff" }, secondary: { main: "#2981C0", contrastText: "#fff" }, error: { main: "#D02F48", contrastText: "#fff" }, shadow: { main: SHADOW_COLOR }, disable: { main: "#757575" } } テストコード実装 テスト方針 ページごとに単体テストコードを実装しました。 アプリ内のあるページを実装した人が、テストコードも合わせて実装するという方針で進めました。 今回のテストコード実装では 主に画面に情報がきちんと表示されているか ユーザーの操作をテスト内で模擬し、正しい振る舞いが画面上でできているか といった、ユーザー目線に近い観点でテストコードを実装しました。 テストツール テストコード実装の際に使用したツールは以下の通りです。 Jest testing-library/react 気をつけたこと・学んだこと きちんとテストコードを書いたり、チーム内でテスト方針を考えたりすること自体初めてだったので、とても学びが多い部分だったと感じております。 APIとの通信が絡む処理については、サービスの共通モックをあらかじめ作ることで、テストコード実装者によって、API処理周りの処理の書き方にばらつきが出ないようにしました。 学んだこととしては、テストコード実装初心者だった我々にとって、Jestやtesting-library/reactで提供されている関数や概念を理解するのに苦労しました。この仕組みはどのように使われ、なぜ必要なのかを一つずつ学んでいきました。 実際に私たちが実装したテストコードの一例をお見せします。 test ( "slackにURLを送信するテスト" , async () => { renderDOM ( "register" ) const emailInput = screen . getByLabelText (/ メールアドレス /) const registerButton = screen . getByRole ( "button" , { name : / 登録 / }) // 入力 await userEvent . type ( emailInput , "test@example.com" ) // 登録実行 await userEvent . click ( registerButton ) await waitFor (() => { expect ( screen . getByText (/ まだ登録は完了していません! /)) . toBeInTheDocument () }) }) test ( "slackにURLを送信するエラー" , async () => { mockRejectedValueOnce ( userService , "sendPasswordRegisterNotification" ) renderDOM ( "register" ) const emailInput = screen . getByLabelText (/ メールアドレス /) const registerButton = screen . getByRole ( "button" , { name : / 登録 / }) await userEvent . type ( emailInput , "test@example.com" ) await userEvent . click ( registerButton ) await waitFor (() => { expect ( screen . getByText (/ 登録できませんでした。再度試してください。 /)) . toBeInTheDocument () }) }) こちらのコードはランチ相手が決定し、Slackに招待を送る部分の処理のテストコードです。正常系でテストを行った後に、異常系やレアケースもきちんとテストするようにしました。 何をテストし、どのような期待値が求められるのかをきちんとコード内で明文化することを意識しました。このコードに関して言うと、ユーザーのタイプ操作やクリック操作は非同期処理になるため、適切にawaitを仕込む必要性がありました。また、ユーザー操作の結果を受けて実行される処理に関しても、ユーザー操作の非同期処理を待ってから処理が走るように設定しなければなりませんでした。この設定を怠ると、非同期処理の部分だけ適切に実行されずに空回りし、望まないテスト結果につながってしまいます。 試行錯誤した部分 上述のように、フロントエンド開発といってもいろいろな工程があります。 特にこの中で一番試行錯誤した点を上げるとすれば、UI・UXデザインだと感じております。 「ユーザーが直感的に使えて、ストレスを感じさせないようなページ遷移、UIデザイン、誘導を行うにはどうすればいいのか」 このテーマを常に意識しながら画面定義を行っていたのですが、毎回スプリントレビューで上司の方々からご指摘をいただいておりました。 主にいただいていたご指摘としては、 同じ確認を何度もさせているので、ユーザーにとってストレス ボタンを押した後の結果が推測できない パーツの配置、サイズにどんなコンセプトがあるのかが考慮されていない などがありました。 改善例 トップ画面の改善 トップ画面からランダムマッチングを選択した際、もともとは以下のような画面レイアウトと遷移を定義していました。 isai-connect-画面遷移 こちらの画面遷移についてご説明します。まず、左側にあるトップ画面に「異才を探す」という黄色いボタンがあります。このボタンをクリックすることで、真ん中に表示されている画面に遷移します。左側にある「ランダムに異才をさがす」というボタンを押すことで、画像右側にある確認画面へと遷移します。 しかし、これでは「異才を探す」という選択を、ユーザーに3回もさせてしまうことになり、明らかに冗長な工程だとわかります。 そこで、操作回数を減らしつつ、ユーザーが操作内容を直感で推測できるように改良したものが、以下の画像になります。 isai-connect-マッチングの選択画面 マッチング方法の選択作業をページ一つにまとめ、ボタンを押せばどのような処理が走るのかが一目でわかるような見た目にしました。 また、上二つのボタンと下の「部署を選んで」ボタンにも工夫した点があります。上二つのボタンは、押下後にすぐにマッチングが走る仕組みです。人数は異なりますが、「すぐにマッチングが走る」というコンセプトが一致しているため、ボタンのサイズや形状を統一させています。対して、下の「部署を選んで」ボタンは、ボタン押下後に部署の選択画面に遷移するため、すぐにマッチングが走るというわけではありません。このようにコンセプトが上の二つのボタンとは異なるため、形状とサイズに違いを持たせました。 プログレスバーの追加 ユーザーが実際にマッチングを行い、マッチングが終わった後の結果表示からSlackへのメッセージ送信完了への画面遷移に関しても、改善前は以下のように定義していました。 isai-connect-プログレスバー実装前 「トップ画面の改善」の節でお見せした改善前の画面遷移と合わせて見てみます。私たち開発側からすれば、この遷移で問題ないように見えてしまいますが、この状態でリリースされたアプリを初めて触るユーザーは違います。この画面遷移のままだと、ユーザーが何かボタンを押した後の結果が、実際に遷移されてからでないとわかりません。 この問題を解決するために導入したのが、画面上部に表示するプログレスバーです。プログレスバーを導入することで、ある操作をした後にどういう状態になるのかが一目でわかるようになりました。 isai-connect-プログレスバー実装後 アプリのフロントエンド開発をしてみて 私たちは常日頃からアプリケーションを利用しています。しかし、いざユーザー視点でアプリを作るとなると、日ごろからアプリを利用している身であるにもかかわらず、考えが及ばなかったり、意思決定に時間がかかったりする場面がたくさんありました。フロントエンド開発に今後も携わる身として、ユーザーにストレスを与えず、直感で機能・場所・状態を即座に推測できるようなUI/UXデザインができるように、日々精進していきたいと思います。私たちが開発したアプリを通じて、部署の垣根を超えたコミュニケーションが、社内でより活発になれば幸いです。 最後までご覧いただきありがとうございました。
この記事は Safie Engineers' Blog! Advent Calendar 4日目の記事です。 はじめに  こんにちは。第3開発部でエンジニアをしている伊東です。今回は2024年新卒エンジニア研修における、バックエンド分野の開発についてお話しします。 はじめに セーフィーでの2024年新卒エンジニア研修と作ったプロダクトの紹介 機能 設計 ER図 シーケンス図 API仕様書 実装 使用技術 ディレクトリ構成 認証 工夫したポイント おわりに セーフィーでの2024年新卒エンジニア研修と作ったプロダクトの紹介  セーフィーでは全体研修後、約3ヶ月のエンジニア研修があり、エンジニアとしての基礎を学びつつ、社内課題を解決するプロダクトを開発しました。課題選定から開発言語、体制まで全て自分たちで決める形式で、私たちは「isai connect」を開発しました。 これは、他部署の方とランチに行くと会社がランチ代を負担してくれる「異才ランチ」制度をより活用し、活発化を図るためのプロダクトです。 詳しくは以下の記事でご覧ください。 新卒研修の紹介とチーム開発前にやったこと 2024年新卒エンジニア研修-アジャイル開発編 2024年新卒エンジニア研修-isai connectについて 2024年新卒エンジニア研修-isai connect開発のアウトプット_サーバーサイド ←本記事 2024年新卒エンジニア研修-フロントエンド開発編 2024年新卒エンジニア研修-インフラ構築編 2024年新卒エンジニア研修-isai connect開発のアウトプット_デバイス編 2024年新卒エンジニア研修-新卒研修の成果発表とその後 機能  isai connectで実装した主要機能は以下の通りです。isai connect管理者にはユーザ管理機能、ユーザにはレコメンド機能とコネクト機能を提供しています。 ユーザ管理 月一で従業員名簿からユーザを作成・更新・削除する機能です。isai connectに登録していないユーザもレコメンドし、コネクトさせる必要があるため従業員名簿からユーザを一括登録しています。 レコメンド 一緒にランチするメンバーを指定したチームからランダムに提示してくれる機能です。「全従業員が保持している属性」「属性判別が容易」の2観点からチーム指定をまず実装しました。今後は様々な属性を指定できるようにしていきます。 コネクト レコメンドされたメンバーに対してランチを誘うSlack DMを送信し、ランチ参加者だけのSlackグループを作成する機能です。社内の主なコミュニケーションツールであるSlackのDM機能を使用することで、メッセージの見逃しリスクを低減し、スムーズな意思決定を促進しています。 設計  isai connectのバックエンド実装を設計書を用いて説明します。 ER図  以下にisai connect用のER図を示します。  各テーブルが管理している情報は以下の通りです。 ユーザ情報 部門情報 部署情報 グループ情報 コネクト実績情報 ユーザに関連する製品情報 コネクト状況の情報 コネクト参加者の情報  コネクト実績とユーザに関連する製品情報を管理するテーブルは、ユーザと多対多の関係になることから、中間テーブルを使用して効率的に管理できるようにしています。 シーケンス図  開発当初は処理ロジックを明確にするためシーケンス図を作成していましたが、API仕様書をフロントエンドと協議して作成する際に実装ロジックが明確になり、共通理解が生まれるため、途中から作成されなくなりました。開発時のシーケンス図の利用頻度は高くはありませんでしたが、参考としてレコメンドからコネクトまでのシーケンス図を掲載します。 API仕様書  1〜3スプリントでは、認識の齟齬を生まないために予めフロントエンドと協議してAPI仕様を策定し、仕様書としてドキュメント化していました。4スプリント目では協議とドキュメント化の時間削減を目的に、バックエンドが定義したAPI仕様をSwagger UIを通じてフロントエンドに渡し、必要であれば都度修正するという試みを行いました。しかしながら、この試みは都度修正の特性上、フロントエンド・バックエンド双方に手戻りを多く強いることになり、結果として多大な時間を浪費することになりました。Swagger UIをドキュメントの代替として用いたことは間違ったアプローチではありませんでしたが、事前の十分な協議なしにこの方法を導入したことが問題でした。  以下に最終的に作成したisai connectのAPI仕様書の一部を示します。  isai/random/は、部門及び部署をクエリパラメータとして指定することで、ランダムなユーザを一人取得するためのAPIです。また、isai/connectは、ホストユーザーと1~3人のゲストユーザーのIDを受け取り、コネクトを行うためのAPIです。 実装  isai connectのバックエンドの実装方法について説明します。 使用技術  配属後の学習コストを減らす目的で、実際にセーフィーで活用されている言語及びフレームワークを選定しました。使用言語、フレームワーク、主要なライブラリは以下の通りです。 言語 Python フレームワーク FastAPI ライブラリ Pydantic SQLAlchemy Alembic ディレクトリ構成  バックエンドの1層目の主要ディレクトリ及びファイルを以下に示します。 app/ ├── connect_db.py ├── cruds/ ├── init_db.py ├── main.py ├── models/ ├── routers/ ├── schemas/ ├── tests/ ├── util/  このディレクトリ構成で開発を進めた結果、ビジネスロジックがcrudsに集中してしまい、ファイルの肥大化と難読化が進行、重複処理が増加するという課題が生じました。この課題を解決するため、今後の開発ではディレクトリ構成の見直しが必要だと考えています。改善策としては、crudsディレクトリ内では純粋なデータベース操作のみを許容し、ビジネスロジックは新たに作成するservicesディレクトリに移動、共通処理の抽出などが挙げられます。これらの変更により、コードの構造が明確になり、保守性と可読性の向上が期待できます。 認証  isai connectの認証では、セキュリティ面と実装の容易さから、OAuth2をベースに、JWTを認証トークンとする方式にしています。基本的な実装はFastAPI公式に従っていますが、トークンが漏洩した場合のリスクを軽減を目的に、追加でリフレッシュトークンを導入しています。また、トークンの保存にはHttpOnlyおよびSecure属性を持つCookieを使用しています。 工夫したポイント  isai connectでは、ユーザの情報取得やDM送信のためにSlack APIを使用しています。これを逐次処理でおこなうと相当な時間を要するため、処理を並行化やマルチスレッド化することが検討されました。並行化とマルチスレッド化を比較したところ、処理時間平均に大きな差異はありませんでしたが、最小と最大の処理時間の差が並行化した方が少く、安定した性能であったため、並行化が採用されました。結果として、DM送信の処理時間を逐次処理したときと比較して2.6倍ほど早めることができました。 おわりに  筆者は、インターンシップで個人でのシステム開発経験を積む機会がありましたが、チームとしてフロントエンドやバックエンドに分かれての開発経験は限られていました。個人開発の際には、設計のドキュメント化を軽視する傾向がありましたが、チーム開発を経験した現在では、チーム内共有の観点からその重要性を強く認識するようになりました。現在所属する部署では、実装だけでなく、事前の調査や事後の評価など、実装の前後のプロセスも成果物の一つとして重視されています。そのため、配属前にドキュメント化の重要性に対する意識を高められたことは、非常に有益でした。  今後、isai connectは開発フェーズから運用フェーズに移行しますが、システムの拡張を継続し、社内コミュニケーションを活発にしたいと考えています。  最後までご覧いただき、ありがとうございました。
この記事は Safie Engineers' Blog! Advent Calendar 3日目の記事です はじめに こんにちは、第1開発部でサーバーサイドエンジニアをしている坂上(さかうえ)です。今回は2024年新卒エンジニア研修で開発したプロダクト「isai connect」について、その背景や機能を紹介します。 はじめに isai connectを作った経緯 ターゲットと課題と解決策 開発を始める前のエピソード isai connectの機能紹介 異才ランチに誘う人を探す機能 SlackのグループDM自動作成機能 コネクト履歴機能 コネクト実績機能 デバイス isai connectを育てていく isai connectを作った経緯 2024年新卒エンジニア研修では、「社内課題を解決するプロダクト開発」というテーマについて取り組みました。これは、セーフィーの中で抱えている課題を見つけ、その解決に向けて、要件定義、設計、開発から運用まで一気通貫して取り組むというものです。 こうして生まれたのがisai connectです。以降では、本プロダクトの開発に着手するまでに行なったセーフィーの中で抱えている課題、ターゲットと解決策の模索、そして、それを解決するisai connectの機能について、紹介します。 新卒研修の紹介とチーム開発前にやったこと 2024年新卒エンジニア研修-アジャイル開発編 2024年新卒エンジニア研修-isai connectについて ←本記事 2024年新卒エンジニア研修-isai connect開発のアウトプット_サーバーサイド 2024年新卒エンジニア研修-フロントエンド開発編 2024年新卒エンジニア研修-インフラ構築編 2024年新卒エンジニア研修-isai connect開発のアウトプット_デバイス編 2024年新卒エンジニア研修-新卒研修の成果発表とその後 ターゲットと課題と解決策 まず、会社における「不」を探るため、以下のプロセスを行いました。 自身の体験や感じたことをリストアップし、共感度の高いものを優先 ユーザーインタビューを実施し、社員の生の声を収集 そこで浮かび上がったのが、セーフィーの福利厚生の1つである異才ランチの課題です。 異才ランチは、他部署の社員とのランチ代を月に2回支給される制度です。新たなアイデアの創出や他部署を巻き込むきっかけとなったり、相互理解に繋がったりといった目的があります。しかし、ユーザーインタビューを通して、以下のような意見がありました。 異才ランチを使えていますか? ついつい月滅になってしまって使えていない できれば知らない人と使いたいけれど誘えない 異才ランチでこうであったら良いなと思う点はありますか? 同じコミュニティ内(開発本部内で仲の良い人など)で固まってしまうことが多いので、他の人と行くきっかけが欲しい このように、社員の中には、誰を選んだら良いかがわからない場合や、見知った仲の方ばかりと行く場合などがあることがわかりました。これは、本来の目的に沿った異才ランチの活用に障壁を感じている方がいるということもできます。 そこで、ターゲットと課題、解決策を以下のように定めました。 ターゲット 異才ランチを使いたいが、誰を誘おうか迷っていたり、そこに障壁を感じている社員 課題 異才ランチを行う際、誰を誘うかやきっかけ作りが利用者にとって難しく感じられることがある 解決策 異才ランチを利用する社員をマッチングするシステムを構築し、異才ランチの実現をサポートする 開発を始める前のエピソード ターゲット、課題と解決策が定まったところで、いざ設計や開発が始まると思いきや、ここで社会人ならではの経験をしました。それは、セーフィーのCTOである森本さんから承認を得るプロセスです。 本プロダクトの開発には、会社の予算が必要でした。そのため、必要なコスト(備品やインフラ料金)を見積もり、プロダクトの価値やメリットを説明する資料を作成しました。7人の想いを込めて、森本さんに直接交渉を行いました。最終的に、無事に賛同していただき、開発のための予算を獲得することができました。この機会を通じて、技術的な関心に留まらず、プロダクトが持つ価値が実際にどのような影響を与えるのかを深く考える貴重な学びを得ることができました。これらを踏まえてisai connectはとても思い入れの深いプロダクトになっています。 isai connectの機能紹介 異才ランチに誘う人を探す機能 課題に挙げた異才ランチに誘うキッカケ作りをより簡単に、より気軽にするために、isai connectでは、3つの方法で異才ランチに誘う機能があります。 3人まとめて 他部署の社員の方々を3人ランダムに選ぶことができます。ボタン1クリックで、気軽に誘うことを目的にこの機能を作りました。 1人ずつ 1人ずつランダムに選ぶことができます。ユーザーが希望する人数でランチに行けるように、段階的に招待する人数を増やせるような機能を作りました。 部署を選んで 部署を選んで、その中から1人ずつランダムに選ぶことができる機能です。興味がある、または、知りたい部署があるユーザーのためにこの機能を作りました。 SlackのグループDM自動作成機能 異才ランチに誘う人を探したのちに、招待メッセージをSlackで送ることができます。異才ランチを始める最初のSlackメッセージを自動化することで、より気軽に誘えるきっかけにしました。また、誘われた人も気軽にお誘いに応えられるようにしました。 誘う人のSlack画面誘った人が、誰に誘ったのかを改めて確認できると同時に、Notion自己紹介のリンクを載せました。ランチに行く前にどんな人なのかを手軽に確認できるようになっています。 誘われた人のSlack画面 誘われた人が、行きましょう😀、か、ごめんなさい💦ボタンを押すことで、誘った人にランチに行けるかどうかのメッセージが飛ぶようになっています。 異才ランチが成立した場合のSlack画面異才ランチが成立すると、自動でグループDMが作成され、参加者に成立したことをお知らせするメッセージが送られます。また、ランチが終了した後に「いってきた」ボタンを押すと、経費申請の手順と必要な情報がSlackでまとめて確認できるようになります。 異才ランチが不成立だった場合のSlack画面誘われた人全員が異才ランチに行くことができなかった場合に、誘った人にその旨を通知する機能です。 コネクト履歴機能 今まで一緒に異才ランチに行ったメンバーや、現在進行中の異才ランチのお誘い状況を一覧で確認できる機能です。これによって、24新卒メンバーの自身の体験にあった、どの方といつ異才ランチに行ったのかが一目瞭然になっています。 コネクト実績機能 異才ランチを利用した回数や、一緒に行ったメンバーの部署の種類の数に応じて、実績を付与する機能です。これは、異才ランチの利用をより楽しくしてもらえるように作りました。この実績は今後増やして行く予定です。 デバイス Webアプリケーションだけでなく、専用デバイスも開発しました。このデバイスは、顔認証後にユーザーのSlackにレシート画像を直接送信する機能を備えています。これにより、異才ランチ後の経費申請で、スマホでレシートを撮影してPCに送る手間を省けます。ユーザーインタビューで挙がった「経費申請の手間を減らしたい」という要望に応える仕組みです。 さらに、デバイスの画面には、isai connectを通じて行われた異才ランチの月間利用数と累計利用数が表示されており、利用状況がリアルタイムで分かるようになっています。 isai connectを育てていく 様々なバックグラウンドを持った24新卒エンジニア7人が集まって、四苦八苦しながらこのisai connectを作りました。今後は、日々の業務と並行して、このプロダクトを運用するだけでなく、さらに成長させていきます。本記事は、プロダクトの説明に留まってしまいましたが、他の記事では、プロダクトを作る過程やチームの様子などを知ることができます。ぜひご覧ください。
この記事は Safie Engineers' Blog! Advent Calendar  2日目の記事です。 はじめに こんにちは!第1開発部でサーバーサイドエンジニアをしている古谷です! 今回は2024年新卒エンジニア研修で行った開発について開発体制の観点からお話しします! はじめに セーフィーでの2024年新卒エンジニア研修と作ったプロダクトの紹介 開発体制をアジャイル開発に決定 スクラムで意識したこと スクラムイベントでの工夫 ユーザーストーリーマッピング スプリントプランニング デイリースクラム スプリントレビュー レトロスペクティブ ポジティブ共有会 結果と感想 セーフィーでの2024年新卒エンジニア研修と作ったプロダクトの紹介 セーフィーでは全体研修後、約3ヶ月のエンジニア研修があり、エンジニアとしての基礎を学びつつ、社内課題を解決するプロダクトを開発しました。課題選定から開発言語、体制まで全て自分たちで決める形式で、私たちは「isai connect」を開発しました。これは、他部署の方とランチに行くと会社がランチ代を負担してくれる「異才ランチ」制度をより活用し、活発化を図るためのプロダクトです。詳しくは以下の記事でご覧ください。 新卒研修の紹介とチーム開発前にやったこと 2024年新卒エンジニア研修-アジャイル開発編 ←本記事 2024年新卒エンジニア研修-isai connectについて 2024年新卒エンジニア研修-isai connect開発のアウトプット_サーバーサイド 2024年新卒エンジニア研修-フロントエンド開発編 2024年新卒エンジニア研修-インフラ構築編 2024年新卒エンジニア研修-isai connect開発のアウトプット_デバイス編 2024年新卒エンジニア研修-新卒研修の成果発表とその後 開発体制をアジャイル開発に決定 開発は新卒エンジニア7人で行いました。開発体制を決める上でウォーターフォール開発かアジャイル開発にするかをチームで話し合い、悩んだ結果アジャイル開発のスクラムに決めました。決め手は新卒研修の目的の一つに「プロダクトが成長し続けることの重要性を知る」が設定されていたことです。3ヶ月という短い期間でプロダクトを成長させるという経験を積むためには、アジャイル開発のスクラムを用いて小さくリリースを繰り返すことが目的の達成に繋がると考えました。 スクラムで意識したこと 私はチームでスクラムを行っていく上でスクラムマスターというポジションでチームに貢献していました。スクラムマスターはチームで誰よりもスクラムに詳しい必要があり、チームにスクラムを浸透させる役割があります。私が意識したことは「一般的な基本のスクラムを実践すること」です。スクラムはよくチームに合わせてアレンジして使われることが多く、正解はないとされています。しかしチームではまだ誰もスクラムを実践したことはなかったためアレンジをする前にまずは基本を知るということを大切にしました。そのために、Udemyを用いてスクラムを勉強しチームに普及しました。今回はスクラムマスターとプロダクトオーナー(テックリードの方が役割としては近い)を役割としてチームで定め、スプリントは2週間で開発を進めました。また、スクラムを実践する上でカンバンも取り入れました。 スクラムイベントでの工夫 ここからはアジャイル開発のスクラムを実践する上での工夫についてお話しします。 ユーザーストーリーマッピング スクラムではスプリントという短い期間(今回は2週間)での開発を繰り返し何度もリリースをすることでプロダクトを作り上げていきます。異才ランチをよくするプロダクトを作ると決めた後、課題を解決するための機能に優先順位をつけるために図1のようなユーザーストーリーマッピングを作成しました。ユーザーストーリーマッピングでは「誰が・何を・なぜ」という型で課題を一つ一つの付箋に書き出し、時系列を横軸に優先度を縦軸に並べたものを作成します。開発する機能の優先順位をつけるための付箋に書き出す課題のちょうどいい粒度を見つけることが難しく、2回作り直しました。「何を」の項目に対して「異才ランチで誰を誘っていいかわからないことを解決する」というような粒度から「異才ランチを誘う相手をランダムで提案する」という機能により近い粒度で書くことで解決しました。始めはこのユーザーストーリーマッピングは意味あるのだろうかと不安になることもありましたが、途中からはスプリントプランニングをしていく上でなくてはならない存在になっていました。 図1 ユーザーストーリーマッピング スプリントプランニング スプリントプランニングは各スプリントの最初に行い、その2週間で何を達成するためにどのコア機能を作るのかをユーザーストーリーマッピングを元にチームで話し合います。まず始めにスプリントゴールを決め、次にそのスプリントゴールに必要なコア機能を取捨選択します。そして、各タスクにストーリーポイントを割り振り、チームのベロシティと比較し調整して完了です。図2はスプリントプランニング後のユーザーストーリーマッピングの一部です。スクラムイベントの中でスプリントプランニングが一番大変でした。7人のイメージしているプロダクトのイメージがそれぞれバラバラで合わせるために長い時間を使ってしまいました。スプリントプランニングの時間はスプリントが1ヶ月だと8時間ぐらいという目安があります。(参考: スクラムガイド )今回はスプリントが2週間なので半分の4時間ぐらいまでだと考えていたのですが、人数が7人と多かったことと、スプリントプランニングを適当にすると変なものが出来上がり2週間の意味がなくなってしまうという理由で時間が伸びても気にしないようにしていました。長い時は7時間以上かかることもありました。とはいえ話し合いに時間をかけすぎて実装の時間が無くなっては困ります。7人のイメージを合わせることに一番時間を使っていたので、その工夫として7人で図3のような簡易的な画面遷移図を作成するなどをしていました。この工夫をするまではイメージを合わせるのに時間がかかっていたり、イメージがずれていることに気付けなかったりということが多かったのですが、この工夫により話し合いがスムーズに進むようになりました。 図2 スプリントプランニング中のMiro 図3 簡易的な画面遷移図 デイリースクラム 毎朝30分ほどバーンダウンチャートを確認しながらスプリントが順調に進んでいるか問題点はないかということを全員で共有する場を作っていました。各メンバーが問題点を早期に共有できるように雑談を織り交ぜたりチェックインをしたりしながら話しやすい環境作りを意識しました。また、スクラムマスターから問題があるか聞くのではなく各メンバーから報告する形にすることで自分から報告するという癖を付けられるようにしました。 スプリントレビュー スプリントレビューでは2週間で開発したものをお披露目し、レビューを受けることで目的を解決できるものになっているかなどを確認しました。第3回目のスプリントレビューからは初めてisai connectを知る方も交えて行うことでより利用者の気持ちを知ることができました。第3回のスプリントレビューではコア機能に触れるまでクリック数が多すぎるという指摘を受けました。動作に説明をつけたいという理由で増やしており、コア機能までは5クリックほど必要でした。しかし、コア機能まで遠いとその分だけユーザーが離脱してしまう可能性が高くなります。最後にはコア機能に触れるまで最短2クリックでできるようになりプロダクトを改善させることができました。他にもスプリントレビューで受けたフィードバックを抜粋しておきます。 ローディングはワクワク感を強めるために一部長めにしてもいいのでは?(第2回スプリントレビュー) ホーム画面の余白が気になる(第3回スプリントレビュー) 日程調整機能があると嬉しい(第3回スプリントレビュー) UIは良くなったがUXはまだまだ改善の余地がある、slackのユーザーに通知が送られた後にユーザーが混乱してしまいそう(第3回スプリントレビュー) シャチのローディングのUIが素晴らしい(第4回スプリントレビュー) 自分たちのロゴはどのページでも表示するようにしよう(第4回スプリントレビュー) レトロスペクティブ レトロスペクティブでは図4のKPT法を用いて「継続すること・改善したいこと・挑戦したいこと」に分けて2週間の振り返りを行いました。今後のチーム開発をより良くするにはということを話し合う上で振り返りとなるとつい改善点ばかりに目を向けてしまいがちですが、KPT法を用いることで良かった点にも目を向けることができ気持ちのいい振り返りをすることができました。ここで出たTryはデイリースクラムで毎日確認し、意識できるように心がけました。 図4 KPT法 ポジティブ共有会 スクラムイベントとしてあるわけではありませんが、ポジティブ共有会を実施しました。これはチームメンバーのいいところをそれぞれNotionでチケットに書き出し褒め合うというものです。きっかけはチームメンバーから自分がどう思われているのか知りたいという要望からでした。3ヶ月のチーム開発をしている間に2回実施しました。スクラムではチームワークがとても重要です。スクラムは全員が自律的に動くことが大切であり、バラバラに動いていては完成するプロダクトもいいものが作れなくなってしまいます。褒め合う時間は少し恥ずかしい面もありましたが、チームメンバーの相互理解の向上や自分がどこで期待されているのかなどを知ることができ、チームの一員としての帰属意識が強くなりました。 結果と感想 新卒研修ではスクラムを用いて5スプリント目まで回すことができました。1スプリント目で開発したものと5スプリント目で開発したものではクオリティが全く違い、プロダクトを成長させていくという経験も積むことができました。Safieというプロダクトを作っていく会社でエンジニアをしていく上で今後自分たちのプロダクトがどんなものになっていくのかを意識しながら開発しなければ世の中の課題を解決できないプロダクトになってしまいます。プロダクトが成長し続けることが重要というよりはプロダクトを運用していく上でどう成長させていくのか見失わないことが重要だと感じました。 この記事を読んで入社した時のイメージがついていただければ幸いです。他の記事では私たちの作ったisai connectについてなども書かれていますのでぜひご覧ください。
この記事は Safie Engineers' Blog! Advent Calendar 1日目の記事です 導入 はじめまして!2024年に入社し、現在は第4開発部 コアデバイスグループに所属しております山口と申します。 今回は、2024年新卒エンジニア研修の紹介をしたいと思います。 導入 新卒研修の軽い紹介 チーム紹介  開発体制について タスク管理について コーディング規則 チーム開発前にやったこと まとめ 新卒研修の軽い紹介 セーフィーの新卒研修ではチーム開発をおこなっています。チーム開発を通してチームマネジメント・開発(フロント、サーバ、デバイス、CI・CD)・運用・保守を学んでいくのが目的になります。 チーム開発では、2024年度の新卒エンジニアは7名で「社内の負」を解決するシステムについて、アイデアを出し合って開発しました。新卒エンジニアメンバーで話し合った結果、社内で用意されている「異才ランチ」という福利厚生制度に着目し、これを活性化しようという話になりました。 異才ランチを効率化するシステムについては他のテックブログで紹介があると思いますので、本記事では頭出し程度にしておきます。 また、新卒研修のトレーナーには去年の新卒の方々が担当してくださっています。 新卒エンジニアメンバーが執筆した記事については以下リンクをご参照ください! 新卒研修の紹介とチーム開発前にやったこと ←本記事 2024年新卒エンジニア研修-アジャイル開発編 2024年新卒エンジニア研修-isai connectについて 2024年新卒エンジニア研修-isai connect開発のアウトプット_サーバーサイド 2024年新卒エンジニア研修-フロントエンド開発編 2024年新卒エンジニア研修-インフラ構築編 2024年新卒エンジニア研修-isai connect開発のアウトプット_デバイス編 2024年新卒エンジニア研修-新卒研修の成果発表とその後 チーム紹介  新卒研修を始めるにあたってチーム名とロゴを作成しました。 今後会社で24卒エンジニアと認識されるより、チームとして認識してほしいこと、チームとして一体感をだしたいなどが理由です。 チーム名には悩みましたが、各メンバーの頭文字をとって SSSTIFY(トリスティフィー) と命名しました。 ロゴは新卒デザイナーに作成してもらいました。こちらも何度かやり取りを繰り返し、最終的に以下のようなデザインになりました。 このロゴは開発したプロダクトでも使用しています。 開発体制について チーム開発でプロダクトをリードするプロダクトリーダーと技術まわりについてリードするテックリードといった役割もチームで選出しました。 出社する頻度もチーム内で決め様々な働き方を試してみて、自分にはどの働き方があっているかなども考えました。 リモートワークでのコミュニケーション方法について考え、我々は「Gather」を使用してみました。リモートワークの際、Gatherではマップ上で話しかけたい人の近くに移動すれば会話ができるので、現実でちょっと話を聞きに行くみたいな感覚に近いものがあって気軽に相談もできたのが良かったと思います。 下記の画像は実際に開発中に使用したGatherの画像になります。 利用ルールは下記のように定めていました。 利用ルール 利用する曜日:月・水・木 リモート可能な日に利用 リモート: 月 出社: 火・金 自由: 水・木 ログイン時間:出勤時~退勤時まで 利用範囲はSSSTIFYの7名とする 他者の招待は原則NG トレーナーさんなど参加が必要な場合は相談 カメラは常にON マイクは基本OFF、話しかける際にON 雑音などを拾う可能性があるため 全体のミーティングはGoogle Meetを利用 個人間の話し合いではGather上で画面共有など利用可 チャットはSlackを利用し、Gatherでは使わない 履歴を残しておくため 我々のチーム開発ではアジャイル開発を取り入れ、スプリントごとに各領域の開発をできるようにもしました。 例えば、今スプリントでフロント開発していた人が次回スプリントではデバイスの開発をしているといった感じです。 下記のように開発に向けたチームの目標を決めていました。 チームでやりたいこと(目標) 型にはめたスクラムを経験してみる レビューを定期的に受ける(進捗定例) スプリントを2周以上回す経験をする 使ってもらえるプロダクトにする 満足度などの定量指標を設ける 自分が使いたいプロダクトを作る 全員が全ての技術に触れる 1スプリントで二つ以上の技術を触れることが目標 いっぱいタスクを消化している人にどんなタスクあるか相談するのもあり チケットは基本メインの技術スタックをとっても良いが、他の分野についてはレビューで寄与する レビューでは動いたからOKといったものではなく、積極的に実装者やその他の関係者に質問するなど理解を深めるよう意識する タスク管理について タスク管理には「Backlog」を使用しました。 チーム開発ではgitのbranch名をBacklogの課題IDと紐づけることでgithub上でプルリクがマージされたらBacklog上でのチケットも完了ステータスに移行するようにし、なるべく繰り返し作業を減らすことを意識して開発に集中しやすい環境を目指しました。 githubのプルリクとBacklogのチケットが紐づいていることで、どのチケットに対するプルリクなのかも一目で判断でき履歴を追いやすいのも良かったです。 コーディング規則 こちらはプルリクでチェックすべきコーディング規則の内容になります。プルリクの内容がどの領域に対する変更なのかでプルリクのテンプレートが決まります。 テンプレに記載されている項目を担当者は確認し、確認ができし次第レビューを各メンバーへお願いするといった流れでレビューしていました。 また、各フォルダごとにCodeOwnerを選定し、各領域で必ずレビューをもらうべき人を決めていました。変更に対して責任を持ってレビューをするといった意味合いも含んでいます。 チーム開発前にやったこと チーム開発がはじまるまでは初めに「Udemy」という動画教材を取り扱っているサイトを用いてプログラミングの基礎について学習をしていました。 私たちはセーフィーの新卒二期生ですが、一期生の方々の研修フィードバックを元に厳選した動画を中心に学習を進めていました。 既に基礎を理解している人は自由に興味のある領域の動画で学習していました。動画教材のリストとしては、セーフィーのプロダクトに関係のあるものが主に選定されています。 Githubを学んだことがない人はUdemyの動画から学んでいましたが、それだけでは理解は浅かったので、チームで集まって実際にコマンドを叩きながら理解を深めていました。やはり実際に手を動かして学ぶのが一番です。 まとめ 本記事を読んで、少しでも入社したときのイメージがついていただけたら幸いです。 研修終了後、別々の部署に配属された事でSSSTIFYのメンバーとの直接的な接点は減りましたが、他部署のシステムや技術について気軽に相談できる関係性が構築できて今も仲良くさせてもらっています。 また、セーフィーでは新卒採用が始まってから2年が経過していますが、実際に研修を経験した方々のフィードバックから研修内容を柔軟に変えて、最良の研修を模索している段階にあります。 来年度入社される新卒エンジニアの方々のためにも、今回の研修についてしっかりフィードバックを行いました。 今後もさらに研修内容をブラッシュアップしていき、来年度の新卒エンジニアの方々が楽しいと思える研修にできると嬉しいです。
概要 こんにちは!2024年新卒エンジニアの古谷です。今回は技育祭 2024【秋】にエンジニアリングオフィスの副部長の武田さんと登壇してきたことについてお話ししようと思います。 概要 技育祭とは 登壇目的 登壇概要 所感 技育祭とは 技育祭は「技術者を育てる」ことを目的としたエンジニアを目指す学生のための日本最大のオンラインカンファレンスです。各企業の経営者やCTO、エンジニアが二日間に渡って多くの学びや気づきを提供するために登壇します。 登壇目的 私の登壇には2つの目的がありました。 2024年新卒エンジニア研修で身につけた「プロダクト開発で大切なこと」を学生の皆さんに共有し、より引っ張りだこなエンジニアになってもらうこと 私が学生時代にウェブアプリを開発していた時には得られなかった知見をたくさん紹介しました。ハッカソンなどの開発では得られにくい、運用を大前提とした開発における大切なことに、興味を持っていただけると考えました 学生の皆さんにセーフィーがどんなことをしているのか知り興味を持っていただくこと 当日は120人を超える方々に見にきていただき、コメントの反応も良好でした。登壇直後にはカジュアル面談の申し込みが来るなど、学生の皆さんに興味を持ってもらうことができました 登壇概要 以下は登壇した時の資料です。 speakerdeck.com スライドの中では、プロダクトとプロジェクトの違いを説明しつつ、プロダクト開発で大切なことを2024新卒エンジニア研修で作った「isai connect」という異才ランチを活発化させるためのプロダクトを例に説明しています。異才ランチはセーフィーの福利厚生の一つで、他部署の方とランチに行くとランチの費用を会社が負担してくれる制度です。 後半は、私と武田さんによるセッションと学生の方々からの質疑応答を行いました。質問には以下のようなものがありました。 なぜセーフィーに入社したのか プロダクトのアイデアを思いつく良い方法 キャリアビジョンとしてプロジェクトマネージャーを経てプロダクトマネージャーを目指すことはあるか マネージャー職でも積極的にコーディングできるか 就職活動時の最終候補企業 所感 新卒で技育祭に登壇することは大変緊張しましたが、学生時代にお世話になった技育祭に社会人になってからも関わることができ嬉しかったです。 セーフィーでは、様々な挑戦ができる環境があります。この記事を読んでもし興味を持っていただけた方は、ぜひ採用ページもご覧ください。カジュアル面談のみでも大歓迎ですので、お気軽にご連絡ください。 safie.co.jp
こんにちは、第3開発部AI Visionグループのおにきです。 この記事では11月16日(土)にセーフィー社内の会議室で行われたイベント、「 第62回 コンピュータビジョン勉強会@関東 ECCV2024読み会 」について紹介したいと思います。 コンピュータビジョン勉強会@関東 開催にいたる経緯 準備 会場の確認と設備チェック 参加者への配慮 懇親会の準備 当日の様子 参加者の到着 セーフィーの紹介 セーフィーからの発表 その他の発表と全体の印象 懇親会 さいごに コンピュータビジョン勉強会@関東 「 コンピュータビジョン勉強会@関東 」は、takminさんを中心とするメンバーによって14年前から運営されている勉強会です。今回で62回目を迎え、コンピュータビジョン分野では長年にわたり継続している老舗の勉強会として知られています。研究・開発をしているリサーチャー、プロダクトの開発をしているエンジニア、大学で研究を行っている学生など、コンピュータビジョンに関わる多様な方が参加者として集まるレベルの高い勉強会です。 これまで様々なテーマで勉強会は開催されてきましたが、CVPR、ECCV、ICCVと言ったコンピュータビジョンの領域でのトップカンファレンスで発表された論文を解読して紹介するという形式の勉強会は参加者も多く盛り上がるテーマの一つでカンファレンスと時期を合わせて開催されてきました。今回はミラノで行われたECCV(The European Conference on Computer Vision)2024が対象の勉強会となりました。 開催にいたる経緯 私自身もコンピュータビジョンのエンジニアとして、10年以上前から何度かこの勉強会に参加してきました。その中で2回ほど発表の機会もいただき、大変お世話になっています。 夏の勉強会に参加した際、主催者の方々と話をする機会がありました。その中で、セーフィーが1年前にオフィス移転をし、100名収容可能な会議室があるので会場提供できるかもという話になりました。 ちょうどその頃「Mobile Dev Japan #3」という勉強会がセーフィー内で開催されていました。これにより、セーフィー社内でもIT系の勉強会の開催に対して前向きな雰囲気が高まりつつありました。 8月頃にECCV読み会の日程調整と参加者募集が始まったので、会場提供できると連絡したところぜひという回答をいただいたのでセーフィーで開催をすることが決まりました。 せっかく自社のオフィスで開催するということで、AI Visionグループから2名のメンバーを登壇させてもらいました。 準備 会場の確認と設備チェック 今回は土曜日の開催ということもあり、そもそも土曜日はビルのエントランスドアが空いているのかなど入館の仕方についての確認を行いました。 会場となる会議室の設備については、私自身が設定したことがなかったため、前日の金曜日夕方にチェックを行いました。平日開催であれば社内にいる人に助けてもらえそうですが、週末となると他の社員は誰もいないので、入念にチェックは行いました。 参加者への配慮 ECCV読み会は休憩を挟みつつ、午後1時~6時半までの長時間で開催されます。トップカンファレンスの論文の内容を紹介するため、参加者も脳をフル稼働します。セーフィーの入っているオフィスビルは週末になるとコンビニが営業しておらず周囲にもコンビニがないため、せめて飲み物とお菓子を提供しようということで水・お茶とブラックサンダーを用意しました。 お茶と水(ブラックサンダーは休憩時間に提供しました) 弊社製品を触っていただけるデモとグッズとパンフレットも用意しました 初めてセーフィーのオフィスに訪問する方ばかりなので迷わないように案内も設置しました。 懇親会の準備 コンピュータビジョン勉強会@関東では毎回勉強会後に懇親会が開かれ、そちらも盛り上がります。今回はセーフィーからスポンサーとしてお酒と食べ物を提供することにしました。みなさんどれくらいお酒を飲むのかの予測はなかなか難しいですが、適当に一人あたりの本数を決めて発注しました。 当日の様子 参加者の到着 開催時間の30分前から会場に入れるように案内を開始しました。当初は90人近くイベント登録していただいていましたが、実際に入った数は50名弱でした。このあたりのキャンセル者の多さはどの勉強会でも共通の悩みのようです。それでも、50名もの方が実際にセーフィーに来ていただいたということは嬉しい限りです。 セーフィーの紹介 takminさんの挨拶の後に、私から会場提供企業としてセーフィーの会社紹介を行いました。50人近いコンピュータビジョンエンジニアの前でセーフィーを紹介し、実際にプロダクトのデモを見てもらうことでセーフィーという会社とセーフィーでのコンピュータビジョンエンジニアの仕事を認識してもらえたかと思います。発表後にXで確認すると参加者からの反応も良かったようです。 セーフィーからの発表 セーフィーからは周さんと橋本さんに登壇してもらいました。 周さんの発表 Li et al., ”VideoMamba: State Space Model for Efficient Video Understanding” Video Understandingタスクのために最新のアーキテクチャであるMambaを応用した論文です。Deep Learning、Transformerに次ぐ新しいアーキテクチャとしてのMambaを説明した後に、Video Understandingタスクに応用するという内容で数理的にかなり複雑なものでしたが、最新のアーキテクチャということもあり参加者の興味は高かったようです。 speakerdeck.com 橋本さんの発表 Ciortan et al. , “Minimalist Vision with Freeform Pixels” CNNの畳み込み演算を光学系で行うことで、計算機での演算を軽量化するという論文です。ECCV2024のBest Paperを受賞した論文で、発想が非常にわかりやすい研究という印象でした。橋本さんは実際に学習をしてみたそうですが上手くいかなかったようですが、実際に手法を試してみるというのは大切な姿勢だと再認識しました。 speakerdeck.com その他の発表と全体の印象 セーフィーからの2名を含め、合計11名の方が論文の紹介を行いました。どの資料もわかりやすく、また質疑も発表者の方への敬意があるやり取りになっており、本当に良い勉強会コミュニティーであると感じました。 コンピュータビジョンと言ってもその扱う領域が幅広いことと、いろいろな発想のもとに研究が行われているということを知ることができ、非常によい刺激を受けることのできる勉強会でした。 懇親会 勉強会後、ネットワーキングを目的とした懇親会を開催しました。参加者は飲食を楽しみながら、それぞれの会社での業務の進め方やコンピュータビジョン分野での業務上の課題など、普段社内で業務を知ることのできない内容について情報交換をすることができました。このように社外の方と交流することで普段考えている課題などを共有したり、他社での状況を知ることができます。それらは日々の業務のヒントにつながっていくと思われるので、今後も積極的に行っていきたいと考えています。 さいごに 今回の勉強会は週末開催で参加者も多く準備が大変でしたが、チーム内外のメンバーの協力のおかげで開催することができました。開催前は不安なことも多々ありましたが、大きな問題もなく無事開催することができました。スタッフとして参加したセーフィーのメンバーからも楽しかったし勉強にもなったという声を聞いており、開催して本当に良かったと感じています。 セーフィーでは今後もコンピュータビジョンを用いた画像認識AIの開発を進めて行くので、一緒に開発を行うメンバーを募集しています。 open.talentio.com
概要 AIチャットツール導入の目的 LLMおよびAIチャットツールの選定 機密情報・個人情報とLLM LLMの比較表 AIチャットツールの比較表 Bedrock Claude Chat AIチャットボットの導入 Slack連携機能 まとめ 概要 近年大規模言語モデル (LLM) 技術の発達に伴い、社内でもGitHub Copilotをはじめとする各種AIツールの導入が進んでいます。 本件ではLLM技術を用いたAIチャットツールとしてAmazon Bedrockおよび Bedrock Claude Chat を導入した経緯について紹介します。 AIチャットツール導入の目的 2022年末にOpenAI社よりChatGPT 3.5がリリースされて以降LLM技術およびAIチャットボットが急速に普及し、様々な分野で活用されるようになりました。 弊社でもGitHub Copilotによるコード生成補助などでAI技術の導入による社内業務効率化が進められており、また生成AIと映像を組み合わせた新たなサービスの創出が進んでいます。 一方でAIチャットサービスについては社内機密情報・個人情報を扱わない範囲で個別に使用することが認められているだけで、本格的な社内業務改善に用いるのには難しい状況でした。 そこで、社内業務効率化のため、あるいはより高度なAIツール導入の足がかりとするため、また生成AIを用いたサービス創出のための経験値を積むために社内AIチャットボットを導入することにしました。 LLMおよびAIチャットツールの選定 LLMおよびAIチャットツールを選定するにあたり下記の点を考慮しました。 LLMの提供においてはサービスプロバイダが入力を再学習のために使用したり不正使用レビューのため閲覧することが多いため、機密情報・個人情報の扱いについては通常のSaaSサービスと比べ追加の検討が必要になります。 LLM性能 同世代のLLMと比較して十分な性能を持つこと AIチャット機能 ユーザーごとのチャット履歴の保存ができること 検索拡張生成 (RAG) による社内ナレッジに基づくAIチャットボットの提供 その他高度な機能 (Agent、外部ツールアクセス等) 管理機能 SSO ユーザーごとの費用の確認 コンプライアンス LLMの入力が再学習に使用されないかオプトアウトが可能であること LLMの入力が人間のレビューに使用されないかオプトアウトが可能であること 費用 安価であること 機密情報・個人情報とLLM SaaSとしてLLMまたはAIチャットサービスを使用する場合、個人情報を入力することは第三者提供にあたり、ユーザー本人の同意が必要になります。 一般にGMail, Google Drive等クラウドサービスで個人情報を扱うには、対象サービスがいわゆるクラウド例外 ( 個人情報の保護に関する法律についてのガイドライン Q7-53 等) に該当する必要があります。 LLMへの入力が再学習など出力の生成以外の用途に用いられる場合、クラウド例外に該当しません。( https://www.ppc.go.jp/news/careful_information/230602_AI_utilize_alert/ ) またLLMへの入力が不正検知などのために人間によるレビューが行われる場合、クラウド例外に該当しなくなるという見解があります。 【AI】生成AIとクラウド例外 本件では再学習および人間によるレビューが行われないことを条件に、機密情報 (社内秘情報・機密保持契約にカバーされるものを除く) および個人情報の扱いが可能な社内AIチャットボットの導入を進めました。 LLMの比較表 名称 Chatbot Arena Score 再学習 レビュー OpenAI ChatGPT GPT-4o-2024-08-06 1264 有り (オプトアウト可) 人力レビュー (オプトアウト申請可) OpenAI ChatGPT API ChatGPT-4o-latest 1338 無し (オプトイン) 人力レビュー (オプトアウト申請可) Anthropic Claude Claude 3.5 Sonnet 1268 有り (オプトアウト可) 人力レビュー (オプトアウト申請可) Anthropic Claude API Claude 3.5 Sonnet 1268 有り (オプトアウト可) 人力レビュー (オプトアウト申請可) Google Gemini Gemini-1.5-Pro-002 1304 有り 人力レビュー Azure OpenAI GPT-4o-2024-08-06 1264 無し 人力レビュー (オプトアウト申請可) Amazon Bedrock Claude 3.5 Sonnet 1268 無し 自動レビュー ※ Chatbot Arena Leaderboard (2024-10-14) より ※ 不正検知レビューのオプトアウトは申請が受諾される必要があります AIチャットツールの比較表 提供方法 対応モデル SSO カスタムプロンプト RAG Reasoning 外部ツール コンテンツ編集 費用 OpenAI ChatGPT SaaS ChatGPT ChatGPT Enterprise (SAML) GPTs GPTs o1-mini Bing, DALL-E, Code Interpreter, Retrieval, Custom Actions Canvas >= $30/user/month (Enterprise) Anthropic Claude SaaS Claude Claude Enterprise Projects Projects - - Artifacts >= $30/user/month (Enterprise) Google AI Studio SaaS Gemini Google Workspace - - - - - 従量課金 Bedrock Claude Chat セルフホスト (UI) + SaaS (LLM) Bedrock (Claude等) Amazon Cognito (SAML/OIDC) BOT BOT ReAct DuckDuckGo - インフラ料金 + API従量課金 Bedrock Claude Chat Bedrock Claude Chat はAmazonによって開発されているチャットボットUIで、Amazon Bedrock基盤モデルによりAnthropic Claude等を利用可能です。ユーザーはCDKを使用して自身のAWS環境にソフトウェアをデプロイすることができます。 Bedrock Claude Chatは必要な条件を満たし、費用がSaaS製品と比べ非常に安価であるためこれを導入しました。 LLM: Anthropic Claude 3.5 Sonnetが使用でき、選定当時での最高性能 AIチャット: ユーザーごとのチャット履歴の保存、RAG等必要な機能が使用可能 SSO: Amazon CognitoによるSSOが使用可能 コンプライアンス: 再学習および人間によるレビューが行われない 費用: 比較的安価なLLM APIが使用でき、インフラ費用が非常に安価 (月額数百ドル程度) Bedrock Claude Chat 画面イメージ AIチャットボットの導入 Bedrock Claude Chatをデプロイし、全社利用を開始しました。 ユーザーはSSOでアプリにログインし、一般的なAIチャットボットとして使用することができます。 またユーザー権限でボットを作成することができ、カスタムプロンプトの設定や外部URLまたはドキュメントを知識ソースとしてRAG機能を構成し、共有することができます。 現在セーフィー製品の仕様のQ&Aボットなどいくつかの公開ボットが稼働しています。 Slack連携機能 Bedrock Claude ChatにはAPI公開機能があり、こちらを利用してSlackとの連携機能を開発しました。 suzuki-safie/slack-chatbot-fn SlackのCustom FunctionとしてBedrock Claude ChatのBotの公開APIを呼ぶことで、Slack上からチャットボットの機能を利用することができます。 まとめ 社内AIチャットボットとしてBedrock Claude Chatを全社導入し、社内業務改善に使用可能なツールを安価に導入することに成功しました。この導入により、AIを活用した業務効率化の基盤が整いました。 今後は以下の取り組みを通じて、AIチャットボットの活用をさらに推進していく予定です: 利用方法の周知と活用促進 RAG(検索拡張生成)などの高度な機能の使用方法について、社内トレーニングや事例共有を実施 ユーザーの利用体験を向上させ、AIチャットボットの日常的な活用を促進 開発用途での利用拡大 GitHubのコードリポジトリをソースとしたRAGの構築 生成AIを用いた新サービスの創出 AIチャットボット以外の用途でのBedrock基盤モデルの活用 社内アプリケーションやサービスへのAI機能の組み込み これらの取り組みを通じて、AIテクノロジーの社内での浸透を図り、業務効率の向上だけでなく、新たなサービスの創出にもつなげていきます。
はじめに セーフィー株式会社 の AI Vision グループでテックリードを務めます橋本貴博です。 私たちのチームでは、レビューの属人化や特定のメンバーへの負担の集中が課題となっていました。どのメンバーがレビューするかによって、そのやり方やフィードバックの質にバラつきが出ることも少なくなく、これがコードの品質に影響を及ぼしていました。 そのため、チーム全体でレビューを行うことで、コードの知識を全員で共有し、レビューのやり方や品質を標準化したいと考えていました。こうすることで、誰がレビューしても同じように高品質なコードが保たれるようになります。 さらに、Pull Request (PR) の数をKPIとして考え、それに基づいて実装を推進することも重要視しました。PRの数を定量的な指標にすることで、チームの成果を把握し、開発の効率化を図りたいと考えました。 そこで、GitHubのPRを解析して可視化するツールを開発し、オープンソースで公開することにしました。このツールを使うことで、PRの状況を簡単に把握できるだけでなく、レビューの分散や効率化にもつながると考えています。 本記事では、開発したツールの機能と活用、利用している GitHub REST API、ツールの使い方について示します。 はじめに 機能 積み上げ縦棒グラフ ヒートマップ ネットワークグラフ サンキーダイアグラム GitHub REST API Search API Reviews API Review Requests API 使い方 ソースコード むすび 機能 特定の期間において、指定されたメンバーが author、reviewer、もしくは requested review されているPRの数を集計します。結果を可視化して png 画像として出力します。出力される図は以下の通りです。 積み上げ縦棒グラフ ヒートマップ ネットワークグラフ ノードの大きさ: PR作成数とレビューした数の合計 エッジの太さ: レビューした数と、レビューされた数の合計 サンキーダイアグラム 以下では、2024年9月の1か月のPRを集計した結果を例として説明をします。 積み上げ縦棒グラフ Author はPRを作成した数です。極端にPR数が少ない場合、実装に時間がかかっていたり、実装以外の業務の割合が多くなっているといった理由が考えられるので注意しています。 Review-requested は現時点でレビュー依頼されている数です。レビュー依頼が特定のメンバーに溜まっている場合は再割り当てが必要な可能性があるので注意しています。 Review-completed は、レビューが完了している数です。PRに対して1回以上のレビュー(comment, approve, request changes)を行った数から、完了していない場合を除くため、現時点でレビュー依頼されている数を除いています。私たちのチームでは特定のメンバーにレビューが片寄ることを防ぐため、可能であればレビュー数が少ないメンバーにレビュー依頼を行うことを推奨しています。 ヒートマップ 積み上げ縦棒グラフは、各メンバーがレビューした総数は分かりますが、レビュー依頼元の内訳を読み取ることはできません。そこで、依頼元と依頼先の関係を可視化するためにヒートマップを出力するようにしました。ヒートマップの縦軸は依頼元、横軸は依頼先を示しています。PR作成者によっては、依頼先が偏りレビュー属人化の傾向があることが読み取れると思います。 ネットワークグラフ ネットワークグラフは、ヒートマップの情報をさらに直感的に分かりやすく可視化することができます。ノードの大きさは各メンバーのPR作成数とレビュー数の合計から、エッジの太さは2人のメンバーの間でレビューした数とレビューされた数の合計から決定しています。 ノードの位置は Spectral Layout を用いています。これにより結びつきが強いノードは近くに配置されます。したがって、コードやレビューの知識共有が近接するメンバーで密に行われており、逆に離れたメンバにはあまり共有が行われていないのではないかと仮説を立てることができます。 サンキーダイアグラム サンキーダイアグラムは、ある量とその流れを可視化します。ここでは、レビュー依頼の量とその流れを見ることができます。下図において、左端の列はレビューの依頼元と依頼の量を、右端の列はレビューの依頼先と依頼された量を示しています。依頼元から依頼先への流れがグレーの帯で示されています。サンキーダイアグラムを用いると、直感的に誰から誰へどれくらいの量が分配されたのか把握できると思います。 GitHub REST API ここでは、GitHub REST API を用いたPR情報の取得方法について説明します。このツールでは3種類のAPIを利用しています。 まず、 REST API for search (Search API) を用いて集計に含めるPRのリストを取得しています。次に、個々のPRについて、 REST API endpoints for pull request reviews (Reviews API)と、 REST API endpoints for review requests (Review Requests API)を用いて、レビューのステータスとレビュー依頼のステータスを取得しています。 集計の高速化のため、過去に取得した時点から更新が無いリポジトリについてはキャッシュを利用しています。 Search API Search API は、 github.com/search と同様のクエリを用いてGitHub 内のオブジェクトを検索することができます。例えば、特定の期間、特定の組織で、特定のメンバが作成したPRを検索するには検索窓に以下のクエリを入力できます。 type:pr org:Safie author:member-a author:member-b author:member-c created:2024-09-01..2024-09-30 上記に対応して、REST API のURLは次のようになります。 https://api.github.com/search/issues?q=type:pr+org:Safie+author:member-a+author:member-b+author:member-c+created:2024-09-01..2024-09-30&sort=created&order=desc&per_page=100 Reviews API レビューしたメンバーを確認するのに Reviews API を用います。リポジトリのオーナーを {owner} 、リポジトリの名前を {repo} 、PRの番号を {pull_number} として、URLは以下になります。 https://api.github.com/repos/{owner}/{repo}/pulls/{pull_number}/reviews Review Requests API 現時点でレビュー依頼されているメンバーを確認するのに、Review Requests API を用います。Reviews APIと同様に、リポジトリのオーナーを {owner} 、リポジトリの名前を {repo} 、PRの番号を {pull_number} として、URLは以下になります。 https://api.github.com/repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers 使い方 config.py に GitHub token と集計したいメンバーのアカウント名を記載します。 github_token = "ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" authors = [ "member-a" , "member-b" , "member-c" , ] 以下のコマンドを実行します。 python analyze.py # 直近1か月の集計 python analyze.py --from_date 2024 -09- 01 --to_date 2024 -09- 30 # 期間の指定 詳細な使い方は、リポジトリの README.md をご覧ください。 ソースコード こちら でソースコードを公開しています。ぜひ使ってみてください。 github.com むすび GitHub REST API を使ってPRを集計し、PRの属人化やチームの生産性の分析に利用する方法を紹介しました。もし同じような課題に直面しているチームがいれば、ぜひこのツールを活用してみてください。 セーフィーでは、新卒・中途を問わず、さまざまな職種の仲間を積極的に募集しています。詳細は セーフィー採用サイト をご覧ください。
こんにちは!Safie第2開発部のAndroidエンジニアのジェローム( @yujiro45 )です。 Androidで3D/ARモデルを表示するのは難しそうに見え、技術的に大変そうですね。 この記事では、 Sceneview-android を使用して簡単に3DとARモデルを表示する方法を紹介します。 SceneViewとは 導入 実装 アニメーション ARで動画を表示する まとめ SceneViewとは SceneView は Google Filament と ARCore を使用して3Dモデルを表示するライブラリです。 Thomas Gorisse (トーマス・ゴリス)と彼のチームによって開発されました。 Google Filament :Googleが開発している物理ベースのリアルタイムレンダリングエンジンです。 ARCore :Googleが開発したAndroid端末向けのARフレームワークです。 SceneViewは、以前のライブラリである Sceneform のKotlinバージョンであり、完全にKotlinで書き直されています。Sceneformはもはやメンテナンスされていません。 技術的には、SceneViewは3Dスペースで、カメラは中央に位置しており、座標はx=0、y=0、z=1です。 該当部分のコード 導入 この記事では、KotlinとJetpack Composeを利用する導入方法について説明します。ただし、SceneViewはAndroidのxml layoutや Flutter や React Native でも利用可能です。 SceneViewは2つのビューを提供します。 ARSceneView : Google FilamentとARCoreの両方を使用して、3DおよびARを表示する目的で利用されます。 SceneView : Google Filamentを使用して3Dモデルを表示するために利用されます。 SceneViewを追加するには、必要に応じてGradleファイルに適切な依存関係を追加するだけです。 ARSceneView dependencies { implementation( "io.github.sceneview:arsceneview:X.X.X" ) } SceneView dependencies { implementation( "io.github.sceneview:sceneview:X.X.X" ) } 💡 GradleファイルにARSceneViewの依存関係を追加すると、ARSceneViewとSceneViewの両方を使用できます。ただし、SceneViewの依存関係のみを追加した場合は、SceneViewのみを使用できます。 実装 SceneViewは現在、GLTFおよびGLBファイルをサポートしています。3Dモデルのファイルをres/rawフォルダに入れてください。3Dモデルを表示するには、 ModelNode を使用する必要があります。これにより、3Dモデルから3Dノードを作成することができます。 *glbとgltfファイルは以下のサイトで無料でダウンロード出来ます。 https://www.cgtrader.com/ https://polyhaven.com/ https://sketchfab.com/tags/glb 3Dファイルを追加したら、以下のコードを使用して表示できます。 ARSceneView SceneviewexampleTheme { val engine = rememberEngine() val modelLoader = rememberModelLoader(engine) // 3Dモデルの読み込み val modelNode = ModelNode( modelInstance = modelLoader.createModelInstance(R.raw.android) ).apply { // 3Dモデルの初期設定 scale = Scale( 1 / 40f ) position = Position( 0f ) } ARScene( modifier = Modifier.fillMaxSize(), engine = engine, modelLoader = modelLoader, childNodes = rememberNodes { // モデルノードの追加 add(modelNode) } ) } SceneView SceneviewexampleTheme { val engine = rememberEngine() val modelLoader = rememberModelLoader(engine) // 3Dモデルの読み込み val modelNode = ModelNode( modelInstance = modelLoader.createModelInstance(R.raw.android) ).apply { // 3Dモデルの初期設定 scale = Scale( 1 / 40f ) position = Position( 0f ) } Scene( modifier = Modifier.fillMaxSize(), engine = engine, modelLoader = modelLoader, childNodes = rememberNodes { // モデルノードの追加 add(modelNode) } ) } ビルドが通ったら、3Dモデルが表示されました! 🎉 ARSceneView SceneView 出典:Sketchfab, https://sketchfab.com/3d-models/android-7c30eda007684abbb78ea4b99d22fc2c  (2024/10/07アクセス) SceneViewにノードを追加するとき、 ドキュメント によれば、ノードのデフォルトの位置は (x=0.0f, y=0.0f, z=0.0f) で、軸は下の画像のようになります。 カメラを別の位置に移動したい場合は、以下のように指定します。 SceneviewexampleTheme { //... Scene( //... cameraNode = rememberCameraNode(engine).apply { position = Position(z= 5f ) } //... ) } アニメーション ModelNodeのtransform()というメソッドを使用して、位置や回転やScaleを変更することができます。 https://github.com/SceneView/sceneview-android/blob/1e303adf92f1f7b67eb9aa4f9fc731d75213ac97/sceneview/src/main/java/io/github/sceneview/node/Node.kt#L620-L633 fun transform( position : Position = this .position, quaternion : Quaternion = this .quaternion, scale : Scale = this .scale, smooth : Boolean = isSmoothTransformEnabled, smoothSpeed : Float = smoothTransformSpeed ) = transform(Transform(position, quaternion, scale), smooth, smoothSpeed) 前のコードでは、3Dモデルを表示する事が出来ましたので、モデルをタップしたときに180度回転させるようにしましょう。 ARSceneView SceneviewexampleTheme { val engine = rememberEngine() val modelLoader = rememberModelLoader(engine) // 3Dモデルの読み込み val modelNode = ModelNode( modelInstance = modelLoader.createModelInstance(R.raw.android) ).apply { // 3Dモデルの初期設定 scale = Scale( 1 / 40f ) position = Position( 0f ) } ARScene( modifier = Modifier.fillMaxSize(), engine = engine, modelLoader = modelLoader, childNodes = rememberNodes { // モデルノードの追加 add(modelNode) }, // タッチイベントのリスナー onGestureListener = rememberOnGestureListener( onSingleTapConfirmed = { _, node -> if (node == modelNode) { // モデルノードの回転 modelNode.transform( rotation = Rotation(z = 180f ), smooth = true ) } } ) ) } SceneView SceneviewexampleTheme { val engine = rememberEngine() val modelLoader = rememberModelLoader(engine) // 3Dモデルの読み込み val modelNode = ModelNode( modelInstance = modelLoader.createModelInstance(R.raw.android) ).apply { // 3Dモデルの初期設定 scale = Scale( 1 / 40f ) position = Position( 0f ) } Scene( modifier = Modifier.fillMaxSize(), engine = engine, modelLoader = modelLoader, childNodes = rememberNodes { // モデルノードの追加 add(modelNode) }, // タッチイベントのリスナー onGestureListener = rememberOnGestureListener( onSingleTapConfirmed = { _, node -> if (node == modelNode) { // モデルノードの回転 modelNode.transform( rotation = Rotation(z = 180f ), smooth = true ) } } ) ) } 結果を見てみましょう! ARSceneView SceneView ARで動画を表示する 3Dモデルの表示方法がわかったので、以下の動画をExoPlayer x Sceneviewで表示できるように実装していきましょう! こちら で無料動画を入手できます。 出典:Pexels, https://www.pexels.com/ja-jp/video/13299023/  (2024/10/07アクセス) Sceneviewのソースコードを見ると、 VideoNode が無効になっていることがわかりました。 また、Nodeのテクスチャを変更するには、Google Filamentの MaterialInstance を作成し、Sceneviewの MaterialLoader を使用して新しいテクスチャを適用する必要があります。そのためには、以下の手順を実行する必要があります。 こちらがコードです!✨ class ExoPlayerVideoMaterial( engine : Engine, exoPlayer : ExoPlayer, private val materialLoader: MaterialLoader, ) { // SurfaceTexture作成 private val surfaceTexture = SurfaceTexture( 0 ).apply { detachFromGLContext() } // SurfaceTexture→Surface作成 private val surface = Surface(surfaceTexture) // Textureのために、FilamentのStream作成 private val stream = Stream.Builder() .stream(surfaceTexture) .build(engine) // Texture作成 private val texture = VideoTexture.Builder() .stream(stream) .build(engine) // VideoTextureを使ったMaterialInstance作成 val videoInstance get() = materialLoader.createVideoInstance(videoTexture = texture).apply { setExternalTexture(texture) } init { // ExoPlayerのSurface設定 exoPlayer.setVideoSurface(surface) } } Sceneview側では、作成した ExoPlayerVideoMaterial を使いましょう! SceneviewexampleTheme { // ExoPlayerの設定... val player = ExoPlayer ... // さっきの作成したExoPlayerVideoMaterial val videoMaterial = ExoPlayerVideoMaterial(engine, player, materialLoader) val videoNode = PlaneNode( engine = engine, // 動画は16:9のため size = Size( 16f , 9f ), // NodeのMaterialInstance設定 materialInstance = videoMaterial.videoInstance, ) ARScene( //... childNodes = rememberNodes { // ノードの追加 add(videoNode) }, ) } 結果を見てみましょう! ARで動画を表示出来ました!😀 まとめ Sceneviewは、3DやARコンテンツを表示するための非常に便利なライブラリです。設定や使用がとても簡単です。しかし、私の個人的な経験から言うと、ドキュメントがあまり多くないため、もう少し複雑なことをしようとすると、Githubのソースコードを見る必要があります。アプリに3Dを追加したい場合は、ぜひ試してみてください! モバイルチームは開発する仲間を募集しています! open.talentio.com
こんにちは!Safie第2開発部のAndroidエンジニアのジェローム( @yujiro45 )です。 今年も、日本最大のAndroid開発者イベントであるDroidKaigi 2024に参加してきました! Day 0のワークショップから最後まで参加しました。この記事では、今年10周年となるDroidKaigiで何をやったのか、何があったのか、個人的におすすめのトークなどについてお話しします! Day 0 - Workshop Day 1 & 2 - Event Booths Sessions Best sessions Compose UIを使ったクリエイティブで複雑なユーザーインターフェース AndroidのMediaPipeによる画像認識と物体検出 Android StudioのGeminiでコーディングの生産性を高める まとめ Day 0 - Workshop JetbrainsのエンジニアSebastian Aignerさん( @sebi_io )はKotlin Multiplatform (KMP)とCompose Multiplatformのワークショップをやってくれました! 出典:DroidKaigi,X, https://x.com/DroidKaigi/status/1833720183393059289  (2024/10/07アクセス) 個人的には、KMPについてあまり知識がありません。いくつかの記事を読んだり、小さな個人プロジェクトで少し試したりしただけで、深くは掘り下げていませんでした。このワークショップは、もっと学ぶ良い機会となりました! ワークショップに参加する前に、開発環境を準備する必要がありました。 ワークショップのリポジトリ をクローンする Fleet (JetBrainsの新しい統合開発環境 (IDE) )をインストールする リポジトリのすべてのプロジェクトをビルドして、正常に動作するか確認する ワークショップは、Kotlin Multiplatformとそのアーキテクチャについての説明から始まりました。KMPの説明はこの記事の目的ではないので、もっと知りたい方は、 こちら のワークショップのスライドをご覧ください。😇 ワークショップでは、3つの課題がありました。 プラットフォーム毎のネイティブAPI(WebのLocalStorage、デスクトップのJava Properties、AndroidのSharedPreferences)を使用して、ローカルに文字列を持続させる関数を作成しました。 二つ目の課題は、Ktorを使用して、画像を取得して表示するためのシンプルなHTTPリクエストを作成しました。 最後の課題は、Jetpack Composeを使用してUIを作成し、リソースフォルダーに置いた画像を表示しました。 ワークショップは難しくはありませんでしたが、Kotlinで異なるプラットフォームのネイティブAPIをどのように使うかや、Jetpack Composeをモバイルアプリ以外でどのように活用するかを学ぶのはとても面白かったです。 Day 1 & 2 - Event Booths Free ice cream 今年は外が暑かったのと、DroidKaigiの10周年を記念して、初めて無料のアイスクリームがありました! Stamp Rally 今年もスタンプラリーがありました。各ブースにはスタンプがあり、必要な数のスタンプを集めると景品がもらえます。今年も全てのスタンプを集めることができました :) Nail art ネイルアートもありました。個人的にネイルアートには興味がありませんが、それが非常に人気がある理由はなんとなく理解できます 😀 出典:DroidKaigi,X, https://x.com/DroidKaigi/status/1833777502004916330  (2024/10/07アクセス) Sessions Best sessions 今年も多くの面白いセッションがあり、順位をつけるのが難しいですが、DroidKaigi 2024での私のお気に入りのトークをご紹介します! 興味があれば、すべてのVODは こちら で見ることができます。 Compose UIを使ったクリエイティブで複雑なユーザーインターフェース このトークでは、ChrisさんがJetpack Composeを使って、ゲームのUIのような非常に興味深いUIデザインを作成することができるのを示しました。Persona 5のUIを例として使用しました。 実際、Jetpack Composeを使って、もっと創造的になろうと努力すべきです。 出典:DroidKaigi, Youtube, DroidKaigi 2024 - [EN] Creative and complex user interfaces with Compose UI | Chris Horner (2024/10/07アクセス) Jetpack Composeがどれほど強力かを実感しました。 Slides : https://speakerdeck.com/chrishorner/creative-uis-with-compose-droidkaigi-2024 デモアプリ: https://x.com/chris_h_codes/status/1835495634335646042 Repository: chris-horner/persona-im AndroidのMediaPipeによる画像認識と物体検出 このトークでは、 MediaPipe をAndroidで使ってオブジェクトの検出や分類を行う方法を見ることができて、とても興味深かったです。MediaPipeはクロスプラットフォームであり、Pythonでも使えるので、個人プロジェクトで試してみたいと思います! 出典:DroidKaigi, Youtube, DroidKaigi 2024 - [EN] Image Recognition and Object Detection with MediaPipe on Android | Anant Chowdhary (2024/10/07アクセス) Android StudioのGeminiでコーディングの生産性を高める このトークは、2人のゲストによって行われました。Android StudioのシニアプロダクトマネージャーであるAdarsh Fernando( @adarshfernando )と、UXデザインリードのChris Sinco( @csinco )です。 Android Studioでは、Copilotは一番人気だと思いますが、GeminiがAndroid Studioでどのように使われるかを見るのは興味深かったです。Geminiによるすべての変更履歴を確認できたり、ユニットテストのシナリオを生成できたりするのは、とてもよかったです。 出典:DroidKaigi, Youtube, DroidKaigi 2024 - [EN] [Guest Talk] Increasing coding productivity with Gemini in Android Studio | Adarsh Fernando, Chris Sinco (2024/10/07アクセス) まとめ 今年もDroidKaigiはとても良かったです。毎年参加者が増えていることが、このイベントの成功を物語っています。多くの優れたエンジニアと出会い、たくさんの人と話し、面白いセッションに参加しました。 来年の開催をもう楽しみにしています! Safieのブースで会いましょう! 😉 モバイルチームは開発する仲間を募集しています! 一緒にDroidKaigiに参加しましょう! open.talentio.com
こんにちは、第2開発部の池田です。 この記事では、2024/07/26 にセーフィー本社で行われたイベント、 Mobile Dev Japan #3 について紹介したいと思います。セーフィー初の(主催ではないですが)自社にて開催された技術系イベントとなります! Mobile Dev Japan 準備〜設営 イベント本番 Safie Viewer Android & SceneView Beginners Guide to SwiftData A History of JavaScript on Mobile Introduction to Kotlin Multiplatform Networking and Q&A 雑感(英語力など) おわりに Mobile Dev Japan mobiledev.jp Mobile Dev Japan は、おもに日本在住の英語話者が参加しているモバイルエンジニアのコミュニティです。Slackでの交流とオフラインのイベントをメインに、精力的に活動されています。English speaker といっても皆さん日本で生活しているので日本語が達者な方も多いですし、その Background はさまざまです。興味を持たれた方はぜひコミュニティのSlackに参加してみてください。 英語に自信がない方でも、 We are mainly speaking English however everyone is welcome to join even if not confident in their English level yet! とのこと! そんなコミュニティが主催しているイベントをセーフィーで開催することになったのは、 第1回のイベント にて当社の Android エンジニア、Jeromeさんが登壇したことがきっかけでした。そこの繋がりでオーガナイザーからイベント会場の候補としてセーフィーにお声が掛かり、第3回イベントの会場提供と飲食のスポンサーをさせていただくことになりました! 準備〜設営 セーフィーでは販売代理店様向けの営業セミナーなどは頻繁に行われており、 PyCon JP などの技術イベントでスポンサーにもなっていますが、自社を会場とするオフラインの技術カンファレンスは初の試みでした。ゲストの入館方法をはじめとして色々と不慣れな準備に苦労しましたが、今回で知見と型ができたので、今後は積極的に自社イベントも開催していきたいと考えています! セミナールーム。わりと無機質です 手作り案内板 ビールとスナック、サンドイッチも準備 Safie Viewerでストリーミング もちろん弊サービスの対応カメラSafie Oneを使って、社内にLIVEストリーミングもさせていただきました。 conpassでのイベント公開、LT枠も早々に埋まり、いよいよイベント当日です。 ビールとスナックも準備できました! イベント本番 オープニングトーク 約30人のゲストを無事に迎えてイベント開始となりました。もちろん英語で進行します。 発表ごとに活発に質問や軽口が飛び交い、リラックスしつつも盛り上がった雰囲気。 途中、ふらりと覗きにきた営業メンバーも「普段のセミナーと全然違いますね。。」と、感心した様子でした。 以下、簡単に登壇の内容を紹介したいと思います。 Safie Viewer Android & SceneView speakerdeck.com まずはセーフィーから、筋肉自慢のAndroidエンジニア、Jeromeさんのスポンサートーク。 今年リリースされたばかりのセーフィーの新サービス、360度カメラのストリーミングにおける3Dデワープ表示について、 Android 版 Safie Viewer の実装内容紹介です。おもに、3D/AR 機能を提供する SceneView ライブラリを利用して、Safie Viewer の映像を 3D モデルにマッピングして動かす具体的な実装手法やハマったポイントなどを紹介しました。 github.com Beginners Guide to SwiftData speakerdeck.com こちらもセーフィーから、今年3月に入社した iOS エンジニアの Adam さんの発表です。 iOS17 から導入された SwiftData について、その基本的な内容と実装方法を紹介しています。 developer.apple.com Adam さんは軽妙なMCでスポンサー紹介のトークも行ってくれた他、社内でも Safie English School と題した英語力の向上イベント(という英語での飲み会)を行ってくれています! A History of JavaScript on Mobile speakerdeck.com Jamie Birch さんの発表。 アプリの話ではなく、モバイル環境におけるJavaScriptエンジンの歴史についてという異色のトーク。個人的にはPSPや各種ガラケーにもバンドルされていたNetFrontが懐かしかったです。。 Introduction to Kotlin Multiplatform Yuya Haradaさんの発表。 クロスプラットフォーム技術Kotlin Multiplatform(KMP)を軸に、自社でのSwiftUI+KMPというスタックの紹介、その利点とチャレンジ部分などについて語られました。 Networking and Q&A 懇親会も活況 数件の飛び入りLT、イベント告知などの後、Networking(懇親会)の時間となりました。 「みんな意外と飲まないですよ」というオーガナイザーのアドバイスで控えめにしたビールの本数が足りなくならないか、少しハラハラしていましたが何とかちょうど良い感じに収まりました。ここで反省としては、ビールにしろチューハイにしろ缶デザインを見ても中身がわからず迷ってる人が多かったので、ドリンク置き場にも何かキャプションを付ければよかったなというところです。お酒もソフトドリンクもよく出た中で、ノンアルコールビールは一本も手に取られませんでした。なるほど。。 懇親会も非常に盛り上がり、またスポンサートークに挟んだ We are Hiring! のスライドから、一部の方には採用にも興味を持っていただけました。 雑感(英語力など) engineers.safie.link engineers.safie.link セーフィーでは今年から本格的にタイ・ベトナムでのビジネスがスタートし、サービスの国際化対応も当然のものとして実装が前提になってきました。また異才一体のカルチャーが示すように、開発本部スタッフにもアメリカ・フランス・ブラジル・韓国・中国といったさまざまなバックグラウンドのメンバーが増え続けています。 一方で、そういったメンバーのほとんどは日本語が堪能ですし、Slackのやり取りや社内ドキュメントはほぼ日本語。まだまだアウトプットの機会が足りないとも思います。昨今AI翻訳がずいぶん賢くなったおかげで英語の読み書きで苦労することはかなり少なくなりましたが、瞬発力を要するこのようなイベントでは自分の英語力にまだまだ至らなさを感じます(要は懇親会であまり話せず凹んだやつですね。。まぁこれは英語力というよりそもそもの会話力というか。ぶつぶつ。。) なので!社内外にたくさんあるチャンスを活かして、このような場をさらに楽しめる英語力の向上を続けていかなくては、という雑感でした。 engineers.safie.link がんばろう。 おわりに 今回は Mobile Dev Japanコミュニティと共催したイベントについての紹介でした。おかげさまで参加者にも好評いただけたようで良かったです。 モバイルチームでは、このように多様な環境で世界に向けたアプリをともに開発する仲間を募集しています! open.talentio.com セーフィーでは今後もこのような技術交流の機会を増やしていきたいと考えています! Thanks for reading! See you next time❤️
こんにちは、フロントエンドエンジニアの阿部です。 弊社では今後のグローバル進出を見据えて、今年から海外への事業を展開しています。 その一環としてSafieViewer・マイページの国際化対応を行いました。 言語は日本語、英語、ベトナム語、タイ語の4言語に対応しており、現段階では主要な機能においてタイムゾーンにも対応しています。 今回はWebフロントの実装に焦点を当て、SafieViewerとマイページの国際化対応について振り返りたいと思います。 なお、Angularフレームワークを使用しているため、実装の説明はAngularに依存します。 多言語対応とタイムゾーン対応 多言語対応 辞書の作成 メリット デメリット 注意点 翻訳サービスの実装 実装 特殊な翻訳パターンへの対応 翻訳するテキストに変数が入る場合 複数形対応 Serviceで実装することの問題点 Angular外では利用できない 野良関数ではDIができない クラスの外だとDIできない 解決方法 タイムゾーン対応 タイムゾーンの取得 タイムゾーン表示 APIレスポンスへの対応 まとめ 多言語対応とタイムゾーン対応 今回の国際化対応のため、主に行ったのは以下の2点です。 多言語対応 ユーザーが利用する言語に応じて、アプリケーションの表示言語を切り替える機能です。国際化対応の中核を成す要素の一つであり、異なる母語のユーザーに対して、より親しみやすいサービスを提供することが目的です。 タイムゾーン対応 異なる地域のユーザーが同じアプリケーションを利用する際に、それぞれの地域の時間に合わせて正確な時刻情報を提供する機能です。異なるタイムゾーンを考慮することで、ユーザーは常に正確な時刻情報を得ることができます。 それぞれについて対応したことや課題について書いていきます。 多言語対応 辞書の作成 多言語対応を実現するためには、各言語に対応した辞書を作成する必要があります。 辞書には言語ごとにキーと対応するテキストが設定されています。 例えば、英語の場合は「こんにちは」に対して「Hello」、また「おはよう」に対して「Good morning」というように対応付けられます。 // ja.json { "こんにちは" : "こんにちは" , "おはよう" : "おはよう" } // en.json { "こんにちは" : "Hello" , "おはよう" : "Good mornig" } 上記のように日本語がキーとなる構成の辞書を作成しました。 この辞書のメリット・デメリットは以下です。 メリット キー名を考える必要がなくなる よく見る辞書の構成は以下のように、英語がキーとなる構成です。 「こんにちは」「おはよう」であれば単純ですがもっと長いテキストの場合はキー名を考えるのがそもそも大変になります。 その点日本語がキーであれば、キー名を考える手間が省けます。 // ja.json { "HELLO" : "こんにちは" , "GOOD_MORNING" : "おはよう" } // en.json { "HELLO" : "Hello" , "GOOD_MORNING" : "Good mornig" } テンプレート上で辞書の探索をしなくても表示される文言がわかる 例えば、以下のようにキーが英語の場合、実際にアプリ上に表示されている文言が一目ではわかりません。表示されている文言を知るには辞書を調べる必要があります。 対して日本語の場合は一目でどんな文言が表示されているかがわかる為、辞書を調べる手間が省けます。 // キーが英語の場合 < div > {{ 'APP_SETTING' | translate }} </ div > // キーが日本語の場合 < div > {{ 'アプリケーションの設定' | translate }} </ div > デメリット 文言を修正する際にキーとセットで変更する必要がある 日本語がキーの辞書の場合、「 アプリケーションの設定 」というテキストを「 アプリケーション設定 」に変更したい場合、キーとテキストの両方を変更する必要があり手間が増えます。 対して英語がキーの場合は、テキストの意味合いが大きく変わらない場合はキーを変更する必要がありません。 // ja.json // キーが日本語の場合 { 'アプリケーションの設定' : 'アプリケーションの設定' } ↓ { // キーの値を変更する必要がある 'アプリケーション設定' : 'アプリケーション設定' } // キーが英語の場合 { 'APP_SETTING' : 'アプリケーションの設定' } ↓ { // キーの変更は必要でなない 'APP_SETTING' : 'アプリケーション設定' } 注意点 この構成の辞書では以下のような場合に注意が必要です。 「月」という日本語を英語にした際に「Monday」と訳すか「Moon」と訳すかは場合によって異なります。 この場合は以下のようにサフィックスをつけるようにして翻訳後の値を明確にすること必要です。 // ja.json { "月_monday" : "月" , "月_moon" : "月" } // en.json { "月_monday" : "monday" , "月_moon" : "moon" } どんな辞書の構成にもメリット・デメリットはあると思うので、色々な構成を検討することが大切です。アプリケーションにマッチする辞書構成を考えてみてください。 翻訳サービスの実装 実装 アプリケーションの言語を切り替えるには、翻訳サービスが必要です。 このサービスではアプリケーション初期化時 or 言語を変更した際にユーザーが選択した言語で辞書をロードし、辞書から対応するテキストを取得します。 実装は以下です。 @Injectable ({ providerIn : 'root' }) export class TranslateService { // アプリケーション初期化時 or 言語変更時にinitalizeを呼ぶ initialize (){ // 辞書をロードし、ロードした辞書を保持しておく } getValue ( key: string ) { // ロードした辞書からkeyで探索した値を返す } } componentではTranslateSeriviceをDI( DependecyInjection )してTransetService#getValueで翻訳を行います。 // component this .translateService . getValue ( 'こんにちは' ) テンプレート上ではpipeを介して、TranslateService#getValueで翻訳を行います。 translatePipeの中でTranslateService#getValueを呼びます。 // html < div > {{ "こんにちは" | translate }} </ div > // translate.pipe.ts @Pipe ({ name : 'translate' }) export TranslatePipe implements PipeTransform { constructor ( private translateService: TranslateService ){} transform ( key: string ) : string { return translateService . getValue ( key ) ; } } 特殊な翻訳パターンへの対応 翻訳といっても単純にテキストを翻訳するだけではありません。 翻訳時に考えるべき特別なパターンについて説明します。 翻訳するテキストに変数が入る場合 以下のようにユーザーが任意の値にできるデータ名が入った文言を翻訳する場合です。 「dataName」を削除しますか? こちらはtranslateService#getValueの引数に変数に当たる値を渡すことで実現しました。 // component this .translateService . getValue ( '「dataName」を削除しますか?' , { dataName : 'テスト' }) // html < div > {{ '「dataName」を削除しますか?' | translate: { dataName: 'テスト' } }} </ div > // → 「テスト」を削除しますか? 辞書のvalueでは変数部分を${{}}で囲むことで、明示的にこの値が変数であることがわかるようにします。 getValue関数で${{}}で囲まれた値を探索して渡ってきた値を挿入するようにすることで実現しました。 辞書は以下のような形になります。 // ja.json { "${{dataName}}を削除しますか?": "${{dataName}}を削除しますか?" } // en.json { "${{dataName}}を削除しますか?": "Do you want to delete ${{dataName}}?" } 複数形対応 主に単位を翻訳する場合に複数形対応が必要になります。 例えば日本語でカメラの数を表示する場合は1台、2台と表記します。これを英語表記にすると1device, 2devicesとなります。 複数形対応が必要な場合はTranslateService#getValueにoptionとしてアイテムのカウントを渡すようにして実現しました。 テンプレートでは以下のようにして利用します。 // html // itemCountから複数形表示にするかどうかを判断する < div > {{ deviceCount }}{{ '台' | translate: { itemCount: deviceCount } }} </ div > 辞書のvalueは、オブジェクトとして複数形と単数形の両方の値を持つようにしました。 // ja.json { "台" : "台" , } // en.json { "台" : { "singular" : "device" , "plural" : "devices" } , } TranslateServiceはitemCountから複数形表示にするかどうかを判断します。 複数形は言語毎にルールが異なるのでそれぞれ対応が必要になります。 ※今回は独自にロジックを実装しましたが、 Intl.PluralRules を上手く使えばそれぞれの言語のルールを気にする必要がなくなりそうなので移行していきたい Serviceで実装することの問題点 翻訳の仕組みをサービスで実装することでいくつかの問題点がありました。 一番の問題はServiceとして実装することで、 DIしなければならない ことです。 以下で問題点について説明します。 Angular外では利用できない 例えばServiceWorkerなどでプッシュ通知を実装しており、ServiceWorker内でプッシュ通知のテキストを定義している場合などです。 ServiceWorkerはAngular外の話なので、サービスを利用することができず翻訳できないという問題があります。 野良関数ではDIができない 例えば以下のようにtypeによって表示するテキストを返す関数の場合です。 export function typeToString ( type: string ) { if ( type === 'hoge' ) { return 'こんにちは' } else if ( type === 'huga' ) { return 'おはよう' } } このような関数の場合は、使う側でTranslateServcieをDIして、この関数にTranslateServiceのインスタンスを渡せば翻訳自体は可能です。 しかし、テキストを返す関数を実装する場合は、以下のようにtranslateServiceを引数に渡せるように実装しなければならなくなります。 // 利用する側 const text = typeToString ( 'hoge' , this. translateService ) ; クラスの外だとDIできない 以下のように定数として定義しており、オブジェクトのテキストをキーに応じて表示する場合などです。 この場合はDIができない為、このままでは翻訳が難しいです。 // component const TEXT_MAP = { 'huga' : 'ふが' , 'hoge' : 'ほげ' } ※関数や定数に関しては、戻り値を翻訳する方法もありますが、使用する側で翻訳処理を挟まなければならないことや翻訳の漏れを考慮すると、文言を定義した場所で翻訳する方が良いと考えています。 // これだと使う側で必ず翻訳をしなければならない // typeToStringの中だけを見た時に翻訳されているかどうかはわからない const text = typeToString ( 'hoge' ) const translatedText = translateService . getValue ( text ) ; 解決方法 詳細は省きますが、TranslateServiceとほとんど中身は同じtranslate関数という関数をjsで実装しました。(DIせずに基本的にはどこからでも呼び出せる。) jsで実装することでServiceWorker内でも使用できるようになります。 translate関数を実装したことで上記の課題は解決できました。 タイムゾーン対応 タイムゾーンの取得 ユーザーが居住している地域のタイムゾーンを正確に取得することは、タイムゾーン対応の実現に重要です。 通常、ブラウザやデバイスから提供される情報を利用して、ユーザーの現在のタイムゾーンを特定します。 ブラウザのタイムゾーンIDを取得するには、 Intl.DateTimeFormat().resolvedOptions().timeZone を使用します。 このプロパティはタイムゾーンIDが取得できない場合に Etc/Unknown という値を返す可能性があるため、この値が返ってくる場合の考慮も必要になります。 タイムゾーン表示 アプリケーション内で時刻情報を表示する際には、ユーザーのタイムゾーンに合わせて適切な時刻を表示する必要があります。これにより、ユーザーは自分の地域に合った時刻を確認することができます。 国際化対応において Unixtime で時間を扱うことはとても重要になってきます。 例えば以下のようにユーザーが2024年4月29日午後1時の映像を再生することを考えます。この日付はユーザーが異なるタイムゾーンに住んでいる場合、表示される時刻が異なります。 SafieViewer 具体的には以下のように時刻が異なるため表示を変更する必要があります。 東京 (日本標準時、JST) の場合: 2024年4月29日午後1時 ベトナム (ベトナム標準時, ICT)の場合: 2024年4月29日午前11時 ニューヨーク(東部標準時、EST)の場合: 2024年4月29日午前12時 UnixTimeで時間を扱っていれば、JavaScriptの Date オブジェクトがブラウザのタイムゾーンに合わせて適切に表示を変更してくれます。 APIレスポンスへの対応 Unixtimeで時間を扱っている場合は問題ないですが、既存のAPIがJST(日本標準時)のレスポンスを持つ場合があります。 このような場合、API側に表示すべきタイムゾーンを知らせるため、リクエストにtzパラメータとして取得したタイムゾーンIDを渡し、API側でそれに応じたレスポンスを返すように修正する等の対応が必要になります。(今回はこの対応を行いました) 新規にAPIを実装する場合は、時間関連のレスポンスをUnixTimeで扱い、フロントエンド側でタイムゾーンIDに応じて時刻表示を切り替えることでより実装が効率的になると思います。 まとめ 今回のブログでは、簡単に多言語対応とタイムゾーン対応についてそれぞれの実装方法や課題について解説しました。 国際化対応では言語や地域の違いを考慮し、ユーザーにとって使いやすいアプリケーションを提供することが重要です。 今回の取り組みを通じて、国際化対応の重要性や実装方法について深く理解することができました。 今回の内容を基に、さらなる機能改善や拡張を行い、より多くのユーザーに価値を提供していきたいと考えています。 セーフィーではエンジニアを積極的に採用しています。 興味がある方は是非下記サイトを一度覗いてみてください。 https://safie.co.jp/teams/engineering/
自己紹介と本日のテーマ 伝えたいこと 発生した問題 観点出しを行ったことによる効果 まとめ 自己紹介と本日のテーマ こんにちは、セーフィーで品質保証業務に従事しているQAエンジニアの佐藤です。 本日は「テストケース作成前の観点出しの重要性」をテーマにお話しします。 このテーマを選んだ理由は、最近のQA業務で実際に起きた出来事から、観点出しの重要性を改めて実感したためです。 今回のブログでは、観点出しをおろそかにした結果発生した問題と、その後の改善策について、自戒の意味も含め共有しようと思います。 伝えたいこと ソフトウェア開発において、品質保証の一環としてテストの実施が不可欠です。そしてそのためのテストケースの作成が必要となります。 しかし、軽微な修正や工数不足などで見落とされがちなのが、テストケース作成前の「観点出し」です。 この記事では、観点出しをおろそかにした結果発生した問題と、その後の改善策について共有します。 発生した問題 僕の担当していたプロジェクトは少数の開発メンバーで限られたリソースの中で開発を行っていました。 最近は開発メンバーや企画メンバーが増え、AIを利用したアプリをリリースするなど、僕が入社した2022年よりも高度な技術や、広い知見が求められるサービスおよびアプリが増えているように感じています。 以前はリリースごとの追加機能のボリュームが少なく、また携わるメンバーも少なかったため、観点の抽出はメンバー同士のコミュニケーションで完結でき、形式的な観点出しのアウトプット資料などを作ることなく進めてしまっていました。 また、自分自身観点出しの重要性がわかっておらず、そのままテストケースを作成したほうが早いのではないかという思いもあったことから、あまり熱心に観点出しを実施してきませんでした。 そのような状況の中で初めて自分が主体となってテスト設計・実施を行う場面がやってきたのですが、以下のような事が発生してしまいました。 実施すべきテストが実施されずにソフトウェア品質の低下を招いた テストケースの体裁や手順や期待値などのレギュレーションにも一貫性がなく他のメンバーが見たときに混乱を招いた 上記のことから結果的にテストケースを一から作り直さなければならず、より作業工数が増大してしまうという大変な思いをしました。 観点出しを行ったことによる効果 些細な改修内容でもテストケースの作り直し等の問題を避けるため、テストケースを作成前には必ず観点出しを行うように心がけました。基本的なことですが非常に重要な作業で、具体的には以下の流れで作業を実施しました。 QAチーム内での観点のレビュー: 該当のプロダクトのQAに携わるメンバーにレビュー依頼を行い、機能ごとにテストすべきポイントを洗い出す ポイントの洗い出しには各機能がどのような要件を満たすべきか、どのように動作するのが期待値なのかを要件定義書などをしっかりと確認することや、それでも不明な点は事前に開発チームへのヒアリングを実施、エラーや例外時の状況でどのように動作するかなどを念頭に入れて行いました。 開発・企画メンバーとの観点レビュー会の実施:QAチームのレビューを基に作成した観点表を開発・企画メンバーに共有し、テスト範囲や内容についての合意を得る ここでは実際に作成した観点の共有をする上で文字だけではくパターン表を用いた見やすい資料作りを心がけたり、追加で確認したい事項などを事前にまとめておきレビュー会当日の限られた時間の中でスムーズに話すことができるように工夫をしました。 以上のことを踏まえて今回テストケースの作成前に観点出しを行った結果、以下のような効果がありました。 テスト観点の可視化を行うことでの開発、QAメンバーとの意思疎通のコストの削減 テスト観点の可視化により、何のためのテストか誰が見てもわかりやすくなり、QAメンバーからテストケースの手順や、期待値についての質問を受けることが少なくなりました。 また、複数のプロダクトのQAが重なっている場合では特に負担となるのはQA期間中の開発チームへの仕様確認です。 あとから追加で仕様確認することはある程度は仕方ないと思ってはいますが、観点漏れを少なくすることでその仕様確認する件数を減らすことができます。 その結果、全体の工数も削減することができました。 テスト観点の網羅性が向上したことでのテスト自体の品質の向上 テスト実施対象の粒度の均一性や、テスト項目作成にあたっての体裁の一貫性の向上 観点出しを行うことで、テストケースの抜け漏れが大幅に減少しました。 あらかじめ定めた観点に沿ってテストケースを作成することで、テストケースの組み立て方を整理しながら作成することができ、誰が見ても理解しやすいテストケースにすることができたと感じています。 まとめ これらの経験を通じて、テストケースを作成する前に「観点出し」を行うことの重要性を知ることが出来ました。 時間が限られている中でも観点だしを省略せず行うことで、結果的に効率的かつ効果的なテストケースを作成することができるので、どのプロダクトにおいても観点出しを作業のフローに取り入れ、品質向上を目指すことが重要だと感じました。 最後に、セーフィーではより良いプロダクトを作り上げ、成長していく仲間を探しています。 この記事を読んで共感する点がありましたら、ぜひ採用ページもご覧ください。 ※採用情報の詳細は こちら からご覧いただけます。 最後まで読んでいただきありがとうございました。
こんにちは!Safie第2開発部のiOS Engineerアダム( @monolithic_adam )です!今年の夏暑いですね! でも夏といえばあれしかないでしょう!そうiOSDC Japanです! 今年もみんな集まって早稲田でワイワイするiOSイベント! 最高の企画してくれたので #iwillblog 熱が冷めないうちにブログ書いています! Day 0は残念ながら現地参加できなかったけどオンラインで楽しくみていました! 各トラックを切り替えながら楽にトーク見えてハイブリッド頑張ってくれているiOSDCに感謝! コードバトルは気になっていて、見始めたら面白くてほぼDay 0全部コードバトル見てしまったw Award 🥇 Favorite Talks Favorite Booth Favorite Activity Favorite Novelty Closing Award 🥇 今年は完全に参加者枠でゆっくり色々楽しめました。楽しかった・よかった企画・ノベルティ紹介したいです! Favorite Talks 一つに絞れなかったので何個か選びました! fortee.jp 最近エラーハンドリングの設計悩んでいるところあるのでこちら本当に助かりました! typed throw使いまくってもいいと思ったら、koherさんのトークでそれを考え直せるまでの素晴らしいトークでした。 fortee.jp Strict Concurrencyの一歩踏み始まっているからこちらもちょうどよかった内容の一つでした。苦労している部分は確かに 現状の超えてはいけないlayerあるな〜と思って資料もう一回見返して、作戦考える! fortee.jp 脆弱性はみんななんとなく把握していると思いますが、こちら本当によかったです!よくある実装・わかりやすい例がいっぱいあって (資料英語だったのもとてもわかりやすかったし😉)モバイルエンジニアみんな一回見るべきセキュリティトークです! fortee.jp GBAとSwiftはゲーマーとして見るしかないと思ってとても面白かったです!こちらをInspirationで、最近N64のコンパイルの Breakthroughで似ていることできるのかな〜と考え始めてめっちゃよかったトークです! fortee.jp MetricKitは使ったことないので、めっちゃ気になったトーク、その何ms以上じゃないとペイロード入らないとか はとても役に立つ情報でした! Favorite Booth うちわでピッタリ1.8m/sできたら賞品もらえる企画本当に楽しかったです! 来年の企画楽しみにしています! Favorite Activity 夏祭っぽいフェースペイント・ネイルで楽しく遊びました!フェースペイントは会社のロゴカスタムで頼めて最高でした! PRでTwitter置いておきます! #iosdc ペイントは無事に終了致しました。3日間に渡り沢山の方々に描かせて頂きました。お客様の持参される絵柄を一発勝負で描くのはとても刺激的でした。いつもお子様対象なので大人が楽しんでくれたのも良きでした!ありがとうございました✨ #iosdc2024 #iosdcpaint #フェイスペインターミホウ pic.twitter.com/0gaaZmpGqt — フェイスペインター☆ミホウ (@fp_mihoo) 2024年8月24日 Safieのロゴをフェースペイントブースで描いてもらえた〜 1階アートブースにはネイルコーナーがあります。 ネイルをしたら是非 #iosdcnail をつけて投稿してくださいね! #iosdc pic.twitter.com/ZAnFsRBSap — iOSDC Japan (@iosdcjp) August 23, 2024 初ネイルで目覚めたかも! Favorite Novelty iOSDCロゴ入り扇子 暑と戦う夏、扇子が大事な道具になるのでiOSDCロゴ入り扇子は嬉しかったです! SPIDERPLUSさんのAnker充電器 Anker mini小さくて便利!出張先で役に立つ! 食べログさんの靴下 黄色くて可愛いソックスでサンダルじゃない時にはく!w メルカリさんのチェキ ちょっと懐かしいPolaroid写真取れて楽しかったです!ネームタグに入れて可愛さアップできたし! iOSDCネイルシール iOSDCで初ネイル楽しかった上に、娘に大好評!次の週末出かける時につける約束している! Closing 2017から参加してきたiOSDCは今年も本当に大成功でした!来年の開催をもう楽しみにしています! Safieのブースで会いましょう!😉 iOSDC今年まじで最高でした!コンテンツも企画も全部良すぎて明日からiOSDC ロスしかない!💅🎨🍻 また来年会いましょう!!! #iosdc pic.twitter.com/yDVZ8oHApo — Adam Henry (@monolithic_adam) August 24, 2024 モバイルチームは開発する仲間を募集しています! 一緒にiOSDC参加しましょう! open.talentio.com