J'ai résumé ce qui est populaire en moi ces jours-ci.
Ce qui était initialement préparé comme une opération sur un ensemble est ** trop fin ou trop spécifique **, et il est difficile de comprendre ce que cela signifie pour l'utilisateur du logiciel. Ici, pour un ensemble Nous résumerons les opérations avec une granularité significative pour l'utilisateur.
Différentes méthodes sont définies à l'avance dans la classe (liste ou mappe) qui représente un ensemble. Cependant, il se peut que vous ne souhaitiez pas utiliser des méthodes dans la logique métier. Par exemple, dans le cas d'utilisation de l'agrégation sur un certain ensemble, Il n'est pas nécessaire d'écrire dans l'ensemble. Inversement, l'état de capacité d'écrire peut provoquer un bogue. La méthode d'implémentation introduite ici peut être utilisée pour limiter les opérations à l'ensemble.
Supposons qu'une application Web agrège le nombre d'événements (événements Push) qui se produisent sur GitHub pour chaque référentiel et le partage sur Twitter.
Supposons une configuration multi-modules dans laquelle les éléments suivants sont divisés en modules.
Nom du module | La description |
---|---|
web | Il existe un package Web qui gère les E / S du navigateur et un package d'application qui réalise les spécifications de l'application.. |
domain | Exprimer la logique métier avec des entités et des modèles. |
infrastructure | Implémenter l'interface définie dans la couche de domaine. |
Le code implémente la logique pour agréger le nombre d'événements qui se sont produits sur GitHub pour chaque référentiel Git. Le code est
La classe GitEvent est définie comme suit.
domain.GitEvent.scala
class GitEvent(val gitRepository: GitRepository, val eventType: GitEventType)
Vous pouvez également obtenir une collection de GitEvents via la méthode getUserEvents de GitEventClient.
domain.client.GitEventClient.scala
trait GitEventClient {
def getUserEvents(gitAccount: GitAccount): Seq[GitEvent]
}
Dans un premier temps, j'ai utilisé le service d'application pour effectuer l'agrégation.Peut-être même en entreprise, le service d'application appelle souvent la méthode de la couche d'accès aux données et traite les données acquises.
web.application.GitActivitySummaryService.scala
class GitActivitySummaryService(){
def summarize(userId: UserId): Seq[GitActivitySummary] = {
val accountService: GitAccountService = new GitAccountService()
val gitAccount = accountService.getByUserId(userId)
//Obtenez des événements en fonction des informations de compte Git acquises.
val eventClient: GitEventClient = new GitHubEventClient()
val gitEvents: Seq[GitEvent] = eventClient.getUserEvents(gitAccount)
//Regrouper par référentiel,Informations sur le référentiel,Générer une collection d'instances avec un certain nombre de fois
events.groupBy(e => e.gitRepository).map(e => new GitActivitySummary(e._1, e._2.size)).toSeq
}
}
Le plus gros problème avec ce code est que la logique d'agrégation d'événements peut être implémentée à différents endroits. Par exemple, jusqu'à présent, seule l'agrégation en temps réel était effectuée sur le Web, mais que faire si la demande suivante se présente?
Étant donné que les autorisations sur les ressources sont différentes entre les applications Web et les lots, nous avons décidé de créer un module batch
.
Bien que le lot nécessite la même logique d'agrégation que l'application Web, il ne peut pas être référencé à partir du lot car la logique a été écrite dans le module Web lors de l'implémentation de l'application Web.
I "Je ne peux pas vous aider, copiez la même classe dans le module batch." Tout le monde "Attendez, attendez, attendez."
J'essaie d'automatiser l'agrégation des événements Git, donc je pense que la logique d'agrégation est la plus grande préoccupation de cette application.C'est pourquoi j'ai créé la classe GitEvents
dans le module domain
. ..
domain.gitEvents.scala
class GitEvents (private val events: Seq[GitEvent]) {
def countByRepository() = {
val gitActivitySummaries = events.groupBy(e => e.gitRepository).map(e => new GitActivitySummary(e._1, e._2.size)).toSeq
new GitActivitySummaries(gitActivitySummaries)
}
}
GitEventClient renvoie également une instance de la classe GitEvents, donc Seq [GitEvent] ne peut plus être manipulé directement en dehors de la classe GitEvents. L'encapsulation orientée objet est quelque chose comme ça.
domain.client.GitEventClient.scala
trait GitEventClient {
def getUserEvents(gitAccount: GitAccount): GitEvents
}
En exposant la méthode de la collection de champs via la classe wrapper comme indiqué ci-dessous, il est possible d'opérer la collection de champs comme si elle était gérée directement.
def foreach(f: GitEvent => Unit) = events.foreach(f)
def map[T](f:GitEvent=>T)=events.map(f)
Si nécessaire, vous pouvez implémenter les méthodes définies dans la collection de champs pour fournir l'API à la classe appelante comme si vous manipuliez directement la collection. Vous pouvez également écrire une expression for en implémentant la méthode iterator.
def iterator = events.iterator
for ( event <- events) {
println(event.eventType)
}
Recommended Posts