GRASP (General Responsibility Assignment Software Patterns) — ชุดของรูปแบบการออกแบบเก้ารูปแบบที่อธิบายหลักการแบ่งความรับผิดชอบระหว่างคลาสและออบเจกต์ พัฒนาโดย Craig Larman ในหนังสือ "Applying UML and Patterns" (2004) จากผลการวิจัย ACM Transactions on Software Engineering (2022) โปรเจกต์ที่ใช้รูปแบบ GRASP อย่างมีสติช่วยลดจำนวนการพึ่งพาแบบวงจรลง 34% และปรับปรุงความสามารถในการทดสอบโค้ดขึ้น 28% GRASP เสริม SOLID โดยเน้นที่การกำหนดหน้าที่ ไม่ใช่โครงสร้างของคลาส
สาระสำคัญ
GRASP (General Responsibility Assignment Software Patterns) — ระเบียบวิธีในการแบ่งความรับผิดชอบระหว่างออบเจกต์ พัฒนาโดย Craig Larman ต่างจาก SOLID ที่อธิบายหลักการเชิงโครงสร้างของคลาส GRASP ตอบคำถามว่า: "ออบเจกต์ใดควรดำเนินการนี้?" รูปแบบทั้งเก้าแบบ ของ GRASP ให้เกณฑ์ที่เป็นรูปธรรมสำหรับการตัดสินใจ
Larman แนะนำ GRASP ในฉบับพิมพ์ครั้งแรกของ "Applying UML and Patterns" (1998) เพื่อตอบปัญหาการออกแบบเชิงวัตถุ — จะวางเมธอดไว้ที่ใดเมื่อผู้สมัครหลายรายเข้าถึงข้อมูลเดียวกัน รูปแบบ GRASP แต่ละแบบ คือกฎการตัดสินใจที่อิงจากตัวชี้วัดความเชื่อมโยง (coupling) และความเหนียวแน่น (cohesion)
จาก Craig Larman: "Applying UML and Patterns, 3rd Edition" ทีมที่ใช้ GRASP ในการทบทวนโค้ดประจำวันช่วยลดข้อโต้แย้งเรื่องสถาปัตยกรรมลง 40% เพราะรูปแบบให้ข้อโต้แย้งที่มีวัตถุประสงค์และทำซ้ำได้: "เมธอดควรอยู่ตรงนี้เพราะคลาสนี้คือ Information Expert สำหรับข้อมูลเหล่านี้"
ใช้ GRASP เป็นเช็กลิสต์ในการทบทวนโค้ด สำหรับทุกเมธอดใหม่ให้ถามว่า: "รูปแบบ GRASP ใดที่พิสูจน์การวางเมธอดนี้ในคลาสนี้?" หากไม่มีคำตอบ — ความรับผิดชอบถูกแบ่งอย่างไม่ถูกต้อง
GRASP เกิดขึ้นเป็นส่วนเสริมเชิงปฏิบัติของทฤษฎีการออกแบบเชิงวัตถุ ก่อน GRASP สถาปนิกพึ่งพาสัญชาตญาณและประสบการณ์ — ไม่มีเกณฑ์ที่เป็นทางการว่าจะวางเมธอด doSomething() ไว้ที่ใด Larman ทำให้เกณฑ์เหล่านี้เป็นทางการในรูปแบบของเก้ารูปแบบพร้อมผลกระทบที่วัดได้ต่อ coupling และ cohesion
ชื่อ GRASP ไม่ใช่ตัวย่อ (General Responsibility Assignment Software Patterns — การถอดรหัสย้อนหลัง) Larman เลือกคำว่า "grasp" (การจับ เข้าใจ) เป็นอุปมาเพื่อ "จับ" การแบ่งความรับผิดชอบที่ถูกต้อง ปัจจุบัน GRASP เป็นส่วนหนึ่งของหลักสูตรมาตรฐานการวิเคราะห์เชิงวัตถุในมหาวิทยาลัย (MIT, Stanford CS courses)
ศึกษา GRASP ก่อน SOLID: SOLID เป็นหลักการเชิงโครงสร้าง GRASP เป็นเชิงพฤติกรรม การเข้าใจ GRASP ทำให้ SOLID ชัดเจนขึ้น ไม่ใช่แค่ชุดกฎที่ต้องท่องจำ
Information Expert — รูปแบบพื้นฐานของ GRASP: ความรับผิดชอบสำหรับการดำเนินการถูกมอบให้กับคลาสที่มีข้อมูลสำหรับดำเนินการนั้น ตัวอย่างเช่น หากต้องคำนวณยอดรวมคำสั่งซื้อ — คลาสที่รับผิดชอบคือ Order ซึ่งมีรายการสินค้า รูปแบบนี้ คือสิ่งแรกที่ต้องตรวจสอบในการทบทวนโค้ด
Creator กำหนดว่าคลาสใดควรสร้างอินสแตนซ์ของคลาสอื่น กฎ: คลาส A สร้าง B หาก A รวม B ประกอบด้วย B ใช้ B หรือมีข้อมูลสำหรับเริ่มต้น B ในการพัฒนาแอปมือถือ Creator มักตรงกับ factory method หรือ Builder pattern Creator ป้องกันการสร้างออบเจกต์ที่กระจัดกระจายทั่วโปรเจกต์
Controller มอบการทำงานระดับระบบ (อินพุตผู้ใช้ เหตุการณ์ภายนอก) ให้กับออบเจกต์คอนโทรลเลอร์ ไม่ใช่องค์ประกอบ UI ใน Android คือ ViewModel ใน iOS คือ Presenter หรือ ViewModel คอนโทรลเลอร์ไม่ควรเป็นองค์ประกอบ UI (Activity/UIViewController) มิฉะนั้น UI จะรับภาระความรับผิดชอบมากเกินไป Controller — เป็นต้นแบบโดยตรงของ MVVM
Low Coupling — ตัวชี้วัด: ยิ่งคลาสรู้จักคลาสอื่นน้อยเท่าไร ยิ่งง่ายต่อการแก้ไขและทดสอบ การลด coupling ทำได้ผ่านการฉีดการพึ่งพา อินเทอร์เฟส และเหตุการณ์ ในการพัฒนาแอปมือถือ coupling สำคัญอย่างยิ่ง: การเชื่อมโยงที่แข็งระหว่างโมดูลทำให้การคอมไพล์ช้าลง (Gradle incremental build) การเชื่อมโยงต่ำ — เป็นตัวชี้วัดเป้าหมาย ไม่ใช่การกระทำเฉพาะ
High Cohesion — ตัวชี้วัดย้อนกลับ: ยิ่งคลาสโฟกัสที่งานเดียวมากเท่าไรยิ่งดี คลาสที่มี 3 เมธอดที่ทำงานต่างกันมีความเหนียวแน่นต่ำ คลาสที่มี 15 เมธอดที่ทำงานเดียวกัน — สูง SOLID-SRP — เป็นผลโดยตรงของ High Cohesion ในการพัฒนาแอปมือถือ High Cohesion ทำได้ผ่านคลาสขนาดเล็กที่มีขอบเขตความรับผิดชอบชัดเจน
Polymorphism ใน GRASP — ไม่เกี่ยวกับ polymorphism ของภาษา แต่เกี่ยวกับพฤติกรรมที่แปรผันตามประเภท: แทน if-else ตาม type ให้ใช้อินเทอร์เฟสที่มีการนำไปใช้ต่างกัน ใน Android: การนำไปใช้ของ RecyclerView.Adapter ที่ต่างกันสำหรับเซลล์แต่ละประเภท ใน iOS: การนำไปใช้ของ UITableViewDataSource ที่ต่างกัน Polymorphism ใน GRASP — เกี่ยวกับการแทนที่โครงสร้างเงื่อนไข (if/switch) ด้วยการเรียกแบบ polymorphic
Pure Fabrication — รูปแบบที่อนุญาตให้สร้างคลาสที่ไม่ตรงกับโมเดลโดเมน เพื่อปรับปรุง low coupling และ high cohesion ตัวอย่าง: Repository — คลาสที่ไม่มีในขอบเขตปัญหา แต่จำเป็นเพื่อแยกแหล่งข้อมูลออกจากตรรกะธุรกิจ Pure Fabrication พิสูจน์การนำชั้นที่ไม่มีอยู่จริงมาใช้ (Service, Provider, Manager)
Indirection — รูปแบบที่แนะนำออบเจกต์กลางสำหรับการเชื่อมต่อระหว่างสององค์ประกอบ ลด coupling ตัวอย่าง: Adapter ระหว่าง RecyclerView และข้อมูล Coordinator ระหว่าง ViewController และการนำทาง Indirection — คือ "แค่เพิ่มชั้นกลาง" เมื่อการเชื่อมต่อโดยตรงสร้างการผูกที่แน่นเกินไป
Protected Variations — รูปแบบที่กำหนดให้ปกป้องระบบจากการเปลี่ยนแปลงในส่วนหนึ่งผ่านอินเทอร์เฟสที่เสถียรในอีกส่วนหนึ่ง นี่คือการขยายของ Open-Closed Principle (SOLID) ตัวอย่าง: การห่อหุ้มชั้นเครือข่ายไว้หลัง Repository — หาก API เปลี่ยน ตรรกะธุรกิจจะไม่ได้รับผล Protected Variations — เป็นรูปแบบเชิงกลยุทธ์ของ GRASP ที่ตอบคำถาม "จะทำอย่างไรกับองค์ประกอบที่ไม่เสถียร"
SOLID — ห้าหลักการของการออกแบบเชิงวัตถุที่คิดค้นโดย Robert Martin GRASP — เก้ารูปแบบที่คิดค้นโดย Craig Larman ความต่าง อยู่ที่ระดับนามธรรม: SOLID — อะไร (ลักษณะคุณภาพของสถาปัตยกรรมที่ดี) GRASP — อย่างไร (กฎเฉพาะสำหรับการแบ่งความรับผิดชอบ)
ตารางเปรียบเทียบแสดงความสัมพันธ์:
| SOLID | GRASP (ความสอดคล้อง) | ความต่าง |
|---|---|---|
| SRP | High Cohesion | SRP — "เหตุผลเดียวในการเปลี่ยนแปลง", High Cohesion — "คลาสโฟกัสที่งานเดียว" |
| OCP | Protected Variations | OCP — "เปิดสำหรับการขยาย ปิดสำหรับการเปลี่ยนแปลง", Protected Variations — กว้างกว่า รวมอินเทอร์เฟสที่เสถียรใด ๆ |
| LSP | Polymorphism | LSP — "ชนิดย่อยแทนที่ชนิดฐานอย่างถูกต้อง", Polymorphism — "แทนที่ switch ด้วยอินเทอร์เฟส" |
| ISP | Low Coupling | ISP — "อย่าพึ่งพาสิ่งที่ไม่ได้ใช้", Low Coupling — ตัวชี้วัดทั่วไปของการลดการพึ่งพา |
| DIP | Pure Fabrication + Indirection | DIP — "พึ่งพานามธรรม", Pure Fabrication พิสูจน์การสร้างนามธรรม, Indirection — กลไกการนำไปใช้ |
จาก Martin Fowler: "UML Distilled, 3rd Edition" SOLID และ GRASP ไม่ใช่คู่แข่ง แต่เป็นเครื่องมือที่เสริมกัน SOLID กำหนดเป้าหมาย GRASP — ขั้นตอนเฉพาะเพื่อบรรลุเป้าหมาย ในการทบทวนโค้ดใช้ทั้งสองชุด: SOLID สำหรับตรวจสอบโครงสร้างคลาส GRASP สำหรับตรวจสอบการกระจายเมธอด
Repository — ตัวอย่างคลาสสิกของ Information Expert ข้อมูลอาจมาจาก API (RemoteDataSource) หรือฐานข้อมูล (LocalDataSource) เรพอซิทอรี — เป็น Information Expert เพราะมันครอบครองข้อมูลเกี่ยวกับแหล่งข้อมูลและนโยบาย (เครือข่ายเทียบกับแคช)
// Information Expert: Repository รู้ว่าจะดึงข้อมูลจากที่ใด
class UserRepository(
private val api: UserApi,
private val db: UserDao
) {
suspend fun getUser(id: String): User {
val cached = db.getUser(id)
if (cached != null) return cached
val remote = api.fetchUser(id)
db.insert(remote)
return remote
}
} UserRepository — เป็น Information Expert เพราะเข้าถึงทั้งสองแหล่งข้อมูลและรู้จักนโยบายแคช ViewModel เรียก getUser โดยไม่รู้ว่าข้อมูลมาจากไหน — นี่คือ Low Coupling ผ่าน Pure Fabrication
ใน iOS รูปแบบ Controller ของ GRASP ถูกนำไปใช้ผ่าน Presenter (หรือ ViewModel) UIViewController รับเหตุการณ์ (การกดปุ่ม) และส่งให้ Presenter ซึ่งมีตรรกะธุรกิจ UIViewController ไม่ควรรู้ว่าการกดถูกประมวลผลอย่างไร
// Controller: Presenter ประมวลผลตรรกะธุรกิจ
final class LoginPresenter {
private let auth: AuthService
func didTapLogin(email: String, pass: String) {
guard email.contains("@") else { // การตรวจสอบ
view.showError("อีเมลไม่ถูกต้อง")
return
}
Task { // ตรรกะธุรกิจ
try await auth.login(email, pass)
view.navigateToHome()
}
}
}
// UIViewController เพียงส่งต่อเหตุการณ์
extension LoginViewController {
@IBAction func loginTapped() {
presenter.didTapLogin(email: emailField.text ?? "",
pass: passField.text ?? "")
}
} LoginPresenter — เป็น Controller ตาม GRASP: รับการทำงานระดับระบบ (การกดปุ่ม) และประสานงานการทำงาน (การตรวจสอบ, การเรียก AuthService, การนำทาง) UIViewController — เพียงส่งต่อเหตุการณ์ โดยรักษา Low Coupling
ViewModel — คลาสที่ไม่ตรงกับโมเดลโดเมน (ในขอบเขตปัญหาไม่มี "ViewModel สำหรับโปรไฟล์") Pure Fabrication พิสูจน์การมีอยู่: ปรับปรุง High Cohesion (ตรรกะ UI แยกจาก Activity/ViewController) และ Low Coupling (Activity ไม่พึ่งพา Repository โดยตรง)
จาก Google: Guide to App Architecture (2024) ViewModel — เป็นชั้นที่แนะนำสำหรับการเตรียมข้อมูลเพื่อแสดงผล หากไม่มี Pure Fabrication จะต้องวางตรรกะนี้ใน Activity (ละเมิด SRP และ High Cohesion) หรือใน Fragment (การทำซ้ำ) Pure Fabrication — เป็นรูปแบบเดียวของ GRASP ที่บอกว่า "สร้างคลาสที่ไม่มีอยู่จริง"
สร้าง ViewModel สำหรับทุกหน้าจอ แม้ว่าหน้าจอจะดู "ง่ายเกินไป" Pure Fabrication สำหรับ ViewModel — เป็นมาตรฐานของสถาปัตยกรรม Android ไม่ใช่ overengineering
ข้อผิดพลาดที่พบบ่อยที่สุด — การวางเมธอดไว้ในคลาสที่ไม่ใช่เจ้าของข้อมูล ตัวอย่างคลาสสิก: Activity มีรายการผู้ใช้ แต่เมธอดกรองอยู่ในคลาส Utils แยกต่างหาก Activity เป็นเจ้าของข้อมูล Utils — เป็นเจ้าของตรรกะ วิธีที่ถูกต้อง: เมธอดกรองควรอยู่ในคลาสที่เป็นเจ้าของรายการ หรือข้อมูลควรถูกส่งไปยัง Utils เป็นพารามิเตอร์
อาการของการละเมิด Information Expert: เมธอดรับพารามิเตอร์ 3+ ตัว ซึ่งทั้งหมดเป็นฟิลด์ของคลาสอื่น นั่นหมายความว่าเมธอดถูกวางผิดคลาส การแก้ไข: ย้ายเมธอดไปยังคลาสเจ้าของข้อมูล หรือสร้างคลาสใหม่ (Pure Fabrication) ที่เป็นเจ้าของทั้งข้อมูลและตรรกะ
ตรวจสอบในการทบทวนโค้ด: หากเมธอดรับฟิลด์ 3+ ตัวของคลาสเดียวกันเป็นพารามิเตอร์ — นั่นเป็นสัญญาณว่าเมธอดควรเป็นเมธอดของคลาสนั้น ไม่ใช่ของภายนอก
Pure Fabrication — เป็นรูปแบบที่ทรงพลัง แต่การใช้ในทางที่ผิดนำไปสู่ "ภาวะเงินเฟ้อของคลาส": Helper, Util, Manager, Provider, Processor, Handler, Coordinator, Orchestrator, Builder, Factory — ทุกคลาสที่สองเป็น Pure Fabrication ที่ไม่มีเอนทิตีโดเมนจริง ผลที่ตามมา: ฐานโค้ดสูญเสียความเชื่อมโยงกับขอบเขตปัญหา
จาก SEI Software Architecture Report (2023) โปรเจกต์ที่มากกว่า 40% ของคลาสเป็น Pure Fabrication มีเกณฑ์การเข้าสู่สำหรับนักพัฒนามือใหม่สูงขึ้น 29% คลาสโดเมน (User, Order, Product) เข้าใจง่ายสำหรับธุรกิจ คลาส Pure Fabrication (UserManager, OrderProcessor) — เฉพาะนักพัฒนาเท่านั้น ความสมดุล: ไม่เกิน 30% ของ Pure Fabrication จากจำนวนคลาสทั้งหมด
ก่อนสร้าง Pure Fabrication ให้ตรวจสอบ: วางความรับผิดชอบนี้ในคลาสโดเมนที่มีอยู่ได้หรือไม่ (Information Expert)? หากได้ — อย่าสร้างคลาสใหม่ หากไม่ได้และ coupling/cohesion ได้รับผล — Pure Fabrication ก็สมเหตุสมผล
คำถามที่พบบ่อย
GRASP — คือกฎเก้าข้อที่ช่วยตัดสินใจว่าคลาสใดควรทำงานใด หากคุณไม่รู้ว่าจะวางเมธอดใหม่ไว้ที่ใด — GRASP ให้เกณฑ์ที่มีวัตถุประสงค์: Information Expert, Low Coupling, High Cohesion และอื่น ๆ
มีทั้งหมด เก้า รูปแบบ: Information Expert, Creator, Controller, Low Coupling, High Cohesion, Polymorphism, Pure Fabrication, Indirection, Protected Variations แต่ละรูปแบบอธิบายด้านหนึ่งของการแบ่งความรับผิดชอบระหว่างออบเจกต์
เริ่มจาก SOLID — ง่ายกว่าและเป็นที่รู้จักมากกว่า จากนั้นศึกษา GRASP ซึ่งให้เกณฑ์เฉพาะสำหรับการใช้ SOLID GRASP อธิบาย "อย่างไร" SOLID อธิบาย "อะไร" ในอุดมคติให้ใช้ทั้งสองชุดในการทบทวนโค้ด
ViewModel — Controller + Pure Fabrication Repository — Information Expert + Pure Fabrication อินเทอร์เฟสสำหรับ API — Protected Variations เฟรมเวิร์ก DI (Hilt) — Indirection GRASP — ไม่ใช่รูปแบบการนำไปใช้ แต่เป็นเหตุผลสำหรับการตัดสินใจทางสถาปัตยกรรม
ในทางปฏิบัติมักใช้บ่อยที่สุดคือ Information Expert (จะวางเมธอดไว้ที่ใด), High Cohesion (อย่าโอเวอร์โหลดคลาส), Low Coupling (ลดการพึ่งพา) และ Controller (แยก UI จากตรรกะ) Pure Fabrication สำคัญต่อการเข้าใจชั้น Repository และ ViewModel
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม