سؤال

We have an email plugin which encrypts a mail's attachments when the user sends an email and gives the mail's recipients permissions to decrypt the attachments. The recipient permissions are stored on a server. The logic which executes on click of Send button involves some user prompts too. For example, if some of the recipients are new, the sender is first prompted to confirm that the new recipients would be created on the server.

Designing this system, I felt that the presentation logic constrained my design of business layer. Because there are prompts to be shown to the sender at certain intervals in the processing of Send event, my business services have to broken up into RecipientService and MailEncryptionService, one to register new recipients and other to encrypt attachments, each called by Presentation layer. If however, there were no requirement to prompt the user in between, we could've created a third MailService business component which merged RecipientService and MailEncryptionService and handled the entire business logic of Send in a single ProcessSend operation which could've been called by Presentation layer. I feel this is business logic as it's the same logic which executes in all our supported platforms. Additionally, if this process were happening in a completely silent back-end mode, then maybe it would've been convenient to have a single call for this.

Is this right thinking? Is Presentation logic putting a constraint on Business layer design? Or am I wrong in merging the 2 distinct services into a single MailService? If so, why? How to decide which discrete business services can be merged into higher ones?

هل كانت مفيدة؟

المحلول

It's a good question. Sometimes the complexities of the real world make it harder to see the big picture, and/or are in conflict with our mental models. I'll have to digress a bit before I get to your actual question, but bear with me.

The key idea is that the very core of your application is the (software) model of the business problem you are trying to solve. A software model is simply a software representation of the real problem or process, that is, a way of looking at things, a way of thinking about the domain, and carries with it certain concepts, relationships, and various other ideas. It emphasizes things that are deemed important by the developers, and disregards details that are deemed insignificant. Note that this means that there can be more than one representation. You can model a domain in more then one way, and different ways will have different pros and cons. Some models will be more flexible then others, depending on the kinds of applications you are making. In general, you will not design the best representation on the first go (whatever "best" turns out to mean eventually).

Now, when we talk about the coupling and the direction of dependencies between various software components, we are talking about the technical details of the structure of our system. We want to make sure that changes propagate only in certain directions. However, the real forces that drive the change in the software are people - the business & the users (they need the software to do certain things in a certain way), and the developers (we need to make our software maintainable, etc.)

So, if the business needs the application to show certain prompts in between parts of the flow of a business process, that is an external force that affects, on one level, the application(-specific) logic, but on another, it reflects how they think about the business process itself. In their mind, it has well defined steps (at least in some circumstances or under some conditions). You need to incorporate that in your domain model, so that it represents their actual business process better. If you think about it that way, it is really the business needs that affect both the business logic and, in turn, the application logic. On the technical side, you keep the application logic dependent on the business logic at compile time (the direction of dependencies is towards the business logic), so that changing the details of how you implement the application logic layer doesn't affect the business layer. But whenever the business logic itself changes, it will likely affect other parts of the system (which is why it's considered the core of the application).

Finally, if a need arises for something like a service that executes these steps as single operation, then that means that the business thinks about their business process in two different ways. I.e., there are two realizations of the same general concept. If you want to reuse the same domain model for both cases, then your domain model has to be able to support (represent) both of these - and if your steps are modeled as independent but composable software components, than you can easily do this. If this isn't readily achievable, then you may need to redesign your domain model to some extent, to make sure that it supports both applications. So, as the number of specific applications with specific demands increases, the generality of the reused domain model increases. Except sometimes it will turn out to be impossible, inconvenient or impractical to have a shared domain model, and you may decide that it's better to have two separate models - your conceptual view changes. So, your representation evolves over time (and over different applications), and your job is really to control how that process reflects on the codebase.

In summary, it's not the presentation that constrains your business logic - instead, it's the needs of the business that drive everything.

نصائح أخرى

You shouldn't let presentation logic drive the business logic.

But in your case I'm not sure you are.

You have a requirement to check the existence of recipients before sending. That's a business requirement.

Mail.Send() should fail if the recipients don't exist already

You then have a presentation requirement around creating new recipients, that a popup be shown. But its just doing the same check that your Mail.Send already does. Checking the existence of a recipient.

You could automate the recipient creation if there wasnt this presentation requirement, but perhapse there is an underlying business rule. Maybe a legal requirement!

A user must positively affirm the creation of new recipients

That could be a popup or a check box or a wizard, that's the presentation bit, but the business rule exists underneath.

Ultimately, an application should satisfy specific needs of its users, within a required scope, given the constraints of the domain. (There's relevant info on "Behaviour-Driven Development" (BDD) or "use cases".) In your example it's probably the user requirements that "constrain" both the business layer and the presentation layer. For example, a "user story" supported by the app could be:

As an email sender
I want to be notified about new recipients of my email
So that I (eg, got correct names OR could save them OR not get spammed, etc.)

Of course, there's also a danger to let your business layer depend on the presentation layer -- it's hard to tell without more specifics about the example.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى softwareengineering.stackexchange
scroll top