APIを開発する必要があります。APIの機能は、サーバーによって公開されたサービスを呼び出すリクエストです。
最初、APIは次のように機能しました。
class Server:
def firstRequest(self, arg1, arg2):
# block of code A
async = Async()
async.callFirstRequest(arg1, arg2)
# block of code B
def secondRequest(self, argA, argB, argC):
# block of code A (identical to that of firstRequest)
async = Async()
async.callSecondRequest(argA, argB, argC)
# block of code B (identical to that of firstRequest)
class Async:
def callFirstRequest(self, arg1, arg2):
doFirstRequest(arg1, arg2)
# run the real request and wait for the answer
def doFirstRequest(self, arg1, arg2):
response = client.firstRequest(arg1, arg2)
def callSecondRequest(self, argA, argB, argC):
doSecondRequest(argA, argB, argC)
# run the real request and wait for the answer
def doSecondRequest(self, argA, argB, argC):
response = client.secondRequest(argA, argB, argC)
server = Server()
server.firstRequest(arg1=1, arg2=2)
server.secondRequest(argA='A', argB='B', argC='C')
重複したコードがたくさんあり、リクエストの引数を渡す方法が好きではありません。引数はたくさんあるので、リクエストからそれらを抽出して、よりパラメトリックなものにしたかったのです。
だから私はこのようにリファクタリングしました:
# using a strategy pattern I was able to remove the duplication of code A and code B
# now send() receive and invoke the request I wanna send
class Server:
def send(self, sendRequest):
# block of code A
asynch = Async()
sendRequest(asynch)
# block of code B
# Request contains all the requests and a list of the arguments used (requestInfo)
class Request:
# number and name of the arguments are not the same for all the requests
# this function take care of this and store the arguments in RequestInfo for later use
def setRequestInfo(self, **kwargs):
if kwargs is not None:
for key, value in kwargs.iteritems():
self.requestInfo[key] = value
def firstRequest(async)
async.doFirstRequest(self.requestInfo)
def secondRequest(async)
async.doSecondRequest(self.requestInfo)
# Async run the real request and wait for the answer
class Async:
def doFirstRequest(requestInfo):
response = client.firstRequest(requestInfo['arg1'], requestInfo['arg2'])
def doSecondRequest(requestInfo)
response = client.secondRequest(requestInfo['argA'], requestInfo['argB'], requestInfo['argC'])
server = Server()
request = Request()
request.setRequestInfo(arg1=1, arg2=2) # set of the arguments needed for the request
server.send(request.firstRequest)
request.setRequestInfo(argA='A', argB='B', argC='C')
server.send(request.secondRequest)
戦略パターンが機能し、重複が削除されました。これに関係なく、特に引数に関しては、複雑なことをするのが怖いです。コードを見ると、簡単で明確に見えないので、それらの扱い方が好きではありません。
そのため、この種のクライアント側APIコードを処理するためのパターンまたはより明確で明確な方法があるかどうかを知りたいと思いました。
引数に辞書(ハッシュ、マップ、言語がキーと値のペアのセットを呼び出すものは何でも)を使用することを再考します。そのようにすると、呼び出し元が必要な値をすべて含んでいるかどうかをコンパイラがチェックできなくなります。開発者がそれを使用して、必要なすべての引数があるかどうかを判断するのは困難です。必要のないものを誤って入れてしまい、必要のないものを忘れてしまいがちです。また、呼び出し時にすべての値を辞書に入れなければならず、すべての関数で辞書をチェックしてすべての引数を抽出しなければならず、オーバーヘッドが増加します。ある種の特殊な構造を使用すると、コンパイラーが引数をチェックする能力や開発者が必要なものを明確に確認する能力を低下させることなく、引数の数を減らすことができます。
サーバーAPIには必要なリクエストと同じ数のエントリが必要です。したがって、開発者は誰でも簡単にAPIを読み取ることができます( 例としてlaskルーティングを参照 )。
コードの重複を避けるために、内部メソッドを使用できます
API、アーキテクチャ、パターンはすべて、コミュニケーションと意図に関するものです。あなたの2番目のバージョンは私には十分にシンプルに見え、多少拡張可能に見えますが、私の意見(またはあなたの意見)はここでは重要ではありません。
フィードバックを取得
ソフトウェアを外側から内側から見てください。ウェブサイトがある場合は、そこから始めます。ソフトウェアが実行することが期待されていることを実行するための1つだけの明白な方法を簡単に見つけることを期待してください。 hallway で誰かを見つけて、ユーザビリティに関するフィードバックを求めます。
主要なビジネスオブジェクトを特定します
ソフトウェアプログラミングは常に2つの異なるものから何かを新しくすることを目的としているため、Server
を取るRequest
を用意することは私には理にかなっているようです。 Server
はおそらく設定が必要であり、適切なデフォルトがあります。使用を容易にするために、おそらくシングルトンまたはファクトリーのようなものを提供します。実際の興味深いものはRequest
で発生します。クライアントは、適切なRequest
オブジェクトを構築する必要があります。意図を明確にし、 ビジネス を明確にします。
コマンドパターン のように、Request
オブジェクトで複数のパブリックメソッドの代わりに継承を使用してさまざまな動作をエンコードすることで、さらに簡単にすることができます。このようにして、クライアントは独自のリクエストを書き込むこともでき、必要に応じてプラグイン(たとえば、setuptoolsのエントリポイントを使用)によって新しいリクエストを提供できます。これにより、Request
オブジェクトが god class にならないようにするか、新しい機能が追加された場合にAPIが変更されるようにします。