Я изучаю использование шаблона портов и адаптеров с многоуровневой архитектурой.
Поэтому у меня будут следующие слои:
- framework / Infrastructure - то есть ASP.NET MVC, Entity Framework, SMTP-клиент
- приложение - логика, которая объединяет ваше приложение и выполняет действия в вашем домене.
- домен - определяет, как работают действия в вашем домене.Определяет отношения между объектами домена
После прочтения https://softwarecampament.wordpress.com/portsadapters/#tc2-3, https://fideloper.com/hexagonal-architecture и нескольких других статей, а также нескольких выступлений на YouTube, я все еще борюсь с тем, как реализовать порты драйверов и адаптеры,Я понимаю идею управляемых портов и адаптеров как то, что я сделал с простой многоуровневой архитектурой.
Но я все еще не понимаю, как будут реализованы порты драйверов и адаптеры.
СНасколько я понимаю, порт драйвера определяет, каким образом внешний слой должен использовать уровень, в котором он находится.Адаптер - это реализация этого порта на уровне, который использует этот порт.
Но есть кое-что, с чем я борюсь ... Как прикладной уровень реализует интерфейс к уровню домена?Разве для этого не требуется, чтобы прикладной уровень знал о взаимодействиях доменного уровня?Это полностью разрушает смысл использования интерфейса.Если уровень домена предоставляет интерфейс, который должен использовать что-то вне его, и адаптер для этого интерфейса реализуется уровнем с использованием интерфейса, это будет означать, что пользователь интерфейса также реализует сам интерфейс.Это похоже на то, как внешний уровень говорит внутреннему уровню, как работать ... что противоречит самой природе разъединения или даже просто интерфейсам в целом.
Похоже, что бизнес-уровень говорит прикладному уровню"Вот интерфейс, который я вам предоставляю ... ИДК, как он будет работать, так что вы говорите мне".Но зачем тогда вообще иметь интерфейс?
Вот код, демонстрирующий то, что я представляю:
applicationLayer.UserRegisteringUseCasePort
public interface UserRegisteringUseCasePort
{
void Register(string username, string password, string passwordConfirm, string name);
}
frameworkLayer.UserRegisteringUseCaseAdapter
public class UserRegisteringUseCaseAdapter : UserRegisteringUseCasePort
{
private IUserRepository _userRepo;
public class UserRegisteringUseCaseAdapter(IUserRepository userRepo)
{
_userRepo = userRepo;
}
public void Register(string username, string password, string passwordConfirm, string name)
{
// validation logic
//... such as:
if (password != passwordConfirm) {
throw new Exception("password no match password confirm!");
}
userRepo.Add(new User(username, password, name));
}
}
Мне кажется, это ужасно, потому что теперь вы заставили каркасный уровень выполнять проверку, которая должна быть частью логики домена (у которой даже не было возможности сделать это, так как мы остановилисьна прикладном уровне).Это также означает, что прикладной уровень на самом деле не объединяет бизнес-логику ... Он просто говорит, какие действия он хочет выполнить, но оставляет вызывающей стороне решать, как это сделать.Должно быть наоборот, верно?
Резюме
Я знаю, что много сказал, так что позвольте мне подвести итог ... Как работают порты драйверов и адаптеры?Как их следует использовать / реализовывать в сценариях реального мира?