GraphQL ปะทะ REST: ศึก API ที่ REST ไม่เคยตาย!

Nuttavut Thongjor

บทความนี้มีจุดมุ่งหมายเพื่อชี้ให้เห็นว่าข้อดีบางอย่างของ GraphQL ก็สามารถสร้างขึ้นได้บน REST

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

หนึ่งในประเด็นฮ็อตร้อนแรงราวสามีคนที่ 8 ของลีนาจังนั่นก็คือ GraphQL แนวคิดส่งตรงจากเจ้าพ่อ Facebook ที่เหล่าสาวก React และไม่ React ขอเพียงแค่คุณหลงรักและศรัทธาในมาร์ค ซักเกอเบิร์ก ต่างอวยไส้แตกแหกไส้ฉีก

วิธีทดสอบความเป็นสาวกของ GraphQL นั้นง่ายมากครับ แค่คุณยิงคำถามไปว่า ทำไมเราต้องใช้ GraphQL ถ้า ก็ REST API มันห่วยไง เป็นคำตอบที่คุณได้รับ ยินดีด้วยครับคุณได้สนทนาธรรมกับสาวก GraphQL ผู้มีดวงตาเห็นธรรมเลเวล 99 เท้าเรืองแสงแล้วหละ

หลายคนที่ไม่เคยได้ยิน GraphQL คงอยากรู้แล้วว่ามันคืออะไร และอีกหลายคนที่รู้อยู่แล้วก็คงอยากทราบว่า RESTful API จะเอาอะไรมาต่อกร ในเมื่อ GraphQL เกิดมาเพื่อแก้ปัญหาของ REST?

เมื่อ REST API เปลี่ยนโลก

กาลครั้งหนึ่งนานนิดหน่อย โลกหมุนไปด้วยแนวคิดของ SOAP Web Service แบบยาสามัญประจำบ้าน คุณครูที่น่ารักและบริษัทต่างๆล้วนสอนและออกแบบ SOA บนพื้นฐานของการเขียน WSDL แต่ไม่ใช่สำหรับปัจจุบันที่เรานิยมออกแบบ API และ service ของเราด้วย RESTful API เพราะความเรียบง่าย REST คุณจึงได้ไปต่อ

อยากได้ข้อมูลหนังสือทั้งหมดใช่ไหม ยิง GET request ซิ จัดไป~

Code
1GET /api/v1/books

อยากได้หนังสือที่มี ID เป็น 1 หรือ? ยิง GET อีกรอบไปเลย ผลาญ 3G กันให้สะใจ~

Code
1GET /api/v1/books/1

หลังจากบันเทิงกับการยิง REST กันไปแล้ว ลองมาดูหน้าตาผลลัพธ์จากการร้องขอข้อมูลหนังสือทั้งกะบิกันบ้างครับ

Code
1{
2 "books": [
3 {
4 "id": 1,
5 "title": "Babel Coder 101",
6 "isbn": 112233,
7 "published_at": "2016-11-11",
8 "authorId": 1
9 },
10 {
11 "id": 2,
12 "title": "Babel Coder 102",
13 "isbn": 112234,
14 "published_at": "2016-11-11",
15 "authorId": 2
16 }
17 ]
18}

Perfect! แค่คืนค่ากลับเป็น JSON โลกก็ดูสวยงาม

ลองจินตนาการต่อครับถ้าแอพพลิเคชันของเราต้องการข้อมูลหนังสือพร้อมทั้งข้อมูลผู้แต่งด้วยเราจะทำยังไง? รอบแรกเราก็ต้องเรียกไปที่ GET /api/v1/books เพื่อให้ได้มาซึ่งข้อมูลหนังสือทั้งหมด แต่ผู้แต่งของเราอยู่ในรูป ID เราจึงต้องวิ่งต่อไปที่ GET /api/v1/authors/:id เพื่อให้ได้ข้อมูลผู้แต่ง ถ้าผู้แต่งเรามีซักสิบคน เราก็ต้องส่ง request เพื่อร้องขอผู้แต่งสิบครั้ง? ดึงข้อมูลจากฐานข้อมูลอีกสิบครั้ง? ช่างเสียเวลาแท้

side-loading ช่วยชีวิต

อย่ากระนั้นเลย เมื่อการร้องขอ author เป็นสิ่งเปลืองแรง เราก็คืนค่าหนังสือกลับมาพร้อมทั้งผู้แต่งซะเลยซิ แบบนี้

Code
1{
2 "books": [
3 {
4 "id": 1,
5 "title": "Babel Coder 101",
6 "isbn": "112233",
7 "published_at": "2015-05-22T14:56:29.000Z",
8 "author": {
9 "id": 1,
10 "name": "Nuttavut Thongjor",
11 "age": 9
12 }
13 },
14 {
15 "id": 2,
16 "title": "Babel Coder 102",
17 "isbn": "112234",
18 "published_at": "2015-05-22T14:56:29.000Z",
19 "author": {
20 "id": 2,
21 "name": "Thongjor Nuttavut",
22 "age": 19
23 }
24 }
25 ]
26}

ก้อนมวล JSON เหล่านี้ช่างตอบโจทย์เราดีแท้ โอเคซื้อเลย!

เมื่อโลกมือถือเบ่งบาน

เมื่อระบบของคุณต้องรองรับการใช้งานบนแพลตฟอร์มมือถือ ด้วยดีไซน์ใหม่ทำให้เราไม่ต้องการข้อมูล published_at ของ book หรือ age ของ author อีกต่อไป (เว้นแต่คุณจะเอาไปแทงหวย) แต่ Restful API ของเรายังคืนกลับด้วยก้อน JSON เต็มรูปแบบเช่นเดิม คำถามอยู่ตรงที่ แล้วเราจะคืนข้อมูลที่ไม่ได้ใช่กลับมาด้วยทำไม?

ศาสตร์ API ฉบับ 7 ป่าช้าด้วย GraphQL

จะดีกว่าไหมถ้าเราอยากขอข้อมูลแบบไหนก็ได้ อยากได้ field อะไรก็ขอได้ไม่ถูกจำกัดด้วยหน้าตาเดิมๆของผลลัพธ์จาก REST API หากเราต้องการเพียงข้อมูล id, title และ ISBN จาก book และต้องการ id, name จาก author เป็นไปได้ไหมที่เราจะร้องขอข้อมูลเช่นข้างล่างนี้ แทนที่จะยิง GET ตู้มเดียวแล้วเสี่ยงโชคกับผลลัพธ์ที่คืนกลับเอาเอง

Code
1books {
2 id,
3 title,
4 isbn,
5 author {
6 id,
7 name
8 }
9}

GraphQL เป็นภาษาสำหรับสืบค้นข้อมูลจาก API ทั้งยังมีส่วนขยายเพื่อประมวลผลไอ้ก้อน request ที่เราส่งมายังฝั่งเซิฟเวอร์อีกด้วย เมื่อก้อนข้อมูลข้างต้นผ่านเข้ามา API Server ที่ใช้ GraphQL จะเข้าใจทันทีว่าเราต้องการข้อมูล id, title และ isbn จาก books และต้องการเฉพาะ id และ name จาก author ฉลาดใช่ไหมหละ?

GraphQL นั้นแก้ปัญหาของ REST API ข้างต้น ต่อไปนี้ทุก response ที่ตอบกลับจะมีเฉพาะข้อมูลที่เราต้องการ เพราะเราสามารถระบุให้คืนกลับเฉพาะฟิลด์ที่เราสนใจได้ นอกจากนี้ GraphQL ยังทำให้เราได้ข้อมูลครบในการร้องขอเพียงครั้งเดียว เราไม่จำเป็นต้องร้องขอข้อมูลรอบแรกเพื่อให้ได้ author_id แล้วนำค่านี้ไปสอบถามเพื่อให้ได้ข้อมูลของ author อีกทอดนึงต่อไปแล้ว

RESTful API ไม่ใช่โคนัน ความจริงไม่มีเพียงหนึ่ง

หลังจากตาลุง Roy Fielding ได้ออกแบบ REST ไว้เมื่อปี 2,000 รูปแบบการใช้งาน REST API อย่างคร่าวๆที่เราพบเห็นกันทุกวันนี้ก็เริ่มแพร่หลายมากขึ้น จากนั้นเราได้มีการกำหนดรูปแบบการใช้งานกันเพิ่มเติม จนกระทั่งมีรูปแบบที่โด่งดังในเฟรมเวิร์กอย่าง Ruby on Rails ลามไปถึงเฟรมเวิร์กอื่นๆที่สืบทอดมรดกจาก Ruby on Rails เช่น Laravel

ตัวอย่างข้อกำหนด REST API ที่เรานิยมปฏิบัติกัน เช่น

  • ใช้ HTTP Verb ให้ถูกต้อง ตัวอย่างเช่นใช้ PATCH สำหรับการอัพเดท article บางส่วน และใช้ POST สำหรับการสร้าง article ใหม่
  • ใช้ HTTP Status Code ให้ถูกต้อง เราไม่ควรส่ง 200 OK พร้อมแปะ error ไปว่า “Not Found” กลับไป แต่ควรส่ง 404 กลับไปแทน หรือกรณี login ด้วยอีเมล์ ถ้าเราหา email ไม่พบนั่นคือไม่มีผู้ใช้งานนี้ในระบบ เราไม่ควรส่ง 404 Not Found กลับไป แต่ต้องส่ง 401 Unauthorized

รายละเอียดอื่นๆเพื่อนๆสามารถอ่านเพิ่มเติมได้จาก ออกแบบ REST API ยังไงดี? แนะนำ jsonapi

แม้เราจะมีหลักปฏิบัติกลางๆที่ใช้กันอยู่ตามที่กล่าวข้างต้น แต่โลกเราไม่ได้มีพื้นที่ไว้เพื่อไอเดียเดียวครับ ตอนนี้เราต่างมี guidelines ผุดออกมาเป็นดอกเห็ดเพื่อแนะนำแนวทางการสร้าง REST API ที่ดี ไม่ว่าจะเป็นแนวทางของ Microsoft หรือของ Heroku หรือของเจ้าอื่นๆที่เลี่ยงไม่ระบุในที่นี้

ปัญหาของ REST ก็แก้ได้ด้วยวิธีของ REST

เมื่อ guidelines ในการสร้าง REST API ยังมีได้หลายเจ้า แล้วทำไมจะมีซักเจ้าที่บอกให้เราออกแบบ API ของเรา เพื่อแก้ปัญหาที่เกิดขึ้นข้างต้นไม่ได้ละ?

ก่อนที่เราจะไปต่อ มาทบทวนกันซักนิดว่าปัญหาของ REST API ตอนนี้มีอะไรบ้าง

  • คืนค่าข้อมูลกลับไม่เพียงพอ เช่นร้องขอข้อมูลหนังสือ แต่ข้อมูลผู้แต่งคืนกลับมาแค่ author_id ทำให้เราต้องร้องขอข้อมูลอีกรอบ เพื่อให้ได้มาซึ่งข้อมูลผู้แต่งฉบับเต็ม
  • คืนค่าข้อมูลกลับเยอะเกินไป ในแพลตฟอร์มต่างๆเราอาจต้องการฟิลด์ต่างกัน บนเดส์กทอปเราอาจต้องการทั้ง isbn และ published_at ของหนังสือ แต่ต้องการเฉพาะ isbn บนแพลตฟอร์มมือถือ หาก API ของเราคืนค่าทั้ง isbn และ published_at กลับมาเสมอ ข้อมูล published_at จะกลายเป็นส่วนเกินทันทีสำหรับการใช้งานบนมือถือของเรา

ไม่ต้องแก้สองปัญหานี้ด้วย GraphQL ก็ได้ เพราะวันนี้ TV Direct ขอนำเสนอ... แท่น แทน แท๊น JSON API

ศาสตร์ API ฉบับคัมภีร์ 7 ดวงดาว ด้วย JSON API

JSON API เป็นอีกหนึ่งสเปคสำหรับการสร้าง REST API นอกจากมันจะรวมแบบแผนที่ดีในการสร้าง API แล้ว เพื่อนๆยังสามารถเสาะหาไลบรารี่เพื่อใช้งาน JSON API กับภาษาหรือเฟรมเวิร์กต่างๆได้อย่างง่ายดาย

แรกเริ่มที่ JSON API ออกมาใหม่ๆ เฟรมเวิร์กรุ่นเดอะอย่าง Ruby on Rails ก็ได้สนับสนุนการใช้งานอย่างสมบูรณ์ผ่าน ActiveModelSerializers รวมไปถึงฝั่ง client อย่าง Ember 2 แม้ชีวิตจะตกอัพ หมาไม่มองโปรแกรมเมอร์เมินขนาดไหน แต่ท่านก็ยังสนับสนุน JSON API ผ่าน Ember Data แต่แรกเลยเชียว

หลังจากอวยสินค้าจนหมดเวลาโฆษณากันไปแล้ว ก็ถึงเวลาแสดงสรรพคุณในการแก้ปัญหาของ REST ข้างต้นกันเสียที...

side-loading ด้วย include

เราต้องการให้การร้องขอข้อมูลจบใน request เดียวโดยไม่ต้องสร้าง request อื่นเพิ่มเพื่อไปขอข้อมูลอื่นอีก เราจึงทำ side-loading นั่นคือรวมสิ่งที่เราอยากได้ไว้ในผลลัพธ์ที่คืนกลับมาซะเลย เช่นเราคืนค่า author ที่ประกอบด้วย id และ name กลับทุกครั้งเมื่อมีการร้องขอข้อมูล book

side-loading ข้างต้นเป็นแนวคิดที่ดี หากแต่ทุก request อาจไม่ต้องการข้อมูล author เสมอไป เมื่อเราคืนค่า author กลับทุกครั้งย่อมเป็นข้อมูลที่สูญเปล่าเมื่อไม่ต้องการ

JSON API แก้ปัญหานี้ด้วยการให้เราระบุว่ามีสิ่งอื่นใดที่เราต้องการเพิ่มเติมไหม ถ้ามีเราต้องระบุภายใต้ include เช่น ถ้าเราต้องการให้การร้องขอข้อมูล books คืนค่า author กลับมาด้วยเราต้องระบุ author ภายใต้ include ดังนี้

Code
1GET /api/v1/books?include=author

เป็นผลให้เกิดการคืนค่ากลับของ author มาด้วยในพร็อพเพอร์ตี้ included

Code
1{
2 "data": [
3 {
4 "type": "books",
5 "id": "1",
6 "attributes": {
7 "title": "Babel Coder 101",
8 "isbn": "112233",
9 "published_at": "2015-05-22T14:56:29.000Z"
10 },
11 "relationships": {
12 "author": {
13 "data": {
14 "id": "1",
15 "type": "people"
16 }
17 }
18 }
19 },
20 {
21 "type": "books",
22 "id": "2",
23 "attributes": {
24 "title": "Babel Coder 102",
25 "isbn": "112234",
26 "published_at": "2015-05-22T14:56:29.000Z"
27 },
28 "relationships": {
29 "author": {
30 "data": {
31 "id": "2",
32 "type": "people"
33 }
34 }
35 }
36 }
37 ],
38 "included": [
39 {
40 "type": "people",
41 "id": "1",
42 "attributes": {
43 "name": "Nuttavut Thongjor",
44 "age": 9
45 }
46 },
47 {
48 "type": "people",
49 "id": "2",
50 "attributes": {
51 "name": "Thongjor Nuttavut",
52 "age": 19
53 }
54 }
55 ]
56}

เลือกเฉพาะ field ที่ต้องการด้วย Sparse Fieldsets

ปัญหาอีกข้อของ REST ที่เรากล่าวถึงคือการคืนกลับของข้อมูลที่มากเกินไป หากเราต้องการให้เซิฟเวอร์ตอบกลับเพียงฟิลด์ที่เราสนใจ JSON API มีทางออกให้กับเพื่อนๆครับผ่านสิ่งที่เรียกว่า Sparse Fieldsets

ถ้าความต้องการคือร้องขอข้อมูล books แต่สนใจเฉพาะฟิลด์ id และ name เราสามารถร้องขอผ่าน HTTP GET ได้ดังนี้

Code
1/api/v1/books?fields[books]=id,name

เราเพียงใช้ query string เพื่อบอกว่า field ที่เราสนใจคือ id และ name เพียงเท่านี้เราก็ได้ผลลัพธ์ตามคำถามที่เราต้องการโดยไม่ต้องพึ่ง GraphQL จ้า

แล้วสรุปว่า GraphQL หรือ REST ดีกว่ากัน?

ปัญหาของ REST ที่เหมือนจะมีเพียง GraphQL ที่แก้ได้ แต่ท้ายที่สุด REST ก็มีวิธีของมันเองในการจัดการปัญหา แล้วสรุปว่าอะไรดีกว่ากัน

มาตรฐาน HTTP

ตามมาตรฐานของ HTTP นั้นกล่าวไว้ว่า เราใช้ GET เพื่อการเข้าถึงข้อมูล, ใช้ POST เพื่อสร้างข้อมูลใหม่, ใช้ PUT เพื่อแทนที่ข้อมูลเดิมทั้งก้อน และใช้ PATCH เพื่อเปลี่ยนแปลงข้อมูลเดิมบางส่วน เป็นต้น เหล่านี้คือหลักการของการใช้ HTTP Verbs ฉบับย่อที่เป็นที่เข้าใจกันดี

REST API ยึดหลักการออกแบบตาม HTTP Verbs ข้างต้น จึงถือว่าเป็นการปฏิบัติตาม standard ของ HTTP แต่ไม่ใช่สำหรับ GraphQL ที่เราเข้าถึงข้อมูลได้สองทางผ่าน GET หรือ POST โดยไม่สนใจความหมายของ HTTP Verb เหล่านั้น

ความง่ายต่อการเรียกใช้

ในกรณีที่โครงสร้างข้อมูลของเราเป็นไปอย่างเรียบง่าย ไม่ต้องการการเข้าถึงที่ซับซ้อนมากนัก วิธีการของ REST ช่วยให้คุณหัวหมุนน้อยสุด

คุณรู้ว่าคุณต้องการข้อมูลหนังสือที่มี ID เป็น 1 แค่คุณเข้าถึง /api/v1/books/1 คุณก็ได้ข้อมูลตามต้องการแล้ว เรียบง่ายและสะดวกใช่ไหมละ

ในมุมกลับถ้าคุณต้องการข้อมูลหนังสือแต่เอาเฉพาะข้อมูล ID, name และ author ของมัน เงื่อนไขพิเศษคือข้อมูล author ที่คืนกลับ เราต้องการแค่ ID และ name เท่านั้น นี่คือสิ่งที่คุณต้องเรียกผ่านมาตรฐานของ JSON API

Code
1GET /api/v1/books?include=author&fields[books]=id,name,author&fields[people]=id,name

เป็นไงหละ อัปรีย์ดีแท้?

ด้วยพลานุภาพแห่ง GraphQL ข้อมูลที่คืนกลับ ย่อมมีรูปร่างเดียวกับสิ่งที่ร้องขอ นั่นคือสิ่งที่จะพลิกชีวิตการร้องขอข้อมูลที่ซับซ้อนให้กับคุณได้

Code
1books {
2 id,
3 name,
4 author: {
5 id,
6 name
7 }
8}

เพียงคุณร้องขอข้อมูลเช่นนี้ผ่าน GraphQL คุณไม่ต้องสร้าง Query String ประหลาดแบบใน JSON API เพียงคุณมองตา คุณก็รู้ไปถึงก้นกบว่าสิ่งที่คืนกลับต้องมีรูปร่างเดียวกับที่ร้องขอนั่นเอง

ถึงตรงนี้เพื่อนๆคงตอบตัวเองได้แล้วครับว่าแบบไหนให้ความรู้สึกง่ายต่อการเรียกใช้งานกว่ากัน สำหรับผู้เขียนคิดว่าวิธีเข้าถึงข้อมูลของ GraphQL นั้นดูดีและเป็นธรรมชาติกว่าเยอะครับ

ความง่ายต่อการสร้าง API

แม้การเรียกใช้ GraphQL จะดูเรียบง่าย แต่การสร้าง API นี่ซิต่างกันราวหน้ามือกับแก้มก้น

เพื่อตอบสนองการส่ง request ที่สวยงามได้ บริการของ GraphQL ที่เพื่อนๆต้องสร้างขึ้นมาจึงไม่ง่ายเท่าใดนัก เพื่อนๆต้องเรียนรู้คอนเซปต์ใหม่ๆในโลกของ GraphQL ไม่ว่าจะเป็น Schemas, Types, Resolvers และอื่นๆ นอกจากนี้เพื่อนๆยังต้องรู้วิธีการแก้ปัญหาในเชิงลึกของ GraphQL ด้วย เช่น ถ้าเพื่อนๆใช้งาน GraphQL แบบลูกทุ่ง เพื่อนๆจะพบเจอกับปัญหา N + 1 queries เป็นแน่ เราก็ต้องรู้จักการแก้ปัญหานี้ด้วยการทำ Batch Requests ผ่าน DataLoader เป็นต้น

การใช้ GraphQL แบบเปล่าเปลือยเป็นบาประดับรากหญ้า ปัญหาหลักที่จะเจอแน่คือเราจะทำ Client Side Caching ยังไง? แต่ถ้าคุณจับคู่กับเทคโนโลยีจากโรงงานเดียวกันอย่าง Relay แล้วหละก็ ปัญหาข้างต้นก็จะผ่านฉลุย

เพื่อเป็นการชำระบาปขั้นต้น คุณจึงควรเรียน Relay ตามมาด้วย หรือถ้าคุณเกลียดขี้หน้า Facebook เพราะ Patent License แล้วหละก็ Apollo คืออีกหนึ่งทางเลือกของคุณ อ้า~ เข้าสเต็ปเดิมคือ Learning Curve ที่สูงปรี๊ดทะลุพลูโตกันไปเลย

แล้วทางฝั่ง REST ละ? แน่นอนครับว่า REST ไม่ใช่ของใหม่แบบ GraphQL เราผ่านร้อนผ่านหนาวมาเยอะ อะไรจึงง่ายกว่ากันเยอะ REST API ได้รับการสนับสนุนให้ใช้งานได้แต่ต้นในแทบจะทุกภาษาและเฟรมเวิร์ก ไม่ว่าจะเป็น Ruby on Rails, Laravel, Phoenix, Hapi และอื่นๆ ผิดกับอีกฝาก ด้วยความใหม่ของ GraphQL คุณจะเจอปัญหาแน่ถ้าคุณใช้ GraphQL กับเซิฟเวอร์ที่ไม่ใช่ Node.js

API Explorer

API Explorer เป็นโปรแกรมที่มีส่วนต่อประสานให้เราทดลองเรียกใช้งาน API ของเราได้

ในฝั่งของ REST มี API Explorer ให้เลือกใช้งานมากมาย เช่น Postman ซึ่งคงผ่านมือเพื่อนๆมาแล้วแทบทุกคน API Explorer เหล่านี้ส่วนใหญ่ไม่มีการตรวจสอบการใส่ข้อมูลให้กับเรา เรากรอกข้อมูลในการเรียกใช้ API ผิดถูกรึเปล่าไม่รู้ ไปตายเอาดาบหน้าแล้วกัน ถ้าได้ข้อมูลกลับมาแบบไร้ Error ก็คงกรอกข้อมูลส่งไปถูกแล้วกระมัง

postman

สำหรับ GraphQL นั้นต่างออกไป เรามี GraphiQL เป็น API Explorer ของฝั่ง GraphQL

GraphiQL

คำถามอยู่ที่ว่า REST ก็มีนะ API Explorer แถมมีมากกว่าตั้งหลายเจ้า ไอ้เจ้า GraphiQL ของ GraphQL จะเอาอะไรมาต่อกร?

GraphiQL นอกจากจะอนุญาตให้คุณร้องขอข้อมูลผ่านตัวมันเองได้แล้ว ข้อความอธิบายการใช้งานและการตรวจสอบการใช้งาน ก็ถือเป็นจุดเด่นที่หาได้ยากใน REST

GraphiQL Features

จากรูปข้างบน GraphiQL บอกเพื่อนๆได้ว่า sex ไม่ใช่ฟิลด์ที่เพื่อนๆสามารถเรียกใช้ได้นะ (มีขีดยึ๊กยือสีแดงเป็นตัวบ่งชี้) พร้อมทั้งแสดงรายการฟิลด์ทั้งหมดที่สามารถเรียกใช้ได้ด้วย อีกจุดที่สำคัญ เพื่อนๆจะเห็นว่าสำหรับฟิลด์ name GraphiQL ยังมีคำอธิบายโผล่มาให้ด้วยว่า The name of this person แถมกระซิบให้อีกนิดว่าฟิลด์นี้เป็น String เจ๋งใช่ไหมละ

GraphiQL ดีงามพระราม 8 ขนาดนี้ แน่ใจหรือว่าฝั่ง REST ทำไม่ได้? ฝั่ง REST ก็มีเครื่องมือหลายตัวครับที่ทำเช่นนี้ได้ เพียงแต่เราต้องเขียนอะไรบางอย่างเพิ่มเติมในโค้ดของเรา เพื่อเพิ่มความสามารถแบบนี้เข้าไป

Schema และ Type

และสิ่งที่ทำให้ GraphiQL สามารถบอกเพื่อนๆได้ว่า ระบบของเราประกอบด้วยฟิลด์อะไรบ้าง, มีอะไรให้เราเรียกใช้บ้าง , แต่ละฟิลด์เหล่านั้นมีชนิดข้อมูลเป็นอะไร และตรวจสอบข้อมูลฟิลด์ยังไง สิ่งเหล่านี้เกิดขึ้นได้เพราะ Type

GraphQL เป็นระบบที่มีชนิดข้อมูลครับ (Type System) เราจึงสามารถสร้างชนิดข้อมูลใหม่ขึ้นมาได้ รวมถึงฟิลด์ที่พึงมีในชนิดข้อมูลเหล่านั้น นอกจากนี้เรายังสามารถเพิ่มคำอธิบายฟิลด์นั้นผ่าน description ได้เช่นกัน ข้างล่างคือตัวอย่างจากการใช้งานผ่าน GraphQL.js ครับ

JavaScript
1const PersonType = new GraphQLObjectType({
2 name: 'Person',
3 fields: () => ({
4 name: {
5 type: GraphQLString,
6 description: 'The name of this person.',
7 },
8 age: {
9 type: GraphQLInt,
10 description: 'The age of this person.',
11 },
12 }),
13})

กลับมาที่คำถามเดิมๆอีกครั้ง แล้ว REST ละ?

ในโลกของ REST เรื่องมีเครื่องมือมากมายเพื่อเพิ่ม Type ให้กับ JSON และ API ของเรา เช่นการใช้ JSON Schema หรือ OpenAPI แน่นอนว่าของเหล่านี้บางทีมก็ไม่ได้ใช้ บางทีมที่ใช้ก็อาจจะไม่ได้ใช้เครื่องมือเดียวกัน นั่นคือความไม่มีมาตรฐานของเครื่องมือทำให้ยากต่อการสับเปลี่ยน ในขณะที่ GraphQL ตั้งอยู่บน Schema และ Type ที่เป็นมาตรฐานเดียว

Linter

เพราะ GraphQL เป็นภาษาและมีมาตรฐานเดียว จึงไม่ใช่เรื่องยากที่จะมีเครื่องมือประเภท Linter ไว้ตรวจสอบความถูกต้องของการเขียนการเขียน GraphQL เช่น eslint-plugin-graphql

อื่นๆ

เนื่องจาก Babel Coder ยังไม่มีบทความเรื่อง GraphQL เพื่อป้องกันความสับสนในบทความนี้ จึงเลี่ยงที่จะกล่าวข้อดีอื่นๆของ GraphQL แต่ต้องบอกเลยครับว่า GraphQL ไม่ได้ขี้เหร่นะ ลองคิดดูซิถ้าของมันหน่อมแน้ม ระดับ Facebook คงไม่เข็นออกมาขายหรอกจริงไหม?

สรุป

เพื่อให้เห็นภาพมากขึ้น เรามาลองเปรียบเทียบเป็นแบบตารางกันดีกว่า

FeatureGraphQLRESTful
มาตรฐาน HTTPไม่ตามมาตรฐานตรงตามการใช้งาน HTTP VERBS
ความง่ายต่อการเรียกใช้งานง่ายมาก เมื่อต้องจัดการกับข้อมูลและฟิลด์ที่ซับซ้อนง่ายมากเมื่อข้อมูลไม่ซับซ้อน
ความง่ายต่อการสร้าง APIยากง่าย
API ExplorerGraphiQLPostman และอื่นๆ
Schema และ Typeเป็นมาตรฐานมีหลายมาตรฐาน เช่น JSON Schema หรือ OpenAPI
LinterมีN/A

ควรหรือไม่ที่จะใช้ GraphQL

สิ่งนึงที่โปรแกรมเมอร์ส่วนหนึ่งมักตกหลุมพรางคือการตามกระแสที่มากเกินไป เทคโนโลยีอะไรมาใหม่ฉันขอเอาหมด ของไหนเขาว่าเลิศฉันหยิบมาใช้กับโปรเจคปัจจุบันทันทีโดยขาดการคำนึงถึงความต้องการที่แท้จริง

GraphQL เป็นเรื่องที่น่าสนใจครับ หากเพื่อนๆมีเวลาก็ควรศึกษาไว้บ้าง ถ้าโปรเจคที่เพื่อนๆทำอยู่ใช้ REST และเจอปัญหาตามที่กล่าวมาต้นบทความ เพื่อนๆไม่ควรย้ายไป GraphQL โดยไม่ไตร่ตรองถึงผลได้ผลเสียครับ ลองมองหาวิธีแก้ปัญหาแบบ REST ดู เช่น ใช้ JSON API หรือออกแบบการใช้งาน Query String เพื่อแก้ปัญหาเหล่านั้น

GraphQL ควรเริ่มกับโปรเจคใหม่ไหม? สิ่งนี้ไม่ได้ขึ้นอยู่กับเทคโนโลยีอย่างเดียว ผมอยากให้เพื่อนๆมองไปที่ทีมครับว่าทุกคนพร้อมที่จะเรียนรู้ไหม การปรับเปลี่ยนไปสู่เทคโนโลยีใหม่ที่ทีมไม่คุ้น มันต้องผ่านการไตร่ตรองหลายรอบหน่อย มีการลองผิดลองถูกซะหน่อยก่อนเริ่มใช้จริง

คำถามครับ คุณอยากกิ๊บเก๋ด้วยแนวทางที่ implement ยากกว่าแบบ GraphQL เพื่อจัดการเว็บบลอคของคุณที่มีคนเข้าชมแค่วันละหลักร้อยรึเปล่า?

ถ้าโครงสร้างข้อมูลที่ต้องการรับส่งจากการเรียกใช้ API ของเพื่อนๆไม่ซับซ้อน การออกแบบตามมาตรฐาน REST ก็ไม่ใช่เรื่องบาปอะไร ไม่งั้นคนเราคงจะบาปกันไปทั้งโลกแล้ว แต่ถ้าเราต้องการประสิทธิภาพในการเข้าถึงข้อมูลที่ดีกว่าแบบที่ Facebook เป็น GraphQL ก็เป็นอีกทางเรื่องที่กิ๊บเก๋ไม่เบา

สรุป

ไม่ว่า REST หรือ GraphQL จะเป็นสิ่งที่เพื่อนๆเลือกใช้เพื่อสร้าง API ขึ้นมา สิ่งหนึ่งที่จะลืมไม่ได้นั่นคือความง่ายในการเข้าถึงและใช้งาน หากการออกแบบนั้นๆเต็มไปด้วยความซับซ้อนย่อมไม่เกิดผลดีทั้งผู้ใช้และผู้สร้าง จึงอยากให้เพื่อนๆไตร่ตรองก่อนครับว่าเราจะสร้างอะไร เพื่ออะไร อย่าวิ่งตามเทรนโดยไม่สนใจว่าเรากำลังทำอะไรอยู่ ไม่ใช่ว่า GraphQL ดังแล้วจะทิ้ง REST ที่ทำงานกับโปรเจคของคุณได้ดีกว่า เพียงเพราะต้องการไหลไปตามกระแสนิยมที่มาใหม่

GraphQL ก็เหมาะสมกับการใช้งานแบบหนึ่ง REST ก็ยังคงเหมาะกับความเรียบง่ายและการใช้งานอีกแบบหนึ่ง ด้วยเหตุนี้ผมจึงขึ้นหัวบทความไว้ว่านี่คือศึกที่ REST ไม่เคยตาย! ยังไงละ

เมื่อ API ของเพื่อนๆดีพอ ก็เตรียมรอคอยได้เลยครับ ว่าซักวันหนึ่งทุกคนจะต้องเห็นค่าและมา #กราบ API กู

ติดตามการสร้าง GraphQL Server ในบทความหน้า Stay tuned!

สารบัญ

สารบัญ

  • เมื่อ REST API เปลี่ยนโลก
  • ศาสตร์ API ฉบับ 7 ป่าช้าด้วย GraphQL
  • RESTful API ไม่ใช่โคนัน ความจริงไม่มีเพียงหนึ่ง
  • ปัญหาของ REST ก็แก้ได้ด้วยวิธีของ REST
  • ศาสตร์ API ฉบับคัมภีร์ 7 ดวงดาว ด้วย JSON API
  • แล้วสรุปว่า GraphQL หรือ REST ดีกว่ากัน?
  • ควรหรือไม่ที่จะใช้ GraphQL
  • สรุป