Là một đối tượng duy nhất được ưa thích hơn nhiều biến?


8

Thật khó để đặt những gì tôi muốn nói vào một tiêu đề, nhưng thật dễ dàng để đưa vào mã.

C ++

Có phải đây là

int offset_x = 10;
int offset_y = 40;
...
element.move(offset_x, offset_y);

Để được ưa thích hơn này?

Vector<int> offset(10, 40);
...
element.move(offset.x, offset.y);

(Lưu ý rằng Vector không giống như std::vector, đó là vectơ 2D. Lớp này có rất nhiều phương thức tôi không cần ở đây, như normalize()scale(). Tôi có nên có một Pointlớp cơ bản hơn cho việc này không?)

JavaScript

Có phải đây là

var offsetX = 10;
var offsetY = 40;
...
element.move(offsetX, offsetY);

Để được ưa thích hơn này?

var offset = {x: 10, y: 40};
...
element.move(offset.x, offset.y);

Câu trả lời:


12

Tôi đã "kế thừa" rất nhiều mã kế thừa bằng cách sử dụng biến thể đầu tiên của bạn và cũng tự mình viết rất nhiều mã bằng cách sử dụng Point2DPoint3Dcác lớp (về cơ bản giống với nội dung của bạn Vector<int>). Biến thể đầu tiên luôn dẫn đến các hàm có quá nhiều tham số và quá nhiều cấu trúc lặp đi lặp lại trong đó phép cộng vectơ đơn giản hoặc phép nhân vô hướng được lặp đi lặp lại nhiều lần trong một vài dòng mã.

Tuy nhiên, sử dụng các lớp vectơ hoặc vectơ 2D, đặc biệt là khi bạn có nhu cầu nhiều thao tác vectơ, làm cho mã sạch hơn, ngắn gọn, dễ đọc và dễ bảo trì hơn. Nếu bạn nên sử dụng một lớp hiện có Vector<int>hoặc viết một Pointlớp của riêng bạn thì không thể nói mà không biết thêm về các chi tiết của mã của bạn, nhưng nói chung, nếu một lớp hiện có đáp ứng nhu cầu của bạn, tại sao không sử dụng lại nó? Các phương pháp bổ sung mà bạn không cần làm tổn thương điển hình. Nhưng không sử dụng bất kỳ lớp điểm / vectơ 2D nào là quyết định sai. Và trong ví dụ của bạn ở trên: nếu bạn có ảnh hưởng đến element.movechức năng, IMHO tốt hơn hết là bạn nên thiết kế nó theo cách bạn có thể gọi element.move(offset)thay vì element.move(offset_x, offset_y).

Ví dụ: giả sử bạn cần một mảng tọa độ điểm và bạn sẽ sử dụng a std::vector. Trong trường hợp đầu tiên, bạn sẽ cần hai std::vector<int> biến, bạn phải đảm bảo hai vectơ đó "đồng bộ" với nhau và tất cả việc thêm các phần tử mới, tìm các phần tử hiện có, đi qua các phần tử đó cần hai dòng mã thay thế của một khi bạn đã chọn để sử dụng std::vector<Point2D>thay thế.


3

Để đưa ra một câu trả lời tổng quát hơn, các biến nên được nhóm lại thành một đối tượng khi nó có ý nghĩa logic để làm như vậy.

  • Là các biến khác nhau về khía cạnh hoặc tính chất của một "điều"?
  • Họ có luôn thuộc về nhau không?
  • Liệu chúng có được sử dụng đủ để biện minh cho bất kỳ công việc bổ sung nào có thể liên quan đến việc tạo ra một đối tượng không?

Trong trường hợp của bạn, tôi sẽ nói rằng mã của bạn cải thiện rõ ràng khi bạn nhóm các biến lại với nhau.

Nhưng nếu các biến được đặt cùng nhau trong một đối tượng không được suy nghĩ kỹ, bạn có thể bị mắc kẹt với một thiết kế khó sử dụng tệ hơn so với sử dụng các biến thông thường.

Ngược lại, có thể thiết kế quá mức: dành quá nhiều thời gian để suy nghĩ và xây dựng cấu trúc hướng đối tượng "hoàn hảo", đến mức nó ngăn bạn thực sự hoàn thành công việc.


1

Trên thực tế, tôi nghĩ cách tốt nhất là làm điều này:

Vector<int> offset(10, 40);
element.moveBy(offset);

Mã này trừu tượng hóa chiều của các vectơ của bạn và cùng một dòng mã ( element.moveBy(offset)) sẽ hoạt động không thay đổi nếu bạn thay đổi vectơ của mình thành 3D, hoặc nhân đôi, hoặc thậm chí tọa độ cực, miễn là các kiểu của bạn thực hiện đúng các thao tác cần thiết.

Ví dụ, hãy xem xét mã sau đây:

Vec wallBounce(Obj& o, cont Wall& w) {
    assert(isUnit(w.normal));
    Vec perp = dot(w.normal, o.velocity) * w.normal;
    o.velocity -= 2 * perp;
}

Bất cứ ai có đủ đầu mối toán học vector sẽ hiểu những gì xảy ra ở đây; Ngoài ra, chức năng là ngắn, đến điểm. Bạn không thể thấy những gì Vecđược gõ, nhưng điều đó thường không thú vị và cũng tầm thường để tìm kiếm; mã rõ ràng và ngắn gọn hơn bù đắp cho nó. Xét cho cùng, mã hóa là tất cả về việc tạo ra sự trừu tượng hóa, và trừu tượng hóa các nhóm vô hướng thành vectơ là một sự trừu tượng hóa rất mạnh mẽ. Đối với các cú đá, hãy thử và thực hiện chức năng trên mà không thực hiện trừu tượng hóa này, cho các vectơ 2D, vectơ 3D và vô hướng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.