90

I always have trouble figuring out if I should name a certain method starting with getSomething versus findSomething.

The problem resides in creating helpers for poorly designed APIs. This usually occurs when getting data from an object, which requires the object as a parameter. Here is a simple example:

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;
}

How and why to decide between naming this method as getRevision() or findRevision()?

Deduplicator
  • 8,591
  • 5
  • 31
  • 50
knownasilya
  • 3,074
  • 3
  • 17
  • 16
  • 4
    the best _helper_ for a poorly designed API is not to mess with tricky naming but establish an [Anticorruption Layer](http://c2.com/cgi/wiki?AnticorruptionLayer): "If your application needs to deal with a database or another application whose model is undesirable or inapplicable to the model you want within your own application, use an AnticorruptionLayer to translate to/from that model and yours." – gnat Jan 09 '13 at 22:00
  • 1
    I have never heard of this concept before. Do you have any better links with examples? – knownasilya Jan 10 '13 at 00:11
  • 2
    Search the web, there's quite a lot of info on it. Eg, [Anatomy of an Anti-Corruption Layer, Part 1](http://moffdub.wordpress.com/2008/09/21/anatomy-of-an-anti-corruption-layer-part-1/) _"it is likely that... you are inevitably faced with the task of interacting with the spaghetti that is already there. Enter the Anti-Corruption Layer..."_ – gnat Jan 10 '13 at 05:02

10 Answers10

121

I use Get when I know the retrieval time will be very short (as in a lookup from a hash table or btree).

Find implies a search process or computational algorithm that requires a "longer" period of time to execute (for some arbitrary value of longer).

Robert Harvey
  • 198,589
  • 55
  • 464
  • 673
  • 4
    +1 I use get when retrieving and find when work has to be done to do a get. – Jim Jan 10 '13 at 03:51
  • 8
    Taking in account that code changes (some parts become optimized and algorithms changes) and changing API is often impossible it doesn't look like a right criteria. What would you do if you replaced `find` with a hash-table algorithm later? – meze May 17 '13 at 13:34
  • 9
    I would also assume, when reading a call, that "find" may be called when the find doesn't succeed because the search criterion doesn't succeed, while "get" is expected to succeed unless there is some unusual problem. – gnasher729 Jul 30 '17 at 17:41
  • What if the function accepts an optional parameter to filter the results based off some condition? Both `get` and `find` would apply depending on how it's used. – ESR Aug 28 '18 at 10:54
98

I would say that find may fail but get shouldn't.

coredump
  • 5,895
  • 1
  • 21
  • 28
  • 39
    If you mean that `find` can return NULL while `get` will never return NULL but might throw (or assert), I agree. – Sjoerd Jan 10 '13 at 00:33
  • 2
    I totally agree with @Sjoerd on this. – mhr Jan 22 '13 at 15:07
  • And what if the `find()` returns `Optional<>`? In that case `find` is also `null` safe. – The Coder Sep 08 '19 at 09:22
  • 3
    @TheCoder I think it's not about null safety. It's about your intention: When you get you are sure what you get exists and if it doesn't it's an exceptional case. Whereas when you find something, you're not sure if it exists or not so not finding it is totally expected. – disklosr Mar 12 '20 at 09:19
66

To quote a conversation I often have with my kids:

me: Hey kid! Go find me some batteries

kid: But where are they?

me: That's why I told you to go find them. If I knew where they were, I would have told you to go get them. Or you could ask your mother.

The same idea holds:

  • use "get" for a method which returns a cheaply available piece of information (and can probably be inlined or otherwise optimized away), or for a piece of information uniquely owned by this object.

  • use "find" for a method which does work to get a piece of information, or uses other objects to find it.

jimwise
  • 7,433
  • 1
  • 30
  • 32
  • 25
    Only a programmer would have this conversation with their kids. "Do you want to take out the trash?" "No." "Will you take out the trash?" "Yes." – Robert Harvey May 19 '16 at 14:51
  • 3
    @RobertHarvey I think I'm having this problem with people. Whenever someone tries to explain something, or asks a question, I usually ask questions back and tell them to be explicit about it. Otherwise we usually end up with a XY problem. If I don't do that, I feel like a walking autocomplete feature. You don't know what's on your mind, you can't put it into words, you babble couple words and expect me to do all the "thinking" for you and help you with that? Nope, not happening :) – akinuri Nov 02 '19 at 10:56
  • 3
    always use `->askMom()` when in doubt. – Kamafeather Sep 16 '21 at 11:07
12

I apply the following pattern:

  • Foo GetFoo() cannot return null and its complexity is at most O(log(n))
  • bool TryGetFoo(out Foo) can return null and its complexity is at most O(log(n))
  • Foo FindFoo() cannot return null and its complexity is at least O(log(n))
  • bool TryFindFoo(out Foo) can return null and its complexity is at least O(log(n))

That way the code is pretty clear on the intent and on the complexity you can expect.

Typically, the Getters are for direct list or dictionary/set access.
The Finders are deep search, full scan of list, etc...

In your case:

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
  • 1,296
  • 1
  • 11
  • 17
7

I have mostly seen (and like to use) this convention:

  • getFoo(<id>) - the caller expects that foo exists. If not, getFoo(0). throws. Mostly, it has some kind of ID as param.

    • Example: getProductByCodeName("BTTF")
  • findFoos(<criteria>) - the caller expects that foo may not exist, in which case the methods returns null. Parameters are typically some "foreign keys" - ids to other objects, or enum values.

    • Example: findCarModelsMadeBy(CarMaker.FORD)
  • listFoos(<ids>) - provides a list of foos, or empty list if none are present. Typically, gives items that are already prepared (eagerly loaded), and may return an Iterator, Stream, Sequence, etc.

    • Example: invoice.listItems()
  • searchFoos(<criteria>) or queryFoos() - does some kind of active search by given values. May also search by vague criteria like patterns, search queries etc.

    • Example: searchBooks(QueryBuilder.withTopicKeywords("japan middle age anjin"))
  • lookupFoo(<uri-like-name>) - typically calls a remote service to get some information by an ID. Comes from the conventions of JavaEE. The ID is usually in some known format, e.g. URI.

    • Example: bankInfoService.lookupBankInfo("NL12")
  • provideFoos() - typical for some kind of repositories which do not change too often and is not supposed to be called too often, like, a provider of implementations of some interface, called during application boot.

    • Example: ProductConfigProvider.provideProductConfigs()
  • loadFoos() - inditaces that loading may involve costly I/O (disk access, database roundtrip, web service call).

    • Example: s3archive.loadFilesFromDay(LocalDate.now())
  • try*Foos() - explicitly indicates that it will handle errors / exceptions, either by returning null, empty list, or a predefined wrapping exception. Often used as a util method to wrap a method unconveniently throwing if it does not find.

  • deriveFoos() or computeFoos() - indicates that Foos are computed in a non-constant time. For instance, converted from a collection on-the-fly at the call-time.

  • buildFoo(...) - the method simply assembles Foo from the given building blocks. Especially useful for testing.

  • formatFoo(...) - whenever you create a String from the parameters.

  • translateFoo(Bar) - when there's a 1:1 relation between Foos and Bars, and this method finds the counterpart.

Ondra Žižka
  • 267
  • 3
  • 6
6

Find implies not having the result, like when executing a database query with some parameters that may change between calls. Get, on the other hand, implies the results are known to the method beforehand or won't change once known, that there are no parameters to the call.
So, I'd use for example Customer findCustomerById(long customerId) and Customer getCustomer()

jwenting
  • 9,783
  • 3
  • 28
  • 45
5

Do not use find or get prefixes. This is a violation of UniformAccessPrinciple coined by bertrand meyer. Why not create a method like the following:

public String revision(Item item)
Desolate Planet
  • 6,038
  • 3
  • 29
  • 38
  • i completely agree with u, great!!!! – Irakli Gabisonia Apr 24 '18 at 11:59
  • 7
    methods do something. The method name should be a verb. "revision" is a horrible method name in this context. – Welcor May 12 '20 at 17:04
  • I have lately seen the recommendation to name pure methods with nouns and impure methods with verbs. See the book [Elements of Clojure](https://www.amazon.com/Elements-Clojure-Zachary-Tellman/dp/0359360580) with its nice chapter on naming and also this other [blog](https://stuartsierra.com/2016/01/09/how-to-name-clojure-functions) on naming functions – beluchin Oct 04 '20 at 13:07
  • In Swift, you can have properties that are set using the assignment operator. So if revision were an integer you could write x = item.revision. Or item. revision += 1. – gnasher729 Sep 22 '22 at 22:10
2

To me, find implies there can possibly be more than one result present. get implies only one.

Karl Bielefeldt
  • 146,727
  • 38
  • 279
  • 479
  • 10
    Seems like it has that feel, but I'm not sure I completely agree. Think of it this way: `getCat` vs `findCat` vs `getCats` vs `findCats`. The `find..` still represents singular objects being returned. The plural should be added to the noun, in my opinion. – knownasilya Jan 09 '13 at 21:44
2

get is appropriate in any case _ in fact it is often assumed that in order to get something you need to find that first. So if you're not sure, use get.

I would use find for methods like findMinimum() or findOptimal(), i.e. where there is some special algorithm which calculates the return value, and doesn't simply make a request to the DB, file system, remote server, etc. to receive some data.

superM
  • 7,363
  • 4
  • 29
  • 38
  • 1
    Good points. Personally I'd probably not use `find` as a prefix in the examples you provided. For computational tasks, like the ones in your example, I would use `calculate` or `compute`. – knownasilya Jan 09 '13 at 21:52
1

I will generally use Get to retrieve an object/value, and Find to retrieve its location (in an array, for example).

for ex:

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

integer i = somearray.Find( 'name');
GrandmasterB
  • 37,990
  • 7
  • 78
  • 131