Автоматизация рабочего места работника регистратуры
Автоматизация
рабочего места работника регистратуры
1. Основная часть
При анализе будем руководствоваться
следующей диаграммой вариантов использования:
Рис. 1. Диаграмма основных вариантов
использования АРМ работника регистратуры
При создании нового врача оператор
вносит в БД всю информацию о нем, которая включает: Ф.И.О. врача, его
специализация, номер кабинета, и график работы.
Таким образом, приходим к введению
класса Doctor, моделирующего сотрудника поликлиники.
Такие свойства как Ф.И.О.,
специализация и номер кабинета класса Doctor можно реализовать стандартными примитивными типами данных
платформы.NET Framework.
При реализации компонента графика
приема врача ограничимся максимальным сроком возможной записи равным одной
неделе.
Данный компонент должен
обеспечивать:
· Составление бланка
расписания с указанным максимальным временем приема одного пациента
· Автоматическое
удаление просроченных записей и заполнение бланка расписания рабочего дня на
следующую неделю
· Добавление сведений
о пациенте в журнал приема выбранного врача
· Изменение сведений
о пациенте в журнале приема выбранного врача
Данный компонент можно декомпозировать
на два подкомпонента - класс DayShedule, инкапсулирующий расписание приема на один день, и класс Timetable, агрегирующий
класс DayShedule и предоставляющий
недельный (максимальный срок, которым мы ограничились) график работы доктора.
Кроме того, для управления базой
данных необходимо разработать графический интерфейс пользователя.
Исходя из структуры системы, удобным
будет интерфейс с разделением сотрудников поликлиники и их пациентов. Также
необходимо предоставить удобную форму для ввода информации о самих сотрудниках
и их режиме работы.
При проектировании интерфейса, будем
руководствоваться следующей упрощенной диаграммой последовательности:
Рис. 2. Диаграмма последовательности
работы в интерфейсе будущей АРМ
В развернутом виде эта диаграмма
представлена на рис. 5.
По итогам анализа имеем
представление об общей структуре разрабатываемой системы и ее будущем
интерфейсе.
В целом, структуру АРМ представляет
следующая диаграмма компонентов:
В качестве СУБД остановимся на
выборе компонента Binding Source стандартной поставки .NET Framework, т. к. он
обеспечивает удобное создание и последующее редактирование сохраняемых в БД
сущностей.
Рис. 3. Диаграмма компонентов
Исходя из поставленных требований и
задач, была составлена следующая диаграмма классов:
Также теперь есть основания
предположить будущую аппаратную часть системы:
Рис. 3. Диаграмма классов
Рис. 4. Диаграмма развертывания
системы
Исходя из диаграммы развертывания и
диаграммы прецедентов, базу данных удобно разместить на одном из серверов
поликлиники, а клиент разрабатываемой АРМ установить непосредственно на рабочие
компьютеры операторов и сотрудников больницы.
Рис. 5. Развернутая диаграмма
последовательности
На этапе анализа было выявлено три
класса, совместная работа которых обеспечит выполнение поставленных задач. Теперь
необходимо спроектировать взаимодействие этих классов между собой и определить
операции над объектами класса.
Проектирование класса Doctor:
При проектировании будем
пользоваться следующей диаграммой возможных состояний сотрудника:
Рис. 5. Диаграмма состояний класса Doctor
На этапе анализа были выявлены
необходимые свойства данного класса, теперь опишем их сигнатуру:
· + BirthDate: DateTime; дата рождения
· + CabinetNumber: Int; номер
кабинета
· + Name: String; Ф.И.О.
· + Specialization: String; специализация
· + Timetable: Timetable; график
приема
Данные свойства предоставляют
публичный аксессор (get) и публичный мутатор (set) с добавлением к нему логики проверки значений на корректность.
При редактировании данных сотрудника
необходимо обеспечить возможность отмены внесенных изменений, что наталкивает
на необходимость имплементации интерфейса ICloneable, возвращающего копию
объекта класса. В результате в класс добавляется еще один метод:
· + Clone(); метод, возвращающий
копию вызывающего объекта
Так как для сохранения данных был
выбран агрегирующий компонент BindingSource, необходимо предоставить возможность создания объектов класса Doctor с полями, значение которых задано по умолчанию. Таким образом,
необходимо объявить конструктор без параметров:
· + Doctor()
Класс Doctor связан с классом Timetable композицией.
При проектировании класса Doctor получена следующая
диаграмма, иллюстрирующая его интерфейс:
Рис. 6. Диаграмма класса Doctor
Проектирование класса DayShedule:
При проектировании будем
использовать следующую диаграмму:
Рис. 7. Диаграмма последовательности
работы с классом DayShedule
Класс DayShedule, моделирующий
график приема доктора на определенный день недели, и предоставляющий
инкапсулированные в нем данные в формате «ключ - значение» (где ключ - время
приема, назначенное пациенту, значение - Ф.И.О. пациента) удобно унаследовать
от класса Dictionary<TimeSpan, string> входящего в стандартную
поставку платформы.NET Framework.
Кроме того, в данном классе также
необходимо инкапсулировать следующие свойства:
· + Date: DateTime; Дата,
следующего рабочего дня
· + DayOfWeek: DayOfWeek; День недели, на
который составляется график
· + Duration: TimeSpan; Продолжительность
рабочего дня
· + EndTime: TimeSpan; Время
окончания рабочего дня
· + Interval: TimeSpan; Время,
выделенное на прием одного пациента
· + IsExpired: bool; Просрочен
ли график
· + StartTime: TimeSpan; Время начала
рабочего дня
Также, для реализации требуемого
поведения, поместим в данный класс следующие методы и конструкторы:
· + DayShedule; конструктор
класса, с передаваемым ему параметром DayOfWeek
· + SyncDate; метод,
синхронизирующий текущую дату с датой в журнале приема
· - ClearTasks; функция,
необходимая для очистки просроченных записей. Вызывается в методе SyncDate
· - ListDate; функция,
для установления следующей даты дня недели, на который составляется данное
расписание
Так как данный класс наследуются от Dictionary<TimeSpan, string>, также необходимо
переопределить следующие методы и конструкторы базового класса:
· # DayShedule(SerializationInfo); конструктор,
необходимый для десереализации объектов класса
· + GetObjectData;
метод, необходимый для сериализации объектов класса
Класс DayShedule - вспомогательная единица инкапсуляции, используемая для обеспечения
работы других классов, разрабатываемой системы.
В ходе проектирования класса,
получили следующую диаграмму его интерфейса:
Рис. 7. Диаграмма класса DayShedule
Проектирование класса Timetable:
Класс Timetable создан для агрегации объектов класса DayShedule и моделирует график
работы врача на неделю.
Для использования средств работы с
коллекциями LINQ платформы.NET Framework, реализуем в данном классе интерфейс
IEnumerable<DayShedule>. Данный интерфейс
позволяет организовать простую итерацию по объектам DayShedule, и также (с использованием LINQ) осуществлять поиск и
сортировку коллекции.
В итоге, интерфейс класса
представляется следующими свойствами, представляющими расписания на каждый день
недели:
· + Monday: DayShedule
· + Tuesday: DayShedule
· + Wednesday: DayShedule
· + Thursday: DayShedule
· + Friday: DayShedule
· + Saturday: DayShedule
· + Sunday: DayShedule
Данные свойства хранятся в приватном
поле _days: List<DayShedule>
Методы, инкапсулированные в данном
классе:
· Timetable; конструктор по
умолчанию
· Sync; метод,
синхронизирующий дату каждого дня графика с текущей датой
· this[]; перегруженный
оператор индексирования
Для имплементации интерфейса IEnumerable<DayShedule> необходимо
реализовать два метода:
· + GetEnumerator;
· - IEnumerable. GetEnumerator;
Объект класса Timetable хранится в каждом экземпляре класса Doctor. Таким образом, мы
имеем отношение композиция между классами.
Диаграмма, иллюстрирующая интерфейс
класса Timetable:
Рис. 9. Диаграмма класса Timetable
На этом этап проектирования можно
закончить. Его результатом является получение полного представления о структуре
разрабатываемой системы, интерфейсах необходимых классов и их взаимодействии.
Также по итогам проектирования была
получена следующая диаграмма:
Рис. 10. Диаграмма зависимостей
Использование базовых принципов ООП:
Наследование:
Класс DayShedule наследуется от типа платформы.NET Framework Dictionary<TimeSpan, string>, в итоге DayShedule также унаследует все
реализованные интерфейсы базового класса, такие как:
· IDictionary; предоставляет
элементы коллекции в виде «ключ - значение»
· ICollection; определяет
методы, используемые для управления коллекциями
· IEnumerable; предоставляет
методы для простого перебор элементов в коллекции
· ISerializable; позволяет
объекту управлять его собственной сериализацией и десериализацией
Класс Timetable наследует интерфейс IEnumerable и переопределяет его виртуальные методы.
Класс Doctor реализует интерфейс ICloneable
Инкапсуляция:
Инкапсулированными переменными
классов являются все публичные свойства этих классов.
Там, где это было возможно,
использовались такие средства инкапсуляция ЯП C# как автоматические свойства. В
остальных случаях добавлялись дополнительные поля классов, обработкой которых
занимались явно заданные свойства с необходимыми проверками в мутаторе.
Обработка исключений:
При написании системы активно
использовались средства обработки исключений.
Оператор throw использовался при
попытке задать некорректное значение свойству класса. Блоки try/catch использовались для
облегчения обработки некорректного ввода, и в случае выброшенного исключения, с
помощью этих блоков пользователю предоставлялась информация о произошедшей
ошибке.
Тестирование
На выбор: открытие ранее созданной
базы данных или создание новой
Рис. 11. Начальный экран работы
программы
Меню работы с персоналом:
Рис. 12. Инструменты работы с
персоналом
Добавление сотрудника
В меню, показанном на рис. 12 выберем
пункт «Добавить»
Рис. 13. Редактирование данных
Рис. 14. Составление графика приема
врача
Добавление пациента
В главном окне программе, выберем
необходимого врача.
Рис. 15. Выбор, на какой день
записываем пациента
Поиск
Рис. 17. Возможные способы поиска
Сортировка
Рис. 18. Возможные способы
сортировки
Удаление сотрудника
В главном окне выберем сотрудника,
которого хотим удалить, затем в меню «Сотрудники» выберем пункт «Удалить».
Рис. 19. Удаление сотрудника
Заключение
В ходе работы, пройдя основные этапы
разработки программного обеспечения, было создано приложение, выполняющее
поставленные задачи и удовлетворяющее поставленным требованиям.
Спроектированный графический интерфейс пользователя отвечает современным
требованием юзабилити.
В качестве парадигмы
программирования была выбрана концепция ООП. Были использованы такие полезные
средства, предоставляемые в рамках этой концепции, как: наследование,
инкапсуляция, композиция и агрегация классов.
Разработанное приложение, хотя и
позволяет выполнять основные функции работника регистратуры, на данном этапе не
позволяет выполнять следующие функции:
· Авторизация в системе
и разделение привилегий пользователей.
· Сохранение истории
болезни пациента.
· Дополнительные
сведения о пациенте.
· Предоставление
отчетности о количестве обслуженных пациентов, проведенном лечении и
процедурах.
В дальнейшем, эти функции будет легко
включить в существующую архитектуру программы, так как в целом ее структура
является слабо связанной и легко расширяемой.
Список литературы
1. Э. Троелсен. Язык программирования С# 2010 и платформа.NET
4.0, 5-е изд. И.Д. Вильямс, 2011. - 1392 с.
. Н. Трей. C# 2010: Ускоренный курс для профессионалов. И.Д. Вильямс, 2010. -
592 с.
. Фаулер М., Скотт К. UML. Основы. Символ-Плюс, 2002. - 192 с.
. Кватрани Т. Rational Rose и UML. Визуальное моделирование. ДМК Пресс, 2001. - 176 с.
Приложение
Листинг программы
Класс
Doctor
#region
Namespace directivesSystem;System. Text. RegularExpressions;Victor. Timetable;
#endregionRegistry
{
[Serializable]class
Doctor: ICloneable
{
#region
FieldsDateTime _birthDate;int _cabinetNumber;string _name;string _specialization;
#endregion
#region
ConstructorsDoctor()
{= new
Timetable();
}Doctor
(string name,birthDate,speciality,cabinetNumber,timetable)
:
this()
{=
name;= birthDate;= speciality;= cabinetNumber;= timetable;
}
#endregion
#region
PropertiesTimetable Timetable {get; private set;}string Name
{{return
_name;}
{
value = value. Trim();(! Regex. IsMatch (value,
@ «^[А-я]+\s+([А-я]\.\s*) {2}$»))new ArgumentException («Ф.И.О. врача задано неверно»);
_name =
value;
}
}DateTime
BirthDate
{{return
_birthDate;}
{((DateTime.
Today - value).TotalDays < 6564) // 18 лет new ArgumentException («Дата рождения задана неверно»);
_birthDate
= value;
}
}string
Specialization
{{return
_specialization;}
{
value = value. Trim();(! Regex. IsMatch (value,
@ «^[А-я]+$»))new ArgumentException («Специальность задана неверно»);
_specialization
= value;
}
}int
CabinetNumber
{(value
<= 0) new ArgumentException («Номер кабинета должен быть больше ноля»);
_cabinetNumber
= value;
}
}
#endregion
#region
Implementation of ICloneableobject Clone()
{
#endregion
}
}
Класс
Timetable
#endregionVictor.
Timetable
{
[Serializable]class
Timetable: IEnumerable<DayShedule>
{
#region
Fields and propertiesreadonly DayShedule Friday;readonly DayShedule
Monday;readonly DayShedule Saturday;readonly DayShedule Sunday;readonly
DayShedule Tuesday;readonly DayShedule Wednesday;readonly
List<DayShedule> _days;
#endregion
#region
ConstructorsTimetable()
{= new
DayShedule (DayOfWeek. Monday);= new DayShedule (DayOfWeek. Tuesday);=
new DayShedule (DayOfWeek. Wednesday);= new DayShedule (DayOfWeek. Thursday);=
new DayShedule (DayOfWeek. Friday);= new DayShedule (DayOfWeek. Saturday);=
new DayShedule (DayOfWeek. Sunday);
_days =
new List<DayShedule>
{,,,,,,
};
}
#endregion
#region
IndexersDayShedule this [int index]
{{return
_days[index];}
}
#endregion
#region
Public methodsvoid RemoveExpired()
{(DayShedule
day in this)
day. SyncDate();
}
#endregion
#region
Implementation of IEnumerableIEnumerator<DayShedule> GetEnumerator()
{_days.
Where (t => t. IsSet).GetEnumerator();
}IEnumerable.
GetEnumerator()
{GetEnumerator();
}
#endregion
}
}
Класс
DayShedule
#region
Namespace directivesSystem;System. Collections. Generic;System. Linq;System.
Runtime. Serialization;
#endregionVictor.
Timetable
{
[Serializable]class
DayShedule: Dictionary<TimeSpan, string>
{
#region
propertiesDayOfWeek DayOfWeek {get; private set;}DateTime Date {get; private
set;}TimeSpan StartTime {get; private set;}TimeSpan EndTime {get; private
set;}TimeSpan Duration {get; private set;}TimeSpan Interval {get; private
set;}bool IsSet {get; private set;}bool IsExpired
{{return
DateTime. Today > Date;}
}
#endregion
#region
ConstructorsDayShedule (SerializationInfo info, StreamingContext context)
: base
(info, context)
{=
(DayOfWeek) info. GetValue («DayOfWeek», typeof (DayOfWeek));= info. GetBoolean
(«IsSet»);(! IsSet);= info. GetDateTime («Date»);= (TimeSpan) info. GetValue
(«StartTime», typeof (TimeSpan));= (TimeSpan) info. GetValue («EndTime», typeof
(TimeSpan));= (TimeSpan) info. GetValue («Duration», typeof (TimeSpan));=
(TimeSpan) info. GetValue («Interval», typeof (TimeSpan));
}DayShedule
(DayOfWeek day)
{= day;
}
#endregion
#region
Public Methodsvoid Set (TimeSpan startTime, TimeSpan endTime, TimeSpan
interval)
{(startTime.
Days > 0) new ArgumentException («Начальное время задано неверно»);
if
(endTime. Days > 0) new ArgumentException («Конечное время задано неверно»);
if
(startTime >= endTime) new ArgumentException («Начальное время должно быть больше конечного»);
StartTime
= startTime;= endTime;= EndTime - StartTime;(interval > Duration) new ArgumentException («Интервал превышает рабочий промежуток»);
IsSet =
true;= interval;();();floatBound = StartTime;(floatBound <
EndTime)
{(floatBound,
string. Empty);
floatBound += interval;
}
}void
Unset()
{=
false;
}void
SyncDate()
{(IsExpired)
{delta
= (DateTime. Today - Date).TotalDays/7;factor = (int) (Math. Abs((int) delta -
delta) < double. Epsilon
? delta
: delta
+ 1);+= new TimeSpan (factor*7, 0, 0, 0);();
}
}
#endregion
#region
Private methodsvoid ClearTasks()
{(TimeSpan
time in Keys. ToList())[time] = string. Empty;
}void
SetNextDateOfDayOfWeek()
{=
DateTime. Today;(Date. DayOfWeek!= DayOfWeek)= Date. AddDays(1);
#endregion
#region
Overrides of Dictionary<TimeSpan, string>override void GetObjectData
(SerializationInfo info, StreamingContext context)
{.
GetObjectData (info, context);. AddValue («DayOfWeek», DayOfWeek);. AddValue
(«IsSet», IsSet);(! IsSet);. AddValue («Date», Date);. AddValue («StartTime»,
StartTime);. AddValue («EndTime», EndTime);. AddValue («Duration», Duration);.
AddValue («Interval», Interval);
}
#endregion
}
}
регистратура интерфейс программа
автоматизация