• Nenhum resultado encontrado

4 UMA LINGUAGEM OO COM SUPORTE A ASSOCIAÇÕES O presente capítulo apresenta a extensão de uma linguagem de

4.2 EXEMPLO DE USO

4.2.1 Implementação do Modelo

O modelo foi implementado a partir do diagrama de classes ilustrado pela Figura 98, aplicando-se diretamente no código Association#, os padrões GRASP especialista, criador, controlador, baixo acoplamento e não fale com estranhos. Este último foi aplicado

na maior parte do projeto, excetuando-se pelas associações em que o association end utilizado para navegação é pertencente à associação.

O resultado desta implementação foi a camada de domínio para o sistema de universidade exemplificado, em que a aplicação tem acesso somente ao controlador fachada24, ilustrado pela Figura 100 e codificado parcialmente na Figura 101.

Figura 100. Controlador da camada de domínio e suas associações.

24 Larman, 2000.

Código Association# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46

public class University {

public static readonly University INSTANCE =

new University(); private University() { }

// Association ends

private rolename Faculties [*] in UniversityToFaculty; private rolename Courses [*] in UniversityToCourse; private rolename Students [*] in UniversityToStudent; private rolename SelectedFaculty [0..1] in

UniversityToSelectedFaculty;

private rolename SelectedSubstitute [0..1] in

UniversityToSelectedSubstitute;

private rolename SelectedCourse [0..1] in

UniversityToSelectedCourse;

private rolename SelectedLecturers [*] in

UniversityToSelectedLecturers;

private rolename SelectedStudent [0..1] in

UniversityToSelectedStudent;

private rolename SelectedLanguage [0..1] in

UniversityToSelectedLanguage;

private rolename Languages [*] in UniversityToLanguage;

// Cadastro de Professores

public void RegisterFaculty(string name, int number)

{...}

public bool SelectFaculty(int number) {...} public void EditSelectedFaculty(string newName,

int newNumber){...}

public void DeleteSelectedFaculty() {...} public string GetSelectedFacultyName() {...} public int GetSelectedFacultyNumber() {...}

public IEnumerable<int> GetFacultiesNumbers() {...}

// Vínculo de Professores com seus Substitutos

public void SelectSubstitute(int substituteNumber) {...} public string GetSelectedSubstituteName() {...}

public int GetSelectedSubstituteNumber() {...}

public void AddSelectedSubstituteToSelectedFaculty()

{...}

public void emoveSelectedSubstituteFromSelectedFaculty()

{...}

public IEnumerable<int>

GetSubstitutesNumbersFromSelectedFaculty() {...} ...

}

Figura 101. Resumo do código Association # da classe controladora University. Para manter o padrão C#/Association# de nomes de métodos, atributos e association ends, estes iniciam sempre com a primeira letra maiúscula, na escrita de código.

A Figura 102 apresenta o código simplificado da classe Faculty. Nesta, assim como nas demais classes, não há a necessidade de encapsulamento dos atributos e criação de métodos setAtributo e getAtributo, porque são utilizados properties em vez de fields para a representação de atributos. Se houver necessidade futura de adicionar controles e/ou operações sobre a atribuição e a recuperação de valores, basta apenas definir um corpo para as operações set e get das properties, da mesma forma que em C#.

Código Association# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

public class Faculty {

// atributos

public string Name { set; get; }

public int Number { set; get; }

// association ends

private rolename Substitutes [*] in Substitutes; private rolename Substituted [*] in Substitutes; private rolename Lectures [*] in Teaches;

// operações

public Faculty(string name, int number) {...} public bool HasSubstitutes() {...}

public IEnumerable<int> GetSubstitutesNumbers() {...} public void RemoveAllSubstitutes() {...}

public void AddSelectedSubstitute(Faculty substitute)

{...}

public void RemoveSubstitute(Faculty substitute) {...} public void RemoveAllSubstituted() {...}

}

Figura 102. Resumo do código Association# da classe Faculty.

Observa-se que não há na classe Faculty, nenhuma referência à associação WorksFor. Isto porque, o association end de nome ras pertence à associação e não a classe. Houve a necessidade de uma pequena modificação do código desta classe em relação ao modelo: o association end de nome Substitutes teve sua multiplicidade alterada de 1..* para * porque é esperado que durante a execução do sistema, primeiro cadastrem-se os professores para que depois se determine quem será substituto de quem. Porém, a regra de negócio que todo professor deve ter pelo menos um substituto é mantida através da verificação da existência de substitutos (chamada do método HasSubstitutes) ao tentar vincular um professor a um curso. Se o professor não tem substitutos, não é possível suceder tal vínculo.

A Figura 103 apresenta o código simplificado das classes Course (linhas 1 a 18) e Student (linhas 20 a 39). Similar à classe Faculty em

relação à associação WorksFor, a classe Course não possui referências à associação CourseToAC e a classe Student não possui referências às associações StudentToRA e StudentToTA.

Código Association# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39

public class Course {

// Atributos

public string Title { set; get; }

// Association ends

private rolename Learners [*] in Attends; private rolename Lecturers [1..*] in Teaches;

// Operações

public Course(string title,

IEnumerable<Faculty> lecturers) {...}

public void RemoveAllLecturers() {...}

public void AddLecturer(Faculty lecturer) {...} public void RemoveLecturer(int lecturerNumber) {...} public IEnumerable<int> GetLecturersNumbers() {...} public void AddLearner(Student learner) {...} public void RemoveLearner(int studentNumber) {...} public IEnumerable<int> GetLearnersNumbers() {...} } public class Student {

// atributos

public string Name { set; get; } public int Number { set; get; } public int Year { set; get; }

// association ends

private rolename Lectures [1..*] in Attends;

public Student(string name, int number, int year) {...}

// operações

public void AddLecture(Course course){...} public void RemoveLecture(Course course) {...}

public void SetMarkOnLecture(Course course, int mark)

{...}

public int GetMarkOnLecture(Course course) {...} public IEnumerable<string> GetCoursesTitles() {...} public void RemoveAllLectures() {...}

public bool IsAttendingCourse() {...} }

Figura 103. Resumo do código Association# das classes Course e Student. Por meio do uso do padrão controlador, a aplicação só modifica e acessa informações da camada de domínio pela chamada de métodos da única instância (singleton) da classe controladora University.

Empregando o padrão não fale com estranhos, as operações da classe controladora encadeiam chamadas a métodos de instâncias das classes associadas a ela. Estas, por sua vez, executam a operação em seu próprio escopo e/ou delegam essa chamada a instâncias de outras classes associadas a estas, assim sucessivamente. Por exemplo: o cadastro de um professor – que deve resultar na criação de uma instância de Faculty e na posterior associação desta com o singleton University, pela associação UniversityToFaculty – é feito pela chamada do método University.RegisterFaculty (linha 24 da Figura 101). Este é responsável por criar a nova instância e associar ela ao singleton.

Um exemplo mais complexo, em que a operação é delegada para além da instância da classe controladora, é: a vinculação de professores substitutos. Está é feita pela prévia seleção do professor a ser substituído (método University.SelectFaculty, linha 25 da Figura 101) e do professor a ser o substituto (método University.SelectSubstitute, linha 33 da Figura 101), seguido da chamada do método University. AddSelectedSubstituteToSelectedFaculty (linha 36 da Figura 101). Este último método, chama o método Faculty.AddSelectedSubstitute (linha 16 da Figura 102) da instância selecionada como professor a ser substituído, passando como argumento o professor selecionado como substituto. Então, neste método, a instância do professor a ser substituído adiciona em sua lista de substitutos, a instância do professor recebida como argumento, por meio da chamada do association end de nome Substitutes (linha 7 da Figura 102).

O código implementado em Association# para esta camada de domínio, assim como o código C# gerado a partir deste por tradução manual, e o código do teste de unidade deste, estão contidos integralmente no Apêndice C.