OO重构试验?? [英] OO refactoring trial ??

查看:68
本文介绍了OO重构试验??的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

OO重构试验

====================

以下是一个简单的试验结构重构(自上而下到OO)

学习练习我正在做。无论你把它称为工厂模式,COR

模式,还是某种模式57,我都不知道在运行时使用什么课程和

我是试图避免冗长的如果序列,测试序列很重要,为了避免代码重复,我将在doit

方法中使用代码对象。


你已经在之前的主题中给了我许多好主意,这就是

它带给你的东西:〜)这样可行,但是请你告诉我:

1)你不喜欢这种方法

2)在递归方法中使用它的含义(引自

但在外面如果装饰者帮忙的话。(/)
3)你可能提供的任何其他评论


谢谢你,

Lee C

=========== ootest.py

============

class MF(对象):

@staticmethod

def findit(t):

for MF .__ subclasses __():

if it.testit(t):

返回它()。doit


A级(MF):

@staticmethod

def testit(tv):

if tv ==''rel ates到A'':

返回True

否则:

返回False


def doit (个体经营):

打印''#做了A#''


B级(MF):

@staticmethod

def testit(电视):

如果电视==''与B''相关:

返回True

:否则:

返回False


def doit(个体经营):

print''#did B#''


mydoit = MF.findit(''与B''相关)

mydoit()


mydoit = MF .findit(''与A''相关)

mydoit()


========试运行====== ========

Python 2.4.1(#2,2005年3月31日,00:05:10)

[GCC 3.3 20030304(Apple Computer, Inc. build 1666)]

输入help,copyright,credit等。或许可证或欲了解更多信息。

OO refactoring trial
====================
Following is a simple trial structure of a refactoring (top-down to OO)
learning exercise I''m doing. Whether you call it a Factory pattern, COR
pattern, or some hinze 57, I don''t know what class to use till run time and
I''m trying to avoid a lengthy "if" sequence, the test sequence is important,
and to avoid code duplication I''ll be using code objects in the "doit"
methods.

You''ve already given me many good ideas in previous threads and this is where
it got you :~) This works, but would you please tell me:
1) What you don''t like about the approach
2) The implications of using this in a recursive approach (referenced from
but outside the recursive function) and if the decorators help with such.
3) Any other comments you might offer

Thank you,
Lee C
=========== ootest.py
============
class MF(object):
@staticmethod
def findit(t):
for it in MF.__subclasses__():
if it.testit(t):
return it().doit

class A(MF):
@staticmethod
def testit(tv):
if tv == ''relates to A'':
return True
else:
return False

def doit(self):
print ''# did A #''

class B(MF):
@staticmethod
def testit(tv):
if tv == ''relates to B'':
return True
else:
return False

def doit(self):
print ''# did B #''

mydoit = MF.findit(''relates to B'')
mydoit()

mydoit = MF.findit(''relates to A'')
mydoit()

======== Test run ==============
Python 2.4.1 (#2, Mar 31 2005, 00:05:10)
[GCC 3.3 20030304 (Apple Computer, Inc. build 1666)]
Type "help", "copyright", "credits" or "license" for more information.

import ootest
#did B#

#did A#
import ootest # did B #
# did A #





推荐答案

Chinook写道:
Chinook wrote:
3)您可能提供的任何其他评论
如果* tv * == *''与* A''相关*:
返回*正确
否则:
返回*错误
3) Any other comments you might offer if*tv*==*''relates*to*A'':
return*True
else:
return*False




制作


返回电视==''与A有关'


以免你的禅师击中你。


Peter



Make that

return tv == ''relates to A''

lest your zen master hit you.

Peter


On Tue,2005年6月28日02:22:13 -0400,Peter Otten写了

(文章< d9 ************* @ news.t-online.com>):
On Tue, 28 Jun 2005 02:22:13 -0400, Peter Otten wrote
(in article <d9*************@news.t-online.com>):
Chinook写道:
Chinook wrote:
3)您可能提供的任何其他评论
3) Any other comments you might offer


if * tv * = = * '' 涉及*至* A '' :
返回*真的
否则:
返回*错误
if*tv*==*''relates*to*A'':
return*True
else:
return*False



使那个

返回电视==''关联到了''

以免你的禅师击中你。

彼得



Make that

return tv == ''relates to A''

lest your zen master hit you.

Peter




谢谢彼得,


因此,在OO中我忽略了更简单的方面。


Lee C



Thank you Peter,

So wrapped up in the OO I overlooked the simpler aspects.

Lee C


李,

有趣的想法,但我认为从MF继承到

的技术会自动将类添加到测试链中。是一个噱头,不会是b $ b规模。


这里有一些事情要考虑:


- 我''我不热衷于强迫你的A,B等。

的班级继承自MF。特别是在像Python这样的鸭子打字语言中,它没有添加任何值,子类没有从他们的

超类中获得默认行为,而且我并不热衷于使用它继承层次结构为

注册测试类。从

__subclasses __()返回的类的顺序是什么?你总是想要这个订单吗?你总是想要b $ b想要所有的子类吗?如果这是其他人将使用的图书馆的一部分,您可能无法预测其他人可能会在您的MF课程中坚持使用哪些子类。


- 项目列表在调用代码中应该是动态的,而不是由类结构静态构建的
。没有办法预测你想要评估的各种序列是什么。


- 让我们称之为MF类MultiEvaluator。 。有几种方法可以在几种方案中评估


。短路,第一场比赛

。最合适,评估所有并获得最佳分数(假设testit

例程返回double或int,而不是bool)


简称电路,假设你有一个匹配A的案例,你想要

以避免任何与B,C等相关的处理。尽可能在test / do

运行时。你*可能*能够在列表构建上做额外的工作

时间。考虑这两种替代设计:


类MultiEvaluator(对象):

def __init __(自我,*类):

self .testClasses = classes [:]


def findit(self,* args):

for c in self.testClasses:

testobj = C()

if testobj.testit(args [0]):

testobj.doit()


MultiEvaluator(A,B).findit("与A有关)


vs.


class MultiEvaluator(object):

def __init __(self,* classes):

self.testClasses = [C()for C in class]


def findit (self,* args):

for test.j在self.testClasses:

if testobj.testit(args [0]):

testobj .doit()


MultiEvaluator(A,B).findit("与B有关)


在第一种情况下,没有B级是永远建造的,所以如果测试对象建造的价格昂贵,你可能会走这条路。在第二个,A()

和B()是提前构建的,所以运行时处理最快是
- 你可以选择这个如果构造时间可以完成

前面。第二个选项可能会导致多线程问题或者使用共享的MultiEvaluator重新进行
重新入侵。


这种构建MultiEvaluator的方式也会带来更多明确的

(我听说比隐含更好)你在测试什么类?

创建你的MultiEvaluator时。


- To让你的testit()和doit()代码更灵活,更强大
强大,我会将(* args)传递给每个,如:


class MultiEvaluator(object):

def __init __(self,* classes):

self.testClasses = classes [:]


def findit(self,* args):

for c in self.testClasses:

testobj = C()

if testobj。 testit(args):

testobj.doit(args)


- 为了鞭挞OO-ness,你可以制作MultiEvaluator

到一个函数对象,通过改变findit到__ call __。然后你的

调用它会改变:


getObj = MultiEvaluator(A,B)

getObj.findit(" ;涉及B")


至:


getObj = MultiEvaluator(A,B)

getObj( 与B有关)


虽然有些人可能声称这是*更少*明确。这个

的目的是你可以将getObj传递给函数例程,比如map

(虽然你也可以传递getObj.findit)。

这些是我的评论。让我们知道你想要得到什么。


- 保罗

Lee,

Interesting idea, but I think the technique of "inherit from MF to
automatically add class to the test chain" is a gimmick that wont
scale.

Here are some things to consider:

- I''m not keen on the coupling of forcing your A,B,etc. classes to
inherit from MF. Especially in a duck-typing language like Python, it
adds no value, the subclasses receive no default behavior from their
superclass, and I''m not keen on using the inheritance hierarchy to
register test classes. What is the order of classes returned from
__subclasses__()? Will you always want this order? Will you always
want all subclasses? If this is part of a library that others will
use, you may not be able to anticipate what subclasses someone else may
stick on to your MF class.

- The list of items should be dynamic in the calling code, not built
statically by your class structure. There''s no way to anticipate what
various sequences you will want to evaluate.

- Let''s call the MF class "MultiEvaluator". There are several ways to
evaluate among several alternatives:
. short-circuit, take first match
. best-fit, evaluate all and take best score (assuming the testit
routines return a double or int, as opposed to a bool)

For short-circuiting, say you have a case that will match A, you want
to avoid any processing related to B,C,etc. as possible at test/do
runtime. You *might* be able to do extra work at list construction
time. Consider these two alternative designs:

class MultiEvaluator(object):
def __init__(self, *classes):
self.testClasses = classes[:]

def findit(self, *args):
for C in self.testClasses:
testobj = C()
if testobj.testit(args[0]):
testobj.doit()

MultiEvaluator(A,B).findit("relates to A")

vs.

class MultiEvaluator(object):
def __init__(self, *classes):
self.testClasses = [ C() for C in classes ]

def findit(self, *args):
for testobj in self.testClasses:
if testobj.testit(args[0]):
testobj.doit()

MultiEvaluator(A,B).findit("relates to B")

In the first case, no B class is ever constructed, so if test object
construction is expensive, you might go this route. In the second, A()
and B() are built ahead of time, so the run-time processing is the
fastest - you might choose this if the construction time can be done up
front. The second option may cause problems for multi-threadedness or
re-entrancy with a shared MultiEvaluator, though.

This style of constructing the MultiEvaluator also makes more explicit
(which I hear is better than implicit) what classes you are testing
when creating your MultiEvaluator.

- To make your testit() and doit() code more flexible and more
powerful, I''d pass (*args) to each, as in:

class MultiEvaluator(object):
def __init__(self, *classes):
self.testClasses = classes[:]

def findit(self, *args):
for C in self.testClasses:
testobj = C()
if testobj.testit(args):
testobj.doit(args)

- In the interests of flogging OO-ness, you could make MultiEvaluator
into a function object, by changing "findit" to "__call__". Then your
invocation of it would change from:

getObj = MultiEvaluator(A,B)
getObj.findit("relates to B")

to:

getObj = MultiEvaluator(A,B)
getObj("relates to B")

Although some might claim this is *less* explicit. The purpose of this
is that you could then pass getObj to functional routines like map
(although you could also pass getObj.findit).

Those are my comments off the top of my head. Let us know what you
come up with.

-- Paul


这篇关于OO重构试验??的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆