某社の某ソリューションの某SDKがクソ過ぎて吐き気がする件

特定されるので某しか言えないんだけど、本当クズ。これほどまでのウンコ製品は久しぶりに見たので愚痴を書いてみる。

この製品は、いわゆるデジタルペンとか言われるものの一種だ。ぺんてるに「デジタルペン」という商品があるが、それとは関係ない。関係ないが、同種の製品である。専用のペンで書いたストロークをベクタフォーマットで取り出したり、文字認識した結果として取得できるというもので、ハードウェアと一緒になって売られているソフトウェアソリューション。

SDKを公開することで、既存の社内システムにも組み込めますよ、というのが売りだが、はっきり言ってこんなクソレベルのSDKで金を取ろうという発想自体がおこがましい。内容は専門学校生が作ったのか?ってレベルで、曲がりなりにも一部上場企業が作っていいようなもんではない。

このメーカーは、元々は別の分野でかなりのシェアを持っており、商品名が固有名詞になっていたこともあるような立派な製品を作っている。今も立派な会社であることは間違いないが、それゆえ、その名前に泥を塗る最低な製品だと思う。以下に問題点を列挙する。

CSVファイルに頼りきったインタフェース仕様

SDKで使用するほとんどのデータを、CSV形式ファイルでやりとりしなければならない。したがって、一時フォルダなどの一時CSVファイルを作成して、それのパスを引数として渡すような処理をたくさん書かなければならない。

ファイルに落とすということはそれだけでパフォーマンスを大幅に劣化させる。あらゆるプログラムのボトルネックはほとんどの場合、IOである。特にビジネス用途に限ればほぼ100%と言っていいだろう。ディスクアクセス、ネットワークアクセス、DB問い合わせ、すべてIOである。

したがって、わざわざパフォーマンスを悪化させるような手段をユーザー(SDKを使う人達)に強制させるのがまずクソ。言い訳できないクソ。

さらにCSVなんてのは、クソに輪をかけたクソで、データ構造の中では最もライブラリが充実していないことに加えて、単純な構造しか表現できない、使うことになんのメリットもないウンコフォーマットなのである。

せめてテキストデータでのやりとりをさせるのであれば、ましてやターゲット言語がC#であるならば、XMLフォーマットにすべきであっただろう。C#にはXMLパーサは標準で組み込まれているが、CSVパーサはない。というか、ほとんどの言語でCSVパーサなんか無い。なぜか。CSVが優れている場面というのは手軽に表計算ソフト向けデータ、もうちょっと譲ってRDBMS系のデータを作れるというあたり「のみ」に限られるからだ。CSVは複雑な構造を持てない上、パーサを作るのも結構面倒である。簡単じゃん、と思った人はちょっと想像して欲しい。内部データに改行やカンマを含まれる場合をも考慮しなければならないのである。

もし彼らが、扱いやすいと思ってアプリケーション間のインタフェースにCSVを採用したのであれば、それだけでプロのレベルに達していないくせに金を取ろうとする不届き者であるということが分かるし、もしそういうつもりが無いのであれば、猛省してインタフェース改善に全力で取り組むべきである。何故ならば、このインタフェースは「プログラマ向け」に公開しているのだ。表計算向けではない。その意味をよく理解してほしい。

CSVファイルの書き出し先がありえない

で、そのCSVファイルの出力方法なんだが、ディレクトリパスを指定してCSVを出力させると、UUID(MicrosotのGUID実装)がファイル名になる。さらに、そのファイルはオブジェクトを表す名前のディレクトリの下に置かれる。

こんなもん、出力したCSVファイルをどうやって読むんだ?と思い、彼らが書いたサンプルプログラムを読むと、なんと、ファイルシステムのディレクトリエントリを読み、"*.csv"ファイルを検索していた。

自分で適当な名前を付けたくせに、名前がわからないからとファイルを検索するのである。なんでこんな実装になっているのだろうか?この人達は頭大丈夫なんだろうか?

XMLドキュメントコメントが無い

ターゲット言語はC#である。対応しているIDEはVisualStudioですとマニュアルに明記されている。なのにXMLドキュメントコメントが無いというのはどういうことだろう。

XMLドキュメントコメント、もしくは、XML Documentationというのは、JavaでいうJavadocみたいなものである。こういう仕組みは、ライブラリやユーティリティーの追加によって利用できるものも含めれば、いまやありとあらゆる言語で導入されていると言って良い。その理由は明らかで、便利だからである。誰がどういうふうに使っても便利だからである。

XMLドキュメントコメントがついていれば、IDE上で説明を自動的に表示し、そのクラスをどのように使えばよいのか、プログラミングしながら理解することが出来る。これは素晴らしいことである。ちゃんと作れば、そもそもAPIマニュアルがほとんど不要なレベルまで持っていける。

彼らはこのSDKを開発している最中、IntelliSenseで説明が出たら便利だな、と一度も思わなかったのだろうか?思わなかったとすれば、彼らの目は節穴であり、全く向上心のない単純作業者エンジニアと言っていい。

APIマニュアルがクソである

先に、IDE(VisualStudioのInteliSense)で使い方が出ないのでウンコ、ということを書いたが、そういう背景があるのでAPIマニュアルを参照しなければならない頻度が高い。

しかしこのマニュアルもクソである。そもそも、SDKをうたっているくせにXMLドキュメントコメントすら書けないようなウンコ共に、まともなマニュアルが書けるわけがないのである。

どのような内容になっているかというと、docomoのガラケーの取説を想像していただくと良いかと思う。あんな感じで、基本的にプログラムを知らないような人たち向けに書いかのような構成になっている。具体的には、「データをインポートしたい場合」「データXを使ってデータYを含むデータを検索したい場合」などといった章立てになっていて、そこからやりたい事を見つける、という感じの使い方をしなければならない。

普通、APIドキュメントというと、すべてのクラスと公開メソッドが列挙されていて、それぞれが何をしているかを説明するような内容になっている。そして、それをリファレンスマニュアルとして使うことで、最小限の時間で使い方を覚える、もっと言うと、クラスやメソッドの名前と構成から、設計思想が理解でき、自然と予想できるようなものがベストだ。

このマニュアルにも、すべてのクラスと公開メソッドが列挙されているような章がある。しかし、それを見てもさっぱり意味がわからない。例えば、GetDocumentというメソッドにIList<DocData>という型の引数があったとして、この説明がどうなっているかというと、

「DocDataのリスト」

としか書いてないのである。アホか。これはなんの情報量もない。IList<DocData>であれば、DocData型のリストであることは、自明なのである。書かなくても分かるのである。そうじゃなくて、我々はDocDataとは何で、ここに指定した引数がどのような影響をおよぼすのかを知りたいのである。

だから、今度はDocDataを調べてみる。すると、DocDataとはEnumであって、TitleとかFieldとかの値が定義されていると書いている。それだけである。結局、当初の疑問は解決できず、使い方を調べるために実験的なコードを書くはめになるのである。

良いSDKであれば、名前だけでプログラマがある程度のことを数秒で予想してしまうような場面を、このマニュアルは数百倍のオーダーの時間をかけ、結局疑問が解消されないのである。

更にムカつくのが、PDFファイル内のテキストをクリップボードにコピーすることを禁じる設定にしてあることだ。お前らのマニュアルの作りが悪くてわからないからドキュメント内検索をかけようとしているのに、さらに非効率な方法を取らせるとは一体どういう了見なのか、3時間位尋問したい。

もしこのコピーを禁じる設定にしてある理由が、「不正利用を防ぐため」とかいうものであるならば、そもそも、人間が利用できるレベルのものを作ってからにしていただきたい。

すべての公開メソッドがAPIという名前のクラスにまとまっている

冗談だろ、と思った。正確にはXYZApiFactoryみたいな名前のクラスが、APIという名前のインタフェースを生成することになっているのだが、XYZApiFactoryでAPIの実装オブジェクトを生成するのは引数なしのstaticメソッドなので、実質Singletonパターンになっているのだろう。全然ファクトリクラスじゃない。

こういうことになっているので、それぞれのメソッドの引数が多い。よく使うメソッドでも4~5個の引数を指定させられる。これはコードの可読性を大幅に損なう。

オブジェクト指向設計になってない

そもそも、ひとつのクラスにすべてのAPIインタフェースを集約するというのはそもそもオブジェクト指向的な設計になっていないのである。オブジェクト指向言語を使ってSDKを作ったのであれば、オブジェクト指向言語的な作りで設計して欲しいものである。これが数人のグループで保守する社内システムであるならまだしも、一応金を取って社外に売り出し、大勢の人が使うことになるSDKなのだから、少なくとも「普通」の、つまりオブジェクト指向的な設計をすべきである。

他にも設計がおかしいところは多々あって、ただのstringデータをラップしただけで、なんのメソッドも公開しないような存在意義の分からないクラスがたくさんある。本当に苦痛なのが、そういう意味不明なクラスをよく使うコードで多用しなければならないことである。

たとえば、「文書」と「文書フォーマット」というクラスがある。システムの中からある文書を参照したい時はBunsyoIDというクラスがあって、それを指定してGetBunsyoメソッドを呼び出せと書いている。しかし、そもそもBunsyoIDが何か分からない。コンストラクタはprivateなのでどこかで生成するものだということがわかるが、それをどのようにして得たらいいのかわからない。やっと、FindBunsyoというメソッドでBunsyoIDを知ることができるというのがわかるが、今度はFindBunsyo関数がBunsyoPathという意味不明な引数を要求する。そうすると今度はBunsyoPathが何か調べなければならない。

こういうことを繰り返し、そもそも何がしたかったのかを忘れた頃になって、ようやくBunsyoIDを得ることができたとしよう。実装したとしよう。実際実行してみると、FindBunsyoメソッドの戻り値はBaseIDとかいう型になっていて、BaseIDはBunsyoIDクラスとBunsyoFormatIDクラスの基底クラスとなっている。で、実際使うときにはこれがBunsyoIDクラスのインスタンスであるという確証を持てないままBaseIDをBunsyoIDに恐る恐るキャストするはめになるのである。

はっきり言って、そもそもIDとかいうクラスが出てくる時点でオブジェクト指向になっていない。「文書」と「文書フォーマット」という概念がシステム上に存在するならば、「文書」「文書フォーマット」をクラスとして定義するべきである。

それらを識別するために必要なBunsyoIDなんてのは、使う側からしたら知ったこっちゃないので、内部に隠蔽して見えないようにすべきだ。それなのに、このSDKではIDクラスを「文書」「文書フォーマット」という概念と等価に扱ってしまっている。自分らの内部事情をさらけ出してユーザーに使うことを強要させる。本当図々しいクソババアみたいなSDKである。

スペルミスがある

根本的にクソ。属性をAtterbutesとか書いてた。そもそもプログラミング以前、一般教養の問題である。

ネーミングセンスもクソ

「Update」とかいうプロパティがあった。これがアップデートされたかどうかを示すフラグなのか、アップデート可能かどうかを示すフラグなのか、何なのかさっぱりわからない。そもそもプロパティという、値を示す名前に動詞を使っていること自体がおかしい。

例えば、これが「CanUpdate」とか「Updatable」であればアップデート可能かどうかを示すフラグであることが一発で分る。
例えば、これが「Updated」であればアップデートされたかどうかを示すフラグであることが一発で分る。
例えば、これが「UpdatedDate」であればアップデートされた日付であることが一発で分る。
例えば、これが「UpdatedTime」であればアップデートされた時刻(おそらく日付時刻)であることが一発で分る。

しかし、実際は「Update」。馬鹿なのだろうか。

戻り値がIList<>

強いて言えば、という感じだが、Listである必要性を持たない戻り値に対して、IList<>インタフェースで定義するのはおかしいと思う。単純に列挙するだけであればIEnumerable<>にすべきではないだろうか。

おそらく、List<>型のオブジェクトを返しているからであることが理由だろう。無闇やたらに高等なことをするインスタンスを使うのはパフォーマンスの面でよろしくない。将来的に内部実装を変えたい時にも、縛りになる可能性がある。もっとも、そこまで考慮できるような開発者であればこんなSDKを開発していないだろうが。

同じ名前のクラスが別のインポート必須なアセンブリに定義してある

VisualStudioで名前解決しようとすると、2つの候補が出てくる。これを作った人たちはこれを見ておかしいと思わなかったのだろうか。思わなかったのでしょうな。あはは。

ArrayIndexOutofExceptionとかを投げてくる

時々、ArrayIndexOutofExceptionなどを投げてくる馬鹿がいる。デバッガ上に表示されるメッセージは、「要素nは配列の範囲外です」みたいになっていて、明らかに引数チェックをサボっていることが伺える。たぶん、添字を即値で指定したり、妙な添字の計算をしているのだろう。

C#で普通に作っていれば、そもそも添字で操作することすらほとんど無いはずだ。彼らはC#でC言語プログラミングしているのだろう。もはや何も言うまい。

例外に含まれている情報が皆無

よくInvalidArgumentExceptionなどという例外が送出されるのだけど、じゃあ具体的にどの引数が想定した値とは違ってどうなっているのかという情報が何もない。InvalidArgumentExceptionというクラスの名前からは想像しようがない。これが引数の数が1つや2つならまだしも、先に述べたように、ほとんどのメソッドで引数を4個も5個もあるのである。しかも、その引数の型はIListだったりするのである。

なぜエラーチェックするコードを書いておきながら、説明を記載しなかったのだろうか?まさか、「4~5個の引数のうち、どれかに誤りがあります!」って、クイズ番組のつもりなのだろうか?俺が回答者なら司会者にドロップキックするね。

結論

みなさんにとっては、訳のわからぬ某製品などというものに対して、ウンコだとかウンコだとか、ウンコ様だとかウンチだとか貶してるわけのわからない記事だったと思うが、まあ、はっきり言わせてもらうと、このSDKはれっきとしたゲロである。とにかく、飲み屋の店員が、仕事柄、絶対やりたくないけど仕事なのでしょうがなくゲロ掃除する、などの場面に見られるような、極力触れたくないものであることは間違いない。

私に選択権があるならばこれを拒否することもできただろう。でもないのでどうしようもない。いや、しかし、これがどれだけ糞かを誰かにフィードバックして、何らかのアクションを起こすのが建設的なのかもしれない。それでもなお私はゲロをゲロだと指摘してゲロ掃除したり、ゲロからウンコを作るようなバカバカしいことを進んでやるほど人間ができていない。なので放置して、早く通りすぎるのを待つだけである。私はひたすら、今夜の営業が終わるのを待ちながら、調子こいた大学生が放射したゲロを掃除する飲み屋の店員、フリーター30代間近なのである。