とあるPJの立て直し: 品質をあげるために

Reading time: 約7分
Publish date: 2020-01-03
Tags: development, turnaround, project management, architecture, quality, cloud, database, coding

 とあるプロジェクトの立て直しの記録に基づいて、プロジェクトマネジメントをテーマにシリーズで書き残したいと思います。今回は品質を上げるために行ったことについて触れます。

要旨


主な品質の課題

 本プロジェクトで顕在化していた品質の課題は設計の段階から発生していました。アーキテクチャそのものを見直さなければ改善しないものがほとんどです。

 それぞれ個別に対応する必要があります。


クラウド設計の課題

 今回はクラウドを用いたシステム開発を行っていました。しかし、クラウドを使用したことのない人が初期設計したと推測され、クラウドのよさを活かせていませんでした。例えば、クラウドの特徴の一つにスケーリングメリットがあげられますが、スケーリングできる部分とできない部分があります。この点を理解せずに、すべてリソースパワーに頼る前提となっていたため、すぐに制約に引っかかることが明らかでした。

 クラウドだからと無尽蔵にリソースがあるわけではなく、あらゆるサービスで制約を持ちます。確かに上限値を引き上げることができる側面もありますが、上限値の引き上げは十分に稼働しスケーリングの必要性が出てきたときに行うものです。まずは制約を理解して制約の中で正しく動作するように設計すべきです。クラウドだからとリソースパワーに頼る前提の設計は早々に破綻しますので、注意しましょう。

 また、サーバーを自前で持たないサーバーレスアーキテクチャもクラウドならではの特徴の一つです。例えば、リアルタイム性や応答速度をそれほど求められず、べき等性の高い処理などでは利便性が高まります。他方で、大きなデータを取り扱ったり、時間の掛かる処理には適していません。要件に合致しているかは慎重に判断して採用しましょう。

 クラウド設計の課題は設計者のスキルアップが必要です。


データベース設計の課題

 データベースはシステムの中心に位置するものです。データベースの設計がなされていない点は品質を大きく下げている要因となっていました。

 1点目は通常起こりえないと思いますので補足しておきますと、元々Key-Valueペアで情報を取り扱う前提で設計していたためNoSQLの構造でデータをもっていました。ところが、ユーザーと紐付く1:1のデータを取り扱うよりも、横断的に情報を取得する管理システムに近い性質であったため、「ユーザー自身の情報は取得しやすいが、横断的な情報の取得がしづらい」という問題に早々にぶつかっていました。私が引き継いだ時点で、この「NoSQLをRDBに置き換えるところまで終えました」という不思議な状態で、なぜそうなったのかという議論の余地もありませんでした。

 2点目は前述の流れを引きずっているのですが、関係データベースに置き換える作業をNoSQLのスキーマのまま行っていました。NoSQLのベストプラクティスとRDBのベストプラクティスは異なります。必ず再設計が必要になりますが、RDBに向けたデータベース設計を行わずにデータベース形式だけを移行させたことが問題です。正規化されていないRDBはパフォーマンスやデータの管理に様々な問題を引き起こします

 3点目はそもそものデータの使い方の問題ですが、全件データを常にフロントエンドに取得して処理する思想になっていたため、データ量が増えると急激にパフォーマンスが低下する状態にありました。100MBのデータを一回のAPI呼び出しで取得しようとする挙動は初めて見ました。ページネーションやLIMITを活用して必要な情報を必要な範囲で取得するように考え直す必要があります。

 データベース設計の課題は設計者、開発メンバーのスキルアップが必要です。


コーディングの課題

 このときは、プログラミング言語としてPythonとJavaScriptが採用されていました。どちらにも言えることですがスクリプト言語であるため、C++やJavaのようなオブジェクト指向でコンパイラ型の言語に比べて、品質の担保がより難しい言語です。初期実装の容易性はありますが、実働環境としての堅牢性の担保にはより一層の注意が必要です。

 テストケースがゼロでないことはよかったですが、1APIにつき正常系の1ケースのみのため、値のバリエーションをちょっと変えるとうまく動かない箇所が多くありました。仕様が不明でテストケースがない箇所ではどのような振る舞いが正解なのかわからないため、そこから考え直す必要がありました。エラーケースのテストがないため、実装にもエラーケースを考慮した部分がありません。アプリケーションエラーなのか、予期せぬエラーなのか判別できません。

 型の重要性については機会があれば別の記事として触れたいと思いますが、品質の担保を容易にしてくれる重要な概念です。

 最後の2点はパフォーマンスに関わる課題です。ループが5重になっていたり、必要のないデータまで取得して処理するため、少量のデータにもかかわらず長時間待たされるような実装が散見されました。

 コーディングの課題は開発メンバーのスキルアップが必要です。


アーキテクチャ設計の課題

 ここまでの前述の問題も広くはアーキテクチャ設計の課題ですが、これら以外の側面でもアーキテクチャ上の課題がありました。

 引き継ぎ段階でアーキテクチャ図が存在しなかったため、アーキテクチャ図を起こしながら全体像を把握する作業を行いました。結果的には内容の把握と課題の把握を同時に効率的に行えました。要件定義書や設計に掛かるドキュメントがないため、どのような振る舞いが正解なのかわからない状況でした。これについては、分かる範囲でくみ取りつつ、もう一度顧客と調整し前進することを選択しました。

 「うまく動かないのにエラーがでていない」という状況に度々出くわしました。驚くことにエラーを補足し握りつぶしている処理が入っていたのです。これはさすがに想定外で予見できませんでした。これでは自分たち自身もデバッグができません。このような箇所を特定し、エラーが出るようにすると大量のエラーが出力されるようになりました。エラーを握りつぶしてもエラーがなくなるわけではありません。絶対にやってはいけません。すべてのエラーに正面から対応しました。

 アーキテクチャ設計の課題は設計者のスキルアップが必要です。

 品質を上げるために最も重要だった要素は、開発を一時停止し技術的負債の解消に注力することでした。前述のように課題が明らかになり対応方法が見えていても対応ができなければ画に描いた餅です。顧客との合意が不可欠です。次回は顧客との関係性について触れたいと思います。