แอปที่ผมออกแบบและสร้างขึ้นเอง แต่ไม่เคยเปิดตัวเลย: Stocketa
(paulstamatiou.com)- ช่วงต้นของการกักตัวโควิดในเดือนมีนาคม 2020, Stocketa เริ่มต้นจาก โปรเจกต์ส่วนตัวเพื่อเรียนรู้ Swift และ SwiftUI และถูกพัฒนาต่อเนื่องมากกว่า 2 ปี สัปดาห์ละ 10–20 ชั่วโมง แต่ไม่เคยปล่อยบน App Store
- เป้าหมายคือเป็น ตัวติดตามพอร์ตสำหรับนักลงทุนทั่วไป ที่รวมสินทรัพย์ซึ่งกระจายอยู่ตามโบรกเกอร์และบริการการเงินหลายแห่งมาไว้ในที่เดียว พร้อมดูผลกำไร/ขาดทุนรายธุรกรรม รวมถึงกำไรที่รับรู้แล้วและยังไม่รับรู้
- แอปนี้เน้น อินเทอร์แอ็กชันที่สร้างขึ้นเอง มากกว่าคอมโพเนนต์มาตรฐานของ iOS โดยทำ pull-to-search, การ์ดหุ้น, ชีตและเมนูแบบคัสตอม, swipe actions, วิดเจ็ต, การนำเข้า TSV เป็นต้น
- ข้อจำกัดเชิงปฏิบัติที่ใหญ่ที่สุดซึ่งขวางการเปิดตัวคือ API ข้อมูลการเงิน โดยมีทั้งปัญหาคุณภาพและขอบเขตข้อมูลของ IEX, ความน่าเชื่อถือของผู้ให้บริการราคา $100 ต่อเดือน, และราคาข้อมูลเชิงพาณิชย์ที่เริ่มต้นมากกว่า $2,000 ต่อเดือนซึ่งไม่เหมาะกับแอปอิสระ
- แม้จะมี LLC, แบ็กเอนด์ Node/Express, TestFlight ขนาดราว 1,000 คน, และรายชื่อผู้รออีกหลายพันคน แต่สุดท้ายก็ยุติโครงการเพราะต้นทุนข้อมูล ภาระซัพพอร์ตลูกค้า และเวลาไม่พอ ขณะที่ประสบการณ์การเรียนรู้ SwiftUI ก็ต่อยอดไปสู่งานที่ Rewind AI โดยตรง
ปัญหาที่ Stocketa พยายามแก้
- Stocketa ตั้งเป้าเป็น แอปติดตามพอร์ตที่ออกแบบมาอย่างดี สำหรับดูสินทรัพย์ลงทุนที่กระจายอยู่หลายที่ในหน้าจอเดียว
- จุดเริ่มต้นมาจากประสบการณ์ส่วนตัวที่รู้สึกยุ่งยากกับการตรวจสอบสินทรัพย์ที่กระจายอยู่ตามโบรกเกอร์และบริการการเงินหลายแห่ง
- ไม่ได้อยากดูแค่ราคา แต่ต้องการเห็นกำไร/ขาดทุนจริงของแต่ละธุรกรรมโดยอิงจากต้นทุนของตัวเอง
- ตัวเลือกในเวลานั้นไม่ตอบโจทย์
- แอปหุ้นแบบง่ายอย่าง Apple Stocks มีกราฟและข่าว แต่ไม่มีฟังก์ชันติดตามจำนวนที่ถือและกำไร/ขาดทุน
- แอปโบรกเกอร์อย่าง Robinhood แสดงได้เฉพาะสินทรัพย์ที่อยู่ในโบรกเกอร์นั้น
- บริการขั้นสูงอย่าง TradingView ไม่ได้เน้นมือถือเป็นหลัก หรือไม่ได้ให้ประสบการณ์ที่ลื่นไหลสวยงามเท่าที่ต้องการ
- บริการที่ปรึกษาการลงทุนอย่าง Personal Capital แม้จะเชื่อมบัญชีได้ แต่ดูรายละเอียดสินทรัพย์รายตัวได้ไม่ลึก และเน้นขายบริการที่ปรึกษาของตัวเองมากกว่า
- แอปติดตามหุ้นขนาดเล็กใน App Store ส่วนใหญ่ยังไม่ถูกใจในด้านดีไซน์และ UX
- แอปการเงินเดิม ๆ มักให้ความสำคัญกับ ความหนาแน่นของข้อมูล จนต้องกดลึกจากรายการไปหน้ารายละเอียดอยู่เรื่อย ๆ ส่วน Stocketa ต้องการแสดงข้อมูลให้มากขึ้นภายในการ์ดบนหน้าหลักตั้งแต่แรก
โครงสร้างแอปที่สร้างด้วย UI แบบคัสตอม
- Stocketa ถูกออกแบบโดยยึดฟีดเดียวและ การ์ดหุ้น เป็นศูนย์กลาง พร้อมลด UI chrome รอบข้างให้น้อยที่สุด
- ไม่ต้องการใช้ tab bar หรือ navigation header แบบมาตรฐาน
- โครงสร้างคือใส่ฟังก์ชันส่วนใหญ่ไว้ภายในการ์ดหุ้นบนไทม์ไลน์หน้าโฮม
- UI เกือบทั้งหมดสร้างด้วย คอมโพเนนต์คัสตอมบน SwiftUI
- ใช้ pull-to-search สำหรับค้นหาและเพิ่มหุ้นใหม่แทน pull-to-refresh
- การ์ดหุ้นแสดงข้อมูลส่วนใหญ่แบบอินไลน์ เช่น การ scrub กราฟ, swipe actions, และสถิติสำคัญ
- เมื่อแตะการ์ด การ์ดเดิมจะอยู่กับที่ แล้วการ์ดข่าวและรายละเอียดการถือครองจะปรากฏขึ้นพร้อมแอนิเมชัน โดยแกนหลักของการทำงานใช้
overlayPreferenceValueและanchorPreference - ชีตแบบคัสตอมมีตัวเลือกวันที่ หน้าจอแนะนำ พื้นหลังดาวระยิบระยับ และการไล่ระดับความโปร่งใสของพื้นหลังตามการลาก
- เมนูแอปแบบคัสตอมถูกออกแบบให้มีพื้นที่แสดงแพ็กเกจเสียเงินหรือสถานะสมาชิก และสามารถปิดได้ด้วยการแตะหรือเลื่อน
- ทั้ง swipe actions และ header ก็ทำขึ้นเอง
- แอ็กชันจะเลื่อนตามระยะปัด และถ้าเกินค่า threshold ที่กำหนดก็จะมีแอนิเมชันเข้าสู่สถานะถูกเลือก
- ปุ่ม header จะดูไร้กรอบเมื่ออยู่บนสุดของหน้า แต่เมื่อเลื่อนลงจะเปลี่ยนเป็นปุ่มแบบนุ่มนวล
- ข้อความ Stocketa จะค่อย ๆ เลื่อนหายขึ้นด้านบนตามการสกอลล์
การติดตามธุรกรรมและฟีเจอร์ของแอป
- การพัฒนาช่วงแรกเริ่มจาก scroll view ของการ์ดหุ้น กราฟ และ persistence ของฐานข้อมูล
- ตอนแรกใช้ Core Data ก่อนจะย้ายไป Firebase ในภายหลัง
- เชื่อมการเรียกและ polling ของผู้ให้บริการข้อมูลการเงิน โดยผู้ให้บริการรายแรกคือ IEX
- Stocketa ไม่ได้เก็บแค่จำนวนหุ้นที่ถือของแต่ละตัว แต่ทำระบบ ติดตามในระดับธุรกรรม
- ต้องการแสดงทั้งกำไร/ขาดทุนรวมของการซื้อขาย และกำไร/ขาดทุนรายธุรกรรม
- ตอนขายต้องรู้วิธีคำนวณต้นทุนอย่าง FIFO, LIFO ฯลฯ และต้องคำนวณว่าหุ้นที่ขายออกมาจากธุรกรรมในอดีตใด
- สำหรับ stock split ต้องรองรับทั้งการใช้ split ใหม่โดยอัตโนมัติและการใช้แบบแมนนวล โดยไม่แก้ไขธุรกรรมเก่าแบบตรง ๆ
- ฟีเจอร์ขยายออกไปทั่วทั้งแอป
- Onboarding: ใช้ flow ที่หน้าเลื่อนเข้ามาตามแกน z แทนคารูเซลทั่วไป และแนะนำคอมโพเนนต์หลักอย่างการ์ดหุ้น
- การนำเข้า TSV: นำเข้าธุรกรรมจากไฟล์ TSV ที่สร้างในสเปรดชีต และเขียนสถานะการนำเข้ากลับลงใน TSV เพื่อรองรับการซิงก์ผ่าน iCloud แล้วนำเข้าซ้ำ
- การกรอกคำสั่งซื้อ: มีฟอร์มเฉพาะหุ้นที่เน้นจำนวน ราคา และวันที่ และเมื่อเปลี่ยนวันที่ ราคาย้อนหลังของวันนั้นจะถูกใช้เป็น placeholder
- การกรอกคำสั่งขาย: รองรับ FIFO, LIFO, Average cost, Highest cost, Lowest cost และ lot แบบระบุเฉพาะ
- หน้าสมัครสมาชิก: มีข้อความแบบพารัลแลกซ์ การค่อย ๆ ชัดขึ้นตามการสกอลล์ การ์ดฟีเจอร์ที่อิงการเคลื่อนไหว และเอฟเฟกต์ fireworks เล็ก ๆ เมื่อถึงด้านล่าง
- การ์ดสมาชิก: แสดงสถานะของบัญชีที่มีการสมัครใช้งานอยู่ในรูปแบบการ์ดอินเทอร์แอ็กทีฟ พร้อมเอฟเฟกต์ starfield และ shimmer บนพื้นหลัง
- การตั้งค่าการแสดงผลการ์ดหุ้น: มีรูปแบบและการตั้งค่าการ์ดหลายแบบ พร้อมไมโครแอนิเมชันตอนสลับ
- การ์ดสถานะการถือครอง: แสดงข้อมูลสรุปรวมตามการตั้งค่าที่ด้านบนของสกอลล์หลัก
- วิดเจ็ต: มี 3 ประเภท คือ หุ้นเดี่ยว, พอร์ตโฟลิโอ, และพอร์ตโฟลิโอแบบเรียบง่าย โดยสี gradient ขนาดใหญ่จะเปลี่ยนตามผลการดำเนินงาน
- ระยะผ่อนผันของ Face ID: มองว่าเป็นสิ่งจำเป็นสำหรับแอปที่จัดการสินทรัพย์การเงิน จึงให้ปรับเวลาผ่อนผันก่อนล็อกใหม่ระหว่างการสลับแอปได้
- ชีตวันหยุดตลาด: แสดงวันตลาดปิดสำหรับบัญชีที่ถือหุ้น และต้องมีโค้ดฝั่งเซิร์ฟเวอร์เพื่อให้วิดเจ็ตจัดการแบบเดียวกัน
- ชีต feedback: แสดงปัญหาที่ทราบและฟีเจอร์ที่วางแผนไว้ พร้อมแนบโทเคนสำหรับยืนยันบัญชีเมื่อเป็นคำถามเฉพาะบัญชี
- การลบบัญชี: รองรับการลบบัญชีอย่างสมบูรณ์ภายในแอปตามข้อกำหนดอัปเดตของ App Store ในปี 2021
เรียนรู้และสร้างใหม่ไปพร้อมกับ SwiftUI
- Stocketa พัฒนาไปพร้อมกับการเรียนรู้ Swift และ SwiftUI ทำให้หลายหน้าจอและบางส่วนของแอปถูก ออกแบบใหม่และเขียนใหม่ อยู่ตลอด
- SwiftUI พัฒนาขึ้นทั้งด้านประสิทธิภาพ คอมโพเนนต์ และฟีเจอร์ตั้งแต่ iOS 13 เป็นต้นมา และใน iOS 17 ก็มีฟีเจอร์อย่าง shaders, keyframes และ scroll transitions
- SwiftUI มีประโยชน์ไม่ใช่แค่เป็นเครื่องมือเขียนโค้ด แต่ยังเป็น เครื่องมือออกแบบ ด้วย
- ดีไซเนอร์สามารถจัดเลย์เอาต์ได้รวดเร็ว
- ใส่อินเทอร์แอ็กชันได้ง่าย
- ใช้เครื่องมือเนทีฟเพื่อดูความรู้สึกของดีไซน์จริงได้
- กรณีที่ต้องใช้ UIKit มีไม่มาก
- text field แบบคัสตอมเพื่อควบคุมการป้อนข้อมูล สไตล์ และรูปแบบได้ละเอียดขึ้น
- CollectionView สำหรับลากเปลี่ยนลำดับหุ้น
- particle emitter อย่าง confetti หรือดาวบนท้องฟ้ายามคืน
UILongPressGestureRecognizerเพื่อรับตำแหน่งที่เริ่มกดค้าง
แบ็กเอนด์และการดูแล TestFlight
- ตอนแรกตั้งใจทำเป็นแอปเรียบง่ายที่ไม่มีแบ็กเอนด์หรือบัญชีผู้ใช้ แต่ไม่นานก็พบว่าต้องมี แบ็กเอนด์ของตัวเอง
- สร้าง backend proxy เพื่อไม่ต้องฝังคีย์ API ข้อมูลการเงินไว้ในแอป
- เพิ่ม rate-limiting และ throttling เพื่อกันต้นทุนที่พุ่งขึ้นจากการใช้ API เกินจำเป็น
- เพิ่ม Sign In With Apple
- แคชสถิติรายหุ้นไว้ช่วงหนึ่ง เพื่อให้หลายบัญชีที่ขอข้อมูลเดียวกันดึงข้อมูลจริงเพียงครั้งเดียว
- แบ็กเอนด์เติบโตจนมีขนาดราว 13,000 LOC บนฐาน Node/Express
- ทำงานบน Cloud Run
- รับผิดชอบด้าน authentication, caching, ข่าว, business logic หลัก, การจัดระเบียบข้อมูล, การแจ้งเตือน, วิดเจ็ต, การเชื่อมหลาย API และการ scraping บางส่วน
- การจัดการงานทำผ่าน Linear
- ใช้จัดการงาน ไอเดีย ฟีเจอร์ feedback ลูกค้า และ milestone
- TestFlight เริ่มจากอัลฟาเล็ก ๆ สำหรับเพื่อนใกล้ตัว แล้วค่อย ๆ ขยาย
- ช่วงหนึ่งเคยเชิญไปประมาณ 1,000 คน
- แม้มีผู้รอหลายพันคน แต่ไม่ขยายเพิ่มเพราะต้นทุน API และโฮสติ้ง รวมถึงภาระในการซัพพอร์ตและตอบ feedback
- feedback มีทั้งความประทับใจแรกที่ดี คำขอฟีเจอร์ และบั๊กรายงานปะปนกัน
การออกแบบและพัฒนาเว็บไซต์
- เว็บไซต์แรกเริ่มเป็น landing page แบบง่ายเพื่อดึงความสนใจและเก็บ อีเมลของผู้รอคิว
- ดีไซน์ช่วงแรกมีองค์ประกอบคลื่นที่อ้างอิงการขึ้นลงของกราฟตลาดหุ้นแบบหลวม ๆ และมีการ์ดหุ้นขนาดเล็กลอยอยู่
- มินิการ์ดมีกราฟเส้นแบบ SVG และเล่นแอนิเมชันตอนโหลดหน้า
- เอฟเฟกต์การเคลื่อนไหวอย่างนุ่มนวลในพื้นหลังทำด้วย
offset-pathCSS และ keyframe animation 2 ชุด
- โฮมเพจ
v1.0เสร็จในต้นปี 2021- มองว่ามีฟีเจอร์ในแอปมากพอที่จะนำเสนอ จึงทำโฮมเพจที่สมบูรณ์ขึ้น
- แทนที่จะใช้รูปแบบทั่วไปของเว็บแอปที่มีโทรศัพท์ในกรอบพร้อมพาดหัว ก็ลองทำให้กรอบโทรศัพท์ 3D เคลื่อนตามการสกอลล์และเล่นวิดีโอตัวอย่างแอป
- เลือกใช้ JavaScript วาดลำดับเฟรมลงบน
canvasและoffscreenCanvasแทน Lottie - ใช้ Rotato สร้าง screencast สั้น ๆ ของ Stocketa เป็นวิดีโอโทรศัพท์ 3D และลำดับเฟรม PNG
- หลังจากนั้น กระบวนการสร้าง ปรับแต่ง และอัปเดตลำดับเฟรมก็กลายเป็นเรื่องยุ่งยากมาก
- โฮมเพจ
v2.0ถูกออกแบบใหม่อีกครั้งในอีก 1 ปีต่อมา- ต้องการรายการฟีเจอร์ที่กวาดตาดูได้ง่ายแทนโมดูลยาว ๆ ที่ซ้ำไปมา เพื่อแสดงฟีเจอร์และการปรับปรุงที่มากขึ้น
- ใช้ เลย์เอาต์แบบ 2 พาเนล โดยมีกรอบอุปกรณ์ตรึงไว้ด้านขวา และรายการฟีเจอร์ที่เลื่อนได้อยู่ด้านซ้าย
- เมื่อเอาเมาส์ไปชี้ที่รายการฟีเจอร์ ภาพหน้าจอในกรอบอุปกรณ์จะเปลี่ยนตาม
- บนมือถือ เปลี่ยนส่วน header ให้เป็นคารูเซลกรอบอุปกรณ์ที่เลื่อนได้
- เพิ่ม gradient ของข้อความ hero ตามการสกอลล์, การเปลี่ยนสีไอคอน, gradient พื้นหลังเมื่อ hover และ particle emitter ของไอคอน
ข้อจำกัดที่เกิดจาก API ข้อมูลการเงิน
- คุณภาพของข้อมูลการเงินที่ Stocketa พึ่งพา ยังไม่ถึงระดับที่เปิดตัวได้จริง
- ผู้ให้บริการรายแรกอย่าง IEX มีปัญหาหลายอย่าง
- กราฟบางครั้งเก่า หรือราคาก็ไม่แม่นยำ
- สินทรัพย์ที่มีการซื้อขายน้อยบนตลาด IEX มีปัญหาหนักเป็นพิเศษ
- ไม่มีข้อมูลตลาด OTC และต้องไปทำไลเซนส์ราคาแพงกับ OTC โดยตรง
- ข้อมูลหุ้นที่จดทะเบียนใน Nasdaq ก็ถูกจำกัดมาก และยังขาดข้อมูลพื้นฐานอย่าง pre-market และ after-hours
- มีการหยุดให้ข้อมูลกองทุนรวมทั้งหมดโดยไม่แจ้งล่วงหน้า
- ผู้ให้บริการเชิงพาณิชย์อีกรายที่ใช้ภายหลังมีราคา $100 ต่อเดือน แต่กลับมีปัญหาด้านข้อมูลและความน่าเชื่อถือมากกว่าเดิม
- endpoint บางอันล้าสมัยหรือคืนค่าข้อมูลผิด
- แม้จะแจ้งปัญหาไป ก็ถูกเพิกเฉยหรือได้รับคำตอบว่าไม่มีบั๊กดังกล่าว
- ข้อมูลบางประเภทหาไม่ได้ง่ายแม้ใช้ API แบบเสียเงิน จนต้องสร้าง เอนจิน scraping ในแบ็กเอนด์เอง
- dividend yield
- earnings dates
- ข้อมูล OEF
- ข้อมูลตลาดคุณภาพสูงมีโครงสร้างราคาที่ไม่เหมาะกับนักพัฒนาแอปอิสระ
- ผู้ให้บริการข้อมูลตลาดสหรัฐรายใหญ่บางเจ้าคิดราคาข้อมูลเชิงพาณิชย์เริ่มที่ $2,000 ต่อเดือน
- ข้อมูลดัชนีหรือข้อมูล options ยังต้องจ่ายเพิ่มต่างหาก
- มีผู้ให้บริการรายหนึ่งเสนอแพ็กเกจสำหรับสตาร์ตอัปที่ $499 ต่อเดือน พร้อมค่าบริการตาม MAU แต่ก็ยังมองว่าแพงเกินความต้องการมาก
- โปรเจกต์ที่ต้องพึ่งพา API ข้อมูลการเงินมีความเสี่ยงแบบเดียวกับการเอาธุรกิจไปวางไว้บน API ของบริษัทภายนอก ซึ่งมองว่าไม่ต่างจากปัญหาการเปลี่ยนแปลง API ของ Twitter และ Reddit
เหตุผลที่หยุดเปิดตัว
- Stocketa เป็น side project มาตั้งแต่แรก ไม่ได้เริ่มต้นในฐานะธุรกิจจริง
- หากจะทำเป็นธุรกิจจริง จำเป็นต้องมีฟีเจอร์และวิธีสร้างรายได้มากกว่านี้
- อาจต้องเข้าไปในพื้นที่อย่างบริการที่ปรึกษาการเงินหรือการซื้อขายหุ้น ซึ่งเป็นสนามที่มีบริษัทยักษ์ใหญ่แข่งขันกันหนาแน่น
- ทิศทางแบบนั้นไม่สอดคล้องกับจุดเริ่มต้นที่อยากทำแอปเรียบง่ายและสวยงาม
- เหตุผลที่ยุติโดยสรุปมี 3 ข้อ
- ข้อมูล: หากจะเปิดตัวด้วยราคาสมัครสมาชิกที่สมเหตุสมผล ก็ต้องมีข้อมูลการเงินที่เชื่อถือได้ ราคาย่อมเยา และคุณภาพสูง แต่ทั้งต้นทุนและความยากในการหาเป็นอุปสรรคใหญ่
- ซัพพอร์ต: จากรูปแบบการใช้งานใน TestFlight เห็นได้ชัดว่าต้องลงทุนมากกับ customer support, อีเมล, การบำรุงรักษา และการพัฒนาฟีเจอร์ต่อเนื่อง
- เวลา: เลือกทุ่มโฟกัสไปที่ Rewind AI มากกว่า และ Stocketa ก็กินเวลาช่วงกลางคืน วันหยุดสุดสัปดาห์ ไปจนถึงเวลาที่ใช้เขียนบล็อกมาหลายปี
- เป้าหมายเดิมในการเรียนรู้ Swift และ SwiftUI ถือว่าบรรลุแล้ว
- แม้จะไม่ได้เปิดตัว แต่ก็ได้เรียนรู้การพัฒนา native iOS อย่างมาก
- ความรู้ด้าน SwiftUI ที่ได้จาก Stocketa ช่วยงานที่ Rewind AI อย่างมาก
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
การที่โปรเจกต์ที่ทำมาหลายปีไม่ได้ถูกใช้งานจริง บางทีก็รู้สึกเหมือนเป็น เหรียญตราเกียรติยศ อยู่เหมือนกัน แม้มันจะไม่ใช่เหรียญตราที่ฉลาดนัก แต่สำหรับนักพัฒนาแบบผมที่หมกมุ่นในทางที่ดีและถูกดูดเข้าไปจนหมดตัว มันแทบจะเป็นบทเรียนที่จำเป็นด้วยซ้ำ
เวลาพูดถึงประสบการณ์เก่าๆ กับความเจ็บปวดที่มาจากตรงนั้น ผมรู้สึกว่าคนฟังมักจะอึ้งไป ถ้าไม่เคยทุ่มเทกับอะไรสักอย่างเกินวันละ 10 ชั่วโมงต่อเนื่องเกิน 1 ปี ก็คงยากที่จะเข้าใจความรู้สึกของการเทเวลาหลายพันชั่วโมงลงไปแล้วไม่ได้ผลลัพธ์อะไรเลย
ผมมีโปรเจกต์ที่สำเร็จมากมาย และตอนนี้ก็ยังไปได้ดี แต่โปรเจกต์ที่กินเวลาหลายปีเหล่านั้นย้อนกลับไปแก้ไม่ได้แล้ว มันอาจจำเป็นต่อการเรียนรู้ แต่พอนึกถึงก็ยังเศร้าและวังเวงอยู่ดี
แต่สิ่งที่ได้มาแทนคือทักษะที่ทำให้เป็นโปรแกรมเมอร์ที่ดีขึ้นมาก และผมก็เริ่มชอบ Swift ถ้าเป็นตอนนี้ ด้วยความก้าวหน้าของเครื่องมือพัฒนาและ API ของ Apple ในช่วง 7 ปีที่ผ่านมา ผมคิดว่าน่าจะสร้างแอปนั้นใหม่ทั้งหมดตั้งแต่ศูนย์ได้ภายในสุดสัปดาห์เดียว
โปรเจกต์แบบนี้ควรค่าแก่การระลึกถึง การเขียนโปรแกรมอาจเป็นศิลปะได้ และศิลปะในฐานะทางออกของการสร้างสรรค์ก็อาจถูกสร้างขึ้นเพื่อตัวเราเองเพียงคนเดียวได้
การคิดยึดผลลัพธ์เป็นศูนย์กลาง ที่เอาความรู้ที่ได้ทีหลังมาย้อนทรมานตัวเองกับโปรเจกต์ในอดีตนั้นไม่ค่อยมีประโยชน์ โปรเจกต์และธุรกิจส่วนใหญ่ล้มเหลว นั่นคือความจริง
ผมนึกถึงบทความของอดีตคนในวงการการเงินคนหนึ่งที่เขียนว่า “ไม่มีใครถูกไล่ออกเพราะบังเอิญทำเงินได้จากดีลแย่ๆ” ในวัฒนธรรมที่เน้นผลลัพธ์ เรามักลืมไปง่ายๆ ว่าสิ่งเดียวที่เราควบคุมได้จริงคือ กระบวนการ
ได้บทเรียนมีค่าอย่างการรู้ว่าเมื่อไรควรหยุดก็จริง แต่มันเป็นคาบเรียนที่ยาวนานเหลือเกิน จนถึงตอนนี้ผมก็ยังไม่กล้านึกย้อนกลับไปให้ชัดๆ
ผมสงสัยว่าอยากแนะนำไหมว่าอย่าเริ่มโปรเจกต์ที่ยาวเกิน 1 ปี ถ้าไม่มั่นใจว่าจะไม่เสียใจแม้ไม่มีใครใช้เลย
เป็นบทความที่ยอดเยี่ยม แต่บทสรุปรู้สึกเศร้า มีแอปมากมายที่ผมอยากให้มีเวอร์ชันแบบ “ไม่มีอะไรเกินจำเป็น” แบบนี้ และปริมาณงานที่ใส่ลงไปในโปรเจกต์นี้ก็น่าทึ่งมาก
ผมเคยปล่อยแอป iOS ที่เรียบง่ายกว่านี้ และโตจากทราฟฟิกธรรมชาติจนมีผู้ใช้แอ็กทีฟต่อวันประมาณ 1,000 คน แต่สุดท้ายก็ปิดไป ใส่ in-app purchase สำหรับลบโฆษณาไว้รายการเดียว ราคา $1.99 หรือ $2.99 ทำเงินได้ราวเดือนละ $70 พร้อมกับต้องจัดการ bug report
ตอนนั้น SwiftUI ยังไม่สุกงอมพอ เลยต้องใช้ UIKit และผมก็เจอ edge case ที่แก้ยากอยู่เรื่อยๆ
จุดแตกหักคือ Google กล่าวหาว่าผมคลิกโฆษณาของตัวเอง แล้วหยุดเสิร์ฟโฆษณา รายได้ทั้งหมดแทบจะหายไป และผมก็ได้ตระหนักว่าต่อให้ตั้งใจทำมันแค่ไหน สุดท้ายก็ขึ้นอยู่กับอารมณ์แปรปรวนของบริษัทเทคยักษ์ใหญ่
Apple หัก 30% จาก in-app purchase ทั้งหมด ส่วนรายได้โฆษณาก็เป็นเงินเล็กน้อย แต่ Google สามารถปิดได้โดยไม่มีเหตุผล และไม่มีช่องทางอุทธรณ์ ผมไม่ได้ตั้งใจจะทำเงินก้อนโต แต่ก็ต้องมีเหตุผลสักอย่างในการใช้เวลาและพลังงานกับมัน และผมไม่สามารถหาเหตุผลรองรับต่อไปได้แล้ว
ผมไม่เข้าใจว่าทำไมไม่ให้ developer ลงทะเบียน อุปกรณ์ที่ยกเว้นรายได้, ช่วง IP หรือรายการตำแหน่งที่ตั้งได้ สุดท้ายเราก็ต้องใช้แอปของตัวเองอยู่แล้ว และหลายครั้งเวลาเลื่อนหน้าจอ แทบเป็นไปไม่ได้เลยที่จะไม่เผลอกดโฆษณาโดยบังเอิญ
การทดสอบในสภาพแวดล้อมจริงก็สำคัญ และยังมีความเป็นไปได้เล็กๆ ที่โฆษณานั้นน่าสนใจจริงๆ จนเราในฐานะลูกค้าที่เป็นไปได้คลิกอย่างถูกต้องตามปกติ แต่แนวทางตอนนี้แทบจะหมายความว่าอย่าใช้แอปของตัวเอง
ผมไม่รู้ว่านโยบายที่โง่โดยพื้นฐานแบบนี้เป็นประโยชน์กับใคร นอกจากนักพัฒนาหรือผู้จัดการของ Google ที่ดื้อจะยึดมันไว้ มันยากขนาดนั้นจริงๆ หรือที่จะจัดการเรื่องนี้ให้ดีขึ้นสักนิด
นักดนตรีในห้องนอนที่ไม่เคยขึ้นแสดงหรือออกอัลบั้มเลยตลอด 20 ปี นักกีฬาวัยเด็กที่ไม่ได้แตะลูกบอลอีกหลังอายุ 18 นักวิ่งที่ไม่ลงแข่ง ปัญญาชนที่ไม่สอนใคร ก็อาจคิดในทำนองเดียวกันได้
ถ้ายึดสมมติฐานเดียวกันว่า “ผลลัพธ์ภายนอก = คุณค่า” มันอาจขยายไปถึงมนุษย์ที่ใช้ชีวิตมาหลายสิบปีแต่ไม่เคยมีลูกด้วยซ้ำ นั่นไม่ใช่ความเชื่อของผม แค่หมายความว่าตามตรรกะแล้วมันไหลไปทางนั้นได้
แต่การตัดสินแบบนั้นเป็นสิ่งประกอบสร้างที่มนุษย์สร้างขึ้น และดูเหมือนเงาสะท้อนของคำสั่งทางชีววิทยาที่อยากส่ง “ลูกของเรา” ที่ฟูมฟักมานานออกสู่โลก เราถามว่าทำไมสิ่งเหล่านั้นจึงไม่ควรมีชีวิตของมันเอง และหวังให้มันสร้างผลงานต่อไปด้วยตัวมันเอง พร้อมเพิ่มเส้นด้ายบางเส้นให้อนาคต
การทำตามคำสั่งนั้นเป็นจุดสูงสุดของศีลธรรม จริยธรรม หรือความสุขหรือไม่ สำหรับบางคนคงใช่ และผมก็ไม่อยากตัดสิน แต่สำหรับบางคน กลับประหลาดที่มันไม่ใช่
สงสัยว่าเขาคิดจะขายโปรเจกต์นี้ไหม แนวคิดถูกใจผม และดูเหมือนจะมีลูกค้าที่สนใจอยู่ด้วย แต่เขาดูไม่อยากรับภาระด้านซัพพอร์ตและการทำเป็นธุรกิจ
ผมทำตัวติดตามสินทรัพย์ (https://jch.app) มาได้ประมาณ 1 ปีแล้ว แต่ฟีเจอร์หรือประสบการณ์ผู้ใช้ยังห่างไกลมาก
เป็นงานที่มหาศาล และบันทึกการเดินทางอย่างลึกซึ้งก็ดีมาก ผมยังตั้งตารอดูด้วยว่า rewind.ai จะมีอะไรออกมาต่อไป
ไม่ได้ต่างอะไรมากจากการที่ผู้คนจำนวนมากทุ่มเวลาไม่รู้จบให้กับโปรเจกต์มากมายที่ไม่ได้มีความหมายใหญ่โตกับใครอื่น เช่น การดัดแปลงจักรยานหรือเล่นกับรถไฟจำลอง
เพียงแต่แอปมีข้อแตกต่างตรงที่เผยแพร่ จัดทำเอกสาร และเก็บรักษาไว้ได้ง่ายแบบนี้ แต่ “เวลาที่ใช้ไปกับการตัดและเชื่อมชิ้นส่วนจักรยานแปลก ๆ” ทำแบบนั้นได้ยาก เว้นแต่จะอัปโหลดทั้งหมดลง YouTube
แน่นอนว่าหลายคนก็ทำแบบนั้น และมันก็มีความหมายอยู่บ้าง แต่เมื่อพยายามเปลี่ยนงานอดิเรกและการแสวงหาส่วนตัวให้กลายเป็นผลิตภัณฑ์ที่มีเป้าหมายอื่นนอกเหนือจากตัวมันเอง บางทีก็อาจพลาดแก่นสำคัญไปเล็กน้อย
ไม่ได้หมายความว่าบทความแบบนี้ผิด ดูไม่ได้บ่นหรือโกรธอะไร และเหมือนที่พูดไว้ตอนต้น คือให้ความรู้สึกว่า “อยากบันทึกมันไว้ที่ไหนสักแห่งในรูปแบบใดรูปแบบหนึ่ง” GitHub ส่วนใหญ่ของผมก็เป็นแบบนั้นเหมือนกัน
การปรับเกณฑ์ประเมินอย่างรีบร้อน แบบนี้อาจไม่ค่อยมีประโยชน์ เพราะมันทำให้ผลลัพธ์จริงพร่าเลือน ในกรณีนี้ผู้เขียนอาจรู้สึกอับอายกับความพยายามที่ “สูญเปล่า” ได้ง่าย แต่ปฏิกิริยาที่เหมาะกว่าน่าจะเป็นความขอบคุณต่อสิ่งที่ได้เรียนรู้
สิ่งที่ได้เรียนรู้จากโปรเจกต์แบบนี้มหาศาลมาก
สิ่งที่น่ากลัวของบทความนี้คือผมเห็นตัวเองอยู่ในนั้นมากเกินไป หมกมุ่นลึกกับการสร้างผลิตภัณฑ์ที่ยอดเยี่ยม จมอยู่กับอัตลักษณ์ของความเป็นช่างฝีมือ และรู้สึกต่อต้านแนวทางที่ “ไร้วิญญาณ” อย่าง MVP ที่ทำเร็ว ๆ แบบหยาบ ๆ กับการทดสอบตลาดซ้ำ ๆ
ถ้าเคยเข้าไปในซับเรดดิต r/SaaS จะเห็นว่านั่นคือสิ่งตรงข้ามกับสิ่งที่ผมสนุกในฐานะนักพัฒนาซอฟต์แวร์เลย
แต่ผมก็รู้เหมือนกันว่าถ้าเปลี่ยนกรอบคิดเรื่องการทดสอบตลาดและการทำซ้ำแบบเร็ว ๆ หยาบ ๆ ได้ มันกลับจะเป็นฐานที่ดีกว่าในการวางใจและโฟกัสกับงานฝีมือ
เข้าใจเลย ผมเองก็ยังทำ แบ็กเอนด์ธนาคาร อยู่เหมือนกัน ทำมา 5 ปีแล้ว ครอบคลุมตั้งแต่ core, บัญชี, ลูกค้า, บัญชีเงินฝาก, การชำระเงิน (SEPA และบัตร), การแจ้งเตือน (คล้าย ServiceNow), การคัดกรองมาตรการคว่ำบาตร, เอนจินความเสี่ยง/มอนิเตอร์ริ่ง, event flow ไปจนถึง reporting
เริ่มสงสัยแล้วว่าผมบ้าหรือโง่กันแน่ที่ไปรับงานยักษ์แบบนี้ไว้ ยังไม่ได้ออกแบบ landing page ด้วยซ้ำ และโค้ดก็ประมาณ 150,000 บรรทัด แล้ว
แม้แพลตฟอร์มเดิมจะมีบั๊ก ข้อจำกัด และปัญหาด้านความปลอดภัยมากมาย แต่การสร้างความไว้วางใจมากพอจะโน้มน้าวให้ลูกค้าย้ายมาใช้ แพลตฟอร์ม core banking ของเรา ใช้เวลานานกว่า 5 ปีมาก
แต่พอแอปมือถือเริ่มสำคัญ ก็เริ่มทำ native app ด้วย และนั่นมันเกินตัวไปมาก สุดท้ายก็ burnout และถึงขั้นล้มละลาย เลยไม่อยากแนะนำ โปรเจกต์ขนาดมหึมา แบบนี้
ได้เรียนรู้เยอะก็จริง แต่ความสูญเปล่าไม่คุ้มค่า เวลาเป็นสิ่งสำคัญเกินกว่าจะเอาไปสร้างของจำนวนมากขึ้นใหม่แบบนั้น ตอนนี้ผมทำแค่โปรเจกต์ “เล็ก” ที่ใช้เวลาสูงสุด 6–12 เดือนเท่านั้น
แล้วก็สงสัยว่ามีโอกาสเป็นโอเพนซอร์สไหม
ถ้ายังปล่อยเวอร์ชันพื้นฐานไม่ได้แม้ตัดทุกอย่างที่อยากเพิ่มออกไปแล้ว ก็ควรพิจารณาพักไว้สักระยะ
ตลอดกว่า 20 ปีที่ผ่านมา ผมสร้างโปรเจกต์และผลิตภัณฑ์มามากมาย และมี 2–3 ตัวที่เติบโตอย่างมาก ตัวอื่น ๆ มีผู้ใช้หลักพัน แต่ไม่มีรายได้ต่อเนื่อง
ตัวหนึ่งที่กลายเป็นธุรกิจทำกำไรได้ เปิดตัวด้วยเวอร์ชันที่ “สร้างในสุดสัปดาห์” แล้วค่อย ๆ สะสมต่อยอดมาตลอด 7 ปี
สภาวะที่คุ้นเคยอาจเป็นกับดักที่ทำให้ยังหาเรื่องทำก่อนเปิดตัวต่อไปเรื่อย ๆ ดังนั้นการปรับกรอบความคิดในใจใหม่อาจเป็นเรื่องดี
เมื่อเร็ว ๆ นี้ผมอ่านเจอว่า Leonardo DaVinci เป็นคน ผัดวันประกันพรุ่ง ตัวยง และมีโปรเจกต์ที่ทำไม่เสร็จอยู่เยอะมาก
ผมเคยชื่นชมเขามาตลอดในฐานะคนที่ประสบความสำเร็จในหลายสาขา แต่พอรู้เรื่องนั้น มุมมองต่อการผัดวันประกันพรุ่งก็เปลี่ยนไปว่าเป็นส่วนหนึ่งของพวกเราที่เป็นคนสร้างสรรค์
จะมองว่าเป็นความล้มเหลวก็ได้ แต่ก็อาจตีความใหม่ได้ว่าเป็นส่วนหนึ่งของกระบวนการ สุดท้ายแล้วเราสนุกกับการสร้างบางสิ่ง
เขาแทบจะเหมือนรับคำแนะนำทั่วไปที่ว่า “ทำ MVP, ปล่อยเร็ว ๆ, แล้วทำซ้ำ” มา แล้วทำตรงกันข้ามอย่างเป๊ะ
เป็นบทความที่ยอดเยี่ยมเกี่ยวกับไซด์โปรเจกต์ที่ดูเท่มาก อ่านอย่างสนใจแล้วไปเจอ rewind.ai ซึ่งก็ดูดีเหมือนกัน
สำหรับสิ่งที่อาจล่วงล้ำความเป็นส่วนตัวได้อย่างการบันทึกหน้าจอและเสียงแบบอัตโนมัติต่อเนื่อง ความเป็นส่วนตัวจึงเป็นหัวใจสำคัญ พออ่านส่วน “Privacy first” แล้วก็เกิดคำถามขึ้นมา
มีข้อความว่า “เข้ารหัสข้อมูลของคุณด้วย FileVault Apple FileVault ทำงานร่วมกับ Rewind เมื่อเปิดใช้งาน ข้อมูลของคุณจะถูกเข้ารหัส” ตรงนี้ Rewind ทำอะไรบางอย่างให้ Apple FileVault “ทำงานร่วมกับ Rewind” หรือเปล่า?
หรือหมายถึง การเข้ารหัสดิสก์ แบบทั่วไปที่ใช้กับทุกอย่างอยู่แล้ว? ถามจริง ๆ นะ ผมอยากใช้ Rewind แต่ถ้อยคำนี้อาจถูกตีความได้ว่าเป็นการแต่งคำให้ดูดีเกินจริง
ข้อความที่ว่า “เฉพาะข้อมูลแบบข้อความที่เกี่ยวข้องเท่านั้นที่จะถูกส่งไปยังคลาวด์ และจะถูกเข้ารหัสระหว่างการส่ง” ก็ให้ความรู้สึกคล้ายกัน “เข้ารหัสระหว่างการส่ง” หมายถึงการเข้ารหัส TLS มาตรฐานหรือเปล่า? Rewind ดูดี แต่ต้องเชื่อถือได้
“ไม่จำเป็นต้องมีการผสานรวมกับคลาวด์ ทุกอย่างทำงานโดยอัตโนมัติ โดยไม่ต้องเชื่อมต่อกับบริการต่าง ๆ อย่าง Gmail, Dropbox, Slack”
แต่เมื่อดูรายละเอียดนโยบายความเป็นส่วนตัวอย่างเป็นทางการที่ https://www.rewind.ai/privacy ก็เขียนไว้ว่า
“[รายการที่เก็บรวบรวม:] ข้อมูลที่ OpenAI สร้างขึ้น ในฐานะส่วนหนึ่งของการผสานรวม OpenAI ของ Rewind AI เราอาจเก็บรวบรวมเอาต์พุตที่ OpenAI สร้างขึ้นด้วย เช่น สรุปการถอดเสียงจากบันทึกเสียง และข้อมูลอื่น ๆ ที่การผสานรวม OpenAI สร้างขึ้น”
ถ้าอย่างนั้น แม้จะบอกว่า “ไม่จำเป็นต้องมีการผสานรวมกับคลาวด์” แต่เสียงของผมถูก แชร์กับ OpenAI หรือเปล่า?
อีกทั้งที่ https://www.rewind.ai/privacy-first ยังเขียนว่า “เกิดอะไรขึ้นเมื่อคุณค้นหาใน Rewind? ข้อมูลการบันทึกทั้งหมดจะอยู่ในเครื่อง”
ไม่รู้ว่าอันไหนกันแน่ ผมอยากเชื่อใจ Rewind แต่ความไม่สอดคล้องกันในคำอธิบายว่าข้อมูลผู้ใช้ถูกจัดการอย่างไรทำให้ลังเล