Sunday, July 31, 2011

Usando colunas esparsas

Colunas esparsas são colunas comuns que têm um armazenamento otimizado para valores nulos. Elas reduzem os requisitos de espaço para valores nulos às custas de maior sobrecarga para recuperar valores não nulos. Considere o uso de colunas esparsas quando o espaço salvo for pelo menos de 20 a 40 por cento. As colunas esparsas e os conjuntos de colunas são definidos usando as instruções CREATE TABLE ou ALTER TABELA.
As colunas esparsas podem ser usadas com conjuntos de colunas e índices filtrados:
  • Conjuntos de colunas
    As instruções INSERT, UPDATE e DELETE podem referenciar colunas esparsas pelo nome. Entretanto, você também pode exibir e trabalhar com todas as colunas esparsas de uma tabela, combinadas em uma única coluna XML. Essa coluna é denominada conjunto de colunas. Para obter mais informações sobre conjuntos de colunas, consulte Usando conjuntos de colunas.
  • Índices filtrados
    Como as colunas esparsas têm muitas linhas de valor nulo, elas são especialmente apropriadas para índices filtrados. Um índice filtrado em uma coluna esparsa pode indexar somente as linhas com valores populados. Isso cria um índice menor e mais eficiente. Para obter mais informações, consulte Diretrizes de criação de índice filtrado.
As colunas esparsas e os índices filtrados habilitam aplicativos, como o Windows SharePoint Services, para armazenar e acessar com eficiência um grande número de propriedades definidas pelo usuário usando o SQL Server.

Índices no SQL Server

Índices nos bancos de dados são utilizados para facilitar a busca de informações em uma tabela com o menor número possível de operações de leituras, tornado assim a busca mais rápida e eficiente.
O exemplo clássico para explicar a utilização de índices é comparar uma tabela do banco de dados a uma lista telefônica, onde a mesma possui um índice por ordem alfabética do sobrenome dos “participantes”. Sabendo a letra inicial do sobrenome é possível refinar a pesquisa iniciando a mesma pela página correspondente a letra do sobrenome.
O SQL Server utiliza o mesmo principio da lista telefônica gravando as informações dos índices em uma estrutura chamada de B-Tree.
Uma estrutura B-Tree possui um nó-raiz que contem uma única página de dados, uma ou mais páginas de níveis intermediários e uma ou mais páginas de níveis folhas. Abaixo segue um exemplo de uma estrutura de B-Tree.

 
Figura 1: Estrutura B-Tree.
Uma B-Tree sempre é simétrica, ou seja, possui o mesmo número de páginas à esquerda e a direita de cada nível.
Obs: Uma página no SQL Server armazena até 8.060 bytes de dados.
Abaixo conforme Figura 2, mostra-se um exemplo de índice em uma estrutura B-Tree para um campo código do tipo inteiro.

Figura 2: Exemplo de índice.
Para construir os níveis raiz e intermediário pega-se o primeiro valor de cada página do nível abaixo junto com o ponteiro da página de onde o valor de dados veio. A cada instrução de inserção, exclusão ou até mesmo alteração é modificado a estrutura dos índices. No caso das páginas utilizadas pelo índice estarem cheias, acontece um processo chamado de divisão de página (page splitting) para comportar a nova estrutura com mais páginas.
Uma busca pelo índice inicia-se no nível raiz percorrendo todas as linhas até achar a cadeia de valores a qual o mesmo se encaixa e através do ponteiro pular para a página do nível intermediário que o mesmo se refere. No nível intermediário repete o mesmo processo até achar a cadeia de valores e pular para a página de nível folha conforme o ponteiro. No nível folha novamente repete-se o processo até achar o valor desejado e nesse momento é localizado os dados necessários.
Por exemplo, conforme a Figura 2, para achar o código 23 iniciaria a busca pelo nível raiz percorrendo as linhas. Como o código 23 está entre 21 e 41 o SQL Server calcula que o código 23 se encontra na seqüência do código 21 e pula para a página do nível intermediário que contem os valores 21 a 31. Em seguida analisaria que a primeira opção (21) se encaixa para a busca e pularia para a página de nível folha que contem a cadeia de 21 a 30, percorreria a mesma até achar o código 23 e finalizaria a busca.
No SQL Server é possível criar índices clusterizados (clustered), não clusterizados (nonclustered), XML e espaciais, sendo os dois últimos para melhorar os recursos de pesquisas em documentos XML e aplicações espaciais, e neste artigo os mesmos não serão abordados. Para maiores esclarecimentos consultar o books online.
Índices clusterizados são ordenados conforme a chave do cluster fornecendo assim uma ordem de classificação para o armazenamento da tabela. Esta ordem de classificação não é a ordem física dos dados e sim a classificação lógica das páginas do índice. É possível definir somente um índice clusterizado por tabela, pois a mesma só pode ser ordenada de uma única maneira.
Índices não clusterizados não classificam ordens e portando é possível criar até 1000 índices nonclustered por tabela tendo cada um no máximo 900 bytes na chave de índice e no máximo 16 colunas. Ao percorrer um índice não clusterizado até seu nível folha em busca do ponteiro para retornar os dados necessários, o mesmo trata os seguintes casos:
·          Existe índice clusterizado na tabela, desta forma o ponteiro aponta para a chave do cluster.
·          Não existe índice clusterizado na tabela, então o ponteiro aponta para a linha de dados da tabela.
A sintaxe para criação de um índice no SQL Server é a seguinte:
CREATE [ UNIQUE ] [ CLUSTERED | NONCLUSTERED ] INDEX index_name
    ON( column [ ASC | DESC ] [ ,...n ] )
    [ INCLUDE ( column_name [ ,...n ] ) ]
    [ WITH ( [ ,...n ] ) ]
    [ ON { partition_scheme_name ( column_name )
         | filegroup_name
         | default
         }
    ]
[ ; ]
::=
{
    [ database_name. [ schema_name ] . | schema_name. ]
        table_or_view_name
}
::=
{
    PAD_INDEX  = { ON | OFF }
  | FILLFACTOR = fillfactor
  | SORT_IN_TEMPDB = { ON | OFF }
  | IGNORE_DUP_KEY = { ON | OFF }
  | STATISTICS_NORECOMPUTE = { ON | OFF }
  | DROP_EXISTING = { ON | OFF }
  | ONLINE = { ON | OFF }
  | ALLOW_ROW_LOCKS = { ON | OFF }
  | ALLOW_PAGE_LOCKS = { ON | OFF }
  | MAXDOP = max_degree_of_parallelism
}
Algumas dicas a serem consideradas na hora de criar índices:
Campos para serem indexados a fim de ganhar desempenho:
·          Chaves Primárias;
·          Chaves Estrangeiras;
·          Colunas acessadas por ranges (between);
·          Campos utilizados em group by ou order by;
Campos que não devem ser indexados:
·          Campos dos tipos: text, image, decimais;
·          Campos calculados;
·          Campos com alta cardinalidade (Masculino ou Feminino);
Criar índices para campos que compreendem uma query que é utilizada com freqüência. Nesse caso de um índice construído de modo que o SQL Server possa satisfazer as consultas completamente lendo apenas o mesmo é chamado de índice de cobertura (covering indexes).
Criar índice clusterizado para campos de chave primária com a propriedade identity.
Criar índice com colunas incluídas (Include). Por exemplo:
CREATE TABLE clientes
(
      Cod INT IDENTITY(1,1) PRIMARY KEY,
      Nome VARCHAR(100),
      UF VARCHAR(2),
      CEP VARCHAR(8)
)
No caso acima é automaticamente criado um índice clusterizado para a chave primária. Vamos seguir o exemplo dizendo que é necessário rodar a seguinte query:
SELECT CEP FROM clientes WHERE UF='RS'
Analisando a query (com fins de demonstrar o exemplo) poderia criar um índice nonclustered para o campo UF. Nesse caso o índice ajudaria a encontrar o valor desejado de uma forma mais rápida, porem o processo de pesquisa seria percorrer o índice e achar o valor desejado que obrigatoriamente o ponteiro apontaria para o cluster que por sua vez apontaria para o dado físico que por sua vez retornaria o valor CEP. Para facilitar esse processo pode-se criar o seguinte índice:
CREATE NONCLUSTERED INDEX IDX_UF ON clientes (UF ASC) INCLUDE(CEP)
Com o índice criado, ao percorrer o mesmo e encontrar o valor para UF desejado o campo CEP incluído não faz parte da indexação, porem é utilizado para retornar sem necessidade de apontar para o cluster, e desta forma se ganha maior desempenho.
Obs: O Exemplo acima foi criado com a finalidade de demonstrar o uso de índices com colunas incluídas, sem levar em consideração análise de desempenho.
Mantendo a integridade dos índices.
Tabelas que sofrem muitas alterações (Insert, Update e Delete) refletem essas modificações nos índices, pois acabam deixando espaços em brancos nas páginas dos mesmos. Estes espaços não utilizados refletem em maior espaço em disco o que acarreta um desperdício de tempo ao percorrer a estrutura do índice.
Para resolver esses problemas é necessário manter a integridade dos índices, utilizando os seguintes comandos:
ALTER INDEX {nome_indice | ALL} ON REBUILD
ALTER INDEX {nome_indice | ALL} ON REORGANIZE
A opção REORGANIZE remove somente a fragmentação no nível folha e a opção REBUILD reconstrói todos os níveis do índice.
Para os comandos acima citados, é possível substituí-los respectivamente por:
DBCC DBREINDEX
DBCC INDEXDEFRAG
Métodos de acessos aos índices e tabelas.
Os acessos aos dados das tabelas e índices podem ser de duas formas, SEEK ou SCAN.
·         SCAN - busca em TODOS os elementos da estrutura (que pode ser uma tabela ou um índice). É usado quando não possui índices que atendam a instrução de select ou quando a quantidade de registros que a query retorna (em percentual) é grande.
·         SEEK - busca binária nos elementos de um índice. É usado quando existe um índice que é adequado e a quantidade de registros (em percentual) retornados é pequena.
Sendo assim, é possível executar as seguintes operações para acesso nas tabelas/índices:
·         TABLE SCAN - Busca em todos os elementos da tabela, de forma seqüencial;
·         INDEX SCAN - Busca em todos os elementos de um índice nonclustered, de forma seqüencial;
·         INDEX SEEK - Busca binária num índice nonclustered;
·         CLUSTERED INDEX SCAN - Busca em todos os elementos de um índice clustered, de forma seqüencial;
·         CLUSTERED INDEX SEEK - Busca binária num índice clustered.
Quando uma tabela possui mais de um índice, o SQL Server precisa tomar uma decisão de qual (is) deles utilizar em uma consulta de dados. Esta escolhe se dá através das estatísticas (statistics) de acesso.
Quando um índice é criado, o SQL Server gera uma estrutura chamada histograma, que armazena informações sobre a distribuição relativa de valores de dados de uma coluna. À medida que o número de valores exclusivos dentro de uma coluna aumenta, a seletividade de um índice aumenta. Os índices mais seletivos são os escolhidos para satisfazerem uma consulta.
Da mesma forma que um índice pode ser danificado com o passar do tempo, o mesmo acontece para as estatísticas. Para atualizar as estatísticas basta rodar a sintaxe abaixo:
UPDATE STATISTICS <nome_tabela>
O comando acima pode ser substituído pela a seguinte store procedure:
SP_UPDATESTATS
Nota-se que a store procedure não possui nenhum parâmetro e desta forma ela atualiza todas as estatísticas de todas as tabelas do banco de dados no qual a mesmo foi executada.
É possível através do SQL Server monitorar as escolhas que o mesmo fez para acessar os dados em uma instrução de busca. Utilizando a ferramenta Microsoft SQL Server Management Studio é possível visualizar todo o processo de leitura ao rodar uma query habilitando o Execution Plan.

Figura 3: Exibição do Execution Plan.
A Figura 3 demonstra como o SQL Server procedeu para realizar a query. Foi utilizado o SELECT descrito neste artigo ao abordar a criação de índices com colunas incluídas.

Figura 4: Resumo do SELECT
A Figura 4 traz as informações referentes à instrução de SELECT conforme a Figura 3.

Figura 5: Resumo das etapas para executar a instrução de SELECT conforme a Figura 4.
Obs: A tabela foi criada para demonstrar o Execution Plan. A mesma não possui nenhum registro e sendo assim os índices e as estatísticas também não possuem informações.
O SQL Server dispõe de uma ferramenta chamada Database Engine Tuning Advisor que é muito útil para analisar os índices existentes em cima de instruções de acesso a uma base dados para sugerir melhorias referentes aos mesmos. Nesse artigo não será abordado como utilizar a mesma, porem fica a dica.

Varchar, Char, NVarchar, NChar e suas variantes MAX

Se você usa o banco de dados SQL Server em suas aplicações já notou a ampla gama de tipos de dados que ele oferece.
A seguir temos alguns tipos de dados do SQL Server para armazenamento de Strings:
ASCII Strings:
Tipos de dados Descrição
char(n) Sequência de caracteres de tamanho fixo. Máximo 8000 caracteres
varchar(n) Sequência de caracteres de tamanho variável. Máximo 8000 caracteres
varchar(max) Sequência de caracteres de tamanho variável. Máximo 1.073.741.824 caracteres
text Sequência de caracteres de tamanho variável. Máximo 2GB de dados de texto
Unicode strings:
Tipos de dados Descrição
nchar(n) Dados Unicode de comprimento fixo. Máximo 4000 caracteres
nvarchar(n) Dados Unicode de comprimento variável. Máximo 4000 caracteres
nvarchar(max) Dados Unicode de comprimento variável. Máximo 536.870.912 caracteres
ntext Dados Unicode de comprimento variável. Máximo 2GB de dados de texto
Essa ampla gama de tipos de dados no SQL Sever pode às vezes causar confusão no momento de decidir qual tipo de dados atribuir a um campo de uma tabela principalmente quando eles são parecidos.

Os tipos de dados VARCHAR, CHAR, NCHAR e NVARCHAR se enquadram nesta categoria e por serem muito usados e muito parecidos geralmente causam uma certa dúvida no momento de sua utilização. (Não vou tratar o tipo de dados text/ ntext)

Meu objetivo é tentar esclarecer as dúvidas a respeito das diferenças entre estes dois tipos de dados.

Então vamos lá...

Qual a diferença entre os esses tipos de dados ?

Qual a diferença entre VARCHAR e CHAR ???
CHAR e VARCHAR são tipos de dados caractere, a diferença é que CHAR é um tipo de dado de comprimento fixo e VARCHAR é de comprimento variável.

Usamod CHAR quando os tamanhos que desejamos armazenar na coluna de uma tabela são de tamanho consistentes e semelhantes. Exemplo: Número de telefone, CEP, CPF, CGC, etc. O tipo CHAR possui um tamanho fixo, assim se você tentar armazenar um valor maior que o definido numa coluna do tipo CHAR ele será truncado.

Se você definir uma coluna da tabela (campo) como CHAR(10) e armazenar um caractere apenas ele vai armazenar mais nove espaços em branco.( Por causa desta característica o tipo de dados CHAR é chamado de tipo de dados com tamanho fixo.)

Use VARCHAR quando os tamanhos a serem armazenados na coluna da tabela variam consideravelmente. Ex: Endereço,Nomes, URL, etc. Dessa forma um valor menor irá ocupar menos espaço que um valor maior.
O tipo de dados VARCHAR armazena somente a quantidade de caracteres que foram definidos na usa criação.
Assim se você definir uma coluna da tabela (campo) como VARCHAR(10) e armazernar um caractere ele vai armazenar somente o caractere sem colocar espaços para completar o tamanho definido na criação.
Quando usar CHAR ou VARCHAR ?
O tipo CHAR deve ser usado quando sabemos que todos os dados armazenados em determinada coluna não são variáveis como, por exemplo, uma coluna que armazena a sigla do estado ou o cep que sempre terão o mesmo tamanho.

Já o VARCHAR deve ser utilizado quando não sabemos o que vamos armazenar. Um exemplo pode ser o nome do cliente, endereço, o email que sempre variam de tamanho.

Qual a diferença entre NVARCHAR E NCHAR ?
NCHAR e NVARCHAR são semelhantes a CHAR e VARCHAR a diferença é que eles armazenam dados no formato Unicode e utilizam para isso a representação de 1 byte para cada caractere usando assim uma representação de 16 bits.
Qual a diferença entre VARCHAR e NVARCHAR ???
VARCHAR é uma abreviação para VARiable-length CHARacter string que é uma sequência de caracateres de texto que pode ser tão grande quanto o tamanho da página para a tabela de banco de dados da coluna em questão.
O tipo de dados VARCHAR armazenam os dados em ASCII e utilizam 1 byte ou 8 bits para representar um caractere.
O tamanho de uma página de tabela é 8196 bytes, e não uma linha em uma tabela pode ser superior a 8.060 caracteres. Este, por sua vez, limita o tamanho máximo de um VARCHAR para 8.000 bytes.

E o tipo de dados NVARCHAR ?

Bem, o N(VARCHAR) significa uNicode e essencialmente , NVARCHAR nada mais é do que um VARCHAR que suporta Unicode ou seja que usa dois bytes para representar um caractere.

O tipo de dados NVARCHAR armazenam os dados em Unicode e utilizam 2 bytes ou 16 bits para representar um caractere.

Um uso mais comum para esse tipo de de dados e quando você deseja armazenar caracteres de idíomas que exigem mais de u m byte para representar um caractere.

Assim quando você define uma coluna como sendo VARCHAR(30) terá 30 bytes alocados para a colun. Se você usar o tipo NVARCHAR(30) terá 60 bytes alocados.
Portanto o tamanho máximo para o tipo de dados VARCHAR (e CHAR) é 8000 bytes e para o tipo de dados NVARCHAR (e NCHAR) é 4000 bytes.
A partir da versão SQL Server 2005 introduziu um novo tipo de dados , o tipo de dados XML que permite armazenar documentos XML em um banco de dados SQL Server.
Para suportar o novo tipo de dados foram introduzidos também 3 novos tipos de dados diferentes: VARCHAR(MAX), NVARCHAR(MAX) E VARBINARY(MAX)
A utilização de MAX indica que esses tipos de dados podem armazenar um valor superior aos seus respectivos limites: 8000 e 4000 bytes.VARCHAR (MAX) - indica que o tamanho máximo de armazenamento para o tipo de dados VARCHAR é 2^31 bytes ( 2 GB)
NVARCHAR (MAX) - indica que o tamanho máximo de armazenamento para NVARCHAR o tipo de dados é
2^31 bytes ( 2 GB)
VARBINARY (MAX) - indica que o tamanho máximo de armazenamento para o tipo de dados VARBINARY é
2^31 bytes ( 2 GB)


Quando usar VARCHAR ou NVARCHAR ?

Depende ???
Poderíamos usar duas linhas de pensamento:




  • Usar VARCHAR a menos que precisamos lidar com uma grande quantidade de dados internacionalizados, neste caso use NVARCHAR;





  • ou
    • Usar NVARCHAR para tudo;
    Se você tem sites que oferecem suporte a vários idiomas, considere usar os tipos de dados que dão suporte a Unicode como NCHAR ou NVARCHAR para minimizar os problemas de conversão de caracteres.
    Se sua aplicação nunca vai precisar tratar textos multilíngues ou lidar com dados internacionalizados você pode usar VARCHAR e assim terá o máximo de 8000 bytes a sua disposição mas se um dia você precisar migrar o tipo de dados o 'bicho vai pegar...'
    Lembre que se você usar NVARCHAR para tudo terá a sua disposição somente 4000 bytes no tipo de dados atribuído. (A menos que use MAX).
    Existe um detalhe importante quando você usa NVARCHAR OU VARCHAR : os campos NVarchar não sofrem influência do Collation e o Varchar sofre.
    Obs: A Collation refere-se ao conjunto de caracteres usado para armazenar dados em campos de texto sendo necessária para fornecer suporte para os muitos idiomas que podem ser usados.
    Quando usamos CHAR ou VARCHAR as colunas são atribuidas a Collation padrão do banco de dados a menos que uma collation específico seja atribuido usando a cláusula COLLATE.

    A incorreta definição da Collation quando você usar VARCHAR, vai afetar muitos caracteres, e , assim alguns registros que contenham por exemplo a palavra "ausência" será mostrado como "aus?ncia" , ou seja, caracteres acentuados não serão representados corretamente.

    Deterministic and Nondeterministic Functions

    Deterministic functions always return the same result any time they are called with a specific set of input values and given the same state of the database. Nondeterministic functions may return different results each time they are called with a specific set of input values even if the database state that they access remains the same.

    The following built-in functions from categories of built-in functions other than aggregate and string functions are always deterministic.
    ABS DATEDIFF PARSENAME
    ACOS DAY POWER
    ASIN DEGREES RADIANS
    ATAN EXP ROUND
    ATN2 FLOOR SIGN
    CEILING ISNULL SIN
    COALESCE ISNUMERIC SQUARE
    COS LOG SQRT
    COT LOG10 TAN
    DATALENGTH MONTH YEAR
    DATEADD NULLIF
    The following functions are not always deterministic, but can be used in indexed views or indexes on computed columns when they are specified in a deterministic manner.
    Function Comments
    CAST Deterministic unless used with datetime, smalldatetime, or sql_variant.
    CONVERT Deterministic unless one of these conditions exists:
    • Source type is sql_variant.

    • Target type is sql_variant and its source type is nondeterministic.

    • Source or target type is datetime or smalldatetime, the other source or target type is a character string, and a nondeterministic style is specified. To be deterministic, the style parameter must be a constant. Additionally, styles less than or equal to 100 are nondeterministic, except for styles 20 and 21. Styles greater than 100 are deterministic, except for styles 106, 107, 109 and 113.
    CHECKSUM Deterministic, with the exception of CHECKSUM(*).
    ISDATE Deterministic only if used with the CONVERT function, the CONVERT style parameter is specified and style is not equal to 0, 100, 9, or 109.
    RAND RAND is deterministic only when a seed parameter is specified.
    All the configuration, cursor, metadata, security, and system statistical functions are nondeterministic. For a list of these functions, see Configuration Functions (Transact-SQL), Cursor Functions (Transact-SQL), Metadata Functions (Transact-SQL), Security Functions (Transact-SQL), and System Statistical Functions (Transact-SQL).
    The following built-in functions from other categories are always nondeterministic.
    @@CONNECTIONS @@TOTAL_READ
    @@CPU_BUSY @@TOTAL_WRITE
    @@DBTS CURRENT_TIMESTAMP
    @@IDLE GETDATE
    @@IO_BUSY GETUTCDATE
    @@MAX_CONNECTIONS GET_TRANSMISSION_STATUS
    @@PACK_RECEIVED MIN_ACTIVE_ROWVERSION
    @@PACK_SENT NEWID
    @@PACKET_ERRORS NEWSEQUENTIALID
    @@TIMETICKS RAND
    @@TOTAL_ERRORS TEXTPTR

    Tail-Log Backups

    This topic is relevant only for databases that are using the full or bulk-logged recovery models.
    In most cases, under the full or bulk-logged recovery models, SQL Server 2005 and later versions require that you back up the tail of the log to capture the log records that have not yet been backed up. A log backup taken of the tail of the log just before a restore operation is called a tail-log backup.
    SQL Server 2005 and later versions usually require that you take a tail-log backup before you start to restore a database. The tail-log backup prevents work loss and keeps the log chain intact. When you are recovering a database to the point of a failure, the tail-log backup is the last backup of interest in the recovery plan. If you cannot back up the tail of the log, you can recover a database only to the end of the last backup that was created before the failure.
    Not all restore scenarios require a tail-log backup. You do not have to have a tail-log backup if the recovery point is contained in an earlier log backup, or if you are moving or replacing (overwriting) the database. Also, if the log files are damaged and a tail-log backup cannot be created, you must restore the database without using a tail-log backup. Any transactions committed after the latest log backup are lost. For more information, see "Restoring Without Using a Tail-Log Backup" later in this topic.

    DBCC (Transact-SQL)

    The Transact-SQL programming language provides DBCC statements that act as Database Console Commands for SQL Server.
    Database Console Command statements are grouped into the following categories.
    Command category Perform
    Maintenance Maintenance tasks on a database, index, or filegroup.
    Miscellaneous Miscellaneous tasks such as enabling trace flags or removing a DLL from memory.
    Informational Tasks that gather and display various types of information.
    Validation Validation operations on a database, table, index, catalog, filegroup, or allocation of database pages.
    DBCC commands take input parameters and return values. All DBCC command parameters can accept both Unicode and DBCS literals.

    Friday, July 29, 2011

    Peter Joseph no Brasil

             
    Video streaming by Ustream

    Sua vida em 10 segundos

    Ciclo de Vida de um Notebook

    Partes Interessadas

    Partes ? Interessadas ?

    Quantas vezes já lhe perguntaram, ou até mesmo você tenha se perguntado, o quanto a sustentabilidade pode ser boa para o negócio ? Quantas vezes você apresentou casos de empresas que foram bem sucedidas com suas estratégias de sustentabilidade, mas alguém de sua empresa comentou: “aqui é diferente” ? A sustentabilidade é, por essência, a arte de entender e considerar o “outro”. Mas o outro, é outra história !

    A eterna busca

    “Diga-me quanto ganharemos que te direi o tamanho do orçamento”
    Talvez esta seja a máxima que impera nos negócios atualmente. Podemos concordar ou não, mas o fato é que este é o canal de diálogo mais eficiente para se entabular uma conversa estratégica com as empresas sob qualquer tema. Não poderia ser diferente para o caso da sustentabilidade na maioria dos casos.
    Neste sentido, diversas organizações se debruçaram para tentar entender qual o retorno que a sustentabilidade pode trazer ao negócio.
    De todos os que conheço, a publicação do World Business Council for Sustainable Development (WBCSD) intitulada “Corporate Ecosystem Valuation – Building the Business Case” é uma daquelas que endereça este ponto de forma mais objetiva.
    Detenha-se aos exemplos apresentados pelo estudo e tente, por um instante que seja, imaginar qual seria a reação dos executivos de uma empresa aqui no Brasil ao conectar estes riscos e oportunidades apresentadas com o negócio que dirigem.
    Exemplos de impactos. Fonte: World Business Council for Sustainable Development
    Se você trabalha em alguma empresa onde os exemplos acima dizem pouca coisa ou não dizem nada, certamente a estratégia de utilizar estes argumentos não seria a mais adequada.
    É claro que devemos olhar para a proposta desta publicação apenas como um guideline que orienta como se estrutura um Business Case de Sustentabilidade, e para tanto, precisaríamos identificar (dentro do escopo do negócio analisado) quais seriam os riscos e oportunidades que mais façam sentido para os tomadores de decisão.
    Riscos e oportunidades somente são úteis quando os tomadores de decisão percebem fazer algum sentido para o negócio que dirigem, na mesma perspectiva de tempo que estes são cobrados pelos resultados. Em outras palavras, se são avaliados pelo curto prazo apenas, pouco adiantará apresentar riscos e oportunidades de médio/longo prazos. Na maioria dos casos, isto não funciona.

    Torre de Babel

    Darei uma longa volta agora, mas é necessário: não é possível falar de riscos e oportunidades para o negócio sem tocar no tema das partes interessadas.
    No início de 2007, estávamos em um projeto de sustentabilidade junto a uma empresa líder em seu setor de atuação no mercado doméstico e iniciando seu processo de internacionalização. Buscávamos identificar os stakeholders e suas demandas de presente e futuro para, a partir daí, identificar os riscos e oportunidades do negócio no campo da sustentabilidade.
    Àquela época, sentíamos que os métodos existentes para identificação de partes interessadas, bem como suas demandas presentes e latentes, não nos atendia. Isto porque temos no Brasil uma cultura muito própria e uma forma de pensar “relacionamentos” um tanto diferente de países onde o controle social sobre as empresas é muito maior. Até aí nenhuma novidade, pois já sabíamos há muito que métodos desenvolvidos em culturas diferentes da nossa não poderiam ser aplicados em sua totalidade e precisariam ser, como dizem os profissionais de tecnologia da informação, tropicalizados.
    Começamos então a repensar o conceito de partes interessadas para a realidade dos executivos que lidávamos localmente, a partir de algumas premissas:
    1)    Uma parte interessada deve representar um agente da sociedade que seja representativo na relação com a empresa;
    2)    A representatividade da parte interessada é dada por múltiplos fatores combinados: seu poder de impactar o negócio, a natureza deste impacto, sua importância em relação ao todo que ela representa, os potenciais riscos e oportunidades para a manutenção do negócio e da parte interessada em si e, o mais importante, os aspectos éticos independentes de todos os demais fatores mencionados (manutenção da vida, dignidade, liberdade, respeito, dentre outros);
    3)    A perspectiva temporal a ser considerada na análise deve levar em consideração não apenas o presente, mas sobretudo o futuro. Não apenas os casos conhecidos, mas os casos com possibilidade de ocorrerem;
    4)    As partes interessadas se relacionam de múltiplas formas com o negócio: direta, indireta e sistemicamente (veremos mais sobre isso adiante).
    Mencionei no post Cadê o foco ? que uma das possibilidades que temos é nos utilizarmos de agendas já conhecidas, como por exemplo o estudo da Fundação Dom Cabral acerca dos desafios de sustentabilidade brasileiros. Entretanto, este estudo é útil para o início do processo da sustentabilidade na empresa. Em certos momentos, é importante trazer a realidade à tona, fazendo valer as opiniões e demandas do conjunto de partes interessadas em relação ao negócio em si.
    Todavia, quando se começa a questionar quais são as partes interessadas de um negócio, chega-se a números incrivelmente não imaginados antes do processo, o que dificulta bastante sua priorização (média=40 e máximo=90 nos projetos que já realizamos). Adicionalmente, a questão de presente e futuro também traz muitas incertezas acerca do que e como considerar neste processo.
    A experiência tem nos mostrado que as partes interessadas podem ser classificadas em pelo menos 3 grandes grupos, todos eles expressando o nível de relacionamento destas com o negócio:
    1. as que se relacionam diretamente com o negócio,
    2. as que se relacionam indiretamente e
    3. aquelas cujo relacionamento é sistêmico.
    Esses grupos de partes interessadas nos levam a maior ou menor dificuldade de identificá-las e entender suas demandas para com o negócio, assim como nos aproxima ou nos distancia dos riscos ou oportunidades inerentes.
    Portanto, para que não soe como uma Torre de Babel os resultados do mapeamento de todas estas demandas, é importante ter alguns critérios sobre como identificar, mapear e priorizar as partes interessadas com as quais se pretende trabalhar no âmbito da agenda de sustentabilidade.
    Partes interessadas de relacionamento direto – são as mais óbvias, por se apresentarem ao negócio de forma explícita. Por exemplo os clientes, as comunidades do entorno ou os fornecedores. São fáceis de identificar, o processo de entendimento de suas demandas não apresentam grandes dificuldades por um simples fato: você sabe quem são e consegue acessá-las de forma relativamente simples. Peguemos um exemplo:
    Fonte: Gestão Origami
    Partes Interessadas de relacionamento indireto – são aquelas cujo relacionamento com a organização não se dá de forma direta, mas indiretamente. Quase sempre são “outras partes” que falam em nome das diretas, como por exemplo o Governo, as ONGs, as Associações de Moradores do entorno da empresa, o Sindicato dos funcionários. Estas partes interessadas ainda são facilmente identificadas, entretanto, sua manifestação em relação à empresa, quando ocorre, tende a representar algum grau de tensão pelo fato de, na relação direta, as questões não terem sido resolvidas entre os envolvidos. Usualmente as partes interessadas da relação do tipo “indireta” tendem a se manifestar pelo interesse de um coletivo pouco ou nada atendido.
    Fonte: Gestão Origami
    Um caso recente desta relação indireta ocorreu no segmento de call centers. Cansados de protocolar ações no PROCON, o Governo apresentou e aprovou projeto de lei regulamentando este tipo de atendimento. O mesmo aconteceu com os bancos no caso das portas giratórias, ou ainda no recall de veículos da empresa FIAT para o modelo Stilo.
    Diversos são os casos conhecidos que não envolvem apenas representantes de consumidores ou clientes, mas também funcionários, comunidades do entorno, comunidades de redes sociais, dentre outros.
    Partes interessadas de relacionamento sistêmico – por fim, mas não menos importante (pelo contrário!), o caso das relações sistêmicas. Este caso envolve um número maior de partes interessadas tratando de determinados temas ou organização. Assume uma dimensão global, envolve especialistas, mídia, blogs, redes sociais, enfim, todo o conjunto da sociedade. Quando um caso de reação sistêmica ocorre quanto a um projeto, uma empresa ou mesmo em relação ao governo, os impactos negativos assumem proporções de maior escala.
    Fonte: Gestão Origami
    Casos recentes de relações sistêmicas que podemos citar são Usina Belo Monte, o impacto do relatório do Greenpeace em relação à Amazônia brasileira, o caso de discriminação de aluna do campus ABC da Universidade Uniban.

    De volta à eterna busca

    Sabemos que a identificação das partes interessadas é importante. Porém, mais importante do que identificá-las, é entender o que demandam hoje e no futuro em relação ao negócio da empresa. Ainda assim, é importante entender as demais partes interessadas que estão indiretamente ou sistemicamente ligadas e como estas tendem a se comportar.
    Fonte: Gestão Origami
    Algumas constatações que podemos traçar a partir daí, no tocante ao que realmente pode ser importante:
    1)    Entender as partes interessadas cujo relacionamento se dá de forma sistêmica com o negócio – só assim a empresa conseguirá se antecipar a elas, tratando os riscos e oportunidades com o tempo devido. Merecem especial atenção as empresas cujos negócios estejam em setores da atividade econômica mais expostos às questões da sustentabilidade, como por exemplo os chamados “temas controversos” (plástico, petróleo, agronegócio em escala, dentre tantos outros).
    2)    Articular-se junto às partes interessadas cujo relacionamento se dá indiretamente com o negócio – só assim a empresa conseguirá dialogar, defender seu interesse dentro de premissas pré-acordadas entre os atores. Pode ser difícil, dado ser um espaço de constante tensão. Mas é desta tensão que devem surgir resoluções que sejam boas para todos no longo prazo, por terem sido minimamente acordadas. Negligenciar a existência deste espaço, não estar aberto ao diálogo, não saber ceder, não saber exigir quando necessário, pode vir custar caro para a empresa no futuro, seja pelo lado do risco, seja pelo lado da oportunidade.
    3)    Dialogar junto às partes interessadas cujo relacionamento se dá diretamente com o negócio –  junto a estas, atuar no relativamente óbvio: ouvir, dialogar. Afinal, estão conectadas ao negócio diariamente e nada mais lógico do que começar o exercício de diálogo com estas.
    Comecei este post falando da busca pelos resultados que a sustentabilidade pode trazer aos negócios. Passei pela proposta do WBCSD que trata da elaboração de um Business Case e, na seqüencia, abordei os aspectos ligados às partes interessadas.
    Para que tudo isso ?
    Nenhum negócio produz resultados contínuos se não estiver alinhado com a sociedade de seu tempo e se não reconhecer a tendência de sua evolução. Portanto, ser sustentável é estar alinhado a esta sociedade, suas demandas, seus desejos, suas contradições. Uma empresa não conseguirá se manter (seja no curto, médio ou longo prazos) se não entender de que sociedade estamos falando. Parece óbvio quando dito, mas convenhamos, não é isto o que muitas empresas têm feito ou priorizado.
    Mas não é muito inteligente de nossa parte lutarmos contra a maré. É claro que precisamos, sempre que possível, tocar na nota “uma empresa sem visão de longo prazo não se sustenta, assim como uma sociedade não se mantém sem um projeto de longo prazo”. Tocar nessa nota é como fixarmos uma marca em nossa trajetória de sustentabilidade na empresa: todos vão se lembrar, mas poucos se sensibilizarão e mudarão de fato no presente, no curto espaço de tempo.
    Logo, como o queremos é fazer que a sustentabilidade avance dentro dos limites possíveis, onde puxamos a corda até o limite, mas sem rompê-la, vejo que algumas mudanças na forma como tratamos deste tema devam ser consideradas. Devemos não apenas mirar no longo prazo, mas sim passar a adotar estratégias mais adequadas ao foco do foco de nosso cliente interno, dos tomadores de decisão. Se a realidade que vivem, se a forma como são cobrados está intimamente ligada ao curto prazo, como podemos trazer questões de curto prazo relacionadas às partes interessadas que possam significar algo de concreto para uma ação efetiva ?
    Não nos esqueçamos que, há não muito tempo, muitas questões eram consideradas de longo prazo e são hoje uma realidade, como: as cotas para deficientes e portadores de necessidades especiais, as questões de assédio moral e sexual, questões relacionadas a gases de efeito estufa, os licenciamentos ambientais para obras de infra-estrutura e de alto impacto, a participação da sustentabilidade nos espaços de notícia, dentre tantas outras.
    O desafio de todos que trabalham com sustentabilidade é identificar temas que façam sentido no contexto das prioridades das lideranças. Podem ser no curto, médio ou longo prazos, não importa. O importante é encontrar uma forma de entrar na agenda a partir de assuntos relacionados ao contexto da empresa (leia-se: partes interessadas) que possam, primeiramente, representar oportunidades (afinal, é muito melhor tratarmos destas – agenda positiva) e depois, os riscos. Sejam nas oportunidades ou nos riscos, repito, é importante que façam sentido para as lideranças.
    Finalizando, se quisermos construir um Business Case de Sustentabilidade, são estes os fatores que devemos levar em consideração. Não adianta “importarmos” modelos de impactos. É imperativo analisarmos e criarmos o nosso próprio modelo, mediante uma detida análise do entorno da empresa, seja pela ótica da oportunidade, seja pela ótica do risco.

    Tuesday, July 26, 2011

    Uma Música Atemporal Sobre Esperança

    Helloween - I Want Out

    Helloween - Forever And One

    O que é uma RFP?

    Request For Proposal. É uma solicitação de propostas feitas pelo comprador, que elabora sua especificação técnica e apresenta para os fornecedores, para a contratação de serviços especializados. Seu objetivo é identificar um ou mais fornecedores que atendam as necessidades do comprador no fornecimento dos bens e serviços requeridos, oferecendo o
    melhor nível de qualidade possível.

    Thursday, July 14, 2011

    Faith No More Easy Live

    DMAIC

    DMAIC (Define, Measure, Analyse, Improve, andControl) refers to a data-driven life-cycle approach to Six Sigma projects for improving process; it is an essential part of a company's Six Sigma programme. DMAIC is an acronym for five interconnected phases: define measure, analyse, improve and control.

    Define by identifying, prioritizing and selecting the right project,
    Measure key process characteristic, the scope of parameters and their performances,
    Analyse by identifying key causes and process determinants,
    Improve by changing the process and optimizing performance,
    Control by sustaining the gain.


    Monday, July 11, 2011

    Receita para manter as coisas como são

    Você pega um homem comum e o coloca no controle,
    Veja-o se transformar em um deus
    Ai você ve a cabeça das pessoas rolarem

    Sunday, July 10, 2011

    Rock n' Roll de Homem!

    CHEGA DE OBA-OBA

    O livro da alemã Judith Mair, empresária do ramo da publicidade, foi lançado na Europa há 3 anos. Caso a autora fosse uma acadêmica, o seu livro não causaria maiores surpresas ao revelar uma análise crítica, lúcida, humanamente responsável, perspicaz e refinada dos mecanismos de controle sutis, desenvolvidos pelas empresas modernas, para melhor garantir desempenhos cada vez mais elevados.Cética em relação aos modismos gerenciais, às sugestões embusteiras de empresas de consultoria que tentam fazer crer que trabalho e lazer são a mesma coisa, às receitas simplificadoras que tentam convencer os funcionários que eles agora são livres e auto-determinados e que o local de trabalho é a nova fonte da felicidade, Mair constrói uma argumentação poderosa que denuncia a empulhação por trás de mensagens belas e vazias no mundo empresarial de hoje, reivindica o direito de uma empresa ser somente uma empresa e de um funcionário o direito de ser um funcionário. Seu livro pode ser visto como uma bela, irreverente e pertinente contribuição às áreas de recursos humanos e análise organizacional, particularmente no que diz respeito ao falso endeusamento de culturas empresariais e a natureza de controles “motivacionais” escondidos sob o manto da sedução. Senão, vejamos algumas de suas idéias barulhentas.

    O esfacelamento do mundo do trabalho trouxe na sua rasteira um enfraquecimento das estruturas organizacionais tradicionais, nas quais horário, contrato, processo e local de trabalho, imagem e qualificações profissionais foram profundamente alterados. A resposta organizacional tem sido alardeada por meio da rapidez e flexibilidade, na abolição de hierarquias, na primazia do trabalho em grupo e na gestão emocional, tudo embalado por um discurso de “empresa humana”. Porém, no dia-a-dia, a vida é mais complicada, pois o descarte dos instrumentos clássicos de gestão deixou um vácuo e tanto as chefias quanto os funcionários estão desorientados e perdidos. As empresas, inundadas de promessas, de bom humor, de trabalho e de convivência harmoniosa, escondem que o trabalho pode ser chato, monótono, rotineiro, limitado e que muitas vezes nega a liberdade e a beleza que o discurso sedutor tenta apregoar. Pretende-se que não existem limites, obrigações e fatos organizacionais nem sempre agradáveis. O discurso da área de recursos humanos proclama o funcionário como a mais valiosa matéria-prima, que o “capital humano” de qualidade é o grande diferencial e que precisa de cuidados e mimos, bem como propõe um mundo do trabalho festeiro e idílico com funcionários felizes, exercendo todo o seu potencial criativo. Ora, o funcionário “emancipado” não tem muito que comemorar, pois o que conta é o resultado. A coação foi substituída pela pressão, regras e estruturas pela sutileza do controle e pela sobrecarga, caracterizando uma ditadura do trabalho que determina o ritmo acelerado do dia do indivíduo e invade a sua vida privada, levando-o mesmo à exaustão.

    E tudo isso diluído no prazer de trabalhar. Não vemao caso se as metas são impossíveis de serem alcançadas, se as cobranças são exageradas e se o funcionário não conta mais com a orientação de seu chefe; ele é obrigado a se sentir livre e a aplaudir a sua recém-conquistada liberdade, responsabilidade e autonomia. O tempo é um organizador da vida, mas o “novo tempo” das empresas desconsidera a noção de hora, dia e semana. Não existe fim de expediente, fim de semana ou vida privada. Fortalecido pela tecnologia mais moderna, principalmente em relação aos poderosos telefones celulares e computadores, o mundo do trabalho invade a vida familiar e amorosa do indivíduo e lembra-o de que ele deve estar sempre a postos. Noites insones, olheiras, úlceras e infartos são sinais de status, exibidos por esses funcionários “insubstituíveis e imprescindíveis”. No longo prazo, a solicitação constante, a privação do sono e a insuficiente compensação no plano privado não são positivas para um trabalho eficaz. Burn-outs, depressão e vários outros sintomas de doenças psicossomáticas são desconsiderados como causados por essa “desorganização” do trabalho, pela usura do tempo de trabalho e pela cobrança crescente de resultados espetaculares.

    O relógio de ponto são os olhares acusadores dos colegas da própria equipe. O mandamento máximo hoje é definido pela capacidade de reação e mudanças rápidas. A experiência não vale nada, objetivos de longo prazo e estabilidade são palavrões. Existe o fetiche da mudança. Tanto no comportamento da empresa como no dos funcionários é o modelo do camaleão que deve ser seguido, permanecendo um amontoado oportunista mutável, sem feição e sem coerência. Perde-se a substância da empresa na forma de saber, experiência, qualificação e talento de seu pessoal. Tudo é tratado como descartável, devendo abrir espaço ao sempre novo. Assim, a organização se torna elástica, orientada por projetos e uma espécie de “anarquia organizada”. As hierarquias são o vilão, pois elas retardam processos, dificultam a cooperação, roubam motivação e inibem as inovações. Pretende-se que nesse “novo modelo” encontra-se a parceria e a igualdade de direito entre todos, que o funcionário se torna um igual, que estão todos no mesmo barco,que todos partilham o mesmo ponto de vista e que tudo diz respeito a todos. Ora, mas sabe-se que o poder está muito bem amarrado nos andares superiores e isso se evidencia tão logo seja conveniente e necessário fazer alguma reestruturação, reduzir custos ou demitir. O que era “cordial” rapidamente se torna autoritário! Em vez de pregar uma igualdade que não existe, exceto como discurso manipulador, as empresas fariam melhor se assumissem que os objetivos e interesses perseguidos por empresários e funcionários não são obrigatoriamente os mesmos e que não é trágico e nem indecoroso expressar essa “desigualdade” em uma relação hierárquica estruturada. Ao invés de precipitadamente abolirem-se as hierarquias, dizendo-as ultrapassadas e autoritárias, os empresários deveriam refletir mais sobre os mecanismos de coordenação e direção. Isso incluiria formalizações mais simples e uma seleção mais conseqüente com decisões mais confiáveis. É exagerado assumir que o funcionário anseie por auto-determinação, que ele deseje exigências obscuras e conversas “participativas” intermináveis, competências e projetos novos todos os dias. Não é absurdo imaginar que os funcionários querem saber precisamente o que se espera dele, com que apoio ele pode contar, que ele possa confiar no seu chefe eque este esteja acessível para dar- lhe feedback e uma avaliação justa. O funcionário não precisa de uma empresa ou um local de trabalho que substitua a sua família, os seus amigos e o seu lazer; tampouco precisa de uma empresa que faça de conta que é um clube, do qual ele é um honorável membro e não um empregado. Motivação é a palavra mágica que tudo resolve e consultores – sem nenhum pudor –recomendam truques refinados e rasteiros para se extrair o “melhor” dos funcionários. Para eles nenhum gasto é muito elevado, nenhum caminho é muito bizarro e nenhum esforço é muito ridículo.

    Motivação é vendida a rodo e só não se motiva quem não quer. Ora, o que se vê são chefes eempresários possuídos pela doutrina da motivação, fazendo promessas difusas e desconexas. Osfuncionários buscam passar a impressão de que estão motivados, como se somente assim fossemcapazes e tivessem alguma qualificação necessária. Sabe-se que o poder dos estímulos (materiais esimbólicos) tem limites que são freqüentemente ignorados. Aqui os meios sabotam os fins e amotivação destrói a própria motivação, visto que os funcionários aprendem a ser resistentes a estímulose almejam outros sempre mais elevados, enquanto o empresário se reduz ao indigno papel deentertainer de manhas e gratificações.O capital “humano” é complexo, obstinado e reage de modo sensível. Uma administração derecursos humanos sólida estabelece as exigências obrigatórias, indica claramente o que deve ser feito, oferece as condições necessárias, alicerça o bom desempenho no respeito e no reconhecimento, exigedesempenhos realistas e que correspondam às qualificações e aos talentos acordados. Um bom trabalhoprecisa de tempo, bom senso e tranqüilidade, particularmente quando se trata de coisas imateriais comoconhecimento, serviços e informações. É importante que os empregados possam realizar aquilo para oqual foram contratados: o seu trabalho. Ao invés de ser um participante de um jogo pirotécnico dedemonstrações diárias em que ele é um mutante, bem humorado, feliz no grupo, amante incondicionalda empresa, um entusiasta espontâneo da vida desregrada da empresa e sua cultura totalitária e invasiva. O trabalho não é necessariamente uma obra de arte, a profissão nem sempre é exercida pela mais profunda vocação e nem o local de trabalho é necessariamente a versão moderna do paraíso. É preciso lembrar que a maioria das empresas, apesar do discurso, não pode garantir realmente um trabalho prazeroso, feliz e divertido. Prazer é prazer e trabalho é trabalho. O prazer não é critério para medir bons desempenhos. No deslocamento das fronteiras entre o trabalho e o lazer, foi o lazer quem perdeu o espaço. É ridículo imaginar que as pessoas preferem passar os seus momentos de lazer confraternizando com colegas detrabalho ao invés de estar com a sua família, os seus amigos e as pessoas que amam. É preciso lembrar que existe uma vida antes e depois do trabalho e que o seu sentido não consiste em preparar o individuo para trabalhar mais. Uma empresa só precisa do conhecimento especial e do talento de seu funcionário, ela não precisa de sua alma e nem que ele se entregue totalmente, com seus pontos fortes e fracos, a sua história pessoal, as suas preferências particulares e as suas esperanças nessa vida. O mundo do trabalho precisa voltar a desenvolver os seus próprios rituais e formas de trato social. Isto significa separar no tempo e no espaço as esferas do trabalho e da vida particular, diferenciando o comportamento próprio de ambas; é preciso ter clara a diferença entre “o papel desempenhado” e a “pessoa em si”.Hoje o que se percebe é que é a personalidade que é avaliada na empresa e não as qualificaçõese a experiência profissional. É preciso ficar atento aos embustes dos títulos, pois atualmente tudo é mobilidade, flexibilidade, criatividade, equipe. Parece que não importam mais a competência e osconhecimentos: avaliam-se as soft skills. O diferencial transforma-se em uniformidade quando 90% dos candidatos em qualquer entrevista para um emprego aprende a dizer que o seu ponto fraco ou defeito é “ser impaciente” ou “ser perfeccionista”. O que se vê a partir daí é o estímulo aos oportunistas domesticados, que modelam os seus comportamentos e gostos para ascender profissionalmente. É uma personalidade por encomenda! Na empresa moderna, a imagem é tudo. Funcionários e produtos são tratados da mesma maneira e parecem ter o mesmo destino: a venda pelo melhor preço. Para além das palavras, a autora explicita o manual de regras de sua empresa, no qual podemos ler no item 16, “In é out: Tudo o que no mundo do trabalho moderno é considerado como a ‘última palavra’ ou o ‘acessório do momento’ não tem lugar aqui. Quem chega de patinete estará melhor em outro lugar”. Ou ainda, o item 19, “ usual é bom: O foco é o trabalho. Dispensamos qualquer cultura empresarial que glamorize a empresa. Não afirmamos que em nossas fileiras se encontram os melhores; não cultivamos nenhum ‘entertainment’, nenhuma atitude, nenhuma superestrutura filosófica. Em vez disso, temos a normalidade banal e o cotidiano sem surpresas. Dispensamos qualquer esforço para transformar o dia-a-dia em ‘happening’ e para sobressair”. Mair demonstra um profundo conhecimento dos mais modernos discursos e mecanismos sutis de controle organizacional, assim como os argumentos mais refinados das diversas correntes dopensamento crítico das organizações. Não se trata de um livro com idéias amadoras, ele transpira umaforte convicção de que o capitalismo e as empresas não podem garantir um trabalho que não seja trabalho. O discurso que tenta convencer que esse trabalho é a fonte última do prazer da vida nada mais é que um tratamento desumano e desonesto. Os seres humanos têm destino melhor para as suas ilusõese sonhos, felizmente.

    Rush - Xanadu ( Exit Stage Left )

    Closer To The Heart

    "And the men who hold high places
    Must be the ones who start
    to mold a new reality
    Closer to the Heart "

    Rush

    Thursday, July 07, 2011

    Verificação, Validação e Teste

    Teste de software é o processo de execução de um produto para determinar se ele atingiu suas especificações e funcionou corretamente no ambiente para o qual foi projetado. O seu objetivo é revelar falhas em um produto, para que as causas dessas falhas sejam identificadas e possam ser corrigidas pela equipe de desenvolvimento antes da entrega final. Por conta dessa característica das atividades de teste, dizemos que sua natureza é “destrutiva”, e não “construtiva”, pois visa ao aumento da confiança de um produto através da exposição de seus problemas, porém antes de sua entrega ao usuário final.
    O conceito de teste de software pode ser compreendido através de uma visão intuitiva ou mesmo de uma maneira formal. Existem atualmente várias definições para esse conceito. De uma forma simples, testar um software significa verificar através de uma execução controlada se o seu comportamento corre de acordo com o especificado. O objetivo principal desta tarefa é revelar o número máximo de falhas dispondo do mínimo de esforço, ou seja, mostrar aos que desenvolvem se os resultados estão ou não de acordo com os padrões estabelecidos.
    Ao longo deste artigo, iremos discutir os principais conceitos relacionados às atividades de teste, as principais técnicas e critérios de teste que podem ser utilizados para verificação ou validação de um produto, assim como exemplos práticos da aplicação de cada tipo de técnica ou critério de teste.

    Conceitos básicos associados a Teste de Software

    Antes de iniciarmos uma discussão sobre teste de software precisamos esclarecer alguns conceitos relacionados a essa atividade. Inicialmente, precisamos conhecer a diferença entre Defeitos, Erros e Falhas. As definições que iremos usar aqui seguem a terminologia padrão para Engenharia de Software do IEEE – Institute of Electrical and Electronics Engineers – (IEEE 610, 1990).
    ·         Defeito é um ato inconsistente cometido por um indivíduo ao tentar entender uma determinada informação, resolver um problema ou utilizar um método ou uma ferramenta. Por exemplo, uma instrução ou comando incorreto.
    ·         Erro é uma manifestação concreta de um defeito num artefato de software. Diferença entre o valor obtido e o valor esperado, ou seja, qualquer estado intermediário incorreto ou resultado inesperado na execução de um programa constitui um erro.
    ·         Falha é o comportamento operacional do software diferente do esperado pelo usuário. Uma falha pode ter sido causada por diversos erros e alguns erros podem nunca causar uma falha.

    A Figura 1 expressa a diferença entre esses conceitos. Defeitos fazem parte do universo físico (a aplicação propriamente dita) e são causados por pessoas, por exemplo, através do mal uso de uma tecnologia. Defeitos podem ocasionar a manifestação de erros em um produto, ou seja, a construção de um software de forma diferente ao que foi especificado (universo de informação). Por fim, os erros geram falhas, que são comportamentos inesperados em um software que afetam diretamente o usuário final da aplicação (universo do usuário) e pode inviabilizar a utilização de um software.

    Figura 1. Defeito x erro x falha

    Dessa forma, ressaltamos que teste de software revela simplesmente falhas em um produto. Após a execução dos testes é necessária a execução de um processo de depuração para a identificação e correção dos defeitos que originaram essa falha, ou seja, Depurar não é Testar!
    A atividade de teste é composta por alguns elementos essenciais que auxiliam na formalização desta atividade. Esses elementos são os seguintes:
    ·         Caso de Teste: descreve uma condição particular a ser testada e é composto por valores de entrada, restrições para a sua execução e um resultado ou comportamento esperado (CRAIG e JASKIEL, 2002).
    ·         Procedimento de Teste: é uma descrição dos passos necessários para executar um caso (ou um grupo de casos) de teste (CRAIG e JASKIEL, 2002).
    ·        Critério de Teste: serve para selecionar e avaliar casos de teste de forma a aumentar as possibilidades de provocar falhas ou, quando isso não ocorre, estabelecer um nível elevado de confiança na correção do produto (ROCHA et al., 2001). Os critérios de teste podem ser utilizados como:
    o        Critério de Cobertura dos Testes: permitem a identificação de partes do programa que devem ser executadas para garantir a qualidade do software e indicar quando o mesmo foi suficientemente testado (RAPPS e WEYUKER, 1982). Ou seja, determinar o percentual de elementos necessários por um critério de teste que foram executados pelo conjunto de casos de teste.
    o        Critério de Adequação de Casos de Teste: Quando, a partir de um conjunto de casos de teste T qualquer, ele é utilizado para verificar se T satisfaz os requisitos de teste estabelecidos pelo critério. Ou seja, este critério avalia se os casos de teste definidos são suficientes ou não para avaliação de um produto ou uma função (ROCHA et al., 2001).
    o        Critério de Geração de Casos de Teste: quando o critério é utilizado para gerar um conjunto de casos de teste T adequado para um produto ou função, ou seja, este critério define as regras e diretrizes para geração dos casos de teste de um produto que esteja de acordo com o critério de adequação definido anteriormente (ROCHA et al., 2001).

    Definidos os elementos básicos associados aos testes de software, iremos a seguir discutir a origem dos defeitos em um software.

    Defeitos no desenvolvimento de software

    No processo de desenvolvimento de software, todos os defeitos são humanos e, apesar do uso dos melhores métodos de desenvolvimento, ferramentas ou profissionais, permanecem presentes nos produtos, o que torna a atividade de teste fundamental durante o desenvolvimento de um software. Já vimos que esta atividade corresponde ao último recurso para avaliação do produto antes da sua entrega ao usuário final.
    O tamanho do projeto a ser desenvolvido e a quantidade de pessoas envolvidas no processo são dois possíveis fatores que aumentam a complexidade dessa tarefa, e consequentemente aumentam a probabilidade de defeitos. Assim, a ocorrência de falhas é inevitável. Mas o que significa dizer que um programa falhou? Basicamente significa que o funcionamento do programa não está de acordo com o esperado pelo usuário. Por exemplo, quando um usuário da linha de produção efetua consultas no sistema das quais só a gerência deveria ter acesso. Esse tipo de falha pode ser originado por diversos motivos:
    • A especificação pode estar errada ou incompleta;
    • A especificação pode conter requisitos impossíveis de serem implementados devido a limitações de hardware ou software;
    • A base de dados pode estar organizada de forma que não seja permitido distinguir os tipos de usuário;
    • Pode ser que haja um defeito no algoritmo de controle dos usuários.
    Os defeitos normalmente são introduzidos na transformação de informações entre as diferentes fases do ciclo de desenvolvimento de um software. Vamos seguir um exemplo simples de ciclo de vida de desenvolvimento de software: os requisitos expressos pelo cliente são relatados textualmente em um documento de especificação de requisitos. Esse documento é então transformado em casos de uso, que por sua vez foi o artefato de entrada para o projeto do software e definição de sua arquitetura utilizando diagramas de classes da UML. Em seguida, esses modelos de projetos foram usados para a construção do software em uma linguagem que não segue o paradigma orientado a objetos. Observe que durante esse período uma série de transformações foi realizada até chegarmos ao produto final. Nesse meio tempo, defeitos podem ter sido inseridos. A Figura 2 expressa exatamente a metáfora discutida nesse parágrafo.

     

    Figura 2. Diferentes Interpretações ao longo do ciclo de desenvolvimento de um software (Uma versão similar pode ser obtida em http://www.projectcartoon.com/cartoon/611) 
    Essa série de transformações resultou na necessidade de realizar testes em diferentes níveis, visando avaliar o software em diferentes perspectivas de acordo com o produto gerado em cada fase do ciclo de vida de desenvolvimento de um software. Esse será o foco da seção seguinte.

    Níveis de teste de software

    O planejamento dos testes deve ocorrer em diferentes níveis e em paralelo ao desenvolvimento do software (Figura 3). Buscando informação no Livro “Qualidade de Software – Teoria e Prática” (ROCHA et al., 2001), definimos que os principais níveis de teste de software são:
    ·        Teste de Unidade: também conhecido como testes unitários. Tem por objetivo explorar a menor unidade do projeto, procurando provocar falhas ocasionadas por defeitos de lógica e de implementação em cada módulo, separadamente. O universo alvo desse tipo de teste são os métodos dos objetos ou mesmo pequenos trechos de código.
    ·        Teste de Integração: visa provocar falhas associadas às interfaces entre os módulos quando esses são integrados para construir a estrutura do software que foi estabelecida na fase de projeto.
    ·        Teste de Sistema: avalia o software em busca de falhas por meio da utilização do mesmo, como se fosse um usuário final. Dessa maneira, os testes são executados nos mesmos ambientes, com as mesmas condições e com os mesmos dados de entrada que um usuário utilizaria no seu dia-a-dia de manipulação do software. Verifica se o produto satisfaz seus requisitos.
    ·        Teste de Aceitação: são realizados geralmente por um restrito grupo de usuários finais do sistema. Esses simulam operações de rotina do sistema de modo a verificar se seu comportamento está de acordo com o solicitado.
    ·        Teste de Regressão: Teste de regressão não corresponde a um nível de teste, mas é uma estratégia importante para redução de “efeitos colaterais”. Consiste em se aplicar, a cada nova versão do software ou a cada ciclo, todos os testes que já foram aplicados nas versões ou ciclos de teste anteriores do sistema. Pode ser aplicado em qualquer nível de teste.

    Dessa forma, seguindo a Figura 3, o planejamento e projeto dos testes devem ocorrer de cima para baixo, ou seja:
    1.      Inicialmente é planejado o teste de aceitação a partir do documento de requisitos;
    2.      Após isso é planejado o teste de sistema a partir do projeto de alto nível do software;
    3.      Em seguida ocorre o planejamento dos testes de integração a partir o projeto detalhado;
    4.      E por fim, o planejamento dos testes a partir da codificação.

    Já a execução ocorre no sentido inverso.
    Conhecidos os diferentes níveis de teste, a partir da próxima seção descreveremos as principais técnicas de teste de software existentes que podemos aplicar nos diferentes níveis abordados.

    Figura 3. Modelo V descrevendo o paralelismo entre as atividades de desenvolvimento e teste de software (CRAIG e JASKIEL, 2002)

    Técnicas de teste de software

    Atualmente existem muitas maneiras de se testar um software. Mesmo assim, existem as técnicas que sempre foram muito utilizadas em sistemas desenvolvidos sobre linguagens estruturadas que ainda hoje têm grande valia para os sistemas orientados a objeto. Apesar de os paradigmas de desenvolvimento serem diferentes, o objetivo principal destas técnicas continua a ser o mesmo: encontrar falhas no software.
    As técnicas de teste são classificadas de acordo com a origem das informações utilizadas para estabelecer os requisitos de teste. Elas contemplam diferentes perspectivas do software e impõe-se a necessidade de se estabelecer uma estratégia de teste que contemple as vantagens e os aspectos complementares dessas técnicas. As técnicas existentes são: técnica funcional e estrutural.
    A seguir conheceremos um pouco mais sobre cada técnica, mas iremos enfatizar alguns critérios específicos para a técnica funcional.

    Técnica Estrutural (ou teste caixa-branca)

    Técnica de teste que avalia o comportamento interno do componente de software (Figura 4). Essa técnica trabalha diretamente sobre o código fonte do componente de software para avaliar aspectos tais como: teste de condição, teste de fluxo de dados, teste de ciclos e teste de caminhos lógicos (PRESSMAN, 2005)

    Figura 4. Técnica de Teste Estrutural.

    Os aspectos avaliados nesta técnica de teste dependerão da complexidade e da tecnologia que determinarem a construção do componente de software, cabendo, portanto, avaliação de outros aspectos além dos citados anteriormente. O testador tem acesso ao código fonte da aplicação e pode construir códigos para efetuar a ligação de bibliotecas e componentes.
    Este tipo de teste é desenvolvido analisando-se o código fonte e elaborando-se casos de teste que cubram todas as possibilidades do componente de software. Dessa maneira, todas as variações originadas por estruturas de condições são testadas. A Listagem 1 apresenta um código fonte, extraído de (BARBOSA et al., 2000) que descreve um programa de exemplo que deve validar um identificador digitado como parâmetro, e a Figura 5 apresenta o grafo de programa extraído a partir desse código, também extraído de (BARBOSA et al., 2000). A partir do grafo deve ser escolhido algum critério baseado em algum algoritmo de busca em grafo (exemplo: visitar todos os nós, arcos ou caminhos) para geração dos casos de teste estruturais para o programa (PFLEEGER, 2004).

    Listagem 1. Código fonte do programa identifier.c (BARBOSA et al., 2000)
    /* 01 */  {
    /* 01 */        char  achar;
    /* 01 */        int   length, valid_id;
    /* 01 */        length = 0;
    /* 01 */        printf ("Digite um possível identificador\n");
    /* 01 */        printf ("seguido por : ");
    /* 01 */        achar = fgetc (stdin);
    /* 01 */        valid_id = valid_starter (achar);
    /* 01 */        if (valid_id)
    /* 02 */                 length = 1;
    /* 03 */        achar = fgetc (stdin);
    /* 04 */        while (achar != '\n')
    /* 05 */        {
    /* 05 */                 if (!(valid_follower (achar)))
    /* 06 */                          valid_id = 0;
    /* 07 */                 length++;
    /* 07 */                 achar = fgetc (stdin);
    /* 07 */        }
    /* 08 */        if (valid_id && (length >= 1) && (length < 6) )
    /* 09 */                 printf ("Valido\n");
    /* 10 */        else
    /* 10 */                 printf ("Invalido\n");
    /* 11 */   }

    Figura 5. Grafo de Programa (Identifier.c) (BARBOSA et al., 2000).

    Um exemplo bem prático desta técnica de teste é o uso da ferramenta livre JUnit para desenvolvimento de casos de teste para avaliar classes ou métodos desenvolvidos na linguagem Java. A técnica de teste de Estrutural é recomendada para os níveis de Teste da Unidade e Teste da Integração, cuja responsabilidade principal fica a cargo dos desenvolvedores do software, que são profissionais que conhecem bem o código-fonte desenvolvido e dessa forma conseguem planejar os casos de teste com maior facilidade. Dessa forma, podemos auxiliar na redução dos problemas existentes nas pequenas funções ou unidades que compõem um software.

    Teste Funcional (ou teste caixa-preta)

    Técnica de teste em que o componente de software a ser testado é abordado como se fosse uma caixa-preta, ou seja, não se considera o comportamento interno do mesmo (Figura 6). Dados de entrada são fornecidos, o teste é executado e o resultado obtido é comparado a um resultado esperado previamente conhecido. Haverá sucesso no teste se o resultado obtido for igual ao resultado esperado. O componente de software a ser testado pode ser um método, uma função interna, um programa, um componente, um conjunto de programas e/ou componentes ou mesmo uma funcionalidade. A técnica de teste funcional é aplicável a todos os níveis de teste (PRESSMAN, 2005).

    Figura 6. Técnica de Teste Funcional.

    Um conjunto de critérios de teste pode ser aplicado aos testes funcionais. A seguir conheceremos alguns deles.

    Particionamento em classes de equivalência

    Esse critério divide o domínio de entrada de um programa em classes de equivalência, a partir das quais os casos de teste são derivados. Ele tem por objetivo minimizar o número de casos de teste, selecionando apenas um caso de teste de cada classe, pois em princípio todos os elementos de uma classe devem se comportar de maneira equivalente. Eventualmente, pode-se também considerar o domínio de saída para a definição das classes de equivalência (ROCHA et al., 2001).
    Uma classe de equivalência representa um conjunto de estados válidos e inválidos para uma condição de entrada. Tipicamente uma condição de entrada pode ser um valor numérico específico, uma faixa de valores, um conjunto de valores relacionados, ou uma condição lógica. As seguintes diretrizes podem ser aplicadas:
    ·        Se uma condição de entrada especifica uma faixa de valores ou requer um valor específico, uma classe de equivalência válida (dentro do limite) e duas inválidas (acima e abaixo dos limites) são definidas.
    ·        Se uma condição de entrada especifica um membro de um conjunto ou é lógica, uma classe de equivalência válida e uma inválida são definidas.

    Devemos seguir tais passos para geração dos testes usando este critério:

    1.      Identificar classes de equivalência (é um processo heurístico)
    o        condição de entrada
    o        válidas e inválidas
    2.      Definir os casos de teste
    o        enumeram-se as classes de equivalência
    o        casos de teste para as classes válidas
    o        casos de teste para as classes inválidas

    Em (BARBOSA et al., 2000) é apresentado a aplicação do critério de particionamento por equivalência para o programa identifier.c. Iremos apresentá-lo como exemplo do uso deste critério de teste. Relembrando, o programa deve determinar se um identificador é válido ou não.

    “Um identificador válido deve começar com uma letra e conter apenas letras ou dígitos. Além disso, deve ter no mínimo 1 caractere e no máximo 6 caracteres de comprimento. Exemplo: “abc12” (válido), “cont*1” (inválido), “1soma” (inválido) e “a123456” (inválido).”

    O primeiro passo é a identificação das classes de equivalência. Isso está descrito na Tabela 1.
     
    Condições de Entrada
    Classes
    Classes
    Tamanho t do identificador
    (1) 1 ??t???6
    (2) t > 6
    Primeiro caractere c é uma letra
    (3) Sim
    (4) Não
    Só contém caracteres válidos
    (5) Sim
    (6) Não
    Tabela 1. Classes de Equivalência do programa identifier.c.

    A partir disso, conseguimos especificar quais serão os casos de teste necessários. Para ser válido, um identificador deve atender às condições (1), (3) e (5), logo é necessário um caso de teste válido que cubra todas essas condições. Alem disso, será necessário um caso de teste para cada classe inválida: (2), (4) e (6). Assim, o conjunto mínimo é composto por quatro casos de teste, sendo uma das opções: T0 = {(a1,Válido), (2B3, Inválido), (Z-12, Inválido), (A1b2C3d, Inválido)}.

    Análise do valor limite

    Por razões não completamente identificadas, um grande número de erros tende a ocorrer nos limites do domínio de entrada invés de no “centro”. Esse critério de teste explora os limites dos valores de cada classe de equivalência para preparar os casos de teste (Pressman, 2005).
    Se uma condição de entrada especifica uma faixa de valores limitada em a e b, casos de teste devem ser projetados com valores a e b e imediatamente acima e abaixo de a e b. Exemplo: Intervalo = {1..10}; Casos de Teste à {1, 10, 0,11}.
    Como exemplo, extraído de (BARBOSA et al., 2000), iremos considerar a seguinte situação:

    "... o cálculo do desconto por dependente é feito da seguinte forma: a entrada é a idade do dependente que deve estar restrita ao intervalo [0..24]. Para dependentes até 12 anos (inclusive) o desconto é de 15%. Entre 13 e 18 (inclusive) o desconto é de 12%. Dos 19 aos 21 (inclusive) o desconto é de 5% e dos 22 aos 24 de 3%..."

    Aplicando o teste de valor limite convencional serão obtidos casos de teste semelhantes a este: {-1,0,12,13,18,19,21,22,24,25}.

    Grafo de causa-efeito

    Esse critério de teste verifica o efeito combinado de dados de entrada. As causas (condições de entrada) e os efeitos (ações) são identificados e combinados em um grafo a partir do qual é montada uma tabela de decisão, e a partir desta, são derivados os casos de teste e as saídas (ROCHA et al., 2001).
    Esse critério é baseado em quatro passos, que exemplificaremos utilizando o exemplo, também extraído de (BARBOSA et al., 2000):

    “Em um programa de compras pela Internet, a cobrança ou não do frete é definida seguindo tal regra: Se o valor da compra for maior que R$ 60,00 e foram comprados menos que 3 produtos, o frete é gratuito. Caso contrário, o frete deverá ser cobrado.”

    1.      Para cada módulo, Causas (condições de entrada) e efeitos (ações realizadas às diferentes condições de entrada) são relacionados, atribuindo-se um identificador para cada um.
    ·     Causa: valor da compra > 60 e #produtos < 3
    ·     Efeito: frete grátis
    2.      Em seguida, um grafo de causa-efeito (árvore de decisão) é desenhado (Figura 7).
     
    Figura 7. Árvore de Decisão – Grafo de Causa-Efeito.

    1.      Neste ponto, transforma-se o grafo numa tabela de decisão (Tabela 2).
    Causa
    Valor da compra
    > 60
    > 60
    <= 60
    #Produtos
    < 3
    >= 3
    --
    Efeito
    Cobrar frete

    V
    V
    Frete grátis
    V


    Tabela 2. Tabela de decisão para o programa de compra pela Internet.

    2.      As regras da tabela de decisão são, então, convertidas em casos de teste.

    Para a elaboração dos casos de teste, devemos seguir todas as regras extraídas da tabela. Esse critério deve ser combinado com os dois outros já apresentados neste artigo para a criação de casos de teste válidos (extraídos das regras) e inválidos (valores foras da faixa definida). Os casos de teste definidos a seguir refletem somente as regras extraídas da tabela de decisão. Fica como exercício pensar nos casos de teste inválidos para este problema.
    ·     Casos de Teste (valor, qtd produtos, resultado esperado) = {(61,2,“frete grátis”); (61,3,“cobrar frete”); (60, qualquer quantidade,“cobrar frete”)}

    Outras técnicas

    Outras técnicas de teste podem e devem ser utilizadas de acordo com necessidades de negócio ou restrições tecnológicas. Destacam-se as seguintes técnicas: teste de desempenho, teste de usabilidade, teste de carga, teste de stress, teste de confiabilidade e teste de recuperação. Alguns autores chegam a definir uma técnica de teste caixa cinza, que seria um mesclado do uso das técnicas de caixa preta e caixa branca, mas, como toda execução de trabalho relacionado à atividade de teste utilizará simultaneamente mais de uma técnica de teste, é recomendável que se fixem os conceitos primários de cada técnica.

    Conclusões

    O teste de software é uma das atividades mais custosas do processo de desenvolvimento de software, pois pode envolver uma quantidade significativa dos recursos de um projeto. O rigor e o custo associado a esta atividade dependem principalmente da criticalidade da aplicação a ser desenvolvida. Diferentes categorias de aplicações requerem uma preocupação diferenciada com as atividades de teste.
    Um ponto bastante importante para a viabilização da aplicação de teste de software é a utilização de uma infra-estrutura adequada. Realizar testes não consiste simplesmente na geração e execução de casos de teste, mas envolvem também questões de planejamento, gerenciamento e análise de resultados. Apoio ferramental para qualquer atividade do processo de teste é importante como mecanismo para redução de esforço associado à tarefa em questão, seja ela planejamento, projeto ou execução dos testes. Após ter sua estratégia de teste definida, tente buscar por ferramentas que se encaixem na sua estratégia. Isso pode reduzir significantemente o esforço de tal tarefa.
    Além disso, é importante ressaltar que diferentes tipos de aplicações possuem diferentes técnicas de teste a serem aplicadas, ou seja, testar uma aplicação web envolve passos diferenciados em comparação aos testes de um sistema embarcado. Cada tipo de aplicação possui características especificas que devem ser consideradas no momento da realização dos testes. O conjunto de técnicas apresentado neste artigo cobre diversas características comuns a muitas categorias de software, mas não é completo.
    Para finalizar, podemos destacar outros pontos importantes relacionados às atividades de teste que podemos abordar em próximos artigos, tais como processo de teste de software, planejamento e controle dos testes e teste de software para categorias específicas de software, como aplicações web. Até a próxima!

    Agradecimentos

    Agradecemos aos professores José Carlos Maldonado e Ellen Barbosa por terem gentilmente autorizado a publicação deste material, cujos exemplos utilizados estão fundamentados em seus trabalhos.

    Referências

    ·         BARBOSA, E.; MALDONADO, J.C.; VINCENZI, A.M.R.; DELAMARO, M.E; SOUZA, S.R.S. e JINO, M.. “Introdução ao Teste de Software. XIV Simpósio Brasileiro de Engenharia de Software”, 2000.
    ·         CRAIG, R.D., JASKIEL, S. P., “Systematic Software Testing”, Artech House Publishers, Boston, 2002. 
    ·         IEEE Standard 610-1990: IEEE Standard Glossary of Software Engineering Terminology, IEEE Press.
    ·         PFLEEGER, S. L., “Engenharia de Software: Teoria e Prática”, Prentice Hall- Cap. 08, 2004.
    ·         PRESSMAN, R. S., “Software Engineering: A Practitioner’s Approach”, McGraw-Hill, 6th ed, Nova York, NY, 2005.
    ·         RAPPS, S., WEYUKER, E.J., “Data Flow analysis techniques for test data selection”, In: International Conference on Software Engineering, p. 272-278, Tokio, Sep. 1982.
    ·         ROCHA, A. R. C., MALDONADO, J. C., WEBER, K. C. et al., “Qualidade de software – Teoria e prática”, Prentice Hall, São Paulo, 2001.