Làm thế nào để các lập trình viên chuyên nghiệp đưa ra phán quyết kêu gọi có nên đi OOP hay không? Nó sẽ thực sự hữu ích cho tôi.
Đối với tôi, có hai điểm quyết định. Đầu tiên, đôi khi nó sẽ rõ ràng ngay từ đầu. Sẽ có rất nhiều loại tương tự mà tất cả đều chia sẻ các phương thức phổ biến khác nhau rộng rãi trong chi tiết triển khai của chúng. Ví dụ, tôi đang xây dựng một hệ thống quy trình công việc và tôi cần khả năng thực hiện các nhiệm vụ tùy ý. Để chạy tác vụ, tôi đã triển khai một lớp cơ sở mà mỗi tác vụ được kế thừa từ đó, với một Execute()
phương thức trừu tượng. Các lớp kế thừa đã cung cấp việc thực hiện, nhưng hệ thống dòng công việc có thể bắt đầu thực thi mà không biết gì về loại nhiệm vụ nào đang được chạy.
Hầu hết các dự án không phải là rõ ràng mặc dù. Điểm quyết định thứ hai là khi một tập hợp con của dự án đã phát triển thành một mớ lớn các câu lệnh if-then hoặc câu lệnh chuyển đổi và đặc biệt là khi các câu lệnh if-then đó yêu cầu rất nhiều mã thiết lập để chạy chính xác. Tôi cảm thấy bản thân bắt đầu mất logic của những gì tôi đang cố gắng thực hiện và mã bắt đầu cảm thấy mong manh. Tại thời điểm đó, thường là một dấu hiệu cho thấy đã đến lúc cấu trúc lại mã thành các lớp cơ sở với các triển khai cụ thể.
Một phần lớn của việc chuyển sang một phong cách hướng đối tượng trái ngược với phong cách chức năng là chuyển đổi các câu lệnh if-then thành các câu lệnh "chạy hành động này". Thay vì một tập hợp các câu lệnh if-then khổng lồ, bạn chỉ cần nói mã để chạy hành động của nó. Hành động nào thực sự được chạy phụ thuộc vào việc triển khai bạn cung cấp.
Ví dụ: đây là kiểu chức năng trong mã giả kiểu C #:
if ( action == "email" ) {
callEmailFunction(userInfo);
}
else if ( action == "sms" ) {
callSmsFunction(userInfo);
}
else if ( action == "web" ) {
endpoint = "http://127.0.0.1/confirm";
confirmWeb(endpoint, userinfo);
}
...
Nhưng có lẽ bạn có thể viết lại nó thành một cái gì đó như thế này:
interface IConfirmable {
void Confirm(UserInfo userinfo);
}
public class ConfirmEmail : IConfirmable {
public void Confirm(UserInfo userinfo) {
// do the appropriate thing to confirm via email
}
}
public class ConfirmSms : IConfirmable {
public void Confirm(UserInfo userinfo) {
// do the appropriate thing to confirm via email
}
}
public class ConfirmWeb : IConfirmable {
// this is a constructor
public ConfirmWeb(string endpoint) {
...
}
public void Confirm(UserInfo userinfo) {
// do the appropriate thing to confirm via web
}
}
Và sau đó là mã:
// An implementation that decides which implementation of the base class to use
// This replaces the if-then statements in the functional programmming.
IConfirmable confirmer = ConfirmerFactory.GetConfirmer();
// get the userinfo however you get it,
// which would be the same way you get it in the functional example.
UserInfo userinfo = ...;
// perform the action.
confirmer.Confirm(userinfo);
Bây giờ, khi có rất ít mã bên trong if-then, điều này có vẻ như rất nhiều công việc không nhận được lợi ích. Và khi có rất ít mã trong if-then, điều đó là chính xác: đó là rất nhiều công việc cho mã khó hiểu hơn.
Nhưng phong cách hướng đối tượng thực sự tỏa sáng khi bạn có nhiều hơn một hành động chứ không chỉ là Confirm()
phương thức cần được thực hiện. Có thể bạn có một thói quen khởi tạo, ba hoặc nhiều phương thức hành động có thể chạy và một Cleanup()
phương thức. Thuật toán cơ sở là giống hệt nhau, ngoại trừ nó thực hiện các cuộc gọi của nó vào các đối tượng thích hợp thực hiện một lớp cơ sở chung. Bây giờ bạn bắt đầu thấy một lợi ích thực sự cho các đối tượng theo phong cách theo định hướng: các thuật toán cơ bản là nhiều dễ đọc hơn nếu nó được kiểm tra if-then báo cáo tại mỗi bước của con đường.