Должны ли функции возвращать null или пустой объект?

Какова наилучшая практика при возврате данных из функций. Лучше ли возвращать нулевой или пустой объект? И почему нужно делать одно над другим?

Рассмотрим это:

public UserEntity GetUserById(Guid userId)
{
     //Imagine some code here to access database.....

     //Check if data was returned and return a null if none found
     if (!DataExists)
        return null; 
        //Should I be doing this here instead? 
        //return new UserEntity();  
     else
        return existingUserEntity;
}

Давайте сделаем вид, что в этой программе будут действительные случаи, что в базе данных с этим GUID не будет никакой информации о пользователе. Я бы предположил, что было бы нецелесообразно бросать исключение в этом случае? Также у меня создается впечатление, что обработка исключений может повредить производительность.

Ответ 1

Возвращение null обычно является наилучшей идеей, если вы намереваетесь указать, что данные отсутствуют.

Пустой объект означает, что данные были возвращены, тогда как возврат null явно указывает, что ничего не было возвращено.

Кроме того, при возврате нуля будет получено исключение null, если вы попытаетесь получить доступ к элементам в объекте, что может быть полезно для выделения багги-кода - попытка получить доступ к элементу ничего не имеет смысла. Доступ к членам пустого объекта не будет невозможен, поскольку ошибки могут быть неоткрытыми.

Ответ 2

Это зависит от того, что имеет наибольшее значение для вашего дела.

Имеет ли смысл возвращать нуль, например. "нет такого пользователя существует?"

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

Или имеет смысл генерировать исключение (a la "FileNotFound" ), если вызывающий код требует пользователя с недопустимым идентификатором?

Однако - из разделения проблем/точки зрения SRP, первые два являются более правильными. И технически первое является самым правильным (но только с волосами) - GetUserById должен отвечать только за то, что нужно - получить пользователя. Обращение с собственным "пользователем не существует", возвращая что-то другое, может быть нарушением SRP. Разделение на другую проверку - bool DoesUserExist(id) было бы подходящим, если вы решите выбросить исключение.

Основываясь на обширных комментариях ниже: если это вопрос дизайна на уровне API, этот метод может быть аналогичен "OpenFile" или "ReadEntireFile". Мы "открываем" пользователя из некоторого репозитория и увлажняем объект из результирующих данных. В этом случае может быть целесообразным исключение. Возможно, это не так, но это может быть так.

Все подходы приемлемы - это просто зависит от более широкого контекста API/приложения.

Ответ 3

Лично я использую NULL. Он дает понять, что нет данных для возврата. Но бывают случаи, когда полезно Null Object.

Ответ 4

Если ваш тип возвращаемого значения является массивом, тогда возвращаем пустой массив, иначе возвращаем значение null.

Ответ 5

Вы должны выбросить исключение (только), если конкретный контракт нарушен.
В вашем конкретном примере, запрашивая UserEntity на основе известного Id, это будет зависеть от того, являются ли отсутствующие (удаленные) пользователи ожидаемым. Если это так, верните null, но если это не ожидаемый случай, то выполните исключение.
Обратите внимание, что если функция была вызвана UserEntity GetUserByName(string name), она, вероятно, не выдавала бы, а возвращала значение null. В обоих случаях возврат пустой UserEntity будет бесполезным.

Для строк, массивов и коллекций ситуация обычно различна. Я помню некоторую директивную форму MS, что методы должны принимать null как "пустой" список, но возвращать коллекции нулевой длины, а не null. То же самое для строк. Обратите внимание, что вы можете объявлять пустые массивы: int[] arr = new int[0];

Ответ 6

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

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

Если отсутствующий пользователь в порядке, (один из возможных нормальных результатов вызова этой функции), верните нуль....

EDIT: (чтобы ответить на комментарий от Адама в другом ответе)

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

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

Ответ 7

Я лично вернул бы null, потому что так я мог ожидать, что будет действовать слой DAL/Repository.

Если этого не существует, не возвращайте ничего, что могло бы быть истолковано как успешное извлечение объекта, null прекрасно работает здесь.

Самое главное - быть последовательным в вашем DAL/Repos Layer, так что вы не путаетесь, как его использовать.

Ответ 8

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

public void GetUserById(Guid id, UserCallback callback)
{
    // Lookup user
    if (userFound)
        callback(userEntity);  // or callback.Call(userEntity);
}

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

public void GetUserById(Guid id, UserCallback callback, NotFoundCallback notFound)
{
    // Lookup user
    if (userFound)
        callback(userEntity);  // or callback.Call(userEntity);
    else
        notFound(); // or notFound.Call();
}

Такой же подход с использованием одного объекта может выглядеть так:

public void GetUserById(Guid id, UserCallback callback)
{
    // Lookup user
    if (userFound)
        callback.Found(userEntity);
    else
        callback.NotFound();
}

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

Ответ 9

Я бы сказал, возвращать null вместо пустого объекта.

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

Это правило, которое я обычно придерживаюсь:

  • Если результат не найден в результате операции первичного ключа, throw ObjectNotFoundException.
  • Если результат не найден в поиске по каким-либо другим критериям, return null.
  • Если результат не найден в поиске по неключевым критериям, которые могут возвращать несколько объектов вернуть пустую коллекцию.

Ответ 10

Мы используем CSLA.NET, и он считает, что неудавшаяся выборка данных должна возвращать "пустой" объект. Это на самом деле довольно раздражает, так как это требует соглашения о проверке того, obj.IsNew скорее, чем obj == null.

Как упоминалось в предыдущем плакате, значения null возвращают код немедленно, что уменьшает вероятность скрытых проблем, вызванных пустыми объектами.

Лично я думаю, что null более изящный.

Это очень распространенный случай, и я удивлен тем, что люди здесь удивляются: на любом веб-приложении данные часто извлекаются с использованием параметра querystring, который, очевидно, может быть искажен, поэтому требуется, чтобы разработчик обрабатывал случаи "не найден".

Вы можете справиться с этим:

if (User.Exists(id)) {
  this.User = User.Fetch(id);
} else {
  Response.Redirect("~/notfound.aspx");
}

... но это дополнительный вызов в базу данных каждый раз, что может быть проблемой на страницах с высоким трафиком. Принимая во внимание:

this.User = User.Fetch(id);

if (this.User == null) {
  Response.Redirect("~/notfound.aspx");
}

... требуется только один вызов.

Ответ 11

Я предпочитаю null, так как он совместим с оператором с нулевой связностью (??).

Ответ 12

Я склонен к

  • return null, если идентификатор объекта не существует, если неизвестно заранее, существует ли .
  • throw, если идентификатор объекта не существует, если он должен.

Я различаю эти два сценария с этими тремя типами методов. Во-первых:

Boolean TryGetSomeObjectById(Int32 id, out SomeObject o)
{
    if (InternalIdExists(id))
    {
        o = InternalGetSomeObject(id);

        return true;
    }
    else
    {
        return false;
    }
}

Во-вторых:

SomeObject FindSomeObjectById(Int32 id)
{
    SomeObject o;

    return TryGetObjectById(id, out o) ? o : null;
}

Третье:

SomeObject GetSomeObjectById(Int32 id)
{
    SomeObject o;

    if (!TryGetObjectById(id, out o))
    {
        throw new SomeAppropriateException();
    }

    return o;
}

Ответ 13

Он будет меняться в зависимости от контекста, но я, как правило, возвращаю null, если я ищу один конкретный объект (как в вашем примере) и возвращу пустую коллекцию, если я ищу набор объектов, но их нет.

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

Ответ 14

Лучшее в этом случае возвращает "null" в случае отсутствия такого пользователя. Также сделайте свой метод статическим.

Edit:

Обычно такие методы являются членами некоторого класса "Пользователь" и не имеют доступа к его членам экземпляра. В этом случае метод должен быть статическим, иначе вы должны создать экземпляр "Пользователь" , а затем вызвать метод GetUserById, который вернет другой экземпляр "Пользователь" . Согласитесь, это сбивает с толку. Но если метод GetUserById является членом некоторого класса "DatabaseFactory" - не проблема оставить его в качестве члена экземпляра.

Ответ 15

В наших бизнес-объектах у нас есть 2 основных метода Get:

Чтобы вещи были простыми в контексте или вы сомневались, что они будут:

// Returns null if user does not exist
public UserEntity GetUserById(Guid userId)
{
}

// Returns a New User if user does not exist
public UserEntity GetNewOrExistingUserById(Guid userId)
{
}

Первый метод используется при получении определенных сущностей, второй метод используется специально при добавлении или редактировании объектов на веб-страницах.

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

Ответ 16

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

Что касается предположения, что это вопрос бизнес-домена - я просто не вижу его с этой стороны уравнения. Нормализация возвращаемых типов является допустимым вопросом архитектуры приложения. По крайней мере, он подлежит стандартизации в практике кодирования. Я сомневаюсь, что есть бизнес-пользователь, который собирается сказать "в сценарии X, просто дайте им нуль".

Ответ 17

Я студентка французского ИТ, поэтому извиняюсь за мой бедный английский. В наших классах нам говорят, что такой метод никогда не должен возвращать нулевой или пустой объект. Пользователь этого метода должен сначала проверить, что объект, который он ищет, существует, прежде чем пытаться его получить.

Используя Java, нас попросят добавить assert exists(object) : "You shouldn't try to access an object that doesn't exist"; в начале любого метода, который мог бы вернуть null, чтобы выразить "предварительное условие" (я не знаю, что это слово на английском языке).

IMO это действительно не просто использовать, а то, что я использую, ожидая чего-то лучшего.

Ответ 18

Если случай не найденного пользователя возникает достаточно часто, и вы хотите иметь дело с ним различными способами в зависимости от обстоятельств (иногда бросая исключение, иногда заменяя пустого пользователя), вы также можете использовать что-то близкое к F # Option или Haskell Maybe, который явно отделяет случай "нет значения" от "найденного!". Код доступа к базе данных может выглядеть следующим образом:

public Option<UserEntity> GetUserById(Guid userId)
{
 //Imagine some code here to access database.....

 //Check if data was returned and return a null if none found
 if (!DataExists)
    return Option<UserEntity>.Nothing; 
 else
    return Option.Just(existingUserEntity);
}

И будет использоваться следующим образом:

Option<UserEntity> result = GetUserById(...);
if (result.IsNothing()) {
    // deal with it
} else {
    UserEntity value = result.GetValue();
}

К сожалению, все, похоже, используют такой тип, как это.

Ответ 19

Я обычно возвращаю null. Он обеспечивает быстрый и легкий механизм для обнаружения, если что-то прикручивается, не бросая исключений, и использует тонны попытки/уловить повсюду.

Ответ 20

Для типов коллекций я бы возвращал пустую коллекцию, для всех остальных типов я предпочитаю использовать шаблоны NullObject для возврата объекта, который реализует тот же интерфейс, что и возвращающий тип. для получения дополнительной информации о шаблоне текст ссылки

Используя шаблон NullObject, это будет: -

public UserEntity GetUserById(Guid userId)

{    // Представьте себе некоторый код для доступа к базе данных.....

 //Check if data was returned and return a null if none found
 if (!DataExists)
    return new NullUserEntity(); //Should I be doing this here instead? return new UserEntity();  
 else
    return existingUserEntity;

}

class NullUserEntity: IUserEntity { public string getFirstName(){ return ""; } ...} 

Ответ 21

Поставить то, что другие сказали более грубо...

Исключения для исключительных обстоятельств

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

С другой стороны, если бы я ожидал, что мой параметр будет отображать первичный ключ, и я должен получить только строку one, если я получил больше одного, я бы выбрал исключение. 0 нормально возвращать null, 2 не является.

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

Теперь я скажу, что это общее правило. Бывают моменты, когда вы можете это сломать. Тем не менее, мой опыт и эксперименты с С# (многие из них) и Java (немного того) научили меня, что гораздо более дорогостоящая производительность имеет дело с исключениями, чем для обработки прогнозируемых проблем с помощью условной логики. В некоторых случаях я говорю с мелодией на 2-3 порядка дороже. Итак, если это возможно, ваш код может закончиться в цикле, тогда я бы посоветовал вернуть нуль и тестирование для него.

Ответ 22

Простите мой псевдо-php/код.

Я думаю, что это действительно зависит от предполагаемого использования результата.

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

Скажем, у меня есть функция, которая берет первичный ключ и массив данных, заполняет строку данными, а затем сохраняет итоговую запись в db. Поскольку я собираюсь заполнить объект своими данными в любом случае, это может быть огромным преимуществом, чтобы вернуть пустой объект из геттера. Таким образом, я могу выполнять идентичные операции в любом случае. Вы используете результат функции getter независимо от того, что.

Пример:

function saveTheRow($prim_key, $data) {
    $row = getRowByPrimKey($prim_key);

    // Populate the data here

    $row->save();
}

Здесь мы видим, что одна и та же серия операций манипулирует всеми записями этого типа.

Однако, если конечная цель возвращаемого значения состоит в том, чтобы читать и делать что-то с данными, тогда я возвращаю значение null. Таким образом, я могу очень быстро определить, не было ли возвращено данных и отобразить соответствующее сообщение пользователю.

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

Пример:

function displayData($row_id) {
    // Logging of the error would happen in this function
    $row = getRow($row_id);
    if($row === null) {
        // Handle the error here
    }

    // Do stuff here with data
}

function getRow($row_id) {
 $row = null;
 try{
     if(!$db->connected()) {
   throw excpetion("Couldn't Connect");
  }

  $result = $db->query($some_query_using_row_id);

  if(count($result) == 0 ) {
   throw new exception("Couldn't find a record!");
  }

  $row = $db->nextRow();

 } catch (db_exception) {
  //Log db conn error, alert admin, etc...
  return null; // This way I know that null means an error occurred
 }
 return $row;
}

Это мое общее правило. До сих пор он работал хорошо.

Ответ 23

Интересный вопрос, и я думаю, что нет "правильного" ответа, поскольку он всегда зависит от ответственности вашего кода. Знает ли ваш метод, нет ли найденных данных или нет? В большинстве случаев ответ "нет", и почему возвращение null и разрешение обработки вызывающего абонента на него является идеальной.

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

Ответ 24

Если возвращаемый объект является чем-то, что можно повторить, я бы возвратил пустой объект, так что мне не нужно сначала проверять значение null.

Пример:

bool IsAdministrator(User user)
{
    var groupsOfUser = GetGroupsOfUser(user);

    // This foreach would cause a run time exception if groupsOfUser is null.
    foreach (var groupOfUser in groupsOfUser) 
    {
        if (groupOfUser.Name == "Administrators")
        {
            return true;
        }
    }

    return false;
}

Ответ 25

Мне нравится не возвращать null из любого метода, а вместо этого использовать функциональный тип Option. Методы, которые не могут возвращать результат, возвращают пустой параметр, а не null.

Кроме того, такие методы, которые не могут возвращать результат, должны указывать, что их имя. Я обычно добавляю Try или TryGet или TryFind в начале имени метода, чтобы указать, что он может вернуть пустой результат (например, TryFindCustomer, TryLoadFile и т.д.).

Это позволяет вызывающему использовать различные методы, такие как конвейерная обработка коллекции (см. Martin Fowler Сборник трубопроводов) на результат.

Вот еще один пример, в котором для уменьшения сложности кода используется возвращаемый вариант вместо значения null: Как уменьшить циклическую сложность: опция Функциональный тип

Ответ 26

Больше мяса для измельчения: пусть говорят, что мой DAL возвращает NULL для GetPersonByID, как советовали некоторые. Что должен сделать мой (довольно тонкий) BLL, если он получит NULL? Передайте этот NULL и позвольте конечному потребителю беспокоиться об этом (в данном случае странице ASP.Net)? Как насчет того, чтобы BLL выбрал исключение?

BLL может использоваться ASP.Net и Win App или другой библиотекой классов - я считаю несправедливым ожидать, что конечный потребитель по существу "знает", что метод GetPersonByID возвращает нуль (если не используются типы нулей, Я думаю).

Мой прием (для чего он стоит) заключается в том, что мой DAL возвращает NULL, если ничего не найдено. ДЛЯ НЕКОТОРЫХ ОБЪЕКТОВ, это нормально - это может быть список из 0: много, поэтому нет никаких вещей в порядке (например, список любимых книг). В этом случае мой BLL возвращает пустой список. Для большинства объектов единственной сущности (например, пользователя, учетной записи, счета-фактуры), если у меня ее нет, то это определенно проблема и бросок дорогостоящего исключения. Однако, видя, как поиск пользователя по уникальному идентификатору, который ранее был задан приложением, должен всегда возвращать пользователя, исключение является "правильным" исключением, как в нем исключительным. Конечный потребитель BLL (ASP.Net, f'rinstance) только когда-либо ожидает, что ситуация будет сложной, поэтому вместо того, чтобы обернуть каждый вызов GetPersonByID в блок try-catch, будет использоваться обработчик необработанных исключений.

Если в моем подходе есть вопиющая проблема, сообщите мне, поскольку я всегда очень хочу учиться. Как отмечали другие плакаты, исключения - дорогостоящие вещи, а "проверка первого" подхода хороша, но исключения должны быть именно такими - исключительными.

Мне нравится этот пост, много хороших предложений для сценариев "это зависит": -)

Ответ 27

Я озадачен количеством ответов (по всему Интернету), в которых говорится, что вам нужны два метода: метод IsItThere() и метод GetItForMe(), и это приводит к состоянию гонки. Что не так с функцией, которая возвращает null, присваивая ее переменной и проверяя переменную для Null все в одном тесте? Мой прежний код C был наперт с помощью

if (NULL!= (variable = function (arguments...))) {

Итак, вы получаете значение (или null) в переменной, а результат - сразу. Неужели эта идиома была забыта? Почему?

Ответ 28

Я согласен с большинством сообщений здесь, которые имеют тенденцию к null.

Мое рассуждение состоит в том, что генерация пустого объекта с непустыми свойствами может приводить к ошибкам. Например, объект с атрибутом int ID имеет начальное значение ID = 0, которое является полностью допустимым значением. Если этот объект, при некоторых обстоятельствах, будет сохранен в базе данных, это будет плохо.

Для чего-либо с итератором я бы всегда использовал пустую коллекцию. Что-то вроде

foreach (var eachValue in collection ?? new List<Type>(0))

- это запах кода, на мой взгляд. Свойства коллекции не должны быть пустыми.

Края края String. Многие говорят, что String.IsNullOrEmpty не является действительно необходимым, но вы не можете всегда различать пустую строку и null. Кроме того, некоторые системы баз данных (Oracle) не будут различать их вообще ('' хранится как DBNULL), поэтому вы вынуждены обрабатывать их одинаково. Причиной этого является то, что большинство строковых значений поступают от пользовательского ввода или от внешних систем, в то время как ни текстовые, ни большинство форматов обмена не имеют разных представлений для '' и null. Поэтому, даже если пользователь хочет удалить значение, он не может ничего сделать, кроме как очистить входной элемент управления. Кроме того, отличие полей с нулевым и не нулевым nvarchar базами данных более чем сомнительно, если ваша СУБД не является оракулом - обязательное поле, которое позволяет '' странно, ваш пользовательский интерфейс никогда не позволит этого, поэтому ваши ограничения не отображают, Поэтому ответ здесь, на мой взгляд, обрабатывает их одинаково, всегда.

Относительно вашего вопроса относительно исключений и производительности: Если вы выбросите исключение, которое вы не можете полностью обработать в своей программной логике, в какой-то момент вам необходимо прекратить работу вашей программы и попросить пользователя повторить все, что он только что сделал. В этом случае оценка производительности catch на самом деле является наименьшей из ваших забот - попросить пользователя слона в комнате (что означает повторную визуализацию всего пользовательского интерфейса или отправку некоторого HTML через Интернет). Поэтому, если вы не следуете анти-шаблону " "Поток программы с исключениями" , не беспокойтесь, просто выбросьте его, если это имеет смысл. Даже в пограничных случаях, таких как" Validation Exception", производительность действительно не проблема, так как вы должны спросить пользователя снова, в любом случае.

Ответ 29

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

Будет существовать большое количество защитных предложений, обрабатывающих нулевую ссылку if (f() != null).

Что такое null, это приемлемый ответ или проблема? Является ли null допустимым для определенного объекта? (представьте, что вы являетесь клиентом для кода). Я имею в виду, что все ссылочные типы могут быть нулевыми, но должны ли они?

Наличие null зависания почти всегда дает несколько неожиданных исключений NullRef время от времени по мере роста вашей базы кода.

Существуют некоторые решения, tester-doer pattern или реализация option type от функционального программирования.

Ответ 30

Вы должны исключать исключение, если это исключительное обстоятельство, что вы вызываете этот код с недопустимым идентификатором пользователя. Если это НЕ исключительное обстоятельство, то то, что вы по существу делаете, это использовать метод "getter", чтобы проверить, существует ли пользователь или нет. Это похоже на попытку открыть файл, чтобы узнать, существует ли он или нет (давайте придерживаемся С#/java здесь) вместо использования метода exist или пытаемся получить доступ к элементам словаря и видеть, существуют ли они, если посмотреть на возвращаемое значение вместо сначала используйте метод "содержит".

Поэтому, скорее всего, вы следуете за дополнительным методом, таким как "существует", чтобы сначала проверить, есть ли такой пользователь. Выполнение исключений, безусловно, не является основанием для того, чтобы просто не использовать их вообще, если у вас нет проблем с производительностью.