attachDevice(Device device)というメソッドがあり、引数は1つだけです。 attachDevice(Device device、String deviceName)のように、このメソッドにもう1つのパラメーターをオーバーロードする状況がありました。
単一の引数付き
public void attachDevice(Device device)
{
..
..
}
二重引数付き
public void attachDevice(Device device, String deviceName)
{
..
device.setName(deviceName);
genericDeviceMap.put(deviceName, device);
..
}
実際、私のチームリーダーから、これら2つのメソッドを1つのジェネリックコールにするように求められました。オーバーロードされたメソッドには、単一のメソッド(上記のように示されている)よりも2行追加されています。 deviceNameを渡す代わりに、空の文字列を渡すことができます。これは、オーバーロードされたメソッドの呼び出しが、単一引数の呼び出しよりもはるかに少ないためです。しかし、引数がnullになる場合は名前を設定しないので、null値を渡す場合はどれほど悪いことでしょう。このシナリオのベストプラクティスはどれですか。
どんな提案も大歓迎です。
注:私がここで述べた実際の問題は、
i)オーバーロードされたメソッドを、コードの重複を避けるために汎用的な1つのメソッドにマージしたかった
ii)コーディングのベストプラクティスを守るために、メソッドに渡す推奨値(空の文字列またはnull値)が必要です。
与えられた回答から、私は自分の問題の最善の解決策を得ました。リンクされた質問 この質問は重複していますnull値の処理に関する情報を提供しますが、私がメモで述べた最初のポイントはカバーしていません。また、NPEがときどきスローされることを認識しているため、パラメーターとしてnullを渡して悪いコードを記述していません。
ありがとう。
null
を使用することはお勧めしません。デバッグが困難なNPEがさらに発生する可能性があるためです(また、本番用コードで発生する場合は高額になります)。
deviceName
が指定されていない場合は、代わりにデフォルトの値を指定できます。このアプローチの最大の欠点は、genericDeviceMap.put(deviceName, device)
の危険性です。これは、キーがデフォルト名であるエントリを暗黙のうちに上書きできるためです(そのため、以前のDevice
を追跡できなくなります)。
_public void attachDevice(Device device)
{
attachDevice(device, "DefaultName");
}
public void attachDevice(Device device, String deviceName)
{
..
device.setName(deviceName);
genericDeviceMap.put(deviceName, device);
..
}
_
現在のアーキテクチャでは、名前なしでgenericDeviceMap
が呼び出されたときにattachDevice
にエントリを追加しても意味がないかもしれません。その場合、2つのattachDevice
の間の共通の動作のみをプライベートメソッドに抽出するのが良い方法です。私は個人的にこの2つの理由でこのアプローチを好まない:
attachDevice
間の動作は同じではありません。一方には副作用(device.setName(deviceName)
)があり、もう一方には副作用がありませんコード:
_public void attachDevice(Device device)
{
preAttachDevice();
postAttachDevice();
}
public void attachDevice(Device device, String deviceName)
{
preAttachDevice();
device.setName(deviceName);
genericDeviceMap.put(deviceName, device);
postAttachDevice();
}
private void preAttachDevice()
{
...
}
private void postAttachDevice()
{
...
}
_
私のお気に入りですが、最も難しいです。これら2つの方法が本当に必要かどうかを自問してみてください。名前を付けて、または付けずにattachDevice
を呼び出すことができるのは本当に意味がありますか? attachDevice
mustは名前で呼び出されると言えるでしょうか?
この場合、コードは1つのメソッドのみに簡略化されます。
_public void attachDevice(Device device, String deviceName)
{
..
device.setName(deviceName);
genericDeviceMap.put(deviceName, device);
..
}
_
または、一方で、本当にMap
個のデバイスとデバイス名を維持し、デバイス名を設定する必要がありますか?そうでない場合は、2番目のメソッドを削除して、最初のメソッドのみを保持できます。
_public void attachDevice(Device device)
{
...
...
}
_
あなたのチームリーダーが悪いコードを作成するように求めていると私は主張します。名前を指定したくない場合に、名前パラメーターとして任意の値を渡す必要があるので、メソッドの使用を検討している開発者が混乱し、混乱を招きます。
代わりに、2つのメソッドを保持します(後者の名前をattachNamedDevice
のような名前に変更して、attachDevice
とは異なることを明確にするために、共通コードをプライベートメソッドに移動します:
public void attachDevice(Device device)
{
preDeviceNameSetup(device);
postDeviceNameSetup(device);
}
public void attachNamedDevice(Device device, String deviceName)
{
preDeviceNameSetup(device);
device.setName(deviceName);
genericDeviceMap.put(deviceName, device);
postDeviceNameSetup(device);
}
private void preDeviceNameSetup(Device device)
{
...
}
private void postDeviceNameSetup(Device device)
{
...
}
そうすることで、APIをクリーンに保ちながら、実装でのコードの重複を回避できます。
私は次のようにします:
device.setName(deviceName)
を呼び出す前にattachDevice(device)
を呼び出します。デバイスの名前を設定するのはattachDevice
メソッドの責任ではありません。attachDevice
メソッドを変更して、デバイスに名前がある場合はgenericDeviceMap
にデバイスを追加します。デバイスに名前がないときにgenericDeviceMap
にもデバイスを追加する必要がある場合は、Device
クラス自体のコンストラクターなどでデフォルトを設定することをお勧めします。 。
public void attachDevice(Device device)
{
// ...
if (device.getName())
{
genericDeviceMap.put(deviceName, device);
}
// ...
}
これにより、懸念が分離され、副作用のある機能から離れることができます。