-1

I have a submission to do for software development and my professor urges us to not use return statements, that return object references.

The task is about a to-do list application, and I wonder if there is any easy way to not implement the todo-list as a object with such writable return references. I managed to do this but since I use JDBC its just writing my tasks to the DB and the re-loading it into my list from the DB, which for me sounds like the same as just writing it directly in the list.

I have the lecture again next Thursday and will ask then, but maybe some of you has a clue. In my opinion its completely justifiable to return a reference to the list, especially since the application changes a lot in scenes and windows.

Edit: Code attached.

Since I have not yet implemented it here is how I would do it.


public class TaskList {
    private static ArrayList<Task> taskList = new ArrayList<>();

    public  ArrayList<Task> getTaskList() {
        return taskList;
    }
}

Then I can get my TaskList in the different scenes like the calendar or overview by simply using the getter and modify the list.

Currently I have this code like that:

public class Calendar {


    private ArrayList<Task> usersTasks = new ArrayList<>();
    
    //Bunch of methods to draw my calendar

    private createTask(){

            Task createdTask = new Task(title,content,prio,color,duedate,today);

            //write task in mySQL db
            DatabaseHandler databaseHandler = new DatabaseHandler();
            databaseHandler.createTask(createdTask,user);
    }

    private getTasks(){

            usersTasks.clear();
            //new dbHandler to fetch as ResultSet and write in ArrayList userTasks

    }
}

I hope the snippets are explaining since I left a lot out. The example is for my calendar view.

So currently, when I create a task, I would write it in the DB, then clear my ArrayList and then re-fetch it.

Hannes
  • 93
  • 5
  • 2
    attach some code please – SoT Jun 22 '20 at 09:42
  • 2
    Java is an OOP language, so from my point of view you cannot _not use return statements, that return object references_ unless you only use primitives. Maybe you can add additional details or clarification to your question. – Glains Jun 22 '20 at 09:43
  • 4
    You need to explain exactly (with code) which references the proffessor was talking about. Is it about not returning references to internal structures? If so, use protective copies. Is it about modifiability? If so, use references made with `Collections.unmodifiableList` etc. But you need to explain their admonition better. – RealSkeptic Jun 22 '20 at 09:45
  • Maybe you should return [immutable objects](https://stackoverflow.com/questions/3162665/immutable-class) when you get the data from the database? – Nowhere Man Jun 22 '20 at 09:52
  • 1
    Returning an immutable object, or a copy of an object, is considered a good practice to ensure encapsulation isn't violated when you are exposing, for example, a List through a getter method. Obviously, that copy will still be returned *as a reference*. There are many cases where returning the original, mutable object through a getter method is perfectly fine, though, and I would say that your professor is a bit overly dogmatic. –  Jun 22 '20 at 10:13
  • Added code. We have the evaluation-table our prof uses, and at the aspect clean code, he writes "no getters return writable references to members" – Hannes Jun 22 '20 at 10:31
  • @Hannes You might want to look at https://stackoverflow.com/questions/33529415/is-it-a-bad-practice-to-add-elements-to-list-using-getter-method-in-java – Progman Jun 22 '20 at 10:33

1 Answers1

1

no getters return writable references to members

Your professor is right.

Suppose you have a class SoccerTeam with a List<Person> members field with the team members in it, and a getter to get the team.

class SoccerTeam {
    private List<Person> members;

    public List<Person> getMembers() {
        return members;
    }
}

Now a caller wants so do something with all of the members, except the goalkeeper:

SoccerTeam team = ... // Get soccer team from somewhere
List<Person> members = team.getMembers();
members.remove(0); // Example where we agree that the goalkeeper is always element #0
doSomethingWithMembers(members);

Now the team lost its goalkeeper! A team with its members should not expose a mutable reference to the lists of members itself. We want to be able to provide a list with team members, without allowing some caller to modify the list of team members.

However,

not use return statements, that return object references

is a little bit poorly worded, since this would allow you to use primitives (or void) only.


  • A fix would be to return a fresh list with the members: a defensive copy:

    public List<Person> getPersons() {
        return new ArrayList<>(this.members);
    }
    

    Calling remove() on the list would not affect the members field of our team instance.

  • Alternatively, you could make an immutable (or more accurately: unmodifiable) list of members during construction of the team. Then the getter could just return the list, because it is guaranteed that the caller cannot modify the list. Trying to do so would result in an UnsupportedOperationException to be thrown.

    public SoccerTeam(List<Person> members) {
        this.members = Collections.unmodifiableList(members);
    }
    
    public List<Person> getMembers() {
        return this.members;
    }
    
  • A third option would be to return a Stream instead of a list. A Stream does not provide a way to modify the underlying source itself. (The elements contained in the source can, however.)

    public Stream<Person> members() {
        return this.members.stream();
    }
    

    This will postpone actual traversal until a terminal operation is called on the stream.

MC Emperor
  • 22,334
  • 15
  • 80
  • 130
  • Your second solution is flawed, in that it doesn't allow the class itself to modify its team. It should probably have its own modifiable list, and wrap in the getter like the first solution. – RealSkeptic Jun 22 '20 at 14:20
  • @RealSkeptic Not necessarily "flawed", it was more or less an example of moving the creation of an immutable list to the constructor. But I admit that the very nature of a football team may not be the best example of something having an unmodifiable list as a field. – MC Emperor Jun 22 '20 at 15:19
  • Thank you for your time :) Helped a lot – Hannes Jun 22 '20 at 15:46