Tái cấu trúc API khách để tránh mã trùng lặp và thông số không rõ ràng


8

Tôi cần phát triển API, các chức năng của API là các yêu cầu gọi dịch vụ được máy chủ trưng ra.

Ban đầu API hoạt động như thế này:

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')

Có rất nhiều mã trùng lặp và tôi không thích cách nó chuyển các đối số cho yêu cầu. Bởi vì có rất nhiều đối số nên tôi muốn trích xuất chúng từ yêu cầu và làm cho một cái gì đó tham số hơn.

Vì vậy, tôi đã tái cấu trúc theo cách này:

# 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)

Các mô hình chiến lược làm việc, sự trùng lặp được loại bỏ. Bất kể điều này tôi sợ có những điều phức tạp, đặc biệt là liên quan đến các đối số, tôi không thích cách tôi xử lý chúng, bởi vì khi tôi nhìn vào mã không có vẻ dễ dàng và rõ ràng.

Vì vậy, tôi muốn biết liệu có một mô hình hoặc một cách tốt hơn và rõ ràng hơn để đối phó với loại mã API phía máy khách này.


1
Bạn đã xem xét hỏi về điều này trên Sàn giao dịch đánh giá mã chưa? Người dùng ở đó chuyên về những thứ như thế này.
Nzall

@NateKerkhofs Có tôi đã xem xét nó, nhưng sau đó tôi chọn Lập trình viên vì đây là bảng để đặt câu hỏi về thiết kế và kiến ​​trúc khi tôi đọc trong phần trợ giúp . Trong Đánh giá mã thậm chí không có thẻ để tái cấu trúc.
k4ppa

2
Đó là bởi vì toàn bộ mục tiêu của CR là tái cấu trúc mã. Về cơ bản, nó ngụ ý rằng tất cả các câu hỏi trong đó là về mã tái cấu trúc. Mã của bạn đã hoạt động, nhưng ngoài ra, các câu trả lời cho rằng bạn muốn kiểm tra mã của mình để tìm lỗi và tái cấu trúc.
Nzall

2
@NateKerkhofs - CR có xu hướng tập trung rất hẹp liên quan đến đánh giá thiết kế. Vì OP đang yêu cầu hướng dẫn về kiến ​​trúc của giải pháp, tôi nghĩ đó là chủ đề cho trang web này.

Câu trả lời:


1

Tôi sẽ xem xét lại bằng cách sử dụng một từ điển (băm, bản đồ, bất cứ thứ gì ngôn ngữ của bạn gọi là một bộ các cặp khóa / giá trị) cho các đối số. Làm theo cách đó khiến trình biên dịch không thể kiểm tra xem người gọi có bao gồm tất cả các giá trị cần thiết hay không. Nó gây khó khăn cho nhà phát triển sử dụng nó để tìm hiểu xem họ có tất cả các đối số cần thiết hay không. Nó dễ dàng vô tình bao gồm những thứ bạn không cần và quên đi những thứ bạn cần. Và cuối cùng, bạn phải đặt tất cả các giá trị vào từ điển khi gọi và phải kiểm tra từ điển trong mọi hàm để trích xuất tất cả các đối số, tăng chi phí. Sử dụng một số loại cấu trúc chuyên dụng có thể giảm số lượng đối số mà không làm giảm khả năng trình biên dịch để kiểm tra chúng và khả năng của nhà phát triển để thấy rõ những gì cần thiết.


Cũng giống như một tiện ích bổ sung, nếu bạn lo lắng về việc đảm bảo tất cả các tham số được truyền cho một yêu cầu đã cho, thì bạn có thể xem xét bằng cách sử dụng các lớp hoặc giao diện trừu tượng (đừng nhớ nếu điều đó tồn tại trong python giống như C # hoặc Java) , nhưng điều đó có thể trở nên quá mức tùy thuộc vào phạm vi hiện tại. Lợi ích chính sẽ là có định nghĩa rõ ràng theo yêu cầu.
eparham7861

0

Tôi nghĩ API máy chủ của bạn nên có nhiều mục theo yêu cầu. Do đó, bất kỳ nhà phát triển nào cũng có thể đọc API dễ dàng ( xem ví dụ định tuyến lask ).

Để tránh trùng lặp trong mã, bạn có thể sử dụng các phương thức nội bộ


0

API, kiến ​​trúc và mô hình là tất cả về giao tiếp và ý định. Phiên bản thứ hai của bạn trông đủ đơn giản với tôi và dường như cũng có thể mở rộng nhưng ý kiến ​​của tôi (hoặc thậm chí của bạn) không phải là vấn đề ở đây.

Nhận phản hồi

Nhìn vào phần mềm của bạn từ ngoài vào trong (không phải từ trong ra ngoài). Nếu có một trang web, bắt đầu từ đó. Hy vọng sẽ dễ dàng tìm thấy một và chỉ một cách rõ ràng để làm những gì phần mềm của bạn dự kiến ​​sẽ làm. Tìm ai đó ở hành lang và yêu cầu phản hồi về khả năng sử dụng.

Xác định đối tượng kinh doanh chính

Vì lập trình phần mềm luôn là về việc tạo ra một cái gì đó mới từ hai thứ khác nhau, nên có một Serverthứ có Requestvẻ hợp lý với tôi. Có Serverlẽ yêu cầu cấu hình và có mặc định hợp lý. Bạn có thể cung cấp một cái gì đó như một singleton hoặc nhà máy để giảm bớt việc sử dụng nó. Các công cụ xen kẽ thực sự xảy ra trong Request. Khách hàng của bạn chỉ phải đảm bảo xây dựng Requestđối tượng thích hợp . Làm cho ý định của bạn rõ ràng và kinh doanh của bạn rõ ràng.

Hãy mở rộng, nhưng đóng cửa để sửa đổi

Bạn có thể làm cho nó đơn giản hơn nữa bằng cách mã hóa các hành vi khác nhau bằng cách sử dụng kế thừa thay vì nhiều phương thức công khai trong Requestđối tượng, khá giống với mẫu lệnh . Bằng cách này, khách hàng cũng có thể viết các yêu cầu của riêng họ và các yêu cầu mới có thể được cung cấp bởi các plugin (ví dụ sử dụng các điểm nhập của setuptools) nếu được yêu cầu. Điều này cũng sẽ đảm bảo rằng Requestđối tượng không bao giờ trở thành một lớp thần hoặc đã thay đổi API nếu các tính năng mới được thêm vào.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.