Вы находитесь на странице: 1из 84

EDITORIAL

EQUIPA PROGRAMAR

/* A todos os bravos que chegaram to longe! */

Poderia comear o editorial por escrever o resto do comentrio em cdigo,


Coordenador mas seria quase um abuso ao qual no me vou dar!
Antnio Pedro Cunha Santos
Como um dia disse, um incontornvel personagem da histria da tecnologia,
no se conectam os pontos olhando para a frente, mas sim para traz. A tecnologia
Editor isso mesmo, um movimento perptuo, em frente, sem parar, sem esperar, sem
Antnio Pedro Cunha Santos pausas, a uma velocidade cada vez mais estonteante. Cheio de surpresas e
segredos, cheio de revezes e avanos, cheio de tudo um pouco! Mas acima de tudo,
cheio! Cheio porque tem um pouco de todos os que nele trabalham, participam, se
Capa envolvem! Sem distino de gneros, classes ou outras que possam existir!
Filipa Peres
Recentemente comemorou-se o dia mundial da mulher, daqui a uns meses
assinala-se o dia mundial da criana, e l para novembro, bem despercebido, em
Redaco alguns pases, comemora-se o dia internacional do homem e l bem perto do final do
Augusto Manzano ano, quase que sem se dar por isso, o dia internacional dos Direitos Humanos, sem
Andr Melancia distines! E tudo isto para dizer que a tecnologia existe para servir todos os seres
Antnio Pedro Cunha Santos humanos! A Programao algo acessvel a todos, sem excepo! Dos que leem
Filipa Peres avidamente livros de programao, e aprendem a programar lendo e escrevendo
Jos Martins
em papel linhas e linhas de cdigo, at aos que usam o ltimo modelo de
Mnica Rodrigues
computador, para dar asas sua imaginao e programar!
Nilo Menezes
Nuno Cancelo Com tantos dias mundiais, falta mencionar um que nos diz muito a todos,
Ricardo Cabral programadores profissionais, programadores aprendizes, e mesmo at aqueles que
Rita Peres s programam por desafio de quando em vez! O ducentsimo quinquagsimo sexto
dia do ano, que nos anos no bixestos calha no 13 de Setembro e nos bissextos no
Staff 12. o dia do Programador! Pois 28 o nmero de valores distintos que podem ser
Antnio Pedro Cunha Santos
representados com um byte de oito bits.
Rita Peres
Tiago Sousa Enquanto esse dia no chega, e os dias vo passando, programem! Que
programar comanda a vida! E comentem o cdigo, para vos rirdes quando o leres
Contacto anos volvidos!
revistaprogramar@portugal-a-
programar.org At prxima edio, boas leituras!
Antnio Santos
Website
http://www.revista-programar.info /** A todos os bravos que chegaram to longe!
* Que programaram durante tantos dias
ISSN * Que leram todo este cdigo, e chegaram a este comentrio
* Sede pacientes! Que a jornada longa!
1 647-071 0 * Cuidado com os bugs! Que eles no vos atrapalhem!
* E lembrem-se deste velho ensinamento:
* Quando eu escrevi este cdigo,
* s eu e Deus sabamos o que ele queria dizer!
* Agora s um de ns sabe! E no sou eu!!!
**/

public void Asm()


{
console.writeln("Feliz quem programa!");
}

A revista PROGRAMAR um projecto voluntrio sem fins lucrativos. Todos os artigos so da responsabilidade dos autores, no
podendo a revista ou a comunidade ser responsvel por alguma impreciso ou erro.
Para qualquer dvida ou esclarecimento poder sempre contactar-nos.

2
NDICE
TEMA DE CAPA
6 Docker: overview - Nuno Cancelo

A PROGRAMAR

15 API Rest com Spring Boot (parte 2) - Jos Martins


21 JavaFX: Passos Seguintes - Nuno Cancelo
26 Um bot para Telegram com o Jogo da velha (Jogo do Galo). - Nilo Menezes
35 Automao do Azure com Windows PowerShell Desired State Configuration - Ricardo Cabral
46 O Problema do casamento Estvel utilizando o Algoritmo Gale-Shapley - Antnio Santos

ELECTRNICA
53 O Problema da falta de GPIO Pins - Antnio Santos

COLUNAS
59 C# - Padro de Arquitetura SOLID - Antnio Santos
61 SQL Curtas - SQL Curtas #2: Dvidas Comuns - Andr Melancia
64 Kernel Panic - A arte, engenho, e muita diverso - Antnio Santos

ANLISES
67 C# 6 - PROGRAMAO COM PRODUTIVIDADE - Mnica Rodrigues
68 Introduo Programao com Python, Algoritmos e logica de programao para iniciantes - Antnio Santos

SEGURANA
70 Segredos de Numerao - Andr Melancia

NO CODE
76 ShiftAppens 2017 - Filipa Peres

78 Raspberry Pi Zero W - Rita Peres


80 Interface Humano-Computador, Nanotecnologia e a dependncia tcnolgica. - Augusto Manzano

EVENTOS

16 de Maro - CiberSegurana e Cibercrime


25 - 27 de Maio - ISELTech17

Para mais informaes/eventos: http://bit.ly/PAP_Eventos. Divulga os teus eventos para o email eventos@portugal-a-
programar.pt

3
NOTCIAS
Jovensde Coimbra na final do Goo- Visual Studio 2017 lanado a
gle Hash Code 2017 7 de Maro
Ter lugar em Paris, no prximo dia 1 de Abril, a final No passado dia 7 de Maro, a Microsoft lanou a ulti-
do Google Hash Code 2017, promovido pela Google. O Hash ma verso do seu ambiente de desenvolvimento Visual Stu-
Code um concurso que visa estudantes e profissionais da dio.
Europa, Mdio Oriente e frica, consistindo na resoluo de
Esta nova verso da j famosa IDE, desta feita reche-
problemas criados pela Google atravs de uma linguagem de
ada de novidades, alm de algumas melhorias em relao
programao. Os participantes podem formar equipas entre
verso anterior, bem como algumas novidades e continua a
dois e quatro elementos, dividindo-se a competio em duas
ser disponibilizado em diversas verses, sendo que se man-
fases: online e final com os 50 melhores classificados.
tem a existncia de uma verso community gratuita.
Trs estudantes naturais de Coimbra participaram na primeira
De todas as novidades desta nova verso do Visual
fase que decorreu em Fevereiro e contou com a participao
Studio destacamos as seguintes:
de 2815 equipas. Ricardo Gomes, da Universidade de Coim-
bra, Miguel Duarte, do Instituto Superior Tcnico da Universi- Ajuda Off-line, bastando instalar o Help Viewer
dade de Lisboa e Pedro Paredes, da Universidade do Porto,
vo disputar a grande final do Google Hash Code 2017. Cdigo colorido e autocomplete para as linguagens
Bat, Clojure, CoffeeScript, CSS, Docker, F#, Groovy,
Em entrevista Ricardo Gomes afirma Sinceramente, no con-
INI, Jade, Javadoc, JSON, LESS, LUA, Make,
tava que a fase de qualificao corresse assim to bem. Ns
Markdown ++, Objective-C, Perl, PowerShell, Python,
tnhamos uma estratgia inicial e, simplesmente, seguimos
Rust, ShaderLab, SQL, Visual Basic .NET, YAML.
essa estratgia. Esperamos superar em Paris o resultado
obtido nesta fase. Snippets de cdigo para as linguagens CMake, C++,
C#, Go, Groovy, HTML, Java, Javadoc, JavaScript,
Lua, Perl, PHP, R, Ruby, Shellscript, Swift, XML

Suporte nativo para as linguagens C++, C#, Go, Java,


JavaScript, PHP, TypeScript, Visual Basic

O compilador de C++ melhorado com suporte para


C++ 11 e C++ 14, alm de suporte preliminar para
algumas funcionalidades no futuro C++ 17.

Suporte para CMake

Suporte para desenvolvimento para GNU/Linux com


C++

Desenvolvimento mvel com C++ (Android e iOS)


Imagem 1 - Miguel Duarte, Ricardo Gomes, Pedro Paredes
Suporte para C# 7.0 e Visual Basic 15

Suporte ao uso de tuples para agrupamento tempor-


rio em memria, de conjuntos de valores tipados.

Suporte para TypeScript 2.1

Suporte melhorado para Apache Cordova, incluindo


um simulador baseado no browser, que permite ver
resultados quase imediatos.

A lista de novidades era demasiado longa para incluir


aqui, por esse motivo apenas foram focadas algumas, deixan-
do o link para o site do Visual Studio onde podero ser en-
contradas todas as novidades e melhorias.
Imagem 2 - Pedro Paredes, Ricardo Gomes, Miguel Duarte https://www.visualstudio.com/en-us/news/releasenotes/
Fonte: Assessoria de Imprensa Universidade de Coimbra vs2017-relnotes

4
TEMA DE CAPA
Docker: overview
TEMA DA CAPA
Docker: overview

pondo o vosso container camada por camada:


Sou muito apologista da metodologia set it and forget
it, configurar as coisas uma vez e reutilizar vezes sem conta 1. Instalar o Sistema Operativo (ex: Ubunto)
a mesma configurao, infraestrutura. Abstrairmos de tal 2. Instalar uma ferramenta (ex: Node)
forma, que o foi configurado sirva para o uso geral da nossa
aplicao ou projeto. Isto muito giro, mas pouco realista se 3. Instalar uma base de dados (ex: Postgres)
tivermos em mente a montanha de projetos e aplicaes que 4. Etc
esto montadas por Portugal (e no s) a fora.
Quando estiver composto o vosso stack aplicacional
Tipicamente, a forma como eu fazia, seria criar uma est pronto a ser feito build e a distriburem por quem enten-
mquina virtual (principalmente em virtualbox) montava a derem.
infraestrutura da forma que queria e depois trabalhava sobre
ela e partilhava a imagem com quem quisesse. Apesar de A imagem Figura 1mostra um stack tradicional em Docker.
funcionar a soluo no era em nada elegante, tinha uma
imagem com cerca de 20GB, com um sistema operativo (que
poderia estar ou no a usar as suas potencialidades), mais o
conjunto de ferramentas e ainda tinha que me preocupar
com as configuraes de rede (para estar exposto para fora
da mquina virtual) e ter mounting points para poder partilhar
ficheiros entre o host e a mquina virtual. Quem j fez isto
pelo menos uma vez sabe a chatice que d.
Em 2013 quando comecei a ouvir falar de Docker e o
que representava naturalmente fiquei bastante interessado.
E ao longo do tempo a empresa tem desenvolvido bastante
trabalho e introduzindo bastantes features, apresentando um
produto de alta qualidade que depressa os gigantes da cloud
(AWS, Google Cloud, Microsoft Azure, etc) agarraram a
oportunidade de integrar o Docker nos seus seus servios
em forma de Container Services.
Afinal o que o Docker
Figura 1: Docker Stack
Docker um projeto open-source que permite criar
Requisitos de Sistema e Instalao
um contentor (container) com a infraestrutura que se preten-
der por forma a poder partilha-la em qualquer mquina e Docker no tem muitos requisitos de sistema, mas os
manter sempre o mesmo comportamento. Este contentor que tm so importantes para temos uma instalao sempre
contem um sistema operativo Linux lightweight, com o tradi- a funcionar.
cional sistema de ficheiros e politicas de segurana que ca-
No endereo http://bit.ly/Docker-System-
racterizam o sistema operativo Linux. Desta forma usa bas-
Requirements podemos encontrar todos os requisitos, sen-
tante menos recursos de memria e de espao em disco.
do os que so mais relevantes os seguintes (no entanto
Um container uma mquina virtual ento? Bem a muito recomendado lerem todos):
resposta ... mais ou menos. No uma mquina virtual no
sentido tradicional a que estamos mais habituados. Vou usar Linux kernel version 3.10 or higher
uma das analogias para diferenciar o Container Docker de
2.00 GB of RAM
uma mquina virtual:
Um Container Docker est para uma Mquina Virtu-
3.00 GB of available disk space
al, como uma Thread est para um Processo. O URI refere os requisitos para Docker Universal
Ou seja, acaba por ser uma Lightweight Virtual Machi- Control Plane, tipicamente para instalar em Cloud ou On-
ne. Permisses, mas os requisitos so semelhantes para os nos-
sos portteis.
A criao de Container segue a filosofia de blocos de
construo (building blocks). Pensem em peas da Lego, Para proceder instalao basta aceder ao endereo
querem construir uma parede e para tal vo colocando peas http://bit.ly/Docker-Install e seguir atentamente as instrues.
atrs de peas. O mesmo acontece com o Docker, vo com- Para os sistemas operativos mais antigos (no demasiado,
claro J) cada pagina refere como instalar a Docker Toolbox,

6
TEMA DA CAPA
DOCKER: OVERVIEW
no entanto chamo a ateno que este produto no supor- Conhecer 20% dos comandos que servem para 80%
tado e as atualizaes j no so to frequentes. das vezes.

O wizard instala trs componentes principais: No necessrio ser um expert em comandos Linux,
mas ajuda j ter trabalhado com ambientes Unix, uma vez que
Docker Engine: o Docker em si. grande parte dos comandos tm uma filosofia semelhante,
mas em contexto diferente.
Docker Compose: permite compor imagens Docker
Por exemplo:
Docker Machine: permite configurar a Virtual Machine
onde o Docker instancia os Containers O comando:

instalado tambm uma aplicao Kitematic, ainda HostApple:~ nunocancelo$ docker ps


est em verso Beta e precisa de algumas melhorias, que
permite de uma forma mais grfica pesquisar imagens no Mostra os containers ativos que esto a correr na m-
Docker Hub e gerir o ciclo de vida de um container. quina e com o id de um container podemos executar o coman-
do:
Nas verses MacOS e Windows o Docker instalado
como servio, o que permite arrancar o Docker quando o HostApple:~ nunocancelo$ docker kill CONTAINER_ID
sistema operativo arrancar. Desconheo se em Linux o com-
portamento semelhante. Que mata o container com esse id.

OK, est instalado e agora? Esta uma pequena lista dos comandos que mais uso:

Bem, os primeiros passos passam por conhecer a attach: Attach to a running container
aplicao, mas recomendo que encontrem um objetivo (por
mais simples que seja) para que a aprendizagem seja a mais exec: Run a command in a running container
proveitosa possvel.
images: List images
Se seguiram o manual de instalao, j perceberam
que para se trabalhar com Docker necessrio trabalhar em info: Display system-wide information
linha de comando. Por incrvel que possa parecer no as-
inspect: Return low-level information on Docker objects
sim to intragvel como possa parecer J. O passo 2 (verso
mac) pede para verificar a verso de cada uma das compo- kill: Kill one or more running containers
nentes:
logs: Fetch the logs of a container
HostApple:~ nunocancelo$ docker --version
Docker version 1.13.0, build 49bf474 ps: List containers

HostApple:~ nunocancelo$ docker-machine --version pull: Pull an image or a repository from a registry
docker-machine version 0.9.0, build 15fd4c7
rm: Remove one or more containers
HostApple:~ nunocancelo$ docker-compose --version
docker-compose version 1.10.0, build 4bd6f1a rmi: Remove one or more images

A verso de cada componente relevante quando se run: Run a command in a new container
est a brincar, pois em cada verso nova o comportamento
poder ser diferente e alguns ajustes podero ter que ser search: Search the Docker Hub for images
feitos.
stats: Display a live stream of container(s) resource
O comando mais til, e que no inicio usado bastan- usage statistics
te, o de ajuda:
Todos restantes tambm so importantes, mas no os
uso com tanta frequncia.
HostApple:~ nunocancelo$ docker help
Antes de avanarmos necessrio esclarecer os pon-
(Por questes de legibilidade no apresentado o resultado)
tos bastantes importantes:
O resultado apresenta todos os comandos suportado
por esta verso do Docker, e para obter ajuda de um deter- Como j foi mencionado anteriormente, um Container
minado comando: uma Lightweight Virtual Machine, mas necessrio
mencionar que uma Image um stack aplicacional pre-
HostApple:~ nunocancelo$ docker COMMAND --help viamente definido. No so a mesma coisa.

Pessoalmente desconheo o comportamento de gran- Uma Image readonly, uma vez criada no pode ser
de parte dos comandos, porem sigo a regra dos 20-80: alterada. Se for necessrio alterar alguma configurao

7
TEMA DA CAPA
DOCKER: OVERVIEW
ou adicionar algo necessrio criar uma nova Image. sha256:c5515758d4c5e1e838e9cd307f6c6a0d620b5e07e6f9
27b07d05f6d12a1ac8d7
Sendo que uma Image (que readonly) vive dentro Status: Downloaded newer image for hello-
world:latest
de um Container quando se sai (exit) desse container,
toda a nova informao que l foi criada perder-se Neste exemplo, a imagem Hello-World o que mostra
aquando a sada do Container. Porm h formas de so todos os passos que fez at concluir:
salvaguardar a informao J.
Hello from Docker!
Docker Hello World This message shows that your installation appears
Para no variar, vamos criar um Hello World para to be working correctly.
comearmos a interagir com o Docker e ver as suas potenci- To generate this message, Docker took the follo-
alidades. wing steps:
1. The Docker client contacted the Docker dae-
Vou replicar o exemplo do manual de instalao do mon.
passo 3 (verso mac) e instalar uma imagem Hello-World: 2. The Docker daemon pulled the "hello-world"
image from the Docker Hub.
3. The Docker daemon created a new container
HostApple:~ nunocancelo$ docker run hello- from that image which runs the
world executable that produces the output you are
Unable to find image 'hello-world:latest' lo- currently reading.
cally 4. The Docker daemon streamed that output to the
latest: Pulling from library/hello-world Docker client, which sent it
78445dd45222: Pull complete to your terminal.
Digest:
sha256:c5515758d4c5e1e838e9cd307f6c6a0d620b5e07e6
f927b07d05f6d12a1ac8d7 Para comeo est porreiro, mas todos concordamos
Status: Downloaded newer image for hello- que no til (como todos os Hello-World :P). Ento vamos
world:latest
tentar algo mais.
Hello from Docker!
This message shows that your installation ap- Continuando o manual vamos instalar um servidor
pears to be working correctly. NGINX, para quem no sabe um servidor HTTP de alta
performance, e aqui j temos algumas novas features porrei-
To generate this message, Docker took the fol- ras.
lowing steps:
1. The Docker client contacted the Docker HostApple:~ nunocancelo$ docker run -d -p 80:80 --
daemon. name webserver nginx
2. The Docker daemon pulled the "hello-world" Unable to find image 'nginx:latest' locally
image from the Docker Hub. latest: Pulling from library/nginx
3. The Docker daemon created a new container 5040bd298390: Pull complete
from that image which runs the 333547110842: Pull complete
executable that produces the output you 4df1e44d2a7a: Pull complete
are currently reading. Digest:
4. The Docker daemon streamed that output to sha256:f2d384a6ca8ada733df555be3edc427f2e5f285ebf46
the Docker client, which sent it 8aae940843de8cf74645
to your terminal. Status: Downloaded newer image for nginx:latest
6a9862f69870db29401404b40fe4247068c609791160cf60060
To try something more ambitious, you can run f0067bf3c2679
an Ubuntu container with:
$ docker run -it ubuntu bash
Como se pode ver, a mquina tinha a imagem local-
Share images, automate workflows, and more mente e foi o repositrio buscar e instalou trs componentes.
with a free Docker ID:
https://cloud.docker.com/ Analisando melhor o comando:

For more examples and ideas, visit: HostApple:~ nunocancelo$ docker run -d -p 80:80 --
https://docs.docker.com/engine/userguide/ name webserver nginx

Vai correr num novo container a imagem nginx, o d


Quando o comando executado, o comportamento
significa que vai correr em modo detach (isto vai correr em
por omisso verificar se a imagem pretendida (no nosso
background), o p 80:80 significa que o container expe o
caso Hello-World) existe localmente. Se existir executa, se-
porto 80 e mapeia internamente com o porto 80 e, por fim, o
no vai ao repositrio (Docker Hub) tentar obter a imagem e
--name permite atribuir um nome ao container. Por omisso
instala a imagem como todas as suas dependncias.
todos os containers tm um nome (e so nicos), podem
Unable to find image 'hello-world:latest' locally no ser nada elucidativos. Em seguida vamos ter um exem-
latest: Pulling from library/hello-world plo em que d para perceber(corri o mesmo comando mas
78445dd45222: Pull complete em a opo --name).
Digest:

8
TEMA DA CAPA
DOCKER: OVERVIEW
A imagem Figura 2 mostra o output: Next Step: Dockerfile
Isto muito til para usar em imagens j feitas, mas e
se no encontrar nenhuma imagem que satisfaa as minhas
necessidades? Ou ento, quero fazer um de raiz? Para aten-
der a esta necessidade foi criado o Dockerfile, que um fi-
cheiro de texto com um conjunto de diretivas que permite
criar imagens.
O manual de referncia do Dockerfile pode ser encon-
trado em http://bit.ly/Dockerfile-Reference.
Como exemplo, vamos supor que temos um site est-
tico que queremos disponibilizar. Para tal, o melhor come-
ar pelo inicio J.
Criamos uma pasta raiz e dentro desta pasta vamos
criar uma outra pasta onde vai estar o nosso site e um fichei-
ro chamado Dockerfile com o seguinte contedo muito sim-
ples.
Figura 2: nginx Dockerfile
Vamos correr o comando ps para vermos a informa-
FROM httpd:2.4
o exposta (por questo de legibilidade algumas colunas COPY ./public-html/ /usr/local/apache2/htdocs/
menos relevantes foram removidas):

HostApple:~ nunocancelo$ docker ps Neste ficheiro usamos duas diretivas:


IMAGE PORTS NAMES
nginx 443/tcp, 0.0.0.0:81->80/tcp FROM: Imagem a partir da qual ns vamos trabalhar.
stupefied_clarke
nginx 0.0.0.0:80->80/tcp, 443/tcp webserver COPY: depois da imagem ser obtida copiamos o nosso site.
Agora vamos compilar o nosso Dockerfile

Como se pode ver, a informao mostra a Image que


estamos a usar, os portos utilizados e o nome atribudo ao HostApple:pap-httpd nunocancelo$ docker build -t
Container. Na primeira linha temos o nome atribudo automa- masterzdran/pap-httpd .
Sending build context to Docker daemon 10.75 kB
ticamente, apesar de engraado no muito til para identifi-
Step 1/2 : FROM httpd:2.4
car o que temos a correr l dentro. 2.4: Pulling from library/httpd
5040bd298390: Already exists
Para parar o Container:
63408554ba61: Pull complete
4dfe9ef0af52: Pull complete
HostApple:~ nunocancelo$ docker stop webserver 84871cd4d3da: Pull complete
b376204f8aa6: Pull complete
2a8d452c2c14: Pull complete
Para reiniciar o Container: 7cfa9c4a8891: Pull complete
Digest:
HostApple:~ nunocancelo$ docker start webserver sha256:1407eb0941b010035f86dfe8b7339c4dd4153e2f7
b855ccc67dc0494e9f2756c
Status: Downloaded newer image for httpd:2.4
Para remover o Container: ---> 67a5f36fd844
Step 2/2 : COPY ./public-html/ /usr/local/apache2/htdocs/
---> b32140ef85b6
HostApple:~ nunocancelo$ docker rm webserver Removing intermediate container 8fd6889baf0f
Successfully built b32140ef85b6
Para remover a Image:
Estamos a fazer build, criamos uma tag (com o -t) e
porque usamos a nomenclatura do ficheiro recomendada,
HostApple:~ nunocancelo$ docker rmi nginx
indicamos onde est o ficheiro para fazer o build (.).
Ele comea a fazer a sua magia.
Podemos dar os parmetros que quisermos pela linha
comandos, mapear portos, mapear volumes, executar co- Quando termina fazemos:
mandos, etc. Pessoalmente recomendo criar um script que
tenha toda a configurao pretendida para executar de uma HostApple:pap-httpd nunocancelo$ docker run -dit -
s vez. Novamente, Set it and Forget it. p 80:80 --name pap-httpd masterzdran/pap-httpd

9
TEMA DA CAPA
DOCKER: OVERVIEW
E quando formos ao browser obtemos a imagem Fig- Por vezes necessrio ver as configuraes de uma
ura 3. imagem para obter informaes de networking, mounting
points, etc. Para obter essa informao usamos o inspect:

HostApple:~ nunocancelo$ docker inspect mas-


terzdran/pap-httpd

O output longo, e por questes de legibilidade no


colocado, mas pode visualizar um vasto conjunto de configu-
raes da image.
Volumes
Como j mencionado, as imagens so readonly e isso
quer dizer que quando o container desligado toda a in-
formao nova perdida. Este comportamento no o
desejado. No nosso exemplo, podemos querer manter os
logs do servidor/aplicao para futuras consultas e neste
momento no nos possvel, ou mesmo queremos atualizar
Figura 3: Dockerfile build example uma pgina do nosso site que tem um erro. Ento como re-
solvemos esta situao?
Se repararem o comando tem dois novos parmetros
o t e o i, e isto significa que querem que o container tenha Existem duas formas que podemos contornar este
um terminal iterativo. desafio: com Data Volumes ou com Data Containers, ambos
funcionam de forma semelhante apesar de serem declarados
Agora que tem o container online e a correr em back-
de forma diferente.
ground, podem ver os logs do servidor http com:
Data Volumes
HostApple:pap-httpd nunocancelo$ docker logs pap
-httpd Imaginemos que queremos ento atualizar a pgina
do nosso exemplo. Uma forma com Data Volumes, em que
Porque os nomes dos containers so nicos, to no arranque da imagem declaramos que existe uma diretoria
nicos como o seu ID, podemos referenciar os container pelo no nosso sistema de ficheiros que mapeada com a direto-
seu nome ao invs do seu id. Neste exemplo queremos ver ria no sistema de ficheiros do container (nomeadamente a
os logs do container pap-httpd. diretoria onde est o nosso site).
Por vezes necessrio entrar no container para re- HostApple:pap-httpd nunocancelo$ docker run -dit
alizar operaes, ver ficheiros de configurao, etc. A manei- -p 80:80 --name pap-httpd -v [Local Path]:/usr/
ra mais simples de entrar dentro de um container atravs local/apache2/htdocs/ masterzdran/pap-httpd
do comando exec:
Este comando vai mapear a diretoria Local Path
HostApple:~ nunocancelo$ docker exec -ti com a diretoria /usr/local/apache2/htdocs/, onde est o site
pap-httpd bash
root@47d280db122c:/usr/local/apache2# no container. Contudo, ao realizarmos este mapeamento o
container deixa de olhar para o contedo da diretoria e pas-
Estamos a dizer que queremos um terminal interacti-
sa a olhar para o volume mapeado. E neste caso a diretoria
vo (-ti) do container pap-httpd e executa o comando bash. E
do host mapeada no a mesma onde est o site, pelo que
depois temos uma linha de comandos dentro do container.
obtenho a Figura 4:
Podemos correr um comando com o docker run? A
resposta depende da imagem que estamos a usar. Neste
exemplo a nossa imagem lana um servidor httpd, se colo-
carmos um comando no fim para ser executado ele vai fazer
overwrite do CMD (ltimo comando de arranque da im-
agem) da aplicao e o servidor no arranca, contudo fi-
camos com a linha de comandos do container disponvel.
E agora para sair? Bem, no executem o exit ou
carregar em ctrl+c, ctrl+d, porque todos eles indicam ao con-
tainer que para fazer shutdown.
Para fazer detach do container pressionem ctrl+p
ctrl+q.

Figura 4: Data Volume Mapping

10
TEMA DA CAPA
DOCKER: OVERVIEW
E navegando para a diretoria public-html temos Este comando particularmente til quando andamos
ento o nosso site Figura 5. a testar provas de conceito e novas Images e queremos
guardar as configuraes para depois as usarmos noutros
containers.
Data Containers
Assim como havia sido mencionado, existe outra for-
ma de ter os dados guardados os Data Containers. O para-
digma um pouco diferente dos Data Volumes uma vez que
so containers na mesma, mas no tm qualquer imagem
associada. Pensem em informao utilizada ou gerada pela
nossa aplicao que precisa de ser guardada e posterior-
mente disponibilizada. Estou a referir-me a logs da
aplicao, da infraestrutura, das bases de dados, etc.
um container em que a nica coisa que faz guar-
Figura 5: Site num Data Volume dar dados, posteriormente podemos aceder e no est asso-
ciado a nenhuma imagem ou container, significando que
Agora est na altura de modificarmos o nosso site
mesmo que os containers morram ou sejam removidos a
localmente e o mesmo ser refletido automaticamente no
sua informao continua viva no Data Container que lhe foi
nosso container.
associado.
Aps algumas alteraes, o nosso site de exemplo
Podemos ter N containers para M propsitos e para
ficou assim como na Figura 6:
cada image container que criemos podemos ter associados
os Data Containers que necessitarmos.
Para usarmos esta funcionalidade necessrio tomar
dois passos:

Criar o(s) Data Container(s)

Associar o(s) Data Container(s)


Vamos ento criar um volume:

HostApple:pap-httpd nunocancelo$ docker create -


v /usr/local/apache2/logs --name pap-httpd-logs
masterzdran/pap-httpd /bin/true

Muitos dos parmetros j nos so familiares e o co-


mando mostra que queremos criar um volume (create v)
com aquela localizao (/usr/local/apache2/logs), vamos dar
Figura 6: Alteraes ao Site um nome para ser mais legvel (pap-httpd-logs). Estamos a
usar a imagem para os containers homogneos e por fim o /
Com pouco esforo o site ficou publicado, bastando
bin/true para informar que tudo correu bem (til se estivemos
fazer refrescar a pgina para refletir as alteraes.
em modo batch).
Neste tipo de mapeamento torna-se simples fazer
Agora, quando associarmos o Data Container a um
backup do site, bastando criar uma copia de segurana da
Container, se este tiver a diretoria mencionada passar a
diretoria mapeada.
escrever no nosso novo container.
No estamos limitados somente a diretorias, po-
Como o Data Container continua a ser um container,
demos mapear tambm ficheiros entre host e container, po-
podemos ver o seu estado:
rm pessoalmente ainda no encontrei uma vantagem em
fazer isso. HostApple:pap-httpd nunocancelo$ docker ps -a
CONTAINER ID STATUS NAMES
Por vezes existe a necessidade de copiar ficheiros 9f48f0ac4f9f Created
dentro dos containers, como os ficheiros de configuraes ou pap-httpd-logs
plug-ins que o container tem. Para tal executamos um novo 77deb89d4063 Up About an hour pap-httpd
comando:
E inspecionar o seu contedo:
HostApple:pap-httpd nunocancelo$docker cp
<containerId>:/file/path/within/container /host/ HostApple:pap-httpd nunocancelo$ docker inspect
path/target pap-httpd-logs

11
TEMA DA CAPA
DOCKER: OVERVIEW
Agora vamos ao segundo ponto, associar o Data No entanto em docker acaba por ser simples. A pgina de
Container ao nosso container e para tal executamos o se- referncia do docker (http://bit.ly/docker-network) explica
guinte comando: muito bem este tema, assim como a sua configurao.
HostApple:pap-httpd nunocancelo$ docker run -dit - Para listar as redes disponveis, executamos o
p 80:80 --name pap-httpd --volumes-from pap-httpd- seguinte comando:
logs -v [Local Path]:/usr/local/apache2/htdocs/
masterzdran/pap-httpd HostApple:pap-httpd nunocancelo$ docker network ls

Como j devem ter reparado o padro de execuo


Como podemos verificar o parmetro --
dos comandos bastante semelhante aos demais comandos
volumes-from pap-httpd-logs associa o nosso Data
j executados. Podemos criar da mesma forma e atribuir um
Container ao container que acabamos de criar.
nome em cada uma das novas redes j criadas.
Outra utilizao para o mesmo parmetro
Por omisso todos os containers ficam associados
para criar backup ou restore.
network Bridge, porm podemos indicar uma outra rede:
Para fazer um backup:
HostApple:pap-httpd nunocancelo$ docker run --
HostApple:pap-httpd nunocancelo$ docker run --rm network=<NETWORK>
--volumes-from pap-httpd-logs -v $(pwd):/backup
ubuntu tar cvf /backup/backup.tar /usr/local/ Desta forma permite-nos ter redes (com nomes
apache2/logs especficos) para conjunto de aplicaes.
tar: Removing leading `/' from member names
/usr/local/apache2/logs/ Agora, temos os containers dentro da mesma rede e
/usr/local/apache2/logs/httpd.pid queremos que eles falem uns com os outros, poderia ser um
bicho de sete cabeas, mas a equipa do Docker simplificou
Neste caso vamos usar uma imagem Ubuntu
a ao.
para executarmos o comando tar para criar um ar-
quivo com o contedo da diretoria.
HostApple:pap-httpd nunocancelo$ docker run -dti -
Para depois fazer restore temos que criar um -link CONTAINER:ALIAS --name LINKED <IMAGE>
novo Data Container e depois executar um coman-
O parmetro --link CONTAINER:ALIAS vai dizer que
do parecido para extrair os ficheiros:
o container que vai ser criado vai est ligado ao container
CONTAINER:ALIAS. E a partir desse momento ambos os
HostApple:pap-httpd nunocancelo$ docker run -v /
usr/local/apache2/logs --name pap-httpd-logs2 containers falam uns com os outros
ubuntu /bin/bash
HostApple:pap-httpd nunocancelo$ docker run --rm -
-volumes-from pap-httpd-logs2 -v $(pwd):/backup
ubuntu bash -c "cd /usr/local/apache2/logs && tar
xvf /backup/backup.tar --strip 1"
usr/local/apache2/logs/
Docker um pro-
jeto open-source que
usr/local/apache2/logs/httpd.pid
Este acaba por ser o procedimento comum para os
processos de migrao, em que temos que fazer backup e
restore de Data Containers. permite criar um con-
Networking
tentor (container) com
At agora temos visto um nico container, onde
reside o nosso servidor web para disponibilizar contedo a infraestrutura que se
esttico.
Os containers so autocontidos e no conhecem pretender por forma a
outros containers. Podemos ter N containers a correr, tantos
os que a nossa virtual machine nos permita ter, e apesar de poder partilha-la em
todos eles poderem ser acedidos pela nossa rede, eles no
se conhecem uns aos outros e por isso no conseguem falar
entre si. Se tivermos um servidor web que precisa de aceder
qualquer mquina e
a uma base de dados que est noutro container, como que
fazemos?
manter sempre o mes-
Para ultrapassar este desafio temos que configurar a
network. Admito que configurao de redes algo que me
mo comportamento.
ultrapassa um pouco, sei o essencial para conseguir aceder
Internet. J
()

12
TEMA DA CAPA
DOCKER: OVERVIEW
Docker Machine fora das diretorias partilhadas.

H pouco mencionei que podemos ter tantos os Dependendo do uso que se quer dar aos containers,
containers que quisermos como o que a mquina virtual recomendo que no se exagere no numero de CPUs e
permitir. Por omisso, quando instalamos o Docker memria RAM atribuda, pois isso vai se refletir diretamente
instalado uma Docker Machine com os recursos na performance do computador no dia a dia. Quando
recomendados (na minha instalao tem dois cores e dois estiverem a testar imagens, novas aplicaes, servidores,
gigabytes de memria RAM), porm por vezes no investiguem os requisitos de sistema e faam umas contas
suficiente para a infraestrutura que queremos montar. de merceeiro, pois existe um trade-off entre a performance
dos containers e a performance do computador.
Apesar de podermos alterar estes parmetros via
linha de comandos, eu pessoalmente acabo por usar a Concluso
interface grfica fornecida. Para aceder a ela, vamos s
Este breve overview sobre o ambiente docker permite
propriedades do icon do docker (uma baleia), que no OSX
sensibilizar sobre as potencialidades deste sistema e de que
est na barra superior, no Windows na barra de status e
forma nos pode facilitar, agilizar o nosso trabalho.
aparece a janela da :
uma excelente forma de ter os sistemas contidos e
por componentes tendo um potencial enorme, e porque tudo
reside em containers, em muito pouco tempo podemos
migrar para a Cloud (um servio de Containers) e ter os
nossos sistemas a funcionar.

Repositrio:
https://gitlab.com/masterzdran/docker-overview

Referencias
Para alm das j referidas no texto:
https://docs.docker.com
https://hub.docker.com
http://odewahn.github.io/docker-jumpstart/building-images-
with-dockerfiles.html

Figura 7: Propriedades do Docker


No Tab Advanced podemos alterar as configuraes
da mquina virtual (aps a alterao necessrio fazer
restart ao servio, que uma opo tambm no icon do
docker). Esta interface permite tambm outras configuraes
como diretorias partilhas ou definies de proxy. Por
omisso no permitido criar Data Volumes e Containers

AUTOR
Escrito por Nuno Cancelo

Curioso por natureza e engenheiro informtico por formao. Desde muito cedo me despertou o interes-
se pelos computadores e informtica com o famoso Spectrum. Tenho um gosto peculiar por aprender
novas coisas frequentemente mesmo que no venha a trabalhar com elas e optimizar os sistemas au-
mentando a sua performance.

13
A PROGRAMAR
API Rest com Spring Boot (parte 2)
Um bot para Telegram com o Jogo da velha (Jogo do Galo).
Automao do Azure com Windows PowerShell Desired State Configuration
O Problema do casamento Estvel utilizando o Algoritmo Gale-Shapley
A PROGRAMAR

API Rest com Spring Boot (parte 2)


Nesta segunda parte, vamos ento adicionar ao nos- Assim sendo, o nosso primero passo ser remover o logback
so projecto um sistema que nos permita criar logs personali- do nosso projecto e para isso vamos recorrer possibilidade
zados sobre o acesso nossa API. que o Maven nos oferece de excluir determinadas depen-
dncias.
Sempre que desenvolvemos uma aplicao, devemos
logo de inicio tratar de providenciar um bom sistema de logs Vamos ento ao ficheiro POM.XML do projecto e localizamos
j que ele uma parte fundamental, seja durante o desen- as linhas referentes dependncia do Spring-boot-starter,
volvimento, seja durante a operao da aplicao. atravs pois atravs deste starter que o logback adicionado no
das mensagens de log (em ficheiro ou no ecr) que podemos nosso projecto.
determinar o que realmente est a acontecer na nossa apli-
cao e mais rapidamente determinar a origem de qualquer <dependency>
problema. <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
Para o programador, muitas vezes a anlise do log </dependency>
fornece respostas que de outra forma seriam muito difceis
de obter. Uma vez que pretendemos excluir uma biblioteca que
por defeito este starter adiciona ao projecto, vamos adicionar
No caso de aplicaes cujo acesso remoto permitido, torna
uma excluso ficando ento este grupo com a seguinte reda-
-se tambm importante poder determinar quais os recursos
o:
acedidos, quando e por quem.
No nosso pequenssimo projecto vamos utilizar o log4J2, <dependency>
uma biblioteca extremamente madura que est debaixo da <groupId>org.springframework.boot
</groupId>
alada da Apache Software Foundation. Existem outras bibli- <artifactId>spring-boot-starter
otecas para o efeito, mas o log4J2 extremamente flexvel e </artifactId>
apresenta uma performance elevada mesmo em sistemas de <exclusions>
<exclusion>
uso intensivo.
<groupId>org.springframework.boot
No faz parte do mbito deste artigo aprofundar as </groupId>
capacidades desta biblioteca, que so imensas, e a quem <artifactId>spring-boot-
estiver interessado em aprofundar os seus conhecimentos starter-logging</artifactId>
aconselha-se a leitura do manual que pode ser encontrado </exclusion>
</exclusions>
em https://logging.apache.org/log4j/2.x/. A literatura pode ser </dependency>
intimidante, e dificilmente uma nica leitura da documenta-
o ser suficiente. A utilizao e compreenso do log4J De seguida, e sempre dentro da zona das dependn-
exige algum esforo e dedicao, mas o aumento de produti- cias do ficheiro pom.xml adicionamos a dependncia do star-
vidade que iremos obter sempre que necessitarmos de fazer ter que o Spring Boot disponibiliza para adicionarmos o lo-
algum tipo de debug nas nossas aplicaes compensa o g4j2 ao nosso projecto. Para isso basta adicionar as seguin-
tempo dedicado ao estudo da biblioteca. tes linhas.
Neste artigo iremos apenas abordar como podemos incluir o <dependency>
log4J2 no nosso projecto, como criar os ficheiros de configu- <groupId>org.springframework.boot
</groupId>
rao necessrios ao seu funcionamento e como gerar um <artifactId>spring-boot-starter-log4j2
ficheiro de log muito simples sobre o acesso nossa API. </artifactId>
</dependency>
Uma vez que o nosso projecto baseado em Maven,
por a que vamos comear, a fim de adicionarmos ao pro-
Em resumo, o que fizemos foi informar que pretenda-
jecto todas as dependncias necessrias.
mos excluir a biblioteca standard de log que o Spring boot
O framework Spring, suporta, de raiz, vrias bibliote- disponibiliza e incluir uma outra.
cas para servios de logging e na verso actual est dispon-
Aps adicionarmos a nova configurao pretendida
vel tambm um starter para o log4J2 o que nos simplifica
ao ficheiro pom.xml devemos grava-lo.
bastante a vida (afinal a simplificao o grande objectivo
do springbot), no entanto por defeito adicionado o logback, Como somos adeptos das boas prticas, o passo
e no esta a biblioteca que pretendemos utilizar aqui. seguinte imediatamente ordenar ao Spring Tool Suite que

15
A PROGRAMAR
API REST COM SPRING BOOT (PARTE 2)
atualize as nossas dependncias. Este ficheiro, no nosso caso, seguir uma semntica
XML, ir conter a seguinte informao
Podemos aceder ao menu do Maven, ou simplesmente
premir ALT+F5.
<?xml version="1.0" encoding="UTF-8"?>
Aps alguns instantes a biblioteca pretendida ser adicionada <Configuration>
<Properties>
ao projecto. <Property name="log-path">logs</Property>
</Properties>
<Appenders>
<Console name="Console-Appender"
target="SYSTEM_OUT">
<PatternLayout>
<pattern>
[%-5level] %d{yyyy-MM-dd
HH:mm:ss.SSS} [%t] %c{1} - %msg%n
</pattern>>
</PatternLayout>
</Console>
<File name="Api-File-Appender"
fileName="${log-path}/api_log.log" >
<PatternLayout>
<pattern>
%-5level %d [%t] %c:%M(%L): %
m%n
</pattern>
</PatternLayout>
</File>
<File name="SpringBoot-File-Appender"
fileName="${log-path}/spring_system_log.log" >
<PatternLayout>
<pattern>
%-5level %d [%t] %c:%M(%L): %
m%n
</pattern>
</PatternLayout>
</File>
</Appenders>
<Loggers>
<Logger name="org.springframework.web"
(pode verificar expandindo o grupo maven dependencies do level="info" additivity="false">
projecto, onde dever agora encontrar as bibliotecas do lo- <AppenderRef ref="SpringBoot-File-
g4J2) Appender"/>
<AppenderRef ref="Console-Appender"/>
Uma vez este processo concludo podemos ento co- </Logger>
<Logger name="pt.api.controllers"
mear a criar a configurao necessria para que o log4J2 level="info" additivity="false">
funcione como pretendemos. <AppenderRef ref="Api-File-Appender"/
>
Existem pelo menos 3 formas de configurar o log4j no <AppenderRef ref="Console-Appender"/>
Spring Boot. Podemos criar as configuraes no ficheiro appli- </Logger>
<Root>
cation.properties, podemos criar um ficheiro de configurao <AppenderRef ref="Console-Appender"/>
especfico, sendo que este ltimo nos permite um grau de con- </Root>
figurao bastante superior que o primeiro mtodo, e ainda </Loggers>
podemos criar a configurao programaticamente atravs de </Configuration>
classes. Vamos agora analisar algumas particularidades deste
ficheiro de configurao. Podemos encontrar algumas sec-
No nosso caso iremos utilizar um ficheiro de configura- es que destacamos, as Properties, os Appenders e os
o. Um facto importante que este ficheiro de configurao Loggers.
tem de residir no local correto do projecto. Se usarmos as con-
figuraes padres do framework, esse local ser a pasta src/ Na seco properties podemos criar pares do tipo
main/resources. chave/valor que ficam disponveis para utilizao em outras
seces do ficheiro. Neste caso apenas utilizamos uma cha-
Vamos ento criar um novo ficheiro na localizao refe- ve a que demos o nome log-path e qual atribumos o valor
rida, e vamos dar a esse ficheiro o nome de log4j2.xml. (nas logs (queremos que os nossos logs sejam criados numa
configuraes padro este nome obrigatrio, e a utilizao de pasta com o nome logs). Isto ir permitir que em todas as
outro nome ir gerar um erro, em que o STS ir indicar que no outras seces do ficheiro podemos usar o nome log-path e
encontra o ficheiro de configurao). Em alternativa pode-se ele ir ser substitudo pelo valor logs.
esquematizar o ficheiro de configurao usando Json ou Yaml,
mas a ideia semelhante. A seco Appenders permite-nos definir as possveis
formas de sada para os loggers. Criamos appenders para a
consola (console) e para ficheiro (file). No caso do logger

16
A PROGRAMAR

API REST COM SPRING BOOT (PARTE 2)


para a consola, definimos o target como system_out, o que logger.info("Classe: "+this.getClass().getName()
dirigir a mensagem log para o stream de sada que por defeito + " ,Mtodo :"+Thread.currentThread
().getStackTrace()[1].getMethodName()
a consola. Nos loggers do tipo file, as mensagens sero redi- + " ,URL :" + request.getRequestURI() +
recionadas para os ficheiros respetivos de acordo com o que " ,parametros : " + request.getQueryString() +
definimos na propriedade filename. ",IP Origem :" + request.getRemoteAddr() );

Em cada um dos appenders, informamos tambm um


Caso ainda se recordem da primeira parte deste arti-
padro de layout que ir definir o formato da mensagem de log.
go, foi feita uma pequena meno sobre termos adicionado o
O mais comum usarmos logs de uma linha num formato leg-
HttpServletRequest request como parmetro aos nossos
vel, no entanto o log4J permite outro tipo de layouts como
mtodos e de como isso nos poderia ser til mais tarde. Pois
Json, Xml entre outros. Aqui vamos utilizar o formato mais sim-
aqui est uma das razes. Atravs do request conseguimos
ples. A definio dos padres de layout (patternLayout) obede-
aceder informao sobre o pedido que foi efetuado pelo
ce a regras prprias que pode consultar em http://
cliente chamador.
logging.apache.org/log4j/2.0/manual/layouts.html#Patterns.
Nestes layouts podemos configurar o formato que queremos O que esta linha faz criar um entrada no log com o
para as datas, espaamentos, nomes ou ID das threads, no- nome da classe, nome do mtodo, o URL do pedido, os pa-
mes dos loggers e uma verdadeira mirade de opes que co- rmetros (caso existam) e o endereo IP de origem do pedi-
brem os casos mais exigentes que porventura possam surgir. do. No caso em que no existam parmetros, o valor regista-
do ser null
Para finalizar temos a seco dos Loggers. O nome que
atribumos aos loggers atravs da propriedade name impor- Aps adicionarmos esta linha a todos os pontos de
tante pois esse o nome que vamos utilizar no cdigo java entrada da nossa API, a classe ClienteController dever
sempre que necessitamos de evocar um logger. Por norma apresentar a seguinte redao:
utilizamos nomes na forma package ou package/class seguin-
do a hierarquia tradicional do Java. package pt.api.controllers;

Ainda dentro dos loggers encontramos um que espe- import java.util.Collection;


cial. O root . Este ir receber todas as mensagens que o siste- import javax.servlet.http.HttpServletRequest;
ma envie e que no estejam enquadradas em nenhum outro import javax.servlet.http.HttpServletResponse;
logger. No caso de nos esquecermos de o criar ele ser criado
import org.slf4j.Logger;
automaticamente pelo log4J2, mas isso poder no ser do import org.slf4j.LoggerFactory;
nosso interesse, pois assim podemos definir para onde devem import
ser canalizadas todas as mensagens que no pertenam aos org.springframework.beans.factory.annotation.Auto
outros loggers. wired;
import org.springframework.http.MediaType;
Agora que temos o ficheiro de configurao criado, po- import org.springframework.http.ResponseEntity;
import org.springframework.http.HttpStatus;
deremos comear a utilizar os loggers no nosso projecto. import org.springframework.web.bind.annotation.
PathVariable;
Vamos abrir a classe ClienteController que tnhamos import org.springframework.web.bind.annotation.
criado na primeira parte do artigo e vamos adicionar uma linha RequestBody;
imediatamente a seguir definio da classe, ficando agora import org.springframework.web.bind.annotation.
RequestMapping;
esta classe com a redao import org.springframework.web.bind.annotation.
@RestController RequestMethod;
public class ClienteController { import org.springframework.web.bind.annotation.
private final Logger logger=LoggerFactory.getLogger RequestParam;
(this.getClass()); import org.springframework.web.bind.annotation.
RestController;
@Autowired
private ClienteRepository clienteRepository; import pt.api.entities.ClienteEntity;
import pt.api.repositories.ClienteRepository;
O que estamos a fazer aqui solicitar LoggerFactory
@RestController
que nos disponibilize um logger baseado na nossa classe (que public class ClienteController {
pertence ao package pt.api.controllers) e se verificarem na private final Logger logger =
configurao temos um logger definido para esta situao que LoggerFactory.getLogger(this.getClass());
ir fazer log na consola e log para o ficheiro com o nome
@Autowired
api_log. private ClienteRepository clienteRepository;
Agora precisamos de informar o que queremos na nos- // EndPoint #1
sa linha de log, e vamos ento adicionar uma linha aos nossos @RequestMapping(value = "/api/v1/cliente/
{id}", method = RequestMethod.GET,
pontos de entrada, que nos ir permitir registar a informao produces = MediaType.APPLICATION_JSON_VALUE)
que pretendendo.
public ClienteEntity getByClienteId
(HttpServletRequest request,

17
A PROGRAMAR
API REST COM SPRING BOOT (PARTE 2)
HttpServletResponse response,@PathVariable }
(value = "id") String id) throws Exception {
// verificao do ID ClienteEntity cliente =
logger.info("Classe: " + this.getClass(). clienteRepository.pesquisaPorNIF(nif);
getName() + " ,Mtodo :" return cliente;
+ Thread.currentThread().getStackTrace() }
[1].getMethodName() + " ,URL :" + // EndPoint #4
request.getRequestURI()+ " ,parametros : " +
request.getQueryString() + ",IP Origem :" @RequestMapping(value = "/api/v1/cliente/
+ request.getRemoteAddr()); save", method = RequestMethod.POST, con-
int idCliente = 0; sumes = MediaType.APPLICATION_JSON_VALUE,
try { produces = Medi-
idCliente = Integer.parseInt(id); aType.APPLICATION_JSON_VALUE)
} catch (Exception ex) {
response.sendError public int saveCliente(HttpServletRequest
(HttpStatus.BAD_REQUEST.value()); request, HttpServletResponse response,
return null; @RequestBody ClienteEntity cliente) throws
} Exception {
// Fetch de um cliente por ID
ClienteEntity cliente = logger.info("Classe: " + this.getClass().
clienteRepository.findOne(idCliente); getName() + " ,Mtodo :"
if (cliente == null) { + Thread.currentThread().getStackTrace()
response.sendError [1].getMethodName() + " ,URL :" + re-
(HttpStatus.NOT_FOUND.value()); quest.getRequestURI() + " ,parametros : "
return null; + request.getQueryString() + ",IP Ori-
} else { gem :" + request.getRemoteAddr());
return cliente;
} if (cliente.getId() != null) {
} response.sendError
(HttpStatus.METHOD_NOT_ALLOWED.value());
// EndPoint #2 }
@RequestMapping(value = "/api/v1/cliente/
all", method = RequestMethod.GET, produces = try {
MediaType.APPLICATION_JSON_VALUE) clienteRepository.save(cliente);
} catch (Exception ex) {
public ResponseEnti- response.sendError
ty<Collection<ClienteEntity>> getAllClientes (HttpStatus.BAD_REQUEST.value());
(HttpServletRequest request, HttpS- }
ervletResponse response) {
logger.info("Classe: " + this.getClass(). return HttpStatus.CREATED.value();
getName() + " ,Mtodo :" }
+ Thread.currentThread().getStackTrace()
[1].getMethodName() + " ,URL :" + re- // EndPoint #5
quest.getRequestURI()
+ " ,parametros : " + request.getQueryString @RequestMapping(value = "/api/v1/cliente/
() + ",IP Origem :" + request.getRemoteAddr update", method = RequestMethod.PUT, con-
()); sumes = MediaType.APPLICATION_JSON_VALUE,
produces = Medi-
Collection<ClienteEntity> clientes = aType.APPLICATION_JSON_VALUE)
clienteRepository.findAll();
return new ResponseEntity<Collection public int updateCliente(HttpServletRequest
<ClienteEntity>>(clientes, HttpStatus.OK); request, HttpServletResponse response,
} @RequestBody ClienteEntity cliente) throws
Exception {
// EndPoint #3
@RequestMapping(value = "/api/v1/cliente", logger.info("Classe: " + this.getClass().
method = RequestMethod.GET, produces = Medi- getName() + " ,Mtodo :"
aType.APPLICATION_JSON_VALUE) + Thread.currentThread().getStackTrace()
[1].getMethodName() + " ,URL :" + re-
public ClienteEntity getByClienteNIF quest.getRequestURI()
(HttpServletRequest request, HttpServletResponse + " ,parametros : " + re-
response,@RequestParam(value = "nif") String nif) quest.getQueryString() + ",IP Origem :" +
throws Exception { request.getRemoteAddr());
logger.info("Classe: " + this.getClass(). // verificar se no nulo e se existe
getName() + " ,Mtodo :" if (cliente.getId() == null ||
+ Thread.currentThread().getStackTrace() clienteRepository.findOne(cliente.getId())
[1].getMethodName() + " ,URL :" + re- == null) {
quest.getRequestURI() + " ,parametros : " + response.sendError
request.getQueryString() + ",IP Origem :" + (HttpStatus.NOT_FOUND.value(), "Erro de ID");
request.getRemoteAddr()); return 0;
}
if (!nif.matches("[0-9]+") && nif.length()
!= 9) { try {
response.sendError clienteRepository.save(cliente);
(HttpStatus.BAD_REQUEST.value()); } catch (Exception ex) {
return null; response.sendError

18
A PROGRAMAR

API REST COM SPRING BOOT (PARTE 2)


(HttpStatus.BAD_REQUEST.value(), "Erro de BD"); e de seguida verifique que devemos ter uma nova pasta adi-
return 0; cionada ao nosso projecto com 2 novos ficheiros.
}
Vamos abrir o ficheiro api_log.log e nele deveremos
return HttpStatus.ACCEPTED.value(); encontrar o log de todos os acessos que fizemos API.
} No ficheiro Spring_system_log.log devermos encon-
// EndPoint #6 trar o log referente ao framework Spring.
@RequestMapping(value = "/api/v1/cliente/
delete/{id}", method = RequestMethod.DELETE, No se assuste se o IP aparecer como
produces = MediaType.APPLICATION_JSON_VALUE) 0:0:0:0:0:0:0:1. Caso esteja a desenvolver e testar no mes-
mo computador, esse o valor que o Spring vai assumir
public int deleteCliente(HttpServletRequest
request, HttpServletResponse response, para localhost.
@PathVariable(value = "id") String clienteID) Se tiver estado atento consola, enquanto efetuou os
throws Exception {
testes da API, poder verificar que as mensagens para alm
logger.info("Classe: " + this.getClass(). de terem ficado armazenadas no ficheiro, aparecem tambm
getName() + " ,Mtodo :" na consola , pois definimos no ficheiro de configurao que
+ Thread.currentThread().getStackTrace()
[1].getMethodName() + " ,URL :" + este logger ligava com o apender Api-File-Appender e com o
request.getRequestURI() Console-Appender.
+ " ,parametros : " + request.getQueryString
() + ",IP Origem :" + request.getRemoteAddr Como passar a nossa API para produo ?
());
// verificao do ID At agora temos estado a trabalhar sempre dentro do
int idCliente = 0; Spring Tool Suite (STS) que j inclui um servidor TomCat e
try { nos permite desenvolver e testar rapidamente. No entanto, o
idCliente = Integer.parseInt(clienteID);
} catch (Exception ex) { objetivo de qualquer aplicao correr fora do ambiente de
idCliente = 0; desenvolvimento.
response.sendError
(HttpStatus.BAD_REQUEST.value()); Neste exemplo, o que pretendemos fazer criar uma
return 0; aplicao que possa ser colocada rapidamente em qualquer
}
computador (que tenha JAVA instalado) e a mesma possa
try { correr imediatamente. Ou seja, no pretendemos instalar o
clienteRepository.delete(idCliente); TomCat, bibliotecas, configurar tudo, etc. O nico pressupos-
} catch (Exception ex) { to que vamos usar aqui, de que estamos a instalar a nossa
response.sendError
(HttpStatus.BAD_REQUEST.value(), "Erro de BD"); aplicao no mesmo servidor onde se encontra instalado o
return 0; MYSQL e que a base de dados est funcional. (se o MYSQL
} estiver em outro servidor, bastar alterar a localizao no ficheiro
return HttpStatus.OK.value(); Application.properties que est definida em spring.datasource.url)
}
} Como todos sabemos as aplicaes java so empa-
cotadas num formato prprio designado por jar. Neste caso o
Testando que queremos criar, o que normalmente se chama de fat
jar ou seja um nico ficheiro que tem todas as dependncias
que o nosso projecto necessita para funcionar, e neste caso
incluindo tambm o servidor.
Ou seja, a nossa API vai ter apenas um ficheiro, e
assim que o executamosVoil. Temos o servidor no ar e a
api a funcionar.
A criao de um fat jar extremamente simples, gra-
as ao Maven e apenas necessitamos de dar um comando
de consola.

Vamos agora correr e testar a nossa API, seguindo os


mesmos passos que efetuamos na primeira parte deste artigo,

19
A PROGRAMAR
API REST COM SPRING BOOT (PARTE 2)
No gestor de ficheiros, navegue at pasta onde est o Podemos executa-lo imediatamente atravs do co-
seu projecto. A pasta deve ter um contedo semelhante ao da mando java -jar apitutorial-1.0.0.jar. (certifique-se que o
imagem, e abra uma linha de comandos nesse local. servidor do Spring tool suite est parado).
Nesta pasta tudo o que tem a fazer digitar o comando Se tudo tiver corrido bem, dever visualizar o arran-
mvn clean package seguido de ENTER e aguardar que o Ma- que do Spring e passado alguns segundos a sua API est
ven trate de baixar todas as dependncias necessrias que em funcionamento e acessvel a partir de qualquer computa-
ainda no estejam no seu computador e de as empacotar. dor da sua rede, a pasta log ser criada e todos os logs se-
ro registados.
Quando o processo terminar dever visualizar uma
mensagem de BUILD SUCCESS. De seguida verifique a pasta No caso de estar a usar um servidor LINUX, o comando para
target e nela dever encontrar 2 ficheiros. Um dever ter a iniciar o mesmo, s dever ter em ateno as permisses
extenso .jar e outro a extenso .original. O ficheiro que quere- das pastas.
mos o que termina em jar. Se seguiu todos os passos como
descrevemos desde o incio, esse ficheiro dever ter o nome
apitutorial-1.0.0.jar, caso contrrio ter o nome que lhe tiver
atribuido.

Sempre que desen-


volvemos uma aplica-
o, devemos logo de
inicio tratar de provi-
denciar um bom siste-
ma de logs j que ele
uma parte fundamental,
seja durante o desen-
volvimento, seja duran- O cdigo presente neste artigo est disponvel em https://
gitlab.com/Java-exemplos/apitutorial-parte2.git
te a operao da aplica- Espero que este artigo seja til para quem se quiser iniciar
no framework Spring, utilizando o Spring Boot.
o.

AUTOR
Escrito por Jos Martins

Natural do Porto, autodidata. Iniciou-se no mundo das tecnologias com um Sinclair ZX-81 onde aprendeu a programar em
basic e assembler. Ao longo de 25 anos ligados s tecnologias, passou por quase todas as linguagens de programao, at
que decidiu assentar praa com JAVA. Atualmente trabalha na PJ Silva Lda, onde desenvolve projetos ligados monitoriza-
o do ensino prtico da conduo automvel. (josetabordamartins@gmail.com).

20
A PROGRAMAR

JavaFX: Passos Seguintes


No artigo anterior dei uma breve introduo sobre como Defining the application layout
programar com JavaFX, conceitos simples que permite come-
Em mdia, cada controlo JavaFX (checkbox, label, etc) tem
ar a desenvolver aplicaes grficas. Neste artigo vou explo-
quatro linhas de cdigo:
rar outros temas interessantes do ponto de vista de desenvol-
vimento e de manuteno de projetos de software com interfa- Instanciar um novo objeto.
ces grficas de desktop.
Definir o seu id.
Ao longo da minha carreira j desenvolvi e participei em
projetos de software de raiz, mas grande parte dela foi a man- Definir o seu comprimento
ter e a melhorar aplicaes legacy, e deixem-me que diga que
existem programadores muito imaginativos J. Um dos temas Definir a sua altura
que mais urticria me causa o facto de o software desenvol-
E depois mais umas quantas linhas para afetar o
vido no poder ser mantido com facilidade, e ao ripple effects
layout (Pane), configurar a Scene e o Stage.
das alteraes simples que so realizadas.
No entanto em cada controlo pode-se personalizar
Como mencionei no artigo anterior, devido necessida-
ainda mais. No caso do controlo textField pode-se definir a
de de alterar uma aplicao em Java Swing, essa mesma alte-
fonte, o seu tamanho, as linhas de contorno da caixa, a cor,
rao no se mostrou nada fcil de realizar, levando-me a pro-
etc.
curar alternativas e migrar para JavaFX. No artigo anterior abri
a porta tecnologia e o que foi apresentado no difere muito Porm o procedimento aborrecido e se pretender
do Java Swing, pelo que pode ser confuso a razo para a alte- atribuir a mesma personalizao para um conjunto de textFi-
rao. elds (ex: 20 caixas de texto).

Quando andei a investigar, o que estava procura era No fim do dia possvel ter umas boas centenas de
um modelo de desenvolvimento que me permitisse definir a linhas com cdigo repetido, montono e que se comea a
interface grfica em separado da lgica da aplicao, ou seja, perspetivar difcil de manter quando se comear a trabalhar
um modelo Model-View-Controller semelhana do que existe com os event handlers. A soluo no coesa ou mesmo
para aplicaes web, ou mesmo para a plataforma Android. E desacoplada e muito menos fcil de manter.
JavaFX tem mesmo o que estava procura e sobre isso que
Styling the application
venho falar.
Com o JavaFX veio algo muito fixe, a separao entre
Antes de comear
a definio da interface grfica e a sua estilizao. E con-
Antes de comear recomendado instalar alguns com- seguida atravs de um ficheiro CSS, sim um simples ficheiro
ponentes. No porque obrigatrio ou necessrio (mesmo) de CSS, semelhana do que usado em pginas web.
mas sim porque auxilia (e muito o desenvolvimento).
necessrio o JDK para ter o JavaFX:
Tal como em HTML, aqui existem as classes e os ids.
JDK 7 update 6: com JavaFX 2.2 As classes identificam o estilo a aplicar a um controlo que
tenha aquela classe ou definir por omisso o estilo de um
JDK 8: com JavaFX 8 controlo. Para os ids o estilo atribudo ao controlo que te-
nha aquele id e nico.
Para quem usa um IDE baseado em Eclipse deve insta-
lar este plugin: Hello World CSS

e(fx)clipse: http://bit.ly/e-fx-clipse Neste breve exemplo, vai ser demonstrado como usar
o CSS na aplicao.
Este plugin incorpora um conjunto de funcionalidades ao IDE
que facilitam o desenvolvimento e publicao dos projetos @Override
JavaFX. public void start(Stage primaryStage)
throws Exception {
// Stage Title
primaryStage.setTitle("Hello World");
Existe outra ferramenta da Oracle que deve ser instalada:
// Begin Scene definition
Scene Builder: http://bit.ly/JavaFX_Scene_Builder Label helloLabel1 = new Label();
helloLabel1.setText("Hello World!");
A ferramenta permite desenhar as interfaces grficas helloLabel1.setId("helloLabel1");
com simples drag-and-drop, configurar eventos etc. Label helloLabel2 = new Label();
helloLabel2.setText("Hello World!");
helloLabel2.setId("helloLabel2");

21
A PROGRAMAR
JAVAFX: PASSOS SEGUINTES

.add(getClass()
Label helloLabel3 = new Label(); .getResource("HelloWorld.css")
helloLabel3.setText("Hello World!"); .toExternalForm());
helloLabel3.setId("helloLabel3"); A partir deste momento, todos os estilos definidos no
CSS esto disponveis na aplicao. O resultado pode ser
VBox vboxPane = new VBox();
vboxPane.getChildren().addAll( visto na Figura 2.
helloLabel1,
helloLabel2,
helloLabel3);
vboxPane.setAlignment(Pos.CENTER);

Scene scene = new Scene(vboxPane,200,200);


// End Scene definition
// Add Scene to Stage
primaryStage.setScene(scene);
// Show Stage
primaryStage.show();
}

O exemplo muito semelhante ao que foi feito no artigo


anterior e segue o mesmo padro. A imagem da Figura 1 mos-
tra o ponto de partida.

Figura 2: .root styling

Como se v o tamanho da letra aumentou e fundo


mudou de cr. Lindo J.
Agora vou alterar o estilo de todos os controlos do
tipo Label:

.label{
-fx-border-color: #3633FF;
-fx-border-width: 3px;
-fx-padding: 10px;
}

e automaticamente o resultado visvel na Figura 3:


Figura 1: Hello World

Vou comear por criar um novo ficheiro CSS ao qual


vou dar o nome HelloWorld.css e vou comear a personalizar
componentes. Muito em breve vo perceber que no sou de-
signer J.
Vou comear por personalizar o componente raiz do
nosso Stage (root) que o controlo base a partir do qual todos
os controlos herdam as suas propriedades.

/* .root is the base element of the Scene */


.root{
-fx-background-color: #d08770;
-fx-font-size: 20px;
}

Tal como acontece em HTML, necessrio indicar que


este ficheiro com estilos deve ser carregado:
Scene scene = new Scene(vboxPane,200,200);
scene.getStylesheets() Figura 3: Label styling

22
A PROGRAMAR

JAVAFX: PASSOS SEGUINTES

Porm comum que apenas um conjunto de controlos De uma forma muito simples foi possvel separar a
tenham um dado estilo, por isso criamos uma classe especifica definio dos estilos e a sua personalizao do cdigo java
para o efeito. em si. No entanto, esta separao no suficiente.
.label-mine{ Hello World - FXML
-fx-border-color: #FF3364;
-fx-border-width: 5px; JavaFX trs outra particularidade fantstica, a possi-
-fx-font-size: 9px; bilidade de descrever em XML toda a interface grfica. O
}
prximo exemplo descreve o mesmo exemplo mas em
FXML.
E no controlo definimos qual a classe que ele usa
Assumindo foi instalado o plugin do e(fx)clipse, criar
Label helloLabel1 = new Label(); um projeto to simples como File -> New -> JavaFX Project
helloLabel1.setText("Hello World!"); e preencher os formulrios. No formulrio da Figura 6, na
helloLabel1.setId("helloLabel1");
helloLabel1.getStyleClass() combo box language escolher FXML. E ser criada uma
.add("label-mine"); estrutura semelhante Figura 7.
E obtm-se o resultado da Figura 4:

Figura 6: New JavaFX Project

Figura 4: Custom Label styling


Por fim, vou definir um estilo para um controlo em espe-
cifico, definindo o seu id.

#helloLabel3{
-fx-border-color: #7B241C;
-fx-border-width: 2px;
-fx-font-size: 28px;
-fx-background-color: #F5B7B1;
-fx-text-fill: #873600;
}
E o seu resultado na Figura 5:

Figura 7: JavaFX Project Structure

O novo projeto contm quatro ficheiros:

Main.java: o ponto de entrada da aplicao.

application.css: o ficheiro de estilos.

HelloWorld.fxml: ficheiro com definio do UI.

HelloWorldController: o ficheiro onde esto defini-


Figura 5: Control Id Styling dos event handlers

23
A PROGRAMAR
JAVAFX: PASSOS SEGUINTES

O Main.java gerado o seguinte: O resultado o espectvel da Figura 8.

public class Main extends Application {


@Override
public void start(Stage primaryStage) {
try {
VBox root = (VBox)FXMLLoader
.load(getClass()
.getResource("HelloWorld.fxml"));
Scene scene = new Scene(root,200,200); sce-
ne.getStylesheets()
.add(getClass()
.getResource("application.css")
.toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}

Muito simples, carrega o xml com a definio da UI, o Figura 8: FXML Output
ficheiro de estilos e mostra a janela. Nada de muito relevante a
Controllers
dizer.
Como mencionei, o ficheiro de Controller acaba por
O ficheiro de estilos vou utilizado o mesmo contedo do
ser o ficheiro de gesto e tratamento de eventos.
exemplo anterior.
Uma vez que um ficheiro FXML s tem um nico Con-
J o ficheiro FXML requer mais ateno. O exemplo a
troller, os atributos podem ter visibilidade pblica. Porm, na
seguir representao em XML do que foi descrito em cdigo
minha opinio, a visibilidade deve ser mais restrita e coloca-
em exemplos anteriores:
se a anotao @FXML. Para mim, torna o cdigo mais leg-
<?xml version="1.0" encoding="UTF-8"?> vel.

<?import javafx.scene.layout.VBox?> Aproveito para deixar outra recomendao, o Control-


ler deve implementar a interface Initializable que tem o mto-
<?import javafx.scene.control.Label?> do initialize. Este mtodo invocado aps todos os ns do
<VBox xmlns:fx=http://javafx.com/fxml/1 FXML terem sido instanciados e til no caso de se preten-
fx:controller=".HelloWorldController" der fazer algo com os controlos antes de comear a aplica-
alignment="CENTER"> o.
<Label fx:id="helloLabel1" O prximo exemplo vou colocar uma label e um boto
text="Hello World!"
styleClass="label-mine"/> (Figura 9) , e quando o boto for pressionado a label apre-
<Label fx:id="helloLabel2" sentar outro texto(Figura 10).
text="Hello World!"/>
<Label fx:id="helloLabel3" Esta a seco relevante do FXML:
text="Hello World!"/>

</VBox> <VBox xmlns:fx="http://javafx.com/fxml/1"


fx:controller=".HelloWorldController"
alignment="CENTER">
<Label
Logo partida visvel que a descrio da UI mais fx:id="helloLabel1"
clara e a sua definio mais legvel. text="Hello World!"
styleClass="label-mine"/>
Os import statements, semelhana do Java, indicam o <Button text="Click"
package e o controlo que utilizado ao longo do ficheiro. fx:id="clickButton"
onAction="#clickButtonEvent"/>
O VBox o pane que utilizei e de notar a instruo </VBox>
fx:controller (cujo o nome da classe foi alterado para ser leg-
vel). Cada ficheiro FXML tem um e um nico controle e para E a implementao do Controller:
identificar os controlos utilizado o fx:id.
public class HelloWorldController
As restantes linhas apenas caracterizam cada um dos implements Initializable {
controlos utilizados. @FXML private Label helloLabel1;
@FXML private Button clickButton;

24
A PROGRAMAR

JAVAFX: PASSOS SEGUINTES

Simples e eficaz J
@Override
public void initialize( Concluso
URL location,
ResourceBundle resources) A partir de agora uma questo de tornar as aplica-
{ es mais funcionais e a satisfazer as necessidades.
// TODO Auto-generated method stub
} JavaFX demonstrou-se ser uma agradvel surpresa,
com as suas componentes MVC que ajudam a simplificar e a
@FXML
public void clickButtonEvent() { manter as aplicaes. A separao da aplicao em trs
Date date = new Date(); camadas (estilos/css, FXML/UI, Controller/Event Handler)
helloLabel1.setText(date.toString()); tornou-se um thumbs-up para mim, tornando o cdigo da
}
} aplicao bastante legvel e simptica de se manter.
Depois de se dominar o FXML (e s depois mesmo),
recomendo a utilizao do SceneBuilder para acelerar o de-
senvolvimento da UI.
Referncias

http://www.oracle.com/technetwork/java/
javase/downloads/javafxscenebuilder-info-
2157684.html

https://dominiks.gitbooks.io/javafx/content/
i18n/fxmlbundles.html

http://www.javafxtutorials.com/tutorials/
switching-to-different-screens-in-javafx-and-
fxml/

https://docs.oracle.com/javase/8/javafx/user-
Figura 9: FXML with Controller interface-tutorial/

https://docs.oracle.com/javase/8/javafx/api/

https://docs.oracle.com/javase/8/javafx/get-
started-tutorial/

http://docs.oracle.com/javase/8/javafx/layout-
tutorial/index.html

http://code.makery.ch/library/javafx-8-tutorial/

Figura 10: FXML with Controller clicked

AUTOR
Escrito por Nuno Cancelo

Curioso por natureza e engenheiro informtico por formao. Desde muito cedo me despertou o interes-
se pelos computadores e informtica com o famoso Spectrum. Tenho um gosto peculiar por aprender
novas coisas frequentemente mesmo que no venha a trabalhar com elas e optimizar os sistemas au-
mentando a sua performance.

25
A PROGRAMAR
Um bot para Telegram com o Jogo da velha (Jogo do Galo).

Num mundo com tantas aplicaes de chat instantneo,


outros pedidos.
o Telegram destaca-se pela rica API que disponibiliza para
criao de bots. Os bots so pequenos programas que podem Em Python 3.5, a programao assncrona teve
interagir com os utilizadores e prestar servios, como executar melhorarias importantes, principalmente em relao
comandos, gerir arquivos ou imagens e at mesmo propor sintaxe. Podemos usar async def para criar uma nova co-
jogos! rotina assncrona e await para esperar a sua execuo.
Veremos mais no cdigo do bot em si. Mas para responder
H j algum tempo que a comunidade Python explora
pergunta desta seco, assncrono para melhorar a
bibliotecas como a Telebot e mais recetemente, a Telepot.
utilizao do processador e responder a vrios jogadores,
Embora a diferena no nome das duas seja apenas uma letra,
alternando entre eles durante o processamento de entra/
o desenho da Telepot parece-me mais robusto e o melhor de
sada, sem os fazer esperar. Como hoje pagamos instncias
tudo: integra chamadas assncronas!
na Amazon, Google Compute Engine ou Azure por hora,
O objetivo deste tutorial mostrar como criar um bot executar o mximo de pedidos com o mnimo de instncias
assncrono, usando a Telepot em Python 3.6. Ele divido em uma presso financeira importante para o programador. A
quatro partes: por que assncrono? obteno da chave para programao assncrona uma alternativa para aliviar esta
rodar o bot, criao do bot, o jogo da velha em si (com presso, sem aumentar a dificuldade de desenvolvimento da
minimax). soluo em si.
Porqu assncrono? Obteno da chave
Sendo um grande f de programao assncrona, no Em primeiro lugar, se ainda no conhece o Telegram,
poderia perder a oportunidade de escrever um bot assncrono. faa o download em https://telegram.org/. Podemos instal-lo
Mas porqu assncrono? no telefone ou simplesmente criar uma conta para utilizar na
web. Basta seguir as instrues do site.
A programao assncrona veio para simplificar a vida
de programadores que no querem e que no precisam de Para criar um novo bot, devemos falar com o
usar threads. Ela extremamente til quando a aplicao BotFather, um bot gerenciador de bots do Telegram. este
passa grandes perodos de tempo espera de uma resposta bot que vai criar um novo bot e uma chave de acesso que
de um dispositivo de entrada ou sada, como a rede. A ideia da precisamos de obter para usar a API. Podemos falar com o
programao assncrona dividir o programa em tarefas. Cada BotFather clicando no link: https://telegram.me/botfather ou
tarefa executada por um loop de eventos, fornecido pela procurando por @BotFather.
biblioteca que responsvel por ativar e desativar tarefas.
Quando uma tarefa precisa de executar uma outra tarefa
assncrona, ela simplesmente pede ao loop para interromper a
sua prpria execuo e retornar apenas quando a outra tarefa
tiver terminado. Este ciclo de ativao e desativao se repete
at a concluso de nosso programa. A grande vantagem que
o processador no fica parado espera de uma resposta da
rede, de um arquivo ou da base de dados. Desta forma, vrios
pedidos podem ser atendidas simultaneamente e tudo isto sem
usar threads. Embora a programao assncrona no substituia
a programao paralela em todos os casos, esta simplifica
enormemente a escrita dos programas que no precisam de se
preocupar com locking ou concorrncia de acesso.
No caso de um bot, vrios utilizadores do Telegram
podem jogar ao mesmo tempo. Para melhorar a utilizao do
processador, o melhor escrever um bot assncrono que vai
responder aos comandos do jogo, mas sem bloquear um
jogador quando outro est simplesmente espera de receber a
resposta do bot. Isto possvel porque o bot utiliza chamadas
REST via http para comunicar com o Telegram. Assim sendo,
os novos comandos chegam pela rede e as suas respostas
tambm so enviadas em requisies http, criando uma tima
oportunidade de suspender a execuo durante a transmisso
e recepo de comandos e libertando o bot para responder a

26
A PROGRAMAR

UM BOT PARA TELEGRAM COM O JOGO DA VELHA (JOGO DO GALO).

Uma vez com a tela de chat aberta com o BotFather, o novo link para aceder ao nosso bot pela web. No meu
digitamos o comando: caso, o bot chama-se velha_bot. O que procuramos a
chave para aceder API. Neste caso, a chave para novo bot
/newbot ser mostrada aps: Use this token to access the HTTP
API. Eu pintei minha chave de preto, mas dever aprecer
No nos podemos esquecer de digitar Enter no fim da
uma string com nmeros e letras. Copiamos esta linha e
linha.
guardamso num local seguro pois vamos precisar da chave
para poder usar a API. A chave parece-se com:
934802948:AODJcjoijcijaoAISDJoiajdoaijAzcWFIS
Pronto, acabamos de criar nosso bot. Agora
precisamos de um programa para traz-lo vida!
Criao do bot
Vamos comear por fazer o download do bot que
desenvolvi para este artigo. O cdigo fonte est disponvel
no GitHub. necessrio ter o git e o Python 3.6 instalados
na mquina para continuar.

Observao: como vrias distribuies de Linux ainda no


possuem a verso 3.6 disponvel nos seus gerenciadores de
pacotes, podemos tambm converter o bot para correr em
Python 3.5. As diferenas so pequenas. Apenas substitui-
mos as f-strings como f{nome} por {}.format(nome).

Se utilizarmos Windows, instalamos o git e o Python


3.6, descarregando diretamente de Python.org.
Se utilizarmos Linux (Ubuntu 16.10), instalamos o git
e o Python 3.6 com os comandos abaixo:

sudo apt update


sudo apt-get install -y make build-essential \
libssl-dev zlib1g-dev libbz2-dev \
libreadline-dev libsqlite3-dev wget \
curl llvm libncurses5-dev libncursesw5-dev \
xz-utils git curl
curl -L https://raw.githubusercontent.com/yyuu/
pyenv-installer/master/bin/pyenv-installer | bash
cat >> ~/.bash_profile <<EOF
A criao do bot feita atravs de uma conversa com export PATH="/$HOME/.pyenv/bin:$PATH"
o BotFather. A primeira coisa que ele pergunta o nome do eval "\$(pyenv init -)"
eval "\$(pyenv virtualenv-init -)"
bot. Escolhemos um novo nome e escrevemos numa nova EOF
linha. Caso o nome j esteja em uso, o bot father pedir para source ~/.bash_profile
escolhermos outro. pyenv install 3.6.0
pyenv virtualenv 3.6.0 velha
pyenv local velha
e depois descarregamos o bot com:
git clone https://github.com/lskbr/velha.git

O git deve descarregar o cdigo fonte e criar um


diretrio velha no computador.
Digitamos:
cd velha
pip install -r requirements.txt
Agora vamos precisar da chave que obtivmos do
BotFather. Substitumos o texto a vermelho pela chave.
Digitamos:
Depois de aceitar o nome do nosso novo bot, o export
BotFather exibe esta mensagem. Na segunda linha, ele mostra BOT_TOKEN=934802948:AODJcjoijcijaoAISDJoiajdoaijAzc
WFIS

27
A PROGRAMAR
UM BOT PARA TELEGRAM COM O JOGO DA VELHA (JOGO DO GALO).
e corremos o bot com: O bot responde e pergunta com qual nvel de dificul-
dade desejamos jogar. Fcil completamente aleatrio, o
python velha.py
computador vai simplesmente preencher uma posio vazia.
Pronto, o bot j deve estar a correr! Mdio e Difcil usam um algoritmo simples, mas muito inte-
ressante do qual vamos falar depois. Eu sugiro que escolha-
Vamos test-lo. Usamos a pesquisa do Telegram e pro-
mos Difcil.
curamos pelo nome do bot. No meu caso @velha_bot, mas
cada um pode substituir pelo nome do seu bot! O bot ento pergunta se queremos comear a jogar
(X) ou se queremos jogar depois do computador (O).

Vejamos que as opes anteriores foram apagadas e


que a mensagem foi substituda. Escolhemos X.

Clicamos ou tocamos em START.

28
A PROGRAMAR

UM BOT PARA TELEGRAM COM O JOGO DA VELHA (JOGO DO GALO).


Finalmente podemos jogar. Clicamos numa posio
disponvel e divertimo-nos com o jogo da velha.
Para jogar novamente, clicamos em Recomear. O bot
avisa o resultado da jogada.

ambiente. No caso, usamos os.getenv para obter o token da


varivel BOT_TOKEN. Por isso precisamos de fazer o export
durante a configurao.
Depois de obtermos o TOKEN, configuramos o log do
programa e depois o loop de eventos em:

loop = asyncio.get_event_loop()

Quando escrevemos cdigo para Python assncrono


utilizamos um loop de eventos. Este loop criado e mantido
pelo mdulo asyncio. Diferente de uma programa clssico,
um programa assncrono submete rotinas para serem execu-
tadas no loop. O loop executa apenas uma rotina de cada
vez, o que simplifica o nosso cdigo sem nos preocuparmos
com paralelismo. A grande vantagem do loop que ele pode
parar a execuo de uma rotina enquanto ela espera por um
dispositivo, ou por uma resposta da rede. Veremos em breve
como Python faz isto. A contra jogada do loop que este s
O Jogo da Velha executa uma rotina de cada vez, assim, caso uma rotina
demore demais a retornar a execuo para o loop, todo o
Agora que instalmos tudo, podemos ver como o pro-
programa ficar bloqueado!
grama foi feito! O programa ficou bem maior do que eu espera-
va, mas vamos por partes. Uma vez que temos nosso loop e o token, criamos
nosso bot com apenas uma linha!
O programa comea na linha 395, com:
bot = telepot.aio.Bot(TOKEN, loop=loop)
# Pega o token da varivel de ambiente BOT_TOKEN # Cria o bot
TOKEN = os.getenv("BOT_TOKEN")

if __name__ == "__main__": Utilizamos a teleport.aio que o mdulo da telepot


logging.basicConfig(level=logging.DEBUG, que suporta programao assncrona. Passamos o TOKEN e
format='%(asctime)s % o loop como parmetros.
(levelname)6s %(filename)s %(funcName)s:%(lineno)d
%(message)s') Finalmente criamos um objeto da classe do Jogo:
loop = asyncio.get_event_loop()
bot = telepot.aio.Bot(TOKEN, loop=loop)
# Cria o bot jogo = JogoDaVelha(bot) # Cria o jogo
jogo = JogoDaVelha(bot) # Cria o jogo
loop.create_task(jogo.stats(loop)) Passamos o bot como parmetro. Isto importante
# Cria a tarefa que limpa as jogadas velhas porque uma vez finalizada a inicializao, o loop que ir
loop.create_task(bot.message_loop({'chat': controlar a execuo do nosso programa.
jogo.chat_handler,
Agendamos a execuo de uma rotina que exibe
'callback_query': jogo.callback_query}))
try: quantas jogadas temos em memria com:
loop.run_forever()
except KeyboardInterrupt: loop.create_task(jogo.stats(loop))
pass # Cria a tarefa que limpa as jogadas velhas
Como o TOKEN no deve ser guardado no GitHub
Vejamos que crimos a tarefa (create_task) no loop,
(caso contrrio seria pblico), o programa precisa de obt-lo do

29
A PROGRAMAR
UM BOT PARA TELEGRAM COM O JOGO DA VELHA (JOGO DO GALO).
passando jogo.stats(loop). Aqui as coisas comeam a ficar O loop fica espera de eventos e executando as co-
diferentes de um programa tradicional. O mtodo jogo.stats rotinas que configurmos. No caso do bot, ele
uma co-rotina e no executado ao ser chamado. Na realida- periodicamente acede aos servidores do Telegram para
de, ele cria uma co-rotina que pode ser chamada pelo loop. O saber se h novas mensagens. Quando uma mensagem
cdigo um pouco diferente de um mtodo normal em Python. chega, ele chama jogo.chat_handler:
O mtodo stats est na linha 386:
async def chat_handler(self, msg):
async def stats(self, loop): """Processa o chat vindo do utilizador"""
"""Imprime estatsticas e limpa jogos content_type, chat_type, chat_id =
antigos""" telepot.glance(msg)
while True: logger.debug(f"Content_type:
jogadas = len(self.jogadas) {content_type} Chat type: {chat_type} Messge:
logger.info(f"Jogadas em memria: {msg}")
{jogadas}") jogo = self.pega_jogo(msg)
self.jogadas.limpa_antigas() await self.reply_markup(jogo, chat_id)
await asyncio.sleep(60, loop=loop)
Vejamos que o mtodo chat_handler foi definido com
Vejamos que ele definido com async def e no com async def, sendo uma co-rotina. Ele simplesmente recebe a
apenas def! esta mudana que faz com que este mtodo mensagem do telegram, que um grande dicionrio com
possa ser chamado pelo loop de forma assncrona. O resto do vrias informaes sobre a mensagem como: o texto da
cdigo praticamente normal, exceto a ltima linha: mensagem, quem a enviou, em que chat, quando foi
enviada, etc.
await asyncio.sleep(60, loop=loop)
O mdulo telepot tem algumas rotinas que ajudam a
Aqui aparece outra novidade, await. esta contruo trabalhar com este dicionrio, como a glance que extrai o
que torna o nosso bot assncrono especial. Quando usamos tipo do contedo, o tipo de chat e o chat_id que
await, pedimos ao loop para parar nossa co-rotina atual (criada necessitamos para responder uma mensagem.
com async def) para executar uma outra co-rotina, no caso
Quando bot chama chat_handler, ele no controla
asyncio.sleep que espera 60 segundos para retornar. impor-
nosso jogo em si, ou seja, no sabe que utilizador enviou a
tante notar que usamos o sleep de asyncio, pois time.sleep
mensagem, mas que o bot recebeu uma mensagem. O que
no uma co-rotina compatvel com o loop e se a utilizarmos,
fazer com a mensagem uma responsabilidade do nosso
todo o programa ir parar enquanto esta no retornar.
programa. Como podemos ter vrios jogos ao mesmo tempo,
Com await, pedimos a execuo de asyncio.sleep. O criamos um dicionrio com as jogadas. Cada mensagem tem
loop ento pra a execuo de stats, chama asyncio.sleep e um user_id de origem e este nmero identifica cada
volta para stats quando esta terminar. A vantagem que asyn- utilizador de Telegram de forma nica (mesmo que ele mude
cio.sleep no pra o loop, deixando-o livre para executar ou- de nome ou de handle). Desta forma, usando o user_id
tras co-rotinas. E nosso cdigo continua simples, como se esta como chave, podemos obter o jogo daquele utilizador. A
quebra de execuo no tivesse acontecido. biblioteca Telepot tem classes muito interessantes que
ajudam a manter o contexto por utilizador ou por chat, estas
A etapa seguinte a configurao do bot para chamar
classes no foram utilizadas neste exemplo, consulte a
mtodos do jogo ao receber uma mensagem ou uma resposta
documentao para mais informaes.
(click dos botes):
Chamamos ento a reply_markup, passando o jogo e
loop.create_task(bot.message_loop({'chat': o chat_id da mensgem para que o bot gere uma resposta:
jogo.chat_handler,
'callback_query': jogo.callback_query}))
async def reply_markup(self, jogo,
Da mesma forma que fizmos com o jogo.stats, vamos chat_id=None):
criar uma co-rotina que ser chamada mais tarde pelo loop. """Dependendo do estado atual do jogo,
Neste caso, passamos um dicionrio com os mtodos que que- retorna as opes disponveis"""
if jogo.tela == 0:
remos chamar quando uma mensagem de chat for recebida e markup = jogo.nivel_de_dificuldade()
para callback_query. Neste caso, a callback_query a respos- mensagem = 'Jogo da Velha - Escolha o
ta que o telegram envia quando clicamos nos botes do jogo. nvel de dificuldade'
elif jogo.tela == 1:
Depois disso, deixamos o loop controlar o nosso progra- markup = jogo.tipo_jogador()
ma: mensagem = 'X sempre joga primeiro.
Voc quer jogar como X ou O?'
elif jogo.tela == 2:
try: markup = jogo.constroi_grelha()
loop.run_forever() mensagem = jogo.mensagem or 'Jogo da
except KeyboardInterrupt: Velha'
pass if jogo.message is None and chat_id is
not None:
A execuo fica dentro de loop.run_forever(), at que a message = await self.bot.sendMessage
paremos com Control+C. (chat_id, mensagem, reply_markup=markup)

30
A PROGRAMAR

UM BOT PARA TELEGRAM COM O JOGO DA VELHA (JOGO DO GALO).


jogo.message = vel_de_dificuldade definido na linha 195. Neste caso, sim-
telepot.message_identifier(message) plesmente passamos uma lista de InlineKeyboardButton,
else: cada um com seu texto e callback_data. O texto mostrado
try:
await self.bot.editMessageText ao utilizador dentro do boto e o callback_data enviado
(jogo.message, mensagem, reply_markup=markup) pelo Telegram caso este boto seja pressionado.
except telepot.exception.TelegramError
as te: desta forma que sabemos qual a opo escolhida
pass pelo utilizador. Quando uma resposta do boto recebida, o
bot chama nosso mtodo callback_query (linha 357):
Podemos perceber que o bot pergunta o nvel de dificul-
dade, se queremos jogar com X ou O antes de nos deixar jo-
gar. Cada uma destas etapas controlada por uma proprieda- async def callback_query(self, msg):
"""Processa a resposta para as escolhas
de de cada jogo que guarda onde estamos para cada jogador. do utilizador"""
Quando o ecr 0, apresentamos as opes de escolha do query_id, from_id, query_data =
nvel de dificuldade. Quando 1, se o jogador quer jogar com telepot.glance(msg, flavor='callback_query')
X ou O, 2 o jogo em si e 3 uma mensagem que informa que a logger.debug(f'Callback Query:
{query_id}, {from_id}, {query_data}')
jogada j terminou. jogo = self.pega_jogo(msg)
logger.debug(f"Callback query:
Vejamos que jogo.message uma varavel que utiliza- utilizador: {jogo.user_id} mensagem: {msg}")
mos para guardar o identificador da mensagem. Isto neces-
srio, pois para no gerar uma nova grelha a cada resposta, if jogo.tela == 0:
self.configura_dificuldade(jogo,
editamos a mensagem precedente (a anterior substituda por query_data)
uma nova, dando a impresso de desaparecer). Assim, se jo- await self.reply_markup(jogo,
go.message nula, enviamos uma nova mensagem com self.msg_chat_id(msg))
self.bot.sendMessage. de notar que utilizamos await, pois elif jogo.tela == 1:
self.configura_primeiro_jogador(jogo,
sendMessage uma co-rotina do bot. Esta linha um pouco query_data)
especial, pois estamos a usar await e atribuindo seu resultado if jogo.computador == "X":
varivel message. Esta uma outra grande vantagem do self.joga_pelo_computador(jogo)
await self.reply_markup(jogo,
await, ele retorna os mesmos valores da co-rotina que acabou self.msg_chat_id(msg))
de executar. Neste caso, durante o tempo de envio desta men- elif query_data == "recomecar":
sagem, o loop fica livre para realizar outras tarefas. Quando jogo = self.jogadas.novo_jogo(jogo)
await self.reply_markup(jogo,
sendMessage retorna, o programa volta a executar na linha do self.msg_chat_id(msg))
await e message recebe seu retorno. Vejamos que imediata- elif len(query_data) == 1 and
mente guardamos o identificador da mensagem em jo- query_data.isdigit() and jogo.tela == 2:
go.message. Desta forma, na prxima vez, editaremos a men- posicao = int(query_data) - 1
if jogo.joga(posicao, jogo.jogador):
sagem precedente, em vez de enviar uma nova. self.verifica_jogada(jogo)
grelha = jogo.constroi_grelha()
No caso de editMessageText, trocamos o contedo da await self.bot.editMessageText
mensagem precedente pela nossa nova tela. Um tratamento (jogo.message, f"Velha: {jogo.mensagem}",
de exceo bsico realizado, pois um utilizador pode clicar reply_markup=grelha)
else:
em um jogo antigo e gerar erros (no tratados aqui para simpli- await
ficar o bot). self.bot.answerCallbackQuery(query_id,
text='Escolha outra posio')
Cada ecr do jogo composto de uma parte texto e elif jogo.tela == 3:
uma srie de botes, especificados no parmetro reply_markup await self.bot.answerCallbackQuery
de sendMessage e de editMessageText. O markup que envia- (query_id, text='Jogada terminada.
Escolha recomear para jogar de novo')
mos gerado em funo do estado atual do jogo. Vejamos
onde criamos o markup com o nvel de diculdade:
Da mesma forma que quando recebemos uma men-
sagem texto, uma mensagem de resposta dos botes rece-
def nivel_de_dificuldade(self):
"""Retorna as opes dos nveis de bida. A resposta em si vem em query_data, extrada pelo
dificuldade do jogo""" telebot.glance (ver que passamos um parmetro fla-
return InlineKeyboardMarkup vor=callback_query:
(inline_keyboard=[
[InlineKeyboardButton(text="Fcil", query_id, from_id, query_data = telepot.glance
callback_data='facil')], (msg, flavor='callback_query')
[InlineKeyboardButton(text="Mdio",
callback_data='medio')],
[InlineKeyboardButton(text="Difcil",
callback_data='dificil')]]) O query_data tem o mesmo texto que especificmos
no callback_data dos nossos botes. O resto Python tradi-
Estamos agora no cdigo da classe Velha, que guarda cional, onde verificamos o estado do jogo e executamos as
o estado do jogo para cada jogador (linha 152). O mtodo n- configuraes necessrias.

31
A PROGRAMAR
UM BOT PARA TELEGRAM COM O JOGO DA VELHA (JOGO DO GALO).
Quando estamos na tela 2 e recebemos um nmero, Utilizada para calcular a jogada do computador.
significa que o utilizador clicou na grelha. A grelha do jogo da
velha foi organizada em 9 posies, numeradas de 1 a 9. Co- O Estado contm a grelha como uma lista de
strings.
mo Python indexa a partir do zero, transformamos esta respos- Espao significa que a posio est livre.
ta num nmero inteiro e subtramos 1 para termos o ndice X ou O que o jogador j marcou esta posio.
respectivo ou a posio que ele jogou.
Grelha
Se observarmos o cdigo fonte, veremos que o estado ndices Posies
0 1 2 1 | 2 | 3
de cada jogo guardado numa lista de strings com nove ele- ---+---+---
mentos. Cada elemento representa uma posio da grelha. Um 3 4 5 4 | 5 | 6
espao em branco para posies vazias, X ou O se um dos ---+---+---
jogadores j marcou aquela posio anteriormente. 6 7 8 7 | 8 | 9
"""
Quando chamamos jogo.joga(posicao, jogo.jogador), GANHANTES = [set(x) for x in [(0, 1, 2), (3, 4,
5), (6, 7, 8),
pedimos que seja realizada uma nova marcao. Este mtodo (0, 4, 8), (6, 4,
retorna False se o utilizador j marcou esta posio e o cdigo 2),
gera uma mensagem de erro: (0, 3, 6), (1, 4,
7), (2, 5, 8)]]
await self.bot.answerCallbackQuery(query_id,
text='Escolha outra posio') def __init__(self, estado=None):
"""estado: estado inicial. Default:
branco"""
self.estado = estado or [" "] * 9
Vejamos que answerCallbackQuery mostra apenas um
overlay no Telegram e no altera a nossa mensagem em si. def jogadas_possiveis(self):
Experimentemos tentar jogar duas vezes na mesma posco """Onde podemos jogar?"""
return posicoes_de(self.estado, " ")
para ver o efeito. Vamos usar este mtodo para enviar
mensagens importantes ao utilizador, especialmente def posicoes_por_jogador(self):
mensagens de erro. """Retorna uma tupla com as posies do
jogador X e do jogador O"""
Em jogo.verifica_jogada, testamos se o jogo acabou e return (posicoes_de(self.estado, "X"),
posicoes_de(self.estado, "O"))
retornamos a nova grelha.
Este o mecanismo geral do jogo. Vejamos um pouco def ganhou(self, posicoes, jogador):
"""Verifica se um dos jogadores ganhou a
como que fizmos o computador jogar. jogada"""
s = set(posicoes)
E o computador Joga Velha for p in Velhus.GANHANTES:
if len(p - s) == 0:
O jogo da Velha muito simples e seria muito chato ter return True
que procurar outro jogador para uma jogada. Vejamos como return False
fazer o computador jogar. Usando uma tcnica chamada
def joga(self, posicao, jogador):
Minimax (https://pt.wikipedia.org/wiki/Minimax). Uma excelente """Joga pelo jogador em um posio
explicao deste algoritmo para resolver o jogo da velha pode especfica"""
ser encontrada em portugus aqui: http://www.maawko.com/ if self.estado[posicao] == " ":
blog/freecodecamp/jogo-da-velha-entendendo-o-algoritimo- self.estado[posicao] = jogador
else:
minimax/ raise ValueError(f"Posio({posicao})
invlida.")
O artigo original em Ingls pode ser lido aqui: (http://
neverstopbuilding.com/minimax). def resultado(self):
jX, jO = self.posicoes_por_jogador()
Infelizmente, o autor escreveu a soluo usando Ruby if self.ganhou(jX, "X"):
(brincadeira) e no em Python. return("X") # X Ganhou
elif self.ganhou(jO, "O"):
O mtodo consiste em gerar as jogadas possveis para return("O") # O Ganhou
elif not self.jogadas_possiveis():
cada jogador, a partir das posies ainda livres. Depois disso, return("*") # Empate sem resultado
verificamos o resultado caso jogssemos naquela posio, else:
ser que ganhamos? Perdemos? Ou empatamos? A ideia return("?") # Inconclusivo
geral atribuir um certo nmero de pontos quando ganhamos
@staticmethod
e o inverso deste nmero para o jogador oponente. def alterna(jogador):
"""Inverte o jogodor atual. X --> O e O -->
Este trabalho feito pela classe Velhus, definida na X"""
Linha 24: return "X" if jogador == "O" else "O"

class Velhus: @staticmethod


""" def melhor(result, jogador):
Classe que simula a grelha e permite calcular if jogador == "X":
as jogas possveis. return max(result.values())

32
A PROGRAMAR

UM BOT PARA TELEGRAM COM O JOGO DA VELHA (JOGO DO GALO).


else: Criamos uma nova instncia de Velhus e jogamos em
return min(result.values()) cada uma destas posies, uma de cada vez. imortante
observar que o estado de Velhus independente do estado
def proxima(self, jogador, estado, nivel=0,
nmax=3): do jogo, pois ainda estamos a verificar onde jogar, ou seja,
"""Cria um dicionrio que calcula as possi fazemos tudo isto sem alterar o estado do jogo em si.
bilidades de futuras jogadas.
jogador: jogador corrente (da vez) j = Velhus(estado[:]) # Cria um tabuleiro
estado: estado do jogo (grelha) hipottico
nivel: nivel atual de recurso, usado j.joga(possivel, jogador) # joga pelo jogador
para diminuir a dificuldade do jogo resultado = j.resultado() # verifica o resultado
nmax: nvel mximo de explorao. da jogada
Retorna caso o nvel atual atinja o mximo.
result: dicionrio com a pontuao por Cada jogada tem um resultado que pode ser vitria
resultado.
""" de X, vitria de O, empate ou indeterminado (significando
result = {} que ningum ganhou ou perdeu ainda).
# Percorre as jogadas possveis
for possivel in self.jogadas_possiveis(): Uma vez na posse do resultado, partimos para
j = Velhus(estado[:]) # Cria um exeo do minimax:
tabuleiro hipottico, a partir do estado atual.
j.joga(possivel, jogador) # joga pelo if resultado == "X" or resultado == "O":
jogador rlocal = 10 - nivel # Atribui pontos com
resultado = j.resultado() # verifica o base no nvel atual
resultado da jogada result[possivel] = rlocal if resultado == "X"
else -rlocal
if resultado == "X" or resultado == "O": elif resultado == "?" and nivel < nmax: # Como o
rlocal = 10 - nivel # Atribui resultado no final, continua a jogar
pontos com base no nvel atual outro = self.alterna(jogador)
result[possivel] = rlocal if lresult = j.proxima(outro, j.estado, nivel +
resultado == "X" else -rlocal 1, nmax)
elif resultado == "?" and nivel < nmax: result[possivel] = self.melhor(lresult,
# Como o resultado no final, continua a jogar outro) if lresult else 0
outro = self.alterna(jogador)
lresult = j.proxima(outro, Como manda o algoritmo, atribuiremos 10 pontos
j.estado, nivel + 1, nmax) para a vitria (X indica vitria do jogador X e O de seu
result[possivel] = self.melhor
(lresult, outro) if lresult else 0 oponente). Destes pontos, deduziremos o nvel para
return result penalizar os resultados que ocorrem aps multiplas jogadas.
Um detalhe importante que o resultado para o jogador X
def melhor_jogada(self, jogador, estado, dmax):
""" positivo e para O negativo, da a inverso de sinal!
Calcula qual a melhor jogada para o jogador
jogador: jogador da vez (para qual a melhor Caso o resultado seja indeterminado, chamamos
jogada ser calculada) recursivamente prximo, mas alternando o jogador para
estado: estado atual do jogo simular as duas jogadas. Notemos que passamos o novo
dmax: nvel mximo de profundidade. Usado estado (j com a nossa jogada hipottica) e incrementamos
para diminuir a dificuldade.
""" o nvel. Utilizamos o nvel para limitar a expanso do jogo e
result = self.proxima(jogador, estado, criar o nvel de dificuldade mdio (que no avalia todas as
nmax=dmax) # Quais so as possiblidades? possiblidades). Ento, avaliamos o resultado de proxima,
melhores_jogadas = []
melhor = self.melhor(result, jogador) mas com a tica do jogador oponente. Vejamos que o
mtodo melhor importantssimo, pois decide se estamos a
logger.debug(Velhus.dump_estado(estado)) maximizar ou minimizar o resultado:
logger.debug(f"Jogador={jogador}")

for posicao, resultado in result.items(): @staticmethod


if resultado == melhor: # Se esta def melhor(result, jogador):
posio tem o melhor score if jogador == "X":
melhores_jogadas.append(posicao) return max(result.values())
logger.debug(f"Melhor: {melhor} else:
{melhores_jogadas} r={resultado} return min(result.values())
posicao={posicao}")
return melhores_jogadas Como dita o algoritmo de Minimax, o jogador X
maximiza as suas jogadas e o jogador O minimiza-as!
Alguns mtodos foram removidos para poupar espao e
facilitar o entendimento. Vamos analisar o mtodo prxima. O mtodo proxima simplesmente calcula os valores
Este mtodo recebe o jogador e o estado da grelha. para todas as jogadas possveis. Desta forma, o mtodo
melhor_jogada pode decidir onde o computador vai jogar:
Ento, para cada posio ainda livre na grelha:
def melhor_jogada(self, jogador, estado, dmax):
for possivel in self.jogadas_possiveis(): result = self.proxima(jogador, estado,
nmax=dmax) # Quais so as possiblidades?

33
A PROGRAMAR
UM BOT PARA TELEGRAM COM O JOGO DA VELHA (JOGO DO GALO).
melhores_jogadas = [] cresce todo dia. Base de dados, sites, rede, tupo j pode ser
melhor = self.melhor(result, jogador) acedido de forma assncrona.
for posicao, resultado in result.items():
if resultado == melhor: # Se esta
posio tem o melhor score
melhores_jogadas.append(posicao)
return melhores_jogadas
Aplicamos novamente o mtodo melhor para filtrar a A criao do bot
melhor jogada. A diferena que o mtodo melhor_jogada
suporta vrias posies com o mesmo resultado, ou seja, feita atravs de uma
vrias posies onde o resultado igual ao mximo. As
melhores jogadas so retornadas e o computador
simplesmente escolhe uma delas aleatoriamente.
conversa com o
BotFather.
Os bots so peque-
nos programas que po- Escrever bots divertido, podem ver um outro bot
que escrevi usando a biblioteca Telebot no GitHub: https://

dem interagir com os github.com/PyNorte/pybrtelegrambot. Este bot utiliza uma


base de dados SQLite para responder a comandos e
guardar os dados dos membros do Grupo Python do Norte
utilizadores e prestar do Brasil. Embora no seja um bot assncrono, tenho certeza
que despertar a vossa curiosidade em escrever bots!
servios, como execu-
tar comandos, gerir ar-
quivos ou imagens e at
mesmo propor jogos!

Este ciclo de jogar, marcar, avaliar os resultados repete-


se at o fim da jogada.
Concluso
Espero que tenham gostado desta soluo e que se
divirtam criando outros bots para o Telegram. Cada bot nico
e apenas arranhamos a superfcie do que pode ser feito com a
Telepot. O Telegram tambm disponibiliza toda a
documentao da sua api no seu site.
Se no programa em Python, fica o convite para
conhecer esta linguagem e a sua comunidade. A programao
assncrona em Python excelente e o nmero de bibliotecas

AUTOR
Escrito por Nilo Menezes

desenvolvedor de software, especializado em programao paralela, assncrona e de sistemas distribudos. Atuou em


diversos projetos europeus como pesquisador nas reas de simulao, telefonia mvel e redes. Coordenou equipes de
desenvolvimento de software para indstrias em Manaus, Brasil. Hoje trabalha em sua empresa na Blgica, prestando
consultoria para o desenvolvimento de sistemas escalonveis e computao em nuvem. mestre em informtica e bacharel
em processamento de dados pela Universidade Federal do Amazonas. autor do livro Introduo Programao com
Python editado pela Editora Novatec e disponvel tanto no Brasil quanto em Portugal. Nilo pode ser encontrado pelo site:
https://python.nilo.pro.br ou no telegram @lskbr e https://t.me/PyCoding.

34
A PROGRAMAR

Automao do Azure com Windows PowerShell


Desired State Configuration


Hoje em dia a automao ajuda muito e extremamen- (DSC) um complemento ao PowerShell que inclui novos
te importante para alguns processos de gesto e administrati- cmdlets e recursos que permitem criar scripts de instalao,
vos. Um dos principais problemas da automao no ser configurao, manuteno ou outros autnomos como por
aceite por todos. A tecnologia no deve ser usada para substi- exemplo:
tuir ningum mas sim para ajudar.
Instalar novas aplicaes e atualizaes;
Vou mostrar como podem fazer automao com o Win-
dows PowerShell. O Windows PowerShell uma linguagem Executar Windows PowerShell scripts;
scripting da Microsoft que estava reservada aos seus produtos
mas isso mudou o PowerShell agora OpenSource e o cdigo Gerir processos e servios do sistema;
est disponvel no GitHub em https://github.com/PowerShell/ Gerir grupos e utilizadores;
PowerShell sendo assim possvel utilizar em outros sistemas
operativos da Apple e Linux. Se pretendem experimentar pri- E muito mais.
meiro tem de instalar o Dot NET Core (https://
Vou demonstrar como criar uma mquina virtual no
www.microsoft.com/net/core) e depois o Windows PowerShell
Microsoft Azure com o sistema operativo Windows Server
(https://github.com/PowerShell/PowerShell/releases/).
2012 com a funcionalidade Internet Information Services (IIS)
ativada e a firewall configurada. O script tambm funciona
com o Windows Server 2016 sendo apenas necessrio mu-
dar a imagem do sistema operativo. O script vai criar auto-
maticamente todos os recursos necessrios para a mquina
como o armazenamento, rede virtual, placa de rede e Inter-
O PowerShell j tem todas as funcionalidades da linha net Protocol (IP) pblico. Vai instalar IIS e configurar a fi-
de comandos existentes na Microsoft e a vantagem de incluir rewall na mquina virtual e as regras de segurana no Azure.
as bibliotecas e funcionalidades do Dot Net que permite criar
O Azure como plataforma um conjunto de servios
scripts de instalao, configurao e gesto de mquinas lo-
que podem ser utilizados para alojar as suas aplicaes e
cais e remotas permitindo aceder ao registo de eventos, pro-
cargas de trabalho na nuvem. O Service Management REST
cessos e servios, registry e muito mais. Alem dos comandos
API um servio web que recebe pedidos para criar, alterar
da Microsoft tambm inclui comandos do Linux que permite a
ou configurar os servios e passa os mesmos para o Micro-
um administrador de sistemas de Linux conseguir utilizar o
soft Azure Fabric Controller que toma as decises com base
Windows PowerShell, por exemplo a listagem de ficheiros.
nesses pedidos e utiliza o Azure Hypervisor para criar novas
mquinas virtuais, se necessrio, nos datacenters.
O Azure est dividido em dois modelos:

Modelo Clssico Modelo Atual

Azure Service Management Azure Resource Manage-


(ASM) ment (ARM) technology

utilizado o portal clssico utilizado o portal atual


https:// https://portal.azure.com

Exemplo da listagem de ficheiros


Os comandos de PowerShell que so invocados nos
scripts tm a denominao de command-lets (cmdlets). O run-
time do PowerShell tambm os invoca atravs das APIs do
Windows PowerShell.
O Windows PowerShell Desired State Configuration

35
A PROGRAMAR
AUTOMAO DO AZURE COM WINDOWS POWERSHELL
Vai ser utilizado o modelo ARM que introduz uma abor- ria para o sistema;
dagem para a gesto de recursos do Azure. As instncias de
servio so referidas como recursos, que podem ser armaze- Install-Module: Instala os itens da galeria;
nados em grupos de recursos, onde os servios podem ser
Publish-Module e Publish-Script: Faz o upload do
criados, geridos, acompanhados, ou podemos excluir todos os
item para galeria;
servios simultaneamente. Tudo isto permite uma gesto em
grupo em que podem monitorizar-se os servios em grupo e Register-PSRepository : Adiciona um repositrio
determinar a taxa de faturao ou recursos de servios indivi- customizado.
duais.
Para instalar os mdulos execute os seguintes
Antes de iniciar a criao do script necessrio instalar cmdlet, o sinal # representa um comentrio no script, um
primeiro os mdulos do Azure no PowerShell, que uma cole- conjunto de comentrios inicia com <# e termina com #>
o de dois mdulos Windows PowerShell que podem ser utili- todos os comentrios esto em escritos em ingls para nor-
zados para gerir servios do Azure. O mdulo mais comum malizao do script.
Service Management este permite gerir servios de instncias
no Azure. A seguinte imagem mostra alguns dos componentes # Install Azure Resource Manager module/cmdlet
contidos no Azure PowerShell Install-module AzureRM
# Install Azure Classic module/ cmdlet
Install-module Azure

Antes de iniciar a instalao execute o cmdlet Set-


ExecutionPolicy que permite alterar a segurana no sistema
para permitir correr scripts locais. Pode sempre ativar e de-
sativar esta segurana em modo administrativo ou no utiliza-
dor atual.

<#
+----------------------------------------------+
| This is a security change to your system in |
Alguns dos componentes do Azure PowerShell | order to execute local scripts. |
+-----------------------------------------------+
Pode instalar-se os mdulos do Azure de duas formas: #>
# Administrator
Instalao Grfica em https://Azure.microsoft.com/pt-pt/ Set-ExecutionPolicy -Scope Process -
downloads/ na seco PowerShell selecione Instalao ExecutionPolicy Bypass
# Current User
para Windows. Set-ExecutionPolicy -ExecutionPolicy ByPass -
Scope CurrentUser
Instalao manual execute uma linha de comandos do <#+---------------------------------------------+
Microsoft Windows, Windows PowerShell ou Windows | To reset the permissions back to default run
the following. |
PowerShell ISE para todas estas opes recomenda- +-----------------------------------------------+
do executar com privilgios administrativos. Para insta- #>
lar um mdulo utiliza-se o cmdlet Install-Module. # Administrator
Set-ExecutionPolicy -Scope Process -
Um mdulo pode ser instalado de duas formas: ExecutionPolicy Default
# Current User
Se for instalado por uma conta de administrador o m- Set-ExecutionPolicy -ExecutionPolicy Default -
Scope CurrentUser
dulo fica disponvel para todos os utilizadores e fica
instalado em [Unidade de disco local]:\Program Fi-
les\WindowsPowerShell\Modules. Com a instalao concluda j pode fazer operaes
no Azure com PowerShell e partir daqui que inicia o script
Se um utilizador no tiver privilgios administrativos de automao.
pode instalar um mdulo no seu perfil da mquina local
Antes de iniciar qualquer operao no Azure neces-
Install-Module AureRM -Scope CurrentUser. A partir do
srio fazer autenticao no servio com o cmdlet Add-
Windows 7 os mdulos ficam guardados em [Unidade
AzureRmAccount. Vai aparecer uma janela do navegador de
de disco local]:\Users\[Nome do utilizador]
internet para introduzir as credenciais da sua conta.
\Documents\WindowsPowerShell\Modules.
<#
Alm de poder instalar mdulos tambm pode remover e pes- +-----------------------------------------------+
quisar outros cmdlest disponveis: | Login Azure Resource Management |
+-----------------------------------------------+
Find-Script: Procura itens na galeria do Microsoft Po- #>
werShell (https://www.powershellgallery.com/); # -- Login Azure RM --
Add-AzureRmAccount
Save-Module e Save-Script: Guardar os itens da gale-

36
A PROGRAMAR

AUTOMAO DO AZURE COM WINDOWS POWERSHELL


Num resource group obrigatrio definir a localizao
geogrfica e a sua identificao. A Microsoft tem vrios data
centers espalhados pelo mundo pode consultar em https://
Azure.microsoft.com/pt-pt/regions/. Normalmente eu utilizo a
Europa do Norte podem existir data centres mais perto/
rpido de Portugal mas esta localizao geogrfica raramen-
te falhou. Para criar um resource group utiliza-se o cmdlet
New-AzureRmResourceGroup.

<#
+-----------------------------------------------+
| Resource Group |
+-----------------------------------------------+
#>
# -- Set the Location --
$Location = "NorthEurope"
# -- Create Resource Group --
cmdlet Add-AzureRmAccount $ResourceGroup = "PSPTLAB"
New-AzureRmResourceGroup -Name $ResourceGroup -
Aps a autenticao se tiver mais que uma subscrio Location $Location -Verbose
na sua conta necessrio selecionar a subscrio em que
pretende trabalhar. Como qualquer linguagem de programao
possvel definir variveis em PowerShell e so definidas co-
mo $NomeDaVariavel = Valor da Varivel por exemplo a
identificao da sua subscrio do Azure HDJDNHDWN
ento devia alterar a varivel $SubscriptionId = Your Subs-
criptionId para $SubscriptionId = HDJDNHDWN antes de
selecionar a subscrio.
# -- Select the subscription Azure--
$SubscriptionId = Your SubscriptionId
Select-AzureRmSubscription -SubscriptionId
$SubscriptionId
cmdlet New-AzureRmResourceGroup
Com o resource group criado podem adicionar-se os
servios. O primeiro a ser criado storage account (conta de
armazenamento) que uma das peas fundamentais num
sistema em nuvem sem um sistema de armazenamento no
consegue armazenar os registos dos servios, disco rgido
virtual de uma mquina virtual, ficheiros, e muito
mais. Ateno que no existe armazenamento ilimitado
at na nuvem h limites. Em todos os servios obrigatrio
a sua identificao e para grande parte a localizao geogr-
fica tambm necessria. Para alm destes existem vrios
nveis de servios no Azure identificado por Specific Pricing
Tier or Stock Keeping Unit (SKU) necessrio selecionar o
tipo de armazenamento que se pretende pode consultar as
cmdlet Select-AzureRmSubscription -SubscriptionId diferenas em https://Azure.microsoft.com/pt-pt/pricing/
details/storage/blobs/ o mais econmico Locally Redundant
O primeiro servio que temos de criar no Azure grupo Storage (LRS), este que vou utilizar. Para criar a conta
de resource group (grupo de recursos). Um resource group utiliza-se o cmdlet New-AzureRmStorageAccount, mas an-
um contentor de servio numa subscrio que permite tes de o fazer deve verificar-se se a identificao est a ser
armazenar os vrios servios no Azure. A vantagem que utilizada por outra pessoa com o cmdlet Get-
pode ter vrios resource groups separados pelo tipo de servi- AzureRmStorageAccountNameAvailability. A verificao
os. Por exemplo pode ter um resource group apenas para importante porque a identificao a conta nica em todo o
rede virtual um para desenvolvimento e outro para produo. universo do Azure porque pode aceder a sua conta de arma-
Isto permite separao da manuteno dos servios. Tudo o zenamento por um endereo de internet.
que fizer no resource group de desenvolvimento no vai afetar
a produo e pode definir administradores para gerir a rede <#
virtual sem que tenha acesso a outros resource groups. +-----------------------------------------------+
| Storage Account |
+-----------------------------------------------+

37
A PROGRAMAR
AUTOMAO DO AZURE COM WINDOWS POWERSHELL
<# # -- Create a Instance-level public IP address
+--------------------------------------------+ (PIP) for Network interface controller (NIC) --
| Storage Account | $PublicIp = New-AzureRmPublicIpAddress -Name
+--------------------------------------------+ "PIP" -ResourceGroupName $ResourceGroup -Location
#> $location -AllocationMethod Dynamic
# -- Set the Storage Account Name and Sku --
$StorageAccountName = "psptlabstorageaccount"
$StorageSkuName = "Standard_LRS" #Specific Pricing
Tier or Stock Keeping Unit (SKU)
# -- Verify is the name is available --
# Get-AzureRmStorageAccountNameAvailability $Stora-
geAccountName
# -- Create Storage Account --
$StorageAccount = New-AzureRmStorageAccount
-ResourceGroupName $ResourceGroup -Name cmdlet New-AzureRmPublicIpAddress
$StorageAccountName -SkuName $StorageSkuName
-Location $Location -Verbose Agora pode criar a placa de rede com o cmdlet New-
AzureRmNetworkInterface necessrio definir a identifica-
o do endereo pblico.

# -- Create NIC with PIP and Subnet --


$NIC = New-AzureRmNetworkInterface -Name "NIC"
-ResourceGroupName $ResourceGroup -Location
$location -SubnetId $Vnet.Subnets[0].Id
-PublicIpAddressId $PublicIp.Id

cmdlet New-AzureRmStorageAccount
Com o armazenamento criado vai ser criado a rede vir-
tual e gama de endereos para comunicao com os servios,
a placa de rede para a mquina virtual que est na rede virtual cmdlet New-AzureRmNetworkInterface
criada e o endereo pblico para a mquina virtual que defi-
Com a rede virtual criada pode criar a mquina virtual,
nido na placa de rede.
a criao da mesma depende todos os servios anteriores
Para criar a rede virtual necessrio primeiro criar o sem os quais no funciona. O Azure disponibiliza vrias ima-
gama do endereamento da rede com o cmdlet New- gens de sistemas operativos no s da Microsoft mas tam-
AzureRmVirtualNetworkSubnetConfig, depois pode criar a bm de outras marcas como o Red Hat, por exemplo, o utili-
rede com o cmdlet New-AzureRmVirtualNetwork e definir a zador livre de escolher o que pretende, o valor que vai pa-
subnet criada. gar, mensalmente, j inclui todo o licenciamento. Tal como a
conta de armazenamento h tambm vrios tipos de mqui-
# nas virtuais e todas elas so diferentes, pode consultar em
+-------------------------------------------------+
| Virtual Network | https://azure.microsoft.com/pt-pt/pricing/details/virtual-
+-------------------------------------------------+ machines/. Vou utilizar uma mquina Standard da srie Dv2
#> destinada a computao para fins gerais de prxima gerao
# -- Create Subnet -- com o sistema operativo Microsoft Windows Server 2012 R2
$Subnet = New-AzureRmVirtualNetworkSubnetConfig
-Name "PSPTLAB" -AddressPrefix 10.0.0.0/24 Datacenter. Para qualquer sistema operativo preciso definir
# -- Create VNet with Subnet -- uma conta de administrador e as suas credenciais de acesso
$Vnet = New-AzureRmVirtualNetwork -Name em PowerShell, pode definir de duas formas.
"PSPTLABVNet" -ResourceGroupName $ResourceGroup
-Location $location -AddressPrefix 10.0.0.0/16
-Subnet $Subnet -verbose Solicitar os dados ao utilizador com o cmdlet Get-
Credential Message e o script fica em standby at
serem inseridas as credencias.

cmdlet New-AzureRmVirtualNetwork
Com a rede virtual criada pode criar o endereo pblico
no Azure que definido como Instance-level public IP address
(PIP) o cmdlet New-AzureRmPublicIpAddress deve definir se
pretende um endereo esttico ou dinmico.
cmdlet Get-Credential

38
A PROGRAMAR

AUTOMAO DO AZURE COM WINDOWS POWERSHELL


Definir uma varivel e converter para um string protegi-
O Add-AzureRmVMNetworkInterface vai adicionar a
da com o cmlet ConvertTo-SecureString.
placa de rede criada. O Set-AzureRmVMOSDisk vai criar o
disco virtual na conta de armazenamento. Por fim para criar
a mquina virtual utiliza-se o cmdlet New-AzureRmVM defi-
nindo a configurao e localizao geogrfica.

<#
+-----------------------------------------------+
| Virtual Machine |
+-----------------------------------------------+
System.Management.Automation.PSCredential #>
# -- Virtual Machine Settings --
Como se pretende automao vai ser utilizada a segun- $VMName = "PSPTLABVM"
da opo mas se partilhar o script com algum lembre-se de $VMSize = "Standard_DS1_v2"
apagar a palavra passe, nome de utilizador e de administrao. $VMPublisherName = "MicrosoftWindowsServer"
O nome de utilizador que estou a utilizar itpro existem no- $VMPublisherOffer = "WindowsServer"
$VMSkus = "2012-R2-Datacenter"
mes que so reservados para o Azure como Admin e Root. $VMOSDiskName = "PSPTLABVMOsDisk"
Para alm das credenciais, na criao da mquina virtual vo # -- Create a PSCredential for Local
definir-se todos os servios criados anteriormente. O processo Administrator Account --
#$cred = Get-Credential -Message "Type the name
de criao mais complexo e vai ser utilizado vrios cmdlets. and password of the local administrator account."
O New-AzureRmVMConfig para criar uma configurao da # -- Create a PSCredential for Local
mquina virtual. O Set-AzureRmVMOperatingSystem para Administrator Account from a Clear Text
definir a identificao da mquina, credenciais de acesso, atua- Password --
$SecurePassword = ConvertTo-SecureString "{INSERT
lizaes automticas e outras definies. O Set- THE PASSWORD" -AsPlainText -Force
AzureRmVMSourceImage define-se a imagem que se preten- $Credential = New-Object
de utilizar; a Microsoft oferece imensas imagens. O seguinte System.Management.Automation.PSCredential
("itpro", $SecurePassword);
cmdlet permite pesquisar as imagens existentes atravs Po- # -- Create the Virtual Machine --
werShell Get-AzureRmVmImageOfferMenu pode experimen- $VM = New-AzureRmVMConfig -VMName $VMName -VMSize
tar com a opo 13, 367, 1. Nem todas as imagens esto dis- $VMSize
$VM = Set-AzureRmVMOperatingSystem -VM $VM -
ponveis em todas as regies. Windows -ComputerName $VMName -Credential
Por exemplo as mquinas virtuais da Symantec no $Credential -ProvisionVMAgent -WinRMHttp
-EnableAutoUpdate
esto disponveis no Norte da Europa. #$VM = Set-AzureRmVMOperatingSystem -VM $VM -
Windows -ComputerName $VMName -Credential
$cred -ProvisionVMAgent -EnableAutoUpdate
$VM = Set-AzureRmVMSourceImage -VM $VM -
PublisherName $VMPublisherName -Offer
$VMPublisherOffer -Skus $VMSkus -Version "latest"
$VM = Add-AzureRmVMNetworkInterface -VM $VM -Id
$NIC.Id
$VM = Set-AzureRmVMOSDisk -VM $VM -Name
$VMOSDiskName -VhdUri "https://
psptlabstorageaccount.blob.core.windows.net/vhds/
psptlabvmosdisk1.vhd" -CreateOption fromImage
New-AzureRmVM -ResourceGroupName $ResourceGroup
-Location $location -VM $VM Verbose
Imagens Symantec no norte da Europa
Ao selecionar Oeste dos EUA j tem mquinas virtuais
disponveis.

Imagens Symantec no oeste dos EUA cmdlet New-AzureRmVM

39
A PROGRAMAR
AUTOMAO DO AZURE COM WINDOWS POWERSHELL
Com a mquina configurada vai ser instado o Internet Estes so os mdulos disponveis no DSC, reco-
Information Services (IIS) por DSC. mendado que instale os que necessita para utilizar Intellisen-
se na criao dos scripts.
Para utilizar o DSC no Azure so necessrios vrios
passos. O script enviado para ser publicado no Azure, antes
de ser publicado verificado a sua configurao, apos vali-
dao o script fica publicado no Azure Automation DSC Li-
feCycle e pode ser utilizado em qualquer mquina virtual no
Azure.

O reposi-
Implemen-
trio im-
ta a confi-
O script porta e
gurao
enviado valida o
do script
para o scrip e faz
que se
reposit- a configu-
encontra
rio. rao da
no reposi-
informa-
trio
o

Os scripts podem ter mais de uma configurao e se-


rem aplicados em mais do que uma mquina. Mas, antes de
publicar, necessrio compreender a estrutura do ficheiro DSC
que constitudo por blocos.
cmdlet Get-DSCResource

Configurao, que
Configuration Config- Se usar algum destes mdulos necessrio definir a
Name
contem a identificao
{
sua importao no script a ser utilizado na mquina de desti-
da configurao.
. no. Por exemplo para definies na Firewall Import-
Ambiente da configu- DSCResource -ModuleName xNetworking. O x nos mdu-
rao param(
Parmetros que so los com o xNetworking significa experimental estes recursos
[Parameter
usados na configura- so corrigidos e monitorizados pelos autores do mdulo.
(Mandatory=$true)]
o. Este grupo
[String[]]$Param7
opcional.
) O DSC no funciona apenas no Windows Server tam-
bm funciona em mquinas clientes como o Windows 10
Implantar a configura-
o nas mquinas Node localhost Pro.
definidas. Pode ter um {
ou mais blocos.

Configurao estrutu-
ral Recurso que pretende
WindowsFeature IIS {
configurar. Pode ter
Name = "Web-Server"
um ou mais blocos. O
Ensure = "Present"
recurso a proprieda-
}
de do cmdlet Get-

WindowsFeature

foreach -parallel
($featureName in
$Name)
{
$feature = Get-
WindowsFeature -
Name $featureName
Automao de idempotntes if(($Ensure -eq
(Propriedade de uma operao de poder ser "Present") -and (! comando winver e cmdlet Get-DscLocalConfigurationManager
aplicada mais do que uma vez sem que o resulta- $feature.Installed))
do se altere) { Um dos requisitos necessrios para trabalhar com
Install-
WindowsFeature -
DSC saber qual a verso do PowerShell que est a ser
Name $featureName utilizada e pode verificar-se com o cmdlet $PSVersionTa-
}
. ble.PSVersion. O DSC foi implementado na verso 4 no Win-
} dows 10 build 14393 utilizada a verso 5.

40
A PROGRAMAR

AUTOMAO DO AZURE COM WINDOWS POWERSHELL


cmdlet PSVersionTable
O que significa que estamos a usar a
framewrok Windows Management Framework (WMF) 5 esta
framework contem o Windows Remote Management, Windows
PowerShell e Background Intelligent Transfer Service e intro-
duz o Windows PowerShell OneGet. Em 27 de janeiro de 2017
foi lanada a verso 5.1 que compatvel com o sistema oper-
ativo Windows 7, Windows 8.1, Windows Server 2008 R2, Win-
dows Server 2012, e Windows Server 2012 R2, Windows Serv-
er 2016 as novidades das nova verso so publicadas no blog
oficial da equipa https://blogs.msdn.microsoft.com/powershell e
no msdn em https://msdn.microsoft.com/en-us/powershell/.
Antes de utilizar o DSC no Windows 8 e Windows Ser-
ver 2012 R2 necessrio verificar se tem instalado a correo
KB2894179, KB2883200, e KB2894029 para instalar pode exe-
cutar o cmdlet Get-Hotfix para instalar o KB2883200 execute
Get-Hotfix Id KB2883200.
Este o contedo do ficheiro DSC para instalar o IIS.
cmdlet Get-Command
A equipa da Microsoft Windows PowerShell tem um
repositrio central no GitHuB de recursos do DSC em https://
Configurao com Configuration github.com/PowerShell/DscResources.
Ambiente da con-
identificao DSCIIS
figurao
DSCIIS. { Voltando ao script de automao a primeira tarefa a
validao e publicao, utiliza-se o cmdlet Publish-
AzureRmVMDscConfiguration . O script vai primeiro ser vali-
dado antes de ser enviado. Se o mesmo no passar a vali-
dado retorna o tipo do erro e a localizao do erro.

Implantar a confi-
gurao na pr- node "localhost"
pria mquina lo- {
cal.

Configurao cmdlet Publish-AzureRmVMDscConfiguration erro no script


estrutural WindowsFeature
IIS Por defeito todos os scirpts publicados vo estar no
{ container windows-powershell-dsc que criado automatica-
Ensure = mente, se no pretender utilizar o container por defeito pode
"Present" criar um e definir o mesmo no cmdlet. Pode consultar todos
Instalao do IIS.
Name = "Web- os ficheiros que esto no container no portal do Azure, Po-
Server"
} werShell, Visual Studio ou Explorador de Armazenamento/
} Storage Explorer compatvel com sistemas operativos Micro-
} soft, Linux e Mac que est disponvel nas transferncias na
pgina do Azure em https://azure.microsoft.com/pt-pt/
downloads/.
Guarde o ficheiro com o nome DSCIIS.ps1 na mesma
localizao do script de automao. <#
+-----------------------------------------------+
| Desired State Configuration (DSC) |
| Install Internet Information Services (IIS) |
Get-Command .\DSCIIS.ps1 | Format-List * +-----------------------------------------------+
#>

41
A PROGRAMAR
AUTOMAO DO AZURE COM WINDOWS POWERSHELL
# -- Publish DSC -- Enquanto o DSC est a ser aplicado pode monitorizar
#Remove-AzureStorageBlob -Blob DSCIIS.ps1.zip - a sua aplicao com o cmdlet Get-
Container windows-powershell-dsc -Context
$StorageContext -Verbose AzureRmVMDscExtensionStatus em que tem que definir o
Publish-AzureRmVMDscConfiguration - nome da mquina e a que grupo de recursos pertence. No
ConfigurationPath ".\DSCIIS.ps1" -ResourceGroupName pode executar esta verificao na mesma janela de Po-
$ResourceGroup -StorageAccountName $StorageAccount- werShell tem que abrir uma nova janela de linha de coman-
Name -Verbose
# -- View Published Blob File -- dos, Windows PowerShell ou PowerShell ISE. Fazer uma
#Get-AzureStorageBlob -Blob DSCIIS.ps1.zip - nova autenticao no Azure RM e executar o cmdlet.
Container windows-powershell-dsc -Context $Stora-
geContext -ErrorAction Stop $VMName = "PSPTLABVM"
$ResourceGroup = "PSPTLAB"
Get-AzureRmVMDscExtensionStatus -VMName $VMName -
ResourceGroupName $ResourceGroup -Verbose

cmdlet Get-AzureRmVMDscExtensionStatus
cmdlet Publish-AzureRmVMDscConfiguration
Com o IIS instalado na mquina virtual necessrio
Com o DSC corretamente validado e publicado pode- abrir os portos de acesso ao IIS por defeito 80 para Hyper-
mos aplicar em qualquer mquina virtual para aplicar utiliza-se text Transfer Protoco (HHTP) e 443 para Hyper Text Transfer
o cmdlet Set-AzureRmVMDscExtension necessrio definir a Protocol Secure (HTTPS). preciso definir em dois lugares
conta de armazenamento, o container onde est o script, o no Firewall da mquina virtual e na segurana no Azure
nome do script e da mquina virtual. Um ponto importante Network Security Groups (NSG).
definir a verso da extenso do DSC. Aps aplicar na mquina
necessrio atualizar a mesma. Para configurar a firewall na mquina virtual vai ser
utilizado um outro script DSC.
# -- Configure DSC in the VM --
$DSCArchiveStorageAccountName = "windows-powershell Configurao com
-dsc" configuration DSCFirewallConfig
identificao DSCFi-
$DSCExtVersion = "2.8" #Version 1.0 to 2.3 was {
rewallConfig.
retired Ambi-
Set-AzureRmVMDscExtension -ResourceGroupName ente
$ResourceGroup -VMName $VMName Tem um parmetro param
da
-ConfigurationArchiveBlob DSCIIS.ps1.zip que define qual a m- (
confi-
-ArchiveStorageAccountName quina que vai ser afe- [string[]]$NodeName = 'localhost'
gura
$StorageAccount.StorageAccountName tada. )
o
-ArchiveResourceGroupName
$StorageAccount.ResourceGroupName Importao dos mdu- Import-DSCResource -
-ArchiveContainerName $DSCArchiveStorageAccountName los DSC necessrios. ModuleName xNetworking
-ConfigurationName DSCIIS -Version $DSCExtVersion
-AutoUpdate:$true -Force
Implantar a configura-
Get-AzureRmVM -Name $VMName -ResourceGroupName o na mquina defini-
Node $NodeName
$ResourceGroup | Update-AzureRmVM do pelo parmetro.
{
# -- Remove DSC From the VM --
#Remove-AzureRmVMDscExtension -ResourceGroupName
$ResourceGroup -VMName $VMName verbose xFirewall Firewall
{
Name = "IISFirewallRule"
DisplayName = "Firewall Rule for
IIS"
Confi- Ensure = "Present"
gura Action = "Allow"
o es- Profile = ("Domain", "Private",
trutural Configurao da Fi- "Public")
rewall na mquina Direction = "OutBound"
Virtual. RemotePort = (443, "80", "8080")
LocalPort = (443, "80", "8080")
Protocol = "TCP"
Description = "Firewall Rule for
IIS"
Service = "WinRM"
}
Set-AzureRmVMDscExtension }
}

42
A PROGRAMAR

AUTOMAO DO AZURE COM WINDOWS POWERSHELL


O mtodo de aplicao exatamente igual ao anterior
DSC do IIS. O script validado se for vlido publicado e pode
ser utilizado.

#
+-------------------------------------------------+
| Desired State Configuration (DSC) |
| Firewall Open TCP Ports for IIS |
+-------------------------------------------------+
#>
# -- Install xNetworking module current user --
Install-Module -Name xNetworking -Scope CurrentUser
# -- Publish DSC --
#Remove-AzureStorageBlob -Blob DSCFirewallCon-
fig.ps1.zip -Container windows-powershell-dsc -
Context $StorageContext -Verbose
Publish-AzureRmVMDscConfiguration
-ConfigurationPath ".\DSCFirewallConfig.ps1" Mostra como as regras do NSG so processadas
-ResourceGroupName $ResourceGroup (docs.microsoft.com).
-StorageAccountName $StorageAccountName -Verbose
# -- View Published Blob File -- Antes de criar um NSG primeiro criam-se as regras
#Get-AzureStorageBlob -Blob DSCFirewallCon-
fig.ps1.zip -Container windows-powershell-dsc - de acesso s depois se cria o NSG e associado a um NIC.
Context $StorageContext -ErrorAction Stop Vo ser criadas duas regras para permitir trfego externo do
# -- Configure DSC in the VM -- protocolo HyperText Transfer rotocol (HTTP) que utiliza a
Set-AzureRmVMDscExtension -ResourceGroupName
$ResourceGroup -VMName $VMName porta 80 e Remote Desktop Protocol (RDP) para acesso re-
-ConfigurationArchiveBlob moto da mquina virtual que utiliza a porta 3389. Para criar
DSCFirewallConfig.ps1.zip as regras utiliza-se o cmdlet New-
-ArchiveStorageAccountName
$StorageAccount.StorageAccountName AzureRmNetworkSecurityRuleConfig que, como indica o
-ArchiveResourceGroupName nome a descrio da regra, os portos de origem e destino,
$StorageAccount.ResourceGroupName e a sua permisso se autoriza ou nega. Um dos pontos fun-
-ArchiveContainerName $DSCArchiveStorageAccountName damentais ao definir uma regra a sua prioridade que nu-
-ConfigurationName DSCFirewallConfig -Version
$DSCExtVersion -AutoUpdate:$true -Force merada entre 100 a 4096 a prioridade definida do menor
Get-AzureRmVM -Name $VMName -ResourceGroupName para o maior.
$ResourceGroup | Update-AzureRmVM
<#
+-----------------------------------------------+
| Azure Network Security Groups (NSG) |
+-----------------------------------------------+
#>
# -- Create NSG Rules --
$NSGRDPRule = New-
AzureRmNetworkSecurityRuleConfig -Name "rdp-rule"
-Description "Allow RDP" -Access "Allow"
-Protocol "Tcp" -Direction "Inbound" -Priority
100 -SourceAddressPrefix "Internet"
-SourcePortRange * -DestinationAddressPrefix *
-DestinationPortRange 3389
$NSGHTTPRule = New-
AzureRmNetworkSecurityRuleConfig -Name "web-rule"
-Description "Allow HTTP" -Access "Allow" -
Protocol "Tcp" -Direction "Inbound" -Priority 101
-SourceAddressPrefix "Internet" -SourcePortRange
* -DestinationAddressPrefix * -
DestinationPortRange 80

execuo do DSC para firewall da mquina virtual


cmdlet New-AzureRmNetworkSecurityRuleConfig
Com a firewall definida na mquina virtual define-se
Com as regras de acesso criadas pode associar a
agora o Azure NSG. O NSG so listas de acesso ou Access
criao do NSG, para tal utiliza-se o comando New-
Control List (ACL) que permitem ou negam o trfego exterior
AzureRmNetworkSecurityGroup que tem que definir o grupo
com o Azure de uma sub-rede da rede virtual (VNet). Como
de recursos, localizao e as regras a adicionar. Pode adici-
qualquer sistema de segurana o NSG contm dois tipos de
onar uma ou vrias regras em simultneo.
regras, regras de entrada e regras de sada e necessrio
definir as prioridades da regra.

43
A PROGRAMAR
AUTOMAO DO AZURE COM WINDOWS POWERSHELL
# -- Create NSG -- Pode fazer um filtro das regras com o cmdlet Get-
$NSG = New-AzureRmNetworkSecurityGroup - AzureRmEffectiveNetworkSecurityGroup indicando a NIC e
ResourceGroupName $ResourceGroup -Location a que grupo de recursos pretende que os resultados sejam
$Location -Name "NSG-FrontEnd" -SecurityRules
$NSGRDPRule, $NSGHTTPRule mostrados como uma tabela numa janela utilizando Out-
# -- Associate NSG to NIC -- GridView
$NIC.NetworkSecurityGroup = $NSG
Set-AzureRmNetworkInterface -NetworkInterface $NIC # -- View filtering --
#$EffNSG = Get-
AzureRmEffectiveNetworkSecurityGroup -
NetworkInterfaceName $NIC.Name -ResourceGroupName
$ResourceGroup
#$EffNSG.EffectiveSecurityRules | Sort-Object
Direction, Access, Priority | Out-GridView

cmdlet Get-AzureRmEffectiveNetworkSecurityGroup
Com as regras criadas est finalizado o script de au-
tomao e pode ser utilizado quando quiser apenas tem de
mudar as variveis existentes para o ambiente pretendido.
No entanto o powershell permite fazer muito mais,
como abrir a pgina do IIS atravs do endereo pblico de
Internet da mquina virtual. Se quiser utilizar o endereo de
Internet necessrio configurar o Fully Qualified Domain
cmdlets New-AzureRmNetworkSecurityGroup e Set- Name (FQDN) no NIC associado a mquina virtual. Pode
AzureRmNetworkInterface abrir o navegador de Internet preferencial atravs do dot Net
com [System.Diagnostics.Process]::Start() o endereo IP
Pode sempre ver o estado das regras com o cmdlet Get obtido com o cmdelt Get-AzureRmPublicIpAddress.
-AzureRmNetworkSecurityGroup a que grupo de recursos pre-
tende que os resultados sejam mostrados como uma tabela <#
+----------------------------------------------+
numa janela utilizando Out-GridView | Open VM IIS WebSite |
# -- View NetWork Security Group -- +----------------------------------------------+
#Get-AzureRmNetworkSecurityGroup -Name $NSG.Name - #>
ResourceGroupName $ResourceGroup | Sort-Object # -- Open IIS WebSite in the Default Browser
Direction, Access, Priority | Out-GridView -- $VMIP = (Get-AzureRmPublicIpAddress -Name PIP -
ResourceGroupName $ResourceGroup).IpAddress
[System.Diagnostics.Process]::Start("http://" +
$VMIP)

cmdlet Get-AzureRmNetworkSecurityGroup com Out-GridVew execuo do navegador de Internet por PowerShell

44
A PROGRAMAR

AUTOMAO DO AZURE COM WINDOWS POWERSHELL


Tambm pode abrir uma ligao de ambiente de traba-
lho remoto ou outra aplicao com Start-Process.

<#
+--------------------------------------------------
--------------+
| Open Remote Desktop Session |
+-------------------------------------------------- remoo do grupo de recursos com sucesso
--------------+
#> O nvel de segurana da conta do Azure a mesma,
# -- Launh Microsoft Terminal Server Connection
#Start-Process mstsc -ArgumentList "/V:$VMIP / nunca mantido nenhum perfil na mquina a no ser que
w:1024 /h:768" grave o seu perfil com cmdlet Save-AzureRmProfile.
Em concluso o DSC timo para automao no
apenas para administradores de sistemas mas tambm para
DevOps, administradores de bases dados e muitos mais.
Pode fazer quase tudo incluindo implementar uma atualiza-
o de segurana em vrias mquinas com o xWindowsU-
pdate o seguinte exemplo vai instalar a atualizao
KB2908279 que est na prpria mquina.

Configuration UpdateWindowsWithPath
{
Import-DSCResource ModuleName
PSDesiredStatedConfiguration, xWindowsUpdate
Node NodeName
{
xHotfix HotfixInstall
{
Ensure = "Present"
Path = "c:/temp/Windows8.1-KB2908279-v2-x86.msu"
Id = "KB2908279"
execuo do Start-Process }
}
Se pretender destruir o grupo de recurso utilizado utilize }
o cmdlet Remove-AzureRmResourceGroup indicando o nome
do grupo de recursos. O DSC no funciona apenas no Azure tambm funci-
ona em mquinas locais. O processo quase idntico, en-
<# quanto no Azure o repositrio e a implementao na mqui-
+-------------------------------------------------- na so tratados automaticamente, enquanto localmente
+ necessrio gerir o repositrio/ficheiros para serem aplicados
| Destroy module 5 demo environment |
+-------------------------------------------------+ nas mquinas remotas e a sua implementao. A vantagem
#> do Azure que trata disso tudo por ns.
# -- Warning: Delete the Resource Group
#Remove-AzureRmResourceGroup -Name $ResourceGroup - Se pretende saber mais sobre Windows PowerShell
Verbose convido a consultar o blog oficial do PowerShell em https://
blogs.msdn.microsoft.com/powershell/ , a documentao da
Microsoft em https://technet.microsoft.com/en-us/library/
bb978526.aspx e o Microsoft Script Center em https://
technet.microsoft.com/pt-pt/scriptcenter/ .
Tambm est convidado a participar na comunidade
PowerShell Portugal (https://pt-pt.facebook.com/
PowerShellPortugal/) como participante e/ou orador.

confirmao da remoo do grupo de recursos

AUTOR
Escrito por Ricardo Cabral

O Ricardo Cabral apaixonado e autodidata em tecnologia da informao com mais 13 anos de experi-
ncia em projetos, desenvolvimento e gesto de TI. Licenciou-se em Engenharia de Informtica pela
Universidade Autnoma de Lisboa. Participante ativo, voluntariado e/ou orador de reunies de comunida-
de portuguesas. Adora partilhar, conviver e aprender. O seu twitter @rramoscabral.

45
A PROGRAMAR
O Problema do casamento Estvel

utilizando o Algoritmo Gale-Shapley


Introduo cos norte-americanos, provaram matematicamente que para
cada nmero igual de homens e mulheres, sempre poss-
O problema do emparelhamento estvel (stable marria-
vel de resolver o problema do emparelhamento estvel, e
ge problem), de forma resumida o problema de encontrar um
estabelecer todas as relaes de forma estvel. Para tal
emparelhamento estvel entre dois elementos de dois conjun-
apresentaram um algoritmo que se propunha a realizar tal
tos de elementos, dada a ordem de preferncias de cada ele-
tarefa. Este algoritmo, realiza um nmero de iteraes, com
mento do conjunto.
etapas definidas. Na primeira iterao do algoritmo, cada
Este problema normalmente apresentado da seguinte elemento h, propem-se a um elemento m) do gnero opos-
forma: Dados n Reis e n Damas de um conjunto de cartas, to, que ele prefere. Por sua vez, cada elemento m) responde
cada Rei e cada Dama estabelece uma ordem de preferncia talvez ao candidato que prefere, e no a todos os outros
para cada um dos elementos opostos (reis ou damas), com candidatos. Nesta etapa, cada elemento m) fica temporaria-
quem gostaria de estabelecer um relacionamento, ou por mente emparelhado com o elemento que lhe mais preferi-
outras palavras, tomar um caf e trocar uns bytes de cdigo! do at ao momento, tal como o candidato h) fica temporaria-
Os pares so estabelecidos de forma a que os pares de ele- mente emparelhado com esse mesmo elemento m). Em to-
mentos opostos prefiram estar juntos no par estabelecido, do das as iteraes subsequentes, primeiro cada elemento h)
que estar com qualquer outro elemento. Quando no existirem no emparelhado, prope-se ao elemento m) de sua prefe-
pares que cumpram estes requisitos o conjunto de pares rncia, a quem no se tinha proposto na iterao anterior.
considerado estvel. Esta tarefa realizada independentemente do facto de o
elemento m) j estar ou no temporariamente emparelhado.
Para que um par no seja considerado estvel, as
Feita esta etapa, cada elemento m) reponde talvez se no
seguintes premissas so observveis:
estiver emparelhada nesse dado momento, ou se prefere
Um dado elemento A do primeiro conjunto de pares, esse proponente por oposio ao seu par provisrio. Caso o
prefere um elemento B do segundo conjunto de pares, elemento m) tenha preferido o novo candidato, ao seu par
ao elemento com que se encontra emparelhado, e actual, ento o candidato passa ao estado disponvel. Este
procedimento permite que cada elemento m) troque de par
O elemento B tambm prefere A, ao elemento ao qual B pelo que lhe for preferido, a cada iterao. Este processo
se encontra emparelhado. decorre at que todos os pares estejam emparelhados.

Notemos que estas duas premissas se encontram ligadas por A complexidade de execuo deste algoritmo de O
um operador e (and), o que significa que ambas tm de ser (n2) onde n o numero de elementos homens ou mulheres.
observadas para que um par seja considerado estvel. Este algoritmo garante dois resultados essenciais:

Em suma um par considerado estvel quando no Todos os pares so estabelecidos (no final no pode
existe nenhum emparelhamento (A,B) em que ambos A e B ocorrer situao nenhuma em que um par esteja de-
estivessem individualmente melhor do que que esto com o semparelhado, de tal forma que todos os homens se
par com que se encontram emparelhados num dado momento. propuseram a uma determinada mulher, num dado
momento no tempo, dado que um homem ir eventu-
Nota Importante: Neste problema existem duas classes que almente propor-se a todas as mulheres se necess-
necessitam de ser emparelhadas, uma com a outra. Caso con- rio. Situao em que cada mulher teve garantidamen-
trrio poderia ser confundido com o problema dos colegas de te pelo menos uma proposta.
quarto (stable roommates problem)
Os pares so estveis. Considerando dois persona-
gens (Pedro e Ins), esto ambos emparelhados,
Existem diversos usos quotidianos do algoritmo Gale- mas no juntos, aps todas as iteraes do algoritmo.
Shapley e do problema do emparelhamento estvel, com uma Assim sendo no ser possvel que eles se prefiram
grande abrangncia de reas de conhecimento, desde a eco- mutuamente por oposio aos seus pares estabeleci-
nomia, passando pela distribuio de alunos por cursos, distri- dos, porque num dado momento se Pedro preferiu
buio de salas de aulas por turmas e horrios, gesto de Ins, ele ter-se- proposto, antes de se propor ao seu
transplantes de rgos vivos (em uso nos EUA), etc.. par actual. Assim, se Ins o tivesse aceite a sua pro-
posta, e ainda assim no tenha terminado emparelha-
A teoria do Algoritmo da com ele, no final do algoritmo, isto significa que ela
Em 1962, David Gale e Lloyd Shapley, dois matemti- o trocou por um outro elemento de quem ela gostou

46
A PROGRAMAR

O PROBLEMA DO CASAMENTO ESTVEL UTILIZANDO O ALGORITMO GALE-SHAPLEY


mais. Assim sendo, ela no pode preferir Pedro ao seu Apesar da simplicidade do algoritmo na sua imple-
par actual. Se por algum acaso ela rejeitou a sua pro- mentao inicial, ficou provado que o resultado seria sempre
posta, muito provavelmente ela j estaria emparelhada mais vantajoso para o grupo que inicia-se a iterao (quer
com um elemento de quem ela gostaria mais do que de fossem os homens, quer fossem as mulheres)., tal como
Pedro. * podemos ver no pseudo-cdigo seguinte.

* Para os efeitos desta explicao considera-se como bug um function emparelhamentoEstavel {


Initializa todos h H e m M para livres
elemento externo ao grupo com o nome de Afonso IV, (neste while homem h livre que ainda tem uma
caso seria rei dos glitches pois a sua interveno resultaria mulher m a quem se propor{
numa falha! m = primeira mulher na lista de h para
quem h ainda no se props
If m Is livre Then
(h, m) ficam emparelhados
else algum par (h', m) j existe
if m prefere h a h'
h() 'fica livre
(h, m) ficam emparelhados
Else
(h', m) permanece emparelhados
}
}

A prova de que existe vantagem para o grupo que


inicia as propostas, pode ser obtida, recorrendo reduo
ao absurdo. Se existisse no conjunto um par (h, m) E que
se tornasse num casamento instvel, ento h teria de preferir
m noiva m com quem foi emparelhado e m teria de preferir
h ao noivo com quem ficou emparelhada. No entanto se h
prefere m a m ento h props-se a m antes de se propor a
m. Tal resultaria no facto de m s rejeitar h, na altura na
mesma altura ou posteriormente, para manter ou ficar com o
noivo que preferisse. Vejamos um exemplo de cdigo em
A verso clssica do problema do casamento estvel, que aps terem sido formados os pares, se perturba o con-
(stable marriage problem) pode traduzir-se de forma simples da junto resultante, para formar um conjunto de relacionamen-
seguinte forma: tos instveis, para posteriormente se verificar a sua estabili-
dade (cdigo em linguagem c, segundo o paradigma proce-
Sendo H = {h1, . . . , hn} e M = {m1, . . . , mn} os conjun-
dimental).
tos de homens e mulheres, um emparelhamento E uma qual-
quer funo injectiva de H em M. Informalmente, um empare- #include <stdio.h>
lhamento , neste caso, um conjunto de n casais
(monogmicos e heterosexuais). Um emparelhamento E diz-se int verbose = 0;
enum {
instvel se e s se existir um par (h, m) /E tal que h prefere burro = -1,
outro m sua parceira em E e m tambm prefere outro h ao alvin, bart, calvin, donnald, eric, farquad,
seu parceiro em E. Caso contrrio, diz-se estvel. george, hercules, iago, jasper, alice, bela,
cinderela, daisy, esmeralda, Fiona, giselle,
Considerando para efeitos de exemplo uma instancia hanna, isabela, jasmine,
em que n = 4 e as listas de preferncias se consideram orde- };
const char *nome[] = {
nadas por ordem (estritamente) decrescente da esquerda para "Alvin", "Bart", "Calvin", "Donnald",
a direita, "Eric", "Farquad", "George", "Hercules",
"Iago", "Jasper", "Alice", "Bela", "Cinderela",
h1 m4 m2 m3 m1 m1 h4 h2 h1 h3 "Daisy", "Esmeralda", "Fiona", "Giselle",
"Hanna", "Isabela", "Jasmine"
};
h2 m2 m3 m4 m1 m2 h3 h1 h4 h2 int pref[jasmine + 1][jasper + 1] = {
{ alice, esmeralda, cinderela, isabela,
jasmine, daisy, Fiona, bela, hanna, giselle },
h3 m2 m3 m4 m1 m3 h2 h3 h1 h4 { cinderela, hanna, alice, daisy, esmeralda,
Fiona, bela, jasmine, isabela, giselle },
{ hanna, esmeralda, alice, daisy, bela,
h4 m1 m3 m2 m4 m4 h3 h4 h2 h1 Fiona, isabela, giselle, cinderela, jasmine },
{ isabela, Fiona, daisy, giselle, hanna,
esmeralda, jasmine, bela, cinderela, alice },
pode-se verificar, atravs duma simples anlise de casos, que { jasmine, daisy, bela, cinderela, Fiona,
{(h1, m4), (h2, m3), (h3, m2), (h4, m1)} um emparelhamento es- esmeralda, alice, isabela, hanna, giselle },
tvel, passvel de ser obtido usando o algoritmo de Gale- { bela, alice, daisy, giselle, esmeralda,
Shapley. isabela, cinderela, jasmine, hanna, Fiona },

47
A PROGRAMAR
O PROBLEMA DO CASAMENTO ESTVEL UTILIZANDO O ALGORITMO GALE-SHAPLEY
{ giselle, esmeralda, isabela, bela, preferem-se mutuamente"
cinderela, alice, daisy, hanna, jasmine, Fiona }, " sobre o par actual.\n",
{ alice, esmeralda, hanna, Fiona, isabela, nome[noivo1], nome[pairs
cinderela, jasmine, bela, giselle, daisy }, [noivo1]], nome[noiva2], nome[pairs[noiva2]]);
{ hanna, cinderela, daisy, giselle, bela, return 1;
alice, Fiona, isabela, jasmine, esmeralda }, }
{ alice, Fiona, jasmine, giselle, esmeralda, return 0;
bela, daisy, cinderela, isabela, hanna }, }
{ bart, farquad, jasper, george, iago, alvin, int mulher_do_vizinho(int noivo1, int noivo2)
donnald, eric, calvin, hercules }, {
{ bart, alvin, calvin, farquad, george, return desejar(noivo1, pairs[noivo2]) +
donnald, iago, eric, jasper, hercules }, desejar(noivo2, pairs[noivo1]);
{ farquad, bart, eric, george, hercules, }
calvin, iago, alvin, donnald, jasper },
{ farquad, jasper, calvin, alvin, iago, int instavel()
hercules, george, donnald, bart, eric }, {
{ jasper, hercules, farquad, donnald, alvin, int i, j, bad = 0;
george, calvin, eric, iago, bart }, for (i = alvin; i < jasper; i++) {
{ bart, alvin, eric, iago, jasper, donnald, for (j = i + 1; j <= jasper; j++)
farquad, george, calvin, hercules }, if (mulher_do_vizinho(i, j)) bad = 1;
{ jasper, george, hercules, farquad, bart, }
alvin, calvin, eric, donnald, iago }, return bad;
{ george, jasper, bart, alvin, iago, donnald, }
hercules, eric, calvin, farquad },
{ iago, calvin, hercules, george, farquad, int main()
bart, alvin, eric, jasper, donnald }, {
{ eric, hercules, george, alvin, bart, int i, unparearric;
jasper, calvin, iago, farquad, donnald },
}; for (i = alvin; i <= jasmine; i++)
int pairs[jasmine + 1], propoeric[jasmine + 1]; pairs[i] = propoeric[i] = burro;
void parear(int homem, int mulher) do {
{ unparearric = 0;
pairs[homem] = mulher; for (i = alvin; i <= jasper; i++) {
pairs[mulher] = homem; if (pairs[i] != burro) continue;
if (verbose) printf("%4s emparelhado com unparearric = 1;
%4s\n", nome[homem], nome[mulher]); propoe(i, pref[i][++propoeric[i]]);
} }
} while (unparearric);
void deixar(int mulher, int homem)
{ printf("Pareando:\n");
pairs[homem] = pairs[mulher] = burro; for (i = alvin; i <= jasper; i++)
if (verbose) printf("%4s deixa %4s\n", nome printf(" %4s - %s\n", nome[i],
[mulher], nome[homem]); pairs[i] == burro ? "burro" :
} nome[pairs[i]]);
int rank(int this, int that) printf(instavel()
{ ? "Casamento no estvel\n"
int i; : "Par estvel\n");
for (i = alvin; i <= jasper && pref[this]
[i] != that; i++); printf("\n Mas se Bart e Farquad
return i; trocassem:\n");
} i = pairs[bart];
parear(bart, pairs[farquad]);
void propoe(int homem, int mulher) parear(farquad, i);
{ printf(instavel() ? "Os pares no eram
int goce = pairs[mulher]; estaveis\n" : "Pareamento estvel\n");
if (verbose) printf("%4s prope-se a %4s\n",
nome[homem], nome[mulher]); return 0;
if (goce == burro) {
parear(homem, mulher); At aqui, em todos os exemplos apresentados, no
} else if (rank(mulher, homem) < rank(mulher, utilizamos preferncias com empates. Ou seja o mesmo ele-
goce)) {
deixar(mulher, goce); mento (homem ou mulher), definir um mesmo valor de prefe-
parear(homem, mulher); rncia (rank) a dois ou mais elementos do gnero oposto.
} Caso o tivesse-mos permitido existiriam trs noes de esta-
}
bilidade. A fraca estabilidade , a super estabilidade e a alta
int desejar(int noivo1, int noiva2) estabilidade.
{
if (rank(noivo1, noiva2) < rank(noivo1, pairs Um par chamado estvel-fraco, a menos que haja
[noivo1]) && rank(noiva2, noivo1) < rank(noiva2, um par em que cada um dos elementos prefira estritamente
pairs[noiva2])) { o outro para o seu par no emparelhamento.
printf( " %4s (c/ %4s) e %4s (c/ %4s)

48
A PROGRAMAR

O PROBLEMA DO CASAMENTO ESTVEL UTILIZANDO O ALGORITMO GALE-SHAPLEY


O cientista Robert W. Irving estendeu o algoritmo de pondncia se existir. O algoritmo computa perfeita corres-
Gale-Shapley por forma a fornecer esse emparelhamento de pondncia entre o conjunto de homens e mulheres, assim,
fraca estabilidade em E(n2) onde n tamanho do problema do encontrando conjunto crtico de homens que esto envolvi-
casamento estvel (Stable Marriage Problem) . Os laos da dos com vrias mulheres. Uma vez que tais emparelhamen-
lista de preferncias de homens e mulheres so quebrados tos nunca so estveis, pois todos os pares so apagados a
arbitrariamente e as listas de preferncias so reduzidas me- sequencia de propostas ser repetida outra vez at que a
dida que o algoritmo prossegue, tal como podemos observar lista de preferncias de algum homem fique vazia, na qual
no pseudocdigo seguinte. nenhum emparelhamento super-estvel exista ou seja obti-
do. De seguida vejamos o pseudo-cdigo que encontra uma
Assign each person to be free;
while (some man m is free) do correspondncia fortemente estvel.
begin attribuir each pessoa to livre;
w := first woman on ms list; repeat
m proposes, and becomes engaged, to w; while (algum homem h is livre) do
if (some man m' is engaged to w) then for each (mulher m na cabea da lista
assign m' to be free; de h) do
for each (successor m'' of m on ws begin
list) do h propoe, and fica emparelhado, to m;
delete the pair (m'', w) for each (sucessor directo h' of h on
end; lista de m) do
output the engaged pairs, which form a stable begin
matching if (h' is emparelhado) to m then
quebrar emparelhamento;
Um emparelhamento considerado super-estvel se apagar o par (h'. m)
no existir nenhum par em que ambos os parceiros prefiram end
estritamente o outro para o seu parceiro ou seja indiferente end
if (o emparelhamento no contem um
entre eles. emparelhamento perfeito) then
begin
O mesmo cientista modificou o algoritmo para verificar encontrar o conjunto critico Z de homens
a existncia de uma correspondncia super estvel e resulta- for each (mulher m que est emparelhada
dos correspondentes a E(n2) no caso de existirem tais empare- com um homem em Z) do
lhamentos. No exemplo seguinte em pseudo-cdigo ilustrado begin
quebrar todos os emparelhamentos
este mesmo conceito. envolvendo m;
for each homem h na cauda da lista
atribuir each pessoa to livre; de m do
repeat apagar o par (h, m)
while (algum homem h is livre) do end;
for each (mulher m na cabea da lista of h) do end;
begin until (lista de algum homem is vazia) or (todos
h propeo, and fica emparelhado, to m; esto emparelhados);
for each (sucessor directo de h' of h if todos is emparelhados then
on lista de m ) do o emparelhamento is super-estavel
begin else
if (h' is emparelhado) to m then no existe emparelhamento fortemente estvel
quebrar emparelhamento;
apagar o par (h'. m);
end Ao longo das paginas anteriores, vimos trs variantes
end de implementao do algoritmo de Gale-Shapley, nomeada-
for each (mulher m que est em emparelhamento ment a clssica, a super estvel e a fortemente estvel, bem
multiplo) do
begin como a implementao deste algoritmo em linguagem c se-
quebrar todos os emparelhamentos gundo o paradigma de programao procedimental. Este
envolvendo M; algoritmo apesar de parecer qui um pouco estranho, ou
for each (homem h na cauda da lista de mesmo maador, aborrecido ou at de pouca utilidade, na
m) do
apagar o par (h. m) realidade tem utilidades bem mais amplas do que pode apa-
end; rentar numa primeira abordagem!
until (lista de algum homem is vazia) or (todos is
emparelhados); Ao longo do tempo, apareceram diversas variantes do
if todos is emparelhados then problema dos casamentos estveis, e diversas variantes
a relao de emparelhamento is um
emparelhamento super-estvel deste algoritmo e at outros algoritmos semelhantes para
else resolver problemas especficos. Dos problemas semelhantes
no existe emparelhamento super-estvel ao problema dos casamentos estveis (stable marriage pro-
blem) mais conhecidos, destacam-se o problema de atribui-
Um emparelhamento super estvel se no houver par
o (assigment problem), cujo objetivo encontrar os empa-
h, m tal que h prefira estritamente m ao seu par e m prefira
relhamentos com peso mximo, num grfico bipartido ponde-
estritamente y ao seu par ou seja indiferente entre os pares.
rado. Estas combinaes no tm de ser estveis, mas em
Robert W. Irving desenvolveu o algoritmo que verifica se existe
algumas aplicaes, um emparelhamento de ponderao
essa correspondncia fortemente estvel e produz a corres-
mxima, mais vantajoso do que um estvel.

49
A PROGRAMAR
O PROBLEMA DO CASAMENTO ESTVEL UTILIZANDO O ALGORITMO GALE-SHAPLEY
O problema dos companheiros de quarto estveis aula a conjuntos de alunos e professores para efeitos de
(stable roommates problema) similar ao problema dos casa- vigilncia de exames, etc
mentos estveis (SMP), mas difere no facto de todos os partici- Neste ultimo exemplo, apenas a titulo de curiosidade,
pantes pertencerem a um s conjunto dividido em nmeros consideremos o seguinte, cada sala, tem como propriedades
iguais. O problema dos internos/hospitais com casais, permite os lugares, a cada sala encontra-se atribudo um docente, a
que um conjunto de residentes, inclua casais, que devem ser este conjunto de pares (sala, doente) ter de ser emparelha-
emparelhados juntos, quer para o mesmo hospital, ou para o do uma turma. Utilizando este algoritmo, poderia ser automa-
mesmo par especifico de hospitais escolhidos pelo casal (por tizada a atribuio de salas para efeitos de exame a turmas
exemplo, um casal quer garantir que vo ficar juntos e no em de forma quase automtica, minimizando a quantidade de
internatos onde ficariam longe um do outro). A adio de ca- salas necessrias para o efeito.
sais ao problema dos residentes / hospitais, torna-o num pro-
blema NP-Completo (referente ao tempo polinomial). Concluso

Um caso mais portugus, possivelmente conhecido do O problema dos casamentos estveis e o algoritmo
leitor, trata-se da soluo proposta para a colocao de docen- de Gale-Shaply, podem ser aplicados a uma infinidade de
tes em Portugal para o ano letivo 2004/2005, desenvolvido reas do conhecimento e situaes quotidianas diversas. O
pela ATX para resolver o problema da colocao de professo- seu vasto uso no dia a dia, ainda que discreto, prova a im-
res nos concursos nacionais para a contratao e colucao portncia deste algoritmo desenvolvido em 1962.
de docentes nos estabelecimentos de ensino. Apesar das difi-
culdades no inicio do ano letivo o problema acabou resolvido.
Apenas por mera curiosidade de programador, de seguida
apresenta-se uma verso resumida, em pseudo-cdigo do al-
goritmo utilizado.

Considerar inicialmente tamb em livres as posicoes


iniciais dos professores que pretendem mudar de
posicao.
Colocar os professores pela ordem da lista de
graduacao, na melhor preferncia ainda livre de
cada professor (alguns professores podem car por
colocar).
if (professores que estavam inicialmente colocados
ficaram todos colocados)
{
goto end;
}
else
{
Os professores que estavam inicialmente
colocados e ficaram por colocar sao colocados
definitivamente nas suas posi coes iniciais, que
deixam de estar livres. Estes professores j nao Referencias
entram nas prximas iteracoes.
}
Repete-se a colocacao com menos estes lugares
livres. The prize in Economic Sciences 2012 (Information for
the public) Stable matching: Theory, evidence, and
Entre outras utilizaes o algoritmo Gale-Shapley, na variante practical design
destinada ao problema SMP , est disponvel como parte do
pacote matchingMarkets, da linguagem R. College Admissions and the Stability of Marriage

Este algoritmo, pode ser aplicado a diversas utilizaes, A I And Game Theory The Joy of Matching Paul
em que se tenham conjuntos que necessitem de ser empare- Harrenstein, David Manlove, Michael Wooldridge
lhados, de forma a obter-se uma melhor relao entre elemen-
tos dos conjuntos. Por exemplo a atribuio de rgos de da- Emparelhamentos, Casamentos Estveis e Algorit-
dores a pacientes que necessitem de transplante, salas de mos de Colocao de Professores

AUTOR
Escrito por Antnio C. Santos

Programar criar um novo mundo escrevendo cdigo, cumprindo os mais elementares desgnios da
vida, aprender, ensinar, criar, partilhar, melhorar e seguir. Formou-se no Instituto Politcnico de Viana
do Castelo. Membro da Comunidade Portugal-a-Programar desde Agosto de 2007, tambm membro da
Sahana Software Foundation, onde Programador Voluntrio desde 2012, actualmente exerce funes
de mentor voluntrio na plataforma MOOC Coursera . Twitter:@apocsantos

50
ELECTRNICA
O Problema da falta de GPIO Pins
Electrnica
O PROBLEMA DA FALTA DE GPIO PINS

exemplo, um CD74HC4067 obtemos 16 pinos usando 4 pi-


Introduo
nos digitais para controlo e um pino analgico para receber o
Numa esmagadora maioria dos circuitos usados em IoT sinal neste caso um valor analgico. Com base na tabela,
e em automao de uma forma geral, como o caso do Arduino/ podemos por exemplo calcular o endereo do pino 10 do
Genuino, existem algumas limitaes em termos de pinos ana- nosso multiplexador. Para tal consultamos a tabela e verifica-
lgicos, que nos podem complicar a tarefa de ligar sensores. mos que para o pino numero 10, o valor em S0 ser zero o
Por exemplo, no Arduino/Genuino Uno [IMG.1], apenas so valor em S1 ser 1, o valor em S2 ser zero e o valor em S3
disponibilizados 6 pinos analgicos que vo de A0 a A5, respe- ser um, e o valor de controlo E ser zero ou seja 01010,
tivamente. para tal colocamos a low a corrente no pino S0 a 1 no S1 a
zero no S2 a 1 no S3 e a zero e E, obtendo o valor binrio
01010 que convertido a decimal seria 10.

Esta limitao torna-se particularmente evidente quando


se pretende ligar mais do que 6 sensores analgicos, ficando
rapidamente sem pinos disponveis para ligar os sensores. Se
uma soluo poderia passar por ligar dois AVRs a comunica-
rem entre si por UART, outra mais simples, mais eficiente e
mais barata, ser utilizar um multiplexador analgico/digital,
para assim multiplicar a quantidade de pinos disponveis.

O mesmo princpio vlido para pinos digitais.

Como funciona? [TAB.1]

Um multiplexador, funciona definindo o fluxo de corren- Qualquer converso podia ter sido exemplo a escolha
te, entre um determinado ponto e um outro determinado ponto, foi sobre o nmero 10 apenas por mero acaso! De qualquer
no caso entre pinos do circuito multiplexador que esteja a ser das formas a tabela ajuda imenso na hora de fazer esta con-
utilizado. Para tal so utilizados pinos para controlar o circuito, verso e independentemente do multiplexador escolhido as
e uma tabela de verdades que permite selecionar o canal por tabelas por regra, constam na folha de dados do circuito.
onde a eletricidade deve fluir. [TAB.1] Apenas para uma referncia de consulta rpida, va-
Para o efeito de seleo da porta do multiplexador a ser mos colocar os valores para cada uma das portas devida-
utilizada, podemos calcular o valor binrio da mesma recorren- mente convertidos abaixo, sendo que para o efeito vamos
do tabela de verdades do circuito. No circuito usado para considerar o valor do pino de controlo como zero para todos
os casos.

53
Electrnica
O PROBLEMA DA FALTA DE GPIO PINS

Valor Binrio Decimal correspondente Com estas ligaes feitas, bastar ligar ao multiplexa-
dor os circuitos, componentes ou sensores a que se preten-
00000 0
da aceder, nas portas do multiplexador de C0 a C15, respeti-
10000 1 vamente. Para no complicar demasiado o exemplo iremos
usar 16 potencimetros, cada um ligado a um dos pinos do
01000 2 multiplexador, e ler cada um de forma independente.
11000 3 Para tal vamos fazer as ligaes da seguinte forma:
00100 4 Ligamos cada um dos potencimetros ao pino de 5vdc do
arduino e o gnd de cada potencimetro de igual forma ao
10100 5 gnd do arduino. Com isto temos estabelecido um fluxo de
corrente entre o arduino e cada potencimetro. Agora falta
01100 6
ligar os pinos de sada de cada potencimetro ao multiplexa-
11100 7 dor. Para tal, ligamos cada um ao respetivo pino do multiple-
xador, entre o C0 para o primeiro dos potencimetros e o
00010 8 C15 para o ultimo. [DIAG.2]
10010 9

01010 10

11010 11

00110 12

10110 13

01110 14

11110 15

Com estes dados podemos ento prosseguir para o [DIAG.2]


exemplo concreto de utilizao de um multiplexador,
Programar
transformar 1 pino de dados em 16 pinos permitindo assim
utilizar mais sensores ou circuitos sem ocupar tantas portas no O objetivo fazer a leitura de cada potencimetro,
circuito base. separadamente. Para tal o circuito deve primeiro colocar os
valores corretos em cada pino de acordo com a tabela, antes
O circuito (pinos analgicos)
de efetuar a leitura. Existem diversas formas de abordar este
Tal como referido anteriormente para este artigo usa- problema em programao, no entanto no exemplo que se
do um arduino/genuino uno ligado a um multiplexador segue, a tabela ser armazenada numa matriz, para facilitar
CD74HC4067 de 16 portas. o trabalho. Uma vez que para cada leitura preciso primeira-
mente colocar os valores corretos, em vez de colocar todo o
Para este exemplo em concreto os pinos de controlo S0
cdigo no main loop do programa, utilizamos uma funo
a S3 do multiplexador so ligados aos pinos digitais, 8, 9, 10 e
que recebe um valor inteiro, correspondente ao nmero do
11 do arduino, os pinos gnd ligados respetivamente, e o pino
pino que se pretende utilizar, e aps ter colocado os valores
vcc do multiplexador ligado ao pino +5vdc do arduino, forne-
correspondentes em cada um dos pinos de controlo, efetua a
cendo assim os 5v dc necessrios para o multiplexador funcio-
leitura, devolvendo o valore resultante. Alm disso esta abor-
nar e o pino analgico zero do arduino ao SIG do multiplexador
dagem acaba sendo til caso se pretendam usar por exem-
para comunicar dados. De notar que o pino de controlo EN do
plo protothreads.
multiplexador permanecer ligado ao GND em paralelo.
[DIAG.1]
//Pinos de controlo do multiplexer
int s0 = 8;
int s1 = 9;
int s2 = 10;
int s3 = 11;

//Pino de comunicao SIG (Signal)


int SIG_pin = 0;
//funcao setup
void setup()
{
pinMode(s0, OUTPUT);
pinMode(s1, OUTPUT);
pinMode(s2, OUTPUT);
[DIAG.1] pinMode(s3, OUTPUT);

54
Electrnica
O PROBLEMA DA FALTA DE GPIO PINS

do arduino. Assim em vez de lermos dados, regulamos


digitalWrite(s0, LOW); apenas o envio de corrente entre os 5vdc do arduino e cada
digitalWrite(s1, LOW); uma das portas do multiplexador, acendendo apenas um led
digitalWrite(s2, LOW); de cada vez.
digitalWrite(s3, LOW);
Para exemplificar uma forma diferente de utilizar a
Serial.begin(9600); tabela de verdades no cdigo desta vez no usada uma
}
funo separada, ficando todo o cdigo no loop principal
//main loop (loop principal do programa) (main loop).
void loop()
{
//percorre o ciclo e l cada um dos 16 valores //arduino code
for (int i = 0; i < 16; i++) byte controlPins[] =
{ {
Serial.print("Valor na porta "); B00000000,
Serial.print(i); B10000000,
Serial.print(" : "); B01000000,
Serial.println(readMux(i)); B11000000,
delay(1000); B00100000,
} B10100000,
} B01100000,
int readMux(int canal) B11100000,
{ B00010000,
int controlPin[] = { s0, s1, s2, s3 }; B10010000,
int muxChannel[16][4] = B11010000,
{ B00110000,
{ 0,0,0,0 }, //porta 0 B10110000,
{ 1,0,0,0 }, //porta 1 B01110000,
{ 0,1,0,0 }, //porta 2 B11110000
{ 1,1,0,0 }, //porta 3 };
{ 0,0,1,0 }, //porta 4 //setup
{ 1,0,1,0 }, //porta 5 void setup()
{ 0,1,1,0 }, //porta 6 {
{ 1,1,1,0 }, //porta 7 DDRD = B11111111;
{ 0,0,0,1 }, //porta 8 }
{ 1,0,0,1 }, //porta 9 //define o pino de output
{ 0,1,0,1 }, //porta 10 void setPin(int outputPin)
{ 1,1,0,1 }, //porta 11 {
{ 0,0,1,1 }, //porta 12 PORTD = controlPins[outputPin];
{ 1,0,1,1 }, //porta 13 }
{ 0,1,1,1 }, //porta 14 //main loop
{ 1,1,1,1 } //porta 15 void loop()
}; {
//percorre os 4 pinos for (int i = 0; i < 16; i++)
for (int i = 0; i < 4; i++) { setPin(i);
{ delay(250);
digitalWrite(controlPin[i], }
muxChannel[canal][i]); }
}
//l o valor do pino selecionado
int val = analogRead(SIG_pin);
//retorna o valor lido

}
return val;
Numa esmagado-
No exemplo acima, o objetivo era ler 16 valores analgi-
cos, provenientes de 16 potencimetros. No entanto isto ape-
ra maioria dos circui-
nas uma utilizao para um multiplexador. Por exemplo, pode-
ria ser usado para controlar 16 rels diferentes, mas no s. tos usados em IoT ()
Pode ser utilizado para por exemplo com dispositivos que co-
muniquem por uart, etc. existem algumas limi-
Desmultiplexao
taes em termos de
Para no complicar e exemplificar o mesmo efeito, mas
desta feita com pinos digitais, pode ser feito com 16 leds. pinos analgicos, que
Em termos de ligaes o circuito ser em tudo idntico
com algumas diferenas chave. Os pinos de controlo, podero nos podem complicar
ser os mesmos, no entanto o pino de dados (SIG) ser ligado
no pino de 5vdc do arduino e os leds todos eles ligados ao gnd tarefas ()

55
Electrnica
O PROBLEMA DA FALTA DE GPIO PINS

Concluso Fontes
Ao longo do artigo, mais do que apresentar um circuito SparkFun https://www.sparkfun.com/products/9056
apresentaram-se duas formas de executar tarefas idnticas
ARM mbed Developer site https://developer.mbed.org/
com cdigo diferente, bem como a multiplexao e desmultiple-
xao de portas recorrendo a um multiplexador simples e de Dan Zilinskas Motion Capture for Runners
baixo custo. A vantagem de expandir substancialmente o n-
Texas Instruments CD74HC4067 DataSheet https://
mero de portas disponveis em cada situao ajuda particular-
www.sparkfun.com/datasheets/IC/CD74HC4067.pdf
mente em circuitos com poucas entradas e sadas, como o
caso dos ATMega328, mas tambm dos ATTiny 45 e dos AT- Frontiernerds http://www.frontiernerds.com/
Tiny 85 que s dispem de 3 portas analgicas e 2 portas digi-
tais, ultrapassando assim algumas das limitaes impostas
pelos controladores.

AUTOR
Escrito por Antnio C. Santos

Programar criar um novo mundo escrevendo cdigo, cumprindo os mais elementares desgnios da
vida, aprender, ensinar, criar, partilhar, melhorar e seguir. Formou-se no Instituto Politcnico de Viana
do Castelo. Membro da Comunidade Portugal-a-Programar desde Agosto de 2007, tambm membro da
Sahana Software Foundation, onde Programador Voluntrio desde 2012, actualmente exerce funes
de mentor voluntrio na plataforma MOOC Coursera . Twitter:@apocsantos

56

COLUNAS
C# - Padro de Arquitetura SOLID
SQL Curtas - SQL Curtas #2: Dvidas Comuns
Kernel Panic -
C#
Padro de Arquitetura SOLID

Introduo no devemos modificar a classe, em vez disso uma nova


classe deve ser criada, a qual ir estender a classe anterior.
Existem diversas orientaes para programao
orientada por objectos, no entanto, neste artigo apenas iremos Vamos supor que temos uma classe chamada Cliente que
focar SOLID com exemplos em C#. tem uma propriedade FacturaNumero a qual tem um tipo
inteiro.
SOLID um acrnimo dos cinco primeiros princpios da
programao orientada a objetos e design de cdigo public class Cliente
identificados por Robert C. Martin Este mesmo acrnimo foi {
introduzido por Michael Feathers, aps observar que os cinco public int FacturaNumero
princpios poderiam se encaixar nesta palavra. {
get;
O que significa S.O.L.I.D. ? set;
}
}
S Princpio de Responsabilidade nica

O Princpio Open Close Futuramente o requisito mudar, agora FacturaNume-


ro dever ser alfanumrico em vez de apenas numero intei-
L Princpio de Substituio Liskov ro. Assim neste caso, devemos criar uma subclasse Cliente-
New com a mesma propriedade mas diferente datatype em
I - Princpio de Segregao de Interface
vez de modificar a anterior.
D Princpio de Inverso de Dependncia public class ClienteNew : Cliente
{
Que princpios ? public new String FacturaNumero
{
Princpio de Responsabilidade nica (SRP) get;
set;
Diz que cada classe dever ter responsabilidade nica. }
Uma classe no dever ter mais que uma razo para mudar. }
Exemplo: Vamos supor que crimos uma classe, Princpio de Substituio Liskov (PSL)
XmlValidator para validao XML a qual tem a responsabilida-
de de validar o XML. Se existe necessidade de atualizar o Um objeto parent dever ser capaz de substituir o seu
XML, ento dever ser criada uma classe separada para o objeto filho durante o polimorfismo em runtime.
mesmo. A classe XmlValidator no dever ser usada para atu- Por exemplo, suponhamos que temos duas classes,
alizar o XML. Cooler e Fan, ambas so heradadas de um interface comum
Vejamos como atualizar: Para isso teremos de criar uma nova chamado ISwitch o qual tem trs mtodos, On, Off e Regula-
classe. te.

public class XmlValidator


{ public class Fan : ISwitch, ILight
public void Validate() {
{ public void On()
//cdigo {
} }
} public void Off()
{
public class XmlUpdate }
{ public void Regulate()
public void DoUpdate() {
{ }
//cdigo }
} public class Bulb : ISwitch
} {
public void On()
{
}
Princpio Open Close (OCP) public void Off()
{
Dever ser aberta para extenso, mas fechada para }
modificao. Isto significa que se escrevemos uma classe e }
est a funcionar agora e bem, vem um novo requisito, ento

59
C#
PADRO DE ARQUITETURA SOLID

Cada classe ir usar um interface, o que requerido. Diferena Entre Segregao de Interface e Substituio
No existe necessidade de usar um interface que no esteja Liskov
requerido. Fan necessria nos trs mtodos por isso pode
Ambos os princpios parecem o mesmo mas existe
usar ambos os interfaces, ISwitch e ILight e Build precisa ape-
uma ligeira diferena, o ISP mais especfico que o LSP. No
nas de um dos dois mtodos para implementar On e Off assim
ISP, at existe mtodo e tambm a sua definio mas no
precisa de implementar apenas um interface chamado ISwitch.
relevante para uma classe em particular por isso, de acordo
com o ISP, precisamos de separar este mtodo num interfa-
Princpio de Segregao de Interface (ISP)
ce separado. Em LSP, o mtodo existe mas no a sua defini-
o por isso no faz sentido mant-lo no mesmo interface
Os interfaces especficos de cliente so melhores que
por isso de acordo com o LSP, precisamos de separa em
um interface de objetivo geral.
interfaces diferentes.
Suponhamos que temos um interface para clique: Princpio de Inverso de Dependncia (ISP)
public interface IClick Este declara dois pontos, o primeiro ponto que um
{ mdulo de nvel mais elevado no dever depender de um
void onClick(Object obj);
} mdulo de nvel baixo. Ambos devem depender da abstra-
o. E o segundo ponto , Abstrao no deve depender do
Com o passar do tempo, solicitam a adio de uma detalhe. O detalhe deve depender da abstrao. Por outras
nova funo onLongClick. Isto implica adicionar um novo mto- palavras, nenhum objeto deve ser criando dentro de uma
do ao interface: classe, eles devem ser passados ou injetados a partir de
fora. E onde ir receber, ser um interface em vez de uma
public interface IClick classe.
{
void onClick(Object obj); class PasseadorDeLivros
void onLongClick(Object obj); {
} ILogWriter writer = null;

Mais algum tempo passado e eis que chega um novo requeri- Public PasseadorDeLivros(ILogWriter writer)
{
mento para adicionar a funo toque e adicionamos o mtodo this.writer = writer;
no mesmo interface. }

public interface IClick public void Notify(string message)


{ {
void onClick(Object obj); writer.Write(message);
void onLongClick(Object obj); }
void onTouch(Object obj); }
}
class LogWriter
{
Neste ponto, decidimos alterar tambm o nome do in- public void Write(string message)
terface porque toque diferente de clique. Desta forma, este {
interface torna-se um problema, genrico e poludo. //Write it into a file
}
Suponhamos que alguns clientes necessitam apenas }
da funo onClick e outro precisam apenas da funo on-
interface ILogWriter
Touch, ento uma ser intil para ambos. O ISP disponibiliza a {
soluo! Divide-se o interface em dois interfaces, ITouch e void Write(string message);
IClick. O cliente que solicitou onClick pode implementar IClick, }
o que precisa do onTouch pode implementar ITouch e o que Agora para criar uma nova mensagem utilizar-se-ia o cdigo
precisa de ambos pode implementar ambos. da seguinte forma:

class Main
public interface IClick {
{ Private void AddPasseadorDeLivros
void onClick(Object obj); {
void onLongClick(Object obj); ILogWriter writer = null;
}
write = new LogWrite();
public interface ITouch PasseadorDeLivros obj = new PasseadorDeLivros
{ (write);
void onClick(Object obj); write.Notify(""message");
void onTouch(Object obj); }
} }

60
C#
PADRO DE ARQUITETURA SOLID

No caso de enviar um email em vez do logwrite, podemos in- Concluso


troduzir uma nova classe chamada MailWrite e herdar a classe
Ao longo do artigo fomos explorando os princpios de
com o mesmo interface ILogwrite. E as alteraes sero as-
SOLID (single responsibility, open-closed, Liskov substitution,
sim:
interface segregation and dependency inversion), acompa-
class Main nhados com exemplos em C#, sem detalhar nenhum dos
{ princpios, pois isso claramente sairia dos objetivos deste
Private void AddPasseadorDeLivros artigo, uma vez que se pretendia apenas uma apresentao
{
ILogWriter writer = null; simples e sucinta, de SOLID em C#. Como sempre, no de-
fendo estas regras como as melhores do mundo, mas ape-
write = new MailWrite(); nas como um bom conjunto, deixando ao cargo do leitor deci-
PasseadorDeLivros obj = new PasseadorDeLivros
(write); dir sempre o que utilizar de acordo com as suas necessida-
write.Notify(""message"); des!
}
}

AUTOR
Escrito por Antnio C. Santos

Programar criar um novo mundo escrevendo cdigo, cumprindo os mais elementares desgnios da
vida, aprender, ensinar, criar, partilhar, melhorar e seguir. Formou-se no Instituto Politcnico de Viana
do Castelo. Membro da Comunidade Portugal-a-Programar desde Agosto de 2007, tambm membro da
Sahana Software Foundation, onde Programador Voluntrio desde 2012, actualmente exerce funes
de mentor voluntrio na plataforma MOOC Coursera . Twitter:@apocsantos

61
SQL Curtas
SQL Curtas #2: Dvidas Comuns

Como mostrar registos por ordem aleatria? Compatibilidade? Consoante o SGBD, podero haver altera-
es nos comandos:
No existe uma forma "standard" de resolver este pro-
blema. Cada SGBD (Sistema de Gesto de Bases de Dados) "BEGIN" e/ou "START";
tem uma forma diferente:
"TRAN", "TRANS" e/ou "TRANSACTION";
CREATE TABLE ProgRand (A INT);
INSERT INTO ProgRand (A) VALUES (9), (8),
(7), (6), (5), (4), (3), (2), (1); "COMMIT" e "ROLLBACK" com/sem
-- Ordem natural (armazenada) "TRANSACTION" frente.
SELECT * FROM ProgRand;
-- Ordem pelo campo A ascendente O que um DEADLOCK?
SELECT * FROM ProgRand ORDER BY A ASC;
-- Ordem aleatria - SQL Server Um deadlock pode acontecer em bases de dados ou
SELECT * FROM ProgRand ORDER BY NewID(); qualquer recurso informtico. Para explicar o que um dead-
-- Ordem aleatria com apenas 3 registos - lock, fica um exemplo:
SQL Server
SELECT TOP (3) * FROM ProgRand ORDER BY NewID
(); O utilizador A comea uma transaco e escreve na
-- Ordem aleatria - Oracle tabela X. A tabela X fica bloqueada enquanto no
SELECT * FROM ProgRand ORDER BY houver COMMIT ou ROLLBACK;
DBMS_RANDOM.VALUE;
-- Ordem aleatria - MariaDB / MySQL O utilizador B comea uma transaco e escreve na
SELECT * FROM ProgRand ORDER BY RAND();
tabela Y. A tabela Y fica bloqueada enquanto no
houver COMMIT ou ROLLBACK;
O que uma TRANSACTION?
Uma transaco um bloco de comandos que suposta- O utilizador A tenta agora escrever (eventualmente
mente devem ser executados "ou todos ou nenhum". Exemplo: apenas ler) da tabela Y, mas esta est bloqueada
pelo utilizador B. Neste caso, fica a aguardar o
CREATE TABLE ProgTran (A INT); COMMIT ou ROLLBACK do utilizador B;
BEGIN TRANSACTION;
INSERT INTO ProgTran (A) VALUES (1), (2), O utilizador B tenta agora escrever (eventualmente
(3); apenas ler) da tabela X, mas esta est bloqueada
SELECT * FROM ProgTran; pelo utilizador A. Neste caso, fica a aguardar o
-- Executar outras alteraes aqui...
-- Executar aqui alguma verificao (nota: COMMIT ou ROLLBACK do utilizador A;
corre apenas ROLLBACK ou COMMIT)
-- Se erro: Ambos os utilizadores esto parados espera do
ROLLBACK; outro, e nenhum conseguir avanar.
-- Caso contrrio tudo ok!
COMMIT; Isto pode acontecer com mais do que dois utilizado-
SELECT * FROM ProgTran;
res encadeados (e.g. ABCA).
Os SGBD mais recentes tm proteces contra dead-
Aqui, se a validao efectuada (erros, questes de ne-
locks. Assim, um destes utilizadores aleatoriamente vai ser
gcio, etc.) der erro, podemos fazer ROLLBACK e os dados
considerado "deadlock victim" e a sua transaco vai ter um
inseridos "provisoriamente" so deitados fora. Apenas fazendo
ROLLBACK automtico (e o utilizador recebe um erro). O
COMMIT sero gravados.
outro ento, no tendo bloqueios alheios, pode completar a
Outro motivo para haver transaces isolar os pedidos sua tarefa.
de dois ou mais utilizadores. Se dois utilizadores executarem o
O comportamento (locks, limitaes, monitorizao,
cdigo em cima, os registos novos de "outros" utilizadores
escolha de vtima, etc.) depende sempre do SGBD.
(ainda no gravados/COMMITted), no aparecero num SE-
LECT tabela. ALTER TABLE ou DROP TABLE + CREATE TABLE?
Coloca-se no entanto uma questo: enquanto o ROLL- Antes de mais, esta pergunta no se aplica apenas a
BACK necessrio para cancelar alteraes, ser que o tabelas, mas tambm a views, stored procedures, bases de
COMMIT necessrio para garantir que o resultado efectiva- dados, logins/utilizadores e muitos outros objectos.
mente escrito? A resposta depende do SGBD (definies de
auto-commit, etc.). Em qualquer caso, sempre recomendado ALTER altera um objecto j existente;
incluir explicitamente um COMMIT no final.
DROP remove um objecto j existente (se for uma
tabela, inclui remover todos os repectivos dados);

62
SQL Curtas
SQL CURTAS #2: DVIDAS COMUNS

CREATE cria um novo objecto. nas em determinadas parties, dependendo do


SGBD):
Voltando pergunta inicial, embora ambas as formas
consigam o mesmo resultado relativamente estrutura base da TRUNCATE TABLE TabelaX;
tabela, apenas o ALTER TABLE mantm as permisses, os
ndices e constraints previamente definidas (e no expressa- DROP apaga (destroi) a tabela, incluindo todos os
mente mencionadas no CREATE TABLE), assim como os da- registos:
dos existentes.
DROP TABLE TabelaX;
Consoante existam outros objectos dependentes do
objecto a modificar, poder no ser possvel fazer DROP (note- Se o objectivo apagar todos os registos duma tabe-
se que o ALTER poder tambm estar limitado). la (mantendo a tabela), deve ser utilizado TRUNCATE e no
DELETE. Isto porque o DELETE analisa os registos um a um
Se estivermos a falar de logins/utilizadores, remover e
antes de apagar (e teoricamente, remove-os dos ndices da
recriar um utilizador apaga todas as permisses j definidas
tabela tambm um a um), enquanto o TRUNCATE remove
em objectos, a pertena a grupos/roles, etc.
numa nica operao todos os registos, primeiro da tabela e
Deve, portanto, ser escolhido o ALTER TABLE (ou depois de todos os ndices.
VIEW, etc.) sempre que possvel.
Quando a tabela tem uma coluna de identidade (auto-
number), outra diferena que o DELETE mantm o nmero
de sequncia actual, enquanto o TRUNCATE reverte o n-
Quais as diferenas entre DELETE, TRUNCATE e DROP?
mero para o valor definido incialmente (tipicamente 1). Aten-
Nada como uma tabela para esquematizar: o que este comportamento no acontece em todos os
SGBD.
Comando DELETE TRUNCATE DROP
Tipo DML DDL DDL Convm tambm desmistificar que um TRUNCATE
no necessariamente igual a um DROP TABLE + CREATE
Registos apagados Tudo ou com Tudo ou por parti- Tudo
WHERE es TABLE, j que no primeiro todas as permisses e objectos
Estrutura Mantm Mantm Remove dependentes se mantm inalterados, e que em muitos SGBD
o TRUNCATE logged e revertvel com um ROLLBACK.
Logging / Transac- Sim Depende do SGBD No
es / Rollback
Foreign Keys Respeitadas Depende do SGBD Depende do
SGBD
Triggers Executam Ignorados Ignorados
Permisses DELETE Depende do SGBD ALTER TA-
(tipicamente AL- BLE
TER TABLE)

DELETE apaga um ou mais registos (eventualmente


todos) de acordo com a respectiva condio WHERE
(ou ausncia desta). Note-se que o "FROM" opcional
em muitos SGBD mas recomendado por compatibilida-
de:

DELETE FROM TabelaX;


DELETE FROM TabelaX WHERE CampoY = Z;

TRUNCATE apaga todos os registos na tabela (ou ape-

AUTOR
Escrito por Andr Melancia

Independent Developer/DBA/Consultant. Microsoft Certified Trainer (MCT) focusing on SQL Server, Azu-
re and IoT. 17+ years' fun developing information and multimedia systems, DBA, project and IT manage-
ment. PowerShell Portugal, IT Pro Portugal and IoT Portugal communities organiser. IPv6 Por-
tugal, DNSSec Portugal and Windows Development Portugal online communities moderator. Actively
volunteering, organising, speaking or just participating at community meetings and events like SQLSatur-
days, SQLBits, SQLRelay, Maker Faire Lisbon, Arduino/Genuino Day Lisbon, Global Azure Bootcamp
Lisbon, etc. Proud uncle and food devouring expert, with dangerous ussy cat as companion.

Go to http://Andy.PT and you'll know the same as the NSA...

63
Kernel Panic
A arte, engenho, e muita diverso

A Arte O Engenho
Programar pode ser uma arte, apesar de ser uma aco Se tivermos em conta que programar, tal como mon-
e no necessariamente uma expresso no sentido mais con- tar legos, jogar jogos como o jogo do burro, tambm conhe-
servador. Nesse caso um programa seria uma forma de arte cido por Jenga, implica algum engenho, no sentido mais
e consequentemente os developers seriam artistas. alargado da definio, programar acaba aguando o enge-
nho! Para os mais nostlgicos para no usar outra palavra,
Ainda assim, isto nem sempre observado desta forma!
que se recordam do tempo dos computadores de 8 bits, co-
Numa atitude quase que patolgica ou desenquadrada pro-
mo o ZX Spectrum e o Timex TC2048 / TC2068 (estes lti-
gramar muitas vezes visto como um ofcio, uma tarefa, um
mos feitos em Portugal), certamente se lembrar do engenho
trabalho e no propriamente uma forma de arte! Por exemplo e
necessrio para carregar um jogo, ou interromper o carrega-
sem divagar muito, ensinam-se artes plsticas, expresso dra-
mento, para se fazer aquele poke fantstico que apesar de
mtica, msica, etc nas escolas, no entanto ainda no existe
pouco nobre j que o objetivo seria ter vidas infinitas no
de forma massificada a programao como matria de ensino
jogo, merecia a nobreza da ingenuidade de o executar. Os
e estudo! Ainda que parea precoce ver os mais novos a
que se lembram disto, nessa altura certamente eram crian-
aprender a programar, certo ser admitir que hoje em dia qua-
as, ou adolescentes. No lhes faltava engenho para inclusi-
se todos sabem usar um tablet, ou mesmo um computador!
ve escreverem os seus prprios jogos, em Basic, que era
interpretados pelo interpretador do computador e executa-
dos, para grande diverso!
Programar exige engenho, agua o engenho, uma
boa forma de despertar o engenho, latente em toda a gente,
para criar coisas novas!
A diverso
Ora aqui chegamos ao final! A diverso! Bem, progra-
mar, pode ser considerado tudo menos divertido! Depende
do ponto de vista de quem o diz! Na realidade, programar,
alm de ser uma arte, um engenho, tambm uma forma
de diverso! Primeiramente porque criar algo inato no ser
Logo porque no programar ? Fica a questo!
humano, que tende a criar coisas novas apenas porque se
Ainda que se diga que programar no uma arte, por diverte a faz-lo! Desde criar novos jogos, a criar novos ob-
este ou aquele motivo, vejamos, programar implica imaginar, jectos, etc Logo tudo o que feito com gosto, acaba sendo
criar, construir, transpor o pensamento abstracto para algo divertido! Quando se comea a programar algo, apenas por
real. Logo em teoria seria uma arte! desporto, ou por satisfao pessoal, ou pelo simples desa-
fio, comea um novo processo de criao e diverso, entre
Um aprendiz de guitarrista, seguindo a partitura, ou a a tentativa o erro, o estudo e a concluso! No preciso ser
tablatura com os acordes, consegue reproduzir a msica, da algo profissional, nem algo feito por profissionais nem to
mesma forma que um aprendiz de programador com um pou- pouco algo feito por adultos! Para uma criana, programar
co de pacincia consegue seguir o cdigo de outro programa- pode ser algo bastante divertido! Deixo o desafio ao leitor de
dor e reproduzir o mesmo resultado. Logo em teoria seria uma desenvolver um pseudo-jogo at mesmo em scratch e envi-
forma de arte! Ainda que esta afirmao possa ser contestada, ar um printscreen do mesmo, para vir a ser includo num
no deixa de ter lgica! Assim podemos passar para o enge- futuro kernel panic!
nho!
Aceita o desafio ?

AUTOR
Escrito por Antnio C. Santos

Programar criar um novo mundo escrevendo cdigo, cumprindo os mais elementares desgnios da
vida, aprender, ensinar, criar, partilhar, melhorar e seguir. Formou-se no Instituto Politcnico de Viana
do Castelo. Membro da Comunidade Portugal-a-Programar desde Agosto de 2007, tambm membro da
Sahana Software Foundation, onde Programador Voluntrio desde 2012, actualmente exerce funes
de mentor voluntrio na plataforma MOOC Coursera . Twitter:@apocsantos

64
Media Partners da Revista PROGRAMAR

Anlises
C# 6 - PROGRAMAO COM PRODUTIVIDADE
Introduo Programao com Python, Algoritmos e logica de progra-
mao para iniciantes
Review
C# 6 - PROGRAMAO COM PRODUTIVIDADE

Ttulo: C# 6 - PROGRAMAO COM O captulo 3, o leitor ir compreender como podemos


PRODUTIVIDADE remover grande parte das ocorrncias das chamadas string
Autores: mgicas do nosso cdigo recorrendo ao novo operador
criado: o nameof. Alm disso ir conhecer o conceito de
Editora: FCA - Editora de Informtica strings interpoladas substituindo o uso do nosso conhecido
Pginas: 103 string.Format, tornando-se mais simples a forma como com-
pomos strings nos nossos programas.
ISBN: 978-972-722-835-5
O captulo 4 apresenta melhorias desenvolvidas no
Formato: eBook uso das excepes, nomeadamente a possibilidade de usar
a expresso await no interior de blocos de catch e finally.
Alm disso, nesta nova verso foi introduzida uma nova fun-
IIntroduo cionalidade, os exception filters. Por fim, o captulo 5 d n-
fase ao Roslyn (oficialmente designado por .Net Compiler
Com o passar dos anos, cada vez mais os programa-
Platform), que trata de transformar o compilador numa API
dores consideram o C# como sendo a linguagem da platafor-
que pode ser consumida pelos nossos programas. Com a
ma .Net. A sua evoluo tem sido constante e tem contribu-
introduo desta plataforma o programador, se necessitar,
do para a simplificao e reduo do trabalho com a escrita
ter abertura de analisar e gerar cdigo.
de cdigo em .Net. As novidades desta nova verso no so
to impressionantes como a do aparecimento do Linq, por
exemplo, mas no deixam de ser teis para aumentar a efici-
ncia do programador.
Este livro que revemos nesta edio constitudo por
Com o passar
cinco captulos e explica as principais novidades introduzidas
no C# 6. dos anos, cada vez
Contedos
mais os programado-
O livro comea por apresentar 3 grandes funcionali-
dades introduzidas nesta verso do C# nomeadamente as
expression bodied members, a directiva using static e por fim
res consideram o C#
os operadores null-conditional. Com as expression bodied
members torna-se possvel a implementao de proprieda-
como sendo a lingua-
des somente de leitura e mtodos a partir de expresses
lambda. A diretiva using static permite-nos aceder aos mem-
gem da platafor-
bros estticos pblicos de um tipo a partir do contexto actual
sem que o nome desses membros tenha que ser precedido ma .Net.
pelo nome do tipo que os define. Por fim e uma das funcio-
nalidades preferidas dos programadores so as null-
conditional em que o programador vai entender como poder
validar se determinadas expresses tm o valor null sem Concluso
recorrer das condies de deciso habituais (ifs).
Um livro de leitura agradvel, bastante sucinto, base-
O captulo 2, o autor descreve a inicializao de pro- ando-se em muitos exemplos prticos para cada funcionali-
priedades implementadas automaticamente e a nova forma dade. Este livro adequa-se a programadores que j tm co-
de inicializao de dicionrios. nhecimentos slidos de C# de verses anteriores.

AUTOR
Escrito por Mnica Rodrigues

Licenciada em Engenharia Informtica e de computadores pelo ISEL. Software engineer com vasta experincia em desenvol-
vimento web nas mais variadas tecnologias, desde HTML5, AngularJs, Asp.Net Web API, Asp.Net MVC, WCF, Entity Fra-
mework e tantas outras. Gosto igualmente de desenhar solues de arquitectura aplicando padres de desenho. Gosto de
participar, entre outros, nos eventos da Microsoft, das comunidades Netponto e outras de forma a estar atenda s tecnologias
emergentes. Linkedin: https://pt.linkedin.com/in/monicascrodrigues

67
Review

Introduo Programao com Python,


Algoritmos e logica de programao para iniciantes


Ttulo: Introduo Programao com concatenao, substituio, remoo de espaos, validao
Python, Algoritmos e logica de progra- de conteudos , formatao e termina com um exemplo me
mao para iniciantes cativou a minha ateno por no ser muito comum em livros
Autores: Nilo Ney Coutinho Menezes de programao, um jogo! Incomum em literatura, mas ainda
assim bastante interessante, e envolvente de todos os as-
Editora: Novatec pectos abordados no livro at ao momento.
Pginas: 103 Nos captulos seguintes o autor continua abordando
ISBN: 978-85-7522-408-3 aspectos mais tcnicos, comeando pelas funes e os as-
pectos de mbito (scope / escopo), parmetros, empacota-
Formato: Capa soft mento e desempacotamento de parametros, passando por
Para a review desta edio, foi-me oferecido pelo funes lambda, nmeros aleatrios e por fim terminado com
autor, o livro Introduo Programao com Python, Algorit- a funo type.
mos e logica de programao para iniciantes 2 edio. No capitulo seguinte aborda ficheiros (arquivos), co-
Dividido em 12 captulos, o livro apresenta uma estru- meando pelos parmetro de linha de comandos, passando
tura bem organizada e de leitura suave, at para os maus por leitura e escrita, e algo interessante, a gerao de HTML.
adversos leitores de livros tcnicos. Comea por apresentar particularmente interessante porque desperta o leitor para
a motivao para a aprendizagem, capaz de cativar tanto outros voos com a programao em python.
iniciantes como estudantes que recorram ao livro para con- No poderia estar completo sem abordar o paradigma
solidar conhecimentos. de programao orientada a objectos, ainda que de forma
No segundo capitulo o autor tem o cuidado de expli- muito resumida, termina com um exerccio.
car como instalar o ambiente de desenvolvimento e o inter- No seria um bom livro de python, sem abordar bases
pretador, nos principais sistemas operativos para computa- de dados, e neste aspecto devo dizer que o autor se esme-
dores, evitando assim potenciais dificuldades, pois nem to- rou, dedicando um capitulo inteiro ao trabalho com bases de
dos utilizam o mesmo sistema operativo e os processos de dados, onde se focam os aspectos mais importantes dessas
instalao diferem entre sistemas operativos. Ainda neste operaes. Ao longo do capitulo os exemplos so apresenta-
capitulo, o autor apresenta de forma simples uma introduo dos recorrendo ao sgbd SQLite, que cada vez mais utiliza-
ao ambiente de desenvolvimento de python, e faculta algu- do, pela sua robustez e simplicidade.
mas recomendaes essenciais para a utilizao deste am-
biente. Quase no terminar do livro o autor, deixa alguns tpi-
cos que os leitores mais curiosos e havidos, podem aprofun-
Nos captulos seguintes, apresenta as noes ele- dar, no terminando assim de forma abrupta, mas deixando
mentares de programao, nomeadamente conceitos de o caminho preparado para uma evoluo continua, passando
variveis, input/output, instrues condicionais, ciclos pelo paradigma de programao funcional, at ao desenvol-
(repeties), etc No entanto, no artigo sexto, apresenta um vimento de jogos em python e o desenvolvimento web.
conceito que apesar de til, bastante negligenciado em
livros destinados a iniciantes, nomeadamente o conceito de Em concluso, creio que o livro seja recomendvel
coleo, incluindo listas, filas, pilhas, dicionrios, tuplas tanto para os leitores mais iniciados, como para os leitores,
(tuples), dicionrios com listas, listas de objectos, entre ou- mais experientes que desejem iniciar-se na linguagem
tros. Adicionalmente foca tambm os aspectos de ordenao python. De igual forma o livro um excelente guia para con-
e enumerao. sulta, apresentando os temas com uma linguagem suave e
captivante.
O stimo capitulo todo ele dedicado a operaes
com strings, desde a pesquisa, ao posicionamento, quebra,

AUTOR
Escrito por Antnio C. Santos

Programar criar um novo mundo escrevendo cdigo, cumprindo os mais elementares desgnios da
vida, aprender, ensinar, criar, partilhar, melhorar e seguir. Formou-se no Instituto Politcnico de Viana
do Castelo. Membro da Comunidade Portugal-a-Programar desde Agosto de 2007, tambm membro da
Sahana Software Foundation, onde Programador Voluntrio desde 2012, actualmente exerce funes
de mentor voluntrio na plataforma MOOC Coursera . Twitter:@apocsantos

68
Segurana
Segredos de Numerao
Segurana

Segredos de Numerao

Neste mundo moderno, tudo um nmero (ou vrios). Adicionalmente, no Carto de Cidado, so adiciona-
Neste artigo veremos alguns exemplos de numeraes utiliza- dos 3 novos dgitos: os primeiros dois (letras) correspondem
das em aplicaes de negcio, o seu significado, como cons- emisso individual do carto ("ZZ" o primeiro carto des-
tru-los e como valid-los. Uma explicao mais detalhada da se cidado, "ZY" o segundo, etc.), e o ltimo corresponde a
matemtica dos dgitos de controlo deixa-se para o leitor. um novo dgito de controlo, j que o dgito de controlo ante-
rior no matemticamente fivel E.g. "12345678 9 ZY6",
Um dgito de controlo (check digit), que pode ser num-
correspondente ao 2 carto pedido pelo cidado 12345678,
rico ou alfanumrico, um valor que pode integrar ou ser sepa-
com os dgitos de controlo 9 (legacy) e 6 (novo).
rado do nmero original e que valida possveis erros de intro-
duo. O erro mais habitual a troca acidental da ordem de Como calcular/validar o primeiro nmero de controlo?
dois dgitos. E.g. "xxxx12xx" or "xxxx21xx". (Exemplo em JavaScript)
Ateno: As funes de validao foram criadas de
function CalculaControlo_NIC(nic) {
acordo com a especificao e testadas apenas com uma if (nic.length > 8) {
amostragem reduzida, pelo que podem conter erros. Verificar return ("ERRO: O NIC deve ter 8
antes de utilizar. dgitos.");
}
Nmero de Identificao Civil (NIC) else if (nic.length < 8) {
nic = ("00000000" + nic).substr(-8);
O nmero presente no Carto de Cidado (ou no antigo }
Bilhete de Identidade) um nmero sequencial (actualmente
Total = 9 * nic.charAt(0)
com 8 dgitos, por haverem cerca de 10500000 cidados em + 8 * nic.charAt(1)
Portugal), com um dgito de controlo em separado. + 7 * nic.charAt(2)
+ 6 * nic.charAt(3)
O primeiro Bilhete de Identidade (nmero "1") foi emitido + 5 * nic.charAt(4)
em 1914 ao ento Presidente da Repblica, Manuel de Arria- + 4 * nic.charAt(5)
+ 3 * nic.charAt(6)
ga. + 2 * nic.charAt(7);
Controlo = 11 - (Total % 11);
if (Controlo > 9) Controlo = 0;

return (Controlo);
}

document.write(CalculaControlo_NIC("12345678"));

Nmero de Identificao Fiscal (NIF/NIPC)


O Nmero de Identificao Fiscal (NIF) partilha a nu-
merao com o Nmero de Identificao de Pessoa Colecti-
va (NIPC). um nmero de exactamente 9 dgitos numri-
cos, em que o ltimo corresponde ao dgito de controlo
(integrado no nmero), e os primeiros correspondem ao tipo
de entidade:

1X: Pessoa singular (completo durante os anos


1980s);

2X: Pessoa singular (emisso comeou no final dos


anos 1980s);

3X: Pessoa singular (reservado - seria necessrio


haver 20 milhes de cidados para utilizar);

4X: Pessoa singular (reservado - seria necessrio


haver 30 milhes de cidados para utilizar);

45: Cidados no residentes;

5X: Pessoa colectiva (NIPC);

70
Segurana

SEGREDOS DE NUMERAO
6X: Entidade pblica; return (Controlo == niss.charAt(10));
}
7X: Situaes especiais (heranas, fundos, etc.); document.write(Valida_NISS("11234567892"));

8X: Empresrio em Nome Individual (obsoleto);


Nmero de Identificao Bancria Portugus (NIB)
9X: Situaes especiais (condomnios, sociedades irre-
gulares ou sem personalidade jurdica, etc.). O NIB um cdigo com 21 dgitos numricos no for-
mato "IIII AAAA CCCC CCCC CCC KK". Os espaos so
Como o dgito de controlo faz parte do nmero, mais opcionais e omitidos na validao:
fcil evitar falhas. No entanto, o algoritmo de clculo idntico
ao do NIC. IIII: Cdigo numrico de instituio financeira (banco,
instituio de investimento, Direco Geral do Tesou-
Como validar o NIF/NIPC? (Exemplo em JavaScript) ro (0781) );
function Valida_NIF(nif) { AAAA: Cdigo do balco (referncia interna, ou zeros
if (nif.length != 9) {
return ("ERRO: O NIF deve ter 9 dgitos."); se no utilizado);
}
CCCC CCCC CCC: Nmero e tipo de conta, incluindo
Total = 9 * nif.charAt(0) quaisquer dgitos de controlo internos da instituio;
+ 8 * nif.charAt(1)
+ 7 * nif.charAt(2) KK: dgitos de controlo.
+ 6 * nif.charAt(3)
+ 5 * nif.charAt(4) Como validar o NIB? Na pgina da Wikipedia existem
+ 4 * nif.charAt(5)
+ 3 * nif.charAt(6) vrios exemplos de validadores em vrias lnguas. O exem-
+ 2 * nif.charAt(7); plo seguinte foi retirado daqui e escrito em PHP:
Controlo = 11 - (Total % 11);
if (Controlo > 9) Controlo = 0;
function isValidNib ($nib)
return (Controlo == nif.charAt(8)); {
} $result = "";
document.write(Valida_NIF("123456789")); if (strlen (intval ($nib) ) != 21)
return "NIB INVALIDO (Standard: 21
algarismos. Introduzido: " .
strlen(intval($nib)) . ")";
Nmero de Identificao da Segurana Social (NISS)
$nnib = str_split (intval ($nib) );
Este nmero tem exactamente 11 dgitos numricos,
sendo o primeiro o tipo, e o ltimo o dgito de controlo: for($i=0; $i < 19 ; $i++)
{
$result = (($result + $nnib[$i]) * 10) %
1xxxxxxxxxC: Pessoa singular, o nmero do meio 97;
atribudo internamente; }
$result = 98 - (($result * 10) % 97);
2nnnnnnnnnC: Pessoa colectiva, o nmero do meio
if($result < 10) $result = "0" + $result;
corresponde exactamente ao NIPC (9 dgitos).
Como validar o NISS? (Exemplo em JavaScript) if(substr ($nib, 19, 2) != $result)
return "NIB INVALIDO";
else
function Valida_NISS(niss) { return "NIB VALIDO";
if (niss.length != 11) { }
return ("ERRO: O NISS deve ter 11
dgitos.");
}
else if (niss.charAt(0) != 1 && niss.charAt International Bank Account Number (IBAN)
(0) != 2) {
return ("ERRO: O NISS deve comear por 1 ou O IBAN um cdigo alfanumrico de dimenso vari-
2."); vel (mximo 34 dgitos). composto pelo cdigo ISO 3166-1
} Alpha-2 do pas (e.g. "PT"), dois dgitos de controlo e de se-
Total = 29 * niss.charAt(0) guida o Nmero de Identificao Bancria nacional (que em
+ 23 * niss.charAt(1) alguns pases alfanumrico). Os espaos so opcionais e
+ 19 * niss.charAt(2) omitidos na validao.
+ 17 * niss.charAt(3)
+ 13 * niss.charAt(4) Em Portugal, e porque a validao do IBAN seme-
+ 11 * niss.charAt(5)
+ 7 * niss.charAt(6) lhante do NIB, o prefixo sempre "PT50", seguido do NIB.
+ 5 * niss.charAt(7) E.g. "PT50 IIII AAAA CCCC CCCC CCC KK".
+ 3 * niss.charAt(8)
+ 2 * niss.charAt(9); Embora tecnicamente semelhante ao NIB, a valida-
Controlo = 9 - (Total % 10); o do IBAN (dois dgitos de controlo) implica somar at va-

71
Segurana

SEGREDOS DE NUMERAO
lores bastante acima dos inteiros usuais nos computadores, n: Nmero individual do carto;
pelo que necessrio utilizar algumas artimanhas matemticas
para calcular. Do ponto de vista Portugus, basta-nos apenas C: dgito de controlo;
confirmar o prefixo "PT50" e validar o NIB conforme indicado
Como validar? Depende do emissor, do tamanho do
em cima. Por esse motivo no reproduzimos aqui o algoritmo
nmero e do algoritmo. Na maioria dos casos utilizado o
de validao do IBAN para o caso internacional.
algoritmo de Luhn.

Cdigo Postal Portugus (CP)


O cdigo postal Portugus, conforme definido pela
entidade privada CTT, tem o seguinte formato "AAAA-BBB
Local", onde:

AAAA: Cdigo postal principal (1000-9999), corres-


pondente zona de distribuio postal (no locali-
dade);

BBB: Cdigo de proximidade (001-999, 000 ou omis-


so se desconhecido), permite identificar o bairro, rua,
o prdio e/ou empresa;

Business Identifier Codes (SWIFT-BIC) Local: Denominao da zona de distribuio e proxi-


Corresponde ao identificador internacional de instituio midade (no necessariamente a localidade oficial).
financeira, cujo formato definido no ISO 9362 e gerido pela Destes, apenas necessrio "AAAA" ou "AAAA-BBB"
Society for Worldwide Interbank Financial Telecommunication sendo o "Local" ignorado no processamento automtico da
(SWIFT). um cdigo alfanumrico (tipicamente letras) que correspondncia. Quando foi criado, h quase 20 anos, os
pode ter 8 ou 11 dgitos, no formato "IIIICCLL" ou valores possveis de "AAAA-BBB" eram cerca de 160000,
"IIIICCLLbbb": estando agora perto dos 200000.

IIII: Cdigo da instituio financeira (letras no caso por- Como validar? Devem ser usadas tabelas de base de
tugus); dados com os valores possveis. No pior caso, validar ape-
nas as gamas indicadas em cima.
CC: Cdigo ISO 3166-1 Alpha-2 do pas (e.g. "PT");
Cdigos DCF e NUTS
LL: Cdigo de localizao (cidade ou outra);
Os cdigos de Distrito, Concelho e Freguesia so utilizados
bbb: Cdigo do balco, referncia interna ou no utiliza- por entidades governamentais para diversos fins, desde as
do; Finanas Comisso Nacional de Eleies. um sistema de
diviso territorial hierarquico ("DDCCFF"), onde cada compo-
E.g. "CGDIPTPL" (Caixa Geral de Depsitos - geral) nente usa 2 dgitos numricos:
E.g. "CGDIPTPLOSF" (Caixa Geral de Depsitos -
DD: Cdigo de distrito, parcialmente baseado no ISO
offshore da Madeira)
3166-2:PT
Carto Bancrio
- 01-18 = Continente;
Os cartes bancrios so compostos por um nmero varivel
- 19-22 = Obsoletos, antigos distritos das Regies
de dgitos numricos (mximo 19, tpico 16). Os primeiros dgi-
Autnomas;
tos correspondem entidade emissora e o ltimo ao dgito de
controlo (e.g. "MIII IInn nnnn nnnC"): - 31-32 = Regio Autnoma da Madeira (diviso por
ilhas);
M: Major Industry Identifier (MII). Valores tpicos so:
- 41-49 = Regio Autnoma dos Aores (diviso por
- 3: American Express, Diners Club, etc. ilhas).
- 4: Visa, Visa Electron, etc.
CC: Cdigo de concelho dentro do distrito. Actual-
- 5: MasterCard, Maestro, etc. mente existem pouco mais de 200 concelhos;

- 6: Discover Card, Maestro, etc. FF: Cdigo de freguesia dentro do concelho. Actual-
mente existem pouco mais de 3000 freguesias, mas
MIII II: Issuer Identification Number (IIN), incluindo o MII
os cdigos das extintas freguesias (originalmente
em cima, correspondente ao banco emissor;
cerca de 4100) foram mantidos.

72
Segurana

SEGREDOS DE NUMERAO
A entidade que gere o Cdigo Postal Portugus fornece Cdigo do produto (dimenso varivel at preencher
tabelas com a correspondncia entre cdigo postal e DCF. 12 dgitos): Atribudo pelo fabricante;
Os cdigos NUTS (Nomenclaturas de Unidades Territo-
Dgito de controlo (1 dgito).
riais Estatsticas) so uma classificao de zonas administrati-
vas definidas ao nvel Europeu: Alguns prefixos tm significado especial:

NUTS-0: Cada um dos pases da Unio Europeia; Comeados por 0 so cdigos UPC-A usados nos
EUA (restantes 12 dgitos iguais);
NUTS-1: Primeira diviso dentro de cada pas. Em Por-
tugal h 3 (PT1=Continente, PT2=Aores, Comeados por 2 so de distribuio restrita e podem
PT3=Madeira); ser criados por qualquer retalhista para uso local (e.g.
fruta a peso no momento);
NUTS-2: Segunda diviso. Em Portugal apenas o Conti-
nente usa esta diviso (PT11=Norte, PT16=Centro, Comeados por 978 e 979 para o ISBN (restantes 10
PT17=Lisboa, PT18=Alentejo, PT15=Algarve), enquanto dgitos do ISBN);
as Regies Autnomas no tm diviso (PT20=Aores,
PT30=Madeira); Comeados por 977 para o ISSN.
Como validar? Depende do tipo de cdigo de barras.
NUTS-3: Terceira diviso (E.g. PT11A=Porto,
Normalmente a validao j feita nos leitores por hardware
PT170=Lisboa);
mas poder ser complementada por validao por software.
NUTS-4 / LAU-1: Diviso administrativa local, corres-
pondente a Concelhos (compatvel com DCF);

NUTS-5 / LAU-2: Diviso administrativa local, corres-


pondente a Freguesias (compatvel com DCF).
Neste mundo mo-
Os cdigos NUTS no so compatveis com DCF, j derno, tudo um n-
que o mesmo distrito pode ter concelhos em NUTS diferentes.
mero (ou vrios). ()
Cdigo de barras
uma explicao mais
Existe um nmero muito elevado de tipos de cdigos de
barras, desde lineares, a 2D e a formatos "estranhos". Os mais
habituais so:
detalhada da matem-
Code 25 Interleaved 2 of 5: Contedo alfanumrico tica dos dgitos de
para fins diversos;

QRCode: Cdigo com 2 dimenses e contedo alfanu-


controlo deixa-se para
mrico para fins diversos;
o leitor.
EAN-13: Internacional, o mais usual em produtos. Tem
13 dgitos numricos;

EAN-8: Um sub-conjunto do EAN-13;


ISBN e ISSN
JAN: Usado no Japo, idntico ao EAN-13;
O International Standard Book Number (ISBN), defini-
UPC-A: Usado nos EUA, compatvel com EAN-13 do no ISO 2108, um nmero de 10 ou de 13 dgitos num-
(primeiro dgito EAN-13 "0"). Tem 12 dgitos numri- ricos. Se tiver 13 dgitos, inclui o prefixo GS1 (978 ou 979)
cos. tornando-se num EAN-13. Poder ter espaos ou "-" no meio
do nmero a separar as seces, e eventualmente o prefixo
Os cdigos compatveis com EAN-13 tm a seguinte composi-
"ISBN":
o:
Prefixo GS1 (3 dgitos, opcional): Torna o ISBN num
Prefixo GS1 (3 dgitos): Determina entre outras coisas o
EAN-13;
pas (e.g. 560=Portugal);
Grupo (dimenso varivel): Pas, regio, grupo de
Cdigo do fabricante (dimenso varivel): Atribudo pelo
lngua, etc.;
GS1;
Editor (dimenso varivel);

73
Segurana

SEGREDOS DE NUMERAO
Publicao (dimenso varivel); O International Standard Serial Number (ISSN), defi-
nido no ISO 3297, um nmero de 8 dgitos utilizado para
Dgito de controlo (1 dgito). identificar publicaes peridicas (revistas, jornais, etc.).
Poder ter o prefixo "ISSN":

Identificador nico da publicao (7 dgitos);

Dgito de controlo (1 dgito) do ISSN.


Um ISBN pode tornar-se num EAN-13:

Prefixo GS1 (3 dgitos): "977";

Identificador nico da publicao (7 dgitos);

Cdigo ISSN (8 dgitos);

Cdigo comercial (2 dgitos): altera sempre que o


preo ou outras condies comerciais mudem;

Dgito de controlo (1 dgito) do EAN-13.


Tanto o ISBN como o EAN-13 no conseguiro identi-
ficar unicamente uma edio especfica da publicao peri-
dica, necessitando sempre dum cdigo de barras adicional
(colocado ao lado) com o nmero da edio (2 ou 5 dgitos,
EAN-2 ou EAN-5).

AUTOR
Escrito por Andr Melancia

Independent Developer/DBA/Consultant. Microsoft Certified Trainer (MCT) focusing on SQL Server, Azu-
re and IoT. 17+ years' fun developing information and multimedia systems, DBA, project and IT manage-
ment. PowerShell Portugal, IT Pro Portugal and IoT Portugal communities organiser. IPv6 Portugal, DNS-
Sec Portugal and Windows Development Portugal online communities moderator. Actively volunteering,
organising, speaking or just participating at community meetings and events like SQLSaturdays, SQLBits,
SQLRelay, Maker Faire Lisbon, Arduino/Genuino Day Lisbon, Global Azure Bootcamp Lisbon, etc.

Proud uncle and food devouring expert, with dangerous ussy cat as companion.

Go to http://Andy.PT and you'll know the same as the NSA...

74
No Code
ShiftAppens 2017
Raspberry Pi Zero W
INTERFACE HUMANO-COMPUTADOR, NANOTECNOLOGIA E A DEPENDNCIA TECNOLGICA.
No Code
SHIFTAPPENS 2017

A meio do passado ms de Fevereiro, nos dias 17, Coimbra, o Alma Shopping e tambm outros igualmente im-
18 e 19, deu lugar no pavilho Mrio Mesquita mais uma portantes.
edio do SHIFT APPens, mais propriamente a 4 edio do
Evento. Como atividade principal era pedido aos participan-
tes que durante os trs dias do evento pudessem desenvol-
ver uma aplicao sua escolha, formando tambm equipas
dinmicas onde vrias personalidades de programao e
design se poderiam misturar. No fim dos trs dias, e sendo
prometido muito cdigo e caf por parte da organizao do
Shift, os participantes poderiam apresentar os seus projetos
ao jri do evento (Carlos Mota Representante do Google
Developers Coimbra; Alcides Marques - Representante do
Laboratrio de Informtica do Instituto Pedro Nunes; Joana
Brites - Representante da Faculdade de Letras da Universi-
dade de Coimbra; Tiago Henriques - Representante da Wit
Software), e serem ento premiados pelo seu trabalho
E como no poderia deixar de ser referido, a marca
(existindo claro, o 1, 2 e 3 prmio). Em conversa com o
Licor Beiro preparou um espao Lounge onde os participan-
relaes pblicas do evento, Filipe Mendes, podemos perce-
tes poderiam recarregar baterias ao longo destes trs dias,
ber que este ano o Hackathon teve bastantes mais participa-
no esquecendo a Boundi, que auxiliou os participantes com
es que nos anos anteriores.
o seu caf e o Mr. Pizza e Rei dos Frangos com a habitual
comida de Hackathon! Alm das Talks (conversas por parte
das empresas patrocinantes), existiram tambm vrios quizes
de cultura geral neste evento, ajudando os participantes a
estender a sua mente. Falemos ento de nmeros: O Shift
APPens contou com a presena de 160 participantes (30%
dos participantes vieram de fora de Coimbra e estima-se que
10% dos participantes eram do sexo feminino), 20 indivduos
de STAFF e ainda 25 voluntrios Juntamente com o IPN
(Instituto Pedro Nunes em Coimbra), o STAFF e os volunt-
rios construram toda a infraestrutura de eletricidade e inter-
net do evento (sendo que os cabos foram cedidos por um dos
patrocinadores do evento). Uma grande novidade este ano foi
que, atravs de uma plataforma chamada Slack, o STAFF e
os participantes do evento puderam estar sempre em contac-
to vendo os participantes quais as prximas atividades a
desenvolver atravs da plataforma. No entanto, esta edio
teve um formato um tanto diferente das duas primeiras, no
existindo agora mentores, mas sim um jri.

Enquanto circulvamos pelo pavilho, o relaes


publicas deu-nos a conhecer o espao e toda a histria ante-
rior ao evento que comeou por ser uma reunio de ami-
gos e estudantes que gostavam de codificar e programar,
para depois se tornar num evento que tem alguma dimenso.
Este ano, como dizia Filipe, houve a possibilidade de alargar
o espao do evento, devido aos participantes, e realizar o
mesmo no pavilho Mrio Mesquita, que conta com instala-
es preparadas para banhos e descanso, sendo este um
dos pontos mais relevantes para o sucesso do Hacktathon
este ano. Ao longo do espao, podamos ver representantes
de empresas como a RedLight Software, a Wit, a Cmara de

76
No Code
SHIFTAPPENS 2017
Quando questionado sobre esta questo, Filipe
Mendes respondeu-nos que para os participantes era mais
fcil aceitar indivduos que tivessem mais experiencia na sua
prpria equipa, ou seja, todos os participantes preferiam ser
ajudados por algum que trabalhasse em conjunto com eles, e
da o evento ter ento comtemplado a inscrio de pessoas
que no fossem apenas estudantes, mas que tambm traba-
lhassem ou tivessem alguma experincia na rea. Contando
com vrios apoiantes de peso ao longo dos anos, no pode-
mos deixar de reparar que nomes como a Microsoft ou a
Deloitte deixaram de fazer parte deste evento, o que os parti-
cipantes e STAFF do Shift vm como uma perda significati-
va.
Podemos referir que mais um ano o SHIFT APPens
foi um sucesso, e que para as prximas edies se esperam
coisas ainda mais random e espetaculares!

AUTOR
Escrito por Filipa Antunes Peres.

Licenciada em Design de Moda e Txtil e Mestre em Marketing, conta ainda com uma especializao em Web Design. Desde
pequena que desenvolveu interesse em vrias reas que tenham a ver com investigao social.

77
No Code
RASPBERRY PI ZERO W

Com o intuito de comemorar o quinto aniversrio da Zero W:


famlia Raspberry Pi, o fim de Fevereiro de 2017 trouxe mais
Especificaes:
uma novidade a esta conhecida famlia. Como no podia
deixar de ser, aqui na Programar continuamos a ser fs des- Dimenses: 65mm 30mm 5mm
ta temtica, motivo pelo qual no hesitamos em dedicar-lhe
algumas linhas nesta edio. SoC: Broadcom BCM2835

Os leitores mais atentos a estas andanas devem CPU: ARM11 funcionando em 1GHz
lembrar-se que numa edio anterior j falamos acerca do
Raspberry Pi Zero, lanado em Novembro de 2015. Ora esta RAM: 512MB
nova placa o mesmo Raspberry Pi Zero mas melhorado
em dois pontos que podem ser essenciais para alguns pro- Wireless: 2.4GHz 802.11n LAN sem fio
jectos. A verso com a letra W que se juntou ao nome da Bluetooth: Bluetooth Classic 4.1 e Bluetooth LE
primeira placa, vem principalmente acrescentar o Wireless e
o Bluetooth 4.0. Estas so de facto as vantagens integradas Alimentao: 5V, fornecido atravs de conector micro
nesta nova verso de uma das placas mais famosas no mun- USB
do da tecnologia.
Vdeo & udio: vdeo 1080p HD e udio via mini-HDMI

Armazenamento: Carto MicroSD

Sada: Micro USB

GPIO: GPIO de 40 pinos compatvel com HAT

Interface serial da cmera (CSI)

2 portas micro USB


O Zero W pode ter sensivelmente o dobro do preo do
Zero, j que foram lanados a 10 dlares e a 5 dlares res-
pectivamente, contudo consoante o nosso objectivo final, o Pi
zero W pode ser de facto uma mais-valia a ponderar.

Para no perder o hbito, o Pi W faz jus sua famlia,
Ilustrao 1 Raspberry Pi Zero W visto de frente todos os modelos Raspberry possuem um sistema Broadcom
num chip (SoC), que inclui uma unidade de processamento
central (CPU) compatvel com ARM. importante referir que
esta verso W praticamente idntica ao anterior Raspberry
Pi Zero v1.3 (o que adicionou o conector da cmara), todos
os chips e componentes ainda esto apenas no lado superior
da placa.
O Pi Zero W usa o mesmo chip Cypress CYW43438
sem fios do Raspberry Pi 3 Model B para o wireless 802.11n
LAN e conectividade Bluetooth 4.0.
No entanto apesar do chip ser o mesmo que o
Raspberry Pi 3, a antena completamente diferente. Em vez
de ser um pequeno chip branco que o contm, a antena no Pi
Zero W impressa na placa.


Ilustrao 2 Raspberry Pi Zero W visto de trs

Para recapitular, aqui est a lista completa de recursos para

78
No Code
RASPBERRY PI ZERO W

reverso da placa Zero W).


Na prtica, na antena no Pi Zero W as ondas de rdio
interagem com aquele espao livre, ressoando na pequena
cavidade apenas na frequncia certa. Os dois capacitores
que esto na parte inferior do plano de terra capturam o sinal
de rdio.
Ilustrao 3 - Antena Wireless Raspberry Pi Model 3 Apesar desta novidadade, certamente seria do agrado
de muitos utilizadores, um conector sma, que permitisse ligar
uma antena wifi externa com maior ganho.
Este novo Raspberry Pi Zero W, apesar de no ser de
todo uma novidade estrondosa como outros antecessores
seus o foram, continua a ser visto como um elemento a pon-
derar, uma vez que vem incrementar as possibilidades de
conectividade da pequena placa com aparelhos exteriores
sem que tenhamos que instalar mais algum mdulo externo,
uma vantagem principalmente para projecto IoT ou outros
projectos que necessitem de conectividade.
Ser de esperar uma adopo maior deste novo
raspberry pi zero, em projectos como o GameBoy Zero,
Ilustrao 4 - Antena Wireless Raspberry Pi Zero W https://goo.gl/b1VnB8, e outros projectos de hardware recor-
Em declaraes oficiais, Roger Thornton, responsvel rendo ao j conhecido software RetroPie, para reproduzir o
por este componente da placa, explicou que "A antena do aspecto e sensao dos jogos das dcadas de 80 e 90 do
Raspberry Pi 3 um componente de montagem em superf- sculo passado.
cie, ao passo que a antena Zero W uma cavidade resso- De igual modo, ao acrescentarem o controlador wifi, o
nante que formada por decapagem de cobre em cada ca- Pi Zero, torna-se tambm mais interessante para utilizao
mada da estrutura PCB". Esta tecnologia foi licenciada por em drones e outros dispositivos autnomos, aliando a conec-
uma empresa sueca, a Proant (conforme se pode ver no tividade do wifi, com a capacidade de processamento e o
gpio do raspberry pi zero.

AUTOR
Escrito por Rita Peres

Natural de Castelo Branco, licenciou-se em Engenharia Informtica pela Universidade da Beira Interior.
Membro do P@P desde Janeiro de 2010. Embaixadora das Geek Girls Portugal Ncleo de Lisboa.

79
25 | 26 | 27 May 2017

O ISELTech17 , que decorrer entre os dias 25 e 27 de Maio no campus do Instituto Superior de Enge-
nharia de Lisboa (ISEL) , um evento aberto a estudantes, trabalhadores e entusiastas de tecnologia que
queiram adquirir novos conhecimentos e demonstrar as suas capacidades, num espao aberto discusso
entre participantes e speakers, abordando temas da atualidade tecnolgica, como: Mobile Development,
Cloud, Web, Gaming, AR/VR, BigData, Internet of Things, Network Engineering e Cibersegurana.
Durante os trs dias do evento sero realizados Workshops para ha rd e soft skills, concursos e sorteios
de licenas de software (estgios, licenas JetBrains e Sketch) bem como diversas talks. O habitual
espao de recrutamento e exposies tambm estar presente, e contar com a presena de entidades na-
cionais e internacionais. O ltimo dia fica guardado para o painel de debate sobre Cibersegurana, com o
tema Segurana na Internet: o que ve ndemos de ns?, procurando abordar temticas como a produtiza-
o do ser humano e a vulnerabilidade da sua privacidade, bem como a ausncia de informao e regula-
mentao, quais os desafios emergentes da segurana na internet e como educar as populaes para tal.
Se te interessas por tecnologia, ters certamente vrias sesses que te iro interessar.

#SocialMedia
Na divulgao nas redes sociais, recomendamos o uso da seguinte hashtag: #ISELTech
+Info
Site/Tickets: iseltech.isel.pt
Sponsors: iseltech.isel.pt#sponsors
Facebook: /iseltech
Slack (convite): https://goo.gl/yIFeri
E mail: iseltech@isel.pt
No Code
INTERFACE HUMANO-COMPUTADOR, NANOTECNOLOGIA E A DEPEN-

DNCIA TECNOLGICA.
Introduo Comenta Jordo (2009) que a nanotecnologia se
encontra empregada em mais de oitocentos produtos,
O presente release tem por finalidade abordar como a
destacando como maior uso a produo de
criao de interfaces avanadas propiciam novos avanos
microprocessadores, afirmando se encontrar
em diferentes reas do conhecimento. Neste contexto, o foco
microprocessadores com 45 nm de tamanho. Cita seu uso
discutido permeia questes sobre a criao e o
em outras reas ao afirmar que:
desenvolvimento da nanotecnologia que pode estar direta ou
indiretamente alterando a interao do homem com o esta tecnologia no foi criada somente para ajudar na
computador. informtica, mas para revolucionar de maneira geral
em qualquer rea onde fosse necessrio. Atualmente,
Um ponto evidente que o imaginrio proposto nas
pode-se relatar a aplicao da nanotecnologia na
produes cinematogrficas, principalmente no que tange a
Medicina, na Qumica, na Fsica quntica, nas
fico cientfica apresenta grandes possibilidades de
indstrias que criam prottipos aeroespaciais,
aplicao no uso de Interfaces Humano-Computador
refinarias e muitas tantas outras reas.
(doravante IHC), tanto no aspecto positivo e benevolente
como pode ser percebido na produo Viagem Apesar de o termo nanotecnologia ter sido cunhado
Fantstica (Fantastic Voyage) de 1966, como no aspecto em 1974 (Jordo, 2009), referencias a esta possibilidade
sombrio e devastador na produo Exterminador do foram apresentadas no cinema, principalmente no estilo de
Futuro (The Terminator) de 1984. Cabe como ilustrao um produo da fico cientfica. A primeira referncia a esta
breve comentrio sobre o filme Minority Report de 2002 que possibilidade ocorreu no ano de 1966 quando os estdios
apresenta um estilo de interface, introduzida tempo depois 20th Century Fox produziram o filme Fantastic Voyage
no console de videogame XBOX da empresa Microsoft com baseado no livro homnimo, escrito por Isaac Asinov que
o perifrico Kinect o qual proporciona uma mecnica de retrata um grupo de mdicos e cientistas que so
jogabilidade semelhante mostrada no filme. miniaturizados em um submarino a uma escala microscpica
e introduzidos em um paciente para destrurem um cogulo
O estudo do tema IHC no est somente presente no
sanguneo.
formato visual da tela de um computador ou no formato
ergonmico que determinado perifrico possa ter para a Passados os anos a miniaturizao de um submarino
interao com certo sistema. Este conceito vai a um nvel com tripulao ainda no possvel, mas possvel a
mais alm. construo de pequenos robs, como os chamados robs de
DNA - DeoxyriboNucleic Acid (ADN - cido
Desoxirribonucleico) feitos de material gentico, sendo estes
Nanotecnologia nano robs que podem carregar determinado anticorpo com
a finalidade de atacar clulas cancergenas, preservando as
Antes de conceituar o que vem a ser nanotecnologia,
clulas saudveis de acordo com exposto pelo professor
cabe conceituar o que vem a ser nanmetro. De acordo com
Stevens Rehen em entrevista ao programa Globo News
Jordo (2009) nanmetro uma forma de medida como so
Cincia e Tecnologia no Brasil (GLOBO, 2013).
o metro e o quilmetro, sendo 1 nm (um nanmetro)
equivalente a um milionsimo do milmetro (SETTI, 2012) ou Na rea mdica Jordo (2009) aponta que:
ainda a bilionsima parte de um metro, sendo esta medida
invisvel a olho nu e comumente utilizada para a medio de
ligaes qumicas (FUNDACENTRO, 2013). temos como exemplo aparelhos para diagnosticar
determinadas doenas, as quais no podem ser
Jordo (2009) adverte que o nanmetro no uma
detectadas apenas com base em sintomas e exames
partcula ou um componente da eletrnica, mas apenas
comuns. Alm disso, a nanotecnologia muito
uma mera forma de medida, acrescenta que o nome
utilizada para criar remdios, afinal, trabalhar com
nanotecnologia, escolhido em 1974 na Universidade
componentes qumicos de tamanho to pequeno,
Cientfica de Tquio decorre do pequeno tamanho de vrios
exige uma tecnologia minscula o suficiente.
itens utilizados para a construo de componentes de alta
tecnologia. Para a rea de estudo da IHC, segundo Gargin (2010,
p. 78) os objetos disponveis em um ambiente podero se
De acordo com o Guia do Estudante (2013)
tornar dispositivos de integrao entre os seres humanos
nanotecnologia a cincia que projeta e desenvolve
como parte de interfaces cada vez mais invisveis e
produtos e processos tecnolgicos a partir de partculas
integradas ao ambiente, graas aos avanos na
minsculas.

81
No Code
INTERFACE HUMANO-COMPUTADOR, NANOTECNOLOGIA E A DEPENDNCIA TECNOLGICA.

miniaturizao desses dispositivos, tornando-os mais computador em substituio a tripulao humana. O curioso
portteis e presentes no cotidiano das pessoas e acrescenta: no episdio so os questionamentos advindos da experincia
proposta, considerada inaceitvel pelo Capito Kirk em ser
substitudo por um computador. O curioso o vis mostrado
Os dispositivos reagiro ao que os seres humanos em relao a uma sociedade acostumada a usar elementos
desejam, antecipando suas necessidades de tecnolgicos avanados como a forma de comunicao
informao, numa interao que ser mais natural e verbal com o computador da nave, onde a IHC quase que
intuitiva. Eles reconhecero e contextualizaro a humana no lado do computador. Este episdio mostra bem o
pessoa ou pessoas sobre o ambiente em que estejam fato de se usar os recursos tecnolgicos como ferramentas
inseridas. A obteno de informaes ocorrer, a de apoio, mas no como substitutos. Assim sendo, este de
partir dos dados existentes nas mais diversas bases, fato o grande desafio na concepo de hardware, software e
de modo muito rpido e todos os campos das cincias na forma de interface destes componentes com o ser
sero afetados pela facilidade e velocidade trazidas humano de maneira que venham a ajudar a sociedade
ao modelo de colaborao. humana a viver melhor, mas no a sucumbir em si mesma.

Anlise Crtica Bibliografia

A partir desta exposio, leva-se a crer que a FUNDACENTRO. Nanmetro. Brasil: Ministrio do Trabalho
nanotecnologia est influenciando a criao de IHC cada vez e Emprego, 2013. Disponvel em: <http://
mais simples, amigveis e adaptadas as necessidades www.fundacentro.gov.br/conteudo.
humanas. asp?D=Nano&C=1558&menuAberto=1556>. Acesso em: 3
de mai. 2013.
Na rea de sade, j esta proporcionando a mdicos
cirurgies maneiras de realizarem cirurgias menos evasivas GARGIN, S. M. Estudo das Evolues das Interfaces
com o uso de robs programados para determinada tarefa, Humano-Computador. So Paulo: Escola de Engenharia de
alm do desenvolvimento de medicamentos a partir dessa So Carlos da Universidade de So Paulo, 2010.
tecnologia. Esta uma maneira de uso de IHC, alm das
GLOBO. Globo News Cincia e Tecnologia. Direo:
janelas dos ambientes grficos encontrados nos
Eugenia Moreyra. Rio de Janeiro: Direo Geral de
computadores e dispositivos de comunicao.
Jornalismo e Esporte, 2013 [produo]. 21,38 min, colorido.
Na rea da informtica e Tecnologia da Informao as Disponvel em: <http://globotv.globo.com/globo-news/globo-
IHCs so mais percebidas, principalmente no formato de news-ciencia-e-tecnologia/t/todos-os-videos/v/cientista-fala-
comunicao que os programas efetuam com o usurio. No sobre-a-ciencia-mostrada-no-cinema-e-sua-possibilidade-real
entanto, h diversos exemplos de interfaces mal elaboradas -de-existir/2427589/>. Acesso em: 2 de mai. 2013.
que transforma o usurio em um jquei de mouse (jquei de
GUIA DO ESTUDANTE. Nanotecnolgia. Brasil: Editora Abril,
rato). Mas h as bem sucedidas como as existentes nos
2013. Disponvel em: <http://guiadoestudante.abril.com.br/
tablets e smartphones que proporcionam a sensao de
profissoes/ciencias-exatas-informatica/nanotecnologia-
folhear a tela.
687230.shtml>. Acesso em: 8 de set. 2016.
Apesar das evolues existentes e daquelas que
JORDO, F. O que nanotecnologia?. Brasil: TecMundo,
ainda viro necessrio tomar o cuidado para no ser
2009. Disponvel em: <http://www.tecmundo.com.br/
seduzido pelo canto da sereia, pois a humanidade est se
amd/2539-o-que-e-nanotecnologia-.htm>. Acesso em: 23 de
tornando cada vez mais dependente dessas tecnologias,
ago. 2016.
ficando cada vez mais sedentria e acostumada com essas
mordomias, corre-se o risco de se ter um mundo similar ao SETTI, R. 1 Milionsimo de Milmetro. Brasil: Revista Veja,
mostrado no filme Wall-e dos estdios Disney. 2012. Disponvel em: <http://veja.abril.com.br/blog/ricardo-
setti/tag/1-milionesimo-de-milimetro/>. Acesso em: 3 de mai.
Cabe, dentro do exposto, questionar um episdio da
2013.
srie Star Trek clssica chamada o Computador Supremo,
onde proposto instalar na nave USS Interprise um

AUTOR
Escrito por Augusto Manzano

Natural da Cidade de So Paulo, tem experincia em ensino e desenvolvimento de programao de software desde 1986.
professor da rede federal de ensino no Brasil, no Instituto Federal de Educao, Cincia e Tecnologia. tambm autor, possuin-
do na sua carreira vrias obras publicadas na rea da computao.

82
Veja tambm as edies anteriores da

52 Edio - Maro 2016 49 Edio - Junho 2015


Revista PROGRAMAR

e muito mais em
53 Edio - Agosto 2016 50 Edio - Setembro 2015
54 Edio - Janeiro 2017 51 Edio - Dezemb ro 2015