REST HATEOAS (mức độ trưởng thành 3) hữu ích / quan trọng như thế nào?


110

Tôi đang tham gia vào một dự án mà một số thành viên nhóm cấp cao tin rằng API REST phải tuân thủ HATEOAS và triển khai tất cả các cấp độ trưởng thành của Richardson ( http://martinfowler.com/articles/richardsonMaturityModel.html )!

AFAIK hầu hết các triển khai REST không tuân thủ HATEOAS và phải có lý do chính đáng khiến nhiều người không làm điều đó. Tôi có thể nghĩ đến những lý do như phức tạp hơn, thiếu khung làm việc (phía máy chủ và máy khách), mối quan tâm về hiệu suất và ...

Bạn nghĩ sao? Bạn đã có kinh nghiệm nào với HATEOAS trong một dự án thế giới thực chưa?


Đây là một bài viết hay về chủ đề này: medium.com/@andreasreiser94/… Về cơ bản, cách "REST" thường được thực hiện, đó là RPC ...
masterxilo

Câu trả lời:


213

Không ai trong cộng đồng REST nói rằng REST là dễ dàng. HATEOAS chỉ là một trong những khía cạnh làm tăng thêm độ khó cho kiến ​​trúc REST.

Mọi người không làm HATEOAS vì tất cả những lý do bạn đề xuất: nó khó. Nó làm tăng thêm sự phức tạp cho cả phía máy chủ và máy khách (nếu bạn thực sự muốn hưởng lợi từ nó).

TUY NHIÊN, hàng tỷ người trải nghiệm những lợi ích của REST ngày nay. Bạn có biết URL "thanh toán" tại Amazon là gì không? Tôi không. Tuy nhiên, tôi có thể thanh toán mỗi ngày. URL đó có thay đổi không? Tôi không biết, tôi không quan tâm.

Bạn có biết chăm sóc không? Bất kỳ ai viết màn hình đều đánh dấu ứng dụng khách tự động của Amazon. Một người có khả năng đã cẩn thận đánh hơi lưu lượng truy cập web, đọc các trang HTML, v.v. để tìm những liên kết nào cần gọi khi nào và với tải trọng nào.

Và ngay sau khi Amazon thay đổi các quy trình nội bộ và cấu trúc URL của họ, những khách hàng được mã hóa cứng đó đã thất bại - vì các liên kết bị hỏng.

Tuy nhiên, những người lướt web bình thường có thể mua sắm cả ngày mà hầu như không gặp khó khăn.

Đó là REST trong hoạt động, nó chỉ được tăng cường bởi con người có thể giải thích và đưa vào giao diện dựa trên văn bản, nhận ra một hình ảnh nhỏ với giỏ hàng và tìm hiểu ý nghĩa thực sự của điều đó.

Hầu hết mọi người viết phần mềm không làm điều đó. Hầu hết những người viết ứng dụng khách tự động không quan tâm. Hầu hết mọi người nhận thấy việc sửa chữa khách hàng của họ khi họ bị hỏng dễ dàng hơn so với việc thiết kế ứng dụng để không bị hỏng ngay từ đầu. Hầu hết mọi người chỉ đơn giản là không có đủ khách hàng ở nơi quan trọng.

Nếu bạn đang viết một API nội bộ để giao tiếp giữa hai hệ thống với sự hỗ trợ kỹ thuật của chuyên gia và CNTT ở cả hai phía của lưu lượng truy cập, những người có thể truyền đạt các thay đổi nhanh chóng, đáng tin cậy và với lịch trình thay đổi, thì REST không mua gì cho bạn. Bạn không cần nó, ứng dụng của bạn không đủ lớn và nó không đủ lâu để tồn tại.

Các trang web lớn với cơ sở người dùng lớn có vấn đề này. Họ không thể chỉ yêu cầu mọi người thay đổi mã khách hàng của họ một cách bất chợt khi tương tác với hệ thống của họ. Lịch trình phát triển máy chủ không giống với lịch phát triển máy khách. Những thay đổi đột ngột đối với API đơn giản là không thể chấp nhận được đối với tất cả mọi người liên quan, vì nó làm gián đoạn lưu lượng truy cập và hoạt động của cả hai bên.

Vì vậy, một hoạt động như vậy rất có thể sẽ được hưởng lợi từ HATEOAS, vì nó dễ tạo phiên bản hơn, dễ dàng di chuyển cho các máy khách cũ hơn, dễ tương thích ngược hơn là không.

Máy khách ủy thác phần lớn luồng công việc của nó cho máy chủ và hoạt động dựa trên kết quả đối với các thay đổi của máy chủ mạnh mẽ hơn nhiều so với một máy khách không làm như vậy.

Nhưng hầu hết mọi người không cần sự linh hoạt đó. Họ đang viết mã máy chủ cho 2 hoặc 3 phòng ban, tất cả đều được sử dụng nội bộ. Nếu nó bị hỏng, họ sẽ sửa nó và họ đã tính điều đó vào các hoạt động bình thường của họ.

Tính linh hoạt, cho dù từ REST hay bất kỳ thứ gì khác, đều tạo ra sự phức tạp. Nếu bạn muốn nó đơn giản và nhanh chóng, thì bạn không làm cho nó linh hoạt, bạn "cứ làm", và xong. Khi bạn thêm các phần tóm tắt và tham chiếu vào hệ thống, thì mọi thứ sẽ khó hơn, nhiều đĩa lò hơi hơn, nhiều mã hơn để kiểm tra.

Phần lớn REST không đạt được gạch đầu dòng "bạn sẽ không cần nó". Tất nhiên, cho đến khi bạn làm.

Nếu bạn cần nó, hãy sử dụng nó, và sử dụng nó khi nó được bày ra. REST không chuyển nội dung qua lại HTTP. Nó chưa bao giờ xảy ra, nó cao hơn thế nhiều.

Nhưng khi bạn cần REST và bạn sử dụng REST, thì HATEOAS là một thứ cần thiết. Đó là một phần của gói và là chìa khóa để làm cho nó hoạt động.


11
Tôi cảm thấy như bạn nên có thêm ít nhất một nghìn lượt thích cho câu trả lời này. Thành thật mà nói, tôi phải tưởng tượng rằng: Câu hỏi REST 'thực sự' quan trọng như thế nào xuất hiện khá nhiều. Khỉ thật, tôi đang làm một số googling chỉ vì lý do đó để sử dụng đạn dược trong một cuộc họp sắp tới khi tôi tìm thấy chủ đề này.
nâng cấp

2
cảm ơn chúa (hoặc mã), ai đó cũng đang nói về nhược điểm của HATEOAS!
IlliakaillI

6
Có lợi thế nào khác sau đó là khả năng dễ dàng thay đổi URL không? Bạn không thể chỉ thêm các tùy chọn mới bởi vì không giống như con người, chương trình không thể hoạt động với một cái gì đó mới. Thêm vào đó, bạn chỉ chuyển từ việc xây dựng các URL biết sang việc biết tên của các hành động.
Jimmy T.

Nếu người tiêu dùng API không biết bất cứ điều gì nó chỉ có thể ủy thác hành động sử dụng 1: 1
Jimmy T.

2
Về việc thay đổi URL, đừng quên rằng máy khách của bạn có thể sử dụng bộ nhớ cache và do đó, bạn phải giữ nguyên hành vi trên máy chủ để xử lý cả URL trước đó (hoặc chỉ thực hiện chuyển hướng). Như bất kỳ chiến lược nào để phát triển API, bạn phải giữ cho hành vi cũ của mình hoạt động. HATEOAS không giúp được gì nhiều ở đó.
Bruno Costa

21

Có, tôi đã có một số kinh nghiệm với siêu phương tiện trong API. Dưới đây là một số lợi ích:

  1. API có thể khám phá: Nghe có vẻ tầm thường nhưng đừng đánh giá thấp sức mạnh của một API có thể khám phá. Khả năng duyệt qua dữ liệu giúp các nhà phát triển khách hàng dễ dàng hơn rất nhiều trong việc xây dựng mô hình tinh thần của API và cấu trúc dữ liệu của nó.

  2. Tài liệu nội tuyến: Việc sử dụng URL làm quan hệ liên kết có thể hướng các nhà phát triển khách hàng đến tài liệu.

  3. Logic của ứng dụng khách đơn giản: Ứng dụng khách chỉ theo dõi các URL thay vì tự xây dựng chúng, sẽ dễ dàng triển khai và duy trì hơn.

  4. Máy chủ có quyền sở hữu các cấu trúc URL: Việc sử dụng siêu phương tiện loại bỏ kiến ​​thức được mã hóa cứng của máy khách về các cấu trúc URL được máy chủ sử dụng.

  5. Tắt tải nội dung đến các dịch vụ khác: Hypermedia là cần thiết khi tắt nội dung tải xuống các máy chủ khác (ví dụ: CDN).

  6. Tạo phiên bản với các liên kết: Hypermedia giúp tạo phiên bản cho các API.

  7. Nhiều triển khai của cùng một dịch vụ / API: Hypermedia là điều cần thiết khi có nhiều triển khai của cùng một dịch vụ / API. Ví dụ, một dịch vụ có thể là một API blog với các tài nguyên để thêm các bài đăng và nhận xét. Nếu dịch vụ được chỉ định theo quan hệ liên kết thay vì URL được mã hóa cứng thì cùng một dịch vụ có thể được khởi tạo nhiều lần tại các URL khác nhau, do các công ty khác nhau lưu trữ nhưng vẫn có thể truy cập thông qua cùng một tập hợp liên kết được xác định rõ ràng bởi một khách hàng.

Bạn có thể tìm thấy lời giải thích chuyên sâu về những gạch đầu dòng này tại đây: http://soabits.blogspot.no/2013/12/selling-benefits-of-hypermedia.html

(có một câu hỏi tương tự ở đây: /software/149124/what-is-the-benefit-of-hypermedia-hateoas nơi tôi đã đưa ra lời giải thích tương tự)


Nhiều triển khai của cùng một dịch vụ: bạn có thể nói rõ hơn không? Tôi không thấy nó giúp ích như thế nào.
Abbadon

Tôi đã cố gắng giải thích nó trong văn bản. Nó có ích gì không?
Jørn Wildt

11

Mức độ trưởng thành 3 của Richardson rất có giá trị và nên được chấp nhận. Jørn Wildt đã tóm tắt một số ưu điểm và một câu trả lời khác của Wilt bổ sung rất tốt cho nó.

Tuy nhiên, mức độ trưởng thành cấp 3 của Richardson không giống như HATEOAS của Fielding. Mức độ trưởng thành 3 của Richardson chỉ là về thiết kế API. HATEOAS của Fielding cũng là về thiết kế API, nhưng cũng quy định rằng phần mềm máy khách không nên cho rằng tài nguyên có cấu trúc cụ thể ngoài cấu trúc được xác định bởi loại phương tiện. Điều này đòi hỏi một ứng dụng khách rất chung chung, như một trình duyệt web, không có kiến ​​thức về các trang web cụ thể. Vì Roy Fielding đã đặt ra thuật ngữ REST và đặt HATEOAS làm yêu cầu tuân thủ REST, câu hỏi đặt ra là: chúng ta có muốn áp dụng HATEOAS không và nếu không, chúng ta có thể gọi API của mình là RESTful hay không? Tôi nghĩ rằng chúng ta có thể. Hãy để tôi giải thích.

Giả sử chúng ta đã đạt được HATEOAS. Phía máy khách của ứng dụng hiện nay rất chung chung, nhưng rất có thể, trải nghiệm người dùng là tồi tệ, bởi vì không có bất kỳ kiến ​​thức nào về ngữ nghĩa của các tài nguyên, việc trình bày các tài nguyên không thể được điều chỉnh để phản ánh những ngữ nghĩa đó. Nếu tài nguyên 'xe' và 'nhà' tài nguyên có cùng loại phương tiện (ví dụ: ứng dụng / json), thì chúng sẽ được trình bày cho người dùng theo cùng một cách, chẳng hạn như một bảng thuộc tính (cặp tên / giá trị).

Nhưng không sao, API của chúng tôi thực sự RESTful.

Bây giờ, giả sử chúng ta xây dựng một ứng dụng khách thứ hai trên API này. Khách hàng thứ hai này vi phạm các ý tưởng HATEOAS và có thông tin được mã hóa cứng về các tài nguyên. Nó hiển thị một chiếc xe hơi và một ngôi nhà theo những cách khác nhau.

API vẫn có thể được gọi là RESTful? Tôi nghĩ vậy. Không phải lỗi của API mà một trong những khách hàng của nó đã vi phạm HATEOAS.

Tôi khuyên bạn nên xây dựng các API RESTful, tức là các API mà một ứng dụng khách chung có thể được triển khai trên lý thuyết , nhưng trong hầu hết các trường hợp, bạn cần một số thông tin được mã hóa cứng về các tài nguyên trong ứng dụng khách của mình để đáp ứng các yêu cầu về khả năng sử dụng. Tuy nhiên, hãy cố gắng viết mã càng ít càng tốt, để giảm sự phụ thuộc giữa máy khách và máy chủ.

Tôi đã bao gồm một phần về HATEOAS trong mẫu triển khai REST của tôi có tên là JAREST .


8

Chúng tôi đang xây dựng một API REST cấp 3 trong đó phản hồi của chúng tôi là HAL-Json. HATEOAS rất tuyệt vời cho cả front-end và back-end nhưng nó đi kèm với những thách thức. Chúng tôi đã thực hiện một số tùy chỉnh / bổ sung để quản lý ACL bên trong phản hồi HAL-Json (điều này không phá vỡ tiêu chuẩn HAL-Json).

Ưu điểm lớn nhất của HATEOAS mà tôi thấy là chúng tôi không cần viết / đoán bất kỳ url nào trên ứng dụng front-end của chúng tôi. Tất cả những gì bạn cần là một điểm nhập ( https://hostname) và từ đó bạn có thể chỉ cần duyệt qua các tài nguyên bằng cách sử dụng các liên kết hoặc liên kết mẫu được cung cấp bên trong phản hồi. Như vậy, việc lập phiên bản có thể được xử lý dễ dàng, đổi tên / thay thế url, mở rộng tài nguyên với các quan hệ bổ sung mà không phá vỡ mã giao diện người dùng.

Lưu trữ tài nguyên trên giao diện người dùng là một miếng bánh bằng cách sử dụng các liên kết tự. Chúng tôi cũng đẩy tài nguyên đến các máy khách thông qua kết nối socket, vì chúng cũng được hiển thị trong HAL nên chúng tôi có thể dễ dàng thêm chúng vào bộ nhớ cache theo cách tương tự.

Một lợi thế khác của việc sử dụng HAL-Json là rõ ràng mô hình phản hồi sẽ trông như thế nào, vì có một tiêu chuẩn được lập thành văn bản cần được tuân theo.

Một trong những tùy chỉnh của chúng tôi là chúng tôi đã thêm một hành động phản đối bên trong đối tượng tự liên kết mà phơi bày đến hết trước những hành động hoặc hoạt động CRUD người dùng đã xác thực được phép thực hiện trên tài nguyên tương ứng ( create:POST, read:GET, update:PUT, edit:PATCH, delete:DELETE). Như thế này, ACL giao diện người dùng của chúng tôi hoàn toàn được quyết định bởi phản hồi API REST của chúng tôi, chuyển toàn bộ trách nhiệm này sang mô hình kết thúc.

Vì vậy, để đưa ra một ví dụ nhanh, bạn có thể có một đối tượng bài đăng trong HAL-Json trông giống như sau:

{
    "_links": {
        "self": {
            "href": "https://hostname/api/v1/posts/1",
            "actions": {
                "read": "GET",
                "update": "PUT",
                "delete": "DELETE"
            }
        }
    },
    "_embedded": {
        "owner": {
            "id": 1,
            "name": "John Doe",
            "email": "john.doe@example.com",
            "_links": {
                "self": {
                    "href": "https://hostname/api/v1/users/1",
                    "actions": {
                        "read": "GET"
                    }
                }
            }
        }
    },
    "subject": "Post subject",
    "body": "Post message body"
}

Bây giờ tất cả những gì chúng ta phải làm trên front end là xây dựng một phương thức AclServicevới một isAllowedphương thức để kiểm tra xem hành động chúng ta muốn thực hiện có nằm trong đối tượng hành động hay không.

Hiện tại trên giao diện người dùng, nó trông đơn giản như sau: post.isAllowed('delete');

Tôi nghĩ REST cấp độ 3 là tuyệt vời, nhưng nó có thể dẫn đến một số đau đầu. Bạn sẽ cần phải hiểu nhiều về REST và nếu bạn muốn làm việc với REST cấp 3, tôi khuyên bạn nên tuân thủ nghiêm ngặt khái niệm REST nếu không bạn sẽ dễ dàng bị lạc đường khi thực hiện nó.

Trong trường hợp của chúng tôi, chúng tôi có lợi thế là chúng tôi đang xây dựng cả front-end nhưng về nguyên tắc nó KHÔNG tạo ra sự khác biệt. Nhưng một cạm bẫy phổ biến mà tôi đã thấy trong nhóm của chúng tôi là một số nhà phát triển cố gắng giải quyết các vấn đề về front-end (kiến trúc) bằng cách thay đổi mô hình back-end của họ để nó "phù hợp" với nhu cầu của front-end.


1
Câu trả lời rất hay. Tôi nghĩ một ví dụ thực tế như vậy là những gì người hỏi ban đầu đang tìm kiếm.
www.admiraalit.nl

2

Tôi đã sử dụng HATEOAS trong một số dự án thực tế, nhưng với cách hiểu khác với Richardson. Nếu đó là những gì sếp của bạn muốn, thì tôi nghĩ bạn nên làm điều đó. Tôi hiểu HATEOAS có nghĩa là tài nguyên của bạn nên bao gồm một loại tài liệu HTML, các siêu liên kết đến các tài nguyên liên quan và các biểu mẫu HTML để hiển thị chức năng cho các động từ không phải GET. (Đây là khi loại Chấp nhận là văn bản / html - các loại nội dung khác không yêu cầu các tính năng bổ sung này.) Tôi không biết niềm tin rằng tất cả các tài nguyên REST trong toàn bộ ứng dụng của bạn phải được gắn với nhau đến từ đâu. Một ứng dụng mạng phải chứa nhiều tài nguyên có thể liên quan trực tiếp hoặc không. Hoặc tại sao người ta tin rằng XML, JSON và các loại khác cần tuân theo điều này. (HATEOAS dành riêng cho HTML.)

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.