บทความ
การพัฒนาด้วย AI
- Anthropic
Effective Context Engineering สำหรับ AI Agent
ขยับจาก prompt engineering สู่การคัด token ที่ให้สัญญาณสูงสุด พร้อม compaction, การจดโน้ตแบบมีโครงสร้าง และสถาปัตยกรรม subagent
อ่าน → - Thoughtworks
Harness Engineering: ออกแบบ “โครงครอบ” รอบ model
ชั้นถัดจาก context — กรอบ Guides (feedforward) กับ Sensors (feedback) นิยาม harness ว่า “ทุกอย่างใน agent ยกเว้นตัว model”
อ่าน → - บทความต้นฉบับของ Kaen
Loop Engineering: ออกแบบวงวนให้ AI ทำงานเองจนจบ
ชั้นบนสุดของซีรีส์ context→harness→loop — วงจร reason → act → observe, เงื่อนไขจบ, verifier และคำเตือนเรื่องปล่อยให้วนโดยไม่มีคนดู
อ่าน → - Thoughtworks
Structured-Prompt-Driven Development (SPDD)
ปฏิบัติต่อ prompt เป็นชิ้นงานชั้นหนึ่งที่เก็บคู่กับ code ใน version control พร้อมตัวอย่าง end-to-end ด้วย openspdd และ REASONS Canvas
อ่าน → - Thoughtworks
ทำความเข้าใจ Spec-Driven Development
Birgitta Böckeler ลองใช้เครื่องมือ SDD สามตัว (Kiro, spec-kit, Tessl) แล้วถอดความว่า “การพัฒนาแบบขับเคลื่อนด้วย spec” หมายถึงอะไร
อ่าน → - Thoughtworks
ดัน AI autonomy ในการเขียน code ได้ไกลแค่ไหน?
ปล่อยให้ Claude สร้าง app Spring Boot แบบ end-to-end เกือบไม่แทรกแซง แล้วพบว่า agent สร้าง scope creep และอ้างว่า test ผ่านทั้งที่ไม่ผ่าน
อ่าน → - บทความต้นฉบับของ Kaen
Ubiquitous Language คือ Context ที่ดีที่สุดที่ให้ AI Agent ได้
ทำไม glossary ของ ubiquitous language ควรเป็น context file แรกที่ป้อนให้ coding agent ก่อน spec เสียอีก พร้อมตัวอย่างแปลงเป็น CLAUDE.md
อ่าน →
สถาปัตยกรรมซอฟต์แวร์
- Robert C. Martin
The Clean Architecture
สังเคราะห์ Hexagonal และ Onion เป็นวงกลมซ้อนกัน (Entities → Use Cases → Interface Adapters → Frameworks) ภายใต้ Dependency Rule
อ่าน → - บทความต้นฉบับของ Kaen
MVC + Service Layer vs. Clean Architecture + DDD
เทียบสองสถาปัตยกรรมบน domain Order เดียวกันทีละ scenario ทั้งราคาที่จ่ายและสิ่งที่ได้กลับมา พร้อมแบบประเมินและบันไดย้ายทีละขั้นที่หยุดค้างได้
อ่าน → - บทความต้นฉบับของ Kaen
Aggregate ควรใหญ่แค่ไหน — ให้ concurrency เป็นคนตอบ
สอง context แก้คนละบรรทัดของออเดอร์ใบเดียวกัน แล้วฝั่งที่ save ทีหลังถูกปฏิเสธ · รันจริงบน EF Core กับ file SQLite แล้วรายงานเป็นจำนวน conflict จำนวนรายการใน ex.Entries และจำนวนแถวที่โหลด ทั้งขอบอ้วนและขอบที่แยกแล้ว
อ่าน → - บทความต้นฉบับของ Kaen
Modular Monolith, Vertical Slice, Clean: สามคำที่ไม่ได้แข่งกัน
สามคำนี้ตอบคนละคำถาม จึงเปิดพร้อมกันได้ทั้งแปดชุด พร้อมเครื่องประกอบสามแกนที่กดเล่นได้ จุดที่มันชนกันจริง และวิธีเลือกทีละ module
อ่าน → - Alistair Cockburn
Hexagonal Architecture (Ports & Adapters)
กันแกน application ออกจากโลกภายนอก (UI, ฐานข้อมูล, test) ด้วย port และ adapter — เปลือกมาตรฐานสำหรับครอบ domain model แบบ DDD
อ่าน → - Martin Fowler
“Event-Driven” หมายความว่าอะไรกันแน่?
แยกสี่ pattern ที่มักถูกเหมารวม: Event Notification, Event-Carried State Transfer, Event Sourcing และ CQRS พร้อมข้อดีข้อเสีย
อ่าน → - Martin Fowler
Microservice Trade-Offs
ชั่งข้อดี (ขอบเขต module ชัด, deploy อิสระ, เลือกเทคโนโลยีได้) กับต้นทุน (ความซับซ้อนแบบกระจาย, eventual consistency, งาน ops) เทียบ monolith
อ่าน →
การทดสอบและคุณภาพ
- บทความต้นฉบับของ Kaen
test ที่ไซต์นี้ยกเป็นตัวอย่างที่ดี จับอะไรไม่ได้บ้าง
แก้ code ของโดเมน Order ให้ผิดทีละจุดแล้วรันชุด test เดิมซ้ำทุกครั้ง · ชุดที่คอร์สยกเป็นตัวอย่างที่ดีปล่อยความผิดพลาดแบบไหนผ่านบ้าง ตัวไหนคือช่องว่างจริง และ test ที่ปิดมันได้ทีละตัว
อ่าน → - บทความต้นฉบับของ Kaen
ภาษาไทยทำให้ code พังคนละชั้นกันสี่ชั้น
ชั้น byte ที่ลบอักขระผิดวิธีแล้วกิน เ กับ ซ ไปด้วย · ชั้น code point ที่ทำให้ \b ของ regex มองไม่เห็นคำไทย · ชั้นคำที่ทำให้เว็บนี้เองค้นคำที่อยู่ในหน้าส่วนใหญ่ของไซต์แล้วได้ศูนย์ · และชั้น culture ที่ทำให้ปีเดียวกันต่างกัน 543
อ่าน →
ข้อมูลและประสิทธิภาพ
- บทความต้นฉบับของ Kaen
ทำไม index ที่คุณเพิ่งเพิ่มถึงไม่ถูกใช้
เปิดแผนจริงจาก SQLite ทีละรูปร่างของ query — function คร่อม column, ลำดับ column ใน composite index, LIKE กับ collation และ ORDER BY ที่ index เรียงให้ไม่ได้
อ่าน → - บทความต้นฉบับของ Kaen
กลไก transaction ของ PostgreSQL — MVCC กับ WAL เป็นเรื่องเดียวกัน
รัน PostgreSQL ตัวจริงสองคอนเนกชันแล้วนับว่าแต่ละระดับ isolation ยอมให้เกิดอะไร · Repeatable Read กัน lost update ได้ทั้งที่เอกสารเรียกมันว่า snapshot isolation แล้วตามราคาของ MVCC ไปดูว่ามันโผล่ที่ WAL ตรงไหน
อ่าน → - บทความต้นฉบับของ Kaen
UNIQUE ที่ยอมให้ซ้ำ — soft delete กับ NULL ที่ไม่เท่ากับตัวเอง
UNIQUE (email, deleted_at) รับอีเมลเดียวกันซ้ำได้สามแถวรวด โดยไม่มี error เพราะ NULL ไม่เท่ากับ NULL ในสายตาของ index · วัดสองทางแก้บน PostgreSQL 18 แล้วพบว่าทางที่อ่านแล้วสะอาดกว่า เปิดรูใหม่ตรงการลบทั้งชุดในคำสั่งเดียว
อ่าน → - บทความต้นฉบับของ Kaen
ขนาด transaction ที่ถูกที่สุดไม่ใช่ใหญ่ที่สุด
รันงานเดียวกันเป๊ะบน PostgreSQL กับ SQLite ทุกขนาด transaction แล้ววัด WAL ด้วยหน่วยของแต่ละตัว · SQLite ลงอย่างเดียวจริง แต่เส้นโค้งของ PostgreSQL เป็นรูปตัว U เพราะ HOT update ตายหมดเมื่อ transaction ยาวเกินไป
อ่าน → - บทความต้นฉบับของ Kaen
code ที่เขียนเพื่อดูแถวที่ลบแล้ว ทำให้เห็นข้อมูลของลูกค้ารายอื่นไปด้วย
`IgnoreQueryFilters()` เป็นสวิตช์ระดับ query ไม่ใช่ระดับตัวกรอง · รัน EF Core 10 ตัวจริงบนคลังที่มีสอง tenant แล้วนับว่าแต่ละท่าคืนแถวของใครมาบ้าง ทั้งใน query ตรง ๆ ใน query ที่ไม่ได้เอ่ยชื่อตารางนั้นเลย และในรายงานที่นับอย่างเดียว
อ่าน → - บทความต้นฉบับของ Kaen
query ตัวเดียวกัน ราคาต่างกันสองพันเท่า เพราะค่าเดินมาถึงเอนจินคนละทาง
keyset pagination ที่เขียนด้วยท่า OR เป็นท่าเดียวที่ LINQ เขียนได้ และมันเร็วตอนคุณวางค่าลงไปทดสอบเอง แต่ช้าตอนแอปส่งค่าเป็น parameter · นับ opcode ทีละท่าบนตาราง 200,000 แถว แล้ววัดซ้ำบน PostgreSQL ด้วยหน่วยของมันเอง
อ่าน → - บทความต้นฉบับของ Kaen
NULL แถวเดียวทำให้ NOT IN คืนศูนย์แถว และท่าที่ตอบผิดคือท่าที่จ่ายน้อยที่สุด
query ที่ถามว่าออเดอร์ไหนยกเลิกแล้วแต่ยังไม่ได้คืนเงิน ตอบว่าไม่มีเลย ทั้งที่มีอยู่สามพันกว่ารายการ เพราะตาราง refunds มีแถวที่ order_id เป็น NULL อยู่แถวเดียว · หน้านี้วัดทั้ง SQLite และ PostgreSQL แล้วถาม EF Core ว่า LINQ ที่เขียนกันทุกวันเดินเข้าช่องนี้หรือไม่
อ่าน → - บทความต้นฉบับของ Kaen
ชื่อไทย 200 ชื่อ เรียง 13 ทาง ได้ 2 ลำดับ และ 188 ตำแหน่งไม่ตรงกัน
`ORDER BY name` บนชื่อไทยให้คำตอบสองแบบ ต่างกัน 188 จาก 200 ตำแหน่ง · วัดสิบสามทางบน SQLite, PostgreSQL 18 และ .NET บนคลังชื่อใบเดียวกัน แล้วพบว่าสิ่งที่ตัดสินลำดับไม่ใช่เอนจิน แต่เป็น base image ของคอนเทนเนอร์ที่ไม่มีใครเลือกเพราะเรื่องภาษาไทย
อ่าน → - บทความต้นฉบับของ Kaen
migration บรรทัดเดียวที่ไม่ได้แตะข้อมูลสักหน้า แต่หยุด query ทุกตัวที่ตามมา
reader ที่เปิด transaction ค้างไว้หนึ่งตัว บวก ALTER TABLE ที่ rewrite ศูนย์หน้าหนึ่งบรรทัด เท่ากับ query แปดตัวที่ไม่ได้รันเลย · วัดความยาวคิวจาก pg_locks บน PostgreSQL 18.6 แล้วตอบว่า lock_timeout เปลี่ยนอะไร
อ่าน →
ภาษาและ platform
- บทความต้นฉบับของ Kaen
C# 8 ถึง 14: อะไรเปลี่ยนการออกแบบ อะไรแค่เปลี่ยนการพิมพ์
เจ็ด version 94 feature แต่มีแค่สิบเจ็ดตัวที่เปลี่ยนสิ่งที่ compiler พิสูจน์หรือบังคับให้ได้ · คลังครบทุกตัวพร้อม code ที่ compile จริงทั้งทิศผ่านและทิศปฏิเสธ
อ่าน → - บทความต้นฉบับของ Kaen
เปิด analyzer ครบทุกตัวแล้ว await ใน foreach ก็ยังไม่มีใครเตือน
เปิดสวิตช์ analyzer ทุกตัวที่ .NET SDK ยอมให้ตั้ง แล้วนับสิ่งที่มันพูด ผลคือ 17 diagnostic ตกลงบน code ที่ await อยู่ในตัววน และไม่มีตัวไหนพูดถึงตัววนเลย · จากนั้นวัดต่อว่า Task.WhenAll ที่ทุกคนบอกให้ใช้ เปลี่ยนพฤติกรรมของ exception อย่างไร และมันทำ code พังในสามกรณีไหน
อ่าน → - บทความต้นฉบับของ Kaen
file .rs เดิมทุก byte เปลี่ยนแค่บรรทัด edition แล้วห้าในหกโปรแกรมให้ผลคนละอย่าง
edition 2021 เปลี่ยนให้ closure จับทีละ field แทนที่จะจับทั้งตัวแปร · เอาซอร์สหก file ชุดเดียวกันไปคอมไพล์สองครั้ง ต่างกันแค่บรรทัดเดียวใน manifest แล้วนับ สามตัวแดงเป็นเขียว หนึ่งตัวเขียวเป็นแดงด้วย E0277 และหนึ่งตัวคอมไพล์ผ่านทั้งคู่แต่พิมพ์ลำดับ drop คนละแบบ
อ่าน → - บทความต้นฉบับของ Kaen
เอกสารสองหน้าของ Epic ให้คำตอบคนละอย่างเรื่อง TObjectPtr และทั้งคู่ถูก
หน้าหนึ่งบอกว่าเลือก TObjectPtr หรือ raw pointer ก็ได้ ไม่กระทบ shipped product · อีกหน้าบอกว่าถ้าไม่แปลงให้ครบ GC อาจคืนหน่วยความจำของ UObject เร็วเกินไป · ทั้งคู่จริง และสิ่งที่ตัดสินว่าประโยคไหนใช้กับคุณคือสวิตช์สองบรรทัดใน DefaultEngine.ini
อ่าน → - บทความต้นฉบับของ Kaen
คีย์เวิร์ดเดียวที่หายไป เปลี่ยนการคัดลอกจากศูนย์เป็นหมื่นหก
move constructor ที่ไม่ได้ประกาศ noexcept ทำให้ std::vector เลือกคัดลอกแทนการย้ายทุกครั้งที่ขยาย · จำนวนครั้งที่ขยายและความจุปลายทางเท่ากันเป๊ะทั้งสองรอบ สิ่งที่ต่างคือตอนขยายมันเลือกทำอะไร · แล้วเปิดสวิตช์ warning ที่แรงที่สุดเท่าที่คอมไพเลอร์ยอมให้ตั้ง ก็ไม่มี diagnostic ตัวไหนพูดถึงต้นทุนนั้น
อ่าน → - บทความต้นฉบับของ Kaen
สองบรรทัดที่เหมือนกันทุกตัวอักษร บรรทัดหนึ่งจอง อีกบรรทัดไม่จอง
Go มีเพดานสามตัวที่ตัดสินว่าของจะอยู่บน stack หรือหนีไป heap ไม่ใช่ตัวเดียว แต่ละบานขยับด้วยหนึ่งไบต์จากศูนย์เป็นหนึ่ง · แล้ว go build -gcflags=-m ซึ่งเป็นเครื่องมือที่คนใช้ตอบคำถามนี้ พูดประโยค does not escape กับทั้งสองฝั่งของบานที่สาม และผิดหนึ่งฝั่ง
อ่าน → - บทความต้นฉบับของ Kaen
สลับสองบรรทัดใน pom.xml แล้ว jar บน classpath เปลี่ยนรุ่น
library ตัวเดียวถูกขอสองรุ่นจากสองเส้นทาง Maven เลือกตัวที่ใกล้ที่สุดแล้วตัดสินการเสมอด้วยลำดับที่พิมพ์ ส่วน Gradle เลือกตัวที่สูงที่สุด · วัดสิบทรงบน resolver ตัวจริงทั้งสองฝั่ง แล้วพบว่าบรรทัดที่คุณเขียนเองเพื่อสั่งมัน ฝั่งหนึ่งเชื่อฟัง อีกฝั่งเขียนทับ และ mvn compile คายคำเตือนเรื่องนี้ศูนย์บรรทัด
อ่าน → - บทความต้นฉบับของ Kaen
ท่าโจมตี JWT ที่ทุกคนท่องจำ ตายหมดแล้ว ส่วนรูที่ยังเปิดคือข้อที่ไม่มีใครสั่งให้ตรวจ
ยิง token แปดใบเข้า verifier เก้าทรงบนสาม library ที่ JVM ใช้จริง รวม 88 ช่อง · alg none กับ alg confusion ถูกปฏิเสธครบ 36 จาก 36 ช่อง · แต่ token ที่ไม่มี exp เลยผ่านทั้งเก้าช่อง และสวิตช์ที่เปิดตรวจ aud ไม่แตะ iss เลยสักนิด
อ่าน → - บทความต้นฉบับของ Kaen
เติมคอมเมนต์บรรทัดเดียวใน .dockerignore แล้วเสีย layer เท่ากับแก้ source
วัดสอง Dockerfile ที่ต่างกันแค่ลำดับของ COPY บนการแก้เจ็ดแบบ รวมสิบสี่ทรง · touch ไม่ทำให้ cache หลุดสักขั้น ส่วน file ใหม่ที่ไม่มีใครอ่านทำให้หลุดเท่ากับแก้ source · และคอมเมนต์ใน .dockerignore ที่ไม่ตัด file ไหนเพิ่ม ก็ราคาเดียวกัน
อ่าน → - บทความต้นฉบับของ Kaen
pattern เดียวกัน ข้อความเดียวกัน แปด engine ตอบตรงกันแค่ทรงเดียว
ให้แปด engine จากสี่ runtime อ่าน pattern จากรายการเดียวกัน สิบห้าทรง รวม 120 ช่อง · ตอบตรงกันหมดแค่ทรงเดียว · และ \b รอบคำไทยในข้อความไทยล้วน ไม่มี engine ไหน match เลยสักตัว ด่านที่เขียนแบบนั้นจึงแดงไม่ได้
อ่าน → - บทความต้นฉบับของ Kaen
switch ที่ไม่มี default มี default อยู่ และมันโยน exception ที่คุณไม่เคยพิมพ์
javac พิสูจน์ได้ว่า switch ของคุณครอบคลุมทุกค่า แล้วมันก็ยังใส่ทางออกที่โยน MatchException ลงใน bytecode ให้อยู่ดี · หน้านี้เดินไปบนทางออกนั้นจริง โดยไม่แตะ file class ของผู้เรียกแม้แต่ไบต์เดียว เปลี่ยนแค่ library บน classpath · และตัวการไม่ใช่ sealed ไม่ใช่ pattern matching
อ่าน → - บทความต้นฉบับของ Kaen
constructor เป็น private แล้ว แต่ยังมีประตูอีกบานที่ compiler สร้างให้เอง
data class ของ Kotlin ที่ประกาศ constructor เป็น private ยังได้ copy() ที่เป็น public มาฟรี · หน้านี้นับว่าเส้นทางไหนผ่าน factory กี่ครั้งและผ่าน init กี่ครั้ง แล้วพบว่าคำอธิบายที่เล่ากันบ่อยที่สุดเรื่องนี้ผิด และผิดในทางที่ทำให้คนถอดยามตัวเดียวที่ยังยืนอยู่
อ่าน → - บทความต้นฉบับของ Kaen
preview ไม่ได้ตรึงแค่ธง มันตรึง class file ไว้กับรุ่น
แปลด้วย --enable-preview แล้วรันโดยไม่ใส่ธง JVM ปฏิเสธตั้งแต่อ่านหัว file พร้อมเลขรุ่นที่มีส่วนรองเป็น 65535 · class นั้นรันได้เฉพาะบนรุ่นที่แปลมัน ไม่ใช่รุ่นนั้นขึ้นไป · พร้อมเกณฑ์สามข้อสำหรับตัดสินใจ
อ่าน → - บทความต้นฉบับของ Kaen
equals ของ record ไม่ใช่ code ที่ใครเขียน และนั่นคือประเด็นทั้งหมด
javap บอกว่า record มี member สาธารณะหกตัวเทียบกับสามตัวของ class ที่เขียนมือ · และสามตัวที่เพิ่มมาเรียก bootstrap method ตัวเดียวกัน จึงเปลี่ยนตามทันทีเมื่อเพิ่ม field ต่างจาก equals ที่ IDE สร้างให้
อ่าน → - บทความต้นฉบับของ Kaen
ย้ายจาก instanceof มาเป็น switch แล้ว null เปลี่ยนความหมาย
instanceof เป็นเท็จเมื่อค่าเป็น null จึงตกลงมาที่กิ่งสำรอง ส่วน switch ที่มี pattern โยน NullPointerException แม้จะมี default เขียนไว้ · การย้ายจึงเปลี่ยนความหมายโดยไม่มีอะไรเตือน
อ่าน → - บทความต้นฉบับของ Kaen
data class ที่มี Array — equals กับ hashCode ถูกสร้างด้วยนิยามคนละอัน
สองอ็อบเจกต์ที่เนื้อในเหมือนกันทุกตัวอักษร ไม่เท่ากัน แต่ hash เท่ากัน · เปิด bytecode แล้วพบว่า equals เรียก Intrinsics.areEqual ส่วน hashCode เรียก Arrays.hashCode · และการแก้ array หลังใส่ลง set ทำให้อ็อบเจกต์หาตัวเองไม่เจอ
อ่าน → - บทความต้นฉบับของ Kaen
lateinit แลกข้อความ error ที่ดี ด้วย field ที่กลายเป็น public
lateinit บอกชื่อ property ตอนแตะก่อนกำหนดค่า ส่วน bang bang ตอบว่า null เฉยๆ · แต่ javap บอกว่า backing field ของ lateinit เป็น public ขณะที่ nullable ได้ private · ด่านของมันอยู่ที่ getter ซึ่งหลบได้
อ่าน → - บทความต้นฉบับของ Kaen
suspend ไม่ใช่เรื่องของ thread — มันเปลี่ยนลายเซ็นที่ JVM เห็น
suspend fun ที่ประกาศคืน Long ถูก JVM มองเป็น method ที่คืน Object และรับ Continuation เพิ่ม · พร้อม class ที่ไม่มีใครเขียนซึ่งมี field ชื่อ label เป็นตัวนับสถานะ และเก็บตัวแปรท้องถิ่นไว้นอก stack
อ่าน → - บทความต้นฉบับของ Kaen
JEP 491 แก้ pinning ที่คนพูดถึงกันหมดแล้ว และเหลือบานที่ไม่มีใครพูดถึง
virtual thread ที่บล็อกขณะถือ monitor เคยตรึง carrier thread ไว้ · JDK 24 แก้ข้อนั้นแล้วจริง หน้านี้นับ event ของ JFR ข้ามสาม version เพื่อยืนยัน · แล้ววัดอีกเคสหนึ่งที่ยังตรึงอยู่บนทุก version รวมทั้งตัวล่าสุด และเคสนั้นคือช่องควบคุมของการวัดไปในตัว
อ่าน →
หมายเหตุ: บทความในหมวดนี้เป็นบทแปล/เรียบเรียงเพื่อการศึกษา โดยให้เครดิตและ link กลับไปยังต้นฉบับเสมอ (ยกเว้นบทที่ระบุว่าเป็น “บทความต้นฉบับของ Kaen”) ศัพท์เทคนิคคงไว้เป็นภาษาอังกฤษตามต้นฉบับเพื่อให้ค้นหาเอกสารต่อได้ง่าย