Como e por que decidir entre os métodos de nomeação com os prefixos "get" e "find"

48

Eu sempre tenho problemas para descobrir se devo nomear um determinado método começando com getSomethingversus findSomething.

O problema reside na criação de auxiliares para APIs mal projetadas. Isso geralmente ocorre ao obter dados de um objeto, o que requer o objeto como parâmetro. Aqui está um exemplo simples:

public String getRevision(Item item) {
    service.load(item, "revision");
    // there is usually more work to do before getting the data..
    try {
        return item.get_revision();
    }
    catch(NotLoadedException exception) {
        log.error("Property named 'property_name' was not loaded", exception);
    }
    return null;
}

Como e por que decidir entre nomear esse método como getRevision()ou findRevision()?

knownasilya
fonte
2
o melhor auxiliar para uma API mal projetada é não mexer com nomes complicados, mas estabelecer uma Camada Anticorrupção : "Se seu aplicativo precisar lidar com um banco de dados ou outro aplicativo cujo modelo seja indesejável ou inaplicável ao modelo que você deseja em seu próprio aplicativo, use um AnticorruptionLayer para traduzir de / para esse modelo e o seu ".
gnat
1
Eu nunca ouvi falar desse conceito antes. Você tem melhores links com exemplos?
knownasilya
1
Pesquise na web, há muitas informações nela. Por exemplo, Anatomia de uma camada anticorrupção, parte 1 "é provável que ... você esteja inevitavelmente enfrentando a tarefa de interagir com o espaguete que já está lá. Entre na camada anticorrupção ..."
gnat

Respostas:

83

Uso Getquando sei que o tempo de recuperação será muito curto (como em uma pesquisa de uma tabela de hash ou btree).

Findimplica um processo de pesquisa ou algoritmo computacional que requer um período de tempo "mais longo" para ser executado (por algum valor arbitrário de mais tempo).

Robert Harvey
fonte
3
+1 Eu uso get ao recuperar e localizo quando o trabalho precisa ser feito para obter um get.
Jim
5
Levando em conta que o código muda (algumas partes se tornam otimizadas e os algoritmos mudam) e a alteração da API geralmente é impossível, não parece um critério correto. O que você faria se substituísse findpor um algoritmo de tabela de hash posteriormente?
meze 17/05
2
Eu também suporia, ao ler uma chamada, que "encontrar" pode ser chamado quando a descoberta não for bem-sucedida porque o critério de pesquisa não for bem-sucedido, enquanto espera-se que "get" seja bem-sucedido, a menos que haja algum problema incomum.
gnasher729
E se a função aceitar um parâmetro opcional para filtrar os resultados com base em alguma condição? Ambos gete findse aplica, dependendo de como é usado.
ESR
62

Eu diria que isso findpode falhar, mas getnão deveria.

coredump
fonte
25
Se você quer dizer que findpode retornar NULL enquanto getnunca retornará NULL, mas pode lançar (ou afirmar), eu concordo.
Sjoerd
1
Eu concordo totalmente com @Sjoerd sobre isso.
mhr
E se os find()retornos Optional<>? Nesse caso, findtambém é nullseguro.
TheCoder
42

Para citar uma conversa que geralmente tenho com meus filhos:

eu: Ei garoto! Vá me encontrar algumas baterias

kid: Mas onde eles estão?

eu: Foi por isso que eu disse para você encontrá- los. Se eu soubesse onde eles estavam, teria dito para você buscá- los. Ou você pode perguntar à sua mãe.

A mesma idéia vale:

  • use "get" para um método que retorna uma informação disponível mais barata (e provavelmente pode ser incorporada ou otimizada) ou para uma informação pertencente exclusivamente a esse objeto.

  • use "find" para um método que funciona para obter uma informação ou usa outros objetos para encontrá-la.

jimwise
fonte
16
Somente um programador teria essa conversa com seus filhos. "Você quer tirar o lixo?" "Não." "Você vai tirar o lixo?" "Sim."
Robert Harvey
@RobertHarvey Acho que estou tendo esse problema com as pessoas. Sempre que alguém tenta explicar alguma coisa ou faz uma pergunta, geralmente faço perguntas de volta e digo a elas para serem explícitas. Caso contrário, geralmente acabamos com um problema XY. Se não fizer isso, me sinto como um recurso de preenchimento automático ambulante. Você não sabe o que está pensando, não pode colocar em palavras, balbucia duas palavras e espera que eu faça todo o "pensamento" por você e o ajude com isso? Não, não está acontecendo :)
akinuri 02/11
3

Encontrar implica não ter o resultado, como ao executar uma consulta ao banco de dados com alguns parâmetros que podem mudar entre as chamadas. Get, por outro lado, implica que os resultados são conhecidos pelo método antecipadamente ou não serão alterados uma vez conhecidos, que não há parâmetros para a chamada.
Então, eu usaria, por exemplo, Customer findCustomerById (long customerId) e Customer getCustomer ()

jwenting
fonte
3

Eu aplico o seguinte padrão:

  • Foo GetFoo() não pode retornar nulo e sua complexidade é O (log (n)) ou menor
  • bool TryGetFoo(out Foo) pode retornar nulo e sua complexidade é O (log (n)) ou menor
  • Foo FindFoo() não pode retornar nulo e sua complexidade é maior que O (log (n))
  • bool TryFindFoo(out Foo) pode retornar nulo e sua complexidade é maior que O (log (n))

Dessa forma, o código é bem claro sobre a intenção e a complexidade que você pode esperar.

Normalmente, os Getters são para acesso direto à lista ou dicionário / conjunto.
Os Finders são pesquisa profunda, varredura completa da lista, etc ...

No seu caso:

public bool TryGetRevision( Item item, out String revision ) 
{
    service.load( item, "revision" );
    // there is usually more work to do before getting the data..
    try 
    {
        revision = item.get_revision();
        return true;
    }
    catch( NotLoadedException exception )
    {
        log.error( "Property named 'property_name' was not loaded", exception );
        revision = "";
        return false;
    }
}
Cyril Gandon
fonte
+1 para a try, curto e preciso
SpaceTrucker
2

geté apropriado em qualquer caso _ de fato, é geralmente assumido que, para obter algo, você precisa encontrá-lo primeiro. Então, se você não tiver certeza, use get.

Eu usaria findmétodos como findMinimum()ou findOptimal(), ou seja, onde existe algum algoritmo especial que calcula o valor de retorno, e não faz simplesmente uma solicitação ao DB, sistema de arquivos, servidor remoto, etc. para receber alguns dados.

superM
fonte
1
Bons pontos. Pessoalmente, provavelmente não usaria findcomo prefixo nos exemplos que você forneceu. Para tarefas computacionais, como as do seu exemplo, eu usaria calculateor compute.
knownasilya
2

Não use encontrar ou obter prefixos. Isso é uma violação do UniformAccessPrinciple, criado por bertrand meyer. Por que não criar um método como o seguinte:

public String revision(Item item)
giorgi dvalishvili
fonte
concordo plenamente com você, ótimo !!!!
Irakli Gabisonia
1

Geralmente usarei Getpara recuperar um objeto / valor e Findrecuperar sua localização (em uma matriz, por exemplo).

por ex:

object o = obj.GetItem( 'name');

integer i = somearray.Find( 'name');
GrandmasterB
fonte
0

Para mim, findimplica que pode haver mais de um resultado presente. getimplica apenas um.

Karl Bielefeldt
fonte
8
Parece que tem essa sensação, mas não tenho certeza se concordo completamente. Pense nisso desta maneira: getCatvs findCatvs getCatsvs findCats. O find..ainda representa objetos singulares sendo retornados. O plural deve ser adicionado ao substantivo, na minha opinião.
procurando