เทคนิคการ Refactor loop ใน neovim
Project neovim เป็น project ที่ fork vim ออกมาเพื่อปรับปรุง source code, quality, improve plugin system และ developer friendly มากขึ้น ซึ่งในตัว project เองได้มีการเขียนเรื่องของเทคนิคการ refactor source code เอาไว้โดยหนึ่งในตัวอย่างของวันนี้เป็นเรื่องของเทคนิคการ refactor loop ซึ่งสามารถนำเอาไป apply กับภาษาอะไรก็ได้ที่มีปัญหาคล้ายกัน
Code ที่เราจะมาดูกันเป็น code ที่ส่วนของการเปลี่ยน mode (เช่น เปลี่ยนเป็น insert mode จาก normal mode) ในตัว vim
while (1) { normal_mode_process_byte(getc()); } void normal_mode_process_byte(char c) { if (c == 'i') // enter insert mode while (1) { insert_mode_process_byte(getc()); } }
จากโค้ดตัวอย่างเราจะสังเกตเห็นว่า
normal_mode_process_byte, insert_mode_process_byte มีการติดต่อกับ IO (ในที่นี้คือ getc)
ใน insert_mode_process_byte จะเกิด infinite loop หากมีการกด ‘i’
ซึ่งการติดต่อพวกนี้มีผลทำให้ทดสอบและ debug ได้ยาก ดังนั้นควรเปลี่ยนมุมมองใหม่โดยนำ state machine มาใช้โดย extract function ที่จัดการเรื่องของการรับ input จาก IO ออกมาก่อนและเปลี่ยนตัวจัดการ state ไปเป็น global variable ซะ
while(1) { process_byte(getc()); } void process_byte(char ch) { if (mode == NORMAL) { normal_mode_process_byte(ch); } else if (mode == INSERT) { insert_mode_process_byte(ch); } }
พอเราเปลี่ยนการจัดการ state มาใช้ global variable ตัว function insert_mode_process_byte และ normal_mode_process_byte ก็สามารถเปลี่ยน state ได้ด้วยการเปลี่ยน global variable นั้นเอง เช่น
void normal_mode_process_byte(char ch) { if (ch == 'i') { mode = INSERT; return; } // do something ... }
เมื่อเราแยกส่วนของ state ออกจาก IO จะสามารถทำการทดสอบได้ง่ายขึ้นของแต่ล่ะ และไม่ต้องพึ่ง IO เลย
ที่มา https://github.com/neovim/neovim/wiki/Refactor-vim-into-a-library

















