После практики DDD я столкнулся с проблемой при внедрении небольшого AES-шифрования/дешифратора (обертывание .NET AesCryptoServiceProvider
).DDD - поведение с дополнительным состоянием: объект службы/значения?
public class Aes256CbcCryptor : ISymmetricCryptor
{
private SymmetricAlgorithm AesProvider { get; set; }
// Poor man's DI - beside the point
public Aes256Cbc()
{
this.AesProvider = new AesCryptoServiceProvider()
{
BlockSize = 128,
KeySize = 256,
Mode = CipherMode.CBC,
Padding = PaddingMode.PKCS7,
Key = // OH DEAR IT TAKES STATE
};
}
public Aes256Cbc(SymmetricAlgorithm aesProvider)
{
this.AesProvider = aesProvider;
}
public byte[] Encrypt(byte[] keyBytes, byte[] plaintextBytes)
{} // TODO
public byte[] Decrypt(byte[] keyBytes, byte[] ciphertextBytes)
{} // TODO
}
Как вы можете видеть, .NET-х AesCryptoServiceProvider
является состоянием - он принимает ключ в качестве свойства. Но, как я понял, службы не должны быть сдержанными.
- Является ли ключ являющимся собственностью (а не, скажем, параметром метода), главное, что здесь происходит?
- Как бы вы реализовали класс в режиме DDD?
- В некоторых ситуациях наличие инициатора с заданным ключом представляется полезным и эффективным (если этот ключ должен использоваться много). Есть ли обоснование для служб с сохранением состояния или альтернатива?
Я предполагаю, что мы могли бы просто создать новый провайдер при каждом вызове метода, но это кажется очень расточительным. Мы могли бы реализовать кэширование, чтобы уменьшить количество отходов, но все это начинает ощущаться чрезмерно.
Другая альтернатива, которую я придумал, заключается в том, чтобы вместо этого создать Aes256CbcCryptorFactory
. Заводской номер CreateCryptor(byte[] key)
возвращает объект Value Aes256CbcCryptor
, который фактически является работоспособным. Потребляющая услуга теперь может, по крайней мере, поддерживать этот объект в рамках одного из его методов, если ему необходимо совершить несколько криптовальных вызовов.
С другой стороны, такая потребительская услуга все еще не может хранить объект Value в одном из своих свойств, поскольку это сделает его работоспособным.
- Увидев, что есть , некоторые льготы, это что-то, что делается? Тип поведения кажется очень servicey для объекта Value, но по крайней мере мы можем иметь некоторое временное состояние.
Вы прокомментировали ваш конструктор с «Бедным человеком». Здесь нет DI: вы используете ключевое слово 'new' для создания экземпляра. Возможно, это твоя проблема. Разве вы не должны зависеть от зависимостей «AesCryptoServiceProvider», а затем пусть ваш состав root беспокоится о состоянии? –
@DavidOsborne Я опустил параметризованный конструктор, но добавил его сейчас. Беспараметрический конструктор является «DI» бедного человека, то есть альтернативой автоматической инъекции каркасом. Однако я заинтригован вашей точкой зрения. Имеет смысл, что корневой состав будет знать, какой ключ использовать. Этот корень был бы самой службой, правильно? Но разве мы не должны были бы держать это * (и это) от достижения состояния? – Timo
«ИД« бедняк »DI без контейнера (blog.ploeh.dk/2014/06/10/pure-di/). То, что на самом деле является корнем состава, зависит от реализации. Казалось бы, вы не можете избежать того факта, что ваша выбранная реализация требует состояния.Вы можете продвигать разрешение этого состояния дальше и дальше вверх/наружу, но в какой-то момент вам нужно будет управлять этим состоянием. –