Khi enums KHÔNG phải là một mùi mã?


17

Tình trạng khó xử

Tôi đã đọc rất nhiều sách thực hành hay nhất về thực hành hướng đối tượng và hầu hết mọi cuốn sách tôi đã đọc đều có một phần mà họ nói rằng enum là một mùi mã. Tôi nghĩ rằng họ đã bỏ lỡ phần mà họ giải thích khi enums hợp lệ.

Như vậy, tôi đang tìm kiếm các hướng dẫn và / hoặc các trường hợp sử dụng trong đó enum KHÔNG phải là mùi mã và trên thực tế là một cấu trúc hợp lệ.

Nguồn:

"CẢNH BÁO Theo quy tắc thông thường, enum là mùi mã và nên được tái cấu trúc thành các lớp đa hình. [8]" Seemann, Mark, Dependency Injection trong .Net, 2011, tr. 342

[8] Martin Fowler và cộng sự, Tái cấu trúc: Cải thiện thiết kế của Bộ luật hiện tại (New York: Addison-Wesley, 1999), 82.

Bối cảnh

Nguyên nhân của tình trạng khó xử của tôi là một API giao dịch. Họ cung cấp cho tôi luồng dữ liệu Tick bằng cách gửi thông qua phương thức này:

void TickPrice(TickType tickType, double value)

Ở đâu enum TickType { BuyPrice, BuyQuantity, LastPrice, LastQuantity, ... }

Tôi đã thử tạo một trình bao bọc xung quanh API này bởi vì phá vỡ các thay đổi là cách sống của API này. Tôi muốn theo dõi giá trị của từng loại đánh dấu nhận được cuối cùng trên trình bao bọc của mình và tôi đã thực hiện điều đó bằng cách sử dụng Từ điển đánh dấu:

Dictionary<TickType,double> LastValues

Đối với tôi, điều này có vẻ như là một cách sử dụng enum đúng cách nếu chúng được sử dụng làm chìa khóa. Nhưng tôi có suy nghĩ thứ hai vì tôi có một nơi để đưa ra quyết định dựa trên bộ sưu tập này và tôi không thể nghĩ ra cách nào để loại bỏ tuyên bố chuyển đổi, tôi có thể sử dụng một nhà máy nhưng nhà máy đó vẫn sẽ có một tuyên bố chuyển đổi ở đâu đó. Dường như với tôi rằng tôi chỉ di chuyển mọi thứ xung quanh nhưng nó vẫn có mùi.

Thật dễ dàng để tìm thấy những điều tuyệt vời, nhưng DO, không dễ dàng như vậy và tôi đánh giá cao nếu mọi người có thể chia sẻ chuyên môn, ưu và nhược điểm của họ.

Suy nghĩ thứ hai

Một số quyết định và hành động dựa trên những điều này TickTypevà dường như tôi không thể nghĩ ra cách nào để loại bỏ các tuyên bố enum / switch. Giải pháp sạch nhất tôi có thể nghĩ đến là sử dụng một nhà máy và trả lại việc thực hiện dựa trên TickType. Thậm chí sau đó tôi vẫn sẽ có một câu lệnh chuyển đổi trả về việc thực hiện giao diện.

Được liệt kê dưới đây là một trong những lớp mẫu mà tôi nghi ngờ rằng tôi có thể sử dụng enum sai:

public class ExecutionSimulator
{
  Dictionary<TickType, double> LastReceived;
  void ProcessTick(TickType tickType, double value)
  {
    //Store Last Received TickType value
    LastReceived[tickType] = value;

    //Perform Order matching only on specific TickTypes
    switch(tickType)
    {
      case BidPrice:
      case BidSize:
        MatchSellOrders();
        break;
      case AskPrice:
      case AskSize:
        MatchBuyOrders();
        break;
    }       
  }
}

25
Tôi chưa bao giờ nghe nói enums là một mùi mã. Bạn có thể bao gồm một tài liệu tham khảo? Tôi nghĩ rằng chúng có ý nghĩa rất lớn đối với một số lượng giá trị tiềm năng hạn chế
Richard Tingle

23
Những cuốn sách đang nói enums là một mùi mã? Nhận sách tốt hơn.
JacquesB

3
Vì vậy, câu trả lời cho câu hỏi sẽ là "hầu hết thời gian".
gnasher729

5
Một giá trị tốt đẹp, an toàn mà truyền đạt ý nghĩa? Điều đó đảm bảo các khóa thích hợp được sử dụng trong Từ điển? Khi nào nó có mùi mã?

7
Không có ngữ cảnh, tôi nghĩ rằng một từ ngữ tốt hơn sẽ làenums as switch statements might be a code smell ...
vui lòng vào

Câu trả lời:


31

Enums được dành cho các trường hợp sử dụng khi bạn đã liệt kê đúng mọi giá trị có thể mà một biến có thể lấy. Không bao giờ. Hãy nghĩ các trường hợp sử dụng như các ngày trong tuần hoặc các tháng trong năm hoặc các giá trị cấu hình của một thanh ghi phần cứng. Những thứ vừa ổn định vừa có thể biểu thị bằng một giá trị đơn giản.

Hãy nhớ rằng, nếu bạn đang tạo một lớp chống tham nhũng, bạn không thể tránh có một tuyên bố chuyển đổi ở đâu đó , vì thiết kế bạn đang gói, nhưng nếu bạn làm đúng, bạn có thể giới hạn ở một nơi đó và sử dụng đa hình ở nơi khác.


3
Đây là điểm quan trọng nhất - thêm một giá trị bổ sung vào enum có nghĩa là tìm mọi cách sử dụng loại trong mã của bạn và có khả năng cần thêm một nhánh mới cho giá trị mới. So sánh với một loại đa hình, trong đó việc thêm một khả năng mới chỉ đơn giản là tạo ra một lớp mới thực hiện giao diện - các thay đổi được tập trung ở một nơi duy nhất, do đó dễ thực hiện hơn. Nếu bạn chắc chắn một loại đánh dấu mới sẽ không bao giờ được thêm vào, enum vẫn ổn, nếu không thì nó sẽ được bọc trong một giao diện đa hình.
Jules

Đó là một trong những câu trả lời tôi đang tìm kiếm. Tôi chỉ không thể tránh nó khi phương thức tôi sử dụng enum và mục đích là tập trung những enum này ở một nơi. Tôi phải tạo trình bao bọc sao cho bao giờ API thay đổi các enum này, tôi chỉ phải thay đổi trình bao bọc chứ không phải người tiêu dùng của trình bao bọc.
stromms

@Jules - "Nếu bạn chắc chắn một loại đánh dấu mới sẽ không bao giờ được thêm vào ..." Câu nói đó sai ở rất nhiều cấp độ. Một lớp cho mỗi loại duy nhất, mặc dù mỗi loại có hành vi giống hệt nhau nằm cách xa phương pháp "hợp lý" nhất có thể có. Không phải cho đến khi bạn có những hành vi khác nhau và bắt đầu cần những câu lệnh "switch / if-then" trong đó dòng cần được vẽ. Nó chắc chắn không dựa trên việc tôi có thể thêm nhiều giá trị enum trong tương lai hay không.
Dunk

@dunk Tôi nghĩ bạn hiểu nhầm ý kiến ​​của tôi. Tôi không bao giờ đề nghị tạo ra nhiều loại với hành vi giống hệt nhau - điều đó thật điên rồ.
Jules

1
Ngay cả khi bạn đã "liệt kê mọi giá trị có thể", điều đó không có nghĩa là loại đó sẽ không bao giờ có chức năng bổ sung cho mỗi trường hợp. Ngay cả một cái gì đó như Tháng có thể có các thuộc tính hữu ích khác, như số ngày. Sử dụng một enum ngay lập tức ngăn khái niệm bạn mô hình hóa được mở rộng. Về cơ bản, đây là một cơ chế / mô hình chống OOP.
Dave Cousineau

17

Thứ nhất, mùi mã không có nghĩa là có gì đó không đúng. Nó có nghĩa là một cái gì đó có thể sai. enumcó mùi vì nó thường xuyên bị lạm dụng, nhưng điều đó không có nghĩa là bạn phải tránh chúng. Chỉ cần bạn thấy mình gõ enum, dừng lại và kiểm tra các giải pháp tốt hơn.

Trường hợp cụ thể xảy ra thường xuyên nhất là khi các enum khác nhau tương ứng với các loại khác nhau với các hành vi khác nhau nhưng cùng một giao diện. Ví dụ, nói chuyện với các phụ trợ khác nhau, hiển thị các trang khác nhau, v.v ... Những điều này được thực hiện tự nhiên hơn nhiều bằng cách sử dụng các lớp đa hình.

Trong trường hợp của bạn, TickType không tương ứng với các hành vi khác nhau. Chúng là các loại sự kiện khác nhau hoặc các thuộc tính khác nhau của trạng thái hiện tại. Vì vậy, tôi nghĩ rằng đây là nơi lý tưởng cho một enum.


Bạn có nói rằng khi enums chứa Danh từ làm mục (ví dụ: Màu sắc), chúng có thể được sử dụng chính xác. Và khi chúng là động từ (Kết nối, Kết xuất) thì đó có phải là dấu hiệu cho thấy nó đang bị lạm dụng?
stromms

2
@stromms, ngữ pháp là một hướng dẫn khủng khiếp cho kiến ​​trúc phần mềm. Nếu TickType là một giao diện thay vì enum, thì các phương thức sẽ là gì? Tôi không thể nhìn thấy bất kỳ, đó là lý do tại sao nó dường như là một trường hợp đáng ghen tị với tôi. Các trường hợp khác, như trạng thái, màu sắc, phụ trợ, v.v., tôi có thể đưa ra các phương thức và đó là lý do tại sao chúng là các giao diện.
Winston Ewert

@WinstonEwert và với bản chỉnh sửa, có vẻ như chúng những hành vi khác nhau.

Ồ Vậy nếu tôi có thể nghĩ ra một phương pháp cho một enum, thì nó có thể là một ứng cử viên cho một giao diện không? Đó có thể là một điểm rất tốt.
stromms

1
@stromms, bạn có thể chia sẻ thêm ví dụ về các công tắc, để tôi có thể hiểu rõ hơn về cách bạn sử dụng TickType không?
Winston Ewert

8

Khi truyền enum dữ liệu không có mùi mã

IMHO, khi truyền dữ liệu bằng cách sử dụng enumsđể chỉ ra rằng một trường có thể có một giá trị từ một tập hợp các giá trị bị hạn chế (hiếm khi thay đổi) là tốt.

Tôi coi nó là tốt hơn để truyền tùy ý stringshoặc ints. Chuỗi có thể gây ra vấn đề bởi các biến thể trong chính tả và viết hoa. Ints cho phép truyền ra các giá trị phạm vi và có ngữ nghĩa chút (ví dụ như tôi nhận được 3từ dịch vụ kinh doanh của bạn, điều đó có nghĩa là gì? LastPrice? LastQuantity? Cái gì khác?

Truyền các đối tượng và sử dụng hệ thống phân cấp lớp không phải lúc nào cũng có thể; ví dụ không cho phép kết thúc nhận để phân biệt lớp nào đã được gửi.

Trong dự án của tôi, dịch vụ sử dụng một hệ thống phân cấp lớp cho các hiệu ứng của các hoạt động, ngay trước khi truyền qua một DataContractđối tượng từ hệ thống phân cấp lớp được sao chép vào một unionđối tượng giống như có chứa một loại enumđể chỉ ra loại. Máy khách nhận DataContractvà tạo một đối tượng của một lớp trong hệ thống phân cấp bằng cách sử dụng enumgiá trị switchvà tạo một đối tượng đúng kiểu.

Một lý do khác khiến người ta không muốn truyền các đối tượng của lớp là dịch vụ có thể yêu cầu hành vi hoàn toàn khác nhau đối với một đối tượng được truyền (chẳng hạn LastPrice) so với máy khách. Trong trường hợp đó, việc gửi lớp và các phương thức của nó là không mong muốn.

Là báo cáo chuyển đổi xấu?

IMHO, một tầng đơn switch gọi các nhà xây dựng khác nhau tùy thuộc vào enumkhông phải là mùi mã. Nó không nhất thiết phải tốt hơn hoặc xấu hơn các phương thức khác, chẳng hạn như cơ sở phản chiếu trên một kiểu chữ; điều này phụ thuộc vào tình hình thực tế.

Có công tắc ở enumkhắp mọi nơi là mùi mã, cung cấp các lựa chọn thay thế thường tốt hơn:

  • Sử dụng đối tượng của các lớp khác nhau của một hệ thống phân cấp có các phương thức được ghi đè; tức là đa hình.
  • Sử dụng mẫu khách truy cập khi các lớp trong hệ thống phân cấp hiếm khi thay đổi và khi các hoạt động (nhiều) nên được kết nối lỏng lẻo với các lớp trong cấu trúc phân cấp.

Trên thực tế, TickType đang được truyền qua dây như một int. Bao bọc của tôi là cái sử dụng TickTypeđược đúc từ nhận int. Một số sự kiện sử dụng ticktype này với các chữ ký khác nhau hoang dã là phản ứng với các yêu cầu khác nhau. Có phải là thông lệ để sử dụng intliên tục cho các chức năng khác nhau? ví dụ: TickPrice(int type, double value)sử dụng 1,3 và 6 typetrong khi TickSize(int type, double valuesử dụng 2,4 và 5? Nó thậm chí có ý nghĩa để tách chúng thành hai sự kiện?
stromms

2

Điều gì nếu bạn đã đi với một loại phức tạp hơn:

    abstract class TickType
    {
      public abstract string Name {get;}
      public abstract double TickValue {get;}
    }

    class BuyPrice : TickType
    {
      public override string Name { get { return "Buy Price"; } }
      public override double TickValue { get { return 2.35d; } }
    }

    class BuyQuantity : TickType
    {
      public override string Name { get { return "Buy Quantity"; } }
      public override double TickValue { get { return 4.55d; } }
    }
//etcetera

sau đó bạn có thể tải các loại của mình từ sự phản chiếu hoặc tự xây dựng nó, nhưng điều chính yếu ở đây là bạn đang giữ nguyên tắc Đóng mở của RẮN


1

TL; DR

Để trả lời câu hỏi, bây giờ tôi đang gặp khó khăn khi nghĩ về một enum thời gian không phải là một mùi mã ở một mức độ nào đó. Có một ý định nhất định mà họ tuyên bố một cách hiệu quả (có giới hạn rõ ràng, số lượng khả năng hạn chế cho giá trị này), nhưng bản chất khép kín vốn có của họ khiến họ kém về mặt kiến ​​trúc.

Xin lỗi khi tôi cấu trúc lại hàng tấn mã kế thừa của mình. / thở dài; ^ D


Nhưng tại sao?

Đánh giá khá tốt tại sao đó là trường hợp từ LosTechies ở đây :

// calculate the service fee
public double CalculateServiceFeeUsingEnum(Account acct)
{
    double totalFee = 0;
    foreach (var service in acct.ServiceEnums) { 

        switch (service)
        {
            case ServiceTypeEnum.ServiceA:
                totalFee += acct.NumOfUsers * 5;
                break;
            case ServiceTypeEnum.ServiceB:
                totalFee += 10;
                break;
        }
    }
    return totalFee;
} 

Điều này có tất cả các vấn đề tương tự như mã ở trên. Khi ứng dụng trở nên lớn hơn, cơ hội có các báo cáo chi nhánh tương tự sẽ tăng lên. Ngoài ra, khi bạn triển khai nhiều dịch vụ cao cấp hơn, bạn sẽ phải liên tục sửa đổi mã này, vi phạm Nguyên tắc Đóng mở. Có những vấn đề khác ở đây quá. Hàm tính phí dịch vụ không cần biết số tiền thực tế của từng dịch vụ. Đó là thông tin cần được gói gọn.

Một chút sang một bên: enums là một cấu trúc dữ liệu rất hạn chế. Nếu bạn không sử dụng enum cho mục đích thực sự của nó, một số nguyên có nhãn, bạn cần một lớp để thực sự mô hình hóa sự trừu tượng một cách chính xác. Bạn có thể sử dụng lớp Enumutions tuyệt vời của Jimmy để sử dụng các lớp để sử dụng chúng làm nhãn.

Hãy cấu trúc lại cái này để sử dụng hành vi đa hình. Những gì chúng ta cần là sự trừu tượng sẽ cho phép chúng ta chứa hành vi cần thiết để tính phí cho một dịch vụ.

public interface ICalculateServiceFee
{
    double CalculateServiceFee(Account acct);
}

...

Bây giờ chúng tôi có thể tạo các triển khai cụ thể của giao diện và đính kèm [vào] tài khoản.

public class Account{
    public int NumOfUsers{get;set;}
    public ICalculateServiceFee[] Services { get; set; }
} 

public class ServiceA : ICalculateServiceFee
{
    double feePerUser = 5; 

    public double CalculateServiceFee(Account acct)
    {
        return acct.NumOfUsers * feePerUser;
    }
} 

public class ServiceB : ICalculateServiceFee
{
    double serviceFee = 10;
    public double CalculateServiceFee(Account acct)
    {
        return serviceFee;
    }
} 

Một trường hợp thực hiện khác ...

Điểm mấu chốt là nếu bạn có hành vi phụ thuộc vào giá trị enum, tại sao không thay vào đó có các triển khai khác nhau của một giao diện tương tự hoặc lớp cha đảm bảo giá trị đó tồn tại? Trong trường hợp của tôi, tôi đang xem các thông báo lỗi khác nhau dựa trên mã trạng thái REST. Thay vì...

private static string _getErrorCKey(int statusCode)
{
    string ret;

    switch (statusCode)
    {
        case StatusCodes.Status403Forbidden:
            ret = "BRANCH_UNAUTHORIZED";
            break;

        case StatusCodes.Status422UnprocessableEntity:
            ret = "BRANCH_NOT_FOUND";
            break;

        default:
            ret = "BRANCH_GENERIC_ERROR";
            break;
    }

    return ret;
}

... Có lẽ tôi nên bọc mã trạng thái trong các lớp.

public interface IAmStatusResult
{
    int StatusResult { get; }    // Pretend an int's okay for now.
    string ErrorKey { get; }
}

Sau đó, mỗi lần tôi cần một loại IAmStatusResult mới, tôi mã hóa nó ...

public class UnauthorizedBranchStatusResult : IAmStatusResult
{
    public int StatusResult => 403;
    public string ErrorKey => "BRANCH_UNAUTHORIZED";
}

... và bây giờ tôi có thể đảm bảo rằng mã trước đó nhận ra nó có IAmStatusResultphạm vi và tham chiếu đến nóentity.ErrorKey thay vì thời hạn dài hơn, phức tạp hơn _getErrorCode(403).

Và, quan trọng hơn, mỗi khi tôi thêm một loại giá trị trả về mới, không cần thêm mã nào khác để xử lý nó . Whaddya biết, enumswitch có khả năng có mùi.

Lợi nhuận.


Làm thế nào về trường hợp, ví dụ, tôi các lớp đa hình và tôi muốn cấu hình cái nào tôi đang sử dụng thông qua một tham số dòng lệnh? Dòng lệnh -> enum -> switch / map -> triển khai có vẻ là một trường hợp sử dụng khá hợp pháp. Tôi nghĩ điều quan trọng là enum được sử dụng để phối hợp, không phải là một triển khai logic có điều kiện.
Ant P

@AntP Tại sao không, trong trường hợp này, sử dụng StatusResultgiá trị? Bạn có thể lập luận rằng enum hữu ích như một phím tắt đáng nhớ của con người trong trường hợp sử dụng đó, nhưng có lẽ tôi vẫn gọi đó là mùi mã, vì có những lựa chọn thay thế tốt không yêu cầu bộ sưu tập đóng.
ruffin

Lựa chọn thay thế nào? Một chuỗi? Đó là một sự phân biệt tùy ý theo quan điểm của "enums nên được thay thế bằng đa hình" - một trong hai cách tiếp cận bắt buộc ánh xạ một giá trị thành một loại; tránh enum trong trường hợp này không đạt được gì.
Ant P

@AntP Tôi không chắc chắn nơi dây được băng qua đây. Nếu bạn tham chiếu một thuộc tính trên một giao diện, bạn có thể ném xung quanh giao diện đó bất cứ nơi nào cần thiết và không bao giờ cập nhật mã đó khi bạn tạo một triển khai mới (hoặc xóa hiện tại) của giao diện đó . Nếu bạn có một enum, bạn đừng có mã cập nhật mỗi khi bạn thêm hoặc loại bỏ một giá trị, và có khả năng rất nhiều nơi, tùy thuộc vào cách bạn cấu trúc mã của bạn. Sử dụng đa hình thay vì enum giống như đảm bảo mã của bạn ở dạng bình thường Boyce-Codd .
ruffin

Đúng. Bây giờ giả sử bạn có N triển khai đa hình như vậy. Trong bài viết của Los Techies, họ chỉ đơn giản là lặp đi lặp lại qua tất cả chúng. Nhưng điều gì sẽ xảy ra nếu tôi muốn áp dụng có điều kiện chỉ một cách thực hiện dựa trên các tham số dòng lệnh? Bây giờ chúng ta phải xác định ánh xạ từ một số giá trị cấu hình sang một số loại triển khai có thể tiêm được. Một enum trong trường hợp này là tốt như bất kỳ loại cấu hình khác. Đây là một ví dụ về tình huống không còn cơ hội nào để thay thế "enum bẩn" bằng đa hình. Chi nhánh bằng cách trừu tượng chỉ có thể đưa bạn đến nay.
Ant P

0

Việc sử dụng enum có phải là mùi mã hay không phụ thuộc vào ngữ cảnh. Tôi nghĩ rằng bạn có thể nhận được một số ý tưởng để trả lời câu hỏi của bạn nếu bạn xem xét vấn đề biểu hiện . Vì vậy, bạn có một bộ sưu tập các loại khác nhau và một tập hợp các hoạt động trên chúng và bạn cần tổ chức mã của mình. Có hai lựa chọn đơn giản:

  • Tổ chức mã theo các hoạt động. Trong trường hợp này, bạn có thể sử dụng phép liệt kê để gắn thẻ các loại khác nhau và có câu lệnh chuyển đổi trong mỗi quy trình sử dụng dữ liệu được gắn thẻ.
  • Tổ chức mã theo các loại dữ liệu. Trong trường hợp này, bạn có thể thay thế phép liệt kê bằng một giao diện và sử dụng một lớp cho mỗi thành phần của phép liệt kê. Sau đó, bạn thực hiện mỗi hoạt động như một phương thức trong mỗi lớp.

Giải pháp nào tốt hơn?

Nếu, như Karl Bielefeldt đã chỉ ra, các loại của bạn đã được sửa và bạn mong muốn hệ thống phát triển chủ yếu bằng cách thêm các thao tác mới vào các loại này, sau đó sử dụng enum và có câu lệnh chuyển đổi là một giải pháp tốt hơn: mỗi khi bạn cần một thao tác mới, bạn chỉ cần thực hiện một thủ tục mới trong khi bằng cách sử dụng các lớp, bạn sẽ phải thêm một phương thức cho mỗi lớp.

Mặt khác, nếu bạn mong muốn có một bộ hoạt động khá ổn định nhưng bạn nghĩ rằng bạn sẽ phải thêm nhiều loại dữ liệu theo thời gian, sử dụng giải pháp hướng đối tượng sẽ thuận tiện hơn: vì các loại dữ liệu mới phải được triển khai, bạn chỉ cần thực hiện tiếp tục thêm các lớp mới thực hiện cùng một giao diện trong khi nếu bạn đang sử dụng một enum, bạn sẽ phải cập nhật tất cả các câu lệnh chuyển đổi trong tất cả các quy trình sử dụng enum.

Nếu bạn không thể phân loại vấn đề của mình theo một trong hai tùy chọn ở trên, bạn có thể xem xét các giải pháp phức tạp hơn (xem lại ví dụ trang Wikipedia đã trích dẫn ở trên để thảo luận ngắn và tham khảo để đọc thêm).

Vì vậy, bạn nên cố gắng hiểu hướng nào ứng dụng của bạn có thể phát triển, và sau đó chọn một giải pháp phù hợp.

Vì những cuốn sách mà bạn đề cập để đối phó với mô hình hướng đối tượng, không có gì đáng ngạc nhiên khi chúng bị thiên vị khi sử dụng enums. Tuy nhiên, một giải pháp hướng đối tượng không phải lúc nào cũng là lựa chọn tốt nhất.

Tóm lại: enums không nhất thiết phải là một mùi mã.


lưu ý rằng câu hỏi đã được hỏi trong ngữ cảnh của C #, một ngôn ngữ OOP. Ngoài ra, việc nhóm theo hoạt động hoặc theo loại là hai mặt của cùng một đồng tiền rất thú vị, nhưng tôi không thấy một nhóm nào "tốt" hơn mặt khác như bạn mô tả. số lượng mã kết quả là như nhau và các ngôn ngữ OOP đã hỗ trợ tổ chức theo loại. nó cũng tạo ra mã trực quan hơn (dễ đọc).
Dave Cousineau

@DaveCousineau: "Tôi không thấy người này" tốt "hơn người khác như bạn mô tả": Tôi không nói rằng người này luôn tốt hơn người kia. Tôi nói rằng cái này tốt hơn cái kia tùy theo ngữ cảnh. Ví dụ: nếu hoạt động được nhiều hay ít cố định và bạn có kế hoạch thêm các loại mới (ví dụ một GUI với cố định paint(), show(), close() resize()hoạt động và các widget tùy chỉnh) thì cách tiếp cận hướng đối tượng là tốt hơn theo nghĩa là nó cho phép để thêm một loại mới mà không ảnh hưởng đến quá nhiều mã hiện có (về cơ bản bạn thực hiện một lớp mới, đó là một thay đổi cục bộ).
Giorgio

Tôi không thấy là "tốt hơn" như bạn mô tả có nghĩa là tôi không thấy rằng nó phụ thuộc vào tình huống. Số lượng mã bạn phải viết là hoàn toàn giống nhau trong cả hai kịch bản. Sự khác biệt duy nhất là một cách là phản đối với OOP (enums) và một cách là không.
Dave Cousineau

@DaveCousineau: Số lượng mã bạn phải viết có thể giống nhau, địa phương (địa điểm trong mã nguồn mà bạn phải thay đổi và biên dịch lại) thay đổi mạnh mẽ. Ví dụ, trong OOP, nếu bạn thêm một phương thức mới vào một giao diện, bạn phải thêm một triển khai cho mỗi lớp thực hiện giao diện đó.
Giorgio

Không phải nó chỉ là vấn đề về chiều sâu VS sao? Thêm 1 phương thức vào 10 tệp hoặc 10 phương thức vào 1 tệp.
Dave Cousineau
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.