Monday, December 13, 2010

View And Model


 What is the relationship between View and Model in Spring Framework?
ViewModel is the glue between View and Model. 
why do we need it?
As we all known, we can divide our system into three layers Presentation, Business and Persistence. When comes to Presentation layer, we usually design it in the MVC design pattern. What we do to divide system different layer is trying to make each part has single responsibility, and also for maintainable. So what we do here is the same.
we use ViewModel to separate the View and Model to decouple the two.For instance, if we changed Model, View was not affected as all, what we should do is to change the ViewModel. Just imagine that if there is no ViewModel, View can directly access the Model, we change Model, we need to change all the view that invoke the Model, which is really painful. But if ViewModel is involved we just need to change it, View doesn't know what happened, actually View should not be allowed to know that. 


How to use ViewModel?
Assumption that we have a MVC:
  • Model: Story
  • View: view_story
  • Controller: StoryController
Controller
@Controller
public class StoryController{
private StoryRepository storyRepository;
@Autowired
public StoryController(StoryRepository storyRepository){
    this.storyRepository = storyRepository;
}
@RequestMapping("/view_stories")
public ModelAndView viewStoreies(){
    ModelAndView result = new ModelAndView("view_stories");
    result.addObject("stories", StoryViewModelHelper.wrapIntoViewModel(storyRepository.getAllStories()));
    return result;

}
}

Model
@Entity
@Table("story")
public class Story{
    @Column(name = "title")
    private String title;

    @Column(name = "owner")
    private User owner;

    @Column(name = "time")
    private Date time;
  
    public Story(String title, User owner, Date time){
        this.title = title;
        this.owner = owner;
        this.time = time;
    }

    public String getTitle() { return title; }
    public void setTitle(String title) { this.title = title; }
    public User getOwner() { return owner; }
    public void setOwner() { this.owner = owner; }
    public Date getTime() { return time; }
    public void setTime() { this.time = time; }
}


StoryViewModel
public class StoryViewModel{
    private String topic;
    private User owner;
    private Date time;
    public StoryViewModel(Story story){
        topic = story.getTitle();
        owner = story.getOwner();
        time = story.getTime();
    }
    public String getTopic(){return topic;}
    public String getUserName(){return owner.fullName();}
    public String getWhenHappened(){return time.toString();}
}


        View
            In the view file there is some code like:          
    <c:forEach items="${stories}" var="${story}">
       <td>${story.topic}</td>
       <td>${story.userName}</td>
       <td>${story.whenHappened}</td>
    </c:forEach>

So in view file we are actually using the StoryViewModel to resolve the information we need to presentate to the user. This is a good practice because we can move all the process logic into this Model which can be easily tested, changed and maintained. Besides that the View and Model are kind of decoupled, if the View need to be changed we don't need to change the related Model, what we need to do is just change the logic of the ViewModel, which is much easier, and costes less.

No comments:

Post a Comment