Вопрос

Предположим, у меня есть метод

public Patient(int id)
{
    ----
}

это возвращает объект Patient с заданным идентификатором..Я мог бы определить контракт двумя способами

  1. Метод вернет значение null, если пациент не существует
  2. Метод выдаст исключение, если пациент не существует.В этом случае я бы также определил метод запроса, который возвращает true, если Пациент существует в базе данных, или false в противном случае...

Какой контракт я должен использовать?Есть еще какие-нибудь предложения?

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

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

И я также думаю, что нулевой шаблон здесь был бы несколько тяжеловесным

Комментарий Роба Уэллса о выбрасывании исключения из-за его неверного идентификатора:я не думаю, что опечатка в имени пациента является исключительным обстоятельством "ИМХО

Это было полезно?

Решение

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

Поэтому стоит структурировать свой API, чтобы избежать избыточных вызовов.

Подумайте, если ваш API похож на это:

// Check to see if a given patient exists
public bool PatientExists(int id);

// Load the specified patient; throws exception if not found
public Patient GetPatient(int id);

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

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

Вот шаблон, который я использовал для хорошего эффекта в прошлом - есть два метода:

// Load the specified patient; throws exception if not found
public Patient GetExistingPatient(int id);

// Search for the specified patient; returns null if not found
public Patient FindPatient(int id);

Понятно, что GetExistingPatient () можно построить, вызвав FindPatient ().

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

Другие советы

Другой вариант - Шаблон пустых объектов .

Вы, вероятно, должны выбросить исключение. Если у вас есть id , который не указывает на действительного пациента, откуда он взялся? Что-то очень плохое, вероятно, произошло. Это исключительное обстоятельство.

РЕДАКТИРОВАТЬ . Если вы делаете что-то кроме поиска, основанного на целочисленных значениях, например, поиск по тексту, тогда возвращение null подойдет. Тем более, что в этом случае вы возвращаете набор результатов, который может быть более одного (более одного пациента с тем же именем, той же датой рождения или какими бы ни были ваши критерии).

Функция поиска должна иметь контракт, отличный от функции поиска.

Это зависит от

Если вы считаете, что обычная операция приведет к тому, что номер патиона не соответствует файлу в БД, тогда должна быть возвращена пустая (NULL) запись.

Но если вы ожидаете, что данный идентификатор всегда будет попадать в запись, тогда, когда он не найден (что должно быть редко), используйте исключение.

Другие вещи, такие как ошибка соединения с БД, должны генерировать исключение.
Как и следовало ожидать, в нормальных ситуациях запрос к БД всегда будет работать (хотя он может возвращать 0 записей или нет).

P.S. Я бы не вернул указатель. (Кому принадлежит указатель ??)
Я бы вернул объект, который может иметь или не иметь запись. Но это вы можете общаться для существования записи внутри. Потенциально умный указатель или что-то немного умнее, чем умный указатель, который понимает текст.

В этом случае я бы попросил метод вернуть null для несуществующего пациента.

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

В данном случае, вероятно, это mosdt:

  1. опечатка в идентификаторе пациента, если он был введен в форму поиска,
  2. ошибка ввода данных или
  3. проблема рабочего процесса в том, что запись пациента еще не введена.

Следовательно, возвращается значение null, а не исключение.

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

Редактировать: Только что увидел, что идентификатор пациента в подписи был целым числом, спасибо Стивену Лоу, поэтому я исправил свой список причин.

Однако мой основной тезис об определении того, когда следует использовать исключения (для системных ошибок) по сравнению с другими методами возврата ошибки (для простых опечаток при вводе данных), остается в силе.ИМХО.

HTH

ваше здоровье,

Роб

В простой ситуации, подобной этой, 1. этого более чем достаточно. Вы можете захотеть реализовать что-то вроде метода обратного вызова, который клиент вызывает, чтобы узнать, почему он вернул значение null. Просто предложение.

принимая ваше описание за чистую монету, вам, вероятно, нужно и то, и другое:

  • неверные идентификаторы - это ошибки / исключения, как указал Адам, но
  • если вам предоставлены идентификаторы в другом месте, которые могли исчезнуть, вам понадобится метод запроса, чтобы проверить их наличие

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

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

Брось исключение.

Если вы вернете ноль, напишите такой код:

Console.WriteLine(Patient(id).Name);

завершится с ошибкой NullReferenceException, если идентификатор не существует, что не так полезно, как, скажем, PatientNotFoundException (id). В этом примере все еще относительно легко отследить, но учтите:

somePatient = Patient(id)

// much later, in a different function:

Console.WriteLine(somePatient);

О добавлении функции, которая проверяет, существует ли пациент: обратите внимание, что это не предотвратит исключение PatientNotFoundExceptions полностью. Например:

if (PatientExists(id))
    Console.WriteLine(Patient(id).Name);

- другой поток или другой процесс может удалить пациента между вызовами PatientExists и Patient. Кроме того, это будет означать два запроса к базе данных вместо одного. Обычно лучше просто попробовать позвонить и обработать исключение.

Обратите внимание, что ситуация отличается для запросов, которые возвращают несколько значений, например, в виде списка; здесь уместно вернуть пустой список, если совпадений нет.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top