-
Notifications
You must be signed in to change notification settings - Fork 18
O Padrão Adapter
Diagrama de representação do padrão Adapter
Um adapter ou wrapper fornece uma interface para diferentes classes para trabalhar em conjunto. No padrão object adapter, o módulo contém uma instância da classe que ele "engloba". Nessa situação, o wrapper faz as chamadas para a instância do objeto "englobado".
Em resumo, o padrão de projetos Adapter consiste em adaptar a interface de uma classe ou objeto para ser usada de outra forma, porém sem alterar a interface ou implementação.
Um caso comum é quando desenvolvemos um código cliente que pretende usar diversas fontes heterogêneas.
O principal trunfo do padrão de projetos Adapter é permitir reuso do código de forma consistente, mantendo compatibilidade com outras bibliotecas e versões anteriores de código. Uma classe adaptadora nada mais é do que uma classe que implementa a interface que se deseja usar e delega a real execução para uma classe terceira que possui a implementação que desejamos usar.
No Rails, o padrão adapter geralmente é implementado para "englobar" os clientes da API, fornecendo uma interface reutilizável para se comunicar com APIs externas. No nosso caso, usamos este padrão para refatorar o código que escrevemos que se comunica com a API do GitHub(OctoKit Client).
Percebemos que estávamos violando alguns princípios, como "Separation of concerns" e "Single responsibility", por isso houve um esforço de refatoração, o que ajudou a modularizar mais o código, e facilitou a construção dos testes.
Podemos ver no código abaixo que em apenas em um único método eram feitas diversas chamadas ao cliente Octokit. Por exemplo, podemos ver que faz-se uma requisição para encontrar o usuário do GitHub, depois faz-se uma requisição para encontrar os repositórios daquele usuário, requisita-se posteriormente as organizações daquele usuário e em seguida os repositórios daquela organização(ões). Ou seja, logo de cara são feitas quatro coisas totalmente independentes dentro de um único método.
def github_projects_list
@current_user = AuthorizeApiRequest.call(request.headers).result
@client = Octokit::Client.new(access_token: @current_user.access_token)
user_login = @client.user.login
user_repos = []
@repos = @client.repositories(user_login)
@form_params = { user: [] }
@form_params[:user].push(login: user_login)
@repos.each do |repo|
user_repos.push(repo.name)
end
@form_params[:user].push(repos: user_repos)
@orgs = @client.organizations(user_login)
@form_params2 = { orgs: [] }
@orgs.each do |org|
repos = @client.organization_repositories(org.login)
repos_names = []
repos.each do |repo|
repos_names.push(repo.name)
end
@form_params2[:orgs].push(name: org.login, repos: repos_names)
end
@form_params3 = @form_params2.merge(@form_params)
render json: @form_params3
end
Após a refatoração, as chamadas às funções ficaram mais atômicas.
module Adapter
class GitHubProject
def initialize(request)
@logged_user = AuthorizeApiRequest.call(request.headers).result
@client = Octokit::Client.new(access_token: @logged_user.access_token)
end
def get_github_user
user_login = @client.user.login
return user_login
end
def get_github_repos(user_login)
@client.repositories(user_login)
end
def get_github_orgs(user_login)
@client.organizations(user_login)
end
def get_github_orgs_repos(org)
@client.organization_repositories(org.login)
end
def get_contributors(github_slug)
@client.contributors(github_slug)
end
end
Vemos que a chamada às funções da Octokit ficaram modularizadas na controller.
def github_projects_list
client = Adapter::GitHubProject.new(request)
user_login = client.get_github_user
@form_params_user = { user: [] }
@form_params_user[:user].push(login: user_login)
user_repos = []
(client.get_github_repos(user_login)).each do |repo|
user_repos.push(repo.name)
end
@form_params_user[:user].push(repos: user_repos)
@form_params_orgs = { orgs: [] }
(client.get_github_orgs(user_login)).each do |org|
repos_names = []
(client.get_github_orgs_repos(org)).each do |repo|
repos_names.push(repo.name)
end
@form_params_orgs[:orgs].push(name: org.login, repos: repos_names)
end
@form_params_user_orgs = @form_params_orgs.merge(@form_params_user)
render json: @form_params_user_orgs
end
- Folha de Estilo
- Esquema de Cores
- Como Usar o Docker
- O Padrão Adapter
- Links e Comandos Úteis
- O Padrão Observer
- Product Backlog
- Quadro Kanban
- Priorização das Histórias
- Sistema de Pontuação
- EVM Agile
- Roadmap
- Post Mortem - Release II
- Termo de Abertura do Projeto
- Plano de Gerenciamento do Projeto
- Plano de Gerenciamento do Escopo
- Plano de Gerenciamento de Requisitos
- Plano de Gerenciamento de Tempo
- Plano de Gerenciamento das Partes Interessadas
- Plano de Gerenciamento de Comunicação
- Plano de Gerenciamento das Aquisições
- Plano de Gerenciamento de Recursos Humanos
- Plano de Gerenciamento dos Riscos
- Plano de Gerenciamento de Configuração de Software
- Plano de Gerenciamento da Qualidade
- Plano de Gerenciamento dos Custos