2008-09-16 26 views
19

Hãy để tôi bắt đầu bằng cách nói rằng tôi không ủng hộ cách tiếp cận này, nhưng tôi đã nhìn thấy nó gần đây và tôi đã tự hỏi nếu có một tên cho nó tôi có thể sử dụng để chỉ các bên có tội đến. Vì vậy, ở đây đi.Có tên nào cho mùi chống mẫu/mã này không?

Bây giờ bạn có một phương thức và bạn muốn trả về một giá trị. Bạn cũng muốn trả lại mã lỗi. Tất nhiên, ngoại lệ là một lựa chọn tốt hơn nhiều, nhưng vì lý do nào đó bạn muốn có một mã lỗi thay thế. Hãy nhớ rằng, tôi đang chơi người ủng hộ ma quỷ ở đây. Vì vậy, bạn tạo ra một lớp chung chung, như thế này:

class FunctionResult<T> 
{ 
    public T payload; 
    public int result; 
} 

Và sau đó tuyên bố chức năng của bạn như thế này:

FunctionResult<string> MyFunction() 
{ 
    FunctionResult<string> result; 
    //... 

    return result; 
} 

Một biến thể của mô hình này là sử dụng một enum cho mã lỗi thay vì một chuỗi . Bây giờ, trở lại câu hỏi của tôi: có một cái tên cho điều này không, và nếu có thì nó là gì?

+1

"Ai đó không phải là thằng ngốc sẽ đập ngón tay của tôi bằng một cái búa khi họ nhìn thấy" hình mẫu "này. Nhưng điều đó khá nhiều áp dụng cho tất cả các mẫu đối tượng. – Will

+1

Nếu đây là một mô hình chống, thì khuyến nghị cho các ngôn ngữ không hỗ trợ trực tiếp ngoại lệ là gì (tôi đang nghĩ đến VB/VBA). –

+1

Nếu chúng không hỗ trợ ngoại lệ, chúng có thể không hỗ trợ mẫu/generics. –

Trả lời

17

tôi đồng ý rằng đây không phải là đặc biệt một antipattern. Nó có thể là một mùi tùy thuộc vào cách sử dụng. Có những lý do tại sao một người thực sự không muốn sử dụng ngoại lệ (ví dụ: các lỗi được trả về không phải là 'ngoại lệ', đối với người mới bắt đầu).

Có những trường hợp bạn muốn có một dịch vụ trả lại mô hình chung cho kết quả của nó, bao gồm cả lỗi và giá trị tốt.Điều này có thể được bao bọc bởi một tương tác dịch vụ mức thấp, dịch kết quả thành một ngoại lệ hoặc cấu trúc lỗi khác, nhưng ở mức dịch vụ, nó cho phép dịch vụ trả lại kết quả và mã trạng thái mà không cần phải xác định một số cấu trúc ngoại lệ phải được dịch qua một ranh giới từ xa.

Mã này có thể không nhất thiết phải là lỗi: xem xét phản hồi HTTP, bao gồm nhiều dữ liệu khác nhau, bao gồm mã trạng thái, cùng với nội dung phản hồi.

+0

Tôi vừa mới phát hiện ra mùi của mã và tôi sẽ cấp cho bạn mùi chống mẫu. Tuy nhiên, không chắc chắn cách cập nhật câu hỏi để phản ánh điều đó. –

1

Cách "Không thể quyết định xem đây có phải là lỗi hay không". Có vẻ như nếu bạn thực sự có một ngoại lệ nhưng muốn trả lại một phần kết quả, bạn sẽ kết quả trong trường hợp ngoại lệ.

4

Tôi không chắc đây là một mẫu chống. Tôi thường thấy điều này được sử dụng thay vì ngoại lệ vì lý do hiệu suất, hoặc có lẽ để làm cho thực tế là phương pháp có thể thất bại rõ ràng hơn. Đối với tôi, nó có vẻ là một sở thích cá nhân hơn là chống mẫu.

10

Vâng, đó là không một antipattern. Thư viện chuẩn C++ sử dụng tính năng này và .NET thậm chí còn cung cấp một lớp đặc biệt FunctionResult trong khung công tác .NET. Nó được gọi là Nullable. Có, điều này không bị hạn chế đối với các kết quả chức năng nhưng nó có thể được sử dụng cho các trường hợp như vậy và thực sự rất hữu ích ở đây. Nếu .NET 1.0 đã có lớp Nullable, nó chắc chắn sẽ được sử dụng cho các phương thức NumberType.TryParse, thay vì tham số out.

+0

+1 để biết thông tin chi tiết và kiến ​​thức về thư viện – Cruachan

2

Cách tiếp cận này thực sự tốt hơn nhiều so với một số cách khác mà tôi đã thấy. Ví dụ, một số hàm trong C, khi chúng gặp lỗi, chúng trở lại và dường như thành công. Cách duy nhất để nói rằng họ thất bại là gọi một hàm sẽ nhận được lỗi mới nhất.

Tôi đã dành hàng giờ cố gắng gỡ lỗi mã semaphore trên MacBook của mình trước khi cuối cùng tôi phát hiện ra rằng sem_init không hoạt động trên OSX! Nó biên dịch mà không có lỗi và chạy mà không gây ra bất kỳ lỗi nào - nhưng semaphore không hoạt động và tôi không thể hiểu tại sao. Tôi thương hại những người mà cổng một ứng dụng sử dụng POSIX semaphores để OSX và phải đối phó với các vấn đề tranh chấp tài nguyên đã được gỡ lỗi.

6

Tôi thường chuyển tải trọng dưới dạng tham chiếu (không const) và mã lỗi dưới dạng giá trị trả lại.

Tôi là một nhà phát triển trò chơi, chúng tôi xua đuổi ngoại lệ

1

Nếu bạn không muốn sử dụng ngoại lệ, cách tốt nhất để làm là trả về mã lỗi/thành công và tham khảo tham số hoặc đối số con trỏ được điền vào kết quả.

Tôi sẽ không gọi nó là kiểu chống. Đó là một phương pháp khả thi rất tốt, thường thích hợp hơn khi sử dụng các ngoại lệ.

1

Nếu bạn mong đợi phương pháp của bạn thất bại đôi khi, nhưng không coi đó đặc biệt, tôi thích mô hình này được sử dụng trong .NET Framework:

bool TryMyFunction(out FunctionResult result){  

    //...  
    result = new FunctionResult(); 
} 
5

Konrad là đúng, C# sử dụng giá trị trả lại tất cả kép thời gian. Nhưng tôi loại như TryParse, Dictionary.TryGetValue, vv phương pháp trong C#.

int value; 
if (int.TryParse("123", out value)) { 
    // use value 
} 

thay vì

int? value = int.TryParse("123"); 
if (value != null) { 
    // use value 
} 

... chủ yếu là vì các mô hình Nullable không quy mô với các loại lợi nhuận phi giá trị gia tăng (ví dụ, trường lớp). Điều này sẽ không hoạt động với Dictionary.TryGetValue(). Và TryGetValue vừa đẹp hơn KeyNotFoundException (không có "ngoại lệ cơ hội đầu tiên" liên tục trong trình gỡ rối, được cho là hiệu quả hơn), đẹp hơn thực hành của Java get() trả về null (nếu giá trị null được mong đợi), và hiệu quả hơn việc phải gọi ContainsKey() trước tiên.

Nhưng điều này vẫn hơi khó hiểu - vì điều này có vẻ như C#, khi đó nó sẽ sử dụng tham số ngoài. Tất cả lợi ích hiệu quả có thể bị mất do instantiating lớp.

(Có thể là Java trừ các "chuỗi" loại là trong chữ thường. Trong Java dĩ nhiên bạn phải sử dụng một lớp học để thi đua giá trị lợi nhuận kép.)

+0

Các loại không có giá trị đã có giá trị 'null'. 'Nullable' về cơ bản là một nỗ lực để tái tạo điều này cho các loại giá trị. Tất nhiên, ngay khi 'null' là một giá trị chấp nhận được, phương thức này sẽ thất bại. –

3

Tôi đồng ý với những người nói rằng đây không phải là một chống mẫu. Đó là một mẫu hoàn toàn hợp lệ trong các ngữ cảnh nhất định. Trường hợp ngoại lệ dành cho trường hợp đặc biệt, giá trị trả lại (như trong ví dụ của bạn) nên được sử dụng trong các trường hợp dự kiến. Một số miền mong đợi các kết quả hợp lệ và không hợp lệ từ các lớp, và cả hai trường đó đều không được mô hình hóa như các ngoại lệ.

Ví dụ, với lượng khí X, xe có thể lấy từ A đến B hay không và nếu có bao nhiêu khí còn lại? Đó là loại câu hỏi lý tưởng cho cấu trúc dữ liệu bạn cung cấp. Không thể thực hiện chuyến đi từ A đến B, do đó không nên sử dụng ngoại lệ.

0

Trong lời bào chữa của các định chống mẫu, mã này vay chính nó để được sử dụng trong một vài cách sau:.

  1. Object x = MyFunction() tải trọng; (bỏ qua kết quả trả về - rất xấu)
  2. int code = MyFunction(). (vứt bỏ tải trọng - có thể không sao nếu đó là mục đích sử dụng.)
  3. FunctionResult x = MyFunction(); // ... (một loạt các đối tượng FunctionResult thêm và mã thêm để kiểm tra xem chúng khắp nơi)

Nếu bạn cần phải sử dụng mã trở lại, đó là tốt. Nhưng sau đó sử dụng mã trả lại. Đừng cố gắng đóng gói thêm một trọng tải với nó. Đó là những thông số refra (C#) là dành cho. Các loại âm ỉ có thể là một ngoại lệ, nhưng chỉ vì có thêm đường nướng trong ngôn ngữ để hỗ trợ nó.

Nếu bạn vẫn không đồng ý với đánh giá này, hãy DOWNVOTE câu trả lời này (không phải toàn bộ câu hỏi). Nếu bạn nghĩ rằng đó là một mô hình chống, sau đó UPVOTE nó. Chúng tôi sẽ sử dụng câu trả lời này để xem cộng đồng nghĩ gì.

+0

Tôi muốn một cái gì đó như TryParse, một trong những param cho trọng tải, với chức năng trả về kết quả. – Meff

1

Cuộc tranh luận về mùi và chống mẫu nhắc tôi chương trình truyền hình "Survivor", nơi bạn có nhiều cấu trúc lập trình khác nhau cố gắng bỏ phiếu cho nhau. Tôi muốn thấy "xây dựng X có những ưu và khuyết điểm như vậy", chứ không phải là một danh sách các sắc lệnh liên tục phát triển về những gì nên và không nên được thực hiện.

Các vấn đề liên quan