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:
- Preferring property access over accessor methods: Is accessing the fields of a struct a good julia-style?