Вы находитесь на странице: 1из 5

Pontifícia Universidade Católica de Minas Gerais

Sistemas de Informação
Algoritmos e Estruturas de Dados
Profa. Michelle Nery Nascimento

Qualidade de Código
Para determinarmos se um programa é bom, diversos fatores devem ser analisados. Entre eles,
alguns mais importantes são:
- Se o programa está correto, se é eficiente e se é de fácil utilização. Neste caso, estar
correto depende dos métodos de desenvolvimento utilizado e dos testes que foram realizados.
Eficiência diz respeito a dois conceitos: eficiência de tempo – quando economiza-se tempo de
processamento para realizar determinada tarefa e eficiência de espaço – quando economiza-se
memória disponível.
- Um outro fator que deve ser analisado quando nos referimos à qualidade de software é
se o programa é fácil de ser alterado, seja para correções ou para atualizações. Neste sentido,
devemos analisar alguns fatores básicos para garantir a qualidade de um software. Alguns deles
são:

• Indentação
• Comentários
• Documentação
• Escolha dos identificadores (nomes de classes e variáveis)
• Uso de comandos e desvios incondicionais
• Return dentro de métodos
• Modularização

Indentação: mostra a estrutura do código. Permite visualizar as relações de dependência entre as


várias construções do programa.

Exemplo:

Código sem indentação:

int [ ]v = new int [10];


public void leVetor() {
for (int i = 0; i < 10; i++)
v[i] = Int32.Parse(Console.Readline())
}
void imprimeInvertido() {
for (int i = 9; i >= 0; i--)
Console.WriteLine(v[i]);
}
public static void main() {
leVetor();
imprimeInvertido();
}
Código indentado:

int [ ]v = new int [10];

public void leVetor()


{
for (int i = 0; i < 10; i++)
v[i] = Int32.Parse(Console.Readline());
}

public void imprimeInvertido()


{
for (int i = 9; i >= 0; i--)
Console.WriteLine(v[i]);
}

public static void main()


{
leVetor();
imprimeInvertido();
}

Comentários: ajudam a entender algoritmos complexos. Permite explicar brevemente o


programa, função ou classe.

Documentação: não é comentário, é um relatório que explica a lógica do seu programa,


descrevendo os algoritmos e estruturas de dados usadas.

Identificadores ou nomes de variáveis, funções e classes: devem ser significativos com a


função que exercem no programa. Deve-se evitar nomes com uma letra apenas. Normalmente as
variáveis devem ser nomeadas usando-se substantivos e as funções ou métodos verbos, para
indicar a operação realizada.
Ex: variável: int contaElemento;
método: public void incrementaValor(){}

Uso de comandos e desvios incondicionais: alguns comandos e desvios dentro do código não
devem ser utilizados. São eles:
• go to
• break
• continue
• return (terminando laço de repetição)

Return dentro de métodos: é desejável apenas um return dentro de métodos pois muitas vezes,
o uso de mais de um return dentro de um método pode gerar confusão, como ocorre quando há
uma relação de dependência entre funções através do comando return.
Exemplo. Imagine um código no qual o método posicaoDe seja utilizado para verificar se um
elemento x está presente em um vetor v contendo n elementos; se x estiver presente no vetor,
então será retornada a posição da primeira ocorrência de x, senão, será retornado o valor -1.

public int posicaoDe(int v[], int n, int x)


{
bool encontrado = false;
int i = 0;
while(i < n && encontrado == false)
{
if ( v[i] == x )
encontrado = true;
else
i++;
}
if ( encontrado == true)
return i;
else
return -1;
}

O maior problema deste método é utilizar o seu valor de retorno para duas finalidades distintas.

Modularização: é a divisão do programa em funções, classes e módulos. Ao dividirmos o


programa em partes, facilitamos sua leitura. Uma grande dificuldade para dividir o programa em
partes é saber como dividir o programa em funções, ou seja, o que devem ser as funções de um
programa, como elas se relacionam.
A divisão deve ser realizada a partir do papel, da tarefa ou da operação a ser realizada
para permitir o reaproveitamento do código já construído e evitar que um trecho seja repetido
várias vezes dentro de um programa. A modularização permite a alteração de um trecho de código
de uma forma mais rápida e para isso é necessário que o módulo seja coeso, ou seja, execute
uma única tarefa e tenha baixo acoplamento, isto é, que o módulo seja o mais independente
possível dos demais módulos.

O acoplamento entre classes ou subsistemas é uma medida de interconexão entre módulos ou


subsistemas. O acoplamento forte significa que os módulos relacionados precisam conhecer
detalhes internos uns dos outros e as alterações se propagam pelo seu código, deixando-o
potencialmente mais difícil de entender.

A coesão é o grau de relacionamento entre as entidades e ações agrupadas em um bloco, ou


seja, é a medida que avalia o módulo individualmente, e quanto maior, melhor a estrutura. Na
prática, o ideal é que cada módulo seja relativamente simples, responsável pela obtenção
de um objetivo bem definido e executado o mais independentemente possível de outros
módulos. Uma outra característica importante é apresentar apenas um ponto de entrada e
saída, pois isto reflete uma boa consistência interna e definição funcional, sendo assim,
favorecerá o seu entendimento, testes e manutenção.

Relação entre acoplamento e coesão: O objetivo de um programador é aumentar a coesão e


diminuir o acoplamento.

Para tornar o acoplamento o menor possível é necessário que suas classes e objetos estejam o
mais isolados possível, neste contexto, temos a ideia do encapsulamento. O encapsulamento
protege o acesso direto aos atributos de um objeto fora da classe onde estes foram declarados.
Esta proteção consiste em se usar modificadores de acesso mais restritos sobre os atributos
definidos na classe. Depois devem ser criados métodos para manipular de forma indireta os
atributos da classe.
Exemplo:

Sem encapsulamento:

class semEncapsulamento
{
int desprotegido;
}

public class testeSemEncapsulamento


{
public static void Main()
{
//instância da classe
semEncapsulamento se = new semEncapsulamento();

//acesso direto ao atributo


se.desprotegido = 10;
Console.WriteLine (“Valor desprotegido” +se.desprotegido):
}
}

Com encapsulamento:

class encapsulado
{
private int protegido;

public void setProtegido(int protegido)


{
this.protegido = protegido;
}

public int getProtegido()


{
return this.protegido;
}
}

public class testeEncapsulado


{
public static void Main()
{
//instância da classe
encapsulado en = new encapsulado();

//acesso direto ao atributo protegido implicará em erro de compilação


em.protegido = 10;

//deve-se acessar os atributos de forma indireta


em.setProtegido(10);
Console.WriteLine(“Valor protegido: ” + em.getProtegido());
}
}

Vantagem: prevenir alterações acidentais. Se alguma modificação ocorrer em variáveis de


instância de um certo objeto, sabemos exatamente quais métodos interagiram com elas: são os
métodos desse objeto. Nenhum outro método pode acessar esses dados. Isso simplifica a escrita,
manutenção e alteração do programa.

DRY: Don't Repeat Yourself

Uma das filosofias mais adotadas no mundo todo e amplamente evangelizada pelos maiores
nomes da programação, independente de linguagem é o DRY (don't repeat yourself) – Não se
repita.
DRY é mais do que apenas uma boa prática de programação, é uma filosofia que envolve evitar
repetições. Trechos de códigos repetidos, na maior parte dos casos, somente tornam o código
mais obscuro e inconsistente. Quando DRY é aplicado com sucesso em um sistema, a
modificação de um único elemento não afetará nenhuma outra parte do sistema, com exceção de
elementos intrincadamente relacionados.

KISS: Keep It Simple, Stupid

KISS é um princípio geral que valoriza a simplicidade de projeto e defende que toda a
complexidade desnecessária seja evitada. KISS é uma filosofia de programação que “prega” a
simplicidade, partes pequenas (módulos) que se unem para resolver um problema maior.

Sugestões para uma boa prática de programação:

• usar a modularização para tratar problemas complexos;


• usar estruturas básicas de controle em cada trecho de código;
• usar definições locais em módulos (evitar definições globais);
• usar a passagens de parâmetros para dentro e fora dos módulos;
• preferir a passagem de parâmetros por valor ao invés da passagem por referência;
• dar nomes às constantes;
• buscar clareza e simplicidade;
• identificar pré-condições e pós-condições, e verificá-las;
• documentar tudo durante o processo: autoria, objetivos, datas, especificações, testes,
referências etc.;
• entrada e saída de cada módulo, e suas condições de uso;
• explicar trechos importantes, ou detalhes não-óbvios;
• apresentar o código de maneira estética e legível;
• usar um só comando por linha, quando possível;
• usar maiúsculas e minúsculas para melhorar a legibilidade;
• escolher bem os nomes de identificadores;
• delimitar blocos em linhas separadas e com indentação;
• fazer definições no início de cada bloco, quando possível;
• fazer definições uma em cada linha, quando possível;
• fazer bom uso das definições de tipos e classes;
• separar os operadores em uma expressão, quando possível;
• identificar cada entrada e saída de um programa;
• testar cada módulo separadamente e após integrá-los;
• testar casos especiais e documentá-los devidamente;
• avaliar a complexidade e estimar seu custo de execução.

Вам также может понравиться