Используйте Получить по типу или Получить по идентификатору

У меня есть метод с именем GetObjectsRelatedToAType, например, GetCarsRelatedToDealership. Какой подход лучше с точки зрения веб-сервисов или сигнатур общего метода:

List<Cars> GetCarsRelatedToDealership( Dealership dealership );

или же

List<Cars> GetCarsRelatedToDealership( id dealership );

Мне нравится объектный подход, потому что он немного более силен, чтобы убедиться, что исходные данные метода верны. Мысли / советы?

6 ответов

Решение

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

Является ли идентификатор единственным элементом информации, который требуется для работы метода? Если так, я бы оставил это на этом.

У объектного подхода есть проблемы.

Dealership dealership;
GetCarsRelatedToDealership(dealership); // dealership is null

var dealership = new Dealership();
GetCarsRelatedToDealership(dealership); // dealership has no id

В этих случаях объект не дает вам никакого преимущества перед идентификатором. Идентификатор может быть неправильным, но вы можете проверить это. Объект делает вещи немного сложнее.

При работе со службами я бы создал пару классов запрос / ответ. Это позволяет вам гарантировать, что ваша подпись никогда не должна меняться. Ваши объекты Request или Response могут измениться, но сигнатура метода не изменится.

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

public class CarsRequest
{
  public int DealershipId { get; set; }
  public int RequesterId { get; set; }
}

public class CarsResponse
{
  public Car[] Cars { get; set; }
}

CarsResponse GetCarsRelatedToDealership(CarsRequest request);

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

Можете ли вы иметь метод взять интерфейс? Это сделало бы его гораздо более гибким и, возможно, проще для тестирования.

List<Cars> GetCarsRelatedToDealership( IDealership dealership );

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

Однако, если у вас часто есть большие сигнатуры методов, когда входные данные не очень хорошо указаны именем метода:

List<Cars> GetCars(int makeId, int modelId, int year, int dealershipId);

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

public class GetCarsOptions
{
    public int MakeId {get;set;}
    public int ModelId {get;set;}
    public int Year {get;set;}
    public int DealershipId {get;set;}
}

List<Cars> GetCars(GetCarsOptions options)
{
    ValidateOptions(options); // make sure the values all make sense.
}

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

Другие вопросы по тегам