Software
Linguagem de Programação
Abstração: Mascara um sistema complexo oferecendo uma interface comum Assembly (bytecode): Linguagem de baixo nível; somente compatível em uma CPU específica
Nível de abstração:
Baixo Nível: Assembly
Médio Nível: C, C++, D, Objective C, etc.
Alto Nível: Java, C#, PHP, Javascript, etc.
Altíssimo Nível: Python, Ruby, Elixir, etc.
Linguagens classificadas pela arquitetura da aplicação:
Desktop: C, C++, Object Pascal, Java, etc.
Web: PHP, Ruby, Javascript, Java, etc.
Compilação e Interpretação
Lexer (Análise Léxica): Lexing ou Tokenização; lê os caracteres de entrada e os agrupa em unidades significativas chamadas tokens, seguindo as regras gramaticais definidas para a linguagem; primeira etapa do processo de compilação
Parser (Análise Sintática): Recebe os tokens, verifica se a sequência de tokens segue a gramática da linguagem e os organiza em uma estrutura hierárquica chamada Parse Tree
Parse Tree: Estrutura sintática do código-fonte; representação intermediária usada pelo compilador para verificar a correção sintática do código
Abstract Syntax Tree: representação mais simplificada e abstrata do código-fonte, derivada da parse tree.
Enquanto a Parse Tree mantém informações adicionais como espaços em branco e comentários, a Syntax Tree foca apenas nos elementos necessários para a geração de código de máquina
Tipo de Execução
Linguagens Hibridas: Java, Erlang, Elixir, etc
Compiladas
Linguagens compiladas: C, C++, Pascal, D, GO, etc
Converte instruções humanas em instruções de máquina
Bytecode gerado antes para execução na hora de execução (Just in Time)
.ELF (Executable and Linkable Format): formato de arquivo padrão comum para arquivos executáveis, código de objeto, bibliotecas compartilhadas
Interpretadas
Linguagens Interpretadas: Python, Ruby, PHP, Javascript, etc
Não são compiladas antes; funcionamento a base de scripts
Bytecode gerado depois para compilar continuamente enquanto executa (Ahead of Time)
Interpretador: AST (Abstract Syntax Tree) modificável Script: Código executado por interpretador que converte em instruções à CPU em sua execução Linguagens Dinâmicas: Que possuem a capacidade de injeção de novos códigos em tempo de execução
Paradigmas de Programação
Conjunto de características que podem ser utilizados para categorizar determinado grupo de linguagens
Um paradigma pode oferecer técnicas apropriadas para uma aplicação específica
Imperativo
Programação Estruturada: C, Pascal, Ada, etc Programação Concorrente: Java e Ada Programação Orientada a Objetos: Java, C#, C++, Objective C, D, etc
Se concentra na descrição passo-a-passo de como alcançar o resultado desejado
É especificado explicitamente as operações a serem realizadas, incluindo sequências de instruções, condições e loops
Controle detalhado sobre o fluxo de execução do programa
Declarativo
Programação Funcional: Lisp, Scheme, Erlang, Elixir, etc
Foca em "o quê" deve ser feito, em vez de "como" fazê-lo
Caracterizado por expressões que descrevem o resultado desejado sem especificar o método exato para alcançá-lo
É comum em linguagens de consulta (SQL) e em algumas linguagens de programação funcional
Vantagens
Mais simples e direto
Mais fácil de entender quando há bugs internos
Mais legível
Mais fácil de testar
Mais fácil de entender a finalidade
Mais fácil de implementar soluções personalizadas
Desvantagens
Menos explorável
Mais verboso
Menos flexível
Mais propenso a erros
Algoritmos
Variáveis tipo Float
Algarismos significativos: número de casas decimais do resultado será igual ao do número com menor número de casas decimais Exemplo: →
Números reais são representados por notação científica multiplicada por uma potência de base
Seu processamento pode se dar pela “quebra” do número em parte inteira e parte decimal
Erros de arredondamento: Por armazenar números em formato binário, algumas frações decimais não podem ser representadas exatamente, onde o valor armazenado pode ser ligeiramente diferente do valor real
Acumulação de erros: Operações repetidas com números de ponto flutuante acumulam os erros de arredondamento, resultando em desvios significativos dos valores esperados
Complexidade do Código
Notação
Levar em consideração apenas repetições de código
Verificar funções/métodos próprios da linguagem
Ignorar constante e utilizar termo de maior grau (pior caso)
Versionamento de Software
Identificadores Baseados em Sequência
São usados para transmitir a significância das alterações entre as versões
Potencial impacto em adotar uma nova versão
Risco de bugs ou alterações não declaradas de quebra
Grau de alterações no layout visual
Número de novos recursos
Há uma variedade de esquemas de versionamento numérico
Versionamento Semântico
Major (alto risco): Modificações Breaking Change (modificação que quebra a compatibilidade da API); identificado nos commits pelo símbolo ! Minor (médio risco): Modificações sem quebra Patch (menor-risco): Incrementos de patch Pre-release tag: Indica estágios de desenvolvimento; alpha(a), beta(b), release candidate(rc), 0.x
Os desenvolvedores podem optar por pular várias versões menores ao mesmo tempo para indicar que recursos significativos foram adicionados, mas não são suficientes para justificar o incremento de um número de versão principal; ex: de 5.1 para 5.5
Outros esquemas conferem significado em sequências individuais:
major.minor[.build[.revision]]
(ex: 1.2.12.102)major.minor[.maintenance[.build]]
(ex: 1.4.3.5249)
Versionamento por Status mais Recente
Sufixo Alfanumérico: Esquema adotado pela versão semântica; traço e caracteres alfanuméricos para indicar status Status Numérico: Esquema que usa números para indicar status como se fosse parte da sequência; escolha típica é a terceira posição para o versionamento de quatro posições Numeric 90+: Esquema que também usa números, mas sob série de uma versão anterior; grande número na última posição, tipicamente 90 ou superior, comumente usado por projetos de código aberto mais antigos
Alpha
1.2.0-a.1
1.2.0.1
1.1.90
Beta
1.2.0-b.2
1.2.1.2
1.1.93
Release candidate (RC)
1.2.0-rc.3
1.2.2.3
1.1.97
Release
1.2.0
1.2.3.0
1.2.0
Post-release fixes
1.2.5
1.2.3.5
1.2.5
Testes de Software
Garantir que o produto atingiu suas especificações e que funciona corretamente no ambiente para qual foi projetado
Defeito ≠ Erro ≠ Falha
Falha: Visível para o usuário, tem por trás algum erro Erro: Cenário não testado pelo desenvolvedor; falha humana; evidencia o defeito Defeito: Bug; erro técnico; causa raiz
Verificação: Verifica se esta sendo construído conforme os requisitos Validação: Valida se as regras de negócio e as expectativas do usuário foram atendidas
Níveis de Teste
Testes Unitários: Focam em validar a funcionalidade de componentes individuais Testes de Integração: Verificam como diferentes partes do sistema funcionam juntas; usados para identificar problemas na interação entre os componentes Testes de Sistema: Verifica se o sistema completo funciona conforme esperado, incluindo todas as suas funcionalidades e integrações; se funciona conforme esperado em um ambiente que simula o real Teste de Regressão: Garante que mudanças recentes ou correções de bugs não tenham introduzido novos defeitos em partes já testadas do software Teste de Aceitação: Últimos testes realizados antes da entrega do produto final; confirmar se o sistema atende aos critérios de aceitação definidos pelas partes interessadas; podem ser divididos em testes de aceitação do usuário (UAT) e testes de aceitação do negócio (BAT)
Alpha ➡ Beta ➡ Cannary
Técnicas de Teste
Caixa Branca: Teste estrutural; garantir qualidade da implementação; validar dados, controles, fluxos, chamadas | Unidade, Integração, Regressão Caixa Preta: Teste funcional; verificar saídas usando vários tipos de entrada; teste sem conhecer a estrutura interna do software | Integração, Sistema, Aceitação Caixa Cinza: Mescla técnicas de Caixa branca e Caixa Preta; analisa parte lógica e também funcionalidade; Engenharia Reversa
Testes não funcionais
Ligados a requisitos não funcionais (e não a regras de negócio) ➡ Qualidade
Comportamento do Sistema
Performance
Escalabilidade
Segurança
Infraestrutura
Utilizam ferramentas/técnicas para apurar o comportamento do sistema em determinadas circunstâncias
Teste de carga: Verificar qual o volume de transações, acessos simultâneos ou usuários que um servidor/software/sistema suporta Testes de stress: Submeter o software a situações extremas; testar os limites do software e avaliar seu comportamento, até quando pode ser exigido e quais as falhas (se existirem) decorrentes do teste Testes de segurança: Segurança cibernética que visa detectar vulnerabilidades em sistemas, software, redes e aplicativos
Last updated