忍者ブログ
趣味と実益を兼ねて将棋のプログラムを作ってみたいなと思っている私の試行錯誤や勉強したことを綴ってゆく予定です。 一番の目的はソフトウェア設計やオブジェクト指向に慣れること ・・・だったのですが、元々の興味や電王戦に触発されたこともあり、AI製作も目指してみたいと今は考えています。 ※はてなに移転しました。
カレンダー
04 2024/05 06
S M T W T F S
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
プロフィール
HN:
cwron
性別:
男性
自己紹介:
将棋の腕前はムラがあるのでなんとも言えませんが、将棋ウォーズや81Dojo基準だと約三段てことになってます。リアルで指す機会が希少です。
Share
ブログ内検索
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

前回の続き的なこと。もうちょい実装にしても設計にしてもいい形があるように思うので。


拍手[0回]

まず前回の実装と実行結果。それぞれラベルをクリックすると開きます。

コード

#!/usr/bin/env python
# -*- coding: utf-8 -*-

class Interpreter:
	def __init__(self, context):
		self.cn = context
	def interpret(self):
		status = SIni()
		for s in self.cn:
			print "======================================="
			status.setCurrent(s)
			status = status.interpret()
		return status

class State:
	SONE=1
	STWO=2
	STHREE=3
	OWN=-1
	#status=[S1,S2,S3]
	#status={SONE:S1, STWO:S2, STHREE:S3}
	
	def __init__(self, current=None):
		if(self.__class__.__name__=="State"):
			raise Exception,"abstract class \"State\""
		self.current = current
		self.prestate = None
	
	def setCurrent(self, s):
		self.current = s
		return self

	def setPrestate(self, pre):
		self.prestate = pre
		return self
	
	def getStateCode(self):
		if(self.current == State.SONE): return State.SONE
		elif(self.current == State.STWO): return State.STWO
		elif(self.current == State.STHREE): return State.STHREE
		else:
			raise Exception, "SyntaxError"
	
	def isMatch(self):
		#s = (self.line)
		#print "isMatch(): "+str(self.__class__.OWN)
		if(self.getStateCode()==self.__class__.OWN):
			#print "T"
			return True
		#print "F"
		return False
	
	def delegate(self):
		#print "		DELEGATE *** "+StateFactory.Create(self.getStateCode(), self.current).__class__.__name__
		#cstate = self
		#return StateFactory.Create(self.getStateCode(), self.current).setPrestate(cstate).interpret()
		s = StateFactory.Create(self.getStateCode(), self.current)
		s.setPrestate(self)
		print "DELEGATE: "+s.prestate.tostring()
		return s.interpret()
		
	def interpret(self):
		if(self.isMatch()):
			# do approximate processing....
			return self
		else:
			return self.delegate()
			i
	def tolist(self):
		ret = [self]
		elm = self
		while not elm.prestate is None:
			ret.insert(0,elm.prestate)
			elm = elm.prestate
		return ret

	def __iter__(self):
		for el in self.tolist():
			yield el
	
	def tostring(self):
		return "State"+str(self.__class__.OWN)

class SIni(State):
	OWN=0
	def interpret(self):
		if(not self.isMatch()):
			return self.delegate()

class S1(State):
	OWN=1
	def interpret(self):
		if(self.isMatch()):
			print "! STATE(1) printing by "+self.__class__.__name__
			print "    > pre: "+self.prestate.__class__.__name__
			return self
		else:
			return self.delegate()
			
class S2(State):
	OWN=2
	def interpret(self):
		if(self.isMatch()):
			print "# state[2] printing by "+self.__class__.__name__
			print "    > pre: "+self.prestate.__class__.__name__
			return self
		else:
			return self.delegate()

class S3(State):
	OWN=3
	def interpret(self):
		if(self.isMatch()):
			print "% sTaTe{3} printing by "+self.__class__.__name__
			print "    > pre: "+self.prestate.__class__.__name__
			return self
		else:
			return self.delegate()
class StateFactory:
	status={State.SONE:S1, State.STWO:S2, State.STHREE:S3}
	@classmethod
	def Create(cls, scode, current):
		return StateFactory.status[scode](current)
		
def test():
	lis = [1,2,3,2,3]
	intp = Interpreter(context=lis)
	result = intp.interpret()
	
	print result.prestate
	print "\n"
	#for elm in result.tolist():
	for elm in result:
		print elm.__class__.__name__
	
	#while not result.prestate is None:
	#	print result.tostring()
	#	result = result.prestate
if __name__=="__main__":
	test()

実行結果

=======================================
DELEGATE: State0
! STATE(1) printing by S1
    > pre: SIni
=======================================
DELEGATE: State1
# state[2] printing by S2
    > pre: S1
=======================================
DELEGATE: State2
% sTaTe{3} printing by S3
    > pre: S2
=======================================
DELEGATE: State3
# state[2] printing by S2
    > pre: S3
=======================================
DELEGATE: State2
% sTaTe{3} printing by S3
    > pre: S2
<__main__.S2 instance at 0x7f0a44f36b90>


SIni
S1
S2
S3
S2
S3

各Stateは「行」が表す情報の「大分類」に相当します。Stateパターンもどきを適用していることで、サブクラス内ではそのクラスが表す「大分類」の内側、内部的な状態遷移に専念させることができます。

なんとなくですが、どうなの?と思ってる部分がいくつかかあって、

  • 内部遷移を各Stateで分離するだけで十分なの?もうちょい分離を進めるべき?
  • Stateはたとえ遷移がない場合であっても新しいStateを作成し、行の数だけStateのリスト構造を持たせるようにした方が良いのではないか
  • Interpretにどの程度の情報を持たせるか?どれだけの責任を持たせるか?

最後のに関して言えば、生のテキストが入ったファイルオブジェクトの参照を保持し、簡単のため除去しているメタ情報の類とか消費時間とかの情報の削除もこのクラス(もしくは内部で持ってるオブジェクト)の責任とすべきか?というようなことになります。インタプリタクラスの責任ってどこまでなのか?クライアントや他のクラスで責任を受け持つべきことって何なのか?というような部分になります。

現状の自分の答えとしては、おそらくInterpreterはファイルを渡して結果を返すまで、つまり最初から最後までの責任を持ち、クライアントにあたる側からはその詳細はある程度隠蔽されているべき。で、「結果を返すまで」だと責任が大きすぎるから、内部では委譲を活用しながらこまごました責任を分担していく。という形が良いのかなと。フォーマット、もしくはバージョン、または実装のバージョンアップに対応するためには、分担するオブジェクトたちの生成や構造の設計についてはAbstractFactory, Builder, Bridge, Decorator, Strategyあたりが必要となってきそうです。あとはComposite, Facadeとかでしょうか。もちろん全部が全部適用可能なわけではないし、必要以上のデザインパターンの使用はかえってコードを理解しづらくし、保守を難しくさせるとも言います。そのあたりはあまり調子に乗らず、デザインパターン至上主義に陥らないよう気をつけたい所ですけどね。とりあえず、このプロトタイプはもっと良いものになる余地があると思うので、もうちょい考察しながら第2弾を作っていきたいです。

p.s

今回久々にjQueryに触りました。だいぶ忘れてたからちょっとは復習できてよかった。

PR
お名前
タイトル
文字色
URL
コメント
パスワード
Vodafone絵文字 i-mode絵文字 Ezweb絵文字
Copyright © nounai.output(spaghetiThinking); All Rights Reserved
Powered by ニンジャブログ  Designed by ピンキー・ローン・ピッグ
忍者ブログ / [PR]