Neste video, vamos mostrar como criar pacotes, classes, e descrever testes.
A primeira coisa a se fazer é abrir o "System Browser".
O System Browser permite navegar pacotes. Aqui estão os pacotes.
Para criar um pacote, vamos clicar em "Add Package", digitar "MyCounter".
Como temos muitos pacotes e não queremos ver todos, seria bom filtrá-los.
Temos nosso pacote "MyCounter".
E aqui, vamos definir uma classe vamos chamá-la "Counter"
e ela tem uma variável de instância, "count".
O pequeno ícone laranja ali indica que o código não foi salvo.
Vamos compilar o código, com a função "Accept".
E agora, vemos a classe "Counter" que foi compilada.
O sistema investiga a classe e mostra dicas de qualidade de código. Veremos isso depois.
Tem uma exclamação em vermelho porque não escrevemos comentários.
Então vamos escrever um primeiro comentário: "Sou um contador simples".
Vamos escrever um pequeno exemplo para que o leitor entenda
como esta classe funciona: "Counter new"...
"Counter increment increment"
"Counter count". Aqui, deve ser igual a dois.
De novo, o código não foi salvo, então vamos compilá-lo.
Foi salvo. Não temos mais um contador.
Agora, vamos definir métodos de acesso.
Colocamos métodos de acesso sob o protocolo "accessing"
Digitamos: "count", retornando a variável "count".
Da mesma forma, digitamos ": aNumber" para fazer um método "setter"
Veja que eu modifiquei o método "count".
Você pode pensar que ele foi descartado, mas não, porque
toda vez que modifico um método com um nome diferente
ele cria um novo método.
Eu compilo o novo método, e tenho “count”.
Agora, podemos de fato testar nosso pequeno programa.
Eu abro o Playground, eu quero criar um contador
Quero criar um contador, adiciono um valor: "C count: 7"
Se eu perguntar qual seu valor, ele me mostra... 7
Agora, queremos escrever isso na forma de um teste
para que assim possamos executar isso automaticamente.
Vamos criar uma classe de teste.
Como criar uma classe de teste em Pharo?
Mudamos a superclasse, dizemos que ela herda "TestCase"
e vamos definir uma classe chamada "CounterTest".
Agora, vamos compilá-la.
Eu tenho uma classe "CounterTest" no meu sistema.
Vamos definir um novo método, eu vou adicioná-lo ao protocolo "tests".
Aqui eu posso definir um novo método.
Métodos de teste devem sempre começar com "test"
e estar em uma classe que herda "TestCase"
Vamos chamá-lo "testCounterisSetAndRead"
Temos praticamente nosso teste, já escrevemos quase tudo.
Vamos indentar um pouco melhor.
Criei meu contador, e aqui digito "self assert: ... equals: 7"
Esta expressão é equivalente a "self assert: c count = 7"
o que é mais prático. Quando você faz algo errado,
o resultado é mais elegante nesta primeira forma.
Vamos compilar.
Agora, posso executar meu teste. e voilà, meu teste está verde.
Quando você tem testes verdes, é uma boa hora para salvar seu código.
Em Pharo, você pode salvar sua imagem.
É o que vou fazer, vou salvar a imagem
Mas só a imagem não é o suficiente.
Vou mostrar como salvar o código em um sistema de versionamento.
Como eu não sei se você terá acesso à Internet,
Eu vou salvar o código em um repositório local.
Veja, existe esse diretório que aponta todos os pacotes
os quais eu posso trabalhar, e que eu ou o sistema instalamos.
Aqui, o sistema mostra pacotes com modificações que não foram salvas
Ignorando os dois primeiros, vemos que "MyPackage" tem um asterisco.
Isto significa que tenho código na imagem que não foi salvo.
O que eu vou fazer: vou clicar em "Save"
Escolho primeiro o repositório, e clico em "Save".
E digito "first version with accessors and a green test"
E "Accept". Agora, um pacote foi salvo. Vamos verificar.
Quando eu abrir este diretório, ele vai conter
vários pacotes instalados pelo sistema.
Mas em particular, se eu filtrar, irei achar
meu pacote e suas versões.
Aconselho que, toda vez que adicionar uma funcionalidade,
você automaticamente salve o código.
Agora, vamos definir um teste antes de implementar uma funcionalidade.
Vamos escrever um teste do que seria incrementar um contador.
"testIncrement" O que queremos obter?
Queremos criar um contador,
atribuir um valor inicial,
depois, incrementá-lo duas vezes.
E o que devo checar?
Que este contador tenha o valor correto.
Eu compilo.
Meu teste está vermelho porque eu não implementei, no contador,
as operações "increment" e "decrement".
E aqui, vou adicionar: "operations"... "increment".
Vamos escrever "self count 2: self count + 1"
Se usamos métodos de acesso internamente ou não,
é uma questão de estilo.
Similarmente, vamos definir "decrement".
Veja que há um teste em "increment", posso executá-lo e ele está verde.
Então tenho dois testes funcionando.
Se eu for pra classe de teste, todos meus testes estão verdes.
O que posso fazer? Vou salvar novamente.
Vou digitar "Adding increment and decrement".
Quando eu inspecionar, terei duas versões do meu pacote.
Vamos escrever um teste para "decrement"
porque não há razão para não fazê-lo.
"Decrement", por exemplo posso atribuir valor "2"
e decrementar duas vezes. Devo obter zero.
Meu teste está verde, então vou salvar.
Agora, o que queremos é, quando executarmos "Counter new"
usando "Print it", ele mostra um contador cujo valor eu não sei.
O que não é muito prático.
Gostaríamos de modificar este comportamento.
Para fazer isso,vamos adicionar um método
chamado ”printOn:", sob o protocolo "printing".
"printOn:" é chamado pelo sistema toda vez que fizermos "printStream".
Ele tem "aStream" como argumento.
O que vamos fazer?
Dizemos que queremos ter um contador, então
tipicamente usaremos a funcionalidade da superclasse.
E gostaria de adicionar um pequeno texto
por exemplo, "with value" e depois, "self count".
Faço isso porque o contador é um número
então quero obter sua representação textual.
Eu digito "cr". Eu compilo.
O sistema diz que posso expressar melhor esse método,
mas não tem problema. No momento, não importa.
Posso digitar "Counter new".
Eu inspeciono, e tenho um contador com valor "nil".
É normal porque ainda não inicializei o contador.
Agora, vamor adicionar suporte à inicialização.
Pra fazer isso, começaremos escrevendo um teste.
Eu digo que o valor na criação de um contador deve ser zero.
Vou digitar "self assert: Counter new count = 0"
Vamos notar que meu teste falhou. Por quê?
Porque se eu executar isso, vou obter "nil"
Como não temos acesso às variáveis de instância
da classe "CounterTest", eu posso selecionar
esta expressão e executá-la diretamente.
Uma vez que este teste falhou, o que posso fazer?
Vou adicionar um método "initialize" sob o protocolo "initialization".
E daí, eu digito "super initialize" e vou dizer "count := 0"
Este método é invocado toda vez que executo o método "new".
Agora posso ver meus testes, eles estão verdes.
Similarmente, se eu executar "count", obterei zero.
Mais uma vez, vamos salvar o código.
O interessante é que posso ver todo meu histórico.
Também posso inspecionar e navegar nesse histórico.
Se eu clicar em "version", posso ver o diff entre esses dois sistemas.
As mudanças entre as versões 3 e 4 são ”initialize", "printOn", e o teste.
Se eu quiser ver a diferença entre as versões 2 e 4,
eu tenho todas essas mudanças.
Resta uma coisa a se fazer, eu gostaria de mudar um pouco
a maneira que os objetos são criados.
Eu começo por criar um teste para esclarecer o que quero obter.
Vou definir um teste chamado "AlternateClassCreation"
Digamos, eu quero garantir que um contador com valor 19,
incrementá-lo, e depois pedir seu valor, obterei 20.
Ok?
Vamos adicionar parênteses aqui, fica melhor.
Mais uma vez, o teste não passa
e o assistente aqui diz: "esta mensagem não existe".
Então, note que a mensagem "withValue:"
não é mandada para um objeto, e sim para uma classe.
Isso significa que devo definir essa mensagem numa classe.
Seleciono "Class", então passo pro nível de classe.
e vou adicionar um protocolo chamado "instance creation"
"withValue: aNumber"... E o que devo fazer?
A primeira coisa a fazer é criar um contador,
uma variável pro contador, farei lentamente.
"self new" para criar um contafor
e eu digito "self count: aNumber"
e vou retornar este contador.
Posso fazer isso de forma mais compacta.
mas, no momento, faremos mais simples.
Eu compilo meu método.
O que significa que agora posso mandar mensagens.
E você viu, quando eu clico neste botão,
eu passo do nível de classe pro nível de instância.
Aqui eu estava no nível de classe, e agora volto
para as mensagens enviadas às instâncias.
O que isso significa? Significa que se executo
"Counter withValue: 18" O que obterei?
Obterei uma instância da classe "Counter".
Obtenho um contador com valor igual a 18,
E aqui posso executar "decrement"
E se atualizo o objeto, eu obtenho 17.
Agora, se inspeciono meus testes, todos eles passam
Então, vou mais uma vez salvar o código e pronto.
Terminado por enquanto.