我的服务方法签名应该如何


How should be my Service method signature?

我正在使用服务层,直到现在我使用的是ServiceObject(它实现了ArrayAccess,Iterator,Countable),但我想知道这是否是一个好主意。

你会做:

ArticleService::createArticle($articleData, $userId);

ArticleService::createArticle(ServiceObject $data);

$data在哪里:

array(
  'title' => 'Lorem ipsum',
  'body'  => 'Dolor sid amet',
  'userId' => 55,
);

ServiceObject 的优点是为每个方法提供通用签名,但有时它看起来效率不高,而且没有被广泛使用,它会失去兴趣。

任何反馈?

将其更改为:

ArticleService::createArticle($title, $body, $user_id);

这非常清楚创建"文章"需要什么。

像您的$articleData$data这样的"选项"数组不可能明智地智能感知,我建议不要这样做。

你的想法扔给一个通用的ServiceObject这实际上是一个非常糟糕的主意。你的动机是高尚的,但这是错误的解决方案。

如果您需要更多说服力,请随时戳。

我认为这里最好的方法是拥有类似的东西

$article = new Article;
$article->title = "Lorem ipsum"
$article->body = "Dolor sit amet"
$article->creator = $userID
ArticleService::createArticle($article)

尽管"createArticle"可能不再是该函数的最佳名称,因为 Article 对象已经创建。你可能会有类似ArticleService::publishArticle($article)的东西,虽然我不知道你在做什么。

你想要的是将数据的构造(Article)与它的使用(ArticleService)分开。

我真正想说的是,不要使createArticle的参数成为泛型数组或"ServiceObject",两者都是参数列表的无用抽象,使其成为真正表示相关实体的类。

我投票支持该对象,因为复杂系统中的代码完成是非常好的事情,并且还有一些自动验证,因为当您知道对象类型时,您可以以某种方式验证它。但是如果你在createSomething中没有复杂的逻辑,那么数组也可以。

第二个更好,你永远不会遇到人们以错误的方式称呼你的方法的问题!阅读和查看所需内容也更容易。对于我作为开发人员来说,很明显我必须传递一个类型 ServiceObject 的对象,然后我开始搜索此类的文档或示例或接口。但是在第一个示例中,我必须阅读 createArticle 的代码才能弄清楚如何处理这两个参数。

第二种方法还将帮助您随着时间的推移保持 API/签名干净。当内部需要一些额外的数据时createArticle您只需通过ServiceObject传递它们,而无需更改签名!

第一个示例的更好签名是:

ArticleService::createArticle(array $articleData, $userId);

在这种情况下$articleData必须是一个数组。这可以防止错误。在 PHP 函数参数中,只能使用数组和类名进行强制转换。

没有正确的方法,但我会在这种特定情况下使用ArticleService::createArticle($articleData, $userId);

我假设文章有一个必需的非空属性 userId(您从上下文中获得)和一个可选(不是很重要)的内容数据,这些数据可能是空的。

这样,文章和用户对象之间的联系就很明显了。可读性略有提高。否则,您需要完全熟悉所需的数据和createArticle方法。

作为证明:当我看到ArticleService::createArticle($articleData, $userId)时,我立即明白了该方法在做什么以及对输入数据的期望,而第二个让我感到困惑。

此外,如果缺少userId,此时将收到错误,而不是在将其插入数据库的那一刻,您可能会遇到更难跟踪的SQL错误。

另一方面,在 ZF 中,使用数组作为参数是很常见的,因此您的代码可能看起来不同。

但是,这主要取决于您的喜好。

我认为更好的方法是注入一个对象。但是为什么服务对象在那里呢?你有一个方法createArticle,那么将文章对象传递给它是合乎逻辑的,不是吗?这样,组织验证过程会更简单,您只需标记要在注释中进行验证的字段。

这也是您使用的方法问题。如果在服务层中使用数据映射器模式,则显然应该向其传递对象。

对于对象,您可以在对象之间拥有透明和清晰的通信接口。对于数组,不清楚您传输什么类型的数据,什么样的字段等等。