0

I have 3 classes in my application:

1. Runner / Main (calls the service class)

2. Service class (carries out buisness logic)

3. Repository class (called by service to make DB queries)

I am unsure of the best way to implement the variables in the service class. Which is the best way of the 2 below and why?

E.g. should I have instance variables:

public class DogService{

    List<Dogs> dogList= new ArrayList<Dog>(); //instance var

    public DogService(){}

    public List<dogs> getAllDogs(){

    dogList=dogRepository.getAll();

    return dogList;

        }

    }

or local variables in method:

public class DogService{

       public DogService(){}

        public List<dogs> getAllDogs(){

       List<Dogs> dogList= new ArrayList<Dog>(); //local var to method

        dogList=dogRepository.getAll();

        return dogList;

            }

        }

Example of using the service class:

public class Runner {

    List<Dogs> listOfAllDogs = new ArrayList<Dog>();

    DogService dogService = new DogService();

    public static void main(String[] args) {

    listOfAllDogs = dogService.getAllDogs();

}
5
  • 1
    It does not make a difference here. Whenever you call getAllDogs, the variable is overwritten anyways. Use a local variable until there's a reason against it. Commented Mar 11, 2016 at 0:22
  • Ok, so why should I use a local var then? In what case would I use an instance var? Commented Mar 11, 2016 at 0:24
  • 2
    Honestly, this question is moot because the service layer is not providing any additional benefit. Better to just ask your repository for the list of dogs unless you have something the service layer should be doing with that list? Also, please format code cleanly! It helps! Commented Mar 11, 2016 at 0:25
  • I do have other methods that make use of the data, I was just showing this as a simple example. Can you reccomend which var type to use? Commented Mar 11, 2016 at 0:26
  • Depending on the functionality of the program, it might be good to implement the dogList in singleton pattern. Commented Mar 11, 2016 at 0:28

3 Answers 3

1

This is entirely opinion, but you're misapprehending what a service layer is typically for, which is:

public class DogService{
  Repository repository;
  public DogService(Repository repo){
    this.repository = repo;
  }

  public List<dogs> getAllDogs(){
    return this.repository.getAll();
  }
}

The service has the responsibility of knowing where to look for dogs. It doesn't get involved in trying to remember specific dogs or look them up: it delegates that responsibility to the underlying repository.

Which, to answer your question, means neither the method nor the instance should remember the list of dogs. If another method, such as getAllDogNames needs to do something funky, it might need an instance variable:

public List<String> getAllDogNames(String prefix){
  List<Dog> dogs = this.getAllDogs();
  List<String> names = new ArrayList<String>();
  for (dog : dogs) {
    names.add(prefix + dog.getName()); //Or whatever
  }
}

But that should be deferred to the appropriate wrapper.

Sign up to request clarification or add additional context in comments.

11 Comments

This is an interesting solution. I can still keep the list in memory throughout my runner class when using this? I.e. to make future calls such as: listOfAllDogs.get(1) etc?
Note that unless you save the list as a member field of the instance, it will not 'stay in memory'... unless the underlying repository does that. If the repo is something like Hibernate, it handles that for you and you don't need to get involved or worry about it. That is generally considered the responsibility of such ORM libraries: handle the pain of keeping authoritative representations of db objects in memory.
I think I know what you mean, however this is my first hibernate project so bear with me! is the example that I gave of my runner class not appropriate in order to be able to delete some dog entities from the list, thereby deleting them from the db, later in the class?
this.repository.delete(id) is what you want. See here.
Ok thanks, so does this essentially carry out the same functionality as deleting from then re-saving the list?
|
1

If the dogList will not change, then having it as a field will allow you to potentially cache it. Probably not a good idea for dogs which may have puppies or die, but if it was a static list or stuff, it would have some uses.

e.g.

 if (dogList == null) {
    dogList= new ArrayList<Dog>(); 
    dogList=dogRepository.getAll();
}

return dogList;

4 Comments

sorry I am not sure what you mean? Thanks
Even if the dogList can be cached, that should probably be handled by the Repository layer instead of the Service.
This sounds like a bad idea as there may be some change in the database (possibly not via the program) that will not be updated to the client the next time you call findAll
@Thilo I agree if we are just talking about some DAO, but I read the question as being quite general
1

In the first case, you create a new ArrayList with your instance, and you keep a reference to the list of dogs after you have left the method. You are wasting memory.

Also, it is a field in your class that you are not using, so it clutters your code with useless lines that you could remove.

It can also be a source of bugs. This variable is declared, and has a name that suggests its purpose. At a later time, another developer could try to use it for something else, and, depending on whether the method was called prior or not, it would work or crash.

In the second case, the variable is not useful, as you can return the result of the getter immediately. But the compiler will take care of that for you, so you don't need to worry about it.

8 Comments

Ok so I should use local vars then? I am confused over the differences in the 2, thanks
In this case, yes, unless you are memoizing like Scary Wombat is suggesting. Having an instance field will keep the list in memory even if you are not using it anymore.
Ok, I will want to keep the list in memory however though throughout my runner class in order to make calls to it, such as .get() etc?
I'm not sure 'wasting memory' is really a concern here. Premature optimization is the devil.
@NathanielFord it is not just wasting memory. You are sitting with a reference that you are not using, you have a field you are not using, overall it is cluttering. I added a paragraph to express that.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.