キャディでエンジニア採用を担当しております片渕です。
今回は2022年2月22日に開催したイベント『【画面キャプチャ禁止】うちの管理画面フロントエンドほぼ全部見せます! 』に登壇のエンジニア(先山・小倉・桐生)からのプレゼン内容をまとめたものをご紹介していきます。
イベントのアジェンダとしては以下の通りです。
生産管理の管理画面(先山)
https://speakerdeck.com/caddi_eng/20220222xian-shan-fa-biao-zi-liao-tenhurev2
先山:
私の方からはKlein(クライン)の概要をお話していきます。Kleinは一言でいうとキャディ社内の受発注を管理しているシステムです。冒頭の資料に記載のあった製造工程・サプライチェーン管理プロダクトを指しています。
キャディにおける受発注とは、お客様が作ってほしい製品の図面を受注して、製造原価を計算し、その製品の製造を加工会社さんに発注します。
発注後は実際の製品ができて、キャディの拠点に届き、そこで品質の担保をしてからお客様に納品します。
この加工会社さんのことをSP(Supply Partner)と社内用語として使っています。
それからサプライチェーンとは、製造の原材料・部品の調達から販売に至るまでの一連の流れを指す用語です。
キャディにおけるサプライチェーンとは、お客様から製品を受注したところから始まります。受注製品はいくつかの工程を経て最終的な製品に仕上がります。例えばA社さんには金属を曲げる加工をお願いし、その品質をキャディが検査した後で、今度はB社さんに塗装をお願いし、またキャディにて品質を確認して、最後にお客様へ納品する流れを指します。
これはキャディから見たサプライチェーンですが、お客様からすると、私たちが納品した製品を使って最終的な製品を製造するため、この先にもサプライチェーンが続いていきます。
ちなみにKleinというプロダクトの名前の由来は、クラインの壺から来ています。よろしければ過去のtech Blogをご覧ください。
(実際の管理画面をご覧いただきながらデモ)
Kleinの管理画面にはお客様から受注した案件が一覧で表示されます。
製品のデータは別の原価計算プロダクトから出力されたcsvをアップロードして登録します。BtoBプロダクトでよくありがちな、例えば大量の製品を受注したので一括でデータを取り込みたいという要望があるため、このようなバルクアップロードやダウンロードの機能を実装しています。
製品の登録が完了したら、ユーザーのオペレーションとしては、どこのSPさんに作業をお願いするか決定します。
例えばこのテストデータの製品は、生地加工と表面処理と熱処理の3つの工程がありますが、生地加工をA社さん、表面処理と熱処理をB社さんにお願いすることとして画面から設定してみます。
お願いするSPさんが決まったら、サプライチェーンを設計します。A社さんからB社さんにいつ製品が届けられるかや、私たちの拠点にいつ搬入されるかなどを画面から入力していきます。入力された情報は別の画面でグラフ構造で表現され、製品の流れをわかりやすくしています。
このサプライチェーン設計画面では、数百点以上の図面を一気に扱うこともあるため、Excelのようにコピペができたりするなど工夫を凝らした画面にしています。この機能はAG-Gridというライブラリを使うことで実現しています。
デモ用なのでかなり省略しているのですが、サプライチェーンを構築した後は、このテストデータの製品をSPさんに発注します。
他にもKleinの特徴として、ステークホルダーが多いので、フローを一律に決めるのが難しい場面でも、要件に対応できるようにしています。不確実性をフロントエンドで吸収しています。
Kleinのソフトウェアのアーキテクチャ
ユーザーのブラウザ上にてReactのアプリケーションが動き、JavaScriptファイルやHTMLファイルはnginxで配信して、CDNがキャッシュしてくれて配信する流れになります。
BFFとの通信にはGraphQLを採用しています。間にCDNがあります。BFFとBEはgRPCで通信しています。Webに関してはTypeScriptで、BEはRustで書かれています。
フロントエンドのアーキテクチャはClient-Side Renderingで、UIのコンポーネントはAnt-Designを使っています。
AG Gridのようなライブラリを使って、大量の製品でもなるべく高速にレンダリングするような取り組みや、一括編集などの機能も対応できるよう工夫しています。
BFFはNest.jsなどを使っていて、コードファーストでGraphQLスキーマを生成できるようにしています。
リポジトリは、MonorepoでFEとBFFを管理していて、これはNest.jsで生成したGraphQLスキーマファイルを使って、ソースコードを自動生成しているためです。最近は、実験的にturborepoを採用しています。
まとめとして、Kleinはキャディの受発注を支えていて、BtoBの要件に答えるために、大量データをいかに早く画面で見ることができるか、レンダリングが快適だったり、一括登録ができるかなど工夫しています。
また、業務フローを一律に決めにくい点もあるので、それらに対応できるようシステムを作っています。
生産パートナー向け管理画面(小倉)
https://speakerdeck.com/caddi_eng/spp-feshao-jie
小倉:
パートナー様(製作会社)に使ってもらうのが、私が説明するパートナーポータルになっていますが、キャディからの見積もりに回答したり注文内容を確認するためのサービスになっています。
アーキテクチャは、Next.jsを使ったフレームワークですが、今回はデザインのところなので、フロントエンドでどうデザインを決めたのか?を説明していきたい。
(デモにて見積もり回答の様子を説明)
Kleinを通じて、この値段で大丈夫ですか?と打診があり回答をしていきますが、AG Gridを使って作っています。
詳細見たければ図面を見ることができ、値段がが問題なければokをしたり、違う値段を提案するのであればその金額を入力できたり。納期や、依頼を辞退をすることやエクセルで一括編集することもできます。
回答があると、Klein側に情報が反映されます。
例えば、納期が厳しいものから作ろうと考えてそれを選ぶと、納品先や値段・図面などを確認することができます。
一覧をエクセルやcsvの形でDLできたり、Ctrl+Cしたらコピーできるなど、エクセルとシームレスにつながるような仕様にしています。
製品名でも検索ができ、パートナー様がやるべきことが全部できるようになっています。
UI/UXデザインについて
コンセプトとしては、今までの作業フローに慣れている人・慣れていない人でも使いやすくすることが必要と考えました。
元々は、メールベースでやり取りをしていた工程なのですが、パートナーポータルを導入して移行してもらうために工夫が必要でした。
最初は全然使ってもらえなかったのですが、表計算ソフトと同じ操作性を実現するためにAG Gridを使って実装したところ、アプリの使用率が26%から90%へと急増しました。
それから、紙での見積もり体験と同じことができるようにも意識したのですが、パートナーポータル導入以前は、パートナー様は図面は印刷したものを見ながらパソコンの画面も見ていることが多かったようです。
パートナーポータルを導入すると、全てパソコン上で確認することになるのですが、大量にタブを開く状態になってしまい大変なことがわかりました。
そのため現在では、別ウィンドウで開くようにしたり、パートナー様は必ずしも広いモニターを持っているわけではないので、いろいろなコンポーネントを折りたためるようにもしています。
デザインのプロセスは、最初はUI/UXに強いデザイナーに専属でチームに入ってもらい、Figmaで紙芝居を作って、FEエンジニアと頻繁にMTGして各コンポーネントの意図を確認をしていました。
ある程度できあがってきたタイミングでは、デザイナーは専属ではなくなり、新しい機能を作るときにエンジニアである程度完成させないといけないので、Antdというコンポーネントライブラリに置き換えて、Miroというホワイドボードアプリを使ってラフなイメージを共有して開発をしています。
コーディングルールについて
最初は、style attributeを禁止しようとか色々あったのですが、現在はファイルサイズは200行未満にしよう、読めるファイルにしましょうという話にしたのが、ワークしているのでシンプルイズベストだなと思っています。
開発中の物流管理の管理画面(桐生)
桐生:
物流拠点プロダクトの話をさせていただきますが、拠点で使うプロダクトを絶賛開発中です。
Kleinで入力されたデータで、予定データをインプットして拠点で働く人たちに情報提供して、その後の作業に役立ててもらうものを作っています。
届いた製品がいつ来て、いつ出すのか?検査して出荷する作業がありますが、リーダーと作業担当者の2つを想定しています。
難しさとしては、物理を伴う難しさがあり、例えば予定を過ぎても届かないとか、個数が足りないとか検査でNGが出るなど、イレギュラーパターンが無数にあるので、それがある前提でオペレーションならびにソフトウェアプロダクトの設計が必要になります。
アーキテクチャやライブラリについて
FEとBEというレイヤー構成になっていてGraphQLでお互い通信しています。FEはNext.jsやChakura-ui・AntdなどのUIコンポーネントを、BEはNestJSを使っています。
ORMとしてはPrismaを使っていることや、GraphOLのクライアントライブラリとしてURQLというのを使っているのも特徴的です。
全体のリポジトリの構成ですが、Monorepoで管理していて、yarnのワークスペースを使っています。Kleinはyarn v1を使っているのですが、こちらはv3を使うようにしています。インストール速度が断然早いなと感じています。
また、nodeそのもののバージョン管理としてvoltaを使っています。自動でnodeインストールしてくれるので便利です。
FEはUIのコンポーネントとして、Chakra UIを使っていて、CSSを書くというよりはpropertyをセットするところ、バックエンドのメンバーにも受け入れられやすいですし、型の補完が効くので開発体験が良いですね。
Antdを使っている理由として、Chakura-uiはプリミティブなコンポーネントが多く、柔軟性は高いものの高機能なコンポーネントがないため、スクラッチで作るのは大変なのでAntdで補完しています。
URQLは、Apollo Clientと比較してシンプルで使いやすく、Bundle Sizeが1/3くらいなので推しのポイントになりますね。 React Suspenseのサポートや、唯一Offlineのサポートをしているところがいいです。
物流拠点で使うプロダクトになるので、ネットワークが切れるなどの可能性もあると想定すると、使えるものになるのではないかと考えています。
バックエンドは、Prismaを使っています。非常に開発体験がよく、prisma schemaを書くとデータベースのmigration codeと型付きprisma clientを自動生成してくれるので、強力な仕組みが備わっています。
あとは、GraphQLとの相性がよく、GraphQLはN+1問題を引き起こしやすいと言われていますが、それをケアする仕組みもそなわっています。
テストについては、StorybookのCSF3.0を使って、Storyを書くようになっています。2.0よりシンプルで、Storybookの定義をJestで再利用可能になったのは大きいと思っています。具体的には、@storybook/testing-reactというパッケージを使って、StoryをJestに取り込んで結合テストを行っています。
Mock Service Worker、これはAPIの Mocking libraryですが、ネットワークリクエストが発生するComponentも簡単にデータをMokingすることができます。
(ここからは実際の管理画面のVS Codeをご覧いただきながらデモ)
今後の展望
まずMonorepoについては、FEもBEのコードを一括で管理できるのはありがたいのですが、ビルド時間が長くなりがちです。
社内の他のプロダクトで、circleci/path-filteringを使って、差分ビルドを実現しているので、こちらのプロダクトでも使いたいなと考えています。
Testingのところでは、結合テストはStorybookに集約していきたいと思っているのですが、interaction testingでは、現在はCI実行ができずJestを使っている状況です。
それがCIで実行できるようになるというissueもあり、それを期待して今後はStorybookで完結できるのではないかなと期待をしています。
最後に
いかがでしたでしょうか?
先山・小倉・桐生など、キャディのフロントエンドエンジニアともっと話を聞いてみたい!という方は、こちらより申し込んでいただけますと幸いです。
また、イベントに関する情報は、キャディのconnpassがありますので、こちらも登録いただけると嬉しいです。
最後までお読みいただきまして、ありがとうございます。