关于使用哪些服务以及按什么顺序的决定是否构成 MVC 控制器方法中的逻辑?

发布于 2024-12-07 01:01:54 字数 1201 浏览 0 评论 0原文

我正在开发的新 ASP.NET MVC 应用程序即将结束,并且我意识到我并没有 100% 明白我的控制器方法中应该发生什么。

操作方法是否更好地决定调用哪些服务/方法以及按什么顺序调用:

AccountService _accountService;
BillingService _billingService;
InvoiceService _invoiceService;

...    

public ActionResult UpgradeAccountPackage(PackageType packageType, int accountId)
{
    _accountService.UpgradeAccountPackage(packageType, accountId);
    _billingService.BillForAccountUpgrade(packageType, accountId);
    _invoiceService.CreateAccountUpgradeInvoice(packageType, accountId);
}

或者是否最好坚持对一个服务进行单一方法调用并允许该方法调用它需要的其他服务/支持方法?

public ActionResult UpgradeAccountPackage(PackageType packageType, int accountId)
{
    // account service upgrades account then calls the BillingService and InvoicService
    // methods called above within this method
    _accountService.UpgradeAccountPackage(packageType, accountId);
}

我倾向于在这里使用第二个示例,因为最初似乎第一个方法会以某种方式构成逻辑,并且意味着 acion 方法必须本质上了解帐户升级过程在我的应用程序中如何工作,这看起来像一件坏事。

然而,现在我的应用程序几乎完成了,它有一个很大的服务层,这种方法导致几乎每个服务都强烈依赖于许多其他服务,并且没有集中的地方来决定业务交易的流程,例如上面提到的那个如上所述,您必须深入研究服务方法才能发现流程。

我正在考虑重构以更类似于上面的第二种方法,或者在控制器和服务层之间引入一个新层来控制流程。

人们倾向于使用第一种方法还是第二种方法?民众的意见是什么?

I am near the end of a new ASP.NET MVC application I have been developing, and I have realised that I am not 100% on what should be goning on in my controller methods.

Is it better for an action method to decide which services/methods are called and in what order like so:

AccountService _accountService;
BillingService _billingService;
InvoiceService _invoiceService;

...    

public ActionResult UpgradeAccountPackage(PackageType packageType, int accountId)
{
    _accountService.UpgradeAccountPackage(packageType, accountId);
    _billingService.BillForAccountUpgrade(packageType, accountId);
    _invoiceService.CreateAccountUpgradeInvoice(packageType, accountId);
}

Or is it better to stick to a single method call to one service and allow this method to call the other services/support method it needs?

public ActionResult UpgradeAccountPackage(PackageType packageType, int accountId)
{
    // account service upgrades account then calls the BillingService and InvoicService
    // methods called above within this method
    _accountService.UpgradeAccountPackage(packageType, accountId);
}

I have tended to go for the second example here, as it seemed originally like the first method would constitute logic in some way, and means the acion method would have to intrinsically know about how the account upgrade process works within my application, which seems like a bad thing.

However, now my application is almost finished it has a large service layer and this approach has led to almost every service having a strong dependency on numerous other services, and there is no centralised place which decides the flow of business transactions such as the one mentioned above, you have to dig around a bit in service methods to discover the processes.

I am considering refactoring to more closesly resemble the second method above, or introducing a new layer in between the controller and service layer which controls the flow of processes.

Do people tend to use the first or second method? What are peoples opinions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

爱她像谁 2024-12-14 01:01:54

我更喜欢第二种方法 - 更容易测试(使用模拟),并且逻辑可供重用。您最终会得到实际业务逻辑的外观,但这并不是坏事。

我不明白为什么你的服务层充满了具体的依赖关系......

要记住的是你希望类依赖于接口,而不是实现。 (然后使用依赖注入工具将其全部串在一起)

在 C# 中,我们可以让一个类实现多个接口。因此,您的服务实现可以实现许多接口,而调用者只需要知道他们需要的部分。

例如,您可能有一个实现 IDepositorIWithdrawerAccountTransactionService。如果您实现复式记账,那么这可能取决于 IDepositorIWithdrawer,实际上,它们仅使用相同的 AccountTransactionService 实例>,但不是必须的,并且实现细节可以在之后更改。

一般来说,一个类对系统中其他类的了解越少越好。

I prefer the second method - much easier to test (using mocks), and the logic is there for reuse. You end up with Facades to your actual business logic, but that's not bad thing.

I don't understand why your service layer is full of concrete dependencies though...

The thing to remember is that you want classes to rely on interfaces, not implementation. (and then string it all together with a Dependancy Injection tool)

In C#, we can have one class implement many interfaces. So your service implementations can implement many interface, and yet the caller need only know about the part they need.

For example, you might have an AccountTransactionService that imlpements IDepositor and IWithdrawer. If you implement double-entry accounting, then that could depend on IDepositor and IWithdrawer, which, in actual fact, just uses the same instance of AccountTransactionService, but it doesn't have to, and the implementation details could be changed afterwards.

In general, the less one class knows about the other classes in the system, the better.

永言不败 2024-12-14 01:01:54

我更密切地使用第一种方法。让控制器控制发生的事情。让服务来决定如何发生。

如果您添加第二层来控制流程流,您的 ActionMethods 是否只会进行一次调用?如果是这样,那么此时看来就没有必要了。

I more closely use the first method. Let the controller control what happens. Let the services decide how that happens.

If you add a second layer to control the flow of processes would that leave your ActionMethods only making the one call? If so, it seems unnecessary at that point.

落日海湾 2024-12-14 01:01:54

您可以拥有一个依赖于多个存储库(而不是其他服务)并定义业务操作的服务层:

public class MyService: IMyService
{
    private readonly IAccountRepository _accountRepository;
    private readonly IInvoiceRepository _invoiceRepository;
    private readonly IBillingRepository _billingRepository;
    public MyService(IAccountRepository accountRepository, IInvoiceRepository invoiceRepository, IBillingRepository billingRepository)
    {
        _accountRepository = accountRepository;
        _invoiceRepository = invoiceRepository;
        _billingRepository = billingRepository;
    }

    public void UpgradeAccountPackage(PackageType packageType, int accountId)
    {
        ...
    }

}

然后让您的控制器将 IMyService 作为依赖项:

public class HomeController: Controller
{
    private readonly IMyService _service;
    public HomeController(IMyService service)
    {
        _service = service;
    }

    public ActionResult UpgradeAccountPackage(PackageType packageType, int accountId)
    {
        _service.UpgradeAccountPackage(packageType, accountId);
        ...
    }
}

我使用存储库和服务将这些多个操作聚合到一个业务事务中。

You could have a service layer which depends on multiple repositories (not other services) and which defines the business operations:

public class MyService: IMyService
{
    private readonly IAccountRepository _accountRepository;
    private readonly IInvoiceRepository _invoiceRepository;
    private readonly IBillingRepository _billingRepository;
    public MyService(IAccountRepository accountRepository, IInvoiceRepository invoiceRepository, IBillingRepository billingRepository)
    {
        _accountRepository = accountRepository;
        _invoiceRepository = invoiceRepository;
        _billingRepository = billingRepository;
    }

    public void UpgradeAccountPackage(PackageType packageType, int accountId)
    {
        ...
    }

}

and then have your controller take IMyService as dependency:

public class HomeController: Controller
{
    private readonly IMyService _service;
    public HomeController(IMyService service)
    {
        _service = service;
    }

    public ActionResult UpgradeAccountPackage(PackageType packageType, int accountId)
    {
        _service.UpgradeAccountPackage(packageType, accountId);
        ...
    }
}

I define simple CRUD operations with the entities on the repositories and the service aggregates those multiple operations into one business transaction.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文