อ่าน Rails blogs หนังสือ ดู conference talks เรียนรู้เยอะเกี่ยวทำ models skinny
เทคนิคเหล่านี้เก่ง เพราะ models จะ ใหญ่หรือซับซ้อนเกินจัดการ แตคุณอยากไปจน models รับผิดชอบแค่ persistence, associations, validations? จะตัดสินใจยังไงว่า logic 多少 ควรอยู่ใน ActiveRecord models?
Skinny แตไม่ เกิน skinny
Active Record pattern ทำงานดีที่สุดตอน models match database schema ใกล้ชิด นั่นคือการออกแบบ! แตหมายความว่าอะไร?
ถ้าโค้ดทำงานจากมุมมอง ActiveRecord model ใส่ใน model ได้
ถ้าโค้ดทำงานข้าม multiple tables/objects ไม่มี owner ชัดเจน ใส่ใน Service Object
สิ่งที่ attribute-like (attributes คำนวณจาก associations หรือ attributes อื่น) ใส่ใน ActiveRecord model
logic ที่ต้อง orchestrate saving/updating multiple models พร้อมกัน ใส่ใน ActiveModel Form Object
โค้ดสำหรับ display/format models ใน view ใส่ใน Rails helper หรือ Presenter
นอกเหนือจาก guidelines นี้ ใช้ rules เหมือน refactor class ใหญ่เกินไป แตโดยทั่วไป ไม่ควร guilty ที่ทิ้ง logic บางส่วน ไว้ใน ActiveRecord models พวกมันออกแบบมาเพื่อมี logic!
Rails เลือก Active Record pattern จึงสมเหตุสมผลที่จะมี logic ใน models แตทำไม Rails เลือก pattern นี้แทน pattern สะอาดกว่า?
What Would Ruby Do?
ใน Patterns of Enterprise Application Architecture Active Record pattern อยู่กลางระหว่าง Row Data Gateway และ Data Mapper Row Data Gateway คือ object-oriented wrapper รอบ table rows แบบ skinniest ของ models Data Mappers ซับซ้อนกว่า Active Records ใช้ convert ระหว่าง objects ที่มีแค่ business logic และ objects ที่มีแค่ persistence logic
所以 ใน context ของ Ruby Active Record เป็น default pattern ที่ถูกต้องอย่างสมบูรณ์
ทำไม?
Ruby ออกแบบมาให้ programmers สนุก ตอนบังคับ tradeoff ระหว่าง cleanliness และ convenience เกือบทุกครั้งเลือก convenience
คิดดู Array มี methods สูงกว่า 100 ใน public API มี methods เยอะที่แค่ aliases เพราะบาง devs ชอบ .detect กว่า .find
ใน context นี้ Rails default pattern ที่สะดวกกว่า flexible หรือ OO purity มากกว่า นี่คือ Ruby way ผมรักมัน
Refactor ไป pattern flexible กว่าตอนต้องได้ แต YAGNI