web-dev-qa-db-ja.com

「クリーンなコード」の実践からかけ離れたコードを保持しながら、巨大なオープンソースライブラリをどのように維持しますか?

私はまだ高品質のコードを書くのが未経験なので、Robert C. MartinによるClean Codeなどの問題に対処する本を読み、有名なライブラリのコードをチェックして、私のスキルを向上させます。

多くのオープンソースライブラリが何年も維持されているため、それらが正しいパスにない可能性はほとんどありませんが、それらの多くのコードは、クリーンなコードを記述するために対処する原則から遠いことがわかりました。数百行のコード。

だから私の質問は:クリーンなコードの原則はあまりにも制限されていますか、そしてこれらのような多くのライブラリでそれらなしで行うことができますか?そうでない場合、これらの原則の多くを考慮せずに巨大なライブラリをどのように維持していますか?

簡単な説明をお願いします。質問が初心者の男からのばかげているようであるなら、私は謝罪します。

[〜#〜]編集[〜#〜]

これをチェック バターナイフ ライブラリー– Androidコミュニティーで最もよく知られているライブラリーの1つ。

81
Islam Salah

ここでは良い答えですが、あなたの butterknife の例について一言言っておきましょう。コードが何をしているのか私にはわかりませんが、一見すると、それは私にとって本当にメンテナンスしにくいように見えません。変数とメソッド名は意図的に選択されているようです。コードは適切にインデントされ、フォーマットされています。コメントがあり、長いメソッドは少なくともブロック構造を示しています。

はい、それはボブおじさんの「クリーンなコード」のルールには決して従わず、一部のメソッドは長すぎる(おそらくクラス全体)です。しかし、コードを見ると、十分な構造がまだあるので、それらのブロックを独自のメソッドに抽出して簡単に「クリーンアップ」できるようになります(リファクタリングツールを使用するときにバグが発生するリスクが低い)。

このようなコードの実際の問題は、1つのブロックと別のブロックを追加して、別のブロックがある程度、場合によっては数年かけて機能することです。ただし、コードは少しずつ進化することが難しくなり、コードを変更してテストするのに少し時間がかかります。また、「別のブロックを追加する」ことでは解決できないものを本当に変更する必要があるが、再構築が必要な場合は、誰かがコードをより早くクリーンアップし始めたことを望みます。

83
Doc Brown

「クリーンコード」に記載されている原則は、常に一般的に合意されているわけではありません。その大部分は常識ですが、著者の意見のいくつかはかなり物議を醸し、誰もが共有しているわけではありません。

特に、短い方法の選択は誰もが同意しているわけではありません。長いメソッドのコードが他の場所で繰り返されていない場合、その一部を別のメソッドに抽出すると(複数の短いメソッドが得られるため)、これらのメソッドは、気にする必要のない他のメソッドから見えるようになるため、全体的な複雑さが増します。したがって、これはトレードオフであり、客観的な改善ではありません。

本のアドバイスも(すべてのアドバイスと同様に)特定の種類のソフトウェア、つまりエンタープライズアプリケーションを対象としています。ゲームやオペレーティングシステムのような他の種類のソフトウェアには、エンタープライズソフトウェアとは異なる制約があるため、異なるパターンと設計原則が機能します。

言語も要因です。クリーンコードはJavaまたは同様の言語を想定しています。CまたはLISPを使用する場合、多くのアドバイスは適用されません。

要するに、本は特定のクラスのソフトウェアについての一人の意見です。それはどこにも適用されません。

オープンソースプロジェクトの場合、コードの品質はひどいものから素晴らしいものまでさまざまです。結局のところ、誰でも自分のコードをオープンソースとして公開できます。しかし、複数のコントリビューターがいる成熟した成功したオープンソースプロジェクトを見ると、彼らが彼らのために働くスタイルに意識的に落ち着いていることはかなり確かです。このスタイルがいくつかの意見やガイドラインに反している場合、(端的に言えば)動作しているコードが意見よりも優先されるため、それは間違っているか無関係であるガイドラインです。

158
JacquesB

概要

JacquesBが書いているように、誰もがロバートC.マーティンの「クリーンコード」に同意するわけではありません。

期待した原則に「違反」していることが判明したオープンソースプロジェクトは、単に他の原則を持っている可能性があります。

私の視点

私はたまたま、Robert C. Martinの原則に非常に準拠しているいくつかのコードベースを監督しています。しかし、私はそれらが正しいであるとは本当に主張していません。私はそれらがうまく機能しているとしか言えません-そして、その「私たち」は実際には少なくとも

  • 当社の製品の範囲とアーキテクチャ、
  • ターゲット市場/顧客の期待、
  • 製品が維持される期間、
  • 私たちが使用する開発方法論
  • 当社の組織構造と
  • 開発者の習慣、意見、過去の経験。

基本的に、これは次のように要約されます。各チーム(会社、部門、オープンソースプロジェクトなど)は一意です。彼らは異なる優先順位と異なる視点を持ち、そしてもちろん異なるトレードオフをします。これらのトレードオフ、およびそれらがもたらすコードスタイルは、主に好みの問題であり、「間違っている」または「正しい」と証明することはできません。チームは、「私たちには効果があるので、これを行う」または「私たちには役に立たないため、これを変更する必要があります」とのみ言うことができます。

とは言っても、何年にもわたって大規模なコードベースを正常に維持できるようにするには、各チームが上記の側面に適していると考える一連のコード規約に同意する必要があります。それは、ロバートC.マーティン、別の作者による実践を採用すること、または独自の手法を発明することを意味するかもしれません。それらを正式に書き留めるか、「例を挙げて」文書化することを意味します。しかし、それらは存在するはずです。

「長いメソッドからいくつかのプライベートメソッドにコードを分割する」という慣行を検討してください。

Robert C. Martinは、このスタイルでは各メソッドの内容を1レベルの抽象化に制限できると述べています。簡単な例として、パブリックメソッドはおそらくverifyInput(...)loadDataFromHardDisk(...)transformDataToJson(...)、最後にsendJsonToClient(...)、これらのメソッドには実装の詳細があります。

  • 一部の人々は、読者が大まかな手順の簡単な概要を取得し、読みたい詳細を選択できるため、このようにしています。
  • すべての詳細を知りたいときは、クラス内を飛び回って実行フローをたどる必要があるため、一部の人はそれを嫌います(これは、JacquesBが複雑性の追加について書いているときに、JacquesBが言及している可能性が高いことです)。

教訓は次のとおりです。彼らは意見を持つ資格があるため、すべて正しいです。

34
Jens Bannmann

多くのオープンソースライブラリは、実際には客観的にコーディングプラクティスに問題があり、その一部に精通しているため、読みやすさに対処できる長期的な貢献者の小さなグループによって困難に維持されています彼らが最も頻繁に維持するコード。事後の可読性を改善するためにコードをリファクタリングすることは、誰もが同じページにいる必要があり、面白くなく、新しい機能が実装されていないのでお金がかからないため、たいていは大変な作業です。

他の人が言ったように、何でも述べるクリーンなコードについての本には、普遍的に合意されていないアドバイスが必ず含まれています。特に、ほとんどすべてのルールは過度の熱意で従うことができ、読みやすさの問題を別の問題に置き換えます。

個人的には、適切な名前がなければ、名前付き関数の作成は避けます。そして、良い名前は短く、関数が外部の世界に対して何をするかを忠実に説明する必要があります。これは、関数の引数をできるだけ少なくして、グローバルに書き込み可能なデータを持たないようにすることとも関連しています。非常に複雑な関数を小さな関数に切り詰めようとすると、その関数がgenulyly complexの場合、引数リストが非常に長くなることがよくあります。読み取り可能なコードの作成と維持は、相互に矛盾する常識のルール間の均衡を保つための課題です。本を読むのは良いですが、実際の読みやすさが向上する場所である誤った複雑さを見つける方法を経験のみが教えてくれます。

13
Kafein

ほとんどのオープンソースプロジェクトは、適切に管理されていません。これには明らかに例外がありますが、オープンソースの世界では多くのジャンクが見つかります。

これは、私が話しているプロジェクトのすべてのプロジェクトオーナー/マネージャーの批評ではなく、単に時間の問題です。これらの人々は、彼らの実際の支払いの仕事のように、彼らの時間と関係があるより良いものを持っています。

最初は、コードは1人の作業であり、おそらく小さいです。小さなコードはクリーンである必要はありません。むしろ、コードをクリーンにするために必要な労力は、利益よりも大きくなります。

時間が経つにつれて、コードは多くの異なる人々によるパッチの山になっています。パッチ作成者は、コードの所有権を感じません。彼らは、この1つの機能を追加するか、この1つのバグを最も簡単な方法で修正したいだけです。

所有者は物事を片付ける時間がないので、他の誰も気にしません。

そして、コードは大きくなっています。そして醜い。

コードを回避する方法がどんどん難しくなるにつれて、人々は間違った場所に機能を追加し始めます。また、バグを修正する代わりに、コードの他の場所に回避策を追加します。

この時点では、人々が気にしないだけでなく、物事を壊すことを恐れているため、もはやdareクリーンアップされません。

私は、コードベースを「残酷で異常な罰」と表現している人がいました。

私の個人的な経験はそれほど悪くはありませんが、非常に奇妙なことがいくつかありました。

7
Stig Hemmer

だれもがしているはずのことをしている人はいない そしてそれがうまくいくなら なぜ私たちはそうなっているのだろう?これらのことを行う

答えは、私見ですが、動作します "十分に良い" 、別名 " 悪い優れている " 哲学 。基本的に、オープンソースとビルゲイツの間の揺るぎない歴史にもかかわらず、彼らは事実上同じ考えを採用しました ほとんどの人はバグではなく機能に関心があります

もちろん、これは「 逸脱の正規化 」にもつながります。これは Heartbleed のような状況につながります。ここで、まるであなたの質問に答えるかのように、大規模な overgrownスパゲッティパイル と呼ばれるオープンソースコード OpenSSL が " ncleaned "のようになりました 10年大規模セキュリティの欠陥 に影響を与える 数千万人 に影響を与える。

ソリューションLibreSSL と呼ばれるまったく新しいシステムを発明することでした クリーンなコードを使用する予定 、そしてもちろん ほとんどnobodyそれを使用する

では、不適切にコード化された巨大なオープンソースプロジェクトをどのように維持するのでしょうか。答えは質問です。それらの多くは、きれいな状態で維持されていません。それらは ランダムにパッチされた数千人の異なる人々 がカバーする さまざまな奇妙なマシンでの使用例 および開発者が行う状況 決してアクセス権を持たないテストする。それはしません まで、コードは「十分に」機能し、誰もがパニックして 問題にお金を投げる と決定します。

では、他に誰もいないのに、なぜ「 正しい方法 」を実行する必要があるのでしょうか。

答えはあなたがすべきではないということです。あなたは するべきかしないか であり、 人間の性質は変化しない のスケールで 世界は変わり続ける に関係なく- 人間寿命 。個人的に、私はそれがそうするように感じている方法が好きなので、私はきれいなコードを書くことだけを試みます。

3
don bright

すでに良い答えがたくさんあります-オープンソースのメンテナーの視点を与えたいと思います。

私の視点

私はそのような多くのプロジェクトのメンテナーであり、すばらしいコードではありません。ライブラリは毎週何百万回もダウンロードされるため、互換性の問題から、そのようなコードを改善できない場合もあります。

それは維持を難しくします-Node.jsコアメンバーとして、私が触れるのを恐れているコードの一部がありますが、関係なく行うべき多くの作業があり、人々はプラットフォームをうまく使用して楽しんでいます。最も重要なことは、それが機能することです。

可読コードについて

あなたが言う時:

それらの多くのコードは、クリーンなコードを記述するためのアドレス指定された原則(たとえば、数百行のコードを含むメソッド)からかけ離れていることがわかりました。

コードの行 それは大きな尺度ではありません 読みやすさの程度。私がLinuxカーネルにリンクした調査を分析し、プログラマーの調査で、「通常の」コード(人々が基本的に期待するコード)と一貫性のあるコードは、理解しやすい点で「クリーン」なコードよりも優れていることがわかりました。これも私の個人的な経験と一致しています。

いくつかのオープンソースプロジェクトはあまり歓迎されていません

Linus "famously" は、デバッガを使用する人々はLinuxで作業するには不十分であり、彼はそれらの多くを引き付けたくないので、Linuxに組み込みデバッガがあるべきではないと述べました。

個人的に私は彼のスタンスには絶対に反対していますが、それは人々がすることでもあります。

2

良いコードを構成するものはコンテキストに依存します。そして、それを導く古典的な本は、オープンソースを議論するには古すぎないにしても、悪い社内コードベースに対する終わりのない戦争を繰り広げる伝統の少なくとも一部です。したがって、ライブラリの目的がまったく異なるという事実を見落とすのは簡単であり、それらはそれに応じて書かれています。次の問題を順不同で検討してください。

  • ライブラリをインポートするとき、またはライブラリからインポートするとき、何をコピーしているのでなければ、内部構造の専門家がツールキットのどの小さな部分を必要としているかを正確に把握できていないでしょう。 Stack Exchangeの回答で、実行するように指示されました。だから私はfrom A import(Pythonの場合など)、何が表示されるか確認してください。しかし、それは私がリストに表示するものは、借りる必要のある論理的なタスクを反映する必要があることを意味し、それがコードベースになければなりません。それを短くする無数のヘルパーメソッドは私を混乱させます。
  • ライブラリは、ほとんどの人が漠然と聞いたことのあるアルゴリズムを使用しようとする最も経験の浅いプログラマーのためにあります。彼らは外部のドキュメントを必要とし、それはコードを正確にミラーリングする必要があります。これは、すべてのリファクタリングを続けてショートメソッドとワンワンの支持者を満足させることはできません。
  • 人々が借りるすべてのライブラリメソッドは、コードが破壊されたり名前が変更されたりすると、コードを世界中で壊して悲惨な結果をもたらす可能性があります。確かに、sklearnが Calinski-Harabaszのタイプミス を修正してくれることを望みますが、それによって別の 左パッドインシデント が発生する可能性があります。実際、私の経験では、ライブラリの進化に関する最大の問題は、すべてをどのように構成するかについて、優れたコードの新しい「改善」を採用しようとするときです。
  • 社内では、コメントは、私が逆流する必要のないあらゆる理由で、せいぜい大体必要な悪です(これらのポイントは多少誇張されていますが)。良いコメントは、コードがどのように機能するかではなく、なぜ機能するかを示しています。しかし、図書館は読者が紙の袋から出て線形代数を書くことができなかった有能なプログラマであることを知っています。言い換えると、everythingはコメントする必要があります:なぜ機能するのですか? (OK、それはまた別の誇張です。)それで、署名行、100行のコメントブロック、文字どおりに署名行に含まれている可能性のある1行のコードが表示されるのはそのためです(もちろん、言語は許可します)。
  • Githubで何かを更新し、コードが受け入れられるかどうかを確認するとします。コードの変更が機能する理由を明確にする必要があります。機能的なコミットの一部としてキャンプサイトをよりクリーンにするためのリファクタリングは、多くの場合、多くの行の節約、再配置、および名前の変更を意味します。

私は他の点について私が言うことができるよりも多くの経験を持つ人々がいると確信しています。

2
J.G.

オープンソースソフトウェアは、複数の作者が関与していることを必ずしも意味しません。ソフトウェア(またはソフトウェアの単位)が1人の作成者によって記述されている場合、長い関数が頻繁に表示されます。

これは、開発プロセスの性質によるものです。シンプルな方法が時間とともに拡張され、新しい機能が追加され、バグが修正されています。

長いメソッドは、新しい作成者の機能の理解を大幅に低下させます。ただし、1人の著者の場合、これが問題になることはめったになく、問題は見過ごされがちです。オープンソースのもう1つの性質は、多くのソフトウェアが積極的に開発されていないため、たとえば、複雑なメソッドを複数の単純なメソッドに分割するようなリファクタリング作業がないことです。

例を示していませんが、私の理解から、これはしばしば開発言語にも関連しています。一部の言語では、最初から厳格なリンティングルールと重いユニットテスト(またはTDD)を実施しています。通常、リンティングとユニットテストの両方でこの問題を回避できます(複雑なメソッドや長いメソッドをユニットテストするのは困難です)。

一般に、ソフトウェアが1人の作成者によって開発され、他の貢献者が小さな問題のみを修正している場合、コードをクリーンにすることは困難です。

1
Sulthan