0

Hi guys,
as I'm looking into the MVC pattern, I thought I'd create a small application to understand a bit more.
Let's look at the code:

//model
package model;

public class StudentModel
{
    private String name;
    private String surname;
    private int number;    

    public String getName()
    {
        return name;
    }
    public void setName(String name)
    {
        this.name = name;
    }
    public String getSurname()
    {
        return surname;
    }
    public void setSurname(String surname)
    {
        this.surname = surname;
    }
    public int getNumber()
    {
        return number;
    }
    public void setNumber(int number)
    {
        this.number = number;
    }

}

//controller
package controller;

import model.StudentModel;
import view.StudentView;

public class StudentController
{
    private StudentModel studentModel;
    private StudentView studentView;
    public StudentController(StudentModel studentModel, StudentView studentView)
    {
        super();
        this.studentModel = studentModel;
        this.studentView = studentView;
    }
}

//view
package view;

public class StudentView
{

    public void displayStudent(String name, String surname, int number){
        System.out.println("Student is: " + name + " " + surname + "\n" + "Number: " + number);
    }
}

//demo
import model.StudentModel;
import view.StudentView;
import controller.StudentController;

public class StudentDemo
{

    public static void main(String[] args)
    {
        StudentView studentView = new StudentView();
        StudentModel model = createStudent("John", "Smith", 34567);
        StudentController studentController = new StudentController(model, studentView );
        studentView.displayStudent(model.getName(), model.getSurname(), model.getNumber());

    }
    public static StudentModel createStudent(String name, String surname, int number){
        StudentModel studentModel = new StudentModel();
        studentModel.setName(name);
        studentModel.setSurname(surname);
        studentModel.setNumber(number);
        return studentModel;
    }

}

OK so, everything works OK, in the sense that I get printed what I expected. But then I run into a problem: what if I want to have multiple students? Does it mean that I have to replicate the code inside StudentDemo, something like this

StudentView studentView = new StudentView();
StudentModel model = createStudent("John", "Smith", 34567);
StudentController studentController = new StudentController(model, studentView );
studentView.displayStudent(model.getName(), model.getSurname(), model.getNumber());

StudentView studentView1 = new StudentView();
StudentModel model1 = createStudent("Jane", "Doe", 56783);
StudentController studentController1 = new StudentController(model1, studentView1 );
studentView.displayStudent(model1.getName(), model1.getSurname(), model1.getNumber());
...

It doesn't sound like a good approach...

3
Contributors
14
Replies
75
Views
2 Months
Discussion Span
Last Post by JamesCherrill
Featured Replies
  • 1. The View class should just be given a reference to the Model that it will display, then all it needs are public methods like displayDetail() or displaySummary(). It should get the individual fields from the Model as needed. 2. If you have a Controller then you shouldn't be calling … Read More

  • I agree with jkon, with the very minor exception that I would be happy to see other methods (more than just get/set) in the Student class, if that's where they fit best. The createStudent method may be a bit of a red herring... in this app so far it's trivial … Read More

  • To me that seems like a violation of everything that OO is about. A Circle should know how to tell you its radius, circumference, area etc. Which of those is held as a attribute and which are calculated on the fly, and which are calculated once then re-used etc is … Read More

3
  1. The View class should just be given a reference to the Model that it will display, then all it needs are public methods like displayDetail() or displaySummary(). It should get the individual fields from the Model as needed.

  2. If you have a Controller then you shouldn't be calling Model or View methods yourself - the Controller should have public task-oriented methods that you call from main or wherever, and the Controller then calls methods in the Model and View as needed.
0

There are many MVC implementations and there is not “right” or “wrong” here. But I also find trivial the second point of  JamesCherrill , also in my point of view Model and View don't communicate (they don't even know the existence of one other) only through a Controller. There are many MVC implementations out there , some have the View to communicate with the Model directly , but after many years I find it cleaner to separate concerns and have a Controller to control ;)

0

That's a fair point.
I certainly agree that the model should never have knowledge of the view (other than via a general "listener" pattern) However I'm personally happy to have the view directly access the public interface of the model. Yes, it's technically cleaner to go via the controller, but in practice this usually means replicating/covering the model's public interface in the controller - which, in my opinion, is an undesirable amount of unneccessary code.
But as you say, there's no right or rong here, just what works best in any particular given situation.

0

Right, let's see if I understand.
So, based on your suggestions, my view class now looks like this:

package view;

import model.StudentModel;

public class StudentView {       
    public void displayStudent(StudentModel studentModel){
            System.out.println("Student is: " + studentModel.getName() + " " + studentModel.getSurname() + "\n" + "Number: " + studentModel.getNumber());
        }
}

I pass a StudentModel reference to it and I get the individual fields from the model with getters.

For the model class itself, I've only added a constructor:

public StudentModel(String name, String surname, int number) {
        super();
        this.name = name;
        this.surname = surname;
        this.number = number;
    }

because I would have to create a StudentModel object from somewhere rather than from the StudentModel itself?
In the Controller class I'm not too sure... I've added a method called createStudent() which creates a new StudentModel object, and I'm also calling the method in the view, like so:

package controller;

import model.StudentModel;
import view.StudentView;

public class StudentController {
    StudentModel studentModel;
    StudentView studentView = new StudentView();
    public void createStudent(){
        studentModel = new StudentModel("John", "Smith", 34566);        
        studentView.displayStudent(studentModel); 
    }

}

Finally the StudentDemo for now has only a call to the createStudent method and the creation of the controller, like so:

import controller.StudentController;
import view.StudentView;

public class StudentDemo
{ 
    public static void main(String[] args)
    {
        StudentController studentController = new StudentController();
        studentController.createStudent();

    }    

}

Is that any better?
With these changes now I seem to be able to handle multiple students: if inside the controller I create another student, it gets outputted OK, for example if I do:

public void createStudent(){
        studentModel = new StudentModel("John", "Smith", 34566);        
        studentView.displayStudent(studentModel);

        studentModel = new StudentModel("Mike", "Doe", 56473);      
        studentView.displayStudent(studentModel); 
0

As I wrote there are many approaches , here is mine in the example you gave above.

Why an object that has properties and methods for a student is called StudentModel and not just Student , wouldn't be clear enough ?
Wouldn't be better if the Student object would be POJO with properties and only getters and setters.

One more thing that I find important is that you have a createStudent method inside the Controller , in my point of view Controller neither instantiates nor modifies Model Objects , it just pass the needed resources to Model classes (Instantiators , Data Workers and more) to do the job, that way the Model can be used without knowing the Controllers that will use it , or even the app.

So in my point of view in a very base level the Controller is giving the resources (as a DB object for example) to Model to create (or modify) an object (or a List of them) and then passes that to the View layer (of course I agree with JamesCherrill that there is no reason to duplicate code , Controller can pass a Model object to View (especially if it is POJO or a list of them) as long as the View doesn't modifies it).

1

I agree with jkon, with the very minor exception that I would be happy to see other methods (more than just get/set) in the Student class, if that's where they fit best.

The createStudent method may be a bit of a red herring... in this app so far it's trivial and just calls a method in the model layer (happens to be a Student constructor). In a more real example it would, as jkon says, deal with data access objects and maybe a student factory to achieve the desired result, so IMHO it's OK to see this version as a kind of placeholder for the real thing.

Votes + Comments
I am not either 100% to that but if the POJO behavior is changing then it is a utilities class with static methods that take that obj in an argument
0

To make it clearer you have a Circle POJO object with only rand as property and getter and setter to it. Should the getPerimeter method be inside that or should be in a Utilities class for Circles as CirclesUtil getPerimeter with argument the circle object? I tend to the second approach in most cases , the Util class for it.

2

To me that seems like a violation of everything that OO is about. A Circle should know how to tell you its radius, circumference, area etc. Which of those is held as a attribute and which are calculated on the fly, and which are calculated once then re-used etc is a private matter for the Circle. By putting the data in one class and the methods in a separate "Utilities" class you are reverting to the older separated model that OO replaced.

Having said that, I think we are in danger of hijacking Violet's thread for our own discussion. Having each stated our position, maybe we should now let it drop until/unless Violet wants to come back onto any of these points. :) JC.

Edited by JamesCherrill

Votes + Comments
Yes maybe the Circle example wasn't so good
0

well, my perspective is that, generally speaking and more from the theory than experience an object, like the student in this case, should be aware of all its properties and methods, so, what @JamesCherrill says seems to me to be more logical. However, when I looked up the MVC model in java, I've found different approaches and I went for what I understood better, which is this one here http://www.tutorialspoint.com/design_pattern/mvc_pattern.htm, nice and simple and that's what I've based my original code on, and in this approach the model doesn't seem to have any methods in it. As what I'm learning is all about OO, then I shall prefere an OO approach.
If having a student factory helps with creating multiple students, then so be it, I will try to add it in. I'm simply taking it slowly as MVC is, for me, a new concept. So, where do we go from here?

0

I've been spending some time going back over the origins of MVC (Smalltalk through to Swift) and I think I've just understood something about how it was intended vs how it's now used in examples like the one you quote.

In the beginning you had an object (or objects) that represents some thing of interest (the model), and OO design makes that intrinsically re-usable. OK so far. Now as a designer of the Smalltalk/Java/etc GUI API you start coding widgets (text fields, buttons etc) and you want them to be reusable. Which means they cannot include any knowledge of any particular model. So you code a generic widget, and the application programmer supplies a controller to glue it all together.
viz: when you code
nameTextField.setText(person.getName());
the person is the model , the nameTextField is the view, and you just coded a controller, exactly as jkon described it. That's where the original MVC thinking comes from.

Where it becomes a controversy is when you create views that are specific to some given situation and the widgetised re-use of the view is not relevant. This happens when the view is a complete panel or window of GUI widgets that displays a complex model, eg a whole person with all their details. You're never going to re-use that class for anything other than displaying a Person. In that case there's no a-priori reason why that view should not have knowledge of the Person's public interface. At that point you have the choice of staying with the fully-separated MVC pattern or simplifying it to allow the view to access the model. That choice is up to you.

Edited by JamesCherrill

1

well,first of all thanks for doing that. For me, really, either way ...generally speaking, it kind of makes sense to me to allow some flexibility and I guess allowing the view to access the model isn't such a bad thing...
Going back to the application, as things currently are, my view has some knowledge of the model because it's using the model's getters to get data out of it:

public void displayStudent(StudentModel studentModel){
            System.out.println("Student is: " + studentModel.getName() + " " + studentModel.getSurname() + "\n" + "Number: " + studentModel.getNumber());
        }

So, is that it then? Are we kind of happy with this?
At the end of the day the purpose of this os for me to understand some basic concepts like MVC :-)

Votes + Comments
Yes , that makes perfectly sense to me
0

If you have a view that's a view of a single model instance then it's common practice to pass the model instance as a parameter inthe view's constructor. In which case displayStudent doesn't need a parameter because it's just going to display the Student that it got when it was constructed.
(If you allow for multiple views/windows/forms open at the same time, each showing a different Student, then this approach keeps the code really clear and simple)

Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.