框架接口;有限的还是广泛的、甜蜜的方法同义词?
我正在开发一个 PHP 框架;它一开始是针对特定应用程序的,但是它已经转变为一个更加不可知的 HMVC 风格的平台,我打算将其重新用于进一步的项目。
无论如何,虽然我是该项目的唯一开发人员,但我对开发核心界面的选择有点矛盾。
我的主要问题是(并且我知道这可能被认为有点主观)是创建一个严格的接口来让客户端程序员工作更合适,还是允许更多的灵活性。通过一个示例可以最好地描述这一点:
class MyDataClass{
public function getData($key){}
public function setData($key, $value){}
}
这满足了简单数据注册表的要求(除了实现细节)。这些方法可以通过返回 $this
进行链接,并且可以包含必要的验证逻辑。现在是另一种 PHP 方法:
class MyDataClass{
public function __get($key){}
public function __set($key, $value){}
}
当然,这也可行,并且通过使用 PHP 的魔力提供了干净的实现。现在,我似乎最常采用的方法是:
class MyDataClass{
public function getData($key){}
public function setData($key, $value){}
public function __get($key){ return $this->getData($key); }
public function __set($key){ $this->setData($key); }
}
提供多个入口点是否像此示例所示是一个糟糕的设计选择?我一直认为将所有交互逻辑集中到一个方法中,但允许不同的语法选择,这将是一个好主意。我现在正在重新考虑这一点,赞成采用更严格的切入点。一个不太简单的例子:
class MySuperDataClass implements ArrayAccess{
// these do the work
public function getData($key){}
public function setData($key, $value){}
public function getChild($name){}
public function setChild($name, self $child){}
// these are just sugary synonyms
public function offsetGet($key){}
public function offsetSet($key, $value){}
public function __get($name){}
public function __set($name, self $child){}
// ...
}
想法?
在OZ_的回应之后,我意识到我没有证明我的选择是合理的,也没有理解我的方法的意图。
例如,直接方法调用(例如getData()
)将在控制器中使用,以将数据绑定到视图。
$view->setData('foo', 'bar')
->setData('alpha', 'beta')
->setData('hello', 'world');
而在视图生成中使用 Magic Sugar 是为了提高可读性和简洁性。
<p><?php echo $view['foo']; ?></p>
<p><?php echo $view['alpha']; ?></p>
<p><?php echo $view['hello']; ?></p>
这就是我参加这样一个大会的原因。我仍然认为这是一个很好的方法,但正如这个问题所暗示的那样,我现在持观望态度,支持更好的做法。
另外:性能正在成为一个问题,因为我看到应用程序不断增长,并且这些调用正在迭代地进行,通过使用我将调用堆栈加倍的糖。当然,我知道微优化,但我认为瓶颈潜力会增加,尤其是在处理 PHP 魔法时(如果我被引导正确理解,尤其是 __call()
) 唯一的检查方法是分析,当然;我一直是一个不成熟的优化者,我想改掉这个习惯。打破不良的设计习惯也很重要。
@jgauffin; View 类为此行为实现了 ArrayAccess、Iterator 和 Countable,并使用了 __get/<代码>__set 魔法。这是视图的糖,而调用原始方法来绑定来自控制器的数据。
<?php if($view->canRender('post')): ?>
<div>
<?php foreach($view->post as $post): ?>
<p><?php echo $post['text']; ?></p>
<?php if($post->canRender('comments')): ?>
<div>
<?php foreach($post->comments as $comment): ?>
<p><?php echo $comment['text']; ?>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php endforeach; ?>
</div>
<?php endif; ?>
I'm developing a PHP framework; it started off as application-specific, however it has moved into a more agnostic HMVC-style platform which I intend on re-purposing for further projects.
Anyways, while I'm the only developer on the project as it stands, I'm a bit conflicted on my choices of developing the core interfaces.
My main question is (and I understand this could be deemed slightly subjective) is it more appropriate to create a strict interface through which client programmers will work, or permit a bit more flexibility. This is best described through an example:
class MyDataClass{
public function getData($key){}
public function setData($key, $value){}
}
This satisfies the requirements (save for implementation details) of a simple data registry. The methods are chain-able by returning $this
, and can contain necessary validation logic. Now the alternative PHP approach:
class MyDataClass{
public function __get($key){}
public function __set($key, $value){}
}
Sure that works too, and provides a clean implementation through the use of PHP's magic. Now, the approach I've seemed to take most often is:
class MyDataClass{
public function getData($key){}
public function setData($key, $value){}
public function __get($key){ return $this->getData($key); }
public function __set($key){ $this->setData($key); }
}
Is providing multiple entry points as this example shows a poor choice in design? I always figured it would be a good idea, by centralizing any interaction logic to a single method, but permitting different syntactic choices. I'm now reconsidering this, in favor of a much stricter entry point. A less brief example:
class MySuperDataClass implements ArrayAccess{
// these do the work
public function getData($key){}
public function setData($key, $value){}
public function getChild($name){}
public function setChild($name, self $child){}
// these are just sugary synonyms
public function offsetGet($key){}
public function offsetSet($key, $value){}
public function __get($name){}
public function __set($name, self $child){}
// ...
}
Thoughts?
I realized after OZ_'s response that I hadn't justified my choice, for understanding the intent of my approach.
For instance, direct method calls (getData()
for example) would be used in controllers, to bind data to a view.
$view->setData('foo', 'bar')
->setData('alpha', 'beta')
->setData('hello', 'world');
Whereas magic sugar is used in view generation for readability and brevity.
<p><?php echo $view['foo']; ?></p>
<p><?php echo $view['alpha']; ?></p>
<p><?php echo $view['hello']; ?></p>
This is how I came to such a convention. I still think it's a nice approach, but as this question alludes, I'm on the fence now in favor of better practices.
Also: Performance is becoming a concern, as I see the application growing, and these calls are being made iteratively, by using the sugar I'm doubling up my call stack. Sure, micro-optimization I know, but I would think bottleneck potential increases, especially when dealing with PHP magic (if I've been led to understand correctly, especially __call()
) The only way to check is to profile, sure; I've always been a premature optimizer, a habit I'd like to break. Breaking poor design habits is important too.
@jgauffin; the View classes implement ArrayAccess
, Iterator
and Countable
for this behavior, as well as making use of __get
/__set
magic. This is the sugar for the view, whereas the raw methods are called to bind data from the controllers.
<?php if($view->canRender('post')): ?>
<div>
<?php foreach($view->post as $post): ?>
<p><?php echo $post['text']; ?></p>
<?php if($post->canRender('comments')): ?>
<div>
<?php foreach($post->comments as $comment): ?>
<p><?php echo $comment['text']; ?>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php endforeach; ?>
</div>
<?php endif; ?>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
想法:
关于模式和设计的好书
Thoughts:
Good book about patterns and design
我认为你前进的方向很棒。该接口将具有 setData/getData 方法。您的实现将实现这些方法,为了方便起见,您可以实现 __set / __get 来调用接口方法。
如果另一个程序员想要扩展功能或向您的系统添加插件,他需要确保他的类实现了您的 setData/getData 方法。
I think the direction you are going is great. The interface would have the methods setData/getData. Your implementation would implement those methods and for convenience you could implement __set / __get to call the interface methods.
IF another programmer wanted to extend the functionality or add a plugin to your system he would need to make sure his classes implemented your setData/getData method.
您想通过数据类实现什么目标?
我看不出以下之间的区别:
和
What are you trying to achieve with your data class?
I don't see the difference between:
and