ข้ามไปยังเนื้อหา

Review checklist

นี่คือ checklist ที่ต้องไล่ตรวจ — ด้วยตา บน diff ไหนก็ได้ ของคุณเองหรือของ AI — หลังจากเครื่องมือใน Verification Tools รันเสร็จและผ่านสะอาดแล้ว มันตั้งใจให้อยู่ในกระดาษหน้าเดียวพอดี: checklist ที่ไม่มีใครเปิดดูจริงระหว่างรีวิวก็ไร้ค่า ทุกบรรทัดลิงก์ไปยัง catalog entry ที่อธิบาย ทำไม เพื่อให้หน้านี้ยังเป็นแค่รายการ ไม่ใช่การรันคอร์สซ้ำ กลุ่มต่าง ๆ เรียงตามลำดับเดียวกับ How to read Flutter code you did not write บวกกลุ่ม Tooling สุดท้ายที่ครอบคลุมว่าอีกแปดกลุ่มถูกตรวจสอบจริงได้อย่างไร

flowchart LR
  A["State &amp; lifecycle"] --> R["Needs a real dispose/rebuild sequence<br/>to surface at all"]
  W["Widget tree &amp; keys"] --> T["Mostly human review<br/>(renders correctly either way)"]
  L["Layout"] --> T2["Framework catches it loudly --<br/>but only the exact arrangement that overflows"]
  As["Async &amp; isolates"] --> R
  N["Navigation"] --> T
  P["Platform"] --> D["Needs the actual platform/runtime --<br/>compiles and analyzes clean otherwise"]
  Pf["Performance"] --> M["Silent cost, not a crash --<br/>needs reading RenderObject properties directly"]
  Tl["Tooling &amp; release"] --> M2["Analyzer/lint catches SOME --<br/>only if the rule is actually enabled"]
อะไรจับแต่ละกลุ่มได้จริง ถ้ามี
  • environment: sdk: ใน pubspec.yaml รองรับ Dart/Flutter เวอร์ชันที่โปรเจกต์นี้เล็งเป้าไว้จริงหรือเปล่า ไม่ใช่ก็อปมาจาก tutorial เก่า?
  • โค้ด Riverpod ไหนเรียก StateProvider/StateNotifierProvider/ChangeNotifierProvider ผ่าน import หลัก flutter_riverpod.dart แทนที่จะเป็น import legacy.dart ที่จำเป็นใน Riverpod 3 หรือเปล่า? ดู AI Bug Catalog entry 5 พิสูจน์ด้วย diagnostic จริง undefined_function
  • ถ้า custom_lint/riverpod_lint ถูก pin ไว้ทั้งคู่ พวกมัน resolve คู่กันได้จริงที่เวอร์ชันเหล่านั้นหรือเปล่า? ดู Verification Tools สำหรับข้อค้นพบ version-conflict จริงและเป็นปัจจุบัน
  • มี ProviderScope อยู่เหนือ ConsumerWidget/ref.watch ตัวแรกหรือเปล่า? ดู AI Bug Catalog entry 1 พิสูจน์ด้วย Bad state: No ProviderScope found จริง
  • ทุก setState ที่เข้าถึงได้จาก .then(), การทำงานต่อหลัง await, Timer, หรือ Stream listener เช็ค mounted ก่อนหรือเปล่า? ดู entry 2 พิสูจน์ด้วย setState() called after dispose() จริง
  • build() ของ widget ไหนเรียก setState บน widget อื่น ที่ยังกลาง build แบบ synchronous หรือเปล่า? ดู entry 3 พิสูจน์ด้วย setState() or markNeedsBuild() called during build จริง
  • field แบบ late เคยถูกอ่านบน path ที่ method ซึ่งกำหนดค่าให้มันอาจยังไม่ทำงานหรือเปล่า? ดู entry 4 พิสูจน์ด้วย LateInitializationError จริง
  • list ของ stateful widget ที่สร้างด้วย for/.map() มี key หรือเปล่า ในเมื่อลำดับของมันเปลี่ยนได้? ดู AI Bug Catalog entry 6 พิสูจน์ด้วย test การเรียงใหม่จริง
  • GlobalKey ตัวเดียวกันถูกใช้ซ้ำข้าม sibling widget แทนที่จะใช้ UniqueKey()/ValueKey ต่อรายการหรือเปล่า? ดู entry 7 พิสูจน์ด้วย Duplicate keys found จริง
  • Scaffold.of(context) เคยถูกเรียกด้วย context ตัวเดียวกันเป๊ะกับที่ Scaffold ที่ล้อมรอบถูก build ด้วย แทนที่จะเป็น context จาก descendant ของ Builder หรือเปล่า? ดู entry 8 พิสูจน์ด้วย Scaffold.of() called with a context that does not contain a Scaffold จริง
  • ListView/GridView/scrollable อื่นถูกวางตรง ๆ ใน Column/Row โดยไม่มีอะไรจำกัดขนาดแกนหลักของมันหรือเปล่า? ดู AI Bug Catalog entry 9 พิสูจน์ด้วย Vertical viewport was given unbounded height จริง — และยืนยันว่ากรณีย้อนกลับ (Column ข้างใน ListView) ไม่ถูก “แก้” โดยไม่จำเป็น
  • Expanded/Flexible เคยถูกใช้เป็นลูกของสิ่งที่ไม่ใช่ Row/Column/Flex หรือเปล่า? ดู entry 10 พิสูจน์ด้วย Incorrect use of ParentDataWidget จริง
  • Row/Column ของ children ขนาดคงที่ไม่มี Expanded/Flexible/scrolling เป็นทางออกสำหรับเนื้อหาที่อาจเกิน viewport หรือเปล่า? ดู entry 11 พิสูจน์ด้วย RenderFlex overflowed จริง
  • async function ถูกเรียกตรง ๆ ข้างใน build() แทนที่จะเรียกครั้งเดียวใน State (initState/field แบบ late final) หรือเปล่า? ดู AI Bug Catalog entry 12 พิสูจน์ด้วยการนับจำนวนการ rebuild-refetch จริง
  • closure ของ compute() capture BuildContext, Zone, หรืออะไรก็ตามที่เข้าถึงได้จาก binding ของ isolate นี้เองหรือเปล่า? ดู entry 13 พิสูจน์ด้วย Illegal argument in isolate message: object is unsendable จริง
  • StreamController ถูกปล่อยไว้ที่ default แบบ single-subscription ในขณะที่มีการเรียก .listen() อิสระมากกว่าหนึ่งครั้งบนมันหรือเปล่า? ดู entry 14 พิสูจน์ด้วย Bad state: Stream has already been listened to จริง
  • route ของ go_router ที่มีพารามิเตอร์ (/pets/:id) ถูกประกาศ ก่อน route แบบ static ที่เฉพาะเจาะจงกว่าในระดับ segment เดียวกัน (/pets/new) หรือเปล่า? ดู AI Bug Catalog entry 15 พิสูจน์ด้วย test misroute จริง
  • context.go()/router.go() ถูกใช้ในจุดที่ user ต้องกดย้อนกลับได้ (navigation แบบดำดิ่งลึก) แทนที่จะเป็น push() หรือเปล่า? ดู entry 16 พิสูจน์ด้วยการเปรียบเทียบความลึกของ route stack จริง
  • callback redirect อ่าน state ภายนอก (auth flag) โดยไม่ได้ชี้ refreshListenable ไปที่สิ่งที่แจ้งเตือนเมื่อ state นั้นเปลี่ยนหรือเปล่า? ดู entry 17 พิสูจน์ด้วย test ที่ค้างหน้า login จริง
  • โค้ดไหนยังใช้ WillPopScope (deprecated ไม่รองรับ predictive-back) หรืออ้างถึง PredictiveBackPageTransitionBuilder (ขาดตัว “s”) หรือเปล่า? ดู entry 18 พิสูจน์ด้วย deprecation info จริงและ undefined_function error จริง
  • dart:io/Platform.isIOS/File ถูกใช้แบบไม่มีเงื่อนไขในโค้ดที่ต้อง build สำหรับ web ด้วยหรือเปล่า? ดู AI Bug Catalog entry 19 พิสูจน์ด้วย flutter build web --release จริงที่สะอาดและซ่อนบั๊กไว้จนกว่าจะถึง runtime จริง
  • การเรียก MethodChannel.invokeMethod สมมติว่ามี native handler ลงทะเบียนไว้ทุก platform ที่แอป ship ไปหรือเปล่า (และทุก test ที่ใช้มัน mock channel หรือเปล่า)? ดู entry 20 พิสูจน์ด้วย MissingPluginException จริง
  • FlutterError.onError ถูกมองว่าครอบคลุม error ทั้งหมด โดยไม่มี runZonedGuarded/PlatformDispatcher.onError สำหรับ error ที่ throw นอก build/layout/paint ของ framework เองหรือเปล่า? ดู entry 21 พิสูจน์ด้วย error จาก Future ธรรมดาจริงที่มีแค่ runZonedGuarded เท่านั้นที่จับได้
  • AnimationController ทุกตัวที่สร้างด้วย SingleTickerProviderStateMixin/TickerProviderStateMixin ถูก .dispose() ใน dispose() ของ State เองหรือเปล่า? ดู AI Bug Catalog entry 22 พิสูจน์ด้วย was disposed with an active Ticker จริง
  • Opacity(opacity: 1.0) ถูกใช้ในจุดที่ค่าไม่เคยเปลี่ยนแปลงจริง ๆ แทนที่จะคืนค่า child ตรง ๆ หรือเปล่า? ดู entry 23 พิสูจน์ด้วยการอ่าน property isRepaintBoundary/alwaysNeedsCompositing ของ RenderOpacity ที่มีชีวิตจริง
  • โค้ดไหนยังส่งตัวเลขเปล่า ๆ ให้ cacheExtent แทนที่จะเป็น scrollCacheExtent: ScrollCacheExtent.pixels(...) หรือเปล่า? ดู entry 24 พิสูจน์ด้วย deprecation info จริงและคำแนะนำจริงจาก dart fix --dry-run
  • const ถูกสมมติว่าถูกบังคับใช้โดย “linter” ทั้งที่ flutter_lints 6.0.0 ที่คอร์สนี้ pin ไว้มีแค่ prefer_const_constructors_in_immutables ไม่มี rule ทั่วไปหรือเปล่า? ดู AI Bug Catalog entry 25 พิสูจน์ด้วยการเทียบ flutter analyze ก่อน/หลังจริง
  • การเรียก print() ไหนถูกสมมติว่าถูกตัดออกจาก release build หรือเปล่า? ดู entry 26 พิสูจน์ด้วย string จริงที่พบคำต่อคำข้างใน main.dart.js ของ release
  • switch บน sealed class ข้าม subtype ไปโดยพึ่งความเคยชินแทนที่จะพึ่ง exhaustiveness check ของ analyzer เองหรือเปล่า? ดู entry 27 พิสูจน์ด้วย non_exhaustive_switch_expression error จริง
  • named parameter หรือชื่อ method ไหนดูสมเหตุสมผลแต่ไม่มีอยู่จริงบน class ที่กำลังพูดถึงหรือเปล่า? ดู entry 28 พิสูจน์ด้วย undefined_named_parameter/undefined_method error จริง — การเช็คที่ถูกที่สุดและใช้เครื่องจักรจับได้ง่ายที่สุดในทั้งหน้านี้
  • CI รันทั้ง flutter analyze AND flutter test (ไม่ใช่แค่ตัวใดตัวหนึ่ง) โดยรู้ว่า analyze พิสูจน์แค่ type/syntax ไม่เคยพิสูจน์พฤติกรรมตอน runtime เลยหรือเปล่า? ดู Verification Tools
  • flutter build web --wasm เคยถูกใช้เป็น portability gate หรือเปล่า หรือมีแค่ default build แบบ JS? ดู Verification Tools พิสูจน์ด้วย --wasm build จริงที่สะอาด
  • harness ของคอร์สนี้เอง (npm run verify, --test <module>/<lesson>) รันกับทุก fence จริงหรือเปล่า ไม่ใช่แค่ human skim? ดู Verification Tools
ทำไม checklist item ของกลุ่ม 'Layout' สำหรับ entry 9 ถึงขอให้ reviewer ยืนยันโดยเฉพาะว่ากรณีย้อนกลับ (Column ข้างใน ListView) ไม่ถูก 'แก้' โดยไม่จำเป็น?
ทำไมกลุ่ม 'Tooling & release' ถึงถามเจาะจงว่า CI รันทั้ง flutter analyze AND flutter test หรือเปล่า แทนที่จะถือว่า analyze ที่สะอาดเพียงพอแล้ว?
checklist item ของกลุ่ม Platform สำหรับ entry 19 บอกว่า flutter build web --release ที่สะอาด 'ซ่อนบั๊กไว้จนกว่าจะถึง runtime จริง' นั่นหมายความว่า reviewer ต้อง*ไม่*สรุปอะไรจาก web build ที่เขียว?