2017-07-10 35 views
2

これは簡単な質問かもしれませんが、私はいくつかの説明を必要とします... 私たちのメソッドは、好ましくは5-10行まで、小さくする必要がありますと言うクリーンコードと呼ばれる本があります。そのためには、メソッドを小さなものに分割する必要があります。 たとえば、次のようにsomeMethod()があるとします。たとえば、「Example」の変更には5行が必要で、別のメソッドに移動して「Example」を修正してsomeMethod()に戻すことにします。これを行うことによって、someMethod()は小さくなり、読みやすくなります。それはいいですが、「副作用」と呼ばれるものがあります。これは、オブジェクトを別のメソッドに渡してそこで変更するべきではないということです。少なくとも、私はそれは悪い考えであると言われました)しかし、私はClean Codeでこれを禁止する何かを見たことはありません。Javaメソッドの副作用

public Example someMethod() { 

    // ... different lines here 

    Example example = new Example(); 
    example = doSomethingHere(example, param1, param2, ...);  

    // ... different lines here 

    return example; 
} 

private Example doSomethingHere(Example example, 'some additional params here') { 

    // ... modify example's fields here ... 

    return example; 
} 

だから、私は方法をこの方法や、そのような副作用を分割させて頂いて禁止され、代わりに私は間違いなく短い方法について話してクリーンなコードのルールを破るかなり長いライン法に対処すべきか? UPDATED


(サブメソッドのためのより具体的な名称)

public Example someMethod() { 

    // ... different lines here 

    Example example = new Example(); 
    example = setExampleFields(example, param1, param2, ...);  

    // ... different lines here 

    return example; 
} 

private Example setExampleFields(Example example, 'some additional params here') { 

    // ... modify example's fields here ... 

    return example; 
} 
+5

doSomethingHere()でサンプルを作成して返さないのはなぜですか?または少なくともこのメソッドからvoidを返しますか?メソッドの唯一の責任がオブジェクトを変更することである場合、オブジェクトを変更することは副作用ではありません。これはメソッドの唯一の効果です。 –

+2

多くのものを渡しているなら、ExampleをContextスタイルのオブジェクトにして独自のパラメータを持たせるのはいかがですか? – Compass

+0

@Compass私はあなたのコメントをさらにアップアップすることができたらいいと思う。 – CraigR8806

答えて

3

の詳細については、
注意する必要がありますそれが唯一の効果であれば副作用があるので、「すべての副作用が悪い」というブランケットの記述はここでは適用されません。

なお、主な質問は次のとおりです。この(面)効果は大丈夫ですか?第一原理について話す

、副作用は、一般的には、二つの理由のために危険である:

  • 彼らはあいまいな/あなたの例では、情報

を隠す

  • 同時実行をより困難にします隠されている情報があります。これはという潜在的な副作用であり、「このdoSomethingHereメソッドは新しいオブジェクトを作成するか、または渡すものを変更しますか?」という質問で公開される可能性があります。 答えは重要であり、さらにそれが公的な方法である場合はさらに重要です。 答えは、doSomethingHereメソッドを読んで見つけるのは簡単です。特に、メソッドを「きれいに保っている」場合は、情報は隠されている/あいまいです。

    この特定のケースでは、doSomethingHereをvoidに戻します。そうすれば、新しいオブジェクトを作成したと思う可能性はありません。 これは単なるアプローチです。多くの開発者が、変更したオブジェクトを返すべきだと私は確信しています。 また、「良い」メソッド名を選択することもできます。 "modifyExampleInPlace"または "changeSomeFieldsInPlace"は、あなたの特定の例imoのかなり安全な名前です。

  • +0

    はい、ちょうど「doSomethingHere」は完全に悪い命名であり、私はより具体的であったはずです。それは本当の事実ではなかったので、私はそれに注意を払わなかった。私の間違い。 – sva605

    +0

    @ sva605私はそれが悪い名前だと言っている限り、特にそれは例であり、 "doSomethingHere"は例のためのかなり標準的なものであると言っていません。実際には、その名前を使用してうれしく思いました。なぜなら、私が副作用について話していたときの意味を具体的に示してくれたからです。 – Jeutnarg

    4

    我々は別のメソッドにオブジェクトを渡し、そこに変更してはなりません。

    誰がそれを言っていますか?これは実際には、「レシピ」を形成する方法で関数を分割し、オブジェクトを適切に埋め込む方法を正確に把握している特定の関数を持つためには良い習慣です。
    推奨されていないのは(おそらく、あなたの推薦がこの規則に誤解されているソース)パブリックAPIを定義し、引数を変更することです。ユーザーは、驚きが少なくなるため、引数を変更していないことに感謝します。その一例は、配列を配列の引数としてメソッドに渡すことです。

    0

    オブジェクトを定義して他のメソッドに渡すと、メソッド自体がそのオブジェクトの内容を変更することがありますが、このオブジェクトは望ましくない場合があります。これは、オブジェクトの参照(シャローコピー)をそのメソッドに渡し、メソッドがそのオブジェクトを変更できるためです。

    たとえば、配列を渡すとき、配列はオブジェクトであり、メソッドに対してメソッドは配列の内容を変更できますが、これは呼び出し元メソッドが期待していない内容になります。

    public static void main(String[] args){ 
        int[] arr= {1,2,3,4}; 
        y(arr); 
        //After the method arr is changed 
    } 
    public void y(int[] comingArray){ 
        comingArray[0] = 10; 
    } 
    

    配列の値を変更することができないことを確認、配列のディープコピーは別の話
    ある方法に送られるべきであるようにするにあなたがprimite型(int型、フロートなどを使用する場合しかしながら、このケースではありません。)

    public static void main(String[] args){ 
        int a= 1 
        y(a); 
        //After the method a is not changed 
    } 
    public void y(int comingInt){ 
        comingInt = 5; 
    } 
    

    によりオブジェクトの性質のために、あなたはそれがactuallではありません、JB Nizetがコメントしたようシャローコピーとディープコピーhttps://www.cs.utexas.edu/~scottm/cs307/handouts/deepCopying.htm

    +0

    サブメソッドの唯一の目的は、引数として取得するオブジェクトを変更することです。 – sva605