Ir para o conteúdo principal
Background Image

Designer de Código - A habilidade que IA não possui (ainda).

··9 minutos·
Rafael Issao
Autor
Rafael Issao
Apaixonado por tecnologia, programação e inovação. Adoro compartilhar conhecimento e aprender coisas novas todos os dias.
Tabela de conteúdos

A IA, com o hype do LLM, já gera CRUDs, telas, resolve bugs e até propõe um conjunto de classes, métodos e funções para criar uma aplicação completa.

Mas há uma habilidade que máquinas não replicam: o design estratégico de código.

Imagine um arquiteto que não apenas coloca tijolos, mas decide onde colocá-los, por quê, e como isso afetará quem morará ali daqui a 10 anos. O Designer de Código é esse arquiteto digital.

Neste artigo, compartilho uma opinião sobre o impacto do IA no design de código e como aproveitar o máximo a codificação, junto com IA.

O objetivo do desenvolvedor
#

O principal objetivo não é escrever código, mas criar soluções para problemas reais enfrentados pelo usuário a ponto de querer pagar pela solução.

O código é uma ferramenta que ajuda o desenvolvedor e a empresa atingir este objetivo.

E não basta somente fazer funcionar. Precisamos codificar de tal maneira que facilite as futuras manutenções e alterações para que o custo para a empresa seja o menor possível.

Para manter o custo baixo da manutenção e alteração, precisamos ter um design com baixo acoplamento e alta coesão.

Esta é uma habilidade que poucos desenvolvedores adquirem ao longo da experiência profissional dentro de uma empresa.

A habilidade que poucos desenvolvem
#

A habilidade de criar um design de código que possui baixo acoplamento e alta coesão é difícil de adquirir.

O primeiro motivo é que, para adquirir esta habilidade, uma das experiências importante e necessária para ganhar esta habilidade é a refatoração.

A refatoração é uma experiência técnica importante para qualquer desenvolvedor, pois nenhum desenvolvedor escreve um código perfeito ou quase perfeito na primeira tentativa.

Ou seja, não sabe onde colocar o tijolo e por que colocar aquele tipo de tijolo.

E também não sabe como o código pode afetar positivamente no futuro.

O segundo motivo é a falta de incentivo das empresas para adquirir esta habilidade.

Normalmente desenvolvedores se tornam destaques na empresa e começam a ocupar cargos de liderança e gestão.

Só que estas mesmas pessoas sabem que é importante refatorar mas não a ponto de investir nisso.

Já que a maioria dos desenvolvedores não sabem mostrar ou incentivar a importância da refatoração na sua empresa, a empresa e a sua liderança não vê sentido em criar incentivos para isso.

O foco da empresa e da liderança se torna então codificar o mais rápido possível. Seja para resolver bugs, criar novas funcionalidades e realizar alterações.

E IA, especificamente os LLM (Large Language Model), tem ajudado empresas e equipes a escreverem código mais rápido.

Entra IA para acelerar a codificação
#

Muitas tarefas cotidianas de um desenvolvedor como:

  • Tirar dúvidas sobre uma tecnologia, linguagem ou projeto
  • Cenários de teste
  • Boilerplate code
  • Auto-complete mais inteligente
  • Documentação

Tem sido facilitado com a ajuda dos LLM.

Mas estas tarefas são os passos que damos quando temos o design estratégico da solução em nossa mente.

Quando precisamos criar algo, por exemplo:

  • Refatoração: Criação de uma nova estrutura, sem alterar o comportamento que atinja um certo requisito de qualidade
  • Novas funcionalidades: Criar um conjunto de código que satisfaça a necessidade do cliente

Precisamos de criatividade e análise crítica das soluções, pois não basta somente funcionar. Deve funcionar em um contexto muito específico.

Por exemplo:

  • O código gerado pode funcionar para um usuário. Mas e se tiver muitos usuários continua funcionando?
  • O código gerado pode ter problema de desempenho quando você utiliza o banco de dados em produção
  • O código refatorado não melhorou a legibilidade ou a facilidade de adicionar novas features

Vamos ver um exemplo de uma refatoração.

IA, ajuda na refatoração
#

Vou utilizar o DeepSeek R1 para me ajudar a refatorar. E vamos supor que temos teste para cada cenário do código.

Vou utilizar o Gilded Rose onde as especificações são estão no link abaixo:

Gilded Rose Requirements

O código original do Gilded Rose está logo abaixo:

package br.com.youready.article.d_2025_01_27.image1;

class GildedRoseOriginal {
    Item[] items;

    public GildedRoseOriginal(Item[] items) {
        this.items = items;
    }

    public void updateQuality() {
        for (int i = 0; i < items.length; i++) {
            if ((!items[i].name.equals("Aged Brie")
                    && !items[i].name.equals("Backstage passes to a TAFKAL80ETC concert"))) {
                if (items[i].quality > 0) {
                    if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) {
                        items[i].quality = items[i].quality - 1;
                    }
                }
            } else {
                if (items[i].quality < 50) {
                    items[i].quality = items[i].quality + 1;

                    if (items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) {
                        if (items[i].sellIn < 11) {
                            if (items[i].quality < 50) {
                                items[i].quality = items[i].quality + 1;
                            }
                        }

                        if (items[i].sellIn < 6) {
                            if (items[i].quality < 50) {
                                items[i].quality = items[i].quality + 1;
                            }
                        }
                    }
                }
            }

            if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) {
                items[i].sellIn = items[i].sellIn - 1;
            }

            if (items[i].sellIn < 0) {
                if (!items[i].name.equals("Aged Brie")) {
                    if (!items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) {
                        if (items[i].quality > 0) {
                            if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) {
                                items[i].quality = items[i].quality - 1;
                            }
                        }
                    } else {
                        items[i].quality = items[i].quality - items[i].quality;
                    }
                } else {
                    if (items[i].quality < 50) {
                        items[i].quality = items[i].quality + 1;
                    }
                }
            }
        }
    }
}

Este código tem coesão baixa e alto acoplamento por ter todas as regras de todos os itens implementadas em um método.

Pedi para o DeepSeek R1 refatorar para aumentar a coesão e diminuir o acoplamento dos itens. A seguinte refatoração foi sugerida:

package br.com.youready.article.d_2025_01_27.image2;

class GildedRose {
    Item[] items;

    public GildedRose(Item[] items) {
        this.items = items;
    }

    public void updateQuality() {
        for (Item item : items) {
            ItemUpdater updater = ItemUpdaterFactory.getUpdaterForItem(item);
            updater.update(item);
        }
    }
}

Parece bom!

O código gerado aproveita a ideia de cada item ter uma regra e cria uma classe Updater para cada tipo de item especial e um normal.

Mas o nome ItemUpdaterFactory faz sentido para você? Estamos usando algum padrão de factory?

Será que não é um Strategy Pattern?

O que você acha?

Eu pedi mais duas sugestões de refatoração:

package br.com.youready.article.d_2025_01_27.image3;

import java.util.HashMap;
import java.util.Map;

class GildedRose {
    Item[] items;
    private final Map<String, UpdateStrategy> strategies = new HashMap<>();

    public GildedRose(Item[] items) {
        this.items = items;
        strategies.put("Aged Brie", new AgedBrieStrategy());
        strategies.put("Backstage passes to a TAFKAL80ETC concert", new BackstagePassStrategy());
        strategies.put("Sulfuras, Hand of Ragnaros", new SulfurasStrategy());
        strategies.put("default", new DefaultStrategy());
    }

    public void updateQuality() {
        for (Item item : items) {
            UpdateStrategy strategy = strategies.getOrDefault(item.name, strategies.get("default"));
            strategy.update(item);
        }
    }
}

O design deste código parece com a primeira sugestão mas tem algumas diferenças.

O nome virou de factory para strategy! E a estrutura interna do código é um pouco diferente também. Por exemplo, vemos um uso do static nas classes. Por que ele fez isso?

É melhor este design?

E a terceira sugestão:

package br.com.youready.article.d_2025_01_27.image4;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;

class GildedRose {
    Item[] items;
    private final Map<String, Consumer<Item>> rules = new HashMap<>();

    public GildedRose(Item[] items) {
        this.items = items;
        rules.put("Aged Brie", this::updateAgedBrie);
        rules.put("Backstage passes to a TAFKAL80ETC concert", this::updateBackstagePass);
        rules.put("Sulfuras, Hand of Ragnaros", item -> {});
        rules.put("default", this::updateDefaultItem);
    }

    public void updateQuality() {
        for (Item item : items) {
            Consumer<Item> rule = rules.getOrDefault(item.name, rules.get("default"));
            rule.accept(item);
        }
    }

    // Regras como métodos separados
    private void updateAgedBrie(Item item) {
        increaseQuality(item);
        item.sellIn--;
        if (item.sellIn < 0) increaseQuality(item);
    }

    private void updateBackstagePass(Item item) {
        /* Similar à versão 1 */
    }

    private void updateDefaultItem(Item item) {
        /* Similar à versão 1 */
    }

    private void increaseQuality(Item item) {
        if (item.quality < 50) {
            item.quality++;
        }
    }
}

Novamente um design parecido mas com algumas diferenças. A principal diferença é o uso das funções no lugar de classes. Mas parece difícil de testar por ter funções privadas. E agora?

Qual é o design mais adequado para o seu momento e seu contexto?

Se você não consegue responder, provavelmente um LLM também não consegue e vai sugerir a solução mais comum e frequente.

Então a habilidade de criar e entender um design se torna importante, mesmo com ferramentas de IA como DeepSeek R1.

Para você poder orientar melhor o modelo, você deve saber o que pedir. Em detalhes sobre o design estratégico adequado para o seu contexto.

Como eu uso DeepSeek R1 e outros modelos para design
#

Eu peço para ele criar algo mas nunca somente copio e não aceito a primeira solução.

Eu sempre peço três ou quatro variantes da solução e tento encontrar uma solução que une todas as sugestões e ainda com adição da minha ideia de design.

Quando você sugere três ou mais sugestões, você tem a oportunidade de aprender com as variantes da solução e tentar criar uma solução própria com seu conhecimento e dentro do seu contexto.

Dicas finais de Design de Código e LLM
#

Você deve saber avaliar o código gerado pelo LLM. Mas a sua avaliação não pode ser baseada em se funciona ou não o código.

A sua avaliação deve responder pelo menos as seguintes perguntas:

  • O código gerado tem um design bom o suficiente para facilitar a alteração futura?
  • O código gerado tem um design bom o suficiente para facilitar a compreensão do código de qualquer um da equipe?
  • O código gerado tem um design bom o suficiente para facilitar a escrita de testes?
  • O código gerado, além de funcionar, atende a outros requisitos de qualidade como concorrência, desempenho, carga, segurança e etc?

Basicamente você deve se tornar o Code Reviewer do código gerado. A única diferença é que você pode fazer as alterações necessárias em vez de pedir as alterações.

Outras dicas para 2025
#

  • Aprenda a fazer design e não fique só na codificação
  • Estude um pouco sobre padrões e princípios
  • Leia livros sobre design
  • Aprenda a fazer análises mais amplas, como por exemplo: Como meu código pode afetar o deploy? Como afeta a manutenção do código?
  • Domine as ferramentas de IA mas não dependa delas
  • Use o modelo de sua preferência e utilize as respostas como esboço inicial da sua solução.

Conclusão
#

Enquanto IA pode automatizar a escrita do código, o desenvolvedor ainda tem a responsabilidade de pensar em qual o melhor design de código para o momento do projeto, produto e empresa.

Um desenvolvedor que conseguir evoluir a habilidade de design, será um profissional que conseguirá trazer mais benefícios para a equipe e empresa do que um modelo de LLM qualquer.

Aprender e saber trabalhar o design do código, junto com LLM para gerar esboço rápido, é um ganho fantástico.

E você? Quais modelos tem utilizado no dia a dia?

Se tiver curiosidade sobre o assunto, pode falar comigo!

🥒🥒 Espero que tenham curtido e até o próximo artigo! 🥒🥒