Brownfield-проект

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

Рубрика Программирование, компьютеры и кибернетика
Вид дипломная работа
Язык русский
Дата добавления 23.11.2016
Размер файла 2,6 M

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Методы:

CheckProcessRoutingDeleteDataAction () - конструктор класса;

async Task<IDataResult<PartCostDetailFormModel, PartCostDetailFormModel>> ProcessAsync(PartCostDetailFormModel contextModel) - метод, выполняющий проверку данных на наличие связей в базе данных. На вход поступает модель, которую необходимо проверить, на выходе получается валидационный результат;

3.1.11 Класс GetPartCostDetailDataAction

Представляет собой класс, который позволяет получить данные для модели на клиенте без перезагрузки страницы. Является ярким примером реализации принципа одностраничного приложения. Реализацией интерфейса IDataAction.

Поля:

_dataResultFactory- поле фабрики результатов, формирует модель результат валидации для дальнейшей передачи на клиент;

_partCostDetailQuoteHelper- поле класса помощника, выполняющего проверку на разрешение редактирования записи, и контейнера констант;

_getPartCostDetailFormDataHelper- помощник для работы с сервисом запросов базы данныхдля получения модели.

Методы:

GetPartCostDetailDataAction () - конструктор класса;

async Task<IDataResult<PartCostDetailFormModel, PartCostDetailFormModel>> ProcessAsync(PartCostDetailFormModel contextModel) - метод, выполняющий получающий данные для конкретной записи в базе данных. На вход поступает модель с ключами, на выходе получается модель отображения;

3.1.12 Класс ViewPartCostDetailFormAction и подобные ему

Представляет собой главный класс, так называемую точку входа в приложение.Данный класс является фабрикой по формированию и наполнению модели данных и модели отображения на серверной стороне приложения. В приложении так же используются однотипные классы для формирования отображения диалоговых окон. Все такие классы имеют название по шаблону View*Action и являются реализацией интерфейса IViewAction. Единственным отличием между диалоговыми окнами и отображением главной страницы является тип возвращаемой модели. Для главной страницы это PageModel, для диалогов - DialogModel.

Поля:

_actionBarModelBuilderFactory - поле фабрики панели действий, формирует модель действий для дальнейшей передачи на клиент;

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

_getPartCostDetailFormDataHelper- помощник для работы с сервисом запросов базы данныхдля получения модели.

_*ModelBuilder -множество классов-фабрик, которые возвращают конкретную модель для наполнения формы. В данном приложении используется два типа моделей: модели таблицы и модель формы, которая выступает контейнером для таблиц. Все такие классы однотипные принимают на вход модель данных, возвращают реализацию интерфейса IPageSectionViewModelBuilder.

Методы:

ViewPartCostDetailFormAction () - конструктор класса;

async Task<IDataResult<PartCostDetailFormModel, PartCostDetailFormModel>> ProcessAsync(PartCostDetailFormModel contextModel) - метод, получающий данные для конкретной записи в базе данных, формирующий из этих данных контекстную модель, инициирующий модель отображения и наполняющий модель отображения секциями. На вход поступает модель с ключами, на выходе получается модель отображения;

3.2 Классы, реализующие фабрики моделей (Builders)

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

Вся форма состоит из секций, каждая секция, созданная методом AddSection() в разметке будет представлять собой тэг <div></div>.

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

3.2.1 Классы построения диалоговых окон*ModelBuilder

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

Поля:

_applicationContext- поле контекста приложения, содержит в себе информацию о текущем пользователе, локализации;

_validationFactory- поле фабрики валидации данных, формирует модель валидации для дальнейшей передачи на клиент;

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

_quoteWizardSettings- контейнер настроек для текущего пользователя;

Методы:

*ModelBuilder() - конструктор класса;

async Task<IDataResult<PartCostDetailFormModel, PartCostDetailFormModel>>Build(Model contextModel) - метод формирования модели отображения. На вход поступает контекстная модель, которую необходимо инициировать, на выходе получается объект модели отображения;

3.2.2 Классы построения таблиц *GridBuilder

Представляют собой классы, формирующие отображение таблиц на странице. Все подобные классы отличаются закрепленным за ними файлом JavaScript, названием количеством/типом колонок таблицы. Являются реализацией интерфейса IPageSectionViewModelBuilder.

Поля:

_applicationContext- поле контекста приложения, содержит в себе информацию о текущем пользователе, локализации;

_validationFactory- поле фабрики валидации данных, формирует модель валидации для дальнейшей передачи на клиент;

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

_quoteWizardSettings- контейнер настроек для текущего пользователя;

Методы:

*GridBuilder () - конструктор класса;

async Task<IDataResult<PartCostDetailFormModel, PartCostDetailFormModel>>BuildAsync (Model contextModel) - метод формирования модели отображения. На вход поступает контекстная модель, которую необходимо инициировать, на выходе получается объект модели отображения таблицы;

3.2.3 Класс построения формы PartCostDetailFormBuilder

Представляет собой класс, формирующие отображение главного контейнера формы на странице. Все модели, полученные с помощью предыдущей фабрики добавляются в контейнер в отдельные секции. Может иметь свои собственные элементы, которые поставляются фрэймворком. Как самостоятельный элемент страницы, может иметь свои собственные элементы управления типа кнопок и ссылок. Является реализацией интерфейса IPageSectionViewModelBuilder.

Поля:

_applicationContext- поле контекста приложения, содержит в себе информацию о текущем пользователе, локализации;

_appUrlProvider- поле фабрики формирования ссылок на любой контент и другие приложения в рамках модуля;

_validationFactory- поле фабрики валидации данных, формирует модель валидации для дальнейшей передачи на клиент;

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

_headerBuilders- поле представляющее собой словарь из ключей, которые получаются из настроек приложения, и отдельных независимых действий для добавления на форму элементов..

_quoteWizardSettings- контейнер настроек для текущего пользователя;

Методы:

PartCostDetailFormBuilder () - конструктор класса;

async Task<IDataResult<PartCostDetailFormModel, PartCostDetailFormModel>>BuildAsync (Model contextModel) - асинхронный метод формирования модели отображения. Может выполнять в себе сложные запросы в базу данных для инициации модели, но в виду архитектурных соображений эта часть логики была вынесена в класс-помощник работы с сервисом базы данных. На вход поступает контекстная модель, которую необходимо инициировать, на выходе получается объект модели отображениятаблицы;

3.3 Модели (Models)

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

3.3.1 Класс GetPartCostDetailFormDataHelper

Представляет собой класс, получающий данные для страницы.

Поля:

_applicationContext- поле контекста приложения, содержит в себе информацию о текущем пользователе, локализации;

_dataSourceInvoker- поле исполнения процедуры в базе данных. На вход принимает модель запроса, на выходе возвращает результат выполнения процедуры;

_glossaryWordProvider-поле, позволяющее получить глосаризованное значеие текстовых составляющих страницы;

_quoteWizardSettings- контейнер настроек для текущего пользователя;

Методы:

GetPartCostDetailFormDataHelper () - конструктор класса;

asyncTaskCalculatePriceSummaryTotalsModelcontextModel) - методкалькуляцииитоговой цены на странице;

asyncTaskGetCostModelMarkupBreakdownData (ModelcontextModel) - методполучения данных для таблицы разницы в прибыли на странице;

asyncTaskGetLinkedInlineProcessRouting (ModelcontextModel) - методметодполучения данных для таблицы встроенных процессов на странице;

asyncTaskGetMarkupSummary (ModelcontextModel) - методкалькуляции прибыли на странице;

asyncTaskGetPartCostDetailFormModelData (ModelcontextModel) - методполучения данных для формы, «главный» метод получения данных, вызывается в первую очередь;

asyncTaskGetQuoteCostRawMaterial (ModelcontextModel) - методполучения данных для таблицы материалов, вводимых в процесс на странице;

asyncTaskCalculateMarkup (ModelcontextModel) - методкалькуляцииразницы в цене на странице;

asyncTaskGetGlossaryLabels (ModelcontextModel) - методполучения локализованных строковых литералов странице;

asyncTaskGetPartCostDetailItems (ModelcontextModel) - методполучения данных для таблицы составляющих процессана странице;

asyncTaskGetProcessRouting (ModelcontextModel) - методполучения процессов для конкретной записи;

asyncTaskGetQuotePartComponentCosts (ModelcontextModel) - методсоставляющих и компонент производственного процесса странице;

asyncTaskSetPriceSummary (ModelcontextModel) - методпересчета и установки нового итогового значения цены;

3.3.2 Класс UpdatePartCostDetailFormDataHelper

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

Поля:

_applicationContext- поле контекста приложения, содержит в себе информацию о текущем пользователе, локализации;

_dataSourceInvoker- поле исполнения процедуры в базе данных. На вход принимает модель запроса, на выходе возвращает результат выполнения процедуры;

_glossaryWordProvider-поле, позволяющее получить глосаризованное значеие текстовых составляющих страницы;

_quoteWizardSettings- контейнер настроек для текущего пользователя;

Методы:

UpdatePartCostDetailFormDataHelper () - конструктор класса;

asyncTaskUpdateCostModelMarkupBreakdownData (ModelcontextModel) - метод обновления данных для таблицы разницы в прибыли на странице;

asyncTaskUpdateLinkedInlineProcessRouting (ModelcontextModel) - метод обновления данных для таблицы встроенных процессов на странице;

asyncTaskUpdateMarkupSummary (ModelcontextModel) - метод обновления прибыли на странице;

asyncTaskUpdatePartCostDetailFormModelData (ModelcontextModel) - метод обновления данных для формы, «главный» метод обновления данных, вызывается в первую очередь;

asyncTaskUpdateQuoteCostRawMaterial (ModelcontextModel) - метод обновления данных для таблицы материалов, вводимых в процесс на странице;

asyncTaskUpdatePartCostDetailItems (ModelcontextModel) - метод обновления данных для таблицы составляющих процессана странице;

asyncTaskUpdateProcessRouting (ModelcontextModel) - метод обновления процессов для конкретной записи;

asyncTaskUpdateQuotePartComponentCosts (ModelcontextModel) - метод обновления составляющих и компонент производственного процесса странице;

3.3.3 Класс PartCostDetailGridHelper

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

Методы:

PartCostDetailGridHelper() - конструктор класса;

public static Dictionary<string, Tuple<Action<FormSection<PartCostDetailFormModel>>, Func<bool>>> AddBuilder(

this Dictionary<string, Tuple<Action<FormSection<PartCostDetailFormModel>>, Func<bool>>> builderDictionary,

string headerName,

Action<FormSection<PartCostDetailFormModel>> action,

Func<bool>func = null)- метод формирования секций формы отображения. На вход поступает словарь из строк-идентификаторов и кортежа методов построения секций модели; вторым параметром является идентификатор булевого типа, который дополнительно ставит ограничение на возможность добавления элемента;

AddNumericTextCssClassWhen- добавляет к определенной ячейке класс стиля по некоторому условию;

AddNumericTextCssClass- добавляет к определенной ячейке класс стиля всегда;

FirstOrDefaultMarkupValue- позволяет получить всегда корректное значение наценки для элемента коллекции наценок по определенному критерию поиска, чтобы избежать null ссылок;

3.3.4 Класс PartCostDetailQuoteHelper

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

Поля:

Набор строковых литералов, отмеченных модификатором const. Содержат в себе сведения о той или иной ошибке;

_applicationContext- поле контекста приложения, содержит в себе информацию о текущем пользователе, локализации;

_dataSourceInvoker- поле исполнения процедуры в базе данных. На вход принимает модель запроса, на выходе возвращает результат выполнения процедуры;

Методы:

PartCostDetailQuoteHelper() - конструктор класса;

IsPartCostDetailQuoteEditable- асинхронный метод который позволяет получить разрешение на изменение текущей модели как на клиентской части приложение, так и на сервере;

3.3.5 ПеречислениеItemGridType

Тип таблицы составляющих.

Поля:

SupplyItem- тип составляющих поставки;

MiscItem- тип составляющих смешанного состава;

GeneralItem- тип составляющих основных процессов.

3.4 Интерфейсы

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

3.5 Классы валидационных моделей (Validation)

К категории классов валидационных моделей относятся классы, которые реализуют интерфейс IValidationModelBuilder<T> , Т - это шаблонный параметр, устанавливается типом проверяемой модели. Реализация интерфейса включает в себя одного метода, который будет создавать модель валидации, наполнять ее правилами и возвращать. Все классы устроены одинаковым образом. Имя класса имеет постфикс ValidationBuilder, поля внутри такой модели отсутсвуют.

Методы:

PartCostDetailFormBuilder () - конструктор при необходимости;

Build() - метод, который внутри создает класс типа ValidationModel, которая поставляется фрэймворком, к созданной модели добавляются правила при помощи метода AddRuleFor(r=>r.Key).Required(). Последний метод говорит о типе проверки. Существует несколько основных типов проверки, поставляемых фрэймворком: поле является обязательным, максимальное/минимальное значение цифрового поля, максимальная/минимальная длина строкового поля, обязательный тип «дата», обязательный тип «целочисленный» и др.Каждое из правил говорит о том, какое ограничение ставится на то или иное свойство. Важным моментом является то, что те поля, которые нужно проверить в коллекции-контейнере реализуются с помощью метода AddCollectionPropertyRulesFor(). В качестве шаблонного параметра передается тип валидируемой коллекции, и только тогда устанавливается то или иное правило;

3.6 Класс QuotePartCostController

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

QuotePartCostController является главным классом в работе приложения. Основной задачей этого контроллера является управление всеми типами запросов в приложении. Каждый из методов контроллера может возвращать отображение модели (View), Файл (File), либо данные в формате JSON.

Контроллер унаследован от базового класса PlexController, который наследуется от общего типа Controller. Важным условием является реализация двух интерфейсов: IAsyncControllerи IResultFilter

public interface IAsyncController : IController

{

/// <summary>

/// Executes the specified request context.

/// </summary>

IAsyncResult BeginExecute(RequestContext requestContext, AsyncCallback callback, object state);

/// <summary>

/// Ends the asynchronous operation.

/// </summary>

void EndExecute(IAsyncResult asyncResult);

}

/// <summary>

/// Defines the methods that are required for a result filter.

/// </summary>

public interface IResultFilter

{

/// <summary>

/// Called before an action result executes.

/// </summary>

void OnResultExecuting(ResultExecutingContext filterContext);

/// <summary>

/// Called after an action result executes.

/// </summary>

void OnResultExecuted(ResultExecutedContext filterContext);

}

Первый интерфейс предназначен для организации асинхронных запросов и возможности вызывать внутри методов контроллера другие асинхронные методы. Каждый из методов должен иметь модификатор asyncи возвращаемый тип Task<>.

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

Все методы контроллера можно разделить на две составляющие: методы Viewи методы Json. К первым методам можно отнести любые методы, которые возвращают на клиент разметку с данными. Разметка представляет собой набор шаблонов, которые конфигурируются фабрикой отображения модели. Такая фабрика должна реализовывать необходимые интерфейсы и возвращать один из трех типов отображения: PageModel, PartialViewили DialogModel.

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

4. РАЗРАБОТКА ПРОГРАММНЫХ МОДУЛЕЙ

При разработке приложения «Plex Online» потребовалась реализация некоторых нестандартных вещей, как, например, функция получения глосаризованных заголовков таблиц, представленных в виде текстовой строки.

4.1 Функция получения глосаризованных заголовков таблиц

Функция получения глосаризованных заголовков делает обращение в базу данных для получения заголовков колонок, глосаризованных под текущую культуру. Основное отличие от стандартной функции заключается в том, что необходимо получить все заголовки сразу, сократив количество запросов в базу данных до одного.Более того, данная функция позволяет задавать опциональные параметры для названий и объединения колонок в Colspan. Такие параметры задаются в названии колонок через вертикальную разделительную черту. Функция расширяема, и в дальнейшем может быть увеличено количество и тип опций.

При анализе опций рассматривалось несколько различных вариантов. Первый вариант представлял собой передачу дополнительного объекта с набором необходимых параметров. Достоинства этого способа: простота программной реализации и простота разбора опций. Недостатки: для каждой опции приходится создавать новый класс, и описывать вариант поведения для этого класса.

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

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

Следует обратить внимание на следующие моменты, которые потребовались для быстрого выполнения функции. Алгоритм предполагает создание новых списков для временного хранения данных, которые могут занимать достаточно много ресурсов. Для удобства и наглядности кода было решено использовать библиотеку LINQдля выборки из списков. Вызов таких методов является каскадным. При таких вызовах создается одна копия списка, и дальнейшая селекция производится из этого списка. В конкретно данном случае были использованы функции Where(), Select(), ToList().

var bulk = labels.Where(l =>(string.IsNullOrEmpty(l) ||

l.Contains("Colspan")) ==

false)

.Select(splitAction)

.ToList();

var glossarizedDictionary =

await _glossaryWordProvider

.GetCustomerWordBulkAsync(bulk);

В представленном коде производится выборка слов, которые необходимо глосаризовать. Из данных слов составляется список, которые отправляется в базу данных. Метод GetCustomerWordBulkAsyncвозвращает словарь, в котором ключ - это исходное слово, полем значения является глосаризованное слово. Из исходного списка необходимо выбрать такие слова, которые не являются пустыми строками, чтобы исключить ошибку, и которые не содержат в себе параметра «Colspan». Далее происходит выборка из списка с помощью делегата splitAction.

Func<string, GlossaryWord>splitAction = inputLabel =>

{

string outputLabel;

if (inputLabel.Contains("Numeric"))

{

outputLabel = inputLabel.Split('|').Any() ?

inputLabel.Split('|')[0]

: string.Empty;

}

else

{

outputLabel = inputLabel;

}

return new GlossaryWord(outputLabel);

};

Данный делегат производит следующее: из каждого элемента выбирается часть строки, которую необходимо глосаризовать. В дипломном проекта используется два типа параметров: Numeric(для задания формата колонки, в которой выравнивание должно быть по левому краю) и Colspan (для создания пустой строки, которая будет растянута на число колонок, заданное в параметре). Colspan отбирается на предыдущем этапе, поэтому делегат исключает цифровые параметры и пустые строки. Строка с параметром парсится по разделителю, необходимое слово возвращается из функции.

Далее следует набор инструкций, которые собирают коллекцию выходных данных на основании списка, полученного из базы данных и текущего списка с параметрами.

var lst = new List<QuoteCostCustomGridHeader>();

foreach (var word in labels)

{

var label = new QuoteCostCustomGridHeader();

if (word.Contains("Colspan"))

{

var colspan = word.Split('|');

label.Colspan = colspan[1].ToInt32();

label.Label = string.Empty;

}

else

{

if (word.Contains("Numeric"))

{

var tempWord = word.Split('|').Any() ? word.Split('|')[0] : string.Empty;

label.Label = string.IsNullOrEmpty(tempWord) ? string.Empty : glossarizedDictionary[tempWord];

label.IsNumeric = true;

}

else

{

label.Label = string.IsNullOrEmpty(word) ? string.Empty : glossarizedDictionary[word];

}

label.Colspan = 1;

}

lst.Add(label);

}

Здесь изначально проверяется, не содержит ли исходный список параметра Colspan. В таком случае в выходную коллекцию добавляется элемент со значением, заданным в параметре. Строка парсится по разделителю, значение добавляется в элемент коллекции.

В случае, если существует глосаризованное слово, производится проверка на наличие параметра Numeric. Такая строка вновь парсится по разделителю, выставляется флаг IsNumeric. Далее исключается пустая строка, а значение глосаризованного слова берется из словаря, полученного от запроса в базу данных. Селекция из словаря производится по ключу исходного списка слов.

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

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

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

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

4.2 Вычисление суммарной наценки

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

Первым шагом будет выбор компонентов, которые относятся к группе «основные компоненты». Идентификатором этой группы является значение 2. Выборка производится стандартным методом библиотеки LINQ. Если список таких компонентов пуст, из функции возвращается исходная модель.

var partList = model.QuotePartComponentCostsGetResponseRows.Where(r => r.SubcontractGroup == 2).ToList();

var partKeys = string.Join(",", partList.Select(l => l.PartKey));

if (partKeys.IsNotNullOrEmpty() == false)

{

return model;

}

var request = new CostComponentsGetV3Request

{

PCN = _applicationContext.CurrentCustomer.PCN,

PartKeys = partKeys

};

var data = await _dataSourceInvoker.InvokeAsync<CostComponentsGetV3Request, CostComponentsGetV3Response>(request);

Из существующих записей создается строка из переменных PartKey, являющихся идентификатором конкретного компонента. Разделителем в такой строке должна быть запятая, такой формат задания требует хранимая процедура в базе данных. Вторым параметром для хранимой процедуры является уникальный номер каждого «поставщика», PCN расшифровывается как PlexCustomerNubmer.

Этот запрос возвращает список из пар Ключ/Значение. Ключом в данной ситуации будет ключ компонента, значением будет величина наценки. Каждая из величин может быть отнесена к одной из трех групп: трудовая наценка (LaborMarkup), наценка на материал (MaterialMarkup)и наценка составляющих подрядов (SubcontractMarkup)

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

var costTypeDictionary = new Dictionary<int, string>

{

{ 0, _quoteWizardSettings.CostTypeAsLabor },

{ 1, _quoteWizardSettings.CostTypeAsMaterial },

{ 2, _quoteWizardSettings.CostTypeAsSubcontract }

};

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

if (data.Rows.Any())

{

var costItem = new CostItem

{

Key = -1,

LaborSummary = 0,

MaterialSummary = 0,

SubcontractSummary = 0

};

foreach (var row in data.Rows)

{

if (costItem.Key != row.Key)

{

costItemsList.Add(costItem);

costItem = new CostItem();

costItem.Key = row.Key;

}

if (costTypeDictionary.ContainsValue(row.CostType))

{

var rowForClosure = row;

switch (costTypeDictionary.Single(r => r.Value.Contains(rowForClosure.CostType)).Key)

{

case 0:

costItem.LaborSummary += row.Cost;

break;

case 1:

costItem.MaterialSummary += row.Cost;

break;

case 2:

costItem.SubcontractSummary += row.Cost;

break;

}

}

}

if (costItem.Key != -1)

{

costItemsList.Add(costItem);

}

}

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

foreach (var row in partList)

{

var partCostItem = new CostItem

{

Key = row.PartKey ?? 0,

LaborSummary = 0,

MaterialSummary = 0,

SubcontractSummary = 0

};

var rowForClosure = row;

var tempRow = costItemsList

.SingleOrDefault(

r => r.Key ==

rowForClosure.PartKey);

if (tempRow != null)

{

partCostItem.LaborSummary = tempRow.LaborSummary;

partCostItem.MaterialSummary = tempRow.MaterialSummary;

partCostItem.SubcontractSummary = tempRow.SubcontractSummary;

}

model.PartCostItemsList

.Add(partCostItem);

}

returnmodel;

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

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

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

5. ПРОГРАММА И МЕТОДИКА ИСПЫТАНИЙ

5.1 Общее описание

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

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

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

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

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

Ниже описаны причины, почему испытание программного обеспечения является обязательным моментом при разработке:

Подобная проверка помогает удостовериться, что у выпускаемого программного обеспечения нет каких-либо технических недоработок. Если же они всё-таки есть, то её разработчики смогут узнать об этом до выпуска программного обеспечения в широкое производство и исправить их. Таким образом, можно будет гарантировать, что программное обеспечение будет работать должным образом.

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

Если программное обеспечение не проходит проверку и выпускается на рынок, то возникает вероятность его неправильной работы. Это может привести к печальным последствиям особенно, если его используют в организациях для работы с важными операциями. А это в свою очередь приведет к тому, что разработчики этого программного обеспечения понесут дополнительные убытки, поскольку именно они ответственны за неправильную работу своих программ.

Дипломный проект тестировался на машинах со следующей конфигурацией:

Intel Core i7, оперативная память 16 ГБ, видеокарта GeForce 9600MGT 256 МБ. Операционная система Windows 7 Ultimate x32 Service Pack 1;

AMD Phenom 2 ядра по 3,0 ГГц, оперативная память 8 ГБ, видеокарта Ge Force 760 GTX 512Mb. Операционная система Windows 7 Ultimate x64.

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

5.2 Ручное тестирование

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

Тестирование проводилось как модульно, так и в полном цикле работы приложения.

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

Полный цикл тестирования включал в себя:

Добавление новых записей в каждую из таблиц.

Загрузку деталей производителем.

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

Создание некорректных частей, деталей и компонентов.

Проверка правильного выполнения логической составляющей приложения.

Проверка интеграции с другими приложениями системы.

Пример чек листа тестирования создания проекта пользователем находится в Приложении Д.

5.3 Юнит-тестирование

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

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

Цель юнит-тестирования -- изолировать отдельные части программы и показать, что по отдельности эти части работоспособны.

Юнит-тестирование позже позволяет программистам проводить рефакторинг, будучи уверенными, что модуль по-прежнему работает корректно (регрессионное тестирование).

Поскольку некоторые классы могут использовать другие классы, тестирование отдельного класса часто распространяется на связанные с ним. Например, класс пользуется базой данных; в ходе написания теста программист обнаруживает, что тесту приходится взаимодействовать с базой. Это ошибка, поскольку тест не должен выходить за границу класса. В результате разработчик абстрагируется от соединения с базой данных и реализует этот интерфейс, используя свой собственный mock-объект. Это приводит к менее связанному коду, минимизируя зависимости в системе.

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

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

Юнит-тестами покрывались наиболее критические участки работы приложения такие как:

1) Создание и редактирование записей.

2) Функционирование различных типов компонент.

3) Добавление\удаление записей.

4) Правильность расчетов при поступлении некорректных данных на вход функций.

6. РУКОВОДСТВО ПОЛЬЗОВАТЕЛЯ

6.1 Развертывание приложения

Программное обеспечение должно быть развёрнуто на веб-сервере IIS перед началом использования. В данном разделе даётся пошаговая инструкция по развёртыванию и запуску веб-сервисов.

Одним из системных требований к установке приложения является наличие IIS и .NET Framework версии 4. В операционной системе Windows 7 IIS является стандартным компонентом, который поставляется с самой ОС. По умолчанию IIS выключен. Включить его можно зайдя в панель управления.

Рисунок 6.1 - Окно включения IIS

Для включения IIS достаточно кликнуть на самом верхнем узле в иерархии (Internet Information Services). Здесь же нужно включить microsoft .NET Framework 3.5.1.

После включения IIS необходимо установить поддержку ASP.NET, на базе которого и будут хоститься сервисы. Делается это с помощью утилиты aspnet_regiis с ключом -i. После выполнения команды ОС должна установить ASP.NET версии 4.

Чтобы проверить, включился ли IIS, можно открыть браузер и написать в адресной строке «localhost». Если IIS был успешно установлен, в браузере появится следующая картинка:

Рисунок 6.2 - DefaultWebSite развёрнутый на IIS

IIS при переходе по адресу localhost загружает веб-сайт по умолчанию, который в англоязычной версии ОС носит название DefaultWebSite.

WCF веб-сервисы могут быть развёрнуты в рамках веб-приложения. Вся работа с IIS и его настройка осуществляется в менеджере веб-сервера, который может быть запущен путём запуска приложения inetmgr из меню «Пуск, выполнить». После этого откроется окно, изображённое на рис. 6.3.

Развернуть веб-сервис можно кликнув правой кнопкой мыши на любом веб-сайте (например DefaultWebSite) и выбрав пункт меню «Add application». Появится диалоговое окно, в котором в поле Alias указывается имя сайта, в качестве пула приложения необходимо оставить значение по умолчанию - DefaultAppPool, а в качестве физического пути к веб-сайту указывается папка, содержащая файлы веб компонента сайта PharmDirect.Web.

Следующим этапом является настройка Application Pool. У него должны быть выставлены Managed режим и .NET Framework 4.5. Также необходимостью является то, что пул а следовательно и само приложение должны быть запущены от пользователя Network Service. В любом другом случае приложение не сможет зайти в базу данных SQL. Также должен быть установлен Microsoft Access Database Engine для работы с OLE Db провайдером для работы с Excel документами. Если установка произведена не будет, сайт запустится однако при попытке загрузки отчета будет выдаваться ошибка соединения.

Проверить правильность развёртывания веб-сайта можно из окна управления IIS. После клика на веб-сайт, нужно нажать кнопку «Browse» на панели «Actions» справа.

Рисунок 6.3 - Окно программы IIS Manager

В случае успешного развёртывания в браузере запустится логин форма сайта PlexOnline

После запуска возможно возникновение серверных ошибок.

Такие ошибки обычно бывают связаны со средой запуска приложения. В разных версиях ОС директориям назначаются разные права. Поэтому если ошибки связаны с нехваткой прав, необходимо проверить наличие прав для пользователя IIS_IUSRS в папках

С:\Windows\ServiceProfiles\NetworkService\AppData\Local\Temp

С:\Windows\Temp

Эти директории используются IIS как рутовые для запуска веб-приложений, поэтому нехватка прав у процесса IIS_IUSRS может вызвать ошибку доступа.

Группа IIS_IUSRS заменяет группу IIS_WPG. В IIS 6.0 группа IIS_WPG обеспечивает минимальные права для запуска рабочего процесса, и администратор должен вручную добавить в эту группу учетную запись, чтобы предоставить пользовательские учетные данные для рабочего процесса. В IIS 7.0 аналогичную роль играет группа IIS_IUSRS, но явно добавлять учетные записи в группу не требуется. Вместо этого IIS 7.0 автоматически зачисляет учетные записи в IIS_IUSRS, когда они назначаются в качестве удостоверения для пула приложений.

Программное обеспечение разворачивалось на машинах с ОС Windows 7 c IIS 7.5. Каких-либо проблем с развёртыванием, кроме описанных ранее, не возникало.

6.2 Авторизация пользователя в системе

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

Авторизация начинается с шага, в котором пользователь вводит свои юридические реквизиты, а также данные о руководстве организации.

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

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

Рисунок 6.4 - Окно авторизации пользователя

Рисунок 6.5 - Окно с неверными ключами

6.3 Создание новых записей в таблицах

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

PartCostDetail, основная информация о квоте.

SubComponents, зависимые процессы от текущего и компоненты текущего процесса.

RawMaterialCostsстоимость сырых материалов, вводимых в процесс.

PartComponentCost, стоимость составляющих процесса.

SupplyItemCost, стоимость поставляемых материалов.

Miscellaneous Costs, прочие расходы.

Fixed Costs, фиксированные расходы.

Разовые затраты.

Суммарные расходы.

Страница всегда может открываться в двух режимах: если текущий процесс находится на рассмотрении (RFQ, запрос на квоту), тогда ни одно из редактируемых полей не будет доступно для изменения. Для защиты приложения от несанкционированного доступа на серверной части выполняется дополнительная проверка на возможность редактирования квоты. Если на клиентской части произойдет ошибка, и квота будет редактируемой, то с сервера вернется невалидный ответ. Пользователь также может посмотреть, оценить, сравнить с похожими процессами.

Второй режим предоставляет полную свободу в управлении процессом.

Рисунок 6.6 - Экран редактирования записи

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

Рисунок 6.7 - Диалоговое окно добавления новой записи с рабочей валидацией

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

Рисунок 6.8 - Обновление страницы с некорректными значениями

При успешном обновлении страницы пользователь увидит сообщение об «успешном обновлении записи».

Рисунок 6.9 - Успешное обновление данных

7. ТЕХНИКО-ЭКОНОМИЧЕСКОЕ ОБОСНОВАНИЕ РАЗРАБОТКИ ДИПЛОМНОГО ПРОЕКТА

7.1 Характеристика программного продукта

Большое значение для работодателя в современном мире имеет планирование и управление ресурсами и процессами на целом предприятии.

«Клиент-серверная часть приложения «Plex Online» для управления и контроля производственного процесса предприятия» представляет собой ERP систему (Enterprise Resource Planning System - Система Планирования Ресурсов Предприятия, пер. с англ.) управления ресурсами компании.

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

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

Разработка подобной единой системы - непростая задача. Обычно каждое подразделение имеет собственную компьютерную систему, оптимизированную для решения его задач.

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

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

Экономическая целесообразность инвестиций в разработку и использование программного продукта осуществляется на основе расчета и оценки следующих показателей:

Разработка проектов программных средств связана со значительными затратами ресурсов (трудовых, материальных, финансовых). В связи с этим создание и реализация каждого проекта программного обеспечения нуждаются в соответствующем технико-экономическом обосновании (ТЭО).


Подобные документы

  • Исследование спецификации логической игры "Сапёр". Системное и функциональное проектирование приложения. Разработка программных модулей. Обзор классов, необходимых для создания интерфейса данного приложения. Инструменты для реализации логической игры.

    курсовая работа [1,2 M], добавлен 13.01.2016

  • Разработка приложения "Программа по приему платежей и расчету по газу", которая послужит для учета и статистики платежей в расчетно-кассовом центре. Системное, функциональное проектирование. Разработка программных модулей. Программа и методика испытаний.

    дипломная работа [806,2 K], добавлен 13.02.2016

  • Системное и функциональное проектирование. Описание взаимодействия с сервером, классов системных компонентов. Обзор функциональных классов из пакетов helpers, dialogs и networking. Разработка программных модулей. Технико-экономическое обоснование проекта.

    дипломная работа [1,7 M], добавлен 15.06.2014

  • Структурные подразделения и отделы организации, ее технические программные средства. Разработка приложений обработки данных на ассемблере, языке программирования высокого уровня. Тестирование и оптимизация программных модулей. Разработка документации.

    отчет по практике [175,0 K], добавлен 30.09.2022

  • Разработка Web-приложения для ООО "Научно-производственная фирма по применению информационных технологий в электрических сетях". Техническое задание, проектирование процессов, создание базы данных, разработка дизайна, тестирование и отладка сайта.

    дипломная работа [3,8 M], добавлен 24.06.2011

  • Разработка приложения "Plex Online" для контроля online-мониторинга производственного процесса, продаж, остатков товара и прочим функционалом. Разработка и тестирование программных модулей. Оптимизация работы базы данных путем кэширования данных.

    дипломная работа [1,8 M], добавлен 06.06.2016

  • Возможности среды программирования delphi при разработке приложения с визуальным интерфейсом. Отладка программных модулей с использованием специализированных программных средств. Тестирование программного обеспечения. Оптимизация программного кода.

    курсовая работа [974,0 K], добавлен 21.12.2016

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

    курсовая работа [3,3 M], добавлен 28.04.2014

  • Структура базы данных web-приложения предприятия ООО "Седово"; автоматизация процесса передачи документов. Разработка технического задания, проектирование БД, функциональное назначение web-приложений, тестирование, отладка и размещение в сети Internet.

    дипломная работа [5,3 M], добавлен 24.06.2011

  • Выполнение отладки программных модулей с использованием специализированных программных средств. Тестирование, оптимизация кода модуля. Реализация базы данных в конкретной системе управления. Анализ проектной и технической документации на уровне компонент.

    дипломная работа [5,0 M], добавлен 08.06.2017

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.