2012-05-23 5 views
2

Этот вопрос аналогичен (подмножестве) this questionтип использования во время выполнения (в C#) для логики расхода

В этом случае она использует тип во время выполнения, чтобы различать между успехом и провалом вернулись результаты.

Довольно часто я вижу следующую картину:

public struct Result { 
    public boolean IsSuccess { get;set;} 
    public string ErrorMessage {get;set;} 
    public int Value {get;set;} 
} 
... 
Result result = someObject.SomeMethod(); 
if (result.IsSuccess) DoSomething(result.Value); 
else handleError(result.ErrorMessage); 

Я думаю, что после более естественно, и выражает намерение более четко (на мой взгляд):

public abstract class Result { } 
public sealed class Failure : Result { 
    public string ErrorMessage { get; set; } 
} 
public sealed class Success : Result { 
    public int Value { get; set; } 
} 
... 
Result result = someObject.SomeMethod(); 
if (result is Success) DoSomething((result as Success).Value); 
else if (result is Failure) handleError((result as Failure).ErrorMessage); 

Также обратите внимание, что .Net (и многие другие языки) используют этот шаблон в блоке try-catch с несколькими предложениями catch (где тип исключения выбирает блок catch).

EDIT: этот шаблон (т.е. полагаясь на тип среды выполнения) идентичен дискриминированных объединений F #, разница в том, что в F # он является родным, а в C# это эмулируются с использованием конструкций, предназначенных для различных целей.

EDIT: Я думаю, что моя основная проблема с первым кодом - это запах кода «частично инициализированный объект». В 100% случаев будет инициализирована только половина объекта. Он также почти нарушает ISP, «почти», потому что когда-то .IsSuccess оценивается, только часть объекта будет использоваться впредь (если это успех только .Result используется, если это свойство ошибки - только ошибки). Решение для проверки типа запуска не имеет этих проблем.

Вопрос в следующем: В чем проблема с использованием этого шаблона? Меня особенно интересуют вопросы из следующих точек зрения: ремонтопригодность, читаемость, тестируемость, концептуальная чистота и ООП/ООД.

+0

Если вы заботитесь о намерении, никогда не используйте «как» для чего-то, что вы уверены. Если результатом является успех, тогда ((Успех)). Значение – Quibblesome

ответ

3

Как правило, я предпочитаю первую форму.

Второй пример требует больше нажатий клавиш и добавляет 4 операции проверки типа. Это также менее очевидно для потребителя (вы не можете путать смысл свойства IsSuccess). Кажется менее логичным выполнить преобразование типа только для того, чтобы определить результат операции (похоже, с использованием исключений для потока программы, вы делаете это , но не должны).

Кроме того, первая форма может служить платформо-независимым механизмом для описания данных. Второе не может. Другими словами, вы можете легко сериализовать тип результата, состоящий из примитивов, и делиться им с любым пользователем, но требуя ограничений проверки типов/исключая эту возможность.

Для улучшения качества вашего объекта Result вы можете сделать коллекцию Messages, которая содержит больше, чем просто строку (возможно, включает код, серьезность, сообщение и т. Д.). Это позволяет всем вашим результатам возвращать сообщения, а не только операции, которые терпят неудачу. Если операция завершилась неудачно, вы можете предположить, что Messages содержит хотя бы одно сообщение об ошибке (и/или запрашивает коллекцию с помощью LINQ, чтобы найти все сообщения, связанные с ошибкой).

+0

Кроме того, последнее намного тяжелее, если мы делаем преждевременную оптимизацию. Хотя структура должна будет хранить свою строку в куче, эта версия на основе классов будет хранить все в куче. – Quibblesome

0

Несколько академическая причина второй формы ошибиться идет что-то вроде:

C#, как язык О.О., разработанный с предположением, что классов будут использоваться для моделирования категории подстилающей системы (бизнес концепции, например), а экземпляры будут использоваться для моделирования фактов.

Использование классов для моделирования фактов является неправильным использованием инструмента.

Хотя я до сих пор не знаю, какие будут практические последствия.

0

Объектно-ориентированный дизайн не важен для информации о выбросах. Этот объект результата имеет очень ограниченный срок службы и поэтому принадлежит к структуре в стеке.

Если вы хотите поговорить о техническом обслуживании/чтении, то люди будут изначально смущены этим кодом.

Если вы хотите перейти объектно-ориентированное на распространение ошибок, тогда используйте исключительно исключения (хотя это приведет к ухудшению производительности этих прецедентов прикосновением).

Смежные вопросы