TECH PLAY

KINTOテクノロジーズ

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

975

初めに KINTOテクノロジーズのグローバル開発グループに所属しているパンヌウェイ(PannNuWai)です。グロバール開発グループでテスト自動化チームの担当としてプロダクト開発チーム用のテスト自動化環境の構築と整備をしていたり、プロダクトのテストチームでテストスクリプトを書いています。 私は、KINTOテクノロジーズに入社するまでもテスティングは担当していましたが、入社してから初めてAppiumの自動化テストを経験し、この間、様々なものを学びました。 Appiumは経験が無く、ゼロから勉強するところからのスタートでした。最初の環境設定から手探りで行いサーバーのアーキテクチャデザインまで行うことができようになりました。 この自動化テストでは、スマホアプリをメインにテストしましたが、その中で解決した課題を共有いたします。 本記事では自動化テストためAppium version 1.22.3を使ってDarkMode(ダークモード)に切り替える方法を話したいと思います。 自動化テストとは ソフトウェアテストは不具合のある製品をリリースしてしまわないよう、ソフトウェアの問題を発見するために行う作業のことです。 本記事で「自動化テスト」とは支援ツールを用いてソフトウェアテストのプロセスを自動化することと言います。 自動化テストのメリット ^1 不具合の早期発見 コストを抑えながら品質を高められる 人的リソースが不足していてもテストできる テストを高速で実施できる ヒューマンエラーを排除できる 営業時間外でもテストできる Appium とは iOSアプリ、Androidアプリ、およびデスクトッププラットフォームではネイティブ、ウェブビュー、ハイブリッドアプリをテストするためのオープンソースツールです。[^2] [^2]: https://appium.io AppiumはJava,PHP,Pythonのプログラミング言語をサポートしているのでテスト者が好きな言語を選びながら簡単に使える自動化テストツールです。 Appiumのアーキテクチャでは Appium Client Appium Server End Device という三つのコンポーネントが有ります。 Appium Clientの中にはモバイルデバイスとアプリの詳細を設定されています。 Appium ServerにはNode.js言語を利用してjsonファイルを起動しながらシミュレーター(iOS)またはエミュレータ(Android)の接続を行います。 最後には起動されたAppium ServerによってEnd Deviceが発行されます。 Appium Inspector とは Appium InspectorはモバイルアプリのUI要系を一意に識別するための標準的な手順です。実際のデバイスまたはシミュレーター(iOS)またはエミュレータ(Android)の両方で動作します。 注意点- Appium Inspectorツールはネイティブモバイルアプリケーションの属性のみを取得するように特別に設計されているため、Web ブラウザ(Chrome)でロケーターを見つけることをサポートしていません。 Appiumデスクトップアプリケーションは、Appiumサーバー自体とElementインスペクタの組み合わせで、テストスクリプトの開発中にモバイルアプリケーションのすべての目に見える要素を検出できるように設計されています。 ^3 Dark Mode(ダークモード)とは ダークモードはスマートフォンやノートパソコンなどのユーザーインターフェースの表示設定です。 明るい画面に対して暗いテキスト(ダークモード)が表示されている代わりに、黒い画面に対して明るい色のテキスト(ライトモード)が表示されることです。 現在ではスマートフォンのAndroidとiOS両方の既存ダークモード機能だけではなく、アプリの中にもダークモード機能をよく使います。モバイルアプリの自動化テストを行う場合はダークモード機能のテストも重要なチェック項目になりました。ですので、今回はAppiumを利用してモバイルアプリのダークモードについて話したいと思います。 問題点 Appiumを利用してダークモードのテストを行う場合、問題点があります。例えば、ログイン画面に username と password の文字が表示されているかをテストする際、Appium inspectorから username と password のelement存在する場所を取得します。通常は以下の通りでelementが表示されているのをチェックするのみです。 AssertTrue(driver.findElementByXPath("USER_NAME").isDisplayed()); AssertTrue(driver.findElementByXPath("PASSWORD").isDisplayed()); ですが、ダークモードの場合、 element の存在する場所を取得して表示をチェックするだけは不十分です。画面が黒い色に変更されているかをチェックするのはダークモードの大事な点です。黒い色と白い色のhexadecimal値をチェックする必要があります。 テスト方法 では、実際にAppiumでダークモードテスケースのソースコードを書いてみましょう。 changeToDarkTheme ステップ 1 Appium inspectorからelementの存在する場所(ElementId)を取得します。 ステップ 2 デフォルト設定がライトモードになっているかどうかを assertElementColorMode(MobileElement elementId, ColorMode colorMode) で確認します。 ステップ 3 ダークモードのボタンを押下します。 ステップ 4 Display設定が ダークモードに変わるかどうかを assertElementColorMode(MobileElement elementId, ColorMode colorMode) で確認します。 public class DisplayChangePage extends Base { public static final String THEME_CELL_ID = "id/theme_parent"; @Test(groups = "DisplayChangePage", dependsOnGroups = "Setting") public void changeToDarkTheme() { driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS); MobileElement themeCell = getDriver().findElementById(THEME_CELL_ID); assertElementColorMode(themeCell, ColorMode.LIGHT); themeCell.click(); driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS); tapElement( findElementByTextContains(ViewType.CHECKED_TEXT, resourceText("darkTheme")) ); themeCell = getDriver().findElementById(THEME_CELL_ID); assertElementColorMode(themeCell, ColorMode.DARK); } } assertElementColorMode Theme cellが存在しているElementIdと変更したいColorModeをパラメータとして設定しています。 ステップ 1 Theme cellが存在しているElementのエビデンスを取得します。 getElementBufferedImage(MobileElement element) を使ってエビデンスを画像ファイルとして保存します。 ステップ 2 保存されている画像ファイルが null にならないようにチェックします。 ステップ 3 画像ファイル(x = 10, y = 10)のポイントからカラーを取得して変更したいダークモードのカラーをチェックします。 public interface AppiumHelpersInterface extends FindElementsInterface { AppiumDriver<MobileElement> getDriver(); Device getDevice(); /** * Get buffered image of mobile element * * @param element Mobile element * @return Buffered image */ default BufferedImage getElementBufferedImage(MobileElement element) { File image = element.getScreenshotAs(OutputType.FILE); try { return ImageIO.read(image); } catch (IOException e) { return null; } } /** * Assert element's color mode * * @param element Mobile Element * @param mode Color mode */ default void assertElementColorMode(MobileElement element, ColorMode mode) { BufferedImage image = getElementBufferedImage(element); Assert.assertNotNull(image); Assert.assertTrue(Utils.getColorString(image, 10, 10).matches(mode.cellRegex())); } } getColorString 取得した画像のx-point, y-pointのカラーをhexadecimalに変更して配列を返却します。 /** * Get color string from image at point x and y * * @param image BufferedImage * @param x int * @param y int * @return Hexadecimal Color String */ public static String getColorString(BufferedImage image, int x, int y) { int rgba = image.getRGB(x, y); int[] rgb = new int[]{ (rgba >> 16) & 0xff, (rgba >> 8) & 0xff, (rgba) & 0xff }; return String.format("%02x%02x%02x", rgb[0], rgb[1], rgb[2]); } cellRegex ダークモードとライトモードの値を判断します。 public enum ColorMode { LIGHT, DARK; public String cellRegex() { // 22222 - lighter black if (this == DARK) return "2[(0-9|a-f)]2[(0-9|a-f)]2[(0-9|a-f)]"; // ffffff return "f[(0-9|a-f)]f[(0-9|a-f)]f[(0-9|a-f)]"; } } public interface ColorModeInterface { String darkModeScript(); Map<String, Object> darkModeSettings(); Map<String, Object> lightModeSettings(); default void configureDarkMode(ColorMode mode) { getDriver().executeScript(darkModeScript(), mode == ColorMode.DARK ? darkModeSettings() : lightModeSettings()); } } 注意点 この方法はAppiumを利用したケースなのでNative Appのダークモード機能だけ使えます。 まとめ 本記事では、ダークモードの切り替える方法について説明しました。 ダークモードの自動化テストのためiOS(version13以上)とAndroid(version 5.0以上)両方で使えます。 今回はNative Appのダークモードテスト機能を行いましたが、今後はWeb Appのダークモードテストも試してみたいと思います。 グローバル開発内のテスト自動化チームは12月から増員しました。今後は、チームメンバーと一緒に、Appiumだけでなく、Katalonなど他のツールも用いた自動化テストに取り組んでいきたいです。 参考 DarkMode Appium Architecture
はじめに はじめまして。KINTOテクノロジーズ オウンドメディア&インキュベート開発グループ マネージャーの近藤です。 長いので社内でも誰も正確にグループ名を呼んでくれません。通称 メディアインキュベG でお願いします。 本記事では私のグループの紹介をさせていただきます。 グループの概要 成り立ち メディアインキュベGは、2022年8月に誕生した新生グループです。 もともとは弊社の主力サービスである 「クルマのサブスク」KINTO ONEのお客さま向けサイト の開発を一手に担う「KINTO開発グループ」というグループだったのですが、だんだんメンバーが増えてきたため、それぞれのチームをより深くマネジメントできるよう、2022年8月から2つのグループに分かれました。 ひとつが KINTO ONE開発グループ 、 そしてもうひとつが私たち オウンドメディア&インキュベート開発グループ です。 担当プロダクト 各グループが開発を担当している主なプロダクトをご紹介します。 KINTO ONE開発グループ プロダクト 概要 URL KINTO ONE 新車サブスクリプションサービスの申し込み機能、お客さまのアフターケア・サポートを行う機能の実装 https://kinto-jp.com/customer/login オウンドメディア&インキュベート開発グループ プロダクト 概要 URL KINTO ONE 新車サブスクリプションサービスのトップページ、取扱車種一覧、利用規約、ランディングページなどのコンテンツ制作 https://kinto-jp.com KINTOマガジン KINTO発のMaaS情報を提供するメディアサイト https://magazine.kinto-jp.com モビリティマーケット 「新しい移動のよろこび」を発見できるサービスサイト https://mobima.kinto-jp.com Prism Japan お出かけ先インスピレーションAIアプリ https://ppap.kinto-jp.com/prismjapan/index.html 中古車プロダクト KINTOが新たに手がける中古車モビリティサービス - 販売店向けプロダクト トヨタ販売店担当者向けのKINTO ONE販促ツールの開発 - ミッション 私たちメディアインキュベGのミッションは、 オウンドメディアと新規ビジネス創出において、テクノロジーとクリエイティブの力でお客さまに KINTOの価値を最大限にお届けする ことです。 グループの名前どおり 「オウンドメディア(自社保有メディア)」 と 「インキュベート(新規ビジネス創出支援)」 の二本柱です。 オウンドメディア(自社保有メディア) KINTOのモビリティサービス・プロダクトの価値をお客さまに有効にリーチさせるためのメディアを創り出す 該当プロダクト:KINTO ONE(ユーザー訴求コンテンツ)、KINTOマガジン、モビリティマーケット、販売店向けプロダクト インキュベート(新規ビジネス創出支援) KINTO ONEに続く新しいモビリティサービスをお客さまに提供すべく、KINTOと共に新規ビジネスを創出し、テクノロジーで支援する 該当プロダクト:Prism Japan、中古車プロダクト グループで取り組んでいること・取り組もうとしていること 品質担保施策 KINTO ONEのユーザー訴求コンテンツは、お客さまのご契約プロセスにおいて大変重要な情報を提供しています。 また、取扱車種やサービスの更新などのビジネスの動きに合わせ、デリバリースパンは平均して1週間です。タイミングによってはそれより短い期間でデリバリーすることもあります。 このような条件下で、一定のアジリティを出しつつクオリティも担保していかなくてはなりません。 従って、今よりさらに品質を担保できるようにするための施策検討と適用は常に行っています。たとえば次のようなものです。 CI/CDパイプラインでの自動チェック 弊社には自前のQAチームがおり、 プロダクトチームが依頼すればテストのプロフェッショナルに品質チェックを実施いただける仕組みが整っています。 ただ、ビジネスの都合によっては、QAテストまでに素材や原稿がどうしても予定通りに揃えられないケースも発生します。 そんな状況でも、抜け漏れなくデリバリーするためにはどうしたらいいか? 私たちはこんな施策をとりました。 改修発生時点で、特定のダミー文字列を入れた仮の状態でコミットする 正しい原稿が届き次第差し替えていき、テスト環境にデプロイする QAテストまでに原稿が間に合ったものは、「正しい原稿が上がっている」という観点でテストいただく QAテストまでに原稿が間に合わなかったものは、どこがダミーであるかをQAチームに伝えた上で「ダミー原稿が上がっている」という観点でテストいただく GitHub Actionsで「特定のダミー文字列が含まれているか」のテストジョブを構築し、mainブランチへのマージ時にチェックが発動するよう設定する こうすればQAのテストも通せて、かつ本番デプロイ時にダミー原稿のまま上げてしまうことも防止できます。 コンフリクト解消時のペアプログラミング必須化 短期間で広範囲のコンテンツ改修が走るため、マージ時点でコンフリクトが発生することはままあります。 このような場合、ひとりだけの判断で解消作業をせず、必ずペアプロで同じ画面を見ながら複数メンバーで確認しつつ解消作業を行うようルール化しています。 また、コンフリクトが発生していないプルリクでも、少なくともひとり以上のレビュアーがApproveしないとマージできないようにGitHubを設定しています。 スキルアップ 様々な経歴やスキルのバックグラウンドを持つメンバーが集まっているメディアインキュベGですが、 自分の所属するプロダクトチーム以外のメンバーが今なにをやっていて、どんな課題で悩んでいるのか、 日々の業務をこなしているだけではなかなか知る機会がありません。 そこで、日常業務以外で時間をとって、各人のスキル発表や技術情報共有の機会を設けています。 勉強会 直近だと、フロントエンドエンジニアによる「デザインシステム+アトミックデザイン勉強会」を企画しています。 バックエンドエンジニアは日々の業務でこのへんになかなか触れる機会がないので、楽しみにしているようです。 技術交流会 KINTO ONE開発グループのメンバーを含め、フロントエンドエンジニア全員参加で技術交流会をやろうとしています。 出社参加メンバーはお菓子やコーヒーなどいただきつつ、オンラインでも参加できる形式で予定しています。 グループ所属チーム・メンバー 前述の通り様々なプロダクトを手がけているメディアインキュベGですが、グループ内のチーム構成としては3つに分かれています。 各チームについて次にご紹介しますが、それぞれのチームがメインで担当しているプロダクトで表すのが分かりやすいと思いますので、 実際のチーム名とは若干異なりますがご容赦ください。 1. KINTO ONE等 メンバー(2022年12月時点) 8名 仕事の進め方 事業会社のエンジニアとして、 KINTO ONEのビジネスを理解した上でシステムとしてどうしていくべきかを考える のが最も重要な仕事です。 言われたことをただこなすのではなく、案件の内容を自分の頭で理解し、わからないことはすぐ問い返して解決し、 影響範囲や最適なロジックを自ら判断した上で案件を進めるのがこのチームの仕事のやり方です。 チームの雰囲気 メンバーの学習意欲が高く、スキルレベルの個人差はあれど、現状に満足してとどまろうとするメンバーはいません。 半期の技術スキルアップ目標もチャレンジングなものが多いです。 チームのこういった空気を牽引している技術リーダーの記事がこちらです。 SvelteKit + Svelte を1年間くらい使ってみた知見など 2. 中古車 メンバー(2022年12月時点) 4名 仕事の進め方 このプロダクトについては諸事情によりあまり具体的なことはお話しできませんが、仕事の進め方の特徴としては、 部署や所属会社の分け隔てなく、全員が意見を出し合えるワンチームとして機能している ことかと思います。 テーマ別の定例を週7本実施、KINTOビジネス側とのミーティングも毎週実施しています。 それ以外でもJiraとSlackで都度やりとりを行います。 チームの雰囲気 プロダクトマネージャーとリードエンジニアがかなり前のめりにビジネス側のプロダクトオーナーに突っ込んでいくので、 エンジニアメンバーは正直全員が全員は追いつけていない面もあるのですが、 それぞれの役割の中でスキルを上げつつ業務理解を深めようとしています。 というかそのリードエンジニアは私なんですけどね。 2021年9月に入社してすぐこのプロジェクトが始動し、以来ずっとリードエンジニアを担当していました。 とはいえ、2022年11月時点ではエンジニアメンバーも当時より増えたので、そろそろスキルトランスファーの段階に入ってきています。 新たなリーダーがチームをしっかり牽引してくれることを期待しています。 3. Prism Japan メンバー(2022年12月時点) 5名 仕事の進め方 プロジェクトマネージャーとプロダクトマネージャーがそれぞれ1名ずつ、エンジニアが3名の体制です。 2022年8月にPrism Japanをローンチして運用フェーズに入っています。 運用・リファクタのフェーズ体制はアジャイルを採用 し、そのためにQAチームから専任QAメンバーをアサインしました。 チームの雰囲気 全員が当事者意識を持って自走できているチームです。 メンバーが互いに尊敬しあい、それぞれの専門分野で長所を生かして短所を補いあう働き方ができているなと感じています。 私のすぐ後ろの席で、いつも課題や改善策についてみんなで論じ合っているのをよく耳にします。 こんな仲間を募集しています 1. KINTO ONE等 PdM システム開発の立場からプロダクトのあるべき姿を考え、提案できるようなPdMチームの設立を目指しています。 【PdM(KINTO ONE等)】の応募はこちらから フロントエンドエンジニア・バックエンドエンジニア プロダクトのあるべき姿の実現のためには、実際に手を動かせるエンジニアも不可欠です。 新しい技術を貪欲に学習し、かつKINTOのビジネスを理解してKINTOと並走していけるポテンシャルを持ったメンバーにジョインしてもらいたいと思っています。 【フロントエンドエンジニア(KINTO ONE等)】の応募はこちらから 【バックエンドエンジニア(KINTO ONE)】の応募はこちらから 2. 中古車 フロントエンドエンジニア・バックエンドエンジニア 中古車ビジネスを理解しKINTOとタッグを組んでシステム開発を進めていけるエンジニアをもっと増やしたいと考えています。 そのノウハウは、現在のプロダクトだけではなく、これから生まれるKINTOの新しいサービスやプロダクトにも必ず活かせます。 つまり、この中古車プロダクトの業務を通じて、KINTO/KTCの企業価値に大きく貢献できるエンジニアになれるはずです。 【フロントエンドエンジニア(中古車)】の応募はこちらから 【バックエンドエンジニア(中古車)】の応募はこちらから 3. Prism Japan バックエンドエンジニア ネイティブアプリの開発を通じて新たなモビリティ市場の開拓に貢献したい方、チャレンジしてみたい方にぜひジョインいただきたいです。 【バックエンドエンジニア(Prism Japan)】の応募はこちらから
Introduction On this second part about localization at KINTO Technologies, we would like to share with you what the team has accomplished so far. The task at hand On my previous article I explained how as data type software translations are often stored as a key-value pair and today we will go through how we manage this data. Having these pairs of keys and terms in mind, we proceed to determine how localization project managers handle the base English and request our Language Service Providers (LSPs) to deliver us back the translations. It is common to see -also in my experience as a freelance translator- engineers create an Excel sheet with one column of translation keys and a second column with the source language terms that are then sent to translation by adding as many columns as target languages needed. There are three main problems I see with this management style: Lack of context Inconsistency issues down the line Prone to human error First, Excel sheets are simple rows of text without any context for the translators: is the term a button? Are there any space limitations design-wise? In the case of storytelling, who is speaking and to whom in what kind of situation? The second problem is that those terms without being fed into a Translation Management System (TMS) will not be recorded anywhere. That can potentially lead to inconsistencies in quality and customer experience in the long run: are we calling it "reservation" or "booking"? And that is only with the source language; imagine this issue multiplied by the number of languages. Finally, it has a high risk of causing human errors on the development side. When the translations are stored in Excel files, they will eventually need to be painstakingly copy-pasted manually into the source code one by one (the "localizable.strings" file in our example previously). This can lead to copy-paste errors, typos, or even bugs if there is no proper QA to do the final check. How we solved it To solve these issues, we have decided not to manage translations in Excel and instead introduced a dedicated tool to manage the translation of our products, called Lokalise . Lokalise is a Translation Management System that manages translation tasks and allows us to have all terms centralized in one place. Another benefit of the tool is the ability to maintain a Translation Memory (a database that records how sentences have been translated before) and start a glossary creation -a vocabulary list- that can be applied across all our products. It also has the capability to connect to GitHub where the source files are stored, which allows us to "pull" the keys that our developers create for a new screen or new functionality, thereafter, "pushing" back all the target languages translations' key-and-term pairings with a pull request to GitHub. Automating the process this way not only raises productivity but also reduces the working time for both developers and the localization team. Furthermore, we can also maintain consistent quality, while ensuring that the integrity of the terms is kept and handed over to our engineers accurately. Another enormous benefit of using Lokalise is that it allows us to import screenshots for each of the terms from our design tool Adobe XD to Lokalise, so translators have visual context when translating in the tool and are not blindly typing away on an information-deprived Excel sheet. Below are the flow diagrams before and after implementing Lokalise for our Global KINTO app, where we also needed to deal with file conversions to have it available for both iOS and Android. Lokalise also takes care of the format conversion when exporting, saving us time: Next Steps One of our next steps is to think about scalability. We were able to automate the updates in the source files through Lokalise, but as the pull requests to each of the files are done one by one, it can quickly become a heavy task as the number of GitHub repositories and products grow over time. One solution we are considering is to create an in-house small management tool that would go in-between Lokalise and GitHub, allowing us to centralize all the pull requests with the updates needed on the source files. As part of our efforts to strengthen our QA processes, another plan is to create a series of style guides, akin to our existing Brand Guidelines. This would further ensure that even translations which are requested to our language service providers are easily understood, maintain the brand's tone and manner without gaps between translators, or even between languages. There are still more ideas and exciting projects awaiting us on the horizon, such as the potential to apply yokotenkai (horizontal deployment) of our activities to other KINTO services around the world. I might talk about these at a later point, but for now, I thank you for your interest in my post! I hope I was able to spark a bit of curiosity on this topic, and that next time you download an app, use a streaming service or play a video game, you think about the technical complexities at play for multi-region content.
はじめに はじめまして。KINTOテクノロジーズでエンジニアの教育研修を担当している熊谷と申します。 私は海外・国内問わず旅行が趣味なのですが、最近では全国各地の空港巡りに興味があります。レストランエリアがとても充実している新千歳空港や、青い海が目の前に広がる那覇空港など魅力的な空港はいくつもあるのですが、私のおすすめは、富山空港。福岡空港ほどではありませんが市街地からも近く、なにより空港内にある寿司屋が本当に美味しいです。北陸の旅に行かれる際は、是非とも立ち寄ってみてください。 さて、今日は我々の組織、エンジニアリング教育研修PJTが普段どういうことをやっているのかをざっくりご紹介させていただきたいと思います。 プロジェクトが始まったきっかけ 私たちは、2022年8月に本格始動した、いわば出来たばかりの組織です。 KINTOテクノロジーズでは積極的に採用活動を行なっており、エンジニア・デザイナー・QAエンジニアなど含め300名近い組織になってきました。 しかしながら、ここ1、2年で急激に拡大をしたため、 これからはこのプログラミング言語で開発をしていくからこういうスキルを持っていてほしい、 あるいは、このキャリアの先にこういったキャリアパスがあってほしい、 といった議論が乏しいままここまで来てしまったという現実があります。 そこで我々は、エンジニア陣が持っているスキルを再整理し、必要なスキルを学びたいときに研修を受けられる環境を作ることを目指して立ち上がりました。 また同時に、エンジニアが抱えている不満や不安を組織の面から改善し、リテンションを上げていく活動もしています。 自走するエンジニア 私たちのミッションとしては、自走できるエンジニアのために何をサポートできるか、を常に考え、行動に移していくことを心がけています。 グループで現在取り組んでいること 教育 研修の一環として、トヨタ生産方式(Toyota Production System:TPS)の研修が実現できました。 私個人としてせっかくトヨタの関連会社に入社したのだから、リーン開発方式の元となったトヨタ生産方式をもっと知りたいと思っておりました。しかし社内でそのような研修はなかったため、トヨタ自動車にお願いして、2回にわたってTPS研修を開催していただき、50名を超える方々にご参加いただきました。「モノ情」と言われる物と情報の流れ図を書くことにより、どこにムダがあるのか、どこに効率化を阻む要素があるのか、を図で分かるようになり、KINTOの業務でも活かすことができています。 グローバル開発グループでは、社内の縦割りが不満に感じているエンジニアが多いことに加え、勉強会でも座学だけだと飽きるという声を受けて、Innovation Dayという企画をやってみようということになり、サポートしています。 また、KINTOテクノロジーズではAWS(Amazon Web Service)やGCP(Google Cloud Platform)といったパブリッククラウドを全面的に採用しており、AWSやGCPの中で私たちをサポートしてくださる方々とも交流が活発になってきています。サポートエンジニアの方々を定期的にお招きして勉強会を実施する等、AWS、GCPの方々と皆で一緒にパブリッククラウドを盛り上げています。 組織開発 社員サーベイにおいて、社内の情報共有が少ないという不満が多く上がっていました。KINTOテクノロジーズでは月一回全社でおこなっているミーティングはあったのですが、一方的な伝達ばかりのことも多く、相互に情報を共有する場になっていないと感じていました。そこで本部会の運営を見直し、本部長からの開発・事業報告の時間に加え、新たに開設したオフィスの紹介を生中継で行ったり、チャットをオープンにしてタイムリーに質問を受け付ける等の改善をおこなっています。そうすることによって、社内のことがよく分かった、社内の風通しが良くなった、との声が多くいただいています。まだまだ改善の途中ではありますが、引き続きオープンで双方向のコミュニケーションを取れるように尽力していきます。 また、毎月多くの中途採用者に入社いただくのですが、自グループ以外のマネージャーとの接点がないため話しかけづらいという声も耳にしています。そこでOJT期間中に他グループのマネージャー、リーダー陣とコミュニケーションが取れるよう、ビルドアップ(関係性の構築を意味するサッカー用語ではありますが)をしていただくように推奨しています。これにより、社内の多方面でのコミュニケーションがより活発になることを期待しています。 グループメンバー メンバーは今のところ2名体制の少数精鋭チームです。私の他に人材エージェントから転職してこられた方もいますので、その営業力を活かし、カンファレンスのスポンサードや生産性指標を測るツールの導入などを積極的に社内提案しています。その生産性指標のツールの導入をきっかけにオンラインのイベントへの登壇依頼をいただくなど、日々の活動がさまざまな新しい出会いを産み出し、活動の輪をより広げていけています。 また、チームはスクラムのメソッドを使っています。2週間を1スプリントとして、スプリントごとに予定タスクと実績を洗い出しています。私たちは長期にわたる施策を実施することも多いのですが、長期施策は抽象的な話が多く具体的に進めることが時に困難です。ですがスクラムを用いることによって、短期的にチェックポイントを設けそれにコミットすることを通じ、長期的な施策もより具体性を持って進められるメリットがあると感じられるからです。 これから挑戦したいこと まずは、エンジニアスキルを明文化したいと考えています。KINTOテクノロジーズにはこういう人材が集まっていて、こういう点は強みを発揮できる、けれどもこういうスキルが足りないと思われるから研修でそれを補おう、という戦略を立てやすくしたいと思っています。 また、定期的に社員サーベイを取れる仕組みを導入することを検討しています。組織開発は一度に成果があらわれるものでもなく、さまざまな施策を組み合わせた結果として徐々に社員の離職率が下がるのだと思います。ですので、定期的に社員サーベイを実施して、今月はこの施策が効いたから次はブラッシュアップしてみよう、といったさまざまな改善ができたらいいと思っています。
Introduction Nice to meet you. My name is Kumagai, and I’m in charge of the Engineering Education Training Project at KINTO Technologies. I enjoy traveling both in Japan and abroad, and recently I've taken a particular interest in visiting airports across the country. There are many appealing airports, such as New Chitose Airport with its excellent dining options, and Naha Airport, where the deep blue sea stretches out right before your eyes. My personal favorite, however, is Toyama Airport. It's not quite as close to the city center as Fukuoka Airport, but it's still very convenient. Most of all, the sushi restaurant inside the airport is absolutely delicious. If you’re traveling in the Hokuriku region, I highly recommend stopping by. Today, I’d like to give you a brief overview of what our team, the Engineering Education Training Project, usually does. How the Project Started We are a newly formed team that officially began full-scale operations in August 2022. KINTO Technologies has been actively expanding its hiring efforts, and our organization has grown to nearly 300 members, including engineers, designers, and QA engineers. However, because of the rapid growth over the past year or two, we’ve reached this point without having much discussion around key topics, such as which programming languages we’ll focus on moving forward and what skills will be expected, or what kind career paths we hope to offer. To address this, we launched the project with the goal of reorganizing the skills our engineers currently have and building a system where they can access training whenever they want to learn something new. At the same time, we’re also working to improve the organizational issues that cause frustration or uncertainty among engineers, with the aim of increasing retention. Self-Driven Engineers Our mission is to continuously think about how we can support engineers who work independently, and to put those ideas into action. What the Group Is Currently Working On Education As part of our training efforts, we were able to offer a session on the Toyota Production System (TPS). Personally, since I had the opportunity to join a Toyota group company, I had always wanted to learn more about TPS, the foundation of lean development practices. At the time, the company had no such training program, so we arranged for Toyota Motor Corporation to hold two TPS sessions, drawing participation from over 50 people. By creating flow diagrams of goods and information, known as "monojou," participants were able to visualize sources of waste and factors that block efficiency. This has proven useful in our daily work at KINTO. In the Global Development Group, many engineers have expressed frustration with the siloed structure within the company. Others have said that study sessions become dull if they are purely lecture-based. In response, we decided to support a new initiative called Innovation Day. KINTO Technologies has also fully adopted public cloud platforms such as AWS (Amazon Web Services) and GCP (Google Cloud Platform), and we’ve been deepening our collaboration with the people who support us within these platforms. We regularly invite support engineers to lead study sessions, and together with the teams from AWS and GCP, we’re working to promote and energize the use of public cloud. Organizational Development In an employee survey, many people expressed dissatisfaction with the lack of information sharing within the company. At KINTO Technologies, we held a company-wide meeting once a month, but it often consisted of one-way communication. We felt it wasn’t functioning as a place for mutual information sharing. To address this, we reviewed how the meeting is run. In addition to setting aside time for the Director General to share development and business updates, we now livestream introductions to newly opened offices and keep chat channels open to accept questions in real time. As a result, we’ve received a lot of positive feedback, such as “I have a better understanding of what’s going on in the company” and “Communication has become more open.” We’re still in the middle of making improvements, but we’ll continue working to create an open environment that enables two-way communication. We also welcome many mid-career hires each month. However, we’ve heard that it can be hard for them to approach managers outside their own group because they don’t have opportunities to interact. To improve this, we encourage communication with managers and leaders from other groups during the OJT period, recommending that they engage in “build-up”, a soccer term that refers to building connections. We hope this will lead to more active communication across different divisions of the organization. Group Members At present, we are a small team of two. In addition to myself, we have a member who joined from a recruitment agency. Leveraging their sales expertise, we actively propose ideas within the company, such as sponsoring conferences and introducing tools to measure productivity. The introduction of one such productivity tool even led to invitations to speak at online events. These kinds of daily efforts continue to create new connections and help us expand the reach of our activities. Our team also follows the Scrum methodology. We operate in two-week sprints, reviewing both planned tasks and achievements each cycle. Many of our initiatives span the long term, and such efforts often involve abstract discussions that can make concrete progress difficult at times. However, using Scrum allows us to set short-term checkpoints and commit to them, which helps us move forward with long-term initiatives in a more concrete and actionable way. What I Want to Try Next First of all, I want to clearly define and document the engineering skills we have. By doing so, I hope to make it easier to develop strategies that identify the types of talent we have at KINTO Technologies, highlight our strengths, and recognize areas where skills are lacking so we can address them through training. We’re also considering introducing a system that allows us to conduct regular employee surveys. Organizational development doesn’t yield results overnight. I believe that by combining a variety of initiatives, we’ll gradually see a reduction in employee turnover. That’s why I’d like to conduct regular surveys and make ongoing improvements. If a certain initiative proves effective in a given month, we can refine it and apply it again moving forward.
こんにちは。KINTOテクノロジーズ、クリエイティブグループでアートディレクションを担当しているアワノと申します。普段は社内全般の視覚に映るコンテンツの方向性をまとめ、決めることなどが仕事です。 今回は、KINTOテクノロジーズテックブログが生まれた時のお話を少しばかりさせていただきます。拙文、読みづらい点ご容赦ください。 はじまりは、 社内エンジニアの情熱がきっかけ 元々TOYOTAから生まれたクルマのサブスクを中心に、モビリティサービスを展開するKINTO。KINTOのテクノロジー部分を担う部署が、KINTOテクノロジーズ。広くモビリティ分野をテクノロジーの力でドライブさせていくことが期待されています。 私たちのヴィジョンやカルチャーに共感してくれる仲間を増やしたい 私たちのヴィジョンやカルチャー、働き方や使っている技術など、どこかに目に見える形になっていたっけ?発信したりしていたっけ?ということで、テックブログで会社の取り組みを発信していこうとなりました。 社内外の人や想いをつなぐ存在になりたい 上述の通り、大きな目的は、社内の取り組みを発信する仕組みを作り知ってもらおう。そして、その中で想いを同じにしてくれる仲間に興味を持ってもらおう。ということで始まりましたが、 次に、人数も増え、組織も拡大したことから、まだまだ社内での情報共有も整っていない部分があり、あの部署では、どんなことやっているのだろうということが普通にあり、ブログを通して普段取り組んでいること、使っている技術、思っていること、興味を持っていることなどを発信することによって、社内でも人と人を繋ぐような存在に育っていけばいいなということも。 私たちの想いをロゴにしたい 発起人のエンジニアの有志グループが中心となって、上述のような目的や要望をまとめ、それを叶えるためのサイトや運用体制などの要件をまとめていきました。社内での共有を経て、無事プロジェクト化。その後、ロゴがあった方がいいということで、クリエイティブグループに声がかかりました。 (さも、自分がかなり関わっていたかのように語ってしまいましたが、私がプロジェクトに関わったのは、ここが最初です。すみません。) そこで、まずは目標や目的、想いなどをコアエンジニアのメンバーにヒアリングさせていただきました。 そこででてきたのがこのような想い。 (すでにまとめられていました) テックブログのVision アウトプットカルチャーをリード テックブログのMission 業務で得た知識を発信する事で理解を深め、世界へ還元する事でテクノロジーの発展に寄与する テックブログのValues 組織の枠を越えたネットワーク構築 情報発信の壁を取り除きアウトプット力強化 文化を醸造する事で採用力を高めエンゲージメント向上 また、KINTOテクノロジーズのメンバーの「舞台裏」を「表舞台」にという想いも。 上述のテックブログのVisionやMissionなどの想いを元に、柔らかくお話しをしながら、造形のヒントとなるキーワードを抽出していきました。 (個人的に、柔らかさは、忌憚のない意見交換に重要だと思っています) このキーワード、方向性を元に社内のデザイナーにラフを作ってもらいます。 (実際のロゴも自分で作るわけではなく、デザイナーと対話しながら詰めていき、実際手を動かして作るのは、デザイナーさんです。) 初回のロゴのラフ案 全体は上述で抽出した方向性をとらえつつ、各案で、それぞれ押し出したいポイントの割合を変えて作っていきます。この時に、より、いろんな使用シーンでの見え方も含めて選んだ方がいいので、PCで表示の場合、スマートフォンで表示の場合、バナーで表示の場合など、いろんな表示場所にロゴを入れたものもセットでつくります。 (違うところで使おうとすると、どうしてもうまくはまらない。なんかぴったりはまってない。ということを後々感じることが極力ないように。) プロジェクトメンバーに見てもらう テックブログのコンセプトを元に、方向性ごとに数案作成し、プロジェクトメンバーからリクエストや感想を引き出し、いいね!というリアクションがもらえれば、よりコンセプトに合う案を絞っていきます。ここで、ん、みたいな空気になると、求めていた期待とギャップがあるということになり、その差を話しながら埋めていく作業まで戻ります。2マス戻るやふり出しに戻るみたいな感じです。)また、ミーティング中にみんなから意見が出たものは、その場でデザインを調整しつつ、タイムリーに意見をデザインに反映しながら方向性を絞っていけたのも良かったです。 大枠の案や方向性が決まり、ここから、決まった案の細部を調整していくブラッシュアップ作業に入っていきます。細かいズレ、バランス、などで受ける印象が結構違ったりするので、地道に詰めていきます。方法は、基準をまず作り、地道にちょっとずつ変化させたパターンを並べて、ベストを探っていくみたいなやり方です。 よし、バランス良いな!他も試してこのバランスがいいなとなったら、使い道に合わせた形状や色のパターンを作っていきます。 最終的に、できたのがこちらです。 (実制作は社内のデザイナーさんです) はめて完成 あとは、実際のテックブログにはめていただき、問題なければ完成です! ガイドラインにまとめる 間違った使われ方がされないように、ルールを決めて、ガイドラインを作成します。「ロゴ周りの余白はこの位確保してね。」とか、「変形や装飾などで違う印象を見る人に与えないようにしてね。」など細かく定義していきます。 終わりに こんな感じで、想いを同じにした仲間たちと一緒により良い形を模索しながら進んでいます。テックブログを読んでいただき、私たちの思っていることや、やっていること、に興味を持っていただけましたら幸いです。それでは、またの機会に。
はじめに こんにちは。KINTOテクノロジーズでバックエンドを担当している森本です。 KINTO ONE開発グループに所属しています。Javaをメインに利用してKINTO ONEの開発をしています。今回は業務とは別に実施しているGraphQLの勉強会について紹介させていただきます。 GraphQLとは GraphQLとはクエリ言語の一つです。SQLのような他の言語とは異なり、特定のデータストアに限らず複数のデータソースとデータをやりとりすることができます。 バックエンド側でスキーマを定義しておけば、フロントエンド側はその定義に従って自由にオブジェクト内の項目を取得することができます。REST APIとは異なり、フロントエンドがバックエンドから返却してほしい情報を柔軟に指定できます。利用しない情報を無駄に取得する必要がなくなり、またネスト構造になっているオブジェクトを取得するために複数回APIを呼ぶ必要もなくなります。 勉強会の目的 勉強会の目的は以下の2つです。 技術力をアップしたい グループを超えて交流したい 技術力をアップしたい 普段の業務で利用している技術とは別に新しい情報をキャッチアップしたいが、ハードルが高いとメンバーそれぞれが感じていました。例えば言語の知識が足りないことが挙げられます。今回のGraphQLのチュートリアルではTypeScriptが利用されていました。そのため、GraphQLを学ぶ前にまずTypeScriptを学ぶ必要がありました。知識や経験が異なるもの同士で補うことで、このような課題をクリアして学習のコストを下げることができます。 グループを超えて交流したい 所属するグループ、チーム、プロジェクトがそれぞれ異なる年齢の近いメンバー同士が交流するきっかけにしたいという思いもありました。既にお互いを認知している仲の良いメンバー同士ではありますが、定期的に集まることでより仲良くなろうという魂胆です。また勉強会を通してお互いの持っている新たな一面を知ることができる機会になるとも考えました。 実施内容 なぜGraphQLか バックエンドでAPIを普段実装しているメンバーは、要件が発生するたびAPIを作成する必要があることに悩みを抱えていました。もちろんサーバー側で処理を行った方が実行速度が速いものはありますが、情報をそのまま返却するAPIを増やしていくのは面倒だと感じていました。そこでGraphQLが解決策として良さそうだという話を聞き、ぜひ試したいと常々思っていました。 また既にGraphQLを利用したことがあるメンバーもいましたが、全体の処理の流れを把握したいという思いがあり、GraphQLを学習することにしました。 勉強会に利用したチュートリアル GraphQLのライブラリにはApollo GraphQLを選び、チュートリアルは以下リンク先のものを使用しました。 GraphQL Tutorials 理由としては、チュートリアルの量が充実しており、入門編として適切だと感じたためです。また勉強会メンバー内に業務でApollo GraphQLを利用したことがある人がいたため、既に社内で実績があると判断したためです。 勉強会の概要 日時 週に1回、18時以降でメンバーの時間が揃うところで実施しました。 メンバー メンバーは25歳から28歳までの若手8人です。それぞれ所属が異なり、Webアプリのフロントエンド・バックエンド、またモバイルアプリのフロントエンド・バックエンドと多様な経験を持つメンバーが集まりました。 実施した範囲 チュートリアルのLift-off IからVまでの全5章を実施しました。GraphQLを実装するにあたり、基本的な事項が記載されています。 形式と工夫した点 勉強会では以下の流れで実施しました。 もくもく会でチュートリアル実施 チュートリアルの内容を発表形式でアウトプットして知識定着 初めはいわゆるもくもく会を実施しました。もくもく会とは、集まったメンバーがそれぞれ黙々と作業・学習をする勉強会のことを指します。 Apollo GraphQLを利用したことのあるメンバーもいると記載しましたが、それでも処理の全体像を把握しているメンバーはいませんでした。そのため、まずはそれぞれが同じチュートリアルを実施し、分からないことが出てきたタイミングで話し合いをして解決する、という流れで実施しました。 しかし本当に理解できているか怪しく、このまま先に進むよりはまずは復習するべき、との意見が出ました。そこで同じチュートリアルを持ち回りで発表し合うことにしました。 発表形式では、発表者はチュートリアルを一言一句理解する必要がありました。もくもく会ではなんとなく進んでいた箇所も、あらためて読み直すと答えが書いてあったということもありました。発表の際には質問ができたり、ソースコードを変更して試してみたり、1人では見つけられなかった新たな気づきもありました。 勉強会の様子。手前には勉強会用に用意したサンドイッチが写っています。 さいごに まずはGraphQLについて深く理解できました。それぞれが持っている知識・経験を使ってお互いを補い合うことで、1人よりも速く・確実に進められました。また学習を共にする仲間がいることで、挫折しそうなときも諦めずに続けられました。 今後はApollo GraphQLのチュートリアルの残っている章を進めたり、さらに新しい技術事項を取り上げて学んでいったりする予定です。 また、何らかのアプリケーションを作ってみたいという話も上がっています。それぞれがトライしてみたい言語やフレームワーク、アーキテクチャを利用してみて、さらに技術力向上に努めていきたいと思います。
About me I am Bharath from Global KINTO. I am a part of Global KINTO ID Platform team and product engagement team. I have also been supporting ad hoc projects like TechPortal and UserPool management screen. I am well versed in OIDC and AWS Cognito. Feel free to reach me anytime at bharath.tv@kinto-technologies.com if you would like to discuss these. I am always excited to talk about ID. About today's topic In order to create contact points with overseas group companies, cultivate the ability to play an active role in the global arena, and further evolve as a global technology company, KINTO Technologies (hereinafter referred to as KTC) participated in the global hackathon "toyotaswarm" hosted by Toyota Motor North America (hereinafter referred to as TMNA) on July 2022. Since I participated in this event from Japan remotely as well, today I'd like to share what we did for this event. Regarding TMNA “SWARM“ Hackathon The second year of this initiative was held over three days from July 27 to 29, 2022, with a total of 270 participants in 40 teams from Toyota Group companies around the world. There were 3 challenges announced this year. #1 Safety #2 Innovate to Carbon Neutral #3 Open Global Technology Innovation Since we thought digital identity is a major challenge and my team has been working on this topic so far, we were selected to participate in the hackathon this year. Idea from our team We at Global KINTO, are focused on making it all easy and simple for the end user to access our mobility services. Our Global KINTO App, aims to be the single app that connects all KINTO services. My team, Global KINTO ID aims to make it easy for end users to access any KINTO service across the globe by registering only once. So the problem we wanted to address in the hackathon also was a similar one. How an end user can share their information across services hassle-free. It doesn’t make sense when a user has to share their name and other details repeatedly to start using a different service. We decided to do a PoC (proof of concept) of a service that can share user information with other services upon consent from the user. About our team Due to visa restrictions, we only have 3 members who participated in the event at Dallas (HQ of TMNA in Texas, US) and the remaining members supported the activity from Japan remotely. Onsite team: Captain: Feng Xu (Group manager) PdM: Dai Sasaki FE: Alex Remote team: FE: Chris.L BE: Bharath During the hackathon We got all warmed up in a few days, and finalized our concept and how to achieve it. Finally, even though we only had 3 members onsite, that didn’t stop us from going forward. We brushed up the idea with the team and built 9 screens, 11 APIs, including many AWS components and over 1100 LoC (Lines of Code). The event started upbeat when the Olympic gold medal winner, Erin Jackson joined us in the event. This is the closest we would have ever gotten to a Olympic medal. The teams were given separate tables to start working on their concepts. It was nice to see all the hyped-up teams get into action. Meanwhile, my team had a tough time getting work done due to a few of us working offsite in a different time zone. It was quite clear what actions each of us should do but we have to integrate everything to come up with the working model. Typical problems like connecting our server to a different IP address or working with AWS CDN in a different region happened but overall things went well. As a result, we cleared round 1. Since only half the teams would pass round 2, it was stressful. We did our best but unfortunately that we didn't pass round 2. What impressed me here was the high degree of perfection of the other teams' ideas. As an example, the idea of prevention of drunken driving and the idea of reducing carbon emissions passed round 2. For both of these, they do not only have a software part, but they also had an embedded solution proposal which included both software and hardware. What we learned from participating TMNA senior management was around the hackathon the whole day, anyone can easily talk with them if they wanted. It was a great opportunity to get close to them and understand their thoughts directly. The people who came from other countries were very open and kind to connect with us. It was a perfect opportunity to make connections between several different organizations which hopefully creates some synergy. Since this event is going to be a regular event from now, we are looking forward to participating in it next time as well and bringing more value for Toyota and the whole world through this activity.
はじめに こんにちは、KINTOテクノロジーズでコーポレートエンジニアをしている及川です。 今回は、KINTOテクノロジーズのIT管理チーム(情シス)ではどのような環境やチームの活動基準で仕事をしていて、何を目指しているのかについて書きたいと思います。 目次 IT管理チームの業務内容や雰囲気 IT管理チームが挑戦したいこと IT管理チームが目指す姿 IT管理チームの業務内容や雰囲気 IT管理チームは幅広い社内業務システムを担当していて、ロケーション的にも遠隔の複数拠点(東京2拠点・名古屋・大阪)で業務をするため自律的に活動していく必要があります。 各拠点のエンジニアが非エンジニアリング業務に割く時間をカットして、エンジニアリングに集中できる時間や環境を提供するために、各拠点にIT管理チームのメンバーを配置しています。 チーム内で前提となる活動基準に合意して、同じ価値を目指して日々業務に取り組んでいるのですが、その活動基準をまとめると以下になります。 Mission ㅤㅤ従業員(社員、パートナー)を中心として、仲間を尊重し、​利便性と ㅤㅤセキュリティーを追求して会社の発展に寄与する。​ Value ㅤㅤ自律​ ㅤㅤㅤㅤ目的​、品質​、プロセス ㅤㅤ協調​ ㅤㅤㅤㅤ相互尊重​、情報共有​、スキルの平準化​ ㅤㅤレスポンス​ ㅤㅤㅤㅤ従業員目線​、素早さ​、正確性​ IT管理チームの立ち位置は、 生活基盤インフラ(電気・水)をイメージして、従業員から頼られる必然の存在を目指す=エンジニアがエンジニアリング以外に時間を取られない環境整備 ために、開発環境をITの側面から支えていくことがIT管理チームの大切な役割となります。 社内システム(SaaS)環境再構築、ゼロトラスト推進、自動化、効率化といった軸で業務を進めて従業員の利便性とセキュリティーを高めつつ、全体最適化を実現するためのソリューションやシステムを導入するプロジェクト業務を実施しています。 日常的なオペレーション業務も実施していて、サービスデスクやオンボーディング、アカウント作成/削除、PCキッティング、PC/スマートフォンやモニターなどのIT備品等の調達・管理といった業務があります。 プロジェクト業務とオペレーション業務の両輪を上手く回転させながらバランスを取りつつ、開発スピードを上げるために必要なことをチーム一丸となって実施しています。 IT管理チームが挑戦したいこと 一年間で従業員が100名以上増え、急成長しているフェーズのため、IT管理チームに求められるスキルセットも変化してきたことにより、上記で書いた、IT管理チームの活動基準、Valueに同意してプロジェクトとオペレーションの2つを実行できるコーポレートエンジニアにJoinしてもらいました。 今ではIT管理チーム内に5つのミニチームがあり、臨機応変かつスピード感のあるスキルを持ったメンバーで業務を推進しています。 なお急速に従業員が増え続ける状況でも、従業員が開発に集中できる環境を構築するため、システムの再設計、ルール構築や変更を実施しています。 KINTOテクノロジーズではWindows、Macの2種類からPCを選択可能ですし、社内システム(SaaS)についても多数活用しているという多種多様な環境です。 多様な環境下でも開発スピードを落とさないことを前提に、適切なシステム環境を実現するため、現状の設計を見直してスピード感を持って最適化を実施しています。 スピード感も必要ですが、環境変更に伴うメリットやデメリットをしっかり把握しチーム内レビューで効果を見極めた上で本番環境へリリースします。本番環境リリース後のレビューもしっかり行い、反省点など次回に活かすことも目的にチーム内プロセスも重要視しながらスキルやノウハウの平準化も進めています。 新しい価値や要望に応えるため現在の使い勝手や内容に満足せず、自分たちで能動的に要望やトレンドをキャッチアップしてシステムやルールをブラッシュアップしています。 IT管理チームが目指す姿 上記で書かせていただいた気持ちの根底は、IT管理チームのやりたいことだけを実現したいという気持ちでは無く、従業員の皆さんをサポートする・したいという気持ちを持ってそれをITで実現することです。 従業員の皆さんに近い運用(現場)にこそ改善のヒントがあり、最上級であるべきだと考えに基づいて、各ミニチームにも様々な運用を担当してもらっています。 その運用業務の中から出てくる改善要望を深堀して、設計やソリューションに当てはめて開発現場が集中できる環境を能動的に創出できるようなチームを目指しています。 私自身、コーポレートエンジニアキャリアの経験はほとんどありませんでしたが、ITで現場環境を改善することや技術には興味がありました。 つまり、バックヤードは様々でも、上記視点やマインドがあればコーポレートエンジニアのキャリアは築けると思います。 従業員に頼りにされる、オープンなIT管理チームを目指して業務に精励していきたいと思います。
Hello, My name is Shweta Oza. I joined KINTO in April 2022 at the Global Development Group. I am an application developer who has recently gained interest in DevOps. I am currently working in the Coupon Team. Our team develops and maintains Coupon APIs for customers/ merchants all over the world. There are many features that are being continuously developed and deployed. For any project it is important to maintain the databases, including data backup and rollback. This way, if anything goes wrong when releasing a new version, you can safely rollback the changes and restore the backup. As an open-source database migration tool, our company uses solutions such as Flyway. Flyway strongly favors simplicity and convention over configuration. It is based around just 7 basic commands: Migrate, Clean, Info, Validate, Undo, Baseline and Repair. Below are a few concepts and simplified procedures about how to back up the database manually using a script. Overview Coupon System is a tool that easily issues and manages coupons that can be used for KINTO services or other partner services. The coupon system is in continuous development to improve and upgrade with new functionalities. With every new change, it is necessary to manage the databases that the coupon system uses; which plays a key role in any software project. In our case, we use MySQL . In coupon, whenever we have any new release the steps we follow are: Get the functionalities developed. Test them locally and then on AWS test environments. Take a backup of the DB before release. Release the new functionalities. If any issues, roll back to the previous version of the release. In order to achieve these we have backup and rollback scripts to reduce the number of instructions to follow in CLI. This saves time and maintains consistency of structure for backups or rollbacks. Let's learn some basics What is a database backup? A database backup is a copy of data that is stored on a server. What is the purpose of a database backup? Backups are used to prevent unexpected data loss. In an event of failure, if the original data gets lost or corrupted, with the help of a backup, it is easy to restore the data again. What are the types of database backup? Physical backup ^1 Physical database backups are backups of physical files that are used to store and recover databases. These include different data files, control files, archived redo logs, and many more. Typically, physical backup data is kept in the cloud, offline storage, magnetic tape, or on a disc. There are two methods to perform a physical backup : Operating system utilities Recovery manager Advantages: Total control of the data. Storage cost is cheaper. Speedy process retrieving backed up data. Disadvantages: Stored data in any device can get corrupted making it hard to recover data. Data can be ruined by natural disasters. Loss of storage devices. Logical backup ^2 Logical backups contains logical data which is retrieved from the database. It contains a view, procedure, function, and table. This is useful when users want to restore or transfer a copy of the database to a different location. Logical backups are not as secure as physical backups in preventing data loss. It only provides structural details. Every week, complete logical backups should be performed. Logical backups are used as a supplement to a physical backup. Advantages: Useful when the user needs to restore the complete database to a previous instance. It is more complex and provides granular recovery capabilities. Disadvantages: Critical for recovery of special components. Less secure compared to physical backup. It only provides structural details. We are going to see all about Logical Database backups in both local and in AWS CLI. Because it is an important step with reference to a developers' perspective to operate with data in DB. To manage Amazon RDS(Relational database service) using AWS CLI Amazon RDS [^3] [^3]: https://aws.amazon.com/rds/ It is a service that can safely use RDB on the cloud without setting up a server. Amazon RDS supports MySQL, MariaDB, PostgreSQL which are open source and widely used, Oracle Database and microsoft SQL server. Pay for only what you use. Amazon CLI [^4] [^4]: https://aws.amazon.com/cli/ The AWS CLI is an integrated tool for managing AWS services that you run from a terminal on Linux or macOS or a command prompt on Windows. Basically, commands are entered and executed from a dedicated tool, but they can also be used to automate processes by writing them in scripts. One thing to keep in mind when managing Amazon RDS from the AWS CLI is that executing a command may not always be reflected immediately. This is because Amazon RDS has a number of failure countermeasures, and it takes time for the settings to be reflected in all of them. Same we will be writing simple scripts for executing tasks of Backups and Rollbacks easily on different environments. How exactly can we take Backups and Rollback DB from CLI at developer's level? Using mysqldump in SQL Format What is mysqldump [^5] [^5]: https://dev.mysql.com/doc/refman/8.0/en/mysqldump.html The mysqldump client is a logical backup program originally written by Igor Romanenko. Database and is usually in the form of a list of SQL statements ("SQL dump") for backup or transfer to another database server (not necessarily MariaDB or MySQL). The dump typically contains SQL statements to create the table, populate it, or both. Using a dump file What is a dump file [^6] [^6]: https://dev.mysql.com/doc/refman/8.0/en/mysqldump.html A dump file is also useful when you upgrade from one release to the next. You can dump a database using an older release and load it under a new release as part of the upgrade process. QUICK HIGHLIGHTS To take DB Dump with data (i.e. both DDL & DML) mysqldump -u root -p DB_Name > backup.sql # AWS CLI mysqldump -u $user -p$password -h $rds_endpoint > backup.dump To take DB Dump without data (i.e. only DDL) mysqldump -d -u root -p DB_Name > backup.sql # AWS CLI mysqldump -d -u $user -p$password -h $rds_endpoint > backup.dump To Roll Back to previous version mysql -u root -p DB_Name < backup.dump # AWS CLI mysql -u $user -p$password -h $rds_endpoint < backup.dump SCRIPT for Backup Things you will need to edit in script before using directly: pathToParameterStoreKeyValueMYSQL_USER pathToParameterStoreKeyValueMYSQL_PASSWORD pathToParameterStoreKeyValueRDS_ENDPOINT DB_Name ######################################################################### ######################################################################### ##### ##### Description: Shell Script to take backup of existing data AWS ##### 1. Choose the env and switch the db connection ##### 2. Create backup directory with today's date ##### 3. Create dump file to backup folder with current db ##### 4. Check dump file size ##### ######################################################################### ######################################################################### read -p "Enter Your Env(env): " x echo "Welcome to ${x} Env!" # MySQL server credentials MYSQL_USER=$(aws ssm get-parameter --with-decryption --name /${x}/pathToParameterStoreKeyValueMYSQL_USER | jq -r .Parameter.Value) MYSQL_PASSWORD=$(aws ssm get-parameter --with-decryption --name /${x}/pathToParameterStoreKeyValueMYSQL_PASSWORD | jq -r .Parameter.Value) RDS_ENDPOINT=$(aws ssm get-parameter --with-decryption --name /${x}/pathToParameterStoreKeyValueRDS_ENDPOINT | jq -r .Parameter.Value) # Set the folder name with date format(eg: 2022-08-15) DATE_FORMAT=$(date +"%Y-%m-%d") TIMESTAMP=$(date +%H%M%s) # Path to local backup directory BACKUP_DIR="tmp/release/backup/${x}/dbbackup/${DATE_FORMAT}" # Use database's names DB="DB_Name" echo "########################################DATABASE########################################" echo "Using Database (DB_Name)" echo "########################################DATABASE########################################" # Create backup directory with today's date mkdir -p ${BACKUP_DIR} FILENAME_PREFIX="backup_${x}_DDL_DML_${TIMESTAMP}_" FILENAME_POSTFIX=".dump" read -p "Enter version eg: v0.0.1: " d FILENAME=$FILENAME_PREFIX${d}$FILENAME_POSTFIX echo "########################################FILEPATH########################################" echo "Created directory" ${BACKUP_DIR} echo "File will be saved as ${FILENAME} " mysqldump -u $MYSQL_USER -p$MYSQL_PASSWORD -h $RDS_ENDPOINT --databases $DB > ${BACKUP_DIR}/${FILENAME} echo "File saved at ${BACKUP_DIR}/${FILENAME}" echo "########################################FILESPATH########################################" # check File size file=${BACKUP_DIR}/${FILENAME} filesize=$(ls -lh $file ) echo "########################################FILESIZE########################################" echo "$file has a size of $filesize" echo "########################################FILESIZE########################################" Procedure for taking backup Place the shell script in AWS CLI Login to AWS Click AWS management console → AWS Systems Manager → Session Manager→ Click Start session Enter the env you want to take backup eg: {env}-{project_name}-{maintenance_server_name} Start session Check if dbbackupDDL_DML.sh file is present If file is not present place dbbackupDDL_DML.sh file in AWS CLI To execute file sh-4.2$ ls dbbackupDDL_DML.sh mysql.sh tmp sh-4.2$ sh dbbackupDDL_DML.sh Enter Your Env(env): env Welcome to env Env! ########################################DATABASE######################################## Using Database (db_name) ########################################DATABASE######################################## Enter version eg: v0.0.1: v0.0.1 ########################################FILEPATH######################################## Created directory tmp/release/backup/env/dbbackup/2022-08-12 File will be saved as backup_env_DDL_DML_06311660285870_v0.0.1.dump mysqldump: [Warning] Using a password on the command line interface can be insecure. Warning: A partial dump from a server that has GTIDs will by default include the GTIDs of all transactions, even those that changed suppressed parts of the database. If you don't want to restore GTIDs, pass --set-gtid-purged=OFF. To make a complete dump, pass --all-databases --triggers --routines --events. File saved at tmp/release/backup/env/dbbackup/2022-08-12/backup_env_DDL_DML_06311660285870_v0.0.1.dump ########################################FILESPATH######################################## #######################################FILESIZE######################################## tmp/release/backup/env/dbbackup/2022-08-12/backup_env_DDL_DML_06311660285870_v0.0.1.dump has a size of -rw-r--r-- 1 ssm-user ssm-user 1.7M Aug 12 06:31 tmp/release/backup/env/dbbackup/2022-08-12/backup_env_DDL_DML_06311660285870_v0.0.1.dump ########################################FILESIZE######################################## sh-4.2$ To check the content of dump file sh-4.2$ less tmp/release/backup/env/dbbackup/2022-08-12/backup_env_DDL_DML_06311660285870_v0.0.1.dump sh-4.2$ Backup will be taken into folder with tmp/release/backup/env/dbbackup/{currentDate}/{FileNameWithTimestamp&Version} If you want to take dump multiple times in a day in individual date folder you will have the file with timestamp. sh-4.2$ cd tmp/release/backup/env/dbbackup/ sh-4.2$ ls 2022-08-09 2022-08-10 2022-08-12 sh-4.2$ cd tmp/release/backup/env/dbbackup/2022-08-12/ sh-4.2$ ls backup_env_DDL_DML_06311660285870_v0.0.1.dump backup_env_DDL_DML_06371660286257_v0.0.1.dump sh-4.2$ SCRIPT for Rollback Things you will need to edit in script before using directly: pathToParameterStoreKeyValueMYSQL_USER pathToParameterStoreKeyValueMYSQL_PASSWORD pathToParameterStoreKeyValueRDS_ENDPOINT DB_Name ######################################################################### ######################################################################### ##### ##### Description: Shell Script to rollback to target SQL ##### 1. Choose the env and switch the db connection ##### 2. Create rollback directory with today's date ##### 3. Choose and input the backup file ##### 4. Input the version of dump file ##### 5. Copy backup dump file to ROLLBACK folder ##### 6. Create dump file to ROLLBACK folder with current db ##### 7. Rollback db with backup dump file ##### 8. Comparison.... ##### ######################################################################### ######################################################################### read -p "Enter Your Env(env): " x echo "Welcome to ${x} Env!" # MySQL server credentials MYSQL_USER=$(aws ssm get-parameter --with-decryption --name /${x}/pathToParameterStoreKeyValueMYSQL_USER | jq -r .Parameter.Value) MYSQL_PASSWORD=$(aws ssm get-parameter --with-decryption --name /${x}/pathToParameterStoreKeyValueMYSQL_PASSWORD | jq -r .Parameter.Value) RDS_ENDPOINT=$(aws ssm get-parameter --with-decryption --name /${x}/pathToParameterStoreKeyValueRDS_ENDPOINT | jq -r .Parameter.Value) # Set the folder name with date format(eg: 2022-08-15) DATE_FORMAT=$(date +"%Y-%m-%d") TIMESTAMP=$(date +%H%M%s) # Path to local rollback directory history ROLLBACK_DIR="tmp/release/rollback/${x}/dbRollback/${DATE_FORMAT}" # Use database's names DB="DB_Name" echo "########################################DATABASE########################################" echo "Using Database (DB_Name)" echo "########################################DATABASE########################################" # Create rollback directory with today's date mkdir -p ${ROLLBACK_DIR} read -p "Enter full dumpFile Path to which you want to rollback: " df echo "dumpFile ${df} selected!" FILENAME_ROLLBACK_PREFIX="rollback_${x}_DDL_DML_${TIMESTAMP}_" FILENAME_BACKUP_PREFIX="backup_${x}_DDL_DML_${TIMESTAMP}_" FILENAME_POSTFIX=".dump" read -p "Enter version eg: v0.0.1: " d FILENAME_ROLLBACK=FILENAME_ROLLBACK_PREFIX${d}$FILENAME_POSTFIX FILENAME_BACKUP=FILENAME_BACKUP_PREFIX${d}$FILENAME_POSTFIX echo "########################################FILEPATH########################################" echo "Created directory" ${ROLLBACK_DIR} # copy dump file to backup folder cp ${df} ${ROLLBACK_DIR}/${FILENAME_ROLLBACK} ROLLBACK_FILE=${ROLLBACK_DIR}/${FILENAME_ROLLBACK} BEFORE_ROLLBACK_DUMP=${ROLLBACK_DIR}/"BeforeRollback_${FILENAME_BACKUP}" AFTER_ROLLBACK_DUMP=${ROLLBACK_DIR}/"AfterRollback_${FILENAME_BACKUP}" mysqldump -u $MYSQL_USER -p$MYSQL_PASSWORD -h $RDS_ENDPOINT --databases $DB > ${BEFORE_ROLLBACK_DUMP} echo "Dump Before Rollback ${BEFORE_ROLLBACK_DUMP}" echo "Rollback to DDL_DML of sql file located at ${ROLLBACK_FILE} " mysql -u $MYSQL_USER -p$MYSQL_PASSWORD -h $RDS_ENDPOINT --databases $DB < ${ROLLBACK_FILE} echo "Rollback successfully done with ${ROLLBACK_FILE}" mysqldump -u $MYSQL_USER -p$MYSQL_PASSWORD -h $RDS_ENDPOINT --databases $DB > ${AFTER_ROLLBACK_DUMP} echo "Dump After Rollback ${AFTER_ROLLBACK_DUMP}" echo "########################################FILESPATH########################################" # check File size before Rollback fileBeforeRollback=${ROLLBACK_DIR}/${BEFORE_ROLLBACK_DUMP} filesizeBeforeRollback=$(ls -lh fileBeforeRollback ) echo "########################################FILESIZE BEFORE ROLLBACK########################################" echo "$fileBeforeRollback has a size of $filesizeBeforeRollback" echo "########################################FILESIZE BEFORE ROLLBACK########################################" # check File size after Rollback fileAfterRollback=${ROLLBACK_DIR}/${AFTER_ROLLBACK_DUMP} filesizeAfterRollback=$(ls -lh fileAfterRollback ) echo "########################################FILESIZE AFTER ROLLBACK########################################" echo "$fileAfterRollback has a size of $filesizeAfterRollback" echo "########################################FILESIZE AFTER ROLLBACK########################################" Footer Procedure for Rollback Place the shell script in AWS CLI Login to AWS Click AWS management console → AWS Systems Manager → Session Manager→ Click Start session Enter the env you want to take rollback eg: {env}-{project_name}-{maintenance_server_name} Start session Check if dbRollbackDDL_DML.sh file is present If file is not present place dbRollbackDDL_DML.sh file in AWS CLI To execute file sh-4.2$ ls dbRollbackDDL_DML.sh mysql.sh tmp sh-4.2$ sh dbRollbackDDL_DML.sh Enter Your Env: env Welcome to env Env! ########################################DATABASE######################################## Using Database (DB_Name) ########################################DATABASE######################################## Enter full dumpFile Path to which you want to rollback: tmp/release/backup/env/dbbackup/2022-08-12 Enter version eg: v0.0.1: v0.0.1 ########################################FILEPATH######################################## Created directory tmp/release/rollback/env/dbRollback/2022-08-13 Dump Before Rollback tmp/release/rollback/env/dbRollback/2022-08-13/BeforeRollback_backup_env_DDL_DML_06311660285870_2022-08-13.dump Rollback to DDL_DML of sql file located at tmp/release/rollback/env/dbRollback/2022-08-13/backup_env_DDL_DML_06311660285870_2022-08-13.dump Rollback successfully done with tmp/release/rollback/env/dbRollback/2022-08-13/backup_env_DDL_DML_06311660285870_2022-08-13.dump Dump After Rollback tmp/release/rollback/env/dbRollback/2022-08-13/AfterRollback_backup_env_DDL_DML_063116602859099_2022-08-13.dump ########################################FILESPATH######################################## ########################################FILESIZE BEFORE ROLLBACK######################################## tmp/release/rollback/env/dbRollback/2022-08-13/BeforeRollback_backup_env_DDL_DML_06311660285870_2022-08-13.dump has a size of -rw-r--r-- 1 ssm-user ssm-user 1.7M Aug 13 06:31 tmp/release/rollback/env/dbRollback/2022-08-13/BeforeRollback_backup_env_DDL_DML_06311660285870_2022-08-13.dump ########################################FILESIZE BEFORE ROLLBACK######################################## ########################################FILESIZE AFTER ROLLBACK######################################## tmp/release/rollback/env/dbRollback/2022-08-13/AfterRollback_backup_env_DDL_DML_063116602859099_2022-08-13.dump has a size of -rw-r--r-- 1 ssm-user ssm-user 1.6M Aug 13 06:31 tmp/release/rollback/env/dbRollback/2022-08-13/AfterRollback_backup_env_DDL_DML_063116602859099_2022-08-13.dump ########################################FILESIZE AFTER ROLLBACK######################################## sh-4.2$ How can you use this in your daily work? You can take quick backups by using script or commands like above to avoid multiple inputs, references to many documents and links for login etc. This will save your time and errors while writing commands by hand. This will provide you systematic and clutter-free folder structure which you can refer whenever you need one. You will need this procedure in case your DB is upgraded, there is data inconsistency, in case you need to release the next version of your system or rollback the data when there is a failure.
こんにちは こんにちは、KINTOテクノロジーズ CIO室でアシスタントをしてます村山です! 本記事ではオフィスや社員のデスク環境をゆるりとご紹介します( ˘ω˘ ) オフィス紹介 まずはオフィス紹介から。 本社の名古屋オフィスです。 社長小寺さんの強い想いが込められていて、 『ナチュラル』『明るさ』を前面に押し出した内装となっています。 また、小寺さんこだわりポイントの右下の焚火は時間によっては炎がつきます。 オフィスの中心位置にあり、ランチ時にはみんなが集まります! 2つめの拠点は室町オフィスです。 室町オフィスには2フロアあり、東京ジャンクションも併設されています。 撮影にも利用されており、おしゃれなスポットですね! コレド室町2の中に入っているので近くにお店が多くて助かります。 食べたいと思ったもの、なんでもありますヨ。 3つめの拠点は神保町オフィスです。 大きい会議室にプラットフォームGのみなさんがいたので撮らせていただきました。 神保町オフィスは会議室が一番多く人気です。 あと、神保町周辺はランチの価格が安いのもいいですよね  おいしいカレーやさんがたくさん!行く度カレーをたべてます🍛 写真右下は神保町オフィス限定KINTOテクノロジーズロゴ入りの自動販売機です。 4つめの拠点はOsaka Tech Labです。 大阪オフィスではないです。Osaka Tech Labです!(ここ重要) 4月に開設されたばかりでまだ社員の少ない拠点ですが みんなで意見を出し合いTech Labをアップデートし続けています。 写真右下の屋上が開放的で人気です。 心斎橋もランチが安い!粉ものおいしい! 関東出身なので、お好み焼き定食は慣れません・・ デスク環境の紹介 つぎはデスク環境の紹介をします。 仕事のしやすい環境というのは人それぞれで、 無駄がなく機能的であることは”環境が整っている”ことになると思いますが、 それだけじゃないですよね。 という前置きをしておいて・・っと! わたしのデスクです。 大量の応援部隊です。なんと整った環境でしょう・・! 副社長景山さんのデスクにもいます。 たまに一匹転がってたりして、あれ、一匹いなくなった!と探している姿にほっこりします。 みなさんもシルバニアを手にしていただけるとわかると思いますが、母性がわきます。 あれ、気が付いたらシルバニアの布教ブログになってしまいそうなのでここら辺で次のデスクにいきますか。 ![社員からひとこと](/assets/blog/authors/uka/member-02.jpg =450x) キーボードもかっこいい! PCとガンプラを作成するのが好きとのこと。良い趣味! 自宅のデスク環境ではたくさんのガンプラに見守られているようですが、 オフィスにも小さいのを連れてきたようです。 シルバニアひとつあげたら仲間が増えてました。いまではシルバニア布教部の一員です! ![社員からひとこと](/assets/blog/authors/uka/member-03.jpg =450x) こんなこと言ってますが仕事できるひとです。 KINTOテクノロジーズのコミュニティにe-sports部があり、先日もみんなでスプラトゥーンをしました。 IT系の会社なだけあってか、ゲーム好きが多いです。 最近の社内ブームは麻雀です! ![社員からひとこと](/assets/blog/authors/uka/member-04.jpg =450x) わかる。 各オフィスを簡単に行き来できたらいいのにな~とか夢みたいなことはおいといて・・ 用があれば他オフィスにも出張させていただいてますが、 各オフィスそれぞれの良さがあって、どのオフィスで仕事するのもすきです! ![社員からひとこと](/assets/blog/authors/uka/member-05.jpg =450x) 書籍が好きな方も多く、弊社の貸出書籍もたくさんありますが 社員同士で書籍の貸し借りをしているのもよく見られます。 あと、KINTOテクノロジーズにきてからSlackというツールを知ったのですが、 かわいい絵文字がたくさんでゆるーいかんじでコミュニケーションとれて 素晴らしいツールですよね・・! ![社員からひとこと](/assets/blog/authors/uka/member-06.jpg =450x) トリプルディスプレイ、エンジニアっぽい!! 機能的でありつつささやかな癒しもありでステキ環境ですね ここまでくればシルバニアは万人受けということがわかっていただけたでしょうか。 さいごに リモートワークが流行ってるご時世ですが、 出社して好きな環境でみんなとコミュニケーションとりつつ仕事するのが いちばんだなーってわたしは思います( ˘ω˘ ) その上で髪色や服装、デスク環境も自由にさせてもらえて 働きやすい環境で仕事できるので楽しいです! それでは、ここまで読んでいただきありがとうございました!
はじめに こんにちは。共通サービス開発グループで複数のサービスが利用する決済プラットフォームの開発チーム[^1][^2]に所属している鳥居です。 この記事をご覧の皆さんは、ローカル開発環境の構築時にこんな経験ありませんか?IDE の設定を環境構築手順書に従って構築したが動かなかったり、プロダクト毎に異なるバージョンの SDK をどちらも動く方法を調べてインストールしたりなど、経験ある方は多いのではないかと思います。 ローカル開発環境構築は、新たに入ってきたプロダクト開発メンバーに襲いかかる、面倒な作業のひとつです。 本記事では Visual Studio Code (以下 VS Code)の Dev Container で開発環境の構築と簡略化・共通化をした事例を紹介します。 VS Code の Dev Container とは Dev Container 環境とは VS Code の拡張機能 Dev Containers を使って構築する開発環境で VS Code と Docker が使うことが出来れば利用可能です。(Windows / Mac / Linux) 次の図のように、Dev Container を立ち上げると VS Code から Docker コンテナをフル機能の開発環境として使用できます。 ホストマシンからソースコードをマウントし、VS Code の拡張機能は コンテナ内にインストールされます。 そのためすでに入っているライブラリとの競合の考慮の必要がありません。 例えばホストマシンで開発をする場合、別のプロジェクトの node.js の指定バージョンが違う場合は n package で node.js のバージョン管理、状況に応じてバージョンの切り替えが必要となるかもしれません。 Developing inside a Container より引用 Dev Container 環境の VS Code の設定や拡張機能、インストールするライブラリや起動するサービスなどは devcontainer.json 、 Dockerfile 、 docker-compose.yml に定義することが出来ます。 Dev Container 環境をビルドする際はこれらの設定を利用して自動的に行わるので、別個にインストールするのに比べ大幅に手順が簡略化されます。 環境構築手順書も Dev Container のビルドまでの手順のみとなります。複数人で開発する際の OS の差異の考慮も不要です。 Dev Container 環境構築手順 今回は Create React App で新しい React アプリケーションの構築を目指します。 今回使用した環境 PC: Surface Laptop4 Windows10: 21H2 (WSL2) WSL2: Ubuntu 20.04 VS Code: 1.73.0 前提 VS Code のインストール Docker のインストール (Windows の場合は WSL2 上にインストール) Docker Desktop for Windows/Mac のインストール 1. 拡張機能 - Dev Containers のインストール まずは Workspace としたいディレクトリで VS Code を開きます。 そして VS Code の拡張機能 Dev Containers をインストールします。 Dev Containers が含まれている Remote Development でも OK です。 2. Reopen in Container でセットアップ開始 左下のアイコンをクリックし、画面上部のメニューから Reopen in Container を選択 (Create Dev Container は別のディレクトリに Dev Container を構築してしまいます) 3. 作成したい Dev Container 環境の設定を選択 今回は Ubuntu を選択しました。 4. Docker コンテナイメージのバージョンを選択 5. 追加する機能を選択 今回は React アプリケーションの作成に必要な Node.js (via nvm) and yarn を選択しました。 追加する機能を選択し 🆗 をクリックすると、Dev Container のビルドが開始されます。 6. Dev Container のビルド完了 ビルドが完了すると、自動で Dev Container に接続された VS Code が起動します。 .devcontainer/devcontainer.json というファイルが生成されており、左下の表記が Dev Container となっていることがわかります。 (以前は .devcontainer/Dockerfile も生成されていました。) VS Code 内のターミナルを開き( ctrl + shift + @ )、次のコマンドを実行すると必要なライブラリがインストールされていることがわかります。 $ node -v v18.12.1 $ yarn -v 1.22.19 次に Create React App を実行します。 $ npx create-react-app typesript プロンプトが表示され、このまま構築できることがわかります。 (React アプリケーションの構築と起動確認は本題からそれるため割愛します。) いかがでしょうか。手動で node.js yarn をインストールして create-react-app をしたことがある方には如何に簡略されているかおわかりいただけるかと思います。 次は今回構築した Dev Container 環境をビルドしてみましょう。 既存の Dev Container 環境のビルド 前提 前提条件は環境構築手順と同様とします。 VS Code のインストール Docker のインストール (Windows の場合は WSL2 上にインストール) Docker Desktop for Windows/Mac のインストール 1. Dev Container の Workspace をホストマシンで開く まずはホストマシンの VS Code で先程作成した Workspace を開きます。 * 拡張機能 Dev Containers がインストールされていない場合 拡張機能 Dev Containers がインストールされていない場合は、次の図のように拡張機能のインストールを推奨されるので、表示に従いインストールしてください。 2. Reopen in Container を選択 拡張機能 Dev Containers をインストール済みの場合は、次の図のように Dev Container の設定ファイルがあるので Dev Container で開き直すかを聞かれます。 Reopen in Container を選択すると Dev Container のビルドが開始されます。 2. 環境構築完了! 構築済みの Dev Container 環境をビルドする際は以上だけです。 2 回目以降の起動も同様に Reopen in Container の選択で開くことが出来ます。Windows の場合は次の図のようにタスクバーの VS Code コンテキストメニュー から直接開くことも出来ます。 React アプリケーションの起動を構築完了とする場合は以下のようなコマンドが必要ですが、そちらについての設定は後述いたします。 // node.js packageのインストール $ yarn install このように構築済みの環境構築は非常に少ない手順で構築出来ます。 devcontainer.json のサンプル 次に私の Dev Container の設定の例を紹介します。 VS Code の設定や拡張機能は linter や formatter などを定義しています。 その他開発支援の機能も設定していますので興味がありましたら調べてみてください。 { // Dev Container の名称設定 "name": "test-devcontainer", // コンテナ立ち上げ時のオプションの指定 // --name ビルドするDocker containerの名称の指定 // これを指定しないとランダムに生成される "runArgs": ["--name=test-devcontainer"], // Docker コンテナイメージ "image": "mcr.microsoft.com/devcontainers/base:jammy", // VS Codeの設定 "settings": { "stylelint.validate": ["css", "scss"], "scss.validate": false, "css.validate": false, "editor.formatOnSave": true, "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.codeActionsOnSave": { "source.fixAll.eslint": true, "source.fixAll.stylelint": true }, // sticky scrollの設定 "editor.stickyScroll.enabled": true, "editor.stickyScroll.maxLineCount": 5, "workbench.colorCustomizations": { "editorStickyScroll.background": "#00708D", "editorStickyScrollHover.background": "#59A2B5" }, // typescript で絶対パスで import する設定 "typescript.preferences.importModuleSpecifier": "non-relative" }, // 追加する VS Code の拡張機能 "extensions": [ "ms-vscode.live-server", "dbaeumer.vscode-eslint", "stylelint.vscode-stylelint", "Syler.sass-indented", "esbenp.prettier-vscode", "ms-python.python", "streetsidesoftware.code-spell-checker", "naumovs.color-highlight", "burkeholland.simple-react-snippets", "formulahendry.auto-rename-tag", "MariusAlchimavicius.json-to-ts", "dsznajder.es7-react-js-snippets", "styled-components.vscode-styled-components", "Gruntfuggly.todo-tree", "42Crunch.vscode-openapi", "mhutchie.git-graph" ], // コンテナ内の実行ユーザーの設定 (推奨設定) "remoteUser": "vscode", // インストールするライブラリ "features": { "ghcr.io/devcontainers/features/node:1": { "version": "lts" }, "ghcr.io/devcontainers/features/python:1": { "version": "3.9" } }, // Dev Container 作成時に実行するコマンド "postCreateCommand": "sh .devcontainer/post-create.sh" } 先程の構築済み環境で別途 yarn install を実行しなかった件は、 postCreateCommand オプションに定義することで環境構築時に自動で実行できます。 私の場合は別途スクリプトを作成しコンテナ構築後に実行する必要がある一連のコマンドを実行しています。 .devcontainer/post-create.sh #!/usr/bin/env sh # bashのgitコマンド補完の追加 echo 'source /usr/share/bash-completion/completions/git' >> ~/.bashrc # yarn global のpathを通す設定 echo 'export PATH="$HOME/.yarn/bin:$PATH"' >> ~/.bashrc # openapi-generator-cliのインストール yarn global add @openapitools/openapi-generator-cli yarn install 導入してみて感じたメリット・デメリット Dev Container 環境で開発をしていて感じたメリット・デメリットを記載します。 メリット 環境構築の手順が単純化出来る 複数人で開発する際にホストマシンの OS を気にしなくて良い 各種ライブラリ、パッケージの手順が不要 バックエンドの場合 mysql や redis を利用することが多いのでより強力 環境構築を宣言的に定義して、共通化出来るので個人によるばらつきが出ない VS Code の設定や拡張機能も定義できる バージョン違いによる思わぬバグの遭遇が起きない ローカル環境を汚さない、別 Workspace との競合が発生しない デメリット VS Code 以外の IDE を使いたい人の要望に応えられない 好みのターミナルが使えない そこそこのマシンスペックが要求される Zoom の画面共有しながらだと厳しい Windows は WSL2 がなんだかんだ重い Mac はファイル I/O に問題を抱えている devcontainer.json の Named Volume の設定で解決できるようです[^3] さいごに いかがでしたでしょうか。Dev Container の便利さが少しでも伝わっていれば幸いです。 私自身、過去には長い環境構築手順書に沿って環境構築をしていた記憶もあり非常に楽な時代になったなと感じています。 また、実際にモブプロに別プロダクトを担当しているメンバーをゲストに迎えた際もすぐに実装に取り組んでもらうことが出来たので Dev Container の利便性を実感しました。 今後の試行錯誤としては以下のようなことを実践してみたいと考えています。 公式記事を参考に Dev Container のパフォーマンスチューニング Amazon EC2 上に Docker を入れて Remote Development using SSH 経由で Dev Container を利用してみたい 応用で IntelliJ IDEA の Remote Development での開発 GitHub Codespaces 上での環境構築 [^1]: 決済プラットフォームの他の取り組みその1、[ グローバル展開も視野に入れた決済プラットフォームにドメイン駆動設計(DDD)を取り入れた ] [^2]: 決済プラットフォームの他の取り組みその2、[ 入社 1 年未満メンバーだけのチームによる新システム開発をリモートモブプログラミングで成功させた話 ] [^3]: 公式記事 Improve container performance
自己紹介・記事要約 my route開発Gのグループマネージャーをやっております、岩元です。 KINTO Technologies(以下KTC)の前身であるKINTO開発部立ち上げ時から在籍している最古参開発メンバーでもあります。 今回は、私が担当しているmy route開発Gの紹介をさせていただきます。 my routeとは my route by KINTO (以下my route)とは何かということを一言で言うなら、 トヨタグループのMaaSアプリ です。 MaaSとはモビリティ・アズ・ア・サービスの略であり、直訳すれば「サービスとしてのモビリティ」という意味になります。 「さまざまな形態の輸送サービスを統合した、オンデマンドでアクセス可能な単一のモビリティサービスとしており、MaaSオペレーターは利用者の要求を満たすべく、公共交通、ライドシェア、カーシェア、自動車シェア、タクシー、レンタカーなどさまざまな交通手段のメニューを用意すること」 ※MaaSアライアンスの定義より 簡単に言うなら、「ICTを活用してマイカー以外の移動をシームレスにつなぐ」ということでしょうか。 トヨタグループでは2018年の福岡での実証実験を皮切りに順次エリアを拡大してきています。 そのためのモバイルアプリとして生まれたものがmy routeであり、実証実験開始当時はトヨタ自動車で開始されたプロジェクトです。現在はKINTO親会社のトヨタファイナンシャルサービス社が主管として運営されており、KTCが開発・運用を行なっています。 これまでとこれからと 内製開発化とリニューアル 2018年のmy routeの実証実験開始時はまだKTCどころかKINTOも存在していませんでした。そのため開発・運用は全て委託先パートナー企業に外注されていました。 そのため、KTCが開発携わるようになって最初に取り組んだ事は、なにはともあれ内製化を進めることでした。また、元々が実証実験用に作られたものから建て増しを繰り返して発展してきたという経緯もあり内部構造的にも疲労限界を迎えていたため、アーキテクチャの刷新も喫緊の課題となっていました。 その第一弾として、まずはAPIを提供するバックエンド部分のリニューアルが行われました。これはマイクロサービスアーキテクチャの導入、開発言語の変更、プラットフォームのAWS化などを含む大規模なものであり、委託先パートナー企業からの巻き取りも同時に進めていたためかなり困難なプロジェクトでしたが、2021年の8月に無事リリースを完了させることができました。このリニューアルにより従来の数倍の速度での地域展開が可能となり、現在に至るまで無事に運用を行い、ほぼ完全に開発の内製化も実現できました。 現在進行中プロジェクト そして現在は、バックエンドリニューアル完了から間も無く開始された新プロジェクトを2023年1月のリリースに向けて絶賛開発中です。 詳細についてはまだオープンにはできないのですが、my route開発エンジニア総勢20名ほどが関わった一大プロジェクトになります。 基盤となるアーキテクチャも大幅に刷新されるため非常に大変なプロジェクトでしたが、完成の見えてきた今、プロジェクトメンバー一丸となって開発にあたっています。 my route開発グループについて my route開発グループはmy routeサービスに紐づいたグループですので、最大のミッションは my routeサービスの成長・発展に寄与すること に尽きます。 そのため、事業とワンチームという意識を持って開発・運用を行う人たちが集まっています。 グループ内は主に以下の3チームに分かれています。 バックエンド開発チーム 運用チーム モバイルアプリ開発チーム 現在はモバイルアプリ開発チームは別グループとして独立してしまいましたが、引き続きmy route開発チームの一員として活動しています。 先述のリニューアル関係の開発だけではなく、現行アプリに関しても、日々の運用、地域展開を通して多くの改善要望が寄せられています。これらを事業と相談し、優先度を付けながら開発を進めています。 新しい仲間へ 元々、実証実験の委託開発プロジェクトとして始まったmy routeですが、2023年1月リリースのプロジェクト完了により完全に内製化され、本当にやりたいことができる準備が整います。そういう意味では、2023年はmy routeにとって勝負の年だと考えています。 この記事を読んで興味を持たれた方、是非とも一緒にmy routeを日本一のMaaSアプリとして成長させていきましょう!
はじめに こんにちは。プラットフォームGでDevOpsエンジニアをしている島村です。 KINTOテクノロジーズのプラットフォームGのDevOpsサポートチーム(とSREチーム)では、CI/CD以外にも、監視ツールの整備やモニタリングツールの改善を実施しています。 プラットフォームGは他にもSystemAdministratorチーム、CCOE、DBREなどがあり、AWSを中心としたインフラの設計・構築運用の他にも会社全体のシステム改善や標準化・最適化を担っています。 その中で、昨年にGAとなったAmazon Managed Service for Prometheus(以降Prometheus)とAmazon Managed Grafana(以降Grafana)とX-Rayを使用したAPMの仕組みを導入しましたので、そのことを記事にしようと思います。 背景 私が入社した2021年5月時点でKINTOテクノロジーズ(当時はKINTO)では、AWSリソース監視・ログ文言の監視を行っていました。ただし、CloudWatchを使用したもので、プラットフォームGが設計・設定を行っていました。 当時はアプリケーション運用としてのメトリクスなどは取得されていませんでした。ログ監視も設定の柔軟性は低く、エラー検知はAWSのメトリクスもしくはログによるものか、外形監視からの通知による受動的な検知と対応が主でした。 よく言われるようなO11yの成熟度からすると「Lv0:計測を始める」もできていない状態です。ただ、プラットフォームG内部では問題と認識していたので、まずは計測を始めようということで、APM+X-Rayを導入することとしました。 O11yの成熟度モデルとかの参考はこちら 要素 APM(Application Performance Management) アプリケーションやシステムの性能を管理・監視すること。アプリケーションパフォーマンス管理とも言い換えられます。アプリケーションやシステムの応答時間や構成要素のパフォーマンスを調査することで、アプリケーション全体の稼働状況を把握し、ボトルネックやシステム障害の要素を素早く把握し、改善に役立てるために使用します。 X-Ray AWSで提供している分散トレーシングの仕組みです。 システム全体におけるサービス間の呼出関係の可視化 特定リクエストにおけるサービス間の呼出関係の可視化 (特定リクエストの処理経路の可視化) システム全体のボトルネックを迅速に特定する 上記のことが可能となります。 タスク(Action) 検討する まずは「Lv0:計測を始める」を満たすことを考えました。実装時には、「Prometheus+Grafana」という前提が提示されており、ちょうどAWSでマネージドサービスとしてプレビューされていたタイミングだったので、そちらを選択しました。 Datadog / Splunk / NewRelic / DynaTraceなど、一般的によく使われているSaaSもありますが、前提条件から検討せずにAWSを使用することとしました。あとから、ここらへんのSaaSを使わなかった理由も分かってきました。その理由だと思うことは後述で。 実装する Prometheus Prometheusへのメトリクス出力については Amazon Managed Service for PrometheusにECSからアプリケーションメトリクスを収集する としてまとめています。2021のKINTO Technologiesのアドベントカレンダーとして作成した記事です。 X-Ray 検討当時のメンバーの資料を引継ぎしまして、 AWS X-Ray SDK for Java をベースとして、ECSタスク定義への取り込みなどを整理し、資料化を行いました。 初期構成 改善する X-Ray SDKのOpenTelemetory化 Java17を使い始めたチームから、X-RayのServiceMapがうまく表示されないという相談がありました。よくよく見ると、 AWS X-Ray SDK for Java はJava8/11には対応を明言していますが、Java17への対応は明言されていません。今は AWSDistro for OpenTelemetry Java が推奨されているようなので、全体的にこちらに切り替えることにしました。APMのCollectorと同居できることも良いことの1つです。 Java aws-observability/aws-otel-java-instrumentation から最新のReleaseのjarファイルをダウンロードし、 src/main/jib 以下に保存するだけで導入ができます。SDK for Javaではサンプリング設定の定義ファイルなどもありましたので、導入が簡素になっている印象です。 ECSタスク定義の環境変数 JAVA_TOOL_OPTIONSにAgentの定義を追加します。OTELの環境変数も追加しています。ECSのタスク定義のjsonを確認すると { "name": "JAVA_TOOL_OPTIONS", "value": "-Xms1024m -Xmx1024m -XX:MaxMetaspaceSize=128m -XX:MetaspaceSize=128m -Xss512k -javaagent:/aws-opentelemetry-agent.jar ~~~~~~" }, { "name": "OTEL_IMR_EXPORT_INTERVAL", "value": "10000" }, { "name": "OTEL_EXPORTER_OTLP_ENDPOINT", "value": "http://localhost:4317" }, { "name": "OTEL_SERVICE_NAME", "value": "sample-traces" } のような形になります。(実際はParameter Storeなどを使うのでちょっと変わりますが) OpenTelemetryColletorのConfig Configuration を参考にしつつ、以下のような形でCollectorのConfigを修正します。 APMとX-Ray両方が入っているかつ、タスクごとにメトリクスにラベルがついている形です。 exporterとして使用している「awsprometheusremotewrite」はAWS-OTEL-COLLECTORのv0.18から非推奨に、v0.21からは機能が除かれており、「PrometheusRemoteWrite」+「Sigv4Auth」を使用するようになってますので、ご注意ください。 receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 http: endpoint: 0.0.0.0:4318 awsxray: endpoint: 0.0.0.0:2000 transport: udp prometheus: config: global: scrape_interval: 30s scrape_timeout: 20s scrape_configs: - job_name: "ktc-app-sample" metrics_path: "/actuator/prometheus" static_configs: - targets: [ 0.0.0.0:8081 ] awsecscontainermetrics: collection_interval: 30s processors: batch/traces: timeout: 1s send_batch_size: 50 resourcedetection: detectors: - env - ecs attributes: - cloud.region - aws.ecs.task.arn - aws.ecs.task.family - aws.ecs.task.revision - aws.ecs.launchtype filter: metrics: include: match_type: strict metric_names: - ecs.task.memory.utilized - ecs.task.memory.reserved - ecs.task.cpu.utilized - ecs.task.cpu.reserved - ecs.task.network.rate.rx - ecs.task.network.rate.tx - ecs.task.storage.read_bytes - ecs.task.storage.write_bytes exporters: awsxray: awsprometheusremotewrite: endpoint: [apm endpoint] aws_auth: region: "us-west-2" service: "aps" resource_to_telemetry_conversion: enabled: true logging: loglevel: warn extensions: health_check: service: telemetry: logs: level: info extensions: [health_check] pipelines: traces: receivers: [otlp,awsxray] processors: [batch/traces] exporters: [awsxray] metrics: receivers: [prometheus] processors: [resourcedetection] exporters: [logging, awsprometheusremotewrite] metrics/ecs: receivers: [awsecscontainermetrics] processors: [filter] exporters: [logging, awsprometheusremotewrite] 現行構成 使ってもらう 特に難儀した点です。 「はじめに」に記載した通り、私はプラットフォームGの所属で、ツールを検討して提供しています。いびつな形ではありますが、DevOpsとしてツールなどを全体最適としたかったので、全社横断(横串)で活動するプラットフォームGに所属しています。そのため、 (問題と思っている)プラットフォームG (そこまで問題と認識していない)アプリケーション担当 という状態に陥りました。最近は地道な活動を通じて、必要性を理解をしてもらえて来ていると思います。 SaaSを使わなかった話 ここは個人的な考えです。 特にO11y関連のSaaSってデータ量も多く、総じてお値段がお高くなるイメージがあります。上記の必要性を理解してもらうまで、「使わない」ツールに対して多額の費用を払うというのは、やはり費用対効果を考えると難しいところです。 O11yの成熟度Lv2の積極的対応くらいまで進むと、俯瞰的にボトルネックやパフォーマンスを見たいという要望が出てきて、そこで使用する価値が生まれてくるのではないかと思います。ログやメトリクスとイベントと紐づけたりなど。受動的な対応までなら、ツールが分割されていても、各人のタスク負荷的や量としては許容されるのかなと思っています。 一時的にGrafanaダッシュボートおじさんができるのは仕方がない。ダッシュボートおじさんのコストよりも、SaaSのコストが低くなれば移行していく…はず。 所感 GrafanaもPrometheusもX-Rayも、マネージドサービスであり導入はSaaSほどは簡単ではありませんが、コストという意味では比較的安価で導入できるものです。DevOpsやSRE活動の初期として、O11yを導入するにあたっては、検討する価値はあるのではないでしょうか。 SaaSを使わなかった話にもありましたが、使い始めてからO11yの価値を見て、改善や活動を見直し、コストを比較してから各種SaaSを使い始めるということでも、良い気はしています。 いや、DatadogとかNewRelicのダッシュボードとかHostMapとか、画面上は綺麗に見えますしなんか動いてて監視・モニタリングしている実感を感じますし、見栄えが良いから(`・ω・´)イインジャネ!!と考えるのは、よくわかります。カッコイイもの…
グローバル開発グループ紹介記事の最終弾として、本日はプロダクト開発チーム、導入開発チーム(導入・DevOps・保守・テスト )、業務エンハンスチームの紹介をいたします。 目次 目次 プロダクト開発チーム はじめに プロダクト開発チームとは メンバーの雰囲気 業務の進め方 これから挑戦したいこと 導入開発チーム 概要 ミッション チームの様子 業務の様子 これからのチャレンジ 業務エンハンスチーム 業務エンハンスチームとミッション 現在取り組んでいること 1言語面での一貫した顧客体験 2グローバルKINTOの社会的責任担保 3グローバル開発グループ全体のポテンシャル底上げ チームの雰囲気 今後挑戦していきたいこと グローバル開発Gで一緒に働く仲間を募集中 プロダクト開発チーム はじめに KINTOテクノロジーズのグローバルKINTO開発グループでアシスタントマネージャーをしている石原です。 本記事ではGlobalグループのプロダクト開発チームの紹介をさせて頂きます。 プロダクト開発チームとは グローバルKINTO開発グループは親会社のトヨタファイナンシャルサービス、海外現地法人、外部パートナー、KINTOテクノロジーズの4社間で進めるKINTOサービスの世界展開を迅速に行えるように、ID、グローバルアプリ、クーポンシステムといったプラットフォーム等を開発しています。 メンバーの雰囲気 ECサイト開発、ソーシャルゲーム開発等多種多様なバックグラウンドを持つメンバーで構成されており、 国籍も様々で中国、インド、フィリピン、ベトナム、フランス、韓国、日本等のメンバーが在籍しています。 コミュニケーションは基本的には日本語がメインですが、英語をメインに使っているチームもあります。 上記の通り様々なスキルを持っているメンバーが集っているので色々な観点での意見がでる事が多く、それぞれの意見を尊重しあう雰囲気です。 業務の進め方 プロダクト毎に開発メンバーをアサインしており、プロダクトマネージャーと共に仕事を進めています。 開発の進め方はチームによって様々ですが、2週間のスプリントでアジャイル開発を行っているチームが多いです。 どういったものを作るのかを決めるのはプロダクトマネージャーの意見だけではなく、エンジニアからも意見を出し合い、より良いプロダクトを作り続けています。 また、プロダクトを成長させる為に様々な技術の取り込みや自分達で必要だと思う仕組みの開発も行っています。 例えば下記のような仕組みを利用しています。 名称 利用プロダクト 導入目的 KMM Global KINTO App iOS・Androidで共通のビジネスロジックを1コードでSDK化する事により、開発効率・テスト効率を促進させる Gatsby Global KINTO Web 高速なWeb Siteを開発する為 マイクロサービスDevelopment Kit(GKMDK) バックエンド、バックオフィス管理画面 サブスクサービス、リースサービスをマイクロサービスで容易に構築する事ができる自社エンジニアによって開発を行った仕組み 認証サービスパッケージ IDプラットフォーム IDサービスを容易に導入する為に作られたパッケージ。Global Login機能(KINTO IDで連携先のサービスの利用が可能な機能)、Social Login機能、Sign up/Sign in機能などIDサービスに必要な機能を持つ自社エンジニアによって開発を行った仕組み KMMやGatsby等の世の中に普及している技術を利用するだけではなく、プロダクトにあった仕組みを自分たちで創り出しています。 例えばマイクロサービスDevelopment Kit(GKMDK)はサブスク、リースサービスを立ち上げる際に短期間でバックエンド及び管理画面の開発を行えるようにする為にエンジニアの発案を基に開発を行っています。 このようにプロダクト開発チームでは決まった要件をただ開発するのではなく、自分で必要だと思う事、良くする為には何が必要かを考え動く自主性・積極性を重要視して業務を行っています。 これから挑戦したいこと 今までは基本機能をメインとして新規開発、改善を行っていましたが、これから世界中に通用するようなプロダクトにアップデートしていきたいと思っています。 導入開発チーム 概要 導入開発チーム(導入チーム、DevOpsチーム、保守チーム、テストチーム)のマネジメントをしている水野です。 私たちは、基盤開発チームで開発したプロダクトを元に各国へグローバルKINTOサービスのIT導入や運用をしています。 表題のチームは多いですが、みなさん各国へKINTOサービスを導入する仲間なので、まとめて紹介します。 ミッション 各チームで細かいミッションは違いますが、共通して3個のミッションがあります。 開発の生産性を上げること 必要としているITサービスを提供すること グローバルKINTOサービスを横展開すること 私たちは、実際にKINTOサービスをカスタマへ提供しようとしている各国KINTO事業者向けにGlobal KINTO AppやKINTO BackOfficeシステムを導入して、各国KINTO事業の迅速な立ち上げに貢献することを目標にしています。 チームの様子 現在、グローバル開発Gの約2割の方が所属しています。 所属メンバーの出身地域は日本、インド、中国、台湾、韓国、ミャンマー、エクアドルなど国際色豊かです。国籍、経歴、文化、年齢が違いますが、それぞれ得意なことを主力に、導入に必要なことは経験が無くてもチャレンジして自分たちの力で開発しています。 まだまだ、勉強中のエンジニアもいますが、周りが手厚くフォローしていて着実に育ってくれています。 また、仕事終わりに出身国のレストランへ食事へ行ったり、スポーツを楽しんだりしている人もいます。 業務の様子 KINTO事業を実施している国は世界中なので、事業者とのコミュニケーションは英語が中心です。 自社内では関係する他のグループとのコミュニケーションは日本語で、自グループ内は英語だったり日本語だったり得意な言語で話しています。 各プロジェクトでは2週間のスプリントでAgile開発を標準にしているチームが多く、パートナーのエンジニアとも活発に意見交換しながら業務を進めています。 それぞれのチーム別に見ると。 チーム 業務内容 導入チーム 現在導入を進めている国の事業メンバーと日々コミュニケーションを取り、ニーズを捉えて必要な機能を導入しています。 DevOpsチーム 各プロジェクトやプロダクトチームのインフラ構築、CICDの構築、運用のサポートを行い、開発の生産性を上げています。 保守チーム 最近発足したチームで、KINTOサービスが稼働している国の事業者の求めに応じて迅速な改善を行っていきます。 テストチーム テスト自動化基盤の構築、将来的にはグループ全体のテストを自動化することを目標に活動しています。 これからのチャレンジ もっと世界にKINTOサービスを展開するため、より迅速なKINTO事業者への貢献が求められていると考えています。 そこで。 旧来の組織やアーキテクチャ・技術に固執せず、生産性を上げる施策を取り続けて世界最速のテックチームになりたい。 特に勉強中も含めた各エンジニアからのボトムアップ提案力を上げて技術力の底上げを行い続けられるチームになりたい。 もっといろいろな経歴を持つ仲間と切磋琢磨していきたい。 これを目指した先により良く、迅速にKINTOサービスを提供できるチームができます。 業務エンハンスチーム 業務エンハンスチームとミッション グローバル開発グループ業務エンハンスチームについて、リーダーの森より紹介いたします。 チームは現在5名のメンバーで構成されていて、ほとんどのメンバーが日本語・英語の両方を話します。 我々はグローバルKINTOビジネスのPublic Relationsとして、以下の3つを提供することをミッションとしています。 言語面での一貫した顧客体験 グローバルKINTOの社会的責任担保 グローバル開発グループ全体のポテンシャル底上げ 現在約60人規模のグローバル開発グループは、社内でも最も大きな組織であり、異なる国籍・カルチャー、経歴を持ったメンバーで構成されています。そんな中、グループ全体を横断したタスクを関係各所を巻き込みながら遂行するのが我々です。 現在取り組んでいること 具体的に我々がどんなタスクをもっているか、先述した3つのミッションに分けてご説明します。 1言語面での一貫した顧客体験 こちらはいわゆるローカライゼーション ^1 の対応となります。 実際に翻訳を行うだけではなく、グループ内で開発しているプロダクトの多言語化の進捗管理やプロセス改善、スタイルガイドの作成など、多言語化に関する全てのタスクを管理しております。 2グローバルKINTOの社会的責任担保 こちらは法務タスクです。関係各社との契約締結や、個人データ保護の対応 ^2 などを担当しております。グローバル開発グループで取り扱う案件は海外案件がほとんどなので、日本の法令のみではなく海外の法令も加味してタスク遂行する必要があります。法務エキスパートではないですが、法務目線を持ちながら、ビジネス・プロダクトの詳細を理解した上で間に立って会話するのが我々です。 3グローバル開発グループ全体のポテンシャル底上げ 冒頭でも記載の通り、国籍・言語・経歴など、多種多様なメンバーが所属しております。その方々が自身の持つ力をストレスなく、最大限に、効果的に発揮できるように環境を整えるのも我々のタスクです。以下がその一例です。 上記はあくまで一例ですが、他にもこのタスクの一環として、12月末にチーム内で”KINTO Global Innovation Days”と題し、社内ハッカソンのようなイベントを実施予定です。この様子は後日、別の記事として公開いたします。 チームの雰囲気 グループ内外様々な業務を広く浅めに多数のタスクを並行してこなしていくことが多いので、チーム内ではコミュニケーションを重視して誰がどのようなタスクを持っているか、工数に無理はないか、などを確認しあっています。「困ったことがあれば業務エンハンスに」と宣言しているので、チーム内でも困ったら常に相談しあえるような雰囲気づくりを心掛けています。 今後挑戦していきたいこと グローバル開発グループはKINTOテクノロジーズ全社でも最大の組織です。 一般的なことですが、コミュニケーションの取り方が難しくなったり、プロセスが複雑になったり、組織が大きくなるにつれて出てくる課題は多々あります。今後組織がさらに拡大した場合にも対応できるよう、各タスクにおいてまずはきちんとプロセスを整備したいです。特にローカライゼーションの部分に関しては今後ビジネスが拡大する上でもプロセスの整備は急務です。 また、コミュニケーションの部分についてはグループ全体のモチベーションを向上できるようなイベントやしかけを今後も企画してまいります。 🔻業務エンハンスチーム主催English Cafeの様子 ※普段はリモートでも対応していますが、写真撮影のタイミングだけ同じ部屋に集まりました。 グローバル開発Gで一緒に働く仲間を募集中 これまで3日連続でグローバル開発Gの紹介をしてまいりました。チームメンバーのインタビューは KINTOテクノロジーズのコーポレートサイト にも掲載しておりますので、ぜひこちらもご覧ください。 KINTOサービスは展開が始まって約2年経ちますが、KINTOサービスを立ち上げたり、リプレイスする国はまだまだこれから出てきます。私たちはこれから各国の期待に応えるため成長できるチームメンバーが必要です。ご興味のある方は 弊社採用サイト からご応募ください!
自己紹介 グローバル開発グループのBharath (バラト) です。 Global KINTO ID Platformチームとプロダクト・エンゲージメント・チームに所属しています。また、Technology PortalやUserPool管理画面など、アドホックなプロジェクトのサポートも行っています。 OpenID Connect (OIDC)とAWS Cognito関係に詳しいので、これらについてご相談があればいつでもお気軽に bharath.tv@kinto-technologies.com までご連絡ください。IDの話ができるのを楽しみにしております。 ハッカソンのテーマ KINTOテクノロジーズは、海外グループ会社とのコネクションを作ること、グローバルな舞台で活躍する力を養うこと、グローバルテクノロジーカンパニーとしてさらに進化することを目的に、2022年7月、Toyota Motor North America(以下、TMNA)が主催したハッカソン「toyotaswarm」に参加しました。 私も日本からリモートで参加しましたので、今回の記事ではその時の様子をお伝えしたいと思います。 TMNA "SWARM" Hackathonについて 2回目の開催となる今年は、2022年7月27日~29日までの3日間、世界中のトヨタグループ各社から40チーム、総勢270名が参加しました。 今回のチャレンジは以下の3つでした。 #1 Safety(安全) #2 Innovate to Carbon Neutral(カーボンニュートラル) #3 Open Global Technology Innovation (オープンイノベーション) もともと我々は「デジタルアイデンティティー」を大きなチャレンジと捉えており、私のチームは本業でもこれまでこのテーマに取り組んできたので、今回のハッカソンに参加することとなりました。 目指すべき姿 我々グローバル開発グループは、エンドユーザーがいかに簡単にモビリティーサービスを利用できるようにするか、を重視しています。例えば同グループで開発しているGlobal KINTO Appは、すべてのKINTOサービスをつなぐことを目指していますし、私の所属するGlobal KINTO IDチームは、エンドユーザーが一度サインアップするだけで世界中のあらゆるKINTOサービスを簡単に利用できるようにすることを目標としています。このハッカソンで解決したかった課題も同様で、「どのようにしてサービス間でエンドユーザーの情報を簡単に共有するか?」というものです。ユーザーが別のKINTOサービスを利用する度に、氏名等の情報を何度も入力しなければいけないのは効率的ではありません。そこで、ユーザーの同意を取得した上で、ユーザー情報を他のサービスと共有できるサービスのPoC(Proof of Concept)を行うことにしました。 チームについて ビザの問題で、ダラス(USのテキサス州にあるTMNAの本社)現地で参加したメンバーは3名のみで、残りのメンバーは日本からリモートでサポートしました。 現地参加メンバー キャプテン: Feng Xu (グループマネージャー) PdM: Dai Sasaki FE: Alex リモート参加メンバー FE: Chris.L BE: Bharath ハッカソンイベント中: 数日間で準備しコンセプトとその実現方法を決めました。現地には3人だけでしたが、大きな障壁とはなりませんでした。アイデアをチーム内でブラッシュアップし、9画面、11API、多くのAWSコンポーネントと1100以上のLoC (Lines of Code)を構築しました。 イベントの具体的な内容としては、まずオリンピック金メダリストであるエリン・ジャクソン選手が登壇し、オープニングを盛り上げてくれました。オリンピックのメダルを最も近い距離で見た瞬間です。 その後、各チームは別々のテーブルを与えられ、コンセプト作りに取りかかります。気合いの入ったチームが一斉に動き出したのは見ていて気持ちよかったです。一方、我々のチームはオフサイトメンバー数人が異なるタイムゾーンで作業をしていたため、作業完了までは少し苦労しました。各自が遂行すべきタスクは明確でしたが、すべてを合わせてしてワーキングモデルを作り上げなければならなかったので、そこに労力を費やしました。サーバーを異なるIPアドレスに接続したり、異なる地域のAWS CDNと連携したりといったよくある問題が発生しましたが、全体的にはうまく進めることが出来たと思います。 結果、我々はラウンド1をクリアすることができました。ラウンド2を通過するのは全体の半分だけなので、さらに大変でした。我々もベストを尽くしましたが、残念ながらラウンド2を通過することはできませんでした。 印象に残ったのは、他チームのアイデアが、非常に完成度の高いものだったということです。たとえば、飲酒運転防止のアイデアやCO2排出量削減のアイデアがラウンド2を通過しました。この2つのアイデアは、いずれもソフトウェアだけでなく、ソフトとハードの両方を組み込んだソリューションでした。 イベント参加から学んだこと TMNA役員の方々は常にハッカソン会場にいて、誰でも気軽に話しかけられたので、彼らをとても身近に感じることができ、また、彼らの想いをダイレクトに理解できました。私にとって素晴らしい経験でした。また、様々な国から来た参加者たちもとてもオープンで、親切に我々に接してくれ、他の参加企業とのコネクションを作るのにも非常に良い機会でした。このイベントから企業同士の相乗効果が生まれることを期待します。今後も、同イベントは定期的に開催される予定ですので、ぜひ次回も参加して、トヨタそして世界中にさらなる価値を提供したいです。
グローバル開発グループ紹介記事の第2弾として、本日はPdMチームとUIUXチームの紹介をいたします。 目次 目次 PdMチーム はじめに PdMチームの役割 メンバーの経歴 手がけているプロダクト KINTOで働くことの難しさと醍醐味 UIUXチーム ミッション Design System Global KINTO App 課題と今後 PdMチーム はじめに グローバル開発グループの佐々木と申します。担当プロダクトのProduct Manager(以下PdM)をやりつつ、PdMが所属するPdMチームのマネジメントもしている私から、チーム紹介をさせて頂きます。 PdMチームの役割 PdMチームは、海外の各KINTOサービスを支えるプロダクトの開発ライフサイクルの中で、各国へどのようなものを提供すべきかに関するプロダクト企画を行っています。もっと具体的に言うと、各国のニーズを確認し、各種リサーチ結果に基づいて、解決すべきペインそして提供すべき価値を特定してプロダクトのあるべき姿を描く。そのうえで、それを実現していくロードマップを策定してプロダクト開発を推進していく役割を担っています。 メンバーの経歴 KINTOはモビリティサービスを提供するブランドなので、PdMチームもその領域の経験者が揃っていると思われがちなのですが、実はそんなことはありません。結構多様なバックグラウンドを持つ人達で構成されているんです。例えば、日本の大手テック企業出身の人、新聞を中心としたメディア企業でPdMだった人、中国大手テック企業にいた人、金融業界の経歴がすごく長い人など、いろいろな経歴やスペシャリティを持つ人が、まだ歴史の浅いモビリティーサービスという領域へ強い興味を持ち、KINTOテクノロジーズへジョインしてくれました。 手がけているプロダクト グローバル開発グループでは複数のプロダクトを開発していますが、どんなプロダクトなのか、1つ実例を紹介してみましょう。複数国のカーシェアリングやレンタカーを1つのアプリで提供できる Global KINTO App(GKA) がそれです。アジアのAという国へ行ったときはその国のカーシェア、中東のBという国へ行ったときはその国のレンタカー、といったように、そのアプリにおいて、複数の国にあるKINTOサービスを切り替えて迷わずスムーズに使うことができる体験を提供するものです。グローバルでサービスを提供しているKINTOならではのスケール感だと思いませんか? KINTOで働くことの難しさと醍醐味 海外の各KINTOサービスへプロダクトを提供し、そのプロダクトを通じてビジネス成果を最大化することがPdMチームのミッションですが、それゆえに困難なこともあります。例えば、各地へプロダクトを提供するにあたっては、事業を運営している現地法人と話して現地のニーズやターゲットを理解しようと考えます。しかし、物理的な距離や商習慣の距離、また文化的な距離、など様々な”距離”が存在するため、実際にどんな人がどのようにプロダクトを使ってKINTOを利用しているのかを把握することに、高いハードルがあります。それでも何とかして有益な情報を入手しなければなりません。そのため、現地とのコミュニケーションにおける深さや質の向上は、私達が提供する価値を左右する非常に重要な要素になっています。 (↓の写真は今年世界各地のTOYOTAグループ企業を集めてアメリカで開催されたHackathonイベントの模様。このような場でグローバルのメンバーと交流することも私達にとっては非常に意義があります。ちなみにこのイベント、2023年も実施予定のようです!) 上記で書いたこと以外にも困難なことはいろいろあるものの、まだ正解がわからないモビリティーサービスにおいては試行錯誤しながらやるからこその魅力があります。各地で実施する新しい取り組みや、新しい形での「移動の喜び」の届け方へ今の段階から関わることができるのは、他の組織ではなかなか味わえないKINTOならではの醍醐味なのではないでしょうか。 モビリティーサービスの将来像について、いろいろな人や各企業が想像力を膨らませて考えています。それでも、この領域では確定的なものがまだまだはっきり見えません。その中で、世界各国にいるKINTOユーザーの気持ちへ寄り添いつつ「移動の喜び」を具現化するプロダクトの実現に興味がある方は、ぜひ一緒に前進させていきましょう。 UIUXチーム ミッション UIUX担当の渡辺です。 「KINTO」のブランドで世界展開している各種モビリティサービスに対して、UIUXチームでは Global KINTO App(GKA) というアプリの制作から、 Global KINTO Entrance Web まで規模の大小問わずたくさんの開発活動に関わっています。 ビジュアル的な制作と論理的な情報設計が私達のミッションです。 トヨタグループという大きなバックボーンがあるのでルールや制約が多いと思われる方もいると思いますが、実は決まっていないことも作っていないものもたくさんあります。 Design System 最近一段落ついた大きなプロジェクトはDesign Systemの構築です。 サービスを構築していくには、職種や技術力の壁を超えて同じクオリティを制作することはとても困難です。その問題を解決する1つがDesign Systemでした。 簡単に言えばデザイナーもエンジニアもコピペするだけで同クオリティのものが簡単に作れるコンポーネント集です。 ゼロからの作成だったので、ロゴ規定やカラートーン、アイコンにいたるまで約1年の製作期間は本当に大変でした(本当に…) 現在は社内での導入はもちろん世界のKINTO各社から導入についてお問い合わせが来るようになりつつあり、その1件1件に涙が出そうなくらい嬉しいです。 Global KINTO App GKAの愛称で親しまれています。「世界中のKINTOサービスを1つのアプリでつなぐ」というコンセプトを持たせたモバイルアプリです。現時点ではタイとカタールのKINTOサービスが実装されています。 GKAではアジャイル開発の1つであるスクラムをベースに体制を作っているためプロデューサー・エンジニア・デザイナーがとても近い距離で話し合いながら進められています。 スクラムといえばエンジニア以外は敷居が高いイメージですが、社内では著名な方を講師に迎えてのワークショップの実施などを積極的に行っているので、とても参加しやすくなってきました。 課題と今後 一方、理想通りにはいかないことも多くあります。グループ企業との関係性が複雑な部分があり、ステークホルダーが多すぎて「なかなか判断が進まず長い期間足踏みをしている場面」もあります。「仮説を立てる段階でのリサーチや検討が不十分な場合」もありプロセス整備をしていくことも今後の課題です。 学ぶことも挑戦することも多いので大変ですが裁量も大きいので、やりたいことに手を上げて発言しやすい環境です。チームメンバーの言語も経歴も様々がゆえに新しい発想や表現に出会う毎日でもあります。未来のモビリティーを想像し、いま無いものを生み出すことにやりがいを感じて、想像力全開で取り組める人にぜひ参加して欲しいと思っています。
こんにちは KINTOテクノロジーズ モバイルアプリ開発Gの小山です。 モバイルアプリの開発・運用に携わっています。担当はiOSです。 今回はGlobal KINTOのモバイルアプリ開発の中でMVVMを採用した内容を紹介したいと思います。 MVVM と Combine 話をする前にまずこれらについて軽く説明をしておきたいと思います。 MVVM ソフトウェア開発におけるアーキテクチャのひとつです。 MVCモデルの派生系で Model-View-ViewModel という構成を取ります。 細かいことを言うとややこしいので簡潔に示すと、 Model データをひとまとめにした存在であり、データのまとまりと簡単な処理を担います。複雑な処理は行いません。 View 画面描写を担う存在です。画面を生成するのに必要なデータを受け取り、ただ描写します。 ViewModel ModelとViewの中間地点の存在で、複数のModelのデータをまとめたり、Viewの状態を保持するための値を持つ役割を担ったりします。 といった感じです。個人の見解です。 ただこれでもiOSやり始め当初の私には理解が難しかったです。 そこでiOSの開発に当てはめるとこんな感じになります。 Model 扱うデータをただひとまとめにします。基準として辞書型を採用するくらいならModelを一つ作ります。Model内のデータに関わるシンプルなメソッドのみを持ちます。 View ViewControllerや個別のViewがこれに当たります。描写に関わるコーディングのみ行い、データの操作は行わず、受け取ったデータをただ描写します。基準としてif文が全くない状態を目指します。 ViewModel ViewControllerからトリガーを受け取ってデータを返却します。ViewControllerとは1対1で、個別のViewに関しては場合によって上位のViewControllerのViewModelが役目を担っても良いです。 これを実現していきたいと思います。本記事の中では特にViewとViewModelの分割をご紹介したいと思います。 Combine 2019年の6月に登場した、Apple公式のリアクティブアーキテクチャを実現するフレームワークです。 それまではリアクティブアーキテクチャを実現するにはサードパーティ製のRxSwiftを使うことがほとんどでしたが、公式でサポートの厚いライブラリがリリースされました。 ちょ、ちょっと待ってリアクティブアーキテクチャってなんだっけ と、思った方もいるかと思います。 私がそうでした。Wikipediaによると以下の通りです。 reactive programming is a declarative programming paradigm concerned with data streams and the propagation of change. -- Wikipedia | Reactive programming これを和訳すると以下の通りです。 データストリームと変更の伝播に関係する宣言型プログラミングパラダイムです。 いまいち分からないですね。 こちらもややこしくせず理解するには、表計算ソフトをイメージすると良いと聞いたことがあります。 以下のような簡単な計算式を入力したとします。 A B C 10 20 =A1+B1 これを入力完了するともちろんC1セルに計算結果が入ります。 A B C 10 20 30 この状態でA1セルを20に書き換えた場合はどうなるでしょうか。 A B C 20 20 40 もちろんC1セルが40に書き変わります。 このようにA1の変更に対応してC1に直接手を加えずに変更を伝播させていくことを、リアクティブアーキテクチャと呼びます。 初めにデータ処理の宣言( =A1+B1 )のみを行い、最後に実データを流す(A1に20を代入)、といったイメージが私はしっくりきました。 背景 前置きが少々長くなりました。我々がなぜCombine、MVVMを採用するに至ったかという話です。 Global KINTOの開発案件を担当した当初、外注していたソースコードを内製に切り替えて間もない状況だったこともあり、既に出来上がっている部分はいわゆるスパゲッティコードの状態でメンテナンス性が非常に悪い状態でした。 あらゆるところでグローバル変数が呼ばれ、どのクラスがどのクラスと依存関係にあるか全く分からない状態でした。 しかし幸いなことに、コードと画面数が比較的少なかったため全体的にアーキテクチャを見直すことで解決をしようと試みました。 この際に、モバイルアプリ開発GにてCombineを使ったMVVMの知見があったため、MVVMのアーキテクチャに則り進めることとなりました。 アーキテクチャに則った設計をきちんとすることで、新規参入したメンバーでも理解しやすく、安全に改修できるようなプロジェクトにすることが目標です。 いざ、実装! 今回はMVVMに則ると決めたので、ViewとViewModelは責務を分離します。 なお、今回の実装ではUIKitを使用します。 View - Part1 Viewでは一切の演算処理を行わない代わりに、イベント発火のタイミングだけをViewModelに伝えたいです。 これを実装するために、CombineのPublisherを利用していきます。 例えば、viewDidLoadのタイミングを送信する必要がある場合、PassthroughSubjectにVoid型を持たせて定義しておきます。 private let didLoad: PassthroughSubject<Void, Never> = .init() これをviewDidLoad時に送信するようにします。 override func viewDidLoad() { super.viewDidLoad() didLoad.send() } また、ボタンのタップ時にはtapPublisher ^combineCocoa を利用するのがスマートです。 まず、対象のボタンをOutlet接続し、送信用のPublisherを準備します。 もしボタンを押したタイミングで表示されている画面のString値を渡したい場合は、VoidではなくStringでPublisherを定義します。 @IBOutlet weak var button: UIButton! @IBOutlet weak var textArea: UITextField! private let tapButton: PassthroughSubject<String, Never> = .init() その後、tapPublisherを利用してイベントを検知してViewModelに送信します。 button .tapPublisher .sink { [weak self] in self?.tapButton.send(textArea.text ?? "") } .store(in: &cancellables) 続いて、ViewModelを見てみましょう。 ViewModel ViewModelではViewから受け取ったイベントトリガーを元に、情報を取得したり生成したりすることで、Viewに必要な情報を集めて返してあげます。 こちらではCombineのOperator、Subscriberを使って実現していきます。 初めに、View側との接続準備のため、ViewModelとは別にInput,Outputの構造体を定義します。 InputはViewから渡されるデータ、Outputはその結果ViewModelから渡したいデータです。 データのやり取りの際に、渡されるデータとエラーの型がきちんと決まっていれば処理は可能であるため、型は一律AnyPublisherを使います。 struct ViewModelInput { let viewDidLoad: AnyPublisher<Void, Never> // 画面が最初に表示されたときにトリガーが欲しい! let tapButton: AnyPublisher<String, Never> // ボタンがタップされたときにテキストが欲しい! } struct ViewModelOutput { let onShowWelcome: AnyPublisher<String, Never> // Welcomeテキストを画面に表示してほしい let onShowText: AnyPublisher<String, Never> // 任意のテキストを画面に表示してほしい let onShowOnlyFirst: AnyPublisher<Void, Never> // 最初にボタンを押された時のみ固定値を画面に出してほしい } 続いて、データの処理部分を作成します。Inputを受け取ってOutputに変換する部分の実装になります。 例えば、viewDidLoad時に特定のAPIを実行するような動作であれば、viewDidLoadのPublisherからOperatorを繋げてAPIリクエストを実行します。 func transform(input: ViewModelInput) -> ViewModelOutput { let apiResponse = input .viewDidLoad .flatMap { api.requestData() } 同様にボタンタップ時、画面上のテキストを基にデータを生成するような動作をしたい場合は、mapを使います。 let text = input .tapButton .map { createText(text: $0) } また他にも、viewDidLoadが呼ばれ、且つボタンのタップもされたときに処理させたいことがあるとします。 そういった場合はPublisher同士を接続することができます。いくつか接続方法がありますが、今回はzipを使います。 let didLoad = input .viewDidLoad let buttonTap = input .tapButton let didLoadAndButtonTap = didLoad .zip(buttonTap) .map { _ in } このように様々なOperatorがCombineやその拡張ライブラリにはすでに準備されているため、コードをシンプルに保ちながら複雑な処理を実現することができます。 Operatorはいくつもありますが、個人的に便利でこれさえ覚えておけばOKというものを以下に挙げておきます。 map flatMap compactMap filter share materialize ^combineExt merge zip combineLatest withLatestFrom ^combineExt そして最後にOutputの型に合わせてreturnしてあげます。 Combineを利用する場合、Operatorを接続するたびに型がどんどん拡張されてしまうため、最後にAnyPublisherにまとめてから生成したデータをViewに返します。 return .init( onShowWelcome: apiResponse.eraseToAnyPublisher(), onShowText: text.eraseToAnyPublisher(), onShowOnlyFirst: didLoadAndButtonTap.eraseToAnyPublisher() ) } View - Part2 ViewModel側が完成したので、Viewと接続して画面描写を行います。 先ほど用意したtransformメソッドを呼び出して、ViewModelでの処理結果を受け取りましょう。 let output = viewModel.transform( input: .init( viewDidLoad: didLoad.eraseToAnyPublisher(), tapButton: tapButton.eraseToAnyPublisher() ) ) 処理結果を受け取ったら、各結果の際にどんな画面描写をするか実装して完成になります。 output .onShowWelcome .receive(on: DispatchQueue.main) .sink { [weak self] in self?.textArea.text = $0 } .store(in: &cancellables) output .onShowText .receive(on: DispatchQueue.main) .sink { [weak self] in self?.textArea.text = $0 } .store(in: &cancellables) output .onShowOnlyFirst .receive(on: DispatchQueue.main) .sink { [weak self] in self?.showCustomMessage("First!") } .store(in: &cancellables) 完成 こうして完成したコードがこちらになります。 class ViewController: UIViewController { @IBOutlet weak var button: UIButton! @IBOutlet weak var textArea: UITextField! private var viewModel: ViewModelProtocol! private let didLoad: PassthroughSubject<Void, Never> = .init() private let tapButton: PassthroughSubject<String, Never> = .init() private var cancellables: Set<AnyCancellable> = .init() func configure(viewModel: ViewModelProtocol) { self.viewModel = viewModel } override func viewDidLoad() { super.viewDidLoad() bind() didLoad.send() } func bind() { let output = viewModel.transform( input: .init( viewDidLoad: didLoad.eraseToAnyPublisher(), tapButton: tapButton.eraseToAnyPublisher() ) ) button .tapPublisher .sink { [weak self] in self?.tapButton.send(textArea.text ?? "") } .store(in: &cancellables) output .onShowWelcome .receive(on: DispatchQueue.main) .sink { [weak self] in self?.textArea.text = $0 } .store(in: &cancellables) output .onShowText .receive(on: DispatchQueue.main) .sink { [weak self] in self?.textArea.text = $0 } .store(in: &cancellables) output .onShowOnlyFirst .receive(on: DispatchQueue.main) .sink { [weak self] in self?.showCustomMessage("First!") // あらかじめメソッドが準備されている想定 } .store(in: &cancellables) } } protocol ViewModelProtocol { func transform(input: ViewModelInput) -> ViewModelOutput } struct ViewModelInput { let viewDidLoad: AnyPublisher<Void, Never> let tapButton: AnyPublisher<String, Never> } struct ViewModelOutput { let onShowWelcome: AnyPublisher<String, Never> let onShowText: AnyPublisher<String, Never> let onShowOnlyFirst: AnyPublisher<Void, Never> } struct ViewModel: ViewModelProtocol { let api: SomeApiProtocol init(api: SomeApiProtocol) { self.api = api } func transform(input: ViewModelInput) -> ViewModelOutput { let didLoad = input .viewDidLoad .share() let apiResponse = didLoad .flatMap { api.requestData() } // Future<String, Never> が返される想定 let buttonTap = input .tapButton .share() let text = buttonTap .map { createText(text: $0) } let didLoadAndButtonTap = didLoad .zip(buttonTap) .map { _ in } return .init( onShowWelcome: apiResponse.eraseToAnyPublisher(), onShowText: text.eraseToAnyPublisher(), onShowOnlyFirst: didLoadAndButtonTap.eraseToAnyPublisher() ) } func createText(text: String) -> String { "\(text) show!!" } } このようにViewとViewModelで明確に役割分担を行うことでコード内に秩序が生まれます。 どのViewでも同じ構成をとることができるため、コードの可読性が向上しメンテナンスもしやすく、役割が決まっているので無理矢理なコーディングが生まれにくいです。 ただしデメリットとしてはCombineやRxSwiftなどのリアクティブプログラミングを経験していない場合、それまでのSwiftとは 言語が変わったかと思うほど理解が難しい 点です。 Global KINTOのiOSのプロジェクトでは、全てのViewをこの構成に則って作成しています。 可読性が向上したことでメンテナンス性も上がり、新規のViewを作成する場合でも作成の仕方にばらつきが出づらくなりました。 最後に モバイルアプリ開発Gでは、本記事のような知見をGlobal KINTO以外のプロダクトに共有したり、これとは全く別の新しいアーキテクチャに挑戦するといったようなことも実践しています。 引き続き、モバイルアプリ開発Gの責務として、iOSの様々な開発手法に挑戦していきたいと思っています!どうぞよろしくお願いします。
KINTOのグローバル展開をサポートしている開発組織を紹介します。 目次 目次 自己紹介 グローバル開発グループの体制について 今後の活動方針の紹介 おわりに 自己紹介 KTCでグローバル開発グループでグループマネージャーをしているFengです。 私は中国でソフトウェア開発を学び、2002年より日本の大学院に進学し、その後は大手電気機器メーカーでソフトウェアエンジニア、自動車部品メーカーでプロジェクトマネージャー、プロダクトオーナーを経て、前職はモビリティ関連部品を取り扱う外資系メーカーの日本トップを務めていたことでKINTOに入社しました。 KINTOに入社してから、各国のステークホルダーたちと密に連携し、KINTOとして必要と思われるグローバル共通なものはどういうものなのかを常に考えながらプロダクト開発及び組織作りをやってきました。 グローバル開発グループの体制について 2019年グループ立ち上げの初期頃は、私がPdMを兼任しながら数名メンバーしかいない中で開発をスタートしていましたが、ちょうど3年経った今(2022年11月)は社員59名になり、その内39名が海外出身ということで、かなりダイバーシティな環境となってきたと感じています。 我々のグループとして、常に海外のKINTOチームとコミュニケーションを取りながら、下記のような業務を遂行してきました。 要件・ニーズを確認してプロダクトを企画・検討 グローバルで共通化できるようなプロダクトを基盤として開発 開発してきたプロダクトを必要に応じて各国への導入開発を実施 よって、今の開発体制もそれらの業務をサイクルとして回せるよう、下記のように構築しています。 PdMチームが企画したプロダクトを、開発チームが開発し、導入チームが各サービスへ導入する流れです。 また、各プロダクトやグループ全体に係る共通のチームとしてUIUXチームと業務エンハンスチームが存在します。 今後の活動方針の紹介 モビリティ事業はまだまだ分からないことがいっぱいある中で、各国KINTO事業をより効率よく支えるために、グローバルで共通化可能なものを念頭に置いて下記四つの方面から活動していく予定です。 おわりに KTCのグローバル開発グループ全体について、簡単ではありますが紹介しました。 各チームの詳細についてはこのあと第二弾でPdMチーム・UIUXチーム、第三弾で開発チーム・導入チーム・業務エンハンスチームの紹介をいたします。 まだ組織として成長している最中であるので、色々課題はありますが、KINTOが目指している Ever Better Mobility For All を実現するために、少しずつ居心地の良い組織をメンバーと一緒に仕上げていきたいと思っています。 また、この記事を見てグローバルでKINTOはどのようなサービスを展開しているのか、グローバル開発グループの雰囲気に興味・関心を持っていただいた方は、ぜひ下記のサイトにもアクセスしてみてください。 KINTOのグローバルポータルサイト KTC採用ページ内グローバル開発Gの紹介記事
はじめに KINTOテクノロジーズで、複数のサービスが利用する決済プラットフォームの開発チーム[^1]に所属している金谷です。 新規プロジェクトに対して、リモートでモブプログラミングを行い、オンスケジュールで開発完了させた事例を紹介します。 [^1]: 決済プラットフォームの他の取り組みは、 グローバル展開も視野に入れた決済プラットフォームにドメイン駆動設計(DDD)を取り入れた をご参照ください。 背景 社内向けの決済に関する業務システムを新規で作るプロジェクトが発足し、東京勤務のプロダクトオーナーと、東京勤務のエンジニアに、私含む大阪勤務の2名による3名のエンジニアの体制で開発することになりました。 素早く作りたいことと、運用コスト(特にAWSコスト)を減らしたいことから、フロントエンドには AWS Amplify をベースとしたReactによるSPAを採用し、いくつか必要なAPIの開発には AWSサーバレスアプリケーションモデル を採用しました。 課題 プロジェクト開始直後の時点で、私は既に不安がありました。 具体的には、私自身が今まで使ったことのないAWSのサービスを使うことです。 自分の不安も共有するべくそれぞれのメンバーに話を聞くと、どうやら集まった3人は、技術的にも得意な領域が異なることが分かりました。 具体的には、フロントエンド・バックエンド・インフラ(AWS)の3領域に分けた場合、開発チームの各メンバーは、2つの領域は得意だが1つは自信がないことが分かりました。 例えばKさんこと私の場合、フロントエンドとバックエンドは大丈夫な反面、AWSに自信がない、といった具合です。奇跡的にも、各技術領域について2人は詳しい事が分かりましたので、誰かに頼り切りになる局面がなさそうだという点で安心しました。 メンバー フロントエンド バックエンド インフラ(AWS) Kさん ◎ ◎ △ Tさん ◎ △ ◎ Nさん △ ◎ ◎ スキルの領域と開発メンバーの得意領域の星取表 また会話する上で分かった一番の不安は、チームで開発していく上での共通認識がないことでした。 例えばフロントエンドだけでも、コンポーネントの粒度はどうするのか?状態管理はどの粒度で行うべきか?Promiseベースかasync/awaitで行くか?テストをどこまで書くべきか?などなど、コードが1行もない状況ですので、すべてを決めていく必要があります。一方で、入社後1年未満のメンバーで構成されたことから一緒に仕事をするのが初めてのメンバーなので、あのプロジェクトのように〜といった共通認識がありません。共通認識の構築はいち早く行う必要がありました。 改めて課題を整理しますと、プロジェクトを成功させるために、以下の2つが大きな課題であると考えました。 共通認識が揃っていない状況でスタートするため、共通認識を早めに構築したい (認識齟齬を減らし良い品質のプロダクトを作りたい) 各々の得意な領域を共有・補完することで、技術力を底上げしたい 上記2つの課題を解消するために、今回のプロジェクトでは、開発のスタイルとしてモブプログラミングを採用することにしました。 モブプログラミングとは モブプログラミング(以下モブプロとします)とは、 モブプログラミング・ベストプラクティス という本では「3人以上の人々が1台のコンピューターの前に座って協力しながら問題を解決していくこと」とされています。 ひとつのPC(画面)で皆が参加するのですが、実際には2つのロールがあります。 3人以上で行うため、モブが2人以上いる状態で、議論しながら方針を決め、タイピストが方針に従いコードに落とし込みます。 タイピスト (PCを操作しコードを書く) モブ (開発の方針を議論して指示する) ひとつの仕事に3人以上が関わるモブプロを理解する上で、リソース効率とフロー効率という考え方が重要になります。詳細は フロー効率性とリソース効率性について #xpjug - SlideShare に譲りますが、モブプロはフロー効率に全振りする仕事の仕方です。 フロー効率最大化が目指したいことではないのですが、モブプロをする以上、フロー効率に軸足を置いた仕事の仕方になります。 試行錯誤した内容・工夫したこと チームメンバーは地理的に離れている関係上、リモートでの開発を余儀なくされます。そのためZoomを使ったリモートモブプロが基本になります。 プロジェクトを成功させるために、課題の解消が必要だと考えていたため、以下の工夫をしながらモブプロを取り入れていきました。 情報量を増やす 情報量を増やすために、画面はタイピストのデスクトップ全体を共有しながら作業しました。共有ウィンドウだけでは、ウィンドウ外で何が起きているか分かりません。OSやツールの使い方も共有したいため、デスクトップ全体を共有しました。 次にタイピストは、考えていることをなるべく声に出しながら作業するようにしました。特に実際にアウトプットの作業を出来るのはタイピストだけなので、ズレがないかを確認する意図もあります。 気がつけば、タイピストも議論に加わることも多くなりました。 本来のモブプロのタイピストとは異なるのですが、共通認識を作ることが大事であると考えていたため、議論参加をヨシ!としていました。 時間を管理する 3人以上が自然に集まってモブプロすることは難しいと考えたため、カレンダーで各員の予定を押さえて、モブプロの時間を確保するようにしました。 モブプロの時間を事前に設定しておくことで、1日の開発にリズムが生まれやすくなります。 また、 ZoomのTimerアプリ を入れて、制限時間を設けるようにしました。モブプロは集中した作業のため、時間を区切らず続けてしまうことで疲労しやすくなります。適度な交代と適度な休憩を入れたいため、タイマーで時間管理するようにしました。書籍や他社事例 [^2] を見ると10分交代と非常に短い時間で交代するようですが、次のタスク単位で分ける関係もあり、30分にしました。 [^2]: https://techblog.yahoo.co.jp/entry/2020052730002064/ フィーチャーチケットを更に細分化してTODO コメントとして残す モブプロ対象のフィーチャーについて、作業を事前に細分化して、修正対象の中心となるソースコードに TODO コメントとして残すようにしました。 TODOコメントを残すには2つのメリットがあります。一つは、フィーチャーのゴールの解像度が上がること。もう一つは、区切りのいいタイミングで交代しやすくなることです。 例えば決済処理を行うユーザー情報の更新APIを新しく作る際に、以下のようなTODOコメントを、コードを書く前に書いていました。この時点で作業内容も作業順番もクリアになるため、段取り良く進める事ができますし、交代や休憩もスムーズでした。 # TODO openapiにユーザー情報更新の定義を追加 # TODO infrastructure - ユーザー情報更新のインターフェース作成 # TODO infrastructure - ユーザー情報更新の処理実装 # TODO application - バリデーション処理実装 # TODO application - ユーザー情報更新の処理実装 # TODO sam template に lambda 定義を追加 # TODO デプロイ、動作確認 def lambda_handler(event, context): pass モブプロする・しないの基準を相対的に設定する すべてをモブプロで開発するのか?という疑問は早い段階で上がりましたが、実際にモブプロを進める上で、難しそう・議論が必要そうなフィーチャーを優先的にモブで実施することにしました。 あくまでスプリント内のフィーチャーのうち、相対的に難しそうなフィーチャーという選び方ではありますが、難しそうなフィーチャーに対する認識も揃ったため、皆に納得感がありました。 また簡単なフィーチャーは、モブプロ以外の時間で各自対応するようにしてバランスを取っていました。 難しそうなフィーチャーはモブプロで片付いているため、モブプロ終了後に簡単なフィーチャーのプルリクエストがガンガン飛んできました。 モブ「プログラミング」以外のこともモブプロで行う モブプログラミングなので「プログラミング」だけを対象にしていたかというとそうではなく、プログラミング以外の作業もモブプロ時間にやっていました。例として2つ挙げます。 コードレビュー コードレビューもモブプロでやっていることがありました。すべてをモブプロでやっていたわけではありませんので、どうしても開発過程を見ていないコードが出てきます。 モブプロの時間の最初に、モブプロ以外で作ったコードを説明する場を設けて、皆が聞いて質問するようにしました。この時間があったおかげで、詰まりがちなレビュー工程も素早くパスできました。 運用に関わる作業 運用に関する作業もモブプロの時間を使って行いました。具体的には、初めてCognitoのユーザープールを作るときや、GitHub Actionsに関する設定を追加するときには、モブプロの時間を使って皆で見ながら作業しました。これにより、運用面のイメージも付くようになりました。 プロダクトオーナーとのコミュニケーションをメンバー全員で出るようにする 開発チーム内の共通認識はできるようになったのですが、プロダクトオーナーも入れた会話がないとずれる恐れがありますし、実際にずれたことがありました。最初の頃は、プロダクトオーナーと私ではよく会話していたのですが、特に議事録も残さず意思決定も曖昧なまま進めていたため、認識のずれが発生していました。 対策として、プロダクトオーナーとのコミュニケーションは全員で参加するようにし、合わせて議事録もリアルタイムで残すようにしました。 以降は認識のずれも減ってきて、手戻りも少なく開発を進められるようになりました。 合わせて、お互い出張する機会を作り、重要な意思決定やオフラインでモブプロする機会を増やしました。 オフラインでモブプロする図 スプリントゼロを設ける (モブプロとは直接関係ない) スプリントゼロを設けさせてほしいとプロダクトオーナーにお願いして、1週間のスプリントゼロ期間を作りました。 スプリントゼロでは、スプリント1でいきなり多くのアウトプットを出せるようにするための準備を行ったのですが、特に私がこだわりをもって行った作業は、以下の2点です。 create-react-app が最低限動くリポジトリを作る create-react-appをデプロイできるようにデプロイ先やGitHub Actionsを整備する つまり、開発環境でワンクリックで動作確認出来る状況を一番はじめに作りました。 継続的デプロイができることで、より良いフィードバックを素早く得ることができます。 継続的デプロイの仕組みを早い段階で作ったことで、いつでも誰でも開発環境に最新のコードをデプロイできるようになりました。それどころかスプリント0のスコープを飛び越えてスプリント1のフィーチャーを終わらせる人も出てきて嬉しい悲鳴でした。 モブプロとは直接の関係はありませんが、新規開発の際にスプリントゼロを設けるのはオススメです。 他にも準備することが盛りだくさんのスプリントゼロの詳細については 【資料公開】スクラムプロジェクト開始のベストプラクティス | Ryuzee.com をご参照ください。 結果の分析と次へのトライ 結果 プロダクトオーナーが求める品質を満たしつつ、オンスケジュールで開発を完了することができました。 その際、「これほどの高品質でスケジュール通り終わったプロジェクトは経験したことがなかった」とご評価いただきました。 また、利用者である業務部門のご担当者にも実際に画面を触っていただいてフィードバックを反映し、最終的に「とても使いやすい」とご評価いただきました。 我々開発メンバーも、苦手意識のある領域も自走できるようになりましたし、自分の強みを更に発揮する方向に進んでいます。 次に活かすための分析 プロジェクトとしては非常に良い成果を出すことができたと思いますが、再現性の高そうな理由を考えると、以下になると考えています。 共通認識を早い段階で揃えることにより、品質を高めて後戻りを減らすことができた スプリントゼロで開発の基盤を作ったことで、作業効率が最初から高くなっていた モブプロを通すことでコミュニケーションが多く発生し、早い段階で関係性構築ができた 総じて早期にコミュニケーションや開発基盤の構築など、よい準備ができたことが良かったのでしょう。 フロー効率に全振りするモブプロを積極的に行うことでスケジュールに遅れが出るのでは?と予想していましたが、そうなりませんでした。その理由として、難しい部分をモブプロで対応する一方で簡単な部分は各メンバーが対応したためではないか?と考えています。開発を進める上でのボトルネックとなる部分に集中できたことが良かったのでしょう。 次へのトライ まずは自分たちだけで言いますと、自分たちだけでは解決できないときに、その問題を解決できる人と一緒にモブプロできるといいなと考えています。技術習得面でも、横のつながりの面でも、良い効果が得られそうだと考えています。 また、もう少し規模の大きいプロジェクトでもモブプロをやってみたいです。フロー効率全振りでは難しいという状況になるとは思いますが、まずは早い段階で共通認識を作ることがどのくらい良いのか?試してみたいです。 まとめ フロー効率を最大化するモブプロですが、揃っていない共通認識を揃えるためにも非常に有用でした。難しい実装に集中してモブプロを行うように使い所を明確にすることで、プロジェクトの遅れを出さずに開発することができました。 KINTOテクノロジーズは、東京と大阪に開発拠点があります。どのような人たちが働いているのか?募集職種はどのようなものがあるのか?気になる方は、 募集職種一覧 をご覧ください。お待ちしております!