Anda di halaman 1dari 8

Pontifícia Universidade Católica de Minas Gerais

Bacharelado em Sistemas de Informação


Algoritmos e Estruturas de Dados - 2009/1
Italo Stefani

Laboratório 07 – Modularização
Para a resolução deste trabalho, lembre-se organizar seu código seguindo os critérios:

• Nomes sugestivos para variáveis;

• Separar trechos de código pelas suas atividades em métodos e funções;

• Comentar os trechos de código conforme sua atividade.

Modularização

Quando desenvolvemos um programa, devemos tomar o cuidado de organizá-lo em atividades simples e bem
definidas. Os comentários nos ajuda a identificar e registrar essas atividades desde a fase de projeto do
algoritmo. É fácil notar que certas atividades devem ser realizadas diversas vezes ao longo do programa para
valores e em situações diferentes. Isso pode fazer com que o trabalho de desenvolvimento se torne um
processo tedioso.

Uma solução para este problema é agrupar um conjunto de códigos responsável por uma determinada
atividade em um módulo, também chamado de método. Podemos definir um módulo da seguinte forma:

Conjunto de instruções para cumprir uma tarefa bem definida agrupadas em uma
unidade com um nome para referenciá-la.

A organização do programa em módulos tem os seguintes benefícios:

• Reduz o tamanho e a complexidade do programa principal: soluções menores e mais simples são
combinadas para resolver um problema maior;

• Facilita a compreensão e manutenção: a leitura passa a ser pela definição das atividades e não por
códigos;

• Permite e facilita reutilização de soluções já existentes: métodos podem ser utilizados em programas
e soluções diferentes;

• Diminui, e muito, erros nos programas: por serem simples, os módulos são facilmente testados e, ao
reutilizá-los, temos mais garantia de utilizar um código correto.
Um bom desenvolvedor não é aquele que resolve problemas com soluções complexas, mas sim aquele que
resolve um problema complexo de forma simples. A modularização é um dos principais artifícios para
alcançar o sucesso em soluções de algoritmos. Tenha sempre em mente, os problemas devem ser resolvidos
em partes, de preferência mais simples.
Exemplo

Considere o seguinte problema: dado três números inteiros, quero saber se o maior deles é maior que a soma
dos menores. Podemos modelar este problema nas seguintes atividades:

1. Lês os números.

2. Encontra o maior número.

3. Somar os números menores.

4. Comparar o maior numero com o resultados da soma.

O seguinte programa em C# resolve este problema. Note que o código é organizado conforme as atividades e
elas são registradas pelos comentários.
using System;
namespace ATPLab {
class Program {
static void Main(string[] args) {
int num1 = 0;
int num2 = 0;
int num3 = 0;
int maior = 0;
int soma = 0;

// Le os numeros
Console.Write("\n Digite o primeiro número: ");
num1 = int.Parse(Console.ReadLine());
Console.Write("\n Digite o segundo número: ");
num2 = int.Parse(Console.ReadLine());
Console.Write("\n Digite o terceiro número: ");
num3 = int.Parse(Console.ReadLine());

// Encontra o maior numero


maior = num1;
if (num2 > maior) {
maior = num2;
}
if (num3 > maior) {
maior = num3;
}

// Soma os numeros menores


soma = num1 + num2 + num3 - maior;

// Compara o maior com o resultado da soma


if (maior > soma) {
Console.Write("\n SIM ");
}
else {
Console.Write("\n NAO ");
}

Console.ReadLine();
}
}
}

Embora o programa esteja bem escrito seguindo as normas de variáveis legíveis, comentários e organização
do código por atividades, podemos ainda melhorá-lo aplicando os conceitos de modularização. Vamos então
entender como métodos podem ser criados em C#.

Em C# os métodos devem ser definidos dentro da classe do programa class Program e fora do método
principal static void Main(string[] args). Para que possamos trabalhar com as variáveis dentro dos
métodos, elas também devem ser declardas fora do método principal. O trecho de código a seguir ilustra onde
métodos e variáveis devem ser declarados:
using System;
namespace ATPLab {
class Program {

/* ### VARIAVEIS GERAIS DEVEM SER DEFINIDAS AQUI ### */

/* ### METODOS DEVEM SER DEFINIDOS AQUI ### */

static void Main(string[] args) {


... ... ...
}
}
}

Primeiro devemos definir um nome para o método, que deve deixar claro sua atividade. Sua definição deve
ser acompanhada de um comentário que explique a atividade realizada. Como podemos notar o métodos
principal static void Main também é um método, de nome Main. Porém, este método é especial, pois é a
partir dele que o programa começa sua execução. Iremos tomar sua definição como exemplo para criar os
métodos que precisamos para resolver o problema citado anteriormente. Assim, as palavras static void
serão utilizadas para definir um método, e iremos entender para que servem em breve.

Dessa forma, podemos começar a criação dos nossos métodos da seguinte forma:
using System;
namespace ATPLab {
class Program {

/* ### VARIAVEIS GERAIS DEVEM SER DEFINIDAS AQUI ### */


static int num1 = 0;
static int num2 = 0;
static int num3 = 0;
static int maior = 0;
static int soma = 0;

/* ### METODOS DEVEM SER DEFINIDOS AQUI ### */


// Le os numeros
static void leNumeros() {
... ... ...
}
// Encontra o maior numero
static void encontraMaior() {
... ... ...
}
// Soma os numeros menores
static void somaMenores() {
... ... ...
}
// Compara o maior com o resultado da soma
static void comparaMaior() {
... ... ...
}

static void Main(string[] args) {


leNumeros();
encontraMaior();
somaMenores();
comparaMaior();

Console.ReadLine();
}
}
}

Dessa forma, definimos 4 métodos, um para cada atividade identificada na modelagem do algoritmo. Note que
nosso programa principal agora, método Main, está definido de forma bem simples e é fácil entender o que ele
faz apensa lendo os métodos.

O passo seguinte é definir o corpo, ou o conjunto de códigos, dos métodos. No nosso exemplo, podemos fazer
isso de forma bem simples, basta copiar o que foi feito antes em cada atividade para dentro das definições dos
métodos correspondente, deixando o programa da seguinte forma:
using System;
namespace ATPLab {
class Program {

/* ### VARIAVEIS GERAIS DEVEM SER DEFINIDAS AQUI ### */


static int num1 = 0;
static int num2 = 0;
static int num3 = 0;
static int maior = 0;
static int soma = 0;

/* ### METODOS DEVEM SER DEFINIDOS AQUI ### */


// Le os numeros
static void leNumeros() {
Console.Write("\n Digite o primeiro número: ");
num1 = int.Parse(Console.ReadLine());
Console.Write("\n Digite o segundo número: ");
num2 = int.Parse(Console.ReadLine());
Console.Write("\n Digite o terceiro número: ");
num3 = int.Parse(Console.ReadLine());
}
// Encontra o maior numero
static void encontraMaior() {
maior = num1;
if (num2 > maior) {
maior = num2;
}
if (num3 > maior) {
maior = num3;
}
}
// Soma os numeros menores
static void somaMenores() {
soma = num1 + num2 + num3 - maior;
}
// Compara o maior com o resultado da soma
static void comparaMaior() {
if (maior > soma) {
Console.Write("\n SIM ");
}
else {
Console.Write("\n NAO ");
}
}

static void Main(string[] args) {


leNumeros();
encontraMaior();
somaMenores();
comparaMaior();

Console.ReadLine();
}
}
}

Dessa forma, conseguimos separar nosso programas em atividades. Note que cada método criado possui menos
código e é mais fácil de entendê-lo se lido separado dos demais. O método principal contem apenas as chamadas
aos métodos criados, de forma que podemos entender o funcionamento do programa por suas atividades,
expressadas pelos nomes dos métodos.

Para realizar a chamada a um método, basta referenciar seu nome, incluindo os parênteses e finalizando com
ponto-e-vírgula. Uma chamada a um método pode ser entendida como um comando que corresponde a execução
dos comandos definidos dentro do método chamado. Seria equivalente a trocar a chamada do método pelo
conjunto de código correspondente. Devemos lembrar que um método pode ser chamado quantas vezes forem
necessárias para solucionar o programa.

Observe que as variáveis utilizadas dentro dos métodos são aquelas declaradas fora do Main. Se elas estivessem
dentro do Main, como antes, elas não seriam visíveis dentro dos métodos e não poderíamos utilizá-las dessa
forma.

Bom, agora já entendemos como funciona um método e podemos ter uma idéia dos benefícios que a
modularização. Então, vamos entender o que significa o qualificador static antes do nome do método. Sem
entrar em muitos detalhes, como regra de C#, o método principal Main deve obrigatoriamente ser qualificado
como static. Assim, ele só pode realizar chamadas a métodos qualificados como static. Por isso nosso
métodos são todos static.

Outra regra de C# diz que variáveis declaradas fora dos métodos, como no nosso caso, se forem utilizadas dentro
de métodos static também devem ser declaradas com o qualificador static. Não há necessidade de
aprofundarmos neste assunto por enquanto, basta seguir essas regras para utilização de variáveis definidas fora
dos métodos qualificados como static.
Procedimentos e Funções

Todos os nossos métodos foram criados precedidos da palavra void. Isso significa que o métodos não retorna
nenhum valor para quem o chamou. Os métodos podem ser classificados de duas formas:

1. Procedimentos: métodos que não retornam nenhum valor para quem o chamou;

2. Funções: métodos que retornam algum valor para quem o chamou.

Assim, nossos métodos foram todos criados como procedimentos, já que não retornam nenhum valor e as
operações são realizadas nas variáveis definidas fora dos métodos. Dessa forma, sua execução se equivale a
troca da chamada pelo conjunto de códigos que definem o procedimento.

Para criarmos uma função, basta definir um tipo para o método. Assim como variáveis, um método pode ser
de um determinado tipo, como int, float, double, string etc. Então podemos retornar um determinado
valor para o ponto da chamada da função. Para isso, utilizamos o comando return. Nessa situação,
precisamos armazenar esse valor retornado em alguma variável.

Por exemplo, se alterarmos nosso procedimento somaMenores para retornar a soma, poderíamos fazer da
seguinte forma:
// Soma os numeros menores
static int somaMenores() {
int sm = 0;
sm = num1 + num2 + num3 - maior;
return sm;
}
Assim, somaMenores passa a ser uma função que retorna a soma dos menores números dentre os três criados.
Note que uma variável sm é definida dentro da função. Dentro de qualquer tipo de método podemos declarar
variáveis que sejam necessárias para a solução daquele problema e ela apenas existirá dentro do método.
Assim, sm não é acessível fora do método somaMenores. Quando isso ocorre, dizemos que a variável sm
somente é visível dentro do método somaMenores.

Com isso, o método principal deve ser alterado para receber o valor retornado pela função da seguinte forma:
static void Main(string[] args) {
leNumeros();
encontraMaior();
soma = somaMenores(); // variavel soma recebe retorno da funcao somaMenores
comparaMaior();

Console.ReadLine();
}
Passagem de parâmetros
Procedimentos e funções podem receber parâmetros em sua chamada. Isso significa que podemos passar
valores de qualquer tipo na chamada do método. Este recurso auxilia no isolamento do método
proporcionando maior independência e reusabilidade. A definição dos parâmetros de um método é
semelhante à declaração de variáveis sem valores iniciais. Os parâmetros são definidos entre os parênteses
que seguem o nome do método. Podemos definir quantos parâmetros forem necessários, separados por
vírgula, e cada um deles pode ser de qualquer tipo.

Por exemplo, poderíamos transformar encontraMaior em uma função que recebe três números inteiro e
retorne o maior dentre eles.
// Encontra o maior dentre 3 numeros
static int encontraMaior(int n1, int n2, int n3) {
int m = num1;
if (n2 > m) {
m = n2;
}
if (n3 > m) {
m = n3;
}
return m;
}

Note que dessa forma podemos aproveitar este método em qualquer problema que precisamos encontrar o
maior elementos dentre três números inteiros. Como a função agora não depende de variáveis declaradas
externamente, a reusalbilidade é garantida.

Nosso método principal ficaria da seguinte forma:


static void Main(string[] args) {
leNumeros();
maior = encontraMaior(num1, num2, num3);
soma = somaMenores(); // variavel soma recebe retorno da funcao somaMenores
comparaMaior();

Console.ReadLine();
}
Na chamada da função encontraMaior os valores de num1, num2 e num3 são copiados para os parâmetros n1, n2
e n3. Então, quando utilizamos n1, n2 e n3 dentro de encontraMaior, estamos acessando os valores copiados
de num1, num2 e num3, que estão fora da função. Vale lembrar que a alteração do valor de n1 dentro da função
não altera o valor de num1.
Exercícios

Para praticar os conceitos de modularizção, resolva os seguintes exercícios. Evite a declaração de variáveis
for a dos métodos. Prefira declarações dentro dos métodos e utilize de parâmetros e funções para trocar
valores entre o método principal e seus procedimentos e funções criados.

1. Construa uma função, denominada EhPar(...), que seja capaz de verificar se um inteiro qualquer é par ou
ímpar. A função deverá ter como argumento o inteiro a ser testado.

2. Diz-se que um inteiro é primo se for divisível apenas por 1 e por si mesmo. Por exemplo, 2, 3, 5, 7 são
primos, mas 4,6,8,9 não são. Escreva uma função que determine se um número é primo. Faça um programa
que utilize esta função para determinar e imprimir todos os números primos entre 1 e 1000.

3. Uma disciplina em um curso possui 20 pontos de trabalho, duas avaliações parciais de 25 pontos e uma
avaliação global 30 pontos. Escreva um programa que leia as notas parciais, trabalho e prova final dos alunos
de uma turma e retorne a nota final total e o conceito, dado pela tabela abaixo:

O programa deve conter:

• Uma tela inicial que leia quantos alunos forem necessários.

• Uma função que recebe os valores das 4 notas e retorne, simultaneamente, a nota final e o conceito
utilizando passagem de valores por referência.

• Uma função que recebe os valores das 4 notas e retorne, simultaneamente, a nota final e o conceito
utilizando passagem de valores por saída.

Anda mungkin juga menyukai