INSTITUTO FEDERAL CATARINENSE
REITORA
Sônia Regina de Souza Fernandes
PRÓ-REITORA DE ENSINO
Josefa Surek de Souza
PRÓ-REITOR DE EXTENSÃO
Fernando José Taques
PRÓ-REITORA DE PESQUISA, PÓS-GRADUAÇÃO E INOVAÇÃO
Fátima Peres Zago de Oliveira
PRÓ-REITORA DE DESENVOLVIMENTO INSTITUCIONAL
Jamile Delagnelo Fagundes da Silva
PRÓ-REITOR DE ADMINISTRAÇÃO
Stefano Moraes Demarco
EDITORA IFC
COORDENADORA
Leila de Sena Cavalcante
CONSELHO EDITORIAL
Claudecir Alberto Schenkel
Fernando José Garbuio
Josefa Surek de Souza
EDITORA DO INSTITUTO FEDERAL CATARINENSE
Rua das Missões, 100 - Ponta Aguda
CEP: 89.051-000 – Blumenau/SC
www.editora.ifc.edu.br
Editora filiada a:
Direção Editorial | Hylson Vescovi Netto | |
Capa e Projeto Gráfico | Hylson Vescovi Netto | |
Editoração Eletrônica | Hylson Vescovi Netto | |
Revisão | Leandro Augusto Loss | |
Copyright © Hylson Vescovi Netto.
Todos os direitos reservados. Proibida a venda.
As informações contidas no livro são de inteira responsabilidade do autor.
Dados Internacionais de Catalogação na Publicação (CIP)
Este livro trata sobre lógica de programação, assunto cujo desenvolvimento provê um raciocínio que pode ser útil em diversos contextos. No mundo prático do trabalho, existem locais nos quais as ações do trabalhador precisam ser realizadas com maior detalhamento. Nesses casos, é preciso criar um procedimento operacional padronizado (POP), um documento que descreve em passos como realizar tarefas. Considerando o contexto de pandemia no qual se encontra o mundo no momento da escrita deste livro, considere como exemplo a atividade de limpeza, desinfeção e sanitização dos ambientes escolares, a fim de preparar tais ambientes para o retorno gradual das aulas, no momento em que isso for possível. Esse trabalho requer uma série de ações que devem ser realizadas com atenção. No IFC, por exemplo, foram criadas instruções detalhadas sobre como devem ser as instalações, a frequência das ações a serem realizadas, os procedimentos a serem realizados e quem são os responsáveis pela realização dessas ações (Figura 1.1). Nesse POP as instruções se encontram de forma textual, organizadas sob a forma de itens a serem observados e cumpridos.
Outro exemplo é a descrição de procedimentos visando garantir a higiene em ambientes de manipulação de alimentos. Essas instruções são tão precisas que há cursos específicos sobre como esses passos devem ser realizados (por exemplo: escolavirtual.gov.br/curso/287). As instrução são detalhadas, informando o local, o que fazer, qual a frequência da ação, como fazer o procedimento, quem é o responsável pela ação e outras observações (Figura 1.2).
Pode-se, assim, tentar expressar a relação entre a lógica de programação e a definição de instruções para se realizar um trabalho por meio da seguinte hipótese: a definição de uma sequência de passos necessários para cumprir uma tarefa contém em si raciocínios e estratégias similares àqueles necessários à construção de um programa. O que essa hipótese afirma é que aprender lógica de programação ajuda a organizar o pensamento, analisar problemas e propor soluções em termos de sequência de passos para se alcançar um objetivo. Para verificar se essa hipótese é verdadeira, cabe ao leitor seguir os conceitos e exemplos descritos neste livro, realizando também a experimentação prática proposta por meio dos programas apresentados. Ao fim do consumo deste material, será possível verificar se surgiram melhoramentos e novos pensamentos nas suas habilidades de sistematização e organização de passos e etapas necessários para a realização de tarefas.
Quando houver dúvida sobre a utilidade em aprender lógica de programação, ou como tal assunto será útil para os anseios profissionais, dê a si próprio o benefício da dúvida sobre quais são as possibilidades de aplicação da lógica de programação nas futuras atuações profissionais que porventura você pretenda. Não busque invalidar o conhecimento contido neste material por julgar que talvez essas informações não sejam necessárias para você. Às vezes gastamos mais tempo pensando em motivos para não fazer ou aprender algo, quando tal tempo e esforço seria muito mais produtivo alimentando a imaginação em possibilidades de ação e realização:
[..] o interessante a respeito desse padrão de comportamento é que, se o que eu demonstrei é uma coisa que você gostaria de ser capaz de fazer, então você bem que poderia gastar seu tempo aprendendo a fazê-lo. Há muitas e muitas coisas que nós não conseguimos fazer. Se você puder programar-se para procurar as coisas que serão úteis para você e para aprendê-las, ao invés de tentar descobrir onde é que fracassa aquilo que lhes estamos apresentando, garanto-lhes que logo irão perceber onde é que as coisas fracassam. Se você usar de modo congruente essa informação, encontrará montes de lugares onde ela não adianta nada. E quando não der certo, sugiro-lhes que experimentem alguma coisa diferente. (BANDLER; GRINDER, 1982, p.110).
Aprender a programar, assim como aprender outros assuntos, é uma tarefa que fica mais fácil quando há interesse do aprendiz em desenvolver tal habilidade. Há muitas possibilidades de aplicar a programação no cotidiano de várias profissões, ou mesmo para resolver muitos tipos de problemas. Portanto, tente alinhar os seus desejos e gostos com os inúmeros problemas que podem ser resolvidos com apoio da programação. Este documento traz, além de referências à programação, situações nas quais a programação pode ajudar a resolver problemas práticos. Este livro busca a redação dos textos segundo a norma culta, a fim de oportunizar ao estudante o contato com bons textos em português, por meio da leitura, enquanto estuda programação.
Sugere-se ao aprendiz que sempre observe o programa citado no texto e digite-o em seu computador, a fim de compreender cada linha do programa, enquanto a mesma está sendo transferida do “papel” para o computador. A impressão deste livro em meio físico é permitida e recomendada, e pode fornecer a experiência multimídia, quando se realiza a leitura em papel e a prática no computador. Um livro tem potencial enorme de aprendizagem com profundidade (youtu.be/gbOM8n9omUE?t=337). Entretanto, caso seja de interesse testar primeiramente se o programa que você vai estudar realmente funciona, o código do programa pode ser obtido diretamente da internet para o seu computador, a fim de testar seu funcionamento. Todo código-fonte citado neste material advém de um programa armazenado no github. Cada endereço é fornecido após a listagem do respectivo código-fonte. Algumas seções estão acompanhadas de vídeos explicativos sobre o conteúdo da seção. Os endereços desses vídeos se localizam no começo da respectiva seção que possui o vídeo, e está sinalizado com o logotipo do site youtube. Neste livro foram também consideradas algumas premissas:
Quatro personagens eventualmente aparecem nesse documento em interações nos conteúdos apresentados. O objetivo desses diálogos é passar, por meio dessas figuras fictícias, algumas dinâmicas que advém da experiência vivenciada em situações reais. Os personagens são Túlio, Pedro, Gabriela e Agnes. Quatro amigos que estudam informática e possuem características bem diferentes. Ao longo do texto será possível conhecê-los melhor. Sigamos suas aventuras!
Agradeço ao discente Leonardo Habitzreuter por ter me confrontado com a realidade da construção de sistemas usando a arquitetura front-end e back-end (em vez da arquitetura integrada), o que provocou uma mudança positiva na minha prática docente para adequar tal fato. Agradeço também aos pareceristas contactados pela editora do IFC, que forneceram valiosas sugestões para o aprimoramento desta obra. Várias sugestões foram realizadas nesta obra, enquanto outras começaram a ser executadas na segunda edição deste livro, ainda por vir.
Este livro contém nove (9) capítulos que estão organizados em uma sequência, com exceção do último capítulo que foi criado para fins de consulta sob demanda (Figura 1.3). O primeiro assunto a ser abordado é a manipulação de repositórios (Capítulo 2), pois o armazenamento de código feito em repositórios públicos cria um “portfólio” de programação. Esse portfólio pode ser útil tanto para apreciação em oportunidades de trabalho tanto para o professor que deseja avaliar os códigos produzidos pelo aluno. A seguir, são introduzidos elementos de apresentação (Capítulo 3), pois todo sistema deve possui uma boa aparência. Sendo assim, é importante conhecer os elementos mais básicos dos quais uma tela de sistema web é feita. Na sequência, encontra-se o conteúdo sobre orientação ao objetos (Capítulo 4), pois essa maneira de desenvolver programas possui grandes vantagens como reutilização e encapsulamento, dentre outras. Uma breve abordagem sobre persistência de dados (Capítulo 5) menciona formas de armazenar os dados, a fim de que eles não se percam e permaneçam gravados.
Após conhecer os elementos básicos de um sistema, inicia-se a construção de um sistema web, utilizando as linguagens python e javascript. Primeiramente, constrói-se uma aplicação monolítica que abriga todos os elementos do sistema (Capítulo 6), para conhecer as potencialidades do python na construção de um sistema web. Essa aplicação apenas lista informações que são previamente cadastradas no sistema como dados de exemplo. A seguir, a aplicação é separada em duas partes: front-end e back-end (Seção 6.2). Ambas as partes continuam desenvolvidas em python, trocando informações por meio textual em formato json. Inicia-se, então, o desenvolvimento da aplicação com o back-end sendo codificado em python e o front-end escrito em javascript (Capítulo 7). O uso de javascript é bastante comum para a construção de front-ends, enquanto o python pode ser utilizado com sucesso na construção de um back-end. O sistema é incrementado gradualmente com funcionalidades que permitem realizar inclusão de dados (Seção 7.2) e exclusão de dados (Seção 7.3). Outra expansão do sistema se refere a criar novas classes para armazenar mais informações, crescendo assim o tamanho do sistema (Capítulo 8). São adicionadas classes por meio de agregação e composição, além de uma classe que possui relacionamento múltiplo com outras classes (N x N). O sistema é concluído com um formulário de inclusão de dados que traz informações de classes relacionadas, para que o dado composto possa ser gravado com dados dessas outras classes (Seção 8.2).
O livro traz também informações básicas sobre o uso de dicionários na linguagem python (Capítulo 9), além de informações adicionais (suplementos) sobre operações que envolvem o uso dessa linguagem. O capítulo de orientação a objetos, chamado “Dados em objetos”, apresenta diversos exemplos de conceitos utilizando as linguagens java e python: classes introdutórias, agregação e uso de construtores (Tabela 1.1). Alguns conceitos permanecem apenas implementados na linguagem python (generalização) ou java (polimorfismo). Edições futuras deste livro pretendem completar as lacunas que existem no presente material, em relação à implementação dos conceitos em ambas as linguagens.
Assunto de orientação a objetos | java | python |
classes introdutórias | sim | sim |
agregação | sim | sim |
generalização | não | sim |
polimorfismo | sim | não |
construtores | sim | sim |
A aplicação desenvolvida a partir do Capítulo 6 deste livro obedece uma organização em camadas (Figura 1.4). Na camada superior (Apresentação) encontram-se elementos que são expostos para exibição e interação com o usuário final do sistema (componentes do front-end): páginas HTML, elementos visuais de estilo (Folhas de estilo - Cascade Style Sheet (CSS)) e programas em javascript. Na camada intermediária se encontra a aplicação, que contém toda a inteligência do sistema: ações, regras de negócio e modelos dos dados. Neste livro é utilizada a linguagem python para a construção da aplicação (back-end). Na última camada, a persistência de dados é realizada com uso do banco de dados SQLite.
É possível representar a arquitetura do sistema desenvolvido neste livro sob outra perspectiva (Figura 1.5). O cliente utiliza um navegador (front-end), que renderiza componentes de interface hospedados no servidor web. A aplicação (back-end) é executada em um servidor web, e contém componentes de negócio e de dados que se comunicam com um servidor de banco de dados, no qual a persistência dos dados é efetivada.
Este livro retrata o conteúdo apresentado ao longo de um ano para uma turma de terceiro ano de um curso técnico em informática integrado ao ensino médio. Porém, o percurso descrito no livro pode ser utilizado também por quem possui conhecimentos de lógica de programação e deseja aprimorar sua habilidade de criação de sistemas de cadastro web para, por exemplo, estar melhor preparado em processos seletivos de trabalho. Nesse caso, basta seguir a construção de sistema proposta a partir do Capítulo 6. Edições futuras deste livro pretendem colocar lado a lado os fundamentos de java e os fundamentos da linguagem python, para assim prover uma aprendizagem por comparação. Essas duas linguagens foram escolhidas para utilização neste livro pois são linguagens praticadas nos cursos de nível médio e superior do IFC Campus Blumenau. São linguagens que foram escolhidas, portanto, também pela instituição de ensino, na elaboração de seus cursos. Além disso, a linguagem java está presente em sistemas atuais e legados, desenvolvidos globalmente e em empresas na região de Blumenau. Já a linguagem python possui grande potencial de realização de atividades com uma quantidade modesta de linhas de código, possuindo também uma curva de aprendizagem que fornece resultados rapidamente.
Este livro está disponível no site da editora do IFC: editora.ifc.edu.br. Ele foi escrito com a ferramenta LATE X e está também disponível no formato HTML de forma online em hylson.com/programar. Se você encontrar erros neste material ou quiser fornecer comentários e sugestões, envie email para hylson.vescovi@ifc.edu.br. Sua mensagem será apreciada e poderá contribuir para futuras edições deste livro.
Como início dos trabalhos, nossos amigos Túlio, Pedro, Gabriela e Agnes decidiram utilizar uma ferramenta para gerenciar seus programas. Não foi mais possível aceitar aquela situação de ficar enviando códigos por email, salvando pastas inteiras em pen-drives. Agnes lembra que muitas vezes ela salvava a mesma pasta várias vezes no pen-drive, apenas inserindo um número de versão (por exemplo: cadpessoa1, cadpessoa2, ...). Essa situação tinha que acabar. Iniciaram os amigos então o estudo de uma ferramenta de versão denominada git (https://git-scm.com/). Com essa ferramenta eles poderiam ter o seu código disponível sempre (Supondo que haja internet para a atualização dos programas), em qualquer lugar.
Agnes iniciou os estudos dizendo que achou um tutorial na internet no qual os passos para utilizar um repositório estavam dispostos e explicados (http://rogerdudler.github.io/git-guide/). Pedro sugeriu, porém, ler mais um pouco sobre o git antes de sair executando comandos com base nas poucas explicações fornecidas. Após leituras e alguma conversa entre os colegas, Agnes resolve formalizar o processo de um “uso feliz” de repositórios usando algumas palavras-chave:
cadastrar ! criar ! clonar ! modificar ! atualizar
Como primeira ação, eles verificaram que é necessário cadastrar uma conta no github. Túlio rapidamente acessou o site http://www.github.com e realizou o cadastro das informações necessárias. O nome de usuário utilizado pelos amigos foi criado com bastante critério, a fim de facilitar sua utilização (Tabela 2.1). O nome completo de Pedro não é um nome incomum, logo ele adicionou um número significativo para ele, a fim de diferenciar seu logins dos demais já existentes (já havia um psoliveira cadastrado).
Nome | Usuário |
Túlio Stein Junior | tsjunior |
Pedro Silva de Oliveira | psoliveira901 |
Gabriela Hoffman Fardin | ghfardin |
Agnes Pirolli Santini | apsantini |
Após cadastrar as contas no github, todos partiram para criar o primeiro repositório. Gabriela estava interessada em armazenar programas de uma disciplina chamada “Programação 2”, logo criou um repositório chamado “programacao2”. Essas tarefas de cadastro e criação de repositório foram executadas no navegador web, no endereço github.com. A seguir, os estudantes abriram os terminais de comando para iniciar a operação de repositórios em modo texto, pois a operação via terminal é simples para a maioria dos comandos comumente utilizados. Túlio foi o primeiro a clonar o repositório vazio que acabara de criar na internet, executando este comando no terminal:
$ git clone https://github.com/tsjunior/pgm2.git
Você consegue descobrir o nome do repositório que Túlio clonou, certo? (O repositório chama-se pgm2) Agnes achou por bem clonar o repositório na página do github, em um botão no canto superior direito que permite efetuar o download do repositório em formato compactado (zip). Túlio advertiu-a, mencionando que repositórios baixados via arquivo ZIP não mantém controle do histórico de alterações! Gabriela clonou o repositório via linha de comando da seguinte forma:
$ git clone https://github.com/ghfardin/programacao2.git
Após executar o comando de clonagem, Túlio observou que foi criada uma pasta chamada “pgm2” no diretório atual. Sendo assim, ele acessou o diretório (ele utilizou o comando $ cd pgm2) para iniciar a construção de seus programas, ou seja, modificar o conteúdo do repositório. Ele, assim como os demais, criou arquivos com programas, pastas, arquivos pdf, etc. Túlio foi o primeiro que terminou de fazer os programas do repositório, e assim seguiu para atualizar o repositório remoto. Afinal, era preciso salvar os programas construídos com tanto afinco naquele momento. Não estava bem claro para ele como seria realizada essa atualização, sendo útil então a ajuda de Pedro, que iniciou um diálogo com Túlio:
— Túlio, grave em sua mente três palavras que podem te ajudar a lembrar a sequência de comandos para atualizar o repositório remoto: add, commit e push. — O que? Não entendi nada! Explica isso direito. — Ok, então você tentar imaginar essa seguinte sequência: adicionar, confirmar e enviar. — Certo, melhorou um pouco. Mas você pode detalhar isso pra mim? |
Após adicionar os arquivos a serem alterados na lista de alterações, é preciso confirmar as alterações, informando uma mensagem que descreve, em termos gerais, o que significam as alterações que foram realizadas. Iniciou-se assim outro diálogo interessante:
— Pedro, você está querendo dizer que eu preciso ficar pensando sobre o que eu fiz no repositório para poder enviá-lo pra internet? Tá de brincadeira comigo né? — Ô Túlio, essa mensagem de confirmação é útil para demarcar no github alguns pontos de avanço do código. Em um primeiro momento parece estranho, mas a gente se acostuma a refletir sobre o que tem feito no código e depois de um tempo a gente se torna hábil para descrever em poucas palavras o que fez nas últimas horas de programação. — Ok, ok, vou acreditar nessa sua teoria. — Pratique e depois me diga o que achou. |
— Então, eu posso colocar uma mensagem assim: “hoje o meu dia foi muito legal”? — (Pedro) Olha, até pode, mas isso não diz nada sobre o seu código. Seria melhor você colocar algo desse tipo: “foram feitas atualizações para melhorar o desempenho”, ou então: “realizada correção de um erro ao dividir números inteiros”. — Ah, que chato isso. Não posso colocar sentimentos nessas mensagens? — Pode sim, que tal: “Hoje consertei o maior bug que encontrei na vida! Demorei cerca de uma hora, mas venci.” — (Túlio) Alguém pode me dizer por favor qual é o comando que faz essa tal de confirmação com mensagem??? |
$ git commit -m ’Consegui inserir uma folha de estilo na página HTML, mesmo com muito barulho na sala’
Inesperadamente, ocorre um erro que deixa todos perplexos. Como poderia toda a teoria discutida e compreendida ter falhado naquele momento? Agnes então entra em cena:
— Pessoal, eu li em algum manual que é preciso configurar o git, informando o nome e o email do usuário que está operando o repositório. — (Gabriela) Hã? E como eu poderia fazer isso?? — Por acaso anotei aqui no caderno, pois achei mesmo que isso poderia servir. Os comandos são estes: $ git config user.name “Agnes” e $ git config user.email “apsantini@gmail.com”. — (Túlio) Certo, mas no meu caso devo trocar o nome do usuário e o email, certo? — Sim, isso mesmo. Cada um coloca o seu nome de usuário e email nos comandos. — (Túlio) Peraí: eu preciso executar esse comando em CADA REPOSITÓRIO que eu clonar? Assim não vai rolar. — (Pedro) Olha só, em máquinas compartilhadas como estas aqui do laboratório você configura o usuário executando esse comando “dentro” do seu repositório. Na SUA CASA, onde só você mexe no git, você pode usar uma palavra especial para informar que TODOS os repositórios daquela máquina vão utilizar o nome de usuário e o email que você informa. — (Túlio) Opa, gostei disso aí. Como é o comando? — Basta acrescentar o termo global, com dois tracinhos antes. — (Túlio) Tá. Como? — Vou mostrar um exemplo, lá em casa eu fiz assim: $ git config --global user.name “Pedro 901”. A seguir, usei este: $ git config --global user.email “psoliveira901@hotmail.com“. — Que número é esse? — É um número que tem um significado pra mim, eu uso pra diferenciar meu nome rsrs. Tem muito Pedro por aí. |
Após todos confirmarem as alterações feitas em seus respectivos repositórios, partiram para o terceiro passo: enviar as alterações adicionadas e confirmadas para o repositório remoto. Túlio rapidamente executa o comando: $ git push e inicia o diálogo:
— Opa, atualizei meu repositório! — (Pedro) Legal! Verifica lá no site do github se as alterações foram enviadas. |
O segundo passo na manipulação de repositórios é a atualização de seu repositório local a partir do repositório remoto. Essa necessidade pode ocorrer, por exemplo, na sequência de eventos descrita a seguir:
O cenário descrito pode ser resolvido apagando-se o repositório existente no computador de sua casa e efetuando-se a nova clonagem. Existe, porém, uma atitude mais apropriada para esse caso: pode-se verificar a situação de atualização do repositório local e, a partir da constatação de que você possui uma versão desatualizada, realizar a atualização. Antes de verificar o estado do repositório local, porém, é preciso atualizar o repositório local com informações do repositório remoto. Acompanhe o diálogo a seguir:
— (telefone chamando) — (Pedro) Alô. — (Agnes) Oi Pedro! Na semana passada eu peguei aquele código que fizemos na última aula de laboratório. Mas olha, quando fui clonar, o git informou que já havia um repositório na máquina com esse nome. Daí apaguei o repositório e clonei novamente. Complicado hein?! Vou fazer isso de novo agora e te liguei só pra avisar que vou começar a mexer no trabalho de programação. — Bom dia Agnes! — Bom dia. — Olha só, fica tranquila. Não precisa apagar e clonar o repositório de novo. Tem alguns comandos que podem ser usados quando a gente já possui o repositório localmente e só quer atualizá-lo. Vou te passar agora, anota aí tá? — Opa, me passa aí que eu vou fazer é já! — Beleza. Primeiramente precisa trazer as metainformações do repositório para o computador local. — Trazer as meta quem? — Ahah são informações de controle do git sobre o seu repositório. Você pode fazer isso com esse comando: $ git remote update. Esse é o primeiro comando que você precisa executar quando chega em um computador que já tem o seu repositório e não tem certeza se ele está atualizado. — Beleza. Executei aqui mas deu um erro. E agora? — Agnes, você entrou no repositório pra poder dar esse comando? Quando a gente abre o terminal, geralmente ele inicia na pasta raiz e a gente tem que entrar na pasta, com o comando $ cd. — Ah foi mal! Não tinha entrado. Deixa fazer aqui... pronto, agora deu certo! Acho que os metadados vieram, pois ele escreveu um monte de coisas na tela depois que eu executei o $ git remote update. — Ok, é isso aí. Se ele mostrou algumas coisas na tela é possível que seu repositório local esteja desatualizado mesmo. — Sim, está! Eu fiz um monte de códigos lá no laboratório. — Tá certo. Vamos conferir isso então agora, vamos ver como está a situação do seu repositório. Segue o comando que mostra isso: $ git status — Opa, legal! Tá mostrando aqui alguma coisa de que o meu repositório está “atrás” do repositório remoto. Algo assim. — Certo. Então seu repositório local está “desatualizado” em relação ao repositório remoto, como esperávamos, certo? — Certo! E daí? — Agora você pede para o git trazer as alterações do repositório remoto e atualizar o seu repositório local. — Pode ser com comando de voz? — Hehe não, segue aqui o comando: $ git pull — Só isso? Hum... entendi, é o contrário de push, que usamos naquele outro comando que envia os dados. — É isso aí. Manda ver. — Executei. Deixa ver aqui... beleza! Tá tudo aqui. Obrigada Pedro! — De nada! Nos vemos na próxima aula. Abraço e quando terminar lembra de fazer add, commit e push. — Valeu! |
Tarefa sugerida: execute as ações a seguir para experimentar a situação de sincronizar seu repositório local.
________________________________________________________________________________________________________________________________________________________
É possível acontecer uma situação na qual haja informações atualizadas mas diferentes nos repositórios local e remoto. Isso pode ocorrer, por exemplo, ao modificar um repositório desatualizado localmente. Nesse caso, para não perder as alterações, deve-se fazer uma operação de junção (mesclar = fundir = merge). Essa necessidade pode ocorrer em um cenário descrito a seguir:
Alguns conflitos podem ser resolvidos automaticamente e outros não. Acompanhe o diálogo a seguir para descobrir como agir em situações de conflito:
— Boa tarde Túlio! — Boa tarde Gabriela. O Pedro me falou que você já está sabendo como resolver problemas usando o git. — Sim, consegui estudar essa parte e já estou praticando. Qual é sua dúvida? — Eu tenho um problema! Continuei desenvolvendo o trabalho de programação mas esqueci de atualizar o repositório local. Agora não consigo fazer o push, dá um erro. O git rejeita minhas alterações! — Certo. Bom, vamos ver se a gente consegue resolver da forma simples. Já está com seu notebook ligado né? Então vamos tentar. Já atualizou o repositório local? — Eu alterei os arquivos e melhorei o trabalho de programação. — Sim, mas quero saber se você já deu aquele comando para o git saber como está o seu repositório local em relação ao remoto. — Ah sei, o comando update. Ainda não fiz. Vou fazer agora então: $ git remote update). Pronto. — Bem, já sabemos que você tem conflitos porque não conseguiu fazer o push, certo? — Isso. — Então, vamos tentar fazer a resolução automática de conflito. Você vai usar o seguinte comando: $ git merge — Pronto, executei. Eita, abriu um editor de texto aqui! — Ele pede pra você informar uma mensagem, parecida com a mensagem do commit. Coloca algo assim: “resolvendo conflito do trabalho de programação”. — Pronto. Salvei e ele saiu do editor de textos. E agora? — Bem, vamos verificar como ficou o repositório local depois da mesclagem. Use aquele comando do status. — Certo: $ git status. Aparentemente tudo certo então. Obrigado!! — Tudo certo? Legal! Então foi feita uma resolução automática de conflito. Agora é só fazer o push e pronto. — Beleza, vou fazer já: $ git push. Ok! Obrigado Gabriela! — De nada. |
Tarefa sugerida: experimente uma situação de fusão com alterações sem conflito (i.e., que pode ser resolvida de maneira automática). Neste caso, serão alteradas linhas diferentes de um mesmo arquivo. Execute a seguinte sequência de ações:
________________________________________________________________________________________________________________________________________________________
Quando as alterações em um mesmo arquivo não podem ser resolvidas automaticamente, é preciso intervir para fazer a mesclagem. É o caso, por exemplo, de uma mesma linha de um arquivo ser alterada de duas formas diferentes (de uma forma no repositório remoto e de outra forma no repositório local). Nesse caso, após a execução do comando de fusão, o arquivo local é alterado e as duas diferentes versões da linha são exibidas no mesmo arquivo, que deve ser editado para definir quais alterações devem prevalecer. As alterações são sinalizadas com caracteres <<<<<<, ====== e >>>>>>. No arquivo local, o conteúdo discrepante que se encontra no repositório local será delimitado pelos caracteres <<<<<< e ======. O conteúdo discrepante existente no repositório remoto será localizado entre os caracteres ====== e >>>>>>. É preciso apagar os caracteres delimitadores, eliminar o conteúdo duplicado e decidir qual conteúdo deve prevalecer, dentre as diferenças. Pode-se optar por um dos conteúdos discrepantes, ou criar um terceiro conteúdo, resultante da fusão dos conteúdos anteriores.
Um de nossos amigos, o Pedro, vivenciou essa situação emocionante de não conseguir atualizar seu repositório remoto devido a conflitos cuja resolução não era automática. Veja a conversa dele com Agnes:
— (Pedro) Oi Agnes! Que bom te encontrar aqui pelo laboratório. — Diga aí Pedrão. — Pois então, estou trabalhando há umas duas horas aqui, mas quando cheguei, peguei a mesma máquina que costumo usar, e como meu repositório já estava aqui, continuei a desenvolver os programas desde a última aula. Mas esqueci que último sábado à tarde resolvi programar um pouco antes de sair para um aniversário à noite. Daí agora estou aqui tentando enviar tudo para o github, mas não vai, não vai. — Calma aí! Você usou add, commit e push? — Sim. Mas ele não faz o push, ele mostra umas coisas escritas, incluindo um termo “rejected”. — Ah sim. Deve haver conflitos que precisam ser resolvidos. Depois dessa mensagem você tentou novamente fazer a junção dos códigos, com o merge? — Não. É mesmo!! Vou tentar, peraí... ah! Olha aí, não vai! — Certo. Então o git não conseguiu resolver seu problema automaticamente. Você vai ter que editar seus arquivos e resolver as diferenças manualmente. — Tá. Eu mexi ... caramba não sei em quais arquivos eu mexi! Foram tantos. — Certo. Mas veja então o resultado do comando $ git status. Ele vai mostrar o caso em que ambos os arquivos foram modificados (versão local e versão remota). — Verdade! Tá listando, olha. — Isso aí. Outro comando interessante é este: $ git diff. Ele mostra os conteúdos diferentes nos arquivos modificados. — Verdade. Nossa, mexi em tudo isso! Muita coisa! — Agora inclui esse parâmetro no comando, pra mostrar só os nomes dos arquivos: $ git diff --names-only. — Opa! Show de bola. Deixa abrir um arquivo destes pra ver... eita! Tem uns símbolos diferentes. — Sim. Após os sinais de menor (<<<<<) está o texto que existe no seu computador local. Depois vem um monte de sinais de igual (=========) e depois o texto que está no servidor remoto, terminando com sinais de maior (>>>>>). — Certo. Então vou ver qual dessas linhas é a certa... tá, escolhi. Daí apago esses caracteres e deixo só o texto que quero, certo? — Isso aí. — Salvo o arquivo... acertei o texto. E agora? — add, commit e push — Beleza! Deu certo. Obrigado! |
Tarefa sugerida: será des crita uma situação de fusão com alterações conflitantes, com alteração de informações da mesma linha (i.e., do mesmo número de linha) nos arquivos local e remoto. Para realizar a mesclagem com conflitos, execute a seguinte sequência de ações:
________________________________________________________________________________________________________________________________________________________
Quando se remove um arquivo de um repositório local, é preciso informar ao git que esse arquivo foi removido. Assim como existe a operação de adicionar arquivos no repositório ($ git add arquivo), existe também um comando para excluir um arquivo do repositório:
$ git rm nome-do-arquivo
Após remover o arquivo, é necessário confirmar essa ação junto ao repositório:
$ git commit -m ’removendo arquivo’
Por fim, deve-se enviar as alterações para o repositório:
$ git push
Caso seja necessário remover uma pasta, pode-se utilizar o parâmetro -r:
$ git rm -r nome-da-pasta
Nesse caso, será removida a pasta e todos os arquivos e subpastas contidas na pasta.
Existe um comando do git para que se possa informar ao git sobre mudanças nos nomes de arquivos e pastas. O comando $ git mv velho novo informa ao git que o arquivo chamado velho passou a se chamar novo. Esse comando pode ser utilizado também para alterar o nome de pastas. A alteração de nome pode ser feita diretamente com o comando mv do git, em vez de renomear o arquivo ou pasta via sistema operacional ou via gerenciador de arquivos.
Quando usar o git em seu computador pessoal no sistema operacional Linux, você pode solicitar que o login e a senha sejam armazenados, para que não seja necessário informar essas informações a cada atualização do repositório remoto. O comando que pode realizar essa ação é este:
git config --global credential.helper store
É possível permitir que outras pessoas tenham acesso de escrita a um repositório, o que pode ser útil em pequenos projetos desenvolvidos em grupo. No site do github, para compartilhar um repositório deve-se acessar o menu de configurações de um repositório, acessar o submenu “Colaboradores” e então adicionar uma informação do colaborador (login do github ou email) (Figura 2.1).
Este capítulo apresentou o uso da ferramenta git para criar e sincronizar repositórios remotos hospedados no site github.com. Foi também abordado como solucionar conflitos entre repositórios (local e remoto), excluir e renomear arquivos. Por fim, tratou-se do compartilhamento de repositórios, para permitir de forma básica que mais de um usuário possa atuar sobre um mesmo repositório.
O desenvolvimento de sistemas pode ser modularizado de forma geral em duas partes: a interface com o usuário e o sistema de processamento e armazenamento de dados. Ao primeiro denominamos front-end, enquanto o segundo é conhecido como back-end. As tecnologias envolvidas no desenvolvimento do frontend incluem HTML, javascript e CSS, e serão abordadas neste capítulo.
Os amigos Tulio, Pedro, Gabriela e Agnes iniciaram seus estudos nos elementos básicos de um front-end para a web: os comandos da HTML (HyperText Markup Language). Toda página HTML é delimitada pelas tags <html> e </html> (Código 3.1, linhas 2 e 14). A página é divida em duas partes principais: o cabeçalho da página, delimitada pelas tags <head> e </head> (linhas 4 e 6), e o corpo da página, delimitada pelas tags <body> e </body> (linhas 8 e 11). No cabeçalho da página considerada, existe a tag title, que define a frase a ser exibida na barra superior do navegador web (é o “título” da página). A tag h1 (linha 9) exibe uma mensagem em formato grande, enquanto a tag p exibe o texto contido na tag em forma de parágrafo (linha 10).
Alguns dos componentes mais comuns que fazem parte de uma página HTML são os links, os estilos de formatação, as imagens e as estruturas de agrupamento conhecidas como div. Esse componentes estão descritos nas próximas seções.
Considere um link para o site do Google. Para criar esse link pode-se utilizar o seguinte código HTML:
<a href=“http://www.google.com”>Google</a>
A tag que especifica links chama-se a e possui o parâmetro href, que especifica o endereço para qual o link aponta. Entre a abertura e o fechamento da tag se encontra o texto que será exibido no link.
As páginas HTML em geral possuem o conteúdo a ser exibido ao usuário. A maneira como as informações serão exibidas é definida pela forma e pode ser especificada em um arquivo de folhas de estilo (Cascade Style Sheet), que possui extensão “.css”. Os principais especificadores de estilos são compostos pelos caracteres # e o ponto (.). O primeiro referencia elementos específicos que possuem identificadores. O segundo referencia grupos de elementos que aplicam uma determinada classe.
Considere o exemplo de um parágrafo que deve ser exibido na cor azul (Código 3.2, linha 12). Uma forma de definir essa formatação é identificar o parágrafo a ser formatado. O parágrafo em questão e então identificado pelo nome primeiro, por meio do parâmetro id. O próximo passo consiste em “ligar” a página a um arquivo de folha de estilo. Essa ação pode ser feita com a tag link (linha 6). Especifica-se, nessa tag, por meio do parâmetro rel, que será feito um vínculo com um arquivo de folha de estilo. O nome do arquivo é fornecido no parâmetro href. Uma formatação pode ser também definida com uso do caracter ponto. Por exemplo, pode-se aplicar uma formatação chamada “amarelo” a um parágrafo (linha 13) e à tag genérica denominada span (linhas 14 e 15), para aplicar a cor amarela ao fundo desses textos. Essa aplicação ocorre com uso do parâmetro class.
O arquivo de estilo é composto pela formatação desejada nos componentes da página HTML (Código 3.3). Define-se que para um elemento identificado por “primeiro” (linha 1) a cor de fundo será igual a azul claro (linha 2). Um estilo chamado “amarelo” é definido como tendo a cor de fundo amarela (linhas 5 a 7).
Fonte: https://github.com/hvescovi/programar2020/blob/master/
02-front-end/01-html-css/03-estilo.css#L1
Imagens são inseridas em páginas HTML por meio da tag img. Uma foto de uma casa pode ser inserida da seguinte maneira:
<img src=“casa.png” />
Uma página pode ser dividida em seções, ou blocos. O componente div pode ser utilizado para construir layouts. Como exemplo, considere seletores de estilo chamados linha e coluna (Código 3.4). Neste material não há interesse em detalhar o conteúdo da configuração de linhas em colunas, mas apenas utilizar esses seletores para construir layouts tabulares.
Com os seletores de linha e coluna pode-se, por exemplo, criar um layout simples com duas colunas (Figura 3.1). Essa configuração pode ser expressa especificando-se que haverá uma div de linha, e em seu interior haverá duas divs de coluna (Código 3.5).
Bootstrap é um conjunto de ferramentas disponibilizado em forma de código livre, para o desenvolvimento de aplicações com uso de HTML, CSS, and Javascript (TEAM, 2020a). A versão atual do bootstrap utilizada durante a escrita deste texto é 4.4.1. O bootstrap faz uso de outras bibliotecas, especificamente: jQuery (biblioteca Javascript) e Popper (biblioteca para facilitar o posicionamento de elementos). Um conjunto de definições denominada Reboot também é utilizado, nas quais diversas configurações visuais são eliminadas e redefinidas pelo bootstrap. Dessa maneira, a exibição de elementos se torna mais similar quando o sistema é acessado por diferentes navegadores web.
Diante dos inúmeros recursos disponíveis pelo bootstrap, forma reunidos aqueles mais relevantes para o desenvolvimento de uma aplicação geral em três tabelas que organizam os elementos principais de conteúdo (Tabelas 3.1), componentes (Tabela 3.2) e alguns utilitários (Tabela 3.3). Cada tabela lista: i) a localização do recurso (caminho), partindo-se da página de documentação do bootstrap; ii) o nome da classe ou tag que implementa o recurso; iii) a descrição do recurso.
Localização | Recurso | Descrição |
Content > Typography > Aligment | text-center | Centralizar elementos (texto, imagens, etc). |
Content > Images > Alignment images | float-left, float-right | Posicionar imagens lado a lado. |
Content > Tables | table, table-striped, table-hover | Tabelas bonitas, zebradas e com destaque ao passar o mouse por cima. |
Content > Figures | <figure>, figure, figure-img, <figcaption>, figure-caption | Imagens acompanhadas por um título descritivo. |
Localização | Recurso | Descrição |
Components > Badges | badge, badge-primary, badge-warning, badge-danger | Pequenas caixas decoradas com textos informativos (por exemplo, contadores). |
Components > Buttons | btn, btn-primary, btn-success, btn-info | Decoração para botões. |
Components > Navs | <nav>, nav, nav-item, nav-link | Decoração para links de navegação. |
Components > Navbar | <nav>, navbar, nav-brand, navbar-toggler, collapse, navbar-collapse, navbar-nav, nav-item, nav-link | Barra de navegação! |
Components > Progress | progress, progress-bar | Barras de progresso. |
Localização | Recurso | Descrição |
Utilities > Borders > Border-radius | rounded, rounded-circle, rounded-pill | Bordas arredondadas e com outras formas aplicáveis em elementos (por exemplo, imagens). |
Utilities > Sizing | vh-100 | Ocupar toda a altura da página. |
Utilities > Spacing | mb-4, pt-2 | Fornecer espaços a elementos (margem e preenchimento - padding). Por exemplo, mb-4 significa margem inferior (bottom) do espaçamento padrão multiplicado por 1.5 |
O boostrap também possui classes quem facilitam a criação de grades. Considere como exemplo uma página que existe uma grade com uma linha, duas colunas na segunda linha e duas colunas na terceira linha (Figura 3.2).
Pode-se observar no código dessa página as tags que definem a utilização do bootstrap (Código 3.6). Inicialmente, são definidas tags para especificar a codificação dos caracteres usados na página (linha 6). A tag seguinte torna possível ao navegador exibir diferentes tamanhos da página conforme o dispositivo utilizado para exibição (linha 7). Na sequência, se inclui a folha de estilos utilizada pelo bootstrap (linha 10).
Fonte: https://github.com/hvescovi/programar2020/blob/master/
02-front-end/02-bootstrap/grade.html#L6
O corpo da página se inicia com a classe container, que abriga todo o conteúdo da página (Código 3.7, linha 16). São definidas as três linhas, com uso da classe row (linhas 17, 20 e 24) e a seguir são feitas as divisões em colunas (linhas 18, 21, 22, 25 e 26). O bootstrap disponiliza a possibilidade de especificar a largura de colunas, considerando-se uma largura máxima de 12 (doze) colunas. Na terceira linha do exemplo, a primeira coluna ocupa uma largura de tamanho igual a 1 (um), enquanto a segunda coluna ocupa uma largura de tamanho 11 (onze). Ambas medidas são relativas à largura de tamanho igual a 12.
Fonte: https://github.com/hvescovi/programar2020/blob/master/
02-front-end/02-bootstrap/grade.html#L16
Por fim, são incluidas nas páginas as bibliotecas javascript (Código 3.8, linhas 32 a 34). Há uma sequência correta na importação das bibliotecas. Além disso, a carga do javascript deve ser feito ao final da página, para que ela possa antes ser exibida e somente depois apresentar qualquer tipo de comportamento dinâmico provido pelo javascript.
Fonte: https://github.com/hvescovi/programar2020/blob/master/
02-front-end/02-bootstrap/grade.html#L32
Os navegadores web são dotados da capacidade de executar programas. Isso ocorre porque há vantagens em se realizar processamento no próprio navegador, em vez de ir até o servidor web buscar informações que poderiam ser realizadas no próprio navegador web. A linguagem adotada como padrão para a execução de programas no navegador web é a Javascript.
Observe a seguir uma página HTML (Figura 3.3) que possui exemplos simples de ações que podem ser realizadas com o javascript (adaptados de (WILSON, 2020)). Essa página e as demais que fazem uso do javascript estão disponíveis para que você possa acessá-las e experimentar seus recursos no seguinte endereço: http://www.hylson.com/javascript. Primeiramente, encontra-se uma caixa de texto que possui um valor inicial em seu conteúdo (Código 3.9, linha 10). Na caixa de texto existe uma definição de evento: se um valor for alterado na caixa de texto (onChange), será emitida uma mensagem de alerta (linha 11). O comando alerté um comando da linguagem javascript e exibe uma caixa de diálogo na tela, com uma mensagem.
Outra ação javascript da página é a obtenção da data atual (Código 3.10, linhas 15 a 17). O comando new Date() retorna a data atual, que é armazenada na variável hoje (linha 16). Esse comando de atribuição é envolvido pelas tags <script> e < nscript>. Quando um certo botão é clicado (linha 18), uma mensagem é exibida por meio da caixa de diálogo (comando alert).
Na sequência, encontra-se definida uma função chamada mudar_fundo (Código 3.11, linha 23). Diversas execuções do comando setTimeout são responsáveis por alterar a cor de fundo do documento (linhas 24 a 30). O comando setTimeout executa uma ação (primeiro parâmetro) após esperar um certo tempo especificado em milisegundos (segundo parâmetro). Após a definição da função, ela é associada ao clique de um botão (linha 33).
O quarto exemplo de comando javascript é o simples preenchimento de um texto na página quando a mesma é aberta (Código 3.12, linhas 37 a 39). O comando document.write exibe na página o texto informado como parâmetro. Esse texto é inserido na posição em que se encontra o comando.
Por fim, é apresentado outro código javascript que realiza prenchimento de um texto na página (Código 3.13, linhas 43 a 52). Porém, desta vez o texto é inserido em um local específico: um elemento da página identificado como “caixa” (linha 45). O comando document.getElementById localiza um elemento na página por meio de seu “id”. Uma vez localizado o elemento, ele pode ser manipulado, por exemplo, inserindo-se código HTML em seu interior. No caso, foi utilizada a propriedade innerHTML para inserir um novo texto que possui formatação HTML para exibição com letras grandes (tag H1, linha 46). O código javascript está encapsulado em uma função (linha 44), que é associada ao clique de um botão (linhas 49 e 50). Concluindo o código da página, o elemento chamado “caixa” é uma div (linha 51), que possui atualmente um texto sendo exibido em cor de fundo amarela. Após o acionamento do botão, apenas o texto será alterado (em seu conteúdo e tamanho).
Ação adicional javascript 1: confira um exemplo lúdico de javascript, no qual uma figura é alterada para simular o efeito de apagar e acender uma lâmpada: https://www.w3schools.com/js/tryit.asp?filename=tryjs_intro_lightbulb. Após a leitura desta seção, será que você consegue explicar o funcionamento desse código da lâmpada?
Ação adicional javascript 2: verifique o funcionamento dos exemplos “divertidos” de páginas com javascript neste endereço: http://www.hylson.com/javascript. Essas páginas foram criadas por alunos que cursaram a disciplina de Programação 2 no curso técnico em informática integrado ao ensino médio, do IFC Campus Blumenau, no ano de 2019. Verifique o código-fonte dessas páginas no link: https://github.com/hvescovi/programar2020/tree/master/02-front-end/03-javascript, dentro da pasta 01-divertidos. Os códigos desta seção usam, em geral, javascript puro. Teremos muito mais poder de programação com uso da biblioteca jQuery, descrita na seção a seguir.
A biblioteca jQuery consiste de um grande conjunto de funções escritas em javascript, e tem por objetivo facilitar o uso de javascript nas páginas HTML. Com jQuery, os comandos javascript podem ser utilizados de uma forma mais sucinta e fácil.
Considere como exemplo uma página HTML que possui uma caixa de texto e uma imagem (Figura 3.4). Acima da caixa de texto existe também uma div, cujo conteúdo será manipulado dinamicamente por linhas de código em javascript. Esses elementos podem ser identificados no código HTML da página (Código 3.14): a div (linha 12), a caixa de entrada (linha 14), um botão (linha 15) e a imagem (linha 16).
Para fornecer comportamento dinâmico à página, com uso das facilidades providas pela biblioteca jQuery, realiza-se a importação da biblioteca com o comando script (Código 3.15, linha 20). No exemplo, a importação é feita diretamente do site do jQuery.
Os comportamentos que estão programados para a página são os seguintes:
Fonte: https://github.com/hvescovi/programar2020/blob/master/
02-front-end/03-javascript/03-basico-jquery/index.html#L20
A execução correta do código javascript que utilizada a biblioteca jQuery na página é condicionada ao documento estar “pronto”, carregado com todos os seus elementos HTML. Para garantir isso, é comum embutir todo o script que faz uso da jQuery sob um comando que verifica se a página está carregada. Na versão mais recente da jQuery existe uma recomendação pelo uso da expressão reduzida $(function(){ (JQUERY, 2019), em detrimento do uso extendido $(document).ready(function(){. Porém, o fato de localizar os scripts ao final da página HTML dispensa a necessidade de se fazer a verificação de carregamento da página.
Exemplificando: se desejarmos proteger o nosso código javascript para que ele seja executado apenas quando a página estiver carregada, devemos localizar esse código conforme segue:
Outra forma de se utilizar esse comando seria assim:
Porém, como mencionamos, se o nosso código javascript estiver localizado ao final da página, o comando ready (ou sua forma reduzida) não é necessário, pois o código javascript será carregado naturalmente apenas depois que toda a página for carregada.
Desejamos agora fazer uma página que possa alterar dinamicamente a folha de estilos que é utilizada na página. Sendo assim, vamos criar três links para que cada um deles possa acionar uma folha de estilo diferente (Figura 3.5).
Na página HTML o link para o arquivo de folha de estilo deve ser criado possuindo um identificador (Código 3.16, linha 7), que será alterado conforme o usuário clica nos links. Deve haver três arquivos de estilo, sendo que inicialmente a página é exibida com o arquivo de estilo chamado “azul.css”. Cada link que altera o estilo possui em seu identificador o nome do arquivo de estilo a ser carregado quando o link for clicado (linhas 11 a 13).
A parte de código javascript inicia importando a biblioteca jQuery (Código 3.17, linha 16). A seguir, o evento de clique de mouse é capturado e associado a qualquer elemento que utilize a classe de estilos chamada “mudar” (linha 19). Note que os links que mudam o estilo da página estão utilizando esse estilo. Quando o link for acionado, a folha de estilos da página é alterada (linha 22).
Vamos detalhar a linha de comando 22:
Após clicar no link amarelo, será exibida a página fazendo uso da folha de estilos “amarelo.css” (Figura 3.6). As folhas de estilo azul e amarelo variam apenas a cor de fundo e o tipo de letra utilizados (Códigos 3.18 e 3.19).
No terceiro exemplo, vamos apresentar uma página que contém uma figura que se move de acordo com a movimentação do mouse (Figura 3.7). O código HTML desta página contém a imagem do carro (Código 3.20, linha 12). Essa imagem é identificada pelo nome “carro” e possui um estilo de posicionamento absoluto, para que a mesma possa ter suas coordenadas alteradas dinamicamente. A biblioteca jQuery é importada (linha 14), seguido pela importação também do nosso código javascript (linha 15). Esse exemplo apresenta uma organização de arquivos na qual a imagem fica em uma pasta chamada “img” e os códigos javascript personalizados se encontram dentro de um arquivo externo, em uma pasta chamada “js”.
O código javascript inicia com a criação de uma variável local chamada mover (Código 3.21, linha 4). Essa variável indica se o carro deve se mover (valor igual a 1) ou se o carro deve ficar parado (valor igual a 0). A seguir, captura-se o evento de movimentação do mouse na tela (linha 7). Quando esse evento ocorrer (mousemove), serão realizadas diversas ações. É preciso, assim, embutir as ações no interior de uma função, e por isso existe a expressão funcion(event). Essa função, entretanto, não possui um nome e existe apenas para agrupar os comandos que estão em seu interior. A função inicia verificando se a movimentação do carro está ativada (linha 10). Em caso positivo, obtém-se as coordenadas atuais do mouse (event.pageX e event.pageY), que são atribuídas às propriedades top e left do elemento chamado “carro” (linhas 12 a 14). Essas propriedades são manipuladas por meio de estilos (por isso a propriedade se chama css), ainda que não haja um arquivo de folhas de estilo sendo utilizado no exemplo. Por fim, se ocorrer um clique de mouse (linha 20), esse evento muda a situação da variável mover (linha 22). Essa expressão de linha única significa que caso o valor da variável seja igual a 1, então deve-se atribuir zero à variável; caso contrário, deve-se atribuir 1 à variável. Assim, o valor é sempre alternado entre os valores zero e um.
AÇÃO ADICIONAL JQUERY: verifique o funcionamento dos exemplos de páginas com javascript que utiliza jQuery neste endereço: http://www.hylson.com/javascript. Verifique o código-fonte dessas páginas, disponíveis neste link: https://github.com/hvescovi/programar2020/tree/master/02-front-end/03-javascript/
Este capítulo abordou elementos que integram um front-end. Foram descritos fundamentos de código HTML e folhas de estilo CSS, essenciais na criação de páginas web. Introduziu também o framework bootstrap para fornecer uma melhor aparência e responsividade às páginas. Por fim, apresentou a linguagem javascript, que provê comportamento dinâmico às páginas, e incluiu exemplos de uso da biblioteca jQuery, a fim de simplificar o código necessário à execução de programas nas páginas web.
Os quatro amigos Pedro, Túlio, Gabriela e Agnes começaram a criar programas que manipulam uma quantidade maior de dados. Tornou-se, assim, necessário fazer um agrupamento de dados coerente. Pedro é o aluno mais metódico do grupo, e como pessoa prevenida que é fez uma leitura sobre um assunto que propõe uma forma viável de agrupar dados: o paradigma de orientação a objetos. Nesse paradigma, os dados são agrupados por analogia a objetos do mundo real. Por exemplo, os dados de uma pessoa são reunidos em um objeto do tipo “Pessoa”. As informações de um automóvel são reunidas em um objeto do tipo “Automovel”. Podem ser criadas várias pessoas e vários automóveis. Essas instâncias de pessoas e automóveis são denominados Objetos. A generalização de um objeto é denominada Classe. Portanto, da classe Pessoa pode-se instanciar uma pessoa com nome igual a “Joao da Silva”, telefone igual a “47 9923 3434” e email igual a “jsilva@gmail.com”. Essa organização de informações em uma classe é a base da orientação a objetos.
Túlio, que é ávido por resultados, complementa a apresentação desse conceito aos colegas, mencionando que existem também as ações que podem ser realizadas sobre os dados. Comportamentos ou ações são processamentos sobre os dados e podem ser vinculados, portanto, às classes. Por exemplo, um automóvel pode possuir uma ação chamada “ligar”, que provoca o acionamento do carro. Outra ação possível de um automóvel pode ser a ação “frear”. Cada ação definida em uma classe é denominada método da classe. Após uma discussão inicial sobre esses conceitos, os amigos buscaram na literatura algumas definições sobre o termo classe:
As classes são instanciadas em objetos, dos quais se pode invocar as operações públicas na forma de mensagens. No entanto, nem todas as classes permitem sua instanciação direta em objetos. As classes que permitem tal ação são chamadas classes concretas. Em muitos casos, pode ser necessária a criação de classes que apenas descrevem conceitos abstratos e que não são transformados em objetos diretamente, as chamadas classes abstratas. Essas classes devem ser herdadas por outras classes concretas, que irão implementar os conceitos abstratos criando uma classe concreta que pode ser instanciada. (DEBONI, 2003, p. 113)
Obtém-se também desse autor definições objetivas sobre a declaração de métodos de uma classe, bem como detalhamentos sobre os métodos nas classes concreta e abstrata:
A assinatura de uma operação ou método é o nome da operação e seu conjunto de parâmetros. Um método abstrato não possui o corpo do método no qual se encontra o algoritmo que o implementa. Uma classe abstrata pode possuir métodos concretos [...].Para uma classe abstrata torna-se concreta, ela deve ser herdada por outra que irá sobreescrever os métodos abstratos com métodos concretos. (DEBONI, 2003, p. 113)
Após a observação teórica dos conceitos, surgiu a necessidade de conhecer a aplicação prática dessas definições.
Como início dos estudos, Gabriela tomou a palavra e sugeriu aos amigos fazer um programa abordando apenas informações básicas e conhecidas por todos. Recomendou, assim, armazenar apenas as informações sobre uma pessoa: nome, email e telefone.
Pedro apresentou a seus amigos a forma mais básica de implementar um classe Pessoa (Código 4.1). Foi criado um módulo (pacote) denominado modelo (linha 1) para agrupar as classes, que são modelos de objetos do mundo real. O nome da classe foi definida como “Pessoa” (linha 3), e os atributos de nome, email e telefone foram definidos como sendo do tipo texto (tipo String; linhas 5 a 7). Após a criação da classe, é preciso fazer um “teste” do programa, criando objetos. Toda classe no Java possui um método executável denominado “main” (linha 9). Esse método permite ao programa Java tornar-se um programa “executável”. Sendo assim, como primeira ação criou-se um objeto do tipo pessoa (linha 11). A seguir, foram definidos valores para o objeto (linhas 13 a 15). Por fim, foram exibidos os valores do objeto, para fins de teste da classe (linha 17).
Pedro, que é o rapaz “certinho” e adora seguir os padrões, observou a primeira versão do programa e sugeriu a primeira mudança: separar o programa em duas partes. A primeira parte vai conter apenas o código do programa de “definição da pessoa” (Código 4.2). Nesse programa temos apenas as informações que serão armazenadas pela classe (Código 4.2, linhas 5 a 7). Esse código pode ser utilizado posteriormente por outros programas para “criar” pessoas, definir os valores dos dados dessas pessoas e utilizar essas informações.
O segundo programa será um código apenas para fazer um “teste” da classe Pessoa (Código 4.3). Em outras palavras, esse programa de teste serve para verificar se a classe funciona da forma esperada.
Após a leitura cuidadosa dos códigos por todos, inicia-se um diálogo entre os amigos:
— (Túlio) Olha só, por que a palavra public foi inserida na classe Pessoa? — (Pedro) Essa declaração é necessária porque uma OUTRA classe vai usar a classe Pessoa. Quando a gente não declara uma classe pública, ela não pode ser usada por outras classes. — Ok. Obrigado. Notei que essa palavra (public) também entrou nos atributos da classe (linha 3 do Código 4.2). Confere? — Sim. Assim como a classe vai ser usada por outro programa, se os atributos vão ser modificados por outro programa, é necessário torná-los públicos. Caso contrário, não poderiam ser acessados diretamente. — Mais alguma mudança nesse código “separado”? — Sim! Como o programa de teste “usa” a outra classe, é preciso declarar esse uso. Em outras palavras, importar a classe (linha 3 do Código 4.3). — (Gabriela) Que legal! E de onde vem essa classe importada? — (Pedro) Vem do código que declara a classe. Ambos os códigos estão no mesmo projeto, apenas encontram-se em pacotes separados. A definição da classe está no pacote modelo e o programa que usa uma instância da classe está na classe teste. — (Agnes) Tá falando difícil hein Pedro? O que é instância? — É um objeto da classe rsrs isso não é difícil. — Agora não mais! Obrigada! |
Em determinado momento que os amigos estavam programando, alguém se deu conta de que já havia visto em algum exemplo de programação um comando que criava objetos no qual os valores do objeto eram informados todos de uma só vez, juntamente com o comando de instanciação. Agnes não se conteve com esse comentário e procurou na internet algo sobre isso. Encontrou, assim, informações sobre o termo “construtor”. E inicia-se um diálogo:
— (Agnes) Pessoal, para tudo! Encontrei uma forma mais simples e concisa de criar objetos. É só a gente usar um construtor com parâmetros. — (Pedro) Hahaha! Isso tá parecendo conversa de construção civil. — É sério! Quando for criar o objeto, já dá pra informar todos os valores dos campos junto com o nome da classe. — (Túlio) Interessante. Tens um exemplo? — Sim! Vou mostrar com esse exemplo da classe Pessoa que estamos desenvolvendo. Olha só, em vez de usar só o comando new Pessoa(), eu posso colocar diretamente os dados da pessoa dentro dos parênteses. Fica assim: new Pessoa(“João da Silva”, “jsilva@gmail.com”, “47 9 9223 1001”). — (Gabriela) Gente! Amei. Menos linhas de código! Fica mais compacto assim. Mas como vou saber a ordem dos dados? Por que você colocou email e depois o telefone? — (Agnes) Hum... em algum lugar isso está definido. Essa ordem é a gente que estabelece. Aí quando for usar basta seguir a ordem). |
Nesse momento de leitura do código, Gabriela tem uma dúvida e não se demora a pergunta:
— (Gabriela) Pessoal, quem pode me explicar o que significa essa palavra this? — (Pedro) Em que lugar Gabriela? — Ali na linha 16 do Código 4.4. — Hum... ok. A questão é a seguinte: os valores dos atributos nome e email foram passados via parâmetro pelo construtor sob os seguintes nomes, respectivamente: n e e. Certo? — Sim. E o terceiro parâmetro foi informado sob o seguinte nome de parâmetro: telefone — Muito bem. Agora imagine se a atribuição do valor do parâmetro para o atributo fosse executada da seguinte forma: telefone = telefone. O que você acha? — Estranho. É igual fazer x = x. E agora? — Então, por isso foi utilizada a palavra this. Ela significa que o nome utilizado a seguir é um atributo da classe, ou seja, pertence a esta classe. Assim, deseja-se que o valor do parâmetro seja atribuído ao valor do atributo: this.telefone (valor do atributo) = telefone (valor do parâmetro). — Beleza Pedro! Entendi. Obrigada! |
Durante os estudos de nossos quatro amigos, Gabriela pensou se não havia uma maneira de validar dados no momento em que os objetos eram criados. Esse é um nível muito baixo de validação, mas essa dúvida não saiu de sua cabeça. Inicia-se assim um diálogo:
— (Gabriela) Pessoal, tenho uma questão. Será que existe uma forma de validar os dados de um objeto no momento em que esse objeto é criado? — (Agnes) Ah, você poderia colocar um “if” no programa que testa o objeto, para verificar os valores desejados. — Sim, mas eu gostaria de fazer essa validação dentro da própria classe que fornece os objetos. — (Pedro) Isso não é trivial, se você acessar diretamente o atributo como estamos fazendo. Por exemplo, se eu utilizar p1.email = “mariasilva@gmail.com”, como vou fazer para verificar se, por exemplo, foi informado o caracter arroba no email? — (Tulio) Gente, tenho a resposta pra vocês. Eu já fiz exatamente isso uma vez: validar email. O que precisa ser feito é usar um método para colocar o valor no atributo, em vez de acessá-lo diretamente. — (Gabriela) Que legal! Posso fazer um método, por exemplo, chamado informarValorDoEmail? — (Tulio) Não. Existe um padrão para esses métodos, que são inclusive conhecidos como setters e getters. — (Pedro) Na verdade, até poderia usar o seu nome sugerido. Mas realmente ia ficar fora do padrão, e isso não é bom, né? — (Agnes) Ah, quem sabe alguém poderia imaginar um nome melhor para o método que vai colocar o valor de um email. — (Pedro) Vamos lá, foco! O nome ideal para o método que coloca valor no campo email é setEmail. — (Gabriela) Certo. E dentro desse método, daí, eu verifico se o valor informado tem uma arroba. Certo? — (Tulio) Certo. |
O programa que faz uso da classe Pessoa (Código 4.7) instancia dois objetos: João (linha 9) e Maria (linhas 15 e 16). Os dados de João são informados um de cada vez (linhas 11 a 13), enquanto os dados de Maria são informados no mesmo momento da criação do objeto (linhas 15 e 16). Por fim, os objetos criados tem seus valores exibidos (linhas 18 a 21). Essa ação de exibição é importante para saber se o objeto teve seu funcionamento conforme esperado.
Túlio foi o responsável por apresentar a classe Pessoa em uma implementação mais sucinta na linguagem python (Código 4.9). O construtor da classe é definido pelo método __init__ (linha 4), no qual existem parâmetros que podem receber os valores do objeto. A palavra self define que o método pertence à classe. Dentro do construtor, os atributos são declarados também usando o termo self (linhas 5 a 7). Tal termo é similar ao this do Java. Cada valor de parâmetro do construtor é associado ao respectivo atributo. Um método denominado __str__é criado para facilitar a execução dos testes (linha 10). Esse método expressa um objeto da classe em termos de string, e também usa o termo self para demonstrar sua associação com a classe (ele pertence à classe).
Fonte: https://github.com/hvescovi/programar2020/blob/master/
01-oo/01-pessoa/python/modelo.py#L1
Iniciando os testes da classe (Código 4.8), verifica-se que o programa está sendo executado ou importado por outro arquivo (linha 16).Caso esteja sendo executado, realiza-se o teste da classe, iniciando com a criação de uma pessoa (linha 19). Os dados da pessoa são informados nas linhas seguintes (19 a 21). O construtor permite criar pessoas também informando os valores diretamente (linha 24). Além disso, podem ser informados apenas alguns valores (linha 27), sendo que os valores obedecem à ordem de declaração definida no construtor. Por fim, todos os dados das pessoas são exibidos (linha 30).
Fonte: https://github.com/hvescovi/programar2020/blob/master/
01-oo/01-pessoa/python/modelo.py#L1
A execução do programa resulta na exibição de todos os dados que foram definidos (Tabela 4.1).
Considere um programa que exibe alguns dados cadastrais de uma pessoa (Código 4.10). Considerando as informações de nome, data de nascimento e número de RG, essas três informações podem ser armazenadas em três variáveis (linhas 6 a 8). A seguir, as informações são exibidas (linha 10).
O mesmo programa pode ser construído segundo um paradigma de orientação a objetos (Código 4.11). Os dados da pessoa são agora informados logo após a declaração da classe (linhas 4 a 6), e o método main da classe agora cria uma variável do tipo Pessoa (linha 8), associa valores aos atributos do objeto (linhas 9 a 11) e exibe os dados (linhas 13 e 14). Compare as versões dos programas estruturado e orientado a objetos para poder observar as diferenças.
Fonte: https://github.com/hvescovi/programar2020/blob/master/
99-fundamentos/java/basico/Pessoa.java#L1
A orientação a objetos muda a maneira como as ações são invocadas sobre os dados. Como exemplo, considere a execução de funções matemáticas. Para calcular a raiz quadrada de um número, na linguagem PHP utiliza-se a função sqrt será aplicada ao número 9. O comando em PHP, portanto, é o seguinte: echo sqrt9;. Na orientação a objetos, em Java, existe uma classe Math que possui o método estático sqrt. Dessa forma, para se obter uma raiz quadrada de nove, executa-se o comando: Math.sqrt(9) (Código 4.12, linha 10). O comando sqrté um método, e não simplesmente uma função. Esse método é estático, pois não é preciso instanciar um objeto da classe Math, e pertence à classe Math.
A manipulação de texto é mais um exemplo prático de como a orientação a objetos altera a forma de realizar as operações. Para obter uma substring de um texto, na linguagem PHP se utiliza a função substr, informando o texto, o início e a quantidade de caracteres. Desse modo, o comando substr(“Alô mundo”, 4, 3) retorna a substring “mun”, pois a substring inicia na posição 4 (contando a partir de zero) e retorna os próximos 3 caracteres. É possível testar esse comando no site http://phptester.net/. Em java, a ação de obter uma substring é realizada pelo comando substring, mas não como uma função, e sim como um método. Isso significa que em vez de aplicar o comando à string, o comando “faz parte da string”, ele “está na string”, é uma ação que “vem junto” com o objeto string. Nesse caso, então, a substring “mun” pode ser obtida usando o método substring do objeto (Código 4.13, linha 15). Os parâmetros do método substring são a posição inicial e a posição final, de forma que o caracter da posição final não será incluído no retorno do método. Note que o comando de obter substring do java é diferente com comando de obter substring do PHP, tanto no nome do comando quanto no significado de um dos parâmetros. O comando substring está disponível no objeto do tipo String (linha 13). Uma outra possibilidade é aplicar o método substring diretamente em uma string, sem declarar variável (linha 18). Isso é possível pois, em Java, qualquer String é considerada um objeto, mesmo que esse objeto não possua uma referência direta (uma variável apontando para ele). No caso do exemplo, não existe uma variável apontando para o conteúdo “Tudo vira objeto” (existente na linha 18).
Por fim, considere o caso de calcular o perímetro de um círculo e exibir as informações desse círculo (Código 4.14). As coordenadas do círculo são armazenadas em variáveis apenas para localizar o círculo em um plano cartesiano (linhas 22 e 23). O raio é a informação necessária para o cálculo do perímetro (linha 24), que consiste em 2