0

In my app, I have many Java model objects (I believe you'd normally refer to them as POJOs?), and I have a central Database singleton class (DatabaseHelper) that extends SQLiteOpenHelper.

My problem: I am unsure where to actually put stuff. Right now I've been putting everything into the DatabaseHelper class and it's getting huge.

This leads me to rethink my approach and that maybe I need to be separating things out.

Should I be putting the database CRUD operations in a dedicated class that acts as a bridge between the model objects and the DatabaseHelper? Or should I be coupling the CRUD methods in the model objects themselves? What about where to store things like the table and column names?

What's considered accepted practice here?

user6419910
  • 155
  • 2
  • 12
  • This is off topic for this site, as there is no technically correct answer- its all a matter of opinion. – Gabe Sechan Jun 08 '16 at 23:55
  • @GabeSechan Tell that to the countless people who have told me my approach is wrong in the past! I'd at least like to know what's considered _bad_ practice, if good practice is up for debate. – user6419910 Jun 09 '16 at 00:01
  • You should have a separate, interface based data access layer. Implementation can change without affecting clients that way. If you learn Spring Boot you won't even have to write code beyond annotated interfaces to create one. – duffymo Jun 09 '16 at 00:03
  • Sorry I don't really know what that means. Interface based data access layer meaning what exactly? Something between the model objects and the database helper? – user6419910 Jun 09 '16 at 00:06

1 Answers1

2

If you have plenty of tables in your database, which I presume you do since you're asking the question, I'd suggest you put all of the CRUD logic into separate classes called Repositories (e.g. ModelRepository).

These classes should have all the things necessary and they'd best be implemented via the interface that has the C R U and D methods, so that if the implementation needs to undergo some changes, everything keeps on working because of the usage of interface. So for every model you need 2 classes, ModelRepositoryInterface which can even extend a common interface with these 4 operations and each can have some additional methods specific to the class itself; and the class that implements the interface, say ModelRepositoryImplementation.

Some basic example, let's assume your Model is called Course:

public class Course {
    //your class logic, constructor, getters, setters, etc.
}

This would be it's repository interface:

public interface CourseRepositoryInterface {
     void addCourse(Course course);
     void deleteCourse(Course course);
     void updateCourse(Course course);

     List<Course> getAllCourses();
}

Something like that, of course it can have more/less methods varying from your needs.

Finally you need a class that implements that interface like:

    public class CourseRepoWithMySqlDatabase implements CourseRepositoryInterface {
     void addCourse(Course course) { //TODO: Implement it }
     void deleteCourse(Course course) { //TODO: Implement it }
     void updateCourse(Course course) { //TODO: Implement it }

     List<Course> getAllCourses() { //TODO: Implement it }
    }

In this class you would implement the methods to do what they need to do with, for example, MySql database. In case you ever needed to switch from MySql to, let's say, another type of database or a no database implementation, you'd just use another class to implement the interface, and pass that where the interface parameter is required.

Pay attention: this is very important. You always need to require the interface in the place where you plan to use its methods.

Vucko
  • 7,371
  • 2
  • 27
  • 45
  • Why would I need to define a `ModelRepositoryInterface` necessarily? Confused by that part – user6419910 Jun 09 '16 at 00:05
  • I've re-read this answer at least 20 times and I am still unsure; can you make a basic basic basic example of what you're referring to? Not asking you to implement all the logic, just the basic layouts showing where everything would go. – user6419910 Jun 09 '16 at 00:18
  • You do not **have** to use interfaces, it's just recommended. You need to gain a deeper insight into what interfaces are, and why to use them. Refer to [this](http://stackoverflow.com/questions/240152/why-would-i-want-to-use-interfaces) question. – Vucko Jun 09 '16 at 11:42
  • Is it necessary to create a separate Crud interface for every single data model? What if I make a blank interface called `CrudModel`, have all my models implement it, and then in another interface called `ModelRepositoryInterface`, define methods like `long addModel(CrudModel model);`, `CrudModel getModel(long id);`, `long updateModel(CrudModel model);`, `void deleteModel(CrudModel model);`, etc. Or is this a bad idea because each model is actually different when it comes to (for example) manipulating the correct model object in the get/update methods? – user6419910 Jun 09 '16 at 12:22
  • For example http://pastebin.com/ddkTYkvX -- would doing it this way be considered bad practice? – user6419910 Jun 09 '16 at 12:29
  • That is basically a good idea in a language where the types are not strict as in Java, for example php. I have that structure in my Laravel project, an interface which has all 4 basic CRUD operations, and it takes any type as a parameter. But I'm positive that this `Profile profile = (Profile) model;` is not smart to do in Java. Casting may throw an Exception if it's the wrong type. – Vucko Jun 09 '16 at 12:47
  • I mean technically couldn't I check first `if (model instanceof Profile){` and then do the rest of the function, otherwise do nothing? Anyways I mention all this because earlier you had said `ModelRepositoryInterface which can even extend a common interface with these 4 operations and each can have some additional methods specific to the class itself` -- is this not what you had in mind, or were you thinking of some different implementation in Java? – user6419910 Jun 09 '16 at 13:14
  • Also: Would you recommend defining things like table names, columns, etc, in the model object or the repo class? – user6419910 Jun 09 '16 at 13:21
  • I'm not quite that experienced as to give you the best advice for that question. Research a bit on your own, or try to do it whichever way feels natural to you. :) – Vucko Jun 09 '16 at 13:28