Вчера у меня была дискуссия с одним из наших разработчиков относительно MVC, точнее о роли компонента модели в MVC.
На мой взгляд, модель должна просто содержать свойства и почти никакой функциональности, поэтому возможно как можно меньше методов в классах моделей.
Мой коллеж, однако, полагает, что модели могут и должны иметь больше, чем это, и предлагают гораздо больше функциональности.
Вот пример, о котором мы говорили.
Пример 1
Скажем, мы хотели создать блог. В блоге есть статьи и теги. Каждая статья может иметь несколько тегов, и каждый тег может принадлежать нескольким статьям. Итак, здесь мы имеем отношение m: n.
В псевдокоде он, вероятно, будет выглядеть примерно так:
class Article{
public int id;
public String title;
public String content;
public Tag[] tags;
// Constructor
public void Article(id, title, content, tags){
this.id = id;
this.title = title;
this.content = content;
this.tags = tags;
}
}
class Tag{
public int id;
public String name;
// Constructor
public Tag(id, name){
this.id = id;
this.name = name;
}
}
Теперь предположим, что мы работаем свободно соединенными здесь, что означает, что может случиться так, что у нас есть экземпляр статьи, у которого пока нет тегов, поэтому мы будем использовать вызов Ajax (для нашего бэкэнд, который имеет базу данных, содержащую все информацию), чтобы получить теги, которые принадлежат нашей статье.
Вот сложная часть. Я считаю, что получение бэкэнд-данных через Ajax + JSON должно быть заданием контроллера, используя выделенный класс, который обрабатывает запрос ajax с использованием синтаксического анализатора:
class MyController{
private void whatever(articleID){
Article article = (Article) ContentParser.get(articleID, ContentType.ARTICLE);
doSomethingWith(article);
}
}
public abstract class ContentParser{
public static Object get(int id, ContentType type){
String json = AjaxUtil.getContent(id, type.toString()); // Asks the backend to get the article via JSON
Article article = json2Article(json);
// Just in case
Tag[] tags = article.tags;
if (tags == null || tags.length <= 0){
json = AjaxUtil.getContent(article.id, ContentType.TAGS); // Gets all tags for this article from backend via ajax
tags = json2Tags(json);
article.tags = tags;
}
return article;
}
// Does funky magic and parses the JSON string. Then creates a new instance of Article
public static Article json2Article(String json){
/*
...
*/
return new Article(id, title, content, tags);
}
// Does funky magic and parses the JSON string. Then creates a new instance of Tag
public static Tag[] json2Tags(String json){
/*
...
*/
return tags;
}
}
Пример 2
Мой коллега полагает, что это нарушает идею MVC, он предполагает, что модель должна позаботиться об этом:
class Blog{
public int id;
public String title;
public Article[] articles;
// Constructor
public Blog(id, title, articles){
this.id = id;
this.title = title;
this.articles = articles;
}
public void getArticles(){
if (articles == null || articles.length <= 0){
String json = AjaxUtil.getContent(id, ContentType.ARTICLE); // Gets all articles for this blog from backend via ajax
articles = json2Articles(json);
}
return articles;
}
private Article[] json2Articles(String json){
/*
...
*/
return articles;
}
}
class Article{
public int id;
public String title;
public String content;
public Tag[] tags;
// Constructor
public Article(id, title, content, tags){
this.title = title;
this.content = content;
this.tags = tags;
}
public Tag[] getTags(){
if (tags == null || tags.length <= 0){
String json = AjaxUtil.getContent(id, ContentType.TAGS); // Gets all tags for this article from backend via ajax
tags = json2Tags;
}
return tags;
}
// Does funky magic and parses the JSON string. Then creates a new instance of Tag
private Tag[] json2Tags(String json){
/*
...
*/
return tags;
}
}
И вне модели вы бы сделали: blog.getArticles();
или article.getTags();
, чтобы получить теги, не беспокоясь о вызове ajax.
Однако, насколько это возможно, я считаю, что этот подход ломается с MVC, потому что в конце дня все модели будут полны методов, которые выполняют различные фанки, а классы контроллера и помощника почти ничего не делают.
В моем понимании MVC модели должны содержать только свойства и минимум "вспомогательных методов" внутри. Например, модель "Статья" может предложить метод getNumOfTags(), но он не должен делать никаких вызовов Ajax сам по себе.
Итак, какой подход правильный?