MVCな画面を書いてみる

お世話になっております。

ウェブDBプレスのvol.53には、「JavaScript/Flash/HTML5スパゲッティコードにならないためのモダン設計入門」という特集があり、それを拝見したところ、自分で実装したくなったので書きました。
本に影響されてコードを書くのは久しぶりです。ちょうどこの夏にスパゲッティコードを生産してしまったせいでしょうか。

<html>
  <head>
    <style type="text/css">
#messageDiv span {
  border-bottom: solid 2px #9999FF;
  width: 300px;
  display: block;
  padding-top: 1px;
}
    </style>
	<script type="text/javascript" src="prototype.js"></script>
	<script type="text/javascript">
var G = {
  model:{
    message: [],
    getMessage: function(){
      return G.model.message;
    },
    addMessage: function(msg){
      var now = new Date();
      G.model.message.push(now.getHours() + ':' + now.getMinutes() + ':' + now.getSeconds() + ': ' + msg);
      if(5 < G.model.message.size()){
        G.model.message.shift();
      }
    }
  },
  update: {
    message: function(elm){
      var messages = G.model.getMessage();
      messages.each(function(msg, index){
        elm.down('span', index % 5).update(msg);
      });
    }
  },
  handler: {
    onButtonClick: function(elm){
      G.model.addMessage('click');
      G.update.message(elm);
    }
  }
}

document.observe('dom:loaded', function(){
  G.update.message($('messageDiv'));
  $('updateButton').observe('click', function(e){
    e.stop();
    G.handler.onButtonClick($('messageDiv'));
  });
});
	</script>

  </head>

  <body>
    <div id="messageDiv">
      <span>&nbsp;</span>
      <span>&nbsp;</span>
      <span>&nbsp;</span>
      <span>&nbsp;</span>
      <span>&nbsp;</span>
    </div>
    <form>
      <input id="updateButton" type="button" value="Button" />
    </form>
  </body>
</html>

ボタンをクリックすると、時刻を表示します。最大5件まで表示し、古いものから捨てていきます。機能としては、記事にあるものとほとんど同じです。
大きく分けると、「model, update, handler」の3つに分かれ、それぞれが「MVC」に対応しているイメージです。

以下、気になっている点を挙げておきます。

  • handlerからupdateを実行しているが、初期処理でmodelへupdateを渡してしまったほうが、よりMVCらしい。
  • modelのデータの持ち方は、文字列にするのではなく、時刻と文字列にわける。フォーマットはupdateで決める。
  • 履歴の最大件数は、modelでもつべきか。

リッチな画面を作るには、JSP-Servlet-BeanなMVCだけでなく、JSPの中のMVCも設計しなければいけないようです。これは大変なことになってきました。

WEB+DB PRESS Vol.53

WEB+DB PRESS Vol.53

以上

追記

Modelを強化しました。

<html>
  <head>
    <style type="text/css">
#messageDiv span {
  border-bottom: solid 2px #9999FF;
  width: 300px;
  display: block;
  padding: 2px;
}

#messageDiv {
  border: double 3px #9999FF;
  background-color: #FFFFDD;
  width: 304px;
  padding: 2px;
}
    </style>
	<script type="text/javascript" src="prototype.js"></script>
	<script type="text/javascript">
//  beginning of MessageCollection
var MessageCollection = Class.create({
  initialize: function() {
	this.messages = [];
	this.maxMessageCount = 10;
  },
  add: function(messageObj){
	this.messages.push(messageObj);
	if(this.maxMessageCount < this.messages.size()){
	  this.messages.shift();
	}
	this.update();
  },
  toArray: function() {
	return $A(this.messages);
  },
  setUpdate: function(updateFunc){
	this.update = updateFunc;
  }
});
//  end of MessageCollection

//  beginning of Message
var Message = Class.create({
  initialize: function(msg){
	this.time = new Date();
	this.message = msg;
  },
  getTime: function(){
	return this.time;
  },
  getMessage: function(){
	return this.message;
  }
});
//  end of Message

var G = {
  model:{
	messages: new MessageCollection(),
    getMessage: function(){
      return G.model.messages.toArray();
    },
    addMessage: function(msg){
	  var messageObj = new Message(msg);
	  G.model.messages.add(messageObj);
    }
  },
  update: {
    message: function(){
	  var elm = $('messageDiv');
      var messages = G.model.getMessage();
      messages.each(function(messageObj, index){
	    var h = messageObj.getTime().getHours();
	    var m = messageObj.getTime().getMinutes();
	    var s = messageObj.getTime().getSeconds();
	    var msg = h + ":" + m + ":" + s + ":" + messageObj.getMessage();
        elm.down('span', index % 10).update(msg);
      });
    }
  },
  handler: {
    onSendClick: function(elm){
      G.model.addMessage($F('messageBox'));
	  $('messageBox').setValue('')

    }
  }
}

document.observe('dom:loaded', function(){
  G.model.messages.setUpdate(G.update.message);
  $('updateButton').observe('click', function(e){
    e.stop();
    G.handler.onSendClick($('messageDiv'));
  });
});
	</script>

  </head>

  <body>
	<form>
	  <div id="messageDiv">
		<input id="messageBox" type="text" />
		<input id="updateButton" type="button" value="Send" />
		<span>&nbsp;</span>
		<span>&nbsp;</span>
		<span>&nbsp;</span>
		<span>&nbsp;</span>
		<span>&nbsp;</span>
		<span>&nbsp;</span>
		<span>&nbsp;</span>
		<span>&nbsp;</span>
		<span>&nbsp;</span>
		<span>&nbsp;</span>
	  </div>
	</form>
  </body>
</html>