Eu tenho o seguinte código:
public void moveCameraTo(Location location){
moveCameraTo(location.getLatitude(), location.getLongitude());
}
public void moveCameraTo(double latitude, double longitude){
LatLng latLng = new LatLng(latitude, longitude);
moveCameraTo(latLng);
}
public void moveCameraTo(LatLng latLng){
GoogleMap googleMap = getGoogleMap();
cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, INITIAL_MAP_ZOOM_LEVEL);
googleMap.moveCamera(cameraUpdate);
}
Penso que desta maneira elimino a responsabilidade de saber o que é uma LatLng
outra aula, por exemplo.
E você não precisa preparar os dados antes de chamar a função.
O que você acha?
Essa abordagem tem um nome? É realmente uma má prática?
design
design-patterns
clean-code
code-smell
bad-code
Tlaloc-ES
fonte
fonte
LatLng
os clientes dessaCamera
classe, provavelmente você não quermoveCameraTo(LatLng)
serpublic
.moveCameraToLocation
emoveCameraTo
/moveCameraToCoords
. Definitivamente não gostaria de passar Location / lat / long com os mesmos nomes.Respostas:
Você está usando o recurso de sobrecarga de método de idiomas para oferecer ao chamador formas alternativas de resolver a dependência dos métodos nas informações posicionais. Você está delegando outro método para resolver o trabalho restante de atualização da câmera.
O cheiro do código aqui seria se você continuasse apenas estendendo a cadeia de métodos chamando métodos. O método de tomada de localização chama o método de tomada dupla, que chama o método de latLng, que finalmente chama algo que sabe como atualizar a câmera.
As cadeias longas são tão fortes quanto o elo mais fraco. Cada extensão da cadeia aumenta a área de cobertura do código que precisa funcionar ou essa coisa quebra.
É um design muito melhor se cada método seguir o caminho mais curto possível para solucionar o problema que lhe foi apresentado. Isso não significa que cada um deve saber como atualizar a câmera. Cada um deve converter seu tipo de parâmetro de posição em um tipo uniforme que pode ser passado para algo que sabe como atualizar a câmera quando apresentado esse tipo.
Faça dessa maneira e você poderá remover um sem quebrar metade de todo o resto.
Considerar:
Isso faz com que lidar com
LatLng
o problema de latitude e longitude . O custo é que ele espalha conhecimentoLatLng
ao redor. Isso pode parecer caro, mas, na minha experiência, é uma alternativa preferível à obsessão primitiva, que é o que evitar o estabelecimento de um objeto de parâmetro o deixa preso.Se
Location
é refatorável, masLatLng
não é, considere resolver isso adicionando uma fábrica aLocation
:Isso também evita muito bem a obsessão primitiva.
fonte
LatLng
ouLocation
objetos. Você pode mostrar o relacionamento entre os dois comNew LatLng(Location)
ouLocation.toLatLng()
se precisar passar de um para o outro.Não há nada de particularmente errado com sua solução.
Mas minha preferência pessoal seria que esses métodos não sejam tão úteis. E complique a interface de qualquer objeto do qual eles se separem.
O
void moveCameraTo(double latitude, double longitude)
código não simplifica realmente o código, pois não vejo problema em simplesmente chamámoveCameraTo(new LatLng(latitude, longitude));
-lo. Este método também cheira a obsessão primitiva.Isso
void moveCameraTo(Location location)
poderia ser melhor resolvido provandoLocation.ToLatLng()
método e chamandomoveCameraTo(location.ToLatLng())
.se fosse C # e se esses métodos fossem realmente necessários, eu os preferiria como métodos de extensão em vez de métodos de instância. O uso de métodos de extensão se tornaria realmente óbvio se você tentasse abstrair e testar a unidade nesta instância. Como seria muito mais fácil falsificar um método único, em vez de várias sobrecargas com conversões simples.
Não vejo razão para que isso seja um problema. Desde que seu código faça referência a classe que contém
void moveCameraTo(LatLng latLng)
, ainda depende indiretamenteLatLng
. Mesmo que essa classe nunca seja diretamente instanciada.Eu não entendo o que você quer dizer. Se isso significa criar uma nova instância ou transformar classes de uma para outra, não vejo problema nisso.
Pensando nisso, sinto que o que estou dizendo também é suportado pelo design de API do próprio .NET. Historicamente, muitas classes do .NET seguiam a abordagem de sobrecargas com parâmetros diferentes e conversões simples. Mas isso foi antes da existência de métodos de extensão. As classes .NET mais modernas são mais leves em suas próprias APIs e, se houver algum método com sobrecarga de parâmetro, elas serão fornecidas como métodos de extensão. Exemplo mais antigo é o NLog ILogger, que possui dezenas de sobrecargas para gravar no log. Compare isso com o Microsoft.Extensions.Logging.ILogger mais recente que possui um total de 3 métodos (e apenas 1 se você contar o próprio log). Mas existem muitos ajudantes e várias parametrizações como métodos de extensão .
Penso que esta resposta mostra que algumas línguas teriam ferramentas para tornar o design mais agradável. Eu não sei muito sobre Java, então não tenho certeza se haveria algum equivalente. Mas mesmo usando métodos estáticos simples pode ser uma opção.
fonte
moveCameraTo(new LatLng(latitude, longitude));
em qualquer lugar do projeto, mas acho que é mais claro usar diretamente o moveCametaTo (latLng), é como um arquivo em java, você pode passar como uma string ou como uma classe PathNão tenho certeza de qual é o nome adequado para isso, se ele tiver um, mas é uma boa prática. Você expõe várias sobrecargas, permitindo que a classe de chamada determine qual conjunto de parâmetros deseja usar. Como você diz, outra classe pode não saber o que é um
LatLng
objeto, mas pode conhecer o seuLocation
.Ter um método chamando o outro também é fundamental, pois você não deseja código duplicado nesses métodos. Como você fez, escolha um método para ser o que faz o trabalho e faça com que os outros métodos o chamem (direta ou indiretamente)
fonte
Se você se importa em usar tipos de métodos, é apenas um recurso de sobrecarga de métodos que é bom.
Mas não há como eliminar a responsabilidade de saber o que é um LatLng . Porque você está inicializando
LatLng latLng = new LatLng(latitude, longitude)
. Isso é totalmente dependente deLatLng
. (Para entender por que a inicialização é um problema de dependência, você pode verificar a injeção de dependência ) A criação de um método sobrecarregado ajuda apenas os clientes que não se importamLatLng
. Se você quer dizer isso, também é bom, mas não acho que seja uma abordagem. São apenas muitos métodos de serviço para clientes.Portanto, existem duas opções para projetar sua arquitetura:
Fugo o mais possível, criando métodos que precisam de tipos primitivos como parâmetros (opção 1). Como se sua empresa muda muitas vezes e você precisa reproduzir parâmetros de método, é realmente difícil alterar e implementar todas as funções de quem chama.
Em vez disso, use interfaces (injeção de dependência). Se você acha que custa e leva mais tempo, use as classes e forneça seus métodos de extensão do mapeador (Opção 2).
fonte