Một tính năng của Envy mã envy là gì và tại sao nó được coi là mùi mã?


53

Câu hỏi này trên SO nói về việc sửa những gì OP nghĩ là mã ghen tị . Một ví dụ khác mà tôi thấy cụm từ tiện lợi này được trích dẫn là trong một câu trả lời gần đây được đưa ra ở đây trong các lập trình viên. Mặc dù tôi đã bỏ một bình luận cho câu trả lời đó để hỏi thông tin nhưng tôi nghĩ rằng nó sẽ giúp ích chung cho các lập trình viên theo dõi Q & A để hiểu ý nghĩa của thuật ngữ ghen tị . Xin vui lòng chỉnh sửa các thẻ bổ sung nếu bạn nghĩ rằng phù hợp.


Câu trả lời:


88

Ghen tị với tính năng là một thuật ngữ được sử dụng để mô tả một tình huống trong đó một đối tượng nhận được tại các trường của đối tượng khác để thực hiện một số tính toán hoặc đưa ra quyết định, thay vì yêu cầu đối tượng tự thực hiện tính toán.

Như một ví dụ tầm thường, hãy xem xét một lớp đại diện cho một hình chữ nhật. Người sử dụng hình chữ nhật có thể cần biết khu vực của nó. Lập trình viên có thể phơi bày widthheightcác trường và sau đó thực hiện tính toán bên ngoài Rectanglelớp. Ngoài ra, Rectanglecó thể giữ widthheightcác trường riêng tư và cung cấp một getAreaphương thức. Đây được cho là một cách tiếp cận tốt hơn.

Vấn đề với tình huống đầu tiên, và lý do nó được coi là mùi mã, là vì nó phá vỡ đóng gói.

Theo nguyên tắc thông thường, bất cứ khi nào bạn thấy mình sử dụng rộng rãi các trường từ một lớp khác để thực hiện bất kỳ loại logic hoặc tính toán nào, hãy xem xét chuyển logic đó sang một phương thức trên chính lớp đó.


7
+1, mặc dù ví dụ của bạn không thực tế, vì một lớp Hình chữ nhật hữu ích thường sẽ phơi bày các trường chiều rộng và chiều cao.
Doc Brown

2
Và mặc dù việc phá vỡ đóng gói có thể xảy ra cùng với "Môi trường tính năng", trong hầu hết các ví dụ trong thế giới thực mà tôi đã thấy cho đến nay có lẽ không phải vậy. Nó xảy ra nhiều hơn trong các tình huống "này, tôi cần tính toán một số thứ chỉ trong mã bằng cách sử dụng đối tượng đó và tôi không chắc liệu tôi có thể chạm vào việc thực hiện của đối tượng đó không / nếu chúng ta nên giao cho đối tượng chịu trách nhiệm cho tính toán đó". Và sau đó, người ta thực hiện tính toán bằng cách sử dụng các trường đã được phơi bày (mặc dù có thể thực hiện sạch hơn nhiều trong đối tượng).
Doc Brown

2
@DocBrown Hãy tưởng tượng một hình chữ nhật được vẽ trên bề mặt hình xuyến, hình nón hoặc hình cầu. Nếu thư viện vẽ hình của tôi tạo ra các đối tượng có khả năng tạo ra kết quả chính xác trong các bối cảnh như vậy, bạn sẽ thật ngu ngốc khi không để chúng tính toán các khu vực của riêng mình - trong bất kỳ bối cảnh nào.
itbruce

1
@OskarN .: Theo định nghĩa chúng ta đang nói về chức năng mà đang cần. Rõ ràng là chúng cần thiết nếu các lớp khác đang thực hiện lại chúng nhiều lần.
Aaronaught

1
@OskarN.: Nó phụ thuộc; đôi khi quyết định là rõ ràng, đôi khi nó là vấn đề của hương vị, và thường là vấn đề kinh nghiệm. Trong bài viết của bạn, có những lý do chính đáng tại sao Scott Meyers viết " đôi khi ít hơn" và anh ta phải mất nhiều năm để hiểu khi không áp dụng "thuật toán để quyết định khi nào thực hiện chức năng thành viên fa".
Doc Brown

1

Có một tình huống có thể xảy ra khi sử dụng rộng rãi các phương thức lớp / struct khác - khi lớp / struct của bạn là một thùng chứa dữ liệu. Thông thường có một chút bạn có thể làm với dữ liệu này mà không cần bối cảnh bên ngoài.

Các lớp như vậy vẫn có thể chứa một số logic bên trong nhưng thường được sử dụng như các thùng chứa:

class YourUid {
 public:
  YourUid(int id_in_workplace_, int id_in_living_place_, DB* FBI_database, int id_in_FBI_database);
  bool IsInvalidWorker() const { return id_in_workplace == consts::invalid_id_in_workplace; }
  bool CanMessWith() const { return !FBI_database_.is_cool(id_in_FBI_database_); }
  int id_in_workplace;
  int id_in_living_place;
 private:
  int id_in_FBI_database_;
  const DB* FBI_database_;
};

@jhewlett trong câu trả lời của anh ấy đề cập đến bài viết này để chứng minh rằng bạn không nên sử dụng rộng rãi các thành viên khác trong lớp, nhưng có một khác có mùi tình huống được mô tả ở đó với ví dụ của tôi:

Danh sách tham số dài. Giới hạn số lượng tham số bạn cần trong một phương thức nhất định hoặc sử dụng một đối tượng để kết hợp các tham số.


1
Làm thế nào để trả lời câu hỏi này?
gnat

@gnat Q là về lý do tại sao nó được coi là "mùi mã". jhewlett đưa ra điểm A với một số giả định quá chung chung được hỏi trong các bình luận. Câu trả lời của tôi là 2 xu để phân biệt "mùi mã" với thực tế thông thường.
Riga
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.