2

リモート サーバーに格納されているオブジェクトを表す短いクラスを作成しようとしています。オブジェクトの属性をリモートサーバーに設定せずにローカルに設定することは、一般的に悪い考えだと思います。これは、ローカル オブジェクトがもはやリモート オブジェクトを表していないことを意味し、その事実を意識することさえありません。

これを処理するために、以下のようなコードを使用することを計画していました。設定したい場合は自分の足を撃つことができますがitem.name、ユーザーは賢明であり、そうしないと想定しています.

class Item(object):
    def __init__(self):
        self.name = get_item_name()

    def set_name(self, name):
        try:
            set_item_name(name)
        except:
            handle_error()
            raise
        else:
            self.name = name

@propertyしかし、最近デコレータに出くわしたので、以下を書くことができました:

class Item(object):
    def __init__(self):
        self._name = get_item_name()

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, value):
        try:
            set_item_name(value)
        except:
            handle_error()
            raise
        else:
            self._name = value

これには、 を使用した属性アクセスを引き続き許可するだけでなく、割り当てitem.nameも処理できるという利点があります。item.name = blah

ただし、コードの 2 番目のブロックは (私にはそう思われる) より優れた動作を提供しますが、属性設定で関数呼び出しを非表示にし、Zenの「明示的は暗黙的よりも優れている」と Python クラスがすべきという一般的な考えを考慮します。ユーザーから物事を隠すのではなく、これにより 2 番目のコード ブロックの Pythonic が少なくなりますか?

4

1 に答える 1

3

オブジェクト指向言語でコードを書くことは、すべてを隠すことです。メソッドをdoSomethingComplex()作成するときは、基本的にアプリケーションの言語で新しい単語を作成します。これにより、メソッドを使用する必要がある開発者から複雑な操作が隠されます。

通常、明示的は暗黙的よりも優れていますが、常にという意味ではありません。あなたの場合、問題はセッターでメソッド呼び出しを隠すことではなく、ネットワークを隠しているという事実にあります。メソッドのユーザーから実際の物理ネットワークを隠そうとするとすぐに、次のケースを正しく処理する必要があります。

  1. リモート側が突然死ぬ
  2. ネットワークがパケットをドロップします (ローカル側でタイムアウト)
  3. リモート側が例外をスローします (何らかの方法でローカル コードに取得する必要がありますが、ローカルでは意味がない可能性があります)。
  4. リモート側は呼び出しを正常に処理しますが、ネットワークは応答をドロップします (したがって、成功しましたが、わかりません)

どんなに頑張っても、この隠された複雑さは漏れ出します。簡単な例として、このコードを使用する開発者は、(他の方法ではなく) ネットワークの例外とタイムアウトを処理する必要があります。

したがって、ここでの中断は、setter でメソッドを呼び出すことよりも、まったく新しいコントラクトを導入することです。

より良い解決策は何ですか?ネットワーク呼び出しを明示的にします。これは、コードのユーザーにとってより明白な努力を意味しますが、彼らは常に自分が何に反対しているのかを知っています (なぜこのセッターが奇妙な振る舞いをするのか疑問に思うのではなく)。

推奨される実装: コマンド パターンを使用して、これらのオブジェクトの状態を変更します。このコマンドには、変更するオブジェクトの ID (ローカル コピーを保持する必要がないため)、変更するフィールド、および新しい値が必要です

リモート側が「成功」と応答したら、ローカルにキャッシュされたコピーを更新します。リモート側からエラーが返された場合は、キャッシュされたコピーを削除して、再度取得できるようにします。

これにより、さらに多くのコードが作成されますが、このコードは非常に単純でわかりやすいものになります。リモート側を隠そうとすると、コードは少なくなりますが、より複雑でわかりにくくなります。

PS: 人々が長い間賢明であると思い込まないでください。

于 2012-07-06T10:02:23.513 に答える