Как определить предварительные условия для внешнего состояния, используя кодовые контракты?

Как мне поставить предварительное условие на Invoke метод в следующем интерфейсе, заявив, что объект, обозначенный ObjectId должен существовать?

interface IDeleteObjectCommand {
   Guid ObjectId { get; }
   void Invoke();
}

Попытка № 1

У меня уже есть команда под названием IObjectExistsCommand который может быть использован для определения, существуют ли объекты. Эти команды могут быть созданы с помощью IObjectExistsCommandFactory, Я думал о том, чтобы сделать следующее, но это добавляет нежелательный шум в интерфейс команды (IMO):

interface IDeleteObjectCommand {
   IObjectExistsCommandFactory ObjectExistsCommandFactory { get; }
   Guid ObjectId { get; }

   // Contract.Requires(ObjectExistsCommandFactory.Create(ObjectId).Invoke());
   void Invoke();
}

Попытка № 2

Аналогично выше, кроме использования ServiceLocator, Нежелательно по понятным причинам, но чище:

interface IDeleteObjectCommand {
   Guid ObjectId { get; }

   // Contract.Requires(ServiceLocator.Get<ObjectExistsCommandFactory>().Create(ObjectId).Invoke());
   void Invoke();
}

РЕДАКТИРОВАТЬ: Точно так же, как бы вы определили постусловия на внешнее состояние? Т.е. говоря, что этот метод приводит к существованию нового файла.

2 ответа

Решение

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

Создайте исключение, если удаляемый объект не существует.

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

interface IDeleteObjectCommand {
   Guid ObjectId { get; }
   DeleteObjectPreconditions? GetImpediments();

   // Contract.Requires(!this.GetImpediments().HasValue);
   void Invoke();
}

enum DeleteObjectPreconditions { ObjectExists, ObjectUnlocked };

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

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

РЕДАКТИРОВАТЬ 2: Это поднимает интересный вопрос... как бы вы определили постусловия на внешнее состояние?

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