昨日、MVCについて、より正確にはMVCでのモデルコンポーネントの役割について、開発者の1人と話し合いました。
私の意見では、モデルにはプロパティのみが含まれ、機能はほとんど含まれていないため、モデルクラスのメソッドは可能な限り少なくなります。
しかし、私の同僚は、モデルにはそれ以上のものがあり、さらに多くの機能を提供できるはずであると信じています。
これが私たちが議論した例です。
例1
ブログを作成したいとしましょう。ブログには記事とタグがあります。各記事には複数のタグを付けることができ、各タグは複数の記事に属することができます。したがって、ここにはam: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;
}
}
ここで、ここで緩く結合して作業していると仮定します。つまり、タグがまだないArticleのインスタンスがある可能性があるため、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の理解では、モデルにはプロパティと最小限の「ヘルパーメソッド」のみが含まれている必要があります。たとえば、モデル「Article」はメソッドgetNumOfTags()を提供できますが、それ自体でAjax呼び出しを実行するべきではありません。
では、どちらのアプローチが正しいのでしょうか?