- เรื่องราวการพัฒนาโครงการ LegiNote ตอนที่ 1 - แนวคิด
- StatPan ได้เริ่มโครงการ LegiNote โดยมีเป้าหมายเพื่อเพิ่มการเข้าถึงร่างกฎหมายและบันทึกการประชุมของรัฐสภา และเพิ่มประสิทธิภาพการออกกฎหมายโดยใช้ AI
โพสต์นี้แปลโดย AI
บทสรุปของโพสต์โดย durumis AI
- โครงการ LegiNote ใช้ Svelte, Rust, Go และ Python ในการพัฒนาเว็บเซอร์วิส โดยเฉพาะเวิร์กเกอร์ที่พัฒนาด้วย Go จะทำหน้าที่รวบรวมและอัปเดตข้อมูล OpenAPI
- เวิร์กเกอร์มีหน้าที่ตั้งค่าตรรกะการรวบรวมข้อมูล การดำเนินการ และการโหลดข้อมูลลงฐานข้อมูล โดยมีเป้าหมายเพื่อเพิ่มขีดความสามารถในการรองรับข้อมูลจาก API ต่างๆ
- โครงการออกแบบโดยแบ่งโฟลเดอร์ตามฟังก์ชันเพื่อลดการพึ่งพาไลบรารีอื่นๆ โดยใช้ PostgreSQL, pq และ sqlx ในการเชื่อมต่อและประมวลผลคำสั่งฐานข้อมูล
สวัสดีครับ ผม StatPan
กำลังเขียนเกี่ยวกับการพัฒนาโครงการ LegiNote ที่เป็นโปรเจกต์ข้างเคียงอยู่ครับ
สำหรับตอนก่อนหน้า สามารถดูได้จากลิงก์ด้านล่างนี้ครับ
โครงสร้างพื้นฐาน
ออกแบบ Leginote โดยได้รับความอนุเคราะห์จากคุณ태양토끼님
Leginote มีเป้าหมายในการพัฒนาเป็นเว็บเซอร์วิสเป็นหลัก และวางแผนที่จะใช้เทคโนโลยีสแตกดังต่อไปนี้ครับ
ฝั่งฟรอนต์เอนด์: Svelte
ฝั่งแบ็กเอนด์: Rust (กำลังพิจารณา rupring เป็นหลัก แต่ยังอาจมีการเปลี่ยนแปลงได้)
เวิร์กเกอร์: Go (มุ่งเน้นการใช้ std อย่างเข้มงวด ยกเว้นไลบรารีที่จำเป็นอย่างยิ่ง)
การวิเคราะห์ข้อมูล: ไพทอน (ตั้งแต่การเตรียมข้อมูลเบื้องต้น ไปจนถึงการประยุกต์ใช้ปัญญาประดิษฐ์ในอนาคต)
จากเทคโนโลยีสแตกข้างต้น ผมจะเน้นเขียนเกี่ยวกับส่วนเวิร์กเกอร์และการวิเคราะห์ข้อมูล ซึ่งเป็นส่วนที่ผมมีส่วนร่วมในการพัฒนาเป็นหลักครับ
มาเริ่มต้นเรื่องราวของเวิร์กเกอร์กันเลยดีกว่าครับ
เวิร์กเกอร์
การเลือกภาษา
โลโก้ golang
ผมเริ่มต้นเขียนโปรแกรมด้วยไพทอน และเนื่องจากปัจจุบันทำงานด้านวิทยาศาสตร์ข้อมูลเป็นหลัก ทำให้ไพทอนเป็นภาษาที่คุ้นเคยที่สุดสำหรับผม อย่างไรก็ตาม ด้วยประสบการณ์การใช้ภาษาสคริปต์เพียงอย่างเดียว ผมจึงมีความปรารถนาที่จะเรียนรู้ภาษาคอมไพล์ที่แข็งแกร่งขึ้น จึงเริ่มให้ความสนใจกับภาษา Go และ Rust
โดยเฉพาะอย่างยิ่ง ภาษา Rust เป็นภาษาที่ผมติดตามอย่างใกล้ชิดในช่วงไม่กี่ปีที่ผ่านมา และมักถูกกล่าวถึงพร้อมกับ C++ และ Golang (แม้ว่า C++ จะเป็นภาษาที่ยอดเยี่ยม แต่ก็ไม่เหมาะสมกับการพัฒนาบริการเครือข่ายในโครงการนี้ครับ และในอนาคตหากไม่ใช่กรณีที่ต้องจัดการกับโครงสร้างภายในของเฟรมเวิร์กการเรียนรู้เชิงลึก ผมก็ไม่แน่ใจว่าจะต้องใช้ภาษา C++ โดยตรงหรือไม่)
หลังจากศึกษา Rust และ Golang รวมถึงการทดลองใช้กับการร้องขอเครือข่ายพื้นฐาน ผมก็ได้ทำความเข้าใจเกี่ยวกับข้อดีข้อเสียของทั้งสองภาษาอย่างคร่าวๆ การอธิบายรายละเอียดข้อดีข้อเสียของทั้งสองภาษาในบทความนี้อาจทำให้เนื้อหาของบทความยาวเกินไป ดังนั้น ผมคิดว่าน่าจะดีกว่าหากเขียนอธิบายแยกต่างหากในภายหลัง โดยสรุปง่ายๆ ก็คือ
ในด้านเครือข่าย สามารถสร้างโครงสร้างได้โดยไม่ต้องพึ่งพาไลบรารีเพิ่มเติม และสำหรับโครงการที่ยังไม่แน่นอนว่าจะสร้างรายได้หรือไม่ จึงตัดสินใจเลือกใช้Golangครับ
บทบาทของเวิร์กเกอร์
หน้าจอ OpenAPI
บทบาทของเวิร์กเกอร์คือการรวบรวมและอัปเดตข้อมูลผ่านเว็บไซต์ OpenAPI ในแต่ละรอบ ซึ่งสามารถแบ่งออกเป็น 3 ส่วนหลักดังนี้ครับ
1. กำหนดตรรกะการรวบรวมข้อมูลสำหรับข้อมูลที่ต้องการ
2. กำหนดตัวรันเนอร์สำหรับการดำเนินการตามตรรกะการรวบรวมข้อมูล
3. บันทึกข้อมูลที่รวบรวมลงในฐานข้อมูล
เป้าหมายคือการขยายขีดความสามารถของระบบโดยการนำขั้นตอนทั้ง 3 ขั้นตอนนี้ไปใช้กับข้อมูล API ต่างๆ ในลักษณะเดียวกัน
แนวทางการออกแบบโครงสร้างโปรเจกต์
มีโครงสร้างทางสถาปัตยกรรมที่หลากหลายสำหรับการออกแบบโครงสร้างของโปรเจกต์ และโดยเฉพาะอย่างยิ่งการใช้เฟรมเวิร์กจะช่วยให้เริ่มต้นโครงการได้ในสภาพแวดล้อมที่มีโครงสร้างอยู่แล้ว อย่างไรก็ตาม ตามที่ได้กล่าวไว้ข้างต้น โปรเจกต์นี้มีเป้าหมายในการพัฒนาโดยลดการพึ่งพาไลบรารีให้น้อยที่สุด ดังนั้น ผมจึงต้องการแยกโฟลเดอร์ตามฟังก์ชันต่างๆ เพื่อให้ใกล้เคียงกับตรรกะที่ได้กำหนดไว้
โครงสร้างของโปรเจกต์จะเป็นดังนี้ครับ
leginote-worker-bill/
├── main.go
├── api/
│ └── client.go
├── db/
│ ├── connection.go
│ └── repository.go
├── util/
│ ├── error.go
│ └── runner.go
│ └── config.go
├── worker/
│ └── worker.go
├── go.mod
└── go.sum
api - การรวบรวมข้อมูลจะทำผ่าน OpenAPI ของข้อมูลสาธารณะ ดังนั้น โค้ดพื้นฐานสำหรับการสื่อสารกับ OpenAPI จึงจะอยู่ในโฟลเดอร์ api ปัจจุบันมีการใช้ API เพียง 1 ตัวหลัก ดังนั้นจึงมีไฟล์ไคลเอนต์เพียงไฟล์เดียว
db - มีการกำหนดตรรกะสำหรับการสื่อสารกับฐานข้อมูล โค้ดภายใน connection รับผิดชอบการเชื่อมต่อเท่านั้น ส่วน repository จะมีตรรกะสำหรับการดำเนินการ SQL แบบ upsert ต่างๆ การเขียน SQL ลงในโค้ดโดยตรงอาจทำให้ซับซ้อนเกินไป ดังนั้นผมจึงวางแผนที่จะสร้างไฟล์แยกต่างหากสำหรับ SQL ในภายหลัง
util - เป็นที่เก็บตรรกะเสริมต่างๆ ที่ใช้ในการทำงาน error เป็นสคริปต์ที่สร้างขึ้นชั่วคราวเพื่อจัดการกับผลลัพธ์ error ที่เกิดขึ้นใน Go ตามที่เนื้อหาในบทความตอนต่อไปจะอธิบาย เหตุผลนี้ก่อให้เกิดปฏิกิริยาลูกโซ่ที่คาดไม่ถึง(?)
ไฟล์ config ใช้สำหรับอ่านไฟล์ .env โดยไม่ต้องใช้แพ็กเกจเพิ่มเติม ดังนั้นจึงได้สร้างฟังก์ชันอ่านไฟล์ .env ขึ้นมาเอง
worker - เป็นที่เก็บตรรกะหลักที่ใช้ api และ db อย่างเหมาะสมเพื่อให้ได้ผลลัพธ์ตามที่ต้องการ หากในอนาคตมีการเพิ่มประเภทของเวิร์กเกอร์ ก็จำเป็นต้องเพิ่มส่วนนี้ด้วยเช่นกัน แต่ตอนนี้มีเพียงตรรกะการทำงานของเวิร์กเกอร์หลักเพียงตัวเดียว
ในอนาคต ผมวางแผนที่จะพัฒนาโค้ดต่อไปโดยรักษาหลักการของสถาปัตยกรรมแบบเลเยอร์
ไลบรารีที่ใช้ในโครงการ
pq สำหรับใช้งานกับ postgres
sqlx สำหรับใช้งานกับคิวรี
สรุปเรื่องเวิร์กเกอร์
การเขียนบทความโดยเน้นเฉพาะทฤษฎีโดยไม่มีโค้ดอาจดูน่าเบื่อ และผมเองก็เริ่มรู้สึกเหนื่อยเหมือนกัน เลยขอสรุปให้จบเร็วๆ หน่อยนะครับ
ตอนที่ 2 จบลงแล้วครับ หวังว่าในตอนที่ 3 เป็นต้นไป ผมจะได้นำโค้ดมาอธิบายประกอบให้มากขึ้นนะครับ
ระหว่างการพัฒนา LegiNote หากมีฟีเจอร์ใดที่คุณคิดว่าจำเป็น หรือมีข้อสงสัยเกี่ยวกับการพัฒนา โปรดแสดงความคิดเห็นได้เลยนะครับ!