TECH PLAY

電通総研

電通総研 の技術ブログ

837

はいどーもー! コミュニケーションIT事業部の宮澤響です! 本記事は 電通総研 Advent Calendar 2024 2日目の記事です! 記念すべき1日目である昨日の記事は、小林日菜美さんの「 【Salesforce認定アソシエイト試験】知識0から1ヶ月で合格した話 」でした! こちらは単なる学習方法や受験方法の紹介記事ではなく、試験前後に小林さんが実際に見舞われた(誰にでも起こり得そうな)トラブルとその回避方法についても分かりやすくまとまっている記事ですので、同試験を受験予定の方もそうでない方も、ぜひご一読ください! ということで、本記事では、 Power Automate を用いて、Backlogで特定の条件のチケットが起票・更新されたときにだけSlackに通知する方法をご紹介します! はじめに まずやってみる SlackへのPower Platform Connectorsの追加 Power Automateワークフローの作成 BacklogへのWebhookの追加 Power Automateワークフローの修正 実行結果 おまけ(Teamsへの通知) おわりに はじめに ああ…Backlogで特定の条件のチケットが起票・更新されたときにだけ通知がほしい…! そう思ったこと、ありませんか? ありますよね? 私はあります! ですが、以下の公式ドキュメントに記載されている方法では、対象チケットの条件を指定することができず、プロジェクト内のあらゆるチケットの起票・更新が通知されてしまいます。 BacklogのSlack連携 BacklogのMicrosoft Teams連携 そのため、例えば「自分が担当者に設定されたチケット」や「優先度が高のチケット」のみを対象としたいケースであっても、Backlogの公式連携機能では実現できません。 とはいえ、上記のようなケースは少なくないと考えています。 そこで、今回は、Power Automateを利用して、上記のようなケースへの対応策をご紹介します。 まずやってみる 大まかな実現方針は以下のとおりです。 最終的に、 Backlog -> Power Automate -> Slack の処理フローを実現します。 Backlog Webhookを利用して、BacklogからPower Automateにチケット情報を送信する Power Automateのワークフローで条件分岐を設定することで、特定の条件のチケット情報のみをフィルタリングする Power Platform Connectorsを利用して、Power AutomateからSlackにメッセージを送信する なお、以降の説明は、設定の都合上、上記3項目の逆順で記載します。 SlackへのPower Platform Connectorsの追加 まずはSlackのチャンネルにPower Platform Connectorsを追加します。 (私自身は「チャネル」表記派ですが、Slackは「チャンネル」表記、Power AutomateやTeamsは「チャネル」表記のようですので、本記事ではそれらに合わせて表記します。) Power Platform Connectorsとは、簡単に言えば、Power Automateをはじめとする Microsoft 社のローコードツールと、Slackなどの外部アプリケーションとを連携させるためのツールです。 なお、 ワークスペース にPower Platform Connectorsがインストールされていない場合は、 Slack ワークスペースにアプリを追加する を参考に、事前にインストールする必要があります。 Power Platform Connectorsの追加 チャンネル右上の「︙」から「チャンネル詳細を開く」を押下します。 「インテグレーション」タブにある「アプリを追加する」を押下します。 「 Microsoft Power Platform Connectors」を探し、「追加」を押下します。 Power Automateワークフローの作成 次に、Power Automateでワークフローを作成します。 なお、このステップではワークフローの大枠を作成するのみであり、詳細な条件などは後続のステップで作成します。 トリガーの追加 「要求」コネクタの「HTTP 要求の受信時」というトリガーを追加します。 少々見つけにくいトリガーなのですが、「HTTP」などと検索すればヒットするかなと思います。 設定が必要なパラメーターは以下のとおりです。 フローをトリガーできるユーザー: 誰でも ※ここでは 誰でも を選択していますが、必要に応じて、セキュリティを考慮したアクセス制限を行うことを推奨します。 アクションの追加 「Slack」コネクタの「メッセージの投稿 (V2)」というアクションを追加します。 なお、対象となるSlack ワークスペース に対して、これまでに一度もPower Automateを連携させたことがない場合には、こちらのアクションを設定する際に、併せて「接続」も新規作成します。(参考: Power Automate での接続の管理 ) 設定が必要なパラメーターは以下のとおりです。 チャネル名:通知を送信したいチャンネル(プライベートチャンネルの場合はカスタム値を入力) メッセージ テキスト:任意(例: チケットきたでー。 ) ワークフローの保存 ここまでの設定で、ワークフローを一旦保存します。 すると、このタイミングで「HTTP 要求の受信時」トリガーの名称が何故か「manual」に変化し、「HTTP URL」に値が設定されます。 「HTTP URL」は後続のステップで利用しますので、「URLのコピー」ボタンでコピーしておいてください。 ワークフローの有効化 「フローの管理」画面に戻り、保存したワークフローを有効化します。 画面上部の「オンにする」ボタンを押下します。 BacklogへのWebhookの追加 続いて、Backlog側の設定を行います。 Webhookの追加 対象となるBacklogプロジェクトの「プロジェクト設定」から「インテグレーション」を選択し、「Webhook」の「設定」ボタンを押下します。 「Webhookを追加する」ボタンを押下します。 Webhookの設定値を入力します。 今回は、以下のように設定します。 Webhook名:任意(例: 宮澤テスト ) Webhook URL:先ほどコピーした「HTTP URL」 通知するイベント: 課題の追加 、 課題の更新 デフォルト(「課題の追加」が選択された状態)のまま、実行テスト欄の「実行」ボタンを押下します。 ダイアログが表示されるので、「OK」ボタンを押下します。 ここまでの設定に不備がなければ、Slackの指定したチャンネルに以下のような通知が送信されるはずです。 「Webhookを追加する」ボタンを押下します。 リク エス ト スキーマ の取得 Webhook一覧に戻り、「送信履歴」タブを押下します。 先ほど実行ボタンを押下した時刻の項目の「すべて表示」を押下します。 最下行の JSON (リク エス ト)をコピーします。 Power Automateワークフローの修正 再びPower Automate側に戻ってきます。 リク エス ト スキーマ の生成 「manual」(トリガー)の「要求本文の JSON スキーマ 」の「サンプルの ペイロード を使用して スキーマ を生成する」を押下し、先ほどコピーした JSON を貼り付けます。 「完了」ボタンを押下します。 すると、「要求本文の JSON スキーマ 」が自動で生成されます。 後続のステップで担当者のユーザーIDを利用するため、 assignee の {} 内に以下の JSON を挿入します。 " type ": " object ", " properties ": { " userId ": { " type ": " string " } } 条件の指定 ここでは、「自分が担当者に設定されていること」を条件としたいと思います。 「manual」と「メッセージの投稿 (V2)」の間に、「Control」コネクタの「条件」というアクションを追加します。 そのまま検索してもヒットしない場合には、ランタイムを「組み込み」に絞った状態で検索するとヒットしやすいかなと思います。 設定が必要なパラメーターは以下のとおりです。 Condition expression:(後続のステップで詳しく説明します。) 左側の「値を選択してください」にカーソルを合わせた際に表示される雷マークのボタンを押下します。 「See more」を押下します。 assignee や category の上にある userId を押下します。 userId は複数存在するため、上記位置の userId を選択するようにしてください。 右側の「値を選択してください」欄に、自分のBacklogのユーザーIDを入力します。 なお、ユーザーIDはBacklogの個人設定画面から確認可能です。 設定内容を確認します。 ミスなく設定できていれば、以下のような状態となっているはずです。 特に、Code viewの7行目が @triggerBody()?['content']?['assignee']?['userId'] となっているかを確認しておいてください。 (異なる userId を選択してしまった場合にはこちらの値が異なって表示されているかと思います。) 「メッセージの投稿 (V2)」を「True」ブロックの中に移動します。 これで全ての設定は完了です! 実行結果 自分を担当者に設定したチケットを起票したところ、無事に通知が届きました! なお、 スクリーンショット などは省略しますが、具体的な通知条件の一例については以下のとおりです。 (通知するイベント: 課題をまとめて更新 については、リク エス ト スキーマ の形式が大きく異なるため、ここまでの設定では対応できていません。) 条件 通知の有無 「担当者:自分」のチケットを起票した場合 あり 「担当者:自分以外」のチケットを起票した場合 なし 「担当者:自分」のチケットの内容(詳細、種別、状態、など)を更新した場合 あり 「担当者:自分以外」のチケットの内容(詳細、種別、状態、など)を更新した場合 なし 「担当者:自分」のチケットを「担当者:自分以外」に更新した場合 なし 「担当者:自分以外」のチケットを「担当者:自分」に更新した場合 あり おまけ(Teamsへの通知) 「 Microsoft Teams」コネクタの「チャットまたはチャネルでメッセージを投稿する」というアクションを利用することで、Teamsに通知を送ることも可能です。 おわりに 本記事では、Power Automateを用いて、Backlogで特定の条件のチケットが起票・更新されたときにだけSlackに通知する方法をご紹介しました。 工夫した点、というほどでもないですが、ポイントとしては、 Power Automateワークフローの修正 のところで assignee の情報を追記したように、フィルタリングに利用したい条件に応じてリク エス ト スキーマ を修正する点が挙げられるかなと思います。 なお、私自身も、現在携わっている案件において、実際にこちらの方法を個人的に利用しています。 (以下のようにメンションとリンクを付与した上で通知させています。) (余談ですが語尾は「ぇー」「しー」「でー」「えふー」「じぇー」「ぉー」「ゅー」「わい」の中からランダムに選択されます。) さて、 電通 総研 Advent Calendar 2024 3日目となる明日の記事は、井手稚菜さんの「 電通 総研IT 文系出身 新卒3年目社員の働き方紹介」です! お楽しみに! 最後までお読みいただき、本当にありがとうございました! 私たちは同じ事業部で共に働いていただける仲間を募集しています! みなさまのご応募、お待ちしています! 株式会社 電通総研 新卒採用サイト <電通×IT>電通グループ基幹システムプロジェクトマネージャー <電通×IT>顧客DX案件プロジェクトマネージャー 政府・自治体向けシステム構築におけるプロジェクトマネージャー/リーダー デジタルマーケティング領域におけるプロジェクトマネージャー/リーダー 新規事業開発領域におけるプロジェクトマネージャー/リーダー エンタープライズ向けDX推進リーダー/エンジニア◆電通グループ協業◆提案活動~開発・運用まで <電通×IT>クラウドアーキテクト <電通×IT>アプリケーションアーキテクト 執筆: @miyazawa.hibiki 、レビュー: @nakamura.toshihiro ( Shodo で執筆されました )
こんにちは!HCM事業部の小林です。 本記事は 電通総研 Advent Calendar 2024 初日の記事となります。 今回は「 Salesforce 」という言葉しか知らなかった筆者が、1か月勉強して Salesforce 認定アソシエイト試験に合格した話です。勉強方法や必要な勉強時間、役に立った過去問などを紹介します。 実は試験を申し込んだ当初は何も分かっておらず、試験当日も100%の力を発揮することができませんでした。 同じように迷う方が少しでも減るように、自分の体験をもとに申込方法と受験の注意点を詳細にお伝えします。 これから受験する人はぜひ最後までご覧いただきたいです。 Salesforce認定アソシエイト試験とは? 試験の勉強方法 Trailmix(トレイルミックス)を進める 過去問を2周する 単語帳をつくる 試験の勉強時間 試験の申込方法 試験直前までにやるべき準備 ①コンピューターの技術要件を確認する ②環境のテストをする ③Respondus Lockdown Browserをインストールする ④生体認証プロファイルを作成する ①~④が試験開始時間の24時間前に完了しなかった場合 準備が必要なかったこと 試験後にあったトラブル 試験結果 おわりに Salesforce 認定アソシエイト試験とは? ひとことで言うと、 Salesforce の資格の中で一番初心者向けの資格 です。 試験の概要は以下のとおりです。 ・試験時間 :70分 ・問題形式 :多肢選択/複数選択方式の40問 ・合格点  :62%以上(32問以上正解で合格) ・受験料  :10,000 円(税抜) ・受験会場 :指定の試験会場または自宅 ・出題範囲 : Salesforce エコシステム(32%)        ナビゲーション(28%)        データモデル(25%)        レポートと ダッシュ ボード(15%) ・受験対象者: Salesforce の実務経験が0〜6ヶ月の人 (※2024年11月現在の情報です。最新情報は Salesforce 認定アソシエイト受験ガイド をご確認ください。) この試験は Salesforce の試験で唯一、 再受験が無料 でできます!たとえ不合格になっても再チャレンジしやすいのが魅力です。 試験の勉強方法 筆者が実施した勉強方法は主に3つです。 Trailmix( トレイルミックス )を進める Trailmixは、 Salesforce の学習サイト「Trailhead」の機能の1つで、いくつかのコンテンツを集めてつくるカリキュラムのことです。アソシエイト勉強用のTrailmixが用意されているので、それを最後まで取り組みました。 利用するには Salesforce のアカウント登録が必要です。 https://trailhead.salesforce.com/ja/users/strailhead/trailmixes/prepare-for-your-salesforce-certified-associate-credential 過去問を2周する noteで過去問を100問掲載している記事を見つけたので問題を2周しました。Trailmixだとあまり出てこなかった単語についても知ることができたのでやってよかったです。 単語帳をつくる Trailmixや過去問を進めていて分からなかった単語は スプレッドシート に記入しました。試験が近づいてきたら単語を隠しながら勉強していました。 試験の勉強時間 試験勉強に費やした1か月間はだいたいこのようなスケジュールでした。 期間 勉強期間 試験1か月前~2週間前 1~2時間 試験1週間前 2~3時間 直前の土日 5~6時間 もともと Salesforce に触ったことがある人や勉強に時間が取れる人は、これより少ない勉強時間でも合格できる気がします。 試験の申込方法 受験方法は、会場に行って試験を受ける「オフライン受験」と自宅から受ける「オンライン受験」があります。 筆者はオンライン受験で申し込みましたが、ここで注意が必要です。 試験の予約にはWebassessorというサイトを利用するのですが、本当は日本語のアカウントで登録すべきところを英語のアカウントで登録していました。 その結果、試験では問題文が全て英語になってしまい、英語が大の苦手な筆者は一度絶望しかけました。試験中にダメ元で日本語にできないか聞いてみましたが無理でした。 もしこの記事を読んでいる時点ですでに英語のアカウントで登録してしまって、キャンセル期限が過ぎている人は気合で頑張りましょう。 後から調べてみると、日本語のアカウントを登録する画面のURLにはsalesforcejpと書いてあることが分かりました。これから登録する人はまずURLを確認してください。 この先もオンライン試験で起こった/起こりうるトラブルを書いていますが、このようなトラブルが怖い人は試験会場での受験を推奨します、、 試験直前までにやるべき準備 オンライン受験を選択した方はいくつか事前準備が必要です。 ①コンピューターの技術要件を確認する パソコンの空き容量や管理者権限、ブラウザのバージョンなどの条件を満たさないと受験できません。 詳しくは Salesforce 公式のオンライン監督試験ガイドをご確認ください。 Mac OS 版 Windows OS 版 ②環境のテストをする 試験ではマイクとウェブカメラの両方が同時に機能する環境が必要です。以下のサイトで確認できます。 https://www.kryterion.com/systemcheck/ ③Respondus Lockdown Browserをインストールする Respondus Lockdown Browserは、試験中にブラウザや他のソフトウェアにアクセスできなくするツールです。 試験で使うPCの管理者権限がない場合、インストールできない可能性があります。インストールする前に確認しておきましょう。 また、公式サイトには「Respondus Lockdown Browser のダウンロードが未完了の場合は、ポップアップウインドウが表示され、ダウンロードが必要であることが分かります。」と書いてありましたが、筆者のPCはダウンロードが完了している場合でもポップアップは消えませんでした。 同じ事象で困っている人の参考になれば幸いです。 ④生体認証プロファイルを作成する 顔認証をして本人確認をするステップです。 画面の指示に従いながら何回か写真を撮ります。撮影中は眼鏡を外すようにしてください。 「We have successfully created your biometric profile (バイオトリックプロファイルの作成に成功しました)」の表示がされたら完了です。 ①~④が試験開始時間の24時間前に完了しなかった場合 これらの準備に時間がかかって試験に間に合わなそうなときや体調不良のときは、試験開始時間の24時間前までならスケジュールの変更・キャンセルが可能です。それ以降の場合は費用が発生するのでご注意ください。 準備が必要なかったこと 前に Salesforce の試験を受けたことがある人に準備することを聞いたものの、結局必要なかったことを紹介します。 眼鏡を外す 以前は眼鏡をしていると外すように指示があったみたいですが、今回は眼鏡をしながら受験をしても大丈夫でした。 身分証明のためのパスポートを用意する 以前は試験前の事前チェックとして、試験官に身分証明書を提示する工程がありましたが、結局身分証明書を提示することはありませんでした。 試験を受ける部屋から物をなくす 以前は受験場所に物がないことを証明するためにカメラで見せなければならなかったようで、知人はお風呂やトイレで受験していました。 ただ現在は、試験官と話すこともなく周囲の確認もありませんでした。 セキュリティソフトをオフにする 事前にオフにせず試験日を迎えましたが、試験直前にオフにしますか?というポップアップが出たのでオフにしてから試験に進みました。 試験後にあったトラブル Salesforce の試験は終了後すぐに結果が表示されるはずですが、試験結果を見てみると試験を受けていないことになっていました。 自分の不手際で試験の説明も全て英語だったことから、自分のミスなのか分からず問い合わせることにしました。 返信が来ましたが、日本の Salesforce 窓口に問い合わせていたみたいで、 アメリ カ本部に問い合わせるよう案内が来ました。 丁寧に問い合わせ方法をご説明いただき、 アメリ カ本部に問い合わせたところ、試験データの送信中にトラブルがあったとのこと。トラブルを修正して試験結果を反映させてくれました! 試験結果 本当にいろいろとありましたが無事に合格し、初めて Salesforce の資格を持つことができました! メールには各分野の正答率も書いてありました。分からない英単語がたくさんあった中でこのくらいとれていればまあまあなのでは?と思っています。 <メールの一部> おわりに いろいろとトラブル続きの受験になってしまいましたが、この際 Salesforce で頻繁に使われる英語くらいは勉強してみようと思うようになりました。 ただ筆者としては試験前後のトラブルは誰にも起こってほしくないので、この記事を読んでから試験に申し込む方は必ず「日本語のアカウント」で申し込んでください。 そしてもし試験後に受験結果がこなくても諦めないでお問い合わせを送ってください。 今後も Salesforce を勉強して使いこなせるようになりたいと思っているので、次回は アドミニストレーター 試験を受験したいです。(もちろん日本語で) 筆者が所属する事業部では様々な 中途採用 のポジションを募集しています! 職種ごとの詳しい募集要項は以下のリンクからご覧ください。 私たちは一緒に働いてくれる仲間を募集しています! 新卒採用ページ 【オープンポジション】自社パッケージ製品の導入プロジェクトマネージャ/リーダ 統合HCMソリューション導入におけるクラウドチームリーダー (東京)統合HCMソリューション 導入プロジェクトマネージャー/リーダー (名古屋)統合HCMソリューション 導入プロジェクトマネージャー/リーダー (大阪)統合HCMソリューション  導入プロジェクトマネージャー/リーダー 執筆: @kobayashi.hinami 、レビュー: @kinjo.ryuki ( Shodo で執筆されました )
こんにちは、XI本部プロダクト イノベーション センターの瀧川亮弘です。 現在行っているWebサイトの運用において、ヘッドレス CMS の導入を検討しています。 本記事では、ヘッドレス CMS の選定で調査したことを共有します。 ヘッドレス CMS とは ヘッドレス CMS とは、フロントエンドを持たない、 CMS (コンテンツ管理システム)のことです。 ここで言うコンテンツとは、ウェブサイトやアプリで使用される、テキスト、画像、動画、音声、ドキュメントなどのデジタルデータを指します。 WordPress のような従来型の CMS では、コンテンツの管理と表示が一体化しています。 管理画面からフロントエンド含めてオールインワンでウェブサイト構築が行えるという利便性がある一方、フロントエンドの柔軟性に欠けるという問題があります。 そこで登場するのが ヘッドレス CMS です。 ヘッドレス CMS は、コンテンツの管理に特化し、コンテンツの表示(フロントエンド)は API を通じて外部に任せます。 これには以下のメリットがあります。 フロントエンドの技術やデザインの柔軟性が向上する。 コンテンツを一元管理し、複数のプラットフォーム(ウェブ、モバイルアプリ、 デジタルサイネージ など)に効率的に配信できる。 上記の理由より、ヘッドレス CMS は近年とても注目されています。 アーキテクチャ 現在、運用しているWebサイトの構成図です。 黄色の部分がヘッドレス CMS を導入することで追加となる部分です。 現在、画像やテキストなどのコンテンツは、 ソースコード と一緒に GitHub で管理しています。 ヘッドレス CMS を導入することで、コンテンツの管理を GUI 上で行えるようにします。 これによりヘッドレス CMS の サブスクリプション コストや運用の手間はかかるようになりますが、エンジニアでなくても画像の差し替えなどが容易に行えるようになります。 技術選定 上記のような静的サイトを高速で配信する構成を Jamstack と呼びます。 Jamstackのコミュニティが公開している、 CMS の満足度とシェアに関するレポートを参考にしました。 縦軸に満足度、横軸にシェアを取るグラフに各種 CMS がプロットされています。 https://jamstack.org/survey/2022/#content-management-systems 満足度の高さ、シェアの高さより、 5. Strapi 6. Sanity について、さらに深く調査することとしました。上図の赤枠で囲っている CMS です。 他の CMS を候補から外した理由については、 ネガティブキャンペーン になってしまうため、ここでは割愛します。 Strapi と Sanity StrapiとSanityについて、実際に触って調査を進めました。 共通の強み 両者に共通する強みは以下のとおりです。 シェアが高く、かつコミュニティも活発なため、今後も継続的な機能改修やサポートが期待できる。 プラグイン のエコシステムが整備されており、機能の拡張性が高い。 多言語対応の言語数に制限がない。(グローバル展開の要件があり、特に重要視) 違いの比較 両者の違いを比較表にまとめます。 Strapi Sanity 強み - 完全に オープンソース の CMS であり、セルフ ホスティング が可能なため、インフラ環境の自由度が高い。 - まずは、PaaS(Strapi Cloud)として利用し、インフラ要件が複雑化してきた場合、セルフ ホスティング に切り替えるという運用も可能。 - UIのデザイン性が高く使いやすい。ドキュメントも見やすい。 - ライブコラボレーション機能により、 Google Docs のように複数ユーザーで同時編集が可能。 - コストを低く抑えられる。 弱み - セルフ ホスティング の場合、インフラの構築・運用の手間がかかる。 - PaaSの場合、Strapiアプリケーション管理用の GitHub またはGitLabの利用が必須。 - UIのデザイン性に劣る。ドキュメントもキャプチャなどが少なく、ややわかりづらい。(個人の感想です) ホスティング PaaS、またはセルフ ホスティング https://strapi.io/integrations/aws SaaS ※Sanity Studio(フロント部分)のみセルフ ホスティング することも可能。 https://www.sanity.io/docs/deployment リリース年 2016年 2017年 国 フランス アメリ カ 管理画面のUI また、一概には言えませんが、傾向としてSanityの方がコストは抑えられそうです。 StrapiだとTeam($499/month)プランからサポートされる、複数環境やスケジューリング機能ですが、Sanityだと Growth ($15/month)プランからサポートされています。 コンテンツ管理ユーザーの人数制限もSanityの方が緩いです。 逆にバックアップ機能は、StrapiだとPro($99/month)プランからですが、SanityだとEnterpriseプランからといったこともあるため、要件によってはStrapiの方がコストを抑えられる可能性もあります。 結論 StrapiもSanityも非常にイケているサービスだと感じました。 要件と照らし合わせ、さらに技術選定の検討を進めます。 最後までご覧いただきありがとうございました。 私たちは一緒に働いてくれる仲間を募集しています! 株式会社 電通総研 新卒採用サイト 執筆: @takigawa.akihiro 、レビュー: Ishizawa Kento (@kent) ( Shodo で執筆されました )
こんにちは、 電通 総研IT第2ビジネスユニット19の奥村です。 現在はOutSystemsというローコード開発プラットフォームを使って、製造系企業の システム開発 を担当しています。 ※ローコード開発とは、「必要最小限の ソースコード 開発でソフトウェア・ アプリ開発 を行う手法」のことです。 この記事では、入社してから現在までの仕事内容についてざっくりと説明します。 この記事が、IT業界に興味のある方の参考になれば幸いです。 自己紹介 2022年に新卒入社して3年目になります。 大学では経済学を専攻していて、ITやプログラミングといったものとは無縁でした。 私がIT業界を目指した理由は、手に職をつけたい、仕事の成果を形として見たいと考えていたからです。(実際にプログラミングして形になると嬉しいです) いろいろ探した結果、IT業界にたどり着きました。 そのため、IT知識ゼロで入社しました。 入社後 入社後は4月~9月の間、ビジネス研修とプログラミング研修を受けます。 ビジネス研修では社会人として必要なスキルを学び、プログラミング研修では基礎の基礎から始まり最終的には Java という言語を使ってシステムを開発する演習を行いました。 IT知識ゼロだったため最初は正直、ついていくのに必死でしたが講師の方や同期の人に質問したりしながら何とかついていきました。 後半になるとある程度、一人でプログラミングできるようになるので安心してください。 配属後 研修後は、OutSystemsを使って開発を行う部署に配属になりました。(ローコード開発に興味があったので希望を出していました) 配属後はまず、OutSystemsの認定資格の取得を目標に学習しました。 OutSystemsの公式HPにト レーニン グが用意されているので、動画やドキュメントを活用してOutSystemsの基本的な使い方を身につけます。大体1ヶ月ほど学習することで認定資格を取得することが出来ます。(やはりローコード開発なだけあり、 Java よりも実装が簡単でIT経験ゼロの身からすると、とてもやりやすかったです) そして、認定資格取得後は実際の業務に参加します。 業務について 現在は製造系企業の費用や予算、人員などを入力する生産管理システムのアプリを開発しています。 システムを利用されるお客様の利益を最大化するうえで、生産管理は非常に重要なシステムの位置づけとなります。 このプロジェクトではお客様の要望として Excel のような操作感を実現する必要があり、OutsystemsのForge(フォージ)のDataGrid(データグリッド)を使用しました。 ※Forge(フォージ)とは、OutSystems上で公開されている共通部品のようなもので、誰でも使用可能です。 Forgeを有効活用することでさらに開発効率や品質向上が期待できます。 DataGridを使用することで、一から実装しなくても表上で入力や編集、並べ替えなどの機能を使えるようになり、素早く実装を行うことができました。Forgeを使っての実装はOutSystemsならではだと思いました。 ↓DataGridを使用した画面です。データを入れただけでこのような見た目になります。(すごく便利です) また、規模の小さい アプリ開発 を一人で担当する機会があったのですが、数週間で実装しお客様に実際に使用していただくことができ、ローコード開発特有のスピード感を改めて感じました。 最後に 今回は入社してからの仕事内容についてざっくりと書きました。 現在は比較的簡単な機能を実装していますが、今後はより複雑な機能にも挑戦していきたいと思います。 Outsystemsは一般的なプログラミング開発と比べると、プログラミング量も少なく簡単に システム開発 ができますが Outsystems特有の知識や論理的に考える ロジカルシンキング などの学習が必要になります。( ロジカルシンキング はまだまだ課題です、、、) ですが、考えたものが形になるまでが早く、実装していて楽しいのが魅力だと思います。 私はIT知識ゼロで入社しましたが、研修を通して知識をつけ、少しずつできることを広げていきました。 働く上で楽しいと思えるのが一番成長できると思います。 最後までお読みいただきありがとうございます。 採用ページ 執筆: @okumura.seiya 、レビュー: @nagamatsu.yuji ( Shodo で執筆されました )
こんにちは、コーポレート本部 サイバーセキュリティ推進部 セキュアシステムデザイングループの福山です。 脆弱性 が日々報告される中、迅速かつ適切な対応を行うためには、効果的な トリアージ が欠かせません。 今回は、 脆弱性 対応を行う組織向けに、効率的な対応プロセスの進め方についてご紹介します。 はじめに FutureVulsについて SSVCを活用したリスク評価の概要 FutureVulsによるリスク評価 I. 事前準備 リスク評価対象とするサンプルシステムの概要 資産の登録 SSVCの設定 Exposure(インターネット露出レベル) Human Impact(攻撃された際の業務影響) 対応期限の設定 II. スキャンの実施から対応方針を決めるまで STEP1: スキャン STEP2: トリアージ SSVCによる評価 STEP3:調査・対応判断 まとめ はじめに 2024年7月、 IPA より「 脆弱性 対応におけるリスク評価手法のまとめ」が公開されました。 下記に公開資料のPDFと資料のポイントが掲載されています。 https://www.ipa.go.jp/jinzai/ics/core_human_resource/final_project/2024/risk-assessment-methods.html まずリスク評価とは、「脅威」「 脆弱性 」「資産」の3要素を考慮して実施し、その結果をもとに優先度をつけることが推奨とされています。 脆弱性 対応におけるリスク評価も同様で、リスクの3要素を加味しつつ、運用負荷も考慮したリスク評価が望ましいです。 上記資料では、SSVC(Stakeholder-Specific Vulnerability Categorization)を活用したリスク評価手法が有効とされています。 そこで本記事では、SSVCを活用したリスク評価をツールを用いて実現する流れをご説明します。 FutureVulsについて 今回は 脆弱性 管理ツールFutureVulsを使ってみたいと思います。 FutureVulsは、 OSS 脆弱性 スキャナのVulsをベースに、 脆弱性 管理を実施できる機能を備えた クラウド サービスです。 参考: https://vuls.biz/ FutureVulsのような 脆弱性 管理ツールを導入することで得られるメリットは大きく次の3つです。 脆弱性 情報の収集を手動で行うことによるチェック漏れや、 脆弱性 対応への対応漏れを防止できる。 脆弱性 情報を一元管理できる。 脆弱性 管理における一連の作業( 脆弱性 のレポート、対応判断等)を自動化することで作業負担を軽減できる。 3の「対応判断」を自動化する機能としてSSVCがあり、リスク評価で活用します。 SSVCを活用したリスク評価の概要 IPA によるとSSVCを活用したリスク評価は、下図の通りとなっています。 本当に対応が必要な 脆弱性 を抽出し、対応優先度を決定します。 SSVC を活用したリスク評価例の概要は、図 2-3 の通りである。 引用元:「 脆弱性対応におけるリスク評価手法のまとめ 」(p.29) 0次評価では、緊急性の高い即時対応を求められる S ランク相当の 脆弱性 情報を評価する。 0次評価の概要は、図 2-4 のとおり。 引用元:「 脆弱性対応におけるリスク評価手法のまとめ 」(p.31) SSVCの具体的な出力結果とランクの対応としては、図2-6のとおりである。 ImmediateがSランク、Out-of-cycleがAランク、ScheduledがBランク、DeferがCランク判定となる。 引用元:「 脆弱性対応におけるリスク評価手法のまとめ 」(p.33) ここでは各用語について説明します。 用語 説明 KEV KEV(Known Exploited Vulnerabilities catalog)は、米国サイバーセキュリティ・インフラセキュリティ庁( CISA )が公開している既知の悪用された 脆弱性 カタログのこと。KEVには、実際に悪用されたことが確認された 脆弱性 の情報が集められており、 脆弱性 が最初に発見された時期や、どのように悪用されているかなどの詳細が含まれている。 JPCERT/CC 注意喚起 JPCERTコーディネーションセンター ( JPCERT/CC )によって、日本国内における深刻かつ影響範囲の広い 脆弱性 などに関する情報が発信される。 CVSS CVSS(Common Vulnerability Scoring System) は、 脆弱性 の深刻度 を評価するための標準的なスコアリングシステム。本記事ではCVSS Base Scoreについて取り上げる。以下のとおり、スコアの範囲によって深刻度が定められている。 ・緊急: 9.0~10.0 ・重要: 7.0~8.9 ・警告: 4.0~6.9 ・注意: 0.1~3.9 ・なし: 0.0 EPSS EPSS(Exploit Prediction Scoring System)とは、Firstが提唱したもので、 脆弱性 が悪用される可能性 を示す指標。次の2つの情報を提供しており、本記事ではEPSS Probabilityについて取り上げる。 ①EPSS Probability: EPSSスコアのことで、今後30日以内に 脆弱性 が悪用される確率 ②EPSS Percentile: 脆弱性 全体の中で、悪用される可能性がどの程度高いかを示す順位(上位何%に位置するか) SSVC SSVCは 脆弱性 の対応優先度 を決めるための指標のことで、4つの入力を基に、緊急度を4段階評価で出力する仕組み。 【入力】  (1)Exploitation: 攻撃コードの公開有無や悪用レベル  (2)Exposure: インターネット露出レベル  (3)Utility Automatable: 攻撃の自動化  (4)Human Impact: 攻撃された際の業務影響 【出力】 「Immediate」: 全リソースを集中し必要に応じて組織の通常業務を停止して可能な限り迅速に対応する 「Out_of_cycle」: 通常よりも迅速に行動し、計画外の機会に緩和策または修復策を実施する 「Scheduled」: 定期メンテナンス時に対応する 「Differ」: 現時点では対応しない 評価の流れについて、細かく図に落とし込んでみました。 IPA によるSSVCを活用したリスク評価では、下図のように0次評価と1次評価は独立しています。 なお、SSVCは「脅威」「 脆弱性 」「資産」の3要素が全て考慮されています。 0次評価=脅威( CISA KEV、 JPCERT/CC 注意喚起) 1次評価=脅威(EPSS) × 脆弱性 (CVSS) 2次評価=脅威 × 脆弱性 × 資産(SSVC) ここまで IPA が提唱する評価手法を紹介しました。 これから紹介するFutureVulsのようなツールを用いることで、SSVCによる評価を自動算出できれば、リスクの3要素全てが網羅されたSSVC一本でのリスク評価が実現できると捉えています。 FutureVulsによるリスク評価 FutureVulsを運用する上で発生する作業には、「各システムの管理者が行う作業」と「組織のFutureVuls管理者が行う作業」の2種類があります。 各システムの管理者:実際に 脆弱性 対応を実施するプロジェクトチームのこと 組織のFutureVuls管理者:CSIRTなど組織の 脆弱性 管理を主導するチームのこと 後述の作業が発生する場面においては、上記のどちらが対応する作業かを色を分けて示しています。 I. 事前準備 今回は、サンプルシステムとして AWS 上の仮想Webシステムを想定して評価を行います。 リスク評価対象とするサンプルシステムの概要 外部のユーザーが利用する簡易Web受付サイト AWS 上に構築されている小規模なシステムで、 OSS を利用したWeb3層構造を想定。 各サーバは全てEC2 インスタンス であるため、OS以上はユーザ側でメンテナンスが発生する。 Webサーバの前段でALB等による認証を行わない。 わざと 脆弱性 が検出されるように、2年ほど前にリリースされた古いソフトウェアバージョンで構成(※実際には攻撃者によって 脆弱性 を突かれる可能性があるため、利用を避けるべきバージョン)。 システム構成 ソフトウェア構成 - Webサーバ - NGINX 1.23.2 - OpenSSL 3.0.6 - APサーバ - Python 3.11.0 - Flask 2.2.2 - uWSGI 2.0.21 - OpenSSL 3.0.6 - DBサーバ - MySQL 8.0.31 - OpenSSL 3.0.6 資産の登録 スキャン方法については、「 CPEスキャン 」という擬似サーバ上にソフトウェアを CPE 形式で登録し、 脆弱性 スキャンできる便利な機能があります。 CPE スキャンで実際のシステムにスキャナを導入する必要はありませんので、ちょっとした検証をする際に役に立ちます。 登録方法としては下図のように、ベンダー名やソフトウェア名を入力すると CPE の候補が表示されるため、登録したい CPE を選択し、バージョン情報を選択するだけで完了します。 ただし、OSの 脆弱性 も検出したいといった場合には、実際にサーバを構築し、 OSS をソースからインストールした上で、「 スキャナ 」をインストールする必要がありますので注意が必要です。 なおDBサーバについては、マネージドサービスであるRDSを例にあげると、「マイナーバージョンの自動アップグレード」を有効化している場合には自動パッチ適用が行われるため、スキャン対象から除外して問題ないと考えます。 参考: https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/USER_UpgradeDBInstance.Upgrading.html#USER_UpgradeDBInstance.Upgrading.AutoMinorVersionUpgrades 今回はEC2 インスタンス に MySQL をインストールしており、ユーザー側でパッチ適用が必要なため、スキャン対象とします。 SSVCの設定 Exploitaion(攻撃コードの公開有無や悪用レベル)とUtility Automatable(攻撃の自動化)は自動出力されるため、Exposure(インターネット露出レベル)、Human Impact(攻撃された際の業務影響)の2つを手動で設定します。 Exposure(インターネット露出レベル) Exposureについては、技術的な判断が必要です。 設定基準については、FutureVulsの記事を参考にしました。 SSVCのExposureとは、「対象システムがインターネットに露出しているレベル」です。対象システムのインターネット露出度に応じて以下の3段階の中から選択します。説明欄には決定のための具体例を記載しています。 引用元:「 インターネット露出サーバの自動特定とSSVC Exposure設定ガイド 」 Webサーバ :前段でALB等による認証はしておらず、インターネットから直接アクセス可能なため、「Open」と判断します。 APサーバ:パブリックIPを保持しておらず、一見controlledと判断してしまいそうになります。 しかしながら実質的な IPアドレス 制限がなく、インターネットからのアクセス経路があるため、こちらも「Open」とします。 DBサーバ:APサーバからのみアクセス可能であり、インターネットに直接面していないため、「Controlled」と判断します。 Human Impact(攻撃された際の業務影響) Human Impactの設定基準については、 IPA の記事を参考にしました。 「Human Impact」 影響の大きさとして、安全性の影響と業務遂行への影響の両面から評価する。安全性の影響としては、「None / Minor / Major / Hazardous / Catastrophic」の五段階で評価する(表C-5)。業務遂行への影響としては、「None / Degraded / Crippled / MEF Failure / Mission Failure」の五段階で評価する(表C-6)。最終的に、「HumanImpact」は安全性の影響と業務遂行への影響の評価を組み合わせて、決定木の選択項目として「Low / Medium / High / Very High」の4種類から評価される(表C-7)。 引用元:「 脆弱性対応におけるリスク評価手法のまとめ 」(p.93 - p.95) 脆弱性 の種類によってはWeb/APサーバの 脆弱性 を突かれることによって、DBに保存されている機密情報が漏洩するケースも考えられます。 よってHuman Impactについてはシステム単位で検討することにします。 安全性の影響:機密情報が漏洩した場合、集団に対する精神的または 心理的 な損害が発生する恐れがあるため、「Major」とします。 業務遂行への影響:機密情報が漏洩した場合、サービスの重要度によっては、複数または全てのミッションに障害を及ぼし、組織のミッションが果たせなくなる可能性があります。今回のWeb受付システムの場合では、組織のミッション達成が低下するレベルの影響と判断し、「MEF Failure」としておきます。 Human Impact:Major × MEF Failure = High SSVCの入力値をまとめると以下の通りとなりました。 サーバ名 Exposure Human Impact Webサーバ Open High APサーバ Open High DBサーバ Controlled High ここでSSVCの ロール設定 という機能を使うことで、サーバ別にSSVCの設定を作成することができます。 ロールを作成し、各サーバに紐づけることによって設定が完了します。 対応期限の設定 FutureVulsに登録されている全グループの設定を管理する「オーガニゼーション設定」と呼ばれる画面では、SSVCのレベルに応じた対応期限を設定できます。 参考: https://help.vuls.biz/manual/csirt_option/ssvc/config/#%E5%AF%BE%E5%BF%9C%E6%9C%9F%E9%99%90 対応期限については IPA の資料に目安の記載がありますが、ここは組織のポリシーに応じて設定してください。 引用元:「 脆弱性対応におけるリスク評価手法のまとめ 」(p.61) II. スキャンの実施から対応方針を決めるまで STEP1: スキャン CPE スキャンでは日次で自動スキャンされますが、ソフトウェア登録後すぐに実行したい場合は、「手動スキャン」を実行することで即時スキャンが可能です。 STEP2: トリアージ 脆弱性 対応における トリアージ とは「対応判断」のことです。 検出された 脆弱性 に対して重要度・緊急度を見極め、許容するものの選別や優先順位の決定などを行います。 SSVCによる評価 スキャン後、「 脆弱性 」タブを開くと、 脆弱性 の検出結果を確認できます。 「重要な未対応」タブの中に、SSVC Out_of_cycleと判断された 脆弱性 が表示されました。 脆弱性 としては4件、NGINX、OpenSSL、 Python の 脆弱性 が検出されているようで、この4件は計画外対応を行う必要があります。 SSVCの算出根拠も確認できます。 一方、SSVC Scheduledの 脆弱性 は「その他の未対応」に分類されました。 ここからは、「重要な未対応」タブに含まれるOut_of_cycle以上の 脆弱性 の調査・対応判断を行います。 STEP3:調査・対応判断 対応優先度が最も高い「Immediate」として検出されたNGINXの 脆弱性 から見ていきます。 まずはタスクのステータスを「INVESTIGATING」に変更し、調査中であることを明示します。 FutureVulsでは 脆弱性 が検出されると、サーバごとに 脆弱性 単位で「 タスク 」が作成され、ステータスを管理します(チケットに近いイメージです)。 続いて「詳細」タブにて、 脆弱性 の詳細情報を確認します。 該当システムに対してどの程度リスクがあるか、といった観点で確認すると良いと思います。 以下、一例として確認する項目をピックアップしました。 「サマリ」:攻撃を受けた場合に想定される影響、各機関が評価したCVSSスコアの一覧 「CVSS」:ネットワークから攻撃可能か等 「攻撃コード」:Exploit-DBや GitHub 上での攻撃コード・実証コードの公開有無 「緩和策」: Red Hat , Microsoft のデータソースにおける緩和策・回避策の有無 参考: https://help.vuls.biz/manual/cve/# 詳細タブ 「トピック」タブでは、 脆弱性 の調査結果やコメントの共有を行います。 参考: https://help.vuls.biz/manual/topic/ 例えば下記のような内容は 機械的 に収集できないため、トピックを利用して情報共有する使い方がおすすめです。 攻撃の成立条件 CVE-2023-44487への対策として、 AWS の基盤自体に緩和策が適用されているといった情報 参考: https://aws.amazon.com/jp/security/security-bulletins/AWS-2023-011/ NGINX自体の緩和策(下記リンク先の「Steps for Mitigating Attack Exposure」参照) 参考: https://www.nginx.com/blog/http-2-rapid-reset-attack-impacting-f5-nginx-products/ 「タスク×サーバ」タブで、どのサーバに 脆弱性 が存在するか確認します。 「タスク詳細」では、対応期限が表示されます。 これは、事前に「オーガニゼーション設定」で設定したSSVCのレベルに応じた「対応期限」が自動的に設定されます。 この対応期限に間に合うように対応予定日を決め、入力後、ステータスを「ONGOING」に変更します。 以上で、NGINXの 脆弱性 調査・対応判断が完了しました。 同様の流れで、OpenSSL、 Python の 脆弱性 についても調査・対応判断を行います。 以上で、「重要な未対応」に関する一連の調査・対応判断の作業が完了し、実際の 脆弱性 対応(事前のテスト、本番パッチ適用等)に移る準備が整いました。 残りの「その他の未対応」については定期メンテナンス実施時に対応するとします。 まとめ 脆弱性 管理ツールFutureVulsを用いて、SSVCによる トリアージ を試してみました。 今回の例では77件のうち、4件の 脆弱性 に対して優先度を上げて対応する結果となりました。 今回は3つのサーバで構成された単一のシステムでしたが、これが複数の環境が混在するシステムとなった場合には、この評価手法はより効果を発揮すると考えられます。 脆弱性 対応において、 IPA が提唱する0次評価・1次評価を導入することで運用負荷を削減し、FutureVulsのようなツールがある場合には2次評価のみで完結するため、より効率化できると言えます。 また、ツールを用いることで 脆弱性 情報の収集、調査、判断の自動化のメリットが得られるため、改めてツールの必要性を実感しました。 以上、最後までお読みいただきありがとうございました。 私たちは共に働いていただける仲間を募集しています! みなさまのご応募、お待ちしています! 株式会社 電通総研 新卒採用サイト 執筆: @fukuyama.kenta 、レビュー: @kou.kinyo ( Shodo で執筆されました )
こんにちは、 電通 総研の金子大地です。 この1年、所属するコミュニケーションIT事業部において、「若手プロジェクトマネージャー(以降「PM」)の育成活動」を行ってきました。その「活動内容」(前編)と「コンテンツ概要」(後編)を学生さん向けに紹介します。 多くの学生さんは、「PM」という言葉を聞いたことがあっても、具体的な仕事内容までは想像できないと思います。また、PMはプロジェクトチーム(多ければ50名以上)の責任者として推進役を担いますが、「そんなことが自分にできるんだろうか」と不安になりませんか。 電通 総研には、PMとしてのチャレンジの舞台と、先輩社員をはじめとするサポート体制があります。この記事が、学生のみなさんの「PM」という仕事への理解のとっかかりとなり、不安を軽減し、 電通 総研でPMをやってみたいかも!と興味を持つきっかけになるとよいなと思います。 また、社会人の方で、 電通 総研に興味を持っている方にも読んでいただきたいので、ぜひお付き合いください。 1. はじめに 2. 電通総研におけるPM育成活動 2-1. 会社全体でのPM育成の取組み 2-2. 現場におけるPM育成活動 3. 私が行った活動の内容 3-1. 私がなぜPM育成活動をしたのか 3-2. PMとしての暗黙知の資料化 3-3. 若手PMへの改善提案 おわりに 1. はじめに プロジェクトとは PMBOK (Project Management Body Of Knowledge)の定義では、「独自のプロダクト、サービス、所産を創造するために実施する有期的な業務」です。つまり、この世にひとつのアウトプットを生み出す、明確な開始・終了のある活動が「プロジェクト」です。世の中には様々なプロジェクトがありますが、本記事では「 システム開発 プロジェクト」を扱います。 プロジェクトの成功とは プロジェクトの成功は、古くからIron Triangle(鉄の三角形)と呼ばれる「Q/品質・C/コスト・D/納期」の達成具合で判断されてきました。その後、「QCD」だけでなくプロジェクトの活動や成果に関与する ステークホルダー の満足度で評価すべきという意見が増え、さらに近年では価値ある成果を提供したかが重視されるようになりました。何をもって「プロジェクト成功」とするかは、議論の対象になるものなのですね。 私はプロジェクトの価値を高めるために、 トレードオフ の関係にある「QCD」のちょうどいいバランスをとって完遂し、関わったお客様・プロジェクトメンバーが満足している(また一緒に仕事したいと思ってもらえる)、という状況を達成する必要があると考えています。 PMとは PMはプロジェクトチームを率いてプロジェクト目標を達成する責任を負っているので、「プロジェクト成功のために何をしたらいいかを考えて行動し続けること」が求められます。抽象的ながらこれが本質だと思っていますが、もう少し補足すると、PMは「プロジェクトの全てを自分事化して向き合い、プロジェクト特性をふまえた計画を立ててコン トロール しつつ、状況変化に対する柔軟な対応」が求められます。 2. 電通 総研におけるPM育成活動 2-1. 会社全体でのPM育成の取組み まずは、 電通 総研の会社としての取組みをご紹介します。 キャリアプラン の提示 電通 総研では、現場配属されてすぐにPMを任されることはありません(少なくとも私は見たことがありません)。「業務 スペシャ リスト」をしっかり経験してからPMを目指すなど、個人の希望・特性を考慮して段階的にPMになることを会社として推進しています。 ※ こちらのページの[キャリアステップ] をご参照ください ※ 以下にリンク先の図を引用しつつ、キャリアの「例」を追記しています。あくまで「例」なので、その点はご注意ください(この通りにキャリアを歩むことが約束されているわけでも、これが正解というわけでもありません)。 育成プログラムの提供 キャリアを積むためには、適切なスキルの獲得が必要です。 電通 総研では、スキル獲得のために多数の研修を提供しており、社費で受講できます。また、資格も社費で取得できます。 PM関連の研修だけでも2024年に26講座を提供しており、延べ638名の社員が申込んでいます。また、PM関連の資格では、PMIが提供している「 PMP (Project Management Professional)」、および IPA ( 情報処理推進機構 )が提供している「プロジェクトマネージャ試験」などを対象に、資格試験の対策・受験、資格維持に関わる費用を会社が負担しています。 ※ こちらのページの[教育体系] をご参照ください プロジェクト実践時の支援 上記で獲得したスキルを実際のプロジェクトで実践できるように、「標準 開発プロセス の提供」と「プロジェクト管理の支援」をしています。標準 開発プロセス (i*yes:アイズ)は CMMI 、ISO9001を参照して作られており、プロジェクトマネジメントを含めた開発の手順を定義しています。「プロジェクト管理の支援」は、提案・計画時などの主要な マイルストーン で、プロジェクト外部のメンバーがプロジェクトリスク等を確認します(RB:レビューボード)。 ※ こちらのページ をご参照ください 2-2. 現場におけるPM育成活動 電通 総研には、組織的な仕組みが用意されていることをご理解いただけましたか。 ですが、やはりこれだけでPMを「実践」するには不安が残るヒトも多いことでしょう。知識を習得しただけで優秀なPMになれるわけではありません。例えば「 PMP 」では、あらゆることを考慮し尽くしたプロジェクトマネジメントを学びますが、実際のプロジェクトで全ての領域を全力で実践すると、お客様の考える予算・期間に収まりません。また、プロジェクト実践時に支援してもらえると言っても、実際にプロジェクトを主体的に動かしていくのは自分自身です。 IPA でもPM育成においては「研修」だけでなく、「 OJT 」や「メンタリング」の重要性を説いています。 そこで、 電通 総研では従前から、 OJT に加えて「メンタリング」として、技術の現場組織のアチコチで「実践的なPMノウハウ」を共有してきました。簡単に言うと、「プロジェクト管理の体系的な知識を、実際のプロジェクトにはこうやって適用する」ということを学べる活動です。業務の傍ら「PM塾」と称して先輩からシリーズもので教わったり、部会発表で若手が自身の学びを共有して先輩に突っ込んでもらったりと、学習する文化があります。私もこうした活動の一端を担った形でして、それをご紹介します。 ※ 補足:プロジェクト特性に応じたプロジェクトマネジメント 各プロジェクトには様々な特性があります。小規模プロジェクトなら力業(ちからわざ)で何とかなることも、大規模プロジェクトではそうもいかず、より計画的に進める必要があります。人命・お金に関わるシステムの場合、そうでないシステムよりもイチ段高い品質が求められます。逆に、初期リリースの品質は ”そこそこ” でいいから、とにかく早期に利用開始したい、と要求をいただくこともあります。 したがって、 PMP 等で知識を得つつも、目の前のプロジェクトでは、予算・期間の制約やお客様の求める優先事項を考慮して「ちょうどいいバランス」でマネジメントする必要があります。そして、一概には言えませんが、それぞれの事業部におけるプロジェクトには似通った特色があるため(進め方が近い/共通する製品を扱う等)、各事業部内でPM育成活動が行われることは、理に適っている面もあります。 3. 私が行った活動の内容 3-1. 私がなぜPM育成活動をしたのか 若手PMは、先輩社員のサポートを受けながらPM経験を重ね、やがて独り立ちします。ですが、簡単には独り立ちできません。「一般知識(研修・資格等)」だけでPM遂行はできず、かといって経験できるプロジェクト数はさほど多くありません(感覚的には、プロジェクト1件あたりの開発期間は6ヶ月~2年くらいが多いです)。 したがって、一般知識と実プロジェクトとは別途、「メンタリング」に主眼を置いた学びの場を提供することで、PMとしての独り立ちを支援したいと考えました。「どう考えて行動するのか」といった本質的な理解を重視しつつ、「実プロジェクトで利用できるテンプレート」も提供し、役立つ活動になることを目指しています。 3-2. PMとしての 暗黙知 の資料化 PMP や研修では学べない「実践的なPMノウハウ」、特に「 暗黙知 の 言語化 」を意識して資料化し、所属組織(コミュニケーションIT事業部)に展開しました。コンテンツ概要は、[後編]でご紹介します。 現時点で展開済の資料( パワポ )が「計800ページ超」とボリューミーなので、週イチで社内のコミュニティに解説メルマガを投稿して、資料を読まなくても概略を理解できるようにしました(なお、それでもなかなか読まれないことを見越して、次項[3-3]の取組みをしています)。 ちなみに、別事業部から「PM経験が浅い 中途採用 者に学んでもらいたい」とお話があったり、グループ会社の方から「社内の人材育成に活用したい」とお声が掛かったりして、所属組織を超えて資料提供をしています。思わぬ反響もあるのだな、と嬉しい誤算でした。 3-3. 若手PMへの改善提案 若手PMが直近で担当したプロジェクトについて、私を含むメンバーが一緒に「振返り」をして、今後に向けた改善対応を考える、というものです。若手PMの「上長(マネージャー)」にも参加してもらうことで、ディスカッション後の改善活動を継続的にフォローしてもらっています。なお、「若手PM」と書いてはいますが、実際の対象者は「社会人4年目~15年目」と、社会人歴で言うとベテランの人もいました。 具体的には以下の流れです。 若手PMに、特に「自分が課題と思っていること(うまくできていないこと等)」を書面で事前 ヒアリ ングし、「どうしたら改善できるか」を対面でディスカッションしました。例えば、「お客様に依頼した作業が頻繁に遅れて、プロジェクト全体が遅延しがち」という課題認識がある場合、「そもそも 電通 総研から分かりやすく依頼内容を伝えられているか」、「お客様に検討していただくために、 電通 総研から提供している情報は充分か」、「お客様の繁忙時期をスケジュールに反映できているか」等の実態を若手PMに説明してもらい、なぜお客様の回答が遅れるかの真因に対しての打ち手をディスカッションします。 ありがたいことにディスカッション後のアンケート回答(若手PM、その上長)は総じて満足度が高く、「他案件の進め方を知る機会となってよかった」、「計画書等のPM資料のテンプレートが役立ちそう」といったコメントが多く見られます。やはり、自分が経験できるプロジェクト数は多くないため、他プロジェクトの進め方を効率よく把握でき、自分流のPMスタイルをブラッシュアップできる場は貴重なのだと思いました。 また、「改善点だけでなく、よい点はよいと評価してもらえたことが自信につながった」というコメントもあり、「なるほど」と思いました。私自身も若手PMの時にはおっかなびっくり「これでいいのかな?」と迷いながらプロジェクトを進めていた記憶があります。確かに、先輩PMに認めてもらうと安心や自信につながるな、と思いました。 おわりに 電通 総研には、「PM」に必要なスキルを学ぶ環境、そして独り立ちを支援する環境があることをご理解いただけましたか。 次回の [後編] では、私が社内展開した「PMノウハウ」のコンテンツ概要を紹介します。またお会いしましょう! 電通 総研でPMをやってみたいと思った方は、ぜひ下記もご参照ください。 私たちは同じ事業部で共に働いていただける仲間を募集しています! みなさまのご応募、お待ちしています! 株式会社 電通総研 新卒採用サイト 株式会社 電通総研 キャリア採用サイト 執筆: @kaneko.taichi 、レビュー: @nakamura.toshihiro ( Shodo で執筆されました )
こんにちは。 電通 総研IT 重松です。 Azure クラウド サービスを使って、アプリケーション開発および アーキテクチャ 構築の業務を行っております。 この記事では、主な業務内容と直近で対応した.NET:Azure Functionsの開発についてご紹介します。 1.初めに 1-1. 自己紹介 2. 業務紹介(Azure Functionsの分離ワーカーモデルへの移行) 2-1. なぜ移行が必要か 2-2. Azure Functionsのモデルの違い 2-3. 移行にあたっての進め方 3. 課題対応(診断設定経由でのログ出力および保存方式においてログが欠落する) 3-1.事象 3-2.原因と回避方法 原因 回避策 補足 4.まとめ 5.終わりに 1.初めに 1-1. 自己紹介 まずは自己紹介をいたします。 私は、新卒で システムエンジニア としてキャリアをスタートし現在は6年目になります。 主に ITアーキテクト として .NET 系の技術 を活用しながら、 クラウド 上で システム開発 の業務に携わっています。 主な業務としては、次のような作業を行っています。 .NETバージョンアップ対応 システムの動作環境を最新の.NET フレームワーク に更新する作業です。 この対応では、まず現在使用している.NETのバージョンを確認し、最新バージョンのリリースノートを調べます。 次に、既存のコードや使用しているライブラリが新バージョンと互換性があるかをチェックし、テスト環境でのアプリケーションで正しく動作するか確認します。 テストが成功したら、本番環境に新しいバージョンを展開し、パフォーマンスを引き続き監視します。 バージョンアップにより、セキュリティの強化や新機能の利用が可能となり、より安全で効率的なアプリケーション運用のために取り組んでいます。 SQL チューニング データベースのクエリ( SQL 文)の性能を改善する作業です。 この対応では、まず無駄な処理を減らし、効率的にデータを取得するためにクエリの書き方を見直します。 次に、適切なインデックスを設定することでデータ検索の速度を向上させ、さらにデータベースがクエリをどのように実行するかを示す実行計画を分析して ボトルネック を特定します。 SQL チューニングは、データベースの 応答時間 を短縮し、全体的なシステムパフォーマンスを向上させるために重要な作業であり継続的に対応しています。 性能試験 システムが要求される性能基準を満たしているかを確認するためのテストです。 この試験では、 応答時間 や スループット 、負荷耐性に焦点を当てます。 具体的には、システムがユーザーのリク エス トにどれくらいの速さで応答するか、一定期間内に処理できる トランザクション の数、同時に多くのユーザーがアクセスした際の安定性を評価します。 性能試験は、システムが実運用で適切に動作することを保証し、 潜在的 な ボトルネック の解消に向けて取り組んでいます。 IaC(Infrastructure as Code)のメンテナンス インフラスト ラク チャをコードとして管理する手法で、その代表的なツールである Terraform を対象に行っています。 Terraformを使ったリソースの構築、コードのGit管理、Terraformやプロバイダーの定期的なバージョンアップ等の作業を実施しています。 これらを行うことで、インフラを安定して運用し、将来的な変更にも柔軟に対応できるように構築に取り組んでいます。 これらの業務を通じて、システムの安定性とパフォーマンスを追求しつつ、新しい技術にも積極的にチャレンジしています。 技術の進化が速いIT業界で、柔軟に対応できるエンジニアを目指して日々取り組んでいます。 2. 業務紹介(Azure Functionsの分離ワーカーモデルへの移行) ここからは、日々行っている業務の1例として、直近に対応した 「Azure Functionsの分離ワーカーモデルへの移行」 をご紹介いたします。 現在担当しているシステムでは、.NET6から.NET8へのバージョンアップ対応を行っております。 上記に伴って、Azure Functionsの実行モデル移行が必要になりました。 2-1. なぜ移行が必要か そもそも実行モデルの移行が必要になった経緯を説明します。 Azure Functionsのイン プロセスモデル が、2026年11月10日をもってサポートが終了することが発表されました。 イン プロセスモデル は継続して利用可能なものの、セキュリティアップデートや新機能の提供は受けられないことから Microsoft 社は、分離ワーカーモデルへの移行を推奨しています。 また、次期バージョン.NET9ではイン プロセスモデル は利用できず、分離ワーカーモデルへの移行が必須であるということから.NET 8に移行するこのタイミングで分離ワーカーモデルへの移行対応が必要になりました。 出典: .NET on Azure Functions – August 2023 roadmap update .NET on Azure Functions – August 2023 roadmap update Azure Functions インプロセス モデル のサポート終了について(追跡 ID FVN7-7PZ) 2-2. Azure Functionsのモデルの違い 次にそれぞれの実行モデルの特徴を以下に記載します。 イン プロセスモデル イン プロセスモデル では、Azure Functionsのランタイムとアプリケーションコードが同じプロセス内で実行されます。 このモデルの主な利点は、ランタイムと密接に統合されているため、パフォーマンスが高く、セットアップが比較的シンプルなことです。短い 応答時間 が求められるシンプルなアプリケーションに適しています。 ただし、ランタイムに依存するため、主にFunction Host側(画像 青枠 )のAzureアップデート等によりLanguage Worker側(アプリケーション)も影響を受けてしまうというデメリットがあります。 また、Function Host側にLanguage Worker側の アセンブリ .dll を読み込ませ、Function Host側 と一体となってコードを実行する仕組み上、.NET の最新バージョンを使いたい場合、Function Host側 が対応しない限りLanguage Worker側(アプリケーション)が利用できないといったデメリットもありました。 分離ワーカーモデル 一方で、分離ワーカーモデルでは、Azure Functionsのランタイムとアプリケーションコードが別々のプロセスとして実行されます。 これにより、Functions Host側に依存することなく、Language Worker側(アプリケーション)は アセンブリ の依存関係やバージョン管理が柔軟に行えるようになったことがメリットとして挙げられます。 しかし、Functions HostとLanguage Worker間における通信が新たに追加されたこと(画像 青線 )、Language Workerが独立したことによる仕様変更を理解しつつ、アプリケーション開発を行うことが重要となります。 分離されたワーカー モデルと Azure Functions 上の .NET のインプロセス モデルの違い 2-3. 移行にあたっての進め方 実際に移行するに当たりどのような作業をしているのかご説明します。 Microsoft 社から、移行に当たっての マイグレーション ガイドライン や実装/アプリケーション構築例などが、公式ドキュメントとして提供されています。 .NET アプリをインプロセス モデルから分離ワーカー モデルに移行する 分離ワーカー モデルで C# Azure Functions を実行するためのガイド 上記を指針として、以下のように各フェーズ毎に対応を行います。 前述に挙げた、 マイグレーション ガイドや実装例には記載されていない機能改修が多数確認されたため、実装~テストの工程は繰り返し行う必要があり、移行作業に時間を要しました。 また、 クラウド 上での システム開発 の特性として、ローカル環境で正常に動作していたものが、 クラウド サービス上では想定外の動作をする、といったことが頻繁に起こりえます。 こういったものを見落とさないためにも、上流の工程はもちろんのこと、テスト方針の決定やテスト実施を慎重かつ正確に行うことが重要になります。 3. 課題対応(診断設定経由でのログ出力および保存方式においてログが欠落する) ここからは、開発を行っていく過程で苦労した課題についてご紹介します。 3-1.事象 担当システムでは、複数のログ出力方式を導入しています。 その中の1つに、Azure提供機能の 診断設定 というものを使用してログ出力するという仕組みを採用しています。 Azure Monitor の診断設定 ログ出力までの経路は以下のようになっています。 ・Azure Functions → ILogger → 診断設定→ ストレージアカウント また、パフォーマンスの観点から、ILoggerの実行はバッファリングして 非同期 で行う仕組みとしていました。 分離ワーカーモデル移行後のアプリケーションで、上記の仕組みを動作させたところ、ログ欠落の事象が発生しました。 課題切り分けのため以下のようなアプローチを試みました。 非同期処理から同期処理への変更 ILoggerの実行を非同期方式から同期処理に変更したところ、ログの欠落は発生しないことを確認しました。 以下がサンプルコードになります。 同期処理によるログ出力(ログ欠落 なし ) public void Run([TimerTrigger( "0 */1 * * * *" )]TimerInfo myTimer, FunctionContext functionContext) { // 開始ログ Logger.Log(aaa, model.Header, "Message" ); await Task.Delay( 1000 ); // 1秒待機 // 終了ログ Logger.Log(bbb, model.Header, "Message" ); } 非同期によるログ出力(ログ欠落 あり ) public void Run([TimerTrigger( "0 */1 * * * *" )] TimerInfo myTimer, FunctionContext functionContext) { // 開始ログ Logger.Log(aaa, model.Header, "Message" ); // 業務処理実装(引数にMicrosoft.Extensions.Logging.Iloggerインスタンスを渡す) // 非同期で Run 呼び出し. Run 内で 1 秒待機中に、本関数内で終了ログが出力されて関数が終了する Run<BaseRequestModel>(myTimer, _logger, functionContext, false ); // 終了ログ Logger.Log(bbb, model.Header, "Message" ); } async Run< T >(xxx myTimer, ILogger logger, yyy functionContext, bool zzz) { logger.LogInformation( "ログA" ); await Task.Delay( 1000 ); // 1秒待機 logger.LogInformation( "ログB" ); } Application Insightsへのログ出力の場合の挙動 前述に挙げた通り、複数のログ出力方式を採用している中の1つにApplication Insightsへのログ出力があります。 こちらの挙動を確認したところ、ログの欠落は発生しないことが確認されました。 以上から、非同期実行と診断設定の出力機構に問題があると推測を立てました。 3-2.原因と回避方法 原因 調査したところ、分離ワーカーモデルでの診断設定によるログ記録までの処理の流れが関係していることが判明しました。 分離ワーカーモデルでは、ホストが実行されるFunctions Hostプロセスと、関数コードが実行されるLanguage Workerプロセスに分離されますが、 診断設定のログは、Language Worker からの関数実行終了後の応答を契機として Functions Host にて記録しているとのことです。(画像 赤線 の部分) 分離ワーカーモデルでは Functions Host と Language Worker のプロセスが分かれていることにより、 「非同期実行したILoggerによるログ出力処理の終了を待たずメインの関数処理を終了してしまうと、関数実行後に記録されるログが拾いきれなくなる」 というものでした。 この仕組みはイン プロセスモデル も同様であるものの、分離ワーカーモデルでプロセス間通信(画像 赤線 )が発生することによりログの欠落が顕在化した、と理解しています。 一方、Application Insights のログは、画像 青線 の通り、Language Worker から直接記録されるため、プロセス間の通信がない分、診断設定ログに比べてログ欠落が発生しなかったのでは、と推測しています。 バックグラウンド タスクが完了していることを確認する 回避策 原因により、サブスレッドの終了を待たずに、メイン関数の処理が終了してしまっていたことでログの欠落が発生していたため、メイン関数の処理にてサブスレッドの終了を監視する処理の追加を試みました。 以下がサンプルコードになります。 public void Run([TimerTrigger( "0 */1 * * * *" )] TimerInfo myTimer, FunctionContext functionContext) { // 開始ログ Logger.Log(aaa, model.Header, "Message" ); // 業務処理実装(引数にMicrosoft.Extensions.Logging.Iloggerインスタンスを渡す) // 非同期タスクを受け取る var task = Run<BaseRequestModel>(myTimer, _logger, functionContext, false ); //非同期処理のタスクをwaitさせる task.Wait(); // 終了ログ Logger.Log(bbb, model.Header, "Message" ); } async Run< T >(xxx myTimer, ILogger logger, yyy functionContext, bool zzz) { logger.LogInformation( "ログA" ); await Task.Delay( 1000 ); // 1秒待機 logger.LogInformation( "ログB" ); } これにより、ログの欠落が回避できることを確認しました。 補足 一方で、サブスレッドの実行終了を待機することでメインスレッド、サブスレッドの実行時間が延びることになります。 それにより、単位時間あたりの関数実行数に対してアクティブとなるスレッド数が増えることになるため スレッド数の上限や使用できるリソースの上限に達しないように注意が必要であると考えています。 4.まとめ マイグレーション ガイド/実装例に、明確に記載されていない内容から発生した課題となります。 しかし、分離ワーカーモデルの仕組みやスレッドの仕様を理解することで対応することが出来ました。 分離ワーカーモデルは日々改修アップデートがされている機能です。 それにより、課題なども多く発生してしまっている状況ですが、これまで培った技術および知識を活用することで課題解決につながると感じました。 5.終わりに 今回は ITアーキテクト の業務紹介と担当案件を1例として紹介いたしました。 難易度の高い業務ではあるものの、最新技術を活用し、複雑な課題を解決するスキルが求められるため、常に技術的な成長とチャレンジがある点が魅力だと感じています。 少しでも参考に、そして ITアーキテクト というものに興味を持っていただければ幸いです。 採用ページ 執筆: @shigematsu.shu 、レビュー: @yukio.kazama ( Shodo で執筆されました )
こんにちは、X イノベーション 本部の 米久 保です。 サンフランシスコで2024年10月29日から30日にかけて開催されたイベント GitHub Universe 2024 に合わせて、さまざまな新技術・新機能に関する リリース が10月29日に GitHub 社より発表されました。 とくに、 GitHub Copilotがマルチモデル対応しAnthropic社のClaude 3.5 Sonnetや Google 社のJemini 1.5 Proなど最新のLLMが使用可能となったこと、 自然言語 だけで動作可能なマイクロアプリを構築できるツール「 GitHub Spark」は SNS 上でも大きな話題となりました。 これらと比べると一見 インパク トは薄いものの、 VS Code の GitHub Copilotでマルチファイル編集を可能とする「 Copilot Edits 」はAIコーディング支援によって開発生産性を飛躍的に向上させることが可能な画期的な機能です。 (生成コードエディタ「Cursor」を使っている方には、「(Cursorの)Composerに相当する機能がいよいよ GitHub Copilotでも実装された」と言えば通じるでしょう)。 本記事では、Copilot Edits機能の活用例として人間とコード生成AIによるピンポンプログラミング( ペアプロ で テスト駆動開発 を行う手法)を題材とし、機能の使い方をご紹介します。なお当該機能は執筆時点でプレビュー版であり、一般公開となる時点ではUIや操作方法、機能が変更される可能性もありますのでご留意ください。 Copilot Editsの基本的な使い方 VS Code のCopilotメニューから[Open Copilot Edits]を選択すると、Copilot Editsのペインが表示されます。Copilot Editsでは、編集対象の複数のファイルをWorking Setという単位にまとめます。[Add Files...]よりファイルを選択してWorking Setに含めた上で、プロンプトを入力して指示を出しましょう(次の図の赤枠部分)。 図の例では、 each.js ファイル(エディタ上部)に空実装の each 関数が定義されており、 each.test.js ファイル(エディタ下部)には each 関数に対するテストケースが3件記述されています。 テスト駆動開発 で少しずつ実装を進めていくために、最初のシンプルなテストケースを除き、 skip を指定してテスト実行対象外としています。 ※言語は JavaScript 、テスティングライブラリはJest、実行環境はNode.jsを利用 コード提案の受け入れ チャットの応答を確認しましょう。Working Setのファイルのうち、修正提案があるものはボールド表示となっています。ファイル名をクリックするとエディタタブが開き、修正内容を確認できます。 差分をプレビュー表示できる ので、とてもわかりやすいですね。 提案内容を受け入れる場合は[Accept]ボタンを、破棄する場合は[Discard]ボタンをクリックします。コード断片をコピー&ペーストで貼り付けたり、カーソルを移動して挿入したりといった作業は不要なのでとても楽です。 注意すべき点が二つあります。 一つ目。個々のコード修正提案を受け入れ(または破棄)した後に[Done]ボタンが表示されますが、これをクリックするとWorking Setに対する編集作業が完了という扱いになってしまうので、最後の最後まで押さないようにしてください。 二つ目。コード修正提案の受け入れはメモリ上の操作であり、明示的に保存を行うまで確定されません。 今回の例のように テスト駆動開発 で進める場合、テストコードを実行して関数の動作を検証する必要があるため、忘れずに保存をしなくてはなりません。 ターミナルから npm run test コマンドを実行してテストを流すと、最初のテストケースがパスし、コード生成AIの提案した実装が正しいことを確認できました。 以下のステップを繰り返して実装を進めていきます。 次のテストケースの skip 属性を外してチャットで実装を指示 コード生成の修正提案を確認して受け入れ テストを実行 全てのテストケースがパスしたら実装完了です! 人間がテストコードを書き、コード生成AIがそれをパスするようなプロダクションコードを書くという一連のやり取り(ピンポンプログラミング)が実現できました。 Tips Copilot Edits機能を使って テスト駆動開発 を進める上で役立つTipsをいくつかご紹介しましょう。 エラーの原因特定 全てのテストケースが一発でパスするような、幸せな物語ばかりではありません。 無情にもテストが失敗し、エラーが吐かれたときにも、コード生成AIの力を借りてエラー原因の特定とコード修正を行うことが可能です。 その場合、チャット欄に #terminalLastCommand を付けてエラー調査を依頼すると、Copilotがターミナルの履歴を参照することで適切な回答をしやすくなります。( #terminalLastCommand はコンテキスト変数と呼ばれるものの一つで、ターミナルにおける直前の実行コマンドとその出力が格納されています)。 コードの説明、 リファクタリング テストをパスする「動作するコード」ができあがったら終わりではありません。「 動作するきれいなコード 」に仕上げる工程が必要です。 自分が書いたコードではなく他人(コード生成AI)が書いたコードですから、まずは実装を理解しなくてはなりません。コード生成AIに説明させましょう。 このとき、単に説明をさせるのではなく、「具体例を用いて処理過程も示すようにしてください」というプロンプトを添えるとよいでしょう。 改善すべき点が見つかった場合、 リファクタリング を指示しましょう。 その他のアップデート 2024年10月29日の GitHub Copilotアップデートには、他にも多くの新機能や機能改善が含まれます。詳しくは 公式ブログ記事 をご参照ください。 まとめ この記事では、 GitHub Copilot( VS Code 版)の新機能であるCopilot Editsを使った テスト駆動開発 をご紹介しました。 Copilot Editsのマルチファイル編集機能は、他にもさまざまな用途で活用できるでしょう。たとえば、メイン関数とメインから呼び出される関数を複数ファイルで構成し、適切に構造分割されたコードを生成させることが可能になります。 私は、コード生成AIに一発で大きなプログラムを生成させることは「ガチャ」だと考えています。プロダクション環境にデプロイするコードの生成を運任せにしてはいけません。コード生成AIが生成するコードの精度と内部品質を向上させる鍵は、 問題を小さく分割すること です。 この記事で紹介したテクニックやCopilot Editsの機能を使うことで、皆さまのコード生成AIライフが向上することを願っています。 コードサンプル 今回の テスト駆動開発 で扱ったサンプルコードを以下に掲載します。 なおこの題材は、以前私がCursor + Claude 3.5 Sonnetで試した内容です( 私の個人ブログ記事 を参照)。 テストコード(人間が作成): const { each } = require("../src/each"); describe("each関数のテスト", () => { test("入力が空の場合", () => { const mockCallback = jest.fn(); each``(mockCallback); expect(mockCallback).not.toHaveBeenCalled(); }); test("データ行の数だけコールバックが呼ばれ、引数にはそれぞれのデータが渡される(属性1つ)", () => { const mockCallback = jest.fn(); each` name ${"Alice"} ${"Bob"} ${"Charlie"} `(mockCallback); expect(mockCallback).toHaveBeenCalledTimes(3); expect(mockCallback).toHaveBeenNthCalledWith(1, { name: "Alice", }); expect(mockCallback).toHaveBeenNthCalledWith(2, { name: "Bob", }); expect(mockCallback).toHaveBeenNthCalledWith(3, { name: "Charlie", }); }); test("データ行の数だけコールバックが呼ばれ、引数にはそれぞれのデータが渡される", () => { const mockCallback = jest.fn(); each` name | age | isAdmin ${"Alice"} | ${25} | ${true} ${"Bob"} | ${30} | ${false} ${"Charlie"} | ${35} | ${true} `(mockCallback); expect(mockCallback).toHaveBeenCalledTimes(3); expect(mockCallback).toHaveBeenNthCalledWith(1, { name: "Alice", age: 25, isAdmin: true, }); expect(mockCallback).toHaveBeenNthCalledWith(2, { name: "Bob", age: 30, isAdmin: false, }); expect(mockCallback).toHaveBeenNthCalledWith(3, { name: "Charlie", age: 35, isAdmin: true, }); }); }); プロダクションコード(コード生成AIが生成): const _ = require('lodash'); function each(strings, ...values) { return (callback) => { const headers = strings[0].trim().split(/\s*\|\s*/); const rows = _.chunk(values, headers.length); _.each(rows, (row) => { const obj = _.zipObject(headers, row); callback(obj); }); }; } module.exports = { each, }; 私たちは共に働いていただける仲間を募集しています! みなさまのご応募、お待ちしています! 株式会社 電通総研 新卒採用サイト 執筆: @tyonekubo 、レビュー: @nagamatsu.yuji ( Shodo で執筆されました )
こんにちは、XI本部プロダクト イノベーション センターの瀧川亮弘です。 現在、Next.jsの Static Exports により、Webサイトの構築を行っています。 本記事ではStatic Exportsの i18n (多言語)対応の実装方法を紹介します。 Static ExportsはNext.jsのアプリケーションを静的コンテンツ(HTML/ JavaScript / CSS /Image)としてエクスポートできる機能です。 Nodeサーバーが不要なため、S3などで簡単に ホスティング できます。 React/Next.jsの コンポーネント ベース指向やルーティング機能などの恩恵を享受しつつ、インフラの運用コストは最小化できます。 リク エス トに対して、静的なHTMLを返すだけなのでパフォーマンスもよいです。 i18n 対応については公式サイトで説明がありますが、説明が簡略的で別途検討することが多かったため、本記事に実装を記載します。 https://nextjs.org/docs/app/building-your-application/routing/internationalization ライブラリの利用も考えましたが、自身で実装してもそれほど複雑ではなかったため、独自に実装することとしました。 例えばこちらのライブラリでは、 タイムゾーン や単位などの i18n 対応も可能なので、要件に応じてライブラリを利用するとよいでしょう。 https://next-intl-docs.vercel.app/ 目標(ビルド後のイメージ) ビルドすると以下のようなoutフォルダが生成されるように実装します。 en, jaといった ロケール ごとのフォルダが生成されます。 例えば、enフォルダ配下のindex.htmlは英語の文言が適用されます。 out ├─en │ ├─hello │ │ └─index.html │ └─index.html ├─ja │ ├─hello │ │ └─index.html │ └─index.html └─index.html outフォルダ配下をそのままサーバーにデプロイすれば、静的サイトを配信できます。 画面の役割とURLの関係です。 ・ホームページ(英語版): https ://[ ドメイン ]/en/index.html ・ハローページ(日本語版): https ://[ ドメイン ]/ja/hello/index.html ・ダミーページ(アクセスされた場合、いずれかの言語のホームページに強制遷移する): https ://[ ドメイン ]/index.html 実装方法 Next.jsのフォルダ構成は自由度が高いため、いくつか流派がありますが、今回はこのようなフォルダ構成とします。 ├─next.config.mjs ├─app │ ├─(root) │ │ ├─layout.tsx │ │ └─page.tsx │ └─[locale] │ ├─hello │ │ └─page.tsx │ ├─layout.tsx │ └─page.tsx ├─constants │ ├─messages │ │ ├─ja.ts │ │ └─en.ts │ └─i18n.ts ├─contexts │ └─i18nContext.tsx ├─hooks │ └─useI18nRouter.ts └─types └─i18n.ts 順に各ファイルの役割を説明します。 まず、Static Exportsを有効化するため、設定ファイルにオプション output: 'export’ trailingSlash: true を指定します。 next.config. mjs const nextConfig = { output: 'export’, trailingSlash: true, } module.exports = nextConfig まずは、画面に表示する文言などを ロケール ごとに定義します。 サポート対象とする ロケール に合わせて、en.tsやja.tsを作成します。 constants/messages/en.ts import { Messages } from '@/types/i18n' ; const messages: Messages = { hello : { title : 'english hello page' , greeting : ( name : string ) => `hello!, ${ name } ` ; } // 省略 } constants/messages/ja.ts import { Messages } from '@/types/i18n' ; const messages: Messages = { hello : { title : '日本語ハローページ' , greeting : ( name : string ) => `こんにちは!, ${ name } ` ; } // 省略 } ロケール ごとに定義したメッセージは、 messagesMap にまとめておきます。 locales は対応する ロケール の配列です。 defaultLocale はデフォルトで利用される ロケール です。 constants/ i18n .ts import { Messages, Locale } from '@/types/i18n' ; import enMessages from './messages/en' ; import jaMessages from './messages/ja' ; export const locales: Locale [] = [ 'en' , 'ja' ] ; export const defaultLocale: Locale = 'en' ; export const messagesMap: { [ key in Locale ]: Messages } = { en : enMessages, ja : jaMessages, } ; 型も定義します。 types/ i18n .ts export type Locale = 'en' | 'ja' ; export type Messages = { hello : { title : string ; greeting : ( name : string ) => string ; } // 省略 } ; 配下の コンポーネント にメッセージを提供する、I18nProvider コンポーネント を定義します。 配下の各 コンポーネント では、useI18nContextを実行することで、メッセージを取得できます。 contexts/i18nContext. tsx 'use client' ; import { createContext, useContext } from 'react' ; import { Locale, Messages } from '@/types/i18n' ; import { messagesMap } from '@/constants/i18n' ; const I18nContext = createContext< | { locale : Locale ; messages : Messages ; } | undefined >( undefined ); export const useI18nContext = () => { const context = useContext(I18nContext); if (!context) { throw new Error ( 'Failed to retrieve I18nContext.' ); } return context; } ; export const I18nProvider = ( { children , locale , } : { children : React.ReactNode ; locale : Locale ; } ) => { const messages = messagesMap[locale]; return ( < I18nContext.Provider value = { { locale , messages } }> { children } </ I18nContext.Provider > ); } ; ロケール 切り替え用の2つの関数を用意します。 switchLocale は、任意の ロケール に切り替える関数です。 appendBrowserLocale は、ブラウザの言語設定に応じて ロケール を切り替える関数です。 サポートしていない場合は defaultLocale の ロケール に切り替えます。 hooks/useI18nRouter.ts import { useRouter, usePathname } from 'next/navigation' ; import { Locale } from '@/types/i18n' ; import { locales, defaultLocale } from '@/constants/i18n' ; export const useI18nRouter = () => { const router = useRouter(); const pathname = usePathname(); // URLのロケールを変更する const switchLocale = ( locale : Locale ) => { const newPath = pathname. replace ( /^\/[^\/]+/ , `/ ${ locale } ` ); router. push (newPath); } ; // URLにブラウザ設定(またはデフォルト)のロケールを付与する const appendBrowserLocale = () => { const browserLocale = window . navigator .language; const locale = locales. find (( locale ) => browserLocale. startsWith (locale)) || defaultLocale; const newPath = pathname. replace ( /^\// , `/ ${ locale } /` ); router. push (newPath); } ; return { switchLocale , appendBrowserLocale } ; } ; ここからappフォルダ配下にレイアウトやページを追加します。 app/[locale]フォルダを作成します。 i18n 対応が必要なページは全てこの[locale]フォルダ配下に配置します。 generateStaticParams の戻り値として、 ロケール 一覧を返すことで、ビルド時に各 ロケール ごとのHTMLが生成されます。 LocaleLayout の引数で ロケール を受け取り、 I18nProvider コンポーネント のpropsに渡します。 これにより、[locale]配下の各 コンポーネント でメッセージが取得できるようになります。 `` app/[locale]/layout. tsx import { I18nProvider } from '@/contexts/i18nContext' ; import { locales } from '@/constants/i18n' ; import { Locale } from '@/types/i18n' ; import '@/styles/main.scss' ; export function generateStaticParams () { return locales. map (( locale ) => ( { locale } )); } export default function LocaleLayout ( { children , params , } : { children : React.ReactNode ; params : { locale : Locale ; } ; } ) { return ( < html lang = {params . locale} > < I18nProvider locale = {params . locale} > { children } </ I18nProvider > </ html > ); } 各ページで useI18nContext を実行して、メッセージを取得します。 app/hello/page. tsx 'use client' ; import { useI18nContext } from '@/contexts/i18nContext' ; export default function Hello () { const { messages } = useI18nContext(); return ( < h1 > { messages . title } </ h1 > // 省略 ); } app/(root)配下にダミーのレイアウトとページを作成します。 ルートのパスにアクセスしてきた場合、app/[locale]/page. tsx の画面に強制的に遷移させます。 appendBrowserLocale を実行し、ブラウザの言語設定に応じた[locale]を指定します。 app/(root)/layout. tsx import { ReactNode } from 'react' ; export default function RootLayout ( { children } : { children : ReactNode } ) { return ( < html > < body > { children } </ body > </ html > ); } app/(root)/page. tsx 'use client' ; import { useEffect } from 'react' ; import { useI18nRouter } from '@/hooks/useI18nRouter' ; export default function RootPage () { const { appendBrowserLocale } = useI18nRouter(); useEffect(() => { appendBrowserLocale(); } ); } 終わりに 最後までご覧いただきありがとうございます。 お役に立てたら光栄です。 参考 https://qiita.com/koshitake2m2/items/dacfdafb833344bada4d 私たちは共に働いていただける仲間を募集しています! みなさまのご応募、お待ちしています! 株式会社 電通総研 新卒採用サイト 執筆: @takigawa.akihiro 、レビュー: @miyazawa.hibiki ( Shodo で執筆されました )
はいどーもー! 閲覧履歴を表示させるためにCtrl+H( Windows )やcmd+Y( Mac )を押下するつもりが誤ってCtrl+Yやcmd+Hを押下してしまう、コミュニケーションIT事業部の宮澤響です! 本記事では、2024年11月1日より新 シラバス Version 2023V4.0.J02 準拠となった JSTQB認定テスト技術者資格 Foundation Level試験 を受験してきた話をまとめます! なお、その場で結果が表示されるタイプの試験ではないため、本記事公開時点では合否は判明していません…あしからず…! JSTQB認定テスト技術者資格 Foundation Level試験とは 受験のきっかけ 何故シラバス切り替え直後のタイミングで受験したのか 利用教材など 受験してみての所感 難易度について 設問について 自身への影響について おわりに JSTQB認定テスト技術者資格 Foundation Level試験とは JSTQB認定テスト技術者資格 Foundation Level試験とは、 ソフトウェアテスト に関する基礎的な理解が問われる試験です。 ソフトウェアテスト 技術者の国際的な資格認定団体 International Software Testing Qualifications Board (ISTQB)の加盟組織である Japan Software Testing Qualifications Board (以下、 JSTQB )が主催している試験の一つであり、「Foundation Level」とあるとおり、 JSTQB認定テスト技術者資格 試験の中では最も基礎的な内容のレベルの試験となります。 実施形式としてはPBT形式とCBT形式の2種類があります。 PBT形式は指定会場に集合して試験を受験する形式であり、基本的に年2回程度開催されています。 一方、CBT形式は全国各地のテストセンターで試験を受験する形式であり、テストセンターの予約枠に空きがあればいつでも受験可能です。 受験のきっかけ きっかけは、 システム開発 案件にて、テストチームをサポートする役割を任されたことです。 私自身が直接テストを設計・実施する立場ではないものの、メンバーをサポートしていくためにはテストに対する一定の理解が必要であると考え、受験することを決定しました。 なお、新 シラバス 対応の試験予約が開始されたのは試験切り替え前日の2024年10月31日でした。 そのため、受験すること自体は決定していたものの、実際に試験を予約したのは試験前日でした。 何故 シラバス 切り替え直後のタイミングで受験したのか 試験範囲の変更直後は、当然ながら当該範囲の過去問題や出題傾向に基づく予想問題が存在しません。 そのため、資格の取得だけを主眼に置くのであれば、旧 シラバス を基に学習を重ね、10月までに試験を受験する方が、合格可能性は高かったかもしれません。 しかし、以下の理由から、私はこのタイミングでの受験を選択しました。 より新しい知識を習得する方が有用であると考えた(資格の取得よりも知識の習得に主眼を置いた)ため 新 シラバス で記述が増加したとされる アジャイル やDevOpsなどの要素が、私にとっては馴染みのあるものであったため 利用教材など 公式シラバス 学習初期と試験直前の計2回、目を通しました。 といっても、あくまで目を通しただけであり、熟読・精読したというほどではありません。 ソフトウェアテスト 教科書 JSTQB Foundation 第5版 シラバス 2023対応 ( アフィリエイト ではないですよの意味を込めて敢えてリンクは記載していませんが、検索すれば難なくヒットすると思います!笑) 私が学習を始めた時点では新 シラバス に対応している教材がおそらくこちらのテキストのみであったため、こちらを活用しました。 こちらも軽く一周した程度ですが、巻末にある模擬試験は、実際の試験問題の雰囲気を体感するために有用だったと感じています。 なお、弊社では、本資格取得のためのサポートとして、各自が選択した教材1冊を会社の経費で購入できます。 そのため、私も上記制度を利用して会社の経費で購入しました。 ソフトウェアテスト資格完全攻略 テス友 テス友とは、テスト技術者資格認定の勉強用アプリケーション/ Webサービス です。 「テスト技術者資格認定の勉強用」とあるとおり、本試験以外にも、JCSQEソフトウェア品質技術者資格認定やIT検証技術者認定試験にも対応しています。 1問1答形式の問題が10問ずつ(変更可能)出題され、1問解答するごとに解説が表示される、という形式であるため、スキマ時間で効率的に試験対策に取り組むことができました。 受験してみての所感 難易度について 難易度としては、やはりFoundation Levelということもあり、 基本情報技術者試験 や 応用情報技術者試験 の内容を理解できていればそれほど苦戦せずに合格できるレベルだと感じました。 具体的にどのような問題が出題されたかは紹介できませんが、先述のテキスト巻末の模擬試験と同等の形式および難易度でした。 設問について とても個人的な感想になってしまいますが、私が直近で受験・取得した資格が問題文が長く複雑なことで有名な AWS Certified Solutions Architect - Professional や AWS Certified DevOps Engineer - Professional であったこともあり、「問題文が短くて目も脳も疲れない…!」というのが第一印象でした。笑 新 シラバス で加筆された アジャイル やDevOpsなどの概念に関しては、関係する設問は何問か出題されたものの、それそのものがメインの設問はほとんどなかった印象です。 また、詳細を記載できないことが残念ですが、作問者の遊び心を感じるイマドキっぽい設問がとても印象に残っています。 自身への影響について 本資格について学習したことで、テストチームの仕事の進め方や大変さなどを理解できるようになり、テストチームの仕事(特に、欠陥レポートの記載、リーダーの方の振る舞い、など)の品質の高さを再認識できました。 それにより、私自身もテストチームをより親身にサポートできるようになった…かもしれません。 (親身かどうかは受け手側の感じ方次第なので「できるようになった」とは言えません…!) 総じて、本資格の受験は私にとっては有意義なものでした。 おわりに 本記事では、新 シラバス 準拠となった JSTQB認定テスト技術者資格 Foundation Level試験を受験してきた話をご紹介しました。 本記事公開時点では新 シラバス に関する記事はまだあまり多くないため、少しでもこれから資格取得を目指す方の参考になれば幸いです。 最後までお読みいただき、本当にありがとうございました! 私たちは同じ事業部で共に働いていただける仲間を募集しています! みなさまのご応募、お待ちしています! <電通×IT>電通グループ基幹システムプロジェクトマネージャー エンタープライズ向けDX推進リーダー/エンジニア◆電通グループ協業◆提案活動~開発・運用まで <電通×IT>クラウドアーキテクト <電通×IT>アプリケーションアーキテクト 製品・プラットフォーム開発エンジニア 執筆: @miyazawa.hibiki 、レビュー: @nagamatsu.yuji ( Shodo で執筆されました )
こんにちは。 電通 総研IT入社3年目の木ノ原です。 現在は第3ビジネスユニットに所属しており、金融機関向けソリューションである、 LINKGATEWAYというパッケージの開発・保守を担当しています。 この記事では、私のこれまでの仕事内容などについてお話しします。 1.自己紹介 私は2022年に新卒入社し、半年の研修を経て第3ビジネスユニットに配属となり、現在は3年目となります。 大学は情報学部 情報工学 科出身で、プログラミングなどについて学んでいました。 また、もともと金融関係のことにも興味があったこともあり、金融関係の仕事に携われる部署を希望したところ 希望通りでかつ、お客様と直接やり取りができる第3ビジネスユニットに配属となりました。 2.これまで行ったこと 【1年目】 4月から9月:新人だけの研修で、そこではビジネスマナーや Java などの研修を行いました。 10月以降:部署へ配属となり、そこで実際にプロジェクトへ参画する前に、 業務知識や C言語 などの研修を行いました。 ここで C言語 を学ぶ理由としては、私たちの部署で扱っているLINKGATEWAYが C言語 のため、 まず、先輩のサポートのもと C言語 を学びます。 【1年目以降】 実際にプロジェクトへ参画し、仕事を行いました。 参画したプロジェクトでは以下の図のように進めていき、 この中で私は要件定義工程以外の全ての工程に関わることができました。 次の項目では私が行ってきた仕事の内容についてお話しします。 3.仕事内容 【プロジェクト概要】 私は1年目の1月より、 UNIX から Linux へのシステム更改のプロジェクトに参画いたしました。 このプロジェクトの簡単な概要としては、OSの変更に伴うポーティングと 勘定系システムとの通信方式を変更するというものです。 以降では各工程で私がどのようなことを行ったか、お話しします。 【設計】 この工程では既存システムの更改ですので、新たな設計書を作成することはなく、 既存の設計書の修正を行います。 新規開発案件と違い、既存のシステムを更改するプロジェクトですので、何が変更になるのか、 それによって何をどう修正しなければならないのか、という事を考えながら行うことが重要になります。 【実装・ 単体テスト 】 この工程では設計工程で担当した機能のプログラム修正と、その機能のテストを行います。 実装は C言語 でプログラムの修正を行い、 単体テスト では自身でテスト仕様書を作成した後、 テストを行っていきます。ここで重要なのは修正したところが問題ないかを確認するだけでなく、 修正したことで他の場所に影響が出ていないかテストを行うことが重要です。 テストを行う際のテストデータの準備については、初めての経験でしたので、 先輩方のサポートを受けて、どのようにテストを行っていくか学びながら進めていきました。 【 結合テスト 】 この工程では内部(社内) 結合テスト と外部(社外) 結合テスト の2工程に分けて行います。 内部 結合テスト では、これまで社内で作成してきたものを結合して、システムが正しく動作するかを検証します。 ここで私は先輩と2人1組になってテストを行ったのですが、自分がこれまで担当してきた機能だけでなく システム全体として、どのような動きをするのか大まかにですが、理解しながら進めることができました。 また、先輩と2人1組になってテストを行ったことで、システムの理解だけでなく、 テストで必要なコマンドの知識や、ちょっとした豆知識なども教えてもらえました。 外部 結合テスト では、お客様とコミュニケーションを取りながら他システムとの連携が 問題なく動作できるかを確認・検証します。 ここで私は実際にお客様とコミュニケーションを取ることはありませんでしたが、 先輩方がどのようにコミュニケーションを取りながら進めているかを見聞きすることはできました。 【総合テスト】 この工程では性能テストや連続稼働テストなどを行い、 実際に運用していく中で問題はないかを確認・検証します。 この工程でも実際にお客様とコミュニケーションを取りながらテストを進めました。 テスト仕様書の作成も行ったのですが、ただ単にこのテストが必要という事だけでなく、 なぜこのテストをする必要があるか等の目的の部分についても教えてもらいながら、 作成を進めることができました。 4.これまでの業務経験から感じたこと 私はこれまで仕事を行ってきて、質問しやすい環境というのはとても大切だと感じました。 初めてプロジェクトに参画し、最初は右も左もわからない状態でしたが、先輩方にサポートしていただき、 質問に対しては優しく答えてくれるだけでなく、プラスαのことまで丁寧に教えてくれる人ばかりでした。 こうしたちょっとしたことでも聞きやすい環境というのは働きやすさにもつながりますし、 これから後輩が増えていく身としては、質問しやすい環境・雰囲気作りはとても重要だなと感じました。 5. 最後に ここまで私の仕事内容についてお話してきましたがいかがでしたか? 私たちの部署はLINKGATEWAYを扱い、たくさんのお客様とお仕事をしています。 そのため必要になる知識は多いですが、その分多くのことを学ぶことができます。 これからもこれを見てくださった皆さんと切磋琢磨していけたらと思います。 以下にLINKGATEWAYと採用ページへのリンクを貼っておきますので、興味を持った方はぜひ見てみてください。 ご覧いただきありがとうございました。 LINKGATEWAY https://www.dentsusoken.com/solution/linkgateway.html 採用ページ 執筆: @kinohara.kazuma 、レビュー: @yamashita.tsuyoshi ( Shodo で執筆されました )
みなさんこんにちは、 電通 総研コーポレート本部システム推進部の佐藤太一です。 設定管理は開発段階だけでなく、運用フェーズでも重要な課題です。MicroProfile Configを活用すれば、設定値の変更が及ぼす影響を最小限に抑えつつ、柔軟な設定管理が実現できます。 このブログエントリでは、MicroProfile Configの基本概念と使い方を初心者向けに解説します。アプリケーションの設定管理を効率化するための第一歩を踏み出しましょう。 はじめに MicroProfile Configの概要 MicroProfile Configを使う目的 アプリケーション開発環境 設定ソース 標準サポートの設定ソース カスタム設定ソースの作成 型変換 標準サポートの型変換 smallrye-config に実装済の型変換 自動的に行われる型変換 Enumを使う コンストラクタを使う ファクトリメソッドを使う まとめ はじめに まずは、MicroProfile Configの概要と利用目的について説明します。 MicroProfile Configの概要 MicroProfile Configは Jakarta EEのMicroProfileに含まれているライブラリです。 このライブラリは、アプリケーションの設定値を外部化し、一元管理するための仕組みを提供します。設定値を ソースコード から分離すると、アプリケーションの保守性や柔軟性が高まるでしょう。 標準で提供されている設定ソースは、 システムプロ パティ、プロパティファイル、 環境変数 です。ただ、設定ソースは柔軟に拡張できるので、データベースから値を取り出したり AWS AppConfigのような クラウド プロバイダー固有のサービスから値を取りだすような事も簡単にできます。 実は、MicroProfile Configは仕様だけが存在するものです。今回の説明に使うのは smallrye-config という Red Hat が実装しているライブラリです。 MicroProfile Configを使う目的 MicroProfile Configを使う理由は、いくつかあります。 まず、設定値の変更に伴う ソースコード の修正を最小限に抑えることで保守性を向上します。さらに、環境毎の設定切り替えが容易になるのでデプロイメントの柔軟性が高まるでしょう。 また、設定された値の型を検証したり、設定値を文字列からアプリケーションで利用する型に自動変換できるので設定ミスによる動作不良を最小限に抑えられます。 加えて、動的な設定変更が必要になるような高い可用性を要求するアプリケーションにも対応できます。 アプリケーション開発環境 具体的な ソースコード を交えた説明をするにあたって、アプリケーションのビルド環境を作りましょう。 エディタはどんなものでも構いませんが、Java21を使って Maven でプロジェクトを作成します。 プロジェクトのルート ディレクト リに配置する pom.xml は以下のような内容です。 <project xmlns = "http://maven.apache.org/POM/4.0.0" xmlns : xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi : schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" > <modelVersion> 4.0.0 </modelVersion> <groupId> com.example </groupId> <artifactId> mp-config-example </artifactId> <version> 0.1.0 </version> <packaging> jar </packaging> <properties> <maven . compiler . source> 21 </maven . compiler . source> <maven . compiler . target> 21 </maven . compiler . target> <project . build . sourceEncoding> UTF-8 </project . build . sourceEncoding> </properties> <dependencies> <dependency> <groupId> io.smallrye.config </groupId> <artifactId> smallrye-config </artifactId> <version> 3.8.2 </version> </dependency> </dependencies> </project> プロジェクトのルート ディレクト リから src/main/java と ディレクト リを作成して ソースコード の格納 ディレクト リとします。 そのまま com/example/config とさらに ディレクト リを掘って、その中に Main.java というファイルで以下の内容を保存します。 package com.example.config; import org.eclipse.microprofile.config.ConfigProvider; public class Main { public static void main(String[] args) { var config = ConfigProvider.getConfig(); var name = config.getValue( "com.example.name" , String. class ); System.out.printf( "Hello, %s%n" , name); } } これが MicroProfile Config を利用する最小限のコードです。簡単ですね。 このまま動かすと com.example.name という設定値が必須項目となりますので、以下のようなエラーになります。 Exception in thread "main" java.util.NoSuchElementException: SRCFG00014: The config property com.example.name is required but it could not be found in any config source at io.smallrye.config.SmallRyeConfig.convertValue(SmallRyeConfig.java: 435 ) at io.smallrye.config.SmallRyeConfig.getValue(SmallRyeConfig.java: 380 ) at io.smallrye.config.SmallRyeConfig.getValue(SmallRyeConfig.java: 359 ) at com.example.config.Main.main(Main.java: 9 ) このエラーに対処するため システムプロ パティに -Dcom.example.name=John を設定してアプリケーションを起動してみましょう。以下のように出力されれば、正しく動作しています。 Hello, John システムプロ パティを起動時に設定するのはやめて、 環境変数 に COM_EXAMPLE_NAME=Alice を設定してからアプリケーションを起動してみましょう。以下のように出力されるはずです。 Hello, Alice これで、MicroProfile Config を使ったアプリケーションの基本的な動作確認は終わりです。非常に簡単ですね。 CDI を使った設定値の取得方法もあるのですが、今回は説明しません。気になる方は仕様を見てください。 参照先: Aggregate related properties into a CDI bean 設定ソース 開発環境をセットアップして設定値を取りだす方法が分かった所で、設定値を保持する仕組みについて説明します。 標準サポートの設定ソース MicroProfile Configが標準で提供している設定ソースを優先度順に並べると以下の3つです。 システムプロ パティ 環境変数 プロパティファイル 優先順位がどのように作用するか、具体的に考えてみましょう。 MicroProfile Configがデフォルトで読むプロパティファイルは META-INF/microprofile-config.properties です。 環境変数 や システムプロ パティに設定がなければ、このファイルに記述された内容が使われますので、ローカルマシンを使った開発ではプロパティファイルを使うのが便利でしょう。 IDE からmainメソッドのあるクラスを実行する際にパラメータを渡すのは、少しだけ面倒ですよね。 アプリケーションをデプロイするにあたってDockerコンテナにパッケージングするとしましょう。 コンテナ オーケストレーション ツールを使うとコンテナをデプロイする時に 環境変数 を追加したり、環境毎に値を切り替えたりするのは非常に簡単です。プロパティファイルに記載があるものをコンテナ起動時に置き換えられます。少し奇妙ですが、MicroProfile Configでは 環境変数 から値を読む際にはキー名の中に含まれる . (ドット)を _ (アンダースコア)に置き換え小文字は大文字に置き換えて処理をします。 例えば、 com.example.name を処理する際には、 環境変数 に COM_EXAMPLE_NAME が定義されている事を期待して処理を行います。 コンテナ オーケストレーション ツールを使っているなら、 環境変数 の置き換えで基本的には対応できるはずです。しかし、緊急避難的に特定のコンテナだけ少し違ったパラメータで動作させたいことは、障害時にはよくあります(障害自体は発生しないで欲しいものですが…)。こういう時にはコンテナの起動パラメータに システムプロ パティを設定することで、既存の設定を上書きできるのです。 なお、 システムプロ パティの値を使う際には、 環境変数 のようなドットからアンダースコアへの置き換えはありません。 カスタム設定ソースの作成 MicroProfile Configが標準で提供している設定ソースは全て静的なものです。つまり、設定値を変更した際に JVM やコンテナを再起動する必要があります。 コンテナを使ってデプロイしているアプリケーションが クラスタ 化されているなら、再起動することはそれほど難しくないでしょうが、様々な事情によって再起動できないアプリケーションは存在しますよね。 カスタム設定ソースを実装すると、こういう要件に対応できます。 この記事では、長くなり過ぎるので AWS のAppConfigをMicroProfile Configから利用するためのカスタムソースを実装する記事をご紹介します。 Implementing a custom ConfigSource in Quarkus using AWS AppConfig 型変換 設定ソースから取りだす際に、文字列としてだけ値を取りだすとアプリケーション内では、そのまま使えない事が多いでしょう。 ここでは、数値や日付として設定値を取りだす方法について説明します。 標準サポートの型変換 まずは、MicroProfile Configが標準でサポートしている型変換を確認してみましょう。 標準で全てのプリミティブ型がサポートされています。つまり、boolean、byte、short、int、long、float、double、charに設定値を自動変換できるのです。同じようにラッパー型であるBoolean、Byte、Short、Integer、Longなども使えます。 特に難しいことはありません、値を取りだす際の第二引数にクラス参照を渡すだけです。例えば以下のようなコードになりますね。 package com.example.config; import org.eclipse.microprofile.config.ConfigProvider; public class Main { public static void main(String[] args) { var config = ConfigProvider.getConfig(); var value = config.getValue( "com.example.intvalue" , int . class ); System.out.printf( "Value is %s%n" , value); } } 設定ソースに一切の値が設定されていない場合のデフォルト値を用意したいことがあります。 通常はOptional型でラップされたものを取りだすための getOptionalValue メソッドを使えばいいのですが、プリミティブ型の時だけは専用のOptional型を使うので少しトリッキーです。以下のようなコードになります。 package com.example.config; import java.util.OptionalInt; import org.eclipse.microprofile.config.ConfigProvider; public class Main { public static void main(String[] args) { var config = ConfigProvider.getConfig(); var value = config.getValue( "com.example.undefvalue" , OptionalInt. class ).orElse( 30 ); System.out.printf( "Value is %s%n" , value); } } 標準でサポートされている型変換としてはClassもあります。Classを指定して値を取りだす際に使われるクラスローダーはThreadから取得できるContextClassLoaderです。 カンマ区切りされた設定値をListや配列として取りだすこともできます。 以下のコードを システムプロ パティに -Dcom.example.listValue=3.1,5.2,4.4,6.8 と設定して実行してみましょう。設定値をカンマ区切りする際に余分なスペースを入れると期待通りに動作しませんので注意してください。 package com.example.config; import java.util.List; import org.eclipse.microprofile.config.ConfigProvider; public class Main { public static void main(String[] args) { var config = ConfigProvider.getConfig(); List<Float> value = config.getValues( "com.example.listValue" , Float. class ); System.out.println( "values are " + value); } } このコードで使われているのは、getValues s メソッドです。複数形のsが付いていますね。見逃し易いので注意してください。これを実行すると以下のように標準出力されるはずです。 values are [ 3.1 , 5.2 , 4.4 , 6.8 ] smallrye-config に 実装済 の型変換 数値型とClass型だけでは、少々不便です。MicroProfile Configの実装であるsmallrye-configには、よく使われる型の変換がいくつか実装されています。 追加でサポートされているクラスは以下のとおりです。 java .net.InetAddress IPv4 アドレスと IPv6 アドレスの両方を扱えます。 java .util.UUID java .util.Currency java .util.BitSet java .util. regex .Pattern java .nio.file.Path ローカルのファイルを扱いたいときに使います。 どれも非常に良く使うものばかりですよね。 自動的に行われる型変換 MicroProfile Configには規約に基づく自動的な型変換機能があります。自分達で定義した型を使いたいときには、この規約をうまく利用しましょう。 より高度なカスタムの型変換機能もありますが、あまり使わないので今回は紹介しません。 Enum を使う まずは、 Enum を使うケースを考えてみましょう。以下のような Enum を定義します。 package com.example.config; public enum Cats { Abyssinian, American_Shorthair, Bengal_Cat, Himalayan; } 普段使っているものと大きな差分はないでしょう。これを使うコードを見てみましょう。 package com.example.config; import org.eclipse.microprofile.config.ConfigProvider; public class Main { public static void main(String[] args) { var config = ConfigProvider.getConfig(); var value = config.getValue( "com.example.cat" , Cats. class ); System.out.println(value); } } このコードを動かす際には、 システムプロ パティとして -Dcom.example.cat=American-Shorthair を設定してください。実行結果として以下のように標準出力されるはずです。 American_Shorthair システムプロ パティとしては、ハイフンを使っていましたが、アンダースコアに読み替えた上で Enum のメンバが選択されていますね。 コンスト ラク タを使う 独自の型に型変換を行うなら引数の型として String もしくは CharSequence を受取るコンスト ラク タを定義するのが簡単です。 例えば、標準でサポートされている型の中には java.math.BigDecimal は含まれていませんが、Stringを引数に受け取るコンスト ラク タが定義されているので型の自動変換ができます。 ちょっと使ってみましょう。 package com.example.config; import java.math.BigDecimal; import org.eclipse.microprofile.config.ConfigProvider; public class Main { public static void main(String[] args) { var config = ConfigProvider.getConfig(); var value = config.getValue( "com.example.number" , BigDecimal. class ); System.out.println(value); } } このコードを動かす際には、 システムプロ パティとして -Dcom.example.number=3344.222 を設定してください。そうすると以下のように標準出力されるでしょう。 3344.222 興味深い振る舞いですよね。 ファクトリメソッドを使う 次はファクトリメソッドが自動的に使われるケースを見てみましょう。 MicroProfileでは public static なメソッドが定義されているとファクトリメソッドとして利用します。メソッド名として有効なのは of valueOf parse です。引数は一つであることを仮定しています。そして、引数の型として有効なのは String もしくは CharSequence です。 例えば、こういうコードになります。 package com.example.config; public class Dogs { String group; public static Dogs of(String value) { var d = new Dogs(); // 少し奇妙なコードだが確実にファクトリメソッドが動いていることが分かるようにコンストラクタを使わない d.group = value; return d; } @Override public String toString() { return "group: " + this .group; } } これを使うコードを見てみましょう。 package com.example.config; import org.eclipse.microprofile.config.ConfigProvider; public class Main { public static void main(String[] args) { var config = ConfigProvider.getConfig(); var value = config.getValue( "com.example.dog" , Dogs. class ); System.out.println(value); } } このコードを動かす際には、 システムプロ パティに -Dcom.example.dog=Hound を設定してみましょう。 実行結果として以下のように標準出力されるはずです。 group : Hound of メソッドがファクトリとして利用されていますね。 まとめ このエントリでは、MicroProfile Configを使った設定管理の方法について説明しました。 MicroProfile Configを使うと、設定値の変更が及ぼす影響を最小限に抑えつつ、柔軟な設定管理が実現できます。設定値を文字列から任意の型に自動変換できるので設定ミスによる深刻な動作不良を防げるでしょう。高い可用性を求められるアプリケーションでも設定ソースを作りこむことで対応できます。 規約に基づいてに実行される型変換では文字列を引数にとるコンスト ラク タやファクトリメソッドがあれば、それが使われます。独自の型を使いたい場合にも簡単に対応できます。 MicroProfile Configをうまく活用してアプリケーションの品質向上に役立ててください。 私たちは共に働いていただける仲間を募集しています! みなさまのご応募、お待ちしています! 株式会社 電通総研 新卒採用サイト 執筆: @sato.taichi ( Shodo で執筆されました )
XI本部 プロダクト イノベーション センター アジャイル 開発グループの徳山です。 前回の記事「 FlutterFlowでFirebaseと連携する方法 」では、FlutterFlowとFirebaseを活用したバックエンドのセットアップ方法を詳しく解説しました。今回は、FlutterFlowを使って開発できる 社内業務向け スマホ アプリ の作成方法を紹介します。これまで解説した内容を確認しながら、実際の アプリ開発 の流れをご覧ください。 はじめに どのようなアプリを作るのか アプリ概要 機能概要 アプリの作成 1. プロジェクトのセットアップ FlutterFlowプロジェクトの作成 データベースの設定 usersコレクションのスキーマ reportsコレクションのスキーマ セキュリティルール 2. 画面作成および機能の実装 ログイン/新規登録 営業報告一覧 営業報告作成 営業報告詳細 営業報告編集 3. テスト 4. ビルドおよびデプロイ 4. ビルドおよびデプロイ 1. Webアプリとしてのデプロイ 2. モバイルアプリ(iOS/Android)としてのデプロイ まとめ 参考資料 はじめに 本記事の目的は、FlutterFlowを利用して社内用の簡単な業務用アプリを短期間で開発する方法を紹介することです。FlutterFlowの利用を検討している方で業務アプリを素早く作りたいと考えている方に向けてステップ バイス テップの解説を提供します。 なお、細かいセットアップ方法についての解説は本記事では行いませんので前回の記事「 FlutterFlowでFirebaseと連携する方法 」を適宜ご参照ください。 また、本記事は2024年10月時点の情報に基づいたものとなります。 どのようなアプリを作るのか アプリ概要 今回作成するアプリは、 営業チーム向けの営業報告共有ツール です。営業チーム内で共有する業務情報を記録し、他のメンバーと共有することを目的としています。このアプリは 単一部署の複数人 が使用することを想定しています。 ミニアプリのため、実装する内容は下記の内容に絞りました。 機能概要 営業活動の報告入力 : 営業が外出先から直接活動内容を入力。 報告の共有 : 営業メンバー間で活動状況が即時に共有される。 進捗管理 : アプリ内で営業進捗を可視化し、確認できるようにする。 アプリの作成 ここからは実際にアプリを作成します。バックエンドは前回解説した Firebase を利用します。 大まかに下記の項目に分けて解説を行います。 プロジェクトのセットアップ 画面作成および機能の実装 テストとデプロイ 1. プロジェクトのセットアップ FlutterFlowプロジェクトの作成 「Quick Report」というアプリ名で新規プロジェクトを作成します。 スマートでクールという印象を与えるため、Themeは「Sleek&Cool」を選択しました。 FlutterFlowからFirebaseのプロジェクトを新規作成し、Auth, Storageも利用できるように有効化しておきます。 Enable Authentication , Create User Collection のトグルをONにしておくことで、ユーザーコレクションの作成とユーザーのログインを自動で設定できます。 また、ログイン状態によって初期表示するページも設定できるため、それぞれ下記を設定しました。 ログイン前 :Signin ページ(FlutterFlowで用意されているテンプレートを利用) ログイン後 :ReportList ページ(空のページを利用) データベースの設定 今回は以下の2つのコレクションを用意します。 users :営業担当者の情報を記録するためのコレクション reports :レポートデータを記録するためのコレクション それぞれの スキーマ は下記となります。 users コレクションの スキーマ FlutterFlowで用意されているユーザー用の定義をそのまま利用しています。 reports コレクションの スキーマ 企業名(company_name)、営業活動の詳細(activity_details)、備考(remarks)、ステータス(status)、作成者の情報(user_id)を管理できるように設計しています。 セキュリティルール users コレクションと reports コレクションに読み書きのアクセス制限を設定します。 users コレクションは、作成は誰でも可能で、それ以外の操作はログインユーザーである本人のみ可能となるように設定します。 reports コレクションは、作成と読み取りはログインユーザーであれば可能で、上書きと削除は作成者のみ可能となるように設定します。 2. 画面作成および機能の実装 次に、アプリの画面を設計します。今回作成する画面設計は下記のとおりです。 画面名 機能 ログイン/新規登録 ユーザーのログインと新規登録を行う 営業報告一覧 営業担当者が登録した営業報告の一覧を表示する 営業報告作成 新しい営業報告を登録する 営業報告詳細 営業報告の詳細を表示する 営業報告編集/削除 既存の営業報告を編集または削除する ログイン/新規登録 FlutterFlowで用意されているテンプレートを活用して作成します。追加したユーザーの名前や電話番号は標準ではusersコレクションに保存されないため、保存する設定をアクションから追加します。 営業報告一覧 営業報告の一覧と報告の作成ができるボタンを配置しています。 一覧の表示は「ListView」 ウィジェット が用意されており、この ウィジェット にデータを渡すことで簡単に作成できます。 今回は reports コレクションのデータを取得してListViewに渡しています。 また、ヘッ ダーナ ビゲーションにユーザーアイコンを設置し、ログアウトができるようにしています。FlutterFlowではログアウトや確認用のダイアログのアクションが用意されているので簡単にログアウトのワークフローを実装できます。 実際に作成した報告の一覧画面は以下のようになります。 営業報告作成 「作成する」ボタンをクリックすることで、営業報告の作成ページに遷移できます。 ステータスは「choice chips」 ウィジェット を利用しています。単一選択と複数選択の両方に対応したオプション選択用の ウィジェット で初期値の設定や Enum (列挙型)のデータ型を利用した選択肢の作成も可能です。 また、フォームの入力内容をチェックするバリデーションも「Form Validation」 ウィジェット を利用することで簡単に設定ができます。文字の長さや入力形式など個別でエラーメッセージも設定が可能です。 「作成する」ボタンをクリックすると下図のようにバリデーションが効いていることを確認できます。 最後は、報告作成時のアクションワークフローを設定します。条件分岐や画面遷移、スナックバーによるメッセージの表示などFlutterFlowでは多くのアクションが標準で用意されているため複雑なワークフローも組むことが可能です。 <報告の作成フロー> フォームの入力内容のチェック Firestoreへのデータの保存 保存が成功したかをチェック 報告一覧ページへの遷移 保存が成功したメッセージの表示 営業報告詳細 営業報告一覧画面から任意の報告を選択したときに詳細画面に遷移するようにします。各報告を表示するContainerの ウィジェット に遷移するためのアクションを設定し、その際に選択した報告のデータ(ドキュメント)を渡すように設定します。詳細画面側ではこの設定を受け取ることで報告の情報を表示できます。 報告詳細画面は下図のとおりです。 FlutterFlowでは「Page State」という機能があり、ページ内で共通の値をセットして利用できる仕組みがあります。担当者の名前は users コレクションからデータを取得する必要があり、この情報は削除や編集ボタンの表示の判定にも使えるので、Page State機能を使って管理します。この機能は右のプロパティパネルから利用ができます。今回はuserのデータが欲しいので salesPerson という名前でuserドキュメント型の定義を行います。 あとは、画面ロード時に salesPerson の値に報告書の作成者をセットするワークフローを組むことで、ページ内で利用することが可能になります。 1. 報告書の user_id のフィールドと一致する users のデータを取得 2. 取得したユーザーのデータを salesPerson にセット これで無事、報告の詳細に必要な情報を全て取得できました。実際の画面は下図となります。 ログインしているユーザーが報告の作成者ではない場合、ボタンの表示がされないように表示の制御をしています。 これはプロパティパネルの Visibility でロジックを設定することで制御ができます。 削除の処理は、報告の作成の時と同様、「Create Document」というアクションの代わりに「Delete Document」を使うことで簡単に実装できます。 営業報告編集 最後に、報告の編集を行うページを作成します。といっても先ほど作成した作成画面とUIもロジックもほとんど同じです。編集画面に必要なデータは、詳細画面に遷移する際にデータを渡したように編集ページに遷移する時も詳細画面のデータを渡すことで取得ができます。ロジックも作成や削除の時とほぼ共通で、「Create Document」の代わりに「Update Document」を利用するだけです。 最後に、ここまで作成した画面一覧と遷移は下図に示します。 サイドメニューから Storyboard を開くことで、アプリの全体像を一目で把握できます。 3. テスト ブラウザではヘッダーメニューから 「プレビューモード」 または 「Run モード」 を使い、アプリの挙動を確認できます。 プレビューモードはロジックが反映されず見た目だけの確認ができます。Runモードは、実データや遷移など本番と同等の挙動の確認ができるといった違いがあります。Runモードはビルドに時間がかかりますが、ロジックを含めた確認ができ、 デバッグ 機能も利用できます。 確認したい範囲に応じてそれぞれのモードを使い分けましょう。 4. ビルドおよびデプロイ 以下に、 「4. ビルドおよびデプロイ」 セクションの不足している内容を補完して書き上げました。 4. ビルドおよびデプロイ FlutterFlowでは、アプリを開発した後に、さまざまな方法でビルドおよびデプロイが可能です。具体的には以下のデプロイ方法があります。手順はドキュメントに詳細が記載されていますので、必要に応じて FlutterFlow Publishing をご確認ください。 1. Webアプリとしてのデプロイ FlutterFlowで作成したアプリを Webアプリ としてデプロイする方法です。これにより、アプリをURL経由でアクセスできるWebアプリとして公開でき、ブラウザから利用できます。 2. モバイルアプリ( iOS / Android )としてのデプロイ 開発したアプリを iOS および Android 向けにビルドして、それぞれのアプリストア( App Store , Google Play )で公開できます。FlutterFlowはFlutterベースのため、1つのコードベースで クロスプラットフォーム のアプリを作成でき、アプリストアでの配信に対応しています。 iOS アプリ : Apple Developer Programへの登録や証明書の取得が必要です。 Android アプリ : Google Play Consoleを通じてAPKまたはAABファイルをアップロードして公開します。 まとめ 架空の営業報告共有アプリを題材にFlutterFlowで社内業務向け スマホ アプリの作成手順を紹介しました。手順や設定が煩雑に感じる方もいらっしゃると思いますが、慣れれば2〜3時間程度でこのレベルのアプリを作成できます。 今回の記事がFlutterFlowでアプリを作成してみたい方やどのようなアプリを作ることができるのかを知りたい方のお役に立てば幸いです。FlutterFlowについてより知りたい方は、公式ドキュメントや私の過去の記事も参考にしていただけると嬉しいです。 参考資料 FlutterFlow ドキュメント Firebase ドキュメント 私たちは共に働いていただける仲間を募集しています! みなさまのご応募、お待ちしています! 株式会社 電通総研 新卒採用サイト 執筆: @tokuyama.raido 、レビュー: @handa.kenta ( Shodo で執筆されました )
始めまして。 電通 総研ITに6年間在籍する小椋と申します。 今回は、入社してから今までの業務を振り返りつつ、記事にいたしました。 弊社を知りたいと考えている皆様のお役に立てると幸いです。 経歴 まずは私の今までの経歴を簡単に紹介したいと思います。 2019年3月 大学卒 2019年4月 電通 総研ITへ新卒入社 4月~6月末 電通 総研グループ研修を受講 7月~9月末 電通 総研IT社研修を受講 10月~2020年3月末 現場配属後、現場にて OJT 研修を受講 2020年4月~現在 複数社が利用する社内基幹システムの開発案件に従事 上記の通り、入社後の研修以降、ずっと1つの大型案件に従事してきました。 入社当時は社会人一年目であるため、数多くの不安がありましたが充実した研修と頼れる上司・先輩社員の助けもあり、 6年目社員として成長し続けてこれたと自負しております。 業務内容(参画している開発案件) 複数社が共通で利用する社内基幹システムの開発です。 このプロジェクトは様々な会社が利用する事を想定しているため、いくつかのフェーズを設け段階的に開発を進めてきました。 執筆時点(2024/9)で、既に数社にてシステム利用が開始されているため保守を担当しつつ、その他の会社への導入に向けた作業を進めております。 このプロジェクトの難しいところはまさに”複数の会社が利用する社内基幹システム”であることです。 今までは各社がそれぞれ独自の社内基幹システムを利用してきましたが、それらを共通のシステム利用に切り替えるため、 各社のニーズを取り入れつつ、統一的なシステムを構築していく必要があります。 そのため、各会社・各部署の方々との密なコミュニケーションが必要不可欠でした。 そのコミュニケーションは各社展開を実施している現在も続いており、不足している機能を補う追加開発も行っております。 開発業務に関して 前述した通り、本システムは複数のフェーズを設けた上で開発を進めてまいりました。 各フェーズの内容は以下のとおりとなります。 フェーズ1:リリースターゲットを数社に絞り開発を実施。 フェーズ2-3:フェーズ1で発生した問題点を解決しつつシステムを新たに構築し、 フェーズ1でターゲットとした会社に公開。保守を行いつつその他の各社へ展開。 現在はフェーズ2-3の"その他の各社へ展開"する作業が続いている状況です。 この案件の開発には特徴がいくつかありますが、Vue、TypeScript、SpringBootを利用した案件である事が特徴の一つとして挙げられます。 特にVueは数年前から JavaScript の フレームワーク として様々な案件で利用されることが増えました。 Vueを利用する利点として挙げられる点は以下のようなものがあります。 画面表示されているデータのリアルタイム更新に優れ、ユーザの操作に応じたUI表現が可能。 開発者の目線から見ても オブジェクト指向 に基づいた設計が容易で、 コンポーネント (部品)を作成する事でスムーズな開発が可能。  (興味がわいた方がいらっしゃいましたら、Vueに関して是非調べてみてください!) 他の特徴としましては、オフショア開発を実施していることも挙げられます。 そのため、上流の工程である設計工程をメインに業務を行い、プロジェクト進捗に関わる様々な経験を積むことが可能です。 デメリットとして、コーディング作業をオフショア側に委託しているため、技術的なスキルの向上機会が少ない事が挙げられます。 ただし、実装をオフショア側へ効率的に依頼する事で、「コードレビューの時間を多くする」・「自習の時間を作る」時間を増やし技術力の向上を図る事が可能です。 では効率的な依頼を実施するには、どのようにしていけば良いでしょうか。 私がこれまでの経験で特に重要視しているのは以下の2点です。 正確な情報を伝えること 日本側の役割・オフショア側の役割を明確にすること "正確な情報を伝えること"のために、正確な文章で記載する事も重要です。 今回のオフショア開発ではやり取りを行う際に日本語でコミュニケーションをとる事が出来たため、 言語の壁はあまり感じることなく作業することができました。 ですが、正確な日本語で正確な情報を伝えることをより意識しなければならない現場でもありました。 不正確な文章はそのまま実装側との認識齟齬を生んでしまうためです。 これは日本国内で設計・実装を行う際でも注意しなければならない基本スキルですが、本開発案件ではより注意が必要だったため、その重要性を実感しました。 ※"正確な文章の作成"に関してはAIに文章校正を実施してもらうなど様々な手段が出てきましたので、 これらのツールを活用し、作業の効率化を図っていきたいと思っております。 "日本側の役割・オフショア側の役割を明確にすること"はこの先PMなどを目指すためにも 必要な能力であると感じております。 どの業種でも当てはまる事ではありますが、仕事をチームで進めていくと、 各個人間には必ずといってもいいほど摩擦が発生してしまうものです。 お互いの役割を明確にしながら、円滑にプロジェクトを遂行する事は この摩擦の発生を抑えるために不可欠な要素であると言えます。 また、発生した問題をチームで協力して解決していくことも大切です。 オフショアとのコミュニケーションは上記のような基本ではあれど重要な要素は何なのかを私に経験させてくれました。 その他の働き方に関して 私が参画したプロジェクトは年単位での開発期間を要する大規模なプロジェクトです。 そのため、コロナ渦の影響も大きく受けた案件となります。 その最たるものがリモートワークの導入でした。 リモートワークの導入に伴い、大きく変化したのがコミュニケーションの在り方です。 例えばTeamsを利用した「ビデオ会議」や「チャットベース」での作業進行が挙げられます。 この方法での作業進行は、相談相手の作業状況が分かり辛く、相互理解を深める上で課題が発生しました。 しかし、徐々に適応し、効率的な情報共有やコミュニケーション方法を各々が習得する事で解決しました。 私の場合、相手がどんな作業を今持っているのかを適宜把握する力が特に伸びたと感じております。 この力は現場での幅広い視野を持つことにもつながり、チームメンバー間の円滑なコミュニケーションを とるための力として、今後も大いに役立つものだと感じております。 最後に 今回は私が従事する案件の内容や現在の働き方等に関してご紹介いたしました。 多くの事を書かせていただきましたが、結論として私が本記事で最もお伝えしたかった事は"コミュニケーションの重要性"であり、弊社ではそれらコミュニケーションスキルを学ぶ機会があるという事です。 今回記事にいたしました内容はもちろん一例です。 他の方(後輩・同期・先輩)はそれぞれ異なる事を多く経験し、それによって重要視している内容が異なる方ももちろんいらっしゃいます。 そのため、私以外にも同様に弊社の働き方などを記事にしている方もいらっしゃいますので、お時間があればそちらもぜひご覧ください! 以上、この記事が読んでくださった皆様の不安解消などの一助となれば幸いです。 採用ページ 執筆: @ogura.ren 、レビュー: @yamada.y ( Shodo で執筆されました )
XI本部 プロダクト イノベーション センター アジャイル 開発グループの徳山です。 前回の記事「 FlutterFlowに制約はある?できることとできないこと 」では、FlutterFlowを使った開発における制約や注意すべきポイントをお伝えしました。今回は、FlutterFlowと相性の良いバックエンドサービスであるFirebaseとの連携について詳しく説明いたします。 はじめに Firebaseとは何か FlutterFlowの接続先について 1. 標準でサポートされているバックエンド(FirebaseやSupabase) 2. API Connector Firebaseとの接続方法(環境構築手順) 事前準備 1. FlutterFlowのプロジェクト作成画面を立ち上げる 2. Firebaseのプロジェクトを作成 FlutterFlowからFirebaseのプロジェクトを作成する場合 FlutterFlowを既存のFirebaseと連携する場合 3. FlutterFlowのプロジェクトの作成 Firebase サービスとの連携 事前準備 認証(Firebase Authentication)について データベース(Firestore Database)について ストレージ(Cloud Storage)について 使用例 コレクションの準備 認証用ページ 認証用ページ タスク一覧ページ タスク登録ページ 動作確認 Supabaseとの違い まとめ 参考資料 はじめに 本記事の目的は、Firebaseの基礎やFlutterFlowと連携する際の基本的な手順を紹介し、初めてノーコード開発やローコード開発に取り組む方やビジネスマンの方に役立つ情報を提供することです。Firebaseを使うことでモバイル アプリ開発 のバックエンド部分を簡略化し、効率的にプロトタイプから本格的なサービス開発へと進むことができます。 FlutterFlowの基本的な知識については、記事「 FlutterFlowとは?ノーコードでスマホアプリ開発を始める方法 」や「 FlutterFlowに制約はある?できることとできないこと 」をご参照ください。 また、本記事は2024年10月時点の情報に基づいたものとなります。 Firebaseとは何か Firebaseは、 Google が提供するBaaS(Backend as a Service)であり、バックエンドの機能開発を簡素化するための多くの機能を提供しています。主な機能には次のものがあります。 Firebase Authentication : パスワード認証や多要素認証といったユーザー認証を簡単に実装できます。例えば、アプリに「 Google でサインイン」ボタンを設置するだけで、ユーザーは Google アカウントで簡単にログインできるようになります。 Firestore Database : 高速で拡張性のあるNoSQLデータベースです。データをリアルタイムで同期できます。例えば、「チャットアプリ」のように、複数のユーザー間でリアルタイムにメッセージを送受信する場合などにも利用できます。 Cloud Storage : 画像や動画などのファイルの保存に適した クラウド ストレージです。たとえば、 プロフィール画像 のアップロード機能などに利用できます。 FlutterFlowはこれらのFirebaseサービスを簡単に活用できるように設計されています。バックエンドの実装が簡素化できるのでFlutterFlowでの機能開発に集中できます。 FlutterFlowの接続先について 先述の通り、FlutterFlowでデータを管理するためには バックエンドとの接続 が非常に重要です。FlutterFlowが提供するバックエンドの接続先としては、主に以下の2つがあります。 1. 標準でサポートされているバックエンド(FirebaseやSupabase) FlutterFlowは、デフォルトでFirebaseやSupabaseとシームレスに連携できます。Supabaseは比較的新しいサービスで内容も魅力的なのですが、FlutterFlowではFirebase連携の方がより早く機能追加される傾向にあるため、ここではFirebaseを用います。 2. API Connector [初心者の方にも分かりやすいように API でデータを取得する簡略図を作成してここに貼る] 標準のFirebase/Supabaseバックエンド以外のサービスを使いたい場合、FlutterFlowの API Connector 機能を使用することで、 REST API を介して他のバックエンドサービスと連携できます。これにより、Firebase以外の独自バックエンドや他のパブリック API (分かりやすいものだと住所や天気、株価などを取得できる API )と連携が可能になります。 Firebaseとの接続方法(環境構築手順) FlutterFlowでFirebaseと連携するためには、いくつかの設定を行う必要があります。英語の見慣れない画面に難しく感じる方もいるかもしれませんが 公式のドキュメント にもしっかり記載されているのでそちらも合わせてご参照ください。 事前準備 Firebaseを利用するにあたり、 Google アカウントが必要となります。アカウントを作成していない場合は、事前に作成しておいてください。 1. FlutterFlowのプロジェクト作成画面を立ち上げる まずは、FlutterFlowにログイン後に「Create Project」よりプロジェクトを作成します。 するとステップ1の画面が表示されるので Setup Firebase のトグルがオンになっていることを確認します。確認後、「Next Step」で次の画面に進みます。 2. Firebaseのプロジェクトを作成 ステップ2の画面では、実際にFirebaseのセットアップを行います。 ここでは、FlutterFlowからFirebaseプロジェクトを新規作成する場合と、FlutterFlowを既存のFirebaseと連携する場合に分けて解説します。 FlutterFlowからFirebaseのプロジェクトを作成する場合 「Create Project」ボタンからFirebaseのプロジェクト設定モーダルを開き、Firebaseで作成するプロジェクト名やリージョンを選択します。指定がなければプロジェクト名はそのまま、リージョンは asia-northeast1(Tokyo) を選択します。 Google アカウントにサインインすることで、FlutterFlowにFirebaseプロジェクトへアクセスや操作する権限が付与され、自動的にFirebaseのプロジェクト作成が開始されます。 作成が完了すると、下図の表示となります。 FlutterFlowを既存のFirebaseと連携する場合 既存のFirebaseプロジェクトの プロジェクトID を入力する必要があるため、まずは連携したいFirebaseプロジェクトの管理コンソールからプロジェクトIDを取得します。FlutterFlowに戻り、取得したIDを入力して「Connect」をクリックします。すると、下記のようなエラーが表示されます。 これはFlutterFlowにFirebaseプロジェクトへのアクセスや操作の権限が与えられていないためです。そのため、既存のプロジェクトと連携する場合はFirebase管理コンソールからFlutterFlowに必要なアクセス権限を追加する必要があります。 下図のようにFirebase管理コンソールから「ユーザーと権限」タブに移動し、「メンバーの追加」ボタンをクリックします。 メールアドレスに firebase@flutterflow.io を入力し、役割は「編集者」を選択します。 設定後、「メンバーを追加」をクリックするとFirebaseのアカウントが追加されたことを確認できます。 FlutterFlowのセットアップ画面に戻り、再度「Connect」をクリックします。すると連携が成功します。 連携は成功しましたが、FirebaseのCloud Functionsという機能を使う場合は firebase@flutterflow.io に以下の2つのロールを追加します。 サービス アカウント ユーザー Cloud Functions 管理者 Cloud Functionsはイベントに対して特定の処理を実行できる機能です。例えば、「ユーザーがログインした際に自動で通知を送る機能を実装したい」場合はCloud Functionsを使用するために設定が必要になります。 追加するには、先ほどのFirebase管理コンソールの「ユーザーと権限」の右下にある「権限に関する詳細設定」のリンクをクリックして Google Cloud の管理画面に移動します。 firebase@flutterflow.io の右に表示されている鉛筆アイコンをクリックし、「別のロールの追加」から サービス アカウント ユーザー と Cloud Functions 管理者 を追加して保存します。 下図のようにロールが変更されていれば完了です。 3. FlutterFlowのプロジェクトの作成 最後に「Start Building」ボタンをクリックして完了です。これでFlutterFlowとFirebaseのプロジェクトの作成と連携が完了です。 実際にはFirebaseの各種サービス(認証やストレージ、データベースなど)を利用するにはFlutterFlowとFirebaseでさらに追加の設定が必要となります。詳細なステップについては、FlutterFlowの公式ドキュメントや FlutterFlow公式 YouTube動画 をご確認ください。 Firebase サービスとの連携 続いて、Firebaseの認証やデータベース、ストレージとの連携についても解説します。すでにFlutterFlowとFirebaseの接続と権限設定が済んでいるため簡単に連携が可能です。 事前準備 Firebaseのサービス(Firebase Authentication, Firestore Database , Cloud Storage)を使うための設定を行います。 FlutterFlowのFirebaseの設定画面を開き、プロジェクトIDの入力欄下にある「Generate Config Files」をクリックします。 これでFlutterFlowからFirebaseのサービスと連携するための準備が完了しました。 認証(Firebase Authentication)について 下図のAuthenticationのページから「Enable Authentication」トグルをオンにして認証を有効にします。 続いてFirebaseの設定画面を開き、「Enable Auth On Firebase」をクリックします。 すると、Firebase Authenticationの管理コンソール画面が開くので「始める」をクリックします。 「ログイン方法」タブ →「ネイティブのプロバイダ」→「メール/パスワード」を選択します。 続いて、メール/パスワードの「有効にする」トグルをオンにして保存します。 これで、FlutterFlowのプロジェクト内でメール/パスワードによる認証が使えるようになりました。 データベース(Firestore Database)について FlutterFlowのサイドメニューからFirestoreを選択肢、「+」ボタンをクリックします。 コレクションの入力モーダルが表示されるので、ユーザー情報用のコレクションを作成するため users と入力し、「Create」をクリックします。 FlutterFlowで用意しているユーザー用の設定を使うか確認されますが、設定の流れを確認するために「No, Thanks」を選択します。 users コレクションが正常に作成されました。 次に、どのようなデータ(ユーザーの名前やメールアドレスなど)を扱うかを設定できるフィールドを設定します。 FlutterFlowでは自分で必要なフィールドを1つずつ設定することはもちろん、AIの力を借りることやFlutterFlowで用意しているデフォルトの定義を利用することもできます。 今回はFlutterFlowの用意しているユーザー用の定義を利用します。 選択後、用意されていたフィールドが反映された users コレクションを確認できます。 次に、 誰がどのような権限 で users コレクションにアクセスできるのかを設定しましょう。 下図の設定ページへのリンクをクリックし、Firestoreの設定画面に移動します。 ここでは作成したコレクションへのアクセス権限の設定を行うことができます。作成するアプリの要件に応じて適切に設定してください。操作ごとにアクセス対象範囲は下記の4つが選択できます。 No One :誰もその操作を行うことができません。 Tagged Users : 指定したフィールド(nameやemailなど)にデータが登録されているユーザーだけ操作を行うことができます。 Authenticated Users : ログインしているユーザーのみ操作を行うことができます。 Everyone : 誰でも操作を行うことができます。 設定ができたら「Deploy」をクリックします。 設定するアクセス権限のルールが表示されますので、問題なければ「Deploy Now」をクリックします。 これでFirestore Databaseを利用できるようになりました。 ストレージ(Cloud Storage)について ストレージはファイルアップロード機能などを利用する場合のみ設定を行います。 まず、認証と同様にFlutterFlowのFirebaseの設定画面を開いて「Enable Storage On Firebase」をクリックします。 Cloud Storageの管理コンソール画面が開くので「始める」をクリックします。 「テストモードで開始する」を選択して「次へ」をクリックします。 リージョンの選択画面に移りますが、Firebaseのプロジェクトのリージョンが選択されているので「完了」をクリックします。 これでCloud Storageも利用できるようになりました。 使用例 ここではFirebase AuthenticationとFirestore Databaseの実際の使用例について解説します。 以下のページを作成して、簡易的なユーザーの新規登録機能とタスクの登録機能を実装します。 認証用ページ :新規登録、ログイン用のページ タスク一覧ページ :ログイン後に表示されるページ。登録したタスクの一覧を表示します。 タスク登録ページ :タスクを新規登録するためのページです。 コレクションの準備 ユーザー( users )とタスク( todos )のデータを管理するために2つのコレクションを作成します。 users はFlutterFlowで用意されているユーザー登録用のコレクションを利用します。 todos は「タスク名、ログインしているユーザーの情報、作成日時」を取得できるように設定します。 認証用ページ FlutterFlowでは便利なページテンプレートが用意されているためそちらを利用します。 認証用ページ 「Auth」の中から任意のものを選択して認証用のページを追加します。 テンプレート内ですでにログイン用のアクションが設定されているので、簡単に認証機能を実装できます。 テンプレートを利用すると、すでに認証に必要なアクションが設定されているため認証ページを簡単に作成できます。 タスク一覧ページ タスク一覧ページは空のページを作成します。ログインしたユーザーのメールアドレスを確認するための Text ウィジェット と登録したタスクの一覧を表示するための ListView ウィジェット を配置します。右上には、タスク登録ページへ遷移するための「+」アイコンを IconButton ウィジェット で配置します。 Text ウィジェット には、ログインしたユーザーのメールアドレス情報がテキストに反映されるように設定します。 ここに表示されるオプションは、先ほど作成した users コレクションに基づいています。 ListView ウィジェット には、 todos コレクションの情報が反映されるように設定します。 タスク登録ページ タスクを登録するためのページを作成します。タスクを入力するための InputField ウィジェット 、入力内容をチェックするための Form ウィジェット 、入力されたタスクを todos コレクションに登録するための Button ウィジェット を配置しているだけのシンプルなページです。 最後に、初期表示されるページとログイン後のページを設定しておきます。 動作確認 では、テストモードでアプリを起動して動作確認をしてみましょう。 テストモードは右上のアイコンから起動できます。 新規登録のフォームに必要事項を入力します。 「登録する」をクリックすると、タスク一覧ページに遷移します。登録したメールアドレスも反映されています。 右上の「+」アイコンよりタスク一覧ページへ遷移し、タスクを入力します。 「登録する」ボタンをクリックすると、タスク一覧ページへ遷移し、入力したタスクが表示されていることを確認できます。 Firestoreにデータが登録されているか確認してみましょう。 「Manage Content」よりFirestoreに登録されているデータを確認できます。 ユーザーのデータは下図のように表示されています。 タスクのデータは下図のように表示されています。 以上でFirebase AuthenticationとFirestore Databaseを利用できていることが確認できました。 Supabaseとの違い Firebaseの他に、SupabaseというBaaSサービスとFlutterFlowは連携が可能です。どちらも優れたバックエンド機能を有するサービスですが、FlutterFlow上では扱いが少し異なります。 Firebaseに関しては、画像やデータの追加、データへのアクセス設定などFirebaseの各種サービスをFlutterFlowのメニューから直接操作できます。 一方、Supabaseの場合はテーブル定義のみFlutterFlowで閲覧できるなど参照できる情報が限定的です。FlutterFlowと連携して扱うことができる機能に両者で大きく差はないものの、開発経験があまりない方はFirebaseで開発を始めることをおすすめします。 まとめ 今回は、FlutterFlowとFirebaseを連携する方法について、Firebaseの特徴から連携方法、Supabaseとの違いを解説しました。Firebaseを活用することでFlutterFlowでの開発を効率化し、認証やデータ管理の手間を省くことが可能です 次回は、FlutterFlowとFirebaseを利用した簡単な社内業務アプリを作成します。ここまで解説した内容を踏まえた記事となりますので、まだ読まれていない方はぜひ下記の記事も閲覧していただければ幸いです。 FlutterFlowとは?ノーコードでスマホアプリ開発を始める方法 FlutterFlow vs Adalo:ノーコードモバイルアプリ開発ツールの比較 FlutterFlowに制約はある?できることとできないこと 参考資料 FlutterFlow ドキュメント Firebase ドキュメント Supabase ドキュメント 私たちは共に働いていただける仲間を募集しています! みなさまのご応募、お待ちしています! 株式会社 電通総研 新卒採用サイト 執筆: @tokuyama.raido 、レビュー: @nagamatsu.yuji ( Shodo で執筆されました )
こんにちは。コーポレート本部 サイバーセキュリティ推進部の耿です。 ElastiCache for Valkey が 日本時間 2024/10/9 に利用できるようになりました 。Valkey とは、ライセンス変更が発生した Redis をフォークしたインメモリデータベースであり、今後も継続して OSS として使用できるよう開発を進めていくことが発表されています。 Redis の代替の選択肢となり得る ElastiCache for Valkey を早速 AWS CDK で作ってみました。 オンデマンド (Self-designed) クラスタを作成する Serverlessクラスタを作成する よもやま話 Valkey の Serverless は安い Node.js 用のクライアント オンデマンド (Self-designed) クラスタ を作成する ElastiCache for Valkey の公式アナウンスからも Serverless クラスタ がプッシュされているのだろうと想像できますが、Serverless ではないオンデマンド クラスタ も作ることができました。最新の ドキュメント では「Self-designed クラスタ 」と表現されているようです。 ElastiCache には L2 コンスト ラク トがないため、L1 で作成します。 import * as elasticache from "aws-cdk-lib/aws-elasticache" ; export class CacheConstruct extends Construct { constructor ( scope : Construct , id : string ) { super (scope, id); // ...(VPC, サブネット, SGの作成は省略) const description = "test-cache" ; new elasticache.CfnReplicationGroup( this , "ReplicationGroup" , { replicationGroupDescription : description, engine : "valkey" , // engine は valkey を指定 engineVersion : "7.2" , // engineVersion は 7.2 を指定すると作成できた cacheNodeType : "cache.t3.micro" , cacheSubnetGroupName : new elasticache.CfnSubnetGroup( this , "SubnetGroup" , { description , subnetIds : vpc.selectSubnets( { subnetGroupName : "private-subnet" } ).subnetIds, } ).ref, cacheParameterGroupName : new elasticache.CfnParameterGroup( this , "ParameterGroup" , { description , cacheParameterGroupFamily : "valkey7" , // パラメータグループは valkey7 を指定 } ).ref, numNodeGroups : 1 , replicasPerNodeGroup : 1 , securityGroupIds : [ mySecurityGroup.securityGroupId ] , atRestEncryptionEnabled : true , transitEncryptionEnabled : true , } ); } } マネジメントコンソールで確認すると、問題なく作成できていました。 Serverless クラスタ を作成する 続いてプッシュされている Serverless クラスタ も作成してみます。L1 の CfnServerlessCache コンスト ラク トを使用します。 ServerlessCache で特徴的なのは cacheUsageLimits パラメータです。Serverless クラスタ の場合、時間あたりの「データストレージ」と「コンピューティングリソース(ECPU)」によって課金額が変わります。 cacheUsageLimits を利用することにより、利用料が想定を超えないようリソース上限を設けることが可能です。Valkey のストレージの最小値は 100MB ですが、 cacheUsageLimits で設定できる「上限値」は現状 1GB でした。ただしこれはスケールした時の上限値なので、保管データ量が少なければ最小 100MB 分の料金しかかからないと思われます。 また、保管時と通信時の暗号化は指定する必要がなく、デフォルトで有効となっていました。 import * as elasticache from "aws-cdk-lib/aws-elasticache" ; export class CacheConstruct extends Construct { constructor ( scope : Construct , id : string ) { super (scope, id); // ...(VPC, サブネット, SGの作成は省略) const serverless = new elasticache.CfnServerlessCache( this , "ServerlessCache" , { serverlessCacheName : "serverless-valkey" , engine : "valkey" , // engine は valkey を指定 cacheUsageLimits : { dataStorage : { // データストレージの上限を指定 unit : "GB" , maximum : 1 , } , ecpuPerSecond : { // ECPUの上限を指定 maximum : 1000 , } , } , majorEngineVersion : "7" , subnetIds : vpc.selectSubnets( { subnetGroupName : "private-subnet" } ).subnetIds, securityGroupIds : [ mySecurityGroup.securityGroupId ] , } ); } } マネジメントコンソールで確認すると、こちらも問題なく作成できていました。 自動でマルチAZとなっているので高可用性が実現できています。 よもやま話 Valkey の Serverless は安い 公式アナウンス に customers can create a cache in under a minute and get started as low as $6/month. とある通り、Valkey を Serverless で使えば従来に比べてとても安く済む可能性があります。ElastiCache の 料金ページ に従って、東京リージョンにおける毎月のデータストレージの最小利用料を計算してみました。最小のデータストレージは 100 MB(0.1 GB)なので、 0.1 (GB) * 0.101 (ドル/ GB-hour) * 24 * 30 (hour/月) = 7.272 (ドル/月) となります。従来のオンデマンド クラスタ だと最小でも14.4 (ドル/月) かかるため、小規模なアプリケーションでも ElastiCache を利用しやすくなったと言えるでしょう。 (これにECPU料金が上乗せされますが、仮定を設けるのがちょっと難しいです。ただ小規模な利用であれば非常に安く済みます。) Node.js 用のクライアント アプリケーションから Valkey に接続するためのクライアントですが、Node.js の場合は ioredis からフォークした iovalkey があります。 参考: Getting started with Valkey using JavaScript ただし今のところ ioredis と大きな変更点はなさそうなので、基本的なオペレーションは ioredis をそのまま利用できました。(全てのオペレーションについては確認できていないため、利用の際には自己責任でお願いします。) iovalkey はまだメジャーバージョンが 1 に到達していないため、適切な時期に iovalkey に移行すると良いでしょう。 私たちは共に働いていただける仲間を募集しています! みなさまのご応募、お待ちしています! 株式会社 電通総研 新卒採用サイト 執筆: @kou.kinyo 、レビュー: @nagamatsu.yuji ( Shodo で執筆されました )
XI本部 プロダクト イノベーション センター アジャイル 開発グループの徳山です。 前回の記事「 FlutterFlow vs Adalo:ノーコードモバイルアプリ開発ツールの比較 」では人気のノーコード開発ツールのAdaloと比較することでFlutterFlowとの機能の違いやメリットを紹介しました。今回は、FlutterFlowの制約について焦点を当てることでFlutterFlowを利用した開発ではどのような注意点があるのか理解を深めていただきます。 はじめに 制約 各制約について 1. デザインの制約 タブバーのデザインが調整できない 多言語に対応していないウィジェットがある 2. ロジックの制約 制約例 標準でサポートしているバックエンドが限定的 エラー発生時の共通処理ができない リストの並び替えができない 開発環境に関する制約 制約例 ブラウザでは、テスト画面の表示に手間がかかる カスタムコードの利用には、FlutterやDartの知識を有する開発者が必要 複数人の開発では作業内容の管理に注意が必要 まとめ 参考資料 はじめに 本記事の目的は、FlutterFlowの制約を明らかにし、開発者が直面する可能性のある課題を理解するための情報を提供します。 FlutterFlowの基本的な知識をまだお持ちでない方は、まず前回の記事「 FlutterFlowとは?ノーコードでスマホアプリ開発を始める方法 」を読んでいただくことをお勧めします。 また、本記事は2024年10月現在の内容に基づいて作成しております。 制約 FlutterFlowには多くの機能やメリットがありますが、一方で以下のような制約もあるため、本格的な アプリ開発 を行う際には、それらに注意する必要があります。 デザインの制約 ロジックの制約 開発環境における制約 各制約について 1. デザインの制約 FlutterFlowは、 ドラッグ&ドロップ による直感的な GUI 操作で画面を作成できる点が大きな特徴です。 しかし、標準で用意されている ウィジェット のビジュアルデザイン調整には限界があり、カスタムコードでの調整が必要な場合があります。検証の中で実際に遭遇したデザイン制約例をいくつか示します。 タブバーのデザインが調整できない 上の図はとあるサンプルアプリのデザインとFlutterFlowで実際に作成した画面の比較画像です。タブバーの ウィジェット はFlutterFlowで用意されており簡単に実装できます。デザインではタブ(新着)の丸っぽい赤い下線がありこれを再現したかったのですが、FlutterFlowではカスタマイズができず再現ができませんでした。 多言語に対応していない ウィジェット がある FlutterFlowには動画プレイヤー用の ウィジェット も用意されています。しかし、再生スピードなどの設定項目が英語でしか表示されず日本語での表示に対応することができません。 2. ロジックの制約 複雑なロジックや独自の機能を実装したい場合、カスタムコードを利用しなければ解決できない(場合によっては利用しても解決できない)制約があります。例としては下記のようなものが挙げられます。 制約例 標準でサポートしているバックエンドが限定的 標準でサポートされているバックエンドサービス(BaaS)はFirebaseまたはSupabaseに限定されています。それ以外の認証サービスやデータベース、ストレージを利用することも可能ですが、「連携することが可能なのか」、「要件に必要な機能は利用できるのか」、「セキュリティ面に問題はないのか」といった項目を別途確認する必要があります。いずれのバックエンドサービスを利用する場合でも必要な機能がない場合はカスタムコードを書く必要があるので、却ってス クラッチ の開発より実装が大変になってしまうといったことも考えられます。 エラー発生時の共通処理ができない アプリ内でエラー(例外)が起きた場合にそれを一括で処理する共通の機能を実装することができません。例えば「〇〇のエラーが起きたらエラーページを表示する」ことを行いたい場合、そのエラーが起こる可能性がある箇所に個別で処理を実装する必要があります。こうした処理の共 通化 はカスタムコードを利用しても対応することはできません。 リストの並び替えができない FlutterFlowではリストの表示を行うために ListView という ウィジェット を利用できます。ListViewにはReorderbleという並び替えを可能にするためのプロパティが用意されているのですが、この標準プロパティだけでは並び替え機能を実装できません。実現するためには下記のようなカスタムコードを実装する必要があります。 List<MenuItemParamsStruct> reorderMenuItems( List<MenuItemParamsStruct> list, int oldIndex, int newIndex, ) { /// MODIFY CODE ONLY BELOW THIS LINE // If the item is being moved to a position further down the list // (i.e., to a higher index), decrement the newIndex by 1. // This adjustment is needed because removing an item from its original // position will shift the indices of all subsequent items. if (oldIndex < newIndex) { newIndex -= 1; } final newList = [...list]; // Remove the item from its original position in the list and store // it in the 'item' variable. final item = newList.removeAt(oldIndex); // Insert the removed item into its new position in the list. newList.insert(newIndex, item); // Return the modified list. return newList; /// MODIFY CODE ONLY ABOVE THIS LINE } このように、FlutterFlowで用意されている機能でもカスタムコードの利用が前提となっている場合があります。 開発環境に関する制約 上記以外の開発手法や体制面といった制約については以下のような例があります。 制約例 ブラウザでは、テスト画面の表示に手間がかかる テスト画面のビルドには2〜3分の時間がかかります。また、変更を反映するには都度リロードを行う必要があり、リロード後に画面が表示されるまで毎回10秒ほど時間がかかります。このように、ブラウザを利用した開発体験は快適とはいえません。 ちなみに、別途セットアップが必要になりますが、デスクトップアプリを利用したローカルでの開発機能( Local Run機能 )を利用することで変更を即座に反映した開発を行うことは可能です。 カスタムコードの利用には、Flutterや Dart の知識を有する開発者が必要 これまで見てきたようにFlutterFlowでモバイルアプリを開発する場合はカスタムコードを利用する場面が多くあります。特に複雑なデザインやロジックを実装する場合は避けられません。そのため、開発の経験が乏しいメンバーだけで凝ったアプリを開発したい場合はカスタムコードの実装難易度の高さから実現が難しい機能やデザインも出てくることを認識する必要があります。 複数人の開発では作業内容の管理に注意が必要 FlutterFlowではブランチ機能が用意されており、開発メンバーによって作業場所を分けながら安心して開発を進めることができます。2024年9月下旬に FlutterFlow5.0がリリース され、自分が新しくどこを開発したかが把握しやすくなりました。一方で、FlutterFlowは日々機能追加が行われているので、まれにブランチのマージ時にエラーが起きて失敗したりします。このため、万が一の デグレ ーション(作業の戻り)に備えてチーム開発では変更内容をきちんと頭に入れて置いたり、ソースを GitHub に連携するなどの予備的対策が必要です。 まとめ 今回は、FlutterFlowの制約についてみてきました。 前回の記事まではメリットを中心にお伝えしてきましたが、今回のようなデメリットや制約もFlutterFlowのモバイル アプリ開発 ではしっかりと理解しておく必要があります。 次回は、FlutterFlowと相性の良いBaaSであるFirebaseとの連携について解説します。 参考資料 FlutterFlow ドキュメント 執筆: @tokuyama.raido 、レビュー: @nakamura.toshihiro ( Shodo で執筆されました )
皆さんこんにちは。システム推進の佐藤太一です。 このエントリでは、 Windows 上にインストールした複数の JVM を上手く切り替える方法について説明します。 はじめに JBangのインストール JBangを使ったJavaのインストール デフォルトのJavaを設定する JBangを使ってJavaを切り替える PowerShellの補助関数を使って切り替える PowerShellのプロファイルを作りこんで自動で切り替える Start-ThreadJob を使う理由 バージョンの評価ロジックについて グローバル変数を使った処理回数の低減 類似するツール まとめ はじめに Java でアプリケーション開発をしていると、気が付いたらたくさんの JVM をインストールしていませんか? 私はCorretto やAdoptOpenJDKなど様々な ディストリビューション の Java 8、 Java 17、 Java 21、 Java 23をそれぞれインストールしています。 eclipse や IntelliJ といった IDE 上でのビルドでは、 IDE がランタイムの選択をサポートしてくれます。 Gradle や Maven にはtoolchainの仕組みがありますので、一旦ビルドが始まってしまえば、適切なランタイムが選択されるでしょう。 しかし、 Windows ではそこに至るまでに動作する JVM を上手く管理する方法が少ないです。 このエントリでは、 JBang を使って複数のバージョンの Java をインストールして管理する方法を説明します。 最後は Mac や Linux では日常的に行われているバージョンの自動切り替えについても、 Windows の PowerShell を使って実現する方法をご紹介します。 今回の説明で使う PowerShell は7.4系です。事前に PowerShell とscoopをインストールしておいてください。 Windows への PowerShell のインストール scoop JBangのインストール まずは、JBangをインストールしましょう。非常に丁寧に書かれたインストールマニュアルがあるので、それほど迷うことはないはずです。 cf. Installation 今回はscoopを使ってインストールしますので以下のコマンドを実行します。 scoop bucket add jbangdev https://github.com/jbangdev/scoop-bucket scoop install jbang JBang用の バケット を追加した上で、その バケット からインストールしていますね。 JBangを使った Java のインストール JBangをインストールしたら、次は Java をインストールします。 JBangで簡易的にインストールできる ディストリビューション はAdoptOpenJDKのみです。 それ以外の ディストリビューション をインストールしたいのであれば、別途インストールした上でJBangの管理下に置く必要があります。今回は簡易的なインストールだけを説明します。 例えば、 Java 8 をインストールするなら以下のコマンドを実行します。 jbang jdk install 8 次は、 Java 17と21をインストールしてみましょう。 jbang jdk install 17 jbang jdk install 21 ディストリビューション が固定されているので、コマンドが非常に簡潔ですね。 インストール済みの Java を一覧にしてみましょう。以下のコマンドを実行します。 jbang jdk list 私の環境では以下のように出力されます。 Installed JDKs (<=default): 8 (1.8.0_412) 17 (17.0.12+7) 21 (21.0.1+12-29) < 21 の右端に < が付いているのは、これをデフォルトの Java に設定しているからです。 デフォルトの Java を設定する では、JBangを使ってデフォルトの Java を設定しましょう。 jbang jdk default 21 これで、デフォルトの Java が21になりました。ついでに 環境変数 も追加しておきましょう。 JBangによってインストールした Java のフルパスを確認するには、以下のコマンドを実行します。 jbang jdk java-env これを実行すると、以下のように出力されます。 $env:PATH="C:\Users\taichi\.m2\jdks\jdk-21.0.1\bin;$env:PATH" $env:JAVA_HOME="C:\Users\taichi\.m2\jdks\jdk-21.0.1" # Run this command to configure your environment: # jbang jdk java-env | iex ユーザのホーム ディレクト リ以下にファイルが作成されている様子を確認できますね。 JBangは、 jdk java-env コマンドの実行結果をiexつまり、 Invoke-Expression することで実行環境を切り替えていくツールというわけです。 何もしていない時に動作する Java を指定するために、 Windows の 環境変数 を設定するツールでPATH 環境変数 と JAVA _HOME 環境変数 を設定しておきましょう。 JBangを使って Java を切り替える 次は、 PowerShell 上で利用する Java を切り替えてみましょう。 まず、 PowerShell のターミナルを開いて現在の Java を確認します。 C:\Users\taichi> java -version openjdk version "21.0.1" 2023-10-17 OpenJDK Runtime Environment (build 21.0.1+12-29) OpenJDK 64-Bit Server VM (build 21.0.1+12-29, mixed mode, sharing) PATH 環境変数 に Java 21が設定されているので、このように表示されます。 これを、 Java 17に切り替えてみましょう。以下のコマンドを実行します。 jbang jdk java-env 17 | iex これで切り替わりましたので、確認してみましょう。 C:\Users\taichi> java -version openjdk version "17.0.12" 2024-07-16 OpenJDK Runtime Environment Temurin-17.0.12+7 (build 17.0.12+7) OpenJDK 64-Bit Server VM Temurin-17.0.12+7 (build 17.0.12+7, mixed mode, sharing) 切り替わっていますね。 Maven やGradleが参照する JAVA _HOME 環境変数 も確認してみましょう。 C:\Users\taichi> $env:JAVA_HOME C:\Users\taichi\.jbang\cache\jdks\17 正しく切り替わっています。 PowerShell の補助関数を使って切り替える JBangを使った切り替えはコマンドが少し長いので、覚えていられないという問題があります。 そこで、 PowerShell のProfileという機能を使って切り替え用のコマンドを実装してみましょう。 プロファイルの詳細については、以下のドキュメントを参照してください。 プロファイルについて 要は $PROFILE でパスを確認できる PowerShell スクリプト にコードを書いておくと PowerShell が起動されるたびに、それが自動的に動く仕組みです。 プロファイルに以下のような関数を定義します。 function global:switchJava([string]$version) { jbang jdk java-env $version | iex java -version } 以下のコマンドを実行してプロファイルをリロードします。 . $PROFILE 補助関数を実行して利用する Java のバージョンを変更してみましょう。新しいターミナルを起動して、以下のコマンドを実行します。 switchJava 17 以下のように出力されて Java のバージョンが切り替わります。 C:\Users\taichi> switchJava 17 openjdk version "17.0.12" 2024-07-16 OpenJDK Runtime Environment Temurin-17.0.12+7 (build 17.0.12+7) OpenJDK 64-Bit Server VM Temurin-17.0.12+7 (build 17.0.12+7, mixed mode, sharing) PowerShell のプロファイルを作りこんで自動で切り替える 補助関数でのバージョン切り替えは便利ですが、ターミナルを起動するたびに利用するべき Java のバージョンを確認して切り替えていくのは面倒です。 現在の ディレクト リ内にある設定ファイルを見て利用する Java を自動的に切り替えてほしいですよね。 Windows 以外の環境で動作する bash や zsh といったシェルでは、例えば .java-version のようなファイルの存在確認をしてその中身によってバージョンを切り替えるという事が一般的に行われています。 Windows ではあまり広く行われていませんが、 PowerShell を使えば実装可能であることを紹介します。 まずは、プロファイルに以下のコードをそのまま追加します。 ただし、既にプロファイルをカスタマイズしている人は global:prompt の編集だけ注意してください。 要は、prompt関数の好きな場所に autoJava を追加すれば動作します。 <# Copyright 2024 DENTSU SOKEN INC. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. #> function global:prompt { $origLastExitCode = $LASTEXITCODE autoJava $LASTEXITCODE = $origLastExitCode } function switchJava([string]$version) { $SB = { param([Parameter(Mandatory = $true)] $version) jbang jdk java-env $version if ($LASTEXITCODE -ne 0) { throw "jbang jdk java-env command failed with exit code $LASTEXITCODE" } } $output = Start-ThreadJob -ScriptBlock $SB -ArgumentList $version | Receive-Job -Wait $output -join "`n" | iex java -version } $global:lastKnownLocation = "" function autoJava { $p = $PWD.Path if ($p -ne $global:lastKnownLocation) { guessJava $global:lastKnownLocation = $p } } function guessJava { $versionFile = Join-Path -Path $PWD -ChildPath ".java-version" if (Test-Path $versionFile) { $content = Get-Content $versionFile $version = $content.Trim() if (findJava $version -eq $true) { $res = switchJava $version } else { Write-Host ".java-versionファイルでは $version が指定されていますが、そのバージョンのJavaはインストールされていません。" Write-Host "jbang jdk install $version を実行するとインストールできるかもしれません。" } } else { useDefaultJava } } function useDefaultJava { foreach ($tup in listJava) { if ($tup.IsDefault -eq $true) { switchJava $tup.Label return } } } function findJava([string]$version) { foreach ($tup in listJava) { if ($tup.Label -eq $version) { return $true } if ($tup.FullVersion -eq $version) { return $true } if ($tup.FullVersion.StartsWith($version)) { return $true } } return $false } function listJava { $SB = { jbang jdk list if ($LASTEXITCODE -ne 0) { throw "jbang jdk list command failed with exit code $LASTEXITCODE" } } $output = Start-ThreadJob -ScriptBlock $SB | Receive-Job -Wait return $output | Select-Object -Skip 1 | ForEach-Object { if ($_ -match '^\s*(\d+)\s+\(([\d\._\+\-]+)\)\s*(<)?\s*') { [PSCustomObject]@{ Label = $Matches[1] FullVersion = $Matches[2] IsDefault = $Matches[3] -eq "<" } } } } コードの細かい処理内容については説明しませんが、いくつかある奇妙な部分について説明します。 Start-ThreadJob を使う理由 jbangコマンドが PowerShell スクリプト だからです。 prompt関数から PowerShell スクリプト が推移的に呼び出されると、呼び出された スクリプト の終了時点で解釈が終了するのです。 私の場合は、 posh-git などを使ってプロンプトを装飾しています。 prompt関数の戻り値がないと、デフォルトのプロンプトになってしまうので困ります。 というわけで、jbangコマンドをジョブとして実行してその結果の標準出力だけを使っているのです。 バージョンの評価ロジックについて findJava関数に実装してあるバージョンの評価ロジックは非常に単純なものです。 JBangでインストールされているバイナリのメジャーバージョン番号との完全一致 JBangでインストールされているバイナリの詳細なバージョン番号との完全一致 JBangでインストールされているバイナリの詳細なバージョン番号との前方一致 . java -versionに記載されているバージョン番号は多くの場合に、メジャーバージョン番号のみです。 Java は非常に高度な互換性を保ちながら開発されているので、日常的な開発において細かいリビジョン番号やパッチ番号を気にする必要はないと考えています。 もし細かい処理が必要な方はこのコードを是非改善して、その内容をブログに書いて貰えるとありがたいですね。 グローバル変数 を使った処理回数の低減 prompt関数は、 PowerShell のプロンプトが表示されるたびに実行される関数なので非常に実行回数が多いものです。 なので、カレント ディレクト リが変更されるまでは Java のバージョンを確認する処理をしないようにしてあります。 そのために使っている変数が lastKnownLocation です。 類似するツール JEnv-for-Windows SDKMAN mise spack まとめ このエントリでは、JBangとそれを使った PowerShell スクリプト を紹介しました。 この スクリプト は少し応用すれば、nodeや Python といった他の言語でも利用できるものです。 このエントリによって、 Windows 環境で快適に開発できる技術者が少しでも増えることを願っています。 私たちは共に働いていただける仲間を募集しています! みなさまのご応募、お待ちしています! 株式会社 電通総研 新卒採用サイト 執筆: @sato.taichi 、レビュー: @yamashita.tsuyoshi ( Shodo で執筆されました )
XI本部 プロダクト イノベーション センター アジャイル 開発グループの徳山です。 前回の記事「 FlutterFlowとは?ノーコードでスマホアプリ開発を始める方法 」ではFlutterFlowについての特徴や機能といった基本知識を紹介しました。今回は、FlutterFlowを同じく人気のあるノーコードツールであるAdaloと比較することで両者の特徴や違いを解説します。よりFlutterFlowへの理解を深める助けになれば幸いです。 はじめに Adaloの概略 FlutterFlowとAdaloの違いについて Adaloの特徴 シンプルなビジュアルエディター 内蔵データベース 各ツールに適した場面 FlutterFlowが適している場面 Adaloが適している場面 まとめ 参考資料 はじめに 本記事の目的は、FlutterFlowとAdaloの特徴や機能を比較し、FluterFlowにどのような強みや弱みがあるのかを理解するための情報を提供します。 FlutterFlowの基本的な知識はある上で、他のローコードツールと具体的にどのような違いがあるのかについて興味がある方を対象としています。 Adaloの概略 Adalo(アダロ) は、FlutterFlowと同じく ドラッグ&ドロップ のビジュアルエディターでモバイルアプリを開発できます。異なる点としてはコードによる機能追加が提供されていないためノーコードでの開発となります。また、最初からデータベースが提供されておりUIのデザインからデータベース設定まで一貫して行うことができる点も異なります。FlutterFlowより用意されている標準の ウィジェット 数やアクション数は少ないですが、その分シンプルなため非エンジニアの方でも手軽に アプリ開発 を始めることができます。 Adaloを利用した アプリ開発 者数の公開はありませんが、Adaloで作成されたアプリの数は100万以上、アプリのエンドユーザー数は200万人以上と多くの利用者に支持されていることが伺えます。 FlutterFlowとAdaloの違いについて 各サービスの代表的な違いについては下表となります。 項目 FlutterFlow Adalo サービス開始 2020 2018 価格(月払い) $30〜 $45〜 アプリの開発言語 Flutter React Native(カスタムコード不可) 対応プラットフォーム iOS 、 Android 、Web、デスクトップ( Windows 、 macOS 、 Linux ) iOS 、 Android 、Web(PWA) ビジュアルエディター Flutter製のモダンな ウィジェット を利用して柔軟なUIデザインが可能 スタイルの制限はあるが、シンプルで直感的なUIデザインが可能 ウィジェット / コンポーネント 豊富な ウィジェット とカスタム コンポーネント の作成が可能 基本的な コンポーネント がそろっているが種類は限定的 バックエンド 外部サービス(Firebase、Supabaseなど)と連携が必要 内蔵データベースを使用可能 独自のロジック カスタムコード( Dart )により挿入可能 カスタムコードの挿入は不可 学習コスト 中程度( Dart やBaaSの知識があると有利) 低い(プログラミング知識不要) コードのエクスポート 可能 不可 拡張性 高い(カスタムコードと外部サービス連携で拡張可能) 低い(プラットフォーム内の機能に制限される) Adaloの特徴 シンプルなビジュアルエディター FlutterFlowと比較すると ツールバー の表示項目(履歴管理や開発者向けのメニュー など)や、 コンポーネント のスタイルプロパティの表示位置が変わったシンプルなエディター画面となります。 FLutterFlowと異なり複数画面を俯瞰しながらデザインができますが、その分画面数が増えると管理が大変になります。 標準の ウィジェット 数は50種類に満たないですが、 マーケットプレイス で無料の ウィジェット が多く用意されているためインストールして利用できます(有料のものもあります)。 一方で、FlutterFlowでは柔軟なスタイル変更が可能でしたがAdaloでは「誰でも簡単に」といったアプリ設計となっているため高度なスタイルのカスタマイズには対応できません。例えば、要素間で〇〇pxの余白を取りたいといった具体的な指定ができないといったことやモバイルヘッダーの高さを細かく調整できないといった制約があります。 内蔵データベース Adalo自身が独自のデータベース機能を持ち、FutterFlowのように外部サービスの利用を前提とした作りになっていません。もちろんAdaloの API で サードパーティ サービスや独自サーバーに接続することは可能です。 各ツールに適した場面 これまでの違いから、それぞれに適した場面は下記の通りです。 FlutterFlowが適している場面 高度なデザインやロジック、独自の機能が求められるアプリ マルチプラットフォーム での対応が必要なアプリ 将来的にコードをエクスポート・拡張したい場合 Adaloが適している場面 シンプルなデザインや機能が限定されたアプリ 開発未経験のメンバーのみでアプリを開発する場合 内蔵データベースを利用して、簡単にデータ管理を行いたい場合 まとめ ここまでAdaloの特徴やFlutterFlowとの違いについてみてきました。 Adaloの他にも私たちのグループでは複数のノーコード・ローコードツールについて調査しましたが、カスタマイズ性や機能性といった点からモバイルアプリ向けではFlutteFlowが最も適していると判断しました。もちろんこれは私たちが業務アプリを扱うことが多いためなので、読者の方の中にはAdaloの方が適している場合もあるでしょう。 それぞれの特徴を捉えた上で、プロジェクトの目的やニーズに合わせて適切なツールを選択することが重要です。 次回はFlutterFlowの具体的な制約について触れ、FlutterFlowでモバイル アプリ開発 を行う上での注意点について解説いたします。 参考資料 FlutterFlow ドキュメント Adalo 公式サイト Adalo ドキュメント 私たちは共に働いていただける仲間を募集しています! みなさまのご応募、お待ちしています! 株式会社 電通総研 新卒採用サイト 執筆: @tokuyama.raido 、レビュー: @miyazawa.hibiki ( Shodo で執筆されました )
はじめに 背景 Azure Data Factory利用時の注意点 Azure DatabricksとAzure Data Factoryの比較 Azure Databricksの利用方法 Azure Databricksの作成 クラスターの作成 PySparkの記述方法 storesコレクション ordersコレクション merged_storesコレクション 終わりに はじめに 電通 総研XI本部AIトランスフォーメーションセンターの岩本です。この記事では、Azure Cosmos DB for MongoDBのデータベース移行手段としてAzure DatabricksとAzure Data Factoryを取り上げ、それぞれの方法のメリット・デメリットを比較します。また、Azure Data Factoryを用いた具体的な実装例を紹介します。 背景 AIトランスフォーメーションセンターでは、Azure OpenAI Serviceを活用したAIチャット・RAGの製品であるKnow Narratorを開発しています。Know NarratorのバックエンドではスケーラブルなNoSQLデータベースであるAzure Cosmos DB for MongoDBを利用しています。理由としては以下の2点です。 Know Narratorのユーザー数は導入いただいているお客様によって様々であり、DBはスケーラブルである必要がある 頻繁なアップデートで後から機能を追加することを想定しているため、DB スキーマ は柔軟に変更可能である必要がある AIトランスフォーメーションセンターでは、今年3月にデータベース移行を伴うKnow Narratorの大型アップデートを顧客に提供しました。データベース移行手段として当初はAzure Data Factoryを検討していましたが、Data Factory上でのUUIDの取り扱いに制限があることが分かったため、最終的にはAzure Databricksを利用することに決定しました。 Azure Data Factory利用時の注意点 UUIDはMongoDB上では binary と type の2つのフィールドを持つオブジェクトとして表現されます。 type はUUIDの生成方法の違いを表しており、これが異なるとUUIDの一意性を維持できません。 CosmosDB for Mongo API に対しData Factoryを利用する際の注意として、元々DBに type=4 として保存している値が、Data Factory上にデータを読み出す際に type=3 として認識されてしまいます。Data Factory上で type を書き換えることはできますが、DBに書き出す際に再度 type=3 となってしまいます。 Microsoft サポートによると、これはData FactoryのCosmosDB for MongoDBコネクタの仕様であり、解消するには書き込み後にCosmosDB側で type を書き換えるコマンドを実行する必要があるとのことでした。 マイグレーション 作業手順が複雑になることを避けるため、今回はData Factoryを利用しませんでした。 Azure DatabricksとAzure Data Factoryの比較 以下のようにAzure DatabricksとAzure Data Factoryはそれぞれ異なる目的と機能を持っています。 Azure Databricks: 高度な分析、データサイエンス、 機械学習 のためのプラットフォーム。 Apache Sparkベースで、高速な ビッグデータ 処理が可能。 ノートブック環境を提供し、データ探索、視覚化、モデルのト レーニン グが容易。 Python 、 Scala 、 SQL 、Rなど多くの言語をサポート。 Azure Data Factory: データ統合とETL(Extract, Transform, Load)パイプラインの構築に特化。 データの移動、変換、 オーケストレーション を視覚的にデザイン可能。 さまざまなデータソース(オンプレミスや クラウド )と連携。 定義されたスケジュールやイベントに基づいたデータパイプラインの実行。 Databricksはデータ処理エンジンとして Apache Sparkを使用しており、Data Factoryに比べて非常に高速にデータ処理を行うことができます。また、料金体系に関してもDatabricksがランタイムの稼働時間のみに課金されるのに対し、Data Factoryはランタイムの稼働時間に加えてデータ量や計算量に応じた課金となるため、一度に大量のデータを処理する場合にはDatabricksが適していると言えます。 また、Databricksは Python や SQL で処理を記述できるため複雑なデータ操作に適しています。Data Factoryは GUI で直感的に処理フローを構成できますが、その分処理の自由度は落ちます。今回のDB マイグレーション では単純にデータを移行するだけでなく、あるコレクションのドキュメントを別のコレクションのドキュメントのフィールドの 入れ子 にするなどある程度複雑な操作が伴いました。このような操作はData Factoryでも実現不可能ではありませんが、複雑な操作は GUI ではかえって時間がかかってしまうためDatabricksを選択しました。 Azure Databricksの利用方法 Azure Databricksの作成 Azure Portal 上でリソースを作成します。 DatabricksからCosmosDBに接続するには、DatabricksのリソースをCosmosDBと同じVNetに配置する(VNetインジェクション)必要があります。 DatabricksのVNetインジェクションでは2つのサブネット(コンテナサブネットとホストサブネット)を利用するため、これらのサブネットを新たにCosmosDBが配置されているVNet上に作成する必要があります。サブネットの範囲はDatabricksで使用できる クラスタ ーノード数に影響するため、 /26 より小さいサブネットは推奨されません。 サブネット範囲と クラスタ ーノード数の具体的な関係については以下のページに記載されています。 learn.microsoft.com クラスタ ーの作成 ワークスペース を起動し、コンピューティング クラスタ ーを作成します。デフォルトの設定値でも特に問題はありませんが、ワーカータイプを安価なものに変更したり、開発環境であればスポット インスタンス を選択するなどしてコストを抑えることができます。 クラスタ ー作成後、ライブラリタブの[新規をインストール]をクリックし、以下の Maven 座標を使って Apache SparkとMongoDBのコネクタをインストールします。 org.mongodb.spark:mongo-spark-connector_2.12:3.0.1 ノートブックを作成し、[接続]をクリックして先ほど作成した クラスタ ーを選択します。 クラスタ ーの起動が完了していれば以下のように クラスタ ー名が表示され、 Python コードが実行可能な状態となります。 ![]( https://media.shodousercontents.com/task_images/983/14ccd520-da84-472e-b3b1-0985c4fea8ec.png PySparkの記述方法 今回、具体的なデータ操作の記述には Apache Sparkの Python API であるPySparkを使用します。Pandasのデータフレームと同じような要領でデータを操作することができ、Pandasを使ったことがある場合はそれほど学習コストをかけずに利用できます。 2つのコレクション (stores, orders) を結合し、ネストされたフィールドをもつコレクションmerged_storesを作成するというシナリオでサンプルコードを以下に示します。 storesコレクション _id store_id phone-number region 60c5ba5e4f1a2f6d2c9b7f92 {"type": 4, "data": "U3RvcmUx"} 123-456-7890 North 60c5ba5e4f1a2f6d2c9b7f93 {"type": 4, "data": "U3RvcmUy"} 987-654-3210 South ordersコレクション _id order_id price created_at store_id 70d5ba6e4f1a2f6d2c9b7f94 {"type": 4, "data": "T3JkZXIw"} 100 2021-06-13 12:00:00 {"type": 4, "data": "U3RvcmUx"} 70d5ba6e4f1a2f6d2c9b7f95 {"type": 4, "data": "T3JkZXIx"} 150 2021-06-14 13:00:00 {"type": 4, "data": "U3RvcmUx"} 70d5ba6e4f1a2f6d2c9b7f96 {"type": 4, "data": "T3JkZXIy"} 200 2021-06-15 14:00:00 {"type": 4, "data": "U3RvcmUy"} 70d5ba6e4f1a2f6d2c9b7f97 {"type": 4, "data": "T3JkZXIz"} 250 2021-06-16 15:00:00 {"type": 4, "data": "U3RvcmUy"} merged_storesコレクション _id store_id phone-number region orders 60c5ba5e4f1a2f6d2c9b7f92 {"type": 4, "data": "U3RvcmUx"} 123-456-7890 North { id: 70d5ba6e4f1a2f6d2c9b7f94, order_id: {"type": 4, "data": "T3JkZXIw"}, price: 100, created_at: 2021-06-13 12:00:00 }, { id: 70d5ba6e4f1a2f6d2c9b7f95, order_id: {"type": 4, "data": "T3JkZXIx"}, price: 150, created_at: 2021-06-14 13:00:00 } 60c5ba5e4f1a2f6d2c9b7f93 {"type": 4, "data": "U3RvcmUy"} 987-654-3210 South { id: 70d5ba6e4f1a2f6d2c9b7f96, order_id: {"type": 4, "data": "T3JkZXIy"}, price: 200, created_at: 2021-06-15 14:00:00 }, { id: 70d5ba6e4f1a2f6d2c9b7f97, order_id: {"type": 4, "data": "T3JkZXIz"}, price: 250, created_at: 2021-06-16 15:00:00 } # 必要なライブラリをインポート from pyspark.sql import SparkSession from pyspark.sql.functions import collect_list, struct from pyspark.sql.types import ( BinaryType, ByteType, IntegerType, StringType, StructField, StructType, TimestampType, ) # データベース接続に必要な情報を設定 src_connection_string = "<移行元DBの接続文字列>" dest_connection_string = "<移行先DBの接続文字列>" source_db = "<移行元DB名>" target_db = "<移行先DB名>" stores_collection = "stores" orders_collection = "orders" merged_stores_collection = "merged_stores" # SparkSessionの初期化 my_spark = SparkSession.builder.appName( "myApp" ).getOrCreate() # storesコレクションのスキーマを定義 stores_schema = StructType( [ StructField( "_id" , StructType([StructField( "oid" , StringType(), True )]), True ), StructField( "store_id" , StructType( [ StructField( "subType" , ByteType(), False ), StructField( "data" , BinaryType(), True ), ] ), True , ), StructField( "phone-number" , StringType(), True ), StructField( "region" , StringType(), True ), ] ) # storesコレクションからデータを読み込み df_stores = ( my_spark.read.schema(stores_schema) .format( "com.mongodb.spark.sql.DefaultSource" ) .option( "uri" , src_connection_string) .option( "database" , source_db) .option( "collection" , stores_collection) .load() ) # ordersコレクションのスキーマを定義 orders_schema = StructType( [ StructField( "_id" , StructType([StructField( "oid" , StringType(), True )]), True ), StructField( "order_id" , StructType( [ StructField( "subType" , ByteType(), False ), StructField( "data" , BinaryType(), True ), ] ), True , ), StructField( "price" , IntegerType(), True ), StructField( "created_at" , TimestampType(), True ), StructField( "store_id" , StructType( [ StructField( "subType" , ByteType(), False ), StructField( "data" , BinaryType(), True ), ] ), True , ), ] ) # ordersコレクションからデータを読み込み df_orders = ( my_spark.read.schema(orders_schema) .format( "com.mongodb.spark.sql.DefaultSource" ) .option( "uri" , src_connection_string) .option( "database" , source_db) .option( "collection" , orders_collection) .load() ) # 初期状態のstoresデータフレームの列名を保存 stores_new_columns = df_stores.columns # 結合時に列名の重複を避けるためstoresデータフレームの列名を変更 df_stores = df_stores.toDF( *[column_name + "_stores" for column_name in df_stores.columns] ) # storesデータフレームとordersデータフレームを結合 df_joined = df_stores.join( df_orders, df_stores.stores_id_stores == df_orders.stores_id, "left_outer" , ) # stores_idを除外したうえでordersをグループ化 orders_new_columns = df_orders.columns orders_new_columns.remove( "stores_id" ) df_merged_stores = df_joined.groupBy(df_stores.columns).agg( collect_list(struct(orders_new_columns)).alias( "orders" ) ) # 列名リストにordersを追加したうえで重複を避けるために変更した列名を元に戻す stores_new_columns.append( "orders" ) df_merged_stores = df_merged_stores.toDF(*stores_new_columns) # 結合されたデータを新しいコレクションに保存 df_merged_stores.write.format( "mongo" ).mode( "append" ).option( "uri" , dest_connection_string ).option( "maxBatchSize" , 1024 ).option( "database" , target_db).option( "collection" , merged_stores_collection ).save() 注意すべき点として、ネストされたフィールドをもつコレクションは読み込み時に スキーマ が自動で推論されません。 スキーマ を指定しないと、ネストされたフィールドの値は構造化されたデータではなくただのテキストとして扱われてしまいます。これを避けるため、サンプルコードではDBからのデータ読み込み時に スキーマ を指定するようにしています。 終わりに この記事ではAzure Cosmos DB for MongoDBのデータベース移行に関してAzure DatabricksとAzure Data Factoryを比較し、Azure Databricksを使った実装例を紹介しました。最後までご覧いただきありがとうございました。 私たちは一緒に働いてくれる仲間を募集しています! AI系プロジェクトマネージャー/リーダー(◎AIコンサル ◎AIプロジェクトマネージャー) AIサービス開発エンジニア 執筆: @iwamoto.yoshik85ca341e9dca4b22 、レビュー: @miyazawa.hibiki ( Shodo で執筆されました )