Method Wrapper in Pharo/Smalltalk II

rotate-zoom-out-withdraw

Tracer

Com base nos códigos no post anterior vamos especializar uma classe MyTracer para obter um trace da atividade de um grupo de objetos.

Um exemplo de um relatório obtido com MyTracer segue abaixo:

my-tracer-example

Note que o método #name foi excluido da instrumentação para evitar um loop infinito já que o mesmo é usado no relatório. São obtidos dois traces no mesmo relatório pela invocação de ClientForRomanCalculator new calculate e MyRomanConverter new toDecimal: 'V'.

A seguir o relatório obtido:


	| sender | ---->> message args ---->> | receiver | ====> result
Sending message #initialize ...
	| systemBorder |  ---->> initialize #() ---->>  | client |
Sending message #initialize ...
	| client |  ---->> initialize #() ---->>  | calculator |
Sending message #initialize ...
	| calculator |  ---->> initialize #() ---->>  | converter |
Returning from #initialize ...
	| calculator |  ---->> initialize ---->>  | converter |  ====> converter
Returning from #initialize ...
	| client |  ---->> initialize ---->>  | calculator |  ====> calculator
Returning from #initialize ...
	| systemBorder |  ---->> initialize ---->>  | client |  ====> client
Sending message #calculate ...
	| systemBorder |  ---->> calculate #() ---->>  | client |
Sending message #firstNumber: ...
	| client |  ---->> firstNumber: #('V') ---->>  | calculator |
Returning from #firstNumber: ...
	| client |  ---->> firstNumber: ---->>  | calculator |  ====> calculator
Sending message #secondNumber: ...
	| client |  ---->> secondNumber: #('XIV') ---->>  | calculator |
Returning from #secondNumber: ...
	| client |  ---->> secondNumber: ---->>  | calculator |  ====> calculator
Sending message #add ...
	| client |  ---->> add #() ---->>  | calculator |
Sending message #toDecimal: ...
	| calculator |  ---->> toDecimal: #('V') ---->>  | converter |
Returning from #toDecimal: ...
	| calculator |  ---->> toDecimal: ---->>  | converter |  ====> 5
Sending message #toDecimal: ...
	| calculator |  ---->> toDecimal: #('XIV') ---->>  | converter |
Returning from #toDecimal: ...
	| calculator |  ---->> toDecimal: ---->>  | converter |  ====> 14
Sending message #toRoman: ...
	| calculator |  ---->> toRoman: #(19) ---->>  | converter |
Returning from #toRoman: ...
	| calculator |  ---->> toRoman: ---->>  | converter |  ====> 'XIX'
Returning from #add ...
	| client |  ---->> add ---->>  | calculator |  ====> 'XIX'
Returning from #calculate ...
	| systemBorder |  ---->> calculate ---->>  | client |  ====> 'XIX'
Sending message #initialize ...
	| systemBorder |  ---->> initialize #() ---->>  | converter |
Returning from #initialize ...
	| systemBorder |  ---->> initialize ---->>  | converter |  ====> converter
Sending message #toDecimal: ...
	| systemBorder |  ---->> toDecimal: #('V') ---->>  | converter |
Returning from #toDecimal: ...
	| systemBorder |  ---->> toDecimal: ---->>  | converter |  ====> 5

Os registros também podem ser inspecionados através da ferramenta #explore:

tracer-recordings

O principal método de MyTracer é o método #recordingOn: abaixo:

mytracer-recordingOn

Note que em prefix e suffix são armazenadas cópias do objeto (self copy) como receivers. Isto preserva os estados de cada objeto como snapshots. Se postcopy for implementado adequadamente a cópia é profunda (Ver deep copy in Smalltalk).

Veja o código também na listagem abaixo:

recordingOn: wherePutRecordings

	wherePutRecordings ifNil: [self error: 'Must pass recordings parameter'].

	recordings := wherePutRecordings.

	MyTracerRecordings registerRecordings: recordings atPackage: package.
	recordings systemBorder: MyTracerSystemBorder new.
	self
		prefix: '[:arguments :selector | |tracerRecordings|
			tracerRecordings := MyTracerRecordings at: self class category.
			tracerRecordings isTooDepth ifTrue: [self inform: ''Possible infinite loop". self error: "Possible infinite loop''].
			tracerRecordings addRecord: (MyMessageSendRecord sender: tracerRecordings senderStack top receiver: self copy selector: selector arguments: arguments).
			tracerRecordings senderStack push: self
		] value: thisContext arguments value: thisContext method selector.';
		suffix: '[:result :arguments :selector | |tracerRecordings|
			tracerRecordings := MyTracerRecordings at: self class category.
			tracerRecordings senderStack pop.
			tracerRecordings addRecord: (MyMessageReturnRecord sender: tracerRecordings senderStack top receiver: self copy selector: selector result: result).
		] value: result_ value: thisContext arguments value: thisContext method selector.'

No próximo post vamos implementar assertions sem e com o uso de pragmas.

Anúncios

Uma resposta para “Method Wrapper in Pharo/Smalltalk II

  1. Pingback: Method Wrapper in Pharo/Smalltalk | 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