2016-10-13 18 views
6

Tôi đang thiết kế một RESTful API và tôi đã đưa ra một vấn đề liên quan đến các tài nguyên phụ.RESTful API - Thiết kế các tài nguyên phụ

Tôi thấy các API khác sử dụng URL đầy đủ để hoạt động trên các tài nguyên phụ. Lấy ví dụ tại số Company has DepartmentsDepartment has Employees.

Ban đầu, tôi thực hiện tất cả các URL có thể. Kết quả trên như sau:

Cách tiếp cận Một

01. ### COMPANY URLS ### 
02. DELETE /companies/{companyId} 
03. GET /companies/{companyId} 
04. POST /companies 
05. PUT /companies/{companyId} 
06. 
07. ### DEPARTMENT URLS ### 
08. DELETE /companies/{companyId}/departments/{departmentId} 
09. GET /companies/{companyId}/departments/{departmentId} 
10. POST /companies/{companyId}/departments 
11. PUT /companies/{companyId}/departments/{departmentId} 
12. DELETE /departments/{departmentId} 
13. GET /departments/{departmentId} 
14. PUT /departments/{departmentId} 
15. 
16. ### EMPLOYEE URLS ### 
17. DELETE /companies/{companyId}/departments/{departmentId}/employees/{employeeId} 
18. GET /companies/{companyId}/departments/{departmentId}/employees/{employeeId} 
19. POST /companies/{companyId}/departments/{departmentId}/employees 
20. PUT /companies/{companyId}/departments/{departmentId}/employees/{employeeId} 
21. DELETE /departments/{departmentId}/employees/{employeeId} 
22. GET /departments/{departmentId}/employees/{employeeId} 
23. POST /departments/{departmentId}/employees 
24. PUT /departments/{departmentId}/employees/{employeeId} 
25. DELETE /employees/{employeeId} 
26. GET /employees/{employeeId} 
27. PUT /employees/{employeeId} 

Như bạn có thể thấy, có rất nhiều URL mà làm điều tương tự. Ví dụ: 08 được nhân đôi 12; 09 được nhân đôi là 13; 17 được nhân đôi của 21 và 25 ...

Tôi muốn loại bỏ trùng lặp nhưng giữ tính nhất quán. Vì vậy, hãy thiết kế lại API với nguyên tắc trong tâm trí sup-resources are fine but sub-sub-resources are not. Những kết quả trên như sau:

Cách tiếp cận B

01. ### COMPANY URLS ### 
02. DELETE /companies/{companyId} 
03. GET /companies/{companyId} 
04. POST /companies 
05. PUT /companies/{companyId} 
06. 
07. ### DEPARTMENT URLS ### 
08. DELETE /departments/{departmentId} 
09. GET /departments/{departmentId} 
10. GET /companies/{companyId}/departments 
11. POST /companies/{companyId}/departments 
12. PUT /departments/{departmentId} 
13. 
14. ### EMPLOYEE URLS ### 
15. DELETE /employees/{employeeId} 
16. GET /employees/{employeeId} 
17. GET /departments/{departmentId}/employees 
18. POST /departments/{departmentId}/employees 
19. PUT /employees/{employeeId} 

Câu hỏi của tôi

Q1. Phương thức B được xem là RESTful? (Tôi đang giả định)

Q2. Có những cạm bẫy nào Phương pháp tiếp cận B Tôi nên xem xét, giả sử rằng tài liệu đó cũng được cung cấp?

Điểm thưởng nếu bạn trỏ đến các API khác theo sau Phương pháp tiếp cận B.

EDIT

Elad Tabak được trình bày những hiểu biết tốt.

Tôi thích một số API sử dụng Tiếp cận B:

https://developers.google.com/youtube/v3/docs/

https://developer.github.com/guides/getting-started/

https://dev.twitter.com/rest/public

+0

Đó là một chút quá rộng, Q3 và 4 cơ bản mời để đổ cuốn sách về thiết kế webservice. Bạn phải hỏi một câu hỏi chứ không phải một câu hỏi. Câu hỏi cốt lõi của bạn có vẻ là kết hợp Q1 + Q2. – Gimby

+0

Cảm ơn Gimby, đồng ý, nó rất rộng và tôi quan tâm nhất đến Q1 và Q2. – Rafa

Trả lời

3

Cả hai phương pháp có thể được coi RESTful, miễn là bạn không phá vỡ những hạn chế REST của định nghĩa trong chapter 5 của luận án Roy Thomas Fielding:

Tôi không thể nhìn thấy những cạm bẫy lớn trong cả hai phương pháp, nhưng tôi muốn các Tiếp cận B qua Tiếp cận Một: URL ngắn hơn, dễ nhớ và không có nhiều thông số được yêu cầu.


Điểm thưởng:SpotifyFacebook API theo phương pháp này. Để chắc chắn có các API khác, nhưng đây là những API mà tôi nghĩ đến.

+1

Thực ra không có URI nào là RESTful per se! Nội dung của nó trả về đáp ứng các ràng buộc RESTful hay không. REST không có gì liên quan đến thiết kế URI sạch nhưng nhiều hơn với việc tách các máy khách khỏi các API máy chủ và do đó máy khách nên sử dụng các URI được trả về với các đáp ứng để thực hiện các hành động tiếp theo về trạng thái hiện tại của nó. Không biết tại sao mọi người lại nhầm lẫn thiết kế URI với cách tiếp cận RESTful. Thêm vào đó Fielding đã làm sáng tỏ một số ràng buộc mà RESTful API phải tuân theo trong [bài đăng trên blog] của anh ấy (http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven) –

3
  1. REST của nói gì về thiết kế URL. Bất kỳ lược đồ URL nào bạn đưa ra đều là RESTful. Bạn nên hỏi nếu đó là thiết kế tốt. Và vâng, cách tiếp cận thứ hai là ưu tiên cao nhất cho phương pháp thứ nhất. Đầu tiên là một tấn tiếng ồn cho khách hàng và một vấn đề bảo trì rất lớn cho chủ sở hữu. Nó cũng hạn chế tính linh hoạt trong tương lai.

  2. Không có cạm bẫy đáng kể nào mà tôi biết, miễn là bạn ghi rõ cách sử dụng điểm cuối. Ví dụ, nó là điển hình cho các điểm cuối lồng nhau để chỉ trả về các phần tử liên quan và DELETEing một phần tử lồng nhau sẽ chỉ xóa liên kết và không xóa chính phần tử đó. Đó là loại hành vi cần phải được tài liệu một cách này hay cách khác.

Điểm thưởng: yêu cầu tài nguyên bên ngoài nằm ngoài phạm vi.

+0

Và để tiếp tục điều này, không có điều gì như một 'tài nguyên phụ' – mcintyre321

2

Phương pháp thiết kế đặt ra một vài câu hỏi mà bạn cần phải xem xét khi lựa chọn giữa hai:

phụ thuộc tồn tại

Trong Một, nó rất trực quan, rằng khi bạn DELETE một công ty, bạn cũng xóa tất cả các tài nguyên phụ của nó - các phòng ban và nhân viên. Trong B, người dùng API cần suy nghĩ một chút về hành động như vậy - tôi có cần phải gọi xóa trên tất cả nhân viên hay đủ để xóa công ty không? tất nhiên, điều này có thể được ghi lại, nhưng nó vẫn không thẳng thắn.

A có lợi thế ở đây, bởi vì nó rất rõ ràng - khi xóa một resouce, bạn xóa tất cả các tài nguyên phụ của nó.

Operation endpoint

Một câu hỏi đặt ra nó - làm thế nào để cập nhật một thực thể? từ điểm cuối nào?

Nếu tôi muốn xóa một nhân viên, liệu có đủ để cập nhật công ty với một nhóm nhân viên mới không? hay tôi phải XÓA nhân viên?

Hoặc nói rằng tôi muốn thay đổi nhân viên từ công ty này sang công ty khác. Trong B, về mặt lý thuyết tôi có thể cập nhật nhân viên với lĩnh vực công ty và được thực hiện với nó. Trong A không có cách nào như vậy ...

A có lợi thế là nó rất thẳng về cách thực hiện hành động - CRUD trên URL tổ chức. B làm cho người dùng API dừng lại và tự hỏi bạn có thể thực hiện hành động nào trên URL nào.

Nhưng đồng thời, B có lợi thế là thay đổi "nuôi dạy con" của thực thể dễ dàng hơn (trong trường hợp có liên quan).

Validation

Trong Một, bạn phải xác nhận địa chỉ URL lập luận phù hợp, như người dùng có thể cung cấp id nhân viên với công ty sai hoặc bộ phận. Trong B không có vấn đề như vậy.

1

Vì vậy, điều này nghe có vẻ hơi điên rồ, nhưng không có thứ như 'nguồn cấp phụ' trong HTTP/REST.

Trong mô hình miền của bạn, một bộ phận không thể tồn tại mà không có công ty.

Bây giờ trong API của bạn, bạn trình bày đại diện json của công ty tại /companies/{companyId} và đại diện của một bộ phận tại số /companies/{companyId}/departments/{departmentId}.

Đó là cả hai 'tài nguyên'. Một tài nguyên, trong thuật ngữ HTTP/REST, chỉ có nghĩa là một điều mà một URL trỏ đến. Vì vậy, đó là 'đại diện json của một công ty' chứ không phải chính công ty.

Thiết kế URL tự nó là một con hẻm chết tự - URL của chúng có thể trông giống như bất cứ điều gì, nó không quan trọng nếu chúng có thể đọc được hay không. Nhà phát triển đưa ra yêu cầu, chọn các URL tùy thuộc vào tên hoạt động từ tài liệu *. Việc cố gắng thêm ý nghĩa vào chính các URL sẽ nhanh chóng trở nên phức tạp và thực sự có thể thêm nhầm lẫn khi thời gian trôi qua.

Tốt hơn là dành thời gian cho tài liệu, thay vì cố gắng để mọi người phỏng đoán mọi thứ về hành vi miền.

* hoặc hypermedia (ví dụ https://github.com/kevinswiber/siren)

Các vấn đề liên quan