Я пытаюсь учиться DDD, но я очень запутался в некоторых терминах, которые используются для описания некоторых вещей, они заставляют мой маленький мозг жариться как маленькое яйцо.
- Что такое логика домена, слой домена, бизнес-логика, бизнес-слой, модель домена, объект домена, событие домена, эксперт по доменам, ядро домена?
- Как обнаружить всё это в моём коде?
- Laravel сделан над этими DDD понятиями? (я часто вижу такие вещи как сервисы, репозитории и др)
- Где я могу научиться DDD очень простым способом? (Я имею ввиду реально очень простым способом)
Что такое домен? Я рассказал об этом уже немного в другом посте, но домен это всего лишь определение которое описывает то для чего вы делаете приложение — проблему которую вы пытаетесь решить. Это может быть разработка форума, система инвентаризации машин, программа для работы с аккаунтами. Это уникальные требования и правила.
Что не является доменом? Домен это не такие вещи как база данных, сессии, куки, роуты, посредники и тд. Это всё инфраструктура приложения или его логика. Она используется для функционирования сайта, но она отделена от всей логики которая используется для осуществления модели домена.
Что такое хостинг, домен и как устроен интернет на понятном языке
Что такое модель домена? Модель домена это абстрактное описание домена. Так же как например глина или цифровая модель концепта машины — она помогает дизайнерам и инженерам визуализировать то, что они собираются построить, и найти потенциальные проблемы с этим на стадии построения модели, чтобы не искать ошибки когда они построили уже 10 000 машин. С точки зрения разработки приложений, модель обычно это ничего больше чем большое кол-во диаграмм, иллюстрирующих как приложение должно себя вести чтобы полностью соответствовать требованиям домена.
Что такое логика домена? Логика домена это просто код который используется для реализации модели домена. Например для форума нужен код для блокировки пользователей, создания обсуждений, редактирования обсуждений, чтобы пользователи могли редактировать только свои обсуждения. Опять же логика домена отличается от таких вещей как код базы данных (или Eloquent) и тд.
Она может использовать Eloquent, но всю работу с базой данных и написанием запросов Eloquent берёт на себя. Ваш домен не должен заботиться об этих деталях. Или не должен иметь понятие что ваши данные идут через HTTP. Это приводит меня к слою домена.
Что такое слой домена? По существу это то же самое что и логика домена — просто иной способ описать её. В идеальном мире, приложения создаются из слоёв, которые складываются друг на друге c хорошо описанными точками интеграции друг с другом. «Инфраструктура» (базы данных, сессии, куки и тд) могут быть одним слоем. «Приложение» (роутеры, контроллеры, посредники, вьюхи) могут быть следующим слоем. Обратите внимание что это относительно общее описание слоёв, и Laravel даёт их вам, чтобы вы могли о них не беспокоиться так сильно. «Домен» это слой который инкапсулирует в себе то что вы проектируете используя Laravel или любой другой фреймворк как средство.
Система доменных имен DNS | Курс «Компьютерные сети»
В идеальном мире ваш домен должен быть в очень маленькой зависимости от слоёв инфраструктуры и приложения.
Что такое объект домена? Это просто объект, который описывает центральный элемент вашей логики домена. Пользователь, Подписчик, Форум и тд. Обычно эти сущности это объекты точно определённые и уникальные. Они так же могут быть и не обязательно уникальными, а могут инкапсулировать некоторые свойства и логику для реиспользования кода.
Команда это простой неуникальный объект например. Или ПериодЗаписи тоже ещё один простой объект (используется для описания дат когда пользователь сможет записать в класс). Но ПериодЗаписи так же может быть и сущностью если вы сделаете его ей и дадите свой уникальный id. Всё зависит от того как вы используете объект.
Объект домена так же может быть старым добрым простым классом (service class, helper class, как назовёте вобщем), не обязательно быстрый простой объект как Команда, но что-либо что вы держите в базе с идентификатором.
По простому, объект домена это по сути что-либо что живёт в слое вашего домена и помогает осуществить модель домена.
Что такое событие домена? Событие домена это просто реакция на что-либо что случилось в слое вашего домена. Возвращаясь назад к примеру с форумом, если пользователь создаёт новое обсуждение, вы хотели бы распространить это событие. Зачем? Некоторые другие правила домена могут зависеть от этого события:
- Когда пользователь создаёт новое обсуждение, отправить email всем подписчикам этой категории форума письмо
- Когда пользователь создаёт новое обсуждение, отправить email всем друзьям/подписчикам этого пользователя
- Когда пользователь создаёт новое обсуждение(в модерируемом форуме), отправить сообщение модератору, чтобы он смог просмотреть и опубликовать обсуждение.
Тем самым при распространении события того, что пользователь создал обсуждение, слушатели события получают об этом информацию не дотрагиваясь до кода который создаёт обсуждение.
Кто такой эксперт по доменам? Это персона которая понимает домен — проблему. Например, скажем вы строите приложение для контроля над воздушными перелётами — эксперт по доменам будет диспетчером который расскажет как контролировать воздушный траффик, как это должно работать и что должно приложение помогать ему делать. Иногда ваши клиенты действительно не являются экспертами в ихнем домене и вы должны идентифицировать проблемы за них. Возможно они не до конца понимают сердце проблемы или не так как они хотят её понимать.
Что такое бизнес-логика, бизнес-слой? Если быть честным, у меня нет хорошего ответа. Можно утверждать что бизнес-слой является подслоем слоя домена. Такие вещи как «если пользователь купит 10 предметов, дайте ему кредит в 50 $» — это бизнес правило которое вы должны осуществить с помощью кода. Но я персонально считаю что «бизнес» и «домен» являются в большинстве случаев взаимозаменяемыми в ихней сущности, не беспокойтесь о разделении их, если в них есть разница, этот процесс может заставить вас рвать на себе волосы в большинстве приложений.
Что такое ядро домена? Ещё одно описание понятия домена.
Источник: gist.github.com
Домены приложений
Операционные системы и среды выполнения обычно содержат определенные средства изоляции приложений друг от друга. Например, в ОС Windows для изоляции приложений используются процессы. Эта изоляция необходима, чтобы гарантировать, что код, выполняемый одним приложением, не сможет нарушить работу других, не связанных с ним приложений.
Домены приложений образуют изолированную область для безопасности, надежности, управления версиями и выгрузки сборок. Домены приложений обычно создаются базовыми средами выполнения, которые отвечают за начальную загрузку среды CLR перед запуском приложения.
Преимущества изоляции приложений
Исторически сложилось так, что для разделения приложений, выполняющихся на одном компьютере, используются границы процессов. Каждое приложение загружается в отдельный процесс, который отделяет его от других приложений, выполняющихся на том же компьютере.
Приложения оказываются изолированными друг от друга, поскольку адреса в памяти привязаны к процессам; бессмысленно использовать в процессе указатель, передаваемый ему из другого процесса. Кроме того, прямые вызовы между процессами невозможны. Вместо этого необходимо использовать прокси, которые обеспечивают уровень косвенности.
Перед запуском управляемый код должен пройти процесс проверки (если администратор не даст разрешение пропустить проверку). В процессе проверки определяется, может ли код предпринимать попытки обращения к неверным адресам памяти или осуществлять другие действия, способные привести к нарушению правильной работы процесса, в котором выполняется этот код. Код, прошедший проверку, называется типобезопасным. Возможность проверки кода на безопасность типа позволяет среде CLR обеспечивать такой же высокий уровень изоляции процессов друг от друга, как и при использовании границ процессов, но со значительно более низкими затратами по производительности.
Домены приложений предоставляют среде CLR более безопасные и гибкие блоки, которые могут использоваться для разделения отдельных приложений. В одном процессе можно запустить несколько доменов приложений с таким же уровнем изоляции, какой обеспечивают отдельные процессы, но без дополнительных издержек на межпроцессные вызовы или переключение между процессами. Возможность выполнения нескольких приложений в одном процессе значительно повышает масштабируемость серверов.
Изоляция приложений также играет важную роль в обеспечении безопасности. Так, например, можно запустить элементы управления нескольких веб-приложений в одном процессе браузера так, что эти элементы управления не смогут получить доступ к данным и ресурсам друг друга.
Изоляция приложений при помощи доменов приложений имеет следующие преимущества.
- Сбои в одном из приложений не затронут прочие приложения. Поскольку типобезопасный код не может вызывать сбои в памяти, использование доменов приложений гарантирует, что код, выполняющийся в одном домене, не окажет воздействия на другие приложения процесса.
- Можно прекратить выполнение отдельных приложений, не останавливая процесс целиком. Использование доменов приложений позволяет выгружать код, используемый отдельным приложением.
Примечание Невозможно выгружать отдельные сборки или типы. Выгрузить можно только домен целиком.
Домены приложений и сборки
В этом разделе описывается связью между доменами приложений и сборками. Чтобы выполнить код сборки, ее необходимо загрузить в домен приложения. Как правило, для запуска приложения в домен приложения необходимо загрузить несколько сборок.
Способ загрузки определяет, можно ли использовать JIT-скомпилированный код сборки в нескольких доменах приложений в процессе и можно ли выгружать сборку из процесса.
- Если сборка загружается как нейтральная к домену, то все домены приложений с одним набором разрешений безопасности могут совместно использовать JIT-скомпилированный код, что снижает требуемый для приложения объем памяти. Однако сборку нельзя выгружать из процесса.
- Если сборка не загружается как нейтральная к домену, она должна быть JIT-скомпилирована в каждом домене приложения, в который она загружается. Однако сборку можно выгрузить из процесса, выгрузив все домены приложений, в которые она загружается.
Следует ли загружать сборки как нейтральные к домену, определяется в хост-приложении среды выполнения при загрузке среды выполнения в процесс. Для управляемых приложений примените атрибут LoaderOptimizationAttribute к методу точки входа процесса и укажите значение из связанного перечисления LoaderOptimization. Для неуправляемых приложений, в которых размещается среда CLR, при вызове функции CorBindToRuntimeEx задайте соответствующий флаг.
Существует три варианта загрузки нейтральных к домену сборок.
- LoaderOptimization.SingleDomain не загружает сборки как нейтральные к домену, за исключением Mscorlib, которая всегда загружается как нейтральная к домену. Этот вариант называется однодоменным, поскольку обычно он используется, когда в хост-приложении запускается только одно приложение в процессе.
- LoaderOptimization.MultiDomain загружает все сборки как нейтральные к домену. Этот вариант используется при наличии нескольких доменов приложений, в каждом из которых выполняется одинаковый код.
- LoaderOptimization.MultiDomainHost загружает сборки со строгими именами как нейтральные к домену, если они и все их зависимости установлены в глобальном кэше сборок. Другие сборки загружаются и JIT-компилируются отдельно для каждого домена приложения, в котором они загружаются, поэтому могут выгружаться из процесса. Этот вариант используется при работе нескольких приложений в одном процессе или при наличии набора сборок, которые являются общими для нескольких доменов приложений, и сборок, которые должны выгружаться из процесса.
JIT-скомпилированный код нельзя сделать общим для сборок, загруженных в контекст загрузки с помощью метода LoadFrom класса Assembly или загруженных из образов с помощью перегрузок метода Load, задающего байтовые массивы.
Сборки, которые были скомпилированы в машинный код с помощью Ngen.exe (средства для создания машинных образов), могут совместно использоваться доменами приложений, если они загружены как нейтральные к домену при первой загрузке в процесс.
JIT-скомпилированный код для сборки, содержащей точку входа приложения, может быть общим, только если все его зависимости могут использоваться совместно.
Сборка, нейтральная к домену, может JIT-компилироваться более одного раза. Например, когда наборы разрешений безопасности двух доменов приложений отличаются, они не могут совместно использовать один и тот же JIT-скомпилированный код. Однако каждая копия JIT-скомпилированной сборки может использоваться совместно с другими доменами приложений, имеющими такой же набор разрешений.
При принятии решения о том, следует ли загружать сборки как нейтральные, осуществляется компромисс между сокращением расхода памяти и производительностью.
- Доступ к статическим данным и методам для нейтральных к домену сборок осуществляется медленнее из-за необходимости изоляции сборок. Каждый домен приложения, обращающийся к сборке, должен обладать собственной копией статических данных, чтобы избежать ссылок на объекты в статических полях, пересекающих границы домена. В результате среда выполнения содержит дополнительные правила для перенаправления вызывающего объекта к соответствующей копии статических данных или метода. Эти дополнительные правила замедляют вызов.
- При загрузке сборки как нейтральной к домену необходимо найти и загрузить все зависимости сборки, поскольку зависимость, которую нельзя загрузить как нейтральную, не позволяет загрузить сборку как нейтральную.
Домены приложений и потоки
Домен приложения формирует изолированную область для безопасности, управления версиями, надежности и выгрузки управляемого кода. Поток представляет собой конструкцию операционной системы, используемую в среде CLR для выполнения кода. Во время выполнения весь управляемый код загружается в домен приложения и выполняется в одном или нескольких управляемых потоках.
Однозначного соответствия между потоками и доменами приложений не существует. В одном домене приложения могут одновременно выполняться несколько потоков, при этом конкретный поток не ограничен одним доменом приложения. Таким образом, потоки могут использоваться в разных доменах приложений. Новый поток для каждого домена приложения не создается.
В любой момент времени каждый поток выполняется в каком-либо домене приложения. В домене приложения может выполняться один или несколько потоков или не выполняться ни одного потока. Среда выполнения отслеживает соответствие потоков и доменов приложений, в которых они выполняются. В любой момент времени можно найти домен, в котором выполняется поток, вызвав метод Thread.GetDomain.
Домены приложений и язык и региональные параметры
Язык и региональные параметры, представляемые объектом CultureInfo, связаны с потоками. Чтобы получить язык и региональные параметры, связанные с выполняющимся в данный момент потоком, используйте свойство CultureInfo.CurrentCulture, а чтобы получить или задать язык и региональные параметры, связанные с выполняющимся в данный момент потоком, используйте свойство Thread.CurrentCulture. Если связанные с потоком язык и региональные параметры явно заданы с помощью свойства Thread.CurrentCulture, они будут связаны с этим потоком и за пределами домена приложения. В противном случае связанные с потоком язык и региональные параметры в любой момент времени определяются значением свойства CultureInfo.DefaultThreadCurrentCulture в домене приложения, где выполняется поток:
- Если значение этого свойства — не null , возвращаемые им язык и региональные параметры связаны с потоком (и следовательно возвращаются свойствами Thread.CurrentCulture и CultureInfo.CurrentCulture).
- Если значение этого свойства – null , с потоком связываются текущие настройки языка и региональных параметров системы.
Программирование с использованием доменов приложений
Домены приложений обычно создаются и управляются программно, хост-приложениями среды выполнения. Однако иногда работать с доменами приложений требуется самим приложениям. Например, приложение может загружать компонент в домен, чтобы иметь возможность выгрузить домен (и компонент) без необходимости останавливать все приложение.
AppDomain — это программный интерфейс для доменов приложений. Этот класс содержит методы для создания и выгрузки доменов, для создания экземпляров типов в доменах и для подписки на различные уведомления, такие как выгрузка домена приложения. В следующей таблице перечислены часто используемые методы AppDomain.
CreateDomain | Создает новый домен приложения. Рекомендуется использовать перегрузку этого метода, в которой определяется объект AppDomainSetup. Это предпочтительный способ установки свойств нового домена, таких как база приложения или корневой каталог приложения, расположение файла конфигурации домена и путь поиска, используемый средой CLR для загрузки сборок в домен. |
ExecuteAssembly и ExecuteAssemblyByName | Выполняет сборку в домене приложения. Это метод экземпляра, поэтому его можно использовать для выполнения кода в другом домене приложения, на который имеется ссылка. |
CreateInstanceAndUnwrap | Создает экземпляр указанного типа в домене приложения и возвращает прокси. Этот метод служит для избежания загрузки сборки, содержащей созданный тип, в вызывающую сборку. |
Unload | Корректно завершает работу домена. Домен приложения не выгружается до тех пор, пока все запущенные в домене потоки не будут остановлены или исключены из домена. |
Среда CLR не поддерживает сериализацию глобальных методов, поэтому для выполнения глобальных методов в других доменах приложений использовать делегаты нельзя.
Неуправляемые интерфейсы, описанные в спецификации Hosting Interfaces Specification для среды CLR, также предоставляют доступ к доменам приложений. Хост-приложения среды выполнения могут использовать интерфейсы из неуправляемого кода для создания доменов приложений внутри процесса и для получения доступа к ним.
Переменная среды COMPLUS_LoaderOptimization
Переменная среды, которая задает политику оптимизации загрузчика по умолчанию для исполняемого приложения.
Синтаксис
COMPLUS_LoaderOptimization = 1
Примечания
Стандартное приложение загружает в домен приложения несколько сборок. После этого можно выполнить содержащийся в них код.
Способ загрузки определяет, может ли JIT-скомпилированный код сборки использоваться несколькими доменами приложения в одном процессе.
- Если сборка загружается как независимая от домена, то все домены приложения с одним набором разрешений безопасности могут использовать один JIT-скомпилированный код. В этом случае приложение использует меньше памяти.
- Если сборка загружается как зависимая от домена, ее необходимо JIT-компилировать во всех соответствующих доменах приложения, при этом в каждом случае загрузчик должен использовать разные внутренние ресурсы.
Если значение флага среды COMPLUS_LoaderOptimization — 1, то хост-приложение среды выполнения использует способ загрузки SingleDomain. Он принудительно загружает все сборки как зависимые от домена, за исключением сборки Mscorlib, которая всегда загружается как независимая. Этот вариант называется однодоменным, поскольку обычно он используется, когда в хост-приложении запускается только одно приложение в процессе.
Флаг среды COMPLUS_LoaderOptimization предназначен для сценариев диагностики и тестирования. Когда он включен, работа может существенно замедляться, а использование памяти — увеличиваться.
Пример кода
Чтобы все сборки для службы IISADMIN загружались как зависимые от домена, добавьте код COMPLUS_LoaderOptimization=1 в многострочный параметр среды в разделе HKEY_LOCAL_MACHINESYSTEMCurrentControlSetservicesIISADMIN.
Key = HKEY_LOCAL_MACHINESYSTEMCurrentControlSetservicesIISADMIN Name = Environment Type = REG_MULTI_SZ Value (to append) = COMPLUS_LoaderOptimization=1
См. также
- System.AppDomain
- System.MarshalByRefObject
- Программирование с использованием доменов приложений и сборок
- Использование доменов приложений
Источник: learn.microsoft.com
Домены приложений .NET
В .NET исполняемые файлы не обслуживаются прямо внутри процесса Windows, как это происходит в случае традиционных неуправляемых приложений. Вместо этого они обслуживаются в отдельном логическом разделе внутри процесса, который называется . В единственном процессе может содержаться несколько доменов приложений, каждый из которых обслуживает свой исполняемый файл .NET. Такое дополнительное подразделение традиционного процесса Windows предоставляет ряд преимуществ, главные из которых описаны ниже:
- Домены приложений играют ключевую роль в обеспечении нейтральности платформы .NET по отношению к операционной системе из-за того, что такое логическое разделение стирает отличия в способе представления загружаемого исполняемого файла лежащей в основе операционной системой.
- Домены приложений являются гораздо менее дорогостоящими в плане потребления вычислительных ресурсов и памяти по сравнению с полноценными процессами. Благодаря этому CLR-среде удается загружать и выгружать домены приложений намного быстрее, чем формальные процессы, и тем самым значительно улучшать масштабируемость серверных приложений.
- Домены приложений обеспечивают более глубокий уровень изоляции для обслуживания загружаемого приложения. В случае выхода из строя какого-то одного домена приложения внутри процесса, остальные домены приложений все равно остаются работоспособными.
Класс System.AppDomain
Платформа .NET позволяет программно осуществлять мониторинг доменов приложений, создавать новые домены приложений (или выгружать их) во время выполнения, загружать в домены приложений различные сборки и решать целый ряд других задач с применением класса AppDomain из пространства имен System, которое находится в сборке mscorlib.dll. Ниже перечислены наиболее полезные методы этого класса:
CreateDomain()
Этот статический метод позволяет создавать новый домен приложения в текущем процессе
CreateInstance()
Этот метод позволяет создавать экземпляр типа из внешней сборки после загрузки соответствующей сборки в вызывающий домен приложения
ExecuteAssembly()
Этот метод позволяет запускать сборку *.ехе внутри домена приложения за счет предоставления имени ее файла
GetAssemblies()
Этот метод позволяет узнать, какие сборки .NET были загружены в данный домен приложения (двоичные файлы СОМ и С игнорируются)
GetCurrentThreadId()
Этот статический метод возвращает идентификатор потока, который является активным в текущем домене приложения
Этот метод применяется для динамической загрузки сборки в текущий домен приложения
Этот статический метод позволяет выгрузить определенный домен приложения из конкретного процесса
Платформа .NET не позволяет производить выгрузку конкретной сборки из памяти. Единственным способом для осуществления выгрузки библиотек программным образом является разрушение обслуживающего домена приложения с помощью метода Unload().
Кроме того, класс AppDomain имеет свойства и поддерживает набор событий, которые могут быть полезны для проведения мониторинга за каким-то доменом приложения. Наиболее интересные свойства и события такого рода кратко описаны ниже:
BaseDirectory
Позволяет извлечь путь к каталогу, который преобразователь адресов использует для поиска сборок
CurrentDomain
Представляет собой статическое свойство и позволяет узнать домен приложения, используемый для выполняющегося в текущий момент потока
FriendlyName
Позволяет получить дружественное имя текущего домена приложения
MonitoringlsEnabled
Позволяет получить или установить значение, указывающее, должна ли работать функция мониторинга за использованием ресурсов ЦП и памяти для текущего процесса. После включения функции мониторинга для процесса отключить ее нельзя
SetupInformation
Позволяет извлечь детали конфигурации определенного домена приложения, которые предоставляются в виде объекта AppDomainSetup
Событие | Описание |
AssemblyLoad | Возникает при загрузке сборки в память |
AssemblyResolve | Возникает, когда преобразователю адресов сборок не удается обнаружить место расположения требуемой сборки |
DomainUnload | Возникает перед началом выгрузки домена приложения из обслуживающего процесса |
FirstChanceException | Позволяет получать уведомление о том, что в домене приложения было сгенерировано какое-то исключение, перед началом выполнения CLR-средой поиска подходящего оператора catch |
ProcessExit | Возникает в используемом по умолчанию домене приложения тогда, когда его родительский процесс завершает работу |
UnhandledException | Возникает при отсутствии обработчика, способного перехватить данное исключение |
Источник: professorweb.ru