Is there a way to adhere to the Single Responsibility Principle without invoking multiple database calls in this code?

StackOverflow https://stackoverflow.com/questions/18651747

Question

I have a portion of code that basically retrieving a Bean object from the database through Hibernate, making some changes to the values of two or three properties before storing it back into the database.

Let's look at a real example. My application's purpose is to allow a couple of people to take a MCQ test. To prevent overloading the database by updating the score every time the user submits an answer, I am storing the score counter in a HashMap which will be flushed to the database at the end of the test. I also require a timestamp to be updated indicating the time that the test has been concluded.

My current design involves two functions.

This first function flushes the score from the HashMap to the database.

private void flushScoreToDatabase(String id) {

    int score = scoreMap.get(id);

    Session session = HibernateUtil.getSessionFactory().getCurrentSession();

    try {
        session.beginTransaction();
        Student student = (Student)session.get(Student.class, Integer.parseInt(id));
        student.setScore(score);
        session.getTransaction().commit();
        scoreMap.remove(id);
    } catch (HibernateException e) {
        session.getTransaction().rollback();
    }
}

The second function will involve updating the timestamp.

private void updateTimestamp(String id) {
    Session session = Hibernate.getSessionFactory().getCurrentSession();

    try {
        sesssion.beginTransaction();
        Student student = (Student)session.get(Student.class, Integer.parseInt(id));
        student.setEndTime(timestamp);
        session.getTransaction().commit();
    } catch (HibernateException e) {
        session.getTransaction().rollback();
    }
}

Both functions will be wrapped by another function that gets the id of the user from the authenticated session.

This is pretty expensive because this involves two SELECT statements as well as two UPDATE statements just to update two different properties for the same user.

Is there a neater way to design the code while adhering to the SRP?

Was it helpful?

Solution

Normally SRP is discussed with reference to a class or module, but I think you're right to consider the meanings of functions, a "ragbag" function whose jobs is to "x and y and z" may not be good design.

Also performing two separate transactions to update score and timestamp is surely excessive.

I would tend to consider the functions in terms of a business meaning, say:

snapshotTest()

and

endTest()

and have a utility function that updates the student's score used by both of those.

In passing, all that transactional stuff is getting in the way of your business logic, can you not use EJBs or Spring to push that to a container?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top