sexta-feira, 23 de novembro de 2012

Este documento contém uma série de notas sobre teste de software, incluindo: 

Teste Funcional
  • Critério - Particionamento por Classes de Equivalência
  • Critério - Análise de Valor Limite
  • Critério - Teste Funcional Sistemático
  • Critério - Grafo de Causa-Efeito 
Teste Estrutural
  • Grafo de Fluxo de Controle
  • Grafo de Fluxo de Dados 
(novo) Teste de Mutação
(novo) Teste Baseado em Modelos
As notas podem ser vistas aqui!

terça-feira, 13 de novembro de 2012

 A busca pela melhoria de performance pode ser alcançada por diversas técnicas, cuja a técnica de programação concorrente já é bastante consolidada e utilizada no mercado. Entretanto, adicionar concorrência possui um custo adicional de conhecimento e a escolha da tecnologia pode ser benéfica ou um entrave na utilização dessa estratégia. Diversos estudos reveleram que o OpenMP é um dos frameworks mais fáceis de serem utilizados, porém ainda há dúvidas sobre a sua performance em relação aos outros. Este trabalho apresenta os resultados através da mudança do paradigma sequencial para a programação concorrente, considerando o aumento do número de threads e diferentes formas de balanceamento de carga entre os processadores. Por fim, para conhecer de fato a eficiência do OpenMP, este estudo realizou uma implementação híbrida utlizando três estratégias de melhoria de perfomance: (i) programação concorrente, (ii) vetorização intrísica usando extensões SSE3 do processador Intel e (iii) técnicas de blocagem para medir o speedup e eficiência em comparação aos frameworks Pthreads e Java Threads.



sexta-feira, 2 de novembro de 2012

Dada uma mochila de tamanho M e N itens com peso P ={P1, P2...Pn} e Valores V = {V1, V2...Vn}, encontre um vetor de X elementos contidos e não contidos na mochila, onde P.X <= M e V.X é o valor máximo possível.

Programa Mochila {

//itens possuem o mesmo índice para pesos e valores e possui índices e zeros no início.
Int M = 11; 
Int itens[][2] = {{0,0},{1,0},{ 2,0},{3,0}} ; 
int pesos[] = {1, 2, 4, 8}; 
double valores[] = {10, 30, 41, 80}
;
int itens[][] = ObtemItensdaMochila(M, itens, pesos, valores);
Para i=0 até itens[0].tamanho-1 faça
            Para j=0 até itens[1].tamanho-1 faça
                Imprima itens[i][j]; //Imprime índice  + “0” ou “1”
            Fim-Para
Fim-Para

int[][] ObtemItensdaMochila (int M, int[] itens, int[] pesos, double[] valores);
//Coluna 0 – Peso, Coluna 1 – Valores
double mochila[][] = itens.tamanho, 2;
//Atribui valores iniciais
mochila[0,0] = pesos[pesos.tamanho-1]; mochila[0,1] = valores[valores.tamanho-1];
//Coluna 0 – Peso, Coluna 1 – Valores
double mochilaItens[][] = itens.tamanho, 2;
mochilaItens[0,0] = mochila[0,0]; mochilaItens[0,1] = mochila[0,1];
int elemento = 0; int j = 0;
Para i=itens[0].tamanho-2 <=0 faça {
 Se (pesoAtual(mochila) + pesos[i] <= M)
        elemento  = elemento+1;
                      mochila[elemento,0] = pesos[i];
                      mochila[elemento,1] = valores[i];
                       Se (valorAtual(mochila) > mochilaItens[j,1])
                               j = j+1;
                               mochilaItens[j,0] = mochila[elemento,0] + mochilaItens[j,0];
                               mochilaItens[j,1] = mochila[elemento,1] + mochilaItens[j,1];
itens[i,1] = 1;
                    Fim-Se
               Senão
                     elemento = elemento-1;
                Fim-Se
 Fim-Para
retorne itens;}

//verifica peso atual da mochila
int pesoAtual(double mochila[][]){
int peso = 0;
Para i=0 até mochila[0].tamanho-1 faça
peso = peso + mochila[i,0];
retorne peso; }

//verifica valor atual da mochila
double valorAtual(double mochila[][]){
double valor = 0;
Para i=0 até mochila[1].tamanho-1 faça
                valor = valor + mochila[i,1];
retorne valor;}

quarta-feira, 31 de outubro de 2012

Resumo: Existem três formas principais de se fazer uso de unidades de vetorização nos processadores atuais: (i) pela programação em código de montagem, (ii) através da programação de funções intrínsecas em linguagens de alto nível ou (iii) usar um compilador que traduz automaticamente as operações escalares em vetoriais. Seja através da programação em linguagem de montagem ou usando funções intrínsecas, o programador deve possuir o controle completo dos detalhes da sua implementação, que geralmente é específica para uma arquitetura. Por isso a perseguição da alta performance, nestes casos, pode incorrer em baixa produtividade e portabilidade do código. Esta trabalho apresenta uma análise de vetorização automática usando o compilador GCC, com o objetivo de analisar quais códigos de programas em C/C++ podem ser vetorizados automaticamente e quais necessitam de esforços para adicionar instruções intrísecas no código para alcançar os benefícios da vetorização.



sexta-feira, 26 de outubro de 2012

In this presentation I will show a set of important topics about Software Engineering Empirical Studies that can be useful for increasing quality on your thesis and monographs in general. You can read this presentation and to think about how to do a good experimentation by apply its objectives, validation methods, questions, answers expected, define metrics and measuring it.  I will exhibit how the researchers selected the data for avoid case studies in a biased way using a GQM methodology to sort the study in a simpler view as well.


The full presentation can be seen here!

sexta-feira, 19 de outubro de 2012

Resumo: Através do paradigma de Programação Orientada a Aspectos (POA) é possível alcançar a modularização e o reuso de código para tratar os interesses transversais dos sistemas, onde diversos estudos ensejam uma integração dos mecanismos de tratamento de exceção com esse objetivo. Entretanto, estudos recentes destacam que ao promover essa integração, o paradigma pode aumentar a propensão a defeitos nos sistemas, porque (i) a construção do código para o tratamento de exceção pode ser feita de forma não intencional pelos aspectos, (ii) a falta de consistência entre os aspectos e os componentes pode resultar em implementações incorretas, além de (iii) existirem evidências que as exceções não são capturadas quando os aspectos atuam como manipuladores de exceções. Este trabalho propõe uma plataforma de geração automática de casos de testes que implementarão inspetores de defeitos orientados a aspectos, cuja integração entre os aspectos e componentes será feita no nível de metamodelos, o que resultará em uma maior consistência na criação dos aspectos com o objetivo de contornar essas barreiras.

Resumo: O produto de matrizes é um tema profundamente pesquisado, pois sugere uma maior facilidade na comparação de performance de programas com a utilização da álgebra linear e algumas métricas para esse fim. Neste trabalho são apresentadas 4 estratégias de implementação: (i) multiplicação normal de matrizes, (ii) multiplicação utilizando blocos, (iii) implementação do algoritmo de Strassen e (iv) utilização da biblioteca ATLAS. O objetivo do estudo é comparar a eficiência entre os algoritmos diante das barreiras advindas da convenção de código e estratégias de acesso à memória cache.

Artigo completo pode ser visto aqui

Resumo: O problema dos “números complicados” é definido por um subconjunto dos números de 1 a 1.000 que devem ser escritos usando expressões aritméticas. Ao final, deverão ser exibidos os 10 números mais complicados, onde o grau de complicação é dado pela quantidade de vezes em que os números são utilizados em uma expressão. O trabalho apresenta uma proposta de solução baseada na técnica de programação dinâmica e tabelas de dispersão.

Resumo: O problema do “circulo cortado” pode ser divido em dois desafios principais, quando os números de 1 a n são ordenados em forma circular. O primeiro é encontrar dois números (a e b) no círculo, de forma que se uma linha for desenhada ligando esses números, cortando o círculo, a soma dos números de um lado do círculo é igual à soma dos números do outro lado. O segundo, é executar todas as combinações possíveis que satisfaçam as condições do primeiro desafio para todos os círculos de tamanho 2 até 2 milhões. O presente trabalho apresenta três propostas de solução: (i) algoritmo híbrido baseado nas técnicas de programação dinâmica e força bruta, (ii) programação linear combinada com a técnica de força bruta e (iii) estratégia de busca mínima e máxima para otimização das soluções anteriores e assim vencer os dois principais desafios do problema.


Resumo: O problema "Palácio dos Espelhos"deseja encontrar uma solução algorítmica para calcular as possibilidades de caminhos que um raio de luz pode percorrer de acordo com um número variado de k reflexões em n placas de vidros. O estudo realizou diversas simulações e apresenta uma abordagem que utiliza o cálculo de seqüências de polinômios.

sexta-feira, 14 de setembro de 2012

A origem do termo confiabilidade apareceu em 1830, quando Babbage projetou um dos primeiros mecanismos de cálculo e, após a primeira geração de computadores, nas duas décadas seguintes. Sistemas de software estão presentes em toda parte controlando muitos dispositivos utilizados todos os dias (e.g. computador pessoal, celulares, caixas bancários, fornos industriais, aviões, foguetes), incluindo os sistemas críticos, cujo tipo de aplicação não pode tolerar um mau funcionamento, pois é aumentado drasticamente o risco às pessoas ou ainda causar grandes perdas econômicas às empresas. Muitos sistemas falham diariamente e algumas falhas mudaram a direção das pesquisas na área de tolerância a falhas. Assim, a prevenção de falhas passou a ser utilizada para incluir um controle mais rigoroso durante a fase de análise e projeto de software, estabelecendo um processo de construção de software com atividades que buscam a identificação de falhas antes da sua implementação. 
A necessidade de melhoria na qualidade software, empregando os mecanismos de tolerância a falhas, tornou-se emergente quando muitos estudos demonstraram que a maioria das falhas nos sistemas modernos tem a sua origem na camada de software, o que contraria uma visão anterior, pois as falhas em hardware foram diminuindo através dos anos como conseqüência da qualidade dos seus componentes. Em 1993, um relatório da NRC (National Research Council) apontou que 81% do total das interrupções nos sistemas foram causadas por falhas em software. A única alternativa eficiente seria alcançar a confiabilidade incorporando mecanismos de tolerância a falhas na camada de software. Assim essas técnicas, especialmente o tratamento de exceção, foram incorporadas às necessidades de confiabilidade e detecção de falhas na Engenharia de Software. O tratamento de exceções foi um grande tema de debate na década de 90 na conferência USENIX C++, onde Koenig e Stroustrup apresentaram um modelo para tratamento de exceções Orientado a Objetos. Recentemente, a tecnologia ou paradigma de Programação Orientada a Aspectos (POA) descreve o tratamento de exceções como uma das preocupações transversais em um programa OO e muitas pesquisas destacaram avanços utilizando linguagens de programação orientadas a aspectos, onde a linguagem AspectJ, uma extensão da linguagem de programação Java, aparece freqüentemente nesses estudos.
A integração dos mecanismos de tratamento de exceção, combinados com a tecnologia de POA levantaram diversas questões. Embora a tecnologia possa ser utilizada para promover a modularidade e reutilização de código no tratamento de exceção, é possível observar em outros estudos que também pode aumentar a propensão a defeitos nos sistemas, ocasionando uma maior evidência de exceções não capturadas. Além disso, o seu tratamento pode ser feito de forma não intencional, quando as exceções são lançadas e capturadas de forma inesperada por existir algum tratamento no código de um aspecto. Outro problema grave é a transparência, que tem sido uma propriedade controversa desde as primeiras pesquisas envolvendo POA. A falta de consistência entre os componentes e os aspectos tende a incorrer em implementações incorretas e os resultados revelaram um impacto negativo dessa propriedade nas falhas dos programas implementados com AspectJ. Outros estudos recentes, como os de Figueroa e Tanter e Coelho et al,  tentaram avaliar as vantagens e desvantagens de se empregar a POA para modularizar o código de tratamento de exceções sob diversas perspectivas, envolvendo as práticas de engenharia de software e outras técnicas conhecidas, a exemplo do Design por Contrato (DbC).
Muitos autores acreditam que esses problemas poderiam ser contornados, com a inserção das técnicas de tolerância a falhas nas fases iniciais do desenvolvimento de softwares, pois geralmente, são empregadas tardiamente nas fases de design. Recentemente, a necessidade de incluir tais mecanismos nessas fases tem sido defendida como uma das principais abordagens para garantia do alcance da confiabilidade. Porém, um dos grandes problemas é o fato de existirem diferentes classes de falhas, erros e defeitos a serem identificadas durante o processo de desenvolvimento de um software. Estas classes podem representar diversos interesses dos sistemas (e.g. persistência, log, trace) e de domínio de aplicação (e.g. regras de negócio) dificultando a utilização das técnicas desde o início do desenvolvimento. Assim, um grande número de estudos foi conduzido tentando compreender onde e como a tolerância a falhas pode ser integrada no ciclo de vida do software.
Este estudo tem como objetivo: (i) conhecer a direção das pesquisas que visam o tratamento de falhas residuais relacionadas com as práticas de engenharia de software, (ii) como estão sendo aplicadas e (iii) quais as limitações das abordagens mais recentes. Espera-se investigar a evolução dessas pesquisas, principalmente, as que utilizam os mecanismos de recuperação dos estados anterior e seguinte ao erro e através de uma perspectiva histórica da relação entre as áreas, apresentar um juízo de valor sobre como essas técnicas estão sendo empregadas no ciclo de vida do software.

domingo, 26 de agosto de 2012

Resumo: Este artigo demonstra a análise do algoritmo proposto para resolução do problema "As Minas Encantadas". O estudo apresenta o método utilizado para análise do problema, trechos do código-fonte desenvolvido e uma análise da sua complexidade e resultados. Para demonstração dos resultados foram feitas diversas análises sobre o tempo de execução do algoritmo, onde foi possível demonstrar que o seu padrão de crescimento em função desses tempos pode ser diferente para o cálculo de entradas pequenas e grandes. Este trabalho também demonstra que o tempo de execução do algoritmo pode ser tolerável diante de entradas ainda maiores que as analisadas no estudo, o que indica ser uma possível solução para resolver o problema proposto.

segunda-feira, 4 de junho de 2012

My last presentation on Agile Project Management have approached the Managing Technical Debt - A Practical Approach Using Continuous Integration and Project Management

sábado, 19 de maio de 2012


Mapas Mentais para o Ensino de Engenharia de Software


Os mapas mentais podem representar qualquer tipo de conhecimento de forma sintética, clara e objetiva. Abaixo estou disponiblizando alguns mapas mentais que podem ser utilizados para o ensino de engenharia de software em cursos técnicos ou superiores de computação como recurso adicional às notas de aulas:



Engenharia de Software
  • Engenharia de Requisitos
  • Projeto de Software
  • Modelo de Processos
  • Modelagem
  • Verificação & Validação
  • Metodologias

Tecnologias de Separação de Interesses (Parnas, Foote, Maes, Wiser, Alexander, Kickzales)
  • Desenvolvimento Baseado em Componentes
  • Separação de Interesses
  • Padrões de Projeto
  • Framework
  • Composição Adaptativa
  • Programação Orientada a Aspectos

Desenvolvimento Ágil
  • Manifesto
  • Princípios
  •  Revisão de Software e Programação em Pares

Extreme Programming (XP) Test-driven Development (TDD)
  • Extreme Programming - Conceitos Básicos, Princípios e Práticas Primárias e Corolárias.
  • Desenvolvimento Baseado em Testes - Manifesto, Teste Automatizado, Objetivo, Características, Estratégias e Padrões.

sábado, 21 de abril de 2012


What agile teams think about agile principles
by Laurie Williams - Communications of the ACM 04/2012 vol.55

In the mid-1990s, the prescribed means of keeping software development projects out of trouble and on schedule was to follow a heavyweight software development methodology consisting of a complete requirements document, including architecture and design, followed by coding and testing based on a thorough test plan. The philosophy was often summarized as “Do it right the first time.” Common belief among software engineers at the time was that projects run into trouble when they do not strictly adhere to a methodology, and, if only they did, all would be well. In reality, all was rarely well.

More here

segunda-feira, 5 de março de 2012


 

2 - Basic Definitions 


3 - Series and Summary



4 - Master Method for Recurrences

 
5 - Converting a Mathematical Definition to a Method

Actually, value-producing recursive algorithms are almost identical to inductive definitions. In fact, creating a value-producing recursive algorithm may require little more than the writing down of the inductive definition.

We can first simply rearrange the parts into an algorithm statement:
    Algorithm factorial(n)
        if n less than or equal to 1
              then the answer is 1
              otherwise the answer is: n×factorial(n-1).

It is easy to see that this algorithm is a straightforward piece-by-piece rewriting of the inductive definition: every piece of the algorithm comes directly from the mathematical definition. The Java method for factorial can be derived just as easily from the algorithm:

    //method for class Calculator
    static int factorial(int n) {
        if (n <= 1)
            return 1;
        else return n * factorial(n - 1);
    }
Each component of the definition—and essentially nothing else—appears in the method. It is not uncommon for value-producing recursive algorithms to flow just as directly from the original definition of the needed result. Any mathematical function that can be defined inductively can be similarly translated into a recursive method. This transforms the problem from one of writing methods to solve problems to one of just defining the problem or the mathematical function.

The same approach will work for any inductively defined mathematical functions such as summation:











becomes:
    //method for class Calculator
    static int sum(int n) {
        if (n <= 1)
            return 1;
        else return n + sum(n - 1);
    }

And it gets better: this example extends directly—almost template-like—to any other summation equation. Thus, the sum of squares:




becomes:
    //method for class Calculator
    static int sumSquares(int n) {
        if (n <= 0)
            return 0;
        else return n*n + sumSquares(n - 1);
    }

Source: “Algorithms and Data Structure: The Science of Computing”

Inscreva-se

Creative Commons 3.0. Tecnologia do Blogger.

Teste a Velocidade da Internet

Siga-me

Curta