Tôi muốn phân biệt giữa hai cách khác nhau để tiếp cận lập trình hướng đối tượng
- Trình mô phỏng: các đối tượng của bạn đại diện cho các đối tượng miền thực, bạn đã lập trình chúng để xử lý bất kỳ chức năng nào liên quan đến miền đó. Các đối tượng được lập trình theo cách này có thể có rất nhiều trạng thái có thể thay đổi và các cộng tác viên ẩn được sử dụng để thực hiện chức năng này.
- Bản ghi + chức năng: đối tượng của bạn chỉ là gói dữ liệu và chức năng hoạt động trên dữ liệu đó. Các đối tượng được lập trình theo cách này có nhiều khả năng trở thành bất biến, đảm nhận ít trách nhiệm hơn và cho phép một người tiêm chích cộng tác viên.
Một nguyên tắc nhỏ là một đối tượng được lập trình theo cách thứ nhất sẽ có nhiều phương thức hơn và nhiều void
phương thức hơn so với cách thứ hai. Giả sử chúng tôi sẽ viết một chuyến bay giả lập và đang thiết kế một lớp máy bay. Chúng tôi sẽ có một cái gì đó như:
class Plane {
void accelerate();
void deccelerate();
void toggleRightFlaps();
void toggleLeftFlaps();
void turnRudderRight();
void turnRudderLeft();
void deployLandingGear();
void liftLandingGear();
// etc.
void tick() throws PlaneCrashedException;
}
Điều này có thể là một chút cực đoan hơn một người có thể gặp phải, nhưng nó được điểm. Nếu bạn muốn thực hiện loại giao diện này, bạn phải giữ bên trong đối tượng:
- Tất cả các thông tin về trạng thái của thiết bị máy bay.
- Tất cả các thông tin về vận tốc / gia tốc của máy bay.
- Tốc độ làm mới mô phỏng của chúng tôi (để thực hiện đánh dấu).
- Chi tiết đầy đủ về mô hình 3d của mô phỏng và vật lý của nó để thực hiện đánh dấu.
Viết một bài kiểm tra đơn vị cho một đối tượng được viết trong chế độ là rất khó vì:
- Bạn cần cung cấp tất cả các bit dữ liệu và cộng tác viên khác nhau mà đối tượng này cần khi bắt đầu thử nghiệm (việc tạo ra chúng có thể rất tẻ nhạt).
- Khi bạn muốn kiểm tra một phương pháp bạn gặp phải hai vấn đề: a) giao diện thường không tiết lộ đủ dữ liệu để bạn kiểm tra (vì vậy cuối cùng bạn phải sử dụng giả / phản ánh để thậm chí xác minh kỳ vọng) b) có nhiều thành phần bị ràng buộc thành một cái mà bạn phải xác minh hành vi trong mỗi bài kiểm tra.
Về cơ bản, bạn bắt đầu với một giao diện có vẻ hợp lý và giống như nó phù hợp với miền, nhưng tính độc đáo của mô phỏng đã khiến bạn tạo ra một đối tượng thực sự khó kiểm tra.
Tuy nhiên, bạn có thể tạo các đối tượng sẽ thực hiện cùng một mục đích. Bạn sẽ muốn hãm bạn Plane
thành các bit nhỏ hơn. Có một dấu PlaneParticle
vết theo dõi các bit vật lý của mặt phẳng, vị trí, vận tốc, gia tốc, lăn, ngáp, v.v., v.v., phơi bày và cho phép người ta thao tác những thứ này. Sau đó, một PlaneParts
đối tượng có thể theo dõi trạng thái của. Bạn sẽ gửi tick()
đến một nơi hoàn toàn khác, giả sử có một PlanePhysics
đối tượng được tham số hóa, ví dụ, lực hấp dẫn, biết được PlaneParticle
và đưa ra một PlaneParts
cách mới để tạo ra một vật mới PlaneParticle
. Tất cả điều này có thể là hoàn toàn bất biến, mặc dù nó không cần phải là một ví dụ.
Bây giờ bạn có những lợi thế về mặt kiểm tra:
- Mỗi thành phần riêng lẻ có ít việc phải làm và dễ thiết lập hơn.
- Bạn có thể kiểm tra các thành phần của bạn trong sự cô lập.
- Những đối tượng này có thể thoát khỏi việc phơi bày nội bộ của họ (đặc biệt là nếu chúng được tạo ra bất biến), vì vậy người ta không cần phải khéo léo để đo lường chúng.
Đây là mẹo: cách tiếp cận hướng đối tượng thứ hai mà tôi mô tả rất gần với lập trình chức năng. Có thể trong các chương trình chức năng thuần túy, hồ sơ và chức năng của bạn là riêng biệt và không bị ràng buộc với nhau trong các đối tượng, chắc chắn một chương trình chức năng sẽ đảm bảo rằng tất cả những điều này. Những gì tôi nghĩ thực sự làm cho thử nghiệm đơn vị dễ dàng là
- Đơn vị nhỏ (không gian nhà nước nhỏ).
- Chức năng với đầu vào tối thiểu (không có đầu vào ẩn).
- Chức năng với đầu ra tối thiểu.
Lập trình chức năng khuyến khích những điều này (nhưng người ta có thể viết các chương trình xấu trong bất kỳ mô hình nào) nhưng chúng có thể đạt được trong các chương trình hướng đối tượng. Và tôi sẽ nhấn mạnh thêm rằng lập trình chức năng và lập trình hướng đối tượng không tương thích.