I'm making my first Java project, and trying to learn OO programming as well as MVC.
Say that you have a class "Products" and a number of objects of that class. Your GUI want to display a list of these objects, possibly also with some filter etc. I can think of several ways to do this:
The GUI could simply read all objects and list them.
Make a globally available method that returns all the objects. This could be placed in some kind of repository for global functions.
Make a static method inside the Products class that returns a list of all objects.
What is the proper way to do this, and where would you put the code?
As you want to learn MVC, you already know that in order to implement MVC pattern you need three layers: Model, View, Controller. In your case, you have the two of the layers, Model (Product) and View (ProductGUI, assuming this is a different class). What you are missing is the Controller.
In order to leverage from MVC, I suggest you to implement the Controller layer with an API approach so that you have an interface, ProductController; and a class implementing the interface, ProductControllerImpl. This interface-class separation lets you to switch between alternative implementations and also allows Mocking your services for user interface testing (See Wikipedia for further explanations).
Let me also try to explain this with a simple example.
Assume you create the interface for your Controller layer as such:
public interface ProductController {
public List<Product> listProducts();
public List<Product> listProducts(NameFilter nameFilter);
}
Then you can create a Mock implementation for this interface for testing purposes as such:
public class ProductControllerImplMock implements ProductController {
List<Product> products;
public ProductControllerImplMock() {
products = new ArrayList<Product>();
}
public List<Product> listProducts() {
products.add(new Product("A"));
products.add(new Product("B"));
return products;
}
public List<Product> listProducts(NameFilter nameFilter) {
products.add(new Product("A"));
return products;
}
}
Note: Assumining you have a NameFilter class that aims at filtering Product's by name.
If you decide to use a database to store your products, then you can implement ProductControllerDatabaseImpl which will query your database and retrieve entities for listing and which will most probably introduce WHERE clause to the query for listProducts(NameFilter) method.
Actually, things are never this simple. What is shown in this example will be referred to as DAO (Data Access Object) in more complex applications and there will be a separate layer, generally called Business layer instead of Controller layer, which will implement the actual logic for the application. But I tried to keep the example as simple as possible for simplicity.
IMHO, the OOP approach would be to expose the collection via a basic accessor method in the Products class. If you're concerned about the collection being modified, either wrap the collection with one of the unmodifiable collections made available by the Collections class, or return a copy.
Edit -
And concerning the GUI, be aware of concurrency-related issues.
Example -
final class Products
{
private final List<Foo> listOfFoo;
Products(List<Foo> listOfFoo)
{
this.listOfFoo = listOfFoo;
}
public List<Foo> getListOfFoo()
{
if(listOfFoo.isEmpty())
{
return Collections.emptyList();
}
return Collections.unmodifiableList(listOfFoo);
}
}
Related
I'm practicing with MVC, DAO and other design patterns for a Java project.
Let's say I have a PageController that interacts with a Student class Model.
public class Student {
private int id;
private String name;
public Student(int id, String name) {
this.id = id;
this.name = name;
}
//Getters and setters blabla
}
and then I have obviously a StudentDAO interface and StudentDAOImpl that executes SQL queries and stuff.
Let's say PageController needs to retrieve a list of all Students (to list them on its page), obviously I have an SQL query to retrieve a List of Students, implemented with a Java method in StudentDAOImpl.
Where should I instantiate studentDao (instance of StudentDAOImpl) though?
Can I simply create a static method in Student that retrieves all the Students? This static method would simply instantiate studentDAO and execute its getAllStudents method to retrieve all the students.
Or I can simply instantiate studentDao in PageController and do all the stuff from there?
In the main case, I think you could use this guide
DAO isn't a model, so you can add a method. I suppose that PageController would have a StudentRepository(StudentDAO) where will be a method getAll.
The structure mostly depends on the logic of your application.
Adding getAllStudents (database access method) to the Student class is, in fact, related to a design pattern called Active Record
Well, it's usually an anti-pattern for some people. Take a look at this article for detailed explanation.
On the other hand, you mentioned that you are using a DAO, which is a different design pattern for the same use case. I recommend you decide on a single option only.
If you are relying on DAO, everything related to data-access goes there. The model class must keep data only. However, be aware that this will lead you to an Anemic Domain Model, which has, in turn, its own drawbacks.
My preferred approach is DDD, it balances the responsibility of the data-related classes in a more consistent way.
Regarding where instantiate your DAO, the rule of thumb is: don't do it. Use Dependency Injection instead.
It's better because it leverages testability and maintainability of your code.
Recently I have really focused on writing clean code and implementing designs and I have stumbled accross a situation where I have several options but cannot decide which one is the appropriate one. I am working on a software that requires persistence on a collection of objects. I decided to implement a DAO Pattern. The thing is that persistency could both be Json OR Xml so I implemented it this way:
I created a Generic DAO:
public interface GenericDao<T> {
public boolean add(T type);
public boolean change(T type);
public void delete(T type);
}
Then I created a CarDAO:
public interface CarDao extends GenericDao<Car> {
public Car getByIdentificationNumber(int id);
public void process();
}
For JSON persistence:
JsonGenericDao:
public class JsonGenericDao<T> implements GenericDao<T> {
public boolean add(T type) {
// implement ADD for json
}
public boolean change(T type) {
// implement Change for json
}
public void delete(T type) {
// implement Delete for json
}
}
JsonCarDao:
public class JsonCarDao extends JsonGenericDao<Task> implements CarDao {
public Car getByIdentificationNumber(int id) {
// Implement logic
}
public void process() {
// Logic
}
}
JsonCarDao extends JsonGenericDao to include the Add, Change, Delete and it also provides additional methods.
The same way is implemented XmlGenericDao and XmlCarDao.
So I end up with the possibility of using XmlCarDao OR JsonCarDao depending on the persistence I want to use.
When implementing the persistence, I used JAXB for XML and Gson for JSON.
I made an EntityCollection<T> class to store the objects inside and I would convert this collection to either XML OR JSON depending on the persistence used and I would retrieve the information from the file to this collection, change what needs to be changed and then rewrite the file.
There are two ways I can implement it:
Option 1:
I could implement the persistence using Gson inside JsonGenericDao and do the same for JAXB inside XmlGenericDao.
Option 2:
I can create an interface Persister<T> and write two classes that implement this interface, therefore JsonPersister<T> and XmlPersister<T> with methods such as update(T type) and acquireAllFromFile(), one of which is going to rewrite the whole file with the new data, and the other one is going to retrieve the information from the file. (Same thing could be done in Option 1 but without making the additional classes)
Then inside JsonGenericDao<T> I can use: JsonPersister<EntityCollection<T>>
and inside XmlGenericDao<T> I can use: XmlPersister<EntityCollection<T>>
therefore packing everything.
The problem here though is thinking about this, it would mean that I can get rid of JsonGenericDao and XmlGenericDao and implement a single PersistenceGenericDao which is going to use a Persister interface inside its CONSTRUCTOR to specify if JsonPersister should be used or XmlPersister should be used. It would basically be a combination of DAO and Strategy Pattern. Now this seems like something I can do.. but it also appears to me that it messes up my initial DAO design. Is it an appropriate thing to do or is it bad practice?
I think your option 2 actually looks like the GoF Bridge Pattern. XmlPersister/JsonPersister are ConcreteImplementors. PersistenceGenericDao is Abstraction, JsonCarDao is RefinedAbstraction.
So the idea actually makes sense. See What problems can the Bridge design pattern solve? to check if you really need the pattern or not.
If you only plan to use XML or JSON persistence, I personally would go with option 2. If you compare JsonCarDao with XmlCarDao, the only difference between them will probably be the mechanics of saving/loading data from some resource (JSON vs. XML). The rest of the logic will probably be pretty much the same. From this point of view, it is reasonable to extract the "saving/loading" into specific implementors and have one generic class for the rest of the DAO logic.
However if you consider relational or NoSQL database persistence, this might not fit that well. Because the DAO logic will probably be different. A method like findById will be pretty different in a relational DAO (query in the DB) compared to a JSON DAO (load data from a JSON file and search the collection of objects for an object with the given ID). In this situation, RelationalPersistence will probably not be very efficient.
I am just starting to apply RealmDB in my application. I have one question regarding nesting objects.
I have previous experience working with Entity Framework. There is one useful feature available in Entity Framework - mappings.
The problem is that I need to have nested object. Here is an example
public class SessionModel extends RealmObject {
private UserModel userModel;
private ExpirationDate expirationDate;
}
As you can see the members are not simple types, but classes instead. Therefore it is problematic to map them correctly.
I wonder if there is any way to use custom retriever or mapper to get collect all objects manually and return a model with all fields set.
Thank you
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?
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.
I am creating an application and at the front I check if the user is an admin, user, moderator or superadmin. Based on this I create a different XML.
So what I currently do is to pass a string in the method argument that converts the object to XML to specify which mapping it should use. However passing those strings around isn't good. Are there any patterns to do this better?
I could bring the role check to the mapping class, and then change the mapping id to the same as the role of the current user. But I don't think security checks fits those classes.
Would you just create an enum to keep the roles and pass that instead of a string?
Or create different classes and use a factory to return the right object?
A Common Interface Approach
By implementing a common interface between all return objects, you can develop some loose coupling in your code. For example:
public interface XmlReturn
{
public void displayXML(); // Just an example method.
}
And a class that implements this interface:
public class AdminXmlReturn implements XmlReturn
{
public void displayXML() { // Some code here for the admin XML }
}
With this, you can generate some sort of factory that takes a discriminator:
public abstract class XmlFactory
{
public static XmlReturn getInstance(String type)
{
// Using string as an example type. Doesn't need to be.
if(type.equals("Admin")) {
return new AdminXmlReturn();
}
}
}
and by referring to the object by it's interface type, you can generate as many different XML files you want, without having to change any code. IE:
public void loadPage(String permission)
{
// permission can be any type. This is just an example.
XmlReturn xml = XmlFactory.getInstance(permission);
xml.displayXML();
// This method exists in all objects that implement XmlReturn
}
Advantages
This approach has the main advantage that you can add as many new XML files and permissions as you want, and you won't need to change the code that loads the XML. This "separation of concerns" will help you to make your program very manageable and extendable.
By porting your decision logic to a factory, you help make your code more readable, and allows other people to abstract away from the details of the inner workings of your program, if you intend on sharing your code.
You question is not very clear. Anyway, I try to give some option:
if you want to serialize to XML different kind of users, then I would suggest to model the different kind of users as a hierarchy of classes, and have a specialized toXML() serialization method in each class. By the way, JAXB can help you a lot, if this is what you want to do.
if you have a class XMLBuilder that writes some XML, and the way the XML is built depends on the kind of user, then I would suggest to model your different kind of users with a hierarchy of classes, and then use method overloading in XMLBuilder, i.e. have several build() methods each one taking as input a different subclass of your user-kind hierarchy.
I hope this helps.