In the design pattern Model-View-Controller (MVC), is the back-end database a part of the Model layer, or is it separated from the Model?
Furthermore is it arguable to say that a MySQL database is not a part of Model, since it's placed separately from the Java code?
Wikipedia defines the model as "the domain objects or data structures that represent the application's state." With this is mind, we can see that although a database isn't strictly part of the codebase, it still represents (holds) data used, and is therefore (at least somewhat) part of the model. It's easier to see this if you try to consider why it wouldn't be part of the Controller or the View (both of which are supposed to work with the Model and not directly on their own.)
Now, like in the pictures #John Doe posted, you'll see that in oder to preserve the MVC structure, you'll need to provide an interface to the database through the Model.
As an over simplified example you could consider writing something like this:
public ModelDatabaseWrapper implements ModelReadWriteInterface {
public ModelDatabaseWrapper() {
/* Prepares to use database... */
}
public Object getValue(Object someQuery) throws ModelReadException {
/* Get something from it... */
}
public void putData() throws ModelWriteException {
/* Insert something int to it... */
}
private DataBaseHandle db;
}
This is only a guideline, but I'd highlight the point of making a generic interface for grouping your Model components based on how they're accessed. In a real application one could have many forms of representing data & state beyond just a database, and so by keeping a clean API it would allow the Controller and View more flexibility much easier.
I hope I helped! :)
The database is the persistence, and not really part of the MVC pattern directly (although it is common to persist model state to a database).
Related
I am working on a project where I need to add users to multiple systems (active directory, a database, & Sisense) based on data received from a spreadsheet. I've coded can get the data input correctly into each system, but I am struggling to figure out how to organize my code, in terms of what design pattern to use.
I have a model class for each component that contains the field each system needs:
ActiveDirectoryUser
SisenseUser
DatabaseUser
Then, I have what I call the worker class for each of these that actually does creates the user in the system.
ActiveDirectoryWorker
SisenseWorker
DatabaseWorker
The basic flow of my code is
Read in each line from the spreadsheet
Validate the input is valid.
Create a instance of each model class that contains the appropriate fields.
Call the individual worker classes that control how the user get added to the respective system. The model instance will be passed into this class.
I've read up on some of the various design patterns, but none of the explanations are in "plain" English. Still learning the ropes here a bit, so I'd appreciate someone suggesting a model that fits my scenario.
It sounds as though you've defined three distinct data models, one for each storage. That makes your job more difficult than it has to be. Instead, consider modelling data based on data in the spreadsheet. You could, for instance, define a class called SpreadsheetUser, which contains the valid data from a spreadsheet row.
Now define an interface, e.g. UserCreator:
interface UserCreator
{
void Create(SpreadsheetUser user);
}
Now loop through each row in your spreadsheet, validate the data and then call Create on a Composite, which could be defined like this:
class CompositeUserCreator : UserCreator
{
UserCreator[] creators;
CompositeUserCreator(params UserCreator[] creators)
{
this.creators = creators;
}
public void Create(SpreadsheetUser user)
{
foreach (creator in creators)
creator.Create(user);
}
}
You also define three concrete implementations of UserCreator, one for each storage system, and create the composite like this:
CompositeUserCreator creator =
new CompositeUserCreator(
new ActiveDirectoryUserCreator(/* perhaps some config values here... */),
new SisenseUserCreator(/* ... and here... */),
new DatabaseUserCreator(/* ... and here... */));
You'll still have the problem of dealing with failures. What should happen if you've already created a user in active directory, but then Sisense creation fails? That is, however, not a problem introduced by the Composite pattern, but a problem which is inherent in distributed computing.
How can I decouple how (or even if) a domain model is viewed from the implementation of the view itself. As an example consider the following code:
public class Student
{
private Set<Course> enrollment;
public void enroll(Course c){
// domain implementation
}
public void unenroll(Course c) {
// domain implementation
}
}
This is a pretty simple example, but it's fine for what I'm asking. What would be a good way of ensuring that the view of this object is decoupled from the actual domain functionality? For example this student should be able to be represented in XML, JSON, or even some sort of game, or not have a view of any kind.
Some of the approaches I've thought of could be something like:
#XmlRootElement(name="student")
public class StudentXmlView implements XmlView<Student> {
#XmlElement(name="enrollment")
private XmlVeiw<Set<Course>> enrollmentView;
}
Would this sort of approach be suitable, or is there some best practice that is typically used in java for separating domain from it's view?
The CQRS architecture is perfect for this kind of separation: it separates the write model (the Aggregates in DDD) from the read model.
The write model is specially designed to protect the business invariants regarding state changes. It executes commands. It cannot be queried.
The read model is designed to be fast and fit for a particular use case. Each use case has other read model. Here you can use whatever technology is best suited.
There is no equality between the write and the read models. You could have 3 write models and 1 read model, or any combination.
In a microservice architecture, each model (write or read) can be a microservice.
The next thing after CQRS is Event sourcing.
Let's say I have a very simple program that adds/edits/removes and lists products, and I don't want to make the user install a data base in his machine. Would it be a bad idea to store all the products in a single class and then serialize/save it whenever a change is made?
The class would be something like this for example:
public class MyProducts implements Serializable {
private List<Product> products;
public void AddProduct(Product p) {
// Adds a product...
}
public void RemoveProduct(Product p) {
// Removes a product...
}
}
Have in mind that it would be a simple program, nothing critical, just so that I don't need to bother with relational data base in such a simple software.
Scenario 2: In a real software, would it be a good idea to store the program's configuration/preferences in a serialized file?
Thanks!
This is probably a Bad Idea (TM) because:
any change requires rewriting the entire file
there is no data integrity guarantee - no ACID
you cannot, in the future, query the file - everything must be in memory.
I would suggest a file based database. There are literally hundreds of embedded database programs for Java, for example:
HyperSQL
H2
Apache Derby
sqlite
Why not use one of them?
If you do want to store the data in a file consider:
defining serialversionuid so that you can control backwards compatibility
possibly using a human readable format such as JSON, rather than Java serialisation, this also has the advantage of being faster.
To answer your last question, in a "real software" I would expect something like a file-database driven with JPA to be used. With current tools, such a Spring Boot, this is almost configuration free.
In my java program, I had a book class and a library class.
The library stores the book object in an array list and then I display it on the screen.
I can add the book and remove the books using functions.
I also use AbstractJtableModel for adding and removing the books.
But now I want to use a database, MySQL, instead of an array list.
How should I change my program?
well, you need to write the whole application :)
you need to create a db, with at least one table, you need to add mysql jdbc library to classpath and using jdbc you can insert/select/update/delete data from DB.
Alternatively, you need to add jdbc and use ORM framework like Hibernate, but depending on your Java knowledge this way can be harder (but easier to maintain in future, if you create big application). Here you can download simple hibernate application, which does CRUD operations with Honey :), you can extract interface similar to suggested by Javid Jamae from TestExample class, and exchange Honey class with Book according to your needs
You might consider using the Data Access Object (DAO) pattern. Just do a Google search and you'll find tons of articles on the topic. Essentially, you'll create a LibraryDao interface with methods like:
public interface LibraryDao {
public void storeLibrary(Library library)
public Library loadLibrary(long id)
public List<Library> searchByTitle(String title)
//...
}
You can implement this interface with straight SQL, or you can use an Object Relational Mapping (ORM) tool to implement it. I highly recommend reading up on Hibernate and the JPA specification.
Abstract the retrieval and storage of the books into a class by itself - you don't want that persistence logic intermingled with your business logic. I'd suggest creating an interface called something like "BookStorageDAO" and then you can have various implementations of that interface. One implementation may be to store the books in an ArrayList while another may be to store the books in a Database.
In this way, you can utilize the interface in your business logic and swap out the implementation at any time.
You would still use the ArrayList in your GUI to persist and display the data. The difference would be you need logic to save and load that ArrayList from a database so that the data is stored even after the program ends.
Side note, extends DefaultTableModel as opposed to AbstractJtabelModel. It completes some of the methods for you.
You don't need a DAO per se, but those answers aren't wrong.
Separation of Concern
What you need to do is separate your application based on concern, which is a pattern called separation of concern. It's a leak to have concerns overlap, so to combat this, you would separate your application into layers, or a stack, based on concern. A typical stack might be include:
Data Access Layer (read/write data)
Service Layer (isolated business logic)
Controller (Link between view and model)
Presentation (UI)
etc., but this will only partly solve your problem.
Program To The Interface
You also (as the others have mentioned) need to abstract your code, which will allow you to make use of dependency injection. This is extremely easy to implement. All you have to do is program to the interface:
public interface PersonService {
public List<Person> getAllPersons();
public Person getById(String uuid);
}
So your application would look like this:
public class PersonApp {
private final PersonService personService;
public PersonApp(PersonService personService) {
this.personService = personService;
}
}
Why is this better?
You have defined the contract for interacting with the Person model in the interface, and your application adheres to this contract without having any exposure to the implementation details. This means that you can implement the PersonService using Hibernate, then later decide you want to use JPA, or maybe you use straight JDBC, or Spring, etc. etc., and even though you have to refactor the implementation code, your application code stays the same. All you have to do is put the new implementation on the classpath and locate it (tip: the Service Locator pattern would work well for that).
Assuming the DAO structure and component interaction described below, how should DAOs be used with persistence layers like hibernate and toplink? What methods should/shouldn't they contain?
Would it be bad practice to move the code from the DAO directly to the service?
For example, let's say that for every model we have a DAO (that may or may not implement a base interface) that looks something like the following:
public class BasicDao<T> {
public List<T> list() { ... }
public <T> retrieve() { ... }
public void save() { ... }
public void delete() { ... }
}
Component interaction pattern is --
service > DAO > model
We found (as have others) that it was straightforward to write a generic DAO as a thin shim on top of the JPA calls.
Many were simply right on top of the JPA. For example, early on we simply had:
public <T> T update(T object) {
return em.merge(object);
}
But the benefit of having the layer is that your layer is extensible, whereas the EM is not.
Later we added an overload:
public Thing update(Thing object) {
// do magic thing processing
}
So, our layer was basically intact, but could handle custom processing.
For example, later, since early JPA didn't have Orphan processing, we added that in our backend service.
Even simple common DAO has value, simply as an abstraction point.
We just didn't need to make one for every group of objects (CustomerDAO, OrderDAO, etc.) like the olden days.
IMHO there is no method the DAO "should" contain in general. It should contain exactly those methods your application needs. This may differ from model to model.
In Hibernate and JPA, methods like save and retrieve are "trivial" operations provided by the session / entity manager, so I don't see much point in adding them to the DAO, apart from maybe insulating the service / business logic from the actual persistence implementation. However, JPA is already an insulation in itself.
Moving persistence code directly into the service layer would bundle the two together. In a small app this might be OK, but over time even small apps tend to grow, and maintenance becomes an issue. Keeping separate concerns separated helps keep the code clean, thus easier to understand, extend and reuse.