.NETの7-ZipまたはCodePlexでオープンソースプロジェクトを行った方法



この記事は、ブログ「.NET」、「オープンソース」、「私はPR」に等しく帰属することができます。 その後。 私が資料を書いたとき、それのほとんどが「オープンソース」であることが明らかになりました...私が間違えた場合、多くを負かさないでください。

だから、以下は2009年2月にCodePlexに投稿されたオープンソースのSevenZipSharpライブラリの開発における私の1年半の経験についての話です。

SevenZipSharpを使用する

ライブラリには、SevenZipExtractorとSevenZipCompressorの2つの主要なクラスがあります。 最初の使用パターン:
//
using ( var extr = new SevenZipExtractor( @"\\" ))
{
extr.Extracting += DoExtractingEvent();
extr.ExtractArchive( @"\" );
DoFinishEvent();
}

//
var extr = new SevenZipExtractor( @"\\" );
extr.Extracting += DoExtractingEvent();
extr.ExtractionFinished += (s, e) => { DoFinishEvent(); extr.Dispose(); extr = null ; };
extr.BeginExtractArchive( @"\" );


* This source code was highlighted with Source Code Highlighter .
2番目の使用パターン:
//
var cmpr = new SevenZipCompressor();
cmpr.CompressDirectory( @"\\\" , @"\" );
DoFinishEvent();
cmpr = null ;

//
var cmpr = new SevenZipCompressor();
cmpr.CompressionFinished += (s, e) => { DoFinishEvent(); cmpr = null ; }
cmpr.BeginCompressDirectory( @"\\\" , @"\" );


* This source code was highlighted with Source Code Highlighter .

この記事をSevenZipSharpのドキュメントにしたくないので、その機能の一部を挙げてください。
それがすべて始まった方法

2009年2月に、私が取り組んだ有料プロジェクトの1つで7-zipアーカイブを扱う必要がありました。 数日間、私は既成の消化可能な解決策の検索に失敗しましたが、CodeProjectに関するこの記事よりも良いものを見つけることができませんでした 。 しかし、彼の不在について人々が不平を言っている多くの投稿を読みました。 そして、私の意志を最初に集め、見つかった記事から始めて、 勇気を持って進み 、7-Zip上のラッパーの独自の実装を書き始めました。 LGPLv3ライセンスの下で、最近開いたCodePlexにコードを配置することにしました。 最初は作業が本格的で、数日ごとにリリース後にリリースをリリースしました(ダウンロードページの「その他のダウンロード」セクションで確認できます )。 それから私の熱意は少し薄れ、私はコードを安定させ始めました。 2009年9月、リリースが頻繁に出なくなり(結婚しました)、それ以来、できる限りプロジェクトをサポートしています。

/ clrフラグを使用して7-Zipを混合アセンブリにコンパイルするオプションが検討されました。 このオプションは拒否されました 第一に、インターフェースは低レベルですぐに使用するには適さず、「アドオン」を作成する必要があり、第二に、/ clr:pureフラグを使用してコードを収集する必要があり、多くのコードを書き直す必要があり、管理されていない部分は依然として残っていました。

SevenZipSharpが最初に登場したとき、私は潜在的な興味のあるユーザー開発者にそれについて伝えたかった。 ライブラリの簡単な説明は可能な限り残しました。StackOverflowの質問への回答、MSDN、Channel 9を含むプログラミングフォーラム、CodeProjectの同じ記事へのコメント、さらには英語版ウィキペディアまで 。 これはすべて結果をもたらし、すぐにGoogle検索結果がトラフィックで最初に出てきました。 私は誰もが自分のプロジェクトを宣伝すべきだと思います。さもなければ、大多数は彼らの存在を知らないでしょう。 広告の掲載結果は、ダウンロード数と訪問数の統計によって推定され、公開されています。

SevenZipSharpおよび7-Zip

多くの人が知っているように、7-ZipはC ++で書かれており、少量のCとCRC32を計算する悪名高いアセンブラー関数を備えています。IgorPavlovはx86、x86-64、ARM向けに実装しました。 コードに関するドキュメントはありません。これは、オープンソース運動に関与するロシアのプログラマーのスタイルです。 たくさんのコードがありますが、それはまったく簡単ではなく、豊富な定義、インターフェース、クラスを理解するのに時間がかかります。 圧縮アルゴリズムの実装はコーデックと呼ばれます。 コーデックは、ala Miranda / Pidginメッセンジャーのプロトコルプラグインのように、標準的な方法でライブラリに組み込まれます。 7-ZipアーキテクチャはCOMと切り離せません。 これはまさにp7zip-POSIXシステム用の7-Zipの開発を妨げるものであり、Igor Pavlovも対処しています。 p7zipでは、COMはその動作をシミュレートする松葉杖に置き換えられ、同時にwindows.hタイプの半分を宣言します。 アルゴリズム自体は完璧に記述されており、非常に安定していますが、上位レベルには、ご想像のとおり、多くの要望が残されています。 著者が今7-Zipを書き始めた場合、Pythonでさえ、理想的にはC#やJavaのような言語で、より理解しやすく、普遍的で移植可能なカーネルアーキテクチャを思いつくだろうと思います(実際、プラスはこの目的には適していません) 。

ちなみに、エンドユーザー向けの7-Zip(7-zip.orgからダウンロードするインストール)は、世紀初頭のVisual Studio 6サンプルになります。 ソリューションファイルはVS2008 / 2010形式に正常に変換され、C / C ++コンパイラを新しいものに置き換えて、すべての最適化フラグ(はい、私の主な職業はコンパイラ)をアクティブにした後、プロファイルを使用して、約15%(LZMA / LZMA2 ) ご注意...

SevenZipSharpが7-Zipをラップする方法は次のとおりです。 COMのCreateObjectを使用して、指定されたインターフェイス(IInArchive、IOutArchive)をサポートするオブジェクトが作成されます。 必要な関数がこのオブジェクトから取得され、目的の結果が達成されます(たとえば、InnArchive.Extract(...))。 長時間の操作中、マネージドコールバックはアンマネージコードから呼び出されます。これにより、エラー処理というすぐに認識できない問題が発生します。 たとえば、コールバックのエラーまたは呼び出されたコールバックユーザーイベントの例外が原因で、奇妙な32ビットエラーコードを除き、警告やわかりやすい情報なしで操作が失敗します。 すべてのコールバックをラップしてtry / catchを実行し、スローされたすべての例外をエラースタックに配置することにしました。エラースタックは、失敗した場合にユーザーに表示されます。 よりエレガントなソリューションがある場合は、それについて教えてください。

愛好家によって7-Zipコード全体をC#に書き直そうとする試みは定期的に行われていますが、議論を超えたものはありません。 アルゴリズムをC ++からC#に作り直すことは有益ではありません:費やされた努力と速度の低下は、クロスプラットフォームと宗教で報われず、すべての微妙さを考慮してカーネルを書き換えることができるのはIgor Pavlovだけです。 私は立証されません:測定のためのLZMA SDKからのC#/。NET上のLZMAは、非管理アルゴリズムよりも4倍遅く動作します。 したがって、おそらくこの状況で最も良いのは、明確でシンプルなインターフェースを持つラッパーを作成することでした。

ある時点で、SevenZipSharpをMono(GNU / Linux)で動作させたいと思いました。 そして、7-ZipがCOMにアタッチされる問題は、その素晴らしさのすべてに現れました。 ライブラリの低レベル部分を最初から書き直す必要がありました。 なぜなら 私がすでに書いたように、7-Zipコードは特定のものであり、 SWIGのような自動ラッピング用のツールは役に立たないことが判明し、それらをまったく機能させるためには、最初にプリプロセッサーでコード全体を調べ、10階建ての定義を削除する必要がありました。 現在、私はゆっくりとCOMに依存しないラッパーを書いています。

開発

おそらく、多くのC#初心者開発者が同じ間違いを繰り返しますが、私も例外ではありません。 FxCopとStyleCopに気付いたとき、私はすぐにそれらを使用しようとしました。 ライブラリコードを良好な状態に維持することは論理的に思えます。 ただし、デフォルトのStyleCopには表示される警告が多すぎるため、設定したくなかったため、すぐに破棄されました。 FxCopは以前から使用されていましたが、ある時点で、基本的なコードの変更に時間をかけすぎて、本質的に何にも影響しないルールを遵守していると思いました。 私が自分でした結論は、これらのツールは個々のプログラミングスタイルを開発するために重要ですが、一人の開発者がそれらに関与するべきではないということです。

当初、SevenZipSharpはVisual Studio 2008で作成され、2番目のフレームワークの下で機能していました。 それでも、.NETのバージョンが小さければ小さいほど、ライブラリを使用する際の問題が少なくなることに気付きました。 多くのCodePlex開発者がこれを理解せず、.NET 4の超近代的な機能を使用してコードの記述を開始し、なぜダウンロード数が少ないのか不思議に思うのは残念です。 それから、Windows Mobile <7には本格的なCOMがあることがわかり、数日後にこれらのモバイルシステムにSevenZipSharpを移植しました。 誰かが知らない場合、通常のフレームワークとコンパクトなフレームワークには多くの違いがあり、コードは小さな変更なしでコンパイルされ、作業は大幅に削減されます。 2つのほぼ同一のブランチを維持することは不合理であると考え、複数の#if /#else /#endif (C ++ソースの標準的なアプローチ)でこの問題を解決しました。

Visual Studio 2010 / C#4が発表されたとき、新しいバージョンの言語の機能をコードに効果的に適用できることがわかりました(たとえば、登場したオプションパラメーターは、単一の論理メソッドの10以上のオーバーロードを排除します)。 後方互換性を維持するために、もう一度#if /#else /#endifを適用しました 。 コードは次第にエレガントなクラスと分岐モンスターから変わり始めました。 SevenZipSharpをMonoに移植するというアイデアが生まれたとき、私はまだいくつかのコードファイルを分岐しました。 そうでなければ、彼は数週間でそれを理解することができません。 その結果、栄光の中で、1つのファイルでさまざまなプラットフォームとフレームワークをサポートするという問題に直面しました。 例:
#if !DOTNET20
/// <summary>
/// Unpacks the whole archive asynchronously to the specified directory name at the specified priority.
/// </summary>
/// <param name="directory">The directory where the files are to be unpacked.</param>
/// <param name="eventPriority">The priority of events, relative to the other pending operations in the System.Windows.Threading.Dispatcher event queue, the specified method is invoked.</param>
#else
/// <summary>
/// Unpacks the whole archive asynchronously to the specified directory name at the specified priority.
/// </summary>
/// <param name="directory">The directory where the files are to be unpacked.</param>
#endif
public void BeginExtractArchive( string directory
#if !DOTNET20
, DispatcherPriority eventPriority
#if CS4
= DispatcherPriority.Normal
#endif
#endif
)
{
SaveContext(
#if !DOTNET20
eventPriority
#endif
);
( new ExtractArchiveDelegate(ExtractArchive)).BeginInvoke(directory, AsyncCallbackImplementation, this );
}


* This source code was highlighted with Source Code Highlighter .

SevenZipSharpは自発的に開発されたことに注意してください。 機能に何かを追加したい場合は、取り込んで追加しました-そして、ボスと相談せず、経営陣と意思決定を調整しませんでした、など。 これには欠点がありますが、バグは即座に修正され、新しい機能の要求は数日で満たされました。 行動の完全な自由-そしてあなたの過ちからの真の学習。

ボーナス

CodePlexのオープンソースプロジェクトへの参加から、予想外の楽しい驚きが現れました。 まず、ReSharperの作成者であるJetBrainsがオープンソースソフトウェア開発者に無料ライセンスを付与していることに気付きました。 私は運を試しましたが、後悔しませんでした-彼らは本当に私にライセンスを与えました。 ReSharperはコードを書くために不可欠なツールであることが証明されており、私はそれについてみんなに助言します。 第二に、最近では、CodePlexはプロジェクトページに広告を表示します(所有者のリクエストにより)。 広告収入は、良い目的のために犠牲になるか、自分に充当されます。 私は2番目のオプションを選択しましたが、1か月あたり約10ドルを受け取ります。 第三に、SevenZipSharpが人気を博したとき、NDependやSciTech .NET Memory ProfilerなどのC#/。NETプログラマー向けの便利なツールを開発している企業からスポンサーになりました。 第4に、[寄付]ボタンは少しのお金をもたらします。 これまでに10ドル以上寄付した人はいませんが、これでも楽しくて刺激的です。

ライブラリに感謝する手紙で、彼らがそれを実際の非常に有名なプロジェクト(たとえば、Stardock)で使用していると報告するとき、それは勇気づけられます。 時々、一緒に図書館で仕事を始めようという提案のある人から手紙をもらいます。 人は通常、熱心で、一緒にすれば素晴らしいことを保証します。 私は誰にでもSVNパスワードを一度も与えないという手紙に書いた応答の後、その人に何ができるかを尋ね、将来のプロジェクトの開発のおおよその計画を説明します。まだ誰も私に連絡していません。 私には奇妙に思えますが、おそらくそのような人々の心理はコメントで説明されます。


継続のない典型的な手紙

私たちは人々について話しているので、私はCodePlexで一般について話します。 数回、彼らはコードを私に寄付しましたが、一度だけ-規則に従って、パッチを通して。 時には実践的なアドバイスを提供し、より良い方法を提案しました。 他のユーザーがあなたを修正し、バグ修正を共有すると非常に便利です。 ただし、バグは、バグが明らかな場合でも、問題トラッカーではなくディスカッションで報告されることがよくあります。 あなたは定期的に質問を読み、それがわき柱、図書館、または不正なユーザーであるかどうかを決定する必要があります。 ただし、すぐに数十個のバグから始まる「参加者」が現れる場合がありますが、そのうちの最良のケースでは、ペアは本当に価値があり、残りは「参加者」以外の誰も必要としない追加機能の追加要求です。 「アンパックが機能しない」などのバグが発生した場合、ライブラリのどのバージョン、エラーの再現方法をコメントで尋ねると、彼は長い間SevenZipSharpを忘れて応答しません。 絶対に。

評価(CodePlexの星、1〜5)を残す人を別々に楽しませる。 彼らが2を入れたときに怒り、理由を説明しません。 しかし、彼らが2を入れて、何も機能しないと言って、ライブラリがあなたのたわごとだと書いているとき、それはまた腹を立てます。 幸いなことに、これはSevenZipSharpではめったに起こりません。他の一般的なプロジェクトとは異なり、このような評価に値するものではないと確信しています。

まとめ

振り返ってみると、無駄ではないSevenZipSharpに連絡したことがわかります。 貴重な経験といくつかの利点の両方が得られました。 「魂のために」あなたのオープンソースプロジェクトを開発する価値があるかどうか尋ねたら、私はためらうことなく答えます-もちろんです!

ご清聴ありがとうございました。

Source: https://habr.com/ru/post/J103521/


All Articles