Đôi khi sao chép mã là kết quả của một "cách chơi chữ": Hai thứ trông giống nhau, nhưng không.
Có thể là quá trừu tượng hóa có thể phá vỡ mô-đun thực sự của hệ thống của bạn. Theo chế độ mô đun hóa, bạn phải quyết định "điều gì có khả năng thay đổi?" và "cái gì ổn định?". Bất cứ thứ gì ổn định đều được đặt trong giao diện, trong khi bất cứ thứ gì không ổn định đều được gói gọn trong quá trình thực hiện của mô-đun. Sau đó, khi mọi thứ thay đổi, thay đổi bạn cần thực hiện được tách biệt với mô-đun đó.
Tái cấu trúc là cần thiết khi những gì bạn nghĩ là ổn định (ví dụ: lệnh gọi API này sẽ luôn có hai đối số) cần thay đổi.
Vì vậy, đối với hai đoạn mã trùng lặp này, tôi sẽ hỏi: Liệu một thay đổi bắt buộc đối với một điều này có nhất thiết phải thay đổi khác không?
Cách bạn trả lời câu hỏi đó có thể giúp bạn hiểu rõ hơn về sự trừu tượng tốt có thể là gì.
Các mẫu thiết kế cũng là công cụ hữu ích. Có lẽ mã trùng lặp của bạn đang thực hiện truyền tải một số dạng và nên áp dụng mẫu lặp.
Nếu mã trùng lặp của bạn có nhiều giá trị trả về (và đó là lý do tại sao bạn không thể thực hiện một phương thức trích xuất đơn giản), thì có lẽ bạn nên tạo một lớp giữ các giá trị được trả về. Lớp có thể gọi một phương thức trừu tượng cho mỗi điểm khác nhau giữa hai đoạn mã. Sau đó, bạn sẽ thực hiện hai triển khai cụ thể của lớp: một cho mỗi phân đoạn. [Đây thực sự là mẫu thiết kế Phương thức mẫu, không bị nhầm lẫn với khái niệm mẫu trong C ++. Ngoài ra, những gì bạn đang xem có thể được giải quyết tốt hơn với mẫu Chiến lược.]
Một cách tự nhiên và hữu ích khác để suy nghĩ về nó là với các hàm bậc cao hơn. Ví dụ, tạo lambdas hoặc sử dụng các lớp bên trong ẩn danh để mã chuyển sang trừu tượng hóa. Nói chung, bạn có thể loại bỏ trùng lặp, nhưng trừ khi thực sự có mối quan hệ giữa chúng [nếu một thay đổi, do đó phải thay đổi] thì bạn có thể bị tổn thương mô-đun, không giúp đỡ nó.