Запутался с объяснением дяди Боба об обработке пустых объектов в книге «Чистый код» - PullRequest
4 голосов
/ 16 июня 2011

Сегодня я читал книгу дяди Боба по обработке исключений, и что я мог вспомнить из обработки нулевых значений, так это то, что методы не должны обрабатывать нулевые значения, потому что это загромождает код.Я немного смущен этим.Я всегда думал, что метод должен всегда следить за тем, чтобы его зависимости не были нулевыми (если они не введены в конструктор и конструктор не гарантирует обнуляемость).Например, если у меня есть метод

public void SendMessage(IEmailSender emailSender, contactList list)
{
    if(emailSender == null)
    {
         throw new ArgumentNullException("Failed to send  
                message.",MethodBase.GetCurrentMethod().GetParameters[0].Name);
    }
    if(list == null)
    {
         throw new ArgumentNullException("Failed to send  
                message.",MethodBase.GetCurrentMethod().GetParameters[1].Name);
    }

    // rest of code goes here

}

Я что-то упустил?

Ответы [ 3 ]

3 голосов
/ 14 июля 2011

Есть две перспективы:
С одной стороны, с вашим подходом вы всегда говорите вызывающему, что именно он сделал неправильно, вызывая ваш метод. Это здорово для звонящего, потому что он может исправить это сразу, когда получит ваше исключение. Это будет верно и допустимо, если вы пишете код API, который используется третьей стороной.

С другой стороны, если вы вызываете свой метод самостоятельно, разумным аргументом для создания исключения является то, что вы хотите иметь возможность обрабатывать эту ситуацию с помощью блока catch внутри вашего вызывающего кода! Если у вас нет причин где-то с этим справляться, зачем вообще выкидывать исключение? Единственная причина, которую я вижу, состоит в том, чтобы вести подробный журнал ошибок, перехватывая эти исключения в GlobalExceptionHandler.

Итак, вы видите, что здесь есть две категории исключений: одна для разработчиков, чтобы избежать неправильного использования API, и другая, которая будет использоваться в качестве результата ошибки метода.

Если вы пишете код API, который будет использоваться другими, ваш выбор будет не слушать Боба; -)

Для тех, кто не читал CleanCode, Боб предлагает две вещи:

1.Не следует писать методы, которые возвращают ноль (чтобы впоследствии избежать ненужных проверок). Так что вместо того, чтобы писать это:

var myObject = GetObjectThatDoesSomthing();  
if(myObject != null)  
{  
myObject.DoSomething();  
}

... вы должны быть в состоянии написать это:

var myObject = GetObjectThatDoesSomething();  
myObject.DoSomething();  

очиститель.

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

public Point Add(Point p1, Point p2)  
{  
    if(p1 == null) throw ArgumentException();  
    if(p2 == null) throw ArgumentException(); 
    ... 
}

Смысл этих правил: если вы будете придерживаться его, вы знаете, что вам не нужно писать эти нулевые проверки, и ваш код становится чище и легче для чтения. Но в тот момент, когда вы используете сторонний код, вы не можете определить, применяли ли они те же правила в своем API, поэтому вы начинаете повторную предварительную или последующую проверку. То же самое, когда вы пишете API для других: как потребители вашего API знают, что вы запрограммировали правила Бобса ...

3 голосов
/ 16 июня 2011

Я не читал книгу, но могу только представить, что дядя Боб выступает за использование шаблона нулевого объекта вместо явной обработки нулевой ссылки.

например, а не

if(log != null)
  log.Write("My log message");

Вместо этого можно создать интерфейс ILogger, содержащий метод Write, и создать два класса, реализующих этот интерфейс: NullLogger и FileLogger. У NullLogger будет пустое тело для реализации метода Write.

На мой взгляд, это отличается от вашей явной проверки предварительных условий, которую вы имеете в своем примере

1 голос
/ 19 июля 2011

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

Если вы пишете закрытый метод, который используется только изтот же класс или некоторый внутренний, вызываемый другим дружественным классом, также написанным вами или вашим соавтором, имеет меньше смысла делать проверки паранойи нулевыми.Ваш инжекционный проект и тесты должны гарантировать, что ваши внутренние компоненты не получают нулевые значения.

И если параметры частного / внутреннего метода по-прежнему получают нулевые значения, это все равно слишком поздно.Бросок исключения ArgumentNull из частного / внутреннего метода не помогает внешнему пользователю устранить причину, поэтому для него не имеет значения, получить ли исключение ArgumentNull или NullReference.

...