共有コーディングパラダイムを使用するという点で、言語Yでプログラムを記述しているように、言語Xで何かを記述するのがなぜ悪いのか[非公開]


25

しばらく前に、私はC ++で書かれた何かについてのSOの質問をし、代わりに手で問題に答えを得るための、コメントは、私はそれがあることが示された場合でも、私のコーディングスタイル上のすべての大騒ぎWIPのコードの一部そして、ベースケースを実行させたときに、後でクリーンアップするつもりだった。(私は非常に多くの票を集めたので、私はSOの担当者がすでにほぼ最悪であるため、質問を撤回することにしました)

なぜ人々は「あなたは初心者だ、自分で性交をする」という厳しいラインを採用するのだろうと思いました。私は、あたかもJavaであるかのようにC ++を書いていると非難されていました。私が理解できない何か、それでも私を困惑させます。

私は、間隔を置いてではあるが、何年もの間、かなりの数のOOP言語でプログラミングを行ってきました。使用可能なライブラリと、手元のジョブに最適な実行環境の観点から、使用する言語を選択します。私はOOPコードにデザインパターンを採用していますが、パターンの使用は適切であり、オブジェクト指向では賢明であると確信しています。私はOOPツールボックスを理解していますが、コーディングの知恵を示すためにきちんとしたトリックを使用するのではなく、本当に必要だと思うときにのみツールを使用することを選択します。(私が知っているのは一流ではありませんが、n00bレベルでもないと思います)。

1行書く前にコードを設計します。テストを定義するために、特定のクラスの目標と、クラスが順守しなければならないテスト基準をリストします。シーケンス図を作成してコードを書く方が簡単なので、インターフェイスが明らかになった後にテストを書くことにしました。

質問で投稿したコードの一部で、スマートポインターを使用する代わりに、ポインターを使用していることを認めなければなりません。できる限りRAIIを使用しています。適切なRAIIとは、nullpointersに対する保護を意味しますが、徐々に作業を進めます。それは進行中の作業であり、後でクリーンアップするつもりでした。この働き方は強く非難されました。

私の見解では、基本ケースが実行可能な思考方法であるかどうかを確認できるように、最初に実際の例を用意する必要があります。また、ベースケースが証明された後、コードのクリーンアップはアジャイルのリファクタリングフェーズの典型的なことだと思います。私はゆっくりとCxx標準を取得していますが、実稼働コードでまだ習得していない概念を使用するリスクを負うのではなく、理解しているものを使用することを好みます。たまに新しいものを試すこともありますが、通常はその目的のために、私が脇に置いているプレイプロジェクトでやっています。

[編集]質問を始める前に、gnatの提案[1]が検索に表示されなかったことを明確にしたいと思います。ただし、彼の提案は質問の1つの側面をカバーしていますが、彼がリンクした質問は私の質問の核心ではなく、その一部にすぎません。私の質問は、自分のコーディングスタイルに対する応答と、さまざまなコーディングスタイルと(見かけの)レベルのスキルを処理する専門的な側面についてです。SOについての以前の質問と、それが適切な事例としての回答です。[/編集]

質問は次のとおりです。あなたのコーディングスタイルを使用していない人をsc笑するのはなぜですか。

手元にある問題/下位区分は次のとおりです。

  • リファクタリングにより後で堅牢になった場合、プロトタイプの状況でエラーが発生しやすいコードを使用するのはなぜプログラミングの悪い習慣になるのでしょうか?
  • C ++で書かれたプログラムは、Javaで書かれたようにどのようにできますか?何が悪いプログラムになっているのですか(現在のスタイルの意図と改善する予定の作業を示したと考えていますか?)
  • 特定のプログラミングパラダイム(たとえば、OOP / DP)で使用される構造を使用することを選択した場合、どのように悪い専門家になりますか?

[1] 高速でバグのあるものを開発し、エラーを修正するか、コードの各行に注意して遅くしますか?


5
The C ++ Loungeの人々にこの質問をする方が良いかもしれません。最初に防炎スーツを着用してください。
ロバートハーヴェイ14年

48
C ++の人々はプログラマーの間では珍しい品種です。お使いのJavaツールキットは、あらゆるツールショップで使用できるパッド入りのレザーケースに馴染みのあるツールを備えた、賢明で十分に理解されているツールボックスです。C ++は、リップソー、電動ドリル、および誰も認識していないいくつかのツールを備えた完全なツールです。これらはすべて、忍者のように処理できます。誰かが入って来て、ツールを棚の間違った場所に戻すと、彼らを苦しめます。彼らはプログラマーの「2度測定、1度カット」です。
ロバートハーヴェイ14年

13
たぶん、FORTRANのように書かれたJavaコードに対するあなたの反応と同じ反応でしょう:単一クラスのすべてのコード、コレクションなし、固定サイズの配列のみint、実際の長さを追跡するための個別の変数。
ケビンクライン14年

14
JavaのようなC ++を作成すると、ヒープ割り当てが多すぎることになり、プログラムのパフォーマンスが低下する可能性があります。言語は特定のパターンを促進するように設計および最適化される傾向があり、これらのパターンを破ると、事態は悪化する傾向があります。
ロボットをゲット14

5
何らかの形で助けを得るためにコードをオンラインで投稿しました。あなたはあなたのスタイルに関するすべてのフィードバックを望んでいない/期待していないことを理解していますが、まったく助けを望まないでしょうか?あなたは善と悪を共にします。プログラマは、コード内の障害を探す必要があります。それが私たちの仕事です。
ジェフ14年

回答:


26

問題のコードを見ずに、C ++でJavaコードを作成する方法はいくつかありますが、他の方法よりも悪い方法もあります。

  1. 極端な場合、Javaのようなソースをレイアウトします。1つのファイル内のすべて、クラス定義内のすべてなどです。
    class HelloWorldApp {
    public:
        void main() {
            cout << "Hello World!" << endl;
        }
    };
    
    これが、Javaソースのレイアウト方法です。C ++では技術的には合法ですが、すべてをヘッダーファイルに配置し、すべてをインラインで(クラス宣言で定義することにより)ひどいスタイルにし、コンパイルパフォーマンスを低下させます。しないでください。
  2. 過度にオブジェクト指向-単純化しすぎると、Javaでは、すべてがオブジェクトである名詞王国です。良い(つまり慣用的な)C ++コードは、すべてをオブジェクトに詰め込もうとする代わりに、無料の関数やテンプレートなどを使用する可能性が高くなります。
  3. RAIIなし-あなたはすでにこれについて言及しました-スマートポインタの代わりにポインタと手動クリーンアップを使用しています。C ++はRAIIやスマートポインターなどのツールを提供するため、優れた(つまり慣用的な)C ++コードはこれらのツールを使用します。
  4. 高度なC ++はありません-JavaとC ++の基本は十分に似ていますが、より高度な機能(テンプレート、C ++のアルゴリズムライブラリなど)に入ると、それらは分岐し始めます。

#1を除いて、これらはいずれもC ++プログラムを悪いプログラムにするものではありませんが、C ++プログラマーとして作業することを好む種類のコードでもありません。(私は非イディオマティックまたはCスタイルのPerl、非イディオマティックPythonなどと一緒に作業するのも楽しみではありません。)言語には独自のツールとイディオムと哲学があり、優れたコードは使用する代わりにそれらのツールとイディオムを使用します最も一般的な分母または別の言語のアプローチを再現しようとしています。特定の言語/問題領域/その他で非イディオマティックなコードを書くことは、誰かを悪いプログラマーにしない、それは単に彼らがその言語/問題領域/その他についてもっと学ぶ必要があることを意味します。そして、それは何の問題もありません。私がもっと学ばなければならないことの非常に長いリストがあり、特にC ++には学ぶべきものがたくさんあります。

後でクリーンアップする目的でエラーが発生しやすいコードを記述するという特定の質問に関しては、白黒ではありません。

  • いくつかのプロトタイプコードが考えられるすべての例外と考えられるすべてのコーナーケースを処理できない場合、それは予想されることです。動作させてから、堅牢に動作させます。問題ない。
  • 単に悪いスタイルまたは悪いデザイン(特定の言語とそのイディオムに悪い、問題に対する根本的に悪いデザインなど)でプロトタイプコードが記述されている場合、それをスローアウェイとして書いていない限り概念実証、あなたは何も得ていません。

例として生のポインターとスマートポインターを使用する場合、C ++で作業する場合、RAIIとスマートポインターを使用することは十分に基本的であるため、後で戻ってクリーンアップするよりも、そのようにコードを記述する方が高速です。繰り返しますが、これを怠ることは、誰かが下手なプログラマー、プロではない、などを意味するわけではありませんが、学ぶべきことがまだあるということです。


11
慣用的なperlがありますか?
ラチェットフリーク14年

21
@Onno 「このネジを曲げずに壁に打ち込むにはどうすればいいですか?」誰もがハンマーを使用しないことを教えてくれます。
シェード14年

9
@Onno C ++では、ポインタとnewはパワーツールと見なされます。自動保管はハンドツールです。
シェード14年

9
@Onno:C ++プログラミングコースは現代のイディオムの採用に遅れがちであり、C ++が発明されて以来、優れたC ++と見なされるものも大きく進化していることを理解する必要があります。
バートヴァンインゲンシェナウ14年

7
C ++の歴史、および言語のより高度な機能の多くが登場する前に言語を学んだ膨大な数のコーダーのために、10年前と同じように書く人によってまだ書かれたくだらないC ++がたくさんあります。RAIIのようなことの難しさは、誰もが最新の方法を使用できるようにすることです。これにより、同じ予測可能な障害の発生を止めることができます。
ロボット

42

各プログラミング言語には一連のイディオムとベストプラクティスがあり、通常はエレガントで正確でパフォーマンスの高いコードになります。他の言語では完全に問題のない、いくつかの最悪のプラクティスを次に示します。

  • for ($i = 0; $i < 42; $i++) { … }PHPではなくPerlで書くと怒ります
    (Perlでは、変数を宣言する必要があり、そのようなループは範囲で繰り返す必要があります)
  • new Foo()正当な理由なしにC ++で書くが、Javaで書かないと泣きます
    (C ++にはガベージコレクションがないため、RAIIを使用する必要があります。それ以外の場合、Noobsはメモリをリークします)
  • C89、Pascal、またはJavaScriptを除き、関数の先頭ですべての変数を宣言する場合、私はうんざりします。
  • すべての関数をPythonのクラスに配置し、Javaのクラスには配置しない場合(私は
    代わりに「OOP」を強制し、最上位の関数をサポートするマルチパラダイム言語です)
  • return nullScalaの場合は泣きますが、Cライクな言語ではありません
    (ScalaにはOption型があるため)
  • OCamlではなくJavaで再帰アルゴリズムを記述した場合、文句を言います
    (OCamlには末尾呼び出しの最適化がありますが、Javaのスタックはすぐにオーバーフローするため)

新しい言語は、あなたが知っているものであるかのように簡単に使用でき、運が良ければ機能します。「Fortranは任意の言語で作成できます」。しかし、XがUを上回る利点を提供する可能性が高いため、言語Xが提供する特定の機能を無視したくないのです。

使用可能なライブラリと手元のジョブに最適な実行環境の観点から使用する言語を選択します」-しかし、この言語Xが手元のジョブの言語Uよりも実際に優れているかどうかは、その言語に精通しているか、それを上手に使用するために十分な知識を得るまでにかかる時間。古いペンナイフがあなたの手に完全にフィットするので実際に欲しいとき、それは木材を最も速く切るからという理由だけで重いチェーンソーを生み出さないでしょう。あなたが実際に木を倒したくない限り。

しかし、あなたの質問は文化的な問題に関するものです。すべてのベストプラクティスを学ぶには多くの時間がかかり、初心者はほとんどの質問をしますが、教祖は答えます。しかし、グルにとって明らかなことは初心者にとっては明らかではなく、グルはそれを忘れることがあります。初心者としての解決策は、質問をやめることではありません。しかし、人は学び、によってベストプラクティス、例えばを適用するために開放性を示すことができるしようとして可能な限りあなたのコードをクリーンアップする前に、他の人にそれを示します。ほとんどの言語には、学習曲線全体が実際には非常に長い場合でも、学習しやすいいくつかのコアベストプラクティスがあります。

よくある問題は、プログラミングの初心者がインデントやその他の書式設定を無視し、プログラムが機能しないために混乱することです。私も混乱するでしょうし、プログラムを理解するための最初のステップは、それが完全にレイアウトされていることを確認することです。そうすると、忘れられていた閉じ引用やカンマの欠落などの単純なエラーが突然明らかになります。あなたはすでに良いフォーマットを実践していると信じていますが、ここでは他のベストプラクティスの比metaです:ベストプラクティスはエラーを防ぎ、ベストプラクティスはエラーを見つけやすくし、ベストプラクティスは問題を見つける前に適用されます

「後で修正します」と言うのは安すぎます。今すぐ修正すれば問題が解決します(また、伝説の「クリーンアップフェーズ」が来ることはないので、唯一の責任あるオプションは、初めて)。少なくとも、他の人に助けを求める前に、できる限りあなたのコードを良くしようとすることは、彼らがあなたのコードについて推論することを容易にします。


いくつかのポイントについては正しいと思いますが、最終的にはあなたがマークを打っているとは思いません。あなたは知識を獲得する経験をする前に知識の達成を前提としている。
オンノ14年

4
@Onno私の主なポイント(あなたが尋ねた質問に答える)は、ある言語の習慣を引き継ぐことができず、それが別の言語のベストプラクティスであると仮定し、最初からきれいなコードを書くことは掃除よりも好ましいことです後でそれを。他の人に助けを求める前に、コードを(できる限り)クリーンアップする必要があります(優れたコードスニペットのヒントについては、sscce.orgを参照してください)。「これを修正してください」とSOにゴミコードをダンプすることは、特によく知っている場合は受け入れられません。
アモン14年

2
しかし、あなたがほのめかしている質問に関して:jm666の答えには重要なポイントが含まれています:教祖は「自分がXグルになりたくないのに、なぜXについて尋ねるのか」と考えます。 。これを解除する方法の1つは、まだ学習曲線の最初の段階にあり、後で検討することですが、現時点ではこのより直接的な質問があることを言及することです。ただし、それは通信の問題であり、プログラミングの問題ではありません。
アモン14年

6
C ++とC#の両方にそれぞれoptional<T>とがありNullable<T>ます。また、RAIIを使用せずに、実際には誰もがC ++でメモリをリークします。
DeadMG 14年

通常、ブロックの先頭で変数を宣言すると、ほとんどの言語でコードが読みやすくなります。このようにして、すべての変数がどのタイプであるかなどを覚えておく必要があるときに、どこを見ればよいかを正確に知ることができます。
レリッシュ

12

私は筋金入りのC ++開発者ではありませんが、...

リファクタリングにより後で堅牢になった場合、プロトタイプの状況でエラーが発生しやすいコードを使用するのはなぜプログラミングの悪い習慣になるのでしょうか?

覚えておくべきことの1つは、C ++のエラーは通常「未定義の動作」を意味するということです。安全な言語では、起こりうる最悪の事態は、プログラムを即座に終了する例外です。C ++では、セグメンテーション違反が発生した場合は幸運です。あなたのプログラムが微妙に何か間違ったことをし続ける可能性は完全にあります。また、一定期間は正常に動作し、バグはかなり後に発生することもあります。

いずれにせよ、プログラムの実行を完全にレールから切り離して未知の領域に移すのに、たった1つのミスが必要です。フルタイムのC ++開発者にとって、「基本ケース」とは「未定義の動作やメモリリークの可能性がない」ことを意味する可能性があります。

C ++で書かれたプログラムは、Javaで書かれたようにどのようにできますか?何が悪いプログラムですか?

私はこれに対する答えはほとんど推測的で意見の多いものではないと思います。ただし、Javaを使いたい場合、Javaには、すべてがオブジェクトでなければならないという事実のような、いくつかのアンチパターンが関連付けられている傾向があります。他の言語であなたがポインタ、ファンクタ、または関数を渡すたい場合は、Javaで、あなたは通常、空虚と狭く、便利なのトンを見つけるThingDoersFooFactoriesIFrobnicators変装だけの機能です。

同様に、他の言語では単純なタプルまたは名前のない構造体を渡すことができますが、Javaでは2つのオブジェクトのみを単純なデータコンテナにバンドルするには、30行以上のNamedThingクラスをsetter、getter、およびJavadocsで事前に定義する必要があります。Javaの機能が比較的不足しているため、プログラマーはオブジェクト指向の二重バックフリップを実行して、時々物事を成し遂げなければなりません。結果のコードは、Java以外ではめったに慣用的ではありません。

次に、C ++では、メモリを手動で管理するために非常に単純化されたオブジェクトグラフが必要であるという事実があります。通常、オブジェクトは他の1つのオブジェクトによって所有されます。Javaでは、ガベージコレクターは参照がなくなったときにクリーンアップされることを保証するため、このような厳しい制約に従う必要はありません。したがって、コードをJavaからC ++に書き直しただけでは、間違いのあるメモリ管理のリスクが必ずあります。

最後に、それはエリート主義である可能性があります。私は彼らが大多数を占めるふりをするつもりはありませんが、C ++開発者の間で「手をつないでバカなことをさせない言語は必要ない」という感情を見たことは間違いありません。彼らの心では、C ++は「本物の」言語であり、その特異性を処理できないなら、あなたは「本物のプログラマ」ではありません。


1
これの多くはJava 8で軽減されます-ラムダスはほとんど日を節約するために乗ります:
Martijn Verburg 14年

@MartijnVerburg Agreeed、そこへの大きな前進。しかし、技術的な問題は簡単に修正できます!古い習慣は激しく死に、スティグマはさらに難しくなります。ちなみに、Javaにはこれらの「新しい」機能は不要であり、次のC ++になろうとしていると不満を言う人もいます。
ドーバル14年

うん、私はいつもそれで私の頭を振る- Javaの意志、意図的に常に進化もっとゆっくり他の言語よりも、それは長期的な主力製品だと。しかし、JVMは飛躍的に多少速くジャンプできるため、Lambdasのようなものが最終的に言語に到達できるようになります。
Martijn Verburg 14年

6

トピックから少し外れた答え...

心配しないでください-これは、どの専門家コミュニティでも一般的な「動作」です。そして、正直に言って、あなたがどんな言語でも上手で、「奇妙な」コードに出会うなら、おそらくあなたもそれを批判するでしょう。(なぜなら、TEACHが必要だから)。

私はperl-worldにいます-次のようなものが表示されます:

$imax=$#array;
$str=""
for($i=0; $i<$imax; $i++) {
    $str = "$str" . $array[$i];
}

の代わりに:

my $str = join '', @array;

必ずコメントしてください-(読む:著者に教える)join関数について。

とにかく、あまりにも多くの批判はまったく逆効果であり、最良の例の1つは次の例です(http://perl-begin.org/humour/#How_can_I_switch_off_the_T.V..3Fから取得

(このビットは、2011年3月23日に匿名でpastebotに投稿されました。編集後、後世のためにここに配置されます。)-少し編集されました

質問:テレビを切り替えるにはどうすればよいですか?

OPが聞きたいことは何ですか?

例:テレビのリモコンのオン/オフボタンを見つけて押します。通常、ボタンは赤で、リモコンの一番上の行にあります。

#perlエキスパートの答え:最初に、「スイッチオン」とはどういう意味ですか?最初に定義します。テレビ、テレビのリモコン、リビングルームも貼り付けません。

... nopasteの後:

あなたの部屋はいです。そして、テレビはひどく見えます。画面でMr. Cleanを使用し、最初にリビングルームを掃除します。2つではなく3つのクリーニングモップを使用します。本当に必要な場合を除き、HDMIを使用し、スカーター(?)コネクターは使用しないでください。テレビのリモコンに判読できないボタンがあります。最初にクリーンアップしてください。あなたは初心者なので、読んでください:

http://experts.blog/how_to_design_a_future_3D_TV.html http://experts.blog/the_basics_of_tv_repairing.html http://experts.blog/viruses_in_living_room_short_essay.html http://experts.blog/global_chip_replacement_guide.html

IRCゲスト:しかし、私はテレビの専門家になりたくありません。

回答:なぜテレビをオンにしたいのですか?!


1
この答えは話題外ではありません。なぜ誰かが型にはまらない言語の使用を批判するのか、そしてなぜその自動批判が行き過ぎになるのかを正確に説明しています。私はそれが好きです。
センモウヒラムシ

1

リファクタリングにより後で堅牢になった場合、プロトタイプの状況でエラーが発生しやすいコードを使用するのはなぜプログラミングの悪い習慣になるのでしょうか?

後で修正することを念頭に置いて迅速かつ汚い文章を書くとき、修正する必要があるものを忘れる危険があります。

C ++で書かれたプログラムは、Javaで書かれたようにどのようにできますか?何が悪いプログラムになっているのですか(現在のスタイルの意図と改善する予定の作業を示したと考えていますか?)

javaでは、特定のオブジェクトの所有者について考える必要はありません。参照を渡すだけで、それが何もないように忘れます。ただし、C ++では、オブジェクトの所有者とそのクリーンアップの責任者を明確に定義する必要があります。

特定のプログラミングパラダイム(たとえば、OOP / DP)で使用される構造を使用することを選択した場合、どのように悪い専門家になる

あなたはしません; C ++はマルチパラダイム言語であり、OOPをかなりよくサポートしますが、他にも多くのことができます。ただし、ほとんどの場合、先のとがったスパイクを木に打ち込む必要があるたびにハンマーを抜くのではなく、作業に適したツールを使用することになります。

あなたが悪い反応を得た理由は、SOのほとんどの人があなたが尋ねている言語でどれくらい慣用的にコーディングできるかによってスキルを判断する傾向があるからです。C ++に精通している人は、過去に噛みついたような悪いコードを見たときにひざまずく傾向があります。


改善を忘れることは一部の人にとっては問題になるかもしれませんが、私はタスクの長いリストを保持しており、この種のジョブにtodoタグを追加することは非常に規律があります。(だから私はVSが好きです。作業管理が非常に得意です)ドキュメントについても同じです。ドキュメントを作成する前にコード行を作成しません。所有権の質問については、シーケンス図のために、だれが誰にリンクを持っているのかをよく知っていると思います。
オンノ14年

1
@Onno:率直に言って、誰もあなたがそのようなものを追跡するのがどれだけ上手かを知らないか気にしません。JavaやCのように見えるC ++を書く人の大部分は、それほど細心の注意を払っていません。経験から、実際にそれを実際に行うことはないことが示されているため、メモを書いて後で修正するよりも、最初に正しいことを学ぶ方がはるかに優れています。
cHao 14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.