読者です 読者をやめる 読者になる 読者になる

アーキテクチャをスマートに。

株式会社ネオジニア代表。ITアーキテクトとしてのお仕事や考えていることなどをたまに綴っています。(記事の内容は個人の見解に基づくものであり、所属組織を代表するものではありません)

共通ライブラリを使いましょう

考え方 プログラミング

今回も実際の開発現場での体験談です。

それは携帯電話向けのシステムの開発プロジェクトでした。
僕はそのプロジェクトに製造工程の途中から引継ぎで入りました。

システムの一部分として、Webアプリで電話帳やメール機能を実現している箇所があり、その部分が自分の担当でした。
それらのWeb機能は簡易的なもので、PHPを使ったCGI的な感じのシンプルなプログラムが数本程度でした。

ひととおりのコーディングがすでに終わっており、結合試験に入ったところでした。

毎日いくつかの不具合が上がってきて、それらを対応していくという日々が始まりました。

そしてある日、とんでもないものを見つけてしまったのです。

とんでもない力作プログラム

試験担当者から、メール機能に関していくつもの不具合と、問い合わせが入ってきました。

問い合わせの内容は、「WebメールがHTMLメールだったらどうなるか」というようなものでした。

システムの仕様としては、テキスト形式のメールしかサポートしないことになっているので、当然HTMLメールが来たとしてもテキスト化して表示するか、エラー表示するか、そんな挙動だろうと思いながら、ソースコードを見てみると。。。

なんと。メールを取得するプログラムがとんでもないことになっていたのです。

PHPで書かれていたそのプログラムは、メールサーバからメールを取得するのに、サーバに対して直接TCPソケットを接続し、POPプロトコルを一つ一つ送信しては応答を解析し、メールデータを取り出していたのです。

そして取り出したメールデータを自力で解析し、件名や差出人と本文をさらに取り出す、ということをやっていたのです。

かなりの力作プログラムだな〜と思ってコードを追いかけていくうち、感心している場合ではなくなってきました。

「これはヤバイ!」

何がヤバイのか。

その力作プログラムは、POPプロトコルの会話制御はまだしも、メールデータの解析処理が全然ちゃんと出来ていなかったのです。

まずマルチパートが考慮されておらず、決め打ちでデータを取り出しているため、HTML形式や添付ファイルなど複雑な構造のメールに対応できていませんでした。
次にエンコーディングの対応が不十分で、Subject(件名)や本文のデコードを JISコード決め打ちでデコードしているため、それ以外の文字コードが来た場合には文字化けします。
他にもいろいろ問題があり、とにかく全然ダメでした。

このプログラムを修正し続けていっても、不具合の温床になるだけ。抜本的な対策が必要です。

というのも、メールデータの解析はかなり複雑なものです。
メールヘッダの解析から、マルチパート形式の取り出し(添付ファイルやHTMLメール)、MIME形式によるデータ種別の判定(HTMLかテキストか画像かなど)、エンコーディング処理など、かなり多くのことを考慮しないといけません。
※POPの仕様はRFC2821、インターネットメールの仕様はRFC2822 にて策定されており、厳密に対応するならばこれらの仕様に従って実装する必要がある。

これをちゃんと実装しようと思えば、めちゃめちゃ大変です。
それだけでひとつのライブラリが出来上がるぐらいです。

ライブラリ?

そうです。

大抵の場合、メールを処理するライブラリが提供されているものです。
PHPの場合も例外にあらず。

IMAPライブラリを使えば簡単にメールサーバから希望のデータを取り出せるのです。
TCPソケットを接続してプロトコルを投げて自力で会話する必要もありません。
メールデータの解析も、ライブラリが一手に引き受けてくれます。
様々な形式のメールに対応しているので、HTMLでもSJISでもQuoted-Printableでも何でもOK。
しかもPOPからIMAPに切り替えることでメールボックスの管理も簡単になり、一石二鳥どころか一石三鳥、いやもっとです。

ライブラリを使おう

僕はすぐにこの力作プログラムを捨てることを決断し、PHP標準のIMAPライブラリを使って書き直すべく、設計見直しを提案しました。

それからコーディングにとりかかり、1日ほどで新しいメールアクセスプログラムを書き上げ、単体テストをパスしてソースコードをコミットしました。
と言ってもIMAPライブラリを呼び出すだけなので、何も難しいことはありません。
コード量も前の4分の1ほどに減りました。

この対応によって、メール関連の不具合はすべて解消し、処理速度も少し向上しました。

全くご苦労様です

今回の件は小規模なプロジェクトだったので、少しの手戻りで済みましたが、
大規模なプロジェクトになるとそうはいきません。

設計工程で手を抜いたつもりが、あとの工程では逆に工数が膨らんでしまうのです。

短絡的に設計してしまう前に、ちょっと考えれば防げたはずです。

「メールの処理をするのは大変だが、いろいろなシステムで行われているはずなので、何か共通ライブラリぐらいあってもよさそうだけど」みたいに思って調査していれば、すぐにわかったはずです。

教訓

よくある処理は、すでに実装されているものがないか調べましょう。
自力でやろうとする前に共通化された部品がないか探しましょう。