Skip to main content

Command Palette

Search for a command to run...

Decomposição funcional

Published
5 min read
Decomposição funcional
A

My name is Lucas. I'm a journalist and software developer who can take photos, print zines and make videos, that's no joke. 📸📰🎬💻🕺😅

Dividir um programa em partes menores, é uma boa prática de programação que nos ajuda a escrever códigos mais legíveis e sintéticos, fáceis de entender. A abordagem de dividir um programa complexo em sub-rotinas é chamado de decomposição funcional.

Resolvendo tarefas complexas

A ideia por trás de decompor um problema complexo em pequenas partes é bem intuitiva. Se você quer preparar uma pizza, não deve somente jogar todos os ingredientes no forno e esperar pelo melhor resultado, ao invés disso, você quebra o preparo em etapas, desde preparar a massa, o recheio até assar. Decomposição funcional parte desse mesmo princípio, quebrar um problema maior em partes menores chamadas de métodos.

Vamos considerar o exemplo de um aplicativo para Smart Home. Trata-se de um aplicativo normalmente usado para controlar dispositivos domésticos de forma remota. Dispositivos como caixas de som, luzes, travas de segurança, entre outros. Imagine que temos um aplicativo com três funções: ligar ou desligar a música, ligar e desligar a luz e controlar a fechadura da porta. Vamos considerar essas ações como partes do nosso software.

Se decompormos essa tarefa, é assim que seu algoritmo pode ser descrito em geral:

  • Analisar os dados de entrada (senha inserida);
  • Verifique se a senha está correta;
  • Pergunte ao usuário o que ele quer fazer;
  • Se a ação for suportada, execute-a.

Imagine que você encapsulasse este programa em código, mas sem um único método. É assim que sua estrutura ficaria:

// ...
        int password = 76543210;
        String speakersState;
        String lampState;
        String doorState;

        // reading the password
        System.out.println("Enter password: ");
        int passwordInput = scanner.nextInt();

        // checking if the password is correct
        if (passwordInput != password) {
            System.out.println("Incorrect password!");
        } else {
            // asking the user what they want to do
            System.out.println("Choose the object: 1 – speakers, 2 – lamp, 3 – door");
            String action = scanner.next();

            switch (action) {
                case "1":
                    // asking the user about speakers

                    switch (speakersState) {
                        case "on":
                            // ...
                        case "off":
                            // ...
                        default:
                            // ...
                    }
                    break;
                case "2":
                    // asking the user about lights...
                case "3":
                    // asking the user about the door...
                }
        }

O aplicativo poderia funcionar perfeitamente com esse código extenso. Porém, imagine que agora precisaremos corrigir uma das funcionalidades por algum motivo externo, ou que precisamos adicionar uma nova funcionalidade. Para isso, teríamos que mexer no código todo. Isso geraria o risco de um erro comprometer toda a execução do aplicativo. Além disso, quanto mais funcionalidade adicionarmos, mais difícil se tornará a leitura do código, pois será um código mais extenso, com mais condicionais.

Para tornar este código menos específico e mais flexível, podemos usar a decomposição funcional. Assim, podemos separar responsabilidades por blocos. Essa separação nos permite ser mais cirúrgicos, e ler, corrigir, alterar ou estender somente funcionalidades específicas, sem a obrigação de alterar todo o programa.

Decompondo um programa em métodos

A decomposição funcional é a atividade em dividir um problema maior em partes menores, ou seja, em várias funções ou métodos. Cada método executa uma tarefa específica para que, quando executarmos determinada sequência desses métodos, possamos obter os resultados desejados.

Para isso, ao analisar um problema, precisamos pensar em quais ações precisaremos repetir ou, alternativamente, quais podemos executar separadamente.

Por meio dessa forma de pensar, que é a base do pensamento computacional, obtemos métodos mais fáceis de ler, entender, reutilizar, testar e depurar.

Vamos analisar novamente o aplicativo Smart Home e descobrir quais etapas podem ser transformadas em métodos separados. Primeiramente, podemos separar nossas operações principais em três métodos: um método para controlar a música, outro para ligar e desligar as luzes e o terceiro para operar a fechadura da porta. Os métodos controlMusic(), que controla a música, controlLight()e controlDoor() poderiam seguir um padrão específico, veja o exemplo:

// method that turns the music on and off

public static void controlMusic() {
    Scanner scanner = new Scanner(System.in);
    System.out.println("on/off?");
    String tumbler = scanner.next();
    if (tumbler.equals("on")) {
        System.out.println("The music is on");
    } else if (tumbler.equals("off")) {
        System.out.println("The music is off");
    } else {
        System.out.println("Invalid operation");
    }
}

Esses métodos de controle executam as principais ações que nosso aplicativo oferece. É claro que essas ações são bastante simplificadas, mas o objetivo principal aqui é mostrar o processo de revisão da funcionalidade do nosso programa.

Para que as coisas funcionem, precisamos criar um método que verifique a senha.

// method that verifies the password and gives access to Smart home actions if the password is correct
public static void accessSmartHome() {
    Scanner scanner = new Scanner(System.in);
    final int password = 76543210;
    System.out.println("Enter password: ");
    int passwordInput = scanner.nextInt();
    if (passwordInput == password) {
        chooseAction();
    } else {
        System.out.println("Incorrect password!");
    }
}

Além disso, precisamos de um método com o menu principal onde você possa escolher a ação, então criamos um método chooseAction(). Este método pergunta ao usuário qual ação ele deseja executar e dá controle ao método que executa a ação escolhida.

Por fim, podemos executar nosso programa decomposto no método main, que é chamado quando nosso programa é iniciado:

public static void main(String[] args) {
    accessSmartHome();
}

Ou seja, este método chama accessSmartHome, que pede para digitar uma senha e, se estiver correta, nos permite gerenciar a casa inteligente.

Adicionando novos recursos

Agora, se quisermos adicionar outra ação, basta definir o método com esta ação. Por exemplo, temos um novo dispositivo inteligente, uma chaleira elétrica. Criamos um método que a liga e desliga. Para acessar o novo método, precisamos modificá-lo chooseAction()adicionando uma nova instrução case:

// method that controls electric kettle
public static void controlKettle() {
    // ...
}

// method with the main menu for choosing the action
public static void chooseAction() {
    Scanner scanner = new Scanner(System.in);
// adding case 4
    System.out.println("Choose the object: 1 – speakers, 2 – lamp, 3 – door, 4 – kettle");
    // ...
        case 4:
            controlKettle();
            break;
    // ...
    }

Como você pode ver, agora temos um programa funcional que não vai falhar se decidirmos alterá-lo um pouco. Podemos testar componentes separados facilmente, pois eles são definidos em métodos separados. Isso também facilita o suporte ao programa no futuro.

Resumo

Neste tópico, aprendemos a importância da decomposição funcional. Ela é usada para dividir um programa em vários métodos. Essa abordagem tem muitas vantagens. Ela nos ajuda a:

  • estruturar o código;
  • seguir a lógica geral do programa;
  • faça alterações facilmente;
  • testar métodos separados.

A decomposição funcional não é a chave para tudo, mas usar essa abordagem nos ajuda a criar programas organizados e compreensíveis, fáceis de trabalhar.

More from this blog

A

Aú Desviante

53 posts

Estudos em Tecnologia e Desenvolvimento de Software