Logo Passei Direto
Buscar
Material
páginas com resultados encontrados.
páginas com resultados encontrados.
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

DEFINIÇÃO
Apresentação da metodologia de desenvolvimento rápido de software (RAD) e sua aplicação prática com o uso da linguagem de programação Python e frameworks para a aceleração do desenvolvimento.
PROPÓSITO
Compreender os conceitos, as fases e vantagens e desvantagens da RAD e apresentar a linguagem de programação Python e frameworks para RAD.
INTRODUÇÃO
O desenvolvimento de software tem como objetivo atender as demandas da sociedade, cada vez mais complexas e com abrangência em diversas áreas. Logo nos primórdios da indústria de software, aplicavam-se metodologias que seguiam etapas que não eram revistas e, no final dos projetos, muitas vezes, desenvolvedores e clientes ficavam frustrados com o resultado obtido. Nesse sentido, a necessidade de criar formas mais eficazes de desenvolver sistemas levou à criação da metodologia rápida de desenvolvimento de software, mais conhecida pela sigla em inglês: RAD (Rapid Application Development). Baseia-se na entrega de protótipos para os clientes, a fim de que possam ter uma noção mais clara do progresso do desenvolvimento do software e que também possam colaborar com comentários que permitam aos desenvolvedores fazer alterações para atender as expectativas do cliente.
MÓDULO 1
Descrever a contextualização, os conceitos,
princípios, as ferramentas e técnicas da metodologia
de desenvolvimento rápido de software (RAD)
CONTEXTUALIZAÇÃO
O desenvolvimento rápido de aplicações RAD (Rapid Application Development) é uma metodologia de desenvolvimento de software com foco na entrega em um período muito inferior ao do ciclo de desenvolvimento tradicional de software. Não se trata de uma entrega final, mas, sim, de um protótipo do software. Para que isso seja possível, é feito um planejamento mínimo para obter um protótipo rápido.
Na metodologia RAD, existe uma concentração no desenvolvimento dos principais módulos funcionais do sistema. Essa versão inicial, que, apesar de limitada, já é funcional, é chamada de protótipo.
PROTÓTIPO DO SOFTWARE
Um protótipo de software é um modelo funcional que equivale funcionalmente a um componente do produto. Ou seja, simula apenas alguns aspectos do produto e é útil para o entendimento e a evolução do sistema final.
Na metodologia RAD, existe uma concentração no desenvolvimento dos principais módulos funcionais do sistema. Essa versão inicial, que, apesar de limitada, já é funcional, é chamada de protótipo.
PROTÓTIPO
É muito útil para a compreensão do sistema.
Serve de demonstração para os clientes.
É mais flexível para mudanças.
Quando está mais evoluído, pode ser integrado ao produto completo para uma entrega mais rápida da versão final.
A RAD também pode ser aplicada para aperfeiçoar o treinamento prático de estudantes de computação, auxiliando-os em seus futuros empregos. Isso porque os estudantes podem aplicar o conhecimento adquirido nas aulas para desenvolver sistemas em etapas, conforme é proposto pela RAD. Como será mostrado mais adiante, o fator humano é um importante requisito para a aplicação dessa metodologia, então a sua aplicação para treinar recursos humanos pode acelerar a curva de aprendizado dentro de um curto período.
Os projetos RAD seguem o modelo iterativo e incremental. As equipes de desenvolvimento são pequenas, compostas por desenvolvedores, analistas de negócio e representantes de clientes. Um dos aspectos mais importantes deste modelo é garantir que os protótipos desenvolvidos sejam reutilizáveis para o projeto do sistema, ou seja, a ideia não é criar unidades descartáveis. Isso não contradiz o fato de o protótipo ser flexível.
MODELO ITERATIVO E INCREMENTAL
O desenvolvimento iterativo promove progressos sucessivos, em que o produto é refinado por etapas. No modelo incremental, o software é entregue em pedaços, que são chamados de incrementos. A ideia é que o software seja criado em ciclos curtos, com introdução de funcionalidades, coleta de feedback e revisão.
O RAD FOCA NO DESENVOLVIMENTO RÁPIDO POR MEIO DE ITERAÇÕES FREQUENTES E FEEDBACK CONTÍNUO.
VOCÊ SABIA
O modelo RAD foi introduzido pelo consultor de tecnologia e autor James Martin em 1991 (MARTIN, 1991). Surgiu como o reconhecimento da necessidade de atender o competitivo mercado de software, que tem uma demanda contínua por novas aplicações. Uma característica que foi explorada para a formalização da RAD foi a flexibilidade do desenvolvimento de software para projetar modelos de desenvolvimento. Trata-se de uma combinação de sessões JAD, desenvolvimento de protótipos, equipes SWAT, entregas com prazo de entrega e ferramentas CASE.
RAD
É muito prática em diversos ambientes modernos de desenvolvimento.
Apresenta uma abordagem útil para criar aplicações de comércio eletrônico e aplicativos de dispositivos móveis.
Possui uma velocidade de entrega que pode determinar o posicionamento de uma empresa em um ambiente de mercado muito competitivo.
Portanto, trata-se de uma metodologia importante a ser empregada para que as empresas lancem suas aplicações antes de seus concorrentes.
OBSERVE NO FLUXO COMO INICIAR UM PROJETO RAD:
 
UMA DAS FORMAS DE INICIAR O PROJETO RAD É ATRAVÉS DA APLICAÇÃO DA METODOLOGIA JOINT APPLICATION DEVELOPMENT (JAD). 
TRATA-SE DE UMA METODOLOGIA NA QUAL USUÁRIOS E ANALISTAS PROJETAM O SISTEMA JUNTOS, SOB UMA LIDERANÇA EM OFICINAS DE TRABALHO. 
A IDEIA É POTENCIALIZAR O RESULTADO DO DESENVOLVIMENTO ATRAVÉS DE DINÂMICAS DE GRUPO. 
OU SEJA, DEFINIR OS OBJETIVOS E AS APLICAÇÕES DO SISTEMA, DESDE A GERAÇÃO DE TELAS ATÉ A GERAÇÃO DE RELATÓRIOS.
TEM COMO PRINCÍPIOS: DINÂMICA DE GRUPO; RECURSOS AUDIOVISUAIS; PROCESSO ORGANIZADO E RACIONAL; A ESCOLHA DO LOCAL; DOCUMENTAÇÃO COM A ABORDAGEM WYSIWIG – “O QUE VOCÊ VÊ É O QUE VOCÊ OBTÉM”.
A RAD foi a precursora do gerenciamento ágil de projetos. As características de prototipagem rápida e ciclos de liberação e iterações mais curtos fortaleceram o posicionamento da RAD como um método eficaz no desenvolvimento de software, tornando-se cada vez mais popular entre as empresas ágeis que procuram métodos que acompanhem o crescimento de suas necessidades comerciais e de clientes. Trata-se de uma metodologia orientada pelo feedback do usuário, e não por um planejamento detalhado e caro.
Os métodos tradicionais de desenvolvimento de software, como, por exemplo, a metodologia de desenvolvimento cascata, seguem modelos rígidos de processo. Isso significa que, nesses modelos tradicionais, os clientes são pressionados a estabelecer os requisitos antes do início do projeto. A iteração ao longo do projeto é baixa, o que complica o processo de mudança para novos requisitos e ajustes de viabilidade.
CONCEITOS
Trata-se de uma abordagem interativa com o objetivo de produzir o desenvolvimento de software de alta qualidade. O resultado da aplicação da RAD é um software com menor custo, menos erros e menor tempo de desenvolvimento.
A RAD PODE SER CONSIDERADA UM TIPO DE TÉCNICA ÁGIL. (NAZ & KHAN, 2015).
A metodologia RAD combina diversas técnicas para acelerar o desenvolvimento de aplicações de software. Outra forma pela qual a RAD é conhecida é como “Construção Rápida de Aplicações”, do inglês Rapid Application Building (RAB). Um dos principais elementos da RAD é o desenvolvimento de protótipos para chegar ao sistema final. Trata-se de um modelo adaptativo, uma vez que o desenvolvimento é feito em iterações em que mudanças podem ser realizadas a partir dos comentários do usuário. A ênfase está na criação rápida de um protótipo, em vez de um planejamento detalhado.
A METODOLOGIA RAD POSSUI QUATRO ELEMENTOS FUNDAMENTAIS:
USO DE FERRAMENTAS PARA DAR SUPORTE AO DESENVOLVIMENTO
O uso de ferramentas CASE facilita a automação no desenvolvimento de sistemas. Isso é obtido através de recursos como geração de código e verificação automática de erros de consistência. As ferramentas CASE, portanto, são usadas para gerar protótipos, dando, assim, suporte ao desenvolvimento iterativo, possibilitando que os usuários finais acompanhem a evolução do sistema à medida que ele está sendo construído.
METODOLOGIA BEM DEFINIDAÉ seguido um processo formal de desenvolvimento com atividades em etapas e entregas intermediárias. As tarefas são organizadas de modo a não negligenciar nenhum dos aspectos pré-acordados, e as técnicas são documentadas para garantir que uma tarefa seja executada da maneira correta.
PESSOAS
Deve haver treinamento das pessoas tanto na metodologia de trabalho como no uso das ferramentas. As tarefas devem ser distribuídas por pequenas equipes, que devem trabalhar bem juntas.
GESTÃO
O gerenciamento do projeto deve ser feito com rapidez. Isso é obtido através de oficinas de Planejamento de Requisitos e Design de Sistema para extrair rapidamente os requisitos dos usuários. Além disso, deve ser feita alocação de tempo fixo (Timebox) para entregar iterativamente o sistema para os usuários.
TIMEBOX
Timebox é o tempo máximo estabelecido para atingir as metas, tomar uma decisão ou executar um conjunto de tarefas
ALÉM DISSO, EXISTEM DOIS TIPOS DE PROJETOS RAD:
INTENSIVO / FASEADO
Como visto até aqui, está claro que a criação rápida de protótipo é a base da RAD. Nas situações em que os projetos são orientados por requisitos de interface do usuário, o desenvolvimento de protótipo é uma escolha muito adequada, pois é normal que o usuário crie a ideia de como a interface do sistema deve ficar ao longo do desenvolvimento do projeto. O desenvolvimento rápido de protótipos tem como pré-requisito o uso de ferramentas com suporte a componentes gráficos. No mercado, desde a década de 1990, existiam diversas ferramentas para esse fim, em que os programadores simplesmente podem selecionar um componente gráfico e arrastá-lo para um formulário. Desse modo, as interações com os usuários finais são mais produtivas, pois, constantemente, recebem um software operacional.
PRINCÍPIOS
Constantemente, os programadores são pressionados a entregar as aplicações em prazos curtos e, muitas vezes, sabe-se com antecedência que o projeto terá de passar por modificações ao longo do desenvolvimento. Essas situações são exemplos em que o desenvolvimento rápido é bastante útil, pois ele está embasado exatamente na entrega rápida de protótipos que incorporam os comentários e as solicitações dos usuários a cada entrega. Para ser eficaz, no entanto, a RAD tem alguns requisitos que não são triviais. Alguns requisitos relacionados aos recursos humanos são os seguintes:
Equipe de desenvolvedores qualificada e motivada.
Usuários comprometidos com a participação ativa ao longo do projeto.
Comprometimento para atingir o resultado satisfatório. 
O desenvolvimento baseado na entrega de protótipos funcionais busca dar a oportunidade para que o usuário possa interagir com o projeto antes de receber o sistema final. Dessa forma, poderá fazer comentários e solicitações que guiarão os desenvolvedores na confecção do produto que atenda às suas expectativas sob o ponto de vista de funcionalidades, recursos, interatividade do sistema (experiência do usuário), relatórios, gráficos, entre outros.
O RAD É BASEADO EM ALGUNS PRINCÍPIOS BÁSICOS, QUE SÃO (FITZGERALD, 1998):
ENVOLVIMENTO ATIVO DOS USUÁRIOS
A metodologia RAD reconhece que o envolvimento do usuário é necessário para reduzir problemas caros de obtenção de requisitos. Além disso, os usuários podem rejeitar completamente os sistemas, se não estiverem suficientemente envolvidos no desenvolvimento. No centro da abordagem da RAD, estão as oficinas de design de aplicativos conjuntos (JAD) e planejamento de requisitos conjuntos.
EQUIPES PEQUENAS COM PODER DE DECISÃO
As vantagens da elaboração de equipes pequenas estão na redução de ruídos de comunicação e na minimização de atrasos devido à burocracia que a hierarquia de uma metodologia tradicional impõe. Em relação aos ruídos de comunicação, os canais que tratam dessa área aumentam proporcionalmente ao tamanho da equipe, portanto equipes pequenas evitam a distorção e o conflito na comunicação. A respeito da redução do tempo, empoderar a equipe aumenta as chances de cumprir os prazos por causa da responsabilidade de tomada de decisão. As equipes têm o poder de tomar decisões sobre o design (embora as mudanças sejam reversíveis).
ENTREGA FREQUENTE DE PRODUTOS
Diferentemente das metodologias de desenvolvimento tradicionais, em que os projetos podem levar muito tempo para serem concluídos, a RAD procura reduzir o tempo de desenvolvimento. Portanto, prazos mais curtos para o desenvolvimento são uma característica importante. Em vez de se concentrar no processo, a RAD tem como premissa a entrega de produtos que satisfazem os requisitos funcionais.
DESENVOLVIMENTO INCREMENTAL E ITERATIVO
Outro princípio fundamental do RAD é que os sistemas evoluem de forma incremental em cada iteração. A cada nova iteração, surgem novos requisitos que são incorporados ao sistema. Desse modo, os sistemas evoluem através da prototipagem iterativa. Existe um entendimento no RAD que a especificação de requisitos é um processo não determinístico e que evolui à medida que desenvolvedores e usuários interagem com o protótipo do sistema.
ABORDAGEM TOP-DOWN
Uma vez que, na metodologia RAD, os requisitos não precisam ser completamente definidos logo no início do projeto, eles são especificados em um nível apropriado ao conhecimento disponível no momento. Estes são então elaborados através de prototipagem incremental. Os sistemas são elaborados e confeccionados à medida que o conhecimento cresce. Além disso, como se trata de uma abordagem de “cima para baixo” caracterizada por um curto período, todas as decisões são consideradas reversíveis rapidamente.
UTILIZAÇÃO DE FERRAMENTAS DE AUTOMAÇÃO (CASE)
Trata-se de usar programas que facilitem a automação de processos, criação de diagramas, realização de testes e quaisquer tarefas que facilitem as entregas dentro dos prazos pré-estabelecidos e, obviamente, com qualidade. Além disso, essas ferramentas facilitam a reutilização de componentes que podem ser usados ao longo do projeto.
O ponto fundamental na metodologia RAD é que se trata de uma abordagem colaborativa entre todas as partes interessadas, que são: patrocinadores, desenvolvedores e usuários ao longo da vida de um projeto.
FERRAMENTAS E TÉCNICAS
A RAD precisa ser suportada por ferramentas que auxiliem no desenvolvimento das aplicações rapidamente. Entre as categorias de ferramentas que dão suporte à RAD para desenvolver projetos de software estão:
Integração de dados
Ambientes de desenvolvimento
Ferramentas de coleta de requisitos
Ferramentas de modelagem de dados
Ferramentas de geração de código
Desde que a RAD foi formalizada, foram desenvolvidas muitas técnicas para a sua utilização. Cada uma das técnicas tem suas particularidades, mas mantém a essência da RAD. No quadro a seguir, conheça algumas dessas técnicas (Naz; Khan, 2015):
	TÉCNICA
	PARTICULARIDADE
	Modelo CBD
	O método que descreve como componentes antigos podem ser reutilizados com os novos.
	RepoGuard
	É um framework para integração de ferramentas de desenvolvimento com repositórios de código-fonte.
	Adição dinâmica ágil
	Técnicas usadas para integração do ágil para tornar o projeto mais adaptável.
	Método baseado em camadas para desenvolvimento rápido de software
	Baseado em camadas que segue o XP.
	Análise de projeto de sistema baseado em simulação
	Desenvolvimento de ferramentas ágeis baseadas em simulação.
	Uso de Ajax no RAD
	Prototipagem rápida em aplicativos e ferramentas da Web.
	Desenvolvimento de aplicativos multiusuário em ambiente distribuído rapidamente.
	Middleware de comunicação.
	Programação extrema
	Adição de reutilização ao XP.
XP
Extreme Programming (XP) consiste em uma metodologia de desenvolvimento de software que tem como objetivo maximizar a qualidade do software e responder mais rapidamente às mudanças nos requisitos do cliente
A ideia do uso das técnicas de RAD é de otimizar os resultados obtidos dentro do tempo estimado, que, pela natureza da RAD, é curto. Essencialmente, um software é construído para atender a alguma demanda, ou seja, existe uma razão para que seja confeccionado. Portanto,a interação com os usuários auxilia o entendimento dos desenvolvedores para construir, agregar e incorporar esse entendimento em um protótipo através de técnicas e ferramentas que acelerem a entrega e reduzam os desvios de compreensão. A concordância sobre o propósito do sistema e a sua evolução é muito importante para o sucesso do projeto. Tanto desenvolvedores como clientes devem estar envolvidos em interações formais que fortaleçam o comprometimento de todos.  
A pressão por soluções de software confiáveis e em curtos prazos favoreceu a criação da metodologia de desenvolvimento rápido de software (RAD). A ideia de entregar protótipos em um ciclo de desenvolvimento incremental e iterativo permite que o usuário possa ter rapidamente uma visão clara de como o sistema está progredindo e se existe alguma questão relacionada aos requisitos que precisa ser aperfeiçoada. Portanto, a colaboração entre desenvolvedores e usuários suporta o desenvolvimento de especificações mais precisas e validadas.
MÓDULO 2
Identificar as fases da RAD
CONCEITOS
A metodologia RAD é caracterizada pelo desenvolvimento do projeto através de etapas iterativas e incrementais, onde um protótipo é entregue ao final de cada ciclo. A proposta é que haja redução nas atividades relacionadas ao planejamento em detrimento do processo de desenvolvimento através de um processo que se caracteriza por incrementos de funcionalidades a cada nova iteração. Desse modo, a expectativa é que as equipes produzam mais em menos tempo, maximizando a satisfação do cliente, uma vez que ele é envolvido no processo. Isso ocorre porque a RAD é estruturada para que as partes interessadas interajam e possam detectar a necessidade de alterações do projeto em tempo real, sem a necessidade de completar longos ciclos de desenvolvimento, e os desenvolvedores possam realizar as implementações rapidamente ao longo das iterações.
O ciclo de vida da RAD foi projetado para direcionar os desenvolvedores na criação de soluções de software que atendam às necessidades dos usuários. Este ciclo de vida trata das atividades que são necessárias para definir o escopo e os requisitos de negócios, além das atividades para projetar, desenvolver e implementar o sistema. Na abordagem de James Martin (MARTIN, 1991), a metodologia RAD possui quatros fases distintas, que são:
FASE 1 - PLANEJAMENTO DE REQUISITOS
As partes interessadas – usuários, gerentes e desenvolvedores – estudam as necessidades de negócios, escopo do projeto, restrições e requisitos do sistema. A gerência só autoriza a continuidade do projeto depois que os membros das equipes concordam sobre o entendimento dos requisitos do sistema.
FASE 2 - DESIGN DO USUÁRIO
São desenvolvidos modelos e protótipos – através da interação de usuários e desenvolvedores – para representar todos os processos, entradas e saídas do sistema. Para isso, são usadas uma combinação de técnicas JAD (Joint Application Development) e ferramentas CASE para representar as demandas do usuário em modelos de trabalho.
FASE 3 - CONSTRUÇÃO
É nesta fase que os protótipos são desenvolvidos. A interação entre usuários e desenvolvedores continua, para que haja sugestões sobre alterações, ajustes, ou melhorias, à medida que unidades do sistema – como telas ou relatórios reais, por exemplo – são desenvolvidas.
FASE 4 - TRANSIÇÃO
São feitos processamento de dados, testes, mudança para o novo sistema e treinamento do usuário.
RESUMINDO
O planejamento de requisitos está focado em determinar as metas e expectativas do projeto e quais são os potenciais problemas que podem ser impeditivos para o desenvolvimento do software. No caso da RAD, onde a entrega rápida de resultados é um dos objetivos principais, a identificação prévia dos requisitos funcionais é muito importante. Na fase de design do usuário, a interação entre os desenvolvedores e os usuários é constante no desenvolvimento de modelos e protótipos que abordam todos os processos, entradas e saídas do sistema. Na fase de construção, converte o protótipo aprovado da fase de design do usuário em um modelo de trabalho. Como já houve bastante interação entre usuários e desenvolvedores na fase anterior, agora o foco dos desenvolvedores está na construção do modelo de trabalho final. Por fim, na fase de transição, o produto está pronto para ser lançado. Aqui, o usuário deve passar por treinamento para começar a usar o sistema.
Existem outras abordagens sobre a divisão das fases da RAD. Por exemplo, uma das mais conhecidas é a de James Kerr (KERR & HUNTER, 1994), em que existem cinco fases distintas, que são:
FASE 1 - MODELAGEM DE NEGÓCIOS
Nesta fase, é feita a obtenção de informações a respeito dos requisitos funcionais do sistema reunidas por várias fontes relacionadas aos negócios, ou seja, o modelo de negócios do produto em desenvolvimento é tratado em termos de fluxo de informações, que são obtidas a partir de vários canais de negócios, tais como entrevistas com usuários do sistema e outras fontes de informação que auxiliem no entendimento do negócio que será tratado. Essas informações são então combinadas, para criar uma documentação que será utilizada para modelar o ciclo de vida dos dados: como os dados podem ser usados, quando são processados e a sua transformação em informações que serão utilizadas por alguma área, ou por algum setor específico do negócio. Portanto, é feita uma análise com viés comercial a fim de encontrar os dados vitais para os negócios: como podem ser obtidos, como e quando são processados e quais são os fatores que os transformam em informações úteis.
FASE 2 - MODELAGEM DE DADOS
Todas as informações que foram obtidas durante a fase modelagem de negócios são analisadas para formar conjuntos de objetos de dados essenciais para os negócios. Através da análise, as informações são agrupadas, de modo que sejam úteis para a empresa, como, por exemplo, na determinação de quais são as entidades principais que serão tratadas pelo sistema. A qualidade de cada grupo de dados, então, é examinada e recebe uma descrição precisa. Em seguida, é feito mapeamento que relaciona esses grupos entre si e qual o significado desses relacionamentos, conforme definido na etapa modelagem de negócios. Avançando um pouco mais, agora deve-se identificar e definir os atributos de todos os conjuntos de dados. Também é estabelecida e definida em detalhes de relevância para o modelo de negócios a relação entre esses objetos de dados.
FASE 3 - MODELAGEM DE PROCESSOS
Esta fase é a etapa da metodologia RAD em que todos os grupos de dados coletados durante a etapa modelagem de dados são analisados sob o ponto de vista de processamento, ou seja, como os dados são convertidos em informações úteis. Durante a fase de modelagem de processos, mudanças e otimizações podem ser feitas, e os conjuntos de dados podem ser definidos com mais detalhes. Quaisquer descrições para adicionar, remover ou alterar os objetos de dados também são criadas durante esta fase. A ideia é a seguinte: os conjuntos de objetos de dados definidos na fase de modelagem de dados são convertidos para estabelecer o fluxo de informações de negócios necessário para atingir objetivos de negócios específicos conforme o modelo de negócios. A modelagem de processamento dos dados para alterá-los, ou utilizá-los para fazer quaisquer outras operações que os transformem, é definida nesta fase. Aqui, também são feitas descrições dos processos para adicionar, excluir, recuperar ou modificar um objeto de dados.
FASE 4 - GERAÇÃO DA APLICAÇÃO
Nesta fase, todas as informações coletadas são codificadas e é construído o sistema que será usado para criar o protótipo. Os modelos de dados criados são transformados em protótipos reais que podem ser testados na próxima fase. O sistema real é construído, e a codificação é feita usando ferramentas de automação para converter modelos de processo e dados em protótipos reais.
FASE 5 - TESTE E MODIFICAÇÃO
Neste momento, são feitos testes dos protótipos criados. Cada módulo é testado de modo a identificar e adaptar os componentespara criar o produto mais eficaz. Como a maioria dos elementos já foi examinada anteriormente, a expectativa é que haja grandes problemas com o protótipo. O tempo total de teste é reduzido no modelo RAD, pois os protótipos são testados independentemente durante cada iteração. No entanto, o fluxo de dados e as interfaces entre todos os componentes precisam ser exaustivamente testados com uma cobertura de teste completa. Como a maioria dos componentes de programação já foi testada, o risco de problemas importantes é minimizado.
O princípio-chave do processo RAD é a redução de atividades burocráticas para se concentrar em um processo iterativo de design e construção, permitindo que as equipes realizem mais em menos tempo, sem afetar a satisfação do cliente. As fases de prototipagem e construção rápida podem ser repetidas, até que o proprietário e os usuários do produto se sintam seguros de que o protótipo e a forma como foi construído atendem aos requisitos do projeto.
Nos métodos tradicionais, como a metodologia cascata, por exemplo, demora bastante até que os desenvolvedores recebam comentários dos usuários, aumentando, assim, as chances de ser necessário refazer partes do sistema, ou seja, retrabalho. Nesse sentido, um dos maiores benefícios da RAD são os comentários dos usuários através da constante interação. O ponto do projeto em que fica mais evidente essa interação está nos componentes de UI/UX do sistema. Com os protótipos, os usuários podem ter mais clareza sobre a forma como o projeto está avançando, e os desenvolvedores podem medir riscos na escolha de tecnologias que venham prejudicar a entrega do projeto, podendo, assim, fazer escolhas em tempo hábil.
UI/UX
O termo UI faz referência a “interface com o usuário” no sentido de telas e demais componentes interativos. Já o termo UX é usado para se referir à “experiência do usuário” com o sistema, ou seja, a melhor forma do usuário interagir com o sistema no aspecto ergonômico de como entrar com dados e obter informações.
CICLO DE DESENVOLVIMENTO
O ciclo de desenvolvimento da metodologia RAD começa com as partes interessadas – usuários e desenvolvedores – definindo um conjunto de requisitos do projeto, que é equivalente ao que seria feito durante o escopo do projeto nos ciclos de desenvolvimento tradicionais. Esse estágio de planejamento é “rápido”, pois a ênfase da metodologia RAD está nas iterações de construção de protótipos que são mais importantes para o sucesso final de um projeto. Todos os envolvidos no projeto – desenvolvedores, clientes, usuários e equipes de software – são levados a interagir entre si, de modo a determinar os requisitos do projeto e, em caso de problemas, quais estratégias serão aplicadas durante o desenvolvimento.
OS REQUISITOS INCLUEM:
Metas – Expectativas – Cronogramas - Orçamento
Espera-se que o cliente forneça a visão para o produto, e, em colaboração com outras partes interessadas, são realizadas pesquisas para finalizar os requisitos com a aprovação de cada parte interessada. É necessário que todos os interessados fiquem convencidos de que o entendimento do projeto está claro desde o início do ciclo de desenvolvimento, pois isso ajuda as equipes a evitar falhas de comunicação e erros dispendiosos.
ATENÇÃO
Outro ponto importante a ser destacado é que um dos princípios fundamentais da RAD é a capacidade de alterar os requisitos em qualquer momento do ciclo de desenvolvimento.
LEVANTAMENTO DE REQUISITOS
Logo no início do levantamento de requisitos, é feita uma pesquisa do ambiente interno para compreender de que forma atender o projeto que será iniciado. Logo depois, é desenvolvido o escopo do sistema proposto. Os processos de negócios e os dados com os quais o sistema trabalhará são usados para definir as suas respectivas funcionalidades. Características como benefícios, custos e riscos potenciais do sistema são identificadas. Passa-se, então, para a documentação de possíveis problemas de gerenciamento, e, por fim, formaliza-se o escopo do sistema. Faz-se também uma estimativa dos recursos e do tempo de implementação. Se o custo e a duração do desenvolvimento já forem definidos, é necessário analisar com mais cuidado o escopo do projeto para verificar se é viável.
OFICINAS JAD
Para completar a análise de negócios e de dados do sistema, são feitas as oficinas JAD, em que são realizados revisões e detalhamento do escopo do sistema para garantir que as entregas ocorram dentro do prazo. Um exemplo de resultado obtido dessa fase são a definição das regras de negócios a serem aplicadas em cada atividade e os atributos de cada entidade. Aqui, elementos de UI/UX, tais como layouts provisórios de telas e dos principais relatórios, são desenvolvidos. Além disso, um esboço do projeto do sistema é desenvolvido. Com a conclusão do design, passa-se a mapear as funcionalidades do sistema com seus componentes de interação.
VALIDAÇÕES DOS PROTÓTIPOS
A consistência do projeto é confirmada através das sucessivas iterações, em que são apresentados protótipos para os usuários validarem. Através de testes, são identificados erros, ou a necessidade de se fazer ajustes no sistema. Ainda nesta fase, são iniciadas estratégias para a implementação do sistema. Em determinado momento, deve-se finalizar o escopo do projeto e o plano de implementação. Por fim, os resultados das interações entre desenvolvedores e usuários são incorporados ao projeto e ao plano de transição. Se tudo for aprovado, passa-se para a fase de construção rápida.
BANCO DE DADOS
Agora, com o ambiente de desenvolvimento concluído, a próxima etapa é o projeto de banco de dados, que deve ser construído conforme a estrutura de dados desenvolvida na fase de design do usuário. O sistema passa a integrar as funcionalidades de banco de dados com os componentes de interação visual. Aplicam-se, agora, os testes, que devem ser executados com dados que simulem situações reais e auxiliem na detecção de possíveis falhas, para que sejam devidamente tratadas, e na documentação do sistema. Cada componente do sistema e as funcionalidades são verificadas de acordo com os requisitos do usuário. Por fim, são iniciados os preparos para a fase de transição através dos planos de trabalho e de contingência.
TRANSIÇÃO
Nesta última fase, a de transição, são feitos treinamentos para o usuário utilizar o sistema antes que seja colocado em produção. Em seguida, o sistema é colocado em produção e, por fim, instalado no cliente. Configurações de hardware, instalações de bibliotecas e demais configurações são concluídas nesta etapa. A última tarefa a ser terminada é a aceitação do sistema por parte do usuário, conforme o que foi estabelecido na etapa inicial do projeto.
Após a definição do escopo do projeto, as equipes iniciam a construção dos modelos e protótipos. O objetivo é demonstrar para o cliente um design funcional o mais rápido possível.
 DESENVOLVEDORES E DESIGNERS – QUE DESENVOLVEM TELAS E COMPONENTES INTERATIVOS – TRABALHAM EM COLABORAÇÃO COM OS CLIENTES ATÉ QUE O PRODUTO ESTEJA PRONTO, PARA QUE OS REQUISITOS FUNCIONAIS SEJAM ATENDIDOS.
 ESSA ETAPA É REPETIDA À MEDIDA QUE O PROJETO É CONSTRUÍDO.
 DURANTE A FASE INICIAL DE PROTOTIPAGEM, OS DESENVOLVEDORES FOCAM SEUS ESFORÇOS EM ELEMENTOS ESSENCIAIS DO SISTEMA PARA PRODUZIR UM PRODUTO QUE SEJA ACEITÁVEL PELO PROPRIETÁRIO DO PRODUTO.
 O USO DE PROTÓTIPOS CONSTRUÍDOS RAPIDAMENTE INCENTIVA O ENVOLVIMENTO DO USUÁRIO NOS TESTES DO SISTEMA E, COMO CONSEQUÊNCIA, SÃO OBTIDOS COMENTÁRIOS QUE PODEM SER UTILIZADOS PARA APERFEIÇOAR O TRABALHO QUE ESTÁ SENDO EXECUTADO, EM VEZ DE TENTAR FAZER AVALIAÇÕES ABSTRATAS DE UM DOCUMENTO DE DESIGN.
 COM ESSES COMENTÁRIOS, OS DESENVOLVEDORES PODEM AJUSTAR OS MODELOS DE FORMA INCREMENTAL, ATÉ QUE SE ATENDA AOS REQUISITOS DO PROJETO. A EXPERIÊNCIA COMPARTILHADA ENTRE AS PARTES INTERESSADAS É OBTIDA ATRAVÉS DA BOA COMUNICAÇÃO. O APRENDIZADO HABILITA A IDENTIFICAÇÃO RÁPIDA DO QUE FUNCIONA E O QUE NÃO FUNCIONA.
A LIBERAÇÃO RÁPIDA DE PROTÓTIPOS AUMENTA AS CHANCES DE DESCOBRIR ERROS PRECOCEMENTE, O QUE LEVA AO AUMENTODA CONFIABILIDADE DO SISTEMA. ATRAVÉS DA CRIAÇÃO DE PROTÓTIPOS, A EQUIPE DE DESENVOLVIMENTO PODE AVALIAR A VIABILIDADE DE COMPONENTES COMPLEXOS. CONSEQUENTEMENTE, AUMENTA-SE A ROBUSTEZ DO SOFTWARE, ALÉM DE FACILITAR ADIÇÕES DE DESIGN FUTURAS.
O DESENVOLVIMENTO RÁPIDO TORNA POSSÍVEL QUE PROTÓTIPOS EVOLUAM PARA A VERSÃO COMERCIAL DO SISTEMA, OU SEJA, QUE AS VERSÕES PARCIAIS PROGRIDAM PARA O SOFTWARE QUE VAI ATENDER ÀS EXPECTATIVAS DO CLIENTE. ATRAVÉS DE INCREMENTOS AO LONGO DAS ITERAÇÕES, NOVOS COMPONENTES E NOVAS ALTERAÇÕES SÃO FEITAS. AS EQUIPES DE DESENVOLVIMENTO USAM FERRAMENTAS COMPUTACIONAIS QUE VIABILIZAM O PROGRESSO RÁPIDO PARA A VERSÃO FINAL DO SISTEMA. NA METODOLOGIA RAD, A MAIORIA DOS PROBLEMAS E AJUSTES SÃO TRATADOS DURANTE A FASE DE PROTOTIPAGEM ITERATIVA.
Nas metodologias tradicionais, os desenvolvedores consomem muito tempo com atividades que não estão diretamente ligadas ao desenvolvimento do projeto. No caso da RAD, são feitos muitos testes, aumentando, assim, as chances de que o resultado satisfaça as expectativas do cliente. A colaboração entre desenvolvedores e usuários finais auxilia na construção de interfaces e funcionalidades que melhorarão todos os aspectos do produto. Os clientes fornecem informações detalhadas com sugestões de alterações – ajustes, ou novas ideias – que resolvem os problemas à medida que são descobertos.
A metodologia RAD se baseia no desenvolvimento iterativo e incremental. Ela é dividida em fases, caracterizando-a, assim, como um método com definição de procedimentos que devem ser seguidos para se atingir a meta do projeto: atender às necessidades do cliente dentro de um prazo curto e sem erros, ou, pelo menos, com o mínimo possível de erros. A existência de mais de uma abordagem para tratar as suas fases não muda a essência do processo, que se caracteriza pela interação constante entre usuários e desenvolvedores.
MÓDULO 3
Distinguir quando aplicar e quando não aplicar RAD
CONCEITOS
A metodologia RAD tem por objetivo fazer a entrega dos sistemas em menos tempo e com menos erros do que os métodos tradicionais de desenvolvimento. No entanto, para implementar esta metodologia, as empresas precisam satisfazer algumas condições, que são (BERGER & BEYNON-DAVIES, 2009):
PESSOAS
Profissionais qualificados e com rápida adaptação, além de trabalhar bem em equipe.
GERENCIAMENTO
Equipes com poder de decisão para evitar perda de tempo, o que é comum nos modelos tradicionais.
USO DE FERRAMENTAS COMPUTACIONAIS (CASE)
Programas que facilitem criação de diagramas e interface com usuário, componentes reutilizáveis (APIs, frameworks e templates, por exemplo) e de fácil manutenção.
A aplicação da RAD gera sistemas cujas telas e demais componentes são padronizados, devido ao uso de ferramentas com bibliotecas e templates reutilizáveis. No entanto, algumas características, como desempenho do sistema e análise de risco, são menos tratadas, pois são atividades que demandam tempo em qualquer projeto. Portanto, a RAD é mais adequada para softwares de baixa complexidade.
Nesta parte do texto, é natural associar a RAD a uma metodologia ágil, inclusive alguns autores fazem essa associação, pois, de fato, há muitas semelhanças entre as duas metodologias e, portanto, as vantagens e desvantagens de ambas seriam idênticas. Entretanto, existem algumas diferenças entre elas. Na RAD, há uma limitação de trabalhar com várias equipes, enquanto no desenvolvimento ágil isso ocorre de modo normal. Outro ponto a ser considerado é o cumprimento dos prazos. Na RAD, o comprometimento é com a rapidez e qualidade das entregas nas iterações, na expectativa, é claro, de que isso se reflita para o projeto como um todo. No caso dos métodos ágeis, existem prazos a cumprir do ponto de vista global do projeto.
ATENÇÃO
A RAD nem sempre é adequada para ser aplicada a um projeto, como será discutido mais adiante. Existem casos, inclusive, em que métodos tradicionais são mais pertinentes. Trata-se de uma metodologia que funciona muito bem sob certas circunstâncias e disponibilidade de recursos e que, em outros casos, não é recomendada, como veremos.
METODOLOGIA RAD – VANTAGENS E DESVANTAGENS
O modelo RAD tem por objetivo a entrega rápida, pois o tempo total de desenvolvimento é reduzido devido à reutilização dos componentes e ao desenvolvimento paralelo. Para que funcione bem, a RAD precisa de profissionais qualificados e que o cliente também se comprometa a colaborar a fim de que os protótipos evoluam para o sistema desejado no prazo determinado. Caso não haja esse compromisso de ambos os lados, a metodologia poderá falhar.
Apesar da rapidez e qualidade da entrega serem as principais vantagens das RAD, também há desvantagens em relação à escalabilidade dos projetos e à demanda por recursos. Sobre a rapidez da entrega, isso é obtido através do uso de ferramentas que auxiliam a conversão de requisitos em código, permitindo, assim, que os desenvolvedores e usuários possam interagir através de protótipos que já são funcionais. A respeito da melhoria da qualidade, com a RAD, será tão melhor quanto um software entregue que atende às necessidades dos usuários, onde são necessárias poucas intervenções para correção de erros, implicando, assim, em baixos custos de manutenção.
Portanto, a aplicação da RAD tem muitos benefícios para o desenvolvimento do projeto, em especial por integrar as equipes de software e seus clientes. Os times de desenvolvimento têm um aumento da sua produtividade, uma vez que rapidez e agilidade são prioridades. Isso melhora os resultados do projeto e torna possível que as entregas ocorram nos prazos estimados. Agora, clique e saiba algumas das principais vantagens do uso de um método RAD (Berger & Beynon-Davies, 2009):
PRINCIPAIS VANTAGENS:
INTEGRAÇÃO ANTECIPADA DO SISTEMA E REDUÇÃO DE RISCOS
A entrega rápida de protótipos que funcionam por parte das equipes da RAD viabiliza que as empresas façam revisões das funcionalidades do projeto desde o início do ciclo de vida do software. Todos os aspectos que se referem ao sistema podem ser reavaliados, devido às iterações frequentes e pelos comentários e sugestões dos usuários, permitindo a análise do progresso dos trabalhos de forma mensurável, que determina se os cronogramas e orçamentos estão no caminho certo. A integração com outros sistemas e serviços é feita no final de um ciclo de vida de desenvolvimento, como ocorre nas metodologias tradicionais. Os testes são realizados durante cada iteração, de modo que as partes interessadas identifiquem e analisem os erros e tratem as vulnerabilidades, resolvendo-os rapidamente, para que não impactem no progresso do desenvolvimento. Redução no risco significa redução nos custos.
ADAPTABILIDADE E COMPARTIMENTAÇÃO DOS COMPONENTES DO SISTEMA
Durante o desenvolvimento, é mais fácil fazer modificações no software, ou seja, enquanto o projeto não é concluído, o software é maleável. É claro que alterações devem ser realizadas com cuidado, pois, por menor que possam parecer, podem afetar todo o sistema. De modo geral, os desenvolvedores podem usar essa flexibilidade para criar protótipos ao longo do processo. Dada essa característica iterativa, designers e desenvolvedores são incentivados a criar componentes funcionais e independentes que sejam reutilizáveis.
VERSÕES ITERATIVAS E MENOR TEMPO DE COLOCAÇÃO NO MERCADO
O uso de ferramentas que suportam o desenvolvimento fortalece as equipes de desenvolvimento a entregar protótipos prontos, ou seja, utilizáveis, para produção mais rápida do que o desenvolvimento feito pelas metodologias tradicionais. As equipes devem ser pequenas, pois a ideia é que o trabalho “repetitivo” seja feito por essas ferramentas, pois, assim, ocorre o aumento da produtividade. As iterações frequentes incentivam a quebra das tarefas, o que é conhecido como “granularização”. Essas tarefas são atribuídas aos membros da equipe, conforme a especialidade e experiência de cada um.
FEEDBACK CONSTANTE DO USUÁRIO
Trata-se de uma das principais características da RAD. A eficiência e a qualidadedo projeto aumentam com a comunicação regular e o feedback constante dos usuários finais. A estrutura iterativa e o acesso aos componentes de UI / UX de um sistema aumentam ainda mais a importância do feedback dos usuários. O fato de os desenvolvedores terem a oportunidade de apresentar para os usuários os protótipos que construíram faz com que fiquem mais confiantes de que estão no caminho certo para satisfazer o cliente quando o produto final é entregue.
Uma das principais características da metodologia RAD é a entrega de protótipos funcionais. Exatamente por isso, a escalabilidade dos projetos é reduzida, pois a aplicação da metodologia sem adaptações inviabiliza a interação com o usuário para um sistema complexo. Este assunto será tratado um pouco mais adiante neste texto. A limitação do tempo de desenvolvimento das iterações é uma característica muito importante para fazer as entregas rápidas, porém é um limitador para a implementação de recursos mais avançados. Portanto, embora a RAD tenha diversos benefícios, há situações para as quais a metodologia não é adequada. Por exemplo, a RAD não funciona bem em projetos onde o risco técnico é alto. A seguir, clique e saiba sobre algumas das desvantagens da RAD (BERGER & BEYNON-DAVIES, 2009):
PRINCIPAIS DESVANTAGENS:
NECESSIDADE DE EQUIPES TECNICAMENTE MUITO QUALIFICADAS
A RAD depende fortemente das habilidades de modelagem – de dados e processos –, e, além disso, é necessário que os profissionais tenham rápida adaptação, pois, devido à natureza da metodologia, é possível haver mudanças significativas ao longo das iterações. Portanto, uma equipe bem qualificada é essencial para identificar e entregar os requisitos de negócios.
FOCO EXIGENTE NA INTERFACE
Os clientes fazem a avaliação da qualidade de uma solução com base no que eles podem interagir em um protótipo. A RAD é caracterizada por iterações nas quais são implementadas novas funcionalidades – incrementos – e, ao final delas, são entregues protótipos. Os clientes podem avaliar os progressos a cada novo lançamento. Devido à rapidez com que os protótipos são implementados, às vezes, os desenvolvedores não aplicam as melhores práticas no projeto, preocupando-se, essencialmente, com o que deve ser entregue para satisfazer as necessidades imediatas do usuário. Isso pode gerar dívidas técnicas, o que pode implicar em problemas quando for entregar a versão final do sistema.
REQUER ALTO NÍVEL DE COMPROMETIMENTO DE TODAS AS PARTES INTERESSADAS
Nos métodos de desenvolvimento tradicionais, os requisitos funcionais são definidos no início do projeto e não são revisitados posteriormente; portanto, clientes e equipes de desenvolvimento não interagem ao longo do projeto. Já na RAD, o entendimento do projeto evolui à medida que é feito; logo, a colaboração entre as partes interessadas é essencial. Caso isso não ocorra, pode haver um comprometimento muito sério da qualidade do projeto.
REQUER SISTEMAS MODULARES E É DIFÍCIL PARA PROJETOS DE GRANDE ESCALA
A natureza da RAD em fazer entregas rápidas ao longo das iterações demanda foco nas partes essenciais do sistema. Desse modo, outros elementos importantes, como questões de segurança, desempenho e tratamento de erros, por exemplo, podem ficar comprometidos. Outro ponto que deve ser considerado é que, para fazer entregas “rápidas” de protótipo, a RAD demanda ferramentas que são padronizadas, ou seja, o desenvolvedor tem pouca flexibilidade no desenvolvimento. Para projetos de baixa complexidade, essa é uma característica muito interessante, mas, para projetos de grande escala, em que há muitas outras tecnologias envolvidas, a RAD não é adequada.
COMPARAÇÃO DE RAD COM OUTRAS METODOLOGIAS
RAD
A primeira e mais importante diferença entre a RAD e as demais metodologias de desenvolvimento é a concentração dos esforços pelo desenvolvimento rápido com entregas constantes de protótipos.
Na RAD trabalha-se com uma única equipe de desenvolvimento, com poucos membros. A ideia é melhorar a qualidade da comunicação e a transferência rápida de informações.
Na RAD, é fundamental envolver o usuário em todo o processo de desenvolvimento.
OUTRAS METODOLOGIAS
Nos outros modelos, de modo geral, a preocupação principal é entregar um produto funcional para o cliente.
Enquanto em outras metodologias trabalha-se com equipes maiores divididas em diferentes especializações, como, por exemplo, o modelo para equipe ágil,
Nas metodologias tradicionais, usuários são envolvidos apenas no início e no final do ciclo de desenvolvimento do projeto.
Como foi apresentado no começo deste módulo, a RAD e as metodologias ágeis têm muitos pontos em comuns. De fato, a RAD é um predecessor das metodologias ágeis, embora essas últimas sejam mais abrangentes do que uma metodologia de desenvolvimento. Suas principais diferenças estão no estabelecimento de um cronograma de entregas, na importância dos comentários dos usuários para o projeto e no desenvolvimento focado em desenvolver protótipos do projeto – que é o caso da RAD – em detrimento do desenvolvimento de características do projeto – que é o caso das metodologias ágeis.
METODOLOGIA RAD – QUANDO APLICAR E QUANDO NÃO APLICAR
A metodologia RAD é adequada para determinados tipos de desenvolvimento, como, por exemplo, quando a interatividade do front-end dos sistemas é uma característica muito importante em detrimento da complexidade do back-end (BERGER & BEYNON-DAVIES, 2009).
QUANDO APLICAR
A RAD não é adequada para as seguintes situações: desenvolvimento de sistemas críticos em tempo real; sistemas de infraestrutura muito grandes e quando os requisitos funcionais precisam ser especificados detalhadamente ainda no início do projeto. Para complementar, a aplicação da RAD não é adequada quando o sistema deve interagir com outros sistemas já existentes.
QUANDO NÃO APLICAR
A RAD é adequada para projetos de pequena escala com equipes também otimizadas de quatro a oito pessoas. No caso de projetos de grande escala, caso seja aplicada a RAD, é necessário que sejam divididos em projetos menores e mais facilmente gerenciáveis. Além disso, é preciso que haja o envolvimento das partes interessadas, de modo a maximizar o entendimento do sistema. Para isso, as equipes precisam ter poderes para tomar decisões.
EQUIPES PRECISAM TER PODERES PARA TOMAR DECISÕES
A capacidade de poder tomar decisões reduz o tempo para realizar modificações sem que haja a necessidade de aprovação por outros níveis hierárquicos dentro da organização. Portanto, a comunicação eficaz no desenvolvimento entre as partes interessadas é bastante importante na RAD.
Nas oficinas de trabalho, em que ocorrem as reuniões entre usuários e desenvolvedores, são usadas ferramentas e técnicas de modelagem para confirmar e documentar o entendimento dos requisitos. Além disso, o desenvolvimento de protótipos auxilia de modo concreto a possibilidade de avaliar se o caminho escolhido para o desenvolvimento do sistema está correto através dos comentários dos usuários.
De forma resumida, a metodologia RAD é adequada desde que as seguintes condições sejam satisfeitas, clique para conhecê-las:
CONDIÇÕES PARA APLICAÇÃO
Disponibilidade de profissionais experientes e comprometidos com um processo de desenvolvimento intensivo e contínuo.
Comprometimento do cliente para participar efetivamente do desenvolvimento do projeto avaliando os protótipos e contribuindo com comentários que deem suporte para que os desenvolvedores avancem no desenvolvimento com aperfeiçoamentos e ajustes.
Seu cliente está disposto a seguir cronogramas do projeto e um cronograma para conclusão do modelo? Todas as partes interessadas precisam estar presentes para aplicar efetivamente essa metodologia.
É necessário que o sistema possa ser dividido em módulos.
Também é necessário ter à disposição programas e infraestrutura adequada para aplicar a RAD.
Para a aplicação da RAD, o projeto, a estrutura tecnológica da organização e a própria cultura da empresa precisam estar adequados para que o desenvolvimento do sistema seja bem-sucedido.
A RAD funcionaperfeitamente para sistemas que podem ser divididos em módulos. Em especial, esses são alguns exemplos para os quais a RAD se encaixa bem:
Sistemas que podem ser modularizados.
Aspectos de interatividade com o usuário UI/UX são muito importantes no projeto.
Ter à disposição profissionais qualificados no uso de ferramentas adequadas ao desenvolvimento rápido; em especial, no uso de frameworks.
Os clientes entendem a importância da interatividade com os desenvolvedores e têm a expectativa de receber protótipos ao longo do projeto.
Desde o início do projeto, já é conhecido que haverá mudanças durante o processo de desenvolvimento.
Essas são algumas situações em que é esperado que a RAD funcionará bem. A RAD é uma metodologia de desenvolvimento com processos bem definidos, em que a colaboração entre usuários e desenvolvedores é fundamental para que os projetos tenham sucesso. A fim de que possa ser aplicada, algumas condições precisam ser satisfeitas. Além de possuir vantagens, a RAD possui desvantagens no sentido que não é adequada para sistemas complexos e de grande escala.
MÓDULO 4
Justificar o Python e as ferramentas (framework) para o desenvolvimento RAD
CONTEXTUALIZAÇÃO
Uma das principais características da RAD é o desenvolvimento de protótipos, de modo que desenvolvedores e usuários possam interagir em um sistema funcional: 
DESSA FORMA, OS USUÁRIOS PODEM USAR O SOFTWARE, AINDA QUE TENHA LIMITAÇÕES, E FAZER COMENTÁRIOS E SUGESTÕES.
 OS COMENTÁRIOS AUXILIAM OS DESENVOLVEDORES A TOMAR DECISÕES QUE MAXIMIZEM A SATISFAÇÃO DOS USUÁRIOS.
E COM A VALIDAÇÃO DO PROTÓTIPO, OS DESENVOLVEDORES MONTAM UM PLANO DE TRABALHO PARA ATENDER AOS REQUISITOS DEFINIDOS PELOS USUÁRIOS.
NESSE SENTIDO, FAZER USO DE FERRAMENTAS DE DESENVOLVIMENTO RÁPIDO É FUNDAMENTAL PARA QUE HAJA BOA TRADUÇÃO ENTRE IDEIAS E REPRESENTAÇÕES VISUAIS E FUNCIONAIS.
A utilização de ferramentas que acelerem o desenvolvimento auxilia na redução do tempo de lançamento no mercado. No ambiente competitivo do mercado de software, trata-se de uma característica muito importante. Frameworks facilitam a codificação e padronizam o uso de recursos; desse modo, a “reusabilidade” de componentes é um dos benefícios que são obtidos e que podem ajudar no desenvolvimento de novos módulos do sistema.
A seguir, serão apresentadas características da linguagem Python, porém já pode ser adiantado que a sintaxe dela é bem mais simples do que muitas outras linguagens do mercado, como o Java, por exemplo. Portanto, escolher o Pyhton como linguagem de desenvolvimento de um projeto pode reduzir consideravelmente o tempo de produção. A ideia é simples: supondo que o número de linhas que um desenvolvedor pode produzir em determinado intervalo é limitado, escolher uma linguagem de sintaxe mais simples ajuda a aumentar a produtividade.
PYTHON
Python é uma linguagem de programação muito usada para diversos fins. Ela possui muitos pacotes para diferentes tipos de aplicações, bibliotecas de GUI, além de ser uma linguagem de programação “enxuta”, no sentido de que sua sintaxe é mais simples do que muitas outras linguagens.
Dadas essas características, entre outras que serão tratadas um pouco mais adiante neste texto, o Python é uma linguagem adequada para a aplicação da metodologia RAD.
	Linguagem Python
	
	Outro ponto que fortalece a escolha do Python para projetos RAD é que muitos frameworks são baseados nela com o objetivo de acelerar o desenvolvimento e garantir desempenho e extensibilidade do código.
	
	É uma linguagem de tipo dinâmico, interpretada e de alto nível. Nela, é possível desenvolver programas estruturados, orientados a objetos e, até mesmo, aplicar conceitos de linguagens funcionais. Possui uma sintaxe que a diferencia de outras linguagens de programação, como Java, C ++ e Java Script.
	
	Para fazer o desenvolvimento de um sistema em Pyhton, é necessário utilizar um ambiente de desenvolvimento, e um dos mais usados é o Spyder (Spyder, 2020), mas existem muitos outros.
 SAIBA MAIS
A instalação dos pacotes no Pyhton também é bem simples, de modo geral. Normalmente, basta digitar: “pip install nome-do-pacote”. Em algumas situações, pode-se ter um pouco mais de trabalho por causa da compatibilidade de versões. Essa questão de configurações de versões, inclusive, é um problema que abrange os projetos de desenvolvimento de modo geral e, sem o apoio de uma equipe focada em questões que incluam esse tipo de problema, perde-se bastante tempo no projeto.
ENTRE OS MOTIVOS PARA ESCOLHER O PYTHON EM PROJETOS RAD, ESTÃO:
PORTABILIDADE
Pode-se trabalhar com Python em diversos sistemas operacionais.
LICENÇA DE CÓDIGO ABERTO
As distribuições do Python são gratuitas e de código aberto sem restrições do uso da licença.
INTEGRAÇÃO COM OUTROS SISTEMAS
Já existem muitos pacotes desenvolvidos para Python que abrangem aplicações de bancos de dados, Web, interfaces gráficas, ciências de dados, entre muitos outros.
DESENVOLVIMENTO RÁPIDO
Por possuir uma sintaxe mais simples do que muitas outras linguagens de programação e, além disso, ter diversos pacotes e frameworks, o Python é uma linguagem muito apropriada para projetos RAD, em que a velocidade do desenvolvimento é considerada um fator fundamental.
OTIMIZAÇÃO DE DESEMPENHO
O Python possui tratamentos específicos para manipulação de listas e de dados de grande porte que otimizam o desempenho do sistema, inclusive para aplicações de big data.
LINGUAGEM INTERPRETADA
Torna mais simples fazer o uso interativo com o programa. No caso de desenvolvimento de protótipos, trata-se de uma característica prática.
Outra vantagem de usar o Python é que a comunidade de usuários é ampla, formada por pessoas com bastante conhecimento e prestativas. Uma das grandes preocupações de qualquer projeto é sobre o suporte que será fornecido ao longo do desenvolvimento; no caso do Python, a comunidade é ativa, ou seja, as pessoas realmente se esforçam para responder a perguntas de diversos níveis de conhecimento. O nível de suporte técnico disponível, gratuitamente, é considerável.
FERRAMENTAS (FRAMEWORK) PARA O DESENVOLVIMENTO RAD
A linguagem Python em si – com seus diversos pacotes disponíveis para instalação gratuita – é uma escolha muito apropriada para desenvolver projetos RAD, mas, além disso, também possui diversos frameworks que auxiliam no ganho de velocidade do tempo de entrega, além de padronizar o desenvolvimento dos sistemas. Com uma interface gráfica obtida rapidamente, o usuário pode interagir com o desenvolvedor com mais qualidade, ou seja, facilita a comunicação entre as partes interessadas, além de manter a motivação no projeto.
OBSERVE ABAIXO OS TIPOS DE FRAMEWORKS SUPORTADOS PELO PYTHON.
FRAMEWORKS (PYTHON)
1 FULL-STACK:
Fornecem uma solução completa de todos os requisitos para o desenvolvedor, desde a geração e validação de formulários até a disponibilização de modelos layouts.
2 MICROFRAMEWORK:
São frameworks que oferecem uma quantidade mínima de serviços. Normalmente, são usados para o recebimento de solicitações, roteamento, despacho e o retorno de uma resposta HTTP.
3 FRAMEWORK ASSÍNCRONOS:
Trata-se de um tipo de microframework que permite lidar com grande conjunto de conexões simultâneas. A estrutura assíncrona é usada para gerenciar operações de longa duração, como transformações de dados.
Ao longo dos últimos anos, o Python tem atraído mais desenvolvedores devido à facilidade de aprendizado e diversidade de aplicações que abrange. A combinação de Python e RAD permite desenvolver rapidamente protótipos que abrangem diversos tipos de aplicações, além do fato de que a aplicação poderá operar em múltiplas plataformas. A seguir, serão tratados alguns exemplos de frameworks em Python para desenvolvimento de GUIs e de aplicações para Web.
FRAMEWORKS GUI PARA PYTHON
A Interface Gráfica do Usuário (GUI) é um aspecto essencial para que possa haver interação com o sistema; portanto, o desenvolvimento de recursos interativos, ainda nos protótipos, possibilita que o usuário tenha uma percepção mais clara de como o projetoestá progredindo. Existem diversos frameworks para Python que tratam desses tipos de recursos, tais como botões, ícones, campos de texto, gráficos, e assim por diante.
ALGUNS FRAMEWORKS GUI PARA PYTHON:
TKINTER
É uma biblioteca que já está embutida na instalação padrão do Python que permite desenvolver interfaces gráficas (TCL DEVELOPER XCHANGE, 2020).
PYQT
É uma biblioteca de componentes gráficos do Python. Ela não é instalada com o Python, além disso tem diferentes tipos de licença (PYQT, 2020).
PYSIDE
É um software livre que executa nos sistemas operacionais Windows, Mac e Linux (PYSIDE, 2020).
KIVY
É um framework de código aberto, em que é possível desenvolver aplicativos “multi-touch” para dispositivos móveis e computadores (KIVY, 2020).
WXPYTHON
É um kit de ferramentas de código aberto que possui suporte para as plataformas Windows de 32 bits, Unix e Mac OS X (WXPYTHON).
Cada um desses frameworks possui particularidades que podem torná-los mais adequados para determinados projetos. Em especial, o framework Tkinter é o framework GUI mais usado do Python.
TKINTER
O framework GUI mais usado do Python, possui componentes que podem ser organizados para facilitar a interatividade com os usuários. O Tkinter possui três classes para gerenciar a organização dos componentes. São elas:
Método pack (): organiza os componentes em blocos antes de posicioná-los no componente pai.
Método grid (): faz a configuração dos componentes em forma de tabela.
Método place (): o posicionamento do componente é feito em um local específico.
Um dos motivos para o Tkinter ser muito usado é que ele já faz parte da biblioteca padrão do Python e é utilizado pelo framework Web Django – que é o framework Web mais usado – para fazer páginas Web. Portanto, não há necessidade de instalá-lo, e, por ser usado pelo Django, torna mais fácil encontrar documentação e exemplos de como usá-lo. Entre os principais componentes do Tkinter, estão:
Button: trata-se de um componente botão. Para adicioná-lo no sistema, basta escrever w=Button(master,option=value).
Canvas: é usado para aplicar design e layouts complexos. Para adicioná-lo no sistema, basta escrever w=Canvas(master, option=value).
CheckButton: é aplicado para selecionar uma opção. Para adicioná-lo no sistema, basta escrever w=CheckButton(master, option=value).
Entry: usado para entrar texto. Para adicioná-lo no sistema, basta escrever w=Entry(master, option=value).
Frame: é usado para agrupar e organizar componentes. Para adicioná-lo no sistema, basta escrever w=Frame(master, option=value).
Label: exibe uma caixa onde se pode inserir texto. Para adicioná-lo no sistema, basta escrever w=Label(Master, option=value).
MenuButton: é usado para criar “menus de topo”. Para adicioná-lo no sistema, basta escrever w=MenuButton(Master, option=value).
Menu: cria menu. Para adicioná-lo no sistema, basta escrever w=Menu(master, option=value).
Message: usado para exibir múltiplas linhas sem texto editável. Para adicioná-lo no sistema, basta escrever w=Message(master, option=value).
Scale: é um componente deslizante que permite selecionar valores de uma escala específica. Para adicioná-lo no sistema, basta escrever w=Scale(master, option=value).
Todos esses componentes estão disponíveis no Tkinter.
RECOMENDAÇÃO
Demais frameworks também possuem diversos recursos, portanto a escolha de um framework é uma decisão que deve ser feita no início do projeto.
FRAMEWORKS WEB PARA PYTHON
Um framework Web é um conjunto de pacotes que habilitam os desenvolvedores a desenvolver aplicações para Web, ou serviços, sem ter de implementar excesso de detalhes, como protocolos, soquetes ou gerenciamento de processos/threads. A maioria dos frameworks para Web focam no desenvolvimento de aplicações do lado do servidor. A responsabilidade pelas comunicações e pela infraestrutura ficam sob a responsabilidade do framework, permitindo que o desenvolvedor possa se concentrar na lógica do sistema.
Os frameworks dão suporte para diversas atividades, como interpretar solicitações – obtenção de parâmetros de formulário, gerenciamento de cookies e de sessões –, produzir respostas (apresentação de dados, como o formato JSon, por exemplo) e fazer armazenamento persistente de dados. É característico de aplicações Web que haja vários tipos diferentes de camadas de programação, geralmente empilhadas umas sobre as outras. Nesse sentido, os frameworks facilitam o rápido desenvolvimento de protótipos.
De modo geral, um framework Web é formado por um conjunto de bibliotecas e um arquivo principal, onde é feita, de fato, a programação. A maioria dos frameworks para aplicações Web incluem padrões que devem ter:
ROTEAMENTO DE URL
Trata de solicitações HTTP recebidas por parte específica do código Python.
OBJETOS DE SOLICITAÇÃO E RESPOSTA
Agrupa as informações recebidas, ou enviadas, para o navegador de um usuário.
TEMPLATE ENGINE
São normalmente usados como um formato intermediário escrito por desenvolvedores para produzir um ou mais formatos de saída, normalmente, HTML, XML ou PDF.
SERVIDOR WEB DE DESENVOLVIMENTO
Executa um servidor HTTP em máquinas de desenvolvimento. Quando os arquivos são atualizados, recarrega automaticamente o código do lado do servidor.
SAIBA MAIS
Existem frameworks Web para Python diversos. Dentre eles, estão:
Django: é um framework de código aberto que é muito bem-sucedido para criar sites complexos baseados em dados. Possui modelos, bibliotecas e APIs que dão suporte na criação de projetos de desenvolvimento da Web escaláveis (Django, 2020).
TurboGears: é um framework que usa a arquitetura MVC (Model View Control), que ajuda no rápido desenvolvimento de aplicações Web (Turbogears, 2020).
Flask: é um framework que suporta o envio de solicitações REST (Flask, 2020).
Bottle: é um framework distribuído como um módulo de arquivo único, sem dependências além da biblioteca padrão do Python. Suporta o envio de solicitações com suporte a URL, bancos de dados de chave/valor e modelos e um servidor HTTP interno (Bottle, 2020).
CherryPy: é um framework que fornece as funcionalidades CRUD (Criar, Recuperar, Atualizar e Excluir) (CherryPy, 2020).
Falcon: é um framework para o desenvolvimento de programas de pequena escala; usa a arquitetura REST e tem disponível vários pacotes complementares para facilitar o desenvolvimento.
O Python possui muitos outros pacotes que servem para operações numéricas, manipulações de listas e impressão de gráficos que são usados, por exemplo, em aplicações de Ciências de Dados, como:
Numpy: com funções para operações matemáticas e lógicas em matrizes (NumPy, 2020).
Pandas: aplicada, especialmente, na análise de dados (Pandas, 2020).
Matplotlib: é uma biblioteca de plotagem que auxilia na criação de gráficos e plotagens 2D, que incluem gráficos de barras, histogramas e muitos outros usando scripts Python.
A abrangência do Python é extensa com frameworks e bibliotecas que podem ser usadas para diversos tipos de aplicações.
A linguagem Python tem características que a tornam uma escolha adequada para aplicação em projetos RAD. Além de ter uma biblioteca e pacotes que cobrem diversos tipos de aplicações, também possui frameworks que são bem documentados e que facilitam a criação de protótipos.
DEFINIÇÃO
Formas de armazenamento e recuperação de dados em arquivos e diretórios, utilizando a linguagem de programação Python.
PROPÓSITO
Compreender os passos necessários para manipulação de arquivos e strings, utilizando boas práticas e tratamento de exceção, para garantir o correto funcionamento do programa.
RECOMENDAÇÃO
Antes de iniciar o conteúdo deste tema, sugerimos que tenha o software Python 3.7 instalado em seu computador. Ele será utilizado nos módulos deste tema.
Você pode pesquisar e baixar o Python 3.7 no site oficial do Python.
Para programar os exemplos apresentados neste módulo, utilizamos a IDE Pycharm Community. Você pode baixar essa IDE gratuitamente no site oficial da JetBrains.
Baixe os CÓDIGOS FONTE PYTHON, deste tema, para lhe auxiliar na realização das atividades.OBJETIVOS
MÓDULO 1 - Identificar as funções de manipulação de arquivos
MÓDULO 2 - Reconhecer as funções de manipulação de strings
MÓDULO 3 - Descrever as exceções na manipulação de arquivos e outras operações
INTRODUÇÃO
Uma das razões pela qual o Python se popularizou foi a facilidade de programar utilizando essa linguagem.
A manipulação de arquivos em Python não é diferente. Os criadores se preocuparam em disponibilizar aos desenvolvedores o que realmente importa!
Com nome de métodos intuitivos, como read(Ler) (ler) e write(Escrever) (escrever), e tratamentos de exceções específica para cada problema, o Python disponibiliza uma simples e poderosa forma de trabalhar com arquivos.
Neste tema, veremos como manipulá-los de forma correta, garantido que o programa rode sem problemas.
É muito comum ajustarmos e prepararmos um texto antes de incluí-lo em um arquivo. Ajustes como remover espaço em branco, colocar todas as letras maiúsculas, substituir palavras e adicionar conteúdo de variável são alguns exemplos.
Esses ajustes podem ser realizados a partir de métodos de manipulação de strings, que também serão tratados neste tema.
MÓDULO 1
Identificar as funções de manipulação de arquivos
CONCEITOS
ABRINDO UM ARQUIVO
Neste módulo, veremos as operações básicas de manipulação de arquivos:
Abrir.
Fechar.
Ler.
Escrever.
A primeira operação que precisamos realizar, independentemente se vamos ler o conteúdo de um arquivo ou adicionar um conteúdo, é abrir o arquivo.
Para abrir um arquivo, o Python disponibiliza a função interna chamada open. Essa função está disponível globalmente, ou seja, não é preciso importá-la.
A função open retorna um objeto do tipo arquivo. Sua forma mais simples de utilização tem a seguinte sintaxe:
ARQUIVO = OPEN (CAMINHO)
Utilizamos a função open com o parâmetro caminho. Esse parâmetro é uma string que representa a localização do arquivo no sistema de arquivos.
No exemplo a seguir, vemos como é fácil abrir um arquivo.
Script inicial e sua saída.
À esquerda da imagem, temos a árvore de diretório, onde podemos verificar a existência dos arquivos script_inicial.py e teste.txt, ambos no mesmo diretório EAD.
Ao centro, temos o código do nosso script e, à direita, a saída do console.
Na linha 1 do script, utilizamos a função open para abrir o arquivo teste.txt. Isso já é suficiente para termos um objeto do tipo arquivo e começar a manipulá-lo.
Na linha 3, imprimimos a frase “Arquivo aberto com sucesso!” apenas para verificar se o programa foi executado sem problemas.
Nesse exemplo, o caminho utilizado para abrir o arquivo foi “teste.txt”, pois o script e o arquivo que abrimos estão no mesmo diretório.
Porém, não precisamos nos limitar a manter os arquivos e scripts no mesmo diretório.
Veja como o Python trata o acesso aos arquivos a seguir.
O caminho de um arquivo pode ser classificado em dois tipos:
ABSOLUTO / CAMINHO ABSOLUTO
Caminho absoluto é a referência completa para se encontrar um arquivo ou diretório. Ele deve começar com uma barra ( / ) ou o rótulo do drive ( C:, D: ...).
Exemplo:
open(“C:\Downloads\arquivo.txt”) – utilizado em ambientes MS Windows.
open(“/home/usuario/arquivo.txt”) – utilizado em ambientes Linux.
RELATIVO / CAMINHO RELATIVO
Caminho relativo é a referência para se encontrar um arquivo ou diretório a partir de outro diretório. Normalmente, a partir do diretório de onde o script está.
Exemplo:
open(“arquivo.txt”), para os casos em que o arquivo está no mesmo diretório do script.
open(“../arquivo.txt”), para os casos em que o arquivo está no diretório acima do script.
A seguir, vamos criar um script que ilustra as diferentes formas de referenciar um arquivo com caminhos absolutos e relativos.
Neste exemplo, alteramos um pouco a forma de exibir o conteúdo.
Script1, sua saída e arquivo dados1.txt.
À esquerda, temos nossa árvore de diretórios.
Ao centro, o script1.py.
À direita, o arquivo dados.txt, e, abaixo, a saída do console do Python. Na linha 1 do script1.py, importamos o módulo os do Python.
Na linha 4, utilizamos a função open para abrir o arquivo “dados1.txt”, que se encontra no mesmo diretório do nosso script. Nessa linha, utilizamos o caminho relativo. Observe que, como o arquivo dados1.txt está na mesma pasta EAD que o script1.py, basta escrever o nome do arquivo como argumento.
Na linha 5, vamos abrir o mesmo arquivo dados1.txt, utilizando o caminho absoluto (completo), que, no nosso exemplo, é: "C:/EAD/dados1.txt".
Nas linhas 8 e 9, vamos abrir o arquivo dados2.txt, que se encontra na pasta documentos. Na linha 8, utilizamos o caminho relativo desse arquivo para abri-lo: "documentos/dados2.txt", enquanto, na linha 9, utilizamos o caminho absoluto: "C:/EAD/documentos/dados2.txt".
O Python também disponibiliza algumas funções para exibir os caminhos absolutos e relativos de um arquivo ou diretório.
Na linha 11, utilizamos a função path.relpath para imprimir o caminho relativo do arquivo1, a partir do nome do arquivo passado como parâmetro.
Na linha 12, utilizamos a função path.abspath para exibir o caminho absoluto do mesmo arquivo.
Observe que, mesmo utilizando o caminho relativo para abrir o arquivo (linha 4), é possível obter o caminho absoluto utilizando a função abspath. Isso pode ser verificado na saída do console.
Na linha 14, utilizamos a função interna print para imprimir a variável arquivo1. Verifique, na saída do console, onde foi impressa a representação do objeto arquivo1:
<_IO.TEXTIOWRAPPER NAME='DADOS1.TXT' MODE='R' ENCODING='CP1252'>
Neste módulo, vamos tratar apenas de arquivos do tipo texto, ou seja, objetos TextIOWrapper. A seguir, vamos apresentar os diferentes modos de acesso aos arquivos.
<_IO.TEXTIOWRAPPER NAME='DADOS1.TXT' MODE='R' ENCODING='CP1252'>
Desmembrando essa saída, temos: o tipo do objeto, TextIOWrapper, que trata de arquivos de texto; o nome do arquivo, name='dados.txt'; o modo de acesso ao arquivo, mode='r'; e a codificação do arquivo, encoding='cp1252'.]
MODOS DE ACESSO A UM ARQUIVO
Quando abrimos um arquivo, precisamos informar ao Python o que desejamos fazer, ou seja, qual será o modo (mode) de acesso ao arquivo. O modo é um dos parâmetros da função open, e cada modo é representado por uma string.
Os principais modos são:
R: LEITURA (READ)
W: ESCRITA (WRITE)
A: ACRESCENTAR (APPEND)
O modo padrão da função open é o modo leitura (“r”).
Esses modos podem ser combinados. Para informar que desejamos ler e escrever em um arquivo, utilizamos a string “r+”, por exemplo.
O Python também nos permite diferenciar arquivos texto de arquivos binários, como uma imagem, por exemplo. Para informar que desejamos abrir um arquivo binário, adicionamos a string “b” ao modo, ficando “rb”, “wb” e “ab”.
A tabela a seguir resume os modos de acesso a arquivos.
	Caractere
	Significado
	'r'
	Abre o arquivo para leitura (default).
	'w'
	Abre o arquivo para escrita, truncando o arquivo primeiro.
	'x'
	Cria um arquivo para escrita e falha, caso ele exista.
	'a'
	Abre o arquivo para escrita, acrescentando conteúdo ao final do arquivo, caso ele exista.
	'b'
	Modo binário.
	't'
	Modo texto (default).
	'+'
	Abre o arquivo para atualização (leitura ou escrita).
Modos de abertura de arquivos em Python. Fonte: Adaptado de Python (2020).
ATRIBUTOS DE UM ARQUIVO
O objeto do tipo arquivo contém alguns atributos importantes, como name, mode e closed, expostos no script a seguir.
Script2, sua saída e arquivo dados.txt.
Na linha 1, abrimos o arquivo utilizando a função open. Como não explicitamos o parâmetro mode, o arquivo será aberto no modo leitura (“r”).
Na linha 3, imprimimos o atributo name do objeto arquivo. Esse atributo contém o nome do arquivo.
Na linha 4, imprimimos o atributo mode do objeto arquivo. Esse atributo contém o modo de acesso do arquivo (r, w, a, rb ...).
Na linha 5, imprimimos o atributo closed do objeto arquivo. Essa atributo serve para verificar se um arquivo está ou não fechado.
Os valores de cada atributo podem ser verificados no console abaixo da imagem.
FECHANDO UM ARQUIVO
Após realizara operação desejada no arquivo, precisamos liberá-lo. Para isso, utilizamos o método close(), que libera a memória alocada pelo interpretador e o uso do arquivo por outros programas, por exemplo.
A seguir, vamos utilizar o script do exemplo anterior como base e adicionar uma chamada ao método close() e verificar o atributo closed novamente.
Em relação ao script do exemplo anterior, adicionamos, na linha 7, uma chamada ao método close() do objeto arquivo.
Na linha 9, imprimimos novamente a propriedade closed, onde podemos observar que seu valor agora é True.
LENDO O CONTEÚDO DE UM ARQUIVO
Agora que já sabemos abrir e fechar um arquivo, vamos ver as formas de ler seu conteúdo.
O Python disponibiliza três métodos para leitura do conteúdo de um arquivo-texto:
READ()
READLINE()
READLINES()
READ()
Retorna todo o conteúdo de um arquivo como uma única string.
READLINE()
Retorna uma linha de um arquivo, incluindo os caracteres de final de linha (\n ou \r\n), e avança o cursor para a próxima linha.
READLINES()
Retorna uma lista onde cada item da lista é uma linha do arquivo.
Na imagem a seguir, Figura 5, temos três scripts, em que cada um utiliza um dos métodos descritos anteriormente para leitura do arquivo.
TRÊS SCRIPTS
Em cada um dos scripts, vamos abrir o mesmo arquivo dados.txt dos exemplos anteriores, ler o conteúdo, verificar o tipo de conteúdo retornado por cada método de leitura e imprimir o valor canônico (real) do conteúdo lido.
Observe que explicitamos o modo de operação como leitura (“r”).
Scripts 4, 5 e 6 e suas respectivas saídas.
No script4.py, mais à esquerda, abrimos o arquivo na linha 1 e, na linha 3, utilizamos o método read() do objeto arquivo para ler o conteúdo de dados.txt e armazená-lo na variável conteudo.
Na linha 5, verificamos o tipo do conteúdo retornado pelo método read(), utilizando a função interna type. Conforme exibido no console, a variável conteudo é um objeto do tipo str (string).
Na linha 8, imprimimos o conteúdo em si, porém utilizamos a função interna repr para mostrar o conteúdo real contido da variável conteudo. Observe que foi retornado todo o texto existente no arquivo dados.txt, que também pode ser verificado no console.
No script5.py, seguimos os mesmos passos do script anterior, porém, na linha 3, utilizamos o método readline().
Na linha 5, verificamos que o tipo do conteúdo retornado pelo método readline() também é um objeto do tipo str (string).
Na linha 8, imprimimos a representação do conteúdo que contém apenas a primeira linha do arquivo dados.txt (incluindo o caractere de final de linha \n). Isso aconteceu porque, quando abrimos o arquivo utilizando o modo leitura (‘r’), o cursor interno de leitura fica posicionado no início do arquivo.
Se chamarmos novamente o método readline(), linha 10, será retornado à próxima linha do arquivo, que foi impressa na linha 13. Confira a saída do script 5 no console abaixo dele.
No script6.py, seguimos novamente os mesmos passos, mas, desta vez, utilizamos o método readlines().
Na linha 5, verificamos que o tipo do conteúdo retornado pelo método readlines() é um objeto do tipo list (lista).
Na linha 8, imprimimos o conteúdo retornado, que é uma lista onde cada item da lista é uma linha do arquivo. Veja a saída desse script no console abaixo dele.
Além dos três métodos apresentados anteriormente, os objetos do tipo arquivo são iteráveis. Com isso, podemos utilizar o laço for diretamente sobre os objetos desse tipo.
No exemplo ao lado, vamos mostrar como iterar diretamente sobre um arquivo.
Na linha 1, abrimos o arquivo da mesma maneira que fizemos nos exemplos anteriores.
Na linha 4, utilizamos o laço for para iterar diretamente sobre a variável arquivo. Para cada iteração, recebemos uma nova linha do arquivo, disponibilizada na variável linha, impressa na linha 5. Observe a saída do console abaixo da figura.
DICA
1 - Quando precisamos abrir um arquivo muito grande, é inviável utilizar os métodos read e readlines, pois eles retornam todo o conteúdo do arquivo de uma só vez, seja na forma de string, seja na forma de lista. Isso pode consumir todos os recursos do computador, travando seu programa.
Nesses casos, precisamos chamar o método readline inúmeras vezes até o final do arquivo ou iterar diretamente sobre o objeto do tipo arquivo.
2 - Após utilizar qualquer um dos métodos para leitura do arquivo apresentados anteriormente, não podemos utilizá-los novamente. Isso acontece porque o cursor estará posicionado ao final do arquivo, e as chamadas aos métodos read, readline ou readlines retornarão vazias.
NA LINHA 1
Abrimos o arquivo em modo leitura.
NA LINHA 3
Lemos todo seu conteúdo utilizando o método read, que é impresso na linha 5. Veja no console à direita da imagem.
NA LINHA 7
Utilizamos o método read para ler novamente o conteúdo do arquivo e atribuímos o valor retornado à variável conteudo_releitura. Na linha 9, imprimimos o conteúdo dessa variável, que, conforme exibido no console, é uma string vazia ('').
Para contornar esse problema, fechamos e abrimos o arquivo novamente, linhas 11 e 14, respectivamente. Na linha 16, utilizamos novamente o método read e imprimimos o conteúdo retornado na linha 18. Observe que, mais uma vez, conseguimos acessar todo o conteúdo do arquivo.
Para demonstrar a utilização do método seek, no mesmo arquivo que já estava aberto, arquivo_reaberto, utilizamos o método seek(0), linha 20. Imprimimos mais uma vez o conteúdo correto do arquivo na linha 23.
Toda a sequência pode ser acompanhada pelo console.
Todos os três métodos apresentados anteriormente aceitam como parâmetro a quantidade de bytes que desejamos ler.
O valor padrão para esse parâmetro é -1, o que corresponde a todo o arquivo.
ESCREVENDO CONTEÚDO EM UM ARQUIVO
Nesta seção, vamos mostrar como, a partir da função open, escrever conteúdo em um arquivo.
A primeira modificação é alterar o modo de acesso ao arquivo. Para escrita de texto, podemos utilizar o modo w (write) ou o modo a (append):
O modo w abre o arquivo para escrita, truncando o arquivo em primeiro lugar. Caso ele não exista, será criado um.
O modo a abre o arquivo para escrita, acrescentando conteúdo ao final dele, caso ele exista. Caso contrário, será criado um arquivo.
O Python disponibiliza dois métodos para escrita de conteúdo em um arquivo texto, para o modo w e para o modo a. Os métodos write e writelines são descritos a seguir:
WRITE (TEXTO)
Escreve todo o conteúdo passado como parâmetro no arquivo.
WRITELINES (ITERÁVEL)
Escreve cada item do iterável (exemplo: lista) no arquivo.
No exemplo a seguir, vamos criar dois scripts para mostrar o uso do modo w. No primeiro, script9, vamos utilizar o método write. No segundo, script10, vamos utilizar o método writelines.
Script 9 e 10 e suas respectivas saída.
No script9, abrimos o arquivo dados_write.txt para escrita utilizando o modo w na linha 1.
Escrevemos os conteúdos utilizando o método write, conforme linhas 2 e 3, e fechamos o arquivo, como exposto na linha 4.
Observe como ficou o arquivo dados_write.txt, abaixo do script9, após a execução desse script.
No script10, criamos uma lista chamada linhas na linha 1. Abrimos o arquivo dados_write.txt para escrita na linha 4, utilizando o mesmo modo de acesso ao arquivo, modo w. Para escrever o conteúdo da lista linhas no arquivo, utilizamos o método writelines, linha 5.
Verifique também o conteúdo do arquivo dados_writelines.txt após a execução do script, abaixo do script10 na figura.
DICA
1 - Fique atento, pois o Python não insere quebra de linha (‘\n’) entre os elementos da lista. Precisamos fazer isso manualmente!
2 - Como o modo w trunca o arquivo, ou seja, remove todo o conteúdo do arquivo, caso ele exista, podemos executar esses scripts repetidas vezes e, ainda assim, o resultado será sempre o mesmo.
No próximo exemplo, vamos mostrar como utilizar o modo append (a) para adicionar conteúdo a um arquivo já existente.
Para isso, vamos abrir o arquivo dados_write.txt, criado pelo script9, utilizando o modo a. Utilizamos esse modo paraacrescentar conteúdo a um arquivo. Confira, a seguir, o script11.
Script11 e sua saída.
Em primeiro lugar, na linha 1, abrimos o arquivo dados_write.txt utilizando o modo escrita a (append).
Na linha 3, utilizamos o método write para acrescentar o texto "\nConteúdo adicional." ao final do arquivo dados_write.txt.
Na linha 5, fechamos o arquivo.
Observe como ficou o conteúdo final do arquivo à direita da imagem, onde a nova frase foi posicionada corretamente ao final do arquivo.
BOAS PRÁTICAS
Uma boa prática ao lidar com arquivos é utilizar a palavra reservada with, disponibilizada pelo Python. Ela garante que o arquivo será fechado adequadamente após utilizarmos o arquivo, não sendo necessário chamar o método close explicitamente.
A sintaxe de utilização do with é:
WITH OPEN(CAMINHO, MODO) AS NOME: (SEU CÓDIGO INDENTADO)
Iniciamos com a palavra reservada with, seguida da função open, a palavra reservada as, um nome de variável que receberá o objeto do tipo arquivo e dois pontos. Todo o código indentado posteriormente está dentro do contexto do with, no qual o arquivo referenciado pela variável nome estará disponível.
Veja como utilizar o with no exemplo a seguir. Clique nas setas e acompanhe.
Script12 e sua saída.
Na linha 3, utilizando a sintaxe do with, o arquivo dados.txt é aberto no modo leitura e atribuído à variável arquivo. Esta variável está disponível em todo o escopo do with, linhas 4, 5 e 6.
Nas linhas 4 e 5, iteramos sobre o conteúdo do arquivo e imprimimos linha por linha.
Na linha 6, imprimimos o nome do arquivo.
Verifique as saídas no console à direita.
MÓDULO 2
Reconhecer as funções de manipulação de strings
CONCEITOS
MÉTODOS DE MANIPULAÇÃO DE STRINGS
Durante a vida de programador, é muito comum nos depararmos com situações em que precisamos realizar alguns ajustes e operações sobre os textos lidos de arquivos.
Ajustes como remover espaço em branco, colocar todas as letras maiúsculas, substituir e contar palavras são alguns exemplos.
Neste módulo, veremos alguns métodos presentes nos objetos do tipo str (string), que são muito utilizados em conjunto com a manipulação de arquivos.
MÉTODO STRIP
Como mostrado nos scripts da figura 5 (script5), ao ler o conteúdo do arquivo, o Python retorna os caracteres de final de linha (\r e \n). Muitas vezes, essa informação não é necessária, principalmente se estivermos tratando uma linha de cada vez.
Dependendo do objetivo, esses caracteres são considerados lixo e podem atrapalhar o processamento que desejamos realizar. Para remover esses caracteres e também espaços em branco adicionais, o tipo str disponibiliza o método strip(). Este método remove esses caracteres do início e do final da linha.
Observe o uso deste método no exemplo a seguir. Clique nas setas para acompanhar cada ação.
Scripts 13a e 13b, suas respectivas saídas e seu arquivo dados13.txt.
Neste exemplo, vamos abrir o arquivo dados13.txt, exibido à direita da figura, e imprimir o conteúdo de cada linha desse arquivo. Vamos utilizar o método repr para verificar o real conteúdo da string.
O script está separado em duas partes, a e b, de forma a se perceber melhor o resultado da utilização do método strip().
Na primeira parte, script13a, abrimos o arquivo no modo leitura, utilizando o with na linha 1, iteramos sobre o objeto arquivo na linha 3 e imprimimos o conteúdo de cada linha na linha 4.
Observe, no console abaixo do script13a, que os espaços em branco no início de cada linha e os caracteres de nova linha (\n) estão presentes na string.
Na segunda parte, script13b, abrimos o mesmo arquivo e iteramos da mesma forma. Porém, desta vez, “limpamos” a linha utilizando o método strip, na linha 4. Este método retorna uma nova string, que é armazenada na variável linha_limpa. Em seguida, na linha 5, imprimimos a representação dessa variável.
Observe a saída do console e verifique que os caracteres em branco do início da linha e os caracteres de nova linha foram removidos.
Um exemplo real de utilização do strip é quando desejamos contar a quantidade de linhas com algum conteúdo em um arquivo. Dependendo do tamanho do arquivo, é inviável remover manualmente as linhas em branco. Para resolver esses problemas, podemos utilizar o método strip, como mostrado a seguir.
Neste exemplo, vamos abrir o mesmo arquivo do exemplo anterior, dados13.txt, e iterar sobre cada linha, incrementando um contador, que será impresso no final.
Para melhor ilustrar, vamos mostrar como contar as linhas sem usar o método strip, script14a, com o strip script14b.
Scripts 14a e 14b e suas respectivas saídas.
No primeiro script, abrimos o arquivo em modo leitura na linha 1, criamos e inicializamos uma variável inteira contador, linha 3, e iteramos seu conteúdo linha a linha, utilizando o loop for, linha 4.
Na linha 5, verificamos se a variável linha, do tipo str, contém algum conteúdo.
Lembrete: Uma variável do tipo string testa para falso apenas se seu conteúdo for vazio ('' ou ""); caso a string contenha, pelo menos, um espaço, ela testará verdadeiro.
Continuando, na linha 6, caso exista algum conteúdo, incrementamos o contador.
Para o primeiro script, o contador obteve valor 7, indicando que o arquivo contém 7 linhas, conforme console abaixo do script14a.
No segundo script, escrevemos praticamente o mesmo código, iniciando pela abertura do arquivo na linha 1, e assim por diante. A exceção é a linha 5, que testa o conteúdo da variável linha após utilização do método strip(). Observe que, agora, contamos corretamente o número de linhas com algum conteúdo, 3.
MÉTODOS COUNT E SPLIT
Outra atividade muito comum na manipulação de arquivos é a contagem do número de vezes que determinada palavra aparece. O Python disponibiliza o método count para strings, que recebe como parâmetro a palavra que desejamos contar e retorna o total de ocorrências dela. Sua sintaxe é a seguinte:
CONTAGEM = VARIAVEL_STRING.COUNT(PALAVRA)
Nela, a variavel_string é uma variável do tipo str e palavra é a string que desejamos contar.
Veja, no exemplo a seguir, como utilizamos o método count para contar a quantidade de vezes em que aparece a palavra “Olá”, no arquivo dados13.txt.
Script 15, sua saída e arquivo dados13.txt.
Após abrir o arquivo na linha 1, utilizamos o método read, linha 2, para retornar todo o conteúdo do arquivo como uma única string e armazená-lo na variável texto.
Na linha 3 utilizamos o método count da variável texto, passando como argumento à string “Olá”.
O total de ocorrências da palavra “Olá” foi armazenado na variável contador, que foi impressa na linha 4.
Observe que o total de ocorrência está correto: 3.
Apesar de ser muito simples a utilização do método count do tipo str, pode gerar alguns efeitos indesejáveis, pois esse método também conta as palavras que contêm parte da string passada como argumento.
EXEMPLO
Considere a frase “Eu amo comer amoras no café da manhã.”. Se utilizarmos o método count, com a string “amo” como argumento, o retorno será 2, pois o método irá considerar tanto a palavra amo quanto a palavra amoras.
Para contornar esse problema, podemos “quebrar” uma frase em palavras e depois verificar se cada palavra é igual à string que buscamos.
Isso nos leva a outro método muito utilizado em processamento de textos, o método split(), que é usado para quebrar uma string em partes menores, retornando uma lista com essas partes. Sua sintaxe é a seguinte:
LISTA_TERMOS = VARIAVEL_STRING.SPLIT(SEPARADOR)
No exemplo, a variavel_string é uma variável do tipo str, e separador é uma string que desejamos utilizar como ponto de quebra do texto. O retorno desse método é uma lista de strings.
Digamos que desejamos usar o método split com separador ‘–‘ na frase: “Amo futebol – Gosto de basquete”.
O resultado seria uma lista onde o primeiro elemento é a string “Amo futebol  ” e o segundo elemento é string “  Gosto de basquete”.
Caso nenhum separador seja passado como argumento, o Python irá utilizar um ou mais espaços como separador padrão.
DICA
A string utilizada como separador não apareceráem nenhum elemento da lista retornada.
Confira, no exemplo a seguir, em que o método split é utilizado em três frases diferentes para mostrar o comportamento deste método.
Script 16 e sua saída.
Na linha 1, temos a primeira frase: “Eu amo comer amoras no café da manhã”. Utilizamos o método split sem argumentos, linha 2, e imprimimos a lista retornada na linha 3.
Observe pelo console que cada item da lista é uma palavra da frase.
Na linha 5, temos a segunda frase: "Amora    abacaxi        abacate            banana". Utilizamos o método split, também, sem argumentos, linha 6, e imprimimos a lista retornada na linha 7.
Observe pelo console que, mesmo havendo muitos espaços em branco entre as palavras da frase, a lista contém apenas as palavras, sem nenhum espaço adicional. O Python é esperto o suficiente para detectar vários espaços contínuos e tratá-los como um único separador.
Na linha 9, temos a última frase: "Carro,moto,avião". Desta vez, utilizamos o método split passando uma vírgula ( , ) como argumento, linha 10. O resultado é uma lista contendo apenas as palavras, sem o separador, conforme podemos ver pelo console.
Agora que sabemos como funciona o método split, no próximo exemplo, vamos utilizar esse método para realizar a contagem da palavra “amo” na frase do exemplo anterior: “Eu amo comer amoras no café da manhã.”. Vamos aproveitar para comparar os resultados obtidos pelos métodos count e split.
Script 17 e sua saída.
Na linha 1, definimos nossa variável frase com o conteúdo descrito anteriormente.
Na linha 4, utilizamos o método count do tipo str para contar diretamente o número de ocorrências da string ‘amo’ na frase.
Pelo console, vemos que o resultado da contagem foi 2. Uma ocorrência pela palavra amo e outra pela palavra amora.
Para realizar a contagem da mesma frase usando o split, vamos criar um contador, linha 7, e quebrar a frase em palavras utilizando o método split, linha 8.
Na linha 9, vamos iterar sobre cada palavra utilizando a variável termo. Para cada termo, comparamos se seu valor é igual a string ‘amo’, linha 10. Caso seja igual, incrementamos o contador, linha 11.
Observe que desta vez alcançamos o resultado correto para a contagem, 1.
DICA
Para evitar iterar sobre a lista, criar contador e realizar comparações, podemos utilizar o método count da lista, que obteremos o mesmo resultado. Confira o código na imagem.
Autor: Autor / Fonte: Autoria própria (2020). Script 18 e sua saída.
Após definida a frase, linha 1, e quebrada em palavras com o método split, linha 3, utilizamos o método count da lista lista_termos para contar a ocorrência da string ‘amo’. Observe que o resultado também está correto.
MÉTODO JOIN
Assim como há a necessidade de quebrar uma frase em uma lista de palavras, podem existir situações em que ocorra o inverso, ou seja, temos uma lista de palavras ou frases e desejamos concatená-las em uma única string.
Para essa operação, utilizamos o método join do tipo str, que retorna uma única string com todos os elementos da lista concatenados, utilizando determinado conector. Sua sintaxe é a seguinte:
STRING_FINAL = “CONECTOR”.JOIN(ITERAVEL)
Onde ‘conector’ é a string que será utilizada entre os elementos da lista que serão concatenados (ex. ‘, ‘) e iteravel é um iterável, como uma lista ou tupla.
No exemplo a seguir, vamos unir os elementos de uma lista utilizando dois conectores diferentes: o conector vírgula (‘, ‘) e o conector de nova linha (‘\n’). Após a união, vamos gravar o conteúdo em um arquivo para mostrar o resultado.
Script 19 e arquivos texto1.txt e texto2.txt.
Em primeiro lugar, na linha 1, criamos a lista minha_lista, que será utilizada nos dois exemplos.
No primeiro exemplo, na linha 3, utilizamos o método join com o conector ‘, ‘ e atribuímos o resultado à variável texto1.
O resultado dessa variável foi gravado no arquivo texto1.txt, que pode ser visto na imagem.
No segundo exemplo, na linha 7, fazemos a junção dos elementos da mesma lista utilizando o conector ‘\n’.
O resultado da junção foi gravado no arquivo texto2.txt, que pode ser visto à direita da imagem. Com isso, fomos capazes de colocar cada elemento da lista em uma linha do arquivo.
Observe que o Python foi esperto o suficiente para não adicionar o conector ao último elemento. Isso pode ser percebido pelo resultado do arquivo texto1.txt.
MANIPULAÇÃO DE VARIÁVEIS EM STRINGS
Até o momento, realizamos operações sobre strings pré-existentes. No entanto, é muito comum precisarmos juntar valores de variáveis com strings.
Agora, veremos algumas funções relacionadas às strings, começando pela formatação de strings (string formatting).
A formatação de strings permite ajustar como uma string será exibida ou gravada em um arquivo, por exemplo. Ajustes como: número de casas decimais em float, exibição de datas, inclusão de variáveis e espaçamento são alguns dos exemplos.
Existem basicamente três formas de realizar a formatação de strings. São elas:
Utilizando f-strings (formatted string literals).
Utilizando o método format() das strings.
Fazendo manualmente.
Veremos como utilizar f-strings, recurso adicionado na versão 3.6 do Python.
F-STRINGS
Os f-strings são tipos especiais de strings que aceitam uma notação especial para permitir a inclusão de expressões diretamente na string.
F-STRINGS
O objetivo principal da criação das f-strings foi facilitar a formatação de strings.
Para definimos uma variável f-string, precisamos incluir, antes das aspas que definem uma string, a letra f (ou F), como, por exemplo:
MINHA_STRING = F”OLÁ MUNDO {EXPR}”
Dentro das f-string, podemos utilizar expressões em Python entre as chaves, delimitadas pelos caracteres { e }.
Essas expressões incluem variáveis ou literais. Inclusive, podemos fazer chamada para funções ou utilizar métodos de variáveis dentro desses delimitadores.
Todo o conteúdo entre os caracteres { e } é substituído pelo resultado da expressão e interpolados à string.
No exemplo a seguir, vamos comparar a manipulação manual de strings com a utilização de f-string. Também vamos mostrar alguns exemplos de uso de literais mais sofisticados dentro de f-strings.
 
LITERAIS
Literal é algo que o interpretador reconhece como uma sintaxe válida (exemplo: 2 > 3 retorna False, [1, 2]) retorna uma lista.
Script 20 e sua saída.
Na linha 1, definimos a variável nome, do tipo string, que será utilizada ao longo do script.
Na linha 3, mostramos como incluir o valor da variável nome no meio de outra string, utilizando o processo manual de concatenação de strings por meio do operador ‘+’.
 
Na linha 4, utilizamos a sintaxe da f-string para incluir o valor da variável nome também no meio de outra string.
Observe que:
A IDE PyCharm já detectou que temos uma expressão entre as chaves e alterou a cor para destacar esse elemento.
No console, o resultado das variáveis minha_string e minha_fstring1 foi o mesmo, porém a sintaxe da f-string é muito mais clara e simples de ser utilizada e entendidas.
Na linha 5, temos o mesmo exemplo da linha anterior, porém chamamos o método upper do tipo str para colocar todas as letras em maiúsculo. Isso foi feito diretamente na expressão!
Na linha 6, utilizamos uma soma na expressão entre chaves, que foi calculada corretamente, conforme console.
Na linha 7, utilizamos o comparador booleano >, que também foi avaliado corretamente.
No último exemplo, na linha 8, utilizamos o operador IN para verificar a pertinência de um número em uma lista, que, mais uma vez, foi avaliado corretamente.
Observe como é fácil e intuitiva a utilização de f-string!
No próximo exemplo, vamos mostrar algumas funcionalidades adicionais de formatação de string utilizando f-string, como a definição de largura de uma string, formatação de float e de datas.
Para facilitar o entendimento, o script21 foi dividido em três trechos. O primeiro trecho, entre as linhas 3 e 6, trata da formatação de largura do conteúdo de expressões, que serve, principalmente, para alinhar conteúdo de texto. No segundo trecho, das linhas 10 a 16, mostramos como formatarfloats. No terceiro trecho, das linhas 20 a 24, mostramos como formatar datas. Clique a seguir para conhecer cada trecho citado.
LINHAS 3 ATÉ 6
No primeiro trecho, definimos uma lista chamada frutas na linha 3 e, na linha 4, percorremos cada item dessa lista.
Para cada item, montamos a f-string minha_fruta, que contém o nome da fruta e o número de letras que a fruta tem. Destacamos essa linha a seguir:
Para indicar a largura, ou melhor, o número de espaços que o conteúdo de uma variável deve ocupar, devemos utilizar a sintaxe {variavel:n}, onde temos o nome da variável, seguida de dois pontos (:) e o número de espaços (n) que se deve ocupar.
Caso o tamanho do conteúdo da variável seja menor que o número n, serão incluídos espaços em branco até completar esse tamanho. A posição dos espaços adicionados depende do tipo da variável. Para variáveis do tipo string, os espaços são adicionados à direita, enquanto para variáveis do tipo inteiro, os espaços são adicionados à esquerda.
Caso o tamanho do conteúdo da variável seja maior que o número n, a formatação será ignorada.
Retornando ao exemplo, desejamos imprimir o nome da fruta de forma que ela ocupe 12 espaços ({fruta:12}), e o número de letras da fruta deve ocupar apenas três espaços ({len(fruta):3}). Observe o resultado obtido no console à direita.
LINHAS 10 ATÉ 16
No segundo trecho, definimos uma variável float na linha 10 e criamos três f-strings para exibir esse conteúdo.
A formatação com f-string nos permite um controle maior de como será exibido um número do tipo float, no qual podemos definir a largura e o número de casas decimais que devem ser exibidos. A sintaxe para formatar um float é a seguinte:
{VARIAVEL_FLOAT:LARGURA.PRECISAO F}
Pelo exemplo, temos o nome da variável do tipo float seguida de dois pontos (:), a largura total que o número deve ocupar, incluindo as casas decimais, e o ponto (separador de decimal), seguido de um ponto (.), o número de casas decimais (precisao) e a letra “f”, que deve estar junto à precisão. A largura é opcional.
Na primeira f-string, na linha 11, utilizamos a expressão {pi:.1f}, ou seja, queremos que seja exibido o valor da variável pi com uma casa decimal apenas. Como não especificamos a largura, ela será calculada de forma a acomodar toda a parte inteira do float.
Na f-string da linha 12, utilizamos a expressão {pi:6.1f}, que indica que o número deve ocupar seis espaços, sendo que, necessariamente, deve ter uma casa decimal.
Na última f-string, linha 13, utilizamos a expressão {pi:.4f}, para que seja exibido o número com quatro casas decimais.
Observe, no console, como ficaram os resultados.
LINHAS 20 ATÉ 24
No terceiro e último trecho, vamos mostrar como formatar datas em expressões f-string.
Na linha 20, definimos a variável data com a data atual, utilizando o método datetime.now().
Na linha 21, criamos uma f-string para exibir o valor da variável data sem informar ao Python qual formatação ele deve utilizar ({data}). Com isso, a data foi impressa no formato padrão: 2020-08-13 10:50:32.262037.
Na linha 22, utilizamos a expressão {data:%d/%m/%Y}, que indica que desejamos exibir a data no formato “dia/mês/ano” (13/08/2020). Veja o resultado no console à direta.
DICA
O Python disponibiliza outras maneiras de formatar datas. Pesquise mais sobre o módulo datetime na documentação oficial para descobrir outras.
MÓDULO 3
Descrever as exceções na manipulação de arquivos e outras operações
CONCEITOS
TRATAMENTO DE EXCEÇÕES
Quando trabalhamos com arquivos, é comum encontrarmos alguns problemas, como arquivo inexistente e falta de permissão para escrever em um arquivo. A maioria desses problemas só pode ser detectada durante a execução do programa.
Quando uma falha inesperada ocorre e o interpretador não consegue resolver o problema, dizemos que houve uma exceção.
Nesses casos, precisamos informar ao interpretador como tratar a exceção, para que o programa não seja interrompido.
EXCEÇÃO.
A exceção é um evento que ocorre quando o programa se desvia do fluxo normal de execução
PORÉM, SE A EXCEÇÃO É UM PROBLEMA INESPERADO, COMO TRATÁ-LA?
Ao desenvolver um programa, precisamos procurar na documentação da biblioteca, do módulo ou da própria linguagem de programação se as funcionalidades que vamos utilizar têm exceções mapeadas. Essas exceções são problemas que podem ocorrer, e é nossa tarefa tratá-las.
Você deve estar se perguntando: “O que seria ‘tratar uma exceção’?”. Tratar uma exceção nada mais é do que dizer ao Python o que fazer, ou quais instruções executar, quando ele encontrar um problema.
Para ilustrar, observe o fluxo a seguir.
Quando abrimos um arquivo em modo leitura e esse arquivo não existe, o Python lança uma exceção do tipo FileNotFoundError.
Se não avisarmos ao Python o que fazer quando isso ocorrer, o programa será interrompido.
Nesse caso, um tratamento para essa exceção poderia ser: exibir um pop-up ao usuário informando que o arquivo não existe.
No exemplo a seguir, vamos mostrar o que acontece quando uma exceção lançada não é tratada.
Script 22 e sua saída.
Na linha 1, imprimimos a string “Abrindo um arquivo”. Essa impressão serve para acompanhar a execução do programa no console.
Na linha 3, abrimos o arquivo teste.txt no modo leitura. Esse arquivo não existe no diretório modulo3 no qual estamos trabalhando, como podemos observar pela árvore de diretórios à esquerda da figura.
Ao executarmos o programa, recebemos um erro, destacado em vermelho no console. O nome do erro é FileNotFoundError, e a sua descrição é No such file or directory (em tradução literal, não existe tal arquivo ou diretório), seguido do nome do arquivo que apresentou o erro, teste.txt.
Essa exceção foi gerada, ou lançada, de acordo com o linguajar da computação, pois o Python não sabia qual caminho tomar ao encontrar esse problema.
Observe que a linha 5 não foi executada, pois o programa parou sua execução assim que o problema foi encontrado.
Para resolver isso, precisamos tratar a exceção, ou melhor, uma possível exceção. Esse tratamento informa ao Python uma rota alternativa, caso ele encontre um problema.
Para tratar exceções, precisamos “envolver” o trecho de código passível de erro com a cláusula try/except ou try/except/finally. Veremos apenas a cláusula try/except.
Veja a sintaxe ao lado:
O código crítico que desejamos executar deve estar no escopo do try, enquanto o código alternativo, que será executado em caso de erro, deve estar no escopo do except.
Uma mesma operação pode lançar mais de um tipo diferente de exceção, em que, para cada tipo, Erro1 e Erro2, devemos ter uma cláusula except específica.
No exemplo da figura, a exceção está disponível por meio da variável erro, de onde podemos extrair mais informações, como veremos a seguir.
Praticamente todas as exceções em Python são herdadas da classe Exception, ou seja, ela é uma exceção muito genérica, lançada por diversos tipos de erros diferentes. Quanto mais genérica, mais abrangente é a exceção.
ATENÇÃO
Não é uma boa prática utilizar exceções abrangentes, pois elas podem silenciar erros que não esperamos. O ideal é tratar as exceções utilizando a forma mais específica possível.
A seguir, apresentamos algumas exceções específicas relacionadas à manipulação de arquivos e alguns motivos que podem gerar essas exceções:
FILEEXISTSERROR
Lançada quando tentamos criar um arquivo ou diretório já existentes.
FILENOTFOUNDERROR
Lançada quando tentamos abrir um arquivo ou diretório que não existem.
PERMISSIONERROR
Lançada quando não temos permissão para realizar uma operação
Todas essas exceções herdam da exceção mais abrangente OSError, que, por sua vez, herda de Exception.
Observe o exemplo a seguir, onde vamos tratar a exceção do exemplo anterior, utilizando a exceção específica mais indicada: FileNotFoundError.
Script 23 e sua saída.
O primeiro passo é “envolver” o código que pode gerar problema com o try. Para isso, indentamos as linhas 4 e 5.
Para tratar o erro, precisamos explicitar qual o tipo de erro que vamos tratar. Nesse caso, FileNotFoundError,como descrito na linha 6.
Indentamos as linhas 7 e 8 para indicar que elas fazem parte do escopo da exceção explicitada na linha 6.
Durante a execução do programa, ao executar a linha 4, o Python encontra um erro, pois tentamos abrir o arquivo teste.txt para leitura, mas ele não existe. Como este código está dentro do escopo do try, o interpretador interrompe imediatamente a execução do código contido nesse escopo e inicia a execução do código do except correspondente ao erro FileNotFoundError. Ou seja, a execução salta da linha 4 para a linha 7.
Na linha 7, imprimimos a mensagem "Arquivo inexistente" e, na linha 8, imprimimos o problema encontrado, disponível na variável erro.
Observe a sequência de execução pelas saídas no console.
Saiba que o Python só consegue tratar a exceção caso o erro esteja mapeado em algum except. Se o interpretador não encontrar o except adequado, será gerado um erro, e o programa será interrompido.
Um problema clássico que ocorre quando lidamos com arquivos é tentar alterar o conteúdo de um arquivo quando ele está aberto em outro programa. No caso do sistema operacional Windows 10, é lançada uma exceção sobre permissão de acesso.
No exemplo ao lado, vamos criar mais um except para tratar o caso de não termos permissão para abrir um arquivo, mostrando o tratamento do problema levantado no parágrafo anterior.
Neste exemplo, vamos tentar abrir o arquivo teste.pdf para escrita, linha 4, porém ele já se encontra aberto em outro programa.
Observe que o fluxo de execução do programa saltou da linha 4 para a linha 10. Na linha 10, temos o início do tratamento da exceção PermissionError, que foi justamente a exceção lançada pelo Python, impressa pela linha 11, e que pode ser verificada no console.
Como dito anteriormente, o Python direciona o fluxo de execução para o trecho onde é realizado o tratamento da exceção lançada.
Vamos explorar mais operações referentes a arquivos e diretórios. Aproveitaremos também para mostrar novas exceções que podem ser lançadas quando utilizamos tais operações.
OUTRAS OPERAÇÕES EM ARQUIVOS
Além das opções para leitura e escrita em arquivos, o Python disponibiliza um conjunto de operações adicionais, como renomear e apagar arquivo, além de operações em diretórios, como listar arquivos de diretórios, criar diretórios etc.
A partir de agora, apresentaremos algumas dessas operações.
Vamos iniciar pela operação de remover um arquivo, que está disponível por meio da função remove do módulo os do Python.
A função remove tem a seguinte sintaxe:
>>> OS.REMOVE(CAMINHO)
Neste exemplo, temos o nome do módulo os, seguido de um ponto e o nome da função remove. Como parâmetro, a função espera o caminho para um arquivo. Para remover diretório, devemos utilizar outra função, rmdir.
Veja ao lado, onde mostramos a função remove.
Iniciamos o script com a importação do módulo os, na linha 1.
Neste exemplo, vamos remover o arquivo teste.txt, que se encontra no mesmo diretório do nosso script. Observe a arvore de diretórios à esquerda.
Na linha 2, utilizamos a função remove, passando como argumento o caminho do arquivo que desejamos remover. Como estamos no mesmo diretório, utilizamos apenas o nome do arquivo.
Pronto! Isso é suficiente para remover um arquivo.
Dentre as exceções lançadas ao usar a função remove, destacamos as seguintes:
FILENOTFOUNDERROR
PERMISSIONERROR
ISADIRECTORYERROR
FILENOTFOUNDERROR
Ocorre quando o arquivo não existe.
PERMISSIONERROR
Ocorre quando não temos permissão para alterar o arquivo.
ISADIRECTORYERROR
Ocorre quando tentamos remover um diretório usando a função remove, em vez de rmdir.
Observe a saída do console, onde tudo ocorreu conforme esperado e nenhuma exceção foi lançada.
A segunda operação que veremos, também muito comum, é a de renomear um arquivo. Essa operação também está disponível no módulo os, mas por meio da função rename.
A função rename tem a seguinte sintaxe:
>>> OS.RENAME(ORIGEM, DESTINO)
 Nesse exemplo, temos o nome do módulo os, seguido de um ponto e o nome da função rename. Como parâmetro, a função espera o caminho para o arquivo que desejamos renomear, origem, e o novo nome do arquivo, destino.
Veja o exemplo ao lado, em que descrevemos o uso dessa função.
Na linha 1, importamos o módulo os, no qual será utilizada a função rename.
Na linha 4, chamamos a função rename com os parâmetros teste_alfa.txt (origem) e teste_beta.txt (destino). Caso tudo ocorra bem, ao final da operação, teremos apenas o arquivo destino.
A seguir, vamos falar sobre algumas exceções que podem ser lançadas quando utilizamos a função rename. Não estamos tratando todas as opções possíveis, mas apenas as mais comuns.
FILENOTFOUNDERROR
Ocorre quando a origem não existe.
PERMISSIONERROR
Ocorre quando não temos permissão para alterar o arquivo de origem ou não temos permissão para escrita do destino.
FILEEXISTSERROR
Ocorre quando o arquivo de destino já existe.
Na figura do nosso exemplo, observe a árvore de diretórios à esquerda. Temos tanto o arquivo teste_alfa.txt quanto o arquivo teste_beta.txt.
Observe a execução do script pelo console e veja que ele saltou da linha 4 para a linha 13. Isso ocorreu porque, como o arquivo teste_beta.txt já existia, a exceção FileExistsError foi lançada.
DICA
Para os casos em que desejamos renomear sobrescrevendo o arquivo destino, caso ele exista, podemos utilizar a função replace, também do módulo os.
OPERAÇÕES EM DIRETÓRIOS
CRIANDO E REMOVENDO DIRETÓRIOS
Trabalhar com arquivos significa trabalhar com diretórios. Nesta seção, vamos mostrar as principais funcionalidades relacionadas à manipulação de diretórios em Python.
Vamos começar pela criação e remoção de um diretório.
Para criar um diretório, utilizamos a função mkdir do módulo os, enquanto, para remover um diretório, utilizamos a função rmdir, também do módulo os.
A sintaxe dessas duas funções são as seguintes:
>>> OS.MKDIR(CAMINHO)
>>> OS.RMDIR(CAMINHO)
Neste exemplo, temos o nome do módulo os, seguido de um ponto e o nome da função mkdir ou rmdir. Como parâmetro, a função espera o caminho para o diretório.
Veja o exemplo a seguir, onde utilizamos essas duas funções.
No script 28, importamos o módulo os na linha 1 e, na linha 4, utilizamos a função mkdir(“meu_diretorio”). O diretório meu_diretorio foi criado na mesma pasta onde o script28 se encontra.
Caso não tenhamos permissão para criar o diretório, será lançada a exceção PermissionError.
Caso o diretório já exista, a exceção FileExistsError é lançada.
No script29, na linha 4, utilizamos a função rmdir para remover o diretório meu_diretorio.
Caso não tenhamos permissão para remover o diretório, será lançada a exceção PermissionError.
Caso o diretório não exista, a exceção FileNotFoundError é lançada.
Para os casos em que o diretório a ser removido não esteja vazio, será lançada a exceção OSError. Essa exceção é mais abrangente. Por isso, não temos como garantir, a princípio, que a exceção lançada ocorre especificamente pelo fato de o diretório não estar vazio.
Nessas situações, precisamos analisar mais o erro, principalmente o número do erro, para verificar o que realmente aconteceu. O número do erro está disponível no atributo errno do objeto erro.
Os códigos dos possíveis erros estão no módulo errno do Python e podem ser utilizados no tratamento das exceções para descobrir o que realmente deu errado.
No exemplo a seguir, vamos mostrar esse problema mais de perto.
Script 30, sua saída e modulo errno.py.
À esquerda, no script30, importamos os módulos os e errno nas linhas 1 e 2.
Na linha 5, tentamos remover o diretório meu_diretorio utilizando a função rmdir. Como o diretório não está vazio, a exceção OSError é lançada, e a execução do programa salta para a linha 8.
Na linha 8, imprimimos o número do erro por meio do atributo errno da variável erro. Observe que o valor impresso foi 41. O erro 41 faz parte da numeração interna de erros do Python, que pode ser verificado no modulo errno à direita da imagem, mapeado como ENOTEMPTY (não vazio).
Na linha 9, comparamos o erro geradopelo programa com o código do erro ENOTEMPTY (erro 41). Caso o resultado da comparação seja verdadeiro, teremos certeza de que o erro ocorreu, pois o diretório não está vazio. Caso contrário, precisaremos analisá-lo novamente.
O WinError 145 é o erro nativo que o Windows retornou. Esse erro foi mapeado pelo Python para o erro 41.
ATENÇÃO
Como a exceção OSError é mais abrangente que as outras exceções que estudamos, ela deve ficar por último. Caso contrário, nunca alcançaremos as exceções mais específicas.
LISTANDO CONTEÚDO DE DIRETÓRIOS
Outra tarefa muito comum quando estamos tratando com arquivos é listar os arquivos presentes em um diretório.
Para isso, podemos utilizar a função scandir do módulo os. Sua sintaxe é a seguinte:
>>> OS.SCANDIR(CAMINHO)
 Neste exemplo, temos o nome do módulo os, seguido de um ponto e o nome da função scandir. Como parâmetro, a função espera o caminho para o diretório.
Como resultado, teremos um iterável (iterator) que retorna objetos do tipo os.DirEntry, que podem ser arquivos ou diretórios. Dentre os atributos e métodos desse tipo de objetos, destacamos:
NAME
Nome do diretório ou arquivo.
PATH
Caminho completo do diretório ou arquivo.
IS_DIR()
Retorna verdadeiro se o objeto é um diretório.
IS_FILE()
Retorna verdadeiro se o objeto é um arquivo.
STAT()
Retorna alguns atributos do arquivo ou diretório, como tamanho.
No exemplo a seguir, vamos mostrar como utilizar essa função.
Script 31 e sua saída.
Neste exemplo, vamos percorrer os arquivos e diretórios da pasta meu_diretorio. A árvore de diretórios pode ser verificada à esquerda da figura.
Na linha 1, importamos o módulo os, onde se encontra a função scandir.
Na linha 4, utilizamos a função scandir utilizando o diretório “meu_diretorio” como argumento. Armazenamos o retorno dessa função na variável entradas.
Na linha 6, iteramos cada entrada e, da linha 7 a 13, imprimimos algumas de suas propriedades.
Observe a saída no console à direita.
CONCLUSÃO
CONSIDERAÇÕES FINAIS
Neste tema, visitamos as principais ações que podemos realizar na manipulação de arquivos e diretórios.
Vimos como abrir um arquivo, ler seu conteúdo e escrever novos conteúdos.
Aproveitamos para mostrar funções de manipulação de strings, que são normalmente relacionadas ao tratamento de arquivos, como quebrar linhas em palavras e juntar listas de strings a um conector em particular.
Além disso, entendemos as principais exceções geradas quando estamos trabalhando com arquivos, de forma a tratá-las e garantir o correto funcionamento de nossos programas.
DESCRIÇÃO
Desenvolvimento de aplicações para armazenamento e recuperação de informação em banco de dados utilizando a linguagem de programação Python.
PROPÓSITO
Compreender os passos e ações necessárias para realizar a manipulação de registro em banco de dados, de forma a garantir o correto funcionamento de programas que tenham essas características.
PREPARAÇÃO
Antes de iniciar o conteúdo, sugerimos que você tenha o software Python 3.7, ou posterior, instalado em seu computador. Ele será utilizado nos módulos deste tema.
Você pode pesquisar e baixar o Python 3.7 no site oficial do Python.
Para programar os exemplos apresentados neste módulo, utilizamos a IDE PyCharm Community. Você pode baixar essa IDE gratuitamente no site oficial da JetBrains.
Para visualizar os dados e tabelas, vamos utilizar o DB Browser for SQLite, também disponível gratuitamente.
Para que você possa acompanhar melhor os exemplos apresentados clique aqui para realizar o download do arquivo “Banco de dados.zip” que contém os scripts utilizados neste conteúdo.
OBJETIVOS
MÓDULO 1 - Reconhecer as funcionalidades de frameworks e bibliotecas para gerenciamento de banco de dados
MÓDULO 2 - Empregar as funcionalidades para conexão, acesso e criação de bancos de dados e tabelas
MÓDULO 3 - Aplicar as funcionalidades para inserção, remoção e atualização de registros em tabelas
MÓDULO 4 - Empregar as funcionalidades para recuperação de registros em tabelas
INTRODUÇÃO
Neste tema, aprenderemos a utilizar o Python para criar aplicações que utilizam banco de dados.
Atualmente, muitas aplicações, como gerenciadores de conteúdo, jogos e sistemas de controle de vendas utilizam banco de dados. É muito importante que o desenvolvedor saiba manipular as informações de um banco de dados.
Nos próximos módulos, mostraremos como criar novos bancos de dados, tabelas e relacionamentos, inserir e remover registros, além de recuperar as informações presentes no banco por meio de consultas.
Para demonstrar a utilização desses comandos, usaremos o banco de dados SQLite, que é um banco de dados leve, baseado em arquivo, que não necessita de um servidor para ser utilizado.
O SQLite está disponível em diversas plataformas, inclusive em celulares com sistema operacional Android.
O SQLite também é muito utilizado durante o desenvolvimento das aplicações, para então ser substituído por um banco de dados mais robusto, como PostgreSQL ou MySQL, quando em produção.
MÓDULO 1
Reconhecer as funcionalidades de frameworks e bibliotecas para gerenciamento de banco de dados
CONCEITOS
CONECTORES PARA BANCO DE DADOS
Quando estamos trabalhando com banco de dados, precisamos pesquisar por bibliotecas que possibilitem a conexão da aplicação com o banco de dados que iremos utilizar.
Na área de banco de dados, essas bibliotecas se chamam conectores ou adaptadores.
Como estamos trabalhando com Python, devemos procurar por conectores que atendam a PEP 249(Python Database API Specification v2.0 - DB-API 2.0).
Essa PEP(Python Enhancement Proposal) especifica um conjunto de padrões que os conectores devem seguir, a fim de garantir um melhor entendimento dos módulos e maior portabilidade entre bancos de dados.
Como exemplo de padrões definidos pela DB-API 2.0, podemos citar:
Nomes de métodos:
close, commit e cursor
Nomes de Classes:
Connection e Cursor
Tipos de exceção:
IntegrityError e InternalError
Como exemplo de conectores que implementam a DB-API 2.0, temos:
psycopg2: Conector mais utilizado para o banco de dados PostgreSQL.
mysqlclient, PyMySQL e mysql-connector-python: Conectores para o banco de dados MySQL.
sqlite3: Adaptador padrão do Python para o banco de dados SQLite.
COMENTÁRIO
Apenas o conector para SQLite está disponível nativamente no Python 3.7. Todos os demais precisam ser instalados.
Como dito na introdução, neste tema, utilizaremos o banco de dados SQLite para demonstrar o desenvolvimento de aplicações Python para banco de dados.
Apesar do nome Lite(leve), o SQLite é um banco de dados completo, que permite a criação de tabelas, relacionamentos, índices, gatilhos(trigger) e visões(views).
O SQLite também tem suporte a subconsultas, transações, junções, pesquisa em texto (full text search), restrições de chave estrangeira, entre outras funcionalidades.
Porém, por não ter um servidor para seu gerenciamento, o SQLite não provê um acesso direto pela rede. As soluções existentes para acesso remoto são “caras” e ineficientes.
Além disso, o SQLite não tem suporte à autenticação, com usuários e permissões definidas. Estamos falando aqui sobre usuários do banco de dados, que têm permissão para criar tabela, inserir registros etc.
Observe que, apesar do SQLite não ter suporte à autenticação, podemos e devemos implementar nosso próprio controle de acesso para nossa aplicação.
PRINCIPAIS MÉTODOS DOS CONECTORES EM PYTHON
Antes de começarmos a trabalhar diretamente com banco de dados, precisamos conhecer algumas classes e métodos disponibilizados pelos conetores e previstos na PEP 249.
Esses métodos são a base para qualquer aplicação que necessite de acesso a banco de dados e estão descritos a seguir:
CONNECT
Função global do conector para criar uma conexão com o banco de dados.
Retorna um objeto do tipo Connection.
CONNECTION
Classe utilizada para gerenciar todas as operações no banco de dados.
Principais métodos:
commit: Confirma todas as operações pendentes;
rollback: Desfaz todas as operações pendentes;
cursor: Retorna um objeto do tipoCursor; e
close: Encerra a conexão com o banco de dados.
CURSOR
Classe utilizada para enviar os comandos ao banco de dados.
Principais métodos:
execute: Prepara e executa a operação passada como parâmetro;
fetchone: Retorna a próxima linha encontrada por uma consulta; e
fetchall: Retorna todas as linhas encontradas por uma consulta.
A utilização desses métodos segue basicamente o mesmo fluxo de trabalho para todas as aplicações que utilizam banco de dados. A seguir, vamos descrever esse fluxo:
Criar uma conexão com o banco de dados utilizando a função connect.
Utilizar a conexão para criar um cursor, que será utilizado para enviar comandos ao banco de dados.
Utilizar o cursor para enviar comandos ao banco de dados, por exemplo:
Criar tabelas.
Inserir linhas.
Selecionar linhas.
Efetivar as mudanças no banco de dados utilizando o método commit da conexão.
Fechar o cursor e a conexão
Observe os scripts a seguir na Figura 2, na qual temos esse fluxo de trabalho descrito na forma de código Python.
Neste momento, vamos focar apenas no script1, mais à esquerda da figura.
Na primeira linha, importamos o módulo sqlite3, conector para o banco de dados SQLite disponível nativamente no Python 3.7. Atribuímos um alias (apelido) a esse import chamado conector. Veremos ao final por que criamos esse alias.
Na linha 4, abrimos uma conexão com o banco de dados utilizando uma URL. O retorno dessa conexão é um objeto da classe Connection, que foi atribuído à variável conexao.
Na linha 7, utilizamos o método cursor da classe Connection para criar um objeto do tipo Cursor, que foi atribuído à variável cursor.
Na linha 10, utilizamos o método execute, da classe Cursor. Este método permite enviar comandos SQL para o banco de dados. Entre os comandos, podemos citar: SELECT, INSERT e CREATE.
Na linha 11, usamos o método fetchall, da classe Cursor, que retorna os resultados de uma consulta.
Na linha 14, utilizamos o método commit, da classe Connection, para efetivar todos os comandos enviados anteriormente. Se desejássemos desfazer os comandos, poderíamos utilizar o método rollback.
Nas linhas 17 e 18, fechamos o cursor e a conexão, respectivamente.
A estrutura apresentada irá se repetir ao longo deste tema, onde, basicamente, preencheremos o parâmetro do método execute com o comando SQL pertinente.
ATENÇÃO
Agora observe os scripts 2 e 3 da Figura 2. e veja que ambas as bibliotecasmysql.connector e psycopg2 contêm os mesmos métodos e funções da biblioteca sqlite3.
Como estamos utilizando o alias conector no import, para trocar de banco de dados, bastaria apenas alterar o import da primeira linha. Isso se deve ao fato de que todas elas seguem a especificação DB-API 2.0.
Cada biblioteca tem suas particularidades, que podem adereçar alguma funcionalidade específica do banco de dados referenciado, mas todas elas implementam, da mesma maneira, o básico para se trabalhar com banco de dados.
Isso é de grande utilidade, pois podemos alterar o banco de dados a qualquer momento, sem a necessidade de realizar muitas alterações no código-fonte.
Mais adiante, mostraremos algumas situações onde as implementações podem diferir entre os conectores.
PRINCIPAIS EXCEÇÕES DOS CONECTORES EM PYTHON
Além dos métodos, a DB-API 2.0 prevê algumas exceções que podem ser lançadas pelos conectores.
Vamos listar e explicar algumas dessas exceções:
	Error
	IntegrityError
	OperationalError
	DatabaseError
	ProgrammingError
	NotSupportedError
ERROR
Classe base para as exceções. É a mais abrangente.
DATABASEERROR
Exceção para tratar erros relacionados ao banco de dados. Também é uma exceção abrangente. É uma subclasse de Error.
INTEGRITYERROR
Exceção para tratar erros relacionados à integridade do banco de dados, como falha na checagem de chave estrangeira e falha na checagem de valores únicos. É uma subclasse de DatabaseError.
PROGRAMMINGERROR
Exceção para tratar erros relacionados à programação, como sintaxe incorreta do comando SQL, tabela não encontrada etc. É uma subclasse de DatabaseError.
OPERATIONALERROR
Exceção para tratar erros relacionados a operações no banco de dados, mas que não estão sob controle do programador, como desconexão inesperada. É uma subclasse de DatabaseError.
NOTSUPPORTEDERROR
Exceção para tratar erros relacionados a operações não suportadas pelo banco de dados, como chamar o método rollback em um banco de dados que não suporta transações. É uma subclasse de DatabaseError.
TIPOS DE DADOS
Cada dado armazenado em um banco de dados contém um tipo, como inteiro, texto, ponto flutuante, entre outros.
Os tipos suportados pelos bancos de dados não são padronizados e, por isso, é necessário verificar na sua documentação quais tipos são disponibilizados.
O SQLite trata os dados armazenados de um modo um pouco diferente de outros bancos, nos quais temos um número limitado de tipos.
No SQLite, cada valor armazenado no banco é de uma das classes a seguir:
	NULL
	Para valores nulos.
	INTEGER
	Para valores que são números inteiros, com sinal.
	REAL
	Para valores que são números de ponto flutuante.
	TEXT
	Para valores que são texto (string).
	BLOB
	Para armazenar valores exatamente como foram inseridos, ex. bytes.
Apesar de parecer um número limitado de classes, quando comparado com outros bancos de dados, o SQLite suporta o conceito de afinidades de tipo para as colunas.
AFINIDADES DE TIPO
Afinidade é a classe preferida para se armazenar um dado em uma determinada coluna.
No SQLite, quando definimos uma coluna durante a criação de uma tabela, ao invés de especificar um tipo estático, dizemos qual a afinidade dela. Isso nos permite armazenar diferentes tipos de dados em uma mesma coluna. Observe as afinidades disponíveis a seguir:
	TEXT
	Coluna para armazenar dados das classes NULL, TEXT e BLOB.
	NUMERIC
	Coluna para armazenar dados de qualquer uma das cinco classes.
	INTEGER
	Similar ao NUMERIC, diferenciando apenas no processo de conversão de valores.
	REAL
	Similar ao NUMERIC, porém os valores inteiros são forçados a serem representados como ponto flutuante.
	NONE
	Coluna sem preferência de armazenamento, não é realizada nenhuma conversão de valores.
A afinidade também permite ao motor do SQLite fazer um mapeamento entre tipos não suportados e tipos suportados. Por exemplo, o tipo VARCHAR(n), disponível no MySQL e PostgreSQL, é convertido para TEXT no SQLite.
Esse mapeamento nos permite definir atributos no CREATE TABLE com outros tipos, não suportados pelo SQLite. Esses tipos são convertidos para tipos conhecidos utilizando afinidade.
A tabela de afinidades do SQLite está descrita a seguir:
	Tipo no CREATE TABLE
	Afinidade
	INT
INTEGER
TINYINT
SMALLINT
MEDIUMINT
BIGINT
UNSIGNED BIG INT
INT2
INT8
	INTEGER
	CHARACTER(20)
VARCHAR(255)
VARYING CHARACTER(255)
NCHAR(55)
NATIVE CHARACTER(70)
NVARCHAR(100)
TEXT
CLOB
	TEXT
	BLOB
	BLOB
	REAL
DOUBLE
DOUBLE PRECISION
FLOAT
	REAL
	NUMERIC
DECIMAL(10,5)
BOOLEAN
DATE
DATETIME
	NUMERIC
A partir desta tabela, mesmo utilizando o SQLite para desenvolvimento, podemos definir os atributos de nossas tabelas com os tipos que utilizaremos em ambiente de produção.
MÓDULO 2
Empregar as funcionalidades para conexão, acesso e criação de bancos de dados e tabelas
CONCEITOS
CONECTANDO A UM BANCO DE DADOS
Neste módulo, vamos aprender a criar e a conectar-se a um banco de dados, criar e editar tabelas e seus relacionamentos.
Como o SQLite trabalha com arquivo e não tem suporte à autenticação, para se conectar a um banco de dados SQLite, basta chamar a função connect do módulo sqlite3, passando como argumento o caminho para o arquivo que contém o banco de dados.
Veja a sintaxe a seguir:
>>> import sqlite3
>>> conexao = sqlite3.connect('meu_banco.db')
Pronto! Isso é o suficiente para termos uma conexão com o banco de dados meu_banco.db e iniciar o envio de comandos SQL para criar tabelas e inserir registros.
Caso o arquivo não exista, ele será criado automaticamente! O arquivo criado pode ser copiado e compartilhado.
Se quisermos criar um banco de dados em memória, que será criado para toda execuçãodo programa, basta utilizar o comando conexao = sqlite3.connect(':memory:').
CRIANDO TABELAS
Agora que já sabemos como criar e se conectar a um banco de dados SQLite, vamos começar a criar nossas tabelas.
Antes de colocarmos a mão na massa, vamos verificar o nosso modelo entidade relacionamento (ER) que utilizaremos para criar nossas tabelas neste primeiro momento. Veja o modelo na Figura 3.
Nosso modelo é composto por três entidades: Pessoa, Veiculo e Marca.
Nossa primeira entidade se chama Pessoa e contém os atributos:
- cpf, como chave primária;
- nome;
- nascimento, para armazenar a data de nascimento da pessoa; e
- oculos, que indica se a pessoa precisa usar óculos.
A segunda entidade se chama Marca, que contém os atributos:
- id, como chave primária,
- nome; e
- sigla.
Nossa terceira e última entidade se chama Veiculo, que contém os atributos:
- placa, como chave primária;
- cor;
- proprietario, que é uma referência à pessoa dona do veículo; e
- marca, referência à marca do veículo.
Para os relacionamentos do nosso modelo, uma pessoa pode ter zero, um ou mais veículos e um veículo só pode ter um proprietário. Uma marca pode estar em zero, um ou mais veículos e um veículo só pode ter uma marca.
Agora que já temos nosso modelo ER, precisamos definir os tipos de cada atributo das nossas entidades. Como estamos trabalhando com SQLite, precisamos ter em mente a tabela de afinidades disponibilizada no módulo anterior.
Vamos definir a nossa entidade Pessoa, de forma que os atributos tenham os seguintes tipos e restrições:
	CPF
	INTEGER (chave primária, não nulo)
	NOME
	TEXT (não nulo)
	NASCIMENTO
	DATE (não nulo)
	OCULOS
	BOOLEAN (não nulo)
Para criar uma tabela que represente essa entidade, vamos utilizar o comando SQL:
CREATE TABLE Pessoa (
cpf INTEGER NOT NULL,
nome TEXT NOT NULL,
nascimento DATE NOT NULL,
oculos BOOLEAN NOT NULL,
PRIMARY KEY (cpf)
);
Observe pela nossa tabela de afinidades, que os tipos DATE e BOOLEAN serão convertidos por afinidade para NUMERIC. Na prática, os valores do tipo DATE serão da classe TEXT e os do tipo BOOLEAN da classe INTEGER, pois armazenaremos os valores True como 1 e False como 0.
Definido o comando SQL, vamos ver como criar essa tabela em Python no exemplo da Figura 4 a seguir.
Na linha 1, importamos o módulo sqlite3 e atribuímos o alias conector.
Observe que envolvemos todo o nosso código com a cláusula try/catch, capturando as exceções do tipo DatabaseError.
Na linha 5, criamos uma conexão com o banco de dados meu_banco.db. Caso esse arquivo não exista, será criado um arquivo no mesmo diretório do script sendo executado.
Na linha 6, criamos um cursor para executar as operações no nosso banco.
Nas linhas 9 a 15, definimos a variável comando, que é uma string contendo o comando SQL para criação da nossa tabela Pessoa.
Na linha 17, utilizamos o método execute do cursor para executar o comando SQL passado como argumento.
Na linha 19, efetivamos a transação pendente utilizando o método commit da variável conexão. Nesse caso, a transação pendente é a criação da tabela.
Nas linhas 22 e 23, capturamos e tratamos a exceção DatabaseError.
Nas linhas 28 e 29 fechamos o cursor e a conexão na cláusula finally, para garantir que nenhuma conexão fique aberta em caso de erro.
Observe como ficou a árvore de diretórios à esquerda da figura após a execução do programa. Veja que agora temos o arquivo meu_banco.db.
ATENÇÃO
Nos exemplos ao longo deste tema, vamos utilizar a mesma estrutura de código do script anterior, porém, vamos omitir as cláusulas try/catch para fins de brevidade.
Agora vamos tratar de nossa próxima entidade, Marca. Vamos defini-la de forma que os atributos tenham os seguintes tipos e restrições:
	id
	INTEGER (chave primária, não nulo)
	nome
	TEXT (não nulo)
	sigla
	CHARACTER (não nulo, tamanho 2)
A codificação latin-1, muito utilizada no Brasil, utiliza um byte por caractere. Como a sigla da marca será composta por 2 caracteres, nosso atributo sigla terá tamanho 2 (CHAR(2) ou CHARACTER(2)).
Para criar uma tabela que represente essa entidade, vamos utilizar o comando SQL:
CREATE TABLE Marca (
id INTEGER NOT NULL,
nome TEXT NOT NULL,
sigla CHARACTER(2) NOT NULL,
PRIMARY KEY (id)
);
Pela tabela de afinidades, o tipo CHARACTER(2) será convertido para TEXT.
Confira a imagem a seguir, Figura 5, para verificar como ficou o script de criação dessa tabela.
Fonte: O AutorFigura: 5.
Após a criação da conexão e do cursor, linhas 4 e 5, definimos uma string com o comando SQL para criação da tabela Marca, linhas 8 a 13.
O comando foi executado na linha 15 e efetivado na linha 18.
Nas linhas 21 e 22, fechamos o cursor e a conexão.
A próxima entidade a ser criada será a entidade Veiculo. Os seus atributos terão os seguintes tipos e restrições.
	PLACA
	CHARACTER (chave primária, não nulo, tamanho 7)
	ANO
	INTEGER (não nulo)
	COR
	TEXT (não nulo)
	PROPRIETÁRIO
	INTEGER (chave estrangeira, não nulo)
	MARCA
	INTEGER (chave estrangeira, não nulo)
Como nossas placas são compostas por 7 caracteres, nosso atributo placa terá tamanho 7 (CHAR(7) ou CHARACTER(7)). Por afinidade, ele será convertido para TEXT.
O atributo proprietario será utilizado para indicar um relacionamento da entidade Veiculo com a entidade Pessoa. O atributo da tabela Pessoa utilizado no relacionamento será o CPF. Como o CPF é um INTEGER, o atributo relacionado proprietario também precisa ser INTEGER.
Analogamente, o atributo marca será utilizado para indicar um relacionamento da entidade Veiculo com a entidade Marca, por meio do atributo id da tabela Marca, que também é um INTEGER.
Veja o comando SQL a seguir para criar a tabela Veiculo e o relacionamento com as tabelas Pessoa e Marca.
CREATE TABLE Veiculo (
placa CHARACTER(7) NOT NULL,
ano INTEGER NOT NULL,
cor TEXT NOT NULL,
proprietario INTEGER NOT NULL,
marca INTEGER NOT NULL,
PRIMARY KEY (placa),
FOREIGN KEY(proprietario) REFERENCES Pessoa(cpf),
FOREIGN KEY(marca) REFERENCES Marca(id)
);
Definido o comando SQL, vamos ver como criar essa tabela em Python no exemplo da Figura 6 a seguir.
Este script também segue os mesmos passos do script anterior até a linha 8, onde definimos a string com o comando SQL para criação da tabela Veiculo.
Esse comando foi executado na linha 19 e efetivado na linha 22.
DICA
Caso a referência da chave estrangeira seja feita a um atributo inexistente, será lançado um erro de programação: ProgrammingError.
Para visualizar como ficaram nossas tabelas, vamos utilizar o programa DB Browser for SQLite.
Após abrir o programa DB Browser for SQLite, basta clicar em Abrir banco de dados e selecionar o arquivo meu_banco.db. Observe a Figura 7 a seguir.
Observe que está tudo conforme o previsto, inclusive a ordem dos atributos obedece a sequência na qual foram criados.
ALTERAÇÃO E REMOÇÃO DE TABELA
Neste momento, temos o nosso banco com as três tabelas exibidas no modelo ER da Figura 3.
Durante o desenvolvimento, pode ser necessário realizar alterações no nosso modelo e, consequentemente, nas nossas tabelas. Nesta parte do módulo, vamos ver como podemos fazer para adicionar um novo atributo e como fazemos para remover uma tabela.
Para alterar uma tabela e adicionar um novo atributo, precisamos utilizar o comando ALTER TABLE do SQL.
Para ilustrar, vamos adicionar mais um atributo à entidade Veiculo.
O atributo se chama motor e corresponde à motorização do carro: 1.0, 1.4, 2.0 etc. Esse atributo deverá conter pontos flutuantes e, por isso, vamos defini-lo como do tipo REAL.
Para alterar a tabela Veículo e adicionar a coluna motor, utilizamos o seguinte comando SQL.
ALTER TABLE Veiculo
ADD motor REAL;
Confira o script da Figura 8, onde realizamos a alteração da tabela Veiculo.
Após se conectar ao banco e obter um cursor, linhas 4 e 5, construímos uma string com o comando ALTER TABLE nas linhas 8 e 9.
Na linha 11, executamos o comando e na linha 14 efetivamos a modificação.
Nas linhas 17 e 18, fechamos o cursor e a conexão.
Observe como ficou nossa tabela após a criação da nova coluna.
Veja, pela Figura 9, queo atributo motor foi adicionado ao final da entidade, obedecendo a ordem de criação.
EXEMPLO
Em algumas situações, pode ser necessário que as colunas sigam uma ordem predeterminada. Um exemplo é quando precisamos carregar os dados de uma planilha diretamente para um banco de dados, para realizarmos o chamado bulk insert (inserção em massa). Nesses casos, as colunas da planilha precisam estar na mesma sequência das colunas do banco.
Como nem todos os bancos de dados, incluindo o SQLite, dão suporte à criação de colunas em posição determinada, vamos precisar remover nossa tabela para recriá-la com os atributos na posição desejada.
Para o nosso exemplo, desejamos a seguinte sequência: placa, ano, cor, motor, proprietario e marca.
No exemplo da Figura 10, vamos remover a tabela Veiculo, utilizando o comando DROP TABLE do SQL e, posteriormente, vamos criá-la novamente com a sequência desejada.
Para remover a tabela Veiculo, utilizamos o seguinte comando SQL.
DROP TABLE Veiculo;
Para recriar a tabela, utilizamos o seguinte comando SQL:
CREATE TABLE Veiculo (
placa CHARACTER(7) NOT NULL,
ano INTEGER NOT NULL,
cor TEXT NOT NULL,
motor REAL NOT NULL,
proprietario INTEGER NOT NULL,
marca INTEGER NOT NULL,
PRIMARY KEY (placa),
FOREIGN KEY(proprietario) REFERENCES Pessoa(cpf),
FOREIGN KEY(marca) REFERENCES Marca(id)
);
Confira como ficou nosso script na Figura 10 a seguir:
Após se conectar ao banco e obter o cursor, criamos a string comando1 com o comando para remover a tabela Veiculo, na linha 8. Na linha 10, executamos esse comando.
Nas linhas 12 a 22, criamos o comando para criar novamente a tabela Veiculo com os atributos na ordem mostrada anteriormente e, na linha 24, executamos esse comando.
Na linha 27, efetivamos todas as modificações pendentes, tanto a remoção da tabela, quanto a criação. Observe que não é preciso efetuar um commit para cada comando!
Nas linhas 30 e 31, liberamos o cursor e fechamos a conexão.
Chegamos ao final do módulo 2 e agora nosso modelo ER está conforme a Figura 11 a seguir:
 SAIBA MAIS
Algumas bibliotecas de acesso a banco de dados oferecem uma funcionalidade chamada mapeamento objeto-relacional, do inglês object-relational mapping (ORM).
ORM
ORM (Object Relational Mapper) é uma mapeamento objeto-relacional, isto é uma técnica de mapeamento objeto relacional que permite fazer uma relação dos objetos com os dados que os mesmos representam.
Esse mapeamento permite associar classes definidas em Python com tabelas em banco de dados, onde cada objeto dessas classes corresponde a um registro da tabela.
Os comandos SQL de inserções e consultas são todos realizados por meio de métodos, não sendo necessário escrever o comando SQL em si. Os ORM nos permitem trabalhar com um nível mais alto de abstração.
Como exemplo dessas bibliotecas, podemos citar SQLAlchemy e Peewee.
Visite as páginas dessas bibliotecas e veja como elas facilitam a manipulação de registros em banco de dados.
No próximo módulo, vamos mostrar como inserir e atualizar os dados em uma tabela.
MÓDULO 3
Aplicar as funcionalidades para inserção, remoção e atualização de registros em tabelas
CONCEITOS
INSERÇÃO DE DADOS EM TABELA
Neste módulo, vamos aprender a inserir, alterar e remover registros de tabelas. Para inserir registros em uma tabela, utilizamos o comando INSERT INTO, do SQL.
Para ilustrar a utilização desse comando, vamos inserir o seguinte registro na tabela Pessoa.
CPF: 12345678900
Nome: João
Data de Nascimento: 31/01/2000
Usa óculos: Sim (True)
O Comando SQL para inserção desses dados é o seguinte:
INSERT INTO Pessoa (cpf, nome, nascimento, oculos)
VALUES (12345678900, 'João', '2000-01-31', 1);
Observe que alteramos a formatação da data para se adequar ao padrão de alguns bancos de dados, como MySQL e PostgreSQL. Para o SQLite será indiferente, pois o tipo DATE será convertido por afinidade para NUMERIC, que pode ser de qualquer classe. Na prática, será convertido para classe TEXT.
Além disso, utilizamos o valor “1” para representar o booleano True. Assim como o DATE, o BOOLEAN será convertido para NUMERIC, porém, na prática, será convertido para classe INTEGER.
Confira como ficou o script para inserção dos dados, Figura 12.
Após se conectar ao banco e obter o cursor, criamos a string com o comando para inserir um registro na tabela Pessoa nas linhas 8 e 9.
Na linha 11, executamos esse comando com a execução do commit na linha 14.
Ao final do script, fechamos o cursor e a conexão.
Observe na figura 13 como ficou nossa tabela pelo DB Browser for SQLite.
INSERÇÃO DE DADOS EM TABELA COM QUERIES DINÂMICAS
É muito comum reutilizarmos uma mesma string para inserir diversos registros em uma tabela, alterando apenas os dados a serem inseridos.
Para realizar esse tipo de operação, o método execute, da classe Cursor, prevê a utilização de parâmetros de consulta, que é uma forma de criar comandos SQL dinamicamente.
COMENTÁRIO
De uma forma geral, as APIs sqlite3, psycopg2 e PyMySQL fazem a concatenação da string e dos parâmetros antes de enviar ao banco de dados.
Essa concatenação é realizada de forma correta, evitando brechas de segurança, como SQL Injection, e convertendo os dados para os tipos e formatos esperados pelo banco de dados.
Como resultado final, temos um comando pronto para ser enviado ao banco de dados.
Para indicar que a string de um comando contém parâmetros que precisam ser substituídos antes da sua execução, utilizamos delimitadores. Esses delimitadores também estão previstos na PEP 249 e podem ser: “?”, “%s”, entre outros.
Na biblioteca do SQLite, utilizamos o delimitador “?”.
Para ilustrar a utilização do delimitador “?” em SQLite, considere o comando a seguir:
>>> comando = “INSERT INTO tabela1 (atributo1, atributo2) VALUES (?, ?);”
Esse comando indica que, ao ser chamado pelo método execute, devemos passar dois parâmetros, um para cada interrogação. Esses parâmetros precisam estar em um iterável, como em uma tupla ou lista.
Veja a seguir como poderia ficar a chamada do método execute para esse comando:
>>> cursor.execute(comando, (“Teste”, 123))
A partir da string e da tupla, é montado o comando final, que é traduzido para:
“INSERT INTO tabela1 (atributo1, atributo2) VALUES (‘Teste’, 123);”
A concatenação é feita da forma correta para o banco de dados em questão, aspas simples para textos e números sem aspas.
No exemplo a seguir, vamos detalhar a utilização de parâmetros dinâmicos, porém, antes, vamos definir uma classe chamada Pessoa, com os mesmos atributos da nossa entidade Pessoa.
A definição dessa classe pode ser vista no script modelo.py. Foi retirado a referência para a figura.
Observe que temos os mesmos atributos que a entidade equivalente, mas com nomes diferentes. Fizemos isso para facilitar o entendimento dos exemplos deste módulo. Confira agora o script10.
Primeiro, importamos o conector na linha 1 e, na linha 2, importamos a classe Pessoa. Ela será utilizada para criar um objeto do tipo Pessoa.
Nas linhas 5 e 6, conectamos ao banco de dados e criamos um cursor.
Na linha 9, utilizamos o construtor da classe Pessoa para criar um objeto com os seguintes atributos: CPF: 10000000099, Nome: Maria, Data de Nascimento: 31/01/1990 e Usa óculos: Não (False). O valor False será convertido para 0 durante a execução do método execute.
Na linha 12, definimos a string que conterá o comando para inserir um registro na tabela Pessoa. Observe como estão representados os valores dos atributos! Estão todos com o delimitador representado pelo caractere interrogação (?)!
Como dito anteriormente, isso serve para indicar ao método execute que alguns parâmetros serão fornecidos, a fim de substituir essas interrogações por valores.
Na linha 13, chamamos o método execute utilizando, como segundo argumento, uma tupla com os atributos do objeto pessoa. Cada elemento dessa tupla irá ocupar o lugar de uma interrogação, respeitando a ordem com que aparecem na tupla.
O comando final enviado ao banco de dados pelo comando execute foi:
INSERT INTO Pessoa (cpf, nome, nascimento, oculos)
VALUES (10000000099,'Maria', '1990-01-31', 0);
Na linha 16, efetivamos o comando utilizando o método commit.
Nas linhas 18 e 19, fechamos o cursor e a conexão.
DICA
Nem todos os conectores utilizam o mesmo caractere como delimitador. Os conectores psycopg2, do PostgreSQL, e PyMySQL, do MySQL, utilizam o “%s”. É necessário ver a documentação de cada conector para verificar o delimitador correto!
INSERÇÃO DE DADOS EM TABELA COM QUERIES DINÂMICAS E NOMES
Além da utilização do caractere “?” como delimitador de parâmetros, o sqlite3 também possibilita a utilização de argumentos nomeados.
A utilização de argumentos nomeados funciona de forma similar à chamada de funções utilizando os nomes dos parâmetros.
Nessa forma de construção de queries dinâmicas, ao invés de passar uma tupla, devemos passar um dicionário para o método execute. Ele será utilizado para preencher corretamente os valores dos atributos.
A utilização de argumentos nomeados nos permite utilizar argumentos sem a necessidade de manter a ordem.
Para ilustrar a utilização dos argumentos nomeados em SQLite, considere o comando a seguir:
>>> comando = INSERT INTO tabela1 (atributo1, atributo2) VALUES (:atrib1, :atrib2);
Esse comando indica que ao ser chamado pelo método execute, devemos passar um dicionário com duas chaves, sendo uma “atrib1” e outra “atrib2”. Observe que há dois pontos (“:”) antes do argumento nomeado!
Veja a seguir como poderia ficar a chamada do método execute para esse comando:
>>> cursor.execute(comando, {“atrib1”:“Teste”, “atrib2”: 123})
A partir da string e do dicionário é montado o comando final, que é traduzido para:
INSERT INTO tabela1 (atributo1, atributo2) VALUES (‘Teste’, 123);
Observe o exemplo da Figura 14, onde vamos criar um script similar ao anterior, no qual vamos utilizar novamente a classe Pessoa, porém o comando para inserir um registro no banco de dados utiliza os argumentos nomeados.
Nas linhas 5 e 6, conectamos ao banco de dados e criamos um cursor.
Na linha 9, utilizamos o construtor da classe Pessoa para criar um objeto com os seguintes atributos: CPF: 20000000099, Nome: José, Data de Nascimento: 28/02/1990 e Usa óculos: Não (False).
Nas linhas 12 e 13, definimos a string que conterá o comando para inserir um registro na tabela Pessoa. Observe os nomes dos argumentos nomeados: cpf, nome, data_nascimento e usa_oculos. Cada um desses nomes deve estar presente no dicionário passado para o método execute!
Na linha 14, chamamos o método execute utilizando, como segundo argumento, um dicionário com os atributos do objeto pessoa, definido na linha 10. Cada argumento nomeado do comando será substituído pelo valor da chave correspondente do dicionário.
O comando final enviado ao banco de dados pelo comando execute foi:
INSERT INTO Pessoa (cpf, nome, nascimento, oculos)
VALUES (20000000099,'José','1990-02-28',0);
Na linha 20, efetivamos o comando utilizando o método commit.
Observe que nosso código está crescendo. Imagine se tivéssemos uma entidade com dezenas de atributos? A chamada do método execute da linha 14 cresceria proporcionalmente, comprometendo muito a leitura do nosso código.
A seguir, vamos simplificar nosso código, de forma que ele permaneça legível, independentemente do número de atributos de uma entidade.
DICA
Quando utilizamos o comando INSERT INTO do SQL para inserir um registro onde todos os atributos estão preenchidos, podemos suprimir o nome das colunas no comando.
Como vamos inserir uma pessoa com todos os atributos, vamos manter apenas os argumentos nomeados no comando SQL.
No próximo exemplo, vamos simplificar mais um pouco nosso código, removendo o nome das colunas no comando SQL e utilizando a função interna vars do Python que converte objetos em dicionários. Observe a Figura 15 a seguir.
Após a criação da conexão e do cursor, criamos um objeto do tipo Pessoa com todos os atributos preenchidos na linha 9. Observe que o valor True do atributo usa_oculos será convertido para 1 durante a execução do método execute.
Na linha 12, criamos o comando SQL “INSERT INTO”, onde suprimimos o nome das colunas após o nome da tabela Pessoa.
Na linha 13, utilizamos o método execute passando como segundo argumento vars(pessoa).
A função interna vars retorna todos os atributos de um objeto na forma de dicionário, no qual cada chave é o nome de um atributo.
Observe na saída do console onde imprimimos o resultado de vars(pessoa), linha 14, e destacado a seguir:
{'cpf': 30000000099, 'nome': 'Silva', 'data_nascimento': '1990-03-30', 'usa_oculos': True}
O comando final enviado ao banco de dados pelo comando execute foi:
INSERT INTO Pessoa VALUES (30000000099,'Silva','1990-03-30',1);
Na linha 17, efetivamos a transação e ao final do script fechamos o cursor e a conexão.
No exemplo a seguir, vamos inserir alguns registros nas outras tabelas, de forma a povoar nosso banco de dados. Vamos utilizar a mesma lógica do exemplo anterior, no qual utilizamos a função vars() e argumentos nomeados.
Primeiro, vamos criar mais duas classes no nosso módulo modelo.py para representar as entidades Marca e Veiculo. Confira essas classes no script da Figura 16.
Para inserir os registros, vamos criar o script definido na Figura 17 a seguir.
No script13, após abrir conexão, vamos utilizar um comando especial do SQLite na linha 4. O comando PRAGMA.
ATENÇÃO
O comando PRAGMA é uma extensão do SQL específica para o SQLite. Ela é utilizada para modificar alguns comportamentos internos do banco de dados.
O SQLite, por padrão, não força a checagem das restrições de chave estrangeira. Isso ocorre por motivos históricos, visto que versões mais antigas do SQLite não tinham suporte à chave estrangeira.
No comando da linha 4, habilitamos a flag foreign_keys, de forma a garantir que as restrições de chave estrangeiras sejam checadas antes de cada operação.
Após a utilização do comando PRAGMA e da criação de um cursor, vamos inserir registros relacionados à entidade Marca e Veiculo no banco.
Vamos começar pela entidade Marca, pois ela é um requisito para criação de registros na tabela Veiculo, visto que a tabela Veiculo contém uma chave estrangeira para a tabela Marca, por meio do atributo Veiculo.marca, que referencia Marca.id.
Na linha 8, escrevemos o comando de inserção de registro na tabela Marca utilizando argumentos nomeados.
Como não iremos passar um valor para o id da marca, que é autoincrementado, foi necessário explicitar o nome das colunas no comando INSERT INTO. Caso omitíssemos o nome das colunas, seria gerada uma exceção do tipo OperationalError, com a descrição indicando que a tabela tem 3 colunas, mas apenas dois valores foram fornecidos.
Na linha 10, criamos um objeto do tipo Marca, que foi inserido no banco pelo comando execute da linha 11.
Para criar uma referência da marca que acabamos de inserir em um veículo, precisamos do id autoincrementado gerado pelo banco no momento da inserção.
Para isso, vamos utilizar o atributo lastrowid do Cursor. Esse atributo armazena o id da linha do último registro inserido no banco e está disponível assim que chamamos o método execute do cursor. O id da linha é o mesmo utilizado para o campo autoincrementado.
Na linha 12, atribuímos o valor do lastrowid ao atributo id do objeto marca1, recém-criado.
Nas linhas 14 a 16, criamos mais um objeto do tipo Marca, inserimos no banco de dados e recuperamos seu novo id.
Nas linhas 19 e 20, temos o comando para inserir registros na tabela Veiculo, também utilizando argumentos nomeados. Como vamos inserir um veículo com todos os atributos, omitimos os nomes das colunas.
Nas linhas 21 a 24, criamos quatro objetos do tipo Veiculo. Observe que utilizamos o atributo id dos objetos marca1 e marca2 para fazer referência à marca do veículo. Os CPF dos proprietários foram escolhidos aleatoriamente, baseando-se nos cadastros anteriores.
Lembre-se de que como os atributos proprietario e marca são referências a chaves de outras tabelas, eles precisam existir no banco! Caso contrário, será lançada uma exceção de erro de integridade (IntegrityError) com a mensagem Falha na Restriçãode Chave Estrangeira (FOREIGN KEY constraint failed).
Na sequência, os veículos foram inseridos no banco pelos comandos execute das linhas 25 a 28.
Os comandos SQL gerados por esse script foram os seguintes:
INSERT INTO Marca (nome, sigla) VALUES ('Marca A', 'MA')
INSERT INTO Marca (nome, sigla) VALUES ('Marca B', 'MB')
INSERT INTO Veiculo VALUES ('AAA0001', 2001, 'Prata', 1.0, 10000000099, 1)
INSERT INTO Veiculo VALUES ('BAA0002', 2002, 'Preto', 1.4, 10000000099, 1)
INSERT INTO Veiculo VALUES ('CAA0003', 2003, 'Branco', 2.0, 20000000099, 2)
INSERT INTO Veiculo VALUES ('DAA0004', 2004, 'Azul', 2.2, 30000000099, 2)
Ao final do script, efetivamos as transações, fechamos a conexão e o cursor.
Neste momento, temos os seguintes dados nas nossas tabelas:
ATUALIZAÇÃO DE DADOS EM UMA TABELA
Agora que já sabemos como inserir um registro em uma tabela, vamos aprender a atualizar os dados de um registro.
Para atualizar um registro, utilizamos o comando SQL UPDATE. Sua sintaxe é a seguinte:
UPDATE tabela1
SET coluna1 = valor1, coluna2 = valor2...
WHERE [condição];
Assim como no comando INSERT, podemos montar o comando UPDATE de três formas. Uma string sem delimitadores, uma string com o delimitador “?” ou uma string com argumentos nomeados.
Também podemos utilizar os delimitadores na condição da cláusula WHERE.
No exemplo a seguir, Figura 18, vamos mostrar como atualizar registros de uma tabela utilizando os três métodos.
Após a abertura da conexão, habilitamos novamente a checagem de chave estrangeira, por meio da flag foreign_keys, ativada pelo comando PRAGMA.
Na sequência, criamos o cursor e definimos a string do nosso primeiro comando de atualização, onde passamos os valores de forma explícita, sem utilização de delimitadores. O string foi atribuído à variável comando1, linha 9.
No comando1, estamos atualizando o valor do atributo oculos para 1 (verdadeiro) para TODOS os registros da tabela. Isso ocorreu, pois a cláusula WHERE foi omitida.
Na linha 10, executamos o comando1.
Na linha 12, criamos um comando de UPDATE utilizando o delimitador “?” para o valor do atributo oculos e explicitamos o valor do cpf na cláusula WHERE. O comando executado pela linha 13 é:
UPDATE Pessoa SET oculos= 0 WHERE cpf=30000000099;
Ou seja, vamos alterar o valor do atributo oculos para zero (falso) apenas para quem tem cpf igual a 30000000099.
Na linha 15, criamos mais um comando de UPDATE, desta vez utilizando o argumento nomeado tanto para o atributo oculos quanto para o cpf da clausula WHERE.
O comando final enviado pela linha 16 ao banco de dados é:
UPDATE Pessoa SET oculos= 0 WHERE cpf= 20000000099;
Onde vamos alterar o valor do atributo oculos para zero (falso) para quem tem cpf igual a 20000000099.
Na linha 19, efetivamos as transações e posteriormente fechamos o cursor e a conexão.
Se tentássemos alterar o CPF de uma pessoa referenciada pela tabela Veiculo, seria lançada uma exceção do tipo IntegrityError, devido à restrição da chave estrangeira.
DICA
Cuidado ao executar um comando UPDATE sem a cláusula WHERE, pois, dependendo do tamanho do banco de dados, essa operação pode ser muito custosa.
REMOÇÃO DE DADOS DE UMA TABELA
Nesta parte deste módulo, iremos aprender a remover registros de uma tabela.
Para remover um registro, utilizamos o comando SQL DELETE. Sua sintaxe é a seguinte:
DELETE FROM tabela1
WHERE [condição];
Assim como nos outros comandos, podemos montar o comando DELETE de três formas. Uma string sem delimitadores, uma string com o delimitador “?” ou uma string com argumentos nomeados. Todos para a condição da cláusula WHERE.
Veja o exemplo da utilização do comando DELETE a seguir, na Figura 19.
Após a criação da conexão, habilitação da checagem de chave estrangeira e aquisição do cursor, criamos o comando SQL “DELETE” na linha 9, onde explicitamos o CPF da pessoa que desejamos remover do banco.
Na linha 10, utilizamos o método execute com o comando criado anteriormente.
O comando final enviado ao banco de dados pelo comando execute foi:
DELETE FROM Pessoa WHERE cpf=12345678900;
Na linha 13, efetivamos a transação e ao final do script fechamos o cursor e a conexão.
Observe que, como as outras pessoas cadastradas são referenciadas pela tabela Veiculo por meio de seu CPF, seria gerada uma exceção do tipo IntegrityError caso tentássemos removê-las.
MÓDULO 4
Empregar as funcionalidades para recuperação de registros em tabelas
SELEÇÃO DE REGISTROS DE UMA TABELA
Neste módulo, aprenderemos a recuperar os registros presentes no banco de dados. Partiremos de consultas mais simples, utilizando apenas uma tabela, até consultas mais sofisticadas, envolvendo os relacionamentos entre tabelas.
Para selecionar e recuperar registros de um banco de dados, utilizamos o comando SQL SELECT. Sua sintaxe é a seguinte:
SELECT coluna1, coluna2, ... FROM tabela1
WHERE [condição];
Assim como nos outros comandos, podemos utilizar uma string sem delimitadores, uma string com o delimitador “?” ou uma string com argumentos nomeados para a condição da cláusula WHERE.
No exemplo a seguir, Figura 20, vamos mostrar como recuperar todos os registros da tabela Pessoa.
Após criar uma conexão e obter um cursor, criamos o comando SQL “SELECT” na linha 8 e destacado a seguir:
SELECT nome, oculos FROM Pessoa;
Observe que estamos selecionando todas as pessoas da tabela, visto que não há clausulas WHERE. Porém, estamos recuperando apenas os dados das colunas nome e oculos.
Executamos o comando na linha 9 e utilizamos o método fetchall do cursor para recuperar os registros selecionados.
Atribuímos o retorno do método à variável registros.
O objeto retornado pelo método fetchall é do tipo lista, impresso pela linha 13 e que pode ser observado pelo console.
Na linha 15, iteramos sobre os elementos retornados e, na linha 16, imprimimos o tipo e o conteúdo dos registros.
Observe que cada registro é uma tupla, composta pelos atributos nome e oculos da entidade Pessoa.
Os registros são sempre retornados em forma de tupla, mesmo que contenham apenas um atributo!
Ao final, fechamos o cursor e a conexão.
ATENÇÃO
Como o SQLite não cria uma transação para o comando SELECT, não é necessário executar o commit.
No exemplo a seguir, Figura 21, vamos criar uma consulta para retornar as pessoas que usam óculos. Observe como ficou o exemplo.
Após abrir a conexão e criar um cursor, definimos o comando para selecionar apenas as pessoas que usam óculos.
Para isso, definimos o comando SQL da linha 8, que, após executado, fica da seguinte forma:
SELECT * FROM Pessoa WHERE oculos=1;
Observe que utilizamos o asterisco (*) para representar quais dados desejamos receber. No SQL, o asterisco representa todas as colunas.
Na linha 12, recuperamos todos os dados selecionados utilizando o fetchall, que foram iterados na linha 13.
Para cada registro retornado, que é uma tupla com os atributos cpf, nome, nascimento e oculos, nessa ordem, criamos um objeto do tipo Pessoa, na linha 14.
Observe que utilizamos o operador * do Python. Esse operador “desempacota” um iterável, passando cada elemento como um argumento para uma função ou construtor.
Como sabemos que a ordem das colunas é a mesma ordem dos parâmetros do construtor da classe Pessoa, garantimos que vai funcionar corretamente.
Das linhas 15 a 18, imprimimos cada atributo do registro e seu respectivo tipo.
Ao final do script fechamos a conexão e o cursor.
Verifique que os dados dos atributos nascimento e oculos estão exatamente como no banco de dados, o nascimento é uma string e o oculos é do tipo inteiro.
COMENTÁRIO
Se estivéssemos utilizando o banco de dados PostgreSQL com o conector psycopg2, como os tipos DATE e BOOLEAN são suportados, esses valores seriam convertidos para o tipo correto.
O conector sqlite3 também nos permite fazer essa conversão automaticamente, mas precisamos fazer algumas configurações a mais.
No exemplo a seguir, Figura 22, vamos mostrar como fazer a conversão de datas e booleanos.
A primeira modificação ocorre nos parâmetros da criação da conexão. Precisamos passar o argumento PARSE_DECLTYPES parao parâmetro detect_types da função connect. Observe como ficou a linha 4.
Isso indica que o conector deve tentar fazer uma conversão dos dados, tomando como base o tipo da coluna declarada no CREATE TABLE.
COMENTÁRIO
Os tipos DATE e TIMESTAMP já possuem conversores embutidos no sqlite3, porém, o tipo BOOLEAN não.
Para informar ao conector como fazer a conversão do tipo BOOLEAN, precisamos definir e registrar a função conversora utilizando a função interna register_converter do sqlite3.
A função register_converter espera, como primeiro parâmetro, uma string com o tipo da coluna a ser convertido e, como segundo parâmetro, uma função que recebe o dado e retorna esse dado convertido.
Na linha 12, chamamos a função register_converter, passando a string “BOOLEAN” e a função conv_bool (converter booleano) como argumentos.
A função conv_bool, definida na linha 9, retorna True para o caso do dado ser 1, ou False, caso contrário. Com isso, convertemos os inteiros 0 e 1 para os booleanos True e False.
O restante do script é igual ao anterior, porém, os dados estão convertidos para o tipo correto.
Verifique a saída do console e observe os tipos dos atributos nascimento e oculos. Agora são das classes date e bool!
SELEÇÃO DE REGISTROS UTILIZANDO JUNÇÃO
Na seção anterior, aprendemos a selecionar registros de apenas uma tabela, mas como podemos buscar registros de tabelas relacionadas?
No exemplo a seguir, Figura 23, vamos buscar os veículos e suas respectivas marcas. Vamos fazer isso por meio da junção de tabelas.
Após abrir a conexão e obter um cursor, selecionamos todos os registros da tabela Veiculo, utilizando o comando da linha 9, executado na linha 10.
Na linha 13, recuperamos todos os registros de veículos utilizando o método fetchall, que foram iterados na linha 14.
Na linha 15, criamos um objeto do tipo Veiculo utilizando o operador * e imprimimos os atributos placa e marca na linha 16.
Verifique no console que os valores do atributo marca são seus respectivos ids, 1 e 2. Isso ocorre, pois no banco de dados, armazenamos apenas uma referência à chave primária da entidade Marca.
E se quisermos substituir o id das marcas pelos seus respectivos nomes?
Para isso, precisamos realizar uma junção das tabelas Veiculo e Marca no comando SELECT.
O comando SELECT para junção de duas tabelas tem a seguinte sintaxe:
SELECT tab1.col1, tab1.col2, tab2.col1… FROM tab1 JOIN tab2 ON tab1.colN = tab2.colM;
Primeiro, definimos quais colunas serão retornadas utilizando a sintaxe nome_tabela.nome_coluna, depois indicamos as tabelas que desejamos juntar e, por último, indicamos como alinhar os registros de cada tabela, ou seja, quais são os atributos que devem ser iguais (colN e colM).
No exemplo a seguir, Figura 24, vamos criar um script de forma que o Veiculo tenha acesso ao nome da Marca, não ao id.
Após criar uma conexão e obter um cursor, definimos o comando SQL para recuperar os dados das tabelas Veiculo e Marca de forma conjunta.
Observe o comando SQL nas linhas 9 a 12 e destacado a seguir:
SELECT Veiculo.placa, Veiculo.ano, Veiculo.cor, Veiculo.motor, Veiculo.proprietario, Marca.nome FROM Veiculo JOIN Marca ON Marca.id = Veiculo.marca;
Vamos selecionar os atributos placa, ano, cor, motor e proprietário do Veiculo e juntar com o atributo nome da tabela Marca. Observe que não vamos utilizar o atributo id da Marca.
As tuplas retornadas serão similares à seguinte:
('AAA0001', 2001, 'Prata', 1.0, 10000000099, 'Marca A')
Na linha 16, recuperamos todos os registros de veículos, que foram iterados na linha 17.
Na linha 18, criamos um objeto do tipo Veiculo utilizando o operador * e imprimimos os atributos placa e marca na linha 19.
Observe pelo console, que agora o atributo marca do nosso objeto do tipo Veiculo contém o nome da Marca.
No próximo exemplo, vamos dar um passo além. Vamos atribuir ao atributo marca, do Veiculo, um objeto do tipo Marca. Desta forma, vamos ter acesso a todos os atributos da marca de um veículo.
Para isso, vamos fazer alguns ajustes no nosso modelo. Observe a Figura 25 a seguir.
Vamos começar pelo nosso modelo. Adicionamos o id ao construtor da classe Marca. Essa alteração foi feita para facilitar a criação do objeto do tipo Marca a partir da consulta no banco. Veremos o motivo mais à frente.
No script principal à esquerda da Figura 27, iniciamos o script com a abertura da conexão e criação do cursor.
Na sequência, na linha 9, criamos o comando SQL SELECT para retornar todas as colunas da tabela Veiculo e Marca, utilizando junção.
Na linha 11, executamos esse comando e os resultados da consulta foram recuperados na linha 14.
Na linha 15, iteramos sobre os registros recuperados.
Na linha 16, imprimimos cada tupla do registro da forma como foram retornados pelo conector. Vamos destacar um exemplo a seguir, que também pode ser observado no console.
('AAA0001', 2001, 'Prata', 1.0, 10000000099, 1, 1, 'Marca A', 'MA')
Destacado em vermelho, temos os atributos relacionados à entidade Veiculo e, em azul, temos os atributos relacionados à entidade Marca.
Na linha 17, utilizamos array slice para selecionar apenas os atributos da Marca. O resultado do slice para o exemplo anterior é a tupla (1, 'Marca A', 'MA'), onde temos os atributos id, nome e sigla. Essa tupla é utilizada em conjunto com o operador * para criarmos um objeto do tipo Marca. Como agora temos acesso ao id da Marca, foi necessário adicionar o id ao construtor da classe Marca.
Para ilustrar, após o slice e desempacotamento, a linha 17 pode ser traduzida para o seguinte código:
marca = Marca(1, 'Marca A', 'MA')
Na linha 18, utilizamos array slice para selecionar apenas os atributos do Veiculo, que retornou a tupla ('AAA0001', 2001, 'Prata', 1.0, 10000000099), onde temos os atributos placa, ano, cor, motor e proprietário. Observe que removemos o id da Marca no slice. Fizemos isso, pois ele será substituído pelo objeto marca criado na linha 17.
Após o slice e desempacotamento, a linha 18 pode ser traduzida para o seguinte código:
veiculo = Veiculo('AAA0001', 2001, 'Prata', 1.0, 10000000099, marca)
Na linha 19, imprimimos a placa do veículo e o nome da marca. Observe que o atributo marca, do Veiculo, faz uma referência ao objeto marca, por isso fomos capazes de acessar veiculo.marca.nome.
No final do script, fechamos a conexão e o cursor.
SELEÇÃO DE REGISTROS RELACIONADOS
Para finalizar, vamos recuperar todas as pessoas, com seus respectivos veículos e marcas.
Para isso, vamos transformar o script anterior em uma função, de forma que possamos utilizá-la no nosso script final. Observe a Figura 26 a seguir.
À direita da imagem, temos o script 19_4. Utilizamos como base o script do exemplo anterior, script19_3, para criar uma função que retorne uma lista dos veículos de uma determinada pessoa.
Essa função tem como parâmetros uma conexão e o cpf de uma pessoa. Esse cpf será utilizado para filtrar os veículos que ela possui. Para isso, utilizamos o delimitador “?” na linha 11 e passamos o cpf da pessoa como argumento para o comando execute da linha 14.
Na linha 15, criamos uma lista vazia, chamada veiculos. Essa lista será povoada com os veículos recuperados pela consulta ao longo do laço for das linhas 17 a 20.
Ao final, fechamos o cursor e retornamos a lista veiculos.
À esquerda da figura, temos nosso script final, script20, cujo objetivo é ter uma lista com as pessoas cadastradas no banco de dados, incluindo seus veículos e marcas.
Após criar a conexão e o cursor, criamos o comando SQL para recuperar as pessoas na linha 10, que foi executado na linha 11.
Na linha 14, criamos a variável do tipo lista pessoas e, na linha 15, recuperamos todos os registros das pessoas utilizando a função fetchall do cursor.
Na linha 16, iteramos pelas pessoas recuperadas e para cada uma, criamos um objeto do tipo Pessoa (linha 17) e recuperamos seus veículos (linha 18).
Para recuperar os veículos, utilizamos a função recuperar_veiculos do script 19_4, passando como argumento a conexão criada na linha 6 e o cpf da pessoa.
Na linha 19, adicionamos cada pessoa à listapessoas criada anteriormente.
Na linha 21, iteramos sobre a lista pessoas e imprimimos seu nome e a lista de veículos que possui.
Ao final, fechamos a conexão e o cursor.
Verifique a saída do console abaixo da figura.
CONCLUSÃO
CONSIDERAÇÕES FINAIS
Neste tema, visitamos as principais ações que podemos realizar na manipulação de registros em banco de dados.
Conhecemos as principais funcionalidades disponibilizadas pelas bibliotecas de gerenciamento de banco de dados que implementam a DB API 2.0, introduzida pela PEP 249.
Vimos como criar um banco de dados e iniciar uma conexão.
Além disso, aprendemos a aplicar as funcionalidades de inserção, remoção e atualização de registros.
Finalmente, empregamos as funcionalidades de recuperação de registros para selecionar e visualizar o conteúdo do banco de dados.
DESCRIÇÃO
Apresentação dos principais frameworks e bibliotecas necessárias para o desenvolvimento de aplicações de interface gráfica (GUI) no Python, Como adicionar widgets para montar a interface gráfica, Como implementar uma interface para incluir dados em tabela e localizar, alterar e excluir dados em tabela.
PROPÓSITO
Compreender como criar uma aplicação GUI em Python que interaja com um banco de dados, de modo a realizar as operações de inserção, consulta, alteração e exclusão de dados em uma tabela.
PREPARAÇÃO
Antes de iniciar o conteúdo deste tema, o aluno precisa ter instalado o Python versão 3, a IDE Spyder e o PostgreSQL.
OBJETIVOS
MÓDULO 1 - Identificar alguns dos principais frameworks e bibliotecas necessárias para a GUI
MÓDULO 2 - Descrever a adição de widgets e montagem da interface gráfica
MÓDULO 3 - Definir a interface para inclusão de dados em uma tabela no banco de dados
MÓDULO 4 - Identificar a interface para localização, alteração e exclusão de dados em tabela
INTRODUÇÃO
Cada vez mais, nós geramos e consumimos dados para poder realizar atividades que vão desde a abertura de uma conta bancária, até as informações que disponibilizamos nas redes sociais.
Portanto, é necessário entender como esses dados são gerenciados, pois são importantes para identificar pessoas, preferências, produtos, transações financeiras, entre tantas outras aplicações.
Para fazer esse gerenciamento, as aplicações fazem uso de sistemas gerenciadores de banco de dados, de modo a tornar possível a realização de operações de inserção, consulta, alteração e exclusão de dados.
Além disso, para que o usuário possa interagir de modo eficiente com o sistema, é importante que ele tenha à disposição uma interface gráfica que facilite o seu acesso às funcionalidades implementadas.
Nesse sentido, a linguagem Python aparece como uma opção muito eficaz para atingir esses objetivos, uma vez que oferece recursos para desenvolver aplicações que integrem interface gráfica com operações no banco de dados.
Ao longo deste trabalho, apresentaremos alguns dos principais frameworks e bibliotecas para desenvolver aplicações de interface gráfica, além de explorarmos como realizar aplicações no banco de dados.
MÓDULO 1
Identificar alguns dos principais frameworks e bibliotecas necessárias para a GUI
CONCEITOS
A linguagem Python possui muitos frameworks para desenvolvimento de aplicações de interface gráfica para interação com o usuário, chamadas, comumente, de GUI (Graphical User Interface).
O framework mais comum é o Tkinter(Python interface to Tcl/Tk (2020)) que já faz parte da instalação Python, mas existem outros frameworks que têm características específicas que podem torná-los a escolha adequada para um projeto.
Entre os frameworks para aplicações GUI mais comuns estão:
TKINTER
É o framework GUI padrão do Python. Sua sintaxe é simples, possui muitos componentes para interação com o usuário. Além disso, seu código é aberto e é disponível sob a licença Python. Caso ela não esteja instalada na sua versão do Python, basta digitar o comando:
pip install tkinter
Para quem usa a IDE Spyder, ver Spyder (2020), é necessário colocar uma exclamação antes do comando “pip”, ou seja, o comando, nesse caso, ficaria:
!pip install tkinter
Para testar a instalação, basta escrever na linha de comando o código abaixo:
import tkinter
tkinter._test()
Se a instalação ocorreu normalmente, vai aparecer uma tela com alguns componentes para que você possa interagir e ter uma impressão inicial do potencial desse framework, conforme a Figura 1.
Devido à importância do Tkinter, vamos explorá-lo com bastantes detalhes mais à frente.
FLEXX
É um kit de ferramentas para o desenvolvimento de interfaces gráficas com o usuário implementado em Python, que faz uso de tecnologia web para sua renderização. O Flexx pode ser usado para criar tanto aplicações de desktop, como para web e, até mesmo, exportar uma aplicação para um documento HTML independente. Para instalar o Flexx, basta digitar o comando:
pip install flexx
Para quem usa a IDE Spyder, é necessário colocar uma exclamação antes do comando “pip”, isso vale para qualquer instalação de biblioteca/framework/pacote.
COMENTÁRIO
Para evitar repetições sobre isso, apresentaremos aqui como instalar o pacote Flexx na IDE Spyder, mas, para os próximos casos, mostraremos apenas a instalação tradicional, ou seja, sem o símbolo de “exclamação”.
No caso do Spyder, o comando deve ser:
!pip install flexx
Uma forma prática de testar a instalação e aprender um pouco mais sobre esse framework, é escrever o código abaixo na linha de comando, ou em um arquivo e executar:
from flexx import flx
class Exemplo(flx.Widget):
def init(self):
flx.Button(text='Olá')
flx.Button(text='Mundo')
if __name__ == '__main__':
a = flx.App(Exemplo, title='Flexx demonstração')
m = a.launch()
flx.run()
Se a instalação estiver correta, vai abrir uma janela, conforme a Figura 2.
CEF PYTHON
É um projeto de código aberto voltado para o desenvolvimento de aplicações com integração ao Google Chrome. Existem muitos casos de uso para CEF. Por exemplo, ele pode ser usado para criar uma GUI baseada em HTML 5, pode usá-lo para testes automatizados, como também pode ser usado para web scraping, entre outras aplicações.
Para instalá-lo, basta digitar na linha de comando:
pip install cefpython3
Para testar a instalação do CEF Python, basta escrever o código abaixo na linha de comando, ou em um arquivo e executar:
from cefpython3 import cefpython as cef
import platform
import sys
def main():
check_versions()
sys.excepthook = cef.ExceptHook # To shutdown all CEF processes on error
cef.Initialize()
cef.CreateBrowserSync(url="https://www.google.com/",
window_title="Olá, mundo! Este é o primeiro exemplo do CEF Python")
cef.MessageLoop()
cef.Shutdown()
def check_versions():
ver = cef.GetVersion()
print("[hello_world.py] CEF Python {ver}".format(ver=ver["version"]))
print("[hello_world.py] Chromium {ver}".format(ver=ver["chrome_version"]))
print("[hello_world.py] CEF {ver}".format(ver=ver["cef_version"]))
print("[hello_world.py] Python {ver} {arch}".format(
ver=platform.python_version(),
arch=platform.architecture()[0]))
assert cef.__version__ >= "57.0", "CEF Python v57.0+ required to run this"
if __name__ == '__main__':
main()
ATENÇÃO
Como esse exemplo, apesar de simples, é um pouco maior, cabe lembrar que a indentação faz parte da sintaxe do Python (Python 3.8.5 documentation, 2020), por isso, é necessário ter bastante cuidado, caso contrário o programa vai apresentar erros.
Bem, se tudo funcionou corretamente, quando o programa executar, vai abrir uma janela conforme a Figura 3:
Observe o título da janela: “Olá, mundo! Este é o primeiro exemplo do CEF Python”.
KIVY
É um framework Python de código aberto para o desenvolvimento de aplicações com interfaces de usuário e multitoque. Ele é escrito em Python e Cython, baseado em OpenGL ES 2, suporta vários dispositivos de entrada e possui uma extensa biblioteca de componentes (widgets).
Com o mesmo código, a aplicação funciona para Windows, macOS, Linux, Android e iOS. Todos os widgets Kivy são construídos com suporte multitoque.
Para instalá-lo, é necessário escrever na linha de comando:pip install Kivy
Uma forma de testar a instalação é escrever e executar o programa:
from kivy.app import App
from kivy.uix.button import Button
class ExemploApp(App):
def build(self):
return Button(text='Olá, Mundo!')
ExemploApp().run()
Se tudo funcionar corretamente, vai aparecer a aplicação, conforme a Figura 4:
Na figura 4, é possível identificar o título da janela “Exemplo” e um componente botão no centro da tela com a mensagem “Olá, Mundo!”. Um ponto interessante pode ser observado no código, que é a utilização da programação orientada a objetos.
É um framework utilizado para o desenvolvimento de jogos. A instalação desse framework pode ser um pouco mais complicada do que os anteriores, em especial, por causa das dependências.
Muitos desses problemas são bem documentados e de fácil acesso na web.
PYFORMS
É um framework Python 3 para desenvolver aplicações que podem operar nos ambientes Desktop GUI, Terminal e Web. A biblioteca é composta por três sub-bibliotecas, cada uma implementando a camada responsável por interpretar a aplicação Pyforms em cada ambiente diferente, que são:
Pyforms-gui.
Pyforms-web.
Pyforms-terminal.
Essas camadas podem ser usadas individualmente, ou em conjunto, dependendo da instalação do Pyforms. Para fazer a instalação básica, é necessário escrever na linha de comando:
pip install pyforms
Uma forma de testar a instalação é escrever e executar o programa:
import pyforms
from pyforms.basewidget import BaseWidget
from pyforms.controls import ControlText
from pyforms.controls import ControlButton
class ExemploSimples(BaseWidget):
def __init__(self):
super(ExemploSimples,self).__init__('ExemploSimples')
#Definition of the forms fields
self._nome = ControlText('Nome', 'Default value')
self._sobrename = ControlText('Sobrenome')
self._nomeCompleto = ControlText('Nome completo')
self._button = ControlButton('Pressione o Botão')
#Execute the application
if __name__ == "__main__":
from pyforms import start_app
start_app(ExemploSimples)
Se tudo funcionar corretamente, vai aparecer a aplicação, conforme a Figura 5:
COMENTÁRIO
No exemplo da Figura 5, é possível ver três caixas de texto, chamadas de “controle de texto” e um componente botão, chamado de “controle de botão” pelo Pyforms. Ele foi projetado para desenvolver aplicações para executar no modo Windows GUI.
PYQT
Uma aplicação desenvolvida no framework PyQt executa nas plataformas Windows, macOS, Linux, iOS e Android.
Trata-se de um framework que aborda, além de desenvolvimento GUI, de abstrações de sockets de rede, threads, Unicode, expressões regulares, bancos de dados SQL, OpenGL, XML, entre outras aplicações.
Suas classes empregam um mecanismo de comunicação segura entre objetos que é fracamente acoplada, tornando mais fácil criar componentes de software reutilizáveis.
Para fazer a instalação básica, é necessário escrever na linha de comando:
pip install PyQt5
Uma forma de testar a instalação é escrever e executar o programa:
import sys
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QLabel, QGridLayout, QWidget
from PyQt5.QtCore import QSize
class HelloWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setMinimumSize(QSize(280, 120))
self.setWindowTitle("Olá, Mundo! Exemplo PyQT5")
centralWidget = QWidget(self)
self.setCentralWidget(centralWidget)
gridLayout = QGridLayout(self)
centralWidget.setLayout(gridLayout)
title = QLabel("Olá Mundo para PyQt", self)
title.setAlignment(QtCore.Qt.AlignCenter)
gridLayout.addWidget(title, 0, 0)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
mainWin = HelloWindow()
mainWin.show()
sys.exit( app.exec_() )
Se tudo funcionar corretamente, vai aparecer a aplicação, conforme a Figura 6:
No exemplo da Figura 6, é possível identificar uma janela, o título da janela e uma mensagem no centro.
WXPYTHON
É um kit de ferramentas GUI baseadas em uma biblioteca C++ chamada wxWidgets, que foi lançada em 1998. O wxPython usa os componentes (widgets) reais na plataforma nativa sempre que possível.
Essa, inclusive, é a principal diferença entre o wxPython e outros kits de ferramentas, como PyQt ou Tkinter.
ATENÇÃO
Desse modo, as aplicações desenvolvidas em wxPython se assemelham a aplicações nativas do sistema operacional em que estão sendo executados.
As bibliotecas PyQt e Tkinter têm componentes personalizados, é por isso que é bastante comum que as aplicações fiquem com um aspecto diferente das aplicações nativas do sistema operacional. Apesar disso, o wxPython também oferece suporte a componentes personalizados.
Para fazer a instalação básica, é necessário escrever na linha de comando:
pip install wxPython
Uma forma de testar a instalação é escrever e executar o programa:
import wx
class Janela(wx.Frame):
def __init__(self, parent, title):
super(Janela, self).__init__(parent, title=title, size = (400,300))
self.panel = ExemploPainel(self)
self.text_ctrl = wx.TextCtrl(self.panel, pos=(5, 5))
self.btn_test = wx.Button(self.panel, label='Pressione esse componente!', pos=(5, 55))
class ExemploPainel(wx.Panel):
def __init__(self, parent):
super(ExemploPainel, self).__init__(parent)
class ExemploApp(wx.App):
def OnInit(self):
self.frame = Janela(parent=None, title="Janela wxPython")
self.frame.Show()
return True
app = ExemploApp()
app.MainLoop()
Se tudo funcionar corretamente, vai aparecer a aplicação, conforme a Figura 7:
No exemplo da Figura 7, é possível identificar uma janela, o seu respectivo título, uma caixa de texto e um botão com a mensagem “Pressione esse componente!”.
PYAUTOGUI
Permite desenvolver aplicações Python que controlem o mouse e o teclado para automatizar as interações com outros aplicativos.
COMENTÁRIO
Uma das situações em que essa característica pode ser muito interessante é na implementação de testes que simulem a interação do usuário com o sistema.
O PyAutoGUI funciona no Windows, macOS e Linux e é executado no Python 2 e 3.
Para fazer a instalação básica, é necessário escrever na linha de comando:
!pip install PyAutoGUI
Uma forma de testar a instalação é escrever e executar o programa:
import pyautogui
screenWidth, screenHeight = pyautogui.size()
currentMouseX, currentMouseY = pyautogui.position()
pyautogui.moveTo(100, 150)
pyautogui.click()
pyautogui.click(100, 200)
pyautogui.move(0, 10)
pyautogui.doubleClick()
pyautogui.moveTo(500, 500, duration=2, tween=pyautogui.easeInOutQuad)
pyautogui.write('Olá, Mundo!', interval=0.25)
pyautogui.press('esc')
pyautogui.keyDown('shift')
pyautogui.press(['left', 'left', 'left', 'left'])
pyautogui.keyUp('shift')
pyautogui.hotkey('ctrl', 'c')
pyautogui.alert('Esta é a mensagem para Tela.')
Nesse código, basicamente, tem-se a seguinte sequência de instruções:
Obter o tamanho do monitor principal.
 Obter a posição XY do mouse.
 Mover o mouse para as coordenadas XY.
 Clicar com o mouse.
 Mover o mouse para as coordenadas XY e clicar nelas.
 Mover o mouse 10 pixels para baixo de sua posição atual.
Clicar duas vezes com o mouse.
Usar a função de interpolação/atenuação para mover o mouse por 2 segundos com pausa de um quarto de segundo entre cada tecla.
 Pressionar a tecla Esc.
 Pressionar a tecla Shift e segurá-la.
 Pressionar a tecla de seta para a esquerda 4 vezes.
Soltar a tecla Shift.
 Pressionar a combinação de teclas de atalho Ctrl-C.
 Mostrar uma caixa de alerta aparecer na tela e pausar o programa até clicar em OK.
Antes de executar o código, cabe um alerta: Essa aplicação, apesar de ser muito simples, vai interagir com o seu sistema.
Se tudo funcionar corretamente, vai aparecer a aplicação, conforme a Figura 8:
A figura 8 vai aparecer depois do “cursor do mouse” se movimentar na tela e o “teclado” escrever a mensagem “Esta é a mensagem para tela”.
As possibilidades de aplicações são muitas para o PyAutoGUI.
PYSIMPLEGUI
Esse pacote foi lançado em 2018 e possui portabilidade com os pacotes: Tkinter, PyQt, wxPython e Remi, portanto aumenta as possibilidades de uso de componentes na programação.
Para fazer a instalação básica, é necessário escrever na linhade comando:
pip install pysimplegui
Uma forma de testar a instalação é escrever e executar o programa:
import PySimpleGUI as sg
sg.theme('DarkAmber')
layout = [ [sg.Text('Texto na linha 1')],
[sg.Text('Entre com um texto na linha 2'), sg.InputText()],
[sg.Button('Ok'), sg.Button('Cancel')] ]
window = sg.Window('Bem-Vindo ao PySimpleGUI', layout)
while True:
event, values = window.read()
if event == sg.WIN_CLOSED or event == 'Cancel':
break
print('Você entrou com: ', values[0])
window.close()
Se tudo funcionar corretamente, vai aparecer a aplicação, conforme a Figura 9:
No exemplo da Figura 9, é possível identificar uma janela, o seu respectivo título, dois componentes “label”, uma caixa de texto e dois botões.
ATENÇÃO
A lista de frameworks e bibliotecas disponíveis para Python ainda tem muitos outros exemplos, como o PySide e o PyObject. A escolha deve levar em consideração a maturidade da biblioteca/framework e da necessidade de o projeto incorporar ou não aspectos mais elaborados de uma GUI.
VANTAGENS E DESVANTAGENS DE UMA INTERFACE GUI
Agora, discutiremos sobre alguns dos aspectos do desenvolvimento de um projeto de interface gráfica.
VANTAGENS
Entre as principais vantagens relacionadas às escolhas por uma determinada biblioteca/framework para um projeto da interface GUI, estão:
Facilitar a interação do usuário com o sistema através da utilização de componentes intuitivos.
Simplicidade de utilizar os componentes em um programa.
Compatibilidade do componente com múltiplas plataformas.
Criar uma camada de abstração para o programador sobre detalhes da programação dos componentes.
Incorporação de aspectos que facilitem a experiência do usuário com o sistema.
Facilitar que o usuário possa alternar rapidamente entre as funcionalidades do sistema.
Ser bem documentada e com uma comunidade engajada, o que ajuda a perceber novas aplicações e evoluções dos componentes que vão melhorar a aplicação dos componentes GUI no sistema.
DESVANTAGENS
Também devem ser levadas em consideração as desvantagens relacionadas às escolhas de bibliotecas/frameworks da interface GUI. Entre essas desvantagens, estão:
Alguns componentes de interface gráfica usam muitos recursos computacionais, pois têm como objetivo ser amigáveis para o usuário, e não necessariamente fazer uso otimizado dos recursos. Como consequência, podem tornar as aplicações muitos lentas para plataformas de versões mais antigas.
O uso dos componentes na programação pode ser excessivamente complexo, fazendo com que o desenvolvedor tenha que desviar esforço do objetivo principal para se preocupar com detalhes dos componentes GUI.
As bibliotecas disponibilizam componentes, mas a aplicação deles no sistema é responsabilidade do desenvolvedor. Além de se preocupar com aspectos de programação, é necessário se preocupar como esses componentes vão ser disponibilizados no sistema, pois, caso contrário, algumas tarefas podem ser mais demoradas devido a muitos níveis de interação para selecionar a escolha desejada, como, por exemplo, o uso excessivo de menus e submenus.
Os componentes precisam ter comportamentos previsíveis. Comportamentos inesperados são potencialmente perigosos, pois podem dar acesso não autorizado a partes do sistema, revelando, assim, vulnerabilidades de segurança.
Sistemas baseados em componentes GUI requerem mais memória RAM para serem executados.
Ainda sobre uso de recursos computacionais, sistemas baseados em componentes GUI demandam por processamento.
Podem ter um comportamento distinto, quando operam em diferentes plataformas, tanto na parte visual, como pela demanda de recursos computacionais.
O tempo necessário para utilizar os componentes GUI no sistema pode ser longo, em especial, quando há necessidade de atender a muitos requisitos de infraestrutura.
A Curva de Aprendizado para profissionais não experientes pode ser proibitiva para o desenvolvimento de projetos de curto de prazo.
Assista ao vídeo a seguir e aprenda a criar uma aplicação com interface gráfica. Neste vídeo, você verá a apresentação do protótipo de sistema que será desenvolvido, os frameworks a serem utilizados e a preparação do ambiente para utilização.
MÓDULO 2
Descrever a adição de widgets e montagem da interface gráfica
CONCEITOS
Neste módulo, o nosso foco será na criação de uma aplicação GUI. Para isso, a biblioteca que vamos usar como referência é a Tkinter.
COMENTÁRIO
Essa biblioteca GUI é considerada a padrão para desenvolvimento de interface gráfica no Python. Ela fornece uma interface orientada a objetos que facilita a implementação de programas interativos.
Para usar o Tkinter – supondo que você já instalou o Pyhton e o pacote Tkinter ‒ é necessário executar as seguintes etapas:
Importar a biblioteca Tkinter. 
Criar a janela principal do programa GUI. 
Adicionar um ou mais dos widgets (componentes).
 Entrar no loop de evento principal para tratar os eventos disparados pelo usuário.
O código fica conforme abaixo:
import tkinter
janela = tkinter.Tk()
janela.mainloop()
Esse programa produz a seguinte saída, conforme a Figura 10.
WIDGETS TKINTER
O Tkinter possui diversos componentes (widgets), tais como botões, rótulos e caixas de texto usados para criar aplicações interativas com o usuário.
Os principais widgets do Tkinter, de acordo com Meier (2015), são:
	Botão (Button)
	É usado para exibir os botões na aplicação. São usados, por exemplo, para confirmar uma ação de salvar os dados.
	Telas (Canvas)
	É usado para desenhar formas, como linhas, ovais, polígonos e retângulos.
	Botão de verificação (Checkbutton)
	É usado para exibir várias opções como caixas de seleção. O usuário pode selecionar várias opções ao mesmo tempo.
	Entrada de texto (Entry)
	É usado para exibir uma caixa de texto de linha única para que o usuário digite valores de entrada.
	Quadros (Frame)
	É usado como um widget de contêiner, isso significa que outros componentes são adicionados a ele com o objetivo de organizar outros widgets.
	Rótulo (Label)
	É usado para fornecer uma legenda de linha única para outros widgets. Também pode conter imagens.
	Caixa de listagem (Listbox)
	É usado para fornecer uma lista de opções para um usuário.
	Menubutton
	É usado para exibir opções no menu.
	Menu
	É usado para fornecer várias possibilidades de comandos a um usuário. Esses comandos estão contidos no Menubutton.
	Mensagem (Message)
	É usado para exibir uma mensagem de texto e um botão para o usuário confirmar uma ação.
	Botão de rádio (Radiobutton)
	É usado para exibir várias opções, como botões de rádio. O usuário pode selecionar apenas uma opção por vez.
	Escala (Scale)
	É usado para fornecer um widget de controle deslizante.
	Barra de rolagem (Scrollbar)
	É usado para adicionar capacidade de rolagem a vários widgets.
	Texto (Text)
	É usado para exibir texto em várias linhas.
	Toplevel
	É usado para fornecer um contêiner de janela separado.
	Spinbox
	É uma variante do widget Entry padrão. Ele é usado para selecionar um número fixo de valores.
	PanedWindow
	É um widget de contêiner que pode conter qualquer número de painéis, organizados horizontalmente ou verticalmente.
	LabelFrame
	É um widget de contêiner simples. Seu objetivo principal é atuar como um espaçador, ou contêiner para layouts de janela.
	tkMessageBox
	Este módulo é usado para exibir caixas de mensagens.
Cada um desses widgets possuem propriedades que permitem personalizar tamanhos, cores e fontes que serão exibidos para o usuário.
Na próxima seção, apresentaremos alguns exemplos que vão ajudar a entender como desenvolver uma aplicação GUI.
DESENVOLVENDO EXEMPLOS DE APLICAÇÕES GUI
DICA
Antes de iniciar esta seção, é fortemente recomendado que você tenha feito a instalação da versão mais atual do Python e tente executar os exemplos.
Vamos apresentar exemplos dos componentes:
Window
Label
Button
Entry
Radiobutton
Checkbox
Text
Message
Sliders
Dialog
Combobox
WIDGET WINDOW (TK.TK())
Para iniciar, a primeira aplicação vai exibir uma janela redimensionável, conforme a Figura 11.
O código dessa aplicação é:
importtkinter as tk
janela = tk.Tk()
janela.title("Aplicação GUI")
janela.mainloop()]
Agora, cada uma das linhas será analisada.
LINHA 1
É feita a importação da biblioteca Tkinter.
LINHA 2
É criada uma instância da classe Tk no objeto “janela”.
LINHA 3
O método “title” é usado para definir um título que aparece no topo da janela, no caso, “Aplicação GUI”.
LINHA 4
A aplicação inicia o loop de evento principal da janela.
Bem, a janela da aplicação anterior é redimensionável, ou seja, o usuário pode alterar as dimensões da janela, se ele clicar com o cursor do mouse na janela e arrastá-la.
Para fixar o tamanho da janela, é necessário determinar essa propriedade conforme o código abaixo:
import tkinter as tk
janela = tk.Tk()
janela.title("Aplicação GUI NÃO Dimensionável")
janela.resizable(False, False)
janela.mainloop()
ATENÇÃO
A principal diferença desse exemplo em relação ao anterior está na linha 4, onde a propriedade de redimensionar a janela é colocada como “Falso”.
WIDGET LABEL
O próximo exemplo apresenta como usar o widget “Label”. O código para gerar uma aplicação com o “Label” é dado por:
import tkinter as tk
from tkinter import ttk
janela = tk.Tk()
janela.title("Aplicação GUI com o Widget Label")
ttk.Label(janela, text="Componente Label").grid(column=0, row=0)
janela.mainloop()
Na Figura 12, é exibido o resultado da execução:
Na linha 5, é feito o posicionamento do componente “label” na “janela” com o gerenciador de layout “grid”.
WIDGET BUTTON
O próximo exemplo apresenta como usar o widget “Button”.
O código para gerar uma aplicação com o componente “Button” é dado por:
import tkinter as tk
contador = 0
def contador_label(lblRotulo):
def funcao_contar():
global contador
contador = contador + 1
lblRotulo.config(text=str(contador))
lblRotulo.after(1000, funcao_contar)
funcao_contar()
janela = tk.Tk()
janela.title("Contagem dos Segundos")
lblRotulo = tk.Label(janela, fg="green")
lblRotulo.pack()
contador_label(lblRotulo)
btnAcao = tk.Button(janela, text='Clique aqui para Interromper a contagem', width=50, command=janela.destroy)
btnAcao.pack()
janela.mainloop()
Este programa vai gerar uma janela com um contador de segundos – que utiliza um componente “label” – e um componente botão com a mensagem “Clique aqui para interromper a contagem”.
Na Figura 13, é exibido o resultado da execução do programa.
As linhas mais importantes deste código são:
LINHA 14
Chamada para a função “contador_label”, que é a função que faz a contagem dos segundos e a atualização dos dados do componente “label”.
LINHA 15
Criação de uma instância do componente “botão” com uma mensagem, largura do componente e o estabelecimento de um comportamento, no caso, fechar a janela, quando o usuário pressionar o botão.
WIDGET ENTRY
Agora, vamos analisar o componente “entry”. Este componente é uma das principais formas do usuário entrar com dados no sistema.
A seguir, é apresentado um exemplo de como usar este componente:
import tkinter as tk
def mostrar_nomes():
print("Nome: %s\nSobrenome: %s" % (e1.get(), e2.get()))
janela = tk.Tk()
janela.title("Aplicação GUI com o Widget Entry")
tk.Label(janela,
text="Nome").grid(row=0)
tk.Label(janela,text="Sobrenome").grid(row=1)
e1 = tk.Entry(janela)
e2 = tk.Entry(janela)
e1.grid(row=0, column=1)
e2.grid(row=1, column=1)
tk.Button(janela, text='Sair',
command=janela.quit).grid(row=3,
column=0,
sticky=tk.W,
pady=4)
tk.Button(janela, text='Exibir Dados', command=mostrar_nomes).grid(row=3,
column=1,
sticky=tk.W,
pady=4)
tk.mainloop()
O código vai produzir uma janela com duas entradas de dados (widgets entry), dois botões e dois componentes rótulos, conforme podemos ver na Figura 14.
Os códigos que estamos apresentando estão evoluindo em termos de aplicações práticas.
No caso do exemplo da Figura 14, com poucas modificações, pode ser aplicado para muitas situações reais.
Agora, analisaremos os principais aspectos do código.
LINHA 2
É implementada a função “mostrar_nomes”, que vai exibir na linha de comando os nomes que estão escritos nas instâncias “e1” e “e2” do componente “entry”.
LINHAS 8 E 9
São feitas as instâncias “e1” e “e2” do componente entry.
LINHAS 10 E 11
“e1” e “e2” são posicionados na janela.
LINHAS 12 E 13
São instanciados objetos do componente “botão”. Em especial, na linha 13, a função “mostrar_nomes” é associada ao comportamento do botão.
WIDGET RADIOBUTTON
O próximo exemplo apresenta como usar o widget “Radiobutton”. O código para gerar uma aplicação com esse componente é dado por:
import tkinter as tk
janela = tk.Tk()
v = tk.IntVar()
tk.Label(janela,
text="""Escolha uma linguagem de programação:""",
justify = tk.LEFT, padx = 20).pack()
tk.Radiobutton(janela,
text="Python",
padx = 25,
variable=v,
value=1).pack(anchor=tk.W)
tk.Radiobutton(janela,
text="C++",
padx = 25,
variable=v,
value=2).pack(anchor=tk.W)
janela.mainloop()
O código vai produzir uma janela com dois “botões de rádio” (widgets radiobutton), conforme a Figura 15.
LINHA 4
É instanciado um componente “label” com a parametrização das propriedades “text”, “justify” e “padx” que correspondem, respectivamente, ao texto, como vai ser justificado e qual a largura em pixels do componente.
LINHAS 5 E 6
São instanciados os componentes “radiobuttons”. Cabe destacar a propriedade “variable”, que recebe o valor “v”, que indica que o componente será colocado na vertical.
WIDGET CHECKBOX
O próximo exemplo apresenta como usar o widget “checkbox”. O código para gerar uma aplicação com esse componente é dado por:
import tkinter as tk
from tkinter import ttk
janela = tk.Tk()
def escolha_carreira():
print("Gerencial: %d,\nTécnica : %d" % (var1.get(), var2.get()))
ttk.Label(janela, text="Escolha sua vocação:").grid(row=0, sticky=tk.W)
var1 = tk.IntVar()
ttk.Checkbutton(janela, text="Gerencial", variable=var1).grid(row=1, sticky=tk.W)
var2 = tk.IntVar()
ttk.Checkbutton(janela, text="Técnica", variable=var2).grid(row=2, sticky=tk.W)
ttk.Button(janela, text='Sair', command=janela.quit).grid(row=3, sticky=tk.W, pady=4)
ttk.Button(janela, text='Mostrar', command=escolha_carreira).grid(row=4, sticky=tk.W, pady=4)
janela.mainloop()
O código vai produzir uma janela com um “label”, dois “checkboxes” e dois botões, conforme a Figura 16.
Agora, vamos analisar os principais aspectos do código.
LINHA 4
É implementada a função “escolha_carreira”, que vai exibir os valores dos objetos “var1” e “var2” que estão relacionadas aos “checkboxes”.
LINHAS 7 E 9
São instanciados os objetos “var1” e “var2”, que serão associados aos “checkboxes”. Quando um “checkbox” for selecionado, o seu respectivo objetivo vai retornar valor 1, caso o componente não seja selecionado, o valor do objeto será 0.
LINHAS 8 E 10
São instanciados objetos dos componentes “checkboxes”, que são associados, respectivamente, às opções Gerencial e Técnica.
WIDGET TEXT
O próximo exemplo apresenta como usar o widget “Text”. O código para gerar uma aplicação com o componente “Text” é dado por:
import tkinter as tk
janela = tk.Tk()
T = tk.Text(janela, height=2, width=30)
T.pack()
T.insert(tk.END, "Este é um texto\ncom duas linhas\n")
tk.mainloop()
O código vai produzir uma janela com um texto, conforme a Figura 17.
Agora, vamos analisar os principais aspectos do código.
LINHA 3
É feita uma instância do componente “Text”.
LINHAS 5
É inserido um texto na instância do componente “text”, que vai ser exibido na tela. Observe que o texto é separado em duas linhas com o uso do “\n”.
WIDGET MESSAGE
O próximo exemplo apresenta como usar o widget “Message”. O código para gerar uma aplicação com o componente “Message” é dado por:
import tkinter as tk
janela = tk.Tk()
mensagem_para_usuario = "Esta é uma mensagem.\n(Pode ser bastante útil para o usuário)"
msg = tk.Message(janela, text = mensagem_para_usuario)
msg.config(bg='lightgreen', font=('times', 24, 'italic'))
msg.pack()
janela.mainloop()
O código vai produzir uma janela com uma mensagem, conforme pode ser visto na Figura 18.
Agora, vamos analisar os principais aspectos do código.
LINHA 4
É instanciado um componente “Message” com uma mensagempara o usuário.
LINHAS 5
O componente é configurado, determinando a cor do “background” e detalhes sobre a fonte da mensagem.
WIDGET SLIDER
O próximo exemplo apresenta como usar o widget “Slider”. O código para gerar uma aplicação com esse componente é dado por:
import tkinter as tk
from tkinter import ttk
def mostrar_valores():
print (w1.get(), w2.get())
janela = tk.Tk()
w1 = ttk.Scale(janela, from_=0, to=50)
w1.pack()
w2 = ttk.Scale(janela, from_=0, to=100, orient=tk.HORIZONTAL)
w2.pack()
ttk.Button(janela, text='Mostrar a Escala', command=mostrar_valores).pack()
janela.mainloop()
O código vai produzir uma janela com duas linhas deslizantes, conforme a Figura 19.
Agora, vamos analisar os principais aspectos do código.
Nas linhas 6 e 8, são instanciados componentes “sliders”.
Além disso, são determinadas as propriedades “from”, “to” e “orient”, que são responsáveis, respectivamente, pelo espectro de escala componente e a orientação do componente na tela.
WIDGET DIALOG
O próximo exemplo apresenta como usar o widget “Dialog”. O código para gerar uma aplicação com o componente “Dialog” é dado por:
import tkinter as tk
from tkinter import messagebox as mb
def resposta():
mb.showerror("Resposta", "Desculpe, nenhuma resposta disponível!")
def verificacao():
if mb.askyesno('Verificar', 'Realmente quer sair?'):
mb.showwarning('Yes', 'Ainda não foi implementado')
else:
mb.showinfo('No', 'A opção de Sair foi cancelada')
tk.Button(text='Sair', command=verificacao).pack(fill=tk.X)
tk.Button(text='Resposta', command=resposta).pack(fill=tk.X)
tk.mainloop()
O código vai produzir uma janela com dois botões, conforme a Figura 20.
RESPOSTA
Caso o usuário pressione o botão “Resposta”, vai aparecer uma janela com a mensagem “Desculpe, nenhuma resposta disponível!”, conforme a Figura 21.
SAIR
Caso o usuário tenha pressionado o botão “Sair”, vai aparecer uma janela com a mensagem “Realmente quer sair?”, conforme a Figura 22.
YES
Caso o usuário pressione o botão “Yes”, vai aparecer uma janela com a mensagem “Ainda não foi implementado”, conforme a Figura 23.
NO
Por outro lado, se o usuário pressionar o botão “No” da janela da Figura 22, vai ser exibida uma janela com a mensagem “A opção de Sair foi cancelada”, conforme a Figura 24.
Agora, vamos analisar os principais aspectos do código.
Nas linhas 4, 6, 7 e 9, são instanciados componentes “messageDialog”.
Esse exemplo é bastante interessante, pois, apesar de pouca implementação, é possível que o usuário tenha bastante interação com o sistema.
WIDGET COMBOBOX
O próximo exemplo apresenta como usar o widget “Combobox”. O código para gerar uma aplicação com esse componente é dado por:
import tkinter as tk
from tkinter import ttk
# Criação de uma janela tkinter
janela = tk.Tk()
janela.title('Combobox')
janela.geometry('500x250')
# Componente Label
ttk.Label(janela, text = "Combobox Widget",
background = 'green', foreground ="white",
font = ("Times New Roman", 15)).grid(row = 0, column = 1)
# Componente Label
ttk.Label(janela, text = "Selecione um mês :",
font = ("Times New Roman", 10)).grid(column = 0,
row = 5, padx = 10, pady = 25)
# Componente Combobox
n = tk.StringVar()
escolha = ttk.Combobox(janela, width = 27, textvariable = n)
# Adição de itens no Combobox
escolha['values'] = (' Janeiro',
' Fevereiro',
' Março',
' Abril',
' Maio',
' Junho',
' Julho',
' Agosto',
' Setembro',
' Outubro',
' Novembro',
' Dezembro')
escolha.grid(column = 1, row = 5)
escolha.current()
janela.mainloop()
O código vai produzir uma janela com um “combobox”, conforme a Figura 25.
Agora, vamos analisar os principais aspectos do código.
LINHA 17
É instanciado um componente “combobox”.
LINHAS 19 A 30
Os meses do ano são atribuídos ao componente.
Agora, o vídeo a seguir dá continuidade e projeta a interface gráfica. No vídeo, serão carregados os widgets necessários para o funcionamento do protótipo.
“Desenvolver um programa em que seja possível realizar as operações CRUD para gerenciar uma agenda telefônica que vai tratar de nomes e números de telefones”.
CRUD
Acrônimo da expressão do idioma Inglês, Create (Criação), Read (Consulta), Update (Atualização) e Delete (Destruição).
A ideia é desenvolvermos uma aplicação CRUD, para que os usuários possam interagir com o sistema para inserir, modificar, consultar e excluir dados de uma agenda telefônica e que essas operações fiquem sob a responsabilidade do sistema gerenciador de banco de dados.
DICA
Inicialmente, é necessário ter o PostgreSQL instalado. Os exemplos apresentados aqui foram implementados na versão 4.24 do PostgreSQL.
O script para criação da tabela é dado por:
CREATE TABLE public."AGENDA"
(
id integer NOT NULL,
nome text COLLATE pg_catalog."default" NOT NULL,
telefone char(12) COLLATE pg_catalog."default" NOT NULL
)
TABLESPACE pg_default;
ALTER TABLE public."AGENDA"
OWNER to postgres;
Para testar se a criação da tabela está correta, pode-se inserir um registro da seguinte maneira:
INSERT INTO public."AGENDA"( id, nome, telefone)
VALUES (1, 'teste 1', '02199999999');
Em seguida, fazemos uma consulta na tabela, conforme abaixo:
SELECT * FROM public."AGENDA";
Se tudo funcionar corretamente, vai aparecer a seguinte saída:
Bem, agora, vamos estudar o pacote que será utilizado para que o Python possa interagir com o PostgreSQL: psycopg2.
ATENÇÃO
O PostgreSQL pode ser integrado ao Python usando o módulo psycopg2. Trata-se de um adaptador de banco de dados PostgreSQL. O pacote psycopg2 é simples, rápido e estável.
Para instalá-lo, basta digitar na linha de comando do Python:
pip install psycopg2
Para poder interagir com o banco de dados PostgreSQL com o uso da biblioteca psycopg2, primeiro é necessário criar um objeto Connection que representa o banco de dados e, em seguida, pode-se criar um objeto cursor que será bastante útil para executar todas as instruções SQL. Isso será detalhado um pouco mais à frente.
Antes disso, porém, vamos apresentar as principais APIs (rotinas de interface de programação) da psycopg2:
PSYCOPG2.CONNECT (DATABASE = "NOMEDOBANCODEDADOS", USER = "LOGINDOUSUÁRIO", SENHA = "SENHADOBANCODEDADOS", HOST = "ENDEREÇODAAPLICAÇÃO", PORTA = "NÚMERODAPORTA")
A conexão com o banco de dados PostgreSQL é feita com essa API. O banco de dados retorna um objeto de conexão, se o banco de dados for aberto com sucesso. Para aplicações que vão rodar localmente, utiliza-se o endereço de localhost dado por 127.0.0.1". A porta de comunicação padrão do PostgreSQL é a "5432", mas esse valor pode ser mudado.
CONNECTION.CURSOR ()
Esta API cria um cursor que será usado ao longo da programação para interagir com o banco de dados com Python.
CURSOR.EXECUTE (SQL [, PARÂMETROS OPCIONAIS])
Esta rotina é aplicada para executar uma instrução SQL. A instrução SQL pode ser parametrizada. Por exemplo, seja o trecho de código abaixo:
nomeDaTabela = 'tabelaExemplo'
cursor.execute(
"insert into %s values (%%s, %%s)" % nomeDaTabela,
[10, 20])
O comando vai executar a instrução “insert” para inserir os valores 10 e 20 na tabela ‘tabelaExemplo’.
CURSOR.EXECUTEMANY (SQL, SEQUÊNCIA_DE_PARÂMETROS)
Esta rotina executa um comando SQL em todas as sequências de parâmetros. Por exemplo, seja o trecho de código:
carros = (
(1, 'Celta', 35000),
(2, 'Fusca', 30000),
(3, 'Fiat Uno', 32000)
)
con = psycopg2.connect(database='BancoExemplo', user='postgres',
password='postgres')
cursor = con.cursor()
query = "INSERT INTO cars (id, nome, preco) VALUES (%s, %s, %s)"
cursor.executemany(query, carros)
O trecho de código começa com uma lista de três carros, na qual cada carro possui um código de identificação, nome e um preço.
Em seguida, é feita uma conexão com o banco de dados “BancoExemplo”.
Logo depois, é criado o cursor que vai ser usado para realizar as operações sobre o banco de dados.
Por fim, é executada a rotina “executemany”, sendo que ela recebe uma query e uma lista de carros que serão inseridos no banco de dados.
CURSOR.CALLPROC ('NOMEDAFUNÇÃO_OU_NOMEDOPROCEDIMENTOARMAZENADO', [PARÂMETROS IN E OUT,])
Esta rotina faz chamada parauma função, ou procedimento armazenado do banco de dados. Os parâmetros IN e OUT correspondem, respectivamente, aos parâmetros de entrada e saída da função, ou procedimento armazenado e devem ser separados por vírgulas.
CURSOR.ROWCOUNT
Este atributo retorna o número total de linhas do banco de dados que foram modificadas, inseridas ou excluídas pela última instrução de “execute“.
CONNECTION.COMMIT()
Este método confirma a transação atual. É necessário que ele seja chamado ao final de uma sequência de operações sql, pois, caso contrário, tudo o que foi feito desde a última chamada até o “commit” não será visível em outras conexões de banco de dados.
CONNECTION.ROLLBACK()
Este método reverte quaisquer mudanças no banco de dados desde a última chamada até o “commit”.
CONNECTION.CLOSE()
Este método fecha a conexão com o banco de dados. Ele não chama o “commit” automaticamente. Se a conexão com o banco de dados for fechada sem chamar o “commit” primeiro, as alterações serão perdidas.
CURSOR.FETCHONE()
Este método busca a próxima linha de um conjunto de resultados de consulta, retornando uma única sequência, ou nenhuma, quando não há mais dados disponíveis.
CURSOR.FETCHMANY([SIZE = CURSOR.ARRAYSIZE])
Esta rotina busca o próximo conjunto de linhas de um resultado de consulta, retornando uma lista. Uma lista vazia é retornada quando não há mais linhas disponíveis. O método tenta buscar quantas linhas forem indicadas pelo parâmetro “size”.
CURSOR.FETCHALL()
Esta rotina busca todas as linhas (restantes) de um resultado de consulta, retornando uma lista. Uma lista vazia é retornada quando nenhuma linha está disponível.
UM EXEMPLO COMPLETO
Agora, apresentaremos um exemplo completo de como usar o psycopg2. O exemplo vai abordar:
Criação de uma tabela
Inserção de dados
Seleção de dados
Atualização de dados
Exclusão de dados
Agora, vamos aos exemplos que implementam as operações CRUD.
CRIAÇÃO DE TABELA
Este primeiro código mostra como criar uma tabela a partir do Python. É uma alternativa em relação a criar a tabela usando o PostgreSQL.
import psycopg2
conn = psycopg2.connect(database = "postgres", user = "postgres", password = "senha123", host = "127.0.0.1", port = "5432")
print("Conexão com o Banco de Dados aberta com sucesso!")
cur = conn.cursor()
cur.execute('''CREATE TABLE Agenda
(ID INT PRIMARY KEY NOT NULL,
Nome TEXT NOT NULL,
Telefone CHAR(12));''')
print("Tabela criada com sucesso!")
conn.commit()
conn.close()
Depois de colocar o programa para executar, se tudo funcionar corretamente, aparecerão as mensagens na tela:
Conexão com o Banco de Dados feita com Sucesso!
Tabela criada com sucesso!
Agora, vamos analisar o código.
LINHAS 1
É feita a importação da biblioteca psycopg2.
LINHA 2
É feita a conexão com o banco de dados. Observe os parâmetros da função “connect”, pois é necessário que você crie um banco no PostgreSQL com usuário e senha, conforme escrito na função.
LINHA 3
É exibida uma mensagem de sucesso para o usuário.
LINHA 4
É criado o cursor que vai permitir realizar operações no banco de dados.
LINHA 5
Executa o comando SQL para criar a tabela “Agenda” com os campos “ID”, “Nome” e “Telefone”.
LINHA 9
É exibida uma mensagem de criação da tabela com sucesso.
LINHA 10
É executada a função “commit” para confirmar a execução das operações SQL.
LINHAS 11
Por fim, é fechada a conexão com o banco de dados.
INSERÇÃO DE DADOS NA TABELA
O exemplo desse código mostra como inserir um registro em uma tabela a partir do Python usando a biblioteca psycopg2.
import psycopg2
conn = psycopg2.connect(database = "postgres", user = "postgres", password = " senha123", host = "127.0.0.1", port = "5432")
print ("Conexão com o Banco de Dados aberta com sucesso!")
cur = conn.cursor()
cur.execute("""INSERT INTO public."AGENDA" ("id", "nome", "telefone") VALUES (1, 'Pessoa 1', '02199999999')""")
conn.commit()
print("Inserção realizada com sucesso!");
conn.close()
As mensagens que vão aparecer depois da execução do programa são:
Conexão com o Banco de Dados feita com Sucesso!
Inserção realizada com sucesso!
Vamos analisar o código.
LINHAS 1 A 4
São realizadas as mesmas operações do exemplo anterior: Importação da biblioteca “psycopg2”, abrir a conexão com o banco de dados “postgres” e impressão da mensagem “Conexão aberta com sucesso!”.
LINHA 5
É executado o comando SQL para inserir dados na tabela AGENDA.
No caso, o registro é formado pelos seguintes dados: O campo “id” recebe o valor 1, o campo “nome” recebe o valor ‘Pessoa 1’ e, por fim, o campo “telefone” recebe o valor ‘02199999999’.
Essa linha tem mais algumas questões que merecem destaque: O uso de aspas simples e duplas.
No caso do banco de dados PostgreSQL, o nome da tabela e dos campos deve estar entre aspas duplas, por causa disso é que o comando insert possui três aspas duplas logo no início e no final. Sendo assim, muita atenção com isso, pois existem algumas variações conforme o sistema gerenciador de banco de dados escolhido.
LINHAS 6 A 8
Do mesmo modo como foi realizado no exemplo de criação da tabela “Agenda”, são realizadas as seguintes operações: “commit” das operações do banco de dados, fechamento da conexão com o banco de dados, impressão na linha de comando da mensagem “Inserção realizada com sucesso!”.
SELEÇÃO DE DADOS NA TABELA
Antes de descrever o exemplo de seleção de dados, já podemos perceber algo em comum em todas as operações dos códigos para trabalhar com banco de dados no início do código:
Importação da biblioteca “psycopg2”.
Abertura da conexão com o banco de dados “postgres”.
POSTGRES
Perceba que esse nome não é do sistema gerenciador de banco de dados, e sim um nome que escolhemos. Poderia ser, por exemplo, “banco_dados_teste”.
E no final do código:
“Commit” das operações realizadas no banco de dados para confirmar a execução delas. Esse comando é obrigatório.
Fechamento da conexão com o banco de dados.
Agora, vamos analisar o código que mostra como selecionar um registro em uma tabela a partir da biblioteca psycopg2 do Python.
import psycopg2
conn = psycopg2.connect(database = "postgres", user = "postgres", password = " senha123", host = "127.0.0.1", port = "5432")
print ("Conexão com o Banco de Dados aberta com sucesso!")
cur = conn.cursor()
cur.execute("""select * from public."AGENDA" where "id" = 1""")
registro = cur.fetchone()
print(registro)
conn.commit()
print("Seleção realizada com sucesso!");
conn.close()
Depois de colocar o programa para executar, se tudo funcionar corretamente, aparecerão as mensagens na tela:
Conexão com o Banco de Dados feita com Sucesso!
(1, 'Pessoa 1', '02199999999 ')
Tabela criada com sucesso!
Vamos analisar os trechos mais importantes do código.
LINHA 5
É feita a consulta na tabela “Agenda” pelo registro com “id” igual a 1, através do comando Select do SQL.
LINHA 6
É executado o método “fetchone” que recupera exatamente um registro do “cursor” e atribui para a variável “registro”.
LINHA 7
É impresso na linha de comando o resultado da consulta armazenado na variável “registro”.
ATUALIZAÇÃO DE DADOS NA TABELA
Este exemplo mostra como atualizar os registros de uma tabela a partir do Python.
import psycopg2
conn = psycopg2.connect(database = "postgres", user = "postgres", password = "senha123", host = "127.0.0.1", port = "5432")
print ("Conexão com o Banco de Dados aberta com sucesso!")
cur = conn.cursor()
print("Consulta antes da atualização")
cur.execute("""select * from public."AGENDA" where "id" = 1""")
registro = cur.fetchone()
print(registro)
#Atualização de um único registro
cur.execute("""Update public."AGENDA" set "telefone" = '02188888888' where "id" = 1""")
conn.commit()
print("Registro Atualizado com sucesso! ")
cur = conn.cursor()
print("Consulta depois da atualização")
cur.execute("""select * from public."AGENDA" where "id" = 1""")
registro = cur.fetchone()
print(registro)
conn.commit()
print("Seleção realizada com sucesso!");
conn.close()
Este código possui três partes distintas, que são:
ETAPA 01
Uma consulta antes da atualização: Que mostra os dados do registro antes de serem modificados.ETAPA 02
A atualização do registro que vai modificar os dados.
ETAPA 03
Uma consulta depois da atualização do registro: Que mostra como ficaram os dados do registro depois de serem atualizados.
ATENÇÃO
A linha 10 é a mais importante deste código. É nela que é executado o comando “update” do sql, que vai atualizar o dado do campo “telefone” do registro, cujo campo “id” contenha o valor “1”.
Perceba, ainda, que é associado o comando “commit” para o comando “update” do sql na linha 11.
EXCLUSÃO DE DADOS NA TABELA
Por fim, vamos ver o exemplo para excluir um registro de uma tabela.
import psycopg2
conn = psycopg2.connect(database = "postgres", user = "postgres", password = "senha123", host = "127.0.0.1", port = "5432")
print ("Conexão com o Banco de Dados aberta com sucesso!")
cur = conn.cursor()
cur.execute("""Delete from public."AGENDA" where "id" = 1""")
conn.commit()
cont = cur.rowcount
print(cont, "Registro excluído com sucesso! ")
print("Exclusão realizada com sucesso!");
conn.close()
Depois de colocar o programa para executar, se tudo funcionar corretamente, aparecerão as mensagens na tela:
Conexão com o Banco de Dados aberta com Sucesso!
1 Registro excluído com sucesso!
Exclusão realizada com sucesso!
Vamos analisar as partes mais importantes do código.
LINHA 5
É executado o comando “delete” do sql que vai excluir o registro cujo campo “id” seja igual a “1”.
LINHA 7
A propriedade “rowcount” do “cursor” retorna a quantidade de registros que foram excluídos da tabela “Agenda”.
LINHA 8
É impresso na linha de comando o total de registros que foram excluídos.
VOCÊ SABIA
Outras bibliotecas para interface com banco de dados.
Além da biblioteca psycopg2, existem outras bibliotecas para trabalhar com vários sistemas gerenciadores de banco de dados. Por exemplo:
pyMySQL: Biblioteca que faz interface com o mysql.
cx_Oracle: Biblioteca que faz interface com o oracle.
PySqlite: Biblioteca que faz interface com o sqlite.
PyMongo: Biblioteca que faz interface com o mongodb, que é um banco de dados NoSQL.
O vídeo a seguir dá continuidade ao desenvolvimento do protótipo do sistema, apresentando a modelagem do banco de dados a ser utilizado, criando o banco e fazendo as inserções/atualizações/remoções necessárias.
MÓDULO 4
Identificar a interface para localização, alteração e exclusão de dados em tabela
CONCEITOS
Até o dado momento, vimos como criar uma aplicação com componentes de interface gráfica e como interagir com um banco de dados.
Neste módulo, criaremos uma aplicação que integra tanto elementos de interface gráfica quanto operações com banco de dados.
A nossa aplicação implementa as operações CRUD, que são: Inserção, seleção, atualização e exclusão de dados.
O usuário vai fazer a entrada de dados através de componentes de caixas de texto (widget entry) e confirmar a ação que deseja, quando pressionar o botão correspondente.
Além disso, os dados que estão armazenados no banco são exibidos em um componente do tipo grade (widget treeview). O usuário tem a possibilidade de selecionar um registro na grade e ele será exibido nas caixas de texto, onde poderão ser modificados ou excluídos.
Na Figura 26, está a interface gráfica da nossa aplicação.
ATENÇÃO
Perceba que alguns dados já estão armazenados no banco e são exibidos na grade. Outra coisa, veja que o usuário selecionou o “produto_7” na grade e seus dados estão exibidos nas caixas de texto.
CRIAÇÃO DA TABELA NO POSTGRESQL
A primeira ação a ser feita é a criação da tabela.
COMENTÁRIO
No caso do nosso sistema, vamos criar a tabela Produto, que tem três campos, que são “CODIGO”, “NOME” e “PRECO”.
Estamos usando o PostgreSQL para gerenciar os nossos dados. O PostgreSQL é um sistema gerenciador de banco de dados de licença gratuita e é considerado bastante robusto para aplicações de um modo geral.
Através da ferramenta pgAdmin, o desenvolvedor pode criar a tabela produto.
Na Figura 27, vemos como criar uma tabela no pgAdmin.
O campo “owner” é o usuário proprietário do banco de dados que terá acesso à tabela “PRODUTO”. No caso, usamos o usuário padrão do PostgreSQL.
Em seguida, precisamos criar os campos tabelas. Para isso, selecionamos a opção “Columns” da Figura 27. Agora, vai ser exibida a tela da Figura 28, na qual podemos adicionar as colunas através da opção “+” no canto superior direito da tela.
Perceba que o campo “CODIGO” é a chave primária da tabela e, além disso, todos os campos não podem ser vazios.
Agora, salvamos a tabela e, finalmente, ela é criada no banco de dados. Na Figura 29, podemos ver a tabela no pgAdmin.
O pgAdmin é bastante útil para fazermos operações sobre as tabelas. Na Figura 30, mostramos como inserir dados na tabela “PRODUTO”.
Para executar o comando de inserção, basta pressionar a seta no canto direito superior da tela.
Outra forma de criar uma tabela é através do próprio Python, com o uso da biblioteca “psycopg2”.
Na Figura 31, mostramos o código para criação da tabela “PRODUTO”. O código para criação da tabela pode ser baixado clicando aqui.
Agora, cada uma das linhas será analisada.
LINHA 8
Importamos a biblioteca psycopg2.
LINHA 9
Fazemos a conexão ao banco de dados “postgres” com o usuário “postgres”, senha “senha123”, host local (127.0.0.1) e porta “5432”.
LINHA 13
Abrimos o cursor. Lembre-se de que é com o cursor que fazemos as operações no banco de dados.
LINHAS 14 A 16
Executamos o comando sql “Create Table” para criar a tabela “PRODUTO” com os campos “CODIGO”, “NOME” e “PRECO”.
LINHA 18
Executamos o comando “commit” para confirmar o comando sql.
LINHA 19
Fechamos a conexão com o banco de dados.
GERAÇÃO DE DADOS ALEATÓRIOS
Uma boa forma de iniciar o projeto é inserindo dados aleatórios na tabela. Para isso, vamos usar o pacote “faker”, que é bastante útil para gerar dados aleatórios.
Na Figura 32, mostramos o código para gerar os dados aleatórios.
LINHA 15
Importamos a biblioteca “faker”.
LINHA 22
Instanciamos um objeto para gerar dados aleatórios no “português do Brasil”.
LINHAS 25 A 31
Geramos os dados aleatórios que serão inseridos na tabela.
LINHAS 34 E 35
Montamos o comando sql. Mas nesse momento, trata-se apenas de um texto (string) que deve seguir uma sintaxe cuidadosa: Três aspas duplas no início e no final do texto. Além disso, perceba os “%s” no trecho do “VALUES” que serão usados para entrar com os dados das variáveis.
LINHA 36
Criamos um registro com as variáveis que serão armazenadas na tabela.
LINHA 37
Aplicamos o comando “execute”, que executa o comando sql com a entrada de dados que definimos na variável registro.
COMENTÁRIO
Esse exemplo é simples, mas ilustra testes que podem ser feitos logo no começo do projeto que são úteis para validar a entrada de dados, além de ser útil para os desenvolvedores aprenderem mais sobre o próprio sistema.
INTERAÇÃO COM O BANCO DE DADOS
Nesta seção, apresentaremos a parte do sistema responsável pelas operações CRUD.
O sistema foi desenvolvido usando programação orientada a objetos. O arquivo do programa foi salvo com o nome “crud.py”.(./docs/crud.zip)
A classe com os métodos para realizar as operações para interagir com o banco de dados é a “AppBD”, conforme podemos ver na Figura 33.
Antes de continuar, lembre-se de que a indentação (espaçamento) faz parte da sintaxe do Python.
LINHA 12
Declaramos a classe “AppBD”.
LINHA 13
Implementamos o construtor da classe, que é o método que é chamado logo que um objeto da classe AppBD for instanciado.
LINHAS 16 A 25
Implementamos o método para abrir a conexão. Perceba as cláusulas “try” e “except”. Isso é fundamental para criar um programa confiável, ou seja, com tolerância a falhas, pois o programa tenta seguir o fluxo normal de execução, ou seja, abrir a conexão com o banco de dados.
COMENTÁRIO
Caso ocorra algum problema, ao invés de o programa interromper a execução e exibir uma mensagem de erro, que pode revelar vulnerabilidades do sistema, que podem ser exploradas por um atacante, vai exibir uma mensagem amigável para o usuário, no caso, será “Falha ao se conectar ao Banco de Dados”.
O próximo método éo que faz consulta no banco de dados, conforme podemos ver na Figura 34.
Vamos destacar os principais pontos do método “selecionarDados”.
LINHA 35
Montamos a instrução de consulta do sql.
LINHA 38
Executamos a instrução sql.
LINHA 39
Recuperamos as linhas que retornaram da consulta sql.
LINHA 52
Retornamos os registros para quem faz a chamada para o método “selecionarDados”.
Agora, vamos explicar o método para fazer a inserção de dados. O código do método está na Figura 35.
LINHA 56
Implementamos a função “inserirDados” e passamos como parâmetros os “codigo”, “nome” e “preco” que serão inseridos na tabela. Além disso, passamos o parâmetro “self”, que é usado para fazer referência aos atributos e métodos da própria classe.
LINHAS 60 E 61
Montamos a instrução sql para fazer a inserção dos dados.
LINHA 62
Montamos o registro que será inserido na tabela.
LINHA 63
Executamos a instrução sql para fazer a inserção do registro da variável “record_to_insert”.
Agora, vamos analisar o método responsável pela atualização de dados. O código é apresentado na Figura 36.
LINHA 80
Implementamos a função “atualizarDados” e passamos como parâmetros os “codigo”, “nome” e “preco” que serão modificados na tabela.
LINHAS 92 E 93
Montamos a instrução sql para fazer a modificação dos dados da tabela.
LINHA 94
Executamos a instrução sql para fazer a modificação do registro de acordo com a tupla “(nome, preco, codigo)”.
Agora, vamos analisar o método que trata da exclusão de dados. O código é apresentado na Figura 37.
LINHA 116
Implementamos a função “excluirDados” e passamos o “codigo” do produto, que será excluído da tabela.
LINHAS 121 E 122
Montamos a instrução sql para fazer a exclusão dos dados da tabela.
LINHA 123
Executamos a instrução sql para fazer a exclusão do registro de acordo com o parâmetro “codigo” passado para o método.
INTERFACE GRÁFICA
Nesta seção, vamos apresentar a parte do sistema responsável pela interação com o usuário através de uma interface gráfica.
Do mesmo modo que a classe “AppBD”, esse programa também foi desenvolvido em programação orientada a objetos.
O arquivo do programa foi salvo com o nome “aplicacaoCRUD.py”. A classe com os atributos e métodos para trabalhar com a interface gráfica e interagir com a classe responsável pelas operações com o banco de dados é a “PrincipalBD”, conforme podemos ver na Figura 38.(./docs/aplicacaoCRUD.zip)
LINHA 9
Importamos a biblioteca Tkinter para interagir com os componentes gráficos.
LINHAS 10
Importamos o módulo ttk para podermos trabalhar com o componente “TreeView”, que foi usado como uma grade para exibir os dados armazenados na tabela “PRODUTO”.
LINHAS 14
Implementamos o construtor ( __init__ ) da classe PrincipalBD, que será chamado logo que um objeto do tipo PrincipalBD for instanciado.
LINHAS 17 A 23
Instanciamos os componentes rótulos (“label”) e caixas de texto (“entry”).
LINHAS 24 A 27
Instanciamos os componentes botões (“button”), que vão acionar as operações CRUD.
ATENÇÃO
Observe que os métodos “fCadastrarProduto”, “fAtualizarProduto”, “fExcluirProduto” e “fLimparProduto” estão vinculados aos botões, ou seja, quando o usuário pressionar um botão, o respectivo método será chamado.
O construtor ainda possui mais duas partes. Uma delas é responsável por instanciar e configurar o componente “TreeView”, conforme podemos ver na Figura 39.
Observe nas linhas 52 e 53 que o método “apresentarRegistrosSelecionados” é vinculado à instância do componente “TreeView”. Esse método será explicado mais à frente.
E a outra posiciona os componentes na tela, conforme podemos ver na Figura 40.
Observe que, na linha 73, fazemos chamada para o método “carregarDadosIniciais”. Mais à frente, vamos explicá-lo com mais detalhes.
Agora, vamos analisar o método “apresentarRegistrosSelecionados”, conforme podemos ver na Figura 41.
Este método exibe os dados selecionados na grade (componente “TreeView”) nas caixas de texto, de modo que o usuário possa fazer alterações, ou exclusões sobre eles.
LINHA 76
Fazemos a chamada para a função “fLimparTela”, que limpa o conteúdo das caixas de texto.
LINHA 77
Obtemos os registros que foram selecionados na grade de registros.
LINHA 79
Os dados do item selecionados são, agora, associados às variáveis “codigo”, “nome” e “preco”.
LINHAS 80 A 82
Os valores das variáveis são associados às caixas de texto.
Agora, vamos analisar o método “carregarDadosIniciais”, que é apresentado na Figura 42.
Este método carrega os dados que já estão armazenados na tabela para serem exibidos na grade de dados (componente “TreeView”).
LINHAS 86 E 87
Os atributos “id” e “iid” são iniciados com valor 0. Eles são necessários para gerenciar o componente “TreeView”.
LINHA 88
É feita a chamada para o método “selecionarDados” que está na classe “AppBD”. Ele recupera todos os registros armazenados na tabela.
LINHAS 91 A 93
Obtemos os valores dos registros e associamos às respectivas variáveis.
LINHAS 98 A 102
Os dados são adicionados ao componente “TreeView”.
Agora, vamos apresentar o método “fLerCampos”, conforme podemos ver na Figura 43.
Este método lê os dados que estão nas caixas de texto e os retorna para quem faz a chamada.
Por exemplo, na linha 114, a variável “codigo” recebe o valor da caixa de texto “txtCodigo” depois que ele é convertido para um valor do tipo “inteiro”.
Na linha 123, as variáveis “codigo”, “nome” e “preco” retornam para quem faz a chamada do método.
Agora, vamos apresentar o método “fCadastrarProduto”, conforme podemos ver na Figura 44.
Este método tem como objetivo fazer a inserção dos dados na tabela “PRODUTOS”.
LINHA 130
Os dados digitados nas caixas de texto são recuperados nas variáveis “codigo”, “nome” e “preco”.
LINHA 131
Fazemos a chamada ao método “inserirDados”, que fará a inserção dos dados na tabela “PRODUTO”.
LINHAS 132 A 136
Os dados são inseridos no componente grade (“TreeView”).
Agora, vamos analisar o método “fAtualizarProduto”, conforme podemos ver na Figura 45.
O objetivo deste método é atualizar os dados que o usuário selecionou na grade de dados (o componente “TreeView”).
LINHA 149
Os dados selecionados da grade de dados são recuperados nas variáveis “codigo”, “nome” e “preco”.
LINHA 150
Chamamos a função “atualizarDados”, que fará as modificações dos dados na tabela “PRODUTO”.
LINHA 152
Os dados selecionados são removidos da grade de dados.
LINHA 153
Fazemos a chamada ao método “carregarDadosIniciais” para recarregar a grade de dados com os dados da tabela.
Agora, vamos analisar o método “fExcluirProduto”, conforme podemos ver na Figura 46.
O objetivo deste método é excluir os dados que o usuário selecionou na grade de dados (o componente “TreeView”).
LINHA 164
Os dados selecionados da grade de dados são recuperados nas variáveis “codigo”, “nome” e “preco”.
LINHA 165
Chamamos a função “excluirDados”, que vai excluir os dados da tabela “PRODUTO”.
LINHA 167
Os dados selecionados são removidos da grade de dados.
LINHA 169
Fazemos a chamada ao método “carregarDadosIniciais” para recarregar a grade de dados com os dados da tabela.
Agora, vamos analisar o método “fLimparTela”, conforme podemos ver na Figura 47.
Este método limpa o conteúdo das caixas de texto, conforme podemos ver nas linhas 179 a 181.
Por fim, apresentamos o programa principal que vai iniciar a execução do sistema, conforme podemos ver na Figura 49.
LINHA 188
Instanciamos o objeto raiz da aplicação gráfica que chamamos de “janela”.
LINHA 189
Instanciamos o objeto principal que vai gerenciar a execução da aplicação.
LINHA 190
Escrevemos uma mensagem para o título da janela.
LINHA 191
Configuramos as dimensões da janela.
LINHA 192
Chamamos o método “mainloop”, que coloca a aplicação para executar até que o usuário interrompa a execução.
CONCLUSÃO
CONSIDERAÇÕES FINAIS
No decorrer do texto, apresentamos os principais frameworks e bibliotecas para desenvolver aplicações de interface gráfica, exploramos a biblioteca “tkinter” com exemplos para usar os seus componentes gráficos e também a biblioteca “psycopg2”, pararealizar operações no PostgreSQL, além de apresentarmos uma aplicação que integra interface gráfica com operações no banco de dados.
A linguagem Python facilita bastante o desenvolvimento de aplicações de interface gráfica e que façam operações no banco de dados. É natural que o desenvolvedor iniciante tenha a impressão de que é um projeto complexo, mas, com um pouco de prática, as vantagens de programar nesse ambiente vão ficar evidentes.
O Python é uma linguagem muito bem documentada e possui uma comunidade engajada em resolver problemas e disponibilizar as soluções em ambientes públicos. Exploramos algumas bibliotecas, mas existem muitas outras. A escolha de uma delas deve levar em consideração questões como tempo para desenvolvimento, maturidade do programador e quais os recursos computacionais que se têm à disposição.
DESCRIÇÃO
Aplicação da metodologia de desenvolvimento rápido de software (RAD) com descrição do levantamento de requisitos, modelagem de negócios e de dados, Design de interface com o usuário e uma aplicação prática com o uso da linguagem de programação Python.
PROPÓSITO
Compreender a aplicação da metodologia RAD para o desenvolvimento de um sistema.
PREPARAÇÃO
Antes de iniciar o conteúdo deste tema, o aluno precisa ter instalado o Python versão 3.8.5 e a IDE Spyder.
OBJETIVOS
MÓDULO 1 - Descrever as etapas para tratamento dos requisitos de um sistema na metodologia de desenvolvimento rápido de software (RAD)
MÓDULO 2 - Descrever as modelagens de negócios e de dados da RAD
MÓDULO 3 - Definir o design de interface com o usuário na RAD
MÓDULO 4 - Esquematizar uma aplicação RAD implementada em Python
INTRODUÇÃO
A metodologia de desenvolvimento rápido de software (RAD) é caracterizada por um processo evolutivo em que usuários e desenvolvedores são engajados através de entregas de versões funcionais do sistema que, apesar de incompletas, permitem que a colaboração seja otimizada.
Os usuários podem operar essas versões e fazer comentários, críticas e sugestões que auxiliam bastante os desenvolvedores a direcionar seus esforços para atender, de fato, às necessidades do cliente. Essas versões parciais são chamadas de protótipos e a ideia é que, ao longo do processo, avancem no sentido de se tornarem a versão final do sistema.
Aspectos como custo-benefício, uso efetivo de tempo, alcançar a satisfação do cliente e controlar riscos são abordados pela RAD através da rápida verificação de inconsistências e alinhamento de entendimento.
Ao longo do texto, abordaremos as etapas de requisitos de um sistema, as modelagens de negócios e de dados e o design da interface com o usuário. No último módulo, apresentaremos uma aplicação RAD simples desenvolvida com o uso da linguagem de programação Python.
MÓDULO 1
Descrever as etapas para tratamento dos requisitos de um sistema na metodologia de desenvolvimento rápido de software (RAD)
REQUISITOS
CONTEXTUALIZAÇÃO
O desenvolvimento rápido de software (RAD) é uma abordagem iterativa e incremental, portanto é um modelo para a construção de software caracterizado pela adaptabilidade, prototipagem rápida e colaboração das partes interessadas.
A ênfase da metodologia está na intensificação da colaboração entre as partes interessadas, ao invés de estar no planejamento do que será feito. É uma forma de as equipes colaborarem com mais sinergia para que desenvolvam aplicações com mais rapidez.
COMENTÁRIO
Além disso, o progresso do desenvolvimento pode ser medido facilmente através da evolução do protótipo, que é a principal forma de maximizar a comunicação entre desenvolvedores e usuários sobre melhorias, ou mudanças do sistema. Os objetivos da RAD são bem definidos: Maior eficiência no uso do tempo das partes envolvidas, comunicação mais produtiva e processo de desenvolvimento otimizado.
A RAD faz uso de ferramentas de desenvolvimento que padronizam a implementação dos sistemas e apoiam os desenvolvedores na implementação de interfaces gráficas com o usuário, manipulação de dados, desenvolvimentos de APIs e outros serviços que poupam o tempo do desenvolvedor, para que possa usá-lo de forma mais eficiente para a implementação do sistema. Segundo Martin (1991), a RAD possui quatros fases distintas, que são:
	Quatro fases da RAD
	Fase de planejamento de requisitos:
	Trata das necessidades de negócios, escopo do projeto, restrições e requisitos do sistema.
	Fase de design do usuário:
	Nessa fase, são desenvolvidos modelos e protótipos para representar todos os processos, entradas e saídas do sistema.
	Fase de construção:
	É nesta fase que os protótipos são desenvolvidos.
	Fase de transição:
	Aqui, são feitos processamento de dados, testes, mudança para o novo sistema e treinamento do usuário.
A seguir, trataremos detalhadamente a fase de planejamento de requisitos.
FASE DE PLANEJAMENTO DE REQUISITOS
CONCEITOS
Independentemente da metodologia que seja empregada para desenvolver um software, é um fato que todo sistema é desenvolvido com um propósito. Para chegar a esse objetivo, um conjunto de itens, chamado de requisitos, deve ser implementado.
 SAIBA MAIS
A área que trata desse assunto é a Engenharia de Requisitos. Ela tem como metas a identificação, modelagem, comunicação e documentação dos requisitos de um sistema e em quais situações ele vai operar. O modo como os requisitos serão implementados é uma decisão que deve ser tomada pela equipe de desenvolvimento.
Os requisitos do sistema basicamente descrevem o que deve ser feito. É importante garantir que eles sejam completos, não se contradigam e que sejam relevantes para o desenvolvimento do sistema.
REQUISITOS
Quanto maior o detalhamento dos requisitos logo no começo do projeto, menores serão as chances de haver a necessidade de mudanças no sistema, quando o desenvolvimento já estiver avançado.
A Engenharia de Requisitos consiste em cinco atividades principais (vide Pressman, 2011):
Elicitação: Identifica os requisitos do sistema.
Análise: Elenca os elementos necessários para tratar os requisitos.
Documentação: Comunica as partes envolvidas sobre o entendimento dos requisitos.
Validação: O que foi implementado deve ser o que foi solicitado.
Gerenciamento: Consiste na priorização dos requisitos.
A seguir, cada uma dessas atividades será detalhada.
ELICITAÇÃO DE REQUISITOS
A elicitação de requisitos, ou ainda, levantamento de requisitos, tem por objetivo identificar os requisitos do sistema e em qual contexto será feita a operação deste com o apoio das partes interessadas. Por contexto, entende-se: Qual é o domínio da aplicação, quais as necessidades do negócio, quais são as restrições do sistema, a quem se destina e quais os pormenores da operação, a fim de obter uma melhor compreensão do sistema a ser desenvolvido.
Entrevistar as partes interessadas é um método para descobrir fatos e opiniões de usuários em potencial e evitar mal-entendidos que podem comprometer o desenvolvimento do sistema. As entrevistas podem ser de dois tipos:
FECHADAS
As partes interessadas respondem um conjunto predefinido de perguntas.
ABERTAS
O engenheiro de requisitos e as partes interessadas discutem o que esperam do sistema.
As entrevistas são vantajosas por fornecerem informações úteis para os desenvolvedores. A desvantagem é que, por se tratar de informações subjetivas, o entrevistador deverá estar atento com a possibilidade de informações conflitantes. Dada a importância do levantamento de requisitos para todo o projeto, é necessário fazer uso de técnicas que auxiliem extrair a maior quantidade de informações úteis. Entre essas técnicas, estão:
CASOS DE USO:
São usados para descrever as interações entre os usuários e o sistema. Eles especificam uma sequência de interações entre um sistema e um ator externo (por exemplo, uma pessoa, uma peça de hardware, outro produto de software). Os requisitos funcionais do sistema de software são representados pelos Casos de Uso, que são, portanto, um importante instrumento para que analistas e usuários possam interagir e validar o entendimento dos requisitos.
OS CENÁRIOS:
Têm porobjetivo simular situações de interações entre os usuários e o sistema. Na descrição dos cenários, deve ser informado como o sistema estava antes de o usuário começar a interação e como ficou depois de esta ter sido concluída.
OBSERVAÇÃO E ANÁLISE SOCIAL:
Aqui, um analista observa os usuários enquanto trabalham e faz anotações. A principal vantagem desta técnica é mostrar o modo como os usuários realmente trabalham e não uma descrição idealizada de como devem trabalhar.
GRUPOS FOCAIS:
É formado por grupos com visão de partes do sistema, os quais ajudam a identificar as necessidades e percepções dos usuários.
BRAINSTORMING: A
Ou tempestade cerebral, é uma reunião em que os participantes podem desenvolver soluções criativas para problemas específicos. Esse processo tem duas fases: A de geração, na qual as ideias são coletadas, e a de avaliação, em que as ideias coletadas são discutidas.
PROTOTIPAGEM:
A ideia é desenvolver aplicações rápidas que ajudem a entender melhor os requisitos do sistema como um todo. Os protótipos podem ser descartáveis e evolutivos.
ANÁLISE DE REQUISITOS
Todas as questões relacionadas aos requisitos são tratadas pela análise de requisitos, desde a determinação das precedências, da consistência deles (ou seja, não devem ser contraditórios entre si), da integridade dos requisitos (isto quer dizer que nenhum serviço ou restrição estará ausente) até a viabilidade dos requisitos. Portanto, a análise preocupa-se em verificar se a implementação dos requisitos é viável com o orçamento e cronograma disponíveis para o desenvolvimento do sistema. A partir da negociação de priorização com as partes interessadas, os conflitos são resolvidos. A principal técnica usada para análise de requisitos são sessões JAD.
 SAIBA MAIS
As sessões JAD ― Acrônimo do inglês para Joint Application Development ― são oficinas de trabalho em que os desenvolvedores e clientes discutem sobre o sistema. O objetivo da JAD é detalhar a solução, de modo que seja possível extrair elementos passíveis de monitoramento até que o projeto seja concluído. Depois da extração dos requisitos, é necessário priorizá-los para estabelecer um cronograma de trabalho que contemple o uso eficiente de recursos e atenda às expectativas do cliente.
DOCUMENTAÇÃO DE REQUISITOS
Nesta etapa, o objetivo é comunicar os requisitos do sistema para as partes interessadas: Clientes e desenvolvedores. O documento de requisitos é a referência para avaliar o sistema, ou seja, para construir testes diversos, verificação e validação e para fazer o controle de mudanças. Esse documento é essencial para que haja concordância entre as partes envolvidas e pode, inclusive, fazer parte do contrato.
GERENCIAMENTO DE REQUISITOS
A captura, o armazenamento, a disseminação e o gerenciamento de informações compõem o gerenciamento de requisitos. Portanto, é nessa etapa que as atividades relacionadas ao controle de mudança e versão, rastreamento de requisitos e dos estados dos requisitos são tratadas. A rastreabilidade de requisitos mapeia a conexão entre requisitos, design e implementação de um sistema para gerenciar mudanças em um sistema.
MODELO TRADICIONAL DE ENGENHARIA DE REQUISITOS APLICADO PARA DESENVOLVIMENTO RÁPIDO DE SOFTWARE (RAD)
Segundo Pressman (2011), o modelo tradicional de engenharia de requisitos para desenvolvimento rápido de software tem as seguintes etapas:
Alguns dos problemas para aplicar técnicas de engenharia de requisitos dos modelos tradicionais para a RAD são:
A RAD se caracteriza por ser um processo evolutivo no qual é incluída uma característica para o projeto em cada ciclo de desenvolvimento. Isso ocorre porque existe a premissa de que os usuários evoluem o seu entendimento do projeto com a análise das entregas, portanto o modelo tradicional é inadequado quando tenta levantar todos os requisitos logo no início do desenvolvimento.
O modelo tradicional não trata de forma específica dos conflitos que podem ocorrer com a implementação dos requisitos ao longo do projeto, como é o caso da RAD em que o projeto vai incorporando sugestões dos usuários ao longo das iterações.
Os mecanismos de priorização de requisitos no modelo tradicional de engenharia de requisitos não se aplicam a projetos baseados na RAD, pois a cada iteração de desenvolvimento do protótipo é necessário estabelecer quais são os requisitos de alta prioridade.
Na RAD, quando o cliente faz sugestões a partir da análise do protótipo, é necessário gerenciar as prioridades do que vai ser implementado para a próxima versão. Os modelos tradicionais não tratam de como deve ser feito o gerenciamento dessas mudanças.
Como visto, então, a RAD precisa de um tratamento específico para fazer o gerenciamento dos requisitos.
MODELO DE ENGENHARIA DE REQUISITOS PARA RAD
A elicitação de requisitos é a principal etapa na RAD. Isto ocorre porque o protótipo depende dela. A técnica mais utilizada para levantamento de requisitos na RAD é a JAD(Joint Application Development). Nas oficinas JAD, as partes interessadas discutem o sistema e definem seus requisitos. São sessões em que as partes interessadas ― usuários e desenvolvedores ― debatem sobre as necessidades do negócio. Isto é muito útil para direcionar o desenvolvimento do projeto e remover todas as ambiguidades a respeito dos requisitos. Assim, ganha-se tempo, que é um recurso caro e limitado para qualquer projeto.
Ao final da extração dos requisitos pela JAD, é necessário analisá-los. Isso é necessário para garantir sua integridade e consistência. Uma das técnicas comumente utilizadas para análise de requisitos é o gerenciamento de conflitos.
MODAL
A gestão de conflitos vai tratar das possíveis contradições que surgiram na JAD. Como a RAD tem como característica desenvolver protótipos, é fundamental que os conflitos, se existirem, sejam removidos, pois não faz sentido implementar um protótipo com requisitos conflitantes.
Agora, depois da remoção dos conflitos entre os requisitos, é necessário fazer a priorização deles para poder partir para o desenvolvimento do protótipo. Seguindo uma sequência lógica, no protótipo, primeiro desenvolve-se as principais funcionalidades do sistema. Uma técnica usada para isso é a classificação por cartões, que consiste na atribuição de “graus de importância” para cada requisito. Dessa forma, é possível comparar as prioridades das diferentes partes interessadas.
ETAPA 1
Na classificação por cartões, todas as funcionalidades do sistema são escritas em cartões individuais. Em seguida, os cartões são dados para todos os participantes das oficinas de trabalho.
ETAPA 2
Cada um atribui a prioridade que acha ser a adequada para o requisito e mostra para os demais. Após algumas rodadas, todos os cartões têm algumas prioridades. Em seguida, faz-se a análise dos graus de todos os cartões para analisar os dados.
ETAPA 3
Depois de analisados, é feita a priorização das funcionalidades com as quais todas as partes interessadas concordam. Trata-se de uma técnica colaborativa e orientada para atender às necessidades do cliente.
Com a priorização dos requisitos definida, passa-se para a documentação deles. Trata-se da formalização do acordo sobre o entendimento dos requisitos entre as partes interessadas. Uma das técnicas para fazer a documentação dos requisitos é através da especificação de requisitos de software. Essa técnica também é utilizada pelos modelos tradicionais para documentação dos requisitos.
Agora, sim, chega-se à principal característica do ciclo de vida de desenvolvimento da RAD, que é a implementação do protótipo.
O protótipo é um programa funcional com um escopo reduzido que reflete para onde o desenvolvimento do sistema está sendo direcionado. O desenvolvimento é feito a partir da priorização dos requisitos, que significa que, inicialmente, as principais funcionalidades do sistema devem ser implementadas.
Terminado o protótipo, ele é apresentado para ser validado pelo cliente. Essa é a etapa mais importante em qualquer ciclo de vida de desenvolvimento, pois todo sistema tem um propósito e, quem o avalia,é o usuário. Na RAD, a validação do protótipo é muito importante para direcionar quais serão as ações a serem tomadas para a próxima iteração.
ATENÇÃO
Na validação do protótipo, o cliente o verifica com base na documentação dos requisitos. No caso de o protótipo corresponder aos requisitos, ele será válido e a próxima fase é a de design. Mas se o cliente rejeitar o protótipo e solicitar melhorias, então será necessário ir para o gerenciamento de requisitos.
O desenvolvimento rápido de software pode ser um método muito eficaz, desde que sejam observados os pré-requisitos para sua aplicação. A RAD cria um ambiente colaborativo e criativo em que as partes interessadas podem participar de um projeto muito detalhado. Com a RAD, pode-se obter resultados rápidos e ideias de sucesso que, dificilmente, seriam implementadas nos modelos tradicionais. É um fato, no entanto, que a RAD também tem suas desvantagens. Seu uso depende de uma equipe de trabalho com diversas habilidades e motivada que se adéque rapidamente a mudanças ao longo do projeto.
MÓDULO 2
Descrever as modelagens de negócios e de dados da RAD
MODELAGEM (NEGÓCIOS E DADOS)
A modelagem de sistema formaliza como os sistemas são definidos. É comum que, durante o desenvolvimento, sejam usadas imagens para ajudar a visualizar alguns aspectos do sistema. Através de representações por meio de diagramas, a modelagem fornece um meio para compreender e comunicar as ideias associadas ao desenvolvimento do sistema.
A RAD é uma metodologia de desenvolvimento de software evolutiva que, além do levantamento de requisitos, visto no Módulo 1, possui outras fases. De modo resumido, segundo Kerr e Hunter (1994), elas podem ser descritas como:
Modelagem de negócios
Nessa fase, é feita a obtenção de informações a respeito dos requisitos funcionais do sistema, reunidas por várias fontes relacionadas aos negócios. Essas informações são então combinadas para criar uma documentação que será utilizada para modelar o ciclo de vida dos dados: Como os dados podem ser usados, quando são processados e a sua transformação em informações que serão utilizadas por alguma área, ou setor específico do negócio. Trata-se, portanto, de uma análise com viés comercial.
Modelagem de dados
Nessa fase, todas as informações que foram obtidas durante a fase anterior são analisadas para formar conjuntos de objetos de dados essenciais para os negócios. Através da análise, as informações são agrupadas de modo que sejam úteis para a empresa. Por exemplo, na determinação de quais são as entidades principais que serão tratadas pelo sistema. A qualidade de cada grupo de dados, então, é examinada e recebe uma descrição precisa. Em seguida, é feito mapeamento que relaciona esses grupos entre si e qual o significado desses relacionamentos, conforme definido na etapa precedente. Avançando um pouco mais, agora deve-se identificar e definir os atributos de todos os conjuntos de dados. Também é estabelecida e definida em detalhes de relevância para o modelo de negócios a relação entre esses objetos de dados.
COMENTÁRIO
A modelagem não é um método exato e exige muita atenção do analista, pois vai ter impacto para todo o projeto. Quanto melhor for o entendimento do sistema, melhor será a qualidade da modelagem e, portanto, mais eficiente será a tradução das demandas do cliente para a implementação do sistema. Os modelos e as informações são representados por meio de diagramas conectados.
A seguir, detalharemos tanto a modelagem de negócios como a modelagem de dados.
MODELAGEM DE NEGÓCIOS
Uma das principais técnicas para representar a modelagem de negócios é utilizar o diagrama de Casos de Uso da UML. Cabe lembrar que a UML (Unified Modeling Language) - que é traduzida para o português como Linguagem Unificada de Modelagem - é uma linguagem padrão para modelagem orientada a objetos. O objetivo dela é dar suporte para que analistas de negócios e desenvolvedores visualizem os seus projetos em diagramas padronizados. Os diagramas mais comuns são o de Casos de Uso e o de Classes.
A escolha do diagrama de Casos de Uso para modelagem de negócios ocorre porque esse diagrama incorpora a dinâmica dos negócios sob várias perspectivas, descrevendo, assim, como as partes interessadas ― chamadas de atores ― interagem com o sistema e entre si. Na Figura 1, é apresentado um exemplo de caso de uso de um sistema simplificado de embarque em um aeroporto.
No modelo, são destacados os atores “passageiro” e “guia de turismo”.
Nas elipses, estão os Casos de Uso que representam os elementos do sistema com os quais os usuários interagem.
Além disso, o diagrama possui um nome, no exemplo do diagrama de Casos de Uso da Figura 1, o nome é “Aeroporto”, que ilustra o escopo do negócio que está sendo modelado. Outros pontos a serem destacados são como os elementos do negócio interagem entre si representando um fluxo de trabalho que será, posteriormente, implementado no sistema.
Em um negócio, existem, pelo menos, três elementos de Casos de Uso de negócios:
	Processos de Negócios Principais
	Processos Auxiliares
	Processos de Gerenciamento
Os processos de negócios principais: Que tratam das principais atividades do negócio.
Os processos auxiliares: São atividades que precisam ser feitas de qualquer modo, para que o negócio funcione.
Os processos de gerenciamento: Representam os processos que gerenciam outros processos e os relacionam com seus proprietários.
Para ilustrar melhor os conceitos apresentados até agora, será dado o exemplo de um restaurante: Os principais Casos de Uso de negócios são marketing e serviços de almoço e de jantar, e o caso de uso auxiliar é a compra de itens de alimentação e limpeza.
ATENÇÃO
Os Casos de Uso principais de negócios devem estar, obrigatoriamente, relacionados a um ator de negócios. Isso ocorre para impor que os negócios estejam vinculados aos serviços que seus usuários solicitam. Uma forma de verificar que a modelagem de negócios está errada é se modelo de caso de uso tiver Casos de Uso que ninguém solicita.
Os Casos de Uso principais de negócios representam a dinâmica do negócio. São acionados por atores que os iniciam e esperam como resposta aos serviços deles. Em outras situações, um ator receberá respostas, ainda que os Casos de Uso não tenham sido iniciados por ele (ator de negócios).
A modelagem de Casos de Uso de negócio facilita o entendimento dos principais processos que estão sendo mapeados, além de auxiliar na reutilização de partes de fluxos de trabalho que são compartilhados entre muitos Casos de Uso de negócios e é um importante instrumento de interação entre as partes interessadas, para evoluir aspectos que precisem de mais detalhamento, ou mesmo correção.
Trata-se de uma forma muito flexível de trabalho em que é possível fazer generalizações, detalhamentos e reutilizações de Casos de Uso dependendo como ele se contextualiza dentro do negócio.
O esforço de modelagem de negócios deve estar circunscrito às necessidades que serão tratadas pelo sistema, ou seja, o escopo da modelagem não deve ultrapassar o que realmente precisa ser modelado, sob o risco de perder o foco do que será tratado e perdendo, assim, a vantagem da modelagem com um excesso de informações que acabam gerando confusão e que, posteriormente, podem ser difíceis de ser eliminadas da modelagem.
A modelagem foca apenas em um subconjunto dos processos de negócios, ou seja, nos processos que realmente fazem parte das necessidades demandadas pelos clientes.
Uma modelagem de Casos de Uso de negócios de boa qualidade deve ter como características:
O mapeamento das partes do negócio que compõem a demanda do cliente.
Os Casos de Uso devem estar de acordo com o negócio que descrevem.
Deve haver um equilíbrio entre o número e o tamanho dos Casos de Uso.
Ter poucos Casos de Uso torna o modelo mais fácil de entender, mas não podem deixar de descrever algum fluxo de trabalho que seja relevante para o negócio. Outra coisa a ser considerada é evitar a redundância de Casos de Uso. Caso perceba-se a ocorrência de uma situação dessas,deve-se fazer uma generalização dos Casos de Uso, pois não fazer isso pode provocar inconsistências na modelagem dos negócios.
TEORIA NA PRÁTICA
Como exemplo de generalização, seja um sistema de pagamento que permite que os frequentadores de uma academia paguem de duas formas: Online e por telefone. Certamente, esses dois cenários terão muitas coisas em comum e diferentes, reflita sobre esse contexto e escreva alguns desses aspectos comuns entre esses dois cenários:
RESOLUÇÃO
Alguns aspectos comuns são: a especificação das informações pessoais e a especificação do meio de pagamento.
Portanto, a melhor maneira de fazer essa modelagem é criar um Caso de Uso (o pai) que contém o comportamento comum e, em seguida, criar dois Casos de Uso filho especializados que herdam o comportamento do pai e que contêm as diferenças específicas para fazer o pagamento online, ou por telefone.
MODELAGEM DE DADOS
A modelagem de dados é o processo que formaliza o ciclo de vida dos dados de modo que possam ser tratados de um jeito formal, por exemplo, o armazenamento em um banco de dados. Trata-se, portanto, de uma representação conceitual de objetos de dados, de suas associações e regras de manipulação. Ela auxilia na representação visual dos dados e no modo como as regras de negócios e demais imposições regulatórias devem ser cumpridas.
Um exemplo dessas imposições é a Lei Geral de Proteção de Dados ― mais conhecida pelo acrônimo, LGPD ―, que impõe diversas regras sobre a transparência e a proteção do uso de dados. Os modelos de dados aumentam a qualidade dos dados dos sistemas, uma vez que fazem uso de convenções de nomenclatura e de segurança.
O modelo de dados indica quais são os dados necessários e como devem ser organizados, ao invés de apontar quais operações precisam ser feitas. Os tipos de técnicas mais comuns para representar os modelos de dados são:
Modelo de entidade e relacionamento (E-R).
UML (Unified Modeling Language).
MODELO DE DADOS
Na sua essência, o modelo de dados visa a garantir que todos os objetos de dados ― que serão usados pelo sistema ― sejam representados com precisão. A ausência de dados pode produzir inconsistências com grande impacto para o negócio do cliente.
Em relação aos bancos de dados dos sistemas, os modelos de dados ajudam a fazer os projetos nos níveis conceitual, físico e lógico. O modo como o modelo é estruturado ajuda a definir as tabelas relacionais, seus campos, chaves primárias e estrangeiras e o modo como devem ser manipulados para atender às regras dos negócios. É um processo trabalhoso, mas investir na construção de um modelo de dados de qualidade vai trazer benefícios no longo prazo tanto sob o ponto de vista tecnológico, com a facilidade de manipulação e manutenção dos dados, como do ponto de vista do negócio.
Basicamente, existem três tipos diferentes de modelos de dados:
Conceitual
Define o que está contido no sistema. Seu objetivo é a organização, definição do escopo, dos conceitos e das regras de negócios.
Lógico
Define o modo como o sistema deve ser implementado independentemente do banco de dados. O objetivo é desenvolver estruturas de dados e um conjunto de regras técnicas.
Físico
Este modelo descreve a forma como o sistema será implementado usando um sistema de banco de dados específico. O objetivo é a implementação do banco de dados que vai, de fato, operar.
Detalhando um pouco mais os modelos, o principal objetivo do modelo conceitual é determinar quais são as entidades, seus atributos e como elas se relacionam. Aqui, não há detalhes da estrutura real do banco de dados. Os elementos básicos do modelo conceitual são:
Entidade: Um elemento que é distinguível no domínio do negócio.
Atributo: Características, ou propriedades de uma entidade.
Relacionamento: Relação de dependência ou associação entre entidades.
EXEMPLO
Exemplos de entidades são Escola e Aluno. O nome, matrícula e endereço são exemplos de atributos da entidade Aluno. Um exemplo de relacionamento entre as entidades Escola e Aluno é dado por “Uma Escola pode ter vários Alunos”.
O modelo conceitual organiza os conceitos de negócios, portanto são essenciais no início do projeto como um meio de comunicação eficiente entre analistas de negócios e clientes. Ele é desenvolvido independentemente das especificações de hardware, ou de software.
O objetivo é fazer a representação dos dados da forma como um usuário os visualiza no contexto do negócio. Também são conhecidos como modelos de domínio, isso porque criam um vocabulário comum para todas as partes interessadas através de conceitos básicos e escopo.
Em relação aos modelos de dados lógicos, o foco está na definição da estrutura dos dados e nas relações entre eles. Ele é iniciado a partir do modelo conceitual e da análise das requisições técnicas e de desempenho das operações que serão realizadas com os dados. Esse modelo cria a base para o modelo físico. Ele não está vinculado a nenhuma tecnologia específica, mas a forma como os dados serão estruturados visa a obter a otimização do desempenho e segurança deles apesar de sua estrutura de modelagem ser genérica.
Uma das técnicas mais comuns para representá-lo é através do diagrama Entidade-Relacionamento, conforme pode ser visto na Figura 11.
Nesse diagrama, são modeladas as entidades Produto e Tipo de Produto.
 SAIBA MAIS
A entidade Produto possui os atributos preço, descrição e código e a entidade Tipo de Produto possui os atributos código e descrição. Além disso, as entidades são relacionadas entre si e os atributos códigos são utilizados para identificar de forma única cada elemento de suas respectivas entidades.
O modelo lógico, portanto, descreve as necessidades de dados para um projeto. Ele é projetado independentemente do banco de dados que será utilizado e os atributos das entidades fornecem a base da sua especificação que será implementada no banco de dados.
Existe outra etapa importante a respeito do modelo lógico, que é a normalização dos dados. Trata-se de uma técnica de organizar os dados de modo a evitar problemas de inconsistências entre eles.
ATENÇÃO
Na seção “Explore +”, são feitas algumas sugestões para você se aprofundar mais sobre o tópico normalização de dados.
Por fim, o modelo de dados físicos descreve detalhadamente como será a implementação no banco de dados. Com esse modelo, o desenvolvedor pode visualizar como os dados serão armazenados no banco de dados e usá-lo para fazer geração do esquema do banco de dados.
Na figura 12, é apresentado um exemplo de modelo físico de dados.
Na Figura 12, as entidades são representadas por tabelas com campos e seus respectivos tipos de dados. Por exemplo, a tabela Produto possui os atributos “código”, que é do tipo inteiro, e “descrição,” que é um tipo “cadeia de caracteres”.
CADEIA DE CARACTERES
Cadeia de caracteres: Em muitos bancos de dados, esse tipo de dado é chamado de “VARCHAR”.
Esse modelo de dados ajuda a visualizar a estrutura do banco de dados e modelar os identificadores das tabelas (chaves primárias), as colunas, restrições, índices e outros recursos do gerenciamento do banco de dados. Além disso, ele contém relacionamentos entre tabelas.
MAIS ALGUMAS CONSIDERAÇÕES SOBRE A MODELAGEM DE DADOS E DE NEGÓCIOS
O objetivo principal de um modelo de dados é oferecer meios para que os objetos de dados sejam representados com precisão. Para isso, eles devem ser detalhados o suficiente para ser aplicados na construção do banco de dados físico. As informações obtidas a partir deles podem ser usadas para definir quais são as chaves primárias e estrangeiras das tabelas, o relacionamento entre elas, além de outras informações que serão úteis para fazer manipulação e manutenção dos dados.
A modelagem de dados é um importante instrumento para a comunicação entre desenvolvedores e clientes, além de ajudar a documentar os mapeamentos de dados, comumente utilizados no processo de extração-transformação-carga de dados (ETL). Por fim, a modelagem de dados identifica fontes corretas de dados para preencher o banco de dados que será utilizado pelosistema.
adaptável
ciclo de vida
componentes
diretamente
estabilize
foco
protótipos
usuário
Parte superior do formulário
O modelo de dados é uma etapa essencial no de qualquer desenvolvimento independentemente da metodologia utilizada. No caso da RAD, na qual a dinâmica do aprendizado do sistema está relacionada às entregas através dos , é natural que o modelo de dados também evolua, mas é esperado que ele rapidamente e o esteja em questões relacionadas ao detalhamento de regras de negócio e na interatividade do usuário com o sistema, ou seja, questões relacionadas a interativos e experiência do . O perfil esperado de um desenvolvedor da RAD é de um profissional com formação sólida, facilidade de aprendizado e muito . Isso, inclusive, é a principal desvantagem da RAD, pois existem muitas expectativas, especialmente, dos desenvolvedores. Parte inferior do formulário
RESPOSTA
A sequência correta é:
O modelo de dados é uma etapa essencial no ciclo de vida de qualquer desenvolvimento independentemente da metodologia utilizada. No caso da RAD, na qual a dinâmica do aprendizado do sistema está diretamente relacionada às entregas através dos protótipos, é natural que o modelo de dados também evolua, mas é esperado que ele rapidamente estabilize e o foco esteja em questões relacionadas ao detalhamento de regras de negócio e na interatividade do usuário com o sistema, ou seja, questões relacionadas a componentes interativos e experiência do usuário. O perfil esperado de um desenvolvedor da RAD é de um profissional com formação sólida, facilidade de aprendizado e muito adaptável. Isso, inclusive, é a principal desvantagem da RAD, pois existem muitas expectativas, especialmente, dos desenvolvedores.
A evolução do sistema pode ter impacto significativo no que foi feito até então. No sentido de construir um sistema que realmente atenda às expectativas do cliente é excelente, pois as constantes interações fortalecem o entendimento e se concretizam em módulos que atendam às requisições do negócio, por outro lado, para o desenvolvedor, torna-se um grande desafio para que tenha tempo de reagir rapidamente e apresentar as melhorias e correções levantadas para as próximas iterações através de incrementos no protótipo.
Tanto a modelagem de dados, como a modelagem de negócios são etapas fundamentais na RAD para compreender corretamente como o negócio funciona, como deve ser formalizado e como os dados devem ser estruturados de modo que sejam adequadamente armazenados e estejam disponíveis para serem usados quando houver necessidade.
MÓDULO 3
Definir o design de interface com o usuário na RAD
DESIGN DA INTERFACE COM USUÁRIO
A criação de uma interface de usuário tem como meta ser um meio de interação para atender às necessidades de modo prático. Portanto, exige do projetista a capacidade de antecipar comportamentos e um conhecimento das diversas soluções existentes que tornem a construção do projeto viável. Isso significa que as limitações de tempo e recursos financeiros também são impostas para o projeto de design com o usuário.
Questões relacionadas à forma, cor e espaço devem ser tratadas quando se considera um sistema que deve resolver problemas e que será usado por diversos usuários. A interatividade do usuário com um sistema é dinâmica, pois trata de eventos que são acionados a partir das ações do usuário para atingir seus objetivos, logo é necessário que o sistema seja intuitivo e que, além disso, leve em consideração restrições que o usuário possa ter tanto físicas, como de ambiente tecnológico que o software vai operar.
Desenvolver um projeto de interface demanda ferramentas e frameworks que facilitem a visualização de protótipos que, após serem testados e aprovados, nortearão os desenvolvedores para a implementação delas. Esses protótipos permitem testar rapidamente conceitos de interação com o usuário, facilitando, assim, a melhor compreensão do sistema, uma vez que são expostos a situações reais, ainda que em um ambiente controlado.
Trabalhar na implementação de protótipos aumenta o engajamento dos usuários e da equipe de desenvolvimento. Isso ocorre porque as ideias relacionadas ao projeto passam a se concretizar em um ambiente interativo em que limitações são evidenciadas e necessidades de melhorias surgem naturalmente.
Quando se fala sobre design de um sistema, o pensamento mais comum é fazer uma associação com elementos de interface do usuário, normalmente, referenciados pelo acrônimo do inglês UI(User Interface), ou, ainda, GUI(Graphical User Interface), que tratam de componentes visuais com os quais o usuário vai interagir, tal como botões, janelas e barras de rolagem.
Mas existe outro elemento muito importante que também compõe o projeto de interface de um sistema, que é a experiência do usuário, conhecido pelo acrônimo em inglês UX (User Experience). Ambos os conceitos serão tratados com mais profundidade mais adiante.
PROTÓTIPO DE INTERFACE
O protótipo de interface de um sistema visa à experimentação de conceitos, de modo que evolua para uma representação do sistema no usuário. Trata-se de uma atividade muito importante, uma vez que vai guiar, concretamente, as escolhas dos desenvolvedores quando começarem a fazer a implementação do sistema.
Para cada componente escolhido, existe um conjunto de propriedades e de métodos associados que devem ser explicitamente configurados e tratados. Isso significa que o tempo de pessoas será alocado no estudo da configuração e no uso de componentes, além de como devem ser testados.
COMENTÁRIO
Em especial, na metodologia RAD, a evolução do projeto de interface pela implementação de protótipos é esperada. Então, além das necessidades de profissionais bem treinados, é necessário que tenham à disposição ferramentas que facilitem esse processo pelo qual podem tornar a definição da interface em algo concreto.
Desenvolver protótipo de interface do usuário ajuda a refinar os requisitos funcionais logo no início do projeto. A implicação disso tem como consequências positivas a redução dos custos de manutenção, treinamento e melhoria do sistema, além de aumentar as chances de o usuário final aceitar a versão final. De modo resumido, segundo Alavi (1984), entre os diversos benefícios de desenvolver protótipos de interface para o usuário, tem-se:
A possibilidade de fazer testes para tratar de questões específicas do produto que dificilmente seriam respondidas por pesquisas.
Um ambiente real para avaliar os conceitos de UI/UX.
Um meio pelo qual todos os envolvidos no projeto podem usar como um ponto de referência para se comunicarem.
Facilita o engajamento dos usuários, pois podem fazer comentários sobre algo com que podem interagir, facilitando, assim, o trabalho posterior da equipe de desenvolvimento.
Melhora a qualidade das especificações funcionais.
Aumenta as chances de o produto atender às demandas.
Tem o potencial de reduzir o custo total de desenvolvimento do produto.
Na RAD, o desenvolvimento de protótipo é um processo natural. No caso de protótipo de interface do usuário, a ideia é que os esforços empregados nos estágios iniciais podem reduzir bastante o custo do software final. Isso ocorre porque depois de algumas interações a interface se estabiliza e, portanto, as chances de ter que implementar muitas mudanças mais adiante no projeto diminuem.
ATENÇÃO
Apesar de todos os benefícios associados à implementação do protótipo de interface, é necessário ter alguns cuidados, entre os quais, estão:
Ignorar limitações que se aplicam ao produto real no processo de prototipagem.
Criar expectativas irreais sobre o produto.
Estabelecer limites no processo de prototipagem.
Questões relacionadas a licenças de produtos, contexto em que vai operar e viabilidade técnica, além de gerenciamento de recursos de tempo e financeiros sempre devem fazer parte da criação de protótipos. Na RAD, isso é essencial, pois a ideia é que o sistema evolua a partir de iterações e incrementos nos protótipos. Se, desde o início do projeto, houver muitos itens para serem tratados, o processo terá maiscustos.
A NECESSIDADE DA CONTEXTUALIZAÇÃO
A sociedade evoluiu em muitos aspectos, inclusive no acesso à informação. Atualmente, os sistemas são usados para diversas aplicações, desde operações financeiras, educativas e de entretenimento. Além disso, os sistemas operam em diversas plataformas, como aplicações web e móveis.
O perfil do usuário também está mais abrangente, desde as pessoas que têm mais facilidade de usar tecnologias, as que ainda não estão habituadas e aquelas que possuem restrições visuais, por exemplo. Portanto, os desafios de projetar uma interface de usuário ficaram bem mais complexos no sentido de que são muitas perspectivas que devem ser observadas. Por outro lado, existem muitas ferramentas e frameworks disponíveis para apoiar o desenvolvimento de protótipos.
O primeiro ponto a ser considerado no desenvolvimento de um projeto de interface é entender a que público ele se destina. A compreensão de que o sistema será usado por outras pessoas e sobre em que contexto vai operar auxilia na criação de protótipos que atinjam mais rapidamente o objetivo esperado. De um modo simplificado, um projeto de interface deve levar em consideração alguns pontos:
Os elementos de interface, tais como os botões, barras de rolagem e menus devem ter um comportamento previsível, isso significa dar previsibilidade para os usuários, de modo que a interação com os componentes seja intuitiva.
Aplicação de recursos que destaque um componente no contexto da aplicação. Por exemplo, usar sombras para botões.
A interface deve ser simples, ou seja, os elementos devem atender aos propósitos dos usuários.
A organização dos elementos deve ser legível. Para obter isso, é importante que haja uma hierarquia que os relacione, além da preocupação em fazer alinhamentos que priorizem o bem-estar do usuário.
O uso de recursos de cores e contrastes deve ser moderado e sempre com o propósito de guiar o usuário para realização de suas tarefas.
Os tamanhos das fontes, estilo ― negrito e itálico, por exemplo ―, maiúsculas e distância entre letras também devem ser contextualizados com o objetivo de dar destaque para o usuário sobre o significado de uma mensagem. Por exemplo, um texto em letras maiúsculas pode ser usado para destacar o cuidado que o usuário deve ter ao realizar alguma ação específica no sistema, como excluir um registro.
Por unidade de interação, por exemplo, telas, a quantidade de ações para executar tarefas deve ser a menor possível. O foco sempre deve ser o usuário, portanto a interface deve ser um guia, para que progridam na execução de tarefas complexas.
Os controles devem estar próximos dos objetos que os usuários desejam controlar. Por exemplo, um botão para enviar um formulário deve estar próximo dele.
Fornecer informações para os usuários a respeito de suas ações do sistema, como mensagens de confirmação de envio, por exemplo.
Em algumas situações, é apropriado aplicar padrões de utilização do sistema para facilitar o trabalho do usuário. Por exemplo, preencher formulários previamente. Essa opção, no entanto, deve ser aplicada com bastante ponderação, pois, apesar de ser bastante útil em muitas situações, pode ser utilizada por pessoas mal-intencionadas para obter indevidamente dados dos usuários.
O design dos componentes deve ser contextualizado com o posicionamento do negócio a que se destina. No caso de sistemas para empresas, é esperado que haja um estilo visual que deve ser mantido.
A interface deve fornecer os próximos passos de como os usuários devem proceder para navegar no sistema e atingir seus objetivos em qualquer contexto.
Na RAD, o desenvolvimento rápido de protótipo é enfatizado em detrimento do planejamento. Ele é feito por meio do fluxo de ideias que são exploradas a partir da interação com as partes interessadas e das soluções de problemas que são detectados durante o processo de prototipagem rápida. Desde o início da RAD, o desenvolvimento de aplicações passou a ser utilizado em diversas situações, como aplicações web e móveis.
A RAD é adequada para situações em que os projetos não são complexos. Por exemplo, funciona bem para criação, ou renovação de páginas de comércio eletrônico. Portanto, a escolha da RAD para implementar o design de interface de usuário deve satisfazer:
ESCOPO DO PROJETO
Deve ser bem definido, para que seja viável visualizar como será a versão final do sistema e, assim, estimar os esforços e recursos necessários para o desenvolvimento do projeto.
DADOS DO PROJETO
Para aplicar a RAD, o projeto já deve ter informações sobre os dados, evitando, assim, a necessidade de aplicar processos de análise de dados que podem consumir bastante tempo e esforços que são difíceis de dimensionar.
DECISÕES DO PROJETO
Apesar de as interações com as partes interessadas serem muito importantes, as decisões sobre o projeto também precisam ser rápidas. Em um projeto em que a hierarquia das decisões é muito forte, o uso da RAD é inadequado, especialmente na confecção de um protótipo de interface com o usuário.
EQUIPE DE PROJETO
O dimensionamento das equipes deve ser pequeno.
Em relação ao último item, parece ser simples, mas a implicação imediata é que os profissionais dessas equipes devem ter múltiplas habilidades, ou seja, além de trabalhar com programação visual, é esperado que o profissional tenha conhecimento sobre banco de dados, desenvolvimento de micro serviços e arquitetura de software. Portanto, a escolha da RAD deve levar em consideração todas estas questões. Logo, depois de analisar esses pontos, e a RAD for a melhor opção, o processo deve seguir as seguintes etapas:
ETAPA 1
Escolha de uma equipe com profissionais que serão capazes de desenvolver projetos de interface e que contribuam sobre a escolha dos componentes.
ETAPA 2
Analisar as metas do projeto e entender o que precisa ser feito, como se encaixam no projeto e o que é necessário fazer para cumprir as metas.
ETAPA 3
Criar um processo iterativo, onde podem ser desenvolvidos protótipos e testes de usabilidade até que seja atingido um ponto que se alinhe com os objetivos do projeto.
TÉCNICAS DE PROTOTIPAGEM DE INTERFACE COM O USUÁRIO
Em outras metodologias de desenvolvimento, faz-se o uso de protótipos também. No entanto, elas se diferenciam da RAD em relação ao objetivo do protótipo. Nas demais metodologias, o protótipo é usado para provar conceitos e, ao longo do desenvolvimento, o sistema é desenvolvido em características. No caso da RAD, a ideia é que o protótipo evoluirá para a versão final do sistema. Portanto, é importante que a RAD trabalhe com o engajamento do cliente por meio da experiência do usuário. Existem algumas técnicas para o desenvolvimento de protótipos de interface, são elas:
SKETCHES
Trata-se de esboços de um projeto. Eles são fáceis de criar e úteis para verificar se os conceitos e requisitos foram totalmente compreendidos sem consumir muito esforço. O seu uso deve ser limitado ao início do projeto, pois é inadequado testar funcionalidades do sistema.
WIREFRAMES
São muito úteis para fazer uma abordagem mais complexa para mapear a interface do usuário. Eles são mais detalhados do que os Sketches, além disso, algumas ferramentas permitem adicionar componentes interativos. Desse modo, o usuário pode fazer navegações no protótipo sem a implementação das funcionalidades.
MOCKUP
Também conhecida como “maquete”, é usada para refletir as opções de design para a escolha de cores, layouts, tipografia, iconografia e aspectos visuais de navegação do produto.
PROTÓTIPOS
São modelos funcionais de sistema. São construídos para tratar tanto das funcionalidades do produto, como também da aparência.
Preparar versões, ainda que simplificadas da interface com o usuário, ajuda os desenvolvedores e designers a implementarem suas ideias e, assim, fornece protótipos interativos para os clientes.
A escolha de uma ferramenta para desenvolver protótipos de interface com o usuário depende de diversos fatores, mas, de um modo simples, entre os itens a serem considerados estão:
	Licença
	Integração
	Fidelidade
	Curva de aprendizagemFacilidade de uso e conforto
	Compartilhamento
LICENÇA
A primeira preocupação de qualquer projeto deve ser a respeito dos direitos de uso de um software. O risco de iniciar um projeto em uma versão de testes de uma ferramenta que não poderá ser usada pela equipe posteriormente pode ser grande. Só faz sentido analisar os demais quesitos se este item for satisfeito.
INTEGRAÇÃO
Algumas ferramentas de prototipagem geram código que pode ser usado diretamente por algumas linguagens de programação.
FIDELIDADE
Os protótipos na RAD são essenciais para a versão final do sistema, portanto devem ser levadas em consideração quais as diferenças entre os elementos de interface do protótipo e o sistema esperado.
CURVA DE APRENDIZAGEM
A metodologia RAD exige ferramentas que apoiem o desenvolvimento rápido, portanto as ferramentas devem ser intuitivas e fáceis de serem utilizadas e aprendidas pelos membros da equipe.
FACILIDADE DE USO E CONFORTO
As ferramentas de prototipagem devem ajudar a aumentar a produção com a redução de etapas necessárias para criar protótipos.
COMPARTILHAMENTO
A ferramenta deve fornecer capacidade de colaboração entre várias pessoas.
A tarefa de projetar o design de um sistema é complexa. Portanto, as escolhas que devem ser tomadas logo no início do projeto RAD precisam considerar fatores que apoiem o desenvolvimento.
MÓDULO 4
Esquematizar uma aplicação RAD implementada em Python
IMPLEMENTAÇÃO EM PYTHON
Neste módulo, será desenvolvida uma aplicação prática de RAD usando o Python (ver Python 3.8.5, 2020). Antes de começar, é necessário pensar sobre alguns pontos sobre a RAD:
A entrega de protótipos para os usuários permite que eles possam interagir com o sistema e, portanto, munir os desenvolvedores com comentários que darão suporte para implementarem melhorias e fazer ajustes.
É uma metodologia adequada para projetos de baixa complexidade.
Ser uma metodologia voltada para entregas rápidas não quer dizer que o desenvolvedor não precisa saber programar bem, ao contrário, pois o perfil dos profissionais de desenvolvimento na RAD exige que tenham domínio em linguagens de programação e ferramentas/frameworks, além de serem adaptáveis e motivados.
Muitas linguagens de programação podem ser aplicadas para um projeto RAD. Neste trabalho, o foco está na linguagem Python por se tratar de uma escolha natural por diversos motivos. Entre eles, estão: A simplicidade da sintaxe, disponibilidade de muitos pacotes, ampla aceitação no mercado, uma grande comunidade engajada na resolução de problemas e licença de software livre.
O exemplo escolhido para apresentar a RAD na prática é de um sistema simples que faz o cadastro das informações pessoais básicas sobre um estudante e de suas notas. Ao final do cadastro, o sistema exibe os dados que foram cadastrados, a média das notas e a situação do estudante, ou seja, se foi aprovado, ou reprovado, ou se está em recuperação.
A seguir, as etapas de requisitos, modelagem de negócios e de dados, além da implementação do sistema serão tratadas.
REQUISITOS
Aqui serão apresentados os requisitos do sistema, que são:
PROPÓSITO
Apresentar uma descrição do Sistema Simplificado de Cadastro de Notas de Alunos. Esta descrição destina-se tanto aos usuários como aos desenvolvedores do sistema.
ESCOPO
Este software será um Sistema de Cadastro de Notas de Aluno. Ele será projetado para informar se os alunos estão aprovados, em recuperação, ou reprovados. Além disso, os dados são gravados em um arquivo Excel para facilitar a integração com outros sistemas. O sistema atenderá às necessidades básicas da coordenação da escola para orientar os alunos enquanto permanece fácil de entender e usar.
INTERFACES DO SISTEMA
O sistema foi projetado para operar no Windows.
INTERFACES DE USUÁRIO
A GUI do sistema possui botões, caixas de texto e grades, facilitando o controle por teclado e mouse.
INTERFACES DE SOFTWARE
O software permite importar e exportar dados em um documento estruturado do MS Excel via formato de dados XLSX.
ESPECIFICAÇÃO DE REQUISITOS FUNCIONAIS
O usuário deve ser capaz de cadastrar o nome do aluno e suas notas.
O usuário deve ser capaz de visualizar os dados cadastrados do aluno, sua média e sua situação: Aprovado, ou reprovado, ou em recuperação.
Os dados são gravados e lidos de uma planilha do Excel.
MODELAGEM DE NEGÓCIOS
A escola RAD decidiu construir um novo aplicativo para facilitar a visualização da situação escolar dos seus alunos. Dados como nome e notas dos alunos serão cadastrados no sistema. Com isso, serão calculadas automaticamente as médias dos alunos e apresentada a sua situação escolar: Aprovado, ou reprovado, ou em recuperação.
Na Figura 18 é apresentado o diagrama de Casos de Uso do sistema de cadastro de notas e visualização da situação escolar dos alunos.
No diagrama estão destacados os atores do sistema que são os alunos e funcionários da escola. Os funcionários vão cadastrar os dados dos alunos que, por sua vez, poderão visualizar as suas respectivas situações escolares.
MODELAGEM DE DADOS
O sistema visa a ser apenas um facilitador de uma etapa do gerenciamento das notas dos alunos. Além disso, os dados serão armazenados em uma planilha Excel.
Na tabela é apresentado o modelo de dados do sistema.
	Campo
	Aluno
	Nota1
	Nota2
	Média
	Situação
	Tipo
	Texto
	Decimal
	Decimal
	Decimal
	Texto
DESIGN DA INTERFACE COM USUÁRIO
A interface gráfica do sistema de cadastro e visualização da situação escolar de alunos foi feita com o uso do pacote Tkinter (TKINTER, 2020). Trata-se da biblioteca de interface gráfica padrão da linguagem de programação Python. No ambiente de desenvolvimento Spyder (ver Spyder, 2020), para fazer a instalação do pacote “tkinter”, basta digitar:
!pip install tkinter
Existem algumas pequenas variações quando se faz a instalação de um pacote no Python. No caso do Spyder, é necessário colocar o símbolo exclamação “!” antes do comando “pip”. Para outras IDEs, é necessário retirar o caractere “!” (símbolo de exclamação) do comando. O pacote Tkinter está disponível na maioria das plataformas Unix, bem como em sistemas Windows. Portanto, é uma boa escolha para o desenvolvimento de interfaces com o usuário.
Para poder usar os componentes gráficos do Tkinter no código é necessário escrever logo no início do sistema as seguintes linhas de código:
import tkinter as tk
from tkinter import ttk
A interface gráfica do sistema é apresentada na figura 19.
Nela, são destacados seis tipos de componentes:
Janela: Trata-se do formulário no qual os demais componentes são organizados. No caso da implementação do sistema, esse componente foi usado da seguinte maneira: janela=tk.Tk()
Rótulo: Que é usado para textos estáticos. No caso do sistema, foi usado para os textos “Nome do Aluno”, “Nota 1” e “Nota 2”. Para referenciá-los no código, é necessário escrever: tk.Label(janela, text='Texto estático').
Caixa de texto: São usadas para os usuários entrarem com os dados dos alunos. No caso do sistema, foi usado para entrar com o “nome do aluno”, a “nota 1” e a “nota 2”. Para referenciá-los no código, é necessário escrever: tk.Entry().
Botão: Usado para iniciar uma ação. No caso do sistema, foi aplicado para cadastrar os dados dos alunos, calcular suas respectivas médias e determinar situação escolar em que o aluno se encontra. Para referenciá-los no código, é necessário escrever: tk.Button();
Visão de árvore: Bastante útil para visualizar os dados. No sistema, foi usado para uma visualização em grade dos dados dos alunos, suas médias e respectivas situações. Para referenciá-lo no código, é necessário escrever: ttk.Treeview().
Barra de rolagem: É um componente útil para interagir com a tabela da “visão de grade”, quando a quantidade de linhas de registros ultrapassa o limite inicial. Para usar no código, é necessário escrever ttk.Scrollbar().
A interface gráfica auxilia no entendimento do sistema. Certamente, é mais fácil fazer sugestões de melhorias a partir de uma experiência real com o sistema do que em um nível abstrato.
DETALHES DE IMPLEMENTAÇÃOAgora, serão abordados aspectos que se referem à implementação do sistema em Python. Vá até a seção “Explore +” e faça o download do arquivo “listaMediaAlunoFinal-v03.py”, assim será possível acompanhar a implementação.
A primeira parte está na escolha dos pacotes que foram utilizados no desenvolvimento do sistema. No caso, foram escolhidos: Tkinter e Pandas. O Tkinter foi escolhido por ser a biblioteca padrão de componentes gráficos do Python e poder ser utilizada em múltiplas plataformas, apesar de o sistema, inicialmente, ter sido projetado para operar no Windows. O pacote Pandas é útil para manipular conjuntos de dados, mais conhecidos pela expressão em inglês de “datasets”. Para usar as bibliotecas/pacotes, foi necessário escrever no código as seguintes linhas:
import tkinter as tk
from tkinter import ttk
import pandas as pd
Antes de continuar, é importante verificar se a instalação das bibliotecas está correta. Na linha de comandos da IDE Spyder, digite a seguinte linha:
import tkinter
Pressione Enter e, em seguida, digite:
tkinter._test()
Pressione a tecla Enter novamente. Se tudo funcionar corretamente, aparecerá uma janela, conforme a figura 20.
Caso não tenha aparecido a janela, houve algum problema de instalação e será necessário corrigi-lo. Com os problemas de instalação resolvidos, passa-se à criação dos elementos de interface gráfica.
Na parte principal do programa, escreva as seguintes linhas de código, conforme a figura 21:
A primeira linha trata da instanciação de um objeto “raiz” do Tkinter onde serão colocados os demais componentes gráficos.
Na linha 2, é feita a instanciação do objeto principal do projeto, onde o ciclo de vida dos componentes será gerenciado – isso inclui a criação, tratamento de ações e liberação para a memória.
Na linha 3, é dada a mensagem “título” para o projeto.
Na linha 4, são estabelecidas as dimensões altura e largura da janela principal.
Na linha 5, por fim, o sistema começa a executar até que o usuário feche a janela principal.
Agora vem a construção do ciclo de vida do programa. Na figura 22, é apresentado o trecho inicial do ciclo de vida dos componentes.
Mesmo para um projeto pequeno, existem muitos detalhes a ser observados. Logo na linha 1 está a implementação da classe principal do sistema. É nessa classe que vai estar a lógica do tratamento do ciclo de vida dos componentes gráficos. Das linhas 4 a 21, cada objeto que se refere a um componente gráfico é instanciado. Em especial, merece atenção a linha 11:
self.btnCalcular=tk.Button(win, text='Calcular Média', command=self.fCalcularMedia)
Nessa linha, o objeto ‘btnCalcular’ do tipo ‘tk.Button’ recebe o texto ‘Calcular Média’, que vai aparecer no botão e, além disso, é associado à função “fCalcularMedia”.
Outro ponto importante para observar no trecho de código da Figura 22 é a linha 2:
def __init__(self, win)
Que é a função “construtora” da classe, ou seja, o primeiro método a ser acionado no ciclo de vida do componente raiz principal.
Ainda na função “init”, os componentes são posicionados na janela principal conforme é possível verificar na Figura 23.
Um trecho interessante de ser destacado é a linha 21. Nele, é feito uma chamada para o método “carregarDadosIniciais”. Esse método é o responsável por carregar os dados que já estão armazenados na planilha para o componente “treeview”, que é a grade que aparece na tela principal. Na Figura 11, é apresentado o código do método “carregarDadosIniciais”.
Como dito anteriormente, o objetivo desse método é carregar os dados da planilha para o componente “treeview” que é a grade que aparece na janela principal. Um dos problemas que podem ocorrer nessa tentativa de carregar os dados é que ainda não existem dados, ou mesmo, uma planilha de onde carregá-los.
 SAIBA MAIS
Caso não seja dado um tratamento explícito para essa situação de exceção, o programa vai apresentar uma mensagem de erro, caso a planilha não exista. O ideal é detectar todas as situações de exceção logo no começo do projeto, pois isso evitará o consumo de horas de testes que podem ser mais bem direcionadas para tentar descobrir problemas mais complexos que podem ser vulnerabilidades para o sistema. O tratamento de exceção foi dado pela aplicação das cláusulas “try-except” (linhas 2 e 21).
Outro ponto interessante de se observar é na linha 4: “dados = pd.read_excel(fsave)”.
Com apenas um único comando, os dados da planilha de dados dos alunos são carregados para a variável “dados”. Isso ocorre com o uso da função “read_excel” da biblioteca “pandas”. Com isso, esses dados podem ser facilmente manipulados no código. O nome pelo qual esse tipo de dado é conhecido é “datasets”. Das linhas 6 a 20, os dados são obtidos da variável “dados” e inseridos no componente “treeview”. Caso ocorra algum problema, será enviada a mensagem “Ainda não existem dados para carregar”.
Esse tipo de programação protege o sistema de eventuais problemas através do estabelecimento de um comportamento previsível. Assim, o código fica menos vulnerável contra ataques que tentem ver mensagens padrões não tratadas que revelem características sobre o código, ou o ambiente em que o sistema está operando.
Agora vem o cálculo da média do aluno, identificação de sua situação escolar e armazenamento de dados no sistema.
Na Figura 25 é apresentado o código que é responsável por essas operações.
Novamente, deve ser destacado o bloco “try-except” nas linhas 2 e 17, pois o sistema está esperando um nome ― que é um campo texto ― e duas notas ―, que são campos numéricos. Caso o usuário entre com um dado inválido, ao invés de gerar uma falha o sistema vai exibir a mensagem “Entre com dados válidos”. Além disso, esse método ainda possui a cláusula “finally” que vai ser executada de qualquer modo. No caso, os campos de entrada serão “limpos”.
No método “fCalcularMedia” são feitas chamadas para os métodos “fSalvarDados” e “fVerificarSituacao”. O método “fSalvarDados” já foi explicado. Em relação ao método “fVerificarSituacao”, ele é apresentado na Figura 26.
É no método “fVerificarSituacao” em que a média é calculada e a situação escolar do aluno é determinada. Das linhas 3 a 8, é encadeada uma série de testes a partir do cálculo da média na linha 2. No final do método, na linha 10, são retornadas as variáveis “media” e a “situacao” que correspondem, respectivamente, à média e à situação escolar do aluno para o método que fez a chamada. Aqui, está mais uma vantagem da sintaxe do Python: Retorno de múltiplas variáveis. Isso facilita bastante o processo de programação, poupando tempo para o desenvolvedor.
ATENÇÃO
Outro ponto que precisa ser observado, mais no sentido da sintaxe do Python, é o uso da palavra reservada “self”. Esse projeto foi programado orientado a objetos (POO). Na POO, a classe é formada por atributos e métodos. Quando são feitas referências aos métodos e atributos na própria classe, é necessário indicar sua origem com o uso da palavra “self” seguida de “.” (ponto-final).
EVOLUÇÕES
O sistema “simplificado de cadastro de notas de alunos” é funcional. Ou seja, com o que foi construído até agora, é possível ter reuniões com os usuários para apresentar resultados, detectar vulnerabilidades, fazer ajustes e propor avanços.
POR EXEMPLO, O USUÁRIO PERCEBEU A NECESSIDADE DE UMA TELA DE LOGIN EM QUE ALUNOS E FUNCIONÁRIOS TIVESSEM VISÕES ESPECÍFICAS DAS FUNCIONALIDADES DO SISTEMA. OUTRO PONTO PARA EVOLUIR É SOBRE O ARMAZENAMENTO DE DADOS, OU SEJA, PARTIR PARA UMA SOLUÇÃO QUE USE UM SISTEMA GERENCIADOR DE BANCO DE DADOS. DE ACORDO COM ESSE CONTEXTO, QUE TIPOS DE VISUALIZAÇÕES DE INFORMAÇÕES QUE OS USUÁRIOS PODERIAM SENTIR NECESSIDADE?
RESPOSTA
Os usuários poderiam perceber a necessidade de ter mais algumas visualizações de informações, como, por exemplo, a média e o desvio-padrão da turma, pois essas informações poderiam apoiar o setor pedagógico da escola no desenvolvimento de estratégias para detectar problemas e propor soluções para a turma de um modo geral.
Portanto, tem uma série de questões nesse exemploque se encaixam em uma metodologia evolutiva como a RAD. Mas é importante que fique claro que a parte mais importante da RAD está na qualidade dos profissionais envolvidos no processo, portanto investir em qualificação técnica e acadêmica é fundamental e no ambiente colaborativo entre as partes interessadas.

Mais conteúdos dessa disciplina