5. ProjectTitle - название проекта.
6. ProjectDescription - описание проекта.
7. ProjectTask - задача проекта.
8. Stakeholders - список всех стейкхолдеров.
9. Requirements - список всех требований.
10. Employees - список всех сотрудников.
11. Tests - список всех тестов
12. LoadProjectDescription - метод загрузки описания проекта.
13. LoadRequirements - метод загрузки требований.
14. LoadEmployees - метод загрузки сотрудников.
15. LoadTests - метод загрузки тестов.
Рисунок 3.1. Класс «Content» игры «IT-менеджер»
Класс «Project», показанный на рис. 3.2 содержит следующие свойства и методы:
1. Budget - бюджет проекта.
2. Time - длительность проекта.
3. IterationTime - длительность одной итерации.
4. Employees - список всех сотрудников.
5. Requirements - список всех требований.
6. Stakeholders - список всех стейкхолдеров.
7. Tests - список всех тестов.
8. PassedDays - свойство, возвращающее текущий день проекта.
9. PassedIterationDays - свойство, возвращающее текущий день итерации.
10. Iteration - свойство, возвращающее текущий номер итерации.
11. Statisfaction - свойство, возвращающее удовлетворенность заказчика.
12. IncrementSatisfaction - метод, увеличивающий удовлетворенность заказчика.
13. DecrementSatisfaction - метод, уменьшающий удовлетворенность заказчика.
14. AddEmployee - метод добавления нового сотрудника.
15. RemoveEmployee - метод удаления выбранного сотрудника.
16. IncrementDay - метод, увеличивающий количество прошедших дней.
17. PayOut - метод, выплачивающий заработную плату сотрудникам.
18. IncrementIteration - метод, увеличивающий количество прошедших итераций.
Рисунок 3.2. Класс «Project» игры «IT-менеджер»
Класс «Employee», изображенный на рис. 3.3, содержит следующие свойства и методы:
1. Id - уникальный идентификатор сотрудника.
2. Name - имя сотрудника.
3. Image - ссылка на фотографию сотрудника.
4. BitmapImage - фотография сотрудника.
5. AnalystSkill - навык аналитика.
6. AnalystCapacity - производительность аналитика.
7. CurrentAnalystCapacity - текущая производительность аналитика.
8. DeveloperSkill - навык разработчика.
9. DeveloperCapacity - производительность разработчика.
10. CurrentDeveloperCapacity - текущая производительность разработчика.
11. TesterSkill - навык тестировщика.
12. TesterCapacity - производительность тестировщика.
13. CurrentTesterCapacity - текущая производительность тестировщика.
14. ArchitectSkill - навык архитектора.
15. ArchitectCapacity - производительность архитектора.
16. CurrentArchitectCapacity - текущая производительность архитектора.
17. Salary - заработная плата сотрудника.
18. SumSalary - выплаченная заработная плата сотруднику.
19. FoundRequirementsNumber - количество найденных требований.
20. DevelopedCodeLinesNumber - количество строк кода разработанного модуля.
21. FoundErrorsNumber - найденное количество ошибок.
22. IsHired - статус нанятости.
23. ClearCurrentCapacity - метод, очищающий записи текущих производительностей.
24. Hiring - метод найма сотрудника.
25. Unhiring - метод увольнения сотрудника.
Рисунок 3.3. Класс «Employee» игры «IT-менеджер»
Класс «Stakeholder» (рис. 3.4) содержит следующие свойства и методы:
1. Id - уникальный идентификатор стейкхолдера.
2. Name - название стейкхолдера.
3. Type - тип.
Рисунок 3.4. Класс «Stakeholder» игры «IT-менеджер»
Класс «Test», изображенный на рис. 3.5, содержит следующие свойства и методы:
1. Name - название теста.
2. IsImportant - статус важности.
Рисунок 3.5. Класс «Test» игры «IT-менеджер»
Класс «Requirement» (рис. 3.6) содержит следующие свойства и методы:
1. Id - уникальный идентификатор требования.
2. Name - название требования.
3. Stakeholder - стейкхолдер, предъявивший требование.
4. ImportantIndex - показатель важности.
5. MinimumSkill - минимальный уровень навыка для поиска требования.
6. DetectionIterationNumber - минимальный номер итерации для обнаружения.
7. IsFound - статус найдено требование или нет.
8. SubRequirements - список нижестоящих требований.
9. SubModules - список нижестоящих модулей.
10. FoundByEmployee - сотрудник, обнаруживший требование.
11. MainRequirement - главное требование.
12. AllSubRequirements - список всех нижестоящих требований.
13. AllSubModules - список всех нижестоящих модулей.
14. GetArchitectedModules - метод, возвращающий список модулей, добавленных архитектором.
15. GetUnarchitectedModules - метод, возвращающий список модулей, еще не добавленных архитектором.
16. AddSubRequrement - метод добавления нижестоящего требования.
17. AddSubModule - метод добавления нижестоящего модуля.
18. GetSubrequirements - метод, возвращающий список всех нижестоящих требований.
19. GetSubmodules - метод, возвращающий список всех нижестоящих модулей.
Рисунок 3.6. Класс «Requirement» игры «IT-менеджер»
Класс «Module», показанный на рис. 3.7, содержит следующие свойства и методы:
1. Name - название модуля.
2. CalculatedExpectedCodeLinesNumber - рассчитываемое архитектором количество строк кода.
3. ExpectedCodeLinesNumber - ожидаемое количество строк кода, установленное в программе.
4. ActualCodeLinesNumber - реальное затрачиваемое количество строк кода разработчиком.
5. Deadline - номер дня окончания разработки модуля.
6. ImportantIndex - показатель важности.
7. IsDeveloped - статус разработки модуля.
8. Iteration - номер итерации добавления работы в план.
9. Tests - список тестов.
10. Errors - список ошибок.
11. Developer - разработчик.
12. Tester - тестировщик.
13. AcceptedByStakeholder - статус принятия стейкхолдером.
14. Requirement - свойство, возвращающее главное требование.
15. CountFixErrors - свойство, возвращающее количество исправленных ошибок.
16. CountNotFixErrors - свойство, возвращающее количество неисправленных ошибок.
Рисунок 3.7. Класс «Module» игры «IT-менеджер»
Класс «Error», изображенный на рис. 3.8, содержит следующие свойства и методы:
1. Type - тип ошибки.
2. IsFixed - статус исправления ошибки.
3. SetErrorType - метод, задающий тип ошибки.
Рисунок 3.8. Класс «Error» игры «IT-менеджер»
3.1.2 Реализация разработанных алгоритмов
В классе «Manager» содержится метод, реализующий алгоритм определения модулей с использованием выбранного архитектора. В представлении программного кода он выглядит следующим образом:
public List<Module> ModelingArchitectedModules(Employee architect)
{
List<Module> newArchitectedModules = new List<Module>();
if (architect != null)
{
foreach (Requirement req in AllFoundRequirements)
{
if (architect.CurrentArchitectCapacity < architect.ArchitectCapacity)
{
List<Module> unarchitectedModules = req.GetUnarchitectedModules();
if (unarchitectedModules.Count > 0)
{
foreach (Module mod in unarchitectedModules)
{
int inaccuracy = 100 - architect.ArchitectSkill;
int randomInaccuracy = RandomNumber.Shared.GetRandomNumberBetween(100 - inaccuracy, 100 + inaccuracy + 1);
mod.CalculatedExpectedCodeLinesNumber = mod.ExpectedCodeLinesNumber * randomInaccuracy / 100;
newArchitectedModules.Add(mod);
}
architect.CurrentArchitectCapacity++;
}
}
}
architect.ClearCurrentCapacity();
Project.IncrementDay();
Project.PayOut();
}
return newArchitectedModules;
},
где inaccuracy - процент разброса выдачи результата от архитектора,
randomInaccuracy - разброс от идеального установленного числа строк кода модуля.
В качестве входного параметра данный метод принимает объект класса «Employee», который по смыслу является архитектором. Выходными данными является список модулей, которые были составлены сотрудником и установлены значения количества строк кода для разработки этих модулей.
Следующий метод был реализован согласно алгоритму расчета ожидаемой длительности разработки и тестирования выбранных модулей с учетом характеристик назначенного сотрудника. В связи с тем, что алгоритмы расчета длительности разработки и тестирования во многом схожи, то в программном коде этот алгоритм был унифицирован и создан один универсальный метод подходящий под обе потребности. Данный разработанный метод представлена в программе следующим образом:
public int CalculateExpectedTime(List<Module> modules, int capacity, bool isNewDevelop = true, bool alreadyInPlan = false)
{
int sumCodeLinesInDay = 0;
double days = 0;
foreach (var job in modules)
{
int actualExpectedCodeLinesNumber = job.ActualCodeLinesNumber > 0 && (alreadyInPlan && job.Developer == null || !alreadyInPlan && !isNewDevelop) ? job.ActualCodeLinesNumber : job.CalculatedExpectedCodeLinesNumber;
sumCodeLinesInDay += actualExpectedCodeLinesNumber;
if (sumCodeLinesInDay > capacity)
{
days += sumCodeLinesInDay / capacity;
sumCodeLinesInDay = sumCodeLinesInDay % capacity;
}
}
if (sumCodeLinesInDay > 0)
{
days++;
}
return (int)Math.Ceiling(days);
}
В качестве входных параметров метод принимает список выбранных пользователем модулей для добавления работ в план, а также значение производительности сотрудника. Навык рабочего в данном случае не нужен, так как для пользователя отображаются только предварительные расчеты по ожидаемой длительности, которые считают, что разработка или тестирование будет происходить по уже известным данным о количестве строк кода модуля. Также на вход подается информация о том, назначена ли разработка на выбранные модули и были ли они ранее добавлены в план на текущей итерации. Выходным параметром является целое число ожидаемой длительности.
Добавление работы в план осуществляется с помощью метода «AddModuleToPlan», выраженного в программном коде следующим видом:
public bool AddModuleToPlan(Module module, Employee developer, Employee tester)
{
if (module != null)
{
if (module.IsDeveloped)
{
if (developer != null)
{
module.Developer = developer;
module.IsDeveloped = false;
module.Tester = (tester != null) ? tester : module.Tester;
module.Iteration = Iteration;
return true;
}
else if (tester != null)
{
module.Tester = tester;
module.Iteration = Iteration;
return true;
}
else return false;
}
else if (developer != null)
{
module.Developer = developer;
module.Tester = (tester != null) ? tester : module.Tester;
module.Iteration = Iteration;
return true;
}
else return false;
}
else return false;
}
Входными параметрами данного метода являются назначаемый на работу модуль, и два сотрудника, реализующие роли разработчика и тестировщика. Выходным параметром является переменная логического типа, задающая успех добавления работы.
Для удаления работы из плана используется следующая функция с выбранным модулем на входе и статусом об успешном удалении на выходе:
public bool RemoveModuleFromPlan(Module module)
{
if (module != null)
{
if (module.IsDeveloped)
{
module.Tester = null;
}
else
{
module.Developer = null;
module.Tester = null;
}
return true;
}
else return false;
}
На этапе разработки используется алгоритм расчета количества строк кода в зависимости от навыка разработчика, поэтому метод, реализующий его, выглядит следующим образом:
public List<Module> CalculateDevelopedModules(int passedDays = -1)
{
passedDays = (passedDays == -1) ? PassedDays : passedDays;
var newPassedDays = passedDays;
var developers = GetDevelopmentPlan.Select(x => x.Developer).Distinct();
foreach (var developer in developers)
{
int sumCodeLinesInDay = 0;
double days = passedDays;
foreach (var job in GetDevelopmentPlan.Where(x => x.Developer == developer))
{
int inaccuracy = 100 - developer.DeveloperSkill;
int randomInaccuracy = RandomNumber.Shared.GetRandomNumberBetween(100 - inaccuracy, 100 + inaccuracy + 1);
job.ActualCodeLinesNumber = job.ExpectedCodeLinesNumber * randomInaccuracy / 100;
developer.DevelopedCodeLinesNumber += job.ActualCodeLinesNumber;
sumCodeLinesInDay += job.ActualCodeLinesNumber;
if (sumCodeLinesInDay > developer.DeveloperCapacity)
{
days += sumCodeLinesInDay / developer.DeveloperCapacity;
sumCodeLinesInDay = sumCodeLinesInDay % developer.DeveloperCapacity;
}
job.IsDeveloped = true;
job.Iteration = Iteration;
job.Errors = new List<Error>();
int countErrors = job.ActualCodeLinesNumber * (100 - developer.DeveloperSkill) / 1000;
for (int i = 0; i < countErrors; i++)
{
var error = new Error();
error.SetErrorType();
job.Errors.Add(error);
}
job.Deadline = (int)Math.Ceiling(sumCodeLinesInDay > 0 ? days + 1 : days);
}
if (sumCodeLinesInDay > 0)
{
days++;
}
if ((int)Math.Ceiling(days) > newPassedDays)
newPassedDays = (int)Math.Ceiling(days);
}
Project.IncrementDay(newPassedDays - passedDays);
return GetNewDevelopedModules;
}
В результате работы метод возвращает список модулей, которые были задействованы в разработке на данной итерации, с измененными новыми данными.
3.2 Тестирование и отладка программы
После реализации программы необходимо провести внутреннее тестирование на наличие ошибок в разработанной программе и исправить все найденные.
В рамках данной работы было проведено тестирование всех функций этапа планирования и разработки игры «IT-менеджер» и результат выполнения подготовленных тестов продемонстрирован в табл. 3.1.
Таблица 3.1. Тестирование функций этапов планирования и разработки
|
Входные данные |
Результат |
Выполнение |
|
|
Выбор архитектора из выпадающего списка сотрудников |
Отображение на экране выбранного сотрудника |
+ |
|
|
Нажатие кнопки «Создать архитектуру модулей». Архитектор выбран |
Отображение на экране информации о новых добавленных модулей и обновление списка всех модулей |
+ |
|
|
Нажатие кнопки «Создать архитектуру модулей». Архитектор не выбран |
Появление сообщения о необходимости выбора архитектора |
+ |
|
|
Выбор модуля из выпадающего списка |
Отображение на экране выбранного модуля |
+ |
|
|
Выбор нескольких модулей из выпадающего списка |
Отображение на экране информации о выбранных модулях |
+ |
|
|
Выбор разработчика из выпадающего списка сотрудников. Выбран хотя бы один модуль |
Отображение на экране выбранного сотрудника и информации об ожидаемой длительности разработки |
+ |
|
|
Выбор разработчика из выпадающего списка сотрудников. Модули не выбраны |
Отображение на экране выбранного сотрудника, информация об ожидаемой длительности разработки не отображается |
+ |
|
|
Выбор тестировщика из выпадающего списка сотрудников. Выбран хотя бы один модуль |
Отображение на экране выбранного сотрудника и информации об ожидаемой длительности тестирования |
+ |
|
|
Выбор тестировщика из выпадающего списка сотрудников. Модули не выбраны |
Отображение на экране выбранного сотрудника, информация об ожидаемой длительности тестирования не отображается |
+ |
|
|
Нажатие кнопки «Добавить в план». Выбран хотя бы один модуль, разработчик и тестировщик |
Добавление в таблицу плана, и отображение добавленных модулей на экране пользователя с информацией о разработчике и тестировщике. Обновление данных о длительности составленного плана |
+ |
|
|
Нажатие кнопки «Добавить в план». Выбран хотя бы один модуль и разработчик. Тестировщик не выбран |
Добавление в таблицу плана, и отображение добавленных модулей на экране пользователя с информацией только о разработчике. Обновление данных о длительности составленного плана |
+ |
|
|
Нажатие кнопки «Добавить в план». Выбран хотя бы один модуль и тестировщик. Разработчик не выбран. Модули уже были ранее разработаны |
Добавление в таблицу плана, и отображение добавленных модулей на экране пользователя с информацией только о тестировщике. Обновление данных о длительности составленного плана |
+ |
|
|
Нажатие кнопки «Добавить в план». Выбран хотя бы один модуль и тестировщик. Разработчик не выбран. Модули не были ранее разработаны |
Появление сообщения о необходимости разработки модулей перед их тестированием |
+ |
|
|
Выбор одной или нескольких строк в таблице плана и нажатие кнопки «Удалить» |
Удаление строк из таблицы плана на экране пользователя. Обновление данных о длительности составленного плана |
+ |
|
|
Выбор одной или нескольких строк в таблице плана и нажатие клавиши «Delete» |
Удаление строк из таблицы плана на экране пользователя. Обновление данных о длительности составленного плана |
+ |
|
|
Нажатие кнопки «Следующий этап» |
Открытие окна этапа разработки. Отображение данных в таблице о состоянии разработки на текущий игровой день |
+ |