TECH PLAY

KINTOテクノロジーズ

KINTOテクノロジーズ の技術ブログ

936

はじめに 初めまして、KINTOテクノロジーズ株式会社(以降、KTC)でプラットフォームグループのCloud Infrastructure Teamでクラウドインフラエンジニアをしている白井です。 普段はAWSで構築されているシステムのインフラ構築、および設計を行っています。趣味は、卓球とゲームです。最近だとスーパーマリオRPGがリメイクされたのを購入し、思い出に浸りながらプレイしています。 今回は、KTCで構築しているCloudFront FunctionsのDeployのプロセスと運用カイゼンをしたお話について、背景も含めてご紹介します! KTCのCloud Infrastructure Teamについて 本題に入る前に、私たちのチームについて補足させていただきます。 KTC ではインフラの構築を Terraform を使用した IaC で管理しています。 歴史的背景など詳しくは同じチームの 島川さん が Terraform を抽象化し環境構築の工数を削減する取り組みについて という資料を公開していますのでぜひそちらをご確認ください。 現状の課題 KTCでは現在、一部のシステムにおけるリダイレクト処理などでCloudFront Fucntions(以降、CF2)を利用しています。 CloudFrontで利用できるエッジ関数 というタイトルでCF2について、同じチームメンバの井木さんが紹介しているので、ぜひご覧になってください。 さて、KTCではCF2を利用する中で、以下3点が課題として上がってきました。 Application TeamとCloud Infrastructure Teamのコミュニケーションコストが大きい Application TeamにCloudWatch Logsに出力されるログの閲覧権限を付与できていない CloudWatch Logsに出力されるログが失効されない状態で残る この三つの課題を解決します。 課題の深掘り 1. コミュニケーションコストが大きくなっている課題 今までのCF2が適用までのプロセスは以下になります。 今までのDeployまでのプロセス DeployがCloud Infrastructure Teamに依存している影響で、CF2のソースコードに問題があった際に、再度上の図の(2)~(4)をCloud Infrastructure Teamにて実施する必要があります。 このフローの問題点としては、 CF2の更新がCloud Infrastructure Teamに依存していること CF2の更新時に、Cloud Infrastructure Teamも影響範囲を確認し、Application Teamとの調整が必要になること 上記二点により、コミュニケーションコストが大きくなっていました。 2. Application Teamがログを閲覧できない課題 KTCでは、Application Teamに引き渡す権限を強く絞っています。その結果、CF2のログの閲覧権限がなく、見えなくなっていました。この状況では、CF2における問題発生時にApplication Teamは調査することができません。 3. CF2のログが恒久的に残る課題 現状、CloudWatchのロググループを設定せず、CF2を構築していました。 CF2の仕様上、CF2のログが出力された際に自動的にus-east-1リージョンのCloudWatchLogsに /aws/cloudfront/function/${FunctionName} というロググループが作成されます。この状況では、ロググループは失効期間が設定されていないため、残り続けコストが嵩んでしまいます。 解決策 問題と解決策を以下にまとめました。 課題 課題 解決策 1 コミュニケーションコストが大きい Application Teamに追加権限を付与し、任意のタイミングでDeployできるようにする 2 Application Teamがログを閲覧できない Application Teamにログ閲覧権限を追加する 3 CF2のログが恒久的に残る 失効期間付きのロググループを先に作成しておく では、それぞれの解決策について深掘りしていこうと思います。 課題1: コミュニケーションコストが大きい 解決策でも述べたように、方針としてはApplication Teamが任意のタイミングでDeployできるようにすることです。 そこで、Deployするまでのプロセスを一新しようと思いました。 まずは、CF2構築前の構成例とプロセスを一新後の構成例をお見せします。 CF2構築前構成例 最終構成例 CF2のDevelopment StageとLIVE Stageについて、補足します。LIVE Stageは実際にCloudFrontに紐づけられて動作しているCF2となります。それとは別にDevelopment Stageでは主に開発用途として使われ、LIVE Stageで流入してくるリクエストの検証が実施できます。 次に、赤文字で記載されているメンテナンスロールとCICDユーザについて少しだけ触れさせていただきます。 メンテナンスロールとCICDユーザ それぞれ以下の役割です。 メンテナンスロールの役割 AWSマネージメントコンソール上での各種AWSサービスの閲覧・更新をすることです。 KTCにおいて、AWSマネージメントコンソールにログインする際には、環境ごとに用意されているアカウントにSSOログインをします。SSOログインをした先で適切に権限を絞られているメンテナンスロールにスイッチロールすることで必要なAWSサービスの閲覧や更新を手動で行うことができます。 同じアカウント内にはさまざまなプロダクトが存在しているため、誤操作防止のため、閲覧・更新権限についても強めの制限をしています。 CICDユーザロールの役割 Github ActionsなどのCICDツールを使用した各種AWSサービスの更新をすることです。 Applicationのデプロイで使用する権限を設定しています。各プロダクトが使用するAWSリソースによって付与する権限を決めています。例えばLambdaとECSをデプロイするプロダクトにはそれをデプロイできる権限を与え、ECSのみをデプロイするプロダクトにはECSのみをデプロイできる権限を与えています。 既存のメンテナンスロールとCICDユーザはCF2の権限が付与されていなかったので、下記権限を追加しました。 { "Action": [ "cloudfront:UpdateFunction", "cloudfront:TestFunction", "cloudfront:PublishFunction", "cloudfront:ListFunctionTestEvent", "cloudfront:GetFunction", "cloudfront:DescribeFunction", "cloudfront:DeleteFunctionTestEvent", "cloudfront:CreateFunctionTestEvent" ], "Effect": "Allow", "Resource": "arn:aws:cloudfront::{AccountID}:function/${aws:PrincipalTag/environment}-${aws:PrincipalTag/sid}-*", "Sid": "" }, { "Action": [ "cloudfront:ListFunctions" ], "Effect": "Allow", "Resource": "*", "Sid": "" } 余談ですが、CF2にはDevelopment StageでLambdaのようにテストリクエストを投げることができます。その中で*TestEventの権限が必要だったのですが、 公式ドキュメント にはそのアクションの記載がされておらず、CloudTrailを頼りに必要な権限を追加していきました。公式ドキュメントが全てではないことに気づくよい例だなと思いました。 次にCloud Infrastructure TeamとApplication Teamの分担について述べていきます。 Cloud Infrastructure TeamとApplicaiton Teamの役割分担 実施作業 Cloud Infrastructure Team Applicaiton Team CF2の権限付与 ○ - サンプルアプリのCF2の作成とCloudFrontへの紐付け ○ - CF2の開発、LIVE Stageへのpublish - ○ CF2の運用・監視 - ○ では、実際にLIVE StageへのDeploy(Publish)までのプロセスを見ていきましょう。 Deployプロセス 1. Application TeamがCloud Infrastructure Teamへ構築を依頼 以下のテンプレートを元に、Jiraベースでチケットを発行していただきます。 CF2の命名: hogehoge e.g.) redirect-cf2 構築する環境一覧: xxx 関連づけるCloudfFrontのARN: arn:aws:cloudfront::{AccoutID}:distribution/{DistributionID} e.g.) arn:aws:cloudfront::111111111111:distribution/EXXXXXXXXXXXXX 関連づけるcache behavior ビューワーリクエスト ビューワーレスポンス hogehoge ○ - 2. Cloud Infrastructure Teamが構築 Cloud Infrastructure Teamで作成したサンプルアプリ(リクエストスルー)のCF2をCloudFrontのビヘイビアに紐付け Application Teamに開発とDeployのための権限をメンテナンスロールとCICDユーザに付与 function handler(event) { var request = event.request; return request; } Cloud Infrastructure Teamが必要なリソースを更新・作成。赤枠が対象。 3. Application TeamがCF2のコードをDevelopment Stageにpublishする。 Development Stageへのソースコード更新方法は下記の通りです。 メンテナンスロールを用いた、AWS マネージドコンソール上からの手動実行 CICDユーザのクレデンシャルを用いた、Github ActionsなどのCI/CDツールを使用した適用 AWSマネージドコンソール上またはCI/CDツールでテストの実施が可能です。 開発とテスト 4. Application TeamがCF2のコードをLIVE Stageにpublishする。 LIVE StageへのpublishもDevelopment Stage への適用と同様にAWS マネージドコンソール、もしくはGithub ActionsなどのCI/CDツールから実行できます。 最終構成 課題2: Application Teamがログを閲覧できない。 ロググループへの閲覧権限を付与します。 { "Action": [ "logs:StartQuery", "logs:GetLogGroupFields", "logs:GetLogEvents" ], "Effect": "Allow", "Resource": "arn:aws:logs:us-east-1:{AccountID}:log-group:/aws/cloudfront/function/${aws:PrincipalTag/environment}-${aws:PrincipalTag/sid}-*-cloudfront-function:log-stream:*", "Sid": "" } メンテナンスロールにおいて、上記のようにロググループの閲覧権限とログのインサイトの閲覧権限を付与しているため、ログが見えるようになりました。 その結果として、問題発生時にApplication Teamが主導で問題発生に取り組めるようになれたと思います。 課題3: CF2のログが失効されない状態で残る。 CF2構築時に併せてCloudWatchLogグループを作成するようにしました。 これは、CF2が作られる過程で参照するモジュールの中に記載することで実現しました。 resource "aws_cloudwatch_log_group" "this" { name = "/aws/cloudfront/function/${local.function_name}" retention_in_days = var.cwlogs_retention_in_days == null ? var.env.log_retention_in_days : var.cwlogs_retention_in_days } まとめと最後に 今回、CF2に対して3つの改善の取り組みを行いました。箇条書きでまとめさせていただきます。 課題1: コミュニケーションコストが大きい 解決策: Application Teamが自分たちでDeploy可能にできる様に権限とプロセスを整理 効果: Application Team が任意のタイミングで実行可能となり必要なコミュニケーションを適切にできる様になった 課題2: Application Teamがログを閲覧できない 解決策: Application Teamにログの閲覧権限を付与 効果: 問題発生時でも自分たちでログを確認し、対応することが可能になった 課題3: CF2のログが恒久的に残る 解決策: 失効期間付き転送先のロググループを先に作成 効果: ログの有効期限を決めたことで、コストの適正化に寄与できた 以上です。ここまで読んでいただき、ありがとうございました!
アバター
3行で概要 スクラムマスターをやっています 会社で利用しているのがJira含めたアトラシアン製品でした Jiraの便利な仕組みをいくつか紹介 はじめに みなさんこんにちは。KTCの小山です。iOS(Swift)エンジニアをしております。最近はスクラムマスターもかじっております。 今回はJiraのプラクティスを紹介したいと思います。 スクラムとJira? スクラムガイド2020 に記載の通り、スクラムマスターには「⾃⼰管理型で機能横断型のチームメンバーをコーチする。」という大きな任務があります。これを満たすために、さまざまな仕掛けを作ることになるかと思いますが、この時にできるだけ人(スクラムマスター)が介さずとも、回る仕組みが重要だと感じております。 ・・・。 ・・・いえ、決してただ楽したいなどとは。 ・・・少し、ほんの僅かばかりしか思っておりませんとも。(みんな楽して仕事したいよね) そもそもJira? Jiraはアトラシアン社の製品で、主にプロジェクト管理に用いられるSaaSになります。詳しくは 公式サイト をご覧ください。タスク管理の機能が非常に多機能で、同じくアトラシアン社が出しているドキュメント管理ツールのConfluenceと親和性が高いです。 なお弊社ではJiraとConfluenceを導入しており、全社員が利用できるようになっています。全社的に採用しているところって多いのかな? ようやく本題 フィールドの作成・必須化 「担当者が課題を詳細に書いてくれない!」 「期限は後で追加しようと思ってたけど忘れてた・・」 こんな声が聞こえてきます。 Jiraを使ったプロジェクト管理では1つ1つの課題にどれだけ情報が残るかで、自分や周りの担当者の素早い理解や、何度も同じ話をすることの防止に繋がります。 Jiraではテンプレートで用意されているフィールドの他に、任意のフィールドを追加してカスタマイズすることができ、さらに必須化も自由に設定できます。これを利用して上記の意見を仕組み化して解決することができると思います。 「担当者が課題を詳細に書いてくれない!」 詳細を書けるようにフィールドを細かく追加してみましょう 「期限は後で追加しようと思ってたけど忘れてた・・」 期限フィールドを必須化しましょう 活用事例 私たちのチームでは「iOS」「Android」「バックエンド」等、どのチームが担当するかを明確にするため、「ラベル」の入力を必須化しています。適当なラベルをつけただけでも必須フィールドとしては満たせてしまいますが、作成中の担当者がつけ忘れてしまう事象の回避には十分でしょう。 「ラベル」の項目を必須化しています 設定方法は「必須」のチェックボックスをポチッとするだけ。とても簡単ですね。ただし、どれもこれも必須にしてしまうと課題の作成が億劫になってしまう懸念もありますので、用法要領はチームで相談の上ご設定くださいね。 自動化 「課題作成するたびに毎回同じ値を入れるのが面倒くさい」 「定期的に課題が正しく運用されているか確認したい」 続いては、こんなフィードバックに対応してみます。 Jiraには自動化という機能があり、Jira使いたての頃は何がなんだか分からなくて避けていました。しかし使ってみると本当に便利。Jiraでできることは大抵これで解決することができます。順番に設定方法を見てみましょう。 「課題作成するたびに毎回同じ値を入れるのが面倒くさい」 トリガーを「課題作成時」にしたアクションを作成してみましょう。 私たちのプロジェクトでは「作成時」に「関連した課題があるかどうか」を判断して自動的にフラグをつけるようにしています。参考にこちらの設定内容を紹介します。 ルールのトリガーには「課題の作成時」を設定 リンクされた課題に「ストーリー」「バグ」があるかを判定 Jiraではただリンクされている課題があるかどうかだけでなく、そのリンクされている課題が何の種類かまで絞り込むことができます。これらを使ってチームのやり方に沿った課題運用をサポートしています。 「定期的に課題が正しく運用されているか確認したい」 こちらはトリガーを「毎日0時」や「毎週月曜日の13時」などに設定してみるのはいかがでしょうか。 私たちのプロジェクトでは、期限付きの課題を忘れないように、定期的に確認できる仕組みを作っています。こちらをご紹介します。 ルールのトリガーに「平日の朝9時」を設定 期限が切れていることをチェック Slack Webhookを使ってメッセージを送信 JiraではSlackへメッセージを飛ばすこともできるため、重要なメッセージは慣れ親しんだSlackに任せて管理することができます。Jira上のコメントだけでは気づけなかった!なんてことを回避することも可能です。 JQL? 自動化の設定の中でちょくちょく出没する「JQL」という単語、聞き馴染みがないですよね。Jiraをタスク管理として使っているだけであれば利用することがないかもしれませんが、管理の観点ではこのJQLのおかげで細やかな設定が可能になっています。 「JQL」とは「Jira Query Language」の略で、Jiraで特定の課題を検索するための独自の言語になります。私自身、Webで必要な情報を検索するのが難しかったため、ここでは自動化で利用しているJQLを紹介したいと思います。 プロジェクトと課題ステータスを絞り込む 定期的な実行ではデフォルトですべてのJiraプロジェクトが適用範囲になってしまうため、何も設定しないまま自動化を設定してしまうと、他のチームの課題をうっかり操作してしまった!なんてこともありえます。 私たちのプロジェクトではスケジュールで実行する自動化については以下の条件を設定しています。 プロジェクトが担当プロジェクトであること ステータスが「Done」もしくは「DROP」であること project = PP20 AND status not in (Done, "DROP") ※PP20の部分にはプロジェクトに設定されたキーを入力 Slackに送信するメッセージに課題の中身を挿入 自動化でも紹介した通り、Slackに連携することは可能ですが、課題の情報がなければSlackで呼びかけられた担当者が困惑してしまいます。 私たちのプロジェクトでは以下の設定でSlackメッセージを作成しています。 *期限の過ぎているチケットがあります。至急内容を確認してください。* @channel > 【<https://hogehoge.atlassian.net/browse/{{issue.key}}|{{issue.key}}>】{{issue.summary}} このようなメッセージに変化します。 実際のSlackメッセージ 終わりに 以上、Jiraの便利設定のご紹介でした。Jiraを使っている方、これから管理ツールをJiraにしようかと選定している方の参考に少しでもなれば幸いです。アジャイルの開発がもっとやりやすく進んでいくために、これからもJiraの便利機能は使い倒していきたいと思います。
アバター
こんにちは、Ashi Singh です 私はグローバル開発グループの一員で、KINTOテクノロジーズには2022年2 月に入社しました。私はアプリケーション開発担当です。現在は、グローバル開発グループが開発するバックオフィスシステムのエンジニアをしています。 概要 私のチームは、他のグローバルチームが使用する基盤パッケージとしてのマイクロサービスの開発と保守を担当しています。認証・認可は、この基盤パッケージに含めるべき主な機能です。認証ソリューションは、クラウド技術にあまり依存しないことが求められていますので、Keycloakを候補として検討することにしました。 Keycloakとは? Keycloakは、アプリケーションとセキュリティサービスに認証機能を最小限の工数で付与できるIDアクセス管理(IAM)ソリューションで、オープンソースとして提供されています。Keycloakにより、ユーザーの認証連携、厳格な認証、ユーザー管理などが可能となります。Keycloakは、OpenID Connect、OAuth 2.0、SAML 2.0 など、主に3種類のプロトコルをサポートしています。シングルサインオンとシングルサインアウトの両方を問題なく実行できます。高速かつ柔軟な動作が可能で、ユーザーアカウントをシームレスに管理でき、データもセッションも保存できます。 Keycloak公式ページ 将来的に、他のクラウドアーキテクチャへの適用も考えられるため、Keycloakはその点において有力な選択肢だと言えます。 課題 Keycloakについての検討を始めるにあたっての最初のステップは、ローカル環境での試行です。 私たちのチームでは、WindowsとMacOSを使用している開発者が同数います。(KINTOテクノロジーズでは、自分が使い慣れたOSを使用できます!) 初期セットアップにおいては、Windowsだけでなく、Intel を搭載したMacOSでも、KeycloakのDockerイメージに問題はありませんでした。ただし、最近のMacOS(主にM1搭載機種)では、スタートアップの際にどうしてもエラーが発生してしまいます。 エラー発生の際に使用していた設定は以下のとおりです。 Keycloak Dockerイメージバージョン:jboss/keycloak:16.1.1 (当プロジェクトで使用されていた最新イメージ。設定も簡単。) 私のローカルPCのバージョン:MacBook Air (M1, 2020) Apple M1 [MacOS Monterey] ソリューション M1搭載機種を使用していた際、このタスクを担当することになりました。調査したところ、Keycloakで使用しているJBossイメージはM1と互換性がないことが判明しました。 解決策は、Mac M1のDockerイメージの変更です。Mac M1 では、通常の jboss/keycloak:16.1.1 イメージの代わりに wizzn/keycloak:14 を KeycloakのDockerイメージとして使用しています。これを機能させるには、設定ファイルの変更も必要です。 変更内容 docker-compose.yml ローカルで Keycloakを実行するための最初のステップとして、Dockerイメージを wizzn/keycloak:14. に変更します。 ボリュームセクションの順序を以下のように変更: volumes: - ./custom-scripts/:/opt/jboss/startup-scripts/ - ./import/backoffice-realm.json:/tmp/backoffice-realm.json.orig #move to after startup-scripts - ./keycloak/themes/your-default-theme:/opt/jboss/keycloak/themes/your-default-theme - ./keycloak/configuration/mysql/change-database.cli:/opt/jboss/tools/cli/databases/mysql/change-database.cli #move to the last このボリュームセクションに追加する必要のある他のすべてのスクリプトは、 ./import/backoffice-realm.json と ./keycloak/configuration/mysql/change-database.cli の間に追加できます。 change-database.cli 次に、データベース (change-database.cli) ファイルにすでに定義されているデータベース設定を削除します。 このファイルでは、緑色で示した変更を実施。 Dockerfile内の変更点 Dockerfileでは、Dockerイメージを wizzn/keycloak:14 へ変更。 Keycloakを実行 Docker compose up-dを使用してKeycloakを実行します。 Keycloak:長所と短所 この最初の不具合を切り抜けると、WindowsとMacOSの両方でKeycloakを効率的に実行できるようになりました。 ユーザー管理とロール管理はインストール後すぐに動作が可能で、MFA認証、セッション管理などのKeycloakの機能がまちがいなく動作することが確認できました。こういった機能の開発は、自身で行うよりもKeycloakを活用することで工数短縮につながります。Facebook、twitterなどのさまざまなソーシャルネットワークをリンクさせるオプションもあり、必要に応じてソーシャルログインを簡単に実装できます。 ただし、対処しておくべきポイントがいくつかあります。Keycloakはカスタマイズが非常に難しく、変更に時間がかかりがちです。Keycloakが依然としてオープンソースプロジェクトであるがゆえですが、ロードマップについての開発側による保証は何もありません。また、バグ修正などは GitHub issues を通して処理されますが、明確な対応期限が設定されていません。 総じて、ソリューションには常にマイナス面が存在するものです。それでも、管理のしやすさや運用性の高さが他の要件を上回っている点からすると、Keycloakは有力なソリューションとして今後活用していけるものだと考えています。
アバター
Spring Bootを2系から3系へバージョンアップしました。 自己紹介 こんにちは。プラットフォーム開発部/共通サービス開発グループ[^1][^2][^3][^4]/決済プラットフォームチームの竹花です。 今回は、決済プラットフォームのAPI・バッチに使用しているSpring Bootのバージョンアップを行った話について書きたいと思います。 解決したい課題・実現したいこと 当時使用していたSpring Bootが2系であったため、サポート期間等を鑑み3系にバージョンアップしたい。 伴って使用しているライブラリのバージョンアップも実施 ライブラリ 移行前(2系) 移行後(3系) Java 17 変更なし MySQL 5.7 8.0 Spring Boot 2.5.12 3.1.0 Spring Boot Security 2.5.12 3.1.0 Spring Boot Data JPA 2.5.12 3.1.0 hibernate Types 2.21.1 3.5.0 MyBatis Spring Boot 2.2.0 3.0.2 Spring Batch 4.3 5.0 Spring Boot Batch 2.5.2 3.0.11 Spring Boot Cloud AWS 2.4.4 3.0.1 試行錯誤した内容・工夫したこと 適用方法 まずは公式のmigrationガイドを参考に、既存コードのまま影響が少ないライブラリのupdate、deprecated解消等を実施。 その後3.1.0に上げて、ひたすら地道に修正 → build、およびテスト → 調整を繰り返しました。 Spring Boot 3.1 Release Notes Spring Boot 3.0 Migration Guide Spring Batch 5.0 Migration Guide javax → Jakarta 多くのファイルに影響を与える javax → Jakarta パッケージへの変更がありました。 パッケージルート以降の名称は変わりなかったので、機械的に置換しました。 DBアクセス周り MySQL-Connector-Java 移行されたとのことで、mysql-connector-jへ変更しました。 Maven Repository MySQLDialect org.hibernate.dialect.MySQLDialect にすることでMySQLのversion違いを吸収してくれるようになりました。 Hibernate-Types バージョンアップに伴い、JPA Entityで使用していたJson型の設定方法が変わりました。 ID generateをIDENTITYに変更 Spring DATA JPAで自動採番の方法が変わったようで、 AUTOのままでは XXX_seq というテーブルを必要とするようになりました。 我々のシステムではMySQLのAuto Incrementを使っていたためJPAで採番機能を利用しないよう対応しました。 Spring Batch Metaテーブルの変更 Spring Batchの管理テーブルの構造が変更されました。 Migration Guidを参考に、 /org/springframework/batch/core/migration/5.0/migration-mysql.sql を使って既存テーブルを更新しました。 ですが、ALTER TABLEを実行しただけでは既存データにより動作時にエラーとなってしまったため、今後の運用に影響しないことを確認してデータを初期化することにしました。 Caused by: java.lang.RuntimeException: java.lang.ClassNotFoundException: LONG at org.springframework.batch.core.repository.dao.JdbcJobExecutionDao$2.processRow(JdbcJobExecutionDao.java:468) ... (BATCH_JOB_EXECUTION_PARAMSのPARAMETER_TYPEに'LONG'という値が入っていました) データの初期化は以下のSQLで行いました。 TRUNCATE TABLE BATCH_STEP_EXECUTION_CONTEXT; TRUNCATE TABLE BATCH_STEP_EXECUTION_SEQ; TRUNCATE TABLE BATCH_JOB_SEQ; TRUNCATE TABLE BATCH_JOB_EXECUTION_SEQ; TRUNCATE TABLE BATCH_JOB_EXECUTION_PARAMS; TRUNCATE TABLE BATCH_JOB_EXECUTION_CONTEXT; SET foreign_key_checks = 0; TRUNCATE TABLE BATCH_JOB_EXECUTION; TRUNCATE TABLE BATCH_JOB_INSTANCE; TRUNCATE TABLE BATCH_STEP_EXECUTION; SET foreign_key_checks = 1; INSERT INTO BATCH_STEP_EXECUTION_SEQ VALUES(0, '0'); INSERT INTO BATCH_JOB_EXECUTION_SEQ VALUES(0, '0'); INSERT INTO BATCH_JOB_SEQ values(0, '0'); BasicBatchConfigurerが使えなくなった DefaultBatchConfiguration を使う方法に変更しました。 StepBuilderFactory、JobBuilderFactoryが非推奨となった new StepBuilder() でJobRepositoryとTransactionManagerを渡すように変更しました。 ItemWriterの引数の型が変わった Listだったものが org.springframework.batch.item.Chunk に変わったので、write処理を修正しました。 修正前 修正後 ItemWriter<Dto> write() { return items -> { ... items.stream() .flatMap(dto -> dto.getDatas().stream()) .forEach(repository::update); ... ItemWriter<Dto> write() { return items -> { ... items.getItems().stream() .flatMap(dto -> dto.getDatas().stream()) .forEach(repository::update); ... @EnableBatchProcessingの挙動が変わった 動作確認時に、chunkモデルのバッチでprocess処理がスキップ?されるような現象が発生しました。 @EnableBatchProcessing の 挙動が変わった ことによる影響で、こちらのアノーテーションを外すことで解消しました。 Spring Cloud AWS ライブラリの変更 本システムではAWSサービスを多く利用しており、連携にSpring Cloud AWSを利用していました。 バージョンアップに伴い、 io.awspring.cloud:spring-cloud-starter-aws を io.awspring.cloud:spring-cloud-aws-starter に変更し(紛らわしい...)、 com.amazonaws:aws-java-sdk を software.amazon.awssdk へ置き換え、動作するよう修正を行いました。 Spring Cloud AWS SES SESに関して AmazonSimpleEmailService が使えなくなったため、JavaMailSenderを使う実装へ変更しました。 使用するJavaMailSenderは、SESのAuto Configurationで構築されたものをDIして利用します。 SQS SQSへの送信等、リクエスト用のオブジェクトをビルダーパターンで構築する形になったので、これに合わせて修正しました。 また、SQSListenerで使用していた@NotificationMessageが無くなったたため、SqsListenerConfigurerを作成し、MessageConverterを用意することで対応しました。 @Bean public SqsListenerConfigurer configurer(ObjectMapper objectMapper) { return registrar -> registrar.manageMessageConverters( list -> list.addAll( 0, List.of( new SQSEventModelMessageConverter( objectMapper, ReciveEventModel.class), ... } @RequiredArgsConstructor private static class SQSEventModelMessageConverter implements MessageConverter { private static final String SQS_EVENT_FILED_MESSAGE = "Message"; private final ObjectMapper objectMapper; private final Class<?> modelClass; @Override public Object fromMessage(Message<?> message, Class<?> targetClass) { if (modelClass != targetClass) { return null; } try { val payload = objectMapper .readTree(message.getPayload().toString()) .get(SQS_EVENT_FILED_MESSAGE) .asText(); return objectMapper.readValue(payload, targetClass); } catch (IOException ex) { throw new MessageConversionException( message, " Could not read JSON: " + ex.getMessage(), ex); } ... } S3 S3へのアップロードについて、 TransferManager を S3TransferManager に変更、署名付きURL発行の実装も修正が必要でした。 SNS SNS送信に関して DefaultTopicArnResolver のままではsns:CreateTopic権限が必須になっていました。 TopicsListingTopicArnResolverを使うようにして、CreateTopic権限不要で動作するよう対応しました。 @ConditionalOnProperty("spring.cloud.aws.sns.enabled") @Configuration public class SNSConfig { @Bean public TopicArnResolver topicArnResolver(SnsClient snsClient) { return new TopicsListingTopicArnResolver(snsClient); } } API周り WebSecurityConfigurerAdapter参照不可 リンクを参考にSecurityFilterChainを使用する方法に変更しました。 spring-security URLパスの厳格化 Trailing Slash(末尾スラッシュ付き)パスが厳格に区別されるようになりました。 本システムは内部の別システムとの連携があったため @RequestMapping にパスを追加し、 対向システムとの調整後追加したパスを除去する流れで対応しました。 追加前 追加後 ... @RequestMapping( method = RequestMethod.GET, value = {"/api/payments/{id}"}, ... ... @RequestMapping( method = RequestMethod.GET, value = {"/api/payments/{id}", "/api/payments/{id}/"}, ... プロパティ名の変更(application.yml) jpa、redis、spring-cloud-aws系などのプロパティ名が変更されました。 こちらは公式情報を参考に適宜調整しました。 デプロイ ECSデプロイで404が発生 なんとかECSへデプロイできるところまで進み、アプリケーションログで起動が確認できたのですが、APIにアクセスすると404に。 確認したところ、ECSのデプロイでHealth Checkが失敗していました。 弊社クラウドプラットフォームエンジニアの方々にも協力を頂き、テレメトリデータ収集に使用していた aws-opentelemetry-agent のversionが古かったことを突き止めました。 1.23.0以降のバージョンのjarに変更することで、正常にデプロイされAPIの疎通が確認できるようになりました。 AWSが提供するOpenTelemetryJava 結果・プラスアルファの知見や応用案、次へのトライなど 様々な要件に対応するためSpring Bootの一般的な実装パターンとなっていない箇所もあるなど、 migration guideだけですんなりと移行できるような構成でなかったところもありますが、 Try & Errorの繰り返しでなんとかリリースすることができました。 地道な積み重ねの作業・レビューに付き合って頂いたチームの皆さんに感謝しています。 今後は下記のような残課題を引き続き対応しながら、Spring Boot3で強化された機能等も活用していきたいと思います。 Swagger-UI こちらはバージョンアップを後回しにしました。 使用していたspring-foxがまだSpring boot3系に対応していないため、springdoc-openapiに変更することも検討しています。 Spring Batch + MySQL 8.0 + DbUnit 一部条件に該当するテストがエラーになってしまいました。 Spring BatchのTransaction管理(metaテーブル操作)が関連していそうなのですが、修正方法について調査中です。 本記事の事例を通して学んだことまとめ Spring Bootのバージョンアップはmigration guideを参考にしながら、地道にbuild・テスト繰り返すことで実施できた。 今回のバージョンアップは影響範囲が大きかったが、テストを用意していたことで修正すべきところが明確になり、効率よく対応できた。 @EnableBatchProcessingの変更のように動かしてみて問題が見つかるケースもあったため、動作確認も必須。 JavaEE関連がJakartaに変わったことで、Spring Bootだけでなく他のライブラリの更新も必要だった。 Security関連がより強固になった(Trailing Slashの厳格化やIgnore PathでもAuthFilterを通るようになった等)。 依存ライブラリ別で更新内容に差があり、特にSpring Cloud AWSの変更は大きく感じた。 もう少しこまめにライブラリ別のバージョンアップを実施していれば、修正範囲を小さくできたかもしれない。 本記事をお読みいただきありがとうございました。 同様にバージョンアップを検討されている方の参考になれば幸いです。 [^1]: 共通サービス開発グループメンバーによる投稿 1 [ グローバル展開も視野に入れた決済プラットフォームにドメイン駆動設計(DDD)を取り入れた ] [^2]: 共通サービス開発グループメンバーによる投稿 2 [ 入社 1 年未満メンバーだけのチームによる新システム開発をリモートモブプログラミングで成功させた話 ] [^3]: 共通サービス開発グループメンバーによる投稿 3 [ JIRA と GitHub Actions を活用した複数環境へのデプロイトレーサビリティ向上の取り組み ] [^4]: 共通サービス開発グループメンバーによる投稿 4 [ VSCode Dev Container を使った開発環境構築 ]
アバター
自己紹介 ご覧いただきありがとうございます! KINTOテクノロジーズ(以下、KTC)のプロジェクト開発部でエンジニアをしている三上裕太郎です 今年の9月入社で普段はフロントエンドエンジニアとして「KINTO FACTORY」の開発業務を行っています 今回、「アジャイル」をテーマに自分のこれまでの経験とKTCに入社してからの取り組みを執筆させていただきます 話すこと タイトルにもある通り、私のチームのアジャイル開発において、バーンダウンチャートが 右肩上がり している(縁起イイネ👍 という状態に対して、正しく進捗管理を機能するために何を取り組んできたかをお話しします 本編 進捗管理のあるべき姿 バーンダウンチャートは残りの作業量が減少していく様子が一目で分かるようになっており、 ステークホルダーへの進捗報告 開発者にとっての視覚的なモチベーション維持 タスクのストッパー早期発見 チームの協力と連携を促進 といった効果やメリットが期待できます 現状の課題定義 上記を踏まえて、私のチームの1スプリントのバーンダウンチャートを取り上げ、感じる課題をまとめてみます 改善前のバーンダウンチャート 作業は進んでいくので当然最終的にグラフは下がっていくのですが 不定期にあるグラフの上昇や終了時点の理想線との開きの大きさが目につきます 結論 ステークホルダーへの進捗報告 意図したグラフの上昇なのかどうかをチームで把握できていないため信用性が低い報告になってしまう 開発者にとっての視覚的なモチベーション維持 グラフに降下傾向がないため、成功体験が得られずモチベーション維持が難しい タスクのストッパー早期発見 デイリーで進捗報告をしているので、タスクの進捗が遅れていることはチームで把握できているが、グラフからはタスクのストッパーが見えずタスクの進捗が滞っていることが分かりづらい チームの協力と連携を促進 日頃のコミュニケーションは十分に取れているが、チャートを通じて協力や連携をとったケースは少ない カイゼンのゴール ゴールしたら終わりではないですが、分かりやすさをとってチームとしてあるべき姿をゴールと表現しました この記事におけるゴールの定義は以下とします チャートを通じてタスクの進捗を把握、コントロールができていること グラフが上昇することを許容しつつ、上がった事由がチームで認識できていること 開発者各々がチャートを通じて達成感を得られること チーム全体の協力と連携が促進できていること カイゼン開始後 今も現在進行形でカイゼン中ですが現時点でチャートは改善傾向にあります 最新のバーンダウンチャート やったこと1 ”意識” カイゼン ” とりあえずスプリントに積んでおこう ” を止める 具体的なアクションは一つでしたが大きく効果があったと思います この意識をチーム全体が持つようになったことでスプリント終了時点での理想線との開きを小さくすることに成功しています 加えてベロシティの精度が上がり、見積りの精度向上も期待できるようになりました やったこと2 ”プランニング” カイゼン 「次スプリントに積みたいチケット置き場」を設ける スプリント中に追加で積まれるチケットの内訳は プランニング時の積み忘れ スプリント中に追加されたチケット 大きく分けるとこの2つでした スプリント中に追加されるチケットには要因がいくつかあり短期的に改善するのは難しかったため、まずはスプリントへの積み忘れを予防するためのアクションを取りました バックログ上に「次スプリントに積みたいタスク置き場チケット」を作成し、以上に並べたタスク(画像赤枠)についてプランニングで議論するようにしたところ以下の効果を実感しています 積み忘れの防止 プランニングまでにタスクをバックログ上部に動かしておくというアクション追加されたことで積み忘れがなった タスク理解度の向上 1チケットに掛けるブレイクダウンの時間が増えたことでメンバー各々のタスク理解度が上がりました 適正な数のタスクをスプリントに積む 意識カイゼンにもつながりますがとりあえず積むのではなく、積むタスクを選別する機会を得られたので、適正な数のタスクをスプリントに積むことができるようになりました やったこと3 ”カイゼン会議” レトロスペクティブとは別に時間を設けてメンバー同士で日頃のスクラムに対する課題や改善点を話し合う時間を取りました 短〜長期的に取り組んでいく課題について話し、ネクストアクションを決めることで、チームの意識が高まりました 結果 ステークホルダーへの進捗報告 意図したグラフの上昇なのかどうかをチームで把握できていないため信用性が低い報告になってしまう グラフの精度・信用性が向上したことで正確な進捗を報告できるようになった 開発者にとっての視覚的なモチベーション維持 グラフに降下傾向がないため、成功体験が得られずモチベーション維持が難しい 明確に降下傾向があり、成功体験が得られるようになった スプリント中に追加されるチケットへのアクションは今後の課題 タスクのストッパー早期発見 デイリーで進捗報告をしているので、タスクの進捗が遅れていることはチームで把握できているが、グラフからはタスクのストッパーが見えずタスクの進捗が滞っていることが分かりづらい 引き続きデイリーで進捗報告を続けるグラフからストッパーを見えるようにする準備は整った印象 チームの協力と連携を促進 日頃のコミュニケーションは十分に取れているが、チャートを通じて協力や連携をとったケースは少ない チャートを通じて協力や連携をとったケースはまだないが、誰がどのタスクを進行中なのかが以前より把握できるようになったので協力や連携が取れる体制づくりはできたと感じている 最後に ご覧いただきありがとうございました 今回はチャートから見えてくるスクラムカイゼンについてお話ししました チームでスクラムを継続していく上でカイゼンを繰り返すのはプロダクトだけでなく、チームやプロセスにも必要だと改めて実感しました レポートやチャートを利用した客観的な改善はデータに基づいていて課題が発見されやすく、改善が目に見えるのでモチベーション維持にもつながります 皆さんのチーム”カイゼン”の一助になれば幸いです 最後に私の所属するKINTO FACTORYでは一緒に働く仲間を募集しています! ご興味があればぜひ下記の求人をチェックしてみてください @ card @ card
アバター
1. Introduction Hello. Torii here, from the team of Common Services Development Group[^1] [^2] [^3] that develops payment platforms used by multiple services. In the previous article ^4 , I shared an example of how Visual Studio Code (from here on, VS Code)'s Dev Container was used to create a comfortable development environment. While Dev Container is very useful, it uses resources on the local machine, so the performance is dependent on the machine's specs. On Mac in particular, interactions between file systems can cause delays. In this article, I will talk about GitHub Codespaces, an upgrade of the Dev Container development environment creation method that our team uses. I will explain how to build a cloud-based development environment easily and efficiently with GitHub Codespaces. In addition, I will show a sample configuration file used in actual development. The sample configuration file is taken from code that is used in actual development and contains methods of using MySQL and LocalStack with Dev Container, methods for local environments to coexist with the Dev Container development environment, and more. 2. Overview of GitHub Codespaces GitHub Codespaces is a service that provides a complete development environment in the cloud and supports VS Code, VS Code Web, IntelliJ, JupyterLab, and other major development tools. These tools can be used on all major platforms— Windows, Mac, and Linux. This allows developers to work in an environment that suits their preferences. Also, if you use VS Code Web, you can access your development environment anywhere you have a browser and work seamlessly between your local machine and the cloud. 3. Specific use cases for GitHub Codespaces GitHub Codespaces can be used in situations like the ones below. 3.1 Cross-Platform Project Development Because it is a cloud-based development environment, GitHub Codespaces does not depend on the developer’s device or OS. This saves you the trouble of building and configuring development environments in various environments from scratch. Developers can use their favorite OS and enjoy the same development environment as everyone else. 3.2 Use in education and workshops Because it is easy to set up a development environment, GitHub Codespaces is particularly useful in educational and workshop settings. Participants can focus on learning and practicing instead of spending time configuring the environment. 3.3 Pull request reviews GitHub Codespaces is deeply integrated with GitHub, so you can open pull requests directly. This allows you to review pull requests smoothly and quickly without having to switch from the branch you are currently working on. 4. GitHub Codespaces setup procedure To build GitHub Codespaces, you need to create a configuration file in the .devcontainer directory, as in Dev Container. These are the steps to setting up GitHub Codespaces. 4.1 Prerequisites GitHub account Target repository 4.2 Procedure for creating a Dev Container Create a .devcontainer directory in the target repository. In the .devcontainer directory, create Dockerfile , Docker-compose.yml , and .devcontainer.json with suitable content in each configuration file (see sample configuration file in the next chapter). Commit the configuration file to the repository and push it. Access your GitHub repository and click the green "Code" button at the top right of the repository page. Select the "Codespaces" tab from the drop-down menu. You can create a new codespace or select an existing codespace to open it. Since this article is for first-time users, we will select "Create new codespace on main". Optionally, you can specify the remote machine's region and specs. Select "New with options..." from the three dots. You will be taken to the Codespaces startup screen. It will take a few minutes to get ready. When it is ready, the Visual Studio Code interface will appear in your browser. You should then be able to edit the code in the repository by launching Codespaces. You can also use a terminal, which allows you to use tools installed in the development environment. 5. Sample configuration file 5.1 Sample devcontainer.json The .devcontainer.json file describes the configurations for Dev Container and Codespaces. This file defines the construction of the development environment, extensions used, configurations, and so on. docker-from-docker is a configuration item for using Docker from the development environment. By adding this configuration, you can use Docker on the host machine from within the dev container. If you do not add this configuration, you will not be able to use Docker from within the dev container. ghcr.io/devcontainers/features/sshd [^5] is a configuration item for JetBrains Gateway Codespaces. JetBrains Gateway Codespaces is a function that allows you to use GitHub Codespaces in the JetBrains IDE. Adding this configuration allows you to access GitHub Codespaces from the JetBrains IDE. { "name": "sample-app", "build": { "dockerfile": "Dockerfile" }, "service": "devcontainer", "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}", "postCreateCommand": "sh .devcontainer/post-create.sh", "features": { "ghcr.io/devcontainers/features/go:1": { "version": "latest" }, // Configurations using Docker on the host machine "docker-from-docker": { "version": "latest" }, // for Jetbrains Gateway Codespaces "ghcr.io/devcontainers/features/sshd:1": { "version": "latest" } }, "settings": { "editor.guides.bracketPairs": true, "editor.stickyScroll.enabled": true, "editor.stickyScroll.maxLineCount": 5, "workbench.colorCustomizations": { "editorStickyScroll.background": "#00708D", "editorStickyScrollHover.background": "#59A2B5" }, "editor.formatOnSave": true, "[go]": { "editor.formatOnSave": true, "editor.defaultFormatter": "golang.go" }, "go.formatTool": "gofmt" }, "extensions": [ "golang.go", "GitHub.vscode-pull-request-github", "GitHub.copilot" ] } 5.2 Sample Dockerfile This Dockerfile is used when building a Docker container for devcontainer and Codespaces. ARG VARIANT="jammy" FROM mcr.microsoft.com/vscode/devcontainers/base:1-${VARIANT} 5.3 Sample .devcontainer/docker-compose.yml This docker-compose file is used to build and run devcontainer and Codespaces containers. This file sets the services, environment variables, and volumes required for the development environment. If you want to access MySQL or LocalStack from within a container, you need to access it with the hostname mysql or localstack instead of localhost . For that reason, we set the hostname as an environment variable, such as MYSQL_HOST or LOCALSTACK_HOST . version: "3" services: devcontainer: build: context: . dockerfile: .devcontainer/Dockerfile environment: TZ: Asia/Tokyo MYSQL_USER: developer MYSQL_PASSWORD: password MYSQL_HOST: mysql:3306 # localstack LOCALSTACK_HOST: localstack:4566 DEFAULT_REGION: ap-northeast-1 AWS_ACCOUNT_ID: "000000000000" AWS_ACCESS_KEY_ID: dummy-access-key AWS_SECRET_ACCESS_KEY: dummy-secret-key volumes: - ..:/workspaces:cached command: /bin/sh -c "while sleep 1000; do :; done" 5.4 Sample docker-compose.yml Here is a sample docker-compose.yml used in general application development. This file is used to configure the services, environment variables, and volumes required by applications such as MySQL [^6] and localstack ^7 . This makes it possible to build and run the containers that make up the application all at once. version: "3" services: app: build: context: . dockerfile: Dockerfile volumes: - .:/workspace ports: - "3000:3000" mysql: container_name: mysql build: ./docker/mysql environment: MYSQL_DATABASE: sample MYSQL_USER: developer MYSQL_PASSWORD: password MYSQL_ROOT_PASSWORD: password volumes: - ./docker/mysql/sql:/docker-entrypoint-initdb.d ports: - 3320:3306 localstack: image: localstack/localstack:latest environment: - HOSTNAME=localstack - SERVICES=s3 - DEFAULT_REGION=ap-northeast-1 - DATA_DIR=/tmp/localstack/data volumes: - "${LOCALSTACK_VOLUME_DIR:-./volume}:/var/lib/localstack" - "/var/run/docker.sock:/var/run/docker.sock" ports: - 4777:4566 6. Using from a VSCode or JetBrains IDE Codespaces can be used from a web browser, or from the VSCode or JetBrains IDE. In this section, I will explain each method. 6.1 Launch Codespaces with VSCode Install the VSCode GitHub Codespaces extension To use Codespaces with VSCode, you need to install the "VSCode GitHub Codespaces" extension. To open the Extensions panel, click the Extensions icon from the activity bar on the left and type "GitHub CodeSpaces" in the search box. Install the GitHub CodeSpaces extension that appears in the search results. You can also install it here . Log in to GitHub In VSCode, launch the GitHub CodeSpaces extension and sign in with your GitHub account. 6.2 Launch Codespaces in the JetBrains IDE Install JetBrains Gateway JetBrains Gateway is a tool that allows you to use GitHub CodeSpaces with IDEs by JetBrains (e.g., IntelliJ IDEA, WebStorm, PyCharm). [^8]These are the steps to launching CodeSpaces on the JetBrains Gateway. As in the previous example, in order to use CodeSpaces with the JetBrains Gateway, you need to add the following configurations to .devcontainer.json . { "features": { "ghcr.io/devcontainers/features/sshd:1": { "version": "latest" } } } Go to the JetBrains Gateway installation page to download the installer and install it. You can also install it from the JetBrains Toolbox . Install GitHub CLI The JetBrains Gateway logs in to GitHub using GitHub CLI. To install GitHub CLI, follow the instructions here . If you are using Windows, you can also use the installer here . Log in to GitHub Launch JetBrains Gateway and install GitHub Codespace. Next, click GitHub Codespaces > Sign in to GitHub in the menu and log in to GitHub. You will see a one-time password and a link to the authentication page. Click the link and log in to GitHub. Enter the one-time password and click the [Continue] button. Next, click the [Authorize github] button. Launch CodeSpaces Select the codespace you want to launch from Your Recent Codespaces and click the [Open] button. If you have not created any codespaces, click on Click here to open the Codespaces creation screen. 7. Pros and cons after using codespaces 7.1 Pros Development environment accessible from anywhere: You can do development work without being tied to a physical location Easy to create an environment within your team: Sharing environment configurations makes setting up new members fast and easy Can share configurations with devcontainers: Ensures the consistency of the development environment Faster setup on new devices: Hardware changes do not hinder project progress Can be used with multiple development tools: Visual Studio Code, Visual Studio Code for the Web, JetBrains IDE, JupyterLab (previously limited to VS Code with Dev Container) 7.2 Cons May cost money: May cost money depending on usage time and resources[^9][^10] JetBrains Gateway still in beta may be unstable: This function is still in development, and some functions may not work as expected Internet connection required: You cannot work offline Performance and security concerns because of running on the cloud: There may be network latency, data protection, and other issues Files that are not managed in the repository and data that is put into MySQL disappear when Codespaces is deleted: If you need permanent data storage, you need a suitable backup strategy 8. Conclusion What did you think? I hope this was helpful. The sample configuration file is taken from code that is used in actual development, and every member develops seamlessly in their own local environment, dev container, and codespaces. We also use it together with VS Code’s Code Tour extension for onboarding new members and workshop-style study sessions. In workshops, Codespaces is very convenient because it takes out the hassle of creating the environment, so we can start the main work immediately. Google Cloud has also released Cloud Workstations [^11]. If you are interested, please feel free to try it. GitHub Codespaces is a powerful tool that makes it easy to build a cloud-based development environment. With Dev Container, you can streamline the environment creation for your entire team. Using GitHub Codespaces makes it even easier to build a development environment and improves team productivity. Please take advantage of GitHub Codespaces . [^1]: Posted by a member of the Common Services Development Group 1 [ About how we incorporated Domain-Driven Design (DDD) into payment platforms, with a view toward global expansion as well ] [^2]: Posted by a member of the Common Services Development Group 2 [ About how a team of people who'd all been with the company for less than a year successfully developed a new system through remote mob programming ] [^3]: Posted by a member of the Common Services Development Group 3 [ Initiatives to improve deployment traceability in multiple environments using JIRA and GitHub Actions ] [ [Creating a Development Environment Using VS Code's Dev Container](https://blog.kinto-technologies.com/posts/2022-12-10-VSCodeDevContainer/) ] [^5]: About devcontainers/features sshd [ devcontainers/features sshd ] [^6]: How to configure MySQL in docker-compose [ Create multi-container apps with MySQL and Docker Compose ] [ [GitHub localstack](https://github.com/localstack/localstack) ] [^8]: Remote development in the JetBrains IDE [ Remote development in the JetBrains IDE ] [^9]: About GitHub Codespaces Billing [ About GitHub Codespaces Billing ] [^10]: Shortening the Default idle timeout configuration can save money. [ Configuring Codespaces ] [^11]: Google Cloud - Cloud Workstations [ Cloud Workstations ]
アバター
Mobile Development Group Study Group (Huang) I am Huang, an Android app developer from the KINTO Technologies Mobile Development Group. In this article, I want to talk about the study group we starteed in the Mobile Development Group at KINTO Technologies. A source of team culture When it comes to software development, I think the first thing you need is a culture of sharing. There are many advantages to sharing information with lots of people, but the biggest is being able to reflect the knowledge and views of people with various perspectives. This not only reduces project risks, but also helps us gain new information. Do we really need a study group? Given how busy we all are with coding, do we really need a skill-sharing study group? There's a tendency to think this way, but the two decades since the dot-com bubble have seen the software industry grow in scale and sophistication extremely rapidly, and development become much more technically complex as well. So, as the scope of software development skills and the knowledge required increases, it's becoming vital to have a development culture that's conducive to sharing information and skills so that people can make decisions and communicate efficiently. Problems to solve I'd been finding it difficult to learn about other areas since joining the company, because I'd always been concentrating on one project. Then, I remembered how in my previous job, I'd gained a variety of new technical insights through a study group. So, I decided to start one up here. People can only spend a limited amount of time on studying, and studying with other members is more efficient than doing it alone. What we want to achieve As a culture of skill sharing develops, the members of the organization will grow more quickly, enabling them to contribute to multiple technical communities. This in turn will help the company develop into one where good human resources can grow. Forming a culture of skill sharing Our Mobile Team's study group consists of team members from the API Team, the Android Team, and the iOS Team. Basically, every week, we all take turns to give presentations about our own know-how, technical trends we're interested in, and skills we're currently learning up on. At the end of each presentation, we set aside time for everyone to exchange views and ask questions with a positive and open attitude. Also, if there's a particular skill, etc. you want to know more about, you can post a message on the bulletin board so someone with the right know-how can help. All Mobile Team engineers get to learn about having a skill-sharing culture through the study group after they join the company. The form of the study group is like this: Free topics (areas you're interested in). Ideas are shared every Thursday. About 20 participants. The participants take turns to be the facilitator. The details of the presentations are shared on Confluence. Are we heading in the right direction? Over the course of doing the study group for a year, I noticed a few things that should be kept in mind. Problem: The study group is a project with a very large number of participants. We weren't sure if we were heading in the right direction, and we needed a way to boost its activity even further. Try: When a problem arises, we all get together and have a meeting to get a picture of the goals, consolidate our ideas, and see if they'll work. Everyone plays a leading role in creating our study group and development culture, by thinking about whether we're doing things right and whether we're understanding and communicating with each other properly. Investing in information sharing within the company The Mobile Team study group uses Confluence as a document management system for sharing information within the company. The study group members use Confluence to create and organize various documents about the skills they know themselves and things they need for their work. I think an in-house document system like Confluence plays a crucial role when it comes to sharing information within the company smoothly. For this reason, the Mobile Team is steadily creating study group-related content in Confluence so that other team members can use the document system more efficiently when searching for knowledge they need. What we want to try Support for presenters from other companies There aren't many mobility service companies in Japan, so we're striving to give presentations on and share examples of good practices through technology conferences and within the community. We want to make them events where we can share our in-house development culture, skills, know-how, and the like with developers from other companies. In conclusion Most developers want a good development culture. For that, I think a good culture will have the following: Core values: A culture where people understand the core values of the services, share knowledge with each other, and are proactive about developing the core skills. DevOps: A culture where people understand that code review and testing are necessary if you want to achieve short development cycles, fault tolerance, and high-quality code. Professionalism: A culture where everyone has a sense of responsibility when it comes to results, takes pride in their work, and can improve each other's levels of expertise. In fact, it'll take a fair amount of time and effort to steadily continue skill-sharing activities and establish a culture like this, but in a team that has a good development culture, the team members will be able to share problems they encounter during development and use their know-how to come up with solutions. And as a result, they'll be able to cut down on trial and error, and ultimately provide the best possible services. We firmly believe that establishing a culture like this is essential if the company and its members are to keep on growing. The Mobile Team will continue to engage with developers from other companies in a variety of ways. I think it's worthwhile to hold Mobile Team study group meetings, and through them, pursue a development culture where everyone shares their skills and grows together. If you'd like to study with us, feel free to contact us anytime.
アバター
👋自己紹介 こんにちは!KINTOテクノロジーズのプロジェクト推進GでPjMをしている佐々木です。 これまでのキャリアでは、プログラマとして働いたり、PLとして設計したり、メンバを育成したり、PMっぽいこと(要件定義、ステークホルダー管理など)をしたりしていました。 前職では3年ほどチームみんなでアジャイルに取り組んでリアルカイゼンジャーニーをしていました。 アジャイル熱が強めなので、今日はアジャイル開発について記事を書かさせていただきます! 🚗トヨタとアジャイル 皆さんは、チームへどのようにアジャイル開発の流儀を取り込んでいるでしょうか。 新規サービスはスクラム、運用・保守業務はカンバンなど、アジャイル開発には様々な形があると思いますが、アジャイル開発を学んでいく上でリーン開発とその源流と言われているトヨタ生産方式(Toyota Production System)に出会った方は多いのではないでしょうか[*1]。 今回は、そんなトヨタグループの一員であるKINTOテクノロジーズのアジャイルへの取り組みを見える化してみようと思います。 そして、見える化を通じて社内でアジャイルに取り組んでいる皆さんが新たな気づきを得る手助けができればと思います。 [*1] トヨタの話を引用しているアジャイル本達 アジャイルサムライ リーン開発の現場 カンバン仕事術  など ::: message ### この記事はこんな人に役立ちます - チームのアジャイルの状態をしりたい - ふりかえりがマンネリ化している - アジャイルの理想と現実で苦しんでいる - KINTOテクノロジーズのアジャイルへの取り組みを知りたい ::: やりかた スクラムチェックリスト で各チームのスクラム度を定量的に見える化 1の結果を眺めながらディスカッション 今後やりたいことをゆるく表明 まずは スクラムチェックリスト を用いてスクラムの切り口でスクラムの各指標をどれくらいできているかを見える化します。 ![サンプル:スクラムチェックリストの結果](/assets/blog/authors/K.Sasaki/image-20231120-002531.png =400x) 見える化できたら、ディスカッションを行います。 ディスカッションには 4Lふりかえり のフレームワークを使います。 https://www.ryuzee.com/contents/blog/14561 :::details スクラムチェックリストの使用上の注意点 配布されているスクラムチェックリストには注意書きがあります。 他のチームと比較して評価に使ったりはしないでください 他のチームと比較して一喜一憂するものではありませんので、あくまで似たようなコンテクストでしゃべるためのきっかけとして使っています。 本記事と似たような使い方をする際は、管理者や評価者としての使用は避け、節度のある大人なメンバ間でおつかいください。 ::: 🎉参加メンバ 社内でスクラムマスター(もしくは似た立場)でスクラムやアジャイルっぽくチーム運営している方にお声をかけて協力を募り、10チーム(10名)の方々に集まっていただきました! 皆さん、お忙しいところご協力いただき、ありがとうございます! やってみた ✅スクラムチェックリスト いろいろな形のチャートができました。 「ウォーターフォールに近いがスクラムイベントを回してる」、「自分では課題を感じていたが点数は高めに出た」などチームの状況によって多種多様な結果となりました。 また「スクラムマスターを置いていないけど開発者同士でスクラムイベントを持ち回りで回している」、「プロダクトバックログにはおこせていないがオーナーとの関係は良好」といったように、点数が低い指標があっても現状重めの課題がないチームもありました。 お互い得意な部分が違うので、自分が苦手な指標について他チームに教えてもらうような使い方もできそうですね。グループAはバックログを整理しているチームが多く、グループBではバックログに課題を感じていたチームが多かったです。バックログ整理の知見が交換できるかも…👀 📒ふりかえり(4Lふりかえり) 2グループに分かれてふりかえりを実施しました。 これまでのキャリアでは発言を引き出すための工夫を凝らしたりしましたが、KINTOテクノロジーズでは5~8分程度でボードがすぐに埋まり、意見が活発な印象をうけました。 赤い付箋は、ほかの人の付箋を見たうえでの皆さんの感想です。 グループAの結果 グループBの結果 ※今回は きんちゃん の勧めでConfuruenceに新しく追加されたWhiteBoardを使用しました。 付箋をそのままJIRAチケットに変換することができ、アクションアイテムの整理に活用できそうです。 🚩ふりかえり結果 複数声が聞こえたものをピックアップしてご紹介します。 PO(プロダクトオーナー)との関係を強めることでサービスに生かしたい、アジリティを上げたいという意見が多くきかれました。自己組織化が進んでいるチームが多い印象をうけました。 よかったこと 見える化することでチームの良いところ、悪いところを知ることができた 理想的なスクラムとの乖離している部分を知ることができた 開発者が責任をもって自律的に仕事できている(自己組織的) かけていること POが不在だったり、POがいてもスクラムイベントに巻き込めていない SP(ストーリーポイント)の設定、見積がうまくできていない チーム人数が多くなってきたので、チームの分割が必要 学んだこと 社内のいろんなチーム・プロダクトでのアジャイルの取り組みを知ることができた チームの状況に応じてスプリント期間を短く・長くしてもよい みんなが今後やりたいこと(抜粋) アクションアイテム…とまではいきませんが、ゆるく決意表明していただきました。 スプリント期間の見直し チームの分割 POとのコミュニケーションの強化 💭感想 入社2か月目の自分の呼びかけにも関わらず、部署も拠点も違う皆さんに参加していただけた事に本当に驚いています(初対面の方もいました)。ご協力いただいた方、本当にありがとうございました。 社内のアジャイルに取り組んでいる人たちに集まっていただくことで、ファシリーテータとして以下のような発見や学びを得ました。 スクラムチェックリストを使うことで、チームのスクラム度を定量的に見える化することができる 取り組み度合が違うチーム同士の話を聞くことで、改善のきっかけが得られたり自分の活動に勇気をもつことができる 各チームのスクラムマスター同士がつながることで、課題の相談先を見つけることができる 組織としての共通課題が見つかった(POとのコミュニケーション強化やチーム分割の必要性) 当日はファシリテーションに徹していたのでリアクション薄めでしたが、参加者の「めげかけていたが、みんなの活動を知れて励まされた」という声をお聞きした時、涙ぐみそうになりました。 私は、これまでのキャリアでアジャイルの課題にぶつかった時には、解決方法や共感を外部の勉強会や本で補充していました。社内でこうしたもやもやを共有できたり、課題を相談する相手がいるのは素晴らしいことだと思います。 🏔まとめ:僕たちアジャイル何合目? KINTOテクノロジーズでは、大規模プロジェクトはウォーターフォールで進めたり、開発の性質に応じて柔軟に開発スタイルが決まります。今回はスクラムという切り口で社内のアジャイル度を見える化してみましたが、それぞれのチームで色んなアジャイルへの取り組み方や課題があることがわかりました。 なので…アジャイル何合目?という問いに対し「これ!」という答えは出ませんでした!(スミマセン) しかしながら、スクラムマスター同士がつながることで、更にみんなでアジャイルの道を進めた気がします! ✨今後やりたいこと 私はプロジェクト推進Gという横断系のチームにいます。 入社したばかりなのでおこがましいですが、これをきっかけに スクラムオブスクラムズ のような取り組みや、ふりかえりのふりかえり会(チームの改善をスクラムマスター同士で共有する会)など、チームを横断した開発を促進する手助けができればいいなぁと考えています。 さて、アジャイルサムライの最後は「アジャイルであるかなんて気にしない」という言葉で締めくくられています。 これからも自分のできる範囲でカイゼンを続け、アジャイル山をみんなで登り続けたいと思います! Be Agile!記事をお読みいただきありがとうございました。
アバター
はじめに こんにちは、KINTOテクノロジーズの長谷川です。 普段はAndroidエンジニアとして、myrouteというアプリの開発をしています。 この記事ではmyrouteのAndroid開発を通じて経験した、データベースのマイグレーションについて紹介します。 記事の概要 RoomはAndroidにおいて、データをローカルに簡単に永続化することができる公式のライブラリです。データをデバイスに保存することはユーザー視点で、オフラインでアプリを使用できるようになるなど大きなメリットがあります。一方で開発者視点では、いくつか必要な作業があります。その一つがマイグレーションです。Room公式ではデータベースの自動マイグレーションに対応していますが、複雑なデータベースの変更を伴うアップデートなどでは手動で対応するケースもあります。本記事では簡単な自動マイグレーションから複雑な手動マイグレーションまで、いくつかのユースケースと共に紹介します。 正しくマイグレーションしないとどうなる? ところで正しくマイグレーションに対応しないと、どうなるのでしょうか?アプリ内の対応状況にもよりますが、大きく分けて2パターンがあります。 アプリが落ちる データが消える 「アプリが落ちる」の方は、Roomを触ったことがある方なら体験したことがあるかもしれません。それぞれの場合に応じて、以下のようなエラーが発生します。 DBバージョンが更新されたのに、適切なマイグレーションが提供されていない場合 A migration from 1 to 2 was required but not found. Please provide the necessary Migration path スキーマを更新したのにDBバージョンがアップデートされていない場合 Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. 手動マイグレーションが正しく動作していない場合 Migration didn't properly handle: HogeEntity(). 基本的には全て開発環境でも発生するはずなので、そこまで問題になることはないと思います。ただし後述する fallback~ 系の対応により、マイグレーションの失敗をもみ消していたりするととても気付きにくく、場合によっては本番環境だけ発生する可能性もあるので注意が必要です。 「データが消える」の方はどうでしょうか?実はRoomはDBオブジェクトの作成時に fallbackToDestructiveMigration() という関数を呼ぶことができます。これはマイグレーションに失敗した場合データを恒久的に削除して、アプリを正常に起動することができる関数です。上記で紹介したエラーなどの対策のためか、それともDBのマイグレーションは手間がかかるため避けたのかは分かりませんがたまに使われているケースを見ます。これを行うとマイグレーションに失敗した場合データが消えてしまう上に気づきづらいのでなるべくマイグレーションを正常に行うようにしましょう。 マイグレーションの4個のシナリオ ここからはアプリ開発を行う上で発生しそうなスキーマの更新を4つの例とともに紹介します。 1. 新しいテーブルの追加 新しいテーブルを追加する場合は既存のデータに影響しないため、自動マイグレーションすることができます。 例えばDBバージョン1では HogeClass というエンティティがあり、DBバージョン2で HugaClass というエンティティを追加した場合、以下のように autoMigrations に AutoMigration(from = 1, to = 2) のような形で渡すだけで大丈夫です。 @Database( entities = [ HogeClass::class, HugaClass::class, // 追加 ], version = 2, // 1 -> 2 autoMigrations = [ AutoMigration(from = 1, to = 2) ] ) abstract class AppDatabase : RoomDatabase() {} 2. テーブルの削除や名前変更、columnの削除や名前変更 削除と名前の変更に関しては自動マイグレーションが可能ですが、 AutoMigrationSpec というものを定義する必要があります。 一番発生しそうなcolumn名の変更の例として、 User というエンティティの name というcolumnを firstName という名前に変更したとします。 @Entity data class User( @PrimaryKey val id: Int, // val name: String, // old val firstName: String, // new val age: Int, ) まずは AutoMigrationSpec を実装したクラスを定義します。そして、 @RenameColumn というアノテーションを付与し、変更するcolumnに対して必要な情報を引数で渡します。 作成したクラスを AutoMigration の対応するバージョンに渡し、それを autoMigrations に渡します。 @RenameColumn( tableName = "User", fromColumnName = "name", toColumnName = "firstName" ) class NameToFirstnameAutoMigrationSpec : AutoMigrationSpec @Database( entities = [ User::class, Person::class ], version = 2, autoMigrations = [ AutoMigration(from = 1, to = 2, NameToFirstnameAutoMigrationSpec::class), ] ) abstract class AppDatabase : RoomDatabase() {} 他にも @DeleteTable や @RenameTable 、 @DeleteColumn というアノテーションが用意されており、削除、名前の変更はこれにより簡単に対応を行うことができます。 3. columnの追加 columnの追加は個人的には一番発生する可能性が高いと思います。ここでは User というエンティティに対して、 height という身長を表すcolumnを追加したとしましょう。 @Entity data class User( @PrimaryKey val id: Int, val name: String, val age: Int, val height: Int, // new ) columnの追加は手動マイグレーションが必要です。理由はRoomにheightのデフォルト値を教えるためです。以下のようにMigratonを継承したオブジェクトを作成し、Databaseオブジェクト作成時に addMigration() に渡すだけです。 database.execSQL の中で必要なSQLステートメントを記述します。 val MIGRATION_1_2 = object : Migration(1, 2) { override fun migrate(database: SupportSQLiteDatabase) { database.execSQL( "ALTER TABLE User ADD COLUMN height Integer NOT NULL DEFAULT 0" ) } } val db = Room.databaseBuilder( context, AppDatabase::class.java, "database-name" ) .addMigrations(MIGRATION_1_2) .build() 4. 主キーを追加する 筆者が経験したアプリでは、主キーを追加するケースもありました。テーブル作成時に想定していた主キーだけでは一意性が保てず、他のcolumnを主キーに追加する場合です。例えばUserテーブルにて、 id が今まで主キーでしたが、 name も主キーにして複合主キーになったとします。 // DBバージョン 1 @Entity data class User( @PrimaryKey val id: Int, val name: String, val age: Int, ) // DBバージョン 2 @Entity( primaryKeys = ["id", "name"] ) data class User( val id: Int, val name: String, val age: Int, ) この場合はAndroidに限った話ではありませんが、新たにテーブルを作り直す方法が一般的です。下記のSQLステートメントでは UserNew というテーブルを新しい主キーの条件で作成し、 User テーブルの情報をコピーします。その後既存の User テーブルは削除して、 UserNew テーブルの名前を User に変更します。 val migration_1_2 = object : Migration(1, 2) { override fun migrate(database: SupportSQLiteDatabase) { database.execSQL("CREATE TABLE IF NOT EXISTS UserNew (`id` Integer NOT NULL, `name` TEXT NOT NULL, `age` Integer NOT NULL, PRIMARY KEY(`id`, `name`))") database.execSQL("INSERT INTO UserNew (`id`, `name`, `age`) SELECT `id`, `name`, `age` FROM User") database.execSQL("DROP TABLE User") database.execSQL("ALTER TABLE UserNew RENAME TO User") } } マイグレーションが正しく動作するか確かめよう! ここまで紹介したマイグレーションの例以外にも、複雑なケースはたくさんあります。筆者が関わっているアプリでも外部キーが関わり合っているテーブルの変更などがありました。そのような場合SQLステートメントをゴリゴリ書いていくしかないのですが、本当にそのSQLが正しく動いているか確認したくなります。そのためにRoomにはMigrationをテストする方法が提供されています。 以下のテストコードでmigrationが適切にできているかテストすることができます。なおテストを行う場合、予め各DBバージョンのスキーマをエクスポートしておく必要があります。詳しくは スキーマをエクスポートする を参考にしてみてください。昔のDBバージョンのスキーマをエクスポートしていなかった場合も、gitのタグなどから過去のバージョンを特定し、スキーマをエクスポートしておくことをお勧めします。 ポイントとしては manualMigrations というリストで定義された変数のように、プロダクションコードとテストコードで実行するmigrationとして同じ値を参照することです。これにより、プロダクションコードで migration5_6 を追加したとしても、テストコードが自動でそれを検証してくれるため安心です。 // production code val manualMigrations = listOf( migration1To2, migration2To3, // 3->4は自動マイグレーションとする migration4To5, ) // test code @RunWith(AndroidJUnit4::class) class MigrationTest { private val TEST_DB = "migration-test" @get:Rule val helper: MigrationTestHelper = MigrationTestHelper( InstrumentationRegistry.getInstrumentation(), AppDatabase::class.java, ) @Test @Throws(IOException::class) fun migrateAll() { helper.createDatabase(TEST_DB, 1).apply { close() } Room.databaseBuilder( InstrumentationRegistry.getInstrumentation().targetContext, AppDatabase::class.java, TEST_DB ).addMigrations(*ALL_MIGRATIONS).build().apply { openHelper.writableDatabase.close() } } } まとめ RoomのマイグレーションをいくつかのUseCaseで紹介しました。 手動マイグレーションはなるべく避けたいですが、そのためにはチーム全体でテーブル設計をしっかり行うことが鍵だと思います。またDBバージョンごとにスキーマをエクスポートすることも忘れずに行いましょう。そうしないと、gitなどで履歴を遡ってスキーマをエクスポートして、それを検証する未来の開発者がちょっと大変ですからね。 以上になります。 参考 https://developer.android.com/training/data-storage/room/migrating-db-versions?hl=ja
アバター
Actually, We're Quietly Evolving! KINTO Technologies-Style In-House Creators Merry Christmas! I'm Aya Sugimoto, a CD in the Creative Group. Today, I'm gatecrashing the blog to introduce you to (& brag about) our team. We belong to KINTO Technologies, a company where at its core is driven by the engineers behind KINTO's car subscription services. It's a tech company as the name implies so engineers take the spotlight; but we're flourishing away there too, in our own little corner. I have a soft spot for challenging new projects, ones that have never been attempted before :-). Our 23 team members (as of December 2022) work on a wide range of projects, from ones we really need to roll our sleeves up for (such as improving the KINTO car subscription site, producing static content, supporting dealers, and branding new services) to more relaxing ones (such as designing in-house goods). We approach them all with creative ideas and a perspective grounded on the customers' points of view. Let me tell you about our work in a dramatic way! Season 1: 2021: Becoming a group that thinks from the customers' points of view. Now, we produce things by discussing them with business side members starting from the upstream processes, but when I first joined the company, the stance was to just produce whatever the business side asked us to. If things had gone on like that, there wouldn't have been much point in having in-house creators at all. So first, we launched a project that originated from us, to raise awareness that there is an in-house group that produces high-quality deliverables and is very willing to discuss things. It was called "A Project Anyone Can Understand." It's harder for us to get to know a lot about cars than it is for business side, but that means we can plan and improve the UX from the point of view of people who aren't very knowledgeable about them—namely, the customers. With that in mind, a cross-functional in-house team system was created to launch the project. It was a daunting prospect because the project had been launched by members who'd only been with the company for a few months (myself among them), but the department managers supported us. We presented the president with a plan created based on the customers' points of view, and got the green light. Once word about the project had spread and it was produced results, we started to gradually gain recognition within the company. Season 2: Teaming up with like-minded colleagues in 2022 Web directors and designers are very busy people. The former get involved starting with the planning for handling the upstream of new services, and organize the requirements and move the production work forward as well. The latter give the services form. We urgently needed to up our creativity levels in order to meet the in-house expectations, too. We strengthened recruiting and boosted the number of members who would relate to our vision for taking a creative leap upward. Then, we made changes to the organizational structure, reviewed the design processes, and more, and successfully shifted to a work style where the business side would ask us to discuss and work on things together with them, instead of just ordering things from us. We're now a highly dependable group with a diverse range of members! Thank you everyone! In addition to web-related work, we're also involved in the graphics, logos, naming, and other branding work for new services, and are playing a part in the bulk of the visual aspects related to customer touchpoints. Season 3: Our evolution will continue in 2023 and beyond An attractive environment for in-house creative group staff is one where the team can talk directly with the business side, without information ending up being relayed like in a telephone game where things get lost along the way. Conveying to each other passions and dreams then giving them form together feels rather deeper than just client work this way. It's rewarding to be able to design something completely, starting from the brand concept. In particular, in our company, the marketing team sits across the aisle, and the development team is also nearby. I also think it's pretty appealing that senior managers like our vice president and president are quite approachable figures in our company. Of course, it also means you can get the negative feedback directly, too :-) ! A project was launched in 2021 to showcase the group's potential far and wide within the company. 2022 was a year where I got to bond with fellow team members who felt the same way about taking this creative leap upward. So now, there are only a few days left in the year. We want to go on the offensive in 2023, covering a wide playing field so that we can evolve and deepen our approach even further, all with the aim of impressing customers through even better mobility services. I'm going to put my brainpower to work as I tackle issues, keep feeling my way forward as I work, also eat a lot and sleep a lot. As I keep working at KINTO Technologies, I fell I will rejuvenate along with the growing business :-). I wish you all a very happy New Year. But first, have a Merry Christmas!
アバター
はじめに こんにちは!KINTOテクノロジーズ(KTC)プロジェクト推進GのRisako.Nです。 普段はPjMとして色々なプロジェクトに参画しています。 KTCにおけるプロジェクトやPjMとは…については、前回 横断プロジェクトの始まり方とPjMのお仕事紹介 という記事でご紹介させていただきましたので、ご興味ある方はそちらの記事をご覧になっていただけるとうれしいです。 いったんここでもざっくりと「PjMとは何か」を紹介させていただくと、KTCでは基本的にプロダクトごとに開発Gやチームがあり、各々のPdM中心に開発が進められています。ただ新しいサービスの立ち上げなどプロダクトを横断する案件、また横断的でなくとも規模が大きい案件などはPjMを置き、プロジェクトを立ち上げ推進させていくという役割をPjMが担うこととなります。 ![](/assets/blog/authors/risako.n/1.png =500x) プロジェクトとしてはKINTO-ONE(サブスク)やKINTO-FACTORYといったKINTOの既存サービス事業に関わるもの、KTCオウンドメディアやサービス、さらにはKINTOとしての新たな事業立ち上げなど多種多様なものが日々発生しており、それぞれのプロジェクトは発生した段階では何がゴールかまだわかっていないことも多くあります。色々なプロジェクトに携わるたびに、そんな不透明な状況下でもプロジェクトを前進させていく力、また自分自身としても前に進んでいく力が必要だなというのを感じており、今回は「前に進んでいく力」=「自走力」をテーマに思うことを書いてみたいと思います! ![](/assets/blog/authors/risako.n/2.png =500x) 「自走力」とは 前書きがだいぶ長くなってしまいましたが「自走力」とは。 近年よく聞こえてくる(特に採用市場などで多いかも)ワードかと思います。なんとなくわかるような、わからないような。。定義を探してみたところ、「自走力」という言葉自体にしっかりとした定義はないようですが、コトバンクには「自走」の定義が記されていました。 他の動力によらず、自身の動力で走ること つまり「自走力」とは「自身の動力で走ることができる力」、仕事に置き換え+αの表現を加えると「(どのような状況下においても、)自分の考え・行動でその仕事を前に進めることができる(、完遂することができる)力」かと思います。カッコ部分はそこまでできるとパーフェクトですね!と思う理想像です。 ![](/assets/blog/authors/risako.n/3.png =250x) 自走力=自分自身の動力で走れること! 「自走できる人」ってどんな人 「自走力」をさらに噛み砕いて、具体的に「自走できる人ってどんな人?」を考えてみます。 ゴールがはっきりしていなくても、前進することができる人 やり方がわからなくても、前進することができる人 誰かの真似をするだけではなく、自分の考えをアウトプットできる人 「自走できない人」で考えるとこんな人かなと思います(自走できる人の逆ですね!)。 指示がないと動けない人 自分がわからないことはできないと決めつけてしまっている人 言われたことをするだけの人 「自走できる人」の表現として「前進」と書きましたが、これもポイントです。「暴走」はダメで、あくまで「きちんと前に進めることができる人」が自走できる人!と思っています。 ![](/assets/blog/authors/risako.n/4.png =250x) くれぐれも暴走してしまわないように! どうやったら「自走できる人」になれるかな そんなやり方があればぜひ教えてほしい…とわたし自身も思っているのですが、ただ色々なプロジェクトに携わり、少なくとも一輪を担っている中でわたし自身がどういうことを心掛けているかを今回ご紹介しようと思います。 対話を大事にする 初めて仕事をするもの同士だと、色々なところにギャップがあるのが当然 思い込みはついついしてしまうものなので、思い込みや決めつけをしないように注意しながら、まずは考えていることを出し合う 考えを出し合っていくことで関係性もできてくる 小さく作ってアウトプットしていく、フィードバックを大事にする わからない状況下では、何か作ることや発信することにも恐れがちになるけれど、まずは小さいものからアウトプットしてまわりの人とのギャップを埋めていく 色々受ける意見は自分の不備不足と捉えず、フィードバックと捉える(後ろ向きに受け取らず、前向きに受け取る) 完了の定義に誤解がないようにする 何をもって完了なのかは人によって違いがちなので、関係者間で共通認識を持つようにする 例えば、チームのタスク運用を見直すことになって担当をアサイン、その後見直しタスクがいつのまにか完了になっていたけれど、マニュアル変更しただけで終わったことになっていた…見直し内容をチーム内で確認・周知して完了と思ってたのに…(自分の当たり前は他人の当たり前ではない) 余計な問題に対して余計に悩まない 悩むのは適切なときに悩む(今悩んでも無駄なことを今悩まない) 今一生懸命考えたとしても、本当に必要なときになると状況が変わっていることもしばしば(一生懸命考えたことが結局無駄になる) 価値とは何か この仕事は何のための仕事なのか、できあがるものは誰の何のためのものなのか、何をもたらすものなのかを意識する(ついつい「やること=目的」になりがち) 開発途中に変更要求があった場合、開発サイドとして途中変更は辛いと思ってしまいがちだけど、今作っているものの価値を考えると、この変更やった方がいいね!と前向きにがんばることができるし、結果的にうれしい 今自分がここに存在する意味、価値を意識する(ただ与えられた仕事をしているだけでは自分の価値って出てないよね、と思う) 自分のできることを意識する 「できないこと」は目につきやすいけど、「できること」(自分の価値)を意識する 例えば、この仕事をする前と今を比べて変わったこと(できるようになったこと)ってなに?と考えて、「できること」「できるようになったこと」を見つける まわりを見習う まわりの人で、あの人のこういうところいいな!と思うところを意識する 意識することで自分もいいなと思う姿に少し近づけることもある 例えば、○○さんは口数は少なめだけど、作る資料はとってもわかりやすい!なにがわかりやすいって感じるポイントなんだろう?といった視点で見ると、わかりやすい資料のコツを見つけることができたり 挙げていくと意外とキリがないな、そして教科書っぽいことばかりだな…と思いましたが、基礎となる意識やスタンスを文章化するとやはり教科書っぽくなってしまうのは仕方ないのかな…ということでご了承ください(この記事をご覧いただいている方にとって、何か1つでも心や目に留まるものがあればいいなぁと思っています)。 自走力とアジャイルマインド 前述したわたしの心掛けを眺めると、随所にアジャイルマインドを感じる方もいらっしゃるかもしれません。 アジャイルの原則にあるself-organizing teams(自律した組織)を形成するには、そもそも1人1人が自律する・自走できる必要があり、そうなれるためのエッセンスがアジャイルやスクラムにあって、これまでの経験の中で植え付けられたんじゃないかな、と自己解釈しています。 The best architectures, requirements, and designs emerge from self-organizing teams. 最良のアーキテクチャ・要求・設計は、 自己組織的なチームから生み出されます。 KTCではプロダクトによってスクラムを採用しているグループもありますし、ウォーターフォール型のグループもあります。ただ開発プロセスがウォーターフォール型であっても、KTC全体総じてのマインドとしてはアジャイル(小さな単位で価値を生み出して、対話と協調を重んじながら改善を繰り返していく)だと思います。そういったアジャイルマインドの環境下で働いてみたいなと思う方がいれば、ぜひKTCにジョインいただけるとうれしいです。 また、もちろんご自身の自走力を発揮したいぞ!と考えられている方にとっても、KTCは思う存分発揮できる環境と思いますのでぜひお待ちしています。 おわりに 今回はKTCの実態がわかるような事例のご紹介はほぼなく、概念的なお話ばかりになってしまいましたが 「自走力」ってなんだろうなぁと思っている方に対して、一例のご紹介 自分自身の「自走力」について考えるきっかけ になれば幸いです。
アバター
はじめに こんにちは!KINTOテクノロジーズの開発支援部に所属する「植村」です。 普段はコーポレートエンジニアとして主にMDM構築・管理などを行っています。 先日、「 KINTOテクノロジーズ MeetUp!~情シスによる情シスのための事例シェア4選~ 」というタイトルで「コーポレートIT領域に特化した、事例発表+座談会形式の勉強会」を開催しました。 今回は、その勉強会で事例発表した「Windowsキッティング自動化のススメ ~Windows Autopilot導入~」の内容について、補足を交えながらテックブログ上で紹介します。 Windows Autopilotとは Windows Autopilotとは、IntuneにWindowsデバイスを登録する方法の一つです。事前にデバイスのハードウェアハッシュ(HWハッシュ)を登録しておくことで、セットアップ時に自動でIntuneに登録される仕組みとなっています。 今回はこのWIndows AutopilotをKTC環境に導入し、PCキッティングの効率化を行ったことについてお話します。 Windows Autopilotによるキッティング自動化の仕組み まずはWindows Autopilotによるキッティング自動化の仕組みについて説明します。 はじめにベンダーまたは管理者がキッティングを行う前にあらかじめPCのHWハッシュをIntuneに登録しておきます。 次にユーザー(または管理者)がPCを起動し、サインインを行います。事前にHWハッシュを登録していたことでPCは自動でIntuneに登録されるようになります。 Windows Autopilotで登録されたPCが所属する動的グループを作成しておくことで、Intune登録したPCは自動でその動的グループに所属するようになります。 各構成プロファイルやアプリの配信設定の割り当て対象に3で示した動的グループを割り当てておくことで、自動的にデバイス制御やアプリ配信が行われるようになります。 Windows Autopilot自体はデバイス登録の機能を担うので1、2のところに該当します。 登録されたデバイスが3、4のところで自動でプロファイル制御やアプリの配信が行われるように動的グループを活用する必要があります。 つまりWindows Autopilot登録の設定だけでなく、自動でデバイス制御設定やアプリ配信が走るように構成することでキッティングの自動化が実現できるわけです。 実際にWindows Autopilotの導入を行ってみた Windows Autopilotの導入に至るまで調査や検証も含めて一か月半くらい掛かりました。 KTC環境においては、既に全PCのHWハッシュ登録自体は完了していたため、行ったことは以下の2点のみでした。 キッティングの際に一番最初に実行されるAutopilotプロファイルというものを、既に登録済みであったHWハッシュに割り当てる。 これまでキッティング時に使用していたキッティング用静的グループを動的グループに差し替える。 Autopilotプロファイルの設定 AutopilotプロファイルをHWハッシュに割り当てることで、「該当するPCはWindows Autopilot方式でIntuneに登録すること」を決定づけることになります。 プロファイルの内容としては主にPCのセットアップ画面で選択する「言語の設定」や「WIndowsライセンス同意」等の選択をスキップさせるか否かを設定することができます。 動的グループの設定 Autopilot登録したデバイスはAutopilotデバイス属性を持つので、この属性を動的メンバーシップルールに設定します。 ※詳しくは以下MSのサイトを参照ください。 Windows Autopilot のデバイス グループを作成する | Microsoft Learn さらに作成した動的グループを構成プロファイルやアプリ配信設定の「割り当て」に指定します。 これによりデバイス登録~デバイス制御までの流れを自動化することが可能になります。 これでWindows Autopilotによるキッティングの自動化の完了です。 導入してみた結果 Autopilotを導入してみてどれくらいの効果が出たのかというと、、、 定量的な結果ですと、導入前と比べて約40%程の作業項目を削減することができました。一方で作業時間についてはそこまでの効率化はできませんでした。アプリのインストールやWindows Updateの実施に多くの時間が掛かっているため、そこの改善には至りませんでした。 また、定性的な効果ですとキッティング作業の自動化・簡略化によって作業漏れなどの人為的ミスが発生しにくい状態にはなりました。 最後に 理想的には所謂ゼロタッチキッティングの実現ができればと思っているのですが、Autopilotの導入で実現てきたかと言われればまだまだ手作業は必要な状態です。 しかしながらデバイス登録からデバイス制御までの一連の流れを自動化できたことは、大いにPCキッティングの効率化に繋がったと思います。 今後も新たな機能を取り入れつつ、更なる効率化に向けて取り組んでいきたいと思います! !
アバター
こんにちは こんにちは、KINTOテクノロジーズ テックブログチームのmaya.sです! 本記事では2023年10月入社のみなさまに、入社直後の感想をお伺いし、まとめてみました。 KINTOテクノロジーズに興味のある方、そして、今回参加下さったメンバーへの振り返りとして有益なコンテンツになればいいなと思います。 IU 自己紹介 KINTO ONE開発部新車サブスク開発GのIUです。KINTO ONEの会員画面や契約のシミュレーション画面等のフロントエンド開発を担当しています。 所属チームはどんな体制ですか? 基本的にフロントエンドチームで活動していて、6人体制です。同期入社の白濱さんと一緒に参画しています。 KINTOテクノロジーズ(以下KTC)へ入社したときの第一印象?ギャップはありましたか? 入社前は大企業のグループ傘下の会社ということで、ある程度古さや固さを覚悟していましたが、思ったよりも伸び伸びと働けています。 特にスピード感は強く感じていて、アイデアの立案から実装、リリースまで短期間で行い、小さなサイクルでサービスを向上させていると感じます。 現場の雰囲気はどんな感じですか? 各自作業に集中して単独の色も強いですが、MTGでは各自の取り掛かっているタスクの共有を行い、手詰まりがあれば皆で解決法を話し合ったり、定期的に輪読会を行って知識の向上をさせています。 ブログを書くことになってどう思いましたか? テックブログを運営していることは入社前に知っていましたが、限られた人だけが執筆を出来るのかと思っていました。ですが基本的に誰でもウェルカムで、むしろ執筆を推奨している環境でした。 何か記事を書くことは好きなので、積極的に参加したいと思います。 ベ ジョンソク(Jongseok Bae) 自己紹介 韓国から来た10月入社のべジョンソクです。プラットフォーム開発部モバイルアプリ開発GのPrismチームのAndroid担当してます。 所属チームはどんな体制ですか? PrismのチームはAgileの形式で色々会議を通じてスケジュールを管理してます。 KTCへ入社したときの第一印象?ギャップはありましたか? 初めにOJTなどを通じて会社の説明に充実していると感じました。今まで経験した会社の場合適当に一日ぐらい説明した感じだったので違うと思いました。また社内勉強会もたくさん実施されていて、見逃しやすい情報もキャッチアップできて本当にいいなと感じました。 現場の雰囲気はどんな感じですか? チームメンバーは親切です。質問したらよく教えてくれて、仕事の中で色々意見共有などもしながら、作業をするのでコミュニケーションしながら作業するのに良い環境だと感じました。 ブログを書くことになってどう思いましたか? 最初は負担でしたが、一ヶ月間感じたことを書くから考えを整理できていいと思います。 ヒュイット マーティン(Martin Hewitt) 自己紹介 マーティンです、フランスから来ました。KINTO-TECHNOLOGIESでPlatform Engineeringをやっています。 所属チームはどんな体制ですか? プラットフォーム・グループには6つのチームがあり、SRE、DBRE、プラットフォーム・エンジニアリング、クラウドなど、それぞれの専門分野に特化しています。 KTCへ入社したときの第一印象?ギャップはありましたか? 真面目に会社を紹介してくれてます!フランスでそんな事ありませんでした。近代的な会社だと感じました、日本の会社のイメージと違う。 現場の雰囲気はどんな感じですか? 皆んなめちゃ優しい!最初は緊張していましたが、すぐに馴染むことができました。 ブログを書くことになってどう思いましたか? 早ー U.A 自己紹介 KINTO ONE開発GのU.Aです。プロデューサーやPdMとして、トヨタの販売店に対するDX支援を担当しています 所属チームはどんな体制ですか? オウンドメディア&インキュベートグループ内のDX Planningチームに所属しています。 直接トヨタの販売店に訪問してお困りごとをお伺いし、ITの力で課題を解決するチームです。 プロデューサー2名、ディレクター3名、デザイナー1名の計6名で業務にあたっています。 KTCへ入社したときの第一印象?ギャップはありましたか? 服装も自由、髪色も自由、出社時間もフレキシブルで何もかもに驚きました。 自分のこれまでの経験を活かして働きつつ、各部署には専門分野に特化した方々が集まって働いているので、顔が広くなればなるほど能力もストレッチでき、とても贅沢な空間に感じています。 現場の雰囲気はどんな感じですか? DX Planningチームは個性豊かで、話題が尽きることがないです。 普段の会話の中からもDX化のヒントになる内容を思いつくことも多いので、コミュニケーションの大切さを日々感じています。 ブログを書くことになってどう思いましたか? もう入社から1カ月経過したことに驚いています!これからも1日1日を大切にしていきたいと思います。 ラセル アハサン(Ahsan Rasel) 自己紹介 プラットフォーム開発部モバイルアプリ開発Gラセル(Rasel)です。バングラデシュから参りました。MyRouteアプリのAndroid版を対応しています。 所属チームはどんな体制ですか? 私を含めて4名体制Multi Nationalチームです。日本、バングラデシュと韓国の方がいます。チームはAgile methodologyで仕事をやっています。 KTCへ入社したときの第一印象?ギャップはありましたか? オリエンで会社のStructureや全ての部のStructure/mission/visionなどについて詳細に知ることができました。前職にもオリエンがあったが、そんなに詳細にはなかったです。自分の意見をCIO/CEOまでに伝えるのはもっと簡単だと思いました。 現場の雰囲気はどんな感じですか? 皆さんがとても優しくて仕事しやすいです。入った後質問多かったですが、皆さんは詳細に説明してくれて嬉しいです。日本語で難しいところがあれば英語も使えるのでもっとスムーズにコミュニケションすることができるので良い感じだと思っています。 ブログを書くことになってどう思いましたか? 早い感じでした。テクニカルブログ書いたことありますが、ノンテクニカルブログは初めてです。また、入社したばかりなので、びっくりしました。 宮澤 祐平(Yuhei Miyazawa) 自己紹介 プラットフォーム開発部オペレーションシステム開発Gの宮澤です。 前職はベンダー側(SIer)でECサイトの開発に従事していました。 KINTO ONE 中古車に関連したバックオフィス業務で扱うシステムの開発をしています。 所属チームはどんな体制ですか? 内製チーム5名、ベンダー様約20名で開発を推進しています。 内製化を推進するため技術レベルの高い方が多く在籍し、よくある「プロパーは推進のみ、技術はベンダーに頼りっきり」は決して無い。 KTCへ入社したときの第一印象?ギャップはありましたか? 働き方の自由度が高く、裁量で働けること。 相手を尊重したコミュニケーション文化がGood!! 現場の雰囲気はどんな感じですか? 騒がしくもなく静かすぎもなく、穏やかな雰囲気です。 「あの店で飲み会してみたい」と言えば開催されるくらいチームの人間関係も良好です。 ブログを書くことになってどう思いましたか? 自己紹介や会社紹介の内容で安心しました。 Ryomm 自己紹介 プラットフォーム開発部モバイルアプリ開発Gの 松阪 / Ryomm (@ioco95) です。iOS版のMyRouteアプリを担当しています。 所属チームはどんな体制ですか? MyRouteのiOS開発チームは、私を含めて6名体制です。 KTCへ入社したときの第一印象?ギャップはありましたか? 入ってみると割と保守的な印象でしたが、こういうことをやりたいと提案してみると後押ししていただけて、のびのびと過ごせています。 現場の雰囲気はどんな感じですか? 作業時間が多く、黙々と集中してタスクを進めることができます。 フルフレックスなので好きな時間にきて好きな時間に帰れるのが新鮮です。在宅の日は5時台から出勤している方もいて、自由だな〜と思いました。 ブログを書くことになってどう思いましたか? ブログがGitHubで記事を作成する形式で新鮮です。 オルソン パウリーン(Pauline Ohlson) 自己紹介 こんにちは!Pauline Ohlsonです。10月からプラットフォーム開発部モバイルアプリ開発GにてAndroidエンジニアを担当しています。 所属チームはどんな体制ですか? 大阪オフィス勤務で、iOSエンジニアと同じエリアに席があります。Androidプロジェクトのメンバーのほとんどが東京なので、自分はリモートで大阪から参加しています。 KTCへ入社したときの第一印象?ギャップはありましたか? 第一印象はKINTOの経緯が面白いなと思ったのと、未来像やアンビションが高い組織で、ここで働けたら面白そうだなと思いました。入社後は、最新のツールや技術を活用できる機会もたくさんありそうでワクワクしましたし、たくさんの方と仲良くなれる機会も思ったより多そうだなと感じてます。CIOやCEOと直接お話しできるチャンスもあって嬉しかったです。 現場の雰囲気はどんな感じですか? みなさん情熱を持ってお仕事されつつもちょっぴり遊び心も持ち合わせた、優しい方が多いです。相手の立場から物を考える方も多いことから効率よく働きやすい環境です。 ブログを書くことになってどう思いましたか? こういった形でブログを書くのは初めてなので、面白くて良いアイデアだなと思いました! 白濱 宏樹 (Hiroki Shirahama) 自己紹介 KINTO ONE開発部新車サブスク開発Gの白濱です。KINTO ONEのフロントエンドを担当しています。 所属チームはどんな体制ですか? 10月入社の私、IUさんを含めて6名体制です。 KTCへ入社したときの第一印象?ギャップはありましたか? フルフレックスで好きな時間に働けるのがとても新鮮でした。 現場の雰囲気はどんな感じですか? 担当タスクを黙々と進めていく感じです。日次の作業報告や週次の振り返り等もあるため、チームメンバーがどのようなことをしているのかを把握できたり、担当タスクについての相談がしやすい環境だと思います。 ブログを書くことになってどう思いましたか? 気になってはいましたが、まさかこんなに早く書くことになるとは…。 さいごに 入社直後に感想をお伺いするという急なお願いであったにも関わらず、 快く引き受けて頂き本日はみなさまありがとうございました! 今回、KINTOテクノロジーズの新たな側面を記事に残せることができたのではないかなと思います。 今後もたくさん面白いコンテンツを作成頂けること、楽しみにしています(笑)
アバター
Introduction Hinomori, Kinoshita, and Nakaguchi from the Mobile Development Group all attended the iOSDC Japan 2022 . It was held as an in-person event for the first time in two years, but also streamed online, giving it a hybrid format. This allowed us to participate in both forms, according to our circumstances. In this article, we'll share our thoughts on the event, and talk about some of the talks that made a particular impression on us. Thoughts Hinomori Let me start by saying that this is the fifth year I've attended, and the novelty items are always amazing! The pamphlet is also getting thicker every year, and I'd like to go through it slowly when I have time. The T-shirt has a very chic design again this year, and has quickly become a favorite to wear at home. Novelty items Pamphlet ![Novelty](/assets/blog/authors/HiroyaHinomori/IMG_1407.jpg =400x) ![Pamphlet](/assets/blog/authors/HiroyaHinomori/IMG_1487.jpg =400x) The event was held this year online and also in person for the first time in three years, but still being a parent of a young child myself, it's tricky to spend the whole day away. So, I grudgingly made do with joining in online. (The Niconico live broadcast will apparently be running until 23:59 on October 12, 2022 , so don't forget to check it out if you haven't already.) There were lots of sessions that really grabbed my attention this time around, but I'd like to talk about the ones that had to do with SwiftUI. Yeah, I know. Everyone's using SwiftUI. There was a case study on View splitting that was very helpful. Documenting rules is important, but I also thought that it's probably important to make sure the documents are easy to find. All about SwiftUI Navigation Point-Free's talk about swiftui-navigation was very informative. I get the feeling it could be used in connections that go all the way to NavigationStack. Adopting SwiftUI for large-scale UIKit-based projects This showed how hard it is to switch an already released app from UIKit to SwiftUI. Sure enough, the initial version of iOS 13 is the major problem, right? Making SwiftUI and UIKit get along A talk about the dos-and-don'ts and how-to's for when you use a mixture of UIKit and SwiftUI. I still go back and forth between UIKit and SwiftUI a lot, so this was very helpful. With the release of iOS 16, the minimum required operating system for many apps is now iOS 14, so I think it's time to start considering using SwiftUI full-on. That's probably why there were so many sessions about it, too. We're planning to steadily shift to SwiftUI in the future. However, keeping past OS versions in mind, we'll need to be careful because there seem to be a few issues to iron out before we can make an application with it entirely. That said, we'd also like to learn more based on what we learned here. Kinoshita I've gone to every iOSDC since the one in Nerima, and this year's narration was spectacular, too. When I heard That voice, the rush of nostalgia made me feel right at home. These are the sessions from this year's iOSDC that left a memory in me: Starting to deliver real-time AR using Unreal Engine and iPhones This session has stuck in my memory partly because I watched it while feeling nice and fresh in the morning, and partly because at the time, I was trying out Uaal with Flutter using Unity's libraries as part of running PoC experiments at work. I'd like to talk about Uaal with Flutter in another blog article if I get a chance. A blog article and resources from the session's speaker can be found at the link below. I gave a talk at iOSDC 2022 The example in the talk used Unreal Engine instead of Unity (which has a proven track record on a variety of platforms), so it was rare and very interesting. The real-time AR synthesis demo scene at the beginning of the session was very nice, and got a lot of enthusiastic comments on Niconico, too. Personally, I think that despite the dearth of information on integrating 3D rendering software into mobile devices to make things easier to handle, there's probably a surprising demand for doing it. I didn't have a lot of information to go on when I was using Uaal with Flutter to build an app either, and had wanted to try it with Unreal Engine if it could handle it. So as I was watching the session, I was wishing I'd know about it sooner. I think it'll very interesting if metaverses get more popular worldwide and more and more knowledge about them gets pooled and shared. Lunches and drinks weren't provided in the venue at this year's iOSDC, so I hope the COVID-19 situation settles down soon, and those lovely pickles make a welcome return. I'm looking forward to the return of an iOSDC where we enjoy a drink with the other participants. A big thank you to all the staff who worked so hard this year. Looking forward to seeing you all again next year! Nakaguchi I've been an iOS engineer for about 2 years, and this was my first iOSDC. I was finally getting the hang of MVVM and Combine, and wanted to make my next step learning about SwiftUI and Concurrency. This year's iOSDC had some very helpful sessions on these. There are lots of aspects that are difficult to understand from written materials like books and technical articles alone, but hearing about them in the presentations made some of them a lot clearer. I want to review the presentations to deepen my understanding. Yeah, I know. Everyone's using SwiftUI. This session had a presentation that focused on splitting in SwiftUI. This part is tricky because there's no one right answer for where to do the split, so I found it very helpful. Important takeaways for me included "Put things into words" and "Document the rules on a by-project basis," and I felt it that for parts everyone has trouble with, it's all the more necessary to explain things clearly. The basics for understanding reactive programming in the Swift Concurrency era As I said above, I'd just started learning about Concurrency, and still couldn't really see why it was useful in the first place. The session also clarified where you can switch from mobile app reactive programming to Concurrency and where you can't, so I felt much happier about that, too. I'd like to use Concurrency as much as possible due to its high readability, so I plan to keep on referring to this presentation. Conclusion iOSDC Japan 2022 was great fun! Hope to see you all again at iOSDC Japan 2023! If you can't wait until then, go and check out KINTO Technologies Careers . We're not just looking for engineers. Also hope to meet some of you after you join us here!
アバター
KINTOテクノロジーズのソフトウェアエンジニアの五条です。 『 Prism Japan 』という、AIがお出かけ先を提案してくれるモバイルアプリのバックエンドを開発しています。 今回は、Prism Japan のプロダクトオーナーをしている 齋藤と共著で、比較的規模の大きいアジャイルチームで、どのように Prism Japan を改善していったのかを紹介します。 Prism Japan とは はじめに、私達が開発している Prism Japan について、簡単に紹介させてください。 Prism Japan は一言でいうと、「AIがお出かけ先を提案してくれるアプリ」です。 「休日にお出かけしたいけど、どこに出かけようか決まってない…」 そんなときに Prism Japan が使えます。 たとえば「気分で検索」機能では、好みの写真を選ぶだけで、ユーザーにおすすめな旅行スポットを提案します。 ユーザーは写真を眺めながら、気分に合った旅行スポットを探すことができます。 2022年8月にiOSアプリをリリースし、Android版は2023年4月にリリースしました。 2023年10月末現在で累計の会員登録数は3万人を超えています。 Prism Japan の開発体制 Prism Japan は iOS と Android で利用できます。モバイルアプリを開発するチームは、 iOS 開発チーム Android 開発チーム で分かれています。 バックエンドは API 開発チーム AI 開発チーム で分かれています。それぞれの分野の専門性を持つメンバーが開発を担当します。 開発チーム以外にも企画・分析・デザインを担当するチームがあります。 プロジェクト全体の方向性を決めて、ユーザーの必要とするであろう機能を考えているのがプロダクトオーナーです。 Prism を主担当としているメンバーで 15人、サブ業務として開発に関わっているメンバーを含めると 20 人となります。 アジャイルチームとしては比較的大所帯と言えるかもしれません。 アジャイル開発を軌道に乗せるためにやったこと Prism Japan 開発チームは、現在はひとつのチームで開発していますが、以前はフロントエンドとバックエンドチームで別チームとして開発を進めていました。 チーム間の作業調整が必要なときは、Slack のチャンネル内でお互いに作業を依頼していました。 作業を依頼したあとは、各々のチームに完全に任せる形です。 組織上、所属部署が分かれていることが分業の背景にありましたが、チームの運営において以下のような課題がありました。 フロントエンド⇔バックエンド間で開発過程を共有しないため、チーム間で意見のすり合わせが行われない フロントエンド⇔バックエンドをまたいだチーム全体の改善が生まれない 作業の依頼ベースで開発が進むため、プロジェクトマネージャーと遠いメンバーはオーナーシップを持ちにくい Prism Japanの初期開発が一段落した段階で、アプリの改善フェーズに適した開発方法に切り替えるべきという議論が始まりました。 上記の課題に対処できる開発方法を検討する中で、ユーザーの反応を見ながら柔軟に仕様変更を行うことができ、モバイルアプリとの相性がよい「アジャイル開発」に切り替えるという点は早々に決まりました。 中でもチーム内でも有識者がいて、課題であったコミュニケーション面でのメリットも大きい「スクラム」を手法として採用することになりました。 ゼロからスクラムを立ち上げる手順 チームメンバー全員がスクラムを経験してきたわけではありません。そのため、スクラムとはどのようなものかをチームメンバー間で共有する必要がありました。 スクラムマスターとなった小山が講師となり、チームでスクラムを学ぶところから始まりました。 詳細は下記の小山の記事を参考にしてください。 iOSエンジニアが認定スクラムマスター研修を受けてスクラムマスターをやってみた話 先ず(勉強)会より始めよ 「これからはスクラムで開発していきたい」というときに、まずはスクラムについての勉強会から始めるのは非常に有用だったと感じています。 チームメンバー全員に前提となる基礎知識を共有した上で、「これからスクラムを始めるぞ」と意識付けができたからです。 スクラムイベントを設定する 勉強会の次の週から、スクラムイベントを設定しました。最初は手探りだったので、スクラムマスターとプロダクトオーナーが中心となって、それぞれのイベントで何をやるかを話し合いました。 はじめに行ったのは以下のような作業です。 2週間のスプリントを設定する プロダクトオーナーがストーリーを作成する 毎日15分のデイリースクラムを始める スプリントプランニングを設定する スプリントレビューを設定する スプリントレトロスペクティブを設定する スクラムマスターが主導して、まずイベントを設定して走り出しました。 この記事ではスクラムイベントの詳細については触れませんが、 スクラムマスターが主導してイベントを設定する スクラムマスターとプロダクトオーナーが密に連携して、イベントを動かす といった具体的なアクションを起こすことで、スクラムが動き出した感覚があります。 特にスクラム開始時点の手探り状態では、チームを動かしていくスクラムマスターの情熱と、やりながら改善していく姿勢が非常に重要だと思います。 チームビルディング スクラム開発を通じて感じたのは、チームが育つ感覚です。 特に、次のような点でスクラムの成長を感じています。 仕様についての議論が気軽に行えるようになった アプリの機能に対するメンバーの意見交換が活発になった スクラムマスターだけに頼ることなく、スクラムを回せるようになった どの組織でも同様かと思いますが、最初からスクラムがうまく回っていたわけではありません。 スクラムでチームを組み始めて最初の1ヶ月は、プロダクトオーナーの齋藤とスクラムマスターの小山が中心となって、常に「チームを良くする方法」を探っていました。 スクラムが淀みなく回るようになるまで、だいたい2ヶ月を要しました。 プロダクトオーナーの役割と悩み 一般的なスクラム開発におけるプロダクトオーナーの役割は開発要件をプロダクトバックログという形で管理し、開発の方向性を定めることでプロダクトの価値を最大化することです。 Prism Japanにおいてもこの点はもちろん最重要ではありますが、『プロダクトの価値の最大化』のために意思決定を行うことは簡単ではなく、当初は自分の決定が正しいのか、本当にユーザーに必要な機能なのかと、悩みは尽きませんでした。 悩みを解決するために2つのことを実行し、今では確かな判断基準をもって意思決定できるようになりました。 やったこと①:Prism Japanが解決するユーザー課題を再定義 ジョブ理論のフレームワークを元にしたワークショップをスクラムメンバー全員で実施しました。 理論についての細かい説明は割愛しますが、これによりPrism Japanがどのような価値をユーザーに提供するアプリであり続けるべきなのかという根幹となる部分を定義することができました。 やったこと②:データドリブンな意思決定の導入 プロダクトオーナー自身がデータエンジニア・データアナリストとしての経験を持つことから、ユーザーログの設計やアプリ利用状況の可視化、課題仮説を元にした分析などを積極的に行っています。 これにより、既存のアプリにおける課題、リリースした機能がユーザーに受け入れられているかなどを確かめつつ、開発方針に落とし込めるようになりました。 スクラムで発生した課題と解決するためにやったこと 最後に、スクラムで開発を進める中で発生した課題と、それを解決するために私達が何をしてきたかを紹介します。 [課題]プロダクトオーナーとエンジニアで「やりたいこと」の認識が合っていなかった スクラムでの開発を始めた当初は要件や仕様を正確に適切なタイミングで伝えることに苦労しました。 そもそも開発着手まで具体的な仕様が決まっていなかったり、口頭でのすり合わせに頼ってしまい、メンバー毎の認識に違いがあったりと原因は様々でした。 [解決方法]スプリントリファインメント、スプリントプランニングの活用 関係の良いスクラムでも礼儀は必要です。 依頼の仕方やタイミングがスクラムイベントにきちんと組み込まれたことは非常に効果がありました。 スプリントリファインメント 次回スプリントが開始になる前の週に実施されます。 プロダクトオーナーがユーザーストーリーについて説明を行い、要件の合意と簡易的な見積もりを行います。 プロダクトオーナーはこの日までに次回スプリントで対応したいユーザーストーリーを確定しておく必要があります。 スプリントプランニング ユーザーストーリーやタスクの優先度を決めた上で、スプリントで達成するゴールを合意します。 過去の実績と照らし合わせて実現可能な作業内容であることも確認するので、エンジニアがスプリント内で実施する内容に責任と自信を持つことができます。 アジャイルスクラムを導入した効果 導入当初の細かな課題はあったものの、以前の開発方法における課題に対してはどのような成果があったかを振り返ってみたいと思います。 フロントエンド⇔バックエンド間で開発過程を共有しないため、チーム間で意見のすり合わせが行われない デイリースクラムで双方が取り組んでいる内容が把握できるようになったという効果がありました。 その他にもリファインメントやプランニングといったイベントではバックエンドの実装方針に対して、フロントエンド側の要望を元にした議論も活発に行われるようになり、開発をスムーズに開始できたり、細かい手戻りなども大幅に減らすことができました。 フロントエンド⇔バックエンドをまたいだチーム全体の改善が生まれない エンジニアがアプリをよりよいものにしたいという主体性・責任感をもって議論に参加するようになったため議論のレベルも以前より数段上のものになったと感じています。 パフォーマンスや今後の拡張性などを意識したアーキテクチャレベルでの議論も行われるようになり、チームが分かれていては議論にすらならなかった内容が、きちんとまとまるようになりました。 作業の依頼ベースで開発が進むため、プロジェクトマネージャーと遠いメンバーはオーナーシップを持ちにくい 作業依頼ではなく、あくまでも依頼するのはユーザーストーリーの実現となったため、エンジニアがそれぞれ実現のための最適な方法を考え、ときには提案まで行うようになっています。 開発自体の改善もそうですが、スプリントをこなすごとに多くのメンバーが成長し続けられていることも実感できています。 最後に 開発メンバーと企画・運用メンバーが共通の目的を持ち二人三脚で改善を進めているという点は特徴的かと思いますが、アジャイルスクラムでの開発を進めている方・これから始めようという方のご参考になれば幸いです! また「Prism Japan」はリリースから1年少し経過したばかりでアプリもメンバーも絶賛成長中です。 こんな体制で開発されたアプリがどのような成長を遂げていくも是非体感してみてください! Prism Japan を触ってみたい方へ Prism Japan は下記のリンクからインストールできます。 iOS: App Store Android: Google Play
アバター
こんにちは。Woven Payment Solution開発グループの大杉です。 私たちのチームでは、 Woven by Toyota において Toyota Woven City で使われる決済システムの開発を行っていまして、普段はKotlin/Ktorによるバックエンドの開発とFlutterによるフロントエンドの開発をしています。 以前の記事 でフロントエンドの技術選定をしてからWebアプリの開発を進めていましたが、今ではWebだけに留まらずモバイルアプリも含めて7つのFlutterアプリを運用するまでに開発規模が大きくなってきました。 今回の記事では、バックエンドエンジニアしかいなかった私たちのチームで、効率的に複数のFlutterアプリをバックエンド開発と並行して開発していくために工夫してきたことを紹介したいと思います。 Flutter and the related logo are trademarks of Google LLC. We are not endorsed by or affiliated with Google LLC. 要約 私たちは、決済システムのバックエンド開発とフロントエンド開発をしているチームです。開発しているアプリは、Webは管理画面、モバイルはWoven CityでのPoCに参加される方の利用を想定した決済関連のアプリを提供しています。 決済システムのバックエンド開発と並行して、Flutterアプリを開発していくためには効率的に開発を進めていくことが必要であり、以下のことを実施してきました。 アプリ共通のアーキテクチャを設計 がんばらないUIコンポーネントの設計方針を策定 技術スタックの統一と開発の流れを定義 アプリ共通のアーキテクチャを設計 バックエンドに限らずフロントエンドのアーキテクチャも時代と共に色々な形のものが提唱されていますが、開発チームやプロダクトのフェーズや性質にあったものを選び、改善していくことが良いことだと思います。 私たちは、バックエンド開発ではクリーンアーキテクチャを採用していることもあり、それに類するLayer-firstなディレクトリ構造でMVVM、リポジトリパターンのみを採用したアーキテクチャをFlutterアプリに適用しています。具体的には以下のようなディレクトリ構成となっています。 ディレクトリ構成 lib/ ├── presentations │ ├── pages │ │ └── home_page │ │ ├── home_page.dart │ │ ├── home_page_vm.dart │ │ ├── home_page_state.dart │ │ └── components │ ├── components │ ├── style.dart // 共通のスタイル定義 │ └── app.dart ├── domains │ ├── entities │ └── repositories // リポジトリのinterface ├── infrastructures │ └── repositories └── main.dart ディレクトリの役割 大きく3つのディレクトリでレイヤー構造を表しています。それぞれのディレクトリの役割について簡単に説明すると、以下のようになっています。 Directory Layer Role presentations プレゼンテーション層 View, ViewModel, 必要であれば状態を定義 domains ドメイン層 ドメインモデルやロジック、リポジトリへのインターフェースを定義 infrastructures インフラ層 APIコールなど、リポジトリ層の実装を定義 レイヤーパターン中心の設計ではユースケース層が欲しくなるかと思いますが、現時点ではフロントエンドにほとんどビジネスロジックが存在しないため、ViewModelに集約しています。 私たちが開発しているアプリは、まだ複雑な機能がなく、基本的にページ = 1つのドメインが成り立っているため、この設計で今のところ上手く開発が回っています。PoCなどで新しくアプリを作成する際は、基本的にこのテンプレートで作り始めるようにし、アプリごとにアーキテクチャの差異が生まれないようにしています。 がんばらないUIコンポーネントの設計方針を策定 UIコンポーネントを設計する際、 Atomic Designは採用しないこと と 積極的に共通コンポーネント化しないこと にしました。 少しネガティブですが、以下のような理由があります。 Atomic Designの分類のレベル感をメンバー全員で揃えるのは難しい 共通コンポーネントを作り込むことよりもページの実装にフォーカスしたい 特に、Flutterで抽象的なWidgetを作り込むのはかなり気合いが必要だった 共通コンポーネントを作る方が正統な進め方だとは思いますが、柔軟に仕様変更しながらアプリを作り変えていくフェーズである現時点ではあまり共通化しない方が短期的なメリットが大きいと判断しました。 技術スタックの統一と開発の流れを定義 状態管理や画面遷移のフレームワークについても色々な技術が生まれては消えていったと思います。初学者はその情報の多さにどのライブラリを使えばいいのか混乱してしまうというのは自分も経験したのでよくわかります。そこで、私たちは以下の技術スタックをどのアプリでも共通して使用することにしています。 技術スタック Target Library 状態管理とProviderの作成 riverpod モデルの定義 freezed 画面遷移 go_router APIクライアント dio , openapi-genrator プロジェクト管理 melos :::message 私たちはOpenAPIを用いたスキーマ駆動開発をしており、バックエンド開発時にで作成したOpenAPIスキーマのyamlファイルを元にフロントエンドのAPIクライアントをopenapi-generatorを使って自動生成をしています。 ::: この 状態管理とProviderの作成 にはRiverpodを利用しています。RiverpodのProviderという概念はバックエンド開発ではあまり馴染みがなく、また、ハンドコードで実装すると思い思いのProviderを実装できてしまうため、実装フローや適用場所をやや厳密に定義しています。 必ず riverpod_generator を使用してProviderを生成する インフラ層のリポジトリとドメイン層のインターフェースをバインドする際は、Providerを使用する @riverpod Future<HogeRepository> hogeRepository(HogeRepositoryRef ref) { final apiClient = await ref.watch(openApiClientProvider); return HogeRepositoryImpl( apiClient: apiClient.getHogeApi(), ); } ViewModelはAsyncNotifierProviderで実装し、Viewで必要となるリポジトリのProviderはViewModelに集約する @riverpod class HogePageViewModel extends _$HogePageViewModel { @override Future<List<Hoge>> build() { return _fetchData(); } Future<List<Hoge>> _fetchData() { repository = ref.watch(hogeRepositoryProvider); return repository.getList(); } Future<void> registerData(Hoge hoge) { repository = ref.watch(hogeRepositoryProvider); return repository.register(hoge); } } Viewは、ViewModelからのAsyncValueを監視してUI表示を行う。または、ViewModelを介してリポジトリへCRUD処理を行う 以上のように、リポジトリの実装〜UIとバックエンドの組み込みのフローを規定しており、スプリントのタスクを作成する際もフローに準じた粒度でチケットを分割するようにしています。 おわりに プロジェクトの中でクライアントアプリの開発優先度が上がったことでフロントエンドの開発ポリシーを規定し、チームで開発が円滑に進められるように工夫して来ました。 Web管理画面の多くが、リスト画面 / 詳細画面 / 編集画面 が基本セットになっていることが多いので、今後はコードジェネレーターを活用してさらに効率よくUI実装ができるような仕込みを取り入れていくことも考えています。
アバター
Hello. I am Ono, from the Woven Payment Solution Development Group. Our team is working on a payment platform that will be used in Toyota Woven City . While the content may be a bit dated, you can check out more about our activities here: 20220422 Woven City Tech Meetup Tech Talk by Rie Ono This article is about using EventStorming , a DDD modeling technique that we use to design our payment system. We're still figuring things out, but I wanted to talk about what we've learned so far. What is EventStorming? EventStorming is a workshop-based method for modeling systems. It was created by Alberto Brandolini. The EventStorming website says: EventStorming is a flexible workshop format for collaborative exploration of complex business domains. Also, in chapter 12 of Learning Domain-Driven Design , titled "EventStorming", the below mention can be found: EventStorming is a low-tech activity for a group of people to brainstorm and rapidly model a business process. In a sense, EventStorming is a tactical tool for sharing business domain knowledge. In other words, it's a workshop for achieving the following goals: - Smoothly extracting domain knowledge from experts Sharing domain knowledge with stakeholders Designing domain models Preparing for our EventStorming Who Should You Ask to Join? The book mentioned above, Learning Domain-Driven Design, states that there should be no more than 10 participants. If there are too many, participants may be reluctant to speak or consensus may be difficult to reach. It also mentions that more insight could be gained if you gather a diverse group of people together. With that in mind, choosing the right group of participants might be the first challenge. Facilitation It's a good idea to have a facilitator to do timekeeping for each of the phases and guide the conversations so that they don't stray too far off topic. In our case, the engineers doing the design work performed this role themselves. Engineers The engineers design and develop the applications. In our case, in addition to our own team's members, we also invited some from the App Team who develop native apps to join in, to share their domain knowledge. Domain Experts The domain experts are those who have deep knowledge of the domains in question. Gathering people who have extensive knowledge about the existing systems, other companies' businesses, and related fields is key. The goal of EventStorming is not only to design software, but also to draw out knowledge from domain experts. In our case, we are lucky to have on board lots of members from the Business Team who've worked on payment systems. Also, our own team leader Kamei has worked in the payment field in the past, and as such, can give input from both engineering and payment points of view. UI/UX Designers and QA Engineers We couldn't do so in this example, but I think it'd also be good to bring in UI/UX designers and QA engineers involved in application development. That way, they'll be able to share their knowledge on how to streamline the UI/UX and QA design. What to Prepare EventStorming can be time-intensive. So I recommend to prepare things in advance so you can do it smoothly. Schedule it properly with all the participants If possible, limit the time to half a day or just one day. You'll be inviting people from various teams, so it might be difficult to schedule it so that everyone can take part. However, it's very important to do so. Place I think gathering participants face-to-face makes it easier for people to speak up. Sticky notes of various colors Prepare some sticky notes in the following colors: Whiteboard and markers Prepare a large whiteboard and markers for the sticky notes. Snacks and drinks for relaxing We wanted to prepare some...but had to give up due to COVID-19. What to know in advance Before the EventStorming began, via text, we shared with the participants information like the goals, prerequisites, and matters already decided on regarding the system we wanted to build, so that we could assume everyone already knew a certain amount about it. We also provided time for brief self-introductions, to make it easier for participants who'd never met before. This time, we did the EventStorming session in English, so we checked beforehand the English terminology needed for the domain knowledge and when facilitating. Thinking Ways to Reduce Face-to-Face Time to Prevent Contagion In Remote EventStorming , Alberto Brandolini writes that EventStorming is hard to do remotely. However, given the current times, we decided to try it online. If you do it face-to-face, to prevent contagion, it is better to prepare a meeting room or open space that's large enough to keep social distancing, while allowing the participants to concentrate. We found Miro to be a helpful tool to proceed online. It has easy-to-use templates such as this one: Judith Birmoser's Event Storming template | Miroverse To reduce the face-to-face time, a small group of team members did the groundwork for Phase 2 (which I'll talk about below). When you do it, get all the participants to review everything, and point out any mistakes or add anything that's missing. How We Did It Now, I'll talk about how we did the EventStorming session. Phase 1: The Big Picture First, create a Big Picture to clarify the overall business process. As you're brainstorming, write the domain events on orange sticky notes. E.g.: "A payment was made." Ask the people who've given opinions on the domain events to explain their ideas, remove any duplicates, check with domain experts to ensure things have been understood correctly, and put the sticky notes in chronological order. Phase 2: Process Modeling Next, model the processes between the Events. Add the sticky notes below to the identified Events. Add the Actors using yellow sticky notes. Think about who or what will carry out the Commands. Add the Commands that cause the Events using blue sticky notes. If you can do View models, write them on green sticky notes. Write the Policies on purple sticky notes. This Policy concept is difficult for me. The idea seems to be to write out the prerequisites and conditions for the Commands. If there are any questions or risks, write them on red sticky notes. Get the domain experts to check that the Events and timeline are correct, and answer any questions. Phase 3: Software Design Next, think in more detail about the context that’s shaping up, and get things ready for the coding to begin. Summarize the picture that seems to be forming regarding maintaining data integrity in terms of the business domains, writing the ideas as Aggregates (bright yellow). If going via external systems, add them with pink sticky notes. Try arranging those that seem like they can be grouped together as a subdomain. If it looks like a UI can be defined at this point, it might be a good idea to create a paper prototype. When you're mostly done, you can discuss the red sticky notes in detail. Alternatively, if you can't reach a conclusion right away, you can do another EventStorming session to dig deeper. What To Do After Once you've gotten this far, go back through the steps in reverse order to make sure nothing has been left out. Software design as a cooperative game with EventStorming Also, in our case, we narrowed the scope and did more EventStorming sessions after identifying the overall domain. Final Thoughts After the Sessions Below are some thoughts after trying out EventStorming: With this method, you can get a more comprehensive, unbiased picture from several colleagues than from just talking individually with them, and then creating the requirements and specifications based on that. Consequently, the communication cost may be lower in the long run. -I thought it was good that knowledge could be shared and checked among multiple members all in one go. Having tried it, I thought it would be very effective when building something from scratch, and also felt it enabled us to compare answers on things we'd been thinking about. While doing the modeling, -We found issues that had been forgotten about or hadn't been seen before. Sometimes, members who were new to a given aspect of the work asked questions and raised issues about it that reflected beginners' perspectives. Members who don't usually get to see each other were able to build connections with each other. These are the difficulties I identified: It takes time to do it, so it was difficult to coordinate all the members' schedules and maintain concentration. Facilitating was difficult. This is just a question of getting used to it, so maybe it'll get better the more we do it. Personally, I also found it tough to facilitate and discuss things in English, so I want to practice that as well. I think it was especially difficult for domain experts to explain in English about payments that were specific to Japanese business practices. Future Issues If we get to do more EventStorming sessions, I hope team members get more and more opportunities to facilitate. I also want to do a bit of studying on the steps for taking the domains identified in the EventStorming and incorporating them into the actual code. Examples: Incorporate the domain description mini language . Apply it to event sourcing . So, those are my impressions from trying out EventStorming!
アバター
こんにちは、KINTOテクノロジーズの森です。ブログを書くのは共著も合わせるともう10回目になりました。驚きです。 ほとんどがイベントレポートなのですが、今回は久しぶりに実務のお話です😎 さて、私は普段、グローバル開発部で Global KINTO Web のPdMと個人情報関係のタスクリードを務めております。個人情報関係は主に各国KINTOサービスのユーザープール関連で入ることが多く、Webサイトの話とはあまり交わらなかったのですが、今回WebでもGDPR対応しましたのでそのお話です。ようやく2つの本業が交わるときがやってまいりました👏👏👏 ユーザープール関係で発生したグローバルデータ移転にGDPR等個人データ関連法の対応をしたお話は私の前回の記事をご参照ください。記念すべき初執筆で、ガチガチな文章なのがおもしろいです😂笑 KINTOのグローバル展開におけるGDPR等個人データ関連法対応 そもそもGDPRとは?対象は? この執筆にあたり、前回記事を読み直していたのですが、肝心の 「GDPRとは?」 が抜けていました。なんてこった🤦 改めてご説明します。 GDPRとは、正式にはGeneral Data Protection Regulation(一般データ保護規則)という名称の法令です。欧州連合(EU)および欧州経済領域(EEA)において、個人データ保護や処理に関して詳細に取り決めています。その目的は域内に居住している人の個人データを保護することです。国籍ではなく、「居住者」が対象です。 欧州企業はもちろん対象となりますが、欧州域外の企業であっても以下の場合は対象となります。 欧州域内に拠点(子会社など)がある場合 欧州向けに商品やサービスを提供している場合 欧州個人データの取り扱いを委託している場合 たとえば、英語のWebサイトだとしても、欧州顧客をターゲットとしてないのであれば対象とならないケースもあります。一方で、インバウンド顧客をターゲットとしたサービスなどは対象となる可能性が高いです。 Global KINTO WebとGDPR対応 Global KINTO Web は世界40か国以上で展開するKINTOサービスのブランドサイトという位置づけです。KINTOは欧州でも多くの国でサービス展開をしているので、欧州のお客様もこのサイトのターゲットです。そのため、GDPR対応は避けられません。 もちろん、リリース時にもプライバシーポリシー等整備していましたが、当初とは運営体制が変わったり、機能が追加されたり、法令も改正されたりと、状況が変わったため、外部法律事務所の力を借りて今回再整備することとなりました。 Global KINTO Webでは問い合わせフォームで問い合わせいただく際にお客様のお名前やメールアドレス、電話番号などの情報を取得している他、サイト改善に役立てるためにCookieも取得しています。 このCookie、日本では「個人関連情報」と位置付けられていますが、GDPRでは「個人情報」の扱いです。ですので、Cookieを取得しているだけでも欧州をターゲットとしていればGDPR対応は必要になります。尚、Cookieについて、GDPR本文では Recital30 に軽く言及されているだけで、その詳細については ePrivacy指令(EPD) 通称Cookie法で具体化・補完されています。 では、Cookieを取得しているWebサイトは何をしないといけないでしょうか?🤔 具体的には以下です。 Receive users’ consent before you use any cookies except strictly necessary cookies. Provide accurate and specific information about the data each cookie tracks and its purpose in plain language before consent is received. Document and store consent received from users. Allow users to access your service even if they refuse to allow the use of certain cookies Make it as easy for users to withdraw their consent as it was for them to give their consent in the first place. (引用) Cookies, the GDPR, and the ePrivacy Directive - GDPR.eu Strictly necessary cookieを除いて、Cookie取得の前にユーザーから 同意を得る 同意を得る前にCookieが追跡するデータとその目的について、 正確で具体的な情報をわかりやすい言葉で提供 する ユーザーから受け取った 同意情報を保管 する ユーザーが特定のCookie取得を拒否してもサービスを利用できるようにする ユーザーが同意を取得したときと同じように、 同意を簡単に撤回 できるようにする (筆者翻訳) GDPR対応ではプライバシーポリシーの整備なども求められますが、Cookieにおいては上記のようなことが別途求められます。皆さんもいろいろなWebサイトを見てCookie取得に関するポップアップ(Cookie同意ポップアップ)やバナーを見かけると思いますが、主にアレです。 Cookieの種類 Cookieはその用途のカテゴリとして4つの区分に分けられます。 カテゴリ 内容 Strictly necessary cookies (厳密に必要なクッキー) サイトが正常に機能するために必要なクッキー。例えばECサイトのカート内商品を保持したり、言語設定をキープしたりするのもこのクッキーの一例です。このクッキーを止めるとサイトが正常に機能しなくなります。ユーザーの同意は不要です。また、個人を特定できる情報を保存することはありません。 Functionality cookies (機能性クッキー) ユーザーが過去に行った選択を記憶することでパーソナライズするクッキー。例えばどの地域の天気情報が必要か、ユーザー名は何か、など。Preferences Cookiesとも呼ばれます。個人を特定できる情報を保存することはありません。 Performance cookies (パフォーマンスクッキー) 主にサイト改善のために利用されるクッキー。どのページを訪れたか、どのリンクをクリックしたかなどのサイト利用情報を収集します。すべて匿名化され、個人を特定できる情報を保存することはありません。Statics Cookiesとも呼ばれます。 Targeting cookies (ターゲット型クッキー) ユーザーの興味からパーソナライズされた広告を表示します。広告のパフォーマンスを測定するために他の広告主と共有することができます。ターゲティングクッキーは、主に広告に使用されるため、Advertising Cookies (広告クッキー)とも呼ばれます。 Global KINTO WebではこのうちStrictly necessary cookiesとPerformance cookiesを取得しています。Strictly necessary cookiesは例えば言語設定の保持や、カート内のアイテム情報保管など、システムを正常に動かすために必要なので同意は不要です。しかし、Performance cookiesに関しては 同意の取得 と 簡単に撤回できる仕組み が必要でした。 Cookie同意ポップアップの課題 Cookie同意ポップアップの設置によって、今まで取れていたユーザーデータの母数がかなり減ってしまうことが懸念されました。理由として、Cookieというよくわからない情報を取得されることに不安を感じてCookieの取得を拒否するユーザーはかなり多いためです。画面に何度も表示されて邪魔なのでとりあえず拒否🙅‍♀️!なんて方もいるのではないでしょうか? そこで、このCookie同意ポップアップの必要性について改めて紐解きました。先述の通り、欧州GDPRでは必須となりますが、日本法の(改正個人情報保護法や電気通信事業法に基づくCookie規制)の解釈ではこのポップアップも不要な場合があります。Global KINTO Webについても、欧州は必要だけどそれ以外は不要という判断となりました。尚、Cookie同意ポップアップをあえて表示することで、CSRの観点ではきちんと対処していることのアピールともなり得ます。今回は実務とのバランスで判断しました。 尚、日本の改正個人情報保護法での解釈については トップコート国際法律事務所のこちらの記事 にわかりやすくまとめられておりますのでぜひご参照ください。 事前調査 欧州にのみ表示するソリューションで実装する流れにほぼ決定しましたが、念のため他のWebサイトも調査することになりました。この夏たまたま欧州へ帰省するチームメンバーがいたため、日本ではポップアップ表示のないWebサイトが欧州ではどうなっているのか、を調べてもらいました。以下がその画面キャプチャです。 Site Japan Europe Facebook ![facebook_ja](/assets/blog/authors/M.Mori/20231205/Facebook_ja.PNG =200x) ![facebook_eu](/assets/blog/authors/M.Mori/20231205/Facebook_eu.PNG =200x) Google ![google_ja](/assets/blog/authors/M.Mori/20231205/google_ja.PNG =200x) ![google_eu](/assets/blog/authors/M.Mori/20231205/google_eu.PNG =200x) Booking.com ![booking.com_jp](/assets/blog/authors/M.Mori/20231205/Booking_ja.PNG =200x) ![booking.com_eu](/assets/blog/authors/M.Mori/20231205/Booking_eu.PNG =200x) Toyota Motor ![toyota_ja](/assets/blog/authors/M.Mori/20231205/toyota_ja.PNG =200x) ![toyota_eu](/assets/blog/authors/M.Mori/20231205/toyota_eu.PNG =200x) 欧州でアクセスすると驚くのが、どのサイトを訪問しても同意を求めるポップアップの嵐!!!😵‍💫 それだけ欧州では個人情報の取り扱いがセンシティブなものになっているということですね。例に挙げたのはCookie同意ポップアップ表示有無ですが、そのほかにもユーザーの所在によって表示するサイトをリダイレクトで切り替えていたり、表示するポリシーを切り替えていたりするサイトもありました。 同意取得フロー というわけで、Cookieにおいて欧州には特別対応をしているサイトが存在すること・そしてポップアップを表示しないとまずい、という事実確認もできたので、いざ実装です。今回は外部法律事務所のアドバイスに基づいて欧州居住者の場合は以下の流れで同意を取得するようにしました。 同意の撤回は プライバシーポリシー の中に [Cookie Preference] ボタンを埋め込んでいつでも撤回できるようにしています。また、この同意は6ヶ月ごとに失効するようにしています。これは、ユーザーに対して定期的にプライバシー設定を見直す機会を提供し、より透明性を確保するためです。 実際の画面 そんなこんなで無事、11月1日にプライバシーポリシーの改訂と共にCookie同意ポップアップをリリースしました。それぞれの地域で見え方が違います。 Japan Europe プライバシーポリシー更新のお知らせはあらゆる国で求められるので、どの国でも見られるようにしています。 Cookie同意ポップアップは欧州だけに表示されるようになっています。 ポリシー更新のお知らせを閉じたら何のバナーも表示されません。 Cookie Preferenceを開くとPerformance Cookiesへの同意を管理できるようになっています。 さいごに GDPRをはじめとする個人データ関連法対応は奥が深く、私自身2年以上従事してもまだまだわからないことだらけです。新たに違反判決が出たり、あらゆる国で法令やガイドラインが制定・改正されるなど、日々状況が変わります。かと言ってユーザビリティを落としたくない、できることを減らしたくない。このバランスの見極めが非常に重要となります 🤔⚖️ 今回のお話もあくまでGlobal KINTO Webの対応として外部有識者の力を借りて実施した実例であり、他のケースに必ずしも当てはまるわけではありません。例えば今回のような拒否率が上がってしまうという課題も、ポップアップをRejectされにくいようなUIUXで回避するといったソリューションも考えられます。そのWebサイトの目的やターゲット、内容などの状況によっても大きく変わりますし、こういった法令自体が解釈による部分が大きいので、一概にこうしておけば絶対大丈夫!とも言い切れないものです。 今後も、Global KINTO Webや各国の状況によって様々なアップデートは必要になってきます。もしCookie同意ポップアップが表示されたら、「あ、ちゃんとやってんだな👍」と思っていただけたら何よりです🙇‍♀️ Reference Cookies, the GDPR, and the ePrivacy Directive - GDPR.eu クッキーは個人情報?規制の対象となるクッキーについて | BizRis Cookie(クッキー)同意ポップアップの実装率と設置場所 Global Reach - グローバル展開する企業を支援 Cookie types
アバター
はじめに KINTOテクノロジーズ(以降KTC)で社内システムのPdMをしている小林です。KTCに入社後は[KINTO ONE]( 【KINTO】新車のサブスク、トヨタから|フルサービスのカーリース (kinto-jp.com) )のサイト再構築プロジェクトにアサインされ、PjM、テスト推進、移行推進を担当しました。アサインされた時にはすでにプロジェクト開始から1年が経過し、開発は完了しており、結合テストを実施してリリースするという局面でしたが、このあと様々な課題にあたることになります。今回はテスト推進担当として最初に遭遇した課題についてご紹介します。 サイト再構築プロジェクトとは KINTOのメインサービスであるKINTO ONE 新車のECサイトをリニューアルする内製開発プロジェクトです。アーキテクチャおよびデータ構造を全面的に見直し、開発生産性を高めることを目的としており、関連するプロダクトやサービスは20以上、ビジネスサイド、開発サイドの窓口担当者は合わせて50名ほどの規模でした。 まずは状況把握 私が入社したのは2022年2月です。まずは週次定例会に参加し状況を把握しつつ、テスト推進や移行推進を実施するという立ち位置でのスタートです。 入社する少し前の2022年1月中頃から内部結合テストが開始されていました。数日程度の遅延はあるものの順調との報告がなされており、この時点では内部結合テストの完了は2022年5月末の予定でスケジュールに違和感は無し。内部結合テストの計画は開発者が作成し、開発に携わっていないメンバーで構成されたテストチームがテストケースの作成と実施を担当するといった理想的な状況でした。 最初の課題 内部結合テストは7つにフェーズ分け進める計画でしたが、2月後半に内部結合テストの進捗に陰りが見え始め、3月最初の報告では1週間遅れとなりました。 このとき後続テストフェーズに影響がある不具合が10件以上あり、修正だけで1週間程度かかる苦しい状況であることがわかりました。このまま計画通りに行けるのか感覚を確かめるため、開発者に状況をヒアリングしたところ以下のような話が出てきました。 単体テストの終了条件がわからない 結合テストの開始条件がわからない 内部結合テストの内容が想定と異なる 開発者がまとめていた資料にはどのようなテストを実施するか記載はあるものの、確かに開始条件や終了条件に関する記載はなく、その手の情報は方針書や計画書にあるだろうと探しますが見当たりません。なるほど確かに。。 想定していたテスト内容について、開発者がまとめていた資料では「一通りの画面遷移を通してテストを行う」と記載があり、テスト項目として以下のような記載がありました。 正しいデータを入力した際に、正しい画面表示・遷移がなされるか DBに正しくレコードが作られているか 途中で処理を中断した際のデータは回復可能か この内容からストーリーをベースにしたテストを想定しているように見え、テストチームが用意したテストケースとも合致しますので、何が混乱のもとになったのか考える必要が出てきました。 ふと開発者がまとめた資料を見るとテストの実行方法について以下のように記載されていることに気づきます。 ブラウザごとにテストを実施する(画面テストと同様) DBについてはDBの値を直接SQLで確認する 単体テストで実施した画面テストと同様との記載。この記載では単体テストと同様のテストをフロントエンドとバックエンドを結合して実施するように見えます。なんとなく混乱の原因がわかりました。認識齟齬のない計画の重要性が感じられる課題です。 課題への対応 テストを止めず無理に進めても遅延が拡大する可能性があるため、この課題への対応は「2週間内部結合テストを止めること」でした。この対応により次のような効果が得られます。 開発サイドのリカバリが可能 テストを止めることにより修正に時間を使うことができ、遅延リカバリが可能となりました。また修正に注力することができるため品質が上がります。開発者とテストチームはテストが進まないストレスから解放されます。 品質管理方針と品質評価基準の整理が可能 テストを止めることにより、内部結合テストのみならずテスト全体の方針や基準の整理が可能となり、以下の内容を周知することができました。 各テストフェーズで確保すべき品質を品質管理方針として定める 各テストフェーズでの品質評価基準を定める 後付けでの方針と基準の提示でしたが、開発者は受け入れてくれました。この柔軟性がKTCの良いところですね。内部結合テストは無事回り始めました。 その後 その後も様々な課題が出てきます。他案件との関係でスケジュール変更が発生した際には、品質強化テストを追加したりと、状況に応じて品質を上げるよう計画を見直しつつ、外部結合テスト、他案件の後追い取込、QAテストを実施し、2023年8月に無事リリースを果たしました。 規模の割にリリース後の障害が少ないと言われています。しかしながら障害が発生すると少なからず業務影響がでてしまいますので、今後もより品質を高められるよう、できることを考えていきたいと思っています。 最後に 今回の経験から、次の2点が重要と考えています。 認識齟齬の無い計画 品質管理方針および品質評価基準の設定 開発者に任せるにしても何かあった際の道標として、計画、方針、基準はきちっと整備すべきと思いました。 また今回課題への対応について気を付けた点は、いずれの対応も開発者に作業指示を行わないという点です。サイト再構築プロジェクトでは詳細設計から内部結合テストまでを開発者に任せる方針としていました。これはプロジェクトの方針であり守りたかった部分です。そこもなんとか守れたかな。 以上、サイト再構築プロジェクトで最初に苦労したことのご紹介でした。
アバター
Introduction Hi everyone! I am Chris from Global Frontend team. Few weeks ago I went to Vue Fes Japan 2023 and I would like to summarize the contents and share some of my thinking. By the way, as a little personal background, I began using Vue early in my career as a web developer, and despite using it consistently since then, it's a bit embarrassing to admit that this was my first time attending this event, which made its debut back in 2018. Nevertheless, I was excited about my first attendance and the opportunity to meet Evan You, the creator of Vue and Vite, so I was looking forward to the event all morning! Once I finally arrived at the venue, I noticed a whiteboard near the entrance, so I took the opportunity to promote our company's presence! Keynote by Evan You In the keynote session, Evan You primarily reflected on Vue 3, discussing both the positives and areas for improvement. He began by acknowledging the challenges faced during the migration from Vue 2 to Vue 3, highlighting specific points: Numerous breaking changes Underestimating the impact on libraries within Vue's ecosystem Not releasing all changes at once On the positive side, he also mentioned the improvements related to version upgrades: Enhanced TypeScript compatibility Introduction of the Composition API Investment in Developer Experience (DX) The continued growth of Vue 3 Based on these points, Evan emphasized the importance of stability in future versions. He wants to ensure that future updates minimize disruptive changes, making it easier for developers to adopt improvements and new features while providing a better development experience. As an example, he mentioned the introduction of a Vue ecosystem CI (Continuous Integration) tool. This tool aims to check for any disruptive impacts on libraries that depend on Vue when upgrading Vue versions. While the tool passed all tests for most cases, it was essential to involve the community, especially for releases like v3.4 alpha, which involved significant refactoring. Feedback was sought from the community regarding this release, which included improvements in memory management and more efficient re-computation. Listening to the keynote, I appreciated Evan addressing the challenges of migrating from Vue 2 to Vue 3, as I had also faced difficulties in that process with products I am working on at the moment (In addition we also use Vuetify which makes things more complicated). Updates on Nuxt Next, Sebastian Chopin, the CEO of NuxtLab, and Daniel Roe, a Nuxt Core team member, presented updates on Nuxt. Sebastian introduced recent updates to Nuxt, including demonstrations of Hybrid Rendering (allowing per-page rendering methods) and deploying Nuxt apps to the edge using Cloudflare. He also called for recruiting more contributors to expand the Nuxt ecosystem. On the other hand, Daniel discussed the Nuxt ecosystem and provided updates on various tools and libraries: Enabling features from Nuxt 3, such as Composition API, in Nuxt 2 using nuxt/bridge Offering various testing capabilities for Nuxt with nuxt/test-utils Allowing page creation using Markdown files (.md) through nuxt/content They concluded by discussing the direction for Nuxt 4, focusing on improving Developer Experience (DX), providing many opt-in tools, and promoting a more open development process to encourage more community participation. Listening to the presentations by both speakers, I, as a Vue/Nuxt user and developer, was inspired by the active community and thought about contributing as a contributor to this community in the future. Perspectives on Open Source Software (OSS) Activities In this session, Anthony Fu shared his experiences and insights about his OSS activities. He began by using the example of the vscode-vue-i18n-ally extension, which focuses on accessibility tools for users of Visual Studio Code, the Vue framework, and the i18n feature. This limited the extension's user base significantly. Anthony discussed two approaches to expand the user base: Removing limitations on tool usage. For instance, making the vscode-vue-i18n-ally extension compatible with frameworks other than Vue, resulting in the creation of i18n-ally . Forming a union of tools: Expanding the user base by creating an ecosystem of tools that cater to different user needs. For example, Nuxt's ecosystem has several support tools that different users require. Such unions help users build a substantial development community. His insights highlighted the importance of not only expanding the user base but also potentially increasing contributors by broadening the utility of OSS tools. After hearing his presentation, I realized that, similar to conventional products, user acquisition is a critical concept in OSS, and attracting more users should always be considered. Q&A Session The last session was a Q&A session where Evan You, Sebastian Chopin, and Daniel Roe answered various questions from the audience. Although the session was one hour long, there were so many pre-submitted questions that only a portion of them could be answered. Here are four questions that left a strong impression: Q: What are your thoughts on Server-Side Components? A: Ultimately, static has its advantages, so it depends on your needs. One use case for Server-Side Components could be e-commerce websites. Q: Migrating from Vue, Nuxt, and Vuetify from version 2 to version 3 is challenging. Can you provide guidance on how to do it? A: It's entirely my fault that it's this challenging, so I apologize! One approach would be to create a new project from scratch and migrate gradually. Q: Are there any recommended design patterns for components in Nuxt? A: There's no specific pattern recommended. Vue was created with the idea of not being tied to specific patterns. Start small, develop gradually, and decide on patterns that work for your specific use case. Q: Are there plans for Vue to support Native app development? A: With the current team, there's no capacity to support it. It would likely require several times the current resources. Consider using Ionic or NativeScript for Vue Native app development. Afterparty The afterparty was a standing buffet, featuring Western and sushi dishes provided by sponsors. I'm quite introverted and usually hesitant to initiate conversations at events, but I mustered the courage to talk to core team members, including Evan, who came to Japan for the event. It was a great experience to have various conversations. I even asked Anthony for advice for those new to open-source development. His advice was, "1. Start with small projects, 2. Have courage." I found his advice very convincing as the biggest difficulty I have is mostly looking at well matured open-source library/tools and I would feel anxious that I am not good enough to contribute. So pick the right-sized project and suddenly the first step should feel easier. Conclusion To be honest, as it was my first time attending a Vue and Nuxt community event, I had a lot of fun. However, what struck me the most was the incredible dedication and mindset of the core open-source contributors. The Vue and Nuxt core teams are not particularly large, and this allows them to make deliberate choices, such as deciding not to pursue Vue Native despite its potential, and to think about how their tools can benefit not just Vue but other frameworks as well. I would like to attend Vue Fes Japan again next year, and I would like to recommend anyone who is interested in such events to join as well!
アバター