Анемичная модель предметной области — не анти-шаблон, а архитектура по принципам SOLID. Domain-Driven Design: создание домена

Анемия - English page

Anemia

This web site presents patients" information regarding different types of anemia. It was created in Russia by hematologists - doctors who are dealing with blood diseases
If you have any questions regarding this resource please contact us through e-mail or by phone (+7-495-741-06-41)

If you have anemia, people may say you have tired blood. That"s because anemia — a condition in which there aren"t enough healthy red blood cells to carry adequate oxygen to your tissues — can make you feel tired.

There are many forms of anemia, each with its own cause. Anemia can be temporary or long term, and it can range from mild to severe.

Anemia is a common blood disorder. Women and people with chronic diseases are at increased risk of the condition.

If you suspect you have anemia, see your doctor. Anemia can be a sign of serious illnesses. Treatments for anemia range from taking supplements to undergoing medical procedures. You may be able to prevent some types of anemia by eating a healthy, varied diet.

Symptoms

The main symptom of most types of anemia is fatigue. Other anemia symptoms include:

  • Weakness
  • Pale skin
  • A fast or irregular heartbeat
  • Shortness of breath
  • Chest pain
  • Dizziness
  • Cognitive problems
  • Numbness or coldness in your extremities
  • Headache

Initially, anemia can be so mild it goes unnoticed. But signs and symptoms increase as the condition worsens.

Causes

Blood consists of both a liquid called plasma and cells. Floating within the plasma are three types of blood cells:

  • White blood cells. These blood cells fight infection.
  • Platelets. These blood cells help your blood clot after a cut.
  • Red blood cells (erythrocytes). These blood cells carry oxygen from your lungs, via your bloodstream, to your brain and the other organs and tissues. Your body needs a supply of oxygenated blood to function. Oxygenated blood helps give your body its energy and your skin a healthy glow.

Red blood cells contain hemoglobin — a red, iron-rich protein that gives blood its red color. Hemoglobin enables red blood cells to carry oxygen from your lungs to all parts of your body, and to carry carbon dioxide from other parts of the body to the lungs so that it can be exhaled.

Most blood cells, including red blood cells, are produced regularly in your bone marrow — a red, spongy material found within the cavities of many of your large bones. To produce hemoglobin and red blood cells, your body needs iron, protein and vitamins from the foods you eat.

Anemia is a state in which the number of red blood cells or the hemoglobin in them is below normal. When you"re anemic, your body produces too few healthy red blood cells, loses too many of them or destroys them faster than they can be replaced. As a result, your blood is low on red blood cells to carry oxygen to your tissues — leaving you fatigued. Common types of anemia and their causes include:

    Iron deficiency anemia. This most common form of anemia affects about one in five women, half of pregnant women and 3 percent of men in the United States. The cause is a shortage of the element iron in your body. Your bone marrow needs iron to make hemoglobin. Without adequate iron, your body can"t produce enough hemoglobin for red blood cells. The result is iron deficiency anemia.

    One way your body gets needed iron is when blood cells die — the iron in them is recycled and used to produce new blood cells. So, if you lose blood, you lose iron. Women with heavy periods who lose a lot of blood each month during menstruation are at risk of iron deficiency anemia. Slow, chronic blood loss from a source within the body — such as an ulcer, a colon polyp or even colon cancer — also can lead to iron loss and iron deficiency anemia.

    Your body also gets iron from the foods you eat. An iron-poor diet can lead to this anemia. In pregnant women, a growing fetus can deplete the mother"s store of iron, leading to iron deficiency anemia.

  • Vitamin deficiency anemias. In addition to iron, your body needs folate and vitamin B-12 to produce sufficient numbers of healthy red blood cells. A diet lacking in these and other key nutrients can cause decreased red blood cell production. People who have an intestinal disorder that affects the absorption of nutrients are prone to this type of anemia. Some people are unable to absorb vitamin B-12 for a variety of reasons and develop vitamin B-12 deficiency anemia, which is sometimes called pernicious anemia. Vitamin deficiency anemias fall into a group of anemias called megaloblastic anemias, in which the bone marrow produces large, abnormal red blood cells.
  • Anemia of chronic disease. Certain chronic diseases — such as cancer, rheumatoid arthritis, Crohn"s disease and other chronic inflammatory diseases — can interfere with the production of red blood cells, resulting in chronic anemia. Kidney failure also can be a cause of anemia. The kidneys produce a hormone called erythropoietin, which stimulates your bone marrow to produce red blood cells. A shortage of erythropoietin, which can result from kidney failure or be a side effect of chemotherapy, can result in a shortage of red blood cells.
  • Aplastic anemia. This is a life-threatening anemia caused by a decrease in the bone marrow"s ability to produce all three types of blood cells — red blood cells, white blood cells and platelets. Many times, the cause of aplastic anemia is unknown, but it"s believed to often be an autoimmune disease. Some factors that can be responsible for this type of anemia include chemotherapy, radiation therapy, environmental toxins, pregnancy and lupus.
  • A variety of diseases, such as leukemia and myelodysplasia, a pre-leukemic condition, can cause anemia by affecting blood production in the bone marrow. The effects of these types of cancer and cancer-like disorders vary from a mild alteration in blood production to a complete, life-threatening shutdown of the blood-making process. Additionally, other cancers of the blood or bone marrow, such as multiple myeloma, myeloproliferative disorders and lymphoma, can cause anemia.
  • Hemolytic anemias. This group of anemias develops when red blood cells are destroyed faster than bone marrow can replace them. Certain blood diseases can cause increased red blood cell destruction. Autoimmune disorders can cause your body to produce antibodies to red blood cells, destroying them prematurely. Certain medications, such as some antibiotics used to treat infections, also can break down red blood cells. Hemolytic anemias may cause yellowing of the skin (jaundice) and an enlarged spleen.
  • Sickle cell anemia. This inherited and sometimes serious anemia, which affects mainly people of African and Arabic descent, is caused by a defective form of hemoglobin that forces red blood cells to assume an abnormal crescent (sickle) shape. These irregular-shaped red blood cells die prematurely, resulting in a chronic shortage of red blood cells. Sickle-shaped red blood cells can also block blood flow through small blood vessels in the body, producing other, often painful, symptoms.
  • Other anemias. There are several other, rarer forms of anemia, such as thalassemia and anemias caused by defective hemoglobin.

Sometimes, no cause of anemia can be identified.

Risk factors

These factors place you at increased risk of anemia:

  • Poor diet. Anyone — young or old — whose diet is consistently low in iron and vitamins, especially folate, is at risk of anemia. Your body needs iron, protein and vitamins to produce sufficient numbers of red blood cells.
  • Intestinal disorders. Having an intestinal disorder that affects the absorption of nutrients in the small intestine — such as Crohn"s disease and celiac disease — puts you at risk of anemia. Surgical removal of or surgery to the parts of the small intestine where nutrients are absorbed can lead to nutrient deficiencies and anemia.
  • Menstruation. In general, women are at greater risk of iron deficiency anemia than are men. That"s because women lose blood — and with it, iron — each month during menstruation.
  • Pregnancy. Pregnant women are at an increased risk of iron deficiency anemia because their iron stores have to serve the increased blood volume of the mother as well as be a source of hemoglobin for the growing fetus.
  • Chronic conditions. For example, if you have cancer, kidney or liver failure, or another chronic condition, you may be at risk of what"s called anemia of chronic disease. These conditions can lead to a shortage of red blood cells. Slow, chronic blood loss from an ulcer or other source within the body can deplete your body"s store of iron, leading to iron deficiency anemia.
  • Family history. If your family has a history of an inherited anemia, you also may be at increased risk of the condition.

Certain infections, blood diseases and autoimmune disorders, exposure to toxic chemicals, and the use of some medications can affect red blood cell production and lead to anemia. Other people at risk of anemia are people with diabetes, people who are dependent on alcohol (alcohol interferes with the absorption of folic acid) and people who adhere to a strict vegetarian diet, who may not get enough iron or vitamin B-12 in their diet.

When to seek medical advice

See your doctor if you"re feeling fatigued for unexplained reasons, especially if you"re at risk of anemia. Some anemias, such as iron deficiency anemia, are common. But don"t assume that if you"re tired, you must be anemic. Fatigue has many causes besides anemia.

Some people learn that their hemoglobin is low, which indicates anemia, when they go to donate blood. Low hemoglobin may be a temporary problem remedied by eating more iron-rich foods or taking a multivitamin containing iron. However, it may also be a warning sign of blood loss in your body that may be causing you to be deficient in iron. If you"re told that you can"t donate blood because of low hemoglobin, ask your doctor if you should be concerned.

If you have a family history of an inherited anemia, such as sickle cell anemia, talk to your doctor and possibly a genetic counselor about your risk and what risks you may pass on to your children.

Tests and diagnosis

Doctors diagnose anemia with the help of a medical history, a physical exam and blood tests, including a complete blood count (CBC). This blood test measures levels of red blood cells and hemoglobin in your blood. Some of your blood may also be examined under a microscope to study the size, shape and color of your red blood cells, which may indicate a diagnosis. For example, in iron deficiency anemia, red blood cells are smaller and paler in color than normal. In vitamin deficiency anemias, red blood cells are enlarged and fewer in number.

If you receive a diagnosis of anemia, your doctor may order additional tests to determine the underlying cause. For example, iron deficiency anemia can result from chronic bleeding of known or unknown ulcers, benign polyps in the colon, colon cancer, tumors, or kidney failure. Your doctor may test for these and other conditions that may underlie the anemia.

Occasionally, it may be necessary to study a sample of your bone marrow to diagnose anemia.

Complications

When anemia is severe enough, it may interfere with your ability to do everyday tasks. You may be too exhausted to work or play. Although anemia is often treatable, it may take several weeks to months for red blood cell levels to return to normal after treatment. Ask your doctor what to expect from treatment.

If you"ve been diagnosed with anemia — it"s often detected during routine blood tests — ask your doctor what treatment is necessary. Then be sure to follow through on treatment, even if you quickly start to feel better. Left unchecked, anemia can lead to a rapid or irregular heartbeat — an arrhythmia. Your heart must pump more blood to compensate for the lack of oxygen in the blood when you"re anemic. This can even lead to congestive heart failure. Untreated pernicious anemia can lead to nerve damage and decreased mental function, as vitamin B-12 is important not only for healthy red blood cells but also for optimal nerve and brain function.

Some inherited anemias, such as sickle cell anemia, can be serious and lead to life-threatening complications. Losing a lot of blood quickly results in acute, severe anemia and can be fatal.

Treatments and drugs

Anemia treatment depends on the cause:

  • Iron deficiency anemia. This form of anemia is treated with iron supplements, which you may need to take for several months or longer. If the underlying cause of iron deficiency is loss of blood — other than from menstruation — the source of the bleeding must be located and stopped. This may involve surgery.
  • Vitamin deficiency anemias. Pernicious anemia is treated with injections — often lifetime injections — of vitamin B-12. Folic acid deficiency anemia is treated with folic acid supplements.
  • Anemia of chronic disease. There"s no specific treatment for this type of anemia. Doctors focus on treating the underlying disease. Iron supplements and vitamins generally don"t help this type of anemia. However, if symptoms become severe, a blood transfusion or injections of synthetic erythropoietin, a hormone normally produced by the kidneys, may help stimulate red blood cell production and ease fatigue.
  • Aplastic anemia. Treatment for this serious anemia may include blood transfusions to boost levels of red blood cells. You may need a bone marrow transplant if your bone marrow is diseased and can"t make healthy blood cells. You may need immune-suppressing medications to lessen your immune system"s response and give the transplanted bone marrow a chance to start functioning again.
  • Anemias associated with bone marrow disease. Treatment of these various diseases can range from simple medication to chemotherapy to bone marrow transplantation. Treatment of these types of anemia usually involves a consultation from a blood specialist (hematologist).
  • Hemolytic anemias. Managing hemolytic anemias includes avoiding suspect medications, treating related infections and taking drugs that suppress your immune system, which may be attacking your red blood cells. Short courses of treatment with steroids or gamma globulin can help suppress your immune system"s attack on your red blood cells. If the condition has caused an enlarged spleen, you may need to have your spleen removed. The spleen — a small organ below your rib cage on the left side — filters out and stores defective red blood cells. Certain hemolytic anemias can cause the spleen to become enlarged with damaged red blood cells.
  • Sickle cell anemia. Treatment for this incurable anemia may include the administration of oxygen, pain-relieving drugs, and oral and intravenous fluids to reduce pain and prevent complications. Doctors also commonly use blood transfusions, folic acid supplements and antibiotics. A bone marrow transplant may be an effective treatment in some circumstances. A cancer drug called hydroxyurea (Droxia, Hydrea) also is used to treat sickle cell anemia in adults.

Prevention

Many types of anemia can"t be prevented. However, you can help avoid iron deficiency anemia and vitamin deficiency anemias by eating a healthy, varied diet that includes foods rich in iron, folate and vitamin B-12.

The best sources of iron are beef and other meats. Other foods rich in iron include beans, lentils, iron-fortified cereals, dark green leafy vegetables, dried fruit, nuts and seeds. Folate, and its synthetic form, folic acid, can be found in citrus juices and fruits, dark green leafy vegetables, legumes and fortified breakfast cereals. Vitamin B-12 is plentiful in meat and dairy products. Foods containing vitamin C, such as citrus fruits, help increase iron absorption.

Eating plenty of iron-containing foods is particularly important for people who have high iron requirements, such as children — iron is needed during growth spurts — and pregnant and menstruating women. Adequate iron intake is also crucial for infants, strict vegetarians and long-distance runners.

Doctors may prescribe iron supplements or multivitamins containing iron for people with high iron requirements. But iron supplements are appropriate only when you need more iron than a balanced diet can provide. Don"t assume that if you"re tired that you simply need to take iron supplements. Overloading your body with iron can be dangerous.

Information from mayoclinic was used in preparation of this page

Анемичная доменная модель

Если ваши доменные объекты являются контейнерами данных и всё, что в них есть, это свойства get/set , то вы используете анемичную доменную модель . Её особенностью является то, что доменный объект не имеет поведения.

Задача

Сценарии использования, к примеру, интернет-магазина:

  1. Пользователь, который зарегистрировался в системе, получает письмо со ссылкой на подтверждение регистрации. Перейдя по ссылке, он подтверждает свою регистрацию и может заходить под своим логином и паролем в систему.
  2. Пользователь может делать заказы
  3. При этом в личном кабинете он видит общую сумму, на которую заказал. В общей сумме текущих заказов не учитываются уже завершенные заказы

Начнем с анемичной модели данных. У нас будет класс Account :

Public class Account { public int Id { get; set; } public bool IsApproved { get; set; } public DateTime? ActivationDate { get; set; } public List Orders { get; set; } }

И класс Order :

Public class Order { public int Id { get; set; } public int Price { get; set; } public Account Account { get; set; } public bool IsComplete { get; set; } }

Реализация

Каждый из сценариев работы довольно просто реализовать:

Сценарий №1. Активация пользователя

Account.ActivationDate = DateTime.Now; account.IsApproved = true;

Сценарий №2. Добавление заказа

Account.Orders.Add(order); order.Account = account;

Сценарий №3. Подсчёт общей суммы

Account.Orders .Where(order => order.IsComplete == false) .Sum(order => order.Price);

Главный вопрос: где будет располагаться этот код?

Решение №0

Есть самое простое и неправильное решение. Мы будем писать этот код прямо в обработчиках на aspx -страницах или WinForms:

Public partial class Default: Page { protected void Page_Load(object sender, EventArgs e) { // выборка объекта account AccountOrdersSumLabel.Text = account.Orders .Where(order => order.IsComplete == false) .Sum(order => order.Price); } protected void AddOrderButton_Click(object sender, EventArgs e) { // выборка объекта account account.Orders.Add(order); order.Account = account; // сохранение объекта account } }

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

Глупо дублировать код, а потом тратить много времени на исправление одного изменившегося бизнес-требования.

Решение №1

Все-таки дублировать не будем. Мы вынесем код реализации наших сценариев в класс со звучным названием AccountHelper или AccountManager . Скорее всего этот класс будет без состояния, а потому статическим.

Получаем:

Public static class AccountHelper { public static void Activate(Account account) { account.ActivationDate = DateTime.Now; account.IsApproved = true; } public static void AddOrder(Account account, Order order) { account.Orders.Add(order); order.Account = account; } public static int CalculateOrdersSum(Account account) { return account.Orders .Where(order => order.IsComplete == false) .Sum(order => order.Price); } }

Проблема классов с названием *Helper или *Manager в том, что они могут себе позволить делать всё, что угодно. Их абстрактные названия позволяют «помогать» классу Account делать абсолютно разные вещи. Такие классы со временем становятся .

У таких классов множество недостатков. Например, трудно тестировать код, который использует эти классы, потому что они статические. Они делают код сильно связаным, т.к. нарушают . Очень часто из одного Helper "а вызывают другие Helper "ы. В итоге, граф зависимостей напоминает паутину из связей.

К тому же, это решение обладает всеми недостатками следующего.

Решение №2

Public interface IAccountService { void Activate(Account account); void AddOrder(Account account, Order order); int CalculateOrdersSum(Account account); } public class AccountService: IAccountService { public void Activate(Account account) { account.ActivationDate = DateTime.Now; account.IsApproved = true; } public void AddOrder(Account account, Order order) { account.Orders.Add(order); order.Account = account; } public int CalculateOrdersSum(Account account) { return account.Orders .Where(order => order.IsComplete == false) .Sum(order => order.Price); } }

Разобрались со связанностью и тестирование. Уже шаг вперёд. Но я вижу ещё две проблемы.

Функций типа AddOrder и CalculateOrdersSum будет довольно много. Через пол года разработки интерфейс IAccountService вырастит до 40-50 функций. «Загрязнение» интерфейса можно было бы пережить, если бы не вторая проблема.

В коде в любом месте можно в обход сервиса написать «свою активацию» пользователя. Например, взять объект Account из базы, выставить ему поле IsApproved в true и при этом забыть обновить поле ActivationDate . Тоже самое касается сценария добавления заказа. Можно вызвать функцию Add у свойства Orders где угодно и забыть выставить поле Account у добавляемого заказа. Это делает систему нестабильной. API приложения беззащитно перед пользователями системы. С таким подходом остается только надеятся, что программист найдёт нужную ему функцию в IAccountService , а не станет изобретать свой подход.

Решение №3

Поместим все эти функции в сам доменный объект Account . Обратите внимание на то, как изменились модификаторы доступа к полям объекта:

Public class Account { private readonly List orders; public Account() { orders = new List(); } public int Id { get; set; } public bool IsApproved { get; private set; } public DateTime? ActivationDate { get; private set; } public IEnumerable Orders { get { return orders; } } public int OrdersSum { get { return Orders .Where(order => order.IsComplete == false) .Sum(order => order.Price); } } public void Activate() { ActivationDate = DateTime.Now; IsApproved = true; } public void AddOrder(Order order) { orders.Add(order); order.Account = this; } }

Теперь домен нашего приложения даёт пользователю готовое API, которое не требудет ни Helper "ов, ни сервисов. К тому же мы уберегаем пользователя от ошибок. Он уже не сможет активировать Account выставив только IsApproved . Теперь функция Activate сама заполнит нужные поля.

Заключение

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

Мартином Фаулером в его классическом труде "Шаблоны корпоративных приложений" (Patterns of enterprise application architecture ) выделено несколько подходов к организации бизнес-логики.

  1. Транзакционный сценарий - бизнес-логика разбивается на процедуры, каждая из которых соответствует конкретному запросу, поступающему от слоя представления.
  2. Табличный модуль - бизнес-логика как и в предыдущем варианте описывается в процедурном стиле, однако манипуляции с каждой таблицей выносятся в отдельный класс, что делает код более структурированным.
  3. Модель предметной области - самый сложный для реализации подход, однако имеющий ряд преимуществ при описании сложной логики. Суть заключается в том, что выделяются объекты, соответствующие объектам предметной области. Описываются отношения между данными объектами, соответствующие отношениям между объектами реального мира. При этом решение технологических вопросов, таких как хранение, безопасность, управление транзакциями как правило выносится за пределы слоя бизнес-логики.

    Выделяют два варианта данного подхода:

    • Насыщенная модель предметной области - данные и поведение инкапсулируются внутри объектов предметной области.
    • Анемичная модель предметной области - в объектах предметной области инкапсулируются только данные, поведение же выносится в слой сервисов, расположенный поверх слоя предметной области.
Если выбор между тем какой шаблон - транзакционный сценарий, табличный модуль или доменную модель - использовать как правило не вызывает проблем, т.к. критерии их применимости четко описаны , то ответ на вопрос использовать или нет анемичную модель предметной области не так очевиден. С одной стороны теоретики объектно-ориентированного подхода считают данный шаблон "антипаттерном", с другой стороны он завоевал определенную популярность в практике разработки корпоративных приложений, что свидетельствует о наличии некоторых преимуществ. Давайте постараемся разобраться в данном вопросе.

Шаблон Модель предметной области

Прежде чем рассуждать о достоинствах и недостатках того или иного варианта, необходимо взглянуть на шаблон в целом. Как было сказано выше, суть данного паттерна в том, что создается сеть связанных объектов, каждый из которых представляет собой модель одного объекта реального мира. При этом данное решение обладает рядом достоинств, упрощающих реализацию сложной логики: программисту доступны все принципы парадигмы ООП, такие как инкапсуляция, наследование и полиморфизм. При этом структура классов отражает структуру реального мира, что упрощает взаимодействие по линии "программист - аналитик". Люди в команде могут общаться на одном языке. Для реализации модели можно применять хорошо знакомые шаблоны проектирования. Так же данный паттерн позволяет реализовать прозрачное для слоя бизнес-логики взаимодействие с хранилищем данным - объекты, моделирующие предметную область ничего не знают о том, что на самом деле они сохраняются, например в базе данных.

Важным преимуществом так же является тот факт, что Модель предметной области позволяет повторно использовать бизнес-логику приложения. В отличие от шаблонов Транзакционный сценарий и Табличный модуль, бизнес-логика не привязана к запросам от слоя представления. Соответственно над ней можно стоить другие варианты слоя представления, например RESTful- или SOAP -сервисы.

К сожалению, за любое достоинство следует платить. В данном случае плата заключается в следующем. Во-первых, повышаются требования к квалификации разработчиков, проектирующих, реализующих и поддерживающих модель предметной области: необходимо уметь строить более сложные абстракции нежели при применении других решений. Во-вторых, повышаются требования к используемым технологиям. В частности нужно иметь довольно мощный слой доступа к данным, который реализовывал бы объектно-реляционное отображение. Реализация шаблона Модель предметной области как правило требует применение мощного ORM -фреймворка, такого как Hibernate , TopLink , EclipseLink или OpenJPA , что с одной стороны требует разработчиков более высокой квалификации, а с другой - снижает производительность разрабатываемой системы и повышает ее хрупкость: любым неосторожным действием, например изменением одной строчки в описании объектно-реляционного отображения можно .

Анатомия насыщенной и анемичной моделей

Чем анатомически отличаются два подхода к построению модели предметной области: насыщенный и анемичный? При насыщенном подходе бизнес-логика, т.е. поведение системы реализуется внутри объектов предметной области. Данный подход не исключает вынесение части поведения в служебные классы, такие как *Service , *Manager , *Helper , но это оправдано только, когда логика затрагивает несколько доменных объектов и не понятно к какому именно она относится. Примером может являться следующая небольшая часть модели предметной области "Телеком". Пользователю нужно подключить себе услугу. Услуга добавляется в рамках заказа. При этом необходимо проверить, что есть организация-провайдер, которая может предоставить услугу с заданным набором параметров. В случае насыщенной доменной модели логика добавления услуги инкапсулируется в методе addNewService(Service service) класса ServiceOrder :

private List < Service> services;

private void addService(Service service) {

if (services == null )

Services = new ArrayList < Service> () ;

Services.add (service) ;

public void addNewService(Service service) throws NotFoundValidProviderException {

ServiceProviderRepository providerRepo = ...;

if (providerRepo.hasAvailableProvider (service.getProp1 () , service.getProp2 () , ...) ) {

AddService(service) ;

else {

throw new NotFoundValidProviderException(service) ;


Анемичная модель предметной области устроена иначе. Классы объектов предметной области лишены поведения. Они имеют только конструкторы и методы доступа к данным. Единственное, что они реализуют - это отношения с другими объектами. Все поведение системы выносится в слой сервисов, реализованный поверх слоя модели предметной области. Продемонстрируем данный подход на том же самом примере, однако теперь класс ServiceOrder будет иметь только методы, осуществляющие доступ к данным. Определение того, имеется ли подходящий провайдер услуги и ее добавление в заказ будет осуществляться в ServiceOrderManager (согласитесь, что ServiceOrderService звучит как-то странно):

public class ServiceOrder {

private List < Service> services;

public List < Service> getServices() {

return services;

public void setServices(List < Service> services) {

this .services = services;


return providerRepo;

if (order.getServices () == null )

Order.setServices (new ArrayList < Services> () ) ;

Order.getServices () .add (service) ;

else {

Критика Анемичной модели предметной области

В сообществе разработчиков распространены два основных соображения против применения шаблона Анемичная модель предметной области:
  • При использовании анемичной модели предметной области мы отклоняемся от принципов ООП . Суть данного критического замечания сводится к тому, что т.к. объекты предметной области в случае анемичной доменной модели не имеют поведения, то мы вступаем в противоречие с базовой идеей ООП - иметь данные и методы их обработки в одном месте.
  • При вырождении модели предметной области в анемичную, теряются все преимущества, которые дает данный шаблон, при этом сохраняются его недостатки . В частности, применение данного шаблона по прежнему требует довольно мощного слоя доступа к данным, реализованного, например, с использованием громоздких ORM -фреймворков.
Давайте рассмотрим данные соображения подробнее. Анемичная модель предметной области противоречит принципам ООП . В каком-то смысле данное соображение справедливо, т.к. объекты предметной области не имеют поведения. Однако доступ ко внутреннему состоянию объектов можно инкапсулировать за методами данного объекта. Продемонстрируем данную идею на нашем примере с добавлением сервиса в заказа: в класс ServiceOrder добавляется метод addService() , при этом метод setServices() делаем приватным:

public class ServiceOrder {

private List < Service> services;

public List < Service> getServices() {

return services;

private void setServices(List < Service> services) {

this .services = services;

public void addService(Service service) {

if (services == null )

Services = new ArrayList < Service> () ;

Services.add (service) ;


Класс ServiceOrderManagerImpl будет осуществлять проверку возможности добавления заказа и вызывать метод addService() класса ServiceOrder :

public class ServiceOrderManagerImpl implements ServiceOrderManager {

private ServiceProviderRepository providerRepo;

public ServiceProviderRepository getProviderRepo() {

return providerRepo;

public void setProviderRepo(ServiceProviderRepository providerRepo) {

this .providerRepo = providerRepo;

public void addNewService(ServiceOrder order, Service service) throws ProviderNotFoundException {

if (providerRepo.hasAvailableProvider (service.getParam1 () , service.getParam2 () , ...) ) {

Order.addService (service) ;

else {

throw new ProviderNotFoundException(service) ;


Проблема заключается в том, что вынесение поведения в другие классы требует чтобы такие методы были публичными. Это существенно ухудшает инкапсуляцию. Любой нерадивый разработчик сможет обратиться к свойству объекта, минуя методы соответствующего сервиса, например добавить сервис в заказ без проверки доступности провайдера.

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

Другие принципы ООП, такие как наследование и полиморфизм, остаются доступными и при использовании анемичной модели предметной области. Большинство современных ORM -фреймворков допускают отображение иерархии классов на базу данных. Например, при построении модели финансового приложения следует учесть различные стратегии расчета лимита овердрафта. Предположим есть две стратегии: нет овердрафта и есть овердрафт с ограниченным лимитом. Построим следующую иерархию классов:




При этом объект класса Account - счет - будет иметь ссылку на конкретную реализацию стратегии расчета овердрафта, применимую для данного счета:

public class Account {

private OverdraftLimitStrategy overdraftLimitStrategy;

public OverdraftLimitStrategy getOverdraftLimitStrategy() {

return overdraftLimitStrategy;


В некотором AccountService мы теперь можем использовать полиморфную реализацию стратегии расчета овердрафта:

public class AccountService {

public void withdraw(Account account, Double amount) {

if (account.getAmount () + account.getOverdraftLimitStrategy () .getLimit () > = amount) {

Account.setAmount (account.getAmount () - amount) ;


Теряются все преимущества, которые дает шаблон Модель предметной области . Как мы рассмотрели выше, преимущества, которые дает моделирование системы в ООП-стиле при использовании анемичной модели предметной области нам по прежнему доступны. Возможно, что получить данные преимущества можно только при грамотной проработке архитектуры системы, в частности - интерфейсов между слоями, но это - соответствующая плата за более простую модель. Способность объектов прозрачно сохраняться в долговременной памяти так же не теряется. Как раньше объект сохранялся соответствующей командой в репозитории (Repository ) или участке работы (Unit of Work ), так и продолжает сохранятся. Синхронизация изменений внутреннего состояния объекта с хранилищем данных не зависит от того, как именно выполняется данное изменение - методом внутри класса объекта или методом сервиса.

Причины популярности шаблона Анемичная модель предметной области

Теперь попытаемся найти ответ на вопрос, почему шаблон Анемичная модель предметной области так популярен. На мой взгляд, основная причина кроется в том, что данный шаблон легче реализуется с помощью современных технологий по сравнению с насыщенной моделью. Наиболее распространенным способом структурирования исходного кода сегодня является шаблон Внедрение зависимостей. При этом в приложении четко прослеживается два источника объектов:
  • IoC -контейнер, который реализует шаблон Инъекция зависимостей и строит служебные объекты: репозитории, сервисы, фасады;
  • ORM -фрейморк, который создает объекты предметной области.
При реализации шаблона Насыщенная модель предметной области возникает проблема связывания объектов, построенных этими двумя способами, в единый граф. Если вернуться к примеру насыщенной модели предметной области, описанному выше, то видно, что в объект класса ServiceOrder нужно каким-то образом передать объект класса, реализующего интерфейс ServiceProviderRepository . Не все ORM -фреймворки позволяют инъектировать в объекты при их построении сторонние зависимости, реализуемые IoC -контейнером. Приходится использовать подходы, обладающие рядом недостатков.
  • Инъекция посредством статических переменных и методов. Репозитории и прочие IoC -объекты передаются как одиночки. Недостатки такого подхода: сложнее подменить объект, например, заменив его на заглушку при тестировании. Так же данный подход вносит скрытые зависимости.
  • Передача зависимостей через метод (не путать с инъекцией через сеттер). Если мы включаем в объект предметной области метод, содержащий бизнес-логику, то в данный метод нужно передавать все требуемые ему объекты: репозитории, фабрики, соединения и т.д. Недостатки такого подхода: усложняется сигнатура методов бизнес-логики, все зависимости выставляются наружу, при усложнении логики метода, ему могут потребоваться новые зависимости, что приведет к изменению сигнатуры метода и необходимости как исправлять вызов метода везде, где он используется, так и как-то передавать новые зависимости в точки вызова.
  • Использовать шаблон Локатор сервисов и передавать каким-то образом реализацию данного шаблона в метод объекта предметной области. Недостатками данного метода являются все недостатки шаблона Локатор сервисов.
  • Вместо зависимостей передавать в метод результат их работы. Но данный подход убирает логику из объекта предметной области и по сути является первым шагом к анемичной модели.

Преимущества шаблона Анемичная модель предметной области

Помимо популярности, вызванной имеющейся инфраструктурой, шаблон Анемичная модель предметной области имеет и ряд собственных преимуществ. Давайте рассмотрим их подробнее.
  1. Простота проектирования и разработки . Как правило Анемичная модель предметной области требует меньше усилий и квалификации для своей разработки. Так как объекты предметной области лишены поведения, которое икапсулируется в сервисах, то снимается вопрос в какой объект предметной области поместить тот или иной метод. Конечно, вместо этого появляются вопросы в какой сервис его поместить, создавать новый сервис или нет, но данные вопросы проще для решения.
  2. Простота генерации на основе хранилища данных : базе данных, WSDL -описанию сервиса, файлу настройки объектно-реляционного отображения и т.д. Данное преимущество особенно ярко проявляется тогда, когда мы строим интерфейс к унаследованной системе, реализованной не на ООП-языке или выставляющей интерфейс в стиле удаленного вызова процедур. При современной нацеленности информационных систем на использование сервисно-ориентированной архитектуры данная особенность подхода играет все большую и большую роль. Это, кстати, отличает текущее положение вещей от времен написания критической статьи Фаулера, в конце концов прошло почти 10 лет. Мне как разработчику клиента к существующей службе предприятия гораздо проще сгенерировать модель данных по ее - службы - контракту (например по WSDL -описанию) и разработать слой классов-менеджеров над данной моделью, нежели строить насыщенную модель предметной области и реализовывать ее интеграцию с удаленной службой.
  3. Простота повторного использования . Если мы имеем приложение, построенное на основе шаблона Анемичная модель предметной области и нам нужно реализовать приложение, работающее с этими же данными, но реализующее другую бизнес-логику, то мы можем переиспользовать классы существующей модели. В случае насыщенной модели предметной области такое переиспользование будет затруднено, т.к. бизнес-логика жестко зашита в классы, реализующие модель предметной области. С данной точки зрения излишняя инкапсуляция скорее вредна нежели полезна.

Заключение

В заключение стоит сказать о том, что последнее дело как в ведении дискуссии, так и в принятии решения - слепое следование мнению тех или иных авторитетов. Всегда стоит помнить, что в науке существует такое понятие, как плюрализм мнений. Есть разные научные школы, придерживающиеся тех или иных подходов. Вполне естественна конкуренция между такими школами. Любые слова того или иного "гуру" могут быть вызваны конъюнктурной составляющей. Не нужно творить себе кумиров, чтобы потом не пришлось в них разочаровываться. Всегда следует думать своей головой и выбирать решение, исходя из собственного опыта и приоритетов прежде всего своего проекта.

Последнее обновление: 19.07.2016

Одним из ключевых компонентов паттерна MVC являются модели . Ключевая задача моделей - описание структуры и логики используемых данных.

Как правило, все используемые сущности в приложении выделяются в отдельные модели, которые и описывают структуру каждой сущности. В зависимости от задач и предметной области мы можем выделить различное количество моделей в приложении.

Все модели оформляются как обычные POCO-классы (plain-old CRL objects), то есть обычные классы на языке C#. Например, если мы работаем с приложением интернет-магазина мобильных телефонов, то мы могли бы определить в проекте следующую модель, представляющую телефон:

Public class Phone { public int Id { get; set; } public string Name { get; set; } public string Company { get; set; } public int Price { get; set; } }

Модель Phone определяет ряд свойств: уникальный идентификатор Id, название, компанию производителя и цену. Это классическая анемичная модель . Анемичная модель не имеет поведения и хранит только состояние в виде свойств.

Однако модель необязательно должна состоять только из свойств. Кроме того, она может иметь конструктор, какие-нибудь методы, поля, вообщем предствлять стандартный класс на языке C#. Модели, которые также определяют поведение, в противоположность анемичным моделям называют "толстыми" моделями (Rich Domain Model / Fat Model / Thick Model). Например, мы можем уйти от анемичной модели, модифицировав ее следующим образом:

Public class Phone { private decimal _discount = 0; public Phone(decimal discount) { this._discount = discount; } public int Id { get; set; } public string Name { get; set; } public string Company { get; set; } public decimal Price { get; set; } public decimal GetPriceWithDiscount() { return this.Price - (this.Price * this._discount); } }

Но какой бы способ описания сущности не был выбран, главное не перегружать класс модели и помнить, что его предназначение состоит прежде всего описывать данные. И модель должна описывать только одну сущность, следуя принципу единой ответственности.

В приложении ASP.NET MVC Core модели можно разделить по степени применения на несколько групп:

    Модели, объекты которых хранятся в специальных хранилищах данных (например, в базах данных, файлах xml и т.д.)

    Модели, которые используются для передачи данных представление или наоборот, для получения данных из представления. Такие модели еще называтся моделями представления

    Вспомогательные модели для промежуточных вычислений

Как правило, для хранения моделей создается в проекте отдельная папка Models . Модели представления нередко помещаются в отдельную папку, которая нередко называется ViewModels .

Проект ASP.NET MVC Core со встроенной аутентификацией по умолчанию уже содержит эти папки, и в них находятся в все необходимые модели. Однако если мы создаем проект без встроенной аутентификации, то эти папки отсутствуют. И соответственно нам надо добавить эти папки вручную. Но опять же подчеркну, что нам необязательно называть папки для хранения моделей именно Models и ViewModels. Это могут быть каталоги с любыми называниями, можно помещать модели в корень проекта, но более распространенным стилем являются названия Models и ViewModels.

Например, создадим новый проект ASP.NET Core по типу Web Application и назовем его ModelsApp . Вначале добавим в проект папку Models для хранения моделей.

И в нее поместим новый класс Company:

Public class Company { public int Id { get; set; } public string Name { get; set; } public string Country { get; set; } }

И также добавим в папку Models класс Phone

Public class Phone { public int Id { get; set; } public string Name { get; set; } public Company Manufacturer { get; set; } public decimal Price { get; set; } }

Эти модели будут описывать данные, которые мы будем использовать. Эти данные могут храниться в базе данных, но для простоты мы определим их в контроллере. Изменим контроллер HomeController следующим образом:

Using System.Collections.Generic; using System.Linq; using Microsoft.AspNetCore.Mvc; using ModelsApp.Models; // пространство имен моделей namespace ModelsApp.Controllers { public class HomeController: Controller { List companies; ListPhones; public HomeController() { Company apple = new Company { Id = 1, Name = "Apple", Country="США" }; Company microsoft = new Company { Id = 2, Name = "Microsoft", Country="США" }; Company google = new Company { Id = 3, Name = "Google", Country="США" }; companies = new List { apple, microsoft, google }; phones = new List { new Phone { Id=1, Manufacturer= apple, Name="iPhone 6S", Price=56000 }, new Phone { Id=2, Manufacturer= apple, Name="iPhone 5S", Price=41000 }, new Phone { Id=3, Manufacturer= microsoft, Name="Lumia 550", Price=9000 }, new Phone { Id=4, Manufacturer= microsoft, Name="Lumia 950", Price=40000 }, new Phone { Id=5, Manufacturer= google, Name="Nexus 5X", Price=30000 }, new Phone { Id=6, Manufacturer= google, Name="Nexus 6P", Price=50000 } }; } public IActionResult Index() { return View(phones); } } }

Список объектом модели передается в представление с помощью метода View() .

И в конце изменим представление Index.cshtml , которое будет выводить все объекты:

@using ModelsApp.Models @model IEnumerable @{ ViewData["Title"] = "Home Page"; }

@foreach (Phone p in Model) { }
@p.Name@p.Manufacturer?.Name@p.Price

Причиной повышенной утомляемости, сонливости, шума в ушах не во всех случаях выступают напряженный режим работы и интенсивный ритм жизни. Если человек испытывает такое и пока не знает, что такое анемия (с лат. anaemia), необходимо обратиться за консультацией к врачу. Под этим термином подразумевают состояние, при котором в организме есть дефицит эритроцитов, выполняющих функцию по переносу кислорода к тканям. Вовремя обратившись за медицинской помощью, можно предотвратить развитие тяжелых форм патологии.

Значение понятия

Гемоглобин является основной частью эритроцитов. В его составе есть ион железа, связывающий кислород. При недостатке красных кровяных тел в организме постепенно наступает аноксия (гипоксия). Симптомами анемии в этом случае выступают усталость, головные боли, одышка. Малокровию по международной классификации болезней присвоен код МКБ-10, согласно данным Минздрава РФ у 15% населения выявляется эта патология. Наиболее подвержены ей беременные (40%), на следующем месте в группе риска находятся дети до 2 лет (18-25%).

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

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

Этиология заболевания

Малокровие диагностируется у пациентов на фоне выявления различных факторов. Известны следующие основные причины анемии:

  1. Потеря большого объема крови при тяжелом менструальном цикле, глубоких ранах, на фоне злокачественного рака толстой кишки, кишечных язв.
  2. Дисфункция почек, при которой снижается производство в костном мозгу эритропоэтина, вырабатывающего ретикулоциты (предшественники эритроциты).
  3. Заболевание может передаться по наследству от родственников первой линии.
  4. Нерациональное питание, дефицит витаминов группы В12 и С, фолиевой кислоты, железа.
  5. Анемия развивается на фоне хронических патологий: болезнь Крона, СПИД, ВИЧ, ревматоидный артрит, карцинома.
  6. Проявление признаков поражения кроветворной системы связано и с психосоматикой. Анемия выступает в качестве специфического сигнала организма о том, что человек излишне самокритичен, недоволен своей жизнью. В этом случае психологи рекомендуют мысленно повторять про себя, что новый путь и мысли не несут угрозы и совершенно безопасны.
  7. Организм некоторых людей не способен усваивать витамин В12, что приводит к развитию малокровия. Уменьшение всасывания полезных веществ могут обусловить молочные продукты, твердая пища, злаки в сыром виде.
  8. При отсутствии заболеваний эритроциты живут 100 дней. При поражении селезенки развивается гемолиз, при котором нарушается их функционирование.
  9. Этанол токсичен для мозговой деятельности и замедляет продукцию эритроцитов. При сочетании этих факторов у хронических алкоголиков существенно повышаются риски развития анемии.
  10. Истощение внутренних резервов железа провоцируется чаще всего у женщин, борющихся с лишним весом и придерживающихся строгих диет.
  11. Анемия нередко проявляется в предоперационном периоде. Поэтому хирург должен оценить в полной мере риск вмешательства и повысить уровень гемоглобина до нормы, чтоб снизить нагрузку на сердечно-сосудистую систему.


Понравилась статья? Поделитесь с друзьями!