วันพุธที่ 9 ธันวาคม พ.ศ. 2558

ws part 5, 10 Best Practices for Better RESTful API

>> ขอยกประโยชน์ที่ได้ทั้งหมดนี้ รวมถึงเครดิตแก่เว็บ
- http://blog.mwaysolutions.com/2014/06/05/10-best-practices-for-better-restful-api/
ที่ช่วยอธิบายวิธีการออกแบบเว็บเซอร์วิสให้เป็นไปในทางที่เกิดประโยชน์แก่ความคิดและการใช้งานครับ

>> ผมอ่านแล้วจึงนำมาเล่าในแบบที่ผมเข้าใจนะ (แต่ถ้าเกิดว่าแปลความผิดไปก็ขออภัยอย่างยิ่ง) เขาบอกว่านี้เป็น 10 วิธีการประดิษฐ์หน้าตาของ uri ที่จะใช้เข้าถึง resource ครับ มาเริ่มกันเลย

1) จงเขียนมันด้วยคำนาม (หากคำนั้นเติม s คือนามพหูพจน์) ไม่เขียนมันด้วยกริยา เพื่อให้ง่ายต่อการสื่อความหมาย ดังตัวอย่างต่อไปนี้

/cars
- สำหรับ GET คืออ่าน list หรือรายการรถทั้งหมดออกมา
- สำหรับ POST คือสร้างรถหนึ่งคัน (ไว้บน server หรือเครื่องที่ให้บริการไงล่ะ)
- สำหรับ PUT คือปรับปรุงเปลี่ยนแปลงกลุ่มของรถทั้งกลุ่ม
- DELETE คือลบรถทุกคันออกจาก server หรือระบบที่กำลังใช้งานอยู่

/cars/711
- สำหรับ GET คือขอรถคันที่มี id เท่ากับ 711 มาให้ฉันหน่อย มันต้องมีเพียงคันเดียว!
- POST เรียกไม่ได้ครับ จะต้องได้ error 405 "ไม่อนุญาต" กลับมา เพราะเราจะไม่สร้างรถโดยระบุ id เข้าไปด้วย, ส่วนใหญ่แล้วรถหนึ่งคันเมื่อถูกสั่งให้สร้างจะเรียกไปที่ POST ของ /cars เฉยๆ และ id ของรถคันนี้ก็จะถูกรังสรรค์มาพร้อมกับตัวรถ
- PUT คือปรับปรุงรถหนึ่งคันที่มี id เท่ากับ 711
- DELETE คือลบรถหนึ่งคันที่มี id เท่ากับ 711

เหล่านี้จัดว่าเป็น api หรือหน้าตาของ uri ที่ดี แต่ตัวอย่างด้านล่างนี้ไม่ดีและไม่ควรทำ เช่น

/getAllCars คือขอรถทุกคัน
/createNewCar คือสร้างรถหนึ่งคัน
/deleteAllRedCars คือลบรถสีแดงทุกคัน

2) ไม่ใช่ GET เพื่อเปลี่ยนแปลงสถานะ นี่คือตัวอย่างที่ไม่ดี

GET /users/711?activate คือผู้ใช้ id เท่ากับ 711 ตอนนี้ถูก activate แล้ว
หรือ
GET /users/711/activate คือความหมายเดียวกัน

ควรใช้ PUT, POST และ DELETE ในการเปลี่ยนแปลงสถานะของ resource นั้นๆตามหน้าที่ของมัน จากตัวอย่างข้างต้นควรใช้ PUT

3) ไม่ใช้คำนามเอกพนจน์ผสมกับคำนามพหูพจน์ เพื่อให้ง่ายควรใช้เพียงคำนามพหูพจน์เท่านั้นสำหรับทุกๆ resources ตัวอย่างเช่น

จงใช้ /cars แทน /car
จงใช้ /users แทน /user
จงใช้ /products แทน /product
จงใช้ /settings แทน /setting

5) ใช้ HTTP headers ในการกำหนดรูปแบบ (formats) ที่ต้องการ (ว่าจะเอา text/plain หรือ application/xml หรือ application/json) ไม่ว่าจะเป็นฝั่งผู้ขอใช้บริการ (client) หรือฝั่งผู้ให้บริการ (server) ควรกำหนดรูปแบบที่ชัดเจนในการพูดคุยกันไปเลย โดยกำหนดผ่าน HTTP-Header ดังนี้
- Content-Type ใช้กำหนดรูปแบบของ request
- Accept ใช้กำหนดรายการรูปแบบที่สามารถยอมรับได้ของ response เช่นปกติไม่ระบุอะไรเลยได้รูปแบบ xml กลับมา พอระบุรูปแบบ json ณ Accept ก็จะได้ json กลับมา (รูปแบบเหล่านี้ขึ้นอยู่กับฝั่งผู้ให้บริการว่าจัดเตรียมให้มากน้อยกี่รูปแบบ)

6) จงใช้ HATEOAS มันคืออะไร?
ย่อมาจาก Hypermedia as the Engine of Application State หรือวิธีการเข้าถึง resource ผ่าน hypertext links หรือลิงค์นั่นแหละ เพื่อการ navigate ที่ยอดเยี่ยม เช่น เราให้บริการค้นหาเครื่อง notebook โดยให้ผู้รับบริการใส่โค้ดเนมของมันเข้ามา ,ทีนี้ผู้รับบริการก็ใส่โค้ดเนมว่า 711 (สมมติไง) เพราะเขาต้องการหา drivers ต่างๆของมัน (พอดีว่าลงวินโดว์ใหม่) ผลลัพธ์ที่เราในฐานะผู้ให้บริการควรจัดเตรียมไว้ควรเป็นดังตัวอย่างนี้ (ดัดแปลงและตัดเอาบางส่วนมา)

{
"id": 711, "model": "X5", "drivers": [ { "id": "23", "name": "Dynaudio sound", "links": [ { "rel": "self", "href": "/api/v1/drivers/23" } ] } ]
}

เห็นไหมว่ามีลิงค์ให้สามารถตามต่อไปยัง drivers ได้

7) มันควรสามารถอำนวยความสะดวกการ filtering (เลือกเอาข้อมูลบางกลุ่ม), sorting (เรียงลำดับ), field selection (เลือกเอาเฉพาะฟิลด์ที่ต้องใช้) และทำ paging ได้ มาดูตัวอย่างกันเลย

- Filtering เช่น
GET /cars?color=red เลือกรถทุกคันที่ทาสีแดง
GET /cars?seats<=2 เลือกรถทุกคันที่มีสองที่นั่ง หนึ่งที่นั่ง หรือไม่มีให้นั่ง?

- Sorting เช่น
GET /cars?sort=-manufacturer,+model
คือเรียงลำดับ manufacturer หรือรายการผู้ผลิตแบบ descending (ใช้เครื่องหมายลบ เพื่อสื่อว่าเรียงแบบมากไปหาน้อย) และ model แบบ ascending (ใช้เครื่องหมายบวก เพื่อสื่อว่าเรียงแบบน้อยไปหามาก)

- Field selection อาทิเช่น
การแสดงผล resource บนโทรศัพท์มือถือที่มีพื้นที่จำกัด เราอาจเลือกได้ว่าจะให้ field ไหนปรากฏบ้าง ทั้งนี้ก็เป็นการลดการจารจรบนเครือข่าย (reduce the network traffic) ทั้งยังเพิ่มความเร็วให้กับ api ของเรา ตัวอย่าง

GET /cars?fields=manufacturer,model,id,color คือขอแค่สี่ฟิลด์มาแสดงผล (ความจริงมีมากกว่าสิบฟิลด์ก็เป็นได้)

- Paging
api ควรสามารถกำหนด limit และ offset ได้ เพื่อความยืดหยุ่นในการดึงข้อมูลจากฐานข้อมูล ค่าเริ่มต้นทั่วไปคือ limit=20 และ offset=0 ตัวอย่าง

GET /cars?offset=10&limit=5 คือขอรถทั้งหมดตั้งแต่คันที่ 10 เป็นต้นไปเป็นจำนวน 5 คัน

และสำหรับค่า total entries หรือจำนวนรายการทั้งหมดตั้งแต่ offset เท่านี้ไปเท่านั้น limit, ก็สามารถหาได้จากการ custom HTTP header เช่น X-Total-Count

ลองคิดถึงหน้ารายงานหรือตาราง เราสามารถสร้าง previous page, next page ตลอดจน first or last page ได้นะครับ โดยความคิดของเจ้า paging นี่แหละ

8) สามารถสร้างลักษณะที่บอกเวอร์ชันของ api ร่วมด้วยจะเริดมาก ด้วยการใช้อักษร v ตัวอย่างเช่น
/blog/api/v1

9) บอก error ด้วย status code เท่าที่จำเป็นและเพียงพอ (รายงานได้เพียง error 500 นี่ไม่เอานะ เลวร้ายเกินไป) status code ที่ควรรายงานได้อาทิเช่น

200 – OK – Eyerything is working
201 – OK – New resource has been created
204 – OK – The resource was successfully deleted

304 – Not Modified – The client can use cached data

400 – Bad Request – The request was invalid or cannot be served. The exact error should be explained in the error payload. E.g. "The JSON is not valid"
401 – Unauthorized – The request requires an user authentication
403 – Forbidden – The server understood the request, but is refusing it or the access is not allowed
404 – Not found
422 – Unprocessable Entity

500 – Internal Server Error

หรือรายงานเป็น error payloads แทน status code ข้างต้นก็ได้ คือแทนที่จะเป็น 200, 400 หรือ 500 ก็เป็นอะไรที่ผู้ขอบริการอ่านแล้วเข้าใจทันที ใช้อีกบริบทหนึ่งมาอธิบายสิ่งที่เกิดขึ้นกับสิ่งที่เขาต้องการจึงจัดว่าแจ่มกว่า

10) ยอมให้สามารถ overrideing HTTP method
เขาว่ามีเครื่องตัวแทน (proxy หรือก็คือเครื่องที่มีสภาวะแวดล้อมดุจเดียวกับเครื่อง server แต่ไม่จัดเก็บข้อมูลจริงๆไว้กับตัว) บางเครื่องรองรับแค่ POST กับ GET เท่านั้น ควรแล้วที่จะต้อง custom HTTP Header ได้ ด้วยการกำหนดค่า X-HTTP-Method-Override, อันนี้ไม่ค่อยเข้าใจ ตัวอย่างไม่มี ในตอนนี้จึงขอผ่านไปก่อนนะครับ

>> และก็ครบสิบข้อ เพื่อที่ part ต่อไปเราจะทดลองนำหลายข้อมาใช้กับเว็บเซอร์วิสตัวอย่างของเรา อิอิ ฝันดีจ้า

ไม่มีความคิดเห็น:

แสดงความคิดเห็น