Steven
Steven3 นาทีที่อ่าน

หน้า Login นั่นแหละคือ Demo

GeekBye v1.7.5 เพิ่ม screenshot ของโปรดักต์ลงหน้า login แล้วลบทิ้งภายในวันเดียวกัน — ก่อนจะสร้างใหม่ด้วยคอมโพเนนต์ของจริงแทน แถมด้วย: ผู้ใช้ที่เร็วกว่า OCR และ style commit 25 ตัวในวันเดียวหน้าตาเป็นยังไงกันแน่

วิศวกรรม
ดีไซน์
UX
GeekBye รีลีส
หน้า Login นั่นแหละคือ Demo

GeekBye v1.7.5 คือรีลีสหนึ่งสัปดาห์ที่มีบุคลิกแตกเป็นสองขั้ว: 37 คอมมิต โดย 28 ตัวเป็นการรีดีไซน์หน้า login — และ 25 ตัวจากในนั้นคือการจูนจิ๋ว ๆ แบบ style(login) ที่ลงจอดทั้งหมดในวันเดียว มันยังเป็นรีลีสที่แก้ race ที่ให้บทเรียนได้ดีที่สุดตัวหนึ่งในโค้ดเบสด้วย ทั้งสองเรื่องคุ้มค่าแก่การเล่า และมาบรรจบกันที่ความคิดเดียวกัน: หน้า login คือสิ่งแรกที่ผู้ใช้ที่ยังไม่ล็อกอินเห็น เพราะฉะนั้นมันควรเป็นตัวโปรดักต์เอง ไม่ใช่รูปถ่ายของโปรดักต์

screenshot ที่อยู่ได้ราวห้าชั่วโมง

การรีดีไซน์เริ่มต้นแบบขนบเดิม จัดโครงใหม่เป็นสองคอลัมน์ วางช่อง sign-in ไว้ซ้าย แล้วโชว์โปรดักต์ทางขวา — เป็นรูปภาพ คอมมิตช่วงสายทำแบบนั้นเป๊ะ: เวลา 11:57 screenshot พรีวิวของจริงเข้ามาอยู่ใน repo เป็น PNG ขนาด 114 KB และถูกอัปเดตหนึ่งครั้งในอีกหกนาทีถัดมา

พอถึง 17:04 มันก็หายไปแล้ว คอมมิตหักเลี้ยวแทนที่รูป static ด้วยคอมโพเนนต์ของจริง 344 บรรทัด — แผง LoginDemo ที่ประกอบจากชิ้นส่วนเล็ก ๆ แปดชิ้นซึ่งจำลอง overlay UI ตัวจริง: pill นำทางสำหรับอัดเสียงพร้อมแท่ง EQ เต้นตุบ ๆ และปุ่มหยุด, แผงแชทพร้อมแท็บ Chat/Transcript, คำตอบของ assistant ที่ render มาให้ดู (อธิบาย useEffect ของ React — ช่างเข้ากับสถานการณ์), ปุ่มลัด "Tell me more / Simplify / Show example", แถว live-prompt และช่องพิมพ์ Assist แบบ ⌘⏎

ขอเป๊ะกับคำว่า "demo" หน่อย เพราะมันเป็นคำที่เคลมเกินจริงได้ง่าย: ปุ่มมี hover state ของจริง — glow, shimmer, transition — แต่ไม่มีอะไรต่อสายเข้ากับการคลิกเลย และช่องพิมพ์เป็นแบบ read-only มันไม่ใช่ sandbox สิ่งที่มันเป็นคือคลังศัพท์ UI ตัวจริงของโปรดักต์ที่ถูก render สด ๆ: โลโก้ asset ตัวเดียวกัน, การตกแต่งขอบ gradient และ backdrop-blur แบบเดียวกัน, การ import productName ตัวเดียวกับที่ระบบ white-label ใช้ — demo จึง rebrand ตัวเองอัตโนมัติให้กับแต่ละโปรดักต์ที่ build จากโค้ดเบสนี้ screenshot ทำแบบนั้นไม่ได้สักอย่าง screenshot เก่าตั้งแต่วันที่คุณถ่ายมัน เบลอบนจอที่ไม่ตรงสเปก และถูกตีตราแบรนด์ถาวรเป็นโปรดักต์ใดก็ตามที่คุณบังเอิญแคปมา คอมโพเนนต์คมชัดทุก DPI ทันสมัยเสมอ และถูกต้องสำหรับทุกแบรนด์ — เพราะมันไม่ใช่รูปถ่ายของ design system มันคือ design system

ส่วน PNG ที่ถูกลบไปนั้น ยังคงอยู่ใน repo ที่ตำแหน่ง release tag — กลายเป็นไฟล์กำพร้า ไม่มีอะไรอ้างถึงมันอีก ทุกโค้ดเบสล้วนแบกซากของแนวทางที่พ่ายแพ้ติดตัวไว้สักสองสามชิ้นเสมอ

style commit 25 ตัวในวันเดียวหน้าตาเป็นยังไง

commit log ของวันนั้นวันเดียวคือสมุดสเก็ตช์ของดีไซเนอร์ ที่ถูกเก็บรักษาไว้อย่างซื่อตรงผิดปกติ อัตราส่วนคอลัมน์ไป 40/60 แล้วก็ 45/55 ป้าย "Works with" เหนือโลโก้แพลตฟอร์มถูกเพิ่มตอนเที่ยง ถูกย้ายตำแหน่ง แล้วถูกถอดออก — อยู่ได้ราวครึ่งวัน แถวโลโก้แพลตฟอร์มเอง (Google Meet, Teams, Zoom, Slack, Webex) ที่เพิ่มมาตอนเช้า 10:59 ถูกลบทิ้งทั้งแถวตอน 22:08 คืนนั้น ส่วน footer ต้องผ่านมหากาพย์สี่แนวทางกว่าจะจัดวางลงตัว: ครอบด้วย wrapper container ตัวเดียว แล้วถอดคลาส centering ออก แล้วจัดกึ่งกลางด้วย flexbox แล้วสุดท้ายก็แค่ขยับมันลงไปชิดขอบล่างอีกนิด

จะอ่านทั้งหมดนี้ว่าเป็นการวนอยู่กับที่ก็ง่ายอยู่ แต่เราอ่านมันว่าเป็นรูปร่างที่แท้จริงของงานดีไซน์: คุณลู่เข้าหาคำตอบด้วยการ render มองดู แล้วปรับ — และการทำแบบนั้นด้วยคอมมิตเล็ก ๆ 25 ตัวแทนที่จะ squash เป็น "redesign login page" ก้อนเดียว หมายความว่าตัวกระบวนการค้นหาเองถูกบันทึกไว้ พอมีคนถามว่า "เราเคยลองแถวโลโก้ครั้งหนึ่งไม่ใช่เหรอ" คำตอบก็อยู่ในประวัติ พร้อม timestamp

ผู้ใช้ที่เร็วกว่า OCR

เรื่องราวฝั่งวิศวกรรมของรีลีสนี้เกิดขึ้นก่อนหน้านั้นห้าวัน ในเชนการแก้สามคอมมิต ตั้งแต่ v1.5.12 การกด Cmd+H จะเข้าคิว screenshot พร้อมฟีดแบ็กทันที: thumbnail โผล่ในคิวทันใด ส่วนการสกัดข้อความ — Apple Vision OCR ในเครื่อง ใช้เวลาราวหนึ่งถึงสองวินาที — รันอยู่เบื้องหลัง อีเวนต์เข้าคิวถูกส่งออกไปพร้อม ocrText: '' ตรง ๆ แบบนั้นเลย พร้อมคอมเมนต์ที่สัญญาว่าเดี๋ยวจะมาเติมให้ทีหลัง

นั่นเป็น optimization ที่ดี และมันก็ผลิต race ออกมาหนึ่งตัว ผู้ใช้มือไวกด Cmd+H แล้วกดส่งคำถามทันที ฟิลด์ข้อความของ screenshot ยังว่างอยู่ request บินออกไปโดยไม่มีเนื้อหาบนจอเลยแม้แต่นิด และโมเดลก็ตอบ — ตามความจริง แบบชวนหัวเสียสุด ๆ — ว่า "I cannot see images" (ฉันมองไม่เห็นรูปภาพ) เส้นทางแบบซื่อ ๆ นี้ไม่ได้พังด้วย error; มันพังด้วยคำตอบที่ถูกต้องต่อคำถามที่ผิด ซึ่งเป็นวิธีพังของซอฟต์แวร์ที่ชวนงงที่สุด

ตัวแก้เอางาน async ที่ optimization เลื่อนไว้มากั้นเส้นทางการ submit: ถ้า screenshot ในคิวตัวไหนยังมี OCR text ว่างอยู่ request จะจอดรอ และ UI แสดงตัวบอกสถานะ "Reading screen..." (กำลังอ่านหน้าจอ); useEffect จะ fire ทันทีที่ข้อความมาถึง แล้วส่ง request พร้อมเนื้อหาที่สกัดครบถ้วน ใน diff มีดีเทลเฉพาะทาง React สองจุดที่ควรขโมยไปใช้: คิวของ screenshot ถูก mirror เข้าไปใน ref ที่ sync ระหว่าง render เพราะเชนของ closure ใน event handler จับ state ที่ค้างเก่าไว้; และ request ที่จอดรอถูกส่งตรง ๆ แทนที่จะผ่าน hook คิว request แบบ generic ด้วยเหตุผล stale closure เดียวกัน

และมีหักมุมแบบตรงไปตรงมาบันทึกอยู่ใน commit message เลย: tracing log ที่เพิ่มมาเพื่อล่า race ตัวนี้เผยให้เห็นบั๊กตัวที่สองบนฝั่ง backend — การประกอบ prompt ทำ screenshot text หล่นหายทั้งก้อนใน code path หนึ่ง อาการเดียว บั๊กสองตัว เจอได้ด้วยการติดเครื่องมือวัดทั้งเชนแล้วเฝ้าดูว่าข้อความหายไปตรงไหน เชนนี้จบลงด้วยการตัดสินใจเชิงโปรดักต์ เก้านาทีหลังการแก้ race: Cmd+H เข้าคิว screenshot สำหรับวิเคราะห์แบบ batch ส่วน Cmd+Enter จะแคปหน้าจอปัจจุบันสดใหม่เสมอ — สอง workflow ที่ชัดเจน แทน workflow กำกวมตัวเดียว (ส่วน Assist ของ Cmd+Enter ทำอะไรจริง ๆ นั้นเป็นโพสต์ของมันเอง: ความช่วยเหลือจาก AI แบบทันทีกับอะไรก็ตามที่คุณกำลังมองอยู่)

โคดาชิ้นเล็กจากสัปดาห์เดียวกัน สำหรับผู้อ่านบทว่าด้วย white-label: User-Agent แบบ Product/version (platform) ได้ตัวแก้สำหรับโหมด dev เพราะ app.getVersion() ใน Electron ที่ยังไม่ได้ package จะคืนเวอร์ชันของ Electron ไม่ใช่ของโปรดักต์ สตริงระบุตัวตนก็อย่างที่รู้กัน รั่วอยู่ในท่อประปาเสมอ

สามสิ่งที่รีลีสนี้สอนเรา

  1. จง render โปรดักต์ อย่าถ่ายรูปมัน demo บนหน้า login ที่สร้างจากคอมโพเนนต์จริง rebrand ตัวเองอัตโนมัติ รอดทุกความหนาแน่นของจอ และเก่าไม่เป็น แนวทาง screenshot ถูกลองแล้วถูกลบภายในวันทำงานเดียว — การทดลองราคาถูก คำตัดสินชัดเจน
  2. ทุก optimization แบบ async ต้องมีประตูกั้นตรงจุดที่ใช้งาน "ฟีดแบ็กทันทีพร้อม OCR text ว่าง" เป็นการตัดสินใจด้าน UX ที่ถูกต้อง แต่เส้นทางการ submit ต้องเรียนรู้ที่จะรอสิ่งที่ optimization เลื่อนไว้ ถ้าคุณเลื่อนงานออกไป จงหาผู้บริโภคผลลัพธ์ของมันให้ครบทุกราย แล้วสอนพวกเขาให้แยกระหว่าง "ว่างเปล่า" กับ "ยังไม่พร้อม"
  3. ติดเครื่องมือวัดทั้งเชน ไม่ใช่แค่ผู้ต้องสงสัย tracing log ตาม screenshot text ตั้งแต่ต้นจนจบ — จาก shortcut handler ไป IPC ไป API client — และนั่นคือเหตุผลที่การสืบสวนครั้งเดียวปิดบั๊กได้สองตัว โดยตัวหนึ่งอยู่อีกฟากของเครือข่าย

สำหรับบทก่อนหน้าของเรื่องราวยุค v1 ดูการประชุมที่กลับมาหาเจอได้จริง ๆ (v1.7.3); และสำหรับภาพรวมทั้งเส้นเรื่อง ดูกายวิภาคของการส่งมอบซอฟต์แวร์ให้สมบูรณ์แบบ

บทความที่เกี่ยวข้อง

ออกแบบ Dashboard ใหม่โดยยึด wave chart หนึ่งอันเป็นหัวใจ
Steven
Steven4 นาทีที่อ่าน

ออกแบบ Dashboard ใหม่โดยยึด wave chart หนึ่งอันเป็นหัวใจ

GeekBye v1.8.2 เปลี่ยน dashboard จากรีโมตคุมการอัดเสียงให้กลายเป็นหน้าวิเคราะห์แบบอ่านอย่างเดียว — stats strip หนึ่งแถบกับ wave chart 7 วัน สององค์ประกอบเด่นนี้เป็นดราฟต์ที่สองทั้งคู่ ถูก ship ภายใน 20 นาทีหลังดราฟต์แรก ในบ่ายวันเดียวกัน

วิศวกรรม
ดีไซน์
Dashboard
การประชุมที่กลับมาหาเจอได้จริง ๆ: รีลีส Timeline
Steven
Steven3 นาทีที่อ่าน

การประชุมที่กลับมาหาเจอได้จริง ๆ: รีลีส Timeline

GeekBye v1.7.3 เปลี่ยน dropdown ของการประชุมให้กลายเป็น timeline ของจริง — วันที่แบบมนุษย์อ่านง่าย, ค้นหาได้, breadcrumb ที่บอกว่าคุณอยู่ในการประชุมไหน ส่วนข้างใต้: race ของ auto-select, screenshot ที่เกิดก่อนการประชุมของตัวมันเอง และการแก้บั๊ก Windows 5 ครั้งใน 28 นาที

วิศวกรรม
UX
เดสก์ท็อป
ส่งมอบสามสิบภาษาโดยไม่มีตาข่ายรองรับ
Steven
Steven4 นาทีที่อ่าน

ส่งมอบสามสิบภาษาโดยไม่มีตาข่ายรองรับ

GeekBye v1.8.3 ต่อ react-i18next เข้าไปและแปลทั้งแอปเป็น 30 ภาษา ส่วนที่เป็น library นั้นเป็นงานปกติ ส่วนที่น่าสนใจคือสิ่งที่ขาดหายไป: ไม่มีการเช็ก key parity และไม่มีตัวดึงสตริง — ภาษาอังกฤษที่ hardcode ไว้จึงหลุดออกมา, typo ภาษาเดนมาร์กหลุดขึ้น production, และ changelog เองก็ตกลงกันไม่ได้ว่าแอปพูดได้ 28, 29 หรือ 30 ภาษากันแน่

วิศวกรรม
i18n
Desktop