Cái nào tốt hơn: một bó getters hoặc 1 phương thức với tham số chuỗi lựa chọn?


15

Miền kiến ​​thức của chúng tôi liên quan đến những người đi bộ trên một tấm ghi áp lực bằng đôi chân trần của họ. Chúng tôi thực hiện nhận dạng hình ảnh dẫn đến các đối tượng của lớp 'Chân', nếu chân người được nhận dạng trong dữ liệu cảm biến.

Có một số tính toán phải được thực hiện trên dữ liệu của bàn chân.

Bây giờ, API nào sẽ tốt hơn:

class Foot : public RecognizedObject  { 
  MaxPressureFrame getMaxPressureFrame();
  FootAxis getFootAxis();
  AnatomicalZones getAnatomicalZones();

  // + similar getters for other calculations

  // ...
}

Hoặc là:

class Foot : public RecognizedObject {
  virtual CalculationBase getCalculation(QString aName);

  // ...
}

Bây giờ, có rất nhiều pro và con tôi có thể nghĩ ra, nhưng tôi thực sự không thể quyết định đâu là quan trọng nhất. Lưu ý, đây là một ứng dụng người dùng cuối, không phải thư viện phần mềm chúng tôi bán.

Có lời khuyên nào không?

Một số pro cho cách tiếp cận đầu tiên có thể là:

  • KISS - mọi thứ đều rất cụ thể. API, nhưng việc thực hiện là tốt.
  • gõ mạnh giá trị trả về.
  • kế thừa từ lớp này là bằng chứng ngu ngốc. Không có gì có thể được ghi đè, chỉ được thêm vào.
  • API rất kín, không có gì đi vào, không có gì có thể bị ghi đè, do đó ít có thể sai.

Một số con:

  • Số lượng getters sẽ tăng lên, vì mọi tính toán mới mà chúng tôi phát minh được thêm vào danh sách
  • API có nhiều khả năng thay đổi và nếu giới thiệu các thay đổi được giới thiệu, chúng tôi cần một phiên bản API mới, Foot2.
  • trong trường hợp sử dụng lại lớp trong các dự án khác, chúng tôi có thể không cần mọi tính toán

Một số pro cho cách tiếp cận thứ hai:

  • Linh hoạt hơn
  • api ít có khả năng thay đổi, (giả sử chúng ta đã trừu tượng hóa chính xác, nếu không, thay đổi sẽ có giá cao hơn)

Một số con:

  • đánh máy lỏng lẻo. Cần phôi trên mỗi cuộc gọi.
  • tham số chuỗi - Tôi có cảm giác xấu về điều đó (phân nhánh trên các giá trị chuỗi ...)
  • Không có trường hợp / yêu cầu sử dụng hiện tại bắt buộc phải linh hoạt thêm, nhưng có thể có trong tương lai.
  • API áp đặt các hạn chế: mọi tính toán cần xuất phát từ một lớp cơ sở. Việc tính toán sẽ được thực hiện thông qua phương pháp 1 này và việc truyền các tham số bổ sung sẽ là không thể, trừ khi chúng ta nghĩ ra một cách truyền linh hoạt hơn, siêu linh hoạt hơn để tăng độ phức tạp hơn nữa.

5
Bạn có thể thực hiện enumvà bật các giá trị của nó. Tuy nhiên, tôi nghĩ rằng lựa chọn thứ hai là xấu xa, bởi vì nó đi chệch khỏi KISS.
Vorac

Khó tìm thấy tất cả các công dụng của một phép tính cụ thể nếu bạn sử dụng tham số chuỗi để kích hoạt nó. Khó có thể là 100% bạn tìm thấy tất cả.
Konrad Morawski

Tận dụng tốt nhất của hai thế giới và viết một mặt tiền với một loạt các getters gọi getCalculation().
kể từ

1
Enums chắc chắn là tốt hơn so với chuỗi! Tôi đã không nghĩ về điều này. Họ hạn chế API và ngăn lạm dụng tham số chuỗi (như concat của mã thông báo và crap khác) Vì vậy, tôi đoán sự so sánh là giữa tùy chọn 1 và tùy chọn 2 với enum thay vì chuỗi.
Bgie

Câu trả lời:


6

Tôi nghĩ rằng trong cách tiếp cận đầu tiên sẽ trả hết. Chuỗi ma thuật có thể tạo ra các vấn đề sau: Lỗi đánh máy, sử dụng sai, an toàn loại trả về không tầm thường, thiếu hoàn thành mã, mã không rõ ràng (phiên bản này có tính năng đó không? Tôi đoán chúng ta sẽ tìm ra trong thời gian chạy). Sử dụng enums sẽ giải quyết một số vấn đề đó, nhưng hãy xem xét những nhược điểm bạn nêu ra:

  • Số lượng getters sẽ tăng lên, vì mọi tính toán mới mà chúng tôi phát minh được thêm vào danh sách

Đúng, điều đó có thể gây phiền nhiễu, tuy nhiên nó giữ cho mọi thứ tốt đẹp và nghiêm ngặt, và cho phép bạn hoàn thành mã ở bất cứ đâu trong dự án của bạn trong bất kỳ IDE hiện đại nào, với các nhận xét tiêu đề tốt hữu ích hơn nhiều so với enums.

  • API có nhiều khả năng thay đổi và nếu giới thiệu các thay đổi được giới thiệu, chúng tôi cần một phiên bản API mới, Foot2.

Đúng, nhưng đó thực sự là một pro rất lớn;) bạn có thể xác định giao diện cho các API một phần, và sau đó bạn không cần phải biên dịch lại lớp phụ thuộc không bị ảnh hưởng bởi các API mới hơn (Vì vậy, không cần Foot2). Điều đó cho phép tách rời tốt hơn, sự phụ thuộc bây giờ là giao diện chứ không phải việc thực hiện. Ngoài ra, nếu một giao diện hiện tại thay đổi, bạn sẽ gặp lỗi biên dịch trong các lớp phụ thuộc, điều này rất tốt để ngăn chặn mã cũ.

  • trong trường hợp sử dụng lại lớp trong các dự án khác, chúng tôi có thể không cần mọi tính toán

Tôi không thấy việc sử dụng chuỗi ma thuật hay enum sẽ giúp ích như thế nào ... Nếu tôi hiểu chính xác, bạn sẽ bao gồm mã trong lớp Foot hoặc bạn chia nó thành một vài lớp nhỏ hơn và điều đó phù hợp với cả hai tùy chọn


Tôi thích ý tưởng API một phần với các giao diện, nó có vẻ như là bằng chứng trong tương lai. Tôi sẽ đi với cái đó Cảm ơn bạn. Nếu nó trở nên quá lộn xộn (chân thực hiện quá nhiều giao diện), sử dụng một số lớp bộ điều hợp nhỏ sẽ linh hoạt hơn: Nếu một số biến thể của bàn chân tồn tại với các api khác nhau (như chân, chân người, chân chó, chân người, có thể có một bộ chuyển đổi nhỏ cho mỗi tiện ích cho phép một tiện ích GUI hoạt động với tất cả chúng ...
Bgie

Một lợi thế của việc sử dụng bộ chọn lệnh là người ta có thể có một triển khai nhận lệnh mà nó không hiểu gọi một phương thức trợ giúp tĩnh được cung cấp cùng với giao diện. Nếu lệnh đại diện cho điều gì đó có thể được thực hiện với gần như tất cả các triển khai bằng cách sử dụng cách tiếp cận mục đích chung, nhưng một số triển khai có thể thực hiện thông qua các phương tiện tốt hơn [ví dụ như IEnumerable<T>.Count], cách tiếp cận như vậy có thể cho phép mã được hưởng lợi ích hiệu suất của mới Các tính năng giao diện khi sử dụng các triển khai hỗ trợ chúng, nhưng vẫn tương thích với các triển khai cũ.
supercat

12

Tôi muốn giới thiệu tùy chọn 3: Làm rõ rằng các tính toán không phải là một phần nội tại của sự trừu tượng của a Foot, nhưng hoạt động dựa trên nó. Sau đó, bạn có thể phân chia Footvà tính toán thành các lớp riêng biệt, như thế này:

class Foot : public RecognizedObject {
public:
    // Rather low-level API to access all characteristics that might be needed by a calculation
};

class MaxPressureFrame {
public:
    MaxPressureFrame(const Foot& aFoot); // Performs the calculation based on the information in aFoot
    //API for accessing the results of the calculation
};

// Similar classes for other calculations

Bằng cách này, bạn vẫn có thể gõ mạnh vào tính toán của mình và bạn có thể thêm các phép tính mới mà không ảnh hưởng đến mã hiện tại (trừ khi bạn mắc lỗi nghiêm trọng về số lượng thông tin được hiển thị bởi Foot).


Chắc chắn đẹp hơn các tùy chọn 1 và 2. Đây chỉ là một bước ngắn để sử dụng mẫu thiết kế chiến lược.
Brian

4
Điều này có thể thích hợp. Điều này có thể là quá mức cần thiết. Phụ thuộc vào mức độ phức tạp của các tính toán. Bạn sẽ thêm MaxPressureFrameStrargety và MaxPressureFrameStrargetyFactory? Và nó có xu hướng biến Foot thành một đối tượng thiếu máu.
dùng949300

Mặc dù đây là một lựa chọn tốt, nhưng việc đảo ngược các phụ thuộc sẽ không hoạt động trong trường hợp của chúng tôi. Bàn chân cũng phải đóng vai trò là một loại trung gian hòa giải, vì một số tính toán cần phải được tính toán lại nếu một số khác thay đổi (do người dùng thay đổi một tham số hoặc như vậy).
Bgie

@Bgie: Với sự phụ thuộc như vậy giữa các tính toán, tôi đồng ý với @ user116462 rằng tùy chọn đầu tiên là tốt nhất
Bart van Ingen Schenau
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.