1 คะแนน โดย GN⁺ 5 시간 전 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • ระหว่างพัฒนา Rust หากต้องคอยจัดการทุกเส้นทางข้อผิดพลาดและปัญหา ownership ให้เรียบร้อยทันที มักทำให้จังหวะการลงมือเขียนสะดุด จึงมีประโยชน์ที่จะสร้าง happy path ให้เสร็จก่อน แล้วติดตามงานที่เหลือด้วย คำเตือน
  • แม้ใช้แค่ Rust มาตรฐาน ก็สามารถผสม unwrap, clone, todo!, คำเตือนพื้นฐานของคอมไพเลอร์ และทริกคอมเมนต์เอกสาร /// เพื่อทำเครื่องหมายโค้ดที่ยังไม่เสร็จได้
  • วิธีเดิมมีข้อจำกัดคือ unwrap และ clone ไม่สร้างคำเตือน ส่วน todo! ก็ยังพึ่งพาคำเตือนทางอ้อม และทริก /// อาจกลายเป็นข้อผิดพลาดตอนคอมไพล์หรือสร้างเอกสารโดยไม่ตั้งใจ ขึ้นอยู่กับตำแหน่งที่ใช้
  • crate wip มี wip!, unwrap_wip, clone_wip, fixme! สำหรับทำให้การ implement ชั่วคราว, unwrap/clone ชั่วคราว, และโน้ตที่ต้องกลับมาแก้ในภายหลัง ปรากฏเป็น คำเตือนเสมอ
  • Meilisearch ใช้ -D warning ใน CI เพื่อเปลี่ยนคำเตือนให้เป็นข้อผิดพลาด ป้องกันไม่ให้โค้ด WIP หลุดเข้ามา และลบ dependency wip ที่เพิ่มไว้ระหว่างพัฒนาออกในขั้นตอนเก็บประวัติให้เรียบร้อยก่อนรีวิว

ทำไมระหว่างพัฒนา Rust ถึงต้องการคำเตือน

  • Rust เป็นภาษาที่ให้ความสำคัญกับ ความถูกต้อง แต่ถ้าต้องจัดการทุกเส้นทางข้อผิดพลาดให้ครบตั้งแต่ระหว่างพัฒนา อาจทำให้ความเร็วและสมาธิในการ implement ลดลง
  • เมื่อ rustc บล็อกการคอมไพล์เพราะเรื่องอย่างการคืนค่า Result, การจัดการข้อผิดพลาด, หรือการทำ edge case ให้ครบ มักจะมีสองทางเลือก
    • ลงมือเขียนการจัดการข้อผิดพลาดแบบสมบูรณ์ทันที แล้วรีแฟกเตอร์หลายรอบกว่าจะพร้อมเปิด PR
    • ทิ้งเครื่องหมายแบบ TODO later ไว้ แล้วลดปัญหานั้นลงมาอยู่ในระดับ คำเตือน เพื่อทำงานปัจจุบันต่อได้
  • คำเตือนช่วยไม่ให้การพัฒนาถูกหยุด แต่ยังคงเป็นสัญญาณว่าต้องเก็บงานให้เรียบร้อยก่อน merge PR
  • Meilisearch รันคอมไพเลอร์ใน CI ด้วยแฟลก -D warning เพื่อเปลี่ยนคำเตือนทั้งหมดเป็นข้อผิดพลาด ไม่ให้โค้ด WIP ถูกปล่อยออกไปโดยไม่ตั้งใจ
  • การรีวิวโค้ดเป็นแนวปฏิบัติพื้นฐานที่ช่วยกันบั๊กและแชร์ความรู้ในทีม แต่ถ้าพึ่งแค่ความจำและความระมัดระวังของคน สุดท้ายก็ยังพลาดได้ จึงต้องมี ราวกันตกเพิ่มเติม

วิธีเลื่อนการเก็บงานโค้ดที่ยังไม่เสร็จด้วย Rust มาตรฐาน

  • เลื่อนการจัดการข้อผิดพลาดด้วย unwrap

    • ถ้าใช้ unwrap กับ Result หรือ Option ก็สามารถดึงค่าภายในออกมาและเขียนส่วนที่เหลือต่อได้ โดยแลกกับการ panic ในเส้นทางที่เกิดข้อผิดพลาด
    • เมื่อส่วนอื่นของโค้ดพร้อมแล้ว ก็สามารถย้อนกลับมาเลือกเอา unwrap ที่ใส่ไว้ชั่วคราวออก แล้วแทนด้วยการจัดการข้อผิดพลาดที่เหมาะสม
    • แนวทางนี้ตั้งอยู่บนสมมติฐานว่า แม้ Rust จะมีโครงสร้างสำหรับจัดการข้อผิดพลาดอย่างถูกต้อง แต่ก็ไม่จำเป็นต้องทำให้เสร็จ ทันที
  • เลื่อนปัญหา ownership ด้วย clone

    • ปัญหา ownership พบไม่บ่อยเท่าการจัดการข้อผิดพลาด แต่การทำ ownership ให้ถูกต้องอาจต้องเปลี่ยนดีไซน์ด้วย
    • ในกรณีนี้ แทนที่จะย้ายค่า ก็สามารถ clone เพื่อหลบปัญหา lifetime ไปชั่วคราวได้
    • ภายหลังสามารถอาศัยประสบการณ์ระบุได้ว่ากรณีไหนควรส่งตัวแปรที่เหมาะสมขึ้นไปใน stack ระดับบนกว่า เพื่อตัด clone ออก
    • แต่เพราะการแก้อาจนำไปสู่การเปลี่ยนโครงสร้างโค้ด การเลื่อนไว้จึงยากกว่าการเลื่อนเรื่องจัดการข้อผิดพลาด
  • ใช้ todo!() เพื่อจองตำแหน่ง implementation ไว้ก่อน

    • มาโคร todo!() ในไลบรารีมาตรฐาน Rust ใช้แสดงว่าโค้ดยังไม่เสร็จ และเป็น placeholder ที่มีประโยชน์ตอนทำ prototype เพื่อให้ผ่านการวิเคราะห์ชนิดข้อมูล
    • เพราะ todo!() diverge ด้วยการ panic จึงสามารถใช้เป็น expression placeholder ได้ในตำแหน่งชนิดข้อมูลส่วนใหญ่
    • ทำให้สามารถกำหนดอินเทอร์เฟซและเรียกใช้ฟังก์ชันได้ก่อน โดยเลื่อน implementation จริงออกไปทีหลัง
    • todo!() ไม่ได้มีไว้เพื่อบอกผู้ใช้โปรแกรมว่าฟีเจอร์ยังไม่ถูก implement แต่ใกล้เคียงกับ เครื่องมืออำนวยความสะดวกสำหรับ WIP ของคนเขียนและคนรีวิวโค้ดมากกว่า
    • หากต้องการสื่อกับผู้ใช้ว่า functionality ยังไม่ถูก implement มีมาโคร unimplemented!() แยกต่างหาก
  • คำเตือนพื้นฐานของคอมไพเลอร์และทริกคอมเมนต์เอกสาร

    • คำเตือนพื้นฐานจากคอมไพเลอร์ Rust ก็มีประโยชน์ในการเผยให้เห็นสถานะที่ยังไม่เสร็จระหว่างพัฒนา
      • binding ที่ไม่ได้ใช้งาน
      • mut ที่ไม่จำเป็น
      • Result และ Option ที่ไม่ได้ใช้งาน
    • หากระหว่างพัฒนาไปซ่อนคำเตือนเหล่านี้ ชั่วคราว ด้วย prefix _ หรือทริกอื่น โค้ดที่ยังไม่เสร็จก็อาจหลุดผ่านไปได้
    • สำหรับ edge case หรือ logic ที่เสียแต่ระบบชนิดข้อมูลตามไม่ถึง บางครั้งก็ต้องทิ้งไว้เป็นคอมเมนต์
    • ถ้าใส่คอมเมนต์ให้ดูเหมือนคอมเมนต์เอกสาร /// Rust จะสร้างคำเตือนเมื่อมี doc comment ที่ไม่มีสิ่งให้เอกสารกำกับ จึงใช้ติดตามปัญหาตรงจุดนั้นผ่านคำเตือนได้

ข้อจำกัดของวิธีมาตรฐาน

  • ปัญหาใหญ่ที่สุดคือทุกเทคนิคไม่ได้สร้างคำเตือนที่เชื่อมกับปัญหาที่ต้องแก้อย่างสม่ำเสมอ
  • todo!() มักทำให้เกิดคำเตือน แต่บ่อยครั้งเป็นผลจาก สาเหตุทางอ้อม เช่น อาร์กิวเมนต์ของฟังก์ชันไม่ได้ถูกใช้ หรือ mutation ที่ควรเกิดไม่เกิดขึ้น
  • unwrap และ clone ไม่สร้างคำเตือนเลย จึงต้องอาศัยการกลับมาไล่อ่านอีกครั้งก่อน PR สุดท้ายเพื่อเอาออก
  • unwrap อาจคงอยู่ใน production ได้อย่างถูกต้อง ทำให้การใช้แบบชั่วคราวเพื่อ WIP กับการใช้จริงปะปนกันได้
  • ทริก doc comment /// ค่อนข้างใกล้เคียงการแฮ็ก และในตำแหน่งของ expression นั้นห้ามใช้ doc comment จึงอาจกลายเป็นข้อผิดพลาดตอนคอมไพล์
  • หากใส่ /// ในตำแหน่งที่เป็นเอกสารได้จริง ก็อาจไม่เกิดคำเตือนตามที่หวัง และทิ้งเอกสารที่ไม่ต้องการไว้ในโค้ดที่ปล่อยใช้งาน

เครื่องมือที่ crate wip มีให้

  • crate wip เป็นชุดเครื่องมือที่ช่วยให้กลยุทธ์ “ทิ้งคำเตือนไว้จัดการทีหลัง” ระหว่างพัฒนา Rust ใช้งานได้สะดวกขึ้น
  • เพิ่มเข้าโปรเจกต์ได้เหมือน crate ทั่วไป
    • cargo add wip
  • ในไฟล์ที่ต้องใช้ สามารถ import prelude ได้
    • use wip::prelude::*;
  • wip อาศัย deprecation warning ของ Rust ดังนั้นถ้า editor ขีดฆ่าการเรียกใช้ฟังก์ชัน deprecated อัตโนมัติ การปิดฟีเจอร์นี้อาจช่วยให้รบกวนน้อยลง
  • wip::wip!

    • มาโคร wip! ทำงานคล้าย todo! แต่จะสร้าง คำเตือน ทุกครั้งที่ใช้
    • ใช้แทน todo! ในตำแหน่งที่ต้องการทำเครื่องหมายโค้ดยังไม่เสร็จได้
    • ในเวอร์ชันแรกใช้ชื่อ todo แต่เมื่อ dependency พยายาม shadow มาโครจาก std Rust ไม่ค่อยชอบแนวทางนี้ ทำให้เกิดปัญหากับการใช้ prelude
  • unwrap_wip และ clone_wip

    • unwrap_wip และ clone_wip ถูก implement เป็น extension trait สำหรับ Result และ Option
    • เมื่ออยู่ใน scope ก็ทำงานเหมือน unwrap, clone ปกติ แต่จะสร้างคำเตือนเมื่อใช้งาน
    • ทำให้สื่อเจตนาได้ชัดว่าไม่ได้ตั้งใจปล่อย unwrap หรือ clone เหล่านี้ไว้ในโค้ดสุดท้าย
  • wip::fixme!

    • มาโคร fixme! เป็นเวอร์ชัน non-panicking ของ wip! และไม่ได้ใช้แทน expression
    • ใช้ได้คล้ายคอมเมนต์ TODO แต่สร้างคำเตือนได้อย่างเสถียรโดยไม่ต้องพึ่งทริก ///
    • มักใช้ทิ้งโน้ตว่ามีจุดที่ต้องกลับมาแก้ทีหลัง

ขั้นตอนการใช้งานและข้อควรระวัง

  • crate wip ถูกนำไปใช้แล้วใน PR ล่าสุดบางรายการ รวมถึง Meilisearch PR #6484 ซึ่งเป็นหนึ่งใน PR ขนาดใหญ่
  • ขั้นตอนทั่วไปคือ ระหว่างพัฒนาให้เพิ่ม dependency wip เข้าไปใน crate ของ workspace แล้วลบออกในช่วง rewrite history ให้เรียบร้อยก่อนรีวิว
  • wip ช่วยให้โฟกัสกับ happy path ได้ โดยไม่ลืมงานที่ต้องกลับมาจัดการภายหลัง
  • แต่ก็มีข้อเสียอยู่
    • ถ้าใส่ fixme โดยไม่ให้บริบทเพียงพอ เวลากลับมาแก้ทีหลังจะทำได้ยาก
    • ใน PR ขนาดใหญ่ จำนวนคำเตือนที่ wip สร้างอาจมากจนกลายเป็นภาระ
  • API ปัจจุบันดูได้จาก เอกสาร wip บน docs.rs

1 ความคิดเห็น

 
GN⁺ 5 시간 전
ความคิดเห็นจาก Lobste.rs
  • พูดตามตรง จากเหตุผลของ wip มันให้ความรู้สึกว่าเป็นการ ประดิษฐ์ Clippy ขึ้นมาใหม่ เพราะไม่เข้าใจว่าเดิมทีควรใช้เครื่องมือนี้อย่างไร
    ฝั่งผู้พัฒนา toolchain แยกแยะกันมาโดยตลอดว่าอะไรควรเป็นคำเตือนของ rustc และอะไรควรเป็น lint ของ Clippy แต่ wip ดูเหมือนเอาความสามารถที่มีอยู่แล้วมาตั้งชื่อใหม่ แล้วฝืนย้าย lint ที่เคยอยู่ใน cargo clippy ไปไว้ฝั่ง cargo check และ cargo build
    ตัวอย่างเช่น คำอธิบายของ wip! ก็คือทำให้ #![warn(clippy::todo)] แสดงขึ้นมานอก cargo clippy โดยแลกกับการเพิ่ม dependency ใหม่และไวยากรณ์ที่ไม่มาตรฐาน ส่วน unwrap_wip ก็คล้ายกับ #![warn(clippy::unwrap_used)]
    สำหรับผม .unwrap() ใช้ตอนทำ prototype เลยเปิด #![warn(clippy::unwrap_used)] ไว้ ส่วน .expect("description of invariant") ใช้ในโค้ด production ตรงที่คนอาจใช้ .unwrap() แทน .unwrap_wip() ดังนั้นจึงไม่ได้เปิด #![warn(clippy::expect_used)] ตัวอย่างเช่น .expect("parse regex from const")
    ส่วน clone_wip กับ fixme! ผมไม่ค่อยแน่ใจ และก็ยังไม่เคยคิดมากพอจะตอบได้ว่านักพัฒนาตั้งใจให้จัดการกรณีแบบนั้นอย่างไร

    • จะบอกว่าเป็นคำพูดตรง ๆ ก็ได้ แต่ก็ไม่ได้เป็นการพูดที่นุ่มนวลนัก :-) ผมใช้สายงานนี้มา 10 ปีแล้ว และแม้จะไม่ได้หมายความว่ารู้ทุกอย่าง แต่ก็น่าจะ ตีความแบบให้ประโยชน์แห่งความสงสัย กันได้บ้าง
      อย่างไรก็ดี ประเด็นที่บทความไม่ได้พูดถึง linter ที่มีอยู่แล้วอย่าง Clippy นั้นก็เป็นเรื่องจริง มันเกี่ยวกับวิธีใช้งานส่วนตัวด้วย เมื่อก่อนผมเคยรัน Clippy ตอนเซฟไฟล์ แต่ในโปรเจ็กต์ของเรา มันช้าเกินไปจนแต่ละครั้งระหว่างการเซฟกินเวลาเป็นนาที เลยเลิกทำแบบนั้น ตอนนี้รันแค่ใน CI กับ pre-push hook
      ถ้าดึงคำเตือนมาไว้ใน rustc จะเร็วกว่าเยอะ และทำให้เห็นคำเตือนแบบ inline ระหว่างทำงานวนซ้ำได้ ซึ่งเป็นหัวใจของ workflow นี้
      การตั้งค่า Clippy อย่างน้อยตอนที่ผมเช็กล่าสุดก็ยังค่อนข้างยุ่งยาก ไม่มีวิธีกำหนด lint ให้ทุก crate ใน workspace พร้อมกันจากในโค้ด ดังนั้นสำหรับ lint ที่อยากห้ามทั้ง workspace ก็ต้องเพิ่ม -D แบบชัดเจนใน CI หรือไม่ก็ใส่ global attribute ซ้ำไปในทุก crate
      #![warn(clippy::todo)] ต้องมีในทุก crate อยู่ดี ดังนั้นสำหรับเรา มันไม่ได้มีข้อดีมากกว่าการเพิ่มหรือลบ crate เฉพาะตอนพัฒนา todo! ผมคิดว่าโดยพื้นฐานแล้วควรถูกเตือนโดย rustc หรือ Clippy อยู่แล้ว และถ้าเป็นแบบนั้นจริง ก็เห็นด้วยว่าประโยชน์ของ wip จะลดลง
      ผมไม่เห็นด้วยกับคำบอกว่า unwrap_wip ก็คือ #![warn(clippy::unwrap_used)] อยู่สองจุด หนึ่งคือในแง่เจตนา การแบ่งว่า unwrap คือ non-production ส่วน expect คือ production นั้นพบได้บ่อย แต่ไม่ได้เป็นสากล สองคือในโค้ดเบสเดิมมี unwrap อยู่ประมาณ 4600 จุด จะเปลี่ยนทั้งหมดเป็น expect ก็ได้ แต่แบบนั้นก็ต้องเสียเวลาอย่างมากไปกับการใส่ข้อความชั่วคราวตามจุดต่าง ๆ หรือรื้อสร้างเงื่อนไขตั้งต้นอย่าง “mutex นี้ไม่ได้ poisoned” หรือ “อยากส่งต่อความล้มเหลวของงานนี้ไปให้ผู้เรียก”
      fixme! มีประโยชน์มาก และน่าใส่ไว้ใน standard library ด้วย จริง ๆ แล้วมันเป็นฟีเจอร์ที่ใช้บ่อยที่สุดใน crate นี้
      ในบทความไม่ได้ลงรายละเอียดพวกนี้ แต่ crate นี้ไม่ได้ตั้งใจเป็นมาตรฐาน มันเป็นไลบรารีเฉพาะทาง เลยมีฟีเจอร์อย่าง wip_iter ด้วย มันช่วยให้ใช้แมโครอย่าง todo ในฟังก์ชัน impl Trait ที่คืนค่าตำแหน่ง iterator ได้ และ wip_future ก็คล้ายกัน ผมเจอบ่อยพอสมควรกับกรณีที่การอนุมานชนิดคืนค่าและ todo ทำงานร่วมกันไม่ได้ จนต้องฝืนสร้าง type ขึ้นมา มีคนหนึ่งถึงกับเสนอให้ทำเป็น compile error โดยปริยายในโหมด release ด้วย และเราวางแผนจะดูเรื่องนั้นพร้อมกับไอเดียปรับปรุงอื่น ๆ
      ถ้าจะถ่วงดุลเรื่องต้นทุนของ dependency ใหม่กับไวยากรณ์ที่ไม่มาตรฐานสักหน่อย มันเป็น dependency แบบไฟล์เดียวที่ใช้แค่ระหว่างพัฒนา และโดยปกติก็ลบทิ้งตอนเสร็จงาน
  • ปัญหาของการทำ prototype ด้วย unwrap คือภายหลังเมื่อต้องใส่การจัดการข้อผิดพลาดให้ถูกต้อง รูปร่างของชนิดคืนค่า อาจเปลี่ยนไป และยิ่งถ้าฟังก์ชันเหล่านั้นถูกใช้ในสไตล์เชิงฟังก์ชัน ก็จะเกิดผลกระทบเป็นลูกโซ่
    แนะนำให้เริ่มด้วย Result โดยใช้ชนิดข้อผิดพลาดอย่าง Box<dyn Error>, สตริง หรือ anyhow ภายหลังจะค่อยเปลี่ยนเป็น enum ข้อผิดพลาดจริงก็ยังได้ แต่การ refactor โค้ดที่หน้าตาเหมือนไม่มีวันล้มเหลวให้กลายเป็นการคืน Result ในภายหลังนั้นยากกว่า
    อีกอย่าง ถ้าใช้ LLM ก็ต้องระวังด้วย LLM เป็นเครื่องจักรจับคู่แพตเทิร์น มันแยกไม่ออกระหว่าง “อันนี้ตั้งใจทำหยาบ ๆ ก่อนแล้วค่อยแก้ทีหลัง” กับ “โปรเจ็กต์นี้ควรจัดการข้อผิดพลาดแบบนี้” เมื่อเวลาผ่านไป มันอาจขยายการตัดสินใจแบบ “เอาแค่ตอนนี้ก่อน” ให้แพร่ไปทั่วได้ ดังนั้นการใส่คอมเมนต์สั้น ๆ ไว้ใน main สักหนึ่งหรือสองจุดเพื่อบอกว่าเมื่อไร/ที่ไหนที่ยอมให้จัดการข้อผิดพลาดแบบหลวม ๆ ได้ ก็น่าจะช่วยได้

  • ผมกับเอกสารไม่เห็นตรงกันเรื่องการตีความ todo!() กับ unimplemented!() แต่ย่อหน้าถัดไปที่ถูกตัดออกไปก็ช่วยถ่วงดุลจุดยืนนั้นได้ระดับหนึ่ง
    ในเอกสารระบุว่า todo! ใช้สื่อเจตนาว่าจะทำในภายหลัง และข้อความคือ “not yet implemented” ส่วน unimplemented! ไม่ได้ให้คำมั่นแบบนั้น และข้อความคือ “not implemented”
    ตอนที่ todo! ถูกเพิ่มเข้ามาใน 1.40.0 มันเป็นแค่ชื่อที่สั้นกว่าเท่านั้น และนอกจากชื่อแล้วก็ไม่ได้ต่างจาก unimplemented!
    ต้องรอถึง 1.42.0 จึงค่อยเอาคำว่า “yet” ออกจากข้อความของ unimplemented เท่าที่ผมจำได้ การกำหนดความหมายแบบนี้ให้แมโครทั้งสองก็ค่อนข้างมีข้อถกเถียงอยู่บ้าง และการปล่อย todo! ออกมาในฐานะคำย่อของ unimplemented! ก็เช่นกัน
    ทุกวันนี้ unimplemented!() มักแนะนำให้ใช้ในที่อย่าง implementation ของ trait ที่ด้วยเหตุผลทางเทคนิคแล้วจำเป็นต้องมี method body แต่ไม่ควรถูกเรียกใช้เลย ตัวอย่างในเอกสาร ก็เป็นลักษณะนั้นพอดี

  • ระหว่างพัฒนา การเพิ่ม dependency wip เข้าไปใน crate ของ workspace แล้วค่อย rewrite history เพื่อลบออกก่อนรีวิว ดูเหมือนน่าจะทำให้ลื่นขึ้นได้อีกด้วยเครื่องมือเสริมบางอย่าง
    การต้อง เขียนไฟล์ล็อกใหม่ ระหว่างแก้ไข PR อยู่กลางทางนั้นน่าลังเลอยู่บ้าง ถ้าระหว่างนั้น dependency tree เปลี่ยนไปที่อื่นด้วย ก็อาจเกิด conflict ที่ไม่จำเป็นได้ อาจจะใช้ jj fix แบบจัดหนักได้เหมือนกัน ไม่ว่าอย่างไร ไอเดียของโปรเจ็กต์นี้ดีมาก และผมคิดว่าสักวันคงได้ใช้ที่ไหนสักแห่ง

  • แมโครสำหรับจดโน้ตแบบไม่ panic อย่าง wip::fixme! เป็นไอเดียที่ดีมากจริง ๆ และ ลูกเล่นด้วย doc comment ก็เป็นวิธีที่เนี้ยบดีและควรจำไว้

  • มีหลายไอเดียที่น่าสนใจและหวังว่าจะต่อยอดไปสู่การเปลี่ยนแปลงฝั่ง rustc ได้ todo!() ควรมี คำเตือนโดยปริยาย จริง ๆ
    จะดียิ่งขึ้นถ้านักพัฒนาสามารถปิดคำเตือนพวกนี้ได้ตอนอยู่ในโหมดแฮ็ก เมื่อคำเตือนมีมากเกินไปมันชวนให้ท่วมท้น และปกติผมก็รัน cargo ในคอนโซล 19 บรรทัดด้านล่าง IDE ระหว่างพัฒนา คำเตือนมักไปกลบทั้งข้อผิดพลาดจริงและคำเตือนที่สำคัญกว่า แค่มีวินัยให้เรียงข้อผิดพลาดไว้ท้ายสุดเสมอก็น่าจะช่วยบรรเทาปัญหานี้ได้
    อีกอย่าง ชื่อ .unwrap_wip() กับ .clone_wip() ยาวเกินไปเมื่อเทียบกับชื่อเดิม ขอเสนอชื่ออย่าง .du() และ .dc() เป็นตัวย่อของ “dev unwrap” กับ “dev clone” น่าจะใช้ง่ายกว่าเวลาต้องเขียนโค้ดเร็ว ๆ

  • จะมีทาง เติม .clone() กับ .unwrap() ให้อัตโนมัติ ในจุดที่จำเป็นได้ไหม? เช่น ด้วยแฟลกหรือฟีเจอร์อย่าง #[wip(autoclone,autounwrap)] อะไรทำนองนั้น อาจทำไม่ได้ แต่ฝันได้

  • ทุกครั้งที่เริ่มโปรเจ็กต์ใหม่หรือ prototype ใหม่ ผมจะใส่บรรทัดพวกนี้ไว้ใน main.rs:
    #![allow(dead_code)]
    #![allow(unused_variables)]
    #![allow(unreachable_code)]
    มันช่วยลดเสียงรบกวนได้มากในช่วงเริ่มต้น