Philip Badilla
Philip Badilla

Reputation: 1058

Class Function Dilemma

I'm current working on a project and stumbled upon a very common problem

"Where should I place this function?"

Basically I have classes which represents models such as

Store, Area, User, Item, Menu, Product and more...

I'm just thinking about some basic functions like CRUD and other search functions.

What most of the things I see in tutorials and examples in the internet is

User.create(), User.delete(), User.update() and User.getUserById(int Id) User.getAllUsers() so on..

Well my problem is it doesn't make sense to me.

Why would a user model have the capability to search all users? Or even create a new user?

Update and delete might have more sense, but getUserById and getAllUsers also don't make sense

What I'm thinking is wouldn't it be the Store model's responsibility to add a user in that store, or create a Menu, Item and Area in that store, and then it's the Menu model's responsibility to add a product to its menu and so on?

And then when searching for a user wouldn't it make more sense for a Store.getAllUsers() or Store.getUserById() or something like Menu.getAllCategories() and Category.getAllProducts()

I know what I'm thinking will require more code and functions but I'm not really sure if what I'm thinking is a sensible architecture, but I feel that it is.

I need some guidance or maybe a kick in the head to get myself thinking straight.

Upvotes: 1

Views: 43

Answers (1)

NotGaeL
NotGaeL

Reputation: 8484

Before deciding how to implement persitence into a web app, there are a few concepts you may need to get a grasp of. There are many different design patterns and there is no one-size-fits-all solution, in my opinion. The proper answer(s) should be language agnostic, but allow me to exemplify one of the possible designs you may want to follow using a basic Java implementation:

Basically you create a DAO that implements persistence (CRUD/SCRUD) into your aplication.

This DAO will map application calls to the persistance layer. Here I'm using Hibernate (tutorial) on Java as ORM:

package org.mywebapp.pojos;

import org.hibernate.Query;
import org.hibernate.Session;

import java.io.Serializable;
import java.util.List;

public class myWebAppDAO {
    private static myWebAppDAO _this = new myWebAppDAO();

    public static myWebAppDAO getInstance() {
        return _this;
    }

    public void persist(Object object) {
        Session session = HibernateUtil.getSessionFactory().openSession();
        session.beginTransaction();
        session.persist(object);
        session.getTransaction().commit();
        session.disconnect();
    }

    public void update(Object object) {
        Session session = HibernateUtil.getSessionFactory().openSession();
        session.beginTransaction();
        session.update(object);
        session.getTransaction().commit();
        session.disconnect();
    }

    public void delete(Object object) {
        Session session = HibernateUtil.getSessionFactory().openSession();
        session.beginTransaction();
        session.delete(object);
        session.getTransaction().commit();
        session.disconnect();
    }

    public Object getById(Class clazz, Serializable id) {
        Session session = HibernateUtil.getSessionFactory().openSession();
        session.beginTransaction();
        Object o = session.load(clazz, id);
        session.getTransaction().commit();
        session.disconnect();
        return o;
    }

    public List getTopicsByRef(int ref) {
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        Query q = session.createQuery("from Topic AS t WHERE t.ref = :ref");
        q.setParameter("ref", ref);
        List topic = q.list();
        session.getTransaction().commit();
        return topic;
    }

    public long getTopicCount(int ref) {
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        Query q = session.createQuery("SELECT COUNT(t) FROM Topic AS t WHERE t.ref = :ref");
        q.setParameter("ref", ref);
        Long l = (Long) q.uniqueResult();
        session.getTransaction().commit();
        return l;
    }

    public User getUser(String email, String password) {
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        Query q = session.createQuery("from User AS e WHERE e.email = :email AND e.password = :password");
        q.setParameter("email", email);
        q.setParameter("password", password);
        User user = (User) q.uniqueResult();
        session.getTransaction().commit();
        return user;
    }

//...

}

See how the ORM takes care of the details of Database query / query results <-> Object conversion, the idea being making your app database agnostic by using JPQL/HQL on your queries. MySQL? Oracle? PostgreSQL? SQLite? Who cares? Set the datasource you want / require and the code remains the same (Normally you'd just use JDBC with the appropriate driver).

Here is an example of a very simple implementation for instantiation of User objects (such as the ones returned by getUser on the DAO); Just a collection of getters and setters with no constrain checks or anything (Check also this example of a Topic pojo):

package org.mywebapp.pojos;

import java.io.Serializable;

public class User
        implements Serializable {
    private static final long serialVersionUID = 1L;
    private String id;
    private String email;
    private String password;
    private String firstName;
    private String lastName;

    public String getId() {
        return this.id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getEmail() {
        return this.email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return this.password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getFirstName() {
        return this.firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return this.lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

And here its User.hbm.xml Hibernate mapping where, in this simple case, you just specify which attribute from user class matches which table and column (Check also this example of a Topic mapping):

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="org.mywebapp.pojos.User" table="user">
        <id name="id" column="id">
            <generator class="uuid" />
        </id>
        <property name="email" column="email"/>
        <property name="firstName" column="firstName"/>
        <property name="lastName" column="lastName"/>
        <property name="password" column="password"/>
    </class>
</hibernate-mapping>

So now you can select users by id, get lists of users... whatever you want to do you just implement it on these classes and the DAO, then import them anywhere your app needs them and you are set.

Best of all: There are many IDE's and frameworks that can take care of this process automatically for you, if you want to avoid these tasks. e.g. See how easy is adding/modifying parameters to/of an entity or entities to/of your model using Java Spring framework on this Java web-app framework comparison; or how in python django framework handles all the interactions between the model and the app really nicely, as you can see in their tutorials: Creating models and Making queries

Upvotes: 1

Related Questions