На информационном ресурсе применяются рекомендательные технологии (информационные технологии предоставления информации на основе сбора, систематизации и анализа сведений, относящихся к предпочтениям пользователей сети "Интернет", находящихся на территории Российской Федерации)

Практически Groovy : Функциональное программирование с помощью использованием замыканий и карринга. Часть 7

Тестирование с помощью замыканий

Перед тем, как подводить итоги, давайте рассмотрим еще одно применение замыканий Groovy. Рассмотрим приложение, которое моделирует компанию (Company) с множеством работников (Employee). Рекурсивное отношение организует агрегацию "один ко многим" между одним Employee (руководитель группы) и многими Employee (члены группы).

На рисунке 1 показана схема класса для такой организации.


Рисунок 1. Приложение Company
Диаграмма класса приложения Company

Вы можете использовать замыкания для оценки архитектурной целостности ваших моделей. Например, в рассматриваемом примере вы можете удостовериться, что каждому работнику назначен менеджер. Простое замыкание hasManager выражает это требование для отдельно взятого сотрудника: def hasManager = { employee -> return (employee.manager != null) }.

Частичное приложение замыкания forAll из приведенного выше, в листинге 6, класса Functor позволяет описать это условие как архитектурное требование: def everyEmployeeHasManager = Functor.forAll.curry(hasManager).

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


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

import fp.*
/**
* Компания с несколькими сотрудниками.
* Каждый работник отвечает перед руководителем группы,
* который, в свою очередь, управляет командой сотрудников.
*/
import java.util.*

class Employee {
@Property id
@Property name
@Property staff = [ : ]
@Property manager = null

String toString() {
return "Employee: ${id} ${name}"
}

def addToTeam(employee) {
staff[employee.id] = employee
employee.manager = this
}

}
class Company {
@Property name
@Property employees = [ : ]

def hireEmployee(employee) {
employees[employee.id] = employee
}

def displayStaff() {
println "Company: ${name}"
println "===================="
employees.each { entry -> println "
${entry.value}" }
}


}
def co = new Company(name : 'Napier')
def emp1 = new Employee(id : 123, name : 'KenB')
def emp2 = new Employee(id : 456, name : 'JohnS')
def emp3 = new Employee(id : 789, name : 'JonK')
co.hireEmployee(emp1)
co.hireEmployee(emp2)
co.hireEmployee(emp3)
emp3.addToTeam(emp1)
emp3.addToTeam(emp2)
co.displayStaff()
// Архитектурные замыкания
def hasManager = { employee -> return (employee.manager != null) }
def everyEmployeeHasManager = Functor.forAll.curry(hasManager)
def staff = new ArrayList(co.employees.values())
println "Every employee has a manager?:
${everyEmployeeHasManager.call(staff)}" // false
наверх