Getter function naming: Consider avoiding nouns

I am (heavily) considering judging using nouns for (exported) getter accessor functions bad practice.

I’ve found myself writing structs with getter accessors named equal to the names of the fields they are getting, i.e. using nouns (singular and plural form), e.g.:

module Foos

export Foo,
    colours,
    shape

struct Foo
    colours::Vector{String}
    shape::String
end

colours(f::Foo) = f.colours
shape(f::Foo) = f.shape

end

since it seems very nice functional-style at first (e.g. enabling code like if shape(foo) == "round" # ....

But then I often also would like to write code that uses that same nouns as a (local) variable names, e.g.:

using Foos
using Test

@testset "shape accessor" begin
    f = Foo(["blue", "green"], "round")
    shape = shape(f) # Yuck!
    @test shape == "round"
end

which yields the, slightly hard to understand error:

     Testing Running tests...
shape accessor: Error During Test at test/foo_tests.jl:6
  Got exception outside of a @test
  UndefVarError: `shape` not defined

The inverse calling order

using Foos
using Test

@testset "shape accessor" begin
    shape = "round"
    f = Foo(["blue", "green"], shape)
    actual_shape = shape(f) # Yuck!
    @test actual_shape == shape
end

(of course / thankfully) yields a more understandable error:

shape accessor: Error During Test at test/foo_tests.jl:7
  Got exception outside of a @test
  MethodError: objects of type String are not callable

Executing the equivalent in the REPL yields:

julia> using Main.Foos

julia> f = Foo(["blue", "green"], "round")
Foo(["blue", "green"], "round")

julia> shape = shape(f)
ERROR: cannot assign a value to imported variable Foos.shape from module Main
Stacktrace:
 [1] top-level scope
   @ REPL[9]:1

If there is consensus on this, I am pondering whether this might worthy of a note in the style guide…? (even though there are surely lots of functions in Base etc. using (common) nouns for method names…)

Related discussion:

2 Likes

Hi @stemann,

I am also struggling with this dilemma since long, but I am tending to use nouns for the getters, i.e., shape(a) instead of getshape(a). Then I use shape_a = shape(a) for the local variables or e.g. myshape = shape(a) if variable a has a much longer name. In any, case I also see the point for preferring getshape.

2 Likes

I prefer to use getter methods instead of property access. Often, i define the methods with the same name as the property but with a of at the end, like:

shape = shapeof(thing)
color = colorof(thing)
6 Likes