Doubt about the responsibility of a get()

Asked

Viewed 337 times

14

It is acceptable to have a method getter that you receive a parameter to be able to have a return variation? Example:

getAllNome("M"); <- retorna tudo que for masculino.
getAllNome("F"); <- retorna tudo que for feminino.
getAllNome(); <- retorna todos os nome, não importa o sexo.

The responsibility of getter is return values, therefore using parameters for it can cause confusion?


Observing: Many places I studied about getters and setters they say that it should not receive argument. Why not? It is not simpler a getter who gets arguments to have different returns? When I say "acceptable" is if I’m making a mistake. Or running from some pattern I don’t know?

GET AND SET

Get

We name an access method with get every time this method is check some field or attribute of a class.

As this method will check a value, it will always have a return like String, int, float, etc. But you won’t have any arguments.

  • 2

    The question is very interesting. The answer would be very broad. C#, for example, does not allow argument in property, but this because the language is better built than Java, which allows because the get() in general is any method of a class. Therefore, correct is not. If some languages allow, the problem is the construction of these languages.

  • Regardless of the language, I think one should ask: does my class need to provide these accessors? Is it a good design for my class that they are provided? The answers to this will depend on the situation.

3 answers

10


I don’t know if this can be considered subjective or not, but there is evidence that the number of bugs in a program is proportional to the amount of lines of code in that program. Regardless of language. More expressive languages/libraries (i.e. that do a lot with little code) tend to produce shorter code, and therefore fewer bugs.

And what does this have to do with the question? Simple: if you pass optional parameters to make your code more concise, then do it! Don’t worry too much about the "purity" of the code: good practices are good not because "someone said they are", but because they solve/avoid a number of problems. But if you don’t see any problem in an approach, there’s no reason to avoid it.

I don’t like getters and setters. I don’t like private attributes. But depending on the type of project and team, they can be necessary things (e.g., numerous teams composed of inexperienced programmers, who are more likely to make mistakes). In this case, more important than following the X or Y standard, it is important to follow a pattern consistent.

For example, jQuery has several functions that function as properties: html, text, attr, prop, css, data... They all work the same way: without arguments, they are one getter; with one argument, are a Setter (additional arguments may exist at the beginning). The name is short, no need to keep typing the prefix (getText vs. setText)... And most importantly, the same convention is used throughout the library, so no surprise!

In Java, there is a very strict convention about the names of the methods and what they should do. Evading this convention is problematic, as it forces those unfamiliar with your code to learn/decorate a new convention. However, getAllNome does not follow - to my knowledge - any pre-established convention, so that you can adopt yours. And even if it did, we need to weigh the pros and cons, as discussed earlier.

Finally, consider transferring this responsibility to another class in order to make its use more consistent. Java unfortunately has no first class functions (nor Extension methods), then it is necessary to do this through an auxiliary class. For example, if your function returns a List, create the interface/class:

interface ListaFiltravel<T> extends List<T> {
    public ListaFiltravel<T> filtrar(String variacao);
    public ListaFiltravel<T> filtrar(String variacao, boolean inPlace);
}

class ArrayListFiltravel<T> extends ArrayList<T> implements ListaFiltravel<T> {
    public ListaFiltravel<T> filtrar(String variacao) {
        return filtrar(variacao, false);
    }

    public ListaFiltravel<T> filtrar(String variacao, boolean inPlace) {
        // Código para filtrar
        // Retorne a própria lista filtrada (inPlace == true) ou uma outra lista
    }
}

And call your method as follows:

meuObjeto.getAllNome().filtrar("M")

In this way, responsibilities are very separate. (But again: does this produce shorter codes? If this is something you only have to do once, I remain in favor of leaving the purity aside and putting the functionality on itself getter. But if it can be repurposed in various parts of your system, then that approach is better.)

9

In my opinion there is confusion about the concept of getters and setters as being access methods, whose goal is to ensure encapsulation protecting the attributes of a class, and the proposed method example getAllNome("M"); that although it has a prefix get does not have the sole responsibility of exposing a property, thus escaping from the definition of what the supporting methods are, as would be, for example, the case of a method getNome().

If we wish to recover the attribute nome of a set of a kind, say Pessoa, as is the case with getAllNome("M"); this method should not participate in the class Pessoa, but of another class with this responsibility, which in turn would only access the names by the get, or access method, getNome() as explained by @mgibsonbr. Still if it is necessary for the method to participate in the class, it could not be considered an access method.

Finally, although its need can be discussed, when we are talking about access methods, a get will never get arguments and a set will receive one, and only one, argument, of the same type that is returned by the getter.

5

Speaking of object orientation, there are reasons to use getters and setters.

Say a Product class that contains the property price. That price is discounted, and every time we get that amount, we want you to apply the discount. In this case, the private property guarantees that the price will not be obtained directly without the discount and we implement no get value reduction.

In your case, I imagine you are dealing with a class person. A (individual) person only has one sex. So get will return this individual value. (char)

In your suggested case, get acts as a custom query. It would be an object method that contains several people and will return an array of Person objects that meet the parameters of your query. There are design standards for implementing this type of logic. The Repository project pattern predicts exactly this type of custom query: you implement a getAllPeople(), which returns an array of all obejtos Pessoa, a getAllSexo(sex char), which returned an array of Person objects with this sex. Then, of each of these Person objects you could call the function getNome() or another to get data from each one.

I advise to study Design Patterns, the book Project Standards: Reusable Solutions, and Agile Principles, Patterns and Practices in C#. These are the classic patterns, but there are many others, like Repository, that are not in these books. The patterns help a lot to understand the application of Object Orientation.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.