C# - Criando métodos (DRY)


 Hoje vamos abordar um conceito básico da linguagem C# : os métodos ou funções.

Um princípio fundamental de programação é o princípio DRY ou Don't Repeat Yourself (Não escreva código duplicado)

Ao programar, se você se pegar escrevendo as mesmas instruções repetidamente, transforme essas instruções em uma função/método.  (No contexto do artigo uma função pode ser entendida como um método.)

As funções ou métodos são como pequenos programas que completam uma pequena tarefa. Por exemplo, você pode escrever uma função para calcular o imposto sobre vendas e, em seguida, reutilizar essa função em muitos lugares em um aplicativo financeiro.

Como os programas, as funções geralmente têm entradas e saídas. Às vezes, elas são descritas como caixas pretas, nas quais você alimenta algumas matérias-primas em uma extremidade e um item manufaturado surge na outra. Depois de criadas, você não precisa pensar em como elas funcionam.

Digamos que você queira ajudar seu filho a aprender a tabuada, então você deseja facilitar a geração de uma tabuada para um número, como a tabuada de 12 usando a linguagem C#, e para isso, a primeira coisa que vem a mente é usar um laço for:

for (int linha = 1; linha <= 12; linha++)
{
    Console.WriteLine($"{linha} x 12 = {linha * 12}");
}

O código acima vai funcionar mas podemos melhorar isso e em vez de exibir apenas a tabuada do 12 podemos criar um código mais flexível que gere a tabuada para um número selecionado.

É aqui que entram as funções ou métodos.

Vamos a seguir criar um pequeno programa para gerar tabuadas entre os números 1 e 255 criando métodos.

using System;
using static System.Console;
namespace CShp_Tabuada
{
    class Program
    {
        static void Tabuada(byte numero)
        {
            WriteLine($"Tabuada do número {numero}:");
            for (int linha = 1; linha <= 12; linha++)
            {
                WriteLine(
                  $"{linha} x {numero} = {linha * numero}");
            }
            WriteLine();
        }

        static void GeraTabuada()
        {
            bool isNumero;
            do
            {
                Write("Informe um número entre 0 e 255 : ";
                isNumero = byte.TryParse(ReadLine(), out byte numero);
                if (isNumero)
                {
                    Tabuada(numero);
                }
                else
                {
                    WriteLine("Número inválido !");
                }
            }
            while (isNumero);
        }
        static void Main(string[] args)
        {
            GeraTabuada();
            Console.ReadLine();
        }
    }
}

Neste exemplo criamos dois métodos :

  1. Tabuada(byte numero)
  2. GeraTabuada();

Veja que mesmo para um exemplo bem simples a utilização de métodos otimiza o código, evitando código repetido e que pode ser reutilizado.

No exemplo anterior executamos uma ação usando um laço for e exibimos o resultado no console mas não houve o retorno de valor pelos métodos usadas.

Vejamos agora outro exemplo onde vamos retornar um valor.

Suponha que você tem que calcular o imposto cobrado pela venda feita entre as unidades da federação no Brasil. Existe uma taxa padrão que é cobrada por alguns estados no valor de 0.18 % mas alguns estados possuem uma taxa diferente.

Veja a seguir um programa C# onde usamos métodos que retornam um valor e que calcula o imposto por unidade da federação:

using static System.Console;
namespace Exemplo2
{
    class Program
    {
        static decimal CalculaImposto(decimal valor, string estado)
        {
            decimal taxa = 0.0M;
            switch (estado)
            {
                case "SP": // São Paulo
                    taxa = 0.4M;
                    break;
                case "RS": // Rio G. do Sul
                case "SC": // Santa Catarina
                    taxa = 0.25M;
                    break;
                case "PR": // Paraná
                case "MG": // Minas Gerais
                    taxa = 0.38M;
                    break;
                case "RJ": // Rio de Janeiro
                    taxa = 0.35M;
                    break;
                case "BA": // Bahia
                case "CE": // Ceará
                case "PE": // Pernambuco
                    taxa = 0.38M; break;
                case "PB": // Paraiba
                case "RN": // Rio G. do Norte
                case "SE": // Sergipe
                    taxa = 0.5M;
                    break;
                default: // Os demais estados
                    taxa = 0.18M;
                    break;
            }
            return valor * taxa;
        }

        static void Main(string[] args)
        {
            Write("Informe o valor(R$) :\n ");
            string valorInformado = ReadLine();
            Write("Informe a Unidade da Federação (UF):\n ");
            string estado = ReadLine().ToUpper();
            if (decimal.TryParse(valorInformado, out decimal valor))
            {
                decimal impostoAPagar = CalculaImposto(valor, estado);
                WriteLine($"Para o estado de {estado}");
                WriteLine($"O valor {string.Format("{0:c}", valor)}");
                WriteLine($"Deve pagar {string.Format("{0:c}", impostoAPagar)} de imposto.");
                WriteLine($"Aliquota de : {impostoAPagar / valor} %");
            }
            else
            {
                WriteLine("Valor inválido!");
            }
            ReadLine();
        }
    }
}

Criamos o método CalculaImposto( decimal valor, string estado) onde devemos passar como parâmetros o valor a ser calculado como um decimal e a unidade da federação como uma string de dois caracteres.

Estamos usando um bloco switch para obter a taxa do imposto conforme o estado e calculando o valor apenas multiplicando o valor pela taxa de imposto.  Abaixo temos o resultado:

Este exemplo foi usado para mostrar o uso de funções que retornam um valor mas o seu código pode ser otimizado.

Você sempre pode substituir um bloco switch ou um bloco if/else if aplicando o princípio SOLID Aberto/Fechado ou Open/Closed (OCP).

Nota:  Também podemos usar o padrão Factory para otimizar a criação de objetos.

Veja mais detalhes em :  Principio Aberto/Fechado e em OOP - princípio Open/Closed (OCP)

E estamos conversados...

"Bendirei o Senhor, que me aconselha; na escura noite o meu coração me ensina!"
Salmos 16:7

Referências:


José Carlos Macoratti