Adaptive Programming – Part 5


Início

Adaptive Programming

Nos post anterior e nos que o antecedem mostramos as consequências de se respeitar a Lei de Demeter. O código é mais fácil de manter já que minimiza a dependência dos detalhes internos de implementação de uma classe pelo código cliente. Por outro lado há muito código repetitivo que serve apenas para “traversal”. O percurso entre os objetos da classe de fachada (Empresa) é realizado recursivamente através de chamadas ao método #todosEmpregados, por exemplo, presente em todas as interfaces no caminho até onde os dados estão: nos objetos da classe Empregado. Os trajetos usados neste caso são: Empresa-Departamento-Empregado e Empresa-Departamento-Divisão-Empregado. Os protocolos das classes vão “inchando” a cada acrécimo de funcionalidade. Para mitigar este problema vamos alterar o código para usarmos o design pattern Visitor e double dispatch.

Visitors

O diagrama com a adoção do pattern Visitor mostra um “enxugamento” da interface:

Agora o código para implementar a regra de negócio e a navegação nos objetos está em um lugar separado: cada visitor que implementa uma funcionalidade. Ele não é muito diferente em estrutura em relação aos códigos anteriores. Abaixo mostramos os códigos para os vários casos:

TodosEmpregadosVisitor:

'From Pharo1.3 of 16 June 2011 [Latest update: #13328] on 22 June 2012 at 7:43:13 am'!
Visitor subclass: #TodosEmpregadosVisitor
	instanceVariableNames: ''
	classVariableNames: ''
	poolDictionaries: ''
	category: 'AdaptiveProgrammingBlogPost-Examples'!

!TodosEmpregadosVisitor methodsFor: 'as yet unclassified' stamp: 'FranciscoAryMartins 6/21/2012 08:22'!
visitDepartamento: umDepartamento
	umDepartamento empregados do: [:each| each acceptVisitor: self].
	umDepartamento divisoes do: [:each| each acceptVisitor: self]	! !

!TodosEmpregadosVisitor methodsFor: 'as yet unclassified' stamp: 'FranciscoAryMartins 6/21/2012 08:23'!
visitDivisao: umaDivisao
	umaDivisao empregados do: [:each| each acceptVisitor: self]! !

!TodosEmpregadosVisitor methodsFor: 'as yet unclassified' stamp: 'FranciscoAryMartins 6/21/2012 08:25'!
visitEmpregado: umEmpregado
	result add: umEmpregado! !

!TodosEmpregadosVisitor methodsFor: 'as yet unclassified' stamp: 'FranciscoAryMartins 6/21/2012 08:20'!
visitEmpresa: umaEmpresa
	umaEmpresa departamentos do: [:each| each acceptVisitor: self]! !

Empresa>>todosEmpregados:

'From Pharo1.3 of 16 June 2011 [Latest update: #13328] on 22 June 2012 at 7:45:21 am'!

!Empresa methodsFor: 'as yet unclassified' stamp: 'FranciscoAryMartins 6/21/2012 18:17'!
todosEmpregados
	| result |
	result := OrderedCollection new.
	self acceptVisitor: (TodosEmpregadosVisitor result: result).
	^ result! !

NomesEmpregadosVisitor:

'From Pharo1.3 of 16 June 2011 [Latest update: #13328] on 22 June 2012 at 8:01:56 am'!
Visitor subclass: #NomesEmpregadosVisitor
	instanceVariableNames: ''
	classVariableNames: ''
	poolDictionaries: ''
	category: 'AdaptiveProgrammingBlogPost-Examples'!

!NomesEmpregadosVisitor methodsFor: 'as yet unclassified' stamp: 'FranciscoAryMartins 6/21/2012 08:26'!
visitDepartamento: umDepartamento
	umDepartamento empregados do: [:each| each acceptVisitor: self].
	umDepartamento divisoes do: [:each| each acceptVisitor: self]	! !

!NomesEmpregadosVisitor methodsFor: 'as yet unclassified' stamp: 'FranciscoAryMartins 6/22/2012 07:52'!
visitDivisao: umaDivisao
	umaDivisao empregados do: [:each| each acceptVisitor: self]! !

!NomesEmpregadosVisitor methodsFor: 'as yet unclassified' stamp: 'FranciscoAryMartins 6/21/2012 08:26'!
visitEmpregado: umEmpregado
	result add: umEmpregado nome! !

!NomesEmpregadosVisitor methodsFor: 'as yet unclassified' stamp: 'FranciscoAryMartins 6/21/2012 08:26'!
visitEmpresa: umaEmpresa
	umaEmpresa departamentos do: [:each| each acceptVisitor: self]! !

Empresa>>#nomesEmpregados

'From Pharo1.3 of 16 June 2011 [Latest update: #13328] on 22 June 2012 at 8:02:32 am'!

!Empresa methodsFor: 'as yet unclassified' stamp: 'FranciscoAryMartins 6/21/2012 18:47'!
nomesEmpregados
	| result |
	result := OrderedCollection new.
	self acceptVisitor: (NomesEmpregadosVisitor result: result).
	^ result! !

NumeroEmpregadosVisitor:

'From Pharo1.3 of 16 June 2011 [Latest update: #13328] on 22 June 2012 at 8:07:11 am'!
Visitor subclass: #NumeroEmpregadosVisitor
	instanceVariableNames: ''
	classVariableNames: ''
	poolDictionaries: ''
	category: 'AdaptiveProgrammingBlogPost-Examples'!

!NumeroEmpregadosVisitor methodsFor: 'as yet unclassified' stamp: 'FranciscoAryMartins 6/21/2012 21:59'!
visitDepartamento: umDepartamento
	umDepartamento empregados do: [:each| each acceptVisitor: self].
	umDepartamento divisoes do: [:each| each acceptVisitor: self]	! !

!NumeroEmpregadosVisitor methodsFor: 'as yet unclassified' stamp: 'FranciscoAryMartins 6/22/2012 07:52'!
visitDivisao: umaDivisao
	umaDivisao empregados do: [:each| each acceptVisitor: self]! !

!NumeroEmpregadosVisitor methodsFor: 'as yet unclassified' stamp: 'FranciscoAryMartins 6/21/2012 22:00'!
visitEmpregado: umEmpregado
	result value: result value + 1! !

!NumeroEmpregadosVisitor methodsFor: 'as yet unclassified' stamp: 'FranciscoAryMartins 6/21/2012 21:59'!
visitEmpresa: umaEmpresa
	umaEmpresa departamentos do: [:each| each acceptVisitor: self]! !

Empresa>>#numeroEmpregados:

'From Pharo1.3 of 16 June 2011 [Latest update: #13328] on 22 June 2012 at 8:07:24 am'!

!Empresa methodsFor: 'as yet unclassified' stamp: 'FranciscoAryMartins 6/21/2012 22:03'!
numeroEmpregados
	| result |
	result := Accumulator value: 0.
	self acceptVisitor: (NumeroEmpregadosVisitor result: result).
	^ result value! !

EmpregadosSalarioMaiorQueVisitor:

'From Pharo1.3 of 16 June 2011 [Latest update: #13328] on 22 June 2012 at 8:13:07 am'!
Visitor subclass: #EmpregadosSalarioMaiorQueVisitor
	instanceVariableNames: 'salario'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'AdaptiveProgrammingBlogPost-Examples'!

!EmpregadosSalarioMaiorQueVisitor methodsFor: 'as yet unclassified' stamp: 'FranciscoAryMartins 6/21/2012 22:41'!
salario
	^ salario! !

!EmpregadosSalarioMaiorQueVisitor methodsFor: 'as yet unclassified' stamp: 'FranciscoAryMartins 6/21/2012 22:40'!
salario: aSmallInteger
	salario := aSmallInteger ! !

!EmpregadosSalarioMaiorQueVisitor methodsFor: 'as yet unclassified' stamp: 'FranciscoAryMartins 6/21/2012 22:29'!
visitDepartamento: umDepartamento
	umDepartamento empregados do: [:each| each acceptVisitor: self].
	umDepartamento divisoes do: [:each| each acceptVisitor: self]	! !

!EmpregadosSalarioMaiorQueVisitor methodsFor: 'as yet unclassified' stamp: 'FranciscoAryMartins 6/22/2012 07:52'!
visitDivisao: umaDivisao
	umaDivisao empregados do: [:each| each acceptVisitor: self]! !

!EmpregadosSalarioMaiorQueVisitor methodsFor: 'as yet unclassified' stamp: 'FranciscoAryMartins 6/21/2012 22:32'!
visitEmpregado: umEmpregado
	(umEmpregado salario > self salario) ifTrue: [
	result add: umEmpregado]! !

!EmpregadosSalarioMaiorQueVisitor methodsFor: 'as yet unclassified' stamp: 'FranciscoAryMartins 6/21/2012 22:29'!
visitEmpresa: umaEmpresa
	umaEmpresa departamentos do: [:each| each acceptVisitor: self]! !

"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!

EmpregadosSalarioMaiorQueVisitor class
	instanceVariableNames: ''!

!EmpregadosSalarioMaiorQueVisitor class methodsFor: 'as yet unclassified' stamp: 'FranciscoAryMartins 6/21/2012 22:39'!
salario: aSmallInteger result: anOrderedCollection
	^ self new
		salario: aSmallInteger ;
		result: anOrderedCollection! !

Empresa>>#empregadosSalarioMaiorQue::

'From Pharo1.3 of 16 June 2011 [Latest update: #13328] on 22 June 2012 at 8:13:22 am'!

!Empresa methodsFor: 'as yet unclassified' stamp: 'FranciscoAryMartins 6/21/2012 22:36'!
empregadosSalarioMaiorQue: aSmallInteger
	| result |
	result := OrderedCollection new.
	self acceptVisitor: (EmpregadosSalarioMaiorQueVisitor salario: aSmallInteger result: result).
	^ result! !

No próximo post vamos evoluir o código para um estilo de metaprogramação.

Anúncios

3 Respostas para “Adaptive Programming – Part 5

  1. Pingback: Adaptive Programming – Part 4 | Crab Log

  2. Pingback: Adaptive Programming – Part 6 | Crab Log

  3. Pingback: Adaptive Programming – Part 1 | Crab Log

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s