Datomic time travel query กับ schema migration

Datomic เป็น database ที่เราสามารถ query จากสถานะของ database ในอดีตได้ เช่น query กับ database ขณะที่ data เป็นเมื่อ 3 อาทิตย์ก่อน ผมเคยมีข้อสงสัยกับคุณสมบัตินี้ว่ามันจะเวิร์คจริงหรอ เช่น ถ้าเราเอาโค้ดปัจจุบันไป query data ในอดีต หรือโค้ดในอดีตที่เรา revert กลับไป ไป query กับ database ปัจจุบันได้เสมอมั้ย (ถ้าใครเคยเขียน Rails อาจจะเคยเจอกรณีที่เมื่อ codebase ของเรา evolve ไปซักพัก เราจะไม่สามารถรัน migration ตั้งแต่ต้นได้ เพราะ model ของเรามีการเปลี่ยนแปลงไปจากวันที่เขียน migration นั้นๆ) หรือเราต้องมีการ sync code กับ database แต่ละช่วงเวลาหรือเปล่า

วันนี้ผมได้คำตอบแล้ว หลังจากได้ฟังคำอธิบายของ David Nolen จากช่วง AMA ของเขาในงาน ReactiveConf 2017

(Update: เวหาบอกมาว่าเค้ามีเขียนวิธีการไว้หมดแล้วที่ The Ten Rules of Schema Growth)

David ตอบว่าเราต้องนำแนวคิด immutability มาใช้ ทำให้ schema เปลี่ยนแปลงแบบไม่เกิด backward incompatible คือ ทำได้แค่เพิ่ม field ห้ามลบ หรือแก้ไขชื่อ พอได้ยินแค่นี้ผมเข้าใจเลย มันมาจาก แนวคิดการเขียนซอฟแวร์ให้ไม่เกิด breaking change ที่ Rich Hickey เคยอธิบายไว้นั่นเอง

Rich เสนอแนวคิดว่าการ  grow software โดยไม่ทำให้เกิด breaking change แก่ผู้อื่นที่มาใช้ software ของเรานั้น เราสามารถทำการเปลี่ยนแปลงได้ 3 ประเภท คือ

  • เพิ่มสิ่งที่ทำ ให้ทำได้มากขึ้น
  • ต้องการจากผู้ใช้งานน้อยลง
  • แก้บั๊ก ของสิ่งที่ทำงานผิดพลาดอยู่

ในมุมของ database คือ เราสามารถเพิ่ม field ได้ แต่ห้ามลบและห้ามแก้ไขชื่อ ตัวอย่างเช่น ถ้า user ของเรามี field tel อยู่ แล้ววันนึงเราอยากจะแยกเป็น home และ office ก็ทิ้ง tel เก่าไว้และเพิ่ม tel_home กับ tel_office เข้าไป

ถ้าเราเอาโค้ดปัจจุบันไป query database ในอดีต ในโค้ดปัจจุบันของเราที่รองรับทั้ง 3 field ก็จะพบแค่ว่า tel_home กับ tel_office เป็น nil

ถ้าเราเอาโค้ดในอดีตมา query database ปัจจุบัน ก็อาจจะพบว่า tel ไม่มีค่าไปแล้ว และมันไม่รู้จัก tel_home กับ tel_office แต่ก็ไม่ทำให้อะไรพัง

สิ่งสำคัญที่จะทำให้การทำงานในลักษณะนี้เป็นไปได้ราบรื่น ตัวภาษาที่ใช้ต้องรองรับ nil ได้เป็นอย่างดี และignore สิ่งที่เกินมาที่ไม่ต้องการได้ การที่ field เพิ่มเกินมา การที่ field หายไป หรือการที่ field เป็น nil ต้องไม่สร้างความลำบากในการเขียนโปรแกรมมากนัก ซึ่ง Clojure เป็นภาษาที่จัดการกับสิ่งนี้ได้ดีมาก

นี่เป็นอีกหนึ่งครั้งที่ผมรู้สึกประทับใจ Clojure และ ecosystem ของมันที่ถูกออกแบบมาทำงานเข้ากันได้เป็นอย่างดีจนทึ่งในความสามารถในการออกแบบของผู้สร้าง ที่สร้างมาราวกับว่าเค้ารู้อนาคตว่าอะไรจะเกิดขึ้น รู้ว่าจิ๊กซอชิ้นต่อไปคืออะไร

 

Leave a comment