สถาปัตยกรรม
สถาปัตยกรรมการใช้คอมโพเนนต์แทนกราฟ

การใช้คอมโพเนนต์แทนกราฟ

Gato GraphQL ไม่ใช้กราฟในการแสดงโมเดลข้อมูล แต่ใช้คอมโพเนนต์แทน

นี่ไม่ใช่แนวทางที่ผิดปกติแต่อย่างใด ภายใต้หัวข้อ Thinking in Graphs โปรเจกต์ GraphQL ได้ระบุไว้ดังนี้ (เน้นโดยผู้เขียน):

กราฟเป็นเครื่องมืออันทรงพลังในการสร้างแบบจำลองปรากฏการณ์ต่าง ๆ ในโลกแห่งความเป็นจริง เนื่องจากมันคล้ายคลึงกับโมเดลความคิดและคำอธิบายเชิงภาษาของกระบวนการที่อยู่เบื้องหลัง ด้วย GraphQL คุณสร้างแบบจำลองโดเมนธุรกิจของคุณในรูปแบบกราฟโดยการกำหนด schema ภายใน schema คุณกำหนดประเภทโหนดต่าง ๆ และวิธีที่โหนดเหล่านั้นเชื่อมต่อหรือสัมพันธ์กัน ในฝั่งไคลเอนต์ สิ่งนี้สร้างรูปแบบที่คล้ายกับการเขียนโปรแกรมเชิงวัตถุ ได้แก่ ประเภทที่อ้างอิงประเภทอื่น ในฝั่งเซิร์ฟเวอร์ เนื่องจาก GraphQL กำหนดเพียงอินเทอร์เฟซ คุณจึงมีอิสระในการใช้งานกับ backend ใด ๆ ก็ได้ (ทั้งใหม่และเดิม!)

สิ่งที่ได้จากคำจำกัดความนี้คือ:

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

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

การทำให้โมเดลข้อมูลเรียบง่ายขึ้นด้วยคอมโพเนนต์

การใช้คอมโพเนนต์เพื่อแสดงโครงสร้างข้อมูลในฝั่งเซิร์ฟเวอร์เป็นวิธีที่เหมาะสมที่สุดในแง่ของความเรียบง่าย เพราะช่วยให้สามารถรวมโมเดลข้อมูลต่าง ๆ เข้าสู่โครงสร้างเดียวได้ แทนที่จะมีขั้นตอนแบบนี้:

สร้าง queries เพื่อส่งให้คอมโพเนนต์ (ไคลเอนต์) => ประมวลผลข้อมูลในรูปแบบกราฟ/ต้นไม้ (เซิร์ฟเวอร์) => ส่งข้อมูลให้คอมโพเนนต์ (ไคลเอนต์)

...ขั้นตอนของเราจะเป็นแบบนี้แทน:

คอมโพเนนต์ (ไคลเอนต์) => คอมโพเนนต์ (เซิร์ฟเวอร์) => คอมโพเนนต์ (ไคลเอนต์)

สิ่งนี้เป็นไปได้เพราะ GraphQL request สามารถมองว่ามีโครงสร้างข้อมูลแบบ "ลำดับชั้นคอมโพเนนต์" โดยที่ทุก object type แทนคอมโพเนนต์หนึ่ง และทุก relationship field จาก object type หนึ่งไปยังอีก object type หนึ่งแทนคอมโพเนนต์ที่ครอบอีกคอมโพเนนต์

ลองใช้ตัวอย่างเพื่อให้เห็นภาพความสัมพันธ์จากคอมโพเนนต์ไปยัง GraphQL query สมมติว่าเราต้องการสร้าง widget "ผู้กำกับแนะนำ" ดังนี้:

Featured director widget

เมื่อใช้ Vue หรือ React (หรือไลบรารีที่ใช้คอมโพเนนต์อื่น ๆ) เราจะระบุคอมโพเนนต์ก่อน ในกรณีนี้ เราจะมีคอมโพเนนต์ภายนอก <FeaturedDirector> (สีแดง) ซึ่งครอบคอมโพเนนต์ <Film> (สีน้ำเงิน) ซึ่งครอบคอมโพเนนต์ <Actor> (สีเขียว) อีกที:

Identifying components in the widget

pseudo-code จะมีลักษณะดังนี้:

<!-- Component: <FeaturedDirector> -->
<div>
  Country: {country}
  {foreach films as film}
    <Film film={film} />
  {/foreach}
</div>
 
<!-- Component: <Film> -->
<div>
  Title: {title}
  Pic: {thumbnail}
  {foreach actors as actor}
    <Actor actor={actor} />
  {/foreach}
</div>
 
<!-- Component: <Actor> -->
<div>
  Name: {name}
  Photo: {avatar}
</div>

จากนั้นเราระบุว่าข้อมูลใดที่แต่ละคอมโพเนนต์ต้องการ สำหรับ <FeaturedDirector> เราต้องการ name, avatar และ country สำหรับ <Film> เราต้องการ thumbnail และ title และสำหรับ <Actor> เราต้องการ name และ avatar:

Identifying data properties for each component

และเราสร้าง GraphQL query เพื่อดึงข้อมูลที่ต้องการ:

query {
  featuredDirector {
    name
    country
    avatar
    films {
      title
      thumbnail
      actors {
        name
        avatar
      }
    }
  }
}

จะเห็นได้ว่ามีความสัมพันธ์โดยตรงระหว่างลำดับชั้นคอมโพเนนต์ข้างต้นกับ GraphQL query นี้