GO Intensive Workshop

--

00:00:59 นาฬิกาจับเวลาถอยหลังบนจอ projector ลดลงมาเรื่อยๆ พร้อมกับภาพตัว service บน ARGO CD เป็นรูปหัวใจแตกสลาย ซึ่งหมายความว่าไม่สามารถนำ service ขึ้น production ได้

ถ้าเป็นหนังก็เป็นภาพ rewind ย้อนหลังกลับไปประมาณ 6 สัปดาห์อย่างรวดเร็ว ผมได้เริ่มเข้าบทเรียน Go Software Engineering Bootcamp รุ่นที่ 2 ที่จัดโดยทาง KBTG Kampus โดยมีเนื้อหา 6 หัวข้อ Git and Collaboration, Software Design, Software Quality, API Design ,DevOps, Refactoring with go และเข้า coaching session สัปดาห์ละครั้ง มีแบบฝึกหัดท้ายบท โดยบทที่ผมชอบเป็นพิเศษ จะมี

  • API Design เรื่อง security ได้ implement JWT (access token , refresh token)
  • Software Quality ตอนทำแบบฝึกหัด test double
  • Dev-ops เรื่อง 12 factor
  • Refactoring with go เรื่อง TDD (RED , GREEN , REFACTOR)

หลังจากเรียนครบ 6 หัวข้อ จะมี final assessment ที่อาจาร์ยได้เตรียมขึ้นมาให้เพื่อให้นำสิ่งที่เรียนมา apply เพื่อให้ได้ api ที่มี functional , non functional ตรงตาม story ที่อาจาร์ยได้กำหนดไว้

Workshop Day 1

เริ่มจากกิจกรรม ice breaking ระหว่างผู้เข้าร่วม workshop และ อีกครั้งหลังจากแบ่งกลุ่ม หลังจากนั้นจะเป็นการเตรียมสร้าง infrastructure และ pipe line ในการ deploy code ขึ้นไปยัง production โดยอาจาร์ยได้ทำการเตรียมตัว terraform ไว้ให้แล้ว เพราะถ้าเขียนเองหมดทั้ง 5 ส่วน น่าจะธาตุไฟเข้าแทรกแน่นอน โดยอาจาร์ยได้อธิบาย concept การนำของต่างๆมาประกอบเป็น pipe line ในการ deploy api

Part 1 Infrastructure provision

จะใช้ วิธี IaC (Infrastructure as Code) โดยผ่านตัว Terraform ในการเตรียม ประกอบไปด้วย

  • EKS (Elastic Kubernetes Service) ไว้สำหรับจัดการตัว Kubernates(K8s)
  • ARGO CD ตัวประสานงานในการ deploy โดนจะทำการ detect change บน github repository เมื่อมีการเปลี่ยนแปลง
  • SONARQUBE ใช้สำหรับเป็นหนึ่งในส่วนประกอบ quality gate เพื่อตรวจสอบ code coverage กับ duplicate code หลังจากมีการ push code ขึ้นมา
  • POSTGRES SQL สำหรับทำการเก็บข้อมูลที่ใช้งานของ api
  • Mapping DNS กับ CLOUDFARE ไว้สำหรับทำการ mapping domain ให้ตัว api และ ARGO CD ให้สามารถเรียกจาก internet ตาม domain ที่เราตั้งไว้

หลังจากเราทำการ provision เสร็จเรียบร้อยแล้วจะมาทำการ set up ตัว ARGO CD เข้ากับตัว git hub ที่เก็บ images และ gitops yml ที่ใช้ในการ deploy แล้วทำการกด create รอสักพักเ ทดลองเข้าตัว health endpoint ว่าสามารถเรียกเข้าใช้งานได้

เป็นอันเสร็จพิธีกรรม ไปพักกลางวันได้

Part 2 Application Programing Interface Design

Brainstorm API Design credit picture workshop team

หลังจากพักกลางวันเสร็จเป็นเรื่องปกติ ที่เมื่อแอร์เย็นๆ กินข้าวมาอิ่มๆ จะมีอาการจิตล่องลอย ก็มีกิจกรรมเรียกสติกลับมา ก่อนเข้า part ถัดไปซึ่งเราจะได้รับ requirement จากทาง PO โดยมี functional ประมาณ 11 story โดยอาจาร์ยให้เวลาประมาณ 60นาทีให้ในกลุ่มช่วยกันออกแบบ api endpoints , JSON request , JSON response + error code ต่างๆ ที่จะใช้ใน api

หลังหมดเวลา อาจาร์ยจะมา comment สิ่งที่ design สิ่งที่ชอบมากคือการแนะนำวิธีการออกแบบแต่ละแบบ มีข้อดีข้อเสียอย่างไร เช่น

api/v1/incomes , api/v1/expenses , api/v1/spenders/:id/incomes

api/v1/transactions , api/v1/spender//:id/transactions

Part 3 Coding

หลังจาก design เสร็จจะแบ่ง story กันในทีมเพื่อทำการ coding ด้วยวิธี pair programing โดนคนหนึ่งเขียน คนหนึ่งจะช่วยบอกข้อมูลต่างๆของ functional รวมถึง copy แปะ struct จาก chat GPT ส่งให้ :P โดยความมันส์ในส่วนนี้ อยู่ที่กติกาคือ

1. Develop แบบ trunk based ห้ามแตก branch ไป coding เงียบๆคนเดียว

Real man push branch main

2. ต้องผ่าน First quality gate โดยมี unit test กำกับทุกไฟล์ ในส่วนนี้อาจาร์ยให้ใช้เครื่องมือที่มีชื่อว่า pre-commit มา setup จะเริ่มทำงานเมื่อสั่ง commit โดยถ้า step นี้ไม่ผ่านของที่เราที่ทำการ dev ไว้จะไม่สามารถทำการ push ขึ้น git repository ของทีมได้

3. ต้องผ่าน Second quality gate โดย มีการ unit test , integration test , sonarqube scan code coverage อย่างต่ำ 80% (ตอนหลังอาจาร์ย ปรับให้เหลือ 60 % (-/|\-)) , scan duplicated code ให้ผ่าน ถึงจะทำการ build image เก็บใน image registry เพื่อเตรียม deploy ต่อไป โดยเราจะอาศัยเครื่องมือที่ชื่อว่า Git Actions และไฟล์ yml จะเริ่มทำงานเมื่อสั่ง push มายัง main repository โดยถ้า step นี้ไม่ผ่านตัว log git action มีสีแดง ทุกคนต้องหยุดสิ่งที่ตัวเองทำอยู่ มาช่วยกันแก้ pipe line ให้เขียว

GIT ACTION after push code to branch main repository

อาจาร์ยแนะนำ วิธีที่ shift left มาใช้ ในตอนเริ่ม start project โดยทำ pipeline CI/CD ให้เรียบร้อยก่อน โดย code ของเราอาจแค่ implement ธรรมดาเช่น เส้น api redirect ไปยัง landing page ธรรมดาก่อนก็ได้ เพื่อเป็นการตรวจสอบว่า service เราสามารถรันได้ บน infra ที่เราเตรียมไว้ ถึงไม่สามารถรันได้ เราก็จะได้ทราบปัญหาตั้งแต่เนิ่นๆดีกว่าไปเจอวันใกล้ go live ตัว service

หลังจากนั้นเราค่อยมาปรุง ความเข้มข้น จิ๊ดจ๊าด กลมกล่อม ของ pipeline ด้วย quality gate ให้เหมาะสมกับตัว service และทีมของเรา เช่น

  • project ที่เราต้องไปดูแลไม่มี unit test เลย (เรื่องสมมตินะครับ :P) เราอาจจะคุยกันในทีมเรื่อง code coverage อาจไม่ต้องถึง 80% ก็ได้ focus ไปที่ service ที่สำคัญก่อนๆ แล้วค่อยทำการขยับ coverage percent ขึ้นไป
  • unit test ว่าเรา point ไปยัง 3rd party service ว่าเป็น url production ถูกต้อง
  • ถ้าเป็น ภาษา java ควรทำการ check unused import library
  • เราแถม private key , username , password ต่างๆ ขึ้นไป git repository หรือไม่

ลองสรุป Part 1 , 3 ออกมาเป็นแผนภาพ

CI/CD in worshop
  • สีเขียว จะเป็น Continuous integration
  • สีน้ำเงิน จะเป็น Continuous delivery
  • สีแดง จะเป็น action ที่ต้องมีการ manual เพราะในสถาณการ์ณจริงเราต้องทำการ confirm ว่า ตัว program ของเราผ่าน QA , SIT , UAT และ approve ใน change committee หรือยังก่อนทำการ deploy

กลับมาที่ workshop อาจาร์ยตั้งเป้าไว้ให้แต่ละกลุ่มต้องนำขึ้น 1 commit โดยที่ pipeline ยังเขียวสดใส เป็นอันแยกย้ายกลับบ้านได้

Workshop Day 2

  • ช่วงเช้า เริ่มมามีกิจกรรมเพื่อความกระฉับกระเฉง ตามด้วยการ stand up meeting เพื่อ sync งานกันว่ามี story ไหน implement เสร็จแล้ว หรือ story ไหน นั้นติด issue อะไร มีข้อเสนอแนะอะไรเพิ่มเติม แล้วแบ่งงานแยกย้ายกันไป implement ต่อ
  • ช่วงสายๆ ก่อนพักกลางวัน อาจาร์ยได้แนะนำ feature toggle มาใช้เปิดปิด feature ใน API โดยอาศัยการอ่าน environment variable ที่สร้าง บน .env file , export ตรงๆ หรือกรณีของ K8s ต้อง config ที่ configmap.yaml และ deployment.yaml เพื่อให้ service ของเรามาอ่านตอน start และทำการ if check เพื่อเปิดปิด feature
  • มีข้อควรระวังในการใช้งานคือ วางจุดที่ใช้ feature toggle ให้ดีอย่าให้กระจายไปในหลายส่วนของ code และที่สำคัญหลังจากทำการ on service ไประยะหนึ่งแล้วไม่มี bug หรือ issue ควรนำ feature toggle ออก อย่าเก็บไว้ เพราะคนมาทีหลังก็ต้องเศร้าต่อไป

if นี้มีไว้ทำไม ?

เอา if นี้ออกจะเป็นอะไรไหม ?

Feature toggle configuration on K8s

เริ่มช่วงบ่าย PO บอกรายละเอียดตัว api ที่ต้องส่งมอบและเริ่มจับเวลาถอยหลัง ซึ่งทางทีมพบปัญหาเรื่อง api บนเครื่องบน production มี message error จาก database เรื่อง constraint ของ table transactions ต้องขอความช่วยเหลือจากอาจาร์ยเพื่อหาวิธีแก้ เนื่องจากตัว script table ทำการตรวจสอบแล้วไม่พบมีการใส่ constraint ไว้

  • อาจาร์ยมาช่วยหาจึงพบสาเหตุว่า ตัว migration tool จะไม่รันไฟล์ที่เคยใช้ migrate ไปแล้ว ต้องทำการสร้าง migration file ตัวใหม่ขึ้นไป alter column ใน table นั้น ซึ่งไม่ทันกับเวลาที่เหลือ
  • เมื่อนาฬิกานับถอยหลังลงมาถึง 00:00:00 อาจาร์ยให้ พับจอลงมาเป็นอันเสร็จสิ้นการ implement และให้ไปเคลียร์สมองให้โล่งๆ เพื่อจะได้พร้อมรับกับ session ต่อไป

session ต่อมาอาจาร์ยได้แนะนำ Migration database tool ตัวนึงไว้จัดการเรื่อง การสร้าง แก้ไข ตัว table ของ database มีชื่อว่า GOOSE เพื่อช่วยแก้ปัญหา developer ในทีมต่างคนต้องมี script เป็นของตัวเอง ทำให้ยากต่อการจัดการ นอกจาก tool ตัวนี้จะเป็นตัวกลางในการ migrate ยังช่วยให้เรา track ดูว่า การ migrate ที่ database ตัวนี้ มี step และใช้ไฟล์ไหนรันไปแล้วบ้าง ทำให้ คนมาที่หลังก็ไม่ต้องเศร้าต่อไป

  • วิธีการใช้งาน ทำการ สร้างไฟล์ที่มี sql script ที่มีตัว goose annotation config (up , down)
  • ทำการเขียนไฟล์ go เพื่อ run แบบ embed เพื่อสั่ง up หรือ down ผ่านตัว code หรือจะรันผ่าน ตัว command line goose ตรงๆเลยก็ได้
  • คำแนะนำก่อนการใช้งาน คือ ถ้า migration file ไหนถูกรันไปแล้ว จะไม่ถูกนำมา run ซ้ำถึงแม้ว่าจะมีการแก้ script ในไฟล์ไปแล้ว ต้องทำการสร้าง migration file ใหม่ขึ้นไป
GOOSE configuration example

session ต่อมาจะเป็นการ Reflect and Review โดยจะเริ่มจากในทีมก่อน ว่าแต่ละคนในทีเจอปัญหาอะไร และมีอะไรที่ต้องปรับปรุงบ้าง แล้วเขียนบน post it ไปแปะที่กระดาน ส่วน review จะเป็นการแบ่งในทีมสองกลุ่มคือ

  • 4 คนวนไปดู code , ผลลัพธ์ , reflect ของกลุ่มอื่นๆ
  • 2 คนจะเตรียม reflection ของทีม ,code และ การยิงเทส ให้แต่ทีมอื่นๆที่จะวนเข้ามาฟัง present จนครบทุกทีม
  • เมื่อวนครบทุกทีมแล้ว ก็จะมาสรุปอีกครั้งในทีมว่า reflect และ code review ของทีมอื่นเป็นอย่างไรบ้าง

session ต่อมาอาจาร์ยจะมา recap 2 วันนี้เราได้เจออะไรบ้างและแนะนำแนวทางการสร้าง software เพราะว่า

programing != softwareEngineering

  • Team Communicate and Collaboration เพราะเราไม่สามารถทำงานคนเดียวได้ใน project

หัวข้อที่สะกิดผมมากที่สุดคือ backward compatibility เพราะการ change กับ software development เป็นของคู่กัน (requirement เกิดขึ้น ตั้งอยู่ ดับไป สาาาาธุ )

  • อาจาร์ยได้ยกตัวอย่างภาษา Go เนื่อง Go ถ้ามีการ update version ใหม่ ตัว Go version เก่าๆยังสามารถใช้งานได้ปกติ
  • ถ้ามองเป็น service สมมติเรามีการ deploy service ของเราเป็น v 1.2 ตัว client ต่างๆที่เรียก service v 1.0 ควรทำงานได้อย่างปกติเช่นกัน

Session สุดท้าย จะเป็น Closing speech จากทางพี่ๆ KBTG มาแชร์ประสบการ์ณและมุมมองของ software engineering

softwareEngineering := scale + time

  • scale เราควรออกแบบให้ service สามารถขยาย เพื่อรองรับจำนวนการใช้งานจำนวนมากได้
  • t้ime เราควรออกแบบให้ service ยืดหยุ่นที่จะต่อยอดใช้งานต่อได้เป็นเวลานาน

go selfDevelopment()

อย่าหยุดพัฒนาตัวเอง ทั้งทักษะการเขียน code, การออกแบบ service , เข้าใจเครื่องมือที่ใช้งาน, trend technology ในอนาคต,การทำงานเป็นทีมและการสื่อสาร

เป็นอันจบ work shop 2 วันอย่างเข้มข้น แต่ในขณะเดียวกันก็เป็นจุดเริ่มต้นที่ต้องศึกษาเพิ่มเติมโดยนำสิ่งที่เรียนมาต่อยอดขึ้นไป

  • ฝีกการเขียน Go (Go Routine , context , logging , saga , outbox , performance optimize)
  • ศึกษาเรื่อง backward compatibility design , การออกแบบ function ที่ทำให้ test ง่าย

ขอบคุณ :)

  • ทุกคนในทีมที่ลุยตัวโจทย์ใน workshop ด้วยกัน และทุกคนที่ไม่ได้อยู่ในทีมเดียวกัน ที่มาแลกเปลี่ยน idea , แนะนำ ในช่วง review code
  • อาจาร์ยทุกท่านที่ถ่ายทอดประสบการ์ณ , lesson learn(case สมมติที่เป็นเรื่องจริง) , คำแนะนำ support ต่างๆในระหว่าง coaching session ,วัน workshop และใน discord (โดยป้ายยาหนังสือไปหลายเล่มเลยที่เดียว)
  • พี่ๆจาก KBTG ที่มาแชร์ประสบการ์ณและมุมมองการทำ software engineering
  • admin และทีมงาน ทุกท่านที่ดูแลประสานงาน ในระหว่าง boot camp และ workshop
  • ทุกคนที่เข้ามาอ่านบทความนี้ด้วยครับ

--

--