Logo Passei Direto
Buscar
Material
left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

Prévia do material em texto

DESENVOLVIMENTO DE SISTEMAS
Allen Oberleitner
Luís Carlos S. Silva
Editora Senac São Paulo – São Paulo – 2020
 
 
Sumário
Capítulo 1 
Apresentação inicial sobre desenvolvimento de
sistemas
1 Evolução do desenvolvimento de sistemas
2 Utilização dos conceitos na prática
Considerações finais
Referências
Capítulo 2 
Introdução a algoritmos
1 Introdução a algoritmos
2 Conceitos de algoritmos
3 Descrição narrativa de um algoritmo
4 Representação de algoritmos por fluxograma
Considerações finais
Referências
Capítulo 3 
Algoritmos variáveis
1 Programação imperativa
2 Utilização de pseudocódigo
3 Declaração de variáveis e constantes
4 Expressões aritméticas, literais, relacionais e de lógica booleana
Considerações finais
Referências
Capítulo 4 
Algoritmos: condicional
1 A arte de tomar decisões
2 Estrutura de controle condicional simples
3 Estrutura de controle condicional composta
Considerações finais
Referências
Capítulo 5 
Algoritmos: repetição
1 Repetir para aprender
2 Enquanto-faça (while)
Considerações finais
Referências
Capítulo 6 
Algoritmos: vetores
1 Teoria dos conjuntos
2 Conceito de vetores
3 Manipulando vetores
Considerações finais
Referências
Capítulo 7 
Algoritmos: matrizes
1 Matriz é tabela?
2 Conceito de matriz
3 Manipulando matriz
Considerações finais
Referências
Capítulo 8 
Programação estruturada
1 Linguagem de programação
2 Linearidade
3 Programação estruturada
Considerações finais
Referências
Capítulo 9 
Programação: funções e procedimentos
1 Conceitos de função
2 Procedimento
3 Aplicando funções
Considerações finais
Referências
Capítulo 10 
Programação: arquivo
1 Processo arquivado!
2 Conceitos de arquivo
3 Manipulando arquivo
Considerações finais
Referências
Capítulo 11 
Programação orientada a objetos
1 Conceito de POO
2 Classes e objetos
3 Aplicação de POO
Considerações finais
Referências
Capítulo 12 
Programação orientada a objetos: classes
1 Composição da classe
2 Instâncias
Considerações finais
Referências
Capítulo 13 
Programação orientada a objetos: Python
1 Linguagem orientada a objetos
2 Conceitos de Python
3 Aplicação de POO: Python
Considerações finais
Referências
Capítulo 14 
Banco de dados
1 Armazenamento de dados
2 Modelos de banco de dados
3 Conceito de banco de dados
4 Instâncias ou ocorrências de uma entidade
Considerações finais
Referências
Capítulo 15 
Linguagem SQL
1 Utilização de SQL nas aplicações
Considerações finais
Referências
Capítulo 16 
Atualização de tabelas em aplicações
1 Conceitos de CRUD (Create, Read, Update, Delete) para SQL
Considerações finais
Referências
Sobre os autores
Capítulo 1
Apresentação inicial sobre
desenvolvimento
de sistemas
Estamos na era dos nativos digitais, pessoas que já nasceram
em um mundo automatizado, virtualizado e conectado à internet.
Mas como essa tecnologia chegou ao que conhecemos hoje?
Na segunda metade do século XX, após o fim da guerra mundial,
os primeiros softwares começaram a surgir. Até aquela época, os
computadores eram programados por meio de chaves manuais e sua
utilização era muito trabalhosa e restrita, se comparado aos dias
atuais.
Essa primeira era de softwares foi marcada pelo uso básico, pois
naquela época não havia muito interesse no desenvolvimento. Como
os computadores eram muito limitados, era possível executar apenas
um programa de cada vez.
Com a visão de novas possibilidades e as necessidades do
mercado, os computadores começaram a ficar maiores, deixaram de
utilizar válvulas – que eram lentas e de alta manutenção, pois
queimavam muito –, migrando para a utilização de componentes
microeletrônicos, que, mesmo nas primeiras versões, já
apresentavam um poder computacional muito maior.
Conforme as décadas foram passando, assim como a tecnologia
dos computadores cresceu exponencialmente, os softwares
buscaram acompanhar essa evolução, otimizando os recursos e
trazendo novas funcionalidades para este poder computacional.
1 Evolução do desenvolvimento de
sistemas
No mundo digital em que vivemos, a utilização de programas e
sistemas está presente em praticamente tudo que nos cerca, mas
para chegarmos onde estamos hoje a programação de softwares
passou por um longo caminho.
A evolução da programação está diretamente ligada à história
dos computadores, e, para entendermos melhor esse conceito,
falaremos um pouco sobre isso.
“A necessidade de desenvolver ferramentas que facilitassem o
uso e o manuseio de operações de cálculos fez com que o ser
humano chegasse ao estágio atual de desenvolvimento da área da
computação” (MANZANO, 1996, p. 17).
A palavra computador significa o que computa ou aquele que
calcula. Na verdade, os computadores não só calculam, mas também
executam outras tarefas associadas, como receber, transmitir e
armazenar dados.
Todo o computador é composto essencialmente por duas
partes, conforme a figura 1:
Figura 1 – Hardware versus software
Fonte: adaptado de Capron; Johnson (2004).
1.1 Como tudo começou
O Eniac foi o primeiro computador digital de larga escala,
construído para quebrar códigos de comunicação do exército inimigo
e realizar vários tipos de cálculos, principalmente de artilharia, afim de
ajudar as tropas aliadas durante a Segunda Guerra Mundial; contudo,
foi mais utilizado nos últimos anos da Guerra Fria.
Segundo Platzman (1979), ele foi construído na escola Moore
por ordem do exército dos EUA. A equipe contava com o engenheiro-
chefe J. Presper Eckert, atuando inicialmente nos conceitos básicos
desenvolvidos por John W. Mauchly, que atuou como principal
engenheiro construtor e como consultor do departamento da
artilharia americana Herman H. Goldstine. O matemático húngaro
John Von Neumann também participou do projeto, desenvolvendo
uma lógica de números pseudoaleatórios, que trouxe um grande
ganho de desempenho. Este computador foi construído na década de
1940, sendo composto por quase 18 mil válvulas, utilização que
marca a primeira geração de computadores e originava repetidos
problemas de manutenção, pois estas queimavam com frequência.
De acordo com Matsuura (2016), mulheres como Ada Lovelace e
Grace Hopper foram fundamentais para o avanço dos softwares. As
seis programadoras do projeto Eniac criaram o sistema do primeiro
computador eletrônico digital, mas nenhuma recebeu o devido
crédito.
Embora o sistema operacional do Eniac fosse feito por cartões
perfurados, a programação não era através de linguagem, e sim por
chaves manuais. Larry Gonick (1983) explica que as válvulas, entre
outras funções, mostravam o resultado dos cálculos, da mesma
maneira que hoje usamos os monitores.
Mesmo que a sua arquitetura seja enorme, a quantidade de
processamento não se comparava à dos computadores atuais.
1.2 O início de uma revolução
No fim da Segunda Guerra Mundial, na década de 1940, a
maioria das pesquisas em todo o mundo, principalmente nos EUA e
na Inglaterra, sobre programas era financiada pelos governos e
desenvolvida como projetos de ciência por universidades, e outras,
mais específicas, pelo exército. Os computadores eram muito
grandes e caros, por isso só eram usados por especialistas. Era um
mundo ainda muito restrito, e as comunidades de especialistas
trabalhavam juntas para chegar a programas que fizessem os
computadores executarem tarefas específicas. Nesta fase, não
existiam grandes investimentos, pois ainda não interessava às
empresas e ao público.
O sistema operacional utilizado era o Unix, desenvolvido pela
AT&T nos laboratórios Bell, em 1969; já os hardwares não eram
específicos, montados conforme a necessidade, utilizando uma
mistura de componentes definidos e configurados por eles. Esses
computadores ficavam muito grandes e eram utilizados em salas
bem espaçosas.
Na metade do século XX, o mundo iniciou uma grande evolução
da tecnologia, unindo os conhecimentos científicos e a produção
industrial. As indústrias concentraram seus trabalhos na pesquisa e
conhecimento, dando início à chamada 3ª Revolução Industrial.
Como início do interesse das empresas pelos computadores,
eles começaram a receber configurações padronizadas e uma
considerável redução de tamanho.
1.3 O nascimento da Apple
Pouco depois, em meados dos anos 1970, dois jovens muito
talentosos decidiram criar algo para o público. Steve Wozniak –
detentor de grandes conhecimentos em programação – e Steve Jobs
– um gênio em vendas – uniram suas habilidades e criaram a
primeira empresa a vender computadores de boa performance para
usuários sem grande conhecimento. Assim nascia a Apple.
A intenção era desenvolver um computador confiável,
relativamente pequeno e que pudesse ser usado em qualquer
residência; para isso, utilizaram o sistema Unix, o mesmo sistema
empregado pelos especialistas, mas com comandos mais simples e
um ambiente mais amigável. Queriam que fosse tão popular quanto
um eletrodoméstico.
 PARA SABER MAIS
Até hoje, o fator de maior sucesso da Apple é o cuidado com os
clientes: mais potência nas configurações, utilizando os
componentes mais seguros do mercado e menos botões por fora,
ou seja, o mais simples e intuitivo possível para os usuários.
Quinafelex (2014) destaca o lançamento do Apple I no
Homebrew Computer Club – clube criado por entusiastas de
tecnologia, que se reuniam no Vale do Silício. Esse modelo era
formado por um kit com placa principal, que poderia ser comprada
em pequenas lojas. Esse kit tinha de se “adaptar”, pois não possuía
seu próprio gabinete. O aparelho tinha um processador de 1 MHz e
uma memória RAM de 8 KB. Inicialmente, o preço era por volta de
US$ 667.
1.4 Microsoft, uma nova visão entra no mercado
Segundo Bill Gates (1995), com o interesse do público crescendo
pela aquisição de computadores pessoais, empresas como a IBM
tinham o controle da produção de hardwares e decidiram fabricar
seus próprios computadores.
O grande problema era que a Apple não concordou em fornecer
seu sistema operacional, uma vez que sua intenção também era
vender um produto completo, com hardware e software juntos.
Neste cenário, surgiram Bill Gates, Paul Allen e Steve Ballmer.
Eles aceitaram o desafio de, em um curto espaço de tempo, fornecer
um sistema operacional. Sabendo que tinham um grande desafio e
pouco tempo para entregar, em 1980 compraram o “QDOS” – um
sistema operacional com várias falhas e bugs. Corrigindo os erros e
realizando diversas melhorias, o transformaram no DOS – Sistema
Operacional de Disco (da sigla em inglês, disk operating system).
Assim, conseguiram cumprir o prazo e entregar o sistema para o
grupo de empresas.
Figura 2 – Tela da DOS – sistema operacional da Microsoft
Atelsek (1983) compara o sistema operacional do PC a uma
caixa de ferramentas que temos em casa. Primeiro, colecionamos as
mais básicas ou essenciais, que realizam as tarefas mais simples,
como uma chave de fenda, um alicate, um martelo, etc. Conforme
vão surgindo outras necessidades, vamos adquirindo ferramentas
mais específicas, como furadeira, serra elétrica e outras.
A Microsoft, diferente da Apple, utilizou a tática de fornecer o seu
sistema para o máximo de fabricantes de hardware possível. Esta
tática acabou trazendo vários problemas, como incompatibilidade
com o hardware de alguns fabricantes e até problemas de segurança
com vírus.
Tanenbaum (2009) diz que as primeiras versões do Windows
apresentavam uma tela colorida com recursos gráficos, mas ainda
utilizam muitos arquivos de configuração do DOS.
1.5 Uma grande mudança no mercado
A possibilidade da utilização dos computadores nas casas e
escritórios impulsionou grandes mudanças na economia e no
mercado de trabalho.
Segundo Rifkin (2014), com a aplicação da tecnologia nas
indústrias, inicialmente, os valores dos produtos não eram baixos,
mesmo utilizando pouca matéria-prima, pois os gastos com estudos
e pesquisas eram altos.
Neste contexto, as atividades que mais se destacaram no
mercado eram as vinculadas à produção de softwares, computadores
e os circuitos microeletrônicos. Estes produtos estavam em alta, pois
eram necessários para a produção de equipamentos na área da
robótica, telefonia, televisão e internet.
Figura 3 – Linha de montagem da indústria automobilística
utilizando robôs autômatos
Fica claro um ciclo de dependência entre eles, sendo que a
inovação de um item afeta diretamente a evolução dos demais.
Na década de 1990, com o surgimento dos computadores com
ambiente gráfico e a popularização da internet, as empresas
começaram uma corrida para acompanhar esse crescimento.
A rotina dos escritórios, naquela época, era muito diferente do
que vivemos nos dias de hoje. Como os computadores ainda não
eram utilizados para estas atividades, tudo era feito em folhas de
papel e armazenado em grandes fichários e arquivos. Como a
internet ainda não era usada, todos os documentos eram enviados e
recebidos por meio de cartas e malotes.
Era necessário transformar todos aqueles documentos, fichas e
planilhas em documentos digitais e registros organizados em banco
de dados.
No mercado de trabalho também tivemos grandes mudanças,
como por exemplo uma corrida para formar e preparar os
funcionários para essa nova tecnologia. Também cresceu muito o
trabalho temporário, contratando digitadores para realizarem essa
transação digital, uma vez que ainda não havia programas de
digitalização confiáveis como temos nos dias de hoje.
O mercado de softwares começou a criar programas para
atender às empresas – eram programas que realizavam tarefas
específicas, sem nenhuma integração. Era muito comum andarmos
por uma loja de materiais de escritório e nos depararmos com
prateleiras repletas de caixas parecidas com caixas de cereais,
contendo os mais diversos títulos de aplicação, como por exemplo
controle de estoque, cadastro de clientes, folha de pagamento,
controle de vendas, etc.
O grande problema desses programas era a falta de integração
entre eles; por exemplo, como o programa de vendas não estava
interligado com o controle de estoque, a atualização no estoque
referente às vendas feitas no dia tinha de ser feita manualmente, no
fim do expediente ou no início do dia seguinte. Outro aspecto
negativo era o fato de nem sempre esses programas terem o formato
necessário para aquele determinado serviço, uma vez que eram
genéricos e produzidos em massa.
Atualmente, os softwares são desenvolvidos exclusivamente,
conforme a necessidade de cada empresa. São sistemas integrados
que não atendem a todas as áreas da empresa, automatizando todas
as informações, mas também se conectam com as filiais, empresas
parceiras e fornecedores.
2 Utilização dos conceitos na prática
Nos dias atuais, temos vivenciado um crescimento exponencial
da tecnologia – os sistemas desenvolvidos hoje executam atividades
complexas, impensáveis há poucos anos.
Acabamos não percebendo, mas ela está a nossa volta, em
todos os lugares – chamamos isso de computação ubíqua.
Weiser (1999) firmou esse termo com a ideia que as tecnologias
mais profundas são aquelas que desaparecem, referindo-se à
conexão de dispositivos que nem se fazem notar, mas estão por toda
a parte.
Utensílios de uso diário, como smartphones, tablets, televisores,
computadores de bordo de carros, eletrodomésticos, sistemas de
segurança, etc., todos estão conectados à internet e incorporados a
nossos hábitos, facilitando o nosso dia a dia.
Essas são algumas das fontes do oceano de dados que é o Big
Data – tecnologia que hoje traz avanços a todas as áreas, cruzando
dados e formando soluções.
Hoje, podemos ver na prática os grandes avanços e poderíamos
citar centenas de inovações, mas vamos falar das mais impactantes.
2.1 A Internet das Coisas
Segundo a SAP (2018), a Internet das Coisas é uma rede
composta de objetos físicos, que podem ser veículos, máquinas,
eletrodomésticos, etc. Esses objetos utilizam sensores e APIs para se
conectar e trocarem dados pela internet.
Utilizando várias tecnologias, como aplicativos, dispositivos
eletrônicos e internet, ela integra, monitora e realiza uma série de
eventos.
Podemos encontrar essatecnologia em diversas áreas de
nossas vidas, no computador de bordo de um carro, em
equipamentos de segurança em nossa residência, em
eletrodomésticos, e muitos outros.
2.2 Inteligência artificial e cognitiva
A inteligência artificial é a área da tecnologia que se propõe a
elaborar sistemas baseados em algoritmos complexos, que simulem
a capacidade humana de analisar e resolver os problemas e tomar
decisões.
Já a inteligência cognitiva, segundo D’Egmont (2016), difere da
inteligência artificial, porque o sistema cognitivo é capaz de aprender.
O exemplo mais famoso desse sistema é o Watson da IBM, uma
plataforma de serviços cognitivos, ou seja, você pode ensiná-lo a
resolver problemas. Hoje, ele é utilizado para as mais diversas
aplicações, desde atendimentos telefônicos e chats, até auxílio na
leitura de exames médicos complexos.
Além de aprender com as informações que recebe, ele também
conta com uma aplicação que reconhece o que compõe a imagem.
Esse recurso pode ser utilizado em diversas atividades, tendo um
espaço especial na segurança.
Considerações finais
O desenvolvimento de sistemas está em ciclo de evoluções
contí nuas. Em relação a outras ciências que os homens estudam, a
tecnologia é a que mais cresce e contribui para o progresso das
demais. Ela é muito nova, tem décadas, mas já se tornou vital para
todos.
Os ciclos têm sido cada vez mais curtos, pois a disseminação de
conhecimento é maior a cada dia e vemos profissionais do mundo
inteiro trazendo mais e mais inovações. A necessidade de adaptação
a este novo mundo é cada vez maior.
Referências
ATELSEK, Jean. Tudo sobre computadores. São Paulo: Editora Quark,
1983.
CAPRON, H. L.; JOHNSON, J. A. Introdução à informática. 8. ed. São
Paulo: Editora Pearson Prentice Hall, 2004.
D’EGMONT, Tahiana. O que é Watson? Plataforma cognitiva?
Inteligência artificial? Um robô?, 16 dez. 2016. Disponível em:
<https://www.ibm.com/blogs/digital-transformation/br-pt/o-que-e-
watson-plataforma-cognitiva-inteligencia-artificial-robo/>. Acesso em:
27 ago. 2018.
GATES, Bill. A estrada do futuro. São Paulo: Companhia das Letras,
1995.
GONICK, Larry. Introdução ilustrada à computação. São Paulo:
Harper & Row do Brasil, 1983.
MANZANO, J. A. N. G.; Oliveira, J. F. Algoritmos: lógica para
desenvolvimento de programação. São Paulo: Editora Érica, 1996.
MATSUURA, S. Hoje minoria da indústria de tecnologia, mulheres
foram fundamentais na gênese da computação, 14 fev. 2015.
Disponível em: <https://oglobo.globo.com/sociedade/historia/hoje-
minoria-na-industria-de-tecnologia-mulheres-foram-fundamentais-na-
genese-da-computacao-15336779#ixzz5PJ1tCp6j>. Acesso em: 27
ago. 2018.
PLATZMAN, G. W. The ENIAC computations of 1950 — gateway to
numerical weather prediction. Bulletin of the American
Meteorological Society, v. 60, 
n. 4, p. 302-312, 1979.
https://www.ibm.com/blogs/digital-transformation/br-pt/o-que-e-watson-plataforma-cognitiva-inteligencia-artificial-robo/
https://oglobo.globo.com/sociedade/historia/hoje-minoria-na-industria-de-tecnologia-mulheres-foram-fundamentais-na-genese-da-computacao-15336779#ixzz5PJ1tCp6j
QUINAFELEX, R. Confira a evolução dos computadores de mesa da
Apple, desde a origem. 27 out. 2014. Disponível em:
<https://www.techtudo.com.br/noticias/noticia/2014/10/confira-
evolucao-dos-computadores-de-mesa-da-apple-desde-origem.html>.
Acesso em: 27 ago. 2018.
RIFKIN, J. A Terceira Revolução Industrial. São Paulo: Bertrand
Editora, 2014.
SAP. O que é Internet das Coisas (IoT)? [s. d.]. Disponível em:
<https://www.sap.com/brazil/trends/internet-of-things.html>. Acesso
em: 27 ago. 2018.
TANENBAUM, A. S. Sistemas operacionais modernos. 3. ed. São
Paulo: Editora Pearson Prentice Hall, 2009.
WEISER, Mark. The computer for the 21st century. obile Computing
and Communications Review, v. 3, n. 3, p. 3-11, 1999.
https://www.techtudo.com.br/noticias/noticia/2014/10/confira-evolucao-dos-computadores-de-mesa-da-apple-desde-origem.html
https://www.sap.com/brazil/trends/internet-of-things.html
Capítulo 2
Introdução a algoritmos
Quando perguntamos o que é algoritmos, muitas pessoas
associariam a algo difícil ou os relaciona a conceitos complexos de
cálculos ou algo assim. Mas será que a primeira impressão está
correta?
Algoritmos na verdade são conceitos simples que usamos em
nosso dia-a-dia. Hoje em dia temos os algoritmos digitais em várias
tarefas do nosso cotidiano.
Quando você acessa um site, faz uma busca, lê os seus e-mails,
se relaciona com seus amigos através de redes sociais e até mesmo
faz aquelas compras on-line, isso tudo só é possível por causa dos
algoritmos. Mesmo quando estamos jogando um jogo, pode ser
aquele joguinho mais simples que você tem no seu smartphone até
aquele mais pesado que só funciona no seu console favorito, os
algoritmos estão trabalhando para te dar diversão.
Seria quase impossível imaginarmos a possibilidade de realizar
tantas tarefas como as que hoje nos sãos impostas sem as
facilidades proporcionadas pelos algoritmos digitais. Utilizamos
algoritmos todo tempo, no computador de bordo dos carros, nos
programas de celular, até mesmo em outros aparelhos mais simples
como um micro-ondas ou um refrigerador, tudo isso é possível
através dos algoritmos.
1 Introdução a algoritmos
Os algoritmos são tão antigos quanto a matemática, os
especialistas divergem muito sobre a sua origem. Temos associado
esta palavra à computação, mas este é um termo que pode ser usado
para várias ciências, inclusive ela nem nasceu da computação. A
teoria mais defendida sobre sua origem é a de que um grande
matemático que viveu na Pérsia no século IX chamado Abu Abdullah
Mohammad Ibn Musa Al-Khawarizmi, nascido em Khawarizm
(Kheva), ao sul do mar Aral.
Sua influência no crescimento de diversas áreas da ciência,
particularmente na matemática e outras como astronomia e
geografia é bastante notória. Ele tinha dentre estas obras, a de nome
Algorithmi de numero indorum (em indiano), que falava sobre
algoritmos que trabalhavam com o sistema de numeração decimal.
Suas obras só foram descobertas e apresentadas ao ocidente no
século XI.
O nome foi sofrendo mudanças por causa da pronuncia de seu
nome Al-Karismi, chegando ao falado hoje “algarismo” e deste
mesmo radical o termo “algoritmo”, termo usado hoje na computação,
mas também é muito utilizado em outras áreas como administração,
engenharia, entre outras.
Segundo Forbellone e Eberspacher (2005), a principal ideia
associada a palavra algoritmos se refere a maneira sistemática de
descrever um conjunto de regras formais para a obtenção de uma
resposta da solução de um problema incluindo fórmulas de
expressão aritmética. Xavier (2014) descreve que algoritmos, de uma
maneira bem simples, é uma sequência de passos ou ações para
atingir um objetivo.
Sua associação à computação se deu a partir da metade do
século passado, época da evolução dos computadores, pois é por
meio deles que é possível criarmos as instruções contidas nas
rotinas que eles trabalham. O crescimento da sua utilização hoje tem
crescido exponencialmente, pois eles são a base do desenvolvimento
dos programas, dos mais simples aos mais complexos.
Com a ampliação do poder de processamento dos computares
que possibilita a execução de tarefas muito mais complexas e as
novas tecnologias de armazenamento de informações, são os fatores
que impulsionaram este crescimento.
O avanço da tecnologia dos hardwares (parte física ou
componentes que formam os computadores), fez possível a
utilização de lógicas cada vez mais complexas e elaboradas para a
resolução dos problemas das mais diversas áreas.
Um dos grandes exemplos que podemos citar é o Big Data. Ele é
um conceito que descreve um grande volume de dados que é gerado
a cada segundo.
Figura 1 – O Big Data sendo usado para tomada de decisões
Hoje as tecnologias que nos auxiliam em diversas atividades do
nosso cotidiano geram muitos dados, que antes eram dispensados,
mas que hoje são armazenados, tratados e geram informações de
grande valor, importantes para a descobertassobre as inúmeras
possibilidades de crescimento econômico e social.
Estas informações, processadas pelos algoritmos que compõem
os sistemas, conseguem dar respostas precisas que até pouco
tempo atrás não seriam possíveis.
Também não poderíamos deixar de falar sobre a utilização de
algoritmos na construção da inteligência artificial, uma área da
computação criada na década de 50 que desenvolve algoritmos
capazes de simularem o raciocínio humano.
Esta área cresceu tão rápido que, em 1997, o supercomputador
Deep Blue, da IBM, venceu pela primeira vez o campeão mundial de
xadrez da época, o russo Gary Kasparov.
Segundo o especialista em Inteligência Artificial, M. Tim Jones, o
programa do Deep Blue era feito por algoritmos que possibilitavam
que ele imaginasse uma média de 200.000.000 de posições por
segundo, por isso o atual campeão acabou perdendo a partida.
(JONES, 2018). Ele ressalta a vitória do supercomputador Watson,
também da IBM, que enfrentou dois dos jogadores humanos de
maior sucesso de todos os tempos e os derrotou na frente de
milhões de telespectadores em 2011.
2 Conceitos de algoritmos
Usamos a lógica para guiar nossos pensamentos ou ações para
chegarmos a uma solução. Devemos ter sempre em mente que a
lógica está correta se ela atingir o objetivo para que ela foi proposta.
Para conseguirmos inserir lógica em nossas atividades,
precisamos aprender a pensar de forma estruturada, ou seja,
desenvolver e aperfeiçoar a técnica de pensamento e seguir uma
sequência de raciocínio que crie passos objetivos e seguros até a
solução.
 IMPORTANTE
Segundo Manzano e Oliveira (2012), para usar o raciocínio lógico, é
necessário ter domínio do pensar, bem como saber pensar, ou seja,
possuir e usar a “arte de pensar”.
Quando organizamos nossos pensamentos de forma lógica
conseguimos associar as informações e transformá-las em base
para nossas soluções.
Analise a lógica a seguir:
Se: todo mamífero é um animal E: todos os gatos são
mamíferos Logo: todos os gatos são animais!
Ou
Se: todos os veículos são transportes E: todas as motos são
veículos Logo: todas as motos são transportes!
No exemplo apresentado usamos a lógica para averiguar uma
situação e chegar a uma conclusão, fazendo associações entre eles.
A primeira parte analisa que se todos os seres mamíferos são
animais e que se todos os gatos são mamíferos, então os gatos
também fazem partes do grupo de animais. A segunda faz uma
análise parecida, que se todos os veículos são chamados de
transportes e se todas as motos são consideradas veículos, então as
motos também fazem parte do grupo de transportes.
Utilizamos a lógica a todo o momento em nossas vidas, quando
pensamos, falamos ou escrevemos, utilizamos a lógica para ordenar
as palavras e dar sentido ao que estamos fazendo.
Ao longo do dia, usamos o nosso raciocínio lógico para
resolvermos questões, das mais simples as mais complexas.
A lógica nos ensina a corrigirmos nosso pensamento, nos
ensinando a usá-lo corretamente. Usando o raciocínio de forma
ordenada dividindo a ação em vários passos até a solução do
problema.
Analise a lógica a seguir:
Se: A porta está fechada E: a mochila está dentro da casa
Logo: Preciso primeiro abrir a porta, entrar em casa para
depois pegar a mochila!
Ou
Se: Se Jussara é mais nova que José E: José é mais novo
que Fábio Logo: Jussara é mais nova que Fábio!
Resolver problemas utilizando o computador não é muito
diferente do que falamos agora, devemos encontrar uma maneira de
escrever o problema de forma que seguindo uma sequência de
passos, atingimos a solução desejada. Isto é algoritmo!
De acordo com Manzano e Oliveira (2012, p.27), “Algoritmos na
Ciência da Computação (Informática), está associada a um conjunto
de regras e operações bem definidas e ordenadas, destinadas à
solução de um problema, ou de uma classe de problemas, em um
número finito de passos. ”
Para termos a necessidade de criar uma solução, precisamos
antes ter um problema. A necessidade de enviar mensagens e
documentos mais rápido fez com que criarem o e-mail, a
necessidade de podermos nos relacionar virtualmente fez com que
criassem o Facebook.
3 Descrição narrativa de um algoritmo
Podemos utilizar diversas formas para escrever um algoritmo.
Isso sempre vai depender muito da sua necessidade e de quem vai ler
o que você produziu.
Escrevemos um algoritmo utilizando a descrição narrativa
quando queremos descrever um problema de forma que o receptor
entenda do assunto mesmo não tendo conhecimento de algoritmos.
O grande problema da forma narrada é que ela, por ser escrita
em uma linguagem comum como o português por exemplo, acaba
criando pontos de imprecisão, ou seja, de dupla interpretação. Isso
faz com que a forma de narrativa traga uma falta de confiabilidade no
entendimento do algoritmo. Outro ponto negativo é o fato dela gerar
uma descrição muito grande para dizer poucas coisas, se
comparando a outras formas.
Quando escrevemos um algoritmo de forma narrativa, mesmo
ele sendo um texto em linguagem simples, devemos escrevê-lo de
forma ordena, lógica e em passos bem definidos.
Se por exemplo, eu fosse passar instruções para uma criança
comprar pães em uma padaria desta forma:
1. Sair da padaria.
2. Pegar a comanda.
3. Pegar a fila do caixa.
4. Pedir 10 pãezinhos.
5. Entregar o dinheiro e a comanda.
6. Pegar a fila dos pães.
7. Conferir o troco.
8. Entrar na padaria.
Tenho certeza que você percebeu que a criança ficaria
totalmente perdida na padaria, pois nada daria certo. Para que uma
criança que ainda não conhece os procedimentos necessários para
uma simples compra de pães ter êxito, precisamos ordenar os
passos na ordem correta. Vamos ver agora como deveríamos
escrever o bilhete para a criança:
1. Entrar na padaria.
2. Pegar a comanda.
3. Pegar a fila dos pães.
4. Pedir 10 pãezinhos.
5. Pegar a fila do caixa.
6. Entregar o dinheiro e a comanda.
7. Conferir o troco.
8. Sair da padaria.
Para utilizarmos a lógica devemos definir o que deve ser feito
para solucionar o problema e colocar na ordem correta para
conseguir chegar na solução. Vamos a outro exemplo bem conhecido
nosso, que poucas pessoas pensariam que seria um algoritmo. Uma
Receita de bolo!
1. Misture os ingredientes.
2. Unte a forma com manteiga.
3. Despeje a mistura na forma.
4. Se houver coco ralado despeje sobre a mistura.
5. Leve a forma ao forno.
6. Enquanto não dourar deixe a forma no forno.
7. Retire do forno.
8. Deixe esfriar.
Repare que neste exemplo, mesmo ele estando na sequência
certa, alguns passos ficaram um pouco imprecisos, como enquanto
não dourar, pois a pessoa que vai fazer o bolo pode não saber o ponto
exato que a massa do bolo deve ficar. Por isso quando usarmos a
linguagem narrativa devemos ter o nível de detalhes compatível com
a precisão que o resultado deve ter, ou seja, o bolo não deve ficar
queimado e nem com a massa crua.
4 Representação de algoritmos por
fluxograma
Podemos representar os algoritmos de forma gráfica, para isso
utilizamos os fluxogramas.
Os fluxogramas são formados de caixas com formato variado
que conectadas de forma ordenada e lógica informam as instruções
a serem executadas. São muito populares por serem de fácil
entendimento das ideias contidas no algoritmo.
A representação do fluxograma é ótima para descrever
algoritmos de pequeno e médio tamanho (XAVIER, 2014).
Considerado um nível intermediário de descrição, o fluxograma
fica entre a narrativa, que vimos a pouco, e a de pseudocódigo, que
veremos um pouco mais a frente. Ele expressa melhor a parte física,
ou seja, de detalhes como entrada e saída de informações, o fluxo
das informações e até mesmo a forma de armazenamento.
Seguindo os princípios de entrada, processamento e saída, ele é
composto de um símbolo para iniciar, uma sequência de comandos e
tomadas de decisão e finaliza, independentemente de quantas
bifurcações geradas por tomadas de decisão, aos símbolos finais,
que são iguais ao início só que desta vem escrito fim.
Figura 2 – Exemplo de um fluxograma,onde se
verifica se a impressora está pronta para
impressão
A seguir temos os símbolos mais utilizados nos fluxogramas:
Figura 3 – Simbologia de fluxograma
Terminal
Símbolo utilizado no início e fim de um fluxograma. Também pode
ser usado na definição de sub-rotinas.
Entrada manual
Simboliza a entrada manual de dados, geralmente feita através de
teclado.
Processamento
Representa a execução de uma operação lógica ou matemática.
Exibição
Representa a saída visual de dados, geralmente através do
monitor.
Decisão
Representa a execução de uma operação lógica ou matemática.
Preparação
Representa a modificação de uma instrução em relação à ação de
sua atividade subsequente.
Processo predefinido
Definição de um grupo de operações estabelecidas como uma
sub-rotina de processamento anexa ao diagrama.
Documento
Representa a saída no formato de um documento.
Conector
Representa a entrada ou saída em outra parte do fluxo. Pode ser
usado para quebras de linhas e continuações em outras páginas.
Linha
Representa a conexão entre os outros elementos do diagrama de
blocos. Quando possui a ponta de um seta significa que está
mostrando a direção do fluxo.
Vamos fazer agora a um exemplo prático, montando um
fluxograma de uma funcionalidade do sistema de uma escola.
Devemos criar um fluxograma simples, que calcule a média de duas
notas de um aluno e logo após confirmando se ele está aprovando.
Levando em conta que a nota de aprovação é 7.
Figura 4 – Exercício proposto para calcular a
média de um aluno e verificar a aprovação
Podemos pode perceber que os fluxogramas ajudam a organizar
nossos pensamentos e facilita para imaginarmos o código antes
mesmo de implementá-lo.
Temos várias vantagens como ele, como:
Mostrar o código de forma organizada.
Simular a execução de um código dentro de um programa.
Mostrar a estrutura do programa em formato gráfico.
Usá-lo para mostrar a navegação de um programa ou site.
Podemos encontrá-los com outros nomes como fluxogramas de
processo, mapas de processos, fluxogramas funcionais, entre outros.
Considerações finais
Para escrevermos instruções para os computadores, precisamos
utilizar a lógica de programação, que nada mais é que um conjunto
de ações organizadas para resolver o problema proposto à aplicação.
Chamamos estes conjuntos de passos de algoritmos e podemos
encontra-los em quase tudo que utilizamos para realizar nossas
tarefas do dia-a-dia.
Podemos escrever estes algoritmos de forma narrativa, que nada
mais é que uma lista organizada de ações, que se seguidas de forma
correta, leva a solução do problema. Também podemos representa-
los de forma gráfica através de fluxogramas, um conjunto de
símbolos conectados que mostram o fluxo de execução de um
algoritmo.
Referências
FORBELLONE, André L. V.; EBERSPACHER, Henri F. Lógica de
Programação: A Construção de algoritmos e estrutura de Dados. 3.
ed. Editora Pearson Prentice Hall, Brasil, 2005.
JONE, M. T. As linguagens da IA. 19 jan. 2018. Disponível em:
<https://www.ibm.com/developerworks/br/library/cc-languages-
artificial-intelligence/index.html>. Acesso: 9 ago.2018.
MANZANO, José Augusto N. G.; OLIVEIRA, Jayr F. Algoritmos: Lógica
para Desenvolvimento de Programação. São Paulo: Editora Érica,
2012.
XAVIER, Gley F. C. Lógica de Programação. São Paulo: Editora Senac
São Paulo, 2014.
https://www.ibm.com/developerworks/br/library/cc-languages-artificial-intelligence/index.html
Capítulo 3
Algoritmos variáveis
O computador é uma máquina capaz de realizar comandos e
cálculos matemáticos, mas, diferente do que muitas pessoas
pensam, ele precisa receber instruções para conseguir realizar todas
essas tarefas. Para isso, criamos programas utilizando algoritmos
para passar essas instruções a ele.
Quando vamos criar um algoritmo, devemos utilizar uma
linguagem que seja imperativa, impondo os passos que ele deverá
executar, de forma que as instruções fiquem explícitas, diretas, sem
deixar dúvidas.
As formas de descrição que utilizamos até agora não são tão
precisas, elas podem deixar dúvidas na hora de um desenvolvedor
implementar a solução.
Assim, como na vida real, se não passarmos todos os detalhes
quando entregamos uma tarefa a alguém, temos uma grande
possibilidade de não recebermos o resultado esperado.
Só teremos a garantia de sucesso se escrevemos algoritmos,
utilizando valores que precisamos para resolver esses problemas,
manipulando-os de forma organizada e com recursos que nos
possibilitam utilizar a lógica computacional para gerar a solução para
todos esses casos.
1 Programação imperativa
Quando vamos criar um programa de computador, devemos
analisar qual paradigma, ou seja, qual o conjunto de características
que, juntas, definirão como ele deve operar para resolver o problema.
A programação imperativa é baseada nos estados de valores que
ele recebe – “variáveis” – e em instruções e comandos que dão a
ideia de ordens, dizer exatamente o que deve ser feito. Por isso, ela é
dinâmica, sendo constantemente mudada durante a sua execução.
 PARA SABER MAIS
Imperativo na língua portuguesa significa que acentua o caráter de
mando, de autoridade, ou exprime uma ordem.
O programador passa as instruções de como e o que o
computador deve fazer quando ler o programa. A utilização de
repetições, condições e atribuição de valores que hoje são usados
constantemente em todas as linguagens surgiram neste paradigma.
Um programa criado em uma linguagem imperativa deixa de ser uma
expressão, e passa a ser um comando.
Estas são algumas linguagens de programação que se baseiam
no modelo imperativo: Basic; C; PHP; Java; Cobol; Pascal; Python e
outros.
Na figura 1, a seguir, temos o modelo computacional do
paradigma imperativo.
Figura 1 – Modelo computacional do
paradigma imperativo
Fonte: adaptado de Sommerville (2011, p. 208).
Vamos apresentar como seria uma programação imperativa,
aplicada a uma tarefa do nosso cotidiano, como por exemplo fazer
um bolo:
Separar os ingredientes: leite, ovo, açúcar, margarina, farinha
e fermento.
Aqueça o forno a 180 graus.
Bata as claras em neve e reserve.
Misturar em uma vasilha grande o açúcar, a margarina e as
gemas.
Adicionar a farinha e o leite.
Mexa até que esteja bem misturado.
Juntar a clara em neve misturando vagarosamente.
Colocar a mistura em uma forma untada.
Coloque no forno aquecido por 40 minutos.
Se colocar o garfo no bolo e ele sair limpo, desligue o forno,
senão, o mantenha por mais cinco minutos.
Desligar o forno.
Repare no exemplo anterior que seu funcionamento utilizou
exatamente os conceitos que falamos até agora. Veja:
Informamos valores, que são os ingredientes.
Damos comandos para o programa executar ações com estes
valores, alterando assim o seu estado.
Recebemos a solução esperada do programa, um bolo
preparado corretamente.
Conforme falamos anteriormente, se analisarmos o algoritmo
que criamos acima e imaginarmos um robô executando os passos,
vamos perceber que devemos melhorar ainda mais este código, uma
vez que o robô não teria conhecimentos de coisas que para nós são
óbvias, como por exemplo:
Verificar se o gás estava aberto antes de ligar o forno.
Quebrar os ovos delicadamente e separar a clara da gema antes
de fazer as claras em neve.
Para untar a forma, deveriam ser utilizadas margarina e farinha.
Chamamos isso de refinamento de código, e devemos fazê-lo até
que tenhamos certeza que nosso código está performático.
Um outro exemplo utilizado por Xavier (2014, p. 26) demonstra a
riqueza de detalhes de um código bem refinado. Nele, temos as
instruções para começarmos a dirigir um carro:
Abrir a porta.
Sentar no banco.
Fechar a porta.
Ajustar o banco e os espelhos retrovisores.
Colocar o cinto de segurança.
Pisar na embreagem.
Pegar o câmbio.
Colocar o câmbio em ponto morto.
Soltar a embreagem.
Ligar o carro.
Pisar na embreagem.
Pegar o câmbio.
Colocar o câmbio na primeira marcha.
Acelerar o carro.
Soltar o freio de mão.
Soltar a embreagem devagar.
Neste exemplo, temos passos precisospara executar a ação –
repare que temos ações que servem de prevenção, preparação para
que o próximo passo tenha sucesso, como garantir que o câmbio
esteja em ponto morto, antes de ligar o carro; assim, mesmo que o
carro já estivesse em ponto morto, garantimos o bom funcionamento
da solução.
2 Utilização de pseudocódigo
O pseudocódigo, que poderíamos traduzir ao pé da letra como
“falso código”, é a linguagem que mais se assemelha às linguagens
que usamos para desenvolver os programas nos computadores. Ela é
a descrição de um algoritmo sem a necessidade de utilizar as
particularidades de uma linguagem de programação.
Segundo Medina e Fertig (2006), o pseudocódigo é uma
linguagem intermediária entre a narrativa e as linguagens de
programação de
alto nível.
 IMPORTANTE
Linguagem de programação de alto nível é aquela que se aproxima
mais da linguagem humana e se distancia da linguagem de
máquina. Ela não controla a parte física do computador, somente
trata da camada de ligação com o usuário, como aplicativos, e não
controla o hardware, como o processador, por exemplo.
É comum vermos outros nomes sendo atribuídos ao
pseudocódigo, como portugol ou português estruturado –
geralmente, utilizados para enfatizar que o pseudocódigo está sendo
escrito em português.
Quando trabalhamos nossos algoritmos utilizando o
pseudocódigo, buscamos ao máximo criar uma rigidez semântica e
sintática para que o código seja lido e interpretado corretamente pela
máquina. Vamos começar com um exemplo simples, sem todos os
passos de criação de um pseudocódigo, mas importante para
aprendermos a estrutura:
Início
Escreva: “Qual a nota do aluno?”
Leia: nota
Se a nota for maior ou igual a 7, então: Escreva: “aluno
aprovado”
Senão:
Escreva: “aluno reprovado”
Fim
Neste programa que acabamos de criar, ele envia uma pergunta
na tela ao usuário, espera ele digitar, verifica e, se o aluno tirou uma
nota igual ou maior que 7, ele responde “aluno aprovado”; senão, ou
seja, se a nota for menor que 7, ele responderá “aluno reprovado”.
Se estivéssemos escrevendo a mesma instrução de forma
narrativa, não teríamos essa riqueza de detalhes em cada ação, que
na hora da programação faria toda a diferença.
 IMPORTANTE
“Ação: Fato que, a partir de um estado inicial, após um período de
tempo finito, produz um estado final previsível e definido” (XAVIER,
2014, p. 32).
Você percebeu que temos alguns detalhes que ainda não
sabemos por que estão lá, como as aspas nas frases e termos mais
curtos e objetivos, como leia ou escreva? Falaremos mais no
momento oportuno.
Quando for construir um pseudocódigo, nunca comece a
escrever desordenadamente o que você tem em mente, procure
seguir estes passos:
1. “Compreensão e Estratégia” – Ao se deparar com um problema
novo, faça o seguinte: a. Separe os dados e o que você precisa
fazer com eles; b. Faça um rascunho para visualizar cada passo.
2. “Crie um plano para a solução” – Agora que tem as informações
sobre o problema organizadas: a. Verifique se já resolveu um
problema parecido; se sim, o que posso aproveitar neste; b. Se o
problema for muito complexo, separe-o em partes, assim fica
mais fácil resolver; c. Não se prenda a um só formato, se tiver
difícil de prosseguir, busque alternativas para resolver o
problema.
3. “Formalize a solução” – Hora de começar a montar o algoritmo:
a. Use o pseudocódigo para montar a solução baseada no plano
que você desenvolveu; b. Cuide para que cada passo seja escrito
de forma correta, não tenha pressa de escrever; muitas vezes,
um programa inteiro não funciona por um simples detalhe.
4. “Realize teste” – Agora com o algoritmo montado, vamos
executá-lo: a. Ao testar, veja se não apresenta nenhuma falha no
passo a passo; b. Verifique se ele solucionou o problema da
forma esperada, utilize valores diferentes para comprovar que
realmente está funcionando.
5. “Refine o código” – Será que ele pode ser melhorado?
a. Veja se não há nenhuma mudança que traga melhorias ao
resultado do programa; b. Verifique se existe algum código
redundante, ou seja, repetido ou que não seja necessário.
Vamos conhecer agora algumas partes que compõem a
estrutura do nosso pseudocódigo:
“Atribuição” – Quando o programa recebe informações,
precisamos atribuí-las a um espaço reservado da memória
chamado variável. Para indicar que o valor está sendo atribuído,
usamos o símbolo . Exemplo: valor 35 ou nome “João”.
“Bloco de Instrução” – Assim, no pseudocódigo, como em outras
linguagens de programação, as instruções são executadas na
sequência em que foram escritas. Por isso, usamos um bloco de
instruções para indicar onde ele se inicia, se desenvolve e
termina. Um bloco de instruções é delimitado pelas palavras
“início” e “fim”. Exemplo:
Início
“primeira instrução”
“segunda instrução”
........
“última instrução”
Fim
“Leia” e “Escreva” – Estas duas instruções são utilizadas para a
entrada e saída de informações para o usuário, são a interface
entre a máquina e quem está utilizando o programa. Todas as
vezes que quisermos mostrar uma mensagem ou resultado na
tela do computador, utilizamos a palavra escreva, seguida do
valor ou mensagem; e quando quisermos receber um valor
digitado pelo usuário, utilizamos a palavra leia, seguida do
endereço onde armazenaremos esta informação. Exemplo:
Início
escreva: (“Qual o seu nome?”) leia: (nome_convidado)
escreva: (“Seja bem-vindo ”,nome_convidado ) Fim
Este código escreve na tela uma pergunta para o usuário, o seu
nome recebe a resposta e armazena no espaço de memória
“nome_convidado” e depois escreve na tela uma mensagem de boas-
vindas personalizada com o nome que ele digitou.
3 Declaração de variáveis e constantes
A maior funcionalidade de um computador é manipular
informações. Para resolver um problema, ele precisa de dados para
processá-los.
É necessário que haja formas de se trabalhar com diferentes tipos
de dados em um programa. Apesar de internamente um
computador manipular unicamente números, as linguagens de
programação permitem que utilizemos outros tipos de
informações nos programas de forma transparente. (MEDINA;
FERTIG, 2006, p. 24)
Antes de continuarmos, precisamos entender alguns conceitos:
“Dados” – Utilizados para se referir ao que realmente está
armazenado, são dados isolados que não fazem sentidos
sozinhos. Exemplo: Nome (primeiro nome e sobrenome),
Endereço (logradouro, número e complemento).
“Informações” – Utilizadas para se referir ao significado dos
dados para um determinado usuário. No exemplo abaixo,
sabemos agora que o endereço é referente àquela pessoa.
Exemplo: Nome e Endereço.
Observe que a função dos nossos programas, basicamente, será
transformar informações iniciais, que usualmente chamamos de
dados, em informações finais, as respostas que serão usadas por
quem utiliza o programa. Temos dois tipos de Dados:
“Dados de Entrada” – Conjunto de informações que o programa
precisa receber para iniciar o processo.
“Dados de Saída” – Conjunto de informações que o programa
devolve como resposta após o processamento.
Agora, vamos fazer uma atividade para fixarmos esses
conceitos. Para cada algoritmo abaixo, pense qual seriam os dados
de entrada e saída:
Algoritmo para calcular a idade de uma pessoa.
Algoritmo para calcular o IMC (índice de massa corporal) de uma
pessoa.
Valor pago referente à dívida de meses de aluguel atrasado.
Para essas perguntas, as respostas seriam:
“Entrada”: data de nascimento e data atual. “Saída”: a idade
naquele instante.
“Entrada”: peso e altura da pessoa; “Saída”: a condição física da
pessoa relativa ao peso.
“Entrada”: valor do aluguel, quantidade de meses, taxa de juros;
“Saída”: valor a ser pago até aquela data.
3.1 Tipos de dados
Os tipos de dados são formas de representar valores do nosso
mundo real computacionalmente. As linguagens de programação
representam e manipulam esses dados, que podem ser classificados
como primitivos e não primitivos.
De acordo com Pinheiro (2012), um tipo de dado caracteriza um
conjunto de valores, determinandoa natureza, o tamanho, a
representação e a faixa de representação. No momento, nosso
enfoque será em sua natureza.
3.1.1 Tipos primitivos
Os tipos de dados primitivos são tipos básicos de dados que
compõem um programa – eles representam números inteiros,
frações, frases, etc. No programa de computador, devemos dizer
exatamente os tipos de dados que serão usados na entrada e saída
das informações.
Exemplo: A linguagem Java é uma linguagem fortemente tipada,
ou seja, se você não utilizar o tipo correto, a operação é interrompida
e uma mensagem de erro será apresentada.
Os tipos de dados primitivos são:
“Inteiro” – toda e qualquer informação numérica que pertence ao
conjunto de números inteiros relativos (negativo, nula ou
positivo).
“Real” – também chamada de flutuante, toda e qualquer
informação numérica que pertence ao conjunto dos números
reais (negativo, nula ou positivo).
“Literais” – também chamada de caractere, toda e qualquer
informação composta de um conjunto de caracteres
alfanuméricos 
(0 a 9), alfabéticos (A...Z, a...z) e especiais ( . , $ @ # ! ? ...).
“Lógico” – também conhecido como booleano, toda e qualquer
informação que pode assumir apenas duas situações
(verdadeiro ou falso, sim ou não).
 IMPORTANTE
Os números armazenados em variáveis, cujo tipo de dados é Literal,
não poderão ser utilizados para cálculos.
3.2 Variáveis
Variável é um tipo de dado armazenado no computador.
Chamamos ele assim porque o seu valor contido pode variar diversas
vezes ao longo do processamento. Ao declararmos uma variável,
estamos na verdade reservando um espaço na memória para aquela
determinada informação, enquanto ela é processada.
Todo dado a ser armazenado na memória de um computador deve
ser previamente identificado segundo o seu tipo; ou seja,
primeiramente, é necessário saber o tipo de dado, para depois
fazer o seu armazenamento adequado. (MANZANO; OLIVEIRA,
1996 p. 43)
Figura 2 – Imagem de uma caixa de correios representando as
locações de memória das variáveis
Imagine as variáveis criadas como se fossem esta caixa de
correio de um prédio – o carteiro só sabe onde deve colocar a
correspondência, porque todas estão com os números dos
apartamentos a que são correspondentes.
Para escrevermos corretamente o seu nome, devemos seguir
algumas regras:
Temos restrição ao primeiro caractere do nome, ele deve ser
sempre uma letra do alfabeto, não pode ser um número ou
símbolos gráficos, como cifrão, tralha, etc.
Não pode haver espaço dentro do nome; se for um nome
composto, como “pessoa jurídica”, devemos utilizar o underline
para separação. Ex.: pessoa_juridica.
Duas variáveis não podem ter o mesmo nome, logo de início o
sistema acusará um erro, mas, mesmo se fosse possível
começar, elas entrariam em conflito, sobrescrevendo as
informações.
Existem algumas palavras reservadas da linguagem que também
não podem ser utilizadas. Conheceremos estas palavras mais
adiante.
Devemos declará-las em nosso programa da seguinte forma: 
var idade: inteiro
3.3 Constantes
Chamamos de constantes todos os valores que não devem ser
modificados durante o processamento. Usamos as constantes para
valores que devem manter o seu valor independentemente dos
processos que as utilizarem.
Podemos usar como exemplo a letra grega “π” (PI), que
precisamos utilizar para cálculos referentes a círculos. Apesar de qual
cálculo estejamos fazendo, o seu valor será sempre o mesmo:
3,14159265. Devemos declará-las em nosso programa da seguinte
forma:
const PI = 3.14159265
Também podemos chamá-las de variáveis somente de leitura.
4 Expressões aritméticas, literais,
relacionais e de lógica booleana
Agora que já conhecemos as formas de declararmos os valores
para serem processados em nossos programas, precisamos
aprender as expressões para manipular estes valores. Para cada tipo
de dado, temos expressões exclusivas:
4.1 Expressões aritméticas
Expressões aritméticas são aquelas que o resultado é do tipo
numérico, podendo ser inteiro ou real. Os operadores que são
permitidos nestas operações são:
Tabela 1 – Símbolos de expressões aritméticas
OPERADOR SIGNIFICADO EXEMPLO
+ Adição 1 + 1
– Subtração 8 – 4
* Multiplicação 5 * 7
/ Divisão 520 / 45
% Módulo (resto da divisão) 65 % 6
** Exponenciação 5 ** 2
4.2 Expressões literais
Expressões literais são aquelas que o resultado é do tipo literal, e
mudam muito de uma linguagem para outra. O operador mais
simples é aquele que faz a concatenação entre dois trechos de texto,
que podemos chamar de string (corda, em português, se referindo a
uma corda de caracteres). O operador de concatenação no
pseudocódigo é o sinal “+”:
Tabela 2 – Símbolo de expressões literais
OPERADOR SIGNIFICADO EXEMPLO
+ Concatenação “Avenida” + “Paulista”
4.3 Expressões relacionais
Permitem efetuar comparações entre duas variáveis. O resultado
da comparação é sempre um valor lógico (booleano), ou seja,
verdadeiro ou falso. Os operadores que podemos utilizar nestas
expressões são:
Tabela 3 – Símbolos de expressões relacionais
OPERADOR SIGNIFICADO EXEMPLO
> Maior a > 7
>= Maior ou igual b >= a
< Menor c < 5
<= Menor ou igual c <= b
= Igual a a = 9
<> Diferente de b <> 0
4.4 Expressões de lógica booleana
Utilizamos as expressões lógicas para analisar condições, e
criamos condições que nos retornam 1 ou 0, ou então, verdadeiro ou
falso. Os operadores utilizados para fazermos esta lógica são:
Tabela 4 – Símbolos de lógica booleana
OPERADOR SIGNIFICADO EXEMPLO
e Conjunção
a = 3 e b <> 9
Se o valor de “a” for igual a 3 e o valor de “b” for diferente de
9, então retornará verdadeiro; caso contrário, retornará falso.
Ou Disjunção
a = 3 ou b <> 9
Se o valor de “a” for igual a 3 ou o valor de “b” for diferente
de 9, então retornará verdadeiro; caso contrário, retornará
falso.
não Negação
não a > 3
Se o valor de “a” não for maior que 3, então retornará
verdadeiro; caso contrário, retornará falso.
Considerações finais
Os algoritmos foram criados para implementarmos a lógica
computacional para a resolução de problemas reais. Para que o
programa que desenvolvemos realmente solucione esses problemas,
temos de ter sempre em mente que os comandos devem ser
expressados de forma imperativa, deixando sempre bem claro o que
deve ser executado; guardar os valores que fazem parte do problema
a ser solucionado, para ser possível manipulá-los na aplicação; e, for
fim, utilizar de forma correta os símbolos que não permitem trabalhar
com esses valores de forma lógica e organizada.
Estes não são apenas princípios iniciais, mas a base para uma
boa programação, que você deverá levar consigo para ter sucesso em
todas as aplicações que for desenvolver.
Referências
MANZANO, J. A. N. G.; Oliveira, J. F. Algoritmos: lógica para
desenvolvimento de programação. São Paulo: Editora Érica, 1996.
MEDINA, M.; FERTIG, C. Algoritmos e programação: teoria e prática.
São Paulo: Editora Novatec, 2005.
PINHEIRO, F. A. C. Elementos de programação em C. Porto Alegre:
Bookman, 2012.
SOMMERVILLE, I. Engenharia de software. 9. ed. São Paulo: Pearson
Prentice Hall, 2011.
XAVIER, G. F. C. Lógica de programação. São Paulo: Editora Senac
São Paulo, 2014.
Capítulo 4
Algoritmos: condicional
Neste capítulo, abordaremos a arte da tomada de decisão. Digo
que é uma arte, pelo fato de não ser nada fácil tomar decisões,
apesar de ser essencial. Você, caro leitor, acabou de tomar uma
decisão: ler esta obra! E a cada linha, a cada página, a cada capítulo,
estamos decidindo o que fazer: se continuamos lendo, se mudamos
de emprego, se começamos logo nosso projeto de Verão, se
casamos ou compramos uma bicicleta.
Por dia, tomamos dezenas e até centenas de decisões para
atingirmos nossos objetivos (como acordar, ir trabalhar, ir à
academia, ir à faculdade, etc.). Com o computador acontece a
mesma coisa. Para que seu computador possa desempenhar uma
tarefa, ou um algoritmo, como visto anteriormente, ele deve decidir
como fazer, como desenvolver os passos necessários.
E adivinhe! Quem diz ao computador qual decisãoele deve
tomar? Sim, você. E é exatamente isso que vamos abordar neste
capítulo. Entender as condições e avisar ao nosso computador como
tomar as decisões, de acordo com cada situação.
1 A arte de tomar decisões
Há muito tempo, o Homem escreve e se preocupa com tomadas
de decisões que norteiam nossas vidas. A obra A arte da guerra, de
Sun Tzu, escrita em 476 a.C., é o exemplo clássico de obra sobre
tomada de decisão como estratégia de liderança, negócios e
competitividade. Em uma de suas célebres frases, Tzu diz que
“devemos conhecer nossos inimigos e a nós mesmos”. Vamos partir
desse princípio para conduzir nossas ações e tomar as decisões
corretas no nosso sistema, para que execute as tarefas que
satisfazem as necessidades dos usuários.
Durante o desenvolvimento de um código, existem diversas
situa ções em que a resolução vai depender de um valor, para que
possa seguir um rumo e, consequentemente, que uma tomada de
decisão também seja seguida. Isso ocorre muito em nosso dia a dia,
quando planejamos uma tarefa, mas as “variáveis” do nosso
cotidiano fazem com que tenhamos que optar por mudanças de
planos. Um exemplo típico é quando estimamos um determinado
tempo para chegarmos em um local e um simples pneu furado do
seu veículo pode atrapalhar todo o planejamento do tempo outrora
estimado.
Vamos utilizar um exemplo de uma situação bastante comum no
dia a dia, de um aluno que quer calcular sua média em uma
determinada disciplina e, logo em seguida, vamos determinar se esse
aluno está APROVADO ou REPROVADO nesta disciplina.
Para nossa situação hipotética, vamos supor que o aluno teve
duas provas e a média é dada pela soma das duas notas dividido por
2: Media = (nota1 + nota2) / 2
As regras serão as seguintes: o aluno estará APROVADO, caso
sua média seja maior ou igual a 6.0; e estará REPROVADO, caso sua
média esteja abaixo de 6.0. Para facilitar o entendimento dessas
regras, vamos desenhar seu fluxograma:
Figura 1 – Fluxograma para cálculo da média
de um aluno e tomada de decisão
Baseado no fluxograma anterior, vamos escrever nosso código e
montar um de nossos primeiros algoritmos. Para começar, vamos
desenvolver em pseudocódigo (ou português estruturado) na IDE[1]
VisuAlg. O VisuAlg é um ambiente de desenvolvimento de algoritmos
em portugol, gratuito e portátil. Portanto, o primeiro passo é baixar
esse ambiente em sua máquina ou no seu pendrive (assim, poderá
levá-lo para onde quiser).
Figura 2 – IDE do VisuAlg
1.1 Estruturando o algoritmo
Antes de falarmos das tomadas de decisões, vamos preparar
nosso ambiente de acordo com o modelo do fluxograma anterior.
Então, no VisuAlg vamos começar nosso código.
Para resolver essa tarefa, teremos que criar três variáveis: duas
para armazenar as notas e uma para armazenar a média calculada.
Observem que essas variáveis são todas do tipo real, ou seja, são
variá veis que armazenam números fracionados (ou números
quebrados), pois as notas podem ter casas decimais, certo?
Contudo, vamos pensar em uma coisa! Como vamos atribuir as
notas do aluno às variáveis? Quem vai digitar essas notas? Por onde?
1.2 Estrutura de entrada e saída de dados
Além de declarar as variáveis, deveremos, também, pedir para o
usuá rio digitar as notas para que sejam armazenadas em nossas
variá veis e, para isso, utilizaremos dois métodos de entrada (input) e
saída (output) de dados que, no VisuAlg são leia() e escreva(),
respectivamente. Esses métodos são utilizados da seguinte maneira,
de acordo com Forbellone e Eberspacher (2005):
Leia()
Quando você precisar que o usuário entre com alguma
informação no seu sistema, utilize esse método. Dentro dos
parênteses, coloque onde essa informação será armazenada, ou seja,
em qual variável. Portanto, no nosso exemplo, se quisermos
armazenar a primeira nota, iremos escrever no VisuAlg:
1. Leia (Nota1)
Escreva()
Quando você precisar escrever alguma informação na tela, utilize
esse método. Essa informação pode ser um texto ou o conteúdo de
uma variável. Ambas devem estar dentro dos parênteses.
 IMPORTANTE
Quando a informação for um texto, este deve vir entre aspas “ “.
E quando a informação for uma variável, apenas devemos colocar o
nome dela.
Também podemos escrever na tela os dois tipos de informações
juntas, no mesmo método escreva(). Para isso, basta separá-las por
vírgula.
No VisuAlg, fica assim:
1. Escreva (“Digite sua nota”) // texto simples
2. Escreva (“Sua nota é “, Nota1) // imprime o texto seguido do
conteúdo da variável Nota1
Você pode escrever comentários em seu código para entender o
que está fazendo. Para isso, basta utilizar duas barras // e, logo em
seguida, seu comentário (como feito no exemplo acima).
Feito isso, nosso algoritmo estará assim:
Figura 3 – Primeira parte do exercício “Cálculo
de Média” no VisuAlg
Nesse momento, já temos nossas duas variáveis declaradas e as
duas notas digitadas pelo usuário e armazenadas nas nossas
variáveis. Agora, precisamos fazer o cálculo da média e depois tomar
a decisão se o aluno está APROVADO ou está REPROVADO.
Não se preocupe, isso é bem simples. Vamos separar nossa
missão em duas etapas: 1. Calcular a média; e 2. Tomar decisão.
 IMPORTANTE
No VisuAlg, atribuir um valor a uma variável, ou seja, dar um valor a
uma variável qualquer, é representada por uma seta ( <- ) apontando
a variável. Exemplo: Nota1 <- 5
Nome <- “João”
Na etapa 1, vamos calcular nossa média e atribuí-la à nossa
variável Média. Para os cálculos, utilize os operadores aritméticos
vistos no capítulo anterior. Veja como ficou nosso algoritmo até
agora:
Figura 4 – Segunda parte do exercício “Cálculo
de Média” no VisuAlg
Já na etapa 2, podemos tomar a decisão se o aluno está ou não
APROVADO, já que temos a variável na qual decidiremos (que é a
media). Para isso, utilizaremos estrutura de controle condicional.
2 Estrutura de controle condicional
simples
Para que estas tomadas de decisões sejam possíveis, devemos
utilizar, segundo Xavier (2014), um comando condicional identificado,
no VisuAlg, como se-entao. Sua sintaxe é simples:
Se (condição-lógica) entao // comandos Senao
// comandos Fimse
É importante saber como criar uma condição lógica para se usar
nas tomadas de decisões. Toda condição lógica é formada pela
comparação de dois valores (sejam esses valores conhecidos ou
conteúdo de variáveis), e essa comparação é dada por um operador
relacional.
O resultado dessa comparação é um FALSO ou VERDADEIRO.
Exemplos de condições lógicas:
1. Comparação de um valor conhecido e uma variável:
Nota1 = 3 // se a nota1 for igual a 3, esse resultado é
VERDADEIRO; se não for igual, o resultado é FALSO
2. Comparação de dois valores desconhecidos, ou seja, de duas
variáveis:
Nota1 >= Nota2 // se a nota1 for maior ou igual à nota2, o
resultado é VERDADEIRO; senão, é FALSO
3. Comparação entre valores não numéricos:
Nome <> “João” // se o nome do usuário for diferente de
João, o resultado é VERDADEIRO; senão, é FALSO
Nem sempre uma tomada de decisão utilizando “SE” vem
acompanhada do “SENAO”.
Utilizamos o “SENAO” quando a condição lógica analisada no
“SE” for “FALSA” e precisamos de uma resposta para essa negativa.
Voltemos ao nosso exercício do cálculo da média. Como
modelado no fluxograma, vamos comparar a média com o valor 6,
perguntando se a média é menor que 6 (media < 6) e, caso o
resultado seja VERDADEIRO, vamos escrever na tela “aluno
REPROVADO”. Caso contrário (se for FALSO), vamos escrever “aluno
APROVADO”. Nosso código ficará da seguinte maneira:
Figura 5 – Terceira parte do exercício “Cálculo
de Média” no VisuAlg
Para verificar o resultado, pressione F9 no VisuAlg para executar
seu código. Mas ainda podemos melhorar um pouco e colocar a
média dele junto com a situação. Por exemplo: aluno REPROVADO
com média _____.
Como colocar a média dele impressa na tela junto com esse
texto? Você já aprendeu isso nas orientações anteriores. Pense um
pouco e resolva esse problema.
 PARA PENSAR
E se o aluno tiver mais do que as duas situações de APROVADO e
REPROVADO?Por exemplo, se ele puder fazer exame?
Vamos imaginar essa nova situação:
Se o aluno tiver a média abaixo de 4.0 estará automaticamente
REPROVADO.
Se o aluno tiver a média entre 4.0 e 6.0 poderá realizar EXAME.
E se a média do aluno estiver acima de 6.0 estará APROVADO.
Agora, temos três possibilidades de resultado na tomada de
decisão. Como resolver isso?
3 Estrutura de controle condicional
composta
Para resolvermos esse problema, vamos recorrer às tomadas de
decisão compostas que, de acordo com Manzano e Oliveira (1996),
realiza ações compostas ou aninhadas, dependendo se a seleção (ou
condição) é verdadeira ou falsa. A condição é uma expressão
processada e transformada em um valor booleano. Podemos
trabalhar esse recurso de duas maneiras:
1. “SE” aninhado positivo
Nessa maneira, temos vários “SE” sequenciais, um dependendo
do outro. Exemplo: Se (media >= 6), então Se (frequência >= 75),
então Escreva (“aluno APROVADO”) Fimse
Note que: o sistema só vai verificar a condição da frequência,
caso a condição anterior seja VERDADEIRA, ou seja, o segundo “SE”
depende do primeiro ser verdadeiro. Caso o primeiro “SE” seja
“FALSO”, o sistema não fará nada e sairá do “SE” pelo comando
“FIMSE”.
2. “SE” aninhado negativo Nessa segunda maneira, temos, também,
vários “SE”, porém, um complementando a negativa do outro, ou
seja, para executar o segundo “SE”, o primeiro deve ser “FALSO”.
Exemplo: Se (media < 4), então Escreva (“aluno REPROVADO”)
Senao
Se (media < 6) entao Escreva (“aluno em EXAME”) Senao
Escreva (“aluno APROVADO) Fimse
Note que: caso o primeiro “SE” seja VERDADEIRO, o sistema não
executa o “SENAO”, escrevendo na tela apenas “aluno REPROVADO” e
saindo da tomada de decisão pelo último “FIMSE”. Porém, caso o
primeiro seja “FALSO”, o sistema executa o “SENAO” e faz uma nova
tomada de decisão. Se este for VERDADEIRO, o sistema escreve
“aluno em EXAME” e não executa o “SENAO” saindo dos dois “FIMSE”.
Todavia, caso este segundo “SE” também seja “FALSO”, o sistema
executa o “SENAO” e escreve na tela “aluno APROVADO” e depois sai
dos dois “FIMSE”.
Aliás, essa é a solução para a situação proposta. Faça no VisuAlg
e analise o resultado.
Para deixar ainda mais interessante nosso algoritmo, vamos
incluir a variável frequência, que deverá ser inserida pelo usuário. A
frequência vai armazenar a porcentagem de presença do aluno na
disciplina e será um número inteiro de 0 a 100 (onde 0 [zero] o aluno
não teve nenhuma presença e 100 [cem] o aluno frequentou todas as
aulas).
Ainda queremos calcular a média do aluno e informar se ele está
APROVADO, REPROVADO ou está de EXAME. A regra para a
frequência será: abaixo de 75% o aluno está automaticamente
REPROVADO. Vamos analisar como ficará nosso código:
algoritmo “Cálculo de média com frequência”
var Nota1, Nota2, Media: real freq: inteiro inicio escreval
(“Digite sua primeira nota”) leia (Nota1) escreval (“Digite sua
segunda nota”) leia (Nota2) escreval (“Digite sua frequência”)
leia (freq) Media <- (Nota1 + Nota2) / 2
se (Media < 4) entao escreva (“aluno REPROVADO”) senao
se (Media < 6) entao se (freq >= 75) entao escreva
(“aluno em EXAME”) senao escreva (“aluno
REPROVADO”) fimse senao se (freq >= 75) entao
escreva (“aluno APROVADO”) senao escreva (“aluno
REPROVADO”) fimse fimse fimse
Lembrando que: o algoritmo pode ser construído de várias
maneiras, por isso seu código pode ficar diferente do apresentado
acima e produzir o mesmo resultado.
Além disso, podemos melhorar ainda mais nosso código com o
uso de operadores lógicos (apresentados no [capítulo 2]). Vamos
abordar mais sobre esse assunto no próximo capítulo; porém, ative
sua curiosidade e tente ajustar seu código considerando esses
operadores.
 NA PRÁTICA
Sugiro que você tente fazer o exercício sozinho. Comece
desenhando o fluxograma e desenvolva o algoritmo no VisuAlg.
Depois compare com nossa solução abaixo e compare os
resultados.
Considerações finais
Tomar uma decisão faz parte do nosso dia a dia, além de ser
extremamente importante, é imprescindível, ou seja, impossível não
fazê-lo. Na computação não é diferente, temos que tomar várias
decisões para cumprir as tarefas necessárias aos objetivos dos
nossos usuários de sistema.
Porém, tomar decisões exige uma comparação (com uso de
operadores relacionais) entre dois valores, seja ele um valor
conhecido ou o conteúdo de uma variável. Além disso, devemos
seguir uma estrutura para tomada de decisão na qual perguntamos
SE o resultado da comparação lógica é FALSA ou VERDADEIRA. Caso
seja verdadeira, os comandos são executados. Caso contrário,
podemos ter ou não o tratamento da sua negativa, ou seja, o SENAO
(este comando é executado quando o resultado da comparação
lógica do SE for FALSA.
Por fim, podemos utilizar esse recurso de tomada de decisão de
maneira aninhada, com vários SE e várias comparações lógicas. No
aninhamento de SE podemos ter duas situações: 1. Aninhamento
positivo (no qual as expressões lógicas dependem de as anteriores
serem VERDADEIRAS, em uma sequência) e 2. Aninhamento negativo
(no qual as expressões lógicas se complementam e a próxima só
será executada caso a anterior seja FALSA).
Referências
FORBELLONE, A. L. V.; EBERSPACHER, H. F. Lógica de programação:
a construção de algoritmos e estrutura de dados. 3. ed. São Paulo:
Editora Pearson Prentice Hall, 2005.
MANZANO, J. A. N. G.; OLIVEIRA, J. F. Algoritmos: lógica para
desenvolvimento de programação. São Paulo: Editora Érica, 1996.
TZU, S. A arte da guerra. Adaptação de James Clavell. 38. ed. Rio de
Janeiro: Editora Record, 2002.
XAVIER, G. F. C. Lógica de programação. São Paulo: Editora Senac
São Paulo, 2014.
[1] IDE, do inglês integrated development environment, ou ambiente
de desenvolvimento integrado, é um programa de computador que
reúne características e ferramentas de apoio ao desenvolvimento de
software com o objetivo de agilizar esse processo.
Capítulo 5
Algoritmos: repetição
Exercícios e atividades cotidianas são comuns a todos nós.
Diariamente, repetimos, seguindo um processo ou padrão, tarefas
costumeiras e cíclicas, como comer, andar, respirar e estudar, por
exemplo.
Essas tarefas podem ser padronizadas, seguindo procedimentos
comuns, estudados aqui neste capítulo, conhecidos como estruturas
de repetição. Também chamadas de loops ou laços de repetição,
analisam condições lógicas e repetem, de uma forma cíclica, seu
trecho de código, de acordo com os resultados obtidos.
Este capítulo apresentará os conceitos de laço e contadores, que
são recursos usados para “contarmos” a quantidade de vezes que o
loop executou. Além disso, você aprenderá como incrementar e
decrementar os passos de um contador e aplicar na prática nosso
aprendizado.
Vamos continuar nosso exercício de cálculo da média,
melhorando seu funcionamento e o deixando mais eficiente. Você
também será provocado a cumprir desafios, com o objetivo de
melhorar a compreensão e se sentir familiarizado com esses
comandos tão úteis na programação de sistemas.
1 Repetir para aprender
Todos nós temos rotinas diárias e cotidianas preestabelecidas,
como levantar cedo, se arrumar, ir trabalhar, almoçar, ir para a
faculdade, ir para a academia e dormir, por exemplo. E repetimos
tantas vezes essas atividades, todos os dias, que acaba se tornando
um ciclo. Note que esse ciclo segue o mesmo processo, sempre; ou
seja, não precisamos inventar novas maneiras de acordar ou ir
trabalhar, todas seguem o mesmo padrão.
Para acordar, precisamos seguir um processo simples de
passos:
Abrir os olhos.
Levantar da cama.
Tomar banho.
Escovar os dentes.
Vestir-se.
Tomar café.
 PARA PENSAR
Note que o ato de “acordar” remete a uma ação com várias
atividades, e não simplesmente abrir os olhos. Chamamos isso de
método ou função, conceitos que discutiremos mais adiante.
Agora, imagine fazer isso todos os dias (e nós fazemos, não é
mesmo?). Quando já sabemos como se faz, torna-se mecânico o
processo e não nos preocupamos em como estamos executando
cada passo dessa tarefa.
O computador tambémexecuta diversas rotinas (ou funções)
repetidas vezes, como um saque em um caixa eletrônico, a
verificação de um cadastro, iniciar o sistema operacional quando
ligamos nosso computador e efetuar uma compra em algum site de
e-commerce, por exemplo. E todas essas rotinas são efetuadas da
mesma maneira, seguindo o mesmo processo, independente de
quem está utilizando a funcionalidade.
Para “facilitar” esse processo, no computador, vamos utilizar
alguns recursos de repetição de rotinas bem conhecidos na
programação. Esses recursos auxiliam bastante em nossa
programação, evitando que nós, programadores, reescrevamos o
mesmo código para atividades comuns. Ao invés disso, podemos
simplesmente criar um código, uma rotina, com o processo definido
pelas regras do nosso negócio e repetimos todas as vezes que
alguém precisar utilizá-las.
Lembra-se do nosso exercício do capítulo anterior? Do cálculo da
média a partir de duas notas do aluno e a tomada de decisão para
sabermos a situação desse aluno (APROVADO, REPROVADO ou EM
EXAME)? Pois bem, vamos continuar esse programa, mas agora com
a seguinte tarefa:
Nós pedimos para o usuário digitar sua nota, certo? Mas não
verificamos se a nota é válida, ou seja, se a nota está entre 0
(zero) e 10 (dez), pois não existe uma nota escolar fora desses
parâmetros. Então, vamos garantir que o usuário não digite uma
nota fora dos padrões.
 IMPORTANTE
Toda vez que o usuário digitar uma nota, devemos verificar se a
nota está dentro dos parâmetros que nós estabelecemos, neste
caso, entre zero e dez.
Como fazer isso e garantir que o programa só vai continuar se a
nota digitada está válida? Vamos entender o fantástico mundo dos
lações de repetição.
1.1 Estruturas de repetição
Quando uma sequência de comandos deve ser executada
repetidas vezes, usamos uma estrutura de repetição. Segundo Deitel
e Deitel (2005), a estrutura de repetição, assim como a de decisão,
envolve sempre a avaliação de uma condição. A diferença entre a
estrutura de decisão e a estrutura de repetição é a quantidade de
vezes que ela executa em nosso sistema. A figura 1 diferencia essas
duas estruturas em uma visão macro:
Figura 1 – Diferença de estrutura condicional e estrutura de
repetição
Note que a imagem A é uma tomada de decisão simples,
utilizando como recurso o “SE” (apresentado no capítulo anterior).
Essa verificação é efetuada apenas uma vez, ou seja, a expressão
lógica é analisada e, se seu resultado for FALSO, o programa segue
para um lado; e, se for VERDADEIRO, segue por outro lado, não
voltando mais para a verificação, o programa segue. A imagem B
mostra uma estrutura de repetição com o recurso “ENQUANTO” (que
vamos estudar em seguida). A expressão lógica também é analisada,
porém, ENQUANTO ela for VERDADEIRA, nosso trecho de código
continua se repetindo, até que ela se “torne” FALSA.
 IMPORTANTE
É importante ficarmos atentos ao resultado da expressão lógica na
estrutura de repetição. Ela deve ter alguma condição, dentro do
código, de mudar seu valor; caso contrário, caímos em um conceito
chamado LOOP INFINITO.
De acordo com Forbellone e Eberspacher (2005), essas
estruturas são também conhecidas como laços de repetição, ou
loops, e o loop infinito acontece quando a condição lógica analisada
for sempre VERDADEIRA. Para que isso não ocorra, devemos nos
preocupar em alterar nossa variável (que está sendo comparada na
condição lógica) dentro do laço de repetição. Daqui a pouco, veremos
como isso funcionará. Por enquanto, vamos ver alguns tipos de
estruturas de repetição e aplicar em nosso exercício.
2 Enquanto-faça (while)
Deitel e Deitel (2005) diz que a estrutura de repetição
“ENQUANTO” permite especificar instruções que devem ser repetidas
enquanto determinada condição for VERDADEIRA. A seguir, é
ilustrada a sintaxe dessa estrutura no VisuAlg:
Enquanto (condição lógica) faça
// código fimenquanto
Veja que a condição lógica é verificada e, quando seu resultado
for VERDADEIRO, o código (dentro do laço) será executado. Quando o
programa chegar na instrução FIMENQUANTO, o programa volta a
analisar a condição lógica e verifica novamente seu resultado. O
sistema fica nesse loop enquanto o resultado da condição for
VERDADEIRA.
Caso essa condição seja FALSA, o programa continua o código
pulando todo o laço de repetição, ou seja, o sistema encontra a
instrução FIMENQUANTO e continua a partir desse ponto, não
executando o código dentro do laço. Por isso, a importância de se
alterar o valor analisado na condição lógica para que possamos sair
desse laço. Caso contrário, ficamos presos dentro dele, causando um
loop infinito.
Agora que sabemos disso, que tal aplicarmos no nosso
exercício?
Vamos cumprir nossa tarefa, que é garantir que a nota digitada
pelo nosso usuário seja válida, ou seja, esteja entre zero e dez. Para
isso, vamos utilizar o recurso de repetição ENQUANTO e os
operadores lógicos.
 PARA SABER MAIS
Entender os operadores lógicos é de extrema importância para a
compreensão das condições lógicas e seus resultados e, assim,
dominar as estruturas de repetição e de tomada de decisão.
Sugerimos a leitura do livro C – como programar, de Harvey Deitel e
Pearson Deitel (2011).
Vamos relembrar que a decisão lógica é a comparação relacional
de dois valores. Caso precisemos comparar mais valores para obter o
mesmo resultado, deveremos fazer uso dos operadores lógicos. No
nosso exercício isso acontecerá, pois deveremos comparar se a nota
digitada é menor que zero OU a nota digitada é maior que dez. São
duas comparações para se obter um único resultado.
Note que estamos fazendo comparações daquilo que NÃO
queremos. Estamos comparando se a nota está fora dos padrões
estabelecidos. Por que fazemos isso, nesse caso? Se a nossa nota
for válida, ou seja, estiver dentro dos padrões de zero a dez, não
queremos que o laço de repetição faça nada. Queremos que o
programa pule todo o laço e continue o código depois do
FIMENQUANTO, pois nossa nota é válida.
Nossa intenção é identificar quando a nota está fora dos padrões
e pedir para o usuário digitar novamente. Após a nova digitação,
devemos verificar outra vez e, se a nota persistir errada (ou seja, se a
condição lógica for VERDADEIRA), o laço será executado de novo,
ficando em um ciclo, até que a condição lógica se torne FALSA
(quando o usuário digitar uma nota válida).
Portanto, nosso código, para verificar a primeira nota, ficará
assim:
Figura 2 – Verificação da Nota1 pela estrutura de repetição
“ENQUANTO”
Na figura 2, o usuário digita a primeira nota e, em seguida, o
sistema a verifica, comparando se ela é menor que zero OU se ela é
maior que dez. Essas são as condições que, quando verdadeiras, nos
levam a pedir novamente a nota, pois está fora dos padrões
estabelecidos.
 PARA PENSAR
O operador lógico “OU” utilizado no código torna o resultado da
condição VERDADEIRA se qualquer uma das duas comparações
forem verdadeiras. Caso precisássemos que as duas condições
fossem verdadeiras, deveríamos usar o operador lógico “E”.
Agora é sua vez. Faça a verificação da segunda nota e teste seu
programa.
Dissemos no início do capítulo que a estrutura de decisão “SE”
realiza apenas uma verificação e segue o programa. Quantas
verificações a estrutura de repetição “ENQUANTO” executa?
Essa estrutura executa enquanto o resultado da condição lógica
analisada for VERDADEIRO.
Na verdade, essa estrutura pode executar quantas vezes forem
necessárias. Nós não sabemos quantas vezes o usuário vai digitar a
nota inválida; enquanto isso, nosso sistema estará “preso”, esperando
a nota correta (claro que podemos limitar a quantidade de tentativas
do usuário, por exemplo, quando ele pode digitar até três vezes a
senha incorreta, caso contrário, sua conta é bloqueada). Para isso,
podemos utilizar “contadores”, que vão nos ajudar muito no próximo
tópico desse capítulo.
Pergunta: e se conhecermos a quantidade de vezes que vamos
executar o laço? Por exemplo, eu quero selecionar os primeiros 10
alunos da sala, ou quero selecionar os seis números da mega-sena,ou ainda indicar três nomes para o Oscar de melhor ator.
2.1 Para-faça (for)
Segundo Xavier (2014), o comando “PARA” é o mais simples das
estruturas de repetição e permite que um trecho de código seja
repetido um número de vezes específico, definido. Portanto, deve-se
saber o número de vezes que se executará o bloco de comando, se é
uma vez ou dez ou “N” vezes.
Para os casos citados anteriormente, temos uma estrutura de
repetição chamada “PARA”; e sua sintaxe, no VisuAlg, é a seguinte:
Para contador de comeco ate
fim passo n faca // código
fimpara
Onde:
Contador: é uma variável de controle (ou índice), na qual será
incrementada ou decrementada, a partir de um valor inicial
previamente estabelecido.
Começo: é o primeiro valor que a variável de controle vai
assumir.
Fim: valor-limite que a variável de controle poderá assumir (valor
máximo).
N: é o incremento ou decremento da variável de controle. Caso
essa variável seja incrementada de 1 em 1, o valor de N será 1.
Se for de 2 em 2, o valor de N será 2, e assim por diante. Porém,
caso a variável de controle seja decrementada, basta inserir o
valor negativo ao N (–1, –2, –3, etc.).
 IMPORTANTE
Nem todos esses valores serão variáveis. Caso a gente conheça o
valor inicial e o valor final e o passo, podemos simplesmente
colocar esses números na sintaxe anterior.
Vamos fazer um exercício para entender o funcionamento desse
laço de repetição. Façamos, no VisuAlg, um algoritmo que mostre, na
tela, a tabuada de um número digitado pelo usuário. Veja o resultado:
Figura 3 – Algoritmo de tabuada
Na figura 3, o laço de repetição “PARA” inicia com o valor zero e
termina em dez com passo incremental de 1. O comando “ESCREVAL”
está imprimindo, na tela, variáveis e textos alternados e separados
por “vírgula”. Lembre-se que os textos devem estar entre aspas. No
final desse comando, é executada uma operação aritmética
(numero*contador). Isso é perfeitamente possível – qualquer
operação aritmética pode ser feita dentro desse comando para
exibição na tela.
 NA PRÁTICA
Para consolidar a aprendizagem, refaça esse exercício imprimindo
apenas os números pares da tabuada. Imprima, também, a tabuada
de trás para frente, ou seja, de 10 até 0. Dica: para ambos os
exercícios, você deve mexer no passo da estrutura “PARA”.
Para finalizar, podemos representar, também, um contador no
laço de repetição “ENQUANTO”. Basta atribuir, fora do laço (na
verdade, antes do laço) o valor inicial a ela. A condição lógica a ser
analisada no laço será a comparação desse contador com o valor
máximo que ele pode atingir. Dentro do laço, antes do
“FIMENQUANTO”, deveremos executar o passo, adicionando mais 1 à
variável, como demonstrado na figura 4.
Vamos representar o laço “PARA” do exercício anterior com um
laço “ENQUANTO”.
Figura 4 – Algoritmo de tabuada com a estrutura de repetição
“ENQUANTO”
Considerações finais
Repetir atividades rotineiras faz parte do nosso cotidiano. A
repetição nos leva ao aprendizado de um processo que nos servirá de
guia para padronizar as atividades do nosso ciclo de tarefas e
afazeres.
Em computação, temos recursos de estruturas de repetição que
são de suma importância para que o processo seja implementado.
Esses recursos são, também, chamados de loops ou laços e avaliam
condições lógicas para executarem o que desejamos.
O laço “ENQUANTO” vai executar sempre que o resultado da
condição lógica for VERDADEIRA, podendo permanecer nesse ciclo
até que nossa condição seja satisfeita e acontecer o que desejamos.
Já no laço de repetição “PARA”, sabemos quantas vezes
executará, pois determinamos onde ele começa e onde ele termina.
Estabelecemos, também, seu incremento ou decremento e utilizamos
o conceito de contador para “contar” a quantidade de vezes que a
estrutura executou.
É importante ressaltar que você deve sempre praticar. A
repetição de exercícios o levará a um nível de aprendizagem e
compreensão que o deixarão familiarizado com esses recursos e
com a lógica implementada.
Portanto, não pare! Continue se exercitando.
Referências
DEITEL, H. M.; DEITEL, P. J. C – como programar. 6. ed. São Paulo:
Editora Pearson Prentice Hall, 2011.
______. Java – como programar. 6. ed. São Paulo: Editora Pearson
Prentice Hall, 2005.
FORBELLONE, A. L. V.; EBERSPACHER, H. F. Lógica de programação:
a construção de algoritmos e estruturas de dados. São Paulo: Editora
Pearson Prentice Hall, 2005.
XAVIER, G. F. C. Lógica de programação. São Paulo: Editora Senac
São Paulo, 2014.
Capítulo 6
Algoritmos: vetores
Armazenar dados, na computação, é primordial para a execução
de inúmeras tarefas cotidianas e, para isso, usamos as variáveis até
agora. Porém, se precisarmos armazenar um número grande de
informações do mesmo tipo, como as idades de uma turma, as notas
de uma classe ou os nomes dos alunos, teremos de utilizar uma
estrutura diferente das variáveis.
Essas estruturas são os vetores, também chamados de array
unidimensional, que têm a capacidade de armazenar vários dados do
mesmo tipo. Porém, para essa execução, devemos informar a
posição, dentro do vetor, onde nossa informação se posicionará
quando estivermos manipulando nosso vetor.
Na manipulação de vetores, vamos inserir dados e buscar algum
dado específico no vetor. Essas duas funcionalidades, muito
utilizadas em computação, exigem a “varredura” do nosso array
(caminhar pelo vetor do início ao fim) e, ao mesmo tempo, indicar em
qual posição (ou índice) nós estamos.
Neste capítulo, vamos entender o funcionamento de um vetor e
sua manipulação (inserção e busca de dados), além da “varredura” do
vetor pelo laço de repetição “PARA”, visto no capítulo anterior. Vamos,
também, continuar nosso exercício de cálculo da média e nos deparar
com novos desafios.
1 Teoria dos conjuntos
Você se lembra da Teoria dos Conjuntos, estudada em
matemática em algum momento da sua vida? Vamos utilizar essa
ideia para explicarmos nosso recurso computacional.
Segundo Dante (2011), chamamos de conjunto toda e qualquer
coleção de elementos, que podem ser números, objetos, figuras,
pessoas, animais e tudo o que podemos ordenar, catalogar ou reunir
em grupos de seus elementos. Por exemplo, se quisermos construir o
conjunto de crianças de uma escola que possuam exatos 10 anos de
idade, podemos dizer que o conjunto é composto pelos alunos
Pedrinho, Joãozinho, Mariazinha e todos os alunos que tenham 10
anos de idade na escola, como ilustrado na figura 1.
Matematicamente, quase sempre os conjuntos serão compostos por
números que dependam de algumas condições, como o conjunto dos
números reais, o conjunto dos números inteiros, o conjunto dos
números maiores do que 2 e menores do que 7, por exemplo.
Figura 1 – Conjunto dos alunos com 10 anos de idade
Agora, imaginem que queremos coletar várias notas escolares
para calcular a média de um aluno. O que fizemos, até então, foi
coletar essa informação e guardar em variáveis, uma por uma, nota
por nota, individualmente. Mas, doravante, precisamos de um
conjunto de notas (por exemplo, cinco notas) para calcular essa
média.
Pelo que conhecemos até agora, deveríamos declarar cinco
variáveis, correto? Você pode pensar: “isso é fácil!”. Porém, se essa
quantidade aumentar – por exemplo, agora quero coletar todas as
notas de uma turma, ou pior, quero todas as notas de uma escola
inteira –, já não fica mais viável declarar tantas variáveis assim, não é
mesmo?
Uma solução simples para guardar esses dados coletados seria
agrupá-los em um conjunto de dados, colocando todos os elementos
em um único lugar. O que acha dessa ideia? É exatamente isso que
vamos fazer. Entretanto, vamos precisar de uma estrutura específica
para guardar, identificar, manipular, inserir novos dados, excluir algum
elemento, ordenar e até efetuar operações matemáticas com os
elementos do nosso conjunto.
Essa estrutura existe e vamos apresentá-la agora.
2 Conceito de vetores
Em algum momento da sua vida, você já deve ter ouvido falar em
vetor – conceito estudado em álgebra linear ou geometria analítica,
ouainda na física, onde um vetor representa o conjunto dos
segmentos orientados de reta que têm o mesmo módulo, a mesma
direção e o mesmo sentido.
Em computação, um vetor (array), ou arranjo, é o nome de uma
matriz unidimensional, considerada a mais simples das estruturas de
dados (TENENBAUM; LANGSAM; AUGENSTEIN, 2007). Geralmente, é
constituída por dados do mesmo tipo (homogêneos) e tamanho, que
são agrupados continuamente na memória e acessados por sua
posição (índice – quase sempre um número inteiro) dentro do vetor.
Quando criamos ou inicializamos um vetor, determinamos o seu
tamanho, que geralmente não se modifica, mesmo que utilizemos
menos elementos. Veja sua sintaxe, no VisuAlg:
Var
Nome_do_vetor: vetor [1..10] de
inteiro
Na verdade, a prática é mais fácil que a teoria.
Imagina que o vetor seja a rua da sua casa. Essa rua tem um
nome, para que possamos achar seu endereço, certo? Esse seria o
nome do vetor. Você poderia me perguntar: professor, e se eu
quisesse achar meu endereço pelo CEP da minha rua? É uma ótima
pergunta. O CEP da rua seria o endereço de memória onde foi criado
seu vetor, nós poderíamos acessar a memória com esse endereço e
encontraríamos nosso vetor lá, sem precisar do seu nome, por
exemplo. Mas isso é outro assunto.
 PARA SABER MAIS
Caso queira saber mais sobre endereço de memória, indicamos a
leitura do assunto “ponteiros”, em “Estrutura de Dados”, p. 27,
apresentado na obra de Aaron Tenenbaum, Yedidyah Langsam e
Moshe Augenstein, intitulada Estrutura de dados usando C.
Para encontrar sua casa, nessa rua, devemos possuir o número
da casa. Esse número corresponde ao índice do vetor. Portanto, para
encontrarmos algum elemento dentro do nosso vetor, devemos
procurá-lo pelo índice, certo? Nem sempre. Essa é uma possibilidade.
Poderíamos encontrar um elemento pelo seu nome (“Joãozinho”) ou
pelo seu valor (caso seja um número, por exemplo). Ou seja,
poderíamos encontrar sua casa pela sua cor ou uma característica
específica dela, como uma árvore ou um toldo, conforme a figura a
seguir:
Figura 2 – Representação metafórica de um vetor
Sabendo disso, vamos declarar nosso primeiro vetor no VisuAlg.
Continuando nosso exercício do cálculo da média, vamos solicitar,
agora, que o usuário digite cinco notas. Guardaremos esses dados
em um vetor chamado “nota”, por exemplo, e depois vamos calcular a
média a partir dessas notas. Não vamos nos esquecer de verificar se
as notas são válidas, ou seja, se estão entre zero e dez.
3 Manipulando vetores
Manipular vetores é inserir os dados, excluir dados e buscar
algum dado do vetor. Para manipular um vetor, vamos utilizar a
estrutura de repetição “PARA”, pois como o tamanho do vetor é
conhecido, sabemos quantas vezes o laço vai executar para percorrer
todo o vetor, inserindo, ou buscando algum dado.
Portanto, nossa declaração ficará assim:
Figura 3 – Declaração do vetor “nota” no
VisuAlg
Declaramos um vetor chamado “nota” para armazenar as notas
digitadas pelo usuário, conforme a figura 3. Como serão cinco notas,
tivemos de indicar, entre colchetes, os índices inicial e final, no caso
do nosso exercício, de 1 a 5. Além disso, indicamos que tipo de dados
serão armazenados nesse vetor. As notas são números decimais,
portanto, declaramos o vetor como “real”.
Contudo, fizemos apenas a declaração desse vetor, que é uma
variá vel que armazena vários valores do mesmo tipo (por isso, é
declarado em “VAR”, no VisuAlg). Agora, precisamos manipular esse
vetor, inserindo os dados (no caso as notas) que o usuário vai digitar.
3.1 Inserindo dados no vetor
Para inserir dados em um vetor, precisamos iniciar pelo primeiro
índice (ou a primeira casa da rua) e colocar um valor dentro dela, igual
fizemos com uma variável comum. Aliás, cada “casa” do nosso vetor
vai se comportar, individualmente, como uma variável comum.
O “esquema” de inserção vai funcionar da seguinte maneira,
conforme figura 4:
Haverá um contador iniciando com o valor do primeiro índice do
vetor (no nosso caso, 1).
Para inserir um valor em uma das “casas” do vetor, precisaremos
indicar qual o índice dessa casa, ou seja, sua posição. Esse
índice é passado dentro dos colchetes do vetor “nota”.
Conforme vamos caminhando (ou “varrendo”) nesse vetor, nosso
contador vai incrementando 1 em seu passo, até a última
posição do vetor (no nosso caso, 5). Nesse momento, com essa
condição lógica, podemos sair do laço “PARA” e teremos nosso
vetor totalmente preenchido com os valores digitados.
Figura 4 – Esquema de inserção de dados em um vetor
Observe, que o comando leia () está recebendo o vetor “nota”,
porém, para inserir o valor na primeira “casa”, devemos informar o
índice da casa, entre colchetes. E quem guarda esse índice é nosso
contador, por isso, o colocamos nos colchetes. A cada passo de
incremento, o contador vai representar a próxima “casa”, e assim por
diante, até que a condição lógica se torne FALSA e o laço seja
encerrado.
Está na hora de botar a mão na massa! Vamos construir nosso
código. A figura 5 mostra o trecho do código correspondente ao laço
de repetição “PARA” solicitando as cinco notas válidas.
Figura 5 – Inserção de notas em um vetor
Veja que o comando escreva() está mesclando texto e variável.
Execute esse algoritmo e veja o resultado. Essa é uma sugestão para
você utilizar em seus próximos códigos, fica bem explicado e
organizado.
Agora, precisamos calcular a média do aluno e indicar sua
situação (APROVADO, REPROVADO ou EM EXAME). Para o cálculo da
média, vamos, novamente, varrer o vetor desde o início, somando
todos os valores encontrados nas “casas”. Vamos utilizar, para nos
auxiliar, um “acumulador” (variável que acumula determinado valor),
conforme vamos somando as notas. Esse acumulador deverá ser
inicializado com um valor neutro (como estamos efetuando uma
soma, vamos atribuir valor zero a essa variável). Então, nosso código,
completo, ficará conforme a figura a seguir:
Figura 6 – Cálculo da média com uso de vetor
O algoritmo desenvolvido é um exemplo completo da inserção de
dados em vetores: controle de notas pelo laço de repetição
“ENQUANTO”; uso dos laços “PARA” (usado para varrer nosso vetor);
utilização de controlador (que armazena a posição da casa na qual
estamos inserindo um dado); e uso de acumulador (variável que
armazena o somatório de todos os valores do nosso vetor). Todos os
conceitos aprendidos nos capítulos anteriores até agora estão
presentes no exemplo do cálculo da média usando vetor. É preciso
treinar bastante, para que esses conceitos e estruturas se tornem
familiares para você.
 NA PRÁTICA
Faça um algoritmo que calcule a média de idade dos seus
familiares. Escolha 10 pessoas entre seus primos, tios, pais e
irmãos e insira suas idades em um vetor “idade”. Depois, mostre na
tela qual é a média da idade de vocês. Para ficar mais interessante,
classifique o status desse grupo da seguinte maneira: CRIANÇA
(entre 0 e 12 anos); ADOLESCENTE (entre 12 e 18 anos); JOVEM
(entre 18 e 39 anos); EXPERIENTE (entre 39 e 59 anos); e IDOSO
(acima de 59 anos).
Até o momento, criamos um vetor, inserimos valores e
conseguimos fazer operações aritméticas com eles. Agora, vamos
supor que a gente queira buscar algum dado específico – por
exemplo, a nota 10. Ou ainda, imagine um vetor com os nomes dos
alunos e a gente queira verificar se algum nome está na lista.
Precisaremos varrer o vetor (previamente preenchido) e verificar seus
valores até encontrar o dado que estamos procurando ou até chegar
no final do vetor e não encontrarmos nada.
Para isso, vamos precisar entender como funciona a busca em
um vetor.
3.2 Buscando dados em vetor
Com um vetor preenchido, uma funcionalidade muito útil, na era
da informação, na qual vivemos, é a busca de um dado. As aplicações
são variadas – como a busca de um nome em uma lista, de um
produto em um estoque, de um número ou um dado financeiro –, ou
seja, para qualquer elemento que queiramos buscar no nosso vetor.
Para isso, vamos precisar varrer o vetor em busca do nosso
dado. A estruturaque varre o vetor é o “PARA”, como já fizemos na
inserção de dados. Contudo, ao invés de inserir um dado, agora
vamos procurar esse dado comparando com os elementos inseridos
no vetor. Essa comparação será uma condição lógica, a qual
produzirá um resultado de FALSO ou VERDADEIRO, ou seja, o dado
que estamos procurando é igual ou não ao dado verificado em cada
casa do nosso vetor.
Vamos voltar ao nosso exercício do cálculo da média. Temos um
vetor de cinco posições preenchido com notas válidas e queremos
procurar uma nota específica, a nota 10, por exemplo. Existem
algumas situações que podem ocorrer:
Encontrarmos uma nota 10. Nesse caso, vamos informar em
qual casa ela está no nosso vetor.
Encontrarmos mais do que uma nota 10. Também vamos
informar em quais casas elas estão, além de informar a
quantidade de notas 10 encontradas.
Não encontrar nenhuma nota 10. Nesse caso, informaremos que
não existe esse dado no nosso vetor.
Figura 7 – Busca de uma nota em um vetor
No trecho de código, apresentado na figura 7, comparamos a
nota que o usuário quer buscar no vetor (nota_buscada) com as
notas inseridas no vetor, em cada posição (nota[contador]), onde o
“contador” está varrendo o vetor da posição inicial (posição 1) até a
final (posição 5). Depois do laço “PARA”, imprimimos, na tela, a
quantidade de notas encontradas (note que a variável “quantidade”
está se comportando com um contador e deve ser declarada como
inteiro).
Vamos tentar buscar um nome agora? Criaremos um vetor de
cinco posições para inserir os nomes dos alunos (esse vetor deve ser
declarado como caractere). Em seguida, vamos procurar um nome
específico nesse vetor, como mostra a figura 8.
Figura 8 – Busca de um nome em um vetor
Existem várias maneiras de se efetuar busca em vetor – essa é a
mais simples. Pensando em desempenho, no pior caso, vamos varrer
todo o vetor e não encontrar o dado procurado. Para se evitar esse
tipo de situação, podemos ordenar nosso vetor (em ordem crescente,
ou alfabética, por exemplo) e conseguir melhor performance nessa
busca.
Como desafio de capítulo, construa um vetor de 10 posições, que
guarda as idades dos alunos. Ordene, em ordem crescente, esse vetor
e procure uma idade específica. Verifique as diferenças com o que
fizemos até agora.
Você pode estar se perguntando: mas por que quero melhorar a
performance? Só estou procurando um nome entre cinco possíveis!
Exatamente, nossa busca é pequena, não sentimos diferença. Mas
pense em um sistema de busca no qual milhares de verificações são
feitas por segundo em vetores gigantescos. Esse é outro assunto!
Considerações finais
Vetores são excelentes estruturas para se armazenar muitos
dados do mesmo tipo, como a lista de nomes ou notas de uma
turma. Eles devem ser declarados com tamanhos definidos e com
tipos determinados. A manipulação de vetor se dá pelo laço de
repetição “PARA”, pois sabemos exatamente em que ponto começar
(primeira casa) e onde terminar (última casa).
A inserção de valores em um vetor deve ocorrer indicando em
que casa vamos atribuir aquele valor. E essa indicação se dá pelo
índice dentro dos colchetes, que segue o nome do vetor. Já a busca
de algum dado no vetor deve ser feita varrendo todo o vetor,
procurando o valor que queremos com todos os valores inseridos,
posição por posição. No final, sabemos quantos dados encontramos
no vetor e as posições exatas onde eles estão.
Tanto na inserção quanto na busca, precisamos indicar o índice
(ou posição) do vetor para referenciar, exatamente, a casa na qual
estamos manipulando. Lembrando que o vetor, como um todo,
armazena vários dados, porém, quando indicada sua posição, se
comporta como uma variável comum.
Continue praticando e treinando muito!
Referências
DANTE, L. R. Matemática: contextos & aplicações. v. 1. São Paulo:
Editora Ática, 2011.
TENENBAUM, A. M.; LANGSAM, Y.; AUGENSTEIN, M. J. Estrutura de
dados usando C. São Paulo: Editora Pearson Prentice Hall, 2007.
Capítulo 7
Algoritmos: matrizes
O uso de matrizes, não só na computação, mas em várias áreas
e até em atividades cotidianas, é muito comum. Esse recurso
também armazena muitos dados do mesmo tipo, como o vetor,
porém, em um formato de tabela.
As matrizes são compostas de linhas e colunas e, por isso, são
chamadas de array bidimensional. Para sabermos em qual posição
um dado será inserido, por exemplo, devemos informar suas
coordenadas, ou seja, em qual linha e em qual coluna devemos inserir
o dado específico.
Neste capítulo, vamos apresentar o que são as matrizes e como
manipular esse recurso. Para varrermos uma matriz, faremos uso do
laço de repetição “PARA”, porém, de uma forma aninhada. Dois laços,
um dentro do outro, serão utilizados. Um para controlar as linhas e
outro para controlar as colunas. Dessa forma, deveremos, no nosso
algoritmo, controlar duas variáveis (linha e coluna).
Além de inserirmos dados na matriz, vamos encontrar um dado
específico nessa tabela. Para ambos os casos, teremos de varrer a
matriz sempre iniciando pela primeira linha, passando por todas as
suas colunas. Depois, avançamos para a segunda linha, varrendo
todas as colunas novamente, e, assim, sucessivamente.
Alguns exercícios serão construídos, e você terá, ao final, um
desafio a cumprir.
1 Matriz é tabela?
Você já deve ter ouvido falar de matriz em algum momento da
vida. Segundo Forbellone e Eberspacher (2005), matriz é um conceito
matemático que se desenvolveu a partir do século XIX, com
matemáticos como Arthur Cayley, Augustin-Louis Cauchy e William
Rowan Hamilton.
Lembra-se das operações efetuadas com matrizes? Adição e
subtração de matrizes, multiplicação e divisão, matriz transposta,
matriz identidade, matriz nula, matriz quadrada, etc.
Apesar de podermos, aqui na computação, realizar todas essas
operações, vamos fazer uma abordagem bem prática sobre matrizes.
Você já deve ter desenvolvido alguma planilha eletrônica no
computador, certo? Ou desenhado uma tabela para representar os
preços dos itens em uma compra de supermercado. Nossa matriz se
comportará como uma tabela e, como toda tabela, será composta de
linhas e colunas.
Tabela 1 – Notas das disciplinas do curso de Desenvolvimento de
Sistemas
ALUNOS ANÁLISE DE SISTEMAS LÓGICA DE PROGRAMAÇÃO GESTÃO DE PROJETOS
André 8,5 7,2 10,0
Maria 7,8 9,0 6,7
Ana 10,0 6,1 8,4
João 5,9 7,4 6,8
Na tabela 1, temos representadas as notas das disciplinas do
curso de Desenvolvimento de Sistemas de alguns alunos da turma.
Cada linha é o registro de um aluno e cada coluna, as disciplinas
desse aluno.
 IMPORTANTE
Esse conceito de registro é importante na computação. Falaremos
mais sobre isso nos capítulos de banco de dados.
Na parte interna da tabela, temos todas as notas. Essa é a nossa
matriz! Podemos chamá-la de matriz de notas e observar que é
composta somente de dados do mesmo tipo (nesse caso, tipo real).
Nossa matriz é formada por quatro linhas e três colunas, portanto, ela
é uma matriz
4 × 3 (lê-se, quatro por três). A tabela 2 representa nossa matriz “nota”
e é exatamente isso que vamos construir nesse capítulo.
Tabela 2 – Matriz “nota” 4 × 3
Essa é a representação gráfica de uma matriz matemática e,
para compreender melhor seus conceitos, aplicação e fundamentos,
devemos nos aprofundar mais no fantástico mundo das matrizes.
2 Conceito de matriz
Segundo Forbellone e Eberspacher (2005), matrizes são arranjos
ordenados que, ao contrário dos vetores, podem ter “n” dimensões,
sendo que essas dimensões lhes dão o nome n-dimensional. Uma
matriz de duas dimensões será chamada bidimensional; uma de três
dimensões, tridimensional, e assim sucessivamente. Neste capítulo,
abordaremos apenas matrizes de duas dimensões (ou seja, matrizes
formadas por linhas e colunas) – podemos chamar nossa matriz de
array bidimensional.
Funciona praticamente da mesma forma que um vetor, porém,
utilizaremos dois índices para acessar o dado que queremos. Lembra
do jogo batalha naval? Tínhamos que acertar um navio, em uma
tabela, indicando em qual linha e em qual coluna elepoderia estar
(tabela 3).
Tabela 3 – Tabela 5 × 5 da batalha naval
Para acessarmos a casa indicada na tabela 3, precisamos
passar as coordenadas necessárias – nesse caso, a linha e a coluna
correspondente à casa. Sempre vamos começar indicando a linha e
logo depois a coluna, separadas por vírgula. Portanto, para termos
acesso à casa destacada, indicamos C,3. Aliás, esse conceito é
bastante importante quando falamos de matrizes – saber
exatamente a posição do dado, a qual queremos buscar. Isso será
essencial na manipulação de matrizes (inserção e busca de dados)
que veremos daqui a pouco. Vejamos como ficaria nossa matriz
“nota” apenas com as coordenadas das posições correspondentes a
cada nota – essa matriz é chamada de genérica, segundo Kuhlkamp
(2011).
Tabela 4 – Matriz genérica representada pela
coordenada de posição
Note que, pela tabela 4, para acessar o dado de uma casa
específica, devemos indicar o nome da matriz (no caso, “nota”) e as
coordenadas de linha e coluna. Por exemplo, qual é a nota
correspondente à “nota 3,2”? Basta voltarmos na tabela de notas, e
verificarmos a posição 3,2 (linha 3 e coluna 2): a nota é 6,1.
Compreendeu? Faça com todas as notas, identificando-as como se
estivesse brincando de batalha naval.
3 Manipulando matriz
Antes de manipular nossas matrizes, devemos declará-las,
primeiramente, e esse procedimento é bem parecido com a
declaração de um vetor, porém, agora, devemos indicar dois índices
(coordenadas) para podermos acessar o dado específico e, assim,
conseguirmos manipular a matriz.
Portanto, a declaração da matriz “nota”, no ambiente VisuAlg,
ficará assim:
Var
Nota: vetor [1..4,1..3] de real
Observe que, para um sistema computacional, a matriz se
comporta como um vetor, porém, com duas dimensões – por isso,
seu nome array bidimensional (DEITEL; DEITEL, 2011). Na declaração
desse “vetor bidimensional), indicamos, dentro dos colchetes, a
posição onde começa a primeira linha e a posição onde termina a
última linha (1..4). Separado por vírgula, indicamos a posição inicial
da primeira coluna e a posição da última coluna (1..3). Portanto, a
matriz “nota” é uma matriz 4 × 3.
Agora que já sabemos declarar uma matriz, precisamos
manipulá-la, ou seja, inserir dados e buscar dados. Não se esqueça
que sempre (sempre mesmo) devemos informar o nome da matriz e
suas coordenadas (linha,coluna).
3.1 Inserindo dados em matriz
Lembra que para varrer um vetor utilizamos o laço de repetição
“PARA”? E para varrer uma matriz? Como a matriz é um vetor
bidimensional, utilizaremos dois laços de repetição “PARA”, um dentro
do outro. O primeiro laço (ou laço externo) vai controlar as linhas e o
segundo laço (ou laço interno), as colunas. Então, como temos dois
laços de repetição, cada um controlando uma coordenada diferente,
vamos precisar de dois controladores (“l” para a linha e “c” para a
coluna). Esses dois controladores são variáveis simples e devem ser
declarados com o tipo inteiro.
 IMPORTANTE
Quando utilizamos um laço de repetição “PARA”, manipulamos uma
linha. Quando utilizamos dois laços de repetição “PARA”,
manipulamos uma tabela.
Vamos verificar, então, como ficará nosso algoritmo para
inserção de dados na matriz “nota”, conforme figura 1.
Figura 1 – Inserção de dados na matriz “nota”
algoritmo “inserindo dados em matriz”
var nota: vetor [1..4,1..3] de real l,c: inteiro inicio para l de 1
ate 4 faca para c de 1 ate 3 faca escreva (“Digite a linha “, l, “
coluna “, c, “ = “) leia (nota[l,c]) fimpara fimpara fimalgoritmo
Note que não colocamos o comando “passo 1” nos dois laços
“PARA”. Podemos omitir essa informação, caso nosso incremento
seja 1 (ou seja, sempre que pretendemos acrescentar 1, ou andar de
1 em 1, no nosso vetor ou matriz, não precisamos colocar a
informação “passo 1”. Para as outras situações, essa informação se
faz necessária).
Quando você for executar esse algoritmo, perceba que a primeira
linha fica “estática” até o laço interno varrer todo o vetor dessa linha,
preenchendo todos os campos. Quando esse laço termina, o laço
externo anda uma posição e vai para a linha 2, onde fica “estático” até
o laço interno varrer todas as colunas dessa linha, e assim por diante,
até acabar a quantidade de linhas e o laço externo terminar. Execute o
algoritmo e verifique o que acontece.
O movimento que esses dois laços executam, trabalhando
juntos, é da direita para a esquerda, de cima para baixo (figura 2). Os
dados são inseridos todos na linha 1 (coluna1, coluna2, coluna3) e
quem varre essas colunas é o laço interno. Quando ele termina, o laço
externo incrementa e vai para a linha 2, onde todos os dados são
inseridos novamente (coluna1, coluna2, coluna3). Esse movimento se
repete até terminarem todas as linhas.
Figura 2 – Movimento de inserção dos laços de
repetição “PARA”
Uma vez nossa matriz preenchida, agora é hora de lermos os
dados armazenados em cada casa. O processo é o mesmo, vamos
varrer a tabela toda imprimindo, na tela, os valores inseridos.
3.2 Buscando dados em matriz
A busca de dados em matriz é tão importante quanto a busca
em vetores. Já que temos dados em uma tabela, precisamos ler
esses dados para entender, por exemplo, qual foi a nota da Ana na
disciplina de lógica de programação e decidir se está aprovada ou
reprovada.
O procedimento é o mesmo da inserção: dois laços “PARA”, um
dentro do outro, o externo controla as linhas e o interno controla as
colunas. Porém, agora, não vamos inserir dados, vamos imprimir na
tela os dados já digitados. A figura 3 apresenta o algoritmo completo:
Figura 3 – Busca de dados na matriz “nota”
algoritmo “inserindo dados em matriz”
var nota: vetor [1..4,1..3] de real l,c: inteiro inicio para l de 1
ate 4 faca para c de 1 ate 3 faca escreva (“Digite a linha “, l, “
coluna “, c, “ = “) leia (nota[l,c]) fimpara fimpara limpatela()
para l de 1 ate 4 faca para c de 1 ate 3 faca escreva (
nota[l,c], “ “) fimpara escreval() fimpara fimalgoritmo
Observe que o método escreva() está imprimindo a nota da
posição específica indicada pela coordenada [l,c] e um espaço em
branco (indicado pelo espaço entre as aspas). Ou seja, serão
impressas, na mesma linha, todas as colunas da matriz, separadas
por um espaço. Antes de terminar o segundo “PARA”, colocamos o
comando escreval() sem nenhum parâmetro. Isso significa que o
sistema vai pular uma linha, indo para a linha 2, imprimindo
novamente todas as colunas dessa linha, separadas por espaços, e
assim sucessivamente. Veja na tabela 5 como fica o resultado,
impresso na tela, de algumas notas dessa matriz:
Tabela 5 – Resultado da impressão dos dados da matriz “nota”
Agora, pense em um outro contexto: e se quisermos imprimir
uma nota específica, e não toda a matriz? Nesse caso, devemos
informar qual a nota, imprimir, indicando as coordenadas de linha e a
coluna dentro do comando escreva().
Escreva ( nota[l,c] )
Para imprimir essa única nota, não há necessidade de utilizar os
laços de repetição, pois não estamos varrendo a matriz. Precisamos
apenas obter as coordenadas da linha e a coluna onde essa nota
está. Podemos, também, imprimir todas as notas acima de 6.0, por
exemplo, para saber quantos alunos estão APROVADOS. Para isso,
precisaríamos varrer toda a matriz, imprimindo apenas as notas
maiores que 6.0, ou seja:
SE ( nota[l,c] >= 6.0 ) entao
Escreva ( nota[l,c] )
O trecho de código, acima, deve estar dentro do “PARA” interno.
Toda vez que formos verificar uma nota, em uma linha e coluna
indicadas pelas coordenadas [l,c], a estrutura “SE” analisa se esta
condição é VERDADEIRA (ou seja, se a nota é maior ou igual a 6.0) e
imprime a nota na tela. Caso quiséssemos contar a quantidade de
notas acima de 6.0, bastaria utilizar um contador dentro da estrutura
“SE”.
Observe, também, que essa estrutura não tem “SENAO”. Isso
porque não queremos fazer nada, caso o resultado da condição
lógica seja FALSA, ou seja, a nota seja menor que 6.0. Faça as
alterações e verifique todos os resultados. Quanto mais você treinar,
mais conseguirá entender o usoe a manipulação desse recurso que é
a matriz.
Considerações finais
As matrizes são recursos bastante parecidos com tabelas, pois
possuem linhas e colunas, e servem para armazenar muitos dados do
mesmo tipo. São, também, chamadas de arrays bidimensionais e
exigem duas coordenadas para localizarmos uma posição específica
para manipulação.
Para varrer uma matriz, é necessário o uso de dois laços de
repetição “PARA” aninhados, ou seja, um dentro do outro. O laço
externo controla as linhas e o laço interno controla as colunas, em um
movimento de cima para baixo, da esquerda para a direita; ou seja,
para manipular uma matriz, percorremos todas as colunas da
primeira linha, depois todas as colunas da segunda linha, e assim
sucessivamente.
Também podemos localizar um dado específico dentro da nossa
matriz, ou inserir um dado em uma posição determinada. Basta
informarmos as coordenadas dessa posição, indicando em qual linha
e em qual coluna vamos manipulá-la. Não se esqueça que, para esses
casos, não precisamos varrer a matriz, pois temos a localização
exata da posição que queremos.
Lembre, também, de informar as coordenadas da posição
sempre dentro dos colchetes, obedecendo a ordem [linha, coluna]
depois do nome da matriz. Exemplo: nota[2,3] – indica a posição
segunda linha, terceira coluna da matriz “nota”.
Referências
DEITEL, H. M.; DEITEL, P. J. C – como programar. 6. ed. São Paulo:
Editora Pearson Prentice Hall, 2011.
FORBELLONE, A. L. V.; EBERSPACHER, H. F. Lógica de programação:
a construção de algoritmos e estruturas de dados. São Paulo:
Editora Pearson, 2005.
KÜHLKAMP, N. Matrizes e sistemas de equações lineares. Santa
Catarina: Editora da UFSC, 2011.
Capítulo 8
 
Programação estruturada
Quando aprendemos lógica de programação e todos os recursos
e estruturas para se construir sistemas e algoritmos, é importante
entender qual linguagem utilizar, quais seus objetivos e usabilidade.
Junto às linguagens de programação, existem os tipos de
programação e cada um tem suas especificidades e características
que melhor se adequam aos nossos objetivos, quando pensamos a
lógica para resolvermos as atividades e tarefas do projeto de
software.
Neste capítulo, apresentaremos a evolução das linguagens de
programação ao longo do tempo, entendendo suas gerações,
vantagens, desvantagens e especificidades. Um comparativo das
linguagens de baixo, médio e alto níveis será trazido para análise do
leitor.
Além disso, vamos apresentar os conceitos dos tipos de
programações linear e estruturada, entender as diferenças entre elas
e as aplicações de modularização (importantes conceitos para a
compreensão da construção de algoritmos em programação
estruturada).
 
1 Linguagem de programação
Com o grande avanço da informática, o computador passou a ter
papel fundamental em todos os segmentos de uma organização (seja
ela empresa ou um governo). Para que o computador execute suas
tarefas e funções, é preciso programá-lo e, para isso, faremos uso
das linguagens de programação. Existem inúmeras definições de
linguagens de programação, porém, para facilitar nossa vida e nosso
entendimento, uma definição simples, segundo Xavier (2014), é que
uma linguagem de programação é um conjunto limitado de
instruções (vocabulário) que cumpre um grupo de regras (sintaxe) e
se organiza de maneira a resolver um determinado problema.
Tal linguagem permite ao programador entender e trabalhar com
dados específicos e precisos, além de poder armazenar e trafegar
esses dados e determinar as ações que devem ser tomadas, de
acordo com as regras aplicadas.
Ao longo dos anos, inúmeras linguagens de programação foram
criadas e desenvolvidas. Umas para uso mais geral e outras para uso
específico em áreas de aplicação exclusivas. Para entendermos
melhor as linguagens, precisamos estudar um pouco mais de perto
as classificações dos níveis em que se encontram essas linguagens,
lembrando que os níveis mais baixos estão mais próximos das
linguagens interpretadas pelo processador e mais distante das
linguagens naturais.
O nível mais baixo que temos é a linguagem de máquina – os
computadores entendem, basicamente, operações de circuitos
elétricos. Sua programação, na forma mais primitiva, é escrita por um
sistema numérico chamado sistema binário – composto apenas
pelos números 0 (zero) e 1 (um) que, combinados, podem representar
qualquer informação que trafega em uma máquina computacional,
sejam elas texto, imagem, áudio, vídeo, etc., conforme mostra a figura
1.
 
Figura 1 – Programação em linguagem de máquina
0 0 1 0 1 1 1 0 1 0 0 1 1 0 1 0 0 1 1 0
1 1 1 0 0 0 1 1 0 1 0 0 1 1 0 0 0 0 1 1
1 0 0 1 0 1 0 0 1 1 0 0 0 1 1 0 1 0 1 0
A linguagem de máquina faz parte da primeira geração das
linguagens de programação e tem como principal vantagem ser
muito rápida e eficiente, pelo fato desse código (binário) ser
executado diretamente na CPU.
Entretanto, essa forma de se programar tem suas desvantagens.
É extremamente difícil sua compreensão (leitura e escrita) e a
combinação binária pode ser muito longa, impossibilitando ao
programador, memorizar essa cadeia de combinações para
representar as instruções lógicas.
Para tentar facilitar a compreensão da linguagem de máquina, foi
desenvolvida a notação hexadecimal, que transformava o sistema
binário (composto apenas de dois elementos) em um sistema de 16
elementos (como mostra a figura 2). Contudo, essa notação também
se apresentava impraticável, apesar da simplificação.
 
Figura 2 – Programação em linguagem hexadecimal
AA 01 1D CA 4B 10 11 0E FF AB 8A 99 23 4C 59 20 A2 33 12 02
6F E4 1B 43 90 1E 88 71 A7 15 A9 BB CB 1F 05 5B 80 00 01 3E
0F 66 51 DD 4C 09 50 21 14 4B 19 98 53 49 1F 00 BA CC 1A 0E
Como essa notação também é inviável em termos práticos para
os programadores, criou-se uma necessidade de desenvolver uma
linguagem que substituía esse conjunto de números por símbolos,
compreensível aos olhos humanos, mas que ainda representasse as
instruções de máquina, conversando, assim, com o hardware. Dessa
forma, nasceu a segunda geração de linguagens de programação
(representadas pelo Assembly e Fortran), que substituiu a notação
binária e hexadecimal por palavras abreviadas, chamadas
mnemônicos, que indicavam a sua operação. Por exemplo:
 
ADD a, b
Na instrução acima, temos o mnemônico ADD (abreviação da
palavra Addition) e dois registradores como parâmetros (a e b).
Quando o processador executa essa instrução, ele soma o conteúdo
de a com o conteúdo de b e armazena o resultado em a. Seria o
equivalente, em português estruturado, a: a <- a + b .
 
 PARA SABER MAIS
O termo mnemônico é derivado do grego “menmóne”, e significa
recordação. A técnica consiste em juntar prefixos das palavras para
decorar uma expressão ou uma frase importante.
A vantagem da utilização dessa notação é evidente, e trouxe uma
revolução na maneira de se programar, que é muito próxima do que
os programadores têm na atualidade. Porém, as linguagens de baixo
nível dependem muito do hardware, ou seja, suas instruções são
escritas levando-se em consideração o processador, as memórias e
os periféricos da máquina na qual serão processadas. Além disso, a
segunda geração de linguagens de programação não é eficiente para
tratar grandes quantidades de instruções, e sua manutenção é
consideravelmente complexa.
A evolução da forma como manipulamos os dados exigiu o
surgimento de estruturas bem definidas e modularizadas das
instruções de código para representar toda a lógica envolvida em
uma programação. Contudo, apesar de pouco utilizada hoje em dia, a
linguagem Fortran continua muito popular em várias comunidades
científicas e de engenharia, desempenhando importante papel de
missão crítica em muitos projetos da Nasa.
Com isso, fez-se necessário o surgimento de linguagens que
trabalhassem um pouco mais próximas da linguagem falada pelo ser
humano, dando início à terceira geração de linguagens de
programação, como C, Pascal e Cobol, por exemplo. São as primeiras
linguagens a trazer uma estrutura com variáveise funções. A
linguagem C, por exemplo, trabalha de uma maneira estruturada, e
algumas de suas instruções são escritas com palavras em inglês,
como se conversássemos com o código. Por exemplo, para
imprimirmos uma mensagem na tela, basta escrevermos o seguinte
comando: printf (“Linguagem de Programação C”). Seria o
equivalente, em português estruturado, ao comando: escreva
(“Linguagem de Programação C”).
Essas linguagens podem ser consideradas de nível médio, e,
assim como as linguagens da segunda geração, também levam em
consideração alguns elementos de hardware, como ponteiro, por
exemplo, e têm como vantagem, além da velocidade de
processamento, a considerável facilidade em se escrever. O Cobol
ainda é amplamente utilizado por grandes instituições financeiras,
como os bancos, por exemplo.
Entretanto, o grande objetivo dos maiores estudiosos de
linguagens de programação é termos uma linguagem na qual
possamos escrever como falamos, com palavras do nosso dia a dia,
sem nos preocuparmos com o hardware na qual serão processadas.
Essas são as linguagens de alto nível, como o Java ou o Python, por
exemplo, e representam a quarta geração das linguagens de
programação. Suas instruções são escritas com palavras em inglês e
seus paradigmas são orientadas a objetos.
 
 PARA SABER MAIS
Paradigma é um conceito das ciências e da epistemologia, que
define um exemplo típico ou modelo de algo. É a representação de
um padrão a ser seguido. É um conjunto de formas vocabulares,
que servem de modelo para um sistema de flexão ou de derivação.
Em orientação a objetos, os paradigmas são os padrões que
definem a linguagem, como classes e objetos, por exemplo. Para se
aprofundar mais no assunto, sugiro a leitura do livro Java – como
programar, de Deitel, H. M.; Deitel, P. J., 8. ed. 2010.
Essas linguagens têm como vantagem a facilidade em se
escrever e construir os códigos, porém, são lentas no processamento,
por estarem mais distantes da máquina, precisando, assim, de maior
esforço de um compilador para transformar seu código em
linguagem de máquina.
 
 PARA SABER MAIS
Compilador é um software que converte uma linguagem de
programação para a linguagem que o computador entende
(linguagem binária), gerando um arquivo com extensão EXE, ou
seja, um programa executável pelo computador. Tradutor é um
programa que traduz um texto de uma língua para outra.
Contudo, uma linguagem de programação, seja ela qual for, é
formada por palavras que são agrupadas em frases para constituir os
comandos e as instruções. Dessa forma, segundo Puga e Rissetti
(2009), podemos chamar as palavras de uma linguagem de
programação de palavras-chave e as frases criadas com essas
palavras, de estruturas de programação.
As primeiras linguagens de programação eram sequenciais e
chamadas de programação linear, pois não havia nenhuma
interatividade e suas instruções e comandos se destinavam a uma
atividade específica. Depois, surgiram as linguagens estruturadas, ou
programação estruturada, que permitiram o desenvolvimento de
sistemas mais interativos, de forma mais organizada e com maior
funcionalidade (PUGA; RISSETTI, 2009). Aliás, essas funcionalidades
e maior interatividade vamos estudar mais a fundo quando falarmos
de funções e procedimentos.
Mais recentemente, a programação orientada a objetos
promoveu uma grande transformação na forma como os sistemas
são concebidos e codificados, trazendo grande interatividade,
processamento distribuído e ampla diversidade de ambientes e
dispositivos, como celulares, por exemplo.
 
2 Linearidade
Segundo Xavier (2014), na programação linear, a construção das
instruções e comandos segue uma sequência de passos
consecutivos, com início e fim definidos. Esse princípio era utilizado
pelas primeiras linguagens de programação, as quais usavam
códigos numéricos ou mneumônicos para a codificação das
instruções.
As linguagens de baixo nível são exemplos de programação
linear,
pois ajudaram a codificar instruções em mneumônicos, que antes
eram escritas como instruções numéricas em binário (o código
binário é formado pelos números 0 e 1 e representam todas as
instruções entendidas por uma máquina no seu processamento). Em
Assembly, por exemplo, a soma de dois números é representada por
“ADD”, que é o mneumônico da expressão em inglês para adicionar.
Algumas linguagens surgiram para ampliar a quantidade de
instruções e facilitar a simbologia utilizada pela programação linear.
Em Basic, por exemplo, as linhas de código são numeradas uma a
uma e a sua execução seguia essa ordem. Caso algum desvio fosse
necessário, devíamos indicar qual linha deveria ser executada usando
a instrução “GOTO” (ir para). A figura 3 apresenta um exemplo da
programação linear:
 
Figura 3 – Exemplo de programação linear
Fonte: adaptado de Puga e Rissetti (2009, p. 22).
Note que a programação linear é escrita em um único bloco
principal, onde todas as instruções, mneumônicos e simbologias
estão, sequencialmente, representadas, resolvendo nosso problema
(tarefa) como um todo. Esse tipo de programação (linear) é restrita na
forma de programar e oferece pouca flexibilidade ao desenvolvedor,
porém, é perfeitamente possível gerar, a partir desse programa, uma
programação estruturada com algumas poucas alterações, fazendo
com que aumente a interação e o poder computacional.
 
 IMPORTANTE
A linguagem Assembly ainda é utilizada em procedimentos que
manipulam diretamente o hardware do computador e em
equipamentos eletrônicos.
A desvantagem da programação linear é a complexidade.
Programas lineares extensos são difíceis de ser desenvolvidos e até
compreendidos, sem falar da manutenção e atualização.
 
3 Programação estruturada
A programação estruturada traz mais interatividade na
construção do algoritmo e na solução de problemas computacionais
(DEITEL; DEITEL, 2010). Imagine pegarmos toda a programação
linear, sequencial, com início e fim, e dividirmos as tarefas com a
finalidade de potencializar a resolução do nosso problema. Não
estamos falando apenas da complexidade de se construir um imenso
programa computacional, mas no custo e no tempo de um projeto de
software.
A divisão de tarefas não é algo trivial e fácil de se resolver.
Imagine que você está participando de uma gincana na sua escola e
sua equipe precisa desenvolver uma série de atividades para ganhar a
competição. Você pode resolver essas tarefas das seguintes
maneiras:
 
1. Todos da equipe resolvem todas as atividades, uma a uma, da
primeira até a última. Isso lembra muito a programação linear.
2. Separar a equipe em grupos menores para resolverem as
atividades separadamente, sem ordem (a não ser que uma
atividade dependa da outra, como um pré-requisito). Note que a
interatividade será bem maior entre os membros da equipe,
como na programação estruturada.
Mas você deve estar se perguntando: Como dividir as tarefas
entre os grupos? Quem tem mais habilidade em qual atividade? Quais
atividades escolher para resolver primeiro? Isso justifica o nome
desse tipo de programação: estruturada. Vamos resolver tudo por
meio das estruturas que essas linguagens nos proporcionam.
Algumas você já conhece, como os comandos de entrada e saída de
dados – escreva() e leia() – as estruturas de tomada de decisão – SE-
ENTAO – e as estruturas de repetição – ENQUANTO-FACA e PARA-
FACA.
Esse tipo de programação, por meio de suas linguagens, nos
proporciona inúmeras estruturas interessantes. Duas delas
estudaremos no próximo capítulo – função e procedimento. Por
enquanto, vamos entender como essa programação funciona.
Na programação estruturada, a divisão de tarefas é um processo
chamado de modularização. Nesse processo, divide-se o programa
em partes ou módulos que executam tarefas específicas. É
importante que essas tarefas, representadas pelos módulos, sejam
específicas e que cada uma delas tenha a maior independência
possível das demais realizadas por outros módulos do programa, ou
seja, a independência funcional está relacionada diretamente à
modularização (PUGA; RISSETTI,2009).
É como se as atividades que você escolhesse para resolver na
gincana fossem independentes umas das outras, ou seja, não pode
ter tarefa repetida sendo executada por duas equipes. Além de causar
retrabalho, vai atrasar a execução de todas as atividades. Imagine
isso em um projeto de software: seria extremamente custoso e
descumpriria o cronograma.
A figura 4 mostra como podemos entender o conceito de
modularização:
 
Figura 4 – Exemplo de programação
estruturada
Note que o bloco principal foi dividido em vários blocos menores,
identificados por letras (A, B, C, D, E e P), que representam os
módulos. O bloco P é o bloco principal; e os blocos de A a E são
atividades que foram divididas. Lembre-se que as atividades não
podem ser as mesmas, por isso separamos as figuras por cores –
cada bloco executa uma atividade específica. O bloco P pode acionar
os outros blocos, quando necessário, na ordem em que precisar ou
seguindo as regras do negócio.
Esses blocos (módulos) podem representar, por exemplo, as
seguintes tarefas: A – inserir as notas de um aluno B – calcular a
média C – verificar sua situação (APROVADO, REPROVADO ou
EXAME) D – imprimir as notas do aluno E – editar alguma nota P –
módulo principal, que gerencia e aciona, na ordem em que for preciso,
todas as outras atividades.
Esses são os conceitos de funções e procedimentos, sistemas
utilizados pela programação estruturada para aplicar o conceito de
modularização.
 
Considerações finais
Verificamos, neste capítulo, os conceitos de linguagens de
programação, na qual entendemos quando se deve utilizar linguagens
de baixo, médio e alto níveis. Além disso, compreendemos os tipos de
programação e suas aplicações.
A programação está em todos os equipamentos eletrônicos
atuais. Cada programa, cada página na internet está escrita em
alguma linguagem de programação. Com o tempo, as linguagens
vêm se unindo, formando linguagens mais fortes e com mais
funções. Ela passou por um grande processo, porém bastante rápido.
Estas linguagens estão ficando cada vez mais fáceis de interpretar e
escrever.
É importante ressaltar que a escolha da linguagem é
fundamental para se atingir o objetivo dos nossos algoritmos e para
que executem as atividades, gerando os resultados esperados. Os
tipos de programação vão influenciar diretamente nessa escolha.
A programação linear é sequencial, com início e fim, e traz pouca
interação e flexibilidade para o desenvolvedor; porém, possui
vantagens, como a velocidade no processamento e a manipulação
direta do hardware do computador. Já a programação estruturada
traz, em seus sistemas, a possibilidade de maior interatividade e
divisão de tarefas, importante conceito para a programação de
sistemas grandes e complexos.
Por fim, compreendemos o conceito de modularização e sua
importância para a construção dos algoritmos na solução das
atividades que exigem alto grau de complexidade, porém, sem perder
a eficiência, pois as tarefas divididas em módulos são independentes
e específicas.
 
Referências
DEITEL, H. M.; DEITEL, P. J. Java – como programar. 8. ed. São Paulo:
Editora Pearson Prentice Hall, 2010.
PUGA, S.; RISSETTI, G. Lógica de programação e estruturas de
dados com aplicação em Java. 2. ed. São Paulo: Editora Pearson,
2009.
XAVIER, G. F. C. Lógica de programação. São Paulo: Editora Senac
São Paulo, 2014.
Capítulo 9
Programação: funções e
procedimentos
Uma das grandes evoluções da programação estruturada é o uso
de modularização, ou seja, dividir as tarefas, buscando otimizar
nossos recursos de tempo e processamento, por exemplo. E isso é
possível com a utilização de funções e procedimentos, que são
pedaços independentes de código capazes de executar uma tarefa
específica.
Neste capítulo, será possível entender o uso das funções e
procedimentos, as diferenças principais entre eles e o conceito de
parâmetros. Aliás, os parâmetros são de extrema importância,
quando tratamos de funções e procedimentos, pois fazem a
comunicação entre os módulos. Além disso, temos o retorno de
valores, que também faz a comunicação de uma função, devolvendo
o valor resultante de sua execução.
1 Conceitos de função
Você já deve ter ouvido falar em função na matemática. Lembra-
se do f(x)? Dos gráficos da função? Mas fique tranquilo, caro leitor.
Apesar de podermos relacionar os conceitos de função da
matemática com as funções da computação, não o faremos aqui.
Vamos direto ao assunto.
Vamos pensar em função como sendo um “cargo” – cargo que
alguém ocupa em uma empresa, por exemplo. Imagine que o diretor
dessa empresa precise aumentar as vendas do seu produto (esse é o
problema a ser resolvido) – ele acionará os departamentos de
marketing, de vendas e de produção. Cada um desses departamentos
tem uma função específica e desenvolverá parte do problema, com o
objetivo de cumprir a tarefa como um todo. A ideia é a mesma que
estudamos no capítulo anterior, na programação estruturada: dividir
as tarefas para otimizar recursos. A isso demos o nome de
modularização.
As funções farão exatamente isso. Teremos um módulo principal
(o diretor da empresa) e vários módulos funcionais (todos os
departamentos da empresa), que vão ajudar a resolver o problema
geral (aumentar as vendas da empresa).
Em computação, segundo Xavier (2014), função é uma sub-
rotina, que consiste em uma porção de códigos, que resolve um
problema muito específico, parte de um problema maior (a aplicação
final). O conceito de função indica a devolução de um valor dessa
função para o módulo que o iniciou. Por exemplo, se o diretor da
empresa solicitou (iniciou) ao departamento de vendas (função
venda) um treinamento de sua equipe, essa função deve retornar uma
resposta (um valor) ao diretor informando sobre o treinamento
efetuado.
 PARA PENSAR
O conceito de função difere da noção de procedimento, já que
devolve um valor: se bem que, em algumas linguagens, essa
distinção não é sequer existente – por exemplo, em C, a
implementação de um procedimento é uma função do tipo void. No
contexto da programação orientada a objetos, essas sub-rotinas
são encapsuladas nos próprios objetos, passando a se designar
métodos.
Existem algumas vantagens em se utilizar funções na
construção de códigos e algoritmos computacionais:
Capacidade de reúso: podemos acionar quantas vezes
quisermos um departamento da empresa. E não só pelo diretor
(que é o módulo principal), mas por qualquer outro módulo que
possa ter acesso àquele departamento – por exemplo, o
departamento de vendas pode acionar a produção solicitando
alguma coisa (o desenvolvimento de sua tarefa específica, no
caso da programação).
Facilidade de manutenção: quando precisávamos efetuar
alguma atualização ou alteração na programação linear,
tínhamos que rever todo o código, linha a linha, e efetuar as
alterações nos preocupando se isso afetaria o restante do código
e o resultado esperado. Na programação estruturada, com o
conceito de modularização, temos a possibilidade de efetuar a
manutenção apenas da função específica, sem afetar o restante
dos módulos (pois, como já dissemos, eles são independentes).
É como se o problema do aumento das vendas da empresa,
citada acima, fosse do departamento de produção. Podemos
efetuar alterações apenas nesse setor, sem interferir no
marketing e nos vendedores, diretamente.
Para utilizarmos função, devemos declará-la primeiro, pois a
função não deixa de ser uma estrutura (módulo) da programação
estruturada. A sintaxe do escopo de uma função, em VisuAlg, é a
seguinte:
funcao <nome_da_função> (parâmetros:
tipo_de_parametro): Tipo_de_retorno Var
// declaração das variáveis internas
Inicio // seção de comandos Retorne
<variável> fimfuncao
Vamos entender cada termo da declaração da nossa função:
funcao: é a palavra-chave do VisuAlg para indicar que
começaremos a criação de uma função. Note que a palavra deve
ser escrita sem cedilha e sem assento.
Nome_da_função: crie um nome para sua função. Esse nome
deve representar a tarefa dessa função e deve respeitar as
mesmasregras e condições de criação dos nomes das variáveis.
Parâmetros: indique quais os parâmetros (valores) que essa
função precisa para poder executar sua tarefa. Geralmente, é
uma variável e deve conter um tipo (tipo_de _parametro).
Falaremos mais sobre os parâmetros no próximo tópico.
Tipo_de_retorno: como o próprio conceito de função diz, ela
deve retornar um valor. Indique, aqui, apenas o tipo desse valor
(os mesmos tipos das variáveis).
Retorne <variável>: a palavra retorne é chave no VisuAlg e indica
que, nesse momento, você retornará um valor para o módulo que
iniciou essa função. À frente da palavra “retorne”, coloque qual
variável deve ter seu valor retornado.
Fimfuncao: quando terminarmos os comandos da nossa função,
devemos indicar, ao VisuAlg, o seu término com a palavra-chave
fimfuncao.
 IMPORTANTE
As funções devem ser declaradas antes do algoritmo principal
(indicada pela palavra-chave algoritmo, no VisuAlg.
Veja como fica a declaração de uma função que faz a soma de
dois números:
funcao soma (a,b: inteiro): inteiro var
resultado: inteiro inicio resultado <- a + b retorne resultado
fimfuncao
As variáveis criadas dentro da função são enxergadas apenas
pela função. Todos os outros módulos não as enxergam e não
conhecem o seu valor. Note que essa função (chamada soma) tem
dois parâmetros (a e b do tipo inteiros). Vamos entender o porquê
desses parâmetros e como utilizá-los.
1.1 Parâmetros
Segundo Puga e Rissetti (2009), parâmetros são variáveis ou
valores que podem ser transferidos do algoritmo principal para um
módulo que está sendo chamado. Eles funcionam como
comunicadores entre os módulos.
No nosso exemplo anterior, a passagem de parâmetros fora
passada pelo módulo que chamou a função (pode ser o principal ou
qualquer outro módulo) e as variáveis a e b receberam os valores das
variáveis passadas para elas. Dentro da função, na seção de
comandos, foi feita a soma desses dois valores e atribuído à variável
interna (ou local) “resultado”. Depois, essa variável foi retornada ao
módulo que chamou a função soma.
Existem dois tipos de passagem de parâmetro: por valor e por
referência.
Passagem de parâmetro por valor: nesse tipo de passagem de
parâmetro, os valores passados pelo módulo que chama a
função são copiados para as variáveis criadas dentro dos
parênteses localizados à frente do nome da função.
Exemplo: funcao soma (a,b: inteiro): inteiro As variáveis a e b, do
tipo inteiros, vão receber uma cópia das variáveis ou valores
passados pelo módulo que chamou essa função. Aliás, vamos criar o
módulo (principal), que vai chamar essa função soma e verificar a
passagem de parâmetros.
1. funcao soma (a,b: inteiro): inteiro 2. var 3. resultado: inteiro
4. inicio 5. // Seção de Comandos 6. resultado <- a + b 7.
retorne resultado 8. fimfuncao 9. algoritmo “soma”
10. var 11. x, y, z: inteiro 12. inicio 13. // Seção de Comandos
14. escreva (“Digite o primeiro número :”) 15. leia (x) 16.
escreva (“Digite o segundo número :”) 17. leia (y) 18. z <-
soma (x,y) 19. escreva (“A soma dos dois números é “, z) 20.
fimalgoritmo
Observe que na linha 18 o algoritmo chama a função soma e
passa os parâmetros x e y (que foram os valores digitados pelo
usuário). Nesse momento, o programa vai até a linha 1 e copia esses
valores para as variáveis a e b. Na linha 6, a soma é efetuada e seu
valor atribuído à variável resultado (que foi uma variável criada dentro
da função, ou seja, é uma variável local). Na linha 7, a função retorna
o valor armazenado pela variável resultado para o algoritmo principal
(quem chamou a função soma). Esse valor chega até a linha 18 (onde
o programa se encontrava “parado” esperando esse valor de retorno)
e o atribui à variável z. 
A linha 19 imprime, na tela, o valor de z.
 NA PRÁTICA
Como a função retorna valor e esse valor foi impresso na tela,
podería mos ter feito o exercício anterior diferente: tiraríamos a linha
18, e na linha 19 poderíamos imprimir o valor da soma chamando,
dentro do comando escreva(), a função soma. Ficaria dessa forma:
escreva (“A soma dos dois números é“, soma (x,y)). Refaça o
exercício no VisuAlg e o execute, verificando seu resultado. Não se
esqueça, também, de retirar a variável z da declaração de variáveis,
pois não estamos mais utilizando-a.
Na passagem de parâmetro por valor, é feita uma cópia dos
valores das variáveis, mantendo os valores originais intactos, ou seja,
as variáveis a e b recebem uma cópia das variáveis x e y. Porém, se
as variáveis x e y mudarem os valores, as variáveis da função soma
não conseguem enxergar, pois a cópia já foi feita. Agora, imagine o
seguinte: e se essa alteração for importante para a função? Como ela
pode enxergar todas as possíveis alterações que estão acontecendo
fora dela? Vamos responder essas perguntas no próximo tipo de
passagem de parâmetros.
Passagem de parâmetro por referência: na passagem de
parâmetro por referência, todos os valores alterados, tanto no
módulo principal quanto na função, são enxergados por ambos.
Aqui, não passamos valores como as cópias feitas na passagem
de parâmetro por valor. Passamos uma referência, um endereço
de memória. Todos os módulos que possuírem esse endereço
conseguem enxergar as alterações efetuadas por qualquer
módulo.
 PARA SABER MAIS
Em linguagens como C, por exemplo, essa passagem é feita
usando-se o & (lê-se: e comercial) antes do nome da variável. Esse
símbolo & indica que estamos passando o endereço da memória
daquela variável, e não o seu valor. O escopo desse tipo de
passagem ficaria assim: function soma (int &a).
No VisuAlg, esse tipo de passagem é feito utilizando-se a palavra
var seguida do nome da variável e seu tipo (tudo isso dentro dos
parênteses, no local indicado por parâmetros: tipo_de_parametro).
Observe que não há retorno nesse tipo de passagem, pois não
precisamos retornar seu valor. Quem tiver seu endereço consegue
enxergar qualquer alteração efetuada por qualquer módulo.
Entretanto, como falamos anteriormente, o conceito de função
indica que ela deve retornar um valor (ao menos no VisuAlg). Então,
devemos utilizar outra estrutura que não retorna valor para o módulo
que o chamou. Está na hora de falarmos sobre procedimentos.
2 Procedimento
O procedimento tem a mesma funcionalidade de uma função,
porém, segundo Pulga e Rissetti (2009), a diferença entre os dois é
que o procedimento não retorna valor. Portanto, não há necessidade
da palavra retorne em seu escopo.
Porém, note uma coisa: para vermos os valores gerados dentro
do procedimento, devemos imprimi-lo na própria estrutura ou utilizar
passagem de parâmetro por referência. Verifique a sintaxe do escopo
de um procedimento:
procedimento <nome_procedimento>
(parâmetros: tipo_de_parametro) Var
// declaração das variáveis internas
Inicio // seção de comandos
fimprocedimento
A palavra-chave é um procedimento que indica o começo da
estrutura. O nome segue as mesmas regras do nome da função, os
parâmetros seguem as mesmas condições, porém não existe
retorno. A palavra
fimprocedimento indica o término da estrutura.
Para entendermos a diferença entre essas duas estruturas, faça
o seguinte exercício no VisuAlg:
1. Procedimento somaP (a,b: inteiro) 2. Var 3. Res: inteiro 4.
Inicio 5. Res <- a + b 6. Fimprocedimento 7. Funcao somaF
(a,b: inteiro): inteiro 8. Var 9. Res: inteiro 10. Inicio 11. Res <-
a + b 12. Retorne res 13. Fimfuncao 14. Algoritmo 15. Var
16. X,Y: inteiro 17. Inicio 18. X <- 10
19. Y <- 20
20. Escreva (“A soma utilizando FUNÇÃO é :”, somaF (X,Y))
21. somaP (X,Y) 22. Fimalgoritmo
Na linha 20, nós chamamos a função somaF dentro do comando
escreva(), pois sabemos que a função retorna valor e precisamos
imprimir na tela. Já na linha 21, chamamos o procedimento somaP,
mas não atribuímos a nenhuma variável, pois sabemos que ela não
retorna valor. Então, como vamos saber o resultado da soma
efetuada dentro da estrutura procedimento? Podemos utilizar dois
recursos:
1. Passagem de parâmetro por referência: No VisuAlg, essa
passagem é feita utilizando apalavra var. Portanto, temos de
mudar a linha 1, inserindo a referência da variável “res” – que
agora será criada dentro do módulo principal, ou seja, na linha
16. A nova linha 1 ficará assim: procedimento somaP (a,b: inteiro;
var res: inteiro). As linhas 2 e 3 não serão mais necessárias (pois
declaramos a variável “res” no módulo principal). E a linha 16
ficará dessa forma: X,Y,res: inteiro. Entretanto, precisaremos
alterar a chamada do procedimento, na linha 21, para somaP
(X,Y,res) e inserir a linha 22 (antes de fechar o fimalgoritmo),
imprimindo o valor da soma efetuada pelo procedimento somaP:
escreva (“A soma utilizando PROCEDIMENTO é :”, res). Faça as
alterações e execute o código (confira a resposta na íntegra no
próximo tópico).
2. Imprimir o resultado da soma dentro do procedimento somaP,
antes de fecharmos o fimprocedimento. Basta colocar o
comando escreva (res) entre as linhas 5 e 6. Corrija o exercício e
execute-o, verificando seu resultado.
3 Aplicando funções
As funções são estruturas bem vantajosas e muito utilizadas na
construção de sistemas computacionais, existindo, portanto,
inúmeras aplicações. Porém, nem sempre precisamos criar todas as
funções nas quais utilizaremos no algoritmo. Isso porque já existem
várias funções prontas para nosso uso e estão “embutidas” na IDE
(compilador ou interpretador) da linguagem que você estiver
trabalhando. Em algumas linguagens, inclusive, devemos indicar em
qual pacote ou biblioteca essas funções estão para podermos utilizá-
las. Mas esse é outro assunto, vamos nos concentrar nas funções.
Nos nossos exercícios de capítulos anteriores, já utilizamos
funções, mesmo sem saber que estávamos fazendo isso. Por
exemplo, limpatela() é um procedimento que não necessita de
parâmetro (observe que entre os parênteses não tem nenhuma
informação). Veja outras funções existentes do VisuAlg, nas quais
podemos utilizar sem criar nada:
Funções numéricas, algébricas e trigonométricas
Abs(expressão) – Retorna o valor absoluto de uma
expressão do tipo inteiro ou real. Equivale a | expressão | na
álgebra.
ArcCos(expressão) – Retorna o ângulo (em radianos) cujo
cosseno é representado por expressão.
ArcSen(expressão) – Retorna o ângulo (em radianos) cujo
seno é representado por expressão.
ArcTan(expressão) – Retorna o ângulo (em radianos) cuja
tangente é representada por expressão.
Cos(expressão) – Retorna o cosseno do ângulo (em
radianos) representado por expressão.
CoTan(expressão) – Retorna a cotangente do ângulo (em
radianos) representado por expressão.
Exp(base, expoente) – Retorna o valor de base elevado a
expoente, sendo ambos expressões do tipo real.
GraupRad(expressão) – Retorna o valor em radianos
correspondente ao valor em graus representado por
expressão.
Int(expressão) – Retorna a parte inteira do valor
representado por expressão.
Log(expressão) – Retorna o logaritmo na base 10 do valor
representado por expressão.
LogN(expressão) – Retorna o logaritmo neperiano (base e)
do valor representado por expressão.
Pi - Retorna o valor 3.141592.
Quad(expressão) – Retorna quadrado do valor representado
por expressão.
RadpGrau(expressão) – Retorna o valor em graus
correspondente ao valor em radianos representado por
expressão.
RaizQ(expressão) – Retorna a raiz quadrada do valor
representado por expressão.
Rand – Retorna um número real gerado aleatoriamente,
maior ou igual a zero e menor que um.
RandI(limite) – Retorna um número inteiro gerado
aleatoriamente, maior ou igual a zero e menor que limite.
Sen(expressão) – Retorna o seno do ângulo (em radianos)
representado por expressão.
Tan(expressão) – Retorna a tangente do ângulo (em
radianos) representado por expressão.
Se quisermos, por exemplo, saber a raiz quadrada de um número
(num) digitado pelo usuário, devemos utilizar a função RaizQ(num).
Não se esqueça que essa função retorna um valor (o resultado da raiz
quadrada), portanto, devemos atribuí-la a outra variável ou imprimir
diretamente dentro do comando escreva().
Então, para demonstrar a aplicação de funções e procedimentos
no VisuAlg, vamos terminar o exercício anterior, da soma dos dois
números, utilizando passagem de parâmetro por referência:
Procedimento somaP (a,b: inteiro; var r: inteiro) Inicio r <- a +
b Fimprocedimento Funcao somaF (a,b: inteiro): inteiro Var
Res: inteiro Inicio Res <- a + b Retorne res Fimfuncao
algoritmo “soma”
var
X,Y, res: inteiro inicio X <- 10
Y <- 20
Escreval (“A soma utilizando FUNÇÃO é :”, somaF (X,Y))
somaP (X,Y,res) escreva (“A soma utilizando
PROCEDIMENTO é :”, res) fimalgoritmo
Note que a variável r, do procedimento somaP é var, ou seja, ela
está recebendo o endereço da memória da variável que for passada
para ela por referência (que no nosso caso é a variável res). Não foi
feita uma cópia dos seus valores. Podemos entender isso,
observando que não houve retorno da variável r para o módulo
principal e, mesmo assim, conseguimos imprimir o valor correto da
soma. Isso foi possível porque os dois módulos (principal e somaP)
têm a referência da variável res.
Considerações finais
Funções e procedimentos são muito utilizados na programação
de sistemas computacionais e são estruturas concebidas a partir da
programação estruturada. O conceito de modularização é muito
importante aqui, pois devemos dividir o objetivo principal em
subtarefas (sub-rotinas) independentes, formando, assim, as funções.
As funções trazem muitas vantagens aos desenvolvedores de
sistemas, como o reúso do código (vimos que existem várias funções
prontas no VisuAlg que foram desenvolvidas por outras pessoas e
que podemos usar livremente) e a manutenção do código (para
alterar uma função, devemos mexer somente nela e não em todo o
código, como na antiga programação linear).
Para funcionar, algumas funções exigem parâmetros, que são
valores necessários para que ela execute sua tarefa específica.
Existem dois tipos de passagem de parâmetro: 1. Por valor (na qual é
feita uma cópia do valor da variável); e 2. Por referência (na qual é
passado o endereço de memória da variável). Em ambos os tipos,
podemos ter retorno ou não. Porém, por definição, as funções sempre
retornam valores e os procedimentos, não.
Existem inúmeras aplicações para funções e procedimentos. O
que estamos fazendo, na verdade, é dividindo nosso algoritmo em
várias partes (módulos), com a finalidade de simplificar e otimizar a
execução do código, tornando cada módulo independente e singular
(específico).
Referências
PUGA, S.; RISSETTI, G. Lógica de programação e estruturas de
dados com aplicação em Java. 2. ed. São Paulo: Editora Pearson,
2009.
XAVIER, G. F. C. Lógica de programação. São Paulo: Editora Senac
São Paulo, 2014.
Capítulo 10
Programação: arquivo
Até agora, todas as informações armazenadas nas variáveis
comuns e nos arrays (vetores e matrizes) foram guardadas de
maneira temporária, ou seja, por serem voláteis, as variáveis e os
arrays não guardavam nossa informação de maneira permanente,
para uso futuro. Eram perdidas quando saíamos do algoritmo.
Porém, tem inúmeras situações em computação nas quais
queremos utilizar essas informações para manipulá-las, por exemplo,
efetuando operações como busca de um nome, alteração de
cadastro e exclusão de um dado qualquer.
Para isso, devemos utilizar uma estrutura diferente das
estudadas até agora. Apresentaremos, neste capítulo, o conceito de
arquivos e vamos entender como armazenar e manipular as
informações por meio de registros (um conjunto de registros forma
um arquivo).
1 Processo arquivado!
Você já deve ter ouvido falar em “arquivo”. Esse conceito não é
exclusivo da computação, e nasceu há muito tempo, quando surgiu a
necessidade de armazenar, de forma definitiva ou por longo período
de tempo, as informações. A célebre frase dos programas policiais do
cinema “processo arquivado!” é um clássico exemplo de
armazenamento de informações (nesse caso, informações de
processos policiais).
Existem inúmeras vantagens em se utilizar esse conceito em
computação. Até agora, estamosutilizando, para armazenar nossos
dados, variáveis e arrays (vetores e matrizes). Entretanto, essas
estruturas apresentam duas características comuns:
São voláteis: ou seja, todos os dados armazenados nas variáveis
e arrays são perdidos quando saímos do programa ou,
simplesmente, desligamos a máquina. Esse tipo de estrutura é
útil quando precisamos armazenar, temporariamente, as
informações para uso imediato.
Têm tamanhos predefinidos: ou seja, as variáveis e arrays têm
um tamanho de armazenamento já conhecido. Por exemplo, as
variáveis comuns armazenam apenas um dado por vez,
enquanto os arrays armazenam uma quantidade maior; porém,
predeterminada no momento de sua declaração (lembre-se dos
valores declarados dentro dos colchetes [1..10] – significa 10
posições no nosso arrays e, consequentemente, 10 posições
para serem armazenadas as informações).
Agora, imagine se precisarmos armazenar uma informação para
utilizarmos mais tarde, como o cadastro de um aluno, por exemplo.
Ou, ainda, se precisarmos cadastrar uma quantidade desconhecida
de alunos em uma faculdade, depois do vestibular, por exemplo.
Como faremos tudo isso?
Antigamente, antes dos computadores (e até hoje, em alguns
lugares ainda são utilizados), recorríamos aos arquivos de aço (figura
1) para encontrarmos uma “ficha” ou “registro” de uma pessoa, aluno
ou de um processo policial, por exemplo, separados em pastas. Cada
pasta continha dados de um determinado assunto, porém, todas elas
estavam armazenadas no mesmo arquivo, que era nomeado com o
assunto mais abrangente comum a todas as pastas. Por exemplo, se
tivermos os cadastros de todos os alunos de uma faculdade, cada
pasta poderia ser o nome dos alunos (identificados em ordem
alfabética) e nosso arquivo poderia se chamar “cadastro de alunos”
ou ainda “alunos regulares”, ou seja, aqueles alunos que estão
matriculados na Instituição de Ensino.
Com os dados armazenados em arquivos, podemos realizar
algumas operações de manipulação de dados básicas (XAVIER,
2014):
Figura 1 – Armazenamento: operações de manipulação de dados
básicas
Fonte: adaptado de Xavier (2014).
Essas quatro operações básicas de manipulação de dados são
de extrema importância para podermos utilizar as informações
(guardar, acessar, modificar) em estruturas como arquivos ou banco
de dados. Falaremos de banco de dados em um capítulo mais
adiante. Por enquanto, é importante saber que uma diferença entre
arquivo e banco de dados, segundo Puga e Rissetti (2009), é que os
arquivos podem ser facilmente criados, utilizando-se os recursos
disponíveis no sistema operacional do computador, ao passo que,
para a criação de um banco de dados, é necessário um software
específico.
 IMPORTANTE
Sistema operacional: software que é responsável pelo
gerenciamento do hardware e do software da máquina, além de
realizar a interface entre usuário e o hardware.
Por hora, o que é importante saber é que armazenaremos dados
do cadastro de aluno em nosso arquivo, e cada aluno cadastrado será
um registro, bem como, cada dado armazenado será um campo.
Vamos entender mais sobre a estrutura de arquivo.
2 Conceitos de arquivo
Segundo Puga e Rissetti (2009), um arquivo é um local reservado
para guardar informações escritas para uso futuro. O arquivo de
computador é uma maneira de armazenar informações em meios
físicos, magnéticos ou ópticos, como, por exemplo, discos rígidos,
discos flexíveis, pen drives, CDs e outros.
Já a definição de Forbellone e Eberspacher (2005) diz que um
arquivo é um conjunto de registros (ou seja, é uma estrutura de
dados), no qual cada registro não ocupa uma posição fixa dentro da
estrutura, não possuindo, portanto, tamanho preestabelecido. Essa
informação, além de importante, é evolucionária para nós: não temos
tamanho fixo, podemos armazenar quantos dados forem necessários
no nosso sistema.
Então, voltemos ao nosso exercício: queremos cadastrar alunos
após o vestibular de uma faculdade, ou seja, vamos fazer a matrícula
desse aluno aprovado no vestibular. Não sabemos a quantidade de
alunos que teremos aprovados. Só o que sabemos são os dados
importantes para efetuar sua matrícula. Vejamos, então, como seria
uma ficha de matrícula desses alunos, na figura 2:
Figura 2 – Ficha de matrícula de aluno
Essa ficha, quando devidamente preenchida, conterá
informações (RA – registro acadêmico, nome, endereço completo,
telefone e e-mail) sobre um único aluno. Podemos representar esse
conjunto de informações por meio da estrutura de dados registrados
e, quando reunirmos várias fichas, estaremos compondo o arquivo
utilizado pela faculdade.
Para representarmos essa estrutura em código (VisuAlg),
precisamos declarar nosso arquivo com todos os campos nos quais
queremos guardar. O VisuAlg, que trabalha com pseudocódigo ou
portugol, nos ajudou bastante até agora. Entretanto, ele não dá um
bom suporte para arquivos. Portanto, vamos declarar e criar um
arquivo, entender seu funcionamento e, logo em seguida, vamos
verificar como se manipula os dados utilizando a estrutura arquivo,
mas não vamos testá-los no VisuAlg. Está quase na hora de
começarmos a ter acesso a uma linguagem comercial, ou seja, uma
linguagem de programação utilizada no mercado de trabalho e que
nos dê suporte a todas as estruturas necessárias para construirmos
nosso sistema.
No [capítulo 13], apresentaremos a linguagem de programação
comercial Python – linguagem orientada a objetos e que está sendo
muito utilizada nas empresas de construção de software, por ser de
fácil entendimento e desenvolvimento.
No VisuAlg, o que podemos fazer, por enquanto, é criar um
arquivo, cadastrando alguns dados com o comando leia() e imprimir
na tela esses dados com o comando escreva(). Porém, segundo o
manual do VisuAlg, existem algumas regras que devem ser seguidas:
1. Se não existir o arquivo com nome especificado, o VisuAlg fará
uma leitura de dados através da digitação, armazenando os
dados lidos neste arquivo, na ordem em que forem fornecidos (o
VisuAlg trabalha da forma sequencial com a estrutura arquivo).
2. Se o arquivo existir, o VisuAlg obterá os dados desse arquivo até
chegar ao seu fim. Daí em diante, fará as leituras de dados
através da digitação.
3. Somente um comando arquivo pode ser empregado em cada
pseudocódigo, e ele deverá estar na seção de declarações (ou
seja, depois de algoritmo e antes de var).
4. Caso não seja fornecido um caminho, o VisuAlg vai procurar
esse arquivo na pasta de trabalho corrente (geralmente, é a pasta
onde o programa VISUALG.EXE está). Esse comando não prevê
uma extensão-padrão; portanto, a especificação do nome do
arquivo deve ser completa, inclusive com sua extensão (por
exemplo, .txt, .dat, etc.).
Ainda, segundo o manual do VisuAlg, a sintaxe do comando é:
Arquivo <nome_do_arquivo>
onde: nome_do_arquivo é uma constante caractere (entre aspas
duplas).
Veja como ficará o código da nossa ficha de matrícula do aluno:
algoritmo “criando arquivo”
arquivo “C:\Users\Mestre
Allen\Documents\SENAC_MATERIAL\matricula.txt”
var RA, nome, rua, num, cidade, bairro, telefone, email:
caracter inicio escreva (“RA: “) leia (RA) escreva (“Nome: “)
leia (nome) escreva (“Rua: “) leia (rua) escreva (“Número :”)
leia (num) escreva (“Bairro: “) leia (bairro) escreva (“Cidade: “)
leia (cidade) escreva (“Telefone: “) leia (telefone) escreva
(“Email: “) leia (email) limpatela() escreval (“O RA desse aluno
é “, RA) escreval (“O nome do aluno é “,nome) escreval (“Seu
endereço é rua “, rua, “, “,num) escreval (“Bairro: “, bairro, “ -
Cidade: “, cidade) escreval (“Seu telefone é “,telefone)
escreval (“E seu email é “,email) fimalgoritmo
Note que declaramos o arquivo com o endereço onde queríamos
que ele fosse criado: ‣ arquivo “C:\Users\Mestre
Allen\Documents\SENAC_MATERIAL\matricula.txt”
Colocamos a palavra-chave arquivo e todo o restante entre aspas
(pois é texto).
Inserimos todos os valores com o método leia() e depois
imprimimos na tela o resultado desse arquivo. Poderíamos ter
utilizado função e procedimento para inserir e imprimiros valores e
chamá-las quantas vezes fossem necessárias.
Observe que, mesmo se você fechar a janela de exibição do
resultado da execução do algoritmo, os dados permanecem gravados
(figura 3).
Figura 3 – Resultado da execução do algoritmo na tela do VisuAlg
Caso você queira entender o conceito de arquivo aplicado nesse
exercício de outra maneira, abra a pasta na qual você criou o arquivo
(aquele endereço que colocamos na segunda linha do algoritmo).
Note que o arquivo do tipo texto foi criado lá, segundo figura 4.
Figura 4 – Criação do arquivo matrícula
E se você abrir esse arquivo, conseguirá identificar todos os
dados inseridos pelo usuário por meio do comando leia() no Visualg,
conforme figura 5. Com o conceito de arquivo, as informações desse
aluno ficarão armazenadas de uma forma definitiva (ou seja, não
volátil) e estarão disponíveis para manipulação (alteração, exclusão
ou, simplesmente, uma consulta futura).
Figura 5 – Arquivo matrícula preenchido
Note duas coisas aqui:
1. Foi criado um arquivo no bloco de notas. Isso porque, como
dissemos antes, a estrutura arquivo utiliza recursos do sistema
operacional.
2. Todos os dados foram inseridos sequencialmente. Caso
digitássemos os dados de outro aluno, o arquivo continuaria do
ponto indicado pela seta.
Entretanto, só fizemos uma das quatro operações básicas de
manipulação de dados na estrutura arquivo, que foi a inserção (ou
criação). Ainda falta apresentar a exclusão, a consulta e a atualização
de dados.
3 Manipulando arquivo
Como a IDE do VisuAlg não nos dá um suporte adequado para
manipular arquivo, vamos começar a preparar nosso código para ser
escrito em uma linguagem comercial. Portanto, apresentaremos as
operações de manipulação de dados da maneira como faremos
nessa linguagem.
Primeiramente, precisamos declarar a estrutura de arquivo
representando a nossa ficha de matrícula do aluno. Como já
definimos, cada aluno será um registro e cada dado contido nesse
registro será um campo. Então, vamos representar a estrutura
registro (ainda em portugol):
Tipo matricula = registro RA, Nome, rua,
num, cidade, bairro, telefone, email:
caracter Fim_registro Tipo arq_mat =
arquivo composto de matricula
Criamos uma “ficha de cadastro” chamada matricula, que é
composta pelos campos RA, Nome, rua, num, cidade, bairro, telefone,
email, todos do tipo de caracter (os campos são formados por
variáveis comuns). Logo em seguida, criamos o “arq_mat” (que é o
arquivo de matrícula), uma vez que sabemos que o conjunto dessas
matrículas formam nosso arquivo.
Pronto. Agora temos duas estruturas para podermos manipular: 
1. Matricula (que é a ficha de inscrição); e 2. Arq_mat (que é o arquivo
que contém todas as matrículas.
Para abrir um arquivo já existente, basta utilizarmos um
comando (função) de abertura de arquivo:
Abrir (nome_do_arquivo)
No nosso exemplo ficará: abrir (arq_mat) Caso queiramos varrer
nosso arquivo em busca de uma informação específica, devemos
abrir o arquivo, avançar os campos e comparar se já achamos a
informação que queremos. Aqui teremos duas situações:
1. Se acharmos a informação que queremos, retornamos o registro.
2. Se não encontrarmos a informação, temos de saber quando o
arquivo terminou. E para essa situação, vamos utilizar a sigla
EOF (end of file) ou, em português, FDA (fim do arquivo).
Portanto, para uma busca de dados no nosso arquivo,
deveremos utilizar os seguintes comandos:
Abrir (arq_mat) Enquanto (arq_mat <> EOF)
faca Se (arq_mat.nome = nome_procurado)
então Retorna matricula Senão
Avança (arq_mat) Fimse
Fimenquanto
Abrimos o arquivo, comparamos se ele já está no fim (EOF) e
depois comparamos se achamos o nome que estamos procurando.
Se encontramos, retorna todo o registro desse aluno, caso contrário,
avançamos no arquivo.
Para efetuar uma alteração de dados, vamos proceder da
mesma forma, porém, ao invés de retornar o registro do aluno (isso
fazemos na busca ou consulta), vamos substituir o dado encontrado
pelo novo dado (efetuando, assim, uma atualização do cadastro ou
edição):
Abrir (arq_mat) Enquanto (arq_mat <> EOF)
faca Se (arq_mat.nome = nome_procurado)
então Arq_mat.rua = novo_endereco Senão
Avança (arq_mat) Fimse
Fimenquanto
Note que fizemos uma busca pelo nome do aluno e, quando o
encontrarmos, alteramos o nome da sua rua.
Falta apenas a operação de exclusão. Para excluir um dado ou
um registro, vamos fazer a busca pela informação e utilizar um
comando de excluir(), passando como parâmetro o dado a ser
excluído ou o registro:
Abrir (arq_mat) Enquanto (arq_mat <> EOF)
faca Se (arq_mat.nome = nome_procurado)
então Excluir (Arq_mat.dado) // exclui o
dado específico Excluir (matricula) //
exclui todo o registro encontrado Senão
Avança (arq_mat) Fimse
Observe que, quando encontramos o nome procurado, temos
duas opções:
1. Excluir o dado específico (um dos campos da ficha de inscrição,
por exemplo);
2. Excluir todo o registro do aluno (nesse caso, todos os campos da
ficha desse aluno serão apagados e o aluno não existirá mais em
nosso arquivo).
 IMPORTANTE
A manipulação de dados em arquivos deve acontecer de acordo
com a necessidade do sistema; e somente pessoas autorizadas
podem efetuar essas operações, senão, poderemos ter arquivos
apagados para encobrir as evidências de crime, por exemplo.
Para fixarmos todos esses conceitos e comandos, é importante
treinar. Portanto, para verificar se seu entendimento nesse capítulo foi
satisfatório, refaça a operação de inserção de dados, utilizando a
estrutura de registro. Logo após, monte um programa no qual o
usuário deva escolher uma das quatro opções de manipulação de
dados e execute a operação com o uso de funções e procedimentos.
 PARA PENSAR
Para maior compreensão, leia o capítulo 9 (p. 157 até 162) do livro
Lógica de programação e estrutura de dados com aplicações em
Java, dos autores Sandra Puga e Gerson Rissetti, Editora Pearson,
2009.
Não se esqueça de fazer tudo em portugol (português
estruturado) e não precisa se preocupar com a estrutura do VisuAlg –
utilize puramente sua lógica, associada aos comandos e às
estruturas da linguagem estruturada.
Considerações finais
Os arquivos são estruturas de dados muito utilizadas em
computação, por permitir que trabalhemos com tamanhos
indefinidos de armazenamento e não serem voláteis, ou seja,
podemos utilizar as informações guardadas para manipulação futura.
As manipulações intrínsecas do arquivo são inserção (inserir um
novo cadastro), exclusão (excluir um dado específico ou um registro
inteiro), atualização (editar ou atualizar o dado de um registro
existente) e busca (procurar as informações de um registro localizado
pelo nome ou um identificador, por exemplo).
A utilização de arquivos é relativamente simples. Não podemos
nos esquecer que existe uma sequência lógica e algumas regras a
serem seguidas, como, por exemplo: não se deve abrir um arquivo
que não existe; não se deve excluir ou alterar um dado que não existe;
em todas as buscar, devemos verificar a possibilidade de não
encontrarmos o que queremos e que o arquivo já chegou ao fim
(EOF) e, o mais importante, nunca podemos deixar uma pessoa não
autorizada manipular um arquivo. Confiabilidade é essencial. Mas
esse assunto será abordado em banco de dados, fique tranquilo.
Referências
FORBELLONE, A. L. V.; EBERSPACHER, H. F. Lógica de programação:
a construção de algoritmos e estrutura de dados. 3. ed. São Paulo:
Editora Pearson Prentice Hall, 2005.
PUGA, S.; RISSETTI, G. Lógica de programação e estruturas de
dados com aplicação em Java. 2. ed. São Paulo: Editora Pearson,
2009.
RODRIGUES, A. Manual do VisuAlg. Curso de Formação profissional
em 
técnico em informática. Instituto Federal de Educação, Ciência e
Tecnologia, [s. d.]. Disponível em:
<http://www.inf.ufsc.br/~bosco.sobral/ensino/ine5201/Visualg2_man
ual.pdf>. Acesso em: 24 fev. 2019.
XAVIER, G. F. C. Lógica de programação. São Paulo: Editora Senac
São Paulo, 2014.
http://www.inf.ufsc.br/~bosco.sobral/ensino/ine5201/Visualg2_manual.pdfCapítulo 11
Programação orientada a objetos
Orientação a objetos é um paradigma muito utilizado hoje em dia
na construção de sistemas computacionais. Existem algumas razões
para usarmos linguagens orientada a objetos como reúso de código,
alta produtividade e facilidade de manutenção.
Neste capítulo, vamos trabalhar com os conceitos básicos
relacionados a este paradigma de programação, compreendendo
seus principais elementos: classes e objetos. Como o próprio nome
sugere, a Programação Orientada a Objetos (POO) está toda baseada
em objetos que são representações virtuais dos objetos que
encontramos no nosso mundo real, como uma cadeira, um
computador, um carro e até uma pessoa e um animal.
Apresentaremos, também, os conceitos de instância (que é a
geração de um objeto a partir de uma classe) e do método construtor
(importante para entender como atribuir valores aos atributos dos
objetos).
Por fim, veremos a aplicação e criação de uma classe, do
método construtor e da instância de um objeto com a utilização da
linguagem de programação orientada a objetos Python.
1 Conceito de POO
Já sabemos que existem vários tipos de linguagens de
programação e vários paradigmas (estudamos dois deles:
programação linear e programação estruturada). Em particular, a
programação estruturada foi uma enorme evolução na forma de se
programar e representar, em código, sistemas mais complexos com
os conceitos de função e modularização. Esses módulos executam
tarefas determinadas, interagindo com outros módulos ou com o
programa principal, retornando valores ou não, dependendo do que
deve ser realizado.
A Programação Orientada a Objetos (POO) representa uma
mudança no enfoque da programação, na forma como os sistemas
eram vistos até então. Representa uma quebra de paradigma,
evolucionando todos os conceitos de projeto e desenvolvimento de
sistemas existentes anteriormente (PUGA; RISSETTI, 2009).
Relembrando o conceito de paradigma, segundo Morris e
Brandon (1994), é um conjunto de regras que estabelecem fronteiras
e descrevem como resolver os problemas dentro dessas fronteiras.
Os paradigmas influenciam nossa percepção, ajudando-nos a
organizar e a coordenar a maneira como olhamos para o mundo.
Portanto, o paradigma de programação orientada a objetos trata
de uma forma diferente o enfoque até o momento trabalhado na
maioria das linguagens de programação, que se sustentavam no
paradigma de programação estruturada (figura 1). A ideia por trás do
paradigma da programação orientada a objetos baseia-se em uma
contextualização mais humana e próxima da realidade, isso
considerando que quase tudo o que temos e lidamos em nosso dia a
dia são objetos. Por exemplo, o carro que você dirige, a casa que você
mora.
Figura 1 – Enfoque tradicional x enfoque
orientado a objetos
Fonte: Adaptado de Puga e Risset (2009, p. 26).
O enfoque da modelagem de sistemas por objetos procura
enxergar o mundo como um conjunto de objetos que interagem entre
si e apresentam características e comportamento próprios
representados por seus atributos e suas operações. Os atributos
estão relacionados aos dados (ou características) e as operações,
aos procedimentos (ou métodos) que um objeto executa.
Portanto, poderíamos pensar que até as pessoas, os animais, ou
qualquer outro tipo de entidade podem ser vistos como objetos.
Devemos, apenas, ter o cuidado de compreender que esses objetos
nem sempre são palpáveis, como um animal, por exemplo. Mas, no
caso abstrato, como um sistema (ou software) podemos imaginar
que eles existem e possuem elementos que os diferenciam (atitudes,
funções e características).
Assim, supondo que desejamos desenvolver um sistema de
controle de estoque para uma empresa, procuramos identificar os
objetos relacionados a esse sistema, como os produtos, os pedidos
de compra, os recibos, as pessoas, etc. Portanto, podemos dizer que
é possível modelar, por meio de orientação a objetos, um setor, um
departamento e até uma empresa inteira.
Com isso, podemos afirmar que o objetivo principal da
orientação a objetos na construção de sistemas computacionais é
permitir que os programas possam ser desenvolvidos de maneira a
espelhar o modo como os objetos são organizados no mundo real,
criando a figura de modelos que podem ser reutilizados quantas
vezes forem necessárias, bem como criar uma estrutura modular, na
qual os problemas possam ser resolvidos sem que o todo seja
afetado.
Segundo Puga e Risset (2009) o uso adequado de recursos de
uma linguagem orientada a objetos tem como objetivo aproveitar
seus benefícios, como reutilização de códigos e aumento da
produtividade, segurança por meio do encapsulamento de dados e
operações, robustez dos programas, aplicações e facilidade de
desenvolvimento, alteração e manutenção dos programas e
aplicações.
Diante disso, é importante saber que a programação orientada a
objetos, segundo Coelho (2012) baseia-se nos seguintes conceitos:
Classes
Atributos
Métodos
Objetos
Encapsulamento
Herança
Existem outros conceitos envolvidos no paradigma da
programação orientada a objetos, como métodos construtores,
polimorfismo e interface, porém vamos nos concentrar nos
destacados acima, pois são os mais importantes na compreensão da
POO.
2 Classes e objetos
Como o próprio nome diz, o paradigma da orientação a objetos
está toda baseada (ou orientada) aos objetos. Portanto, eles são os
elementos principais e que devemos entender de uma forma
concreta. Segundo Xavier (2014) um objeto é uma extensão do
conceito de objeto do mundo real, em que se podem ter coisas
tangíveis, um incidente (evento ou ocorrência) ou uma interação
(transação ou contrato).
Por exemplo, em um sistema acadêmico em que João é um
aluno (objeto) e Carlos é um professor (objeto) que ministra aulas
(objeto) da disciplina (objeto) algoritmos, para poder assistir às aulas
da disciplina do professor Carlos, João precisa fazer uma matrícula
(objeto) no curso (objeto) de computação.
Com base no exemplo anterior, temos as seguintes ocorrências
de objetos:
Tangíveis: aluno e professor
Incidente: curso, disciplina e aula
Interação: matrícula
A identificação dos objetos em um sistema depende do nível de
abstração de quem faz a modelagem (engenharia de software
utilizando diagramas, por exemplo). Não existe um modelo correto.
Isso dependerá de quem faz a modelagem e de processos
sucessivos de refinamento, até que se possa encontrar um modelo
adequado a cada aplicação.
 PARA SABER MAIS
Abstração consiste em concentrar-se nos aspectos essenciais,
próprios, de uma entidade e em ignorar suas propriedades
acidentais. Isso significa concentrar-se no que um objeto é e faz,
antes de decidir como ele deve ser implementado em uma
linguagem de programação.
Se ainda está complicado de entender o paradigma orientado a
objeto, pense da seguinte maneira: identifique os objetos como sendo
as entidades que desempenham alguma tarefa no seu sistema e que
tenha características que o diferencia de outros objetos do mesmo
tipo. Vamos voltar ao nosso exemplo acadêmico:
Por que professor é um objeto? Qual função ele desempenha em
nosso sistema? Qual característica o diferencia de outro
professor?
Vamos responder essas perguntas e, assim, teremos convicção
se professor realmente é um objeto em nosso sistema.
1. Professor desempenha função em nosso sistema? SIM,
professor leciona uma disciplina.
2. Professor possui alguma característica que o diferencia de outro
professor? SIM, professor tem nome. O professor Carlos é
diferente do professor Alfredo, por exemplo.
Com as duas questões respondidas positivamente, temos a
certeza de que professor é um objeto em nosso sistema. Façamos
com aluno também:
1. Aluno desempenha alguma função em nosso sistema? SIM,
aluno assiste as aulas.
2. Aluno possui alguma característica que o diferencia de outro
aluno? SIM, aluno também possui nome. O aluno João não é o
mesmo que o aluno Maria.
Mas, você pode se perguntar: e se os nomes forem iguais? Serão
o mesmo objeto? A resposta é NÃO. Mesmo tendo algumascaracterísticas iguais, como o nome, por exemplo, ainda serão
objetos diferentes e algum atributo os diferenciarão, como endereço,
telefone, e-mail ou mesmo um ID (identificador) único e pessoal,
como o CPF, por exemplo. A figura 2 mostra dois objetos alunos do
nosso sistema.
Figura 2 – Objetos aluno do sistema acadêmico
Faça as mesmas perguntas para os outros objetos e tente com‐ 
preender porque realmente são objetos em nosso sistema
acadêmico.
 IMPORTANTE
Os IDs (identificadores e chaves únicas) são uma identificação de
cada objeto e será muito importante para a compreensão de banco
de dados, que será estudado nos últimos capítulos dessa obra.
Uma vez identificados os objetos, precisamos entender como
esses objetos são utilizados no sistema. TODOS os objetos que
existem em um sistema computacional são criados a partir de uma
CLASSE. Segundo Coelho (2012), uma classe é um modelo formado
por propriedades ou características (que são os atributos) e
funcionalidades (que são os métodos) e definem o comportamento
básico dos objetos oriundos de uma classe.
Em vários livros e conteúdos da Internet, você vai encontrar
definições como a de Puga e Risset (2009) onde diz que classe é uma
coleção de objetos que podem ser descritos por um conjunto básico
de atributos e possuem operações semelhantes. Entretanto, não
gosto de “conjunto de objetos” e vou explicar o motivo.
Classe é como um molde que irá gerar os objetos. Imagine que
você queira fazer ovos de páscoa na sua casa. A primeira coisa que
terá de fazer é comprar uma fôrma para poder construir seus ovos. E,
claro, deverá, também, comprar chocolate (vários tipos, amargo,
branco, preto) e os acompanhamentos (avelã, nozes, granulado).
Então, com tudo em mãos, agora é a hora de fabricar os ovos.
Nesse momento, te farei uma pergunta: quantos ovos você é
capaz de produzir com a fôrma (molde) que comprou? Vários!
Quantos seus ingredientes permitirem, certo? Portanto, sua fôrma
conterá informações que os ovos terão, como tamanho, forma, peso,
tipo de chocolate, recheio, etc. Sua fôrma se comporta como uma
classe e os ovos que estão sendo gerados são os objetos oriundo
dela. Aliás, a criação dos objetos a partir de uma classe demos o
nome de instância. Então, voltando ao conceito de classes, é um
molde que guarda as características (atributos) e comportamento
(métodos) dos objetos que serão instanciados dela.
 IMPORTANTE
Não são as classes que guardam os objetos, eles são instanciados
a partir das classes e podem utilizar todos os atributos e métodos
que a classe disponibiliza.
A figura 3 mostra a classe ALUNO gerando dois objetos do tipo
“aluno”. Note, que, cada aluno possui valores para os atributos que a
classe disponibiliza. A classe não atribui valor a um atributo, mas o
objeto sim. Por exemplo, temos os atributos Nome, RG e RM (registro
de matrícula) porém, somente os alunos, instanciados (ou seja, os
objetos) é que tem valor atribuído ao nome, número do RG e o
número da matrícula identificando, assim, cada objeto como sendo
único.
Figura 3 – Instância de objetos do tipo “Aluno”
Observe, também, que os atributos têm tipo, pois na verdade são
variáveis (podem ser variáveis comuns ou arrays) e os métodos são
acompanhados de “parênteses” no final, pois são funções (podendo,
inclusive, receber parâmetro e retornar valor). Vamos ver como criar
uma classe e instanciar um objeto?
3 Aplicação de POO
Para aplicarmos os conceitos de classes e objetos precisaremos
de uma linguagem de alto nível que suporte o paradigma de
orientação a objetos. Nós utilizaremos, nessa obra, a linguagem
Python que será estudada e explicada no [capítulo 13]. O que
precisamos saber, por enquanto é que com essa linguagem podemos
criar as classes e instanciar os objetos. Não vamos criar, nesse
capítulo, nenhum programa funcional. Vamos apenas demonstrar a
aplicação de POO na criação dos dois principais conceitos desse
paradigma.
 PARA SABER MAIS
Python é uma linguagem de programação de alto nível, interpretada,
de script, imperativa, orientada a objetos, funcional, de tipagem
dinâmica e forte. Foi lançada por Guido van Rossum em 1991.
Como acabamos de dizer, os atributos da classe são variáveis e
os métodos são funções. No nosso exemplo da classe ALUNO iremos
criar funções (métodos) que efetuem todas as tarefas na qual
precisamos. Uma informação importante que devemos saber, antes
de começar, é que não vamos trabalhar na IDE do VisuAlg. O Python
possui IDE diferente, mas falaremos disso mais adiante, não se
preocupe. O importante agora é entender o conceito e saber aplicar e
criar nossas classes.
Criar uma classe em Python é muito simples. Basta utilizar a
palavra reservada da linguagem class seguido do nome da classe e
dois pontos ao final “:”. Portanto, a primeira linha de nossa classe
“Aluno” ficaria assim:
Class Aluno:
pass
A palavra pass significa que a classe está vazia, não temos
nenhum conteúdo nela ainda. Logo em seguida, podemos criar um
método para receber todos os atributos iniciais para a criação dos
objetos.
Esse método é único e possui um nome específico: método
construtor. Na verdade, esse método recebe, por parâmetro, os
valores das variáveis na qual o objeto deve iniciar e atribui seus
valores quando a instância é feita.
É como se, no momento em que o aluno for criado, eu informar,
para o método construtor (que o constrói) qual o seu nome, qual seu
RG e qual seu RM. Esse método pega essas informações e armazena
dentro das variáveis desse objeto.
Vamos ver como ficaria nosso método construtor. A sintaxe para
a criação desse método é a seguinte: palavra reservada def <espaço>
dois underlines palavra reservada init seguido de dois underlines (self,
variável1, variável2...): Parece complicado, mas não é. Vamos traduzir
para código tudo o que dissemos:
Def __init__ (self, nome, RG, RM):
pass
Dentro desse método vamos atribuir os parâmetros passados
para as variáveis da classe. Isso significa que, sempre que criarmos
um objeto, devemos passar esses valores e esse método atribui às
variáveis da classe, instanciando um objeto com alguns valores
iniciais. A palavra reservada self significa que iremos utilizar variáveis
locais e é obrigatório dentro de cada método:
Def __init__ (self, nome, RG, RM):
Self.nome = nome Self.rg = RG
Self.rm = RM
Pronto! Nosso método construtor está terminado. Basta colocar
o método dentro da classe Aluno. Observe que as três variáveis que
estão juntas das palavras self são da própria classe e as três variáveis
passadas por parâmetros vieram de fora da classe, que quem a
chamou (como vimos no capítulo sobre Funções e Procedimentos).
Vamos verificar nossa classe:
Class Aluno:
Def __init__ (self, nome,
RG, RM): Self.nome =
nome Self.rg = RG
Self.rm = RM
Simples não é mesmo? E para instanciarmos um objeto “aluno”
basta, dentro da classe principal, por exemplo, declararmos o nome
do objeto e dizer que ele é do tipo da classe (nome da classe) e
passar os valores exigidos pelo método construtor.
Obj_aluno = Aluno (‘João’,
’22.222.222-Y’, ‘13579’)
Note que, o nome do objeto é “obj_aluno” (poderia ser qualquer
nome) e dissemos que ele é do tipo Aluno (o sinal de = faz essa
atribuição) e passamos, por parâmetros, o nome, o número do RG e o
número do RM (tudo entre aspas simples, pois é tudo texto).
E se quisermos trocar o nome ou o número do RM desse aluno,
seguindo os preceitos das operações básicas de manipulação de
dados visto no capítulo de arquivo? Para fazer isso precisaremos criar
métodos que façam essa manipulação. Mas isso é assunto para
nosso próximo capítulo.
Considerações finais
A Programação Orientada a Objetos (POO) trouxe um novo
enfoque no mundo da programação: o paradigma orientado a objetos
e rompe com a tradicional forma de se desenvolver sistemas que
tínhamos até então.
O reúso de código, a alta produtividade e a facilidade em se
programar (por ser uma linguagem de alto nível) são algumas das
vantagens em se utilizar esse tipo de paradigma. A identificação de
objetos do mundo reale sua forma de se comunicarem, assim como
seu comportamento (método) e suas características (atributos)
foram introduzidos em uma única estrutura chamada classe.
A classe é o molde para a criação (ou instanciação) de objetos
que possuem as mesmas características e comportamento.
Podemos efetuar quantas instâncias quisermos a partir de uma única
classe, desde que respeitemos os parâmetros exigidos no método
construtor dessa classe.
Podemos, dessa maneira, representar praticamente qualquer
coisa (empresa, departamentos, sistemas acadêmicos, bibliotecas e
até um zoológico) com o uso da orientação a objetos e uma
linguagem que suporte esse paradigma, como o Python, por exemplo.
Referências
COELHO, Alex. JAVA com Orientação a Objetos. Rio de Janeiro:
Editora Ciência Moderna Ltda., 2012.
MORRIS, Daniel C.; BRANDON, Joel S. Reengenharia: reestruturando
sua empresa. São Paulo: Makron Books, 1994.
PUGA, Sandra; RISSET, Gerson . Lógica de programação e estruturas
de dados com aplicação em Java; 2ª edição, São Paulo: Editora
Pearson, 2009.
XAVIER, Gley F. C. Lógica de Programação. São Paulo: Ed. SENAC,
2014.
Capítulo 12
Programação orientada a objetos:
classes
A classe é um dos conceitos mais importantes no paradigma de
orientação a objetos e seu entendimento é primordial para
desenvolvedores, analistas de sistemas, arquitetos de softwares,
testes, etc.
A composição da classe com os atributos e os métodos começa
na modelagem por meio de diagramas, como o diagrama de classes,
por exemplo, e culmina na sua construção, por meio de uma
linguagem de programação que suporte o paradigma.
Neste capítulo, apresentaremos como identificamos as classes
em um sistema, como determinamos os atributos e os métodos de
cada uma delas e como modelamos, utilizando uma ferramenta case
sob os padrões da UML.
Conceitos como herança e encapsulamento serão abordados e
codificados com a ajuda da linguagem de programação orientada a
objetos Python.
1 Composição da classe
Como foi dito no capítulo anterior, uma classe é o molde para a
criação de um objeto no paradigma orientado a objetos. Essa classe
é composta de atributos e métodos e existem alguns conceitos, os
quais podemos aplicar sobre as classes, como herança e
encapsulamento. Daqui a pouco, apresentaremos esses conceitos;
por enquanto, vamos estudar um case:
 PARA SABER MAIS
Na tradução, case significa “caso” – é a história de um
acontecimento empresarial: pode ser a criação de uma empresa,
um produto ou serviço ou outros acontecimentos relacionados ao
ambiente corporativo, que podem servir como aprendizagem para
outros profissionais. Os cases são frequentemente utilizados em
escolas de negócios.
Imaginem que precisamos modelar, em nosso sistema, um
objeto veículo para aluguel. Porém, essa loja aluga tanto veículos
terrestres (carros, ônibus e caminhões) quanto veículos aéreos
(aviões e helicópteros) e veículos aquáticos (barcos e jet ski). Além
disso, precisaremos modelar, também, o cliente (quem vai alugar os
veículos) e as lojas (serão várias lojas espalhadas por todas as
regiões do Brasil). A loja só aluga os veículos para pessoas físicas e
precisa dos dados: nome, endereço, telefone, e-mail e cartão de
crédito. No momento da locação, a loja precisa saber a data de
retirada, a data de entrega, o tipo de veículo e o número da habilitação
do condutor. A loja também pode cobrar taxas sobre cada veículo no
ato da locação. Além de alugar, o cliente também pode renovar o
aluguel e antecipar a devolução. E a loja, no momento da entrega,
pode cobrar por alguma avaria no veículo.
Temos um case relativamente grande para solucionarmos. O
primeiro passo é identificar os objetos (lembre-se que um objeto
realiza alguma função no nosso sistema e possui alguma
característica que o diferencia de outros objetos do mesmo tipo).
Conforme destacamos, veículo é um objeto, pois pode ser locado
e cadastrado, por exemplo, e possui atributos como marca, modelo,
ano, placa, opcionais, etc. Agora, e aqueles vários tipos de veículos
que mencionamos? Carros, aviões, barcos, jet sky, helicóptero,
caminhão e ônibus? O que são?
São objetos também, certo? Sim, são objetos. Porém, podemos
agrupá-los em tipos:
1. Terrestre: carro, ônibus e caminhão.
2. Aquático: barco e jet sky.
3. Aéreo: avião e helicóptero.
Cada um desses três tipos identificados (terrestre, aquático e
aéreo) serão nossos objetos. Os demais veículos (carro, ônibus,
barco, jet sky, avião, helicóptero e caminhão) serão modelos
específicos de cada tipo de veículo, entre os três destacados acima.
Note o que acabamos de fazer: um sistema hierárquico, onde
colocamos veículo como sendo o objeto mais geral – terrestre,
aquático e aéreo – sendo objetos específicos de veículo, e os demais
veículos, como tipos ainda mais específicos de seus respectivos
objetos (terrestre, aquático ou aéreo), como representado na figura 1.
Figura 1 – Hierarquia de tipos de veículos
Esse tipo de esquema nos ajuda a organizar a estrutura de
negócio do nosso sistema, ou seja, o entendimento das regras de
negócio fica mais claro quando as separamos por tipos e subtipos
(como no sistema de hierarquia utilizado).
Entretanto, segundo Puga e Rissetti (2009), um objeto só existe
quando há uma classe para o criar. Ou seja, só estamos falando de
objetos até agora (claro, são eles que executam tarefas em nosso
sistema), mas eles só existem se houver um molde para fabricá-los. E
esse molde é a classe.
Portanto, entendendo cada veículo e tipo de veículo como sendo
uma classe, temos uma hierarquia de classes. Esse é o conceito de
herança no paradigma orientado a objetos e, segundo Deitel e Deitel
(2005,
p. 301) é “uma forma de reutilização de software, na qual uma nova
classe é criada, absorvendo membros de uma classe existente e
aprimorada com capacidades novas ou modificadas”.
 PARA SABER MAIS
Com a herança, os programadores economizam tempo durante o
desenvolvimento de programa, reutilizando software de alta
qualidade testado e depurado. Isso também aumenta a
probabilidade de um sistema ser implementado efetivamente.
Deitel e Deitel (2005, p. 301), ao criar uma classe, em vez de
declarar atributos e métodos completamente novos, “podemos
designar que essa nova classe deverá herdar os atributos e métodos
de uma classe existente”, chamada de superclasse, e a nova classe,
subclasse – cada subclasse se torna a superclasse para futuras
subclasses.
Trocando em miúdos, a classe veículo é a superclasse e as
classes terrestre, aquática e aérea, são suas subclasses, ou seja, elas
herdam tudo o que a classe veículo possuir. Além disso, as classes
terrestre, aquática e aérea serão superclasses das subclasses carro,
ônibus, caminhão, barco, jet sky, avião e helicóptero. Desse modo,
todas essas classes herdam os atributos e métodos de suas
superclasses, em todos os níveis. Quanto mais descemos a camada
na hierarquia, mais específica vai ficando a classe.
Para entendermos exatamente o que está acontecendo, vamos
modelar nossas classes com os atributos e os métodos exigidos em
cada uma delas. Como a classe veículo é a mais geral (é a classe
genérica), deve conter atributos e métodos gerais, componentes de
todos os veículos. Por exemplo, modelo, marca, ano, cor, combustível
(atributos) e locomover-se, frear, virar, abastecer (métodos).
Já as classes terrestre, aquática e aérea devem conter
elementos específicos de cada uma. Como elas serão heranças de
classe veículo, não precisamos repetir os atributos e métodos –
vamos herdar da classe já existente. Portanto, terrestre poderia ter
eixos, número de rodas, placa (atributos) e estacionar, ajustar
retrovisores, acender pisca-alerta (métodos). Já a classe aquática
poderia ter casco, proa, popa (atributos) e flutuar, navegar (métodos).
Finalmente, a classe aérea pode ter hélice, calda, propulsor (atributos)
e voar, pousar, planar (métodos).
Observe que essas classes (terrestre, aquática e aérea), além de
executarem os métodos descritos anteriormente, também podem
executar os métodos da sua classe pai(veículo). Daqui a pouco, você
verá vários exemplos que facilitarão seu entendimento do conceito de
herança.
Para as demais classes, devemos nos questionar se realmente
serão classes ou apenas objetos instanciados das suas classes
genéricas. As perguntas são as mesmas que já estamos fazendo: 1.
Desempenha tarefa específica no sistema (deve ser diferente da
classe genérica) e possui atributo que o diferencia dos demais
(também deve ser diferente da classe genérica)? Se não houver nada
específico, não serão novas classes, apenas instâncias? Caso
contrário, devemos encontrar os atributos e métodos específicos de
cada classe.
Por exemplo, se colocarmos na classe carro o atributo
“habilitação”, podemos verificar que esse atributo também será
exigido em caminhão e em ônibus. Portanto, não é um atributo
específico da classe carro e sim da classe terrestre. Mas, se
quisermos identificar a “tara” do veículo, por exemplo, é uma
característica de caminhão, ou o número de passageiros em pé, é
característica de ônibus. Só podemos separar esses atributos e
métodos se realmente nosso sistema exigir (não se esqueça que as
regras de negócio são ditadas pelo cliente comprador do sistema; é
ele quem dirá se há a necessidade dessas informações no
programa). Mas, por questões apenas didáticas, vamos modelar
todas as classes, para entendermos como ficariam as heranças na
nossa hierarquia de classes (figura 2).
Figura 2 – Diagrama de classes de veículo sistema veículos
O modelo de diagrama de classes foi criado em uma ferramenta
case, seguindo padrões UML, e a seta utilizada para relacionar as
classes representa uma herança. Para entender o conceito da
herança no modelo de diagrama, devemos ler, na direção da seta, “é
um tipo de”. Por exemplo, terrestre “é um tipo de” veículo? Se a
resposta for SIM, a herança pode ser efetuada. Caso contrário, por
exemplo, se invertermos a seta: veículo “é um tipo de” terrestre?
Nesse caso, a resposta é NÃO, pois temos outros veículos não
terrestres (barco, por exemplo). Então, a herança não pode ser
efetuada.
 PARA SABER MAIS
Para saber mais sobre UML e ferramentas case, recomendamos a
leitura do livro UML 2: uma abordagem prática, do autor Gilleanes T.
A. Guedes.
Mas não terminamos ainda. Faltam as classes do cliente e da
loja.
Como a loja só aluga para pessoa física e sabemos que as lojas
que estão espalhadas pelo Brasil são pessoa jurídica, podemos
utilizar o conceito de herança aqui também. Pessoa Física e Pessoa
Jurídica podem ser subclasses da superclasse Pessoa. Basta, agora,
determinarmos os atributos e métodos de cada uma delas.
A classe Pessoa será composta pelos elementos mais genéricos,
como nome, endereço, telefone e email (atributos) e cadastrar
pessoa, editar pessoa e excluir pessoa (métodos). A classe Pessoa
Física pode conter o CPF e a classe Pessoa Jurídica pode ser
composta por CNPJ e Inscrição Estadual, por exemplo (figura 3).
Figura 3 – Diagrama de classes de Pessoa do
sistema veículos
Nesse momento, podemos fazer algumas perguntas:
E os atributos “data de retirada”, “data de devolução”, “tipo de
veículo”?
E os métodos “calcular taxa”, “calcular avaria”?
Onde seriam colocados esses elementos? Na verdade, nesse
momento, surge uma classe associativa chamada Locação, que é a
transação de negócio, ou seja, o ato de alugar um veículo. Ela é
associativa, porque “nasce” da associação entre a classe cliente e a
classe veículo. Portanto, vamos juntar as duas partes do diagrama de
classes que construímos até agora e inserir a classe Locação, com
seus atributos e métodos (figura 4).
Figura 4 – Diagrama de classes completo do sistema veículos
Após a identificação de todas as classes do sistema e a
modelagem por meio do diagrama de classes (com os atributos e
métodos), é hora de codificarmos as classes utilizando a linguagem
Python. Vamos desenvolver todas as classes e suas respectivas
heranças.
Class Veiculo:
Def __init__ (self, modelo, marca, cor, ano, combustivel):
Self.modelo = modelo Self.marca = marca Self.cor = cor
Self.ano = ano Self.comb = combustivel Class Terrestre
(Veiculo): Def __init__ (self, modelo, marca, cor, ano,
combustivel, eixo, num_roda, placa) Super().__init__ (modelo,
marca, cor, ano, combustivel) Self.eixo = eixo Self.roda =
num_roda Self.placa = placa Class Aquatico (Veiculo): Def
__init__ (self, modelo, marca, cor, ano, combustivel, casco,
proa, popa) Super().__init__ (modelo, marca, cor, ano,
combustivel) Self.casco = casco Self.proa = proa Self.popa =
popa Class Aereo (Veiculo): Def __inti__ (self, modelo, marca,
cor, ano, combustivel, helice, calda, propulsor)
Super().__init__ (modelo, marca, cor, ano, combustivel)
Self.helice = hélice Self.calda = calda Self.prop = propulsor
Class Carro (Terrestre): Def __init__ (self, num_porta, modelo,
marca, cor, ano, combustivel, eixo, num_roda, placa)
Super().__init__ (modelo, marca, cor, ano, combustivel)
Super().__init__ (eixo, num_roda, placa) Self.porta =
num_porta Class Onibus (Terrestre): Def __init__ (self,
num_pass_pe, modelo, marca, cor, ano, combustivel, eixo,
num_roda, placa) Super().__init__ (modelo, marca, cor, ano,
combustivel) Super().__init__ (eixo, num_roda, placa)
Self.pass_pe = num_pass_pe Class Caminhao (Terrestre):
Def __init__ (self, tara, modelo, marca, cor, ano, combustivel,
eixo, num_roda, placa) Super().__init__ (modelo, marca, cor,
ano, combustivel) Super().__init__ (eixo, num_roda, placa)
Self.tara = tara Class Barco (Aquatico): Def __init__ (self,
ancora, modelo, marca, cor, ano, combustivel, casco, proa,
popa) Super().__init__ (modelo, marca, cor, ano, combustivel)
Super().__init__ (casco, proa, popa) Self.ancora = ancora
Class Jetski (Aquatico): Def __init__ (self, manopla, modelo,
marca, cor, ano, combustivel, casco, proa, popa)
Super().__init__ (modelo, marca, cor, ano, combustivel)
Super().__init__ (casco, proa, popa) Self.man = manopla
Class Aviao (Aereo): Def __init__ (self, asa, flap, modelo,
marca, cor, ano, combustivel, helice, calda, propulsor)
Super().__init__ (modelo, marca, cor, ano, combustivel)
Super().__init__ (helice, calda, propulsor) Self.asa = asa
Self.flap = flap Class Helicoptero (Aereo): Def __init__ (self,
modelo, marca, cor, ano, combustivel, helice, calda,
propulsor) Super().__init__ (modelo, marca, cor, ano,
combustivel) Super().__init__ (helice, calda, propulsor) Def
voar_parado (self) Pass Class Pessoa:
Def __init__ (self, nome, endereco, telefone, email) Self.nome
= nome Self.end = endereco Self.tel = telefone Self.email =
email Class PessoaFisica (Pessoa): Def __init__ (self, CPF,
nome, endereco, telefone, email) Super().__init__ (nome,
endereco, telefone, email) Self.cpf = CPF
Class PessoaJuridica (Pessoa): Def __init__ (self, CNPJ, IE,
nome, endereco, telefone, email) Super().__init__ (nome,
endereco, telefone, email) Self.cnpj = CNPJ
Self.ie = IE
Class Locacao:
Def __init__ (self, data_entrega, data_retirada, Tipo_veiculo)
Self.dt_entr = data_entrega Self.dt_ret = data_retirada
Self.veiculo = tipo_veiculo
Note alguns pontos importantes:
A herança é caracterizada pela classe passada por parâmetro na
criação da nova classe. Por exemplo, a nova classe Terrestre
herda de Veículo: class Terrestre (Veículo).
Neste caso, devemos passar os valores dos atributos da classe
Terrestre e da classe Veículo por meio da palavra reservada
super().
A classe Carro herda de Terrestre e, indiretamente, de Veículo:
class Carro (Terrestre).
Neste caso, devemos passar os valores dos atributos das
classes Carro, Terrestre e Veículo, sempre com a palavra
reservada super() quando for superclasse.
Na classe Helicóptero, só criamos o método “Voar_parado()”,
sem passar parâmetro e sem instruções (pass). Repare que não
é o método construtor.
Não criamos os métodos das outras classes, pois não temos as
instruções (o que fazer em cada método). Porém, basta seguir a
mesma sintaxe da classe Helicóptero.
Com isso, identificamos as classes do nosso sistema,
modelamos com o diagrama de classes e criamos todas as classes
com a linguagemorientada a objetos Python. Vamos instanciar os
objetos, então?
2 Instâncias
Instanciar é criar um objeto a partir de uma classe. Não devemos
esquecer de passar os parâmetros exigidos pela classe no momento
da instância. Vamos criar os objetos Veículo, Terrestre e Carro para
entender o conceito da herança e dos métodos construtores.
V = Veículo (‘Kicks’, ‘Nissan’, ‘prata’, ‘2019’, ‘flex’)
T = Terrestre (‘Kicks’, ‘Nissan’, ‘prata’, ‘2019’, ‘flex’, 2, 4,
‘GMM7718’)
C = Carro (4, ‘Kicks’, ‘Nissan’, ‘prata’, ‘2019’, ‘flex’, 2, 4, ‘GMM7718’)
Note que, cada vez que criamos um objeto, dependendo do tipo,
precisamos passar as quantidades e os valores dos atributos
exigidos pelos métodos construtores. Isso só acontece no momento
da instância. Mas e se quisermos alterar algum valor depois de criado
o objeto? Por exemplo, se quisermos alterar o número de portas do
nosso carro.
No capítulo anterior, não mostramos como alterar o valor de um
atributo. Não podemos simplesmente alterar diretamente no atributo
da classe, por que todos os atributos estão encapsulados por
motivos de segurança. Segundo Coelho (2012), encapsulamento vem
de encapsular, que em programação orientada a objetos significa
separar o programa em partes, o mais isolado possível. A ideia é
tornar o software mais flexível, fácil de modificar e de criar novas
implementações. O encapsulamento serve para controlar o acesso
aos atributos e métodos de uma classe.
Por exemplo, imagine um casulo de uma borboleta. Ele está
protegido do acesso de outros animais; só quem está dentro do
casulo é que tem acesso aos nutrientes ali contidos. Na
programação, protegemos um dado de acesso externo quando
queremos controlar, internamente, como será feita a modificação
desse dado. Para isso, a própria classe, por meio de métodos
específicos, pede a informação por parâmetro e altera o valor da
variável internamente. O mesmo procedimento acontece quando
alguém requisita o valor de uma variável encapsulada. Esse alguém
solicita, por meio de métodos específicos, qual informação ele deseja
obter e a própria classe acessa a variável, lê seu valor e retorna para
quem requisitou.
Em linguagens puramente orientadas a objetos, como o Java,
por exemplo, existem modificadores de acesso que são utilizados
para privar os atributos do acesso direto, tornando-os privados, e
implementam-se métodos públicos que acessam e alteram os
atributos. Em Python, basta colocarmos um underline antes do nome
da variável, no método construtor. Reescrevendo a classe Carro,
temos:
Class Carro (Terrestre): Def __init__ (self, num_porta, modelo,
marca, cor, ano, combustivel, eixo, num_roda, placa)
Super().__init__ (modelo, marca, cor, ano, combustivel)
Super().__init__ (eixo, num_roda, placa) Self._porta =
num_porta
Em negrito, destacamos a variável “_porta” como sendo privada
de acesso externo (ou seja, acesso de outras classes). Para
modificarmos os valores dessa variável, devemos criar um método
setPorta (parâmetro) e passar, por parâmetro, o valor a ser
substituído.
Class Carro (Terrestre): Def __init__ (self, num_porta, modelo,
marca, cor, ano, combustivel, eixo, num_roda, placa)
Super().__init__ (modelo, marca, cor, ano, combustivel)
Super().__init__ (eixo, num_roda, placa) Self._porta =
num_porta Def setPorta (num_porta):
Self._porta = num_porta
Pronto! O método para inserir um valor no atributo num_porta
está destacado em negrito. Uma vez criado o objeto “C” do tipo Carro,
basta chamarmos o método setPorta e passar o novo número de
portas.
C.setPorta (5)
Assim como existem métodos para inserirmos valores aos
atributos, existem os métodos que leem o valor já inserido em um
atributo, nos retornando seu conteúdo. Esses são os métodos “get” e,
para lermos qual valor foi inserido na variável “_porta”, basta
chamarmos o método “getPorta()”.
Class Carro (Terrestre): Def __init__ (self, num_porta, modelo,
marca, cor, ano, combustivel, eixo, num_roda, placa)
Super().__init__ (modelo, marca, cor, ano, combustivel)
Super().__init__ (eixo, num_roda, placa) Self._porta =
num_porta Def setPorta (num_porta):
Self._porta = num_porta
Def getPorta ():
Return self._porta
Agora, basta chamar o método e imprimir seu valor na tela,
assim como fizemos em portugol com o VisuAlg:
Print (C.getPorta())
Simples, não é mesmo? Sugiro que você faça os “get” e “set” para
todas as variáveis de todas as classes para treinar e fixar os
conceitos aprendidos neste capítulo.
Considerações finais
Modelar e construir as classes de um sistema é uma das etapas
mais importantes no ciclo de um projeto de software. Neste capítulo,
identificamos as classes de um sistema de locação de veículos e
utilizamos o conceito de herança, aproveitando esse ótimo recurso do
paradigma da orientação a objetos, tendo como vantagem o reúso e
a otimização de código.
Nesse conceito, é importante manter um sistema de hierarquia
entre as classes, sendo que a classe do topo da hierarquia é a mais
genérica e, conforme vamos descendo na hierarquia, as classes vão
se tornando mais específicas. Nesse caso, uma classe específica é
chamada de subclasse e a classe genérica, superclasse.
Cada objeto criado deve respeitar as exigências dos atributos
passados por parâmetros, conforme os métodos construtores (da
própria classe e das superclasses). Para acessar os métodos
construtores das superclasses, devemos usar a palavra reservada
super().
Por motivos de segurança do paradigma orientado a objetos, os
atributos das classes devem ser protegidos e privados de acessos
externos (acessos de outras classes). Por esse motivo, para
acessarmos e modificarmos o valor de um atributo, devemos
construir métodos “set” e passar o valor a ser atribuído por
parâmetro.
Seguindo a mesma ideia, temos os métodos “get” para ler e
retornar um valor anteriormente atribuído a um atributo, seja por um
método “set” ou pelo método construtor no momento de sua criação.
Referências
COELHO, A. Java com orientação a objetos. Rio de Janeiro: Editora
Ciência Moderna Ltda., 2012.
DEITEL, H. M.; DEITEL, P. J. Java – como programar. 6. ed. São Paulo:
Editora Pearson Prentice Hall, 2005.
GUEDES, G. T. A. UML 2: uma abordagem prática. 3. ed. São Paulo:
Editora Novatec, 2018.
PUGA, S.; RISSETTI, G. Lógica de programação e estruturas de
dados com aplicação em Java. 2. ed. São Paulo: Editora Pearson,
2009.
Capítulo 13
Programação orientada a objetos:
Python
O paradigma orientado a objeto está muito presente e atuante
hoje em dia. Pela facilidade no desenvolvimento e no reúso de código,
os programadores dão preferência a esse tipo de linguagem.
Porém, não é tão simples assim a escolha da melhor linguagem
de programação. Precisamos levar em consideração muitos fatores,
como velocidade de processamento, segurança, recursos da
linguagem e facilidade de manutenção, assim como a facilidade e o
conhecimento da linguagem pelo desenvolvedor, é claro.
Neste capítulo, vamos apresentar os pilares do paradigma
orientado a objetos e conhecer a linguagem Python, que vem
ganhando muito espaço no mundo inteiro. Além disso, veremos
alguns comandos básicos e os conceitos de classe e objeto, como
aplicações da linguagem.
1 Linguagem orientada a objetos
Como já estudado, em capítulos anteriores, a orientação a
objetos é um paradigma que tem como principais elementos as
classes e os objetos, que são representações abstratas do mundo
real. A programação orientada a objetos (POO) exige linguagens
específicas, ou pelo menos que suportem os conceitos do paradigma
orientado a objetos, como C#, Java e Python, por exemplo.
Para compreendermos exatamente do que se trata a orientação
a objetos, vamos entender quais são os requerimentos de uma
linguagem para ser considerada nesse paradigma. De acordo com
um artigo escrito por Henrique Machado Gasparotto (2014),
desenvolvedor fullstack, a linguagem precisa atender a quatro tópicos
bastante importantes:
1.1 Abstração
A abstração é a capacidade de ignorar os detalhes das partes
para focalizar a atenção em um nível mais elevadode um problema
(BARNES; KÖLLING, 2004). Em outras palavras, precisamos extrair
um objeto do mundo real para nosso sistema computacional. E, para
isso, temos que imaginar o que esse objeto vai realizar dentro de
nosso sistema.
O conceito de abstração em orientação a objetos divide um
problema em várias partes e tenta resolver os subproblemas como
blocos independentes. Por exemplo, imaginem um carro sendo
projetado e construído por uma indústria automobilística. Em vez de
implementar o carro em um único objeto, construiríamos objetos
separados como um motor, caixa de engrenagens, roda, assento e
assim por diante.
Saber identificar qual objeto do mundo real vamos representar
em nosso sistema e quais partes são componentes desse objeto não
é tarefa fácil, e vai exigir um pouco de experiência dos analistas e
projetistas de software.
Mas uma dica é: identifique o objeto e quais atributos são
necessários para descrever suas características. Em seguida,
identifique os métodos, que são as ações que esse objeto vai
desempenhar dentro do sistema. Por exemplo, o objeto carro tem
como atributos marca, modelo, cor, ano, chassi e, como métodos,
andar, parar, buzinar, ligar, etc. Dessa maneira, demos o primeiro
passo em relação à abstração desse objeto em nosso sistema.
1.2 Encapsulamento
O encapsulamento é uma das principais técnicas do paradigma
de programação orientada a objetos. Segundo Coelho (2012), este
conceito é útil para garantir que a solução dos problemas propostos
seja sempre realista e que cada elemento só enxergue o que
realmente é importante.
Trocando em miúdos, encapsular significa proteger. Esse
conceito, na orientação a objetos, protege nossos atributos e
métodos de acesso externo indevido. Por exemplo, se quisermos
trocar a cor de um carro, não podemos acessar diretamente a
variável “cor” da classe carro. O que temos de fazer é acessar um
método que nos permita efetuar essa alteração. Lembrando que os
objetos, dentro do nosso sistema, só podem fazer alguma coisa por
meio de ações (que são os métodos na orientação a objetos).
Esses métodos de atribuir um valor a uma variável ou obter o
valor dessa variável têm nomes específicos na programação
orientada a objetos:
Método GET: esse método acessa a variável e retorna seu valor
para o objeto que a chamou.
Método SET: esse método atribui um valor à variável solicitada
pelo objeto. O valor é passado por parâmetro.
1.3 Herança
Herança é um dos conceitos mais utilizados na programação
orientada a objetos. Segundo Deitel e Deitel (2010), herança é uma
forma de reutilização de software em que uma nova classe é criada,
absorvendo membros de uma classe existente e aprimorada com
capacidades novas ou modificadas.
Como vimos em capítulos anteriores, a herança segue uma ideia
de hierarquia, onde a classe mais acima da camada é a mais
genérica, ou seja, possui atributos e métodos gerais daquele objeto.
Por exemplo, se nossa classe for “animal”, não podemos colocar,
como método, “amamentar”, ou como atributo, “pele”, pois sabemos
que nem todos os animais amamentam ou possuem pele.
Entretanto, sabemos que existe um grupo específico de animais
que tem essa característica e esse atributo: os “mamíferos”. Portanto,
podemos fazer uma herança de “mamíferos” em “animais”, pois todo
mamífero é animal e todo mamífero amamenta. Finalizando,
podemos dizer que as classes abaixo na camada hierárquica são
classes específicas, ou classes filhas, ou ainda, em algumas
linguagens, subclasses.
1.4 Polimorfismo
Outro conceito importante na programação orientada a objetos é
o chamado polimorfismo. A palavra polimorfismo vem do grego
polimorfos, e significa diversas formas. E é exatamente esse o
sentido desse conceito no paradigma orientado a objeto. De acordo
com Coelho (2012), o polimorfismo nada mais é que a definição de
métodos com o mesmo nome, que definem a solução de um mesmo
problema, seja na própria classe, seja na superclasse.
Por exemplo, imaginem uma classe genérica “eletrodoméstico” –
essa classe possui um método, ou ação, “Ligar()”; e mais duas
classes filhas (ligadas com herança) “televisão” e “geladeira”, que não
serão ligadas da mesma forma. Assim, precisamos, para cada uma
das classes filhas, reescrever o método “Ligar()”, como mostra a
figura 1. Apesar do mesmo nome, cada classe vai utilizar esse
método de uma forma diferente, passando parâmetros diferentes; e o
método saberá o que deve ser feito, de acordo com o objeto que o
chamar e os parâmetros que foram passados.
Figura 1 – Diagrama de classes com polimorfismo
Esses conceitos, ou pilares, são fundamentais no paradigma
orientado a objetos e serão implementados pelas linguagens que
suportam tal paradigma. Entretanto, cada linguagem possui uma
sintaxe e semântica próprias, utilizando, dessa forma, comandos e
palavras-chave específicos. Porém, seja qual for a linguagem
utilizada, todas terão os mesmos objetivos e produzirão os mesmos
efeitos.
Entretanto, não podemos nos esquecer das vantagens que esse
tipo de programação possui, justificando, assim, sua enorme
utilização entre desenvolvedores do mundo todo:
Reúso de código.
Diminuição do tempo de desenvolvimento e de linhas de códigos.
Aplicação de modularização.
Facilidade de manutenção de código.
Porém, a programação orientada a objetos também pode
apresentar um ponto negativo: sua execução é muito mais lenta que
uma linguagem estruturada, por exemplo. Isso é explicado pelo alto
nível das linguagens orientadas a objetos. Quanto mais alto o nível da
linguagem, mais longe da máquina ela se encontra, precisando de
mais transformação dos seus comandos para linguagem de máquina
(linguagem binária). Mas, em muitos casos, isso não será um
problema, tendo em vista que, hoje em dia, o hardware está cada vez
mais rápido e os processadores respondem muito bem a esse
processo de transformação.
No momento atual em que estamos, tecnologicamente essa
execução mais lenta não é sentida. Isso significa que, em termos de
desenvolvimento de sistemas modernos, a programação orientada a
objetos é a mais recomendada, devido às vantagens que foram
apresentadas. Essas vantagens são derivadas do modelo de
programação, que busca uma representação baseada no que vemos
no mundo real.
Agora, embora existam várias linguagens orientadas a objetos,
como C++, C# e Java, por exemplo, a pergunta agora é: qual
linguagem de programação vamos estudar? Responderemos esta
questão a seguir.
2 Conceitos de Python
Vamos começar explicando o porquê do Python. Além do fato de
que o Python hoje é a linguagem mais utilizada para desenvolvimento
de script´s para integrações de ambientes em diferentes plataformas,
também é uma linguagem simples para aprender a programação e
que contém em sua comunidade um forte pilar para a sua
propagação e incentivo a sua utilização.
Um outro fator importante, de acordo com Forbellone e
Eberspacher (2005), é que o Python é a linguagem de programação
mais utilizada no mundo de segurança da informação. Não vamos
nos estender sobre sua história, mas algumas informações são
importantes:
O Python foi lançado na internet em 1991 (comparada com
outras linguagens mais tradicionais, como a linguagem C, por
exemplo, o Python é um bebê).
O seu criador chama-se Guido Van Rossum, um holandês que
desenvolveu essa linguagem com o intuito de criar algo que não
se parecesse com qualquer outro concorrente; por isso, já na sua
concepção, o Python tinha como objetivo atender aos
profissionais que trabalham com tecnologia, mas que são
“resistentes” à programação, como: cientistas, engenheiros de
diversas áreas, especialistas em dados, especialistas em
segurança, entre outros. Por isso, duas palavras nortearam o
trabalho de Guido Van Rossum, são elas: legibilidade e
produtividade.
Alocação de memória e gerenciamento de recursos são
conceitos com que não precisamos nos preocupar em Python,
uma vez que a própria linguagem se encarrega de controlar, de
maneira eficiente, esses serviços. Em relação ao desenvolvedor,
isso é de grande valia, uma vez queo programador foca apenas
no desenvolvimento da sua solução/ferramenta.
 PARA SABER MAIS
O Python é uma linguagem livre, que depende bastante da sua
comunidade, por isso, não deixe de participar “ativamente” da
comunidade. Temos uma comunidade para brasileiros, como o
grupo Grupy-SP. Você vai se surpreender em como poderá ser útil e
como vai aprender de maneira mais rápida e eficiente participando
de uma comunidade.
Outra característica, que é muito polêmica no mundo dos
desenvolvedores Python, é responder à pergunta: Python é
interpretado ou compilado? Vamos começar demonstrando as duas
arquiteturas mais comuns, utilizadas pelas linguagens de
programação:
Figura 2 – Modelo para representação de uma linguagem
compilada
A figura 2 demonstra uma compilação, o caso da linguagem C,
por exemplo, em que você escreve um arquivo com comandos em C,
gera um arquivo fonte, exemplo: aplicacao.c. Quando conclui o seu
código, precisa executá-lo em outro computador, que não terá a
linguagem C instalada, então você compila, ou seja, gera um arquivo
executável no seu computador, normalmente com extensão “exe”, o
qual ficaria com o nome aplicacao.exe. Esse arquivo executável não
depende mais da existência do C na máquina em que será executado.
 IMPORTANTE
Um compilador é um programa de computador que, a partir de um
código-fonte escrito em uma linguagem compilada, cria um
programa semanticamente equivalente, porém escrito em outra
linguagem, 
código-objeto.
Vejamos agora outra arquitetura utilizada pelas linguagens de
programação. Um exemplo que utiliza essa arquitetura é a linguagem
Basic, em que o código-fonte agora não será convertido, apenas será
interpretado por alguma aplicação que a própria linguagem possui, ou
seja, caso queira executar sua aplicação, deverá instalar o
responsável da linguagem que interpretará o seu código-fonte.
Não será gerada outra forma de arquivo. É como ocorre com o
HTML (que não é exatamente uma linguagem de programação, mas
não entraremos no mérito da questão nesse momento), que depende
de um browser para que seja executado. Sem um browser, um HTML
é apenas um aglomerado de códigos, conforme a figura 3:
Figura 3 – Modelo para representação de uma linguagem
interpretada
Mas o que ocorre com o Python? Segundo Rhodes e Goerzen
(2015), o Python trabalha dentro da arquitetura interpretada, ou até
mesmo com as duas arquiteturas (compilada e interpretada) juntas,
formando uma arquitetura híbrida, o que termina causando as
eternas discussões: o Python faz uso da arquitetura interpretada,
compilada e/ou híbrida?
 IMPORTANTE
O software interpretador é um programa de computador que
executa instruções escritas em uma linguagem de programação,
sem gerar um arquivo executável.
Quando você gera o seu código-fonte em Python (arquivo com
extensão .py), poderá compilá-lo, o que vai gerar um arquivo com
extensão .pyc (Python Compile), que não é independente, vai precisar
da ferramenta que vai interpretar o seu conteúdo, a qual chamamos
de PVM (Python Virtual Machine). Logo, para executar um arquivo
compilado em Python, você não precisa do Python como ferramenta,
vai precisar apenas da PVM instalada, ou seja, nesse processo ele
compilou e interpretou, logo é híbrido.
Mas como afirmamos anteriormente, o Python não obriga a
compilação, ou seja, um arquivo .py (código-fonte) pode ser
diretamente interpretado pela PVM (essa é a situação mais comum
de utilização do Python no mercado), logo ele é interpretado.
Diante dessa característica, podemos nos fazer uma outra
pergunta: qual o paradigma do Python?
Eis mais uma vantagem do Python em relação às outras
linguagens que são mais engessadas em relação aos paradigmas,
porque o Python é multiparadigma, ou seja, atende alguém que já
esteja adaptado a pensar e organizar os seus códigos por meio do
paradigma orientado a objetos, aqueles que fazem uso do paradigma
estruturado, e até mesmo aqueles que trabalham com o paradigma
funcional (ou linear), que é o paradigma mais distante do Python, mas
que também pode ser utilizado.
Essa característica de ser multiparadigmas termina tirando o
peso do conhecimento prévio sobre os paradigmas e a preocupação
em adotar mais esses conceitos, que são mais importantes para
aqueles que atuam ou desejam atuar como desenvolvedores.
Muito mais prático, não? Perceba como isso está no seu dia a
dia. Vamos a um exemplo: o controle remoto da sua televisão. Se ele
ainda não existisse, você seria obrigado a ligar, trocar os canais e
controlar o volume diretamente na sua TV, certo? E se essas funções
dessem qualquer tipo de problema? Você deveria levar até um técnico
para realizar a manutenção. Então, perceba como é mais útil usar
uma linguagem multiparadigmas.
Com todas essas funções (ligar/desligar, aumentar/diminuir
volume, trocar de canais) em um controle remoto, caso você tenha
algum problema nesses módulos, basta levar o controle para a
manutenção, ou ainda trocar por outro, o que torna o processo muito
mais simples e rápido. E ainda pode ser reaproveitado, pois caso você
tenha outra TV igual, poderá aproveitar o controle remoto de uma em
outra.
3 Aplicação de POO: Python
Mas, afinal, qual é a utilização prática dessa linguagem? Primeiro,
vamos entender mais uma característica do Python. Imagine uma
longa estrada, onde em uma das suas extremidades encontraremos a
CPU e, na outra, o desenvolvedor.
Então, quando você trabalha com linguagem de alto nível, o seu
programa/ferramenta parte de um ponto dessa estrada, mais
próximo ao desenvolvedor. Isso significa que ele está mais distante
da CPU e, para chegar lá, vai demorar um pouco mais, quando
comparamos com uma linguagem de baixo nível, que está mais
próxima da CPU.
Por isso, existe uma diferença de performance entre uma
linguagem de alto nível e uma linguagem de baixo nível. A quantidade
de processos que existem entre a ferramenta do desenvolvedor e a
CPU é maior quando a linguagem utilizada é de alto nível, e haverá
menos processos quando a linguagem for de baixo nível.
Por outro lado, pelo fato de a linguagem de alto nível estar mais
próxima do desenvolvedor, é mais legível para ele. Quanto mais se
avança na estrada em direção à CPU, mais difícil vai ficando a leitura
e a interpretação do código pelo programador. Por exemplo, observe
as linhas a seguir:
1. se nota<6 .e. nota>=4 entao 2.
if nota<6 and nota>=4: 3. if
(nota<6 && nota>=4) {
Na primeira linha, a interpretação é mais clara, pois está em
altíssimo nível. Na verdade, não é nenhuma linguagem de
programação de mercado, mas seria a linha de comando do VisuAlg,
que auxilia no processo de aprendizagem de programação.
Já na segunda linha, a interpretação começa a ficar um pouco
mais obscura – ela está escrita em Python; e, na terceira linha, o nível
é ainda mais baixo, tornando o código mais ilegível – está escrito em
Java. Perceba que quanto mais alto o nível, mais fácil para ser
compreendida, ou seja, mais fácil para que você possa aprender.
Falando em aprender, está na hora de colocarmos a mão na
massa. Lembre-se de que até agora a maior preocupação foi situar
você em relação ao Python, esclarecer a importância dessa
linguagem para sua formação, apresentar os conceitos mais comuns
com que você poderá se deparar no mercado de trabalho, entender
como funciona e qual a principal proposta da linguagem de
programação Python.
Vamos fazer nosso primeiro programinha em Python. Não
vamos nos preocupar agora com a IDE, ou seja, onde escrever o
código para executar os comandos Python. Vamos apenas entender
os comandos mais simples e a sintaxe dessa linguagem.
No ambiente apropriado, para imprimir “Olá, mundo!” na tela
basta utilizar o comando de saída:
Print (“Olá, mundo!”)
Bem simples, não é mesmo? Agora vamos utilizar os conceitos
de classe e objeto, para diferenciar da programação estruturada, na
qual temos feito até agora:
Class Teste():
Def __init__ (self): Print (“Objeto
criado!”) Def imprime (self): Print
(“Olá, mundo!”) Class principal():
Obj_teste = Teste() Obj_teste.imprime()Note que criamos a classe “Teste”, que possui o método
construtor (que imprime, na tela, a frase “Objeto criado!”) e o método
imprime, que, quando acionado, vai imprimir na tela (pelo comando
print) a frase “Olá, mundo!”. Na classe “Principal”, nós criamos
(instanciamos) o objeto “obj_teste” e, logo em seguida, esse objeto
chama o método imprime: obj_teste.imprime().
Esse método é chamado, e seu código executado. Como o
método possui somente o comando print, a frase que está sendo
passada por parâmetro será impressa na tela, produzindo esse
resultado, conforme a figura a seguir:
Figura 4 – Resultado da execução dos comandos Python
Objeto criado!
Olá, mundo!
Notaram que foram impressas duas frases (“Objeto criado!” e
“Olá, mundo!”)? Isso ocorreu porque, assim que o objeto “obj_teste” é
instanciado, ele chama, automaticamente, o método construtor.
Como esse método tem o comando print, seu parâmetro é impresso
(“Objeto criado!”). Para imprimir a frase “Olá, mundo!”, o objeto teve
que chamar o método imprime.
Simples, não é? Treine mais exercícios como este e não deixe de
participar das comunidades.
Considerações finais
Neste capítulo, apresentamos os pilares de uma linguagem
orientada a objetos (abstração, encapsulamento, herança e
polimorfismo). A abstração diz respeito ao que um objeto executará
em nosso sistema: encapsular é proteger nossos atributos e métodos
de acessos externos, às vezes, indevidos; herança é quando uma
subclasse (ou classe filha) herda os atributos e métodos de sua
classe pai; e polimorfismo são várias formas diferentes de se
executar o mesmo método em objetos diferentes.
Além disso, compreendemos os conceitos e a utilização da
linguagem de programação Python e suas características peculiares,
como multiparadigmas, híbrida (interpretada e compilada) e ser uma
linguagem de alto nível. Não se esqueça que a linguagem Python é a
mais utilizada no mundo, em segurança da informação.
Por fim, vimos algumas aplicações dos comandos Python e a
execução de uma classe e uma instância de objeto, gerando duas
impressões de frases, na tela, por meio do comando print.
Referências
BARNES, D. J.; KÖLLING, M. Programação orientada a objetos com
Java: uma introdução prática utilizando o BlueJ. São Paulo: Editora
Pearson Prentice Hall, 2004.
COELHO, A. Java com orientação a objetos. Rio de Janeiro: Editora
Ciência Moderna Ltda., 2012.
DEITEL, H. M.; DEITEL, P. J. C – como programar. 8. ed. São Paulo:
Editora Pearson Prentice Hall, 2010.
DEVMEDIA. Os 4 pilares da programação orientada a objetos. [s. d.].
Disponível em: <https://www.devmedia.com.br/os-4-pilares-da-
programacao-orientada-a-objetos/9264>. Acesso em: 15 jan. 2019.
FORBELLONE, A. L. V.; EBERSPACHER, H. F. Lógica de programação:
a construção de algoritmos e estrutura de dados 3. ed. São Paulo:
Editora Pearson Prentice Hall, 2005.
GASPAROTTO, Henrique Machado. Os 4 pilares da programação
orientada a objetos. DevMedia. 2014. Disponível em:
<https://www.devmedia.com.br/os-4-pilares-da-programacao-
orientada-a-objetos/9264>. Acesso em: 15 jan. 2019.
RHODES, B.; GOERZEN, J. Programação de redes com Python: guia
abrangente de programação e gerenciamento de redes com Python 3.
São Paulo: Editora Novatec, 2015.
https://www.devmedia.com.br/os-4-pilares-da-programacao-orientada-a-objetos/9264
https://www.devmedia.com.br/os-4-pilares-da-programacao-orientada-a-objetos/9264
Capítulo 14
Banco de dados
Utilizamos os computadores para realizar diversos tipos de
tarefas, das mais simples até as mais complexas. Ao longo do dia,
agendamos compromissos, fazemos cálculos, realizamos compras,
mandamos mensagens e até utilizamos para lazer (como ouvir
músicas, assistir filmes, jogar e muitas outras atividades).
Para realizar tarefas, o computador se tornou algo tão primordial,
que criaram o smartphone – um celular que executa praticamente
todas as funcionalidades de um computador e nos conecta por meio
da internet a várias redes sociais e de pesquisa, 24 horas por dia,
onde quer que estejamos.
Tudo isso gera uma imensidão de informações, dados e mais
dados sobre tudo e todos que trafegam neste mar de informações.
Mas como é possível organizar essas informações de forma que
possamos armazenar, localizar e utilizá-las rapidamente?
Para isso, utilizamos os bancos de dados – estruturas de
armazenamento que organizam e interligam conjuntos de
informações que possamos manipular.
Neste capítulo, conheceremos essas estruturas, como são
formadas e como se relacionam umas com as outras para realizar o
armazenamento dos dados de forma organizada e performática.
1 Armazenamento de dados
Para realizarmos as tarefas do nosso cotidiano, interagimos ao
longo do dia com diversos sistemas, tanto os que manipulamos
diretamente, como arquivos no nosso computador e smartphone, até
os que vemos sendo manipulados enquanto nos atendem em
supermercados ou no metrô, por exemplo. Repare que, em todos
estes casos, as informações estão sendo acessadas, processadas e
guardadas.
Pegando o exemplo do supermercado, você já parou para pensar
que, ao passarmos o código de barras de um produto no caixa, ele
automaticamente mostra o preço e informações, tais como: o nome,
a marca, o peso e outros? Ainda mais se pensarmos que existem
milhares de produtos à disposição sendo vendidos lá?
Esta organização é possível devido ao banco de dados que,
segundo Medeiros (2013), é um conjunto de dados com certas
características, com a finalidade de armazenamento persistente dos
dados e dotado de mecanismos de manipulação para a obtenção de
informações e recuperação de dados posteriormente dentro de um
sistema de informação.
No início, os programas desenvolvidos para escritórios e
empresas tinham uma estrutura de arquivo de dados, que eram
usados para guardar as informações manipuladas pelo sistema, e
esta era embutida na aplicação, ou seja, os arquivos que guardavam
as informações ficavam juntos e integrados com os arquivos de
programação, que eram usados para executar as tarefas. Isso era um
grande problema, pois se houvesse a necessidade de alguma
mudança, afetaria diretamente as informações guardadas e, se
outros programas precisassem das mesmas informações, teriam
grandes problemas para se integrar.
Já nos sistemas atuais, é imprescindível que todas as áreas
estejam integradas; por exemplo, o departamento de compras com o
almoxarifado da empresa, para que o sistema possa apontar quando
será necessária uma nova compra para repor o estoque ou para que,
em uma cadeia de lojas, possa ser possível saber em qual unidade
tem um determinado produto, além do volume de armazenamento
ser muito maior. Por isso, hoje para manipular os dados é utilizado
um sistema exclusivo, formado por uma coleção de programas para
esta função, chamado sistema gerenciador de banco de dados
(SGBD – database management system).
 IMPORTANTE
O SGBD é um sistema de software de uso geral, que facilita o
processo de definição, construção, manipulação e
compartilhamento de banco de dados entre diversos usuários e
aplicações (ELMASRI; NAVATHE, 2011, p. 3).
Os sistemas que atendem todas as áreas que geram uma grande
quantidade de informações – como fábricas, bancos, hospitais,
universidades, unidades do governo, e tantas outras – utilizam os
SGBDs para gerenciar suas informações.
Imagine agora em uma empresa, quantos tipos de informações
suas operações produzem? Podemos rapidamente pensar em dados
dos produtos, sobre as contas de clientes e fornecedores, sobre seus
funcionários, departamentos, planejamento, orçamento, é uma
infinidade de informações, que, nos dias de hoje, além de serem vitais
para organização e controle delas, se transformam em uma poderosa
ferramenta de tomada de decisão. Mas isso veremos um pouco mais
à frente.
Puga, França e Goya (2013) trazem definições sobre banco de
dados, que poderíamos sintetizar assim: banco de dados é uma
coleção de dados persistentes, usada pelo sistema de aplicação de
uma determinada empresa.
Vamos definir alguns termos importantes que serão muitoúteis
nos nossos estudos:
Dados: é um registro, uma unidade básica de informação, por
exemplo um nome, um endereço, uma data, um valor, etc. Repare
que vistos de forma isolada não nos trazem um significado.
Informação: é um conjunto de dados dispostos de forma
organizada no momento em que o usuário ou o sistema solicita
gerar conhecimento.
Exemplo:
Nome: Andréia; Endereço: Av. Dom Pedro I número 57.
O que temos acima são alguns dados sobre uma pessoa; se os
associarmos em um contexto, teremos uma informação: Andréia
mora na Av. Dom Pedro I número 57.
Percebe a diferença? Dados devidamente associados nos trazem
conhecimento!
Persistente: entende-se por dados persistentes aqueles que,
uma vez aceitos em um SGBD para a entrada no banco de dados,
somente poderão ser removidos por uma requisição explícita a
ele, ou seja, uma vez gravado, só será removido por um comando
direto;
Coleção de dados: um grande conjunto de dados armazenados
e inter-relacionados, que atendem as necessidades de vários
usuários que utilizam o sistema.
Vamos entender melhor como o SGBD é utilizado. Na figura 1,
podemos ver como o SGBD é utilizado para proteger e gerenciar os
dados.
Figura 1 – Esquema de funcionamento do
SGBD
Os usuários de seus terminais acessam o sistema de aplicação
para realizar suas tarefas diárias e, todas as vezes que este sistema
precisa realizar alguma interação com as informações que estão
gravadas no banco de dados – seja ler, gravar, alterar, listar, deletar ou
até mesmo simplesmente consultar –, ele realiza as tarefas por meio
do SGBD. Assim, se outros sistemas de aplicações precisassem das
mesmas informações, poderíamos interligá-los ao mesmo SGBD,
sem a necessidade de fazer alteração no outro sistema.
2 Modelos de banco de dados
O modelo de dados é uma representação gráfica daquilo que
precisamos armazenar dentro de um banco de dados. Esta estrutura
de armazenamento é representada por meio de um diagrama, que
chamamos de modelo.
Três modelos representam fases na concepção do projeto desse
banco, como segue:
Modelo conceitual: Leal (2015) explica que tem por objetivo
representar as principais necessidades de negócio – é uma visão
macro do que precisamos armazenar. Ele é elaborado a partir
das primeiras conversas com o usuário, onde vamos entender o
que precisa ser armazenado, de que maneira, como as
informações precisam se associar e relacionar dentro da
estrutura de negócios.
Exemplo: Clínica Veterinária. Dentro de uma conversa com
um cliente para a criação de um banco para esta clínica, ele
começa a explicar que o veterinário realiza consultas,
atendendo diversos pacientes e realizando exames. Assim,
eu começo a visualizar a necessidade de armazenar alguns
tipos de dados no banco (veterinário, consultas, pacientes,
exames).
A figura 2 mostra uma indicação gráfica do modelo conceitual de
um relacionamento entre o veterinário e o exame.
Figura 2 – Exemplo de modelo conceitual
Modelo lógico: é uma continuação do modelo conceitual,
elaborado a partir das informações que coletamos e
organizamos no conceitual. Os elementos que foram levantados
começam a receber as características deste armazenamento, ou
seja, quais os dados que temos que guardar de cada uma destas
entidades. Segundo Puga, França e Goya (2013), o modelo lógico
de dados reflete as propriedades necessárias para a tradução do
modelo conceitual, de maneira que seja possível a descrição dos
elementos capazes de serem interpretados pelo SGBD.
Exemplo: Quais são os dados que devemos guardar do
veterinário e do exame? Temos de analisar as necessidades
do negócio, para definir esses atributos.
Na figura 3, temos a mesma visão do relacionamento entre a
entidade do veterinário com o exame, só que expressando como o
sistema deve se comportar.
Figura 3 – Exemplo de modelo lógico
Modelo físico ou relacional: também é uma evolução do modelo
anterior (lógico); nesta fase, devemos definir qual é o SGBD em
que o projeto será implementado, pois cada SGBD tem
características específicas e, assim, definir detalhes técnicos,
como tipo de dados, qual é a chave primária, a chave estrangeira,
se o campo é opcional ou obrigatório e outras características que
veremos mais à frente. Puga, França e Goya (2013) enfatizam
que o modelo físico é a evolução que descreve como deverá ser
o armazenamento físico, utilizando os termos computacionais.
A figura 4 mostra a última fase de modelagem; o modelo físico
ou relacional traz os últimos detalhes necessários para a
implementação do banco. Nele, constam os atributos e quais tipos de
valores terão.
Figura 4 – Exemplo de modelo físico ou
relacional
3 Conceito de banco de dados
Agora, vamos sintetizar alguns conceitos importantes do que
vimos até o momento. O banco de dados relacional é modelado e
organizado em entidades que se relacionam. Para entendermos
melhor como as informações se organizam em entidades, vamos
imaginar cada entidade como uma tabela.
 IMPORTANTE
Entidades são elementos ou objetos perfeitamente distinguíveis. 
No processo de modelagem, as entidades são os primeiros
elementos a ser considerados, por estarem explícitos ou evidentes
(MEDEIROS, 2013, p. 36).
Mas como identificar uma entidade? Para isso, podemos nos
perguntar: O que faz parte do contexto deste negócio?
Com certeza, as respostas farão parte de: coisas tangíveis,
funções, incidentes e interações.
Coisas tangíveis: são objetos, as entidades mais fáceis de
serem percebidas, como: avião, carro, livro, casa, etc.
Funções: são os papéis que uma pessoa ou uma organização
podem desempenhar, como: médico, paciente, cliente,
administrador, corretor, etc.
Incidentes: são utilizados para registrar uma ocorrência ou fato,
qualquer coisa que acontece em um determinado tempo, como:
uma ligação, uma corrida de táxi, um acidente.
Interações: são como um contrato ou transação, algo que é
realizado entre duas ou mais partes, como: uma compra, um
casamento, etc.
Definimos como entidade cada conjunto de informações
relativas a um elemento – como nos exemplos anteriores, ele é
representado por um retângulo e deve conter todos os atributos que
precisaremos, relativos àquele elemento.
Exemplo: em um dos animais atendidos na clínica veterinária,
teríamos atributos como: código, nome, idade, peso, raça, sexo, etc.
Os atributos representam as informações das entidades, então,
olhando o exemplo acima, nome e idade são atributos da entidade
animal do nosso modelo de negócio.
Segundo Medeiros (2013, p. 37):
Atributos são as características de uma entidade. Eles podem ter
uma faixa de valores ou de domínio e se caracterizar por serem
atômicos (simples) ou não atômicos (compostos). Assim, apesar
da possibilidade de fazermos o contrário, devemos sempre
procurar construir atributos simples.
O quadro 1 mostra como poderia ser a tabela que conteria as
informações dos animais tratados na clínica veterinária.
Quadro 1 – Exemplo de uma tabela representando uma entidade
ANIMAL
CÓDIGO NOME IDADE PESO RAÇA SEXO
001 Suzi 9 9,6 Poodle Fêmea
002 Thor 5 10,0 Pitbull Macho
003 Lilika 3 4,2 Beagle Fêmea
O quadro 1 representa a entidade animal; nela, temos os
atributos em formato de colunas e, nas linhas, registros
representando cada animal cadastrado. Assim, temos todos os
dados organizados em uma estrutura, e quando procuramos um
animal, por qualquer que seja sua característica, temos os seus
demais dados também.
Chave primária: cada entidade tem um atributo principal, que
deve ser único, e seu valor não pode ser repetido entre os
registros – chamados de chave primária. Normalmente,
utilizamos um atributo numérico e sequencial para tal tarefa,
como código ou matrícula. Repare que, nos exemplos anteriores,
sempre começamos os atributos de uma entidade por um
atributo como este.
Chave estrangeira: um banco de dados é composto por quantas
entidades forem necessárias para representar o modelo de
negócio proposto. Em um banco de dados, as entidades se
interligam por atributos-chave, nos possibilitando relacionar as
informações umacom a outra. Para estes atributos, damos o
nome de chave estrangeira, que nada mais é do que um atributo
em uma entidade que recebe a chave primária do outro.
No quadro 2, podemos ver a chave primária da tabela cliente
sendo utilizada como chave estrangeira na tabela animal. Perceba
que assim os animais dos registros 1 e 3 recebem a referência do
cliente que está no registro 1.
Quadro 2 – Exemplo de uma relação entre tabelas representando
entidades
No quadro 2, temos a tabela animal – a mesma que vimos no
quadro 1 –, só que agora com uma coluna a mais, chamada
CLIENTE_cod, e outra tabela chamada cliente, que contém os dados
dos donos dos animais. Uma das características mais importantes
em um banco de dados é a unicidade, ou seja, que cada informação
deve ser única, não se repetindo em registros diferentes. Ou seja,
usando a chave estrangeira, que nada mais é do que uma coluna
contendo a chave primária da outra tabela que precisamos relacionar,
para indicar quais registros de uma tabela tem ligação com o da
outra.
Sendo assim, podemos perceber que os animais Suzi e Lilika –
que tem no campo CLIENTE_cod o valor 001 – pertencem ao cliente
Luís Carlos, que é o cliente cadastrado por este código. É dessa
forma que as entidades vão se relacionando e formando os bancos
de dados.
4 Instâncias ou ocorrências de uma
entidade
As instâncias ou ocorrências de uma entidade representam um
conjunto de valores de um elemento, que são inseridos em um banco
que já está formado. Quando olhamos para uma entidade como a
cliente do quadro 2, que contém atributos como nome, CPF e
telefone, e eu tenho os valores como o nome José Augusto, o CPF
245.678.985-85, o telefone 2458-7845, estes valores formam o que
chamamos de instâncias ou ocorrências. Se colocarmos essa
entidade em forma tabular, como nos exemplos anteriores, elas
representam uma linha, conforme o quadro 3 a seguir.
Quadro 3 – Exemplo de instância ou ocorrência
No quadro 3, vemos a entidade cliente sendo visualizada em
forma de tabela – a sua segunda linha, que está em destaque,
representa uma ocorrência, o registro de um cliente no banco de
dados.
Como já podemos perceber, os atributos qualificam e
caracterizam uma entidade. Eles devem sempre ser escritos no
singular, em letras minúsculas e sem acentos.
Quando estamos analisando e definindo os atributos das
entidades do nosso banco de dados, podemos identificá-los e
classificá-los em vários tipos:
Simples: guardam um único valor indivisível, como data de
admissão, estado civil, nome, etc.
Composto: é um atributo composto por vários outros; por
exemplo, o endereço, que é composto por várias informações,
como rua, número, CEP, bairro, cidade e estado.
Multivalorado: pode ter várias ocorrências associadas a ele; por
exemplo, telefone – um mesmo cliente pode informar vários
números, como o da residência, o comercial e o celular.
Determinante: são os atributos que têm características que
podem garantir a unicidade, ou seja, garantir que, se procurado
ou utilizado, ele seja referente a uma única ocorrência; por
exemplo, o código de Renavam de um carro ou o número de uma
nota fiscal – valores que só um deles pode ter.
É muito importante levarmos em conta todas essas
particularidades quando estamos modelando a estrutura do nosso
banco de dados, de forma que venhamos a garantir a unicidade, a
confiabilidade e a integridade de suas informações.
Considerações finais
Quando começamos a entender o que é um banco de dados,
vamos percebendo a sua necessidade e compreender melhor como
os programas conseguem armazenar e manipular as informações
que usamos em todas as áreas da nossa vida.
Ao conjunto formado pelo banco de dados e o sistema de
gerenciamento de banco de dados, chamamos de aplicação de
banco de dados, que hoje é um componente essencial da vida na
sociedade moderna. Devemos ter sempre em mente que, para que
essas aplicações tenham sucesso na sua função, devemos modelar
sua estrutura para que os dados armazenados venham a suprir todas
as necessidades do negócio.
Identificar corretamente todas as entidades que a aplicação
requer e entender o modelo de negócio da empresa para relacionar
estas entidades de forma correta, criando as chaves primárias e
estrangeiras de forma que garanta a unicidade, integridade e a
acessibilidade das informações, é essencial para o sucesso não só da
própria aplicação de banco de dados, mas de todo o sistema
implantado na empresa.
Lembre-se, um bom sistema de banco de dados não é formado
apenas por comandos de controle elaborados e complexos, mas
também de uma base de dados bem organizada.
Referências
ELMASRI, R.; NAVATHE, S. B. Sistemas de banco de dados. 6. ed. São
Paulo: Editora Pearson Addison-Wesley, 2011.
LEAL, G. C. L. Linguagem, programação e banco de dados: guia
prático de aprendizagem [Livro Eletrônico]. Curitiba: InterSaberes,
2015. 2Mb; PDF.
MEDEIROS, L. F. de. Banco de dados: princípios e prática [Livro
Eletrônico]. Curitiba: InterSaberes, 2013.
PUGA, S.; FRANÇA, E.; GOYA, M. Banco de dados: implementação em
SQL, PL/SQL e Oracle 11g. São Paulo: Editora Pearson, 2013.
Capítulo 15
Linguagem SQL
Seus dados escolares, bancários, da sua casa, do seu carro e até
da sua rede social, tudo isso e muito mais está armazenado em
bases de dados das empresas e de instituições responsáveis por
eles. Mas como conseguir gerenciar todas essas informações de
uma forma segura, sem perca de dados e quebra de sigilo, acessando
os dados rapidamente?
Neste capítulo, vamos começar e entender como os sistemas
conseguem se conectar e ter acesso a essa base de dados,
administrando e manipulando-a através de uma linguagem padrão
universal chamada SQL, que proporciona comandos precisos,
utilizados nos SGBDs.
1 Utilização de SQL nas aplicações
Desde os primeiros computadores, o objetivo principal de sua
utilização era criar programas que recebiam dados, processando-os,
e nos entregavam em forma de saída informações como resultado
deste processo. Conforme a tecnologia foi evoluindo e a sua
utilização aumentando, surgiu a necessidade de armazenar essas
informações. O armazenamento de dados abriu um enorme leque de
novas utilizações, principalmente na área comercial para os
computadores.
Segundo Oliveira (2002), em junho de 1970, no jornal Association
of Computer Machinery, E. F. Codd, que na época era membro do
Laboratório de Pesquisas da IBM, situado em San Jose, estado da
Califórnia, publicou um trabalho intitulado “A Relational Model of Data
for Large Shared Data Banks” (Um Modelo Relacional de Dados para
Grandes Bancos de Dados Compartilhados) – esse trabalho tinha a
finalidade de criar uma linguagem que se adaptasse ao banco de
dados relacional. Puga, França e Goya (2013) lembram que este
projeto trabalhava em paralelo com um outro projeto, que visava
desenvolver um sistema de gerenciamento de banco de dados
relacional, chamado “System R”.
Essa linguagem foi a estrutura base usada no desenvolvimento
de uma outra linguagem, que se tornou padrão para manipular
informações em Banco de Dados Relacionais, camada SQL (em
inglês, structured query language, ou linguagem de consulta
estruturada).
Elmasri e Navathe (2011) completam dizendo que o modelo usa
um conceito de relação matemática, que se parece com uma tabela
de valores, pois seu bloco de montagem básico e sua base teórica
residem em uma teoria de conjunto e lógica de predicado de primeira
ordem.
Oliveira (2002) conta que, inicialmente, chamada de Sequel,
acrônimo para “structured english query language”, a linguagem SQL
foi concebida e desenvolvida pela IBM, utilizando os conceitos de
Codd. Já em 1979, a Relational Software Inc., hoje chamada Oracle
Corporation, lançou a primeira versão comercial da linguagem SQL.
No mesmo ano de seu lançamento comercial, duas entidades –
a Ansi (American National Standards Institutes Instituto Nacional
Americano de Padrões) e a ISO (Internacional Standards Organization
Organização Internacional de Normatização) – trabalharam na sua
padronização, uma vez que, mesmosendo desenvolvida pela IBM,
logo surgiram várias adaptações criadas por outros produtores.
O primeiro padrão oficial criado pela Ansi foi em 1986, o SQL-86,
que consistia basicamente na linguagem SQL da IBM, com poucas
modificações. A ISO também adotou o mesmo padrão em 1987.
Depois que a Ansi e a ISO começaram a caminhar juntas, tivemos
mais algumas atualizações:
Figura 1 – Linha do tempo das atualizações da SQL
Basicamente, a linguagem SQL é um conjunto de comandos que
manipulam a base de dados. Com ela, podemos cuidar de sua
estrutura, mantendo e criando, gerenciando seus dados, incluindo,
excluindo, modificando e pesquisando informações nas suas tabelas.
Como ela é uma linguagem que apenas executa comandos
diretamente nos SGBDs, necessitamos utilizar uma linguagem de
programação tradicional, como C, Pascal, COBOL, JAVA, entre outras,
para sua utilização. Assim, embutimos os comandos SQL no código
dessas linguagens, sempre que a aplicação acesse a base de dados.
Alguns até dizem que ela é uma sublinguagem, mas, na verdade, ela
tem a função específica de manipular o banco de dados.
Nos modelos de banco de dados relacionais, a estrutura de
dados que utilizamos são as entidades, que também podemos
chamar de tabelas para melhor ilustrar. Em uma base de dados,
podemos ter diversas tabelas, cada qual contendo um tipo específico
de informação. A linguagem SQL é tão poderosa e prática, que com
um simples comando podemos fazer pesquisas em várias tabelas,
atualizar ou até excluir vários dados.
Uma das grandes diferenças em relação a outras linguagens de
programação é que ela não é procedural, ou seja, podemos
especificar o que deve ser feito, e não como deve ser feito. Isso
possibilita que um comando atinja várias linhas da tabela, e não uma
por uma. Por isso, devemos tomar muito cuidado quando
executamos um comando, para atingirmos somente os dados que
precisamos, sem perder ou alterar os demais.
Com suas seguidas evoluções, a linguagem se tornou a mais
utilizada ferramenta de definição e manipulação de banco de dados
relacionais. Hoje, é a linguagem dos SGBDs mais utilizada no
mercado, como MySQL, DB2, SQL Server, etc.
 IMPORTANTE
“Teoricamente, deveria ser possível transferir facilmente os
comandos SQL de um banco de dados para outro. Contudo, isso
não é possível. Naturalmente, boa parte do trabalho poderá ser
aproveitada, mas 
deve-se fazer adaptações, em função do banco de dados que está
sendo utilizado” (OLIVEIRA, 2002, p. 19).
Devido à padronização realizada pela Ansi e pela ISO, a
linguagem SQL apresenta algumas características que mostram
porque ela se tornou tão popular:
A padronização das instruções: respeitando as particularidades
de cada SGBD, o SQL segue a mesma nomenclatura e formato
em todos eles.
Facilidade de mudanças: a migração de dados entre sistemas
fica muito simples, pois devido a padronização as adaptações
que devem ser feitas, são apenas nas poucas diferenças entre os
SGBDs.
Treinamento de profissionais: se é necessário a migração de um
SGBD para outro, o treinamento de profissionais é mínimo, pois
os comandos são praticamente os mesmos, sendo necessário
apenas o conhecimento das pequenas diferenças. Isso traz uma
grande economia de tempo e dinheiro para as organizações.
Múltipla visão de dados: através dos recursos possíveis de
consulta dos comandos do SQL, podemos recuperar as
informações no formato que venha a agregar mais valor ao
negócio.
Puga, França e Goya (2013) enfatizam que a linguagem SQL é
dividida em três categorias de instruções. Acompanhe cada uma
delas a seguir.
1.1 Definição e manutenção de dados
As instruções DDL (data definition language linguagem de
definição de dados) são a linguagem usada para definição da estrutura
de dados. Este termo foi inicialmente atribuído ao modelo de banco de
dados Codasyl (conference on data systems languages conferência
sobre as linguagens de sistema de dados), onde o esquema de banco
de dados era escrito em uma linguagem de definição de dados que
descrevia os registros, campos e entidades que constituíam o modelo
de dados. No início, só se referia a um subconjunto SQL, mas hoje
também é usada em um sentido genérico, para se referir a qualquer
linguagem para descrição de estrutura de dados.
Os seus parâmetros, assim que compilados, são armazenados
em um conjunto de arquivos chamados de dicionários de dados, ou
catálogo. Ele contém os metadados, que são os dados a respeito das
estruturas de armazenamento; assim, sempre que necessário, o
SGBD consulta esses metadados – na verdade, a cada operação
sobre o banco.
Vamos imaginar que um sistema de uma loja de automóveis
precisa recuperar as informações de alguns campos, como chassis,
placa e Renavam da sua frota. O SGBD vai verificar se os campos que
citamos há pouco estão definidos para este arquivo. O interpretador
DDL processa os comandos criados pelo programador na definição
do banco.
A definição e a manutenção das estruturas do banco de dados,
como por exemplo a criação do banco e as tabelas pelas quais ele é
composto, assim como as relações entre estas tabelas, são feitas
através das instruções do DDL, que são:
CREATE – comando de criação de estruturas de tabelas do
banco de dados.
ALTER – comando de alteração da estrutura de tabelas do banco
de dados.
DROP – comando de eliminação da estrutura de tabelas do
banco de dados.
TRUNCATE – comando de exclusão física de linhas e tabelas.
RENAME – comando de renomeação de tabelas do banco de
dados.
COMMENT – comando de inclusão de comentários das tabelas
do banco de dados.
1.2 Manipulação de dados
As instruções DML (data manipulation language / linguagem de
manipulação de dados) são consideradas uma família de linguagens
utilizadas para recuperar, incluir, remover e modificar informações de
banco de dados. O padrão SQL é “não procedural” – os usuários não
necessitam especificar o caminho de acesso. DMLs foram utilizadas,
inicialmente, apenas para uso direto de programas de computador,
mas, com o surgimento do SQL, elas também podem ser usadas por
pes soas. Todas as vezes que você está utilizando um sistema, quer
seja no serviço ou em casa, e insere, altera, lista ou deleta uma ou
mais informações em um cadastro de clientes, ou em uma conta de
um serviço, você está fazendo com que o sistema que está utilizando
aplique estes comandos no banco de dados. Os comandos DML são:
INSERT – comando utilizado para inserção de dados no banco.
UPDATE – comando utilizado para alteração de dados no banco.
DELETE – comando utilizado para exclusão de dados no banco.
SELECT – comando utilizado para consulta ou busca de dados
no banco.
MERGE – comando utilizado para a combinação das instruções
INSERT, UPDATE e DELETE.
Dentro ainda da parte de manipulação, temos também a DCL
(data control language / linguagem de controle de dados), que é uma
linguagem usada para controlar o acesso aos dados em um banco de
dados. Ela é muito importante, quando pensamos nos aspectos de
segurança e organização, pois com estes comandos podemos definir
os diferentes níveis de acessos e os privilégios concedidos aos
usuários, ou seja, quais as informações contidas nos bancos eles
podem ver. As instruções DCL são:
GRANT – comando utilizado para configurar a atribuição de
privilégios aos usuários de banco de dados.
REVOKE – comando utilizado para revogar os privilégios que os
usuários tinham anteriormente no banco de dados.
1.3 Controle de transação de dados
A TCL (transaction control language / linguagem de controle de
transação) é usada para gerenciar as mudanças feitas por instruções
DML. Ela permite que as declarações sejam agrupadas em
transações lógicas. Basicamente, ela é responsável pela persistência
final das informações nos bancos de dados. Os comandos TCL são:
COMMIT – comando utilizado para confirmar as alterações
feitas no banco. É como se você salvasse um documento no
Word, depois de feitas todas as alterações desejadas.
ROLLBACK – comando utilizado para desistência das alterações
realizadas. Neste caso, écomo se você fizesse alterações no
documento do Word e fechasse o documento sem salvar as
alterações – elas seriam todas perdidas.
SAVEPOINT – comando utilizado para criar um ponto no meio
das transações que está realizando, para que você mais tarde
possa fazer um ROLLBACK.
Segundo Silberschatz, Korth e Sudarshan (2012), a definição de
dados da SQL é muito importante, pois o conjunto de relações em um
banco de dados precisa ser especificado por meio da DDL, que
permite a especificação não só de um conjunto de relações, mas
também de informações sobre cada relação, incluindo:
O esquema para cada relação.
Os tipos de valores que serão usados em cada atributo.
As restrições que vão garantir a integridade das informações.
O conjunto dos índices a serem mantidos para cada relação.
A estrutura física de armazenamento de cada relação.
 IMPORTANTE
Para iniciar a implementação de um banco de dados, cada usuário
possui uma área de trabalho denominada esquema. O esquema é
um elemento do banco de dados que agrupa os demais objetos
pertencentes a um determinado usuário, tais como tabelas, visões,
índices, entre outros. Ao criar um usuário, automaticamente um
esquema também é criado para ele, e, como consequência, o nome
do esquema é o mesmo que o do usuário. (PUGA; FRANÇA; GOYA,
2013, p. 171)
Quando criamos um banco de dados e suas respectivas tabelas,
devemos trabalhar com muito cuidado ao definirmos que tipo de
informação será armazenada em cada atributo. Dependendo de
nossa escolha, podemos criar problemas na hora de persistir e
manipular as informações. Normalmente, os sistemas devem tratar
os dados (verificar se o tamanho e forma condizem com o que deve
ser armazenado), antes de enviar ao banco, mas, independentemente
disso, devemos especificar o tipo de dados, para garantir a
integridade das informações. A tabela a seguir apresenta os tipos de
dados da linguagem SQL:
Quadro 1 – Tipos de dados SQL
INTEGER OU
INT Número positivo ou negativo inteiro.
SMALLINT Mesma função do INTEGER, mas ocupa a metade do espaço.
NUMERIC Número positivo ou negativo de ponto flutuante. Deve-se informar otamanho total do campo e a quantidade de casas decimais.
DECIMAL Semelhante ao NUMERIC, mas em alguns bancos pode ter maior precisãoapós a vírgula.
REAL
Número de ponto flutuante de precisão simples. Os valores são
armazenados em representação exponencial, sendo arredondados para o
nível mais próximo de precisão.
DOUBLE
PRECISION
Número de ponto flutuante de precisão dupla. Comporta-se como o real,
mas permite maior aproximação de resultados.
FLOAT Número de ponto flutuante, em que você define o nível de precisão(número de dígitos significativos).
BIT Armazena um número fixo de bits. O número de bits deve ser indicado; docontrário, o padrão será 1.
BIT VARYING Igual ao bit, permitindo armazenar valores maiores. Utilizado normalmentepara armazenamento de imagens.
DATE Permite armazenar datas.
TIME Permite armazenar horários.
TIMESTAMP Permite armazenar uma combinação de data e hora.
CHARACTER
VARYING OU
VARCHAR
Permite armazenar uma cadeia de caracteres (letra, símbolos e números).
Tamanho deve ser informado e será fixo. Mesmo não sendo usado
totalmente, fisicamente o espaço será ocupado.
INTERVAL Intervalo de data ou hora.
Como falamos anteriormente, a linguagem SQL é padronizada,
mas um SGBD pode ter algumas particularidades em sua sintaxe.
Vamos ver alguns exemplos de tipos de dados que são usados pela
ORACLE:
Quadro 2 – Tipos de dados ORACLE
VARCHAR2 (TAMANHO) Dados de caractere de comprimento variável.
CHAR (TAMANHO) Dados de caractere de comprimento fixo.
NUMBER (P,S) Dados numéricos de comprimento variável.
DATE Valores de data e hora.
CLOB Dados de caractere de um byte até 4 gigabytes.
BLOB Dados binários de até 4 gigabytes.
Como vamos trabalhar com o banco ORACLE posteriormente,
vamos falar um pouco mais sobre os tipos de dados dele para
entendermos melhor:
VARCHAR2 – O tipo VARCHAR2 armazena caracteres de
tamanho variável. Deve se especificar o tamanho máximo em
bytes.
O tamanho máximo de um dado tipo VARCHAR2 é de 4.000
bytes.
O VARCHAR2 tem como subtipos VARCHAR e STRING, com
características semelhantes, apenas para se compatibilizar com
os padrões ANSI/ISO e tipos IBM.
EXEMPLO: VARCHAR2
NOME VARCHAR2(40) NOME= “Lucas dos Santos”, pelo
tamanho ser variável, são armazenados apenas os caracteres
utilizados. É aplicado em campos como nome, logradouro, bairro,
etc.
CHAR – O tipo CHAR armazena caracteres de tamanho fixo.
Pode--se opcionalmente definir o tamanho máximo de um tipo
CHAR. Se um tamanho não for definido, seu default será 1. O
tamanho máximo é especificado em bytes, e não em caracteres.
Portanto, o tamanho do CHAR vai depender de quantos bytes
vão ocupar os caracteres. Seu tamanho máximo é de 2.000
bytes.
O tipo CHAR possui um subtipo para se compatibilizar com o
padrão ANSI/ISO, chamado CHARACTER, que possui exatamente
as mesmas características.
EXEMPLO: CHAR
NOME CHAR(10) – Exemplo de conteúdo: NOME = “Lucas”
Neste caso, será armazenado “Lucas ”. Mesmo o nome só tendo
cinco caracteres ORACLE, completa as posições com espaços
vazios até totalizar os 10.
OBS. Normalmente, ele é utilizado para armazenar valores
booleanos.
NUMBER – Armazena valores inteiros ou de ponto flutuante
entre 1E-130 e 1E125.
Para ser compatível com os tipos ANSI/ISO e IBM, o tipo
NUMBER tem subtipos, com definições idênticas às dos padrões
de origem. São eles: DEC, DECIMAL, DOUBLE PRECISION, FLOAT,
INTEGER, INT, NUMERIC, REAL, SMALLINT.
EXEMPLO: NUMBER
Representando o número: 7,456,123.89
NUMBER(9) = 7456124
NUMBER(9,1) = 7456123.9
NUMBER(*,1) = 7456123.9
NUMBER(9,2) = 7456123.89
DATE – Armazena informações de data. Uma data é composta
por: ano, mês, dia, hora, minuto, segundo e milissegundo.
Pode-se usar uma função chamada SYSDATE e obter a data
atual.
Uma data válida é qualquer data que esteja entre 1/1/4712 AC e
31/12/9999 DC.
O formato da data depende do formato definido para o sistema
gerenciador de banco de dados.
CLOB – Utilizado para armazenar informações até 4.000 bytes,
por exemplo, arquivos .xml.
BLOB – Utilizado para armazenar imagens, áudios e vídeos.
Considerações finais
Bancos de dados e sistemas de banco de dados são
componentes essenciais da vida na sociedade moderna.
Quem quer trabalhar na área de desenvolvimento de sistemas,
seja na programação, ou na gestão, precisa ter um conhecimento ao
menos básico de SQL, pois hoje praticamente todos os sistemas
interagem com banco de dados. Além disso, essa é a linguagem
universal para atender qualquer necessidade de busca e manipulação
de informações em um banco relacional.
Podem ocorrer pequenas variações nesta linguagem,
dependendo do SGBD, mas a sintaxe dos comandos tem a mesma
estrutura; assim, estes conhecimentos acompanharam você por toda
sua vida profissional.
Referências
CODD, E. F. A relational model of data for large shared data banks.
Communications of the ACM, v. 13, n. 6, p. 377-387, 1970.
ELMASRI, R.; NAVATHE, S. B. Sistemas de banco de dados. 6. ed. São
Paulo: Editora Pearson Addison-Wesley, 2011.
OLIVEIRA, C. H. P. SQL: curso prático. São Paulo: Editora Novatec,
2002.
ORACLE. Tipos de dados nativos. [s. d.] Disponível em:
<http://download.
http://download.oracle.com/docs/cd/B19306_01/server.102/b14220/datatype.htm#i16209
oracle.com/docs/cd/B19306 ‐
_01/server.102/b14220/datatype.htm#i16209>. Acesso em: 27 jan.
2019.
______. Tipos de dados Oracle. [s. d.]. Disponível em:
<http://download.oracle.com/docs/cd/B28359_01/server.111/b28318
/datatype.htm#i2093>. Acesso em: 27 jan. 2019.
PUGA, S.; FRANÇA, E.; GOYA, M. Banco de dados: implementação em
SQL, PL/SQL e Oracle 11g . São Paulo: Editora Pearson, 2013.
SILBERSCHATZ, A.; KORTH, H. F.; SUDARSHAN, S. Sistema de banco
de dados. 6. ed. Rio de Janeiro: Elsevier, 2012.
http://download.oracle.com/docs/cd/B19306_01/server.102/b14220/datatype.htm#i16209
http://download.oracle.com/docs/cd/B28359_01/server.111/b28318/datatype.htm#i2093Capítulo 16
Atualização de tabelas em aplicações
Se analisarmos sistemas que se baseiam em cadastros de
pessoas e produtos, como um e-commerce, por exemplo, vamos
perceber que eles praticamente se resumem em manipular os dados
que estão contidos neles – desde o cadastro de um novo cliente,
passando pelo controle dos produtos, chegando até no registro de
uma nova compra. Neste capítulo, vamos apreender a utilizar os
comandos DML, responsáveis por todas estas tarefas, que se
resumem em quatro operações básicas: gravar, alterar, listar e excluir
informações; por isso, ao desenvolver um sistema, pensamos como
início implantar este controle em todas as informações. É uma
prática tão primordial, que deram um nome para ela: CRUD.
1 Conceitos de CRUD (Create, Read,
Update, Delete) para SQL
Quando uma pessoa se prepara para ser um profissional na área
de desenvolvimento de sistemas, um dos seus principais objetivos
para começar a entender como a programação funciona é fazer um
sistema que realize um CRUD no banco de dados.
O termo CRUD é o acrônimo de Create, Read, Update e Delete –
palavras em inglês que representam as quatro operações básicas
para os bancos de dados relacionais, que são: Inserir, Ler, Atualizar e
Apagar informações.
Mas antes de aprendermos mais sobre estes comandos, vamos
entender primeiro como as tabelas são criadas.
Oliveira (2002) diz que a primeira coisa que devemos fazer, assim
que o modelo físico foi definido, é implementá-lo, usando comandos
DDLs (data definition language).
Toda a organização de dados em um modelo relacional é
realizada através de tabelas – elas são a parte mais importante de
um banco de dados, pois possibilitam que as informações sejam
armazenadas em entidades que representam os objetos do mundo
real, definindo todos os atributos destes objetos, que são pertinentes
ao modelo de negócio, e que tipo de dado é mais apropriado para
armazenar o valor destes atributos.
Silberschatz, Korth e Sudarshan (2012) citam o create table
como comando para criação das tabelas de um banco de dados.
Nele, definimos o nome que será atribuído à tabela, suas colunas que
representam os atributos, os tipos de dados que os atributos vão
receber, assim como os constraints, que são as regras que serão
impostas à tabela. Segundo Oliveira (2002, p. 75), constrains:
são regras agregadas a colunas ou tabelas. Assim, pode-se definir
como obrigatório o preenchimento de uma coluna que tenha um
valor-padrão quando uma linha for incluída na tabela ou quando
aceitar apenas alguns valores predefinidos. No caso de regras
aplicadas a tabelas, tem-se a definição de chaves primárias e
estrangeiras.
Para exemplificar, vamos imaginar que queremos criar uma
tabela em nosso banco de dados que contenha os dados de pessoas
físicas, clientes de um suposto comércio.
Quadro 1 – Exemplo de tabela pessoa física
PESSOA_FISICA
NUM_PESSOA_F NOM_PESSOA NUM_CPF DAT_NASCIMENTO SEX_PESSOA
001 José de Souza 152.321.987-10 12/12/1980 M
Após definirmos o nome e os atributos que teremos na tabela,
precisamos identificar quais são os tipos de valores que devemos
utilizar para guardar os dados de cada atributo.
num_pessoa_f: este primeiro campo será um número de
controle, que será atribuído para cada pessoa cadastrada. Mais
adiante, entenderemos por que este campo é importante. Como
é um número, e pretendemos ter de 1 a 99.999 pessoas
cadastradas, vamos definir este tipo de dado como: NUMBER(5).
nom_pessoa: este campo é para armazenar o nome da pessoa.
Como os nomes são formados por letras e acentos, que são
caracteres especiais e podem ser tanto curtos como compridos,
vamos definir este tipo de dado como: VARCHAR2(50).
num_CPF: este campo vamos usar para armazenar o número do
CPF – como eles podem conter até 11 dígitos, vamos definir este
tipo de dado como: NUMBER(11). É sempre uma boa prática
utilizarmos este tipo de formatação para números de
documentos, pois assim não corremos o risco da informação ser
inserida de formas diferentes, como por exemplo um CPF com
pontuação e outro só com os números. Isto é muito importante
para mantermos a unidade dos dados.
dat_nascimento: este campo vai armazenar a data de
nascimento da pessoa cadastrada. No ORACLE, temos um tipo
específico para armazenar datas e horários; assim, para este
campo, vamos definir o tipo de dado como: DATE.
sex_pessoa: neste último campo, vamos armazenar o sexo da
pessoa, normalmente para evitarmos a possibilidade do usuário
que estiver manipulando o banco através do sistema, ou até
mesmo via instrução direta, escrever a mesma informação de
formas diferentes, como: Masculino, Masc., M, etc. Vamos
delimitar o campo para um caractere apenas, ficando este tipo
de dado como: CHAR(1).
Como temos agora todas as informações necessárias, só
precisamos definir qual será a chave primária da nossa tabela – a
informação que será única e nos permitirá identificar um registro em
meio a todos os outros. Lembra que falamos que o campo
num_pessoa era muito importante e veríamos o porquê logo adiante?
Pois ele será a nossa chave primária e vamos indicar isto através de
uma constraint em nosso comando.
Vamos ver como deverá ficar o nosso comando create table
para criar essa tabela e todos os seus detalhes:
CREATE TABLE PESSOA_FISICA (
num_pessoa_f NUMBER(5), nom_pessoa
VARCHAR(50), num_CPF NUMBER(11),
dat_nascimento DATE, sex_pessoa CHAR(1),
PRIMARY KEY (num_pessoa_f) );
É muito importante nos atentarmos a esta sintaxe para montar o
comando – a única coisa que não é obrigatória é a quebra de linha
que foi dada. Só está assim para facilitar a leitura do comando; se
desejar, pode digitar tudo em apenas uma linha.
Agora que entendemos como uma tabela é criada, podemos
voltar ao estudo do CRUD. Segundo a Oracle, o intuito de uma
aplicação que realiza o CRUD no banco de dados é permitir que o
usuário execute todo o conjunto de operações para manipular esses
dados, incluindo inserir, atualizar, listar e excluir informações.
O quadro 2 relaciona os comandos SQL a este termo:
Quadro 2 – Comandos do termo CRUD
C Create INSERT – Insere informações em linhas ou registros da tabela
R Read SELECT – Consulta ou busca uma ou mais informações no banco
U Update UPDATE – Atualiza uma ou mais informações no banco
D Delete DELETE – Apaga uma ou mais informações no banco
Você reparou que todos os comandos citados acima fazem
parte da divisão de comandos do SQL chamados DML (data
manipulation language)?
A função da divisão DML na linguagem SQL é garantir que os
dados sejam armazenados, localizados, alterados ou excluídos,
sempre que necessário. Esta é a razão desses comandos serem
chamados de comandos de manipulação de banco de dados.
1.1 CREATE – Comando INSERT
Quando precisamos usar as tabelas do nosso banco de dados,
devemos utilizar o comando INSERT – com ele, podemos inserir uma
ou mais informações.
Segundo Elmasri e Navathe (2011), em uma forma mais simples,
INSERT é usado para acrescentar uma única linha a uma tabela, mas
podemos utilizá-lo para trabalhos mais complexos, conforme a
necessidade.
Utilizando a tabela criada no quadro 1, vamos inserir um novo
registro, ou seja, vamos criar novas informações utilizando o
comando INSERT.
Quadro 3 – Inserindo um novo registro na tabela pessoa física
PESSOA_FISICA
NUM_PESSOA_F NOM_PESSOA NUM_CPF DAT_NASCIMENTO SEX_PESSOA
001 José de Souza 152.321.987-10 12/12/1980 M
002 Maria da Silva 254.456.987-85 25/06/1984 F
Para utilizarmos o comando INSERT, Elmasri e Navathe (2011)
explicam que temos de especificar o nome da tabela, os campos e os
valores que serão inseridos. Vejamos como ficará o nosso comando:
INSERT INTO PESSOA_FISICA (
Num_pessoa_f, nom_pessoa, num_cpf, dat_nascimento,
sex_pessoa ) VALUES (
002, ‘Maria da Silva’, 25445698785,
TO_DATE(‘25/06/1984’, ‘DD/MM/YYYY’), ‘F’
);
Repare que, na execução do comando INSERT, temos alguns
cuidados especiais quanto ao preenchimento dos dados que estão
sendo inseridos no banco de dados, por exemplo:
Caracteres: sempre que inserirmos caracteres,como fizemos
nos campos de nome e sexo, devemos envolvê-los por aspas
simples, assim o sistema pode compreender com exatidão o seu
início e fim.
Data: o tipo de dados DATE pode receber datas e horas; assim,
devemos especificar com detalhes quando estivermos inserindo.
Devemos começar por TO_DATE e, entre parênteses, colocar o
valor da data entre aspas simples e, depois de uma virgula, o
formato que esta data deve assumir.
Para agilizar o processo e deixar mais curta a instrução,
podemos executar o mesmo comando sem ter que informar os
nomes dos campos. Mas, para isso, devemos obedecer fielmente a
sequência de campos, conforme foram criados com o comando
create table. Vamos ver como ficaria o comando:
INSERT INTO PESSOA_FISICA VALUES (
002, ‘Maria da Silva’, 25445698785,
TO_DATE(‘25/06/1984’, ‘DD/MM/YYYY’), ‘F’
);
Oliveira (2002) nos lembra que, se por algum motivo, não
tivermos o valor de um ou mais campos no momento da inserção,
devemos colocar a expressão NULL no local onde seria inserido o
valor. Só que mesmo que a palavra NULL seja um conjunto de
caracteres, por ser uma instrução, ela não deve ser envolvida entre
aspas.
1.2 READ – Comando SELECT
Uma das principais vantagens da utilização de bancos de dados
para o armazenamento de informações é a possibilidade de
localizarmos uma ou mais informações de maneira fácil e rápida,
independentemente da quantidade de informações que temos
armazenadas.
Silberschatz, Korth e Sudarshan (2012) reforçam, dizendo que o
processamento da consulta se refere ao conjunto de atividades
envolvidas na extração de dados de um banco de dados.
Veja a seguir sua estrutura básica:
SELECT [DISTINCT | ALL] { * | coluna, coluna, ....}
FROM tabela WHERE condição ORDER BY coluna, coluna, ...
Onde:
SELECT: especifica as colunas (campos) desejadas na pesquisa;
DISTINCT: não mostra eventuais valores repetidos de colunas;
ALL: mostra todos os valores, mesmo que repetidos. Esse é o
padrão se o DISTINCT não for definido; portanto, não precisamos
escrevê-lo;
FROM: determina em que tabelas serão efetuadas as pesquisas;
WHERE: condição para que se execute a pesquisa (filtra dados);
ORDER BY: especifica em que ordem deverá ser apresentada a
pesquisa desejada – por qual campo está ordenada (de forma
crescente ou decrescente).
Vamos ver alguns exemplos baseados na nossa tabela pessoa
física:
1. Suponhamos que queremos todas as informações da tabela:
SELECT * FROM PESSOA_FISICA;
2. Queremos agora somente o valor de dois campos (nome e data
de nascimento): SELECT NOM_PESSOA, DAT_NASCIMENTO
FROM PESSOA_FISICA;
3. E se quiséssemos receber primeiro a data de nascimento,
despois o nome: SELECT NOM_PESSOA, DAT_NASCIMENTO
FROM PESSOA_FISICA ORDER BY DAT_NASCIMENTO,
NOM_PESSOA;
4. Agora, se quiséssemos apenas os homens da lista:
SELECT * FROM PESSOA_FISICA WHERE SEX_PESSOA = ‘M’.
Podemos perceber que, com as opções de instruções que temos
no comando SELECT, conseguimos personalizar o resultado de
nossas pesquisas, nos proporcionando uma infinidade de opções.
1.3 UPDATE – Comando UPDATE
Utilizamos o comando UPDATE para alterar ou atualizar
informações no banco de dados. Elmasri e Navathe (2011) definem
que ele é usado para modificar valores de atributos de uma ou mais
linhas selecionadas na tabela. Neste comando, a cláusula WHERE
também será muito importante para definirmos quais dados serão
atualizados.
Vejamos a sua estrutura:
UPDATE <nome da tabela> SET <nome da coluna> = <novo
conteúdo para o campo>, <novo conteúdo para o campo>,
<nome da coluna> = <novo conteúdo para o campo>, ...
WHERE <condição>;
Vamos fazer um exemplo para entender melhor. Suponha que eu
queira mudar o nome que está no nosso primeiro registro, de José de
Souza para João de Souza. A instrução ficaria assim:
UPDATE PESSOA_FISICA SET NOM_PESSOA = ‘João de
Souza’
WHERE NUM_PESSOA_F = 001;
Repare que com o SET informamos o campo e o novo valor para
ele e, com a cláusula WHERE, definimos que esta alteração deveria
ser efetuada no registro número 001.
1.4 DELETE – Comando DELETE
A função do comando DELETE é eliminar linhas não desejadas
da minha tabela; por isso, é muito importante sempre usarmos junto
a cláusula WHERE, informando a condição, pois senão podemos
excluir todas as informações de nossa tabela.
 IMPORTANTE
Se você especificar na cláusula WHERE a chave primária de uma
tabela, somente uma linha da tabela será excluída. Se for outra
condição, várias linhas poderão ser excluídas. Portanto, tome
cuidado com a condição que definirá esse limite. Caso não seja
especificada e cláusula WHERE, todas as linhas da tabela serão
excluídas (OLIVEIRA 2002, p. 95).
Vamos ver como fica sua estrutura:
DELETE FRON <nome-tabela> WHERE <condição>
Vamos supor que Maria da Silva não é mais cliente da loja, e
vamos utilizar o comando DELETE para excluir o seu cadastro:
DELETE FROM PESSOA_FISICA WHERE NUM_PESSOA_F =
1;
Repare que usamos a chave primária para definir a condição de
qual registro deveria ser excluído.
Considerações finais
Com o crescimento do número de dados disponíveis no
mercado, seja dentro da própria empresa ou informações externas
importantes para tomada de decisão, cada vez mais se torna
relevante a elaboração precisa e funcional da estrutura de
armazenamento de dados nos bancos de dados.
O estudo para aperfeiçoamento e as novas tecnologias que vêm
surgindo para este fim tendem a decidir o sucesso das empresas em
relação à disputa de mercado com suas concorrentes.
As tecnologias para armazenamento e mineração de dados, hoje,
estão entre as disciplinas mais importantes na área de TI.
Referências
ELMASRI, R.; NAVATHE, S. Sistemas de banco de dados. 6. ed. São
Paulo: Editora Pearson Addison-Wesley, 2011.
OLIVEIRA, C. H. P. de. SQL: curso prático. São Paulo: Editora Novatec,
2002.
SILBERSCHATZ, A.; KORTH, H. F; SUDARSHAN, S. Sistema de banco
de dados. 6. ed. Rio de Janeiro: Elsevier, 2012.
VASILIEV, Yuli. Building Oracle JET CRUD Applications Interacting with
an Oracle Database. Oracle. [s. d.]. Disponível em:
<https://developer.oracle.com/databases/building-jet-crud-apps-
odb12c>. Acesso em: 3 fev. 2019.
https://developer.oracle.com/databases/building-jet-crud-apps-odb12c
Sobre os autores
Allen Oberleitner possui mestrado em Engenharia de
Informação pela Universidade Federal do ABC (UFABC). Possui pós-
graduação (especialização) em Gestão Financeira e graduação em
Ciência da Computação, ambos pela Universidade Municipal de São
Caetano do Sul (USCS). Atua como docente na Faculdade de
Informática e Administração Paulista (Fiap) desde 2014 e, a partir de
2019, assumiu a coordenação do curso de Tecnologia em Análise e
Desenvolvimento de Sistemas presencial da IES, onde atua em
regime integral desde 2016. Atuou em outras instituições, como a
Anhanguera Educacional, onde foi docente de 2012 até 2016.
Coordenou, nessa mesma IES, os cursos de Tecnologia em Análise e
Desenvolvimento de Sistemas e Sistemas de Informação, de 2014 a
2016. Também atuou como docente na Universidade Nove de Julho
(Uninove) de 2013 a 2015, nos cursos técnicos do Pronatec. Exerceu
cargo de operação em Produção e TI na empresa Air Liquide de 1998
a 2005, desenvolvendo atividades como programação e automação.
Possui um livro lançado em 2015 sobre aprendizagem e tecnologias.
Luís Carlos S. Silva é formado em Análise e Desenvolvimento de
Sistemas e possui MBA em Desenvolvimento de Aplicações e Games
para Dispositivos Móveis e Internet das Coisas, ambos pela
Faculdade de Informática e Administração Paulista (Fiap). Atua na
área de informática desde 1995 e em diversas instituições de ensino,
lecionan do disciplinas de análise e programação e coordenando
cursos da área. Atualmente, desempenha funções de gestão
acadêmica e ministra dis ciplinas de graduação e pós-graduação nas
áreas de análise, gestão de segurança da informação e
desenvolvimento web, mobile e de games em instituições como Fiap-
SP e Unyleya-DF.
Administração Regional do Senac no Estado de São Paulo
Presidente do ConselhoRegional
Abram Szajman
Diretor do Departamento Regional
Luiz Francisco de A. Salgado
Superintendente Universitário e de Desenvolvimento
Luiz Carlos Dourado
Editora Senac São Paulo
Conselho Editorial
Luiz Francisco de A. Salgado Luiz Carlos Dourado Darcio Sayad Maia Lucila
Mara Sbrana Sciotti Jeane Passos de Souza
Gerente/Publisher
Jeane Passos de Souza
Coordenação Editorial/Prospecção
Luís Américo Tousi Botelho Márcia Cavalheiro Rodrigues de Almeida
Administrativo
João Almeida Santos
Comercial
Marcos Telmo da Costa
Designer Educacional
Jussara Cristina Cubbo
Revisão Técnica
Lenilson Lemos Vila Boas
Coordenação de Preparação e Revisão de Texto
Luiza Elena Luchini
Preparação de Texto
Asa Comunicação e Design
Revisão de Texto
Asa Comunicação e Design
Projeto Gráfico
Alexandre Lemes da Silva Emília Correa Abreu
Capa
Antonio Carlos De Angelis
Editoração Eletrônica
Michel Iuiti Navarro Moreno
Ilustrações
Michel Iuiti Navarro Moreno
Imagens
iStock Photos
Produção do ePub
Ricardo Diana Rodolfo Santana 
Proibida a reprodução sem autorização expressa.
Todos os direitos desta edição reservados à Editora Senac São Paulo Rua 24 de
Maio, 208 – 3º andar Centro – CEP 01041-000 – São Paulo – SP
Caixa Postal 1120 – CEP 01032-970 – São Paulo – SP
Tel. (11) 2187-4450 – Fax (11) 2187-4486
E-mail: editora@sp.senac.br
mailto:editora@sp.senac.br
http://www.editorasenacsp.com.br/
Home page: http://www.editorasenacsp.com.br
© Editora Senac São Paulo, 2018
http://www.editorasenacsp.com.br/
Dados Internacionais de Catalogação na Publicação
(CIP)
(Jeane Passos de Souza - CRB 8ª/6189)
Oberleitner, Allen
Desenvolvimento de sistemas / Allen Oberleitner,
Luís Carlos S. Silva. – São Paulo: Editora Senac São Paulo,
2020. (Série Universitária) Bibliografia.
e-ISBN 978-85-396-2809-4 (ePub/2020)
e-ISBN 978-85-396-2810-0 (PDF/2020)
1. Desenvolvimento de sistemas 2. Linguagem de
programação 3. Algoritmos – Conceitos 4. Programação
orientada a objetos 5. Banco de dados (Ciência da
computação) I. Silva, Luís Carlos S. II. Título. III. Série
19-950t CDD – 003
005.13
005.74
BISAC COM051000
COM051010
COM051300
COM051210
Índice para catálogo sistemático
1. Desenvolvimento de
sistemas 003
2. Linguagem de programação 005.13
3. Banco de dados (Ciência da computação) 005.74
MODAGASTRONOMIATURISM
ODESIGNTECNOLOGIAEDUCAÇ
ÃOARTESHOTELARIACIÊNCIA
SHUMANASFOTOGRAFIACOM
UNICAÇÃOARQUITETURAGEST
ÃOMEIOAMBIENTESAÚDE
 
http://www.livrariasenac.com.br/
https://pt-br.facebook.com/editorasenacsp/
https://twitter.com/editorasenacsp
https://www.instagram.com/editorasenacsp/
	Capítulo 1 Apresentação inicial sobre desenvolvimento de sistemas
	1 Evolução do desenvolvimento de sistemas
	2 Utilização dos conceitos na prática
	Considerações finais
	Referências
	Capítulo 2 Introdução a algoritmos
	1 Introdução a algoritmos
	2 Conceitos de algoritmos
	3 Descrição narrativa de um algoritmo
	4 Representação de algoritmos por fluxograma
	Considerações finais
	Referências
	Capítulo 3 Algoritmos variáveis
	1 Programação imperativa
	2 Utilização de pseudocódigo
	3 Declaração de variáveis e constantes
	4 Expressões aritméticas, literais, relacionais e de lógica booleana
	Considerações finais
	Referências
	Capítulo 4 Algoritmos: condicional
	1 A arte de tomar decisões
	2 Estrutura de controle condicional simples
	3 Estrutura de controle condicional composta
	Considerações finais
	Referências
	Capítulo 5 Algoritmos: repetição
	1 Repetir para aprender
	2 Enquanto-faça (while)
	Considerações finais
	Referências
	Capítulo 6 Algoritmos: vetores
	1 Teoria dos conjuntos
	2 Conceito de vetores
	3 Manipulando vetores
	Considerações finais
	Referências
	Capítulo 7 Algoritmos: matrizes
	1 Matriz é tabela?
	2 Conceito de matriz
	3 Manipulando matriz
	Considerações finais
	Referências
	Capítulo 8 Programação estruturada
	1 Linguagem de programação
	2 Linearidade
	3 Programação estruturada
	Considerações finais
	Referências
	Capítulo 9 Programação: funções e procedimentos
	1 Conceitos de função
	2 Procedimento
	3 Aplicando funções
	Considerações finais
	Referências
	Capítulo 10 Programação: arquivo
	1 Processo arquivado!
	2 Conceitos de arquivo
	3 Manipulando arquivo
	Considerações finais
	Referências
	Capítulo 11 Programação orientada a objetos
	1 Conceito de POO
	2 Classes e objetos
	3 Aplicação de POO
	Considerações finais
	Referências
	Capítulo 12 Programação orientada a objetos: classes
	1 Composição da classe
	2 Instâncias
	Considerações finais
	Referências
	Capítulo 13 Programação orientada a objetos: Python
	1 Linguagem orientada a objetos
	2 Conceitos de Python
	3 Aplicação de POO: Python
	Considerações finais
	Referências
	Capítulo 14 Banco de dados
	1 Armazenamento de dados
	2 Modelos de banco de dados
	3 Conceito de banco de dados
	4 Instâncias ou ocorrências de uma entidade
	Considerações finais
	Referências
	Capítulo 15 Linguagem SQL
	1 Utilização de SQL nas aplicações
	Considerações finais
	Referências
	Capítulo 16 Atualização de tabelas em aplicações
	1 Conceitos de CRUD (Create, Read, Update, Delete) para SQL
	Considerações finais
	Referências
	Sobre os autores

Mais conteúdos dessa disciplina