Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a best practice for accessing business logic services in a web app?

Is there a best practice for instantiating / calling business logic layer service in a web app? I've got a large number services that I keep instantiating and then disposing for just one method call.

Should these be implemented as providers? Or maybe accessed from a singleton?

Example code:

void ShipProduct(){
  ProductService service = new ProductService();
  service.Ship(aProduct);
}

Obviously it's a lot more complicated than that, I just don't know if I'm doing something wrong by creating new instances of these services everywhere.

like image 753
Jim Anderton Avatar asked Dec 22 '22 13:12

Jim Anderton


2 Answers

I'd be wary of the singleton. It's often abused in places where it's not always needed. You should only use a singleton if there should only ever be one instance of that class at a time. In this example, you'd use a singleton only if you wanted to performa exactly one Ship() action at a time.

One pattern I like to use a lot is to create a private readonly field for the services in a class which might look like this:

public ShippingController
{
    private readonly ProductService productService;

    public ShippingController(ProductService service)
    {
         productService = service;
    }        

    void ShipProduct(Product aProduct)   
    {
        service.Ship(aProduct);
    }
}

At least this way, you're not bound by either decision, you could create a global ProductService that is used all over your application, or you could create a new instance and pass it in, that way you can have the best of both worlds.

As for which way is better, it depends on your situation. Think carefully about what the exact requirements for the use of your service are and implement accordingly.

like image 111
lomaxx Avatar answered Dec 25 '22 03:12

lomaxx


I always find it best to have loose coupling between application tiers so I would recommend that you introduce some level of abstraction between your service client code (ProductService) and the code that calls it.

In a lot of cases (I am not sure if this is your case) any given team may access any other tier of the application in a product-like way. In other words, another team may own the business layer and could potentially introduce breaking changes into your tier's code.

I would recommend that you create a service client factory for instantiating client objects and return custom interface types from your factory that only expose the members you choose. This not only gives you loose coupling but also the flexibility to configure and tweak your client objects in a central location.

Enough talk, here is some code:

using System;

// this is your interface that will create the 
// loose coupling that you want
interface IProduct { void Ship(); }

// make sure you generate your proxy code with
// partial classes so you can then create your 
// own parial class to implement the interface
partial class ProductService : IProduct
{
    public void Ship()
    {
        // in here you would do validation
        // and other things and then call the
        // real ship method on the client
    }
}

static class Factory
{
    public static IProduct GetProduct()
    {
        // configure away...do 
        // whatever you need to do...

        return new ProductService() as IProduct;
    }
}
like image 42
Andrew Hare Avatar answered Dec 25 '22 04:12

Andrew Hare