Design de software

Biblioteca vs. framework: o critério é “quem chama quem” (inversão de controle)

Chamamos Alamofire de biblioteca e SwiftUI de framework. Mas os dois não são apenas “usar código criado por outra pessoa”? Qual é a diferença?

4 min de leitura
Imagem de capa de Biblioteca vs. framework: o critério é “quem chama quem” (inversão de controle)

Chamamos Alamofire de biblioteca e SwiftUI de framework. Mas os dois não são apenas “usar código criado por outra pessoa”? Qual é a diferença?

É comum ouvir que “um framework é maior”, mas o tamanho não é o essencial. Existem frameworks pequenos e bibliotecas enormes.

Quem chama quem.

Esse único critério se conecta naturalmente ao conceito importante de inversão de controle (IoC). Você também o encontrará ao estudar injeção de dependência, então entendê-lo bem aqui traz vantagens.

Este é o resumo principal.

  1. Biblioteca: conjunto de ferramentas que meu código chama quando precisa. O controle está comigo
  2. Framework: estrutura que controla o fluxo e chama meu código. O controle está com o framework
  3. Essa direção invertida das chamadas é chamada de inversão de controle
  4. Princípio de Hollywood: “Não nos chame; nós ligaremos para você”

Biblioteca: a ferramenta que eu chamo

Uma biblioteca é um conjunto de código que implementa previamente uma funcionalidade específica. Meu código decide completamente quando e em que ordem usá-la.

// Meu código controla o fluxo
let json = try JSONDecoder().decode(User.self, from: data)
let hash = SHA256.hash(data: input)

Eu defino o início, o fim e o fluxo geral do programa e, no caminho, uso as ferramentas necessárias. É como tirar uma chave de fenda da caixa de ferramentas. A chave de fenda não decide a ordem do trabalho.

Alamofire e Kingfisher pertencem a essa categoria. Eu decido quando enviar requisições de rede e quando carregar imagens.


Framework: a estrutura que me chama

Um framework é uma estrutura que já define a arquitetura geral e o fluxo de execução da aplicação. Eu preencho com código os pontos deixados em aberto.

Em um app iOS, isso fica claro. UIKit e SwiftUI controlam o ponto de entrada, o loop de eventos e o ciclo de vida das telas. O que escrevo, como viewDidLoad, body e onAppear, é código que o framework chama em momentos definidos.

struct ProfileView: View {
    var body: some View {   // Eu não chamo.
        Text("Hello")       // SwiftUIEle chama quando necessário
    }
}

Nunca chamo body manualmente. O SwiftUI decide quando e quantas vezes ele será chamado. O controle do fluxo mudou de mãos.

A direção das chamadas é inversa. Isso é inversão de controle.
A direção das chamadas é inversa. Isso é inversão de controle.

Inversão de controle e o princípio de Hollywood

Essa relação invertida tem um nome: inversão de controle (IoC).

Em um programa procedural comum, meu código controla o fluxo e chama o código externo. Em um programa baseado em framework, o framework controla o fluxo, e meu código é chamado nos pontos que registrei. O controle passou para a direção oposta; por isso “inversão”.

A forma espirituosa de expressar isso é o princípio de Hollywood.

“Não nos chame; nós ligaremos para você.” — Não ligue; nós entraremos em contato.

Um ator que faz um teste não fica ligando para a produtora. Quando é escolhido, a produtora entra em contato. Essa é exatamente a relação entre um framework e meu código.

O padrão delegate segue o mesmo princípio. Ao implementar UITableViewDataSource, sou eu que chamo cellForRowAt? Não. A table view me chama quando precisa. A sintaxe do mundo dos frameworks está espalhada por todo o código.


Então, o que muda na prática?

A forma de aprender é diferente. Em uma biblioteca, basta procurar “quais funcionalidades existem”; em um framework, primeiro você precisa aprender “quando ele me chama” (ciclo de vida e convenções de chamada). É por isso que o estudo de UIKit começa pelo ciclo de vida.

O custo de substituição é diferente. É possível trocar uma biblioteca alterando apenas os pontos de chamada, mas, como todo o código se apoia na estrutura do framework, substituí-lo equivale praticamente a reescrever tudo. Por isso migrar de UIKit para SwiftUI não é trocar algumas funções.

A estratégia de testes é diferente. É difícil executar isoladamente o código chamado pelo framework sem o próprio framework. Por isso o conselho de separar a lógica em uma camada independente de framework (Swift puro) é tão recorrente.

Não nos chame; nós ligaremos para você — o princípio de Hollywood
Não nos chame; nós ligaremos para você — o princípio de Hollywood

Em uma frase para entrevistas

“Uma biblioteca é uma ferramenta chamada pelo meu código, enquanto um framework é uma estrutura que controla o fluxo e chama meu código. Essa diferença na direção do controle é chamada de inversão de controle.”

As perguntas seguintes costumam ser “dê um exemplo de IoC” (métodos de ciclo de vida, delegates) e depois “por que isso é bom?” (padroniza o fluxo e permite que o desenvolvedor se concentre na lógica de negócio).


Resumo

  • O critério de distinção é a direção das chamadas, não o tamanho
  • Biblioteca: ferramenta que meu código chama quando precisa. O controle está comigo
  • Framework: estrutura que controla o fluxo e chama meu código em momentos definidos. O controle está com o framework
  • Esse controle invertido é a inversão de controle (IoC), também conhecida como princípio de Hollywood
  • viewDidLoad, body e os métodos delegate são todos códigos que são chamados
  • Diferenças práticas: primeiro se aprende o ciclo de vida do framework, a substituição é difícil e separar a lógica é essencial para os testes