5

何年も前に、誰が最も難読化された C コードを生成できるかを競うコンテストが行​​われ、結果の一部は劇的に判読不能になりました。C.がそうだった。特にプリプロセッサを使用すると、本当に問題が発生する可能性があります。

ただし、C# の新しい機能の多くは、コードを難読化する素晴らしい機会を提供します。コードの簡潔さと明快さの適切なバランスを見つけることについて、誰か意見があるかどうか疑問に思っていました。議論のために一例を挙げましょうListView。(はい、データバインディングでできることは知っていますが、ここで私と一緒に行ってください。)

コントロールは、次の配列で満たされる 2 列です。

struct Person
{
    public string name;
    public string address;
};

1つの明確で簡単な方法は次のとおりです。

private void Fill(Person[] people)
{
    foreach(Person person in people)
    {
        string[] columns = new string[2];
        columns[0] = person.name;
        columns[1] = person.address;            
        ListViewItem item = new ListViewItem(columns);
        listView1.items.Add(item);
    }
}

明確でわかりやすい。

次のように書くこともできます。

private void Fill(Person[] people)
{
    foreach(Person person in people)
    {
        string[] columns = new string[] { person.name, person.address };
        ListViewItem item = new ListViewItem(columns);
        listView1.items.Add(item);
    }
}

あるいは:

private void Fill(Person[] people)
{
    foreach(var person in people) // Note use implicit typing here
    {
        listView1.items.Add(new ListViewItem(
        new string[] { person.name, person.address }));
    }
}

最後に、次のように書くこともできます。

private void Fill(Person[] people)
{
    Array.ForEach(people, item =>
    listView1.items.Add(new ListViewItem(
    new string[] { person.name, person.address}));
}

それぞれが多かれ少なかれ、言語のさまざまな新機能を使用しています。簡潔さと明快さのバランスをどのように見つけますか? 難読化された C# コンテストを毎年開催する必要がありますか?

4

6 に答える 6

26

何が難しいか知っていますか?他の人が読んで維持できるコードを書く。どんな馬鹿でも、コンパイル可能で保守不可能なコードを書くことができます。

常に保守性を優先してください。それがバランスを見つける方法です。

編集:

「どんな愚か者でも、コンピューターが理解できるコードを書くことができます。優れたプログラマーは、人間が理解できるコードを書きます。」

  • Martin Fowler 著、リファクタリング: 既存コードの設計の改善

上記の引用を見つけてくれたroygbivに感謝します。彼の引用を殺したファウラーに謝罪します。以前に読んだことは知っていたのですが、場所を思い出せませんでした。

于 2010-01-23T21:52:16.107 に答える
6

すべてを 1 行に詰め込んでも、「難読化」にはなりません。不必要に多くのスクロールが必要になるだけです。C# を知っている人にとっては、提示された例を理解することはまだ簡単です。また、改行を使用した場合、他の例よりもはるかに優れているか劣っているものはありません。

于 2010-01-23T21:58:08.997 に答える
2

可読性を最大限に高めるためのコードですが、次のとおりです。

  1. 余分な冗長性と構文上のノイズが可読性を損なうことに注意してください。より簡潔な表記によって意図をより直接的に表現できる場合、より簡潔にすることで可読性が向上する可能性があります。たとえば、実際のラムダ関数を単一メソッド インターフェイスでシミュレートする場合と比較してください。

  2. あなたのコードを読む他の人々はまともなプログラマーであり、あなたが使用している言語を知っていると仮定してください。言語弁護士レベルの知識を仮定するのではなく、実用的な知識を持っていると仮定してください。コード モンキーがコードを保守しやすくなるかもしれませんが、実際に何をしているかを知っているメンテナンス プログラマーとあなたの両方を悩ませることになるため、最小公分母に合わせてコーディングしないでください。

より具体的には、例 1 には、非常に単純なものに対して構文上のノイズが多すぎます。例 4 は、人間が解析するのが非常に困難です。2 と 3 はどちらもかなり良いと思いますが、例 3 の場合は、人間がすべての関数呼び出しのネストを簡単に解析できるように、少し再フォーマットします。

private void Fill(Person[] people)
{
    foreach(var person in people)
    {
        listView1.items.Add(
            new ListViewItem(
                new string[] { person.name, person.address }
            )
         );
    }
}

これで、両方の長所が得られました。人間が簡単に解析でき、余分で不必要に冗長な一時変数がありません。

編集:また、暗黙的な変数の型付けを使用すると思います。つまり、varほとんどの場合は問題ありません。暗黙の型付けが唯一の種類の型付けである動的言語では、人々は完全に読みやすいコードを記述します。ほとんどの場合、変数の正式な型は、コードの高レベルの意図とはほとんど関係のない低レベルの詳細です。

于 2010-01-24T00:40:50.657 に答える
1

少なくともここで提供する例に関しては、最後の例に到達するまで、難読化が進むとは思わない。それでも、あいまいさの唯一の理由はラムダの存在であり、慣れるまでに時間がかかります. したがって、初心者は最後のものに問題を抱えているかもしれませんが、古い野生の C 競争のエントリが読めなかったように、他のものが読めないことに気付くべきではありません。

違いは、これらの C# の例はすべて同じレベルの抽象化にあるということです。より簡潔な例では、単に「綿毛」が取り除かれます。C では、A) 任意に名前が変更された/エイリアスが設定されたコンストラクト、および B) 1 つのステートメントにバンドルされた複数レベルのメモリ アクセスにより、あいまいさが生じる可能性があります。

全体として、どの言語でもコードを不明瞭にすることができますが、C# が C のようにその傾向があるとは思いません。実際、より高度な言語を使用している場合でも、多くの言語よりも明確な言語であると思います。構成します。

于 2010-01-23T21:55:33.403 に答える
1

C# および VB.NET 言語は、C よりも高いレベルで動作するため、より明確にするために設計されました。C は、いわば金属に近いプログラミングです。C のように難読化された C# を記述することは設計上不可能です。

「どんな愚か者でも、コンピューターが理解できるコードを書くことができます。優れたプログラマーは、人間が理解できるコードを書きます。」

  • Martin Fowler 著、リファクタリング: 既存コードの設計の改善
于 2010-01-23T22:32:56.523 に答える
0

この例が難読化されているとは思いません。

まず、意図が非常に明確であるため、初心者はコードを理解しないよりもラムダが何をするかを学ぶ可能性が高くなります。これは、より「高度な」テクニックを使用するのに最適な場所です。自分が何をしているのかわからない人でも、自分が何を「すべき」かを理解しています。

第二に、上記のすべては難読化されていないだけでなく、完全に慣用的な C# です。最後の 1 つは、ほとんどの人 (私が使用したことのある) が LINQ を利用する Array.ForEach があまり広く使用されていないため、おそらくそれほど多くはありません。

于 2012-11-28T12:56:37.893 に答える