如何设计合理的service?
今天碰到一个bug,最后发现原因应该就是service的设计不当(另一个提问)
那么我们应该如何设计合理的service?有哪些要注意的?什么才是好的service?有哪些的例子可以参考?
回复内容:
今天碰到一个bug,最后发现原因应该就是service的设计不当(另一个提问)
那么我们应该如何设计合理的service?有哪些要注意的?什么才是好的service?有哪些的例子可以参考?
我的解决办法如下,有什么缺点请指教:
Service应该分为2种:1,名词Service; 2, 行为Service
如:UserService 与 RegisterService
对于【名词Service】其里面每个method都必须返回相应的对象,如UserService下的upgrade(uid)就必须返回被升级后的user对象。
对于【行为Service】只对外暴露出一个execute(data),excute(data)必须返回行为成功与否的状态以及被施加这个行为的对象,如RegisterService下的excute(data)就必须返回注册成功与否,以及如果成功了它影响的对象。
通常我们约定对外只调用【行为Service】,再在【行为Service】里调用多个【名词Service】和其他【行为Service】,如在RegisterService::execute(data)里调用UserService::create(), UserService::markNewbee(uid),SendEmailService::execut()等;
【名词Service】中允许调用别的【名词Service】,但不允许调用【行为Service】,如UserService::upgrade不单单可以修改user也可以调用LogService::create来创建log,但不能调用LogoutService::execute()来登出用户。
可以简单的理解为一个Model处理它那张数据库表,一个【名词Service】处理多个Model,一个【行为Service】处理多个【名词Service】,这里【行为Service】也就是设计模式里的facade,可以配合command模式使用。
所有Service的每个method的入参都可以是id或者对象实例,如upgrade()可以接受uid也可以接受user作为入参。
回到我的另一个提问,可以这么写
<code>class AService { function get(aid_or_object) { if (aid_or_object instanceOf A) { return aid_or_object; } return A.getById(aid); } } class PService { function get(pid_or_object) { if (pid_or_object instanceOf P) { return pid_or_object; } return P.getById(pid); } } class Do2Service { function execute(aid_or_object, pid_or_object = null) { a = AService.get(aid_or_object); if (pid_or_object instanceOf P) { p = pid_or_object } else { p = PService.get(a.pid); } p.s = 'zz'; p.save(); a.save(); return [:success, a, p]; } } class Do3Service { function execute(pid_or_object) { p = PService.get(pid_or_object); p.s = 'cc'; p.save(); return [:success, p]; } } class Do1Service { function execute(pid_or_object) { p = PService.get(pid_or_object); p.s = 'yy' if condition1 result, a, p = Do2Servce.execute(p.aid, p) if condition2 result, p = Do3Servce.execute(p) if condition3 p.a = 'a'; p.b = 'b'; p.save() return [:success, p, a]; } } </code>
你的问题的本质,是两个“主语”(只是在你的案例中恰好都是service而已)的各自一个“行为”(do1 和 do2)含有了完全相同的一个“行动效果”(修改p.s的值)。
冲突不在于service,而在于行动效果冗余。
试想一下,换一个案例,其中只有一个主语,两个行为(do1 和 do2)都是它的,那么问题也是等价的。
两个行为有重叠的行动效果,实在太常见的了。
关键在于,你怎样界定,哪种重叠是满足需求的?哪种是错误、不合理的?
举一个满足需求的例子:
需求是:p是一个鼠标悬停的tips(界面组件)。先根据鼠标坐标,赋值p.top为一个值。随后,计算tips是否超出了窗口边缘。如果是,则计算tips的top的最大值(因为窗口大小可能会被改变,所以需要计算),然后赋值p.top为该最大值。p.left同理。
这是我做网页前端开发时遇到过的需求。
你的解决办法,大概可以解决你的那一个具体案例,但换成别的情况可能就又不对症了。
在我看来,关键在于,一个行为的源头(往往是事件)所导致一连串行动效果,其中要避免出现重叠;除非需求要求必要的重叠。
这“一连串”的“串法”,是设计上要想清楚的。你已经在朝这个方向努力了,只是关注点稍有偏离。
至于串的过程中的对象(主语/宾语)是不是service、是何种service,倒是没有关系。

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

AI Hentai Generator
Générez AI Hentai gratuitement.

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds

PHP 8.4 apporte plusieurs nouvelles fonctionnalités, améliorations de sécurité et de performances avec une bonne quantité de dépréciations et de suppressions de fonctionnalités. Ce guide explique comment installer PHP 8.4 ou mettre à niveau vers PHP 8.4 sur Ubuntu, Debian ou leurs dérivés. Bien qu'il soit possible de compiler PHP à partir des sources, son installation à partir d'un référentiel APT comme expliqué ci-dessous est souvent plus rapide et plus sécurisée car ces référentiels fourniront les dernières corrections de bogues et mises à jour de sécurité à l'avenir.

Visual Studio Code, également connu sous le nom de VS Code, est un éditeur de code source gratuit – ou environnement de développement intégré (IDE) – disponible pour tous les principaux systèmes d'exploitation. Avec une large collection d'extensions pour de nombreux langages de programmation, VS Code peut être c

Ce tutoriel montre comment traiter efficacement les documents XML à l'aide de PHP. XML (Language de balisage extensible) est un langage de balisage basé sur le texte polyvalent conçu à la fois pour la lisibilité humaine et l'analyse de la machine. Il est couramment utilisé pour le stockage de données et

Une chaîne est une séquence de caractères, y compris des lettres, des nombres et des symboles. Ce tutoriel apprendra à calculer le nombre de voyelles dans une chaîne donnée en PHP en utilisant différentes méthodes. Les voyelles en anglais sont a, e, i, o, u, et elles peuvent être en majuscules ou en minuscules. Qu'est-ce qu'une voyelle? Les voyelles sont des caractères alphabétiques qui représentent une prononciation spécifique. Il y a cinq voyelles en anglais, y compris les majuscules et les minuscules: a, e, i, o, u Exemple 1 Entrée: String = "TutorialSpoint" Sortie: 6 expliquer Les voyelles dans la chaîne "TutorialSpoint" sont u, o, i, a, o, i. Il y a 6 yuans au total

Java 8 présente l'API Stream, fournissant un moyen puissant et expressif de traiter les collections de données. Cependant, une question courante lors de l'utilisation du flux est: comment se casser ou revenir d'une opération FOREAK? Les boucles traditionnelles permettent une interruption ou un retour précoce, mais la méthode Foreach de Stream ne prend pas directement en charge cette méthode. Cet article expliquera les raisons et explorera des méthodes alternatives pour la mise en œuvre de terminaison prématurée dans les systèmes de traitement de flux. Lire plus approfondie: Améliorations de l'API Java Stream Comprendre le flux Forach La méthode foreach est une opération terminale qui effectue une opération sur chaque élément du flux. Son intention de conception est

Python est un langage d'introduction à la programmation idéal pour les débutants grâce à sa facilité d'apprentissage et ses fonctionnalités puissantes. Ses bases incluent : Variables : utilisées pour stocker des données (nombres, chaînes, listes, etc.). Type de données : Définit le type de données dans la variable (entier, virgule flottante, etc.). Opérateurs : utilisés pour les opérations mathématiques et les comparaisons. Flux de contrôle : contrôlez le flux d'exécution du code (instructions conditionnelles, boucles).

Java Made Simple : Guide du débutant sur la puissance de programmation Introduction Java est un langage de programmation puissant utilisé dans tout, des applications mobiles aux systèmes d'entreprise. Pour les débutants, la syntaxe de Java est simple et facile à comprendre, ce qui en fait un choix idéal pour apprendre la programmation. Syntaxe de base Java utilise un paradigme de programmation orienté objet basé sur les classes. Les classes sont des modèles qui organisent ensemble les données et les comportements associés. Voici un exemple simple de classe Java : publicclassPerson{privateStringname;privateintage;

Python permet aux débutants de résoudre des problèmes. Sa syntaxe conviviale, sa bibliothèque complète et ses fonctionnalités telles que les variables, les instructions conditionnelles et les boucles permettent un développement de code efficace. De la gestion des données au contrôle du flux du programme et à l'exécution de tâches répétitives, Python fournit
