圧縮・解凍ソフト CubeICE をゼロから改修

気付けば数年ぶりの更新となってしまいました。私は、普段 キューブ・ソフト (CubeSoft) と言う会社で様々な Windows ソフトウェアを開発・公開していますが、その一つに CubeICE と言うファイルの圧縮・解凍(展開)を行うソフトウェアがあります。今回、この CubeICE に対して 6 月~ 8 月にかけてゼロから書き直す大改修を行ったので、その記録として何かを書きたいと思い、久々にブログを執筆しています。

なぜ CubeICE をゼロから書き直したのか?

CubeICE は、7-Zip と言う圧縮・解凍ソフトウェアのライブラリ部分を修正して日本語の文字コード推測・変換処理を追加し、そのライブラリを利用した GUI アプリケーションとともに公開しているソフトウェアです。

CubeICE メイン画面

2011 年に最初のバージョンを公開して以降、Zip ファイルを Windows、Mac 間でやり取りするユーザを中心に、文字化けが発生しにくいと言う一定の評価を頂いていました。また、圧縮ファイルにマウスカーソルを合わせるとファイルの一覧を確認できるシェル拡張機能なども好評で、現在でも多くのユーザにご利用頂いています。この CubeICE ですが、公開からしばらく経った段階で私の方でもいくつかの問題点を把握しており、その中でも大きな問題は以下の 2 点でした。

  • ボタンのクリック等、GUI の反応に大きな問題が存在する
  • ファイル数の多い圧縮ファイルを解凍する際、非常に長い時間を要する

これらはともに GUI プログラミングや 7-Zip を利用する上での(初期開発当時の)私の知識不足が原因で発生したものですが、ソフトウェアの根幹部分に存在する問題であった事もあり改修に多くの時間を要する事が予想されたため、長らく保留事項となっていました。しかし、現在でも引き続き多くのユーザにご利用頂いており、何とかしたいと言う気持ちは強くありました。また、「7-Zip」v16.00には危険な脆弱性の修正も。「PeaZip」にもアップデートが提供される - 窓の杜 などを始めとして、ここ 1, 2 年、圧縮・解凍ソフトウェア(ライブラリ)に脆弱性が見つかり、修正バージョンがリリースされる頻度が高まっている傾向が伺えます。そうした緊急度の高い修正に対して素早く追随するための開発体制を整えると言う意味でも、改修の必要性を強く感じていたため、今年の大きなテーマの一つとして、CubeICE にあるこれらの問題の根本的な解決を図るべく、ゼロから書き直す事を決定しました。

CubeICE 改修の概要

改修に際しての一番大きな決断はプログラミング言語を C++ から C# に変更する事でした。

CubeICE は当初 C++ と Win32 API のみで開発されていました。これは、開発開始当時においては、一般ユーザの .NET Framework に対するネガティブな印象がまだ完全には払拭されたとは言えないのではないかと言う判断によるものでしたが、その後の保守作業の大変さを生んだ要因の一つともなりました。2017 年時点においては、さすがにもう .NET Framework も広く認知されたと見なして良いだろう事と、GUI の非同期処理をまともに実装するにあたり、他はともかく async/await と呼ばれる機能だけはどうしても利用したいと言う個人的な思いから、この決断に至りました。その甲斐もあって、GUI の反応の悪さに関しては問題ないレベルまで改善できたと思います。

もう一つの課題は 7-Zip との連携に関する部分で、具体的には COM インターフェースから 7-Zip ライブラリ (7z.dll) を利用する方法の改修となります。従来の CubeICE では 7-Zip との連携に不完全な部分があり、これが「多数のファイルを含む圧縮ファイル」を解凍する際に処理時間が異常に長くなってしまう現象の原因でした。7-Zip との連携に関しては、随分昔に @rofi に詳細を調べてもらっていたのですが、前述したような都合で実際には活用されないまま時間が過ぎてしまいました。今回、当時の調査結果等も参考にしながら、ようやく該当部分の実装を終える事ができたので、この場を借りて御礼申し上げます。

尚、修正効果については、CubeICE 0.8.0β のリリースノート でも触れましたが、サンプルケースとしてハードディスク上(not SSD)で「59,763 個のファイルを持つ 135MB の Zip ファイル (boost_1_64_0.zip)」を解凍したところ、CubeICE 0.7.3β では約 35 分かかっていたのが、0.8.0βでは約 7 分まで改善しました。Windows 標準の展開機能を含めていくつか比較してみましたが、少なくとも CubeICE だけが特別遅いと言う現象は解決できたのではないかと思います。

まともな開発および保守環境の構築

今回ゼロから書き直すに当たり、ソフトウェアのバージョンアップと言う最終目的とは別に、開発中に設定したテーマとしてまともな開発および保守環境を構築すると言うものがありました。具体的には、以下のような項目となります。

  • git によるバージョン管理の徹底
  • アプリケーション部分を含めたユニットテストの作成
  • 継続的インテグレーション (CI) 環境の構築

まず、バージョン管理は、自ソフトウェアの開発プロジェクトは 2010 年の頃から git によるバージョン管理を続けているので大きな変化はないのですが、既存の OSS プロジェクトをカスタマイズする際におざなりになる傾向がありました。このせいで、前述した 7-Zip の脆弱性に対する修正をカスタマイズ版に反映する時に苦労した経験から、何とかしたいと感じた課題です。7-Zip に関しては、フォークしたリポジトリ (Cube.Native.SevenZip) に対していくつかのブランチを用意し、オリジナル版の修正を反映しやすくする事で改善を試みました。改修後に発生した 7-Zip 側のアップデートは 1 度しかないのですが、この時は git の自動 merge のみで完了できたので、従来に比べて随分と楽になった事を実感できました。

ユニットテストに関しては、ライブラリ部分に関しては当初からそれなりにテストケースを作成していましたが、View 側に近づくにつれて不十分になっていくと言う実感がありました。また、旧 CubeICE では、ユーザ設定に応じて圧縮・解凍結果が正常に変化しているかどうかの確認を人力テストに依存している部分が残っていたため、これを自動化する必要性も感じていました。今回は、改修当初からアプリケーション部分のユニットテストも後回しにしないように注意しながら進めた結果、コマンドラインとユーザ設定を指定して圧縮・解凍処理を実行すると言う実アプリケーションとほぼ同様の流れをユニットテスト上で再現できる形まで持っていく事ができました。また、解凍処理で対応している圧縮形式に関しても、可能な限りサンプルファイル (Examples) を用意する事で、特定の圧縮形式の解凍処理にのみ発生する問題も早期に検知できる体制となってきました。

最後に、CI 環境の構築については、ごく少数で開発している事でローカル環境で十分と思っていた所もあり、ずっと後回しになっていました。しかし、1 年位前に AppVeyor と言う Windows アプリケーションの CI に特化したような Web サービスが存在する事を知り、github との連携で比較的簡単に導入できる事もあって基本的なライブラリ用プロジェクトから少しずつ導入を進めていました。そこで、今回、アプリケーションまで含めた導入プロジェクトの第一弾として CubeICE のプロジェクト全てを CI 環境上に構築する事を決めました。

Cube.FileSystem.SevenZip が C# の実装(≒ CubeICE のアプリケーション部分)、Cube.Native.SevenZip が 7-Zip のカスタマイズ部分となっています。共有ライブラリ部分を含めてまだ NuGet には公開していない事で AppVeyor の設定ファイルの記述に 1, 2 日悩みましたが、何とかテストを自動実行できる所まで構築できました。また、AppVeyor と同時にコード・カバレッジを可視化する Web サービスである Codecov とも連携しましたが、テストケースを記述していく上で当初の予想以上にここから得られる情報が役に立っていると実感しています。AppVeyor と Codecov を利用して実感した利点については、また別の機会にまとめたいと思います。

おわりに

CubeICE も最初の公開が 2011 年と言う事で、気付けばもう 6 年位もの間、多くのユーザに利用されている事になります。CubePDF 等でも同様の感想を抱く事が多いのですが、世に出たアプリケーションの寿命は、自分が開発を始めた頃(2010 年位)に漠然とイメージしていたよりもずっと長いものなのだなと改めて実感させられます。

圧縮・解凍と言う処理の観点から見ると、世の中全体としては文字コードが UTF-8 に統一される方向にあり、いずれは文字コードが異なるせいで文字化けが発生するような状況もなくなっていくかもしれません。しかし、完全にそう言った時代がやってくるにはもうしばらく時間が必要で、後 10 年位は引き続き CubeICE のような機能も必要とされるのではないかと感じています。これから 10 年、様々な修正、改良を続けていく上で、今回少し時間をかけて構築したものが役に立ってくれる事を期待しています。