[DESBRAVANDO SOLID] Dúvida sobre o "Quem chama quem" do capítulo 3.4

A minha dúvida é sobre o capítulo 3, tópico 4 “NÃO SE REPITA”

Mais precisamente nas páginas 44 e 45 estamos avaliando opções de design de código:

então temos aqui algumas opções de “quem chama quem”

  • Main chama RenderizadorMDParaHTML, que chama GeradorPDF e GeradorEPUB
  • Main chama RenderizadorMDParaHTML, GeradorPDF e GeradorEPUB, coordenando as classes

mas eu consigo enxergar uma terceira opção, que me parece melhor mas queria saber a opinião do autor sobre:

o Main chamaria GeradorPDF e GeradorEPUB, e essas duas classes iriam chamar o RenderizadorMDParaHTML, pois o método renderiza iria retornar uma String

E o código ficaria assim:

    //GeradorPDF
    public void gera(Path diretorioDosMD, Path arquivoDeSaida){
        try(var writer = new PdfWriter(Files.newOutputStream(arquivoDeSaida));
            var pdf = new PdfDocument(writer);
            var pdfDocument = new Document(pdf)) {
            
            //TRECHO DO CÓDIGO QUE IRIA POPULAR A VARIÁVEL HTML
            RenderizadorMDParaHTML renderizadorMDParaHTML = new RenderizadorMDParaHTML();
            String html = renderizadorMDParaHTML.renderiza(diretorioDosMD);

            List<IElement> convertToElements = HtmlConverter.convertToElements(html);
            for (IElement element : convertToElements) {
                pdfDocument.add((IBlockElement) element);
            }
            // TODO: não adicionar página depois do último capítulo
            pdfDocument.add(new AreaBreak(AreaBreakType.NEXT_PAGE));

        } catch (Exception ex) {
            throw new IllegalStateException("Erro ao criar arquivo PDF: " + arquivoDeSaida.toAbsolutePath(), ex);
        }
    }

    //GeradorEPUB
    public void gera(Path diretorioDosMD, Path arquivoDeSaida){
        var epub = new Book();

        //TRECHO DO CÓDIGO QUE IRIA POPULAR A VARIÁVEL HTML
        RenderizadorMDParaHTML renderizadorMDParaHTML = new RenderizadorMDParaHTML();
        String html = renderizadorMDParaHTML.renderiza(diretorioDosMD);

        //TODO: usar título do capítulo
        epub.addSection("Capítulo", new Resource(html.getBytes(), MediatypeService.XHTML));

        var epubWriter = new EpubWriter();

        try {
            epubWriter.write(epub, Files.newOutputStream(arquivoDeSaida));
        } catch (IOException ex) {
            throw new IllegalStateException("Erro ao criar arquivo EPUB: " + arquivoDeSaida.toAbsolutePath(), ex);
        }
    }

Gostaria de saber o que acha dessa opção e se seria uma opção viável no nosso contexto.

Obrigado e parabéns pelo livro, está sendo uma leitura fantástica para mim.

1 curtida

Olá, @Arthur98.

Ótima questão! E obrigado por livro com atenção! :slight_smile:

Eu lembro que durante os cursos e workshops já avaliamos essa opção.

Acho que a questão seria pensar onde queremos deixar o acoplamento e, em consequência, a responsabilidade a mais.

Se fizermos o design que você sugere, as classes GeradorPDF e GeradorEPUB teriam uma responsabilidade a mais que é coordenar a renderização de Markdown para HTML, invocando RenderizadorMDParaHTML.

O argumento que uso pra manter o design escolhido no livro é o mesmo: a Main já é uma classe coordenadora por excelência. A responsabilidade de coordenar os objetos é natural para a Main.

Já para as geradores de PDF e EPUB, seria algo a mais para elas fazerem e mais um motivo para modificar ambas, sabe?

Acho que é uma opção válida, que remove uma responsabilidade da Main mas a passa para 2 outras classes.

Isso é uma lição interessante: em software, a complexidade nunca morre, ela sempre muda de lugar. Michael Feathers brinca com termodinâmica, cunhando o termo Lei da Conservação da Complexidade [1]

I strongly believe that there is a law of conservation of complexity in software. When we break up big things into small pieces we invariably push the complexity to their interaction.

[1] Michael Feathers - Microservices Until Macro Complexity

1 curtida