「クリーンコード」の実践からはほど遠いコードを使用しながら、巨大なオープンソースライブラリをどのように維持しますか。


80

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

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

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

簡単な説明をいただければ幸いです。質問が初心者の人からばかげていると思われる場合、私は謝罪します。

編集

Butterknifeライブラリでこのを確認してください。Androidコミュニティで最もよく知られているライブラリの1つです。


71
偏ったサンプルに苦しんでいます。「よく知られている」ライブラリのコードをチェックすると言います。さて、ベストプラクティスに従っていないために自力で崩壊したライブラリは「よく知られている」ものではなく、不明瞭になりました。
ヨルグWミットタグ

3
たとえばLinuxソースをチェックしましたか?
マーティンシュレーダー

55
ソフトウェアの価値の主要な尺度は、コードがどれだけ「クリーン」であるかではなく、特定のタスクをどれだけ満たすかです。何かを書くためだけにソフトウェアを書くのを好む人もいますが、ほとんどの人にとって、コードは目的を達成するための手段にすぎません。
whatsisname

3
誰もあなたに反対しません。問題は、貧弱なコードを何年も維持する方法ですか?なぜ進化の繰り返しの多くでクリーンアップされなかったのですか?
イスラム教サラー

13
質問の前提(長期間維持されるオープンソースプロジェクトは、ある特定の本の著者のベストプラクティスの概念に本質的に準拠する必要があるということ)は完全に間違っており、どこから得たのかわかりません。質問の前提を広げてください。
軌道上の明るさレース

回答:


84

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

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

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


コメントは詳細なディスカッション用ではありません。この会話はチャットに移動さました
ヤンニス

158

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

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

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

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

要するに、この本はソフトウェアの特定のクラスに関する独り言です。どこにも当てはまりません。

オープンソースプロジェクトに関しては、コードの品質はひどいものから素晴らしいものまであります。結局のところ、誰でもコードをオープンソースとして公開できます。しかし、複数の貢献者がいる成熟した成功したオープンソースプロジェクトを見ると、彼らが自分に合ったスタイルに意識的に落ち着いていることを確信できます。このスタイルが何らかの意見やガイドラインに矛盾している場合、(簡潔に言えば)作業コードが意見に勝るので、間違っているか無関係であるのはガイドラインです。


18
「特定の種類のソフトウェアに向けて準備された」ための+1。これは、このトピックおよび類似のトピックに関するほとんどの本に拡張できます。読んでいるものすべてを一粒の塩で取りましょう。書かれた時間、ターゲット環境、開発方法論、その他のあらゆる要因によって偏る場合があります。
レジナルドブルー

16
その本に従うと、多くの人が「ガベージコード」と呼ぶものを厳密に作成します。
フランクヒルマン

16
@FrankHileman:その本の推奨事項のどれにも従わない。
Doc Brown

5
@ jpmc26-あなたのリンクされた答えは、私が親しんでいる科学プログラミングに関する分野に関係しています。私は最近、ジョンソン宇宙センターのいくつかのシミュレーションで使用される重力モデルを相対論的に正しいものにするためのウィッシュリストアイテムを取得しました。コメントと空白行を数えて、ニュートン重力への相対論的摂動を計算するコードを書いたコードは145行の長さで、すべてが1つの関数になっています。通常、私は自分で45行の関数を作成し、145は言うまでもありません。しかし、この場合はそうではありません。...
デビッドハンメン

12
...問題の関数は、ジャーナルペーパーYの方程式Xを実装しているため、間違いなく単一目的ルールに従います。(式がページの4分の1をカバーすることは詳細に説明されています。)この関数を部分に分割する意味のある場所はなく、そうする意味のある理由もありません。ボブおじさんが軽whichするコメント この場合、これらは絶対に必要であり、これは科学的プログラミングの典型です。モデルのTeXドキュメントで関連するジャーナル参照を見るのは良いことですが、実装で参照するのも良いことです。
デビッドハンメン

34

概要

JacquesBが書いているように、すべての人がRobert C. Martinの「Clean Code」に同意しているわけではありません。

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

私の視点

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

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

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

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

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

ロバートC.マーティンはこのスタイルは、抽象化の1つのレベルに各メソッドの内容を制限することができますことを言う-簡略化した例として、公共の方法は、おそらく唯一のようなプライベートメソッドへの呼び出しで構成されますverifyInput(...)loadDataFromHardDisk(...)transformDataToJson(...)そして最後にsendJsonToClient(...)、これらの方法を持っています実装の詳細。

  • 読者は、高レベルの手順の概要をすばやく把握し、読みたい詳細を選択できるため、これを好む人もいます。
  • すべての詳細を知りたいときは、実行フローに沿ってクラス内をジャンプする必要があるため、これを嫌う人もいます(これは、JacquesBが彼が複雑さの追加について書いているときに言及しているものです)。

教訓は次のとおりです。意見を述べる権利があるので、それらはすべて正しいです。


13

実際、多くのオープンソースライブラリは客観的にコーディングの問題に苦しんでおり、最も頻繁に維持するコードの部分に精通しているため、貧弱な可読性に対処できる長期的な貢献者の小さなグループによって困難を抱えて維持されています。事実を理解しやすくするためにコードをリファクタリングすることは、誰もが同じページにいる必要があり、面白くなく、新しい機能が実装されていないため費用がかからないため、多くの場合、非常に困難です。

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

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


2
私は付け加えます:単に何かが「オープンソース」だからといって、だれもが貢献者であるという意味ではありません。多くの場合、多くのオープンソースプロジェクトは、良くも悪くも自分のプロジェクトを他の貢献者から隔離するクリークによって維持されています。誰もそれを変更する必要がないか、誰もその方法を理解できないために、フォークされない場合、従来のスタイルのコードはおそらく変更されません。
can-ned_food

7

ほとんどのオープンソースプロジェクトは管理が不十分です。それには明らかに例外がありますが、オープンソースの世界にはたくさんのジャンクがあります。

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

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

時間が経つにつれて、コードは多くの異なる人々によるパッチの山になります。パッチ作成者はコードの所有権を感じず、この1つの機能を追加するか、この1つのバグを可能な限り簡単な方法で修正することを望みます。

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

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

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

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

コードベースを「残酷で異常な罰」と表現する人がいます。

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


23
この回答で「オープン」と「ソース」という言葉を削除すると、引き続き同じように真実になります。
スティーブンM.ウェッブ

これは、クローズドソースソフトウェアにも同様に当てはまると思います。
マークロテベール

3

誰も彼らがしているはずのことをしていない場合、あなたはこのようなものがどのように機能するのかを尋ねているように思えますそして、それが機能する場合、なぜこれらのことを行うことになっているのでしょうか?

私見の答えは、それは「十分に良い」、「悪い ほど良い哲学としても知られているということです。基本的に、オープンソースとビルゲイツの間の岩だらけの歴史にもかかわらず、彼らは事実上、ほとんどの人がバグではなく機能を気にするという同じ考えを採用しました

もちろん、これはまた、「に私たちをリード逸脱の正常化のような状況につながる」ハートブリード大規模な、あなたの質問に答えるために正確にいるかのように、生い茂った スパゲッティパイルと呼ばれるオープンソースコードのOpenSSLは、「行ってきました汚れたようなもののために」10年数千万人の人々に影響を与える大規模な セキュリティ上の欠陥に巻き込まれる

解決策は、と呼ばれる全く新しいシステムを発明したLibreSSLた、きれいっぽいコードを使用しようとし、そしてもちろん、ほとんど 誰も それを使用していません

では、巨大な不適切にコーディングされたオープンソースプロジェクトはどのように維持されますか?答えは質問にあります。それらの多くは、クリーンな状態で維持されていません。それらは、開発者がテストにアクセスできないさまざまな奇妙なマシンや状況でのユースケースをカバーするために何千人もの異なる人々によってランダムにパッチれます。このコード、誰もがパニックに陥り、問題にお金投じることを決定するまで「十分に」機能します

だから、他に誰もいないのに、なぜあなたは何かを「正しい方法」でやる必要がありますか?

答えはすべきではありません。あなたはそうするかしないかのどちらかであり、人間の性質は人間の生涯の規模で変化しないため、世界は関係なく回転し続けます。個人的に、私はきれいなコードを書くようにしています。


1
非常に多くのリンク...一見すると、この答えはホバー広告にひっかかっているか、ウィキペディアのページであると思いました。
ジョニーヘンリー

2

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

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

私よりも経験のある人は他の点に言及できると思います。


最初の箇条書きについて。そのため、パブリック/プライベートメソッドがあります。内部でプライベートメソッドまたは内部メソッドを呼び出すパブリックAPIを公開します。2番目の箇条書きも不正確です。短いパブリックメソッドのドキュメントを作成できず、多くの小さなメソッドを呼び出すことができない理由はありません。
FC

@FCinこれは、メンテナーがすべてのメソッドの前後で常に正しいキーワードを使用することを忘れない限り、実行可能なアプローチです。または、簡単でエラーが発生しにくいものを実行できます。
JG

C#、Java(ボブおじさんがよく言っている)などの言語では、アクセス修飾子は実際にコードを記述するために使用される最も基本的なツールです。正しいキーワードを使用することは、コードの記述の一部です。
-FC

@FCin他のいくつかの言語では明示的ではありませんが、必要な修飾子を必ずしも使用しない社内C#コードベースでも作業しました。
JG

だから、彼らはボブおじさんの本を読むべきです:)
FC

2

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

私の視点

私は、すばらしいコードではないこのようなプロジェクトの多くのメンテナーです。ライブラリは毎週数百万回ダウンロードされるため、互換性の問題のために、このようなコードの改善が妨げられることさえあります。

Node.jsのコアメンバーとして、触れるのが怖いコードの部分がありますが、関係なくやらなければならない多くの仕事があり、人々はプラットフォームを成功裏に使用して楽しんでいます。最も重要なことは、それが機能することです。

読み取り可能なコード

あなたが言う時:

それらの多くのコードは、きれいなコードを書くための原則からはほど遠いことがわかりました。たとえば、数百行のコードを含むメソッドです。

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

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

Linusは「有名なことです」と言っています。デバッガを使用している人はLinuxで動作するのに十分ではなく、もっと多くの人を引きつけたくないので、Linuxにはデバッガを組み込むべきではありません。

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


1

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

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

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

あなたは例を示していませんが、私の理解から、これはしばしば開発言語に関連しています。一部の言語では、最初から厳格なリンティング規則を実施し、重い単体テスト(またはTDD)を実施しています。通常、リンティングと単体テストの両方がその問題を防ぎます(複雑/長いメソッドの単体テストは困難です)。

一般に、ソフトウェアが1人の著者によって開発され、他の貢献者が小さな問題を修正するだけであれば、コードをきれいにするのは難しくなります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.