Try GraphQL (จากมุมมองของ Client Dev)
สิ่งที่เราจะเข้าไปข้องแวะวันนี้คือ …

GraphQL
… 1 GraphQL คืออะไร
… 2 มีอะไรบ้างที่ทำมา support GraphQL
… 3 Client Side Dev ต้องรู้อะไรบ้าง
… 3.1 พื้นฐานการสร้าง query และ mutation
… 3.2 Schemas & Types
… 3.3 ยิง GraphQL server จาก tool อะไรได้บ้าง
… 1 GraphQL คืออะไร ?
GraphQL เป็น query language สำหรับ API มันไม่ได้ผูกกับ database หรือว่า storage engine ใดๆเฉพาะเจาะจง เราจึงสามารถใช้ implementation และ/หรือ ข้อมูลที่มีอยู่แล้วได้
ในการสร้าง GraphQL service จะมีการกำหนด type และ field บน type นั้นๆ จากนั้นจึงสร้าง function สำหรับแต่ละ field ของแต่ละ type นั่นเอง
ขอยกตัวอย่าง ‘Login User’ service
type Query {
me: User
}
type User {
id: ID
name: String
}GraphQL service ข้างต้น ประกอบด้วย
- type Query ซึ่งมี field me โดยที่ field me นั้นมี type เป็น User
- type User ประกอบด้วย field id และ name โดยที่มี type เป็น ID และ String ตามลำดับ
หลังจากกำหนด type และ field แล้ว จากนั้นก็ทำการสร้าง function สำหรับแต่ละ field ในแต่ละ type
function Query_me(request) {
return request.auth.user;
}function User_name(user) {
return user.getName();
}
ในขั้นตอนของการ query query ที่ถูกส่งเข้ามาจะถูก validate (เช็ค types และ field ว่าถูก defined ไว้จริงๆ) และ execute โดยการรัน function ที่จัดทำไว้ และสร้าง result ออกมา
มาดูตัวอย่างของการ query กัน
{
me {
name
}
}result ที่ได้จาก query ข้างต้น จะออกมาในรูปแบบข้างล่าง
{
"me": {
"name": "Luke Skywalker"
}
}ถึงจุดนี้ ถ้ายังมองไม่เห็นภาพก็ไม่เป็นไร ส่วนต่อๆไปจะช่วยให้ภาพในหัวชัดเจนขึ้น
… 2 มีอะไรบ้างที่ทำมา support GraphQL
Programming Language อะไรบ้างที่มี Library สำหรับการ implement GraphQL ? ต้องถามก่อนว่า พูดถึงฝั่งไหน เพราะการคุยกันเป็น GraphQL นั่นต้องอาศัยความร่วมมือจากทั้งฝั่ง Server และ Client นั่นเอง มันก็เหมือนกับการสื่อสารของคนเรา ถ้าเราใช้ภาษามือในการสื่อสารออกไป ถ้าผู้รับสารเข้าใจภาษามือก็จะสามารถรับสารได้

ถ้าพูดถึงทาง Server-side นั้น GraphQL ถูก support ในหลายภาษาด้วยกัน เช่น JavaScript, Go, etc.
ส่วนฝั่งของ Client ก็มี Library ที่หลากหลาย อาทิเช่น

- Swift : Apollo iOS
- Java/Andriod : Apollo Android
- JavaScript : Apollo Client, etc.
- etc.
นอกจาก Server-side Framework และ Client Libraries ที่ถูกทำขึ้นมา support GraphQL ในแต่ละฝั่งแล้ว ยังมีพวก Tool และ Service ที่ทำขึ้นมา facilitate การใช้งาน GraphQL กันอีก
- graphiql (npm): interactive in-browser GraphQL IDE
สามารถลองเล่น IDE ได้จาก http://graphql.org/swapi-graphql/ - Graphcool (github): BaaS (Backend as a Service) เป็น service ในการสร้าง GraphQL backend โดยที่เราสามารถจัดการกับ database schema และ data ผ่าน web UI ได้


ศึกษาต่อได้ที่ http://graphql.org/code/
… 3 Client Side Dev ต้องรู้อะไรบ้าง
… 3.1 พื้นฐานการสร้าง query และ mutation
… … 3.1.1 Type & Field & Argument
ลองดูตัวอย่างดังต่อไปนี้

ตัวอย่างด้านล่าง แสดงการ query type ‘Topic’ โดยที่ทำการส่งค่า argument ‘name’ เข้าไป และกำหนดให้ result ประกอบไปด้วย field ‘name’ และ ‘detail’
{
Topic(name: "GraphQL") {
name
detail
}
}เปลี่ยน query ข้างบนเป็น ภาษาพูด ก็คือ “ช่วยหา Topic อันที่ field ‘name’ มีค่าเป็น “GraphQL” ให้หน่อย ถ้าเจอก็ส่ง field ‘name’ และ ‘detail’ ของมันกลับมาให้ด้วย”
จาก query ด้านบน จะได้ result ประมาณนี้
{
"data": {
"Topic": {
"name": "GraphQL",
"detail": "How to use GraphQL"
}
}
}สังเกตได้ว่า
- result มีรูปแบบเดียวกับ query
- query มีลักษณะเป็นแบบ Interactive— คือเราสร้างกำหนดรูปแบบ result ได้ตามที่ต้องการ เช่น เราสามารถเพิ่ม field ‘presentingDate’ ของ Topic เข้าไปได้ เพื่อให้แสดง ‘presentingDate’ใน result ด้วย
ลองเพิ่ม field ‘presentingDate’ และ ‘speaker’
{
Topic(name: "GraphQL") {
name
presentingDate
speaker {
name
}
}
}Result
{
"data": {
"Topic": {
"name": "GraphQL",
"presentingDate": "2017-08-30T17:00:00.000Z",
"speaker": {
"name": "Peter"
}
}
}
}สังเกตได้ว่า
- field ที่เราต้องการนั้นอาจจะเป็น Object ก็ได้ ในที่นี้ field ‘speaker’ เป็น Object type ‘Speaker’ สำหรับกรณีนี้ สามารถใส่ sub-selection ของ field นั้นๆไปด้วย ดังเช่น ‘name’ ภายใต้ field ‘speaker’ เป็นต้น
… … 3.1.2 Fragment
query {
Speaker(name: "Peter") {
... SpeakerInfo
}
}fragment SpeakerInfo on Speaker {
id
name
}
จาก query ข้างต้น สังเกตได้ว่ามีสิ่งที่เราไม่คุ้นตา ดังนี้
- keyword query : ซึ่งที่ผ่านมาไม่ได้ใส่ไว้ เพราะมันละได้นั่นเอง
- keyword fragment : fragment คือ reusable units — เป็นการแยกสิ่งที่ reuse ได้ออกมา ซึ่งเป็นการลดความซับซ้อนของ query อีกด้วย
Result
{
"data": {
"Speaker": {
"id": "cj6q53a172dzy0174pgk0t3bn",
"name": "Peter",
"email": "Peter@gmail.com"
}
}
}… … 3.1.3 Variable & Operation Name
query GetSpeakerByName ($name: String) {
Speaker(name: $name) {
id
email
}
}มีอะไรใหม่บ้าง
- ‘$name’ คือ variable name ที่ pass เข้ามา
- ‘$name’ มี type เป็น String
- ‘$name’ ถูกนำไปใช้ใน query ได้ตรงๆเลย คือ แปะ variable ‘$name’ เข้าไป ตอน query type ‘Speaker’
- GetSpeakerByName เป็น Operation Name ซึ่งตัวอย่างก่อนๆหน้าเราไม่ได้ใช้ เนื่องจากว่ามันละได้ มอง Operation Name ให้เหมือนกับ function name ของ programming language ที่เราเขียนๆกันนั่นแล

ภาพข้างบนนี้ เป็นการ query ผ่าน Graphcool playground ซึ่งมีบริเวณด้านล่างซ้ายให้เราใส่ query variable
… … 3.1.4 Mutation
สำหรับ GraphQL แล้ว request ที่ส่งไปแล้วทำให้เกิดการ write data จะถูกทำผ่าน mutation และสำหรับ mutation เราสามารถถามหา nested field จาก สิ่งที่ return ได้เช่นเดียวกับ query

และมีสิ่งสำคัญอีกสิ่งหนึ่งเกี่ยวกับ query และ mutation ขอยกมาทั้ง paragraph เลยละกัน
Multiple fields in mutations
A mutation can contain multiple fields, just like a query. There’s one important distinction between queries and mutations, other than the name:
While query fields are executed in parallel, mutation fields run in series, one after the other.
This means that if we send two
incrementCreditsmutations in one request, the first is guaranteed to finish before the second begins, ensuring that we don't end up with a race condition with ourselves.source: http://graphql.org/learn/queries/#multiple-fields-in-mutations
… 3.2 Schemas & Types
… … 3.2.1 Type & Field
ถ้าจะคุยกันเป็น GraphQL ก็ต้องติดต่อกันในรูปแบบของ GraphQL schema language

ฺBasic component ของ GraphQL schema ประกอบด้วย
- object types
- field
จากตัวอย่างข้างต้น ทำความเข้าใจได้ดังต่อไปนี้
- field ‘name’ และ ‘appearsIn’ สามารถเป็นส่วนหนึ่งของการ query บน type Charactor ได้
- String เป็น scalar type ไม่สามารถมี sub-selections ใน query ได้
- non-nullable (!) เป็นการการันตีว่าจะมีค่าเสมอ
- [Episode]! การันตีว่าได้ array ของ Episode มาแน่ๆ แต่จำนวนของ Episode ใน array อาจจะเป็น 0 ก็ได้
… … 3.2.2 Query Type & Mutation Type
schema {
query: Query
mutation: Mutation
}type ส่วนใหญ่ใน schema มักจะเป็น object type ทั่วไป แต่มีอยู่ 2 type ที่พิเศษหน่อยก็คือ Query และ Mutation
ทุก service ของ GraphQL จะต้องมี query type แต่จะมีหรือไม่มี mutation type ก็ได้ สอง type นี้ก็เหมือน type อื่นๆ ความพิเศษของมันอยู่ตรงที่ มันกำหนด entry point ของทุกๆ GraphQL query นั่นเอง ดูตัวอย่างข้างล่างดังนี้
query {
hero {
name
}
droid(id: "2000") {
name
}
}ถ้าเราสามารถ query แบบด้านบนได้ นั่นแปลว่า GraphQL service จำเป็นต้องมี ‘hero’ type และ ‘droid’ type ดังนี้
type Query {
hero(episode: Episode): Character
droid(id: ID!): Droid
}สำหรับ mutation คอนเซปต์ก็เป็นแบบเดียวกับ query นั่นเอง
… … 3.2.3 Scalar Type
Scalar Type
- concrete data
- เป็นส่วนปลายสุดของ query (leave of the query)
- ไม่มี sub-field
- ประกอบด้วย type เหล่านี้ — Int, Float, String, Boolean, ID
ID เป็น type ที่ represent unique identifier แม้ว่า ID จะ serialized แบบ String แต่การที่ระบุว่าเป็น type นี้ก็เป็นการบ่งบอกอย่างนึงว่ามันตั้งใจที่จะไม่มีคุณสมบัติ human-readable หรือพูดง่ายๆก็คือ ไม่สื่อความหมายนั่นเอง
… 3.3 ทดสอบการยิง request ไปที่ GraphQL server จาก tool อะไรได้บ้าง
… … 3.3.1 Test ผ่าน terminal
query {
Speaker(name: "Peter") {
id
email
}
}query ข้างต้นถูกยิงไปที่ GraphQL server endpoint (ในที่นี่เราใช้ Graphcool Service) ได้โดยใช้ curl ดังนี้
curl 'https://yourendpointurl' -H 'content-type: application/json' --data-binary '{"query":"query {Speaker(name: \"Peter\") {email}}"}' --compressed
… … 3.3.2 Test ผ่าน Postman


Sum up
ถึงตรงนี้เราได้ศึกษาพื้นฐานเกี่ยวกับ GraphQL เบื้องต้นมาพอสมควร พอจะมีภาพในหัวแล้วว่า GraphQL มันคืออะไร เราต้องรู้อะไรบ้างที่จะพูดภาษานี้ได้ และมี tool อะไรมาช่วยเราในการศึกษา หรือใช้งานจริงได้บ้าง ซึ่งเพียงพอที่จะขยับไปดูต่อในส่วนของ implementation ที่ทำให้ client application ของเราคุยกับ GraphQL Server ได้
หัวข้อที่ควรศึกษาต่อมีดังนี้
- การทำให้ client application ปั้น GraphQL query / mutation request ส่งไปที่ GraphQL server ได้
… สำหรับ Swift Application นั้น Apollo iOS ช่วยท่านได้ - หา GraphQL service หรือ สร้าง GraphQL server ขึ้นมาเอง (เพื่อไม่ให้เหนื่อยไปซะก่อน เลือกวิธีแรกเถอะ ^__^)
… Graphcool ก็เป็นตัวเลือกที่ OK เลย เพราะมัน setup ไม่ยาก เหมาะที่จะเป็น GraphQL server ให้เราซ้อมมือ
สุดท้ายก็ขอขอบคุณผู้อ่านทุกท่านที่(ทน)อ่านกันมาจนจบ ^__________^


