C ++の美しいコードとは何ですか?なぜほとんどのプログラマーはそんなに気にかけているのですか?[閉まっている]


8

ほとんどのプロジェクトはC ++ APIを使用しているため、APIの制約とプロジェクト自体の制約を扱います。

私はプログラミングの初心者ですが、OOPを使用するのは好きではありません。他のプログラマーが何らかの種類のデータ編成の一貫性を壊すのを防ぐためにプライベートスコープで制限することが非常に重要である理由を明確に誰も説明できなかったためです。

QtやOgre3Dのような素晴らしいものを作ることができるので、私はまだOOPで大丈夫ですが、それらはAPIであり、アプリケーションではなく、それらのコードは完璧である必要があり、誰も作業を批判できません。

ほとんどのプログラマーがAPIではなくアプリを作成しているため、なぜ天才的なコードを設計するような完璧なコードを作成し、これに時間を費やしたいのか、よくわかりません。


19
完全ではない古いコードに戻って機能を追加したり、バグを修正したりするための2年の猶予を与えてください。最初に、人々がそれをできるだけ正しく明確にすることに関心がある理由がわかります。周りの時間。
R0MANARMY 2011

(この質問)[ programmers.stackexchange.com/q/65216/8823]を参照してください。あなたがプログラマーではないからではなく、なぜ美しいコードが良いのかについての良い説明があるからです
オースティンハイド

2
この質問は、美しいコード、OOP、またはプライベートスコープについてですか?本当に分からない。
Sean McMillan

1
うわー...どこから始めればいいのかわからない。私はあなたのコードを見たり操作したりする必要がないことを願っています...
Rig

1
優れたコードと優れたAPIには、多くの共通点があります。優れたOOPコードには、適切に設計されたAPIとまったく同じように見えるインターフェースが必要です。
rwong

回答:


12

「誰も島ではないという言葉を聞いたことがありますか?

ほとんどのプログラマにとってこれは真実です。「単なるアプリ」であるコードを書く人はほとんどいない。重要なアプリの多くでは、1人のプログラマーがUIを作成しますが、UIはデザイナーが簡単に変更する必要があります。また、ビジネスロジック(Controller、ViewModel、または呼び出したいもの)への明確なデータバインディングを可能にする必要があります。別のプログラマーがそのコントローラーを作成しますが、これはしばしば非常に複雑になる可能性がありますが、フロントエンドプログラマーが簡単に使用できるように単純である必要があります。そのビジネスロジックコーダーは、データレイヤー(モデル、リポジトリなど)を作成した人からのコードを使用しています。OOPを使用する必要はありませんが、OOPが非常に優れているのは、インターフェースの背後でロジックをカプセル化できるため、作業している他の人がコードを壊すことなくコードを使用できるようにすることです(そのインターフェースをテストした場合)。抽象化は特効薬ではありません、

だから、あなたは今「真剣に、私は例外であり、誰も私のコードを見たり、コードで作業したりすることはない」と言っているかもしれません。十分に公平ですが、数か月後にそのアプリのバグを修正する必要がある場合、またはいくつかの機能を追加したい場合、そのコードを書いた人と今それを変更している人がいることがわかるでしょう全く違う二人。だらしないコードを書く理由の核心にあるものを覚えていると思うことがよくありますが、実際には、6か月後の自分は、アプリケーションに今行ったハッキン​​グを覚えていません。あなたの将来の自己は十分に対処するでしょう、それで彼/彼女に休憩を与えませんか?


43

どんな愚か者も、コンピューターが理解できるコードを書くことができます。優れたプログラマーは、人間が理解できるコードを作成します。〜マーティン・ファウラー

一言で言えば、それが美しいコードを気にしたい理由です。

コンピュータのコードを書く必要はありません。とにかく、コンピューターはバイナリコードのみを理解します(これは、コンパイラーとインタープリターを経由してソースコードから生成されます)。美しさや明快さ、またはコードが想定どおりに機能するかどうかは関係ありません。

あなたは仲間のプログラマーのためにコードを書きます。そして、彼らはあなたのために同じことをします。他の誰かが書いたコードを理解できない場合、バグを見つけて修正したり、新しい機能を追加したりする可能性は何だと思いますか?


1
完全に暗号化されたコードをC ++で書くのは特に簡単だと私は付け加えます。これが、この言語でこれがさらに重要である理由です。
deadalnix、2011

1
まあ、私はこの引用に本当に同意しません。再利用可能なコードは良いコードであり、真実ですが、言語は、プログラマーがより速く作業できるように作られ、必ずしも他のプログラマーに読まれる必要はありません。コードを読むのは骨が折れるので、コメントを入力するか、デザインを変更して人間が理解しやすくなるようにします。ただし、優れたデザインには常に「わかりやすい」とは限りません。プログラムは単純なタスクと複雑なタスクの両方を実行でき、プログラミング言語は洗練されたアプリを設計する方法を制限する可能性があります。プログラミング言語は、物事をより洗練されたものではなく、より簡単にします。
jokoon

3

もちろん、将来再びコードが必要になる可能性があるかどうかわからないように他の人が言ったことは当然です。

しかし、私にとって重要な点が1つあります。なぜ私は常に美しいコードを書こうとしているのかです。

良くなるためのトレーニングです。

使用する言語やプログラミングの一般的な概念について何か新しいことを学んだら、すぐにそれを活用しようとし、それを私の日常のワークフローとメンタルツールチェーンの一部にしようとします。

OOPのようなものについて読むだけなら、数週間以内にそのほとんどを忘れてしまいます。そして、小さな問題にそれを適用することによって独学しない限り、あなたはそれを大きな問題に適切に適用する方法のトレーニングを受けることは決してありません。

例:

プライベートスコープで制限することがなぜ重要なのですか?

小さなプロジェクトではそうではありません。一部の言語(Rubyなど)でも、この種のカプセル化はある程度妨げられています。しかし、それには用途があります。たくさんの。

そしてそれを使用すると、特定の問題とあなたが学ぶ必要がある多くの詳細が付属します。小さなプロジェクトでそれを使用すると、これがわかります。コンパイラーからは初めてのエラーメッセージが表示され、小さなプロジェクトでは問題の原因をより簡単に見つけることができます。

C ++の名前空間について学びます。小規模なプロジェクトではそれほど必要はありません。ヘッダーファイルとインクルードの一般的な構造についても同様です。小さなコードベースを保護することで、このすべてを早い段階で学ぶことができます。



1
  1. R0MANARMYがコメントで述べたこと。クリーンで「美しい」コードを使用すると、自分だけでなく、自分の後に来る他の人にとっても、将来の読み取り、理解、維持、変更、修正が容易になります。

  2. 一部の人々は、何かをするとき、それを可能な限り最善の方法で、可能な限り最善の方法で作ろうとするので、それは「完璧」、またはこの場合は「美しい」です。この一連の人々と開発者(私も含めて!)の間に大きな重複があることがわかりました。

ただし、「美しい」、「きれい」、「エレガント」は非常に主観的な用語であり、人によって異なることを意味します。私が見てきたことから、美しく、クリーンで、エレガントであると広く見なされているコード、

  • 読みやすく、理解しやすい
  • 不要なコードを配置しないか、ほとんど配置しない
  • 簡単に拡張および/またはモジュール化されている
  • 十分に文書化されている
  • 関連する言語/技術の標準に従います
  • そして、予期しないことは何もしません(たとえば、アクセサメソッドの副作用)

1

メンテナンス性について同意します。自分で比較的大きなプロジェクトを作成してみてください。バグの修正、新機能の追加など、すべての混乱が見られます。ただし、美しさについては、

(少なくともC ++)プログラミングはARTであるため、美しいコードは望ましい製品品質です。


1
ラムダの導入により、ホルムアルデヒドに含まれるサメは減少しましたが、
Martin Beckett

1

[...]他のプログラマーが何らかの種類のデータ編成の一貫性を壊すのを防ぐためにプライベートスコープで制限することが非常に重要である理由をはっきりと説明できる人は誰もいません。

十分に小さなコードベースを備えた十分に小さなチームで、優れた標準(たった1人)と十分に調整されている場合、誰でもすべてのデータフィールドを操作できるように、すべてのデータを公開する信頼できるソフトウェアを見つけることができます。struct大きく開いたとして暴露structアクセスにそのヘッダを含む誰のための広いオープン定義。マーフィーの法則は、これらの場合に常に適用されるわけではありません。

しかし、私は、数百万のLOCがあり、80年代にさかのぼる巨大なコードベースの反対のシナリオで作業してきました。かろうじて同じ言語、人々がとにかく従わないことが多いSDK以外のコーディング標準、ユニット/統合テスト、ブランチなしのSVNの使用、場合によってはコードをチェックインせずに6週間、バグで爆破すること、およびそれまでは、情報を隠蔽して不変条件を維持することの価値を本当に理解していました

私は自分のマシンで一貫して問題を再現することさえできず、時にはチーム全体の間で誰もできなかったバグに対処しました。そして、あらゆる種類の試行錯誤の後で、ユーザーから報告された問題またはそれに似た問題をようやく幸運に再現できたとき(そして、試行錯誤は、ソフトウェアの非効率性とユーザーエンドの生産に対するデバッグでの実行との組み合わせにより、多くの場合、数時間かかりましたデータは、データをロードするためだけに15分以上かかることがよくあります)。文字列の長さがのようなガベージネガティブ数に設定されstructている文字列型の場合は、までトレースします。len-921141282

それは決して起こらないはずですが、誰がそれをしたのですか?したがって、メモリブレークポイントを設定して調べる必要があり、最終的に設定したとき、それは、初期化されていない変数の算術演算のカスケード相互作用のようであり、最終的には文字列lenフィールドが負のガベージ番号に設定され、そのコードにはありませんでした数年で変更されました。それはレーダーの下を飛んだ。

そして、すべてその時、このような多くのバグに遭遇した後、私はそれだけで使用した場合どのくらいの、より信頼性の高い当社のソフトウェアは次のようになり、自分自身に考えたgetterssetters?ゲッターとセッターは一般に、可能な最悪の種類のインターフェース設計を示しますが、誰かが文字列の長さを負の値に設定しようとした場合、セッターは少なくともアサーションエラーをトリガーする可能性があります。私たちはそのバグのを捕まえることができた以前は秒単位で導入された正確な時間であり、何時間もの調査努力の集大成ではありません。そして、それは開発者として利己的に考えているだけです。ユーザーとQAチームを救うことができた悲しみのすべての時間をカバーしているわけではありません。あなたが徹夜で修正した最近の35のバグに直面してセッターとゲッターを使用した場合、システムがどれほど良くなるか夢見ているときに、システムがかなり悪い場所にあることを知っています。

structsこれらのデータフィールドにアクセスするシステム内の場所を見つけるためだけに、他の誰もこれらのデータフィールドにアクセスするべきではないという方法で文書化されたケースさえありました。

したがって、これらは、最悪のシナリオに直面することによって本当に最大限に感謝することができるものですが、十分に調整されたチームと小さなコードベースで残りの人生を過ごすのに十分な運がなければ、多くの場合そうなるでしょう。強力なコーディング標準。

C ++の美しいコードは何ですか[...]?

それは難しいことです。私はまだそれを理解しようとしています。私が長年にわたって書いた、または少なくとも信頼性が高く、比較的時代を超えて安定している(変更を必要としない)少なくとも、私が美しく考えるコードのほとんどはCで、最近はLuaで書かれました。私はまだ、数年後にそれを振り返ることができず、少なくともそれを変更できればよい思うまで、時の試練に合格しているように見えるC ++コードを書くのに苦労しています。C ++ 11からずっと簡単になっているように感じますが、変更を確認せずにコードがどれだけうまく機能しているかを確認するには、何年か必要です。私にとっての究極の「美しさ」は「安定性」です。それ以上の変更を必要とせず、誘惑すらしなくても、関連性があり、今後何年にもわたって役立つコードのように、


0

さて、クリーンで有用な(「美しい」は不十分な修飾子です)インターフェースを定義することは、すべてを確認することです:

  1. ユーザーは、インターフェースを読むだけで、オブジェクト(またはオブジェクトのシステム)の使い方を最小限の苦痛で理解できます。
  2. ユーザーはオブジェクト/システムを間違った方法で使用するのに苦労します-インターフェースは何か間違ったことをしたり、問題を早期に知らせたりするのを難しくします。
  3. インターフェースは、有用な抽象化を記述します。

ポイント1.および2.では、ユーザーとの契約について多くのことを考える必要があります。その契約、つまりプロトコルは、ユーザーがシステムをどのように使用できるかをユーザーに伝える方法です。たとえば、読み取り専用メンバー関数(constメンバー関数)は、その関数を呼び出すことができるはずの状況で多くのことを伝えます。同様に、各機能の属性により、ユーザーはシステムを機能させるために必要な最小限の情報を収集して提供することができます。

すべての点をまとめると、インターフェースはユーザーに役立つサービスのみを表示する必要があることを示唆しています。最初に、ユーザーによるシステムの使用を、システムが作成された目的のみに制限する。第二に、彼が内部状態を間違った方法で操作することを避けることによって。したがって、C ++でこれを実現する最も簡単な方法は、メンバーまたはグローバル関数(名前空間内)を使用して、すべてのメンバーをプライベートにし、システムが提供するサービスを明示的に示すことです。別の方法は、PImplイディオムを使用することです。

第三に、そして最も重要なことは、インターフェースが有用な抽象化を提供することです。これは、ユーザーが実装を理解する必要がないことを意味します。車や洗濯機を運転しているとき、それがどのように構築されているのか知りたくありません(たとえ私がテクノロジーオタクだったとしても...)。私はそれを使用する必要があるだけで、中身を気にする必要はありません。

それは難しい。

プログラミング言語の設計やクラスの設計などのプロトコル定義は、最初に考えたほど明白ではありません。インターフェースの設計の細部を理解するには、多くの経験が必要です。

非常に低レベルの概念を表す構造またはクラスを定義しているときは、これらすべては面白くありません。ハードウェアのレベルが高くなるほど、クリーンで明確で有用なインターフェースが必要になります。

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