Использование атрибутов для нормализации и валидации бизнес-сущностей
Страница 2. Методы проверки данных на соответствие бизнес-правилам


Одна из задач обеспечения целостности данных - это их валидация (Data validation). В отличие от остальных задач, обеспечивающих присутствие данных, валидация определяет годность, адекватность данных установленным бизнес-правилам. Вот основные методы проверки (70-300):

- Range checking involves making sure that the data’s value is within a set of limits determined by the functional specification.

- Data format checking involves making sure that the data conforms to a set of format specifications, such as currency formatting, telephone number formatting, or length-of-character strings.

- Data type checking involves making sure that the data belongs to the proper data type and that an invalid data type is not used to represent the data when it is written to the database.

то есть проверка границ, формата и типа данных.

Для этого есть 2 пути - проверка при вводе (невозможность ввести некорректные данные) при этом код валидации и нормализации привязан к UI-компоненту , или проверка производится при сохранении, код проверки в этом случае может находиться на любом уровне. В зависимости от архитектуры приложения эти проверки могут находиться в самой сущности, в отдельном компоненте (например в фабрике), в DAL-компоненте, с использованием XML-файлов правил и т.д. В 70-300 разделение немного другое (в зависимости от расположения):

- Client-side checks can ensure that invalid data is not posted to a database. These checks can be coded in many ways, including in scripts, in the user interface controls, as part of an executable program, or as part of a Web page. For example, if a field on a Web page denotes a monetary value, validation controls on the page can ensure that the information in that field is the proper data type and format.

- Server-side checks, which are executed by the DBMS engine, can be implemented with field data types, default values, and constraints. These checks can also ensure that invalid data is not stored in the database.

Майкрософт не рекомендует перегружать БД-сервер подобными проверками, поскольку это увеличивает его нагрузку и может привести к возникновению узкого места (bottleneck) если сервер обслуживает большое количество клиентских запросов.

Мы не будем рассматривать методы валидации на сервере БД, рассмотрим клиентские.

You can enforce data integrity through logic that is encapsulated in a component and is called or invoked as needed. The criteria for the logic are determined by the business rules, including any additional data integrity requirements that have been identified for the solution.

После некоторого количества времени проведенного за написанием кода-по-книжкам (подавляющее большинство примеров используют методы с DataSet), я решил для себя, что лично мне ближе "точная" работа с объектами - ручная загрузка и сохранение. Валидация на UI конечно более гибкая и мощная (например, можно менять содержимое/доступность/видимость одних контролов в зависимости от содержания других), но написание такого кода сложно в создании и поддержке, если UI становится относительно сложным (50-100 контролов разбитых по вкладкам). Кроме того этот код очень сложно использовать повторно, разве что отдельным кусочками.

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

Такое желание возникло и у меня, и свой "движок" я решил написать с использованием атрибутов, это решало бы сразу несколько задач. Во-первых, это простота создания и изменения - чтобы добавить проверку поля достаточно приписать к нему требуемый атрибут и указать дополнительные параметры (если они нужны). Во-вторых, это простота понимания и создания правил непрограммистами, то есть атрибуты можно описать в доступной форме и на основании этого составлять ТЗ.

Из минусов такого подхода - использование механизма отражения (Reflection) снижает быстродействие кода, и невозможность изменить правила без перекомпиляции кода. И если вторую проблему можно смягчить, вынося сущность в отдельную сборку (достаточно перекомпилировать только её), то с первой проблемой, по-видимому, ничего сделать нельзя :( Вообще этот механизм (валидации) не критичен по времени, в крупных приложениях большее знчение имеет его обслуживаемость. Например при изменении любого правила необходимо применить это изменение к клиентским приложениям (эта проблема решается определенными типами архитектуры приложения). Кроме того, поскольку атрибут применяется только для одного поля невозможно создавать проверки взаимосвязанных полей (на самом деле можно, но эти проверки уже hardcoded, т.е. зашиты в программном коде).

В качестве примера будем использовать такую сущность:

/// <summary>

/// Person Entity

/// <para>1.15</para>

/// </summary>

public class Person
{
public Person(int id)
{
m_ID = id;
}

#region Properties
#region Members

int m_ID = -1;
string m_Resume = string.Empty;
string m_Communication = string.Empty;
string m_ExtraInfo = string.Empty;
string m_Email = string.Empty;
string m_Name = string.Empty;

DateTime m_Birthday = DateTime.Today;

int m_Sex = -1;

ArrayList m_languages = new ArrayList();

#endregion

public int ID
{
get { return m_ID;}
}

public string Name
{
get { return m_Name;}
set { m_Name = value;}
}


public string Resume
{
get { return m_Resume;}
set { m_Resume = value;}
}

public string ExtraInfo
{
get { return m_ExtraInfo;}
set { m_ExtraInfo = value;}
}

public string Email
{
get { return m_Email;}
set { m_Email = value;}
}

public DateTime Birthday
{
get { return m_Birthday;}
set { m_Birthday = value;}
}

public int Sex
{
get { return m_Sex;}
set { m_Sex = value;}
}

public ArrayList Language
{
get { return m_languages;}
set { m_languages = value;}
}

#endregion
}  

Думаю с полями все понятно, в списке ArrayList Language мы буду хранить идентификаторы иностранных языков (первичный ключ в справочнике).

 

 
Следующая статья »