
Colocation คืออะไร
colocation เป็นเทคนิคการเขียนและจัดการโค้ด ให้อยู่ในตำแหน่งใกล้ๆ กัน ทำให้หาโค้ดที่เกี่ยวข้องกันได้ง่ายขึ้น ตัวอย่างเช่น ย้ายโค้ดที่อยู่คนละโฟลเดอร์กัน มาอยู่ที่โฟลเดอร์เดียวกัน หรือโค้ดที่อยู่คนละไฟล์กัน มารวมอยู่ที่ไฟล์เดียว เพื่อให้แก้ไขและทำให้เราอ่านทำความเข้าใจโค้ดได้ดีขึ้น เป็นวิธี refactor ที่คอนเซปง่ายๆ แต่ใช้ได้ผลดีทีเดียว
ตัวอย่างการใช้งาน
เรามาดูตัวอย่างของ colocation กับ โค้ดที่ไม่ได้ใช้ colocation กันดีกว่า เพื่อให้รู้ความแตกต่าง
// user-module.ts
class UserService {
private users: Map<number, string> = new Map();
constructor() {
this.initUsers();
}
private initUsers(): void {
this.users.set(1, "Alice");
this.users.set(2, "Bob");
this.users.set(3, "Charlie");
}
public getUserById(id: number): string | undefined {
return this.users.get(id);
}
}
class UserComponent {
private userService: UserService;
constructor(userService: UserService) {
this.userService = userService;
}
public displayUserName(userId: number): void {
const userName = this.userService.getUserById(userId);
if (userName) {
console.log(`User Name: ${userName}`);
} else {
console.log("User not found.");
}
}
}
const userService = new UserService();
const userComponent = new UserComponent(userService);
userComponent.displayUserName(2);
จะเห็นว่า เรามี class ว่า UserService และ UserComponent ซึ่งตัว UserComponent เวลาใช้งาน จะต้องส่ง UserService ไปเป็น constructor ทุกครั้ง หมายความว่าเวลาเราจะแก้ไขโค้ดแล้ว ถ้า 2 class นี้มันอยู่ในไฟล์เดียวกัน เราก็จะอ่านและก็แก้ไขได้ง่ายขึ้นและรวดเร็ว
ทีนี้เรามาดู anti-pattern ของ colocation กันบ้างดีกว่า
// user.service.ts
class UserService {
// implementation...
}
// user.component.ts
class UserComponent {
// implementation...
}
// File: app.module.ts
// Contains module-level configurations, unrelated to UserService or UserComponent.
จะเห็นว่าทั้ง 2 class จะอยู่คนไฟล์กันแล้ว บางทีอยู่คนละโฟลเดอร์กันด้วยซ้ำ ทำให้เวลาแก้ไขไฟล์ จะทำให้เราอ่านยากขึ้นมานิดนึง เพราะต้องสลับกันดูไปมา
การใช้งานกับ Frontend (React)
import React from 'react';
// components/user/Users.js
function UserComponent({ userName }) {
return (
<div>
<h1>User Name: {userName}</h1>
</div>
);
}
export default UserComponent;
// components/user/UserService.js
class UserService {
getUsers() {
// Fetch users from API or database
return [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' },
];
}
}
export default UserService;
อันนี้เป็นตัวอย่างการ colocation ที่ 2 ไฟล์ทำงานคนละอย่างกัน แต่ก็ยังอยู่โฟลเดอร์เดียวกัน ทำให้ยังอ่านง่ายอยู่
มาดูตัวอย่างของ anti-pattern กัน
// components/UserComponent.js
import React from 'react';
function UserComponent({ userName }) {
return (
<div>
<h1>User Name: {userName}</h1>
</div>
);
}
export default UserComponent;
// services/UserService.js
class UserService {
getUsers() {
// Fetch users from API or database
return [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' },
];
}
}
export default UserService;
จะเห็นว่าทั้ง 2 ไฟล์จะย้ายไปอยู่คนละโฟลเดอร์กันแล้ว เวลาเราเปิดเข้าไปในโฟลเดอร์ services อาจจะเจอ ไฟล์อื่นปนอยู่ด้วย ทำให้หาโค้ดยากขึ้นมานิดนึง
สรุปว่าเมื่อไหรควรใช้ colocation
จะเห็นว่าการแยกไฟล์อยู่ใกล้ๆ หรือที่เดียวกัน นั้นช่วยให้หาโค้ดที่เกี่ยวข้องเจอง่ายขึ้น แต่การแยกโค้ดไว้คนละที่ ก็ทำให้แบ่งหมวดหมู่และโค้ดเป็นระเบียบเหมือนกัน แล้วเมื่อไหร่เราควรจะทำ colocation กันนะ?
- Related Functionality – โค้ดดังกล่าว ส่วนมีความเกี่ยวข้องกันมาก หรือมีหลายๆ ส่วนคล้ายกัน
- Dependency – โค้ดดังกล่าว ไม่ได้ใช้มีการ reuse กับส่วนอื่นเลย เพราะฉะนั้นจับมารวมที่เดียวกันเลยก็ได้
- Readability and Understandability – เวลาเราอ่านโค้ด แล้วรู้สึกว่าต้องสลับหน้าต่างกันไปมาเยอะเกินไป ลองย้ายมาอยู่ใกล้ๆ กันไหม แล้วเปรียบเทียบดูว่าอ่านง่ายขึ้นหรือป่าว
colocation เป็นเทคนิคนึงที่เรา refactor ให้โค้ดอ่านง่ายขึ้นโดยไม่ต้องแก้ไขโค้ดเลย แค่ย้ายที่อยู่ไฟล์เฉยๆ จึงเป็นวิธีนึงที่ง่ายและมีประสิทธิภาพ น่าจะเป็นจุดเริ่มต้นในการ refactor ที่ดีครับ


