Archive for May 2010
Tornando dependências opcionais com autoload
Uma técnica bacana e que pouca gente conhece é usar o autoload para carregar classes. A função do autoload é a mesma do require (por baixo dos panos, o autoload usa o require), a diferença é que o autoload carregará o arquivo apenas quando for necessário. A idéia é que as constantes sejam registradas e associandas ao arquivo que deve ser requerido, por exemplo:
autoload :MinhaLib, 'minha_lib'
Note que o primeiro argumento é um símbolo, e não a classe. Com módulos é a mesma coisa:
module MeuModulo autoload :MinhaLib, 'meu_modulo/minha_lib' end
Ou ainda:
module MeuModulo # coisas do meu modulo end MeuModulo.autoload :MinhaLib, 'meu_modulo/minha_lib'
Dessa forma, quando a constante MinhaLib (ou MeuModulo::MinhaLib, no caso do módulo) for usada, o arquivo ‘minha_lib‘ será carregado automaticamente. Qual a utilidade disso? Bem, se a constante não for usada, o arquivo não será carregado, o que nos trás duas vantagens:
- Como as classes desnecessárias não serão carregadas, a biblioteca será carregada mais rapidamente
- Conseguimos um mecanismo para tornar dependências opcionais
A primeira vantagem é óbvia, mas a segunda é meio implícita e depende de como o projeto está estruturado.
Por exemplo digamos que temos uma gem, que dependa da gem mail, mas apenas se o usuário desejar notificações. Se declararmos a mail como dependência na gemspec, quando alguém for instalar nossa gem, a mail será instalada mesmo que o usuário não precise dela.
O que podemos fazer para relaxar as dependências é usar o autoload para registrar a constante Mail,
e deixar a cargo do usuário instalar a dependência caso ele precise. Um exemplo de como seria o esqueleto da nossa gem:
# minha_gem.rb autoload :Mail, 'mail' # faz o que precisa ser feito # a gem será carregada apenas se o usuário desejar notificações # as notificações poderiam ser configuradas por um arquivo *.yml por exemplo if user_wants_notification? Mail.new ... end
Um exmplo de uso dessa técnica pode ser visto na gem backup, que antes especificava várias dependências na gemspec, e após uma pequena reestruturação, deixaram de ser obrigatórias. Veja aqui como foi feito. Outro exemplo de gem que usa essa técnica é a devise, vale a pena dar uma olhada no código
.
Se você desenvolve alguma gem que usa adaptadores, e esses adaptadores dependem de outras gems, você encontrou um bom uso para o autoload, e vai deixar seus usuários mais felizes por não precisarem instalar o que não usarem
.
Referências:
http://www.rubyinside.com/ruby-techniques-revealed-autoload-1652.html
http://ruby-doc.org/core/classes/Module.html
Me recomende