Chatwork Creator's Note

ビジネスチャット「Chatwork」のエンジニアとデザイナーのブログです。

ビジネスチャット「Chatwork」のエンジニアとデザイナーのブログです。

読者になる

Chatworkに入社してから3ヶ月の間に感じたこと

この記事は Chatwork AdventCalendar 2021 10 日目の記事です。

qiita.com


8 月から Chatwork のフロントエンド開発部にjoinさせて頂きました、林 です。

元々 SES として様々な顧客の管理系 Web アプリなどをサーバーサイド、フロントエンド一気通貫で実装などしていた人間で、 自社開発したい!フロントエンドをもっと深掘りしたい!と考えていた際にご縁があって拾って頂きました。

社名は聞いたことがあり、サーバーサイドがモダンな感じ・社員のアウトプットも活発。 所謂「イケイケな会社」というイメージでしたが、入社して蓋を開けてみたらフロントエンドもチャレンジングなことをしており、 ギャップに驚いたのが正直なところです。(イケイケな会社であることは変わりなかった。)

このまま会社の雰囲気、アピールポイントを記事にするでも良かったのですが、 同じような内容の記事は過去に別の方が触れていたりしていると思いますので、 今回は3カ月の中でつらいと感じた出来事と 「じゃぁ、どうするの?」 と言った今後のお話しをさせていただきます。

つらいこと

コードの迷宮

サービスが開始して10年経つプロダクトと言うこともありコード量が半端なく多いです! 聞いたところフロントエンドだけでも15万行ほどのプロダクトになっているとのこと。
なおかつ、その全てがモダンなアーキテクチャのイケイケな実装というわけではありません。

大きく三世代に分かれたアーキテクチャのコードが複雑に織り重なっており、 その全貌を知る人はいないとされています・・・*1

私も入社直後のオンボーディングでは、コンポーネント一つ表示させることにも苦労しました。

今でも不具合やご意見ご要望の内容を見た際に 「この辺りかな?」 と言った勘所が上手く働かないことが多いです。
積み重ねてきた経験値が今に直結せず、結構なつらみを感じます。

じゃあ、どうするの?

1にも2にもプロダクトに慣れるしかないと言うのが本音です。

入社して、ありとあらゆる情報をキャッチアップしながら、いち早くバリューを提供する。
理想ではありますが誰もが出来るとは言い難いですね。
ならば、出来ることは会社とそのプロダクトに早く慣れることだと思います。

幸いにも弊社ではモブプロ, 社内勉強会, 1on1 や朝会後の相談時間(別名: 二次会)など、 現場にいち早く慣れる・溶け込める環境が整っており、メンターやMGR,同僚の皆さんに 同期・非同期問わずいつでも相談できる状態になっています。

特にモブプロは開発部チャットで一言書けば、よほど間が悪くない限り誰かが「どしたん?話聞こか?」と寄り添って来てくれて、そのままモブプロが始まることも多いです。

プロダクトの資料に関しても全てではないですが、各機能の仕様書や「なぜこの仕様になったのか?」と言う意思決定の履歴を記した資料(ADR)などもドキュメント化されており、 開発者は誰でもそれらを参照できるので、 問題に直面 → 資料から自己解決 となることも少なくありません。

こう言った環境に身を置きながら、現在もコードの迷宮を日々探索し、 織り重なったコードをメンバー全員で一枚一枚解しながらプロダクトを前に進めています。


null参照

Chatwork のフロントエンドは全てがモダンな実装というわけではなく、過去の実装を継ぎ接ぎ改修しながら成長してきたプロダクトです。

JavaScriptの実装のままで型定義が無かったり、DOMをJQueryで操作しているコードもまだまだ存在しています。(JQueryJavaScriptでの実装は古いからだめ!悪!と言うわけではないですが、ずっと旧実装に依存するわけにもいかない)

そう言った昔のコードを読みすすめ・改修する上で、個人的につらいと感じるのは、 「nullである可能性がある」変数を参照し&それに気付けない時です。

近年ではtsconfigの設定やeslintなどでnull参照の恐れがあるものを事前に検知できたり、 ビルド時に失敗するようにしたりと様々な対策を行なってはいるのですが、 旧実装の全てに対して、nullでない状態にするのはかなりの労力が必要となります。

そのため@ts-expect-errorを用いて、問題を握りつぶしてビルドを通しているコードもあり、 そう言ったコードを見かけるたびに 「つらい、、、早く無くしたい」 と感じています。

じゃあ、どうするの?

「駆逐してやる!!この世から・・・一匹残らず!!」は些か苛烈な表現ですが、 こちらの問題も順を追ってひとつひとつ潰して行くしかないと思っています。 プログラムの世界には奇跡も魔法もないのです。

基本的には担当するチケットの対応の中で、null参照を行なっているコードに出会った時に併せて、以下の様にリファクタしています。 (コード内容はイメージです。)

  • ifによるnullチェック(早期リターン)
    • みなさんお馴染みnullチェック。
  // ユーザーの部署情報を返す、なければnull
  const nullAbleDepartment = getDepartmentOrNull(userId); 
  if (nullAbleDepartment === null) {
    return null;
  }
  // 早期リターンに引っかからないと言うことは null ではない。
  consolt.log(nullAbleDepartment.getName());
  • assertion functionsによるnull許容型の型推論
    • assertion functionを用いてnullの場合に例外を送出することで、呼び出し以降のコードでは型が推論できるようになります。
      紹介はしていますが、実際はまだ検討段階です。
  function assertIsDefined<T>(value: T) assert value is NonNullable<T> {
    if (value === null || value === undefined) {
      throws new Error('error value is ${value}');
    }
  }

  function hoge() {
    // ユーザーの部署情報を返す、なければnull
    const nullAbleDepartment = getDepartmentOrNull(userId); 
    asseIsDefined(nullAbleDepartment);
    // asserIsDefinedで例外が送出されていないので後続処理では、渡した値がnullではないことが保証されている。
    consolt.log(nullAbleDepartment.getName());
  }
  • 旧実装を新実装にしてしまう
    • これはまだ自分はできていないのですが、全部新品にして諸々の問題なくそうよってムーブだと思います。
      旧実装が見つかり次第なくなっていく事になるので、これが出来る様になりたい。

assertion functionはぜひ利用したい仕組みではあるのですが、 フロントエンドで頻繁にErrorを飛ばされて後続の描画が止まってしまうとユーザー体験を損なうことにもなりかねない為、 例外時にどう振る舞うかの考慮が必要になります。

それでも早期リターンよりもスマートに記述できる点は魅力的なので、利用できる場面では積極的に利用してnull参照におけるつらみを軽減していきたいと思っています。

こう言ったリファクタリングで出てきた課題もチームで共有して、対応方針への合意を得ながら進めることが出来るので、 一人で課題を発見して孤独に数時間悩むなどもありません。


まとめ

  • 新旧入り乱れた巨大なプロダクトコードにもなるべく早く慣れることが出来る環境が整ってるよ。
  • 旧実装の負債はあるけれど、それを解消できるように常日頃からコードのメンテナンスを行なっているよ。

と言うことで、次の方にバトンを回したいと思います。

*1:ここら辺の内容に興味がある方は、ぜひ JSConf2021 で登壇した弊社フロントエンド開発部マネージャーのスライドをご覧いただけると。