views:

315

answers:

4

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.

+2  A: 

I've done both actually. It depends on what goal you are trying to accomplish. If you're trying to increase the brevity of your code, a singleton / static reference to the service you're trying to call helps.

Services.ProductService.Ship(aProduct)

However, you have to remember that anything you put into a singleton that's not a natural singleton creates an artificial bottleneck. If the construction / disposal of your services isn't resource intensive (it won't be if it just contains business logic) I'd keep doing what you're doing.

Also, creating an architecture where you really don't need one makes the code a bit harder to follow. It's all a judgment call.

Hope that helps!

Zachary Yates
+3  A: 

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.

lomaxx
+2  A: 

For a simple web app I would ask, I would ask this question: Is any given service stateful between calls (including connection object to db, etc)?

  • Yes) Instantiate per call
  • No) Use Singleton service

If the service is maintaining state between calls then it is prolly not thread safe. If it isn't maintaining any state between calls, then it prolly is. Ultimately you have to think about thread safety. Does a single service work with many clients calling it at once?

Either way you implement it, I would use a factory pattern to achieve a level of polymorphism and to separate the instantiation of the service from the implementation. Consider the following psuedo-C#-code:

public static class ServiceFactory
{
  public static T GetService<T>()
  {
    //either instantiate a new service 
    //or retrieve singleton service here base on type T
  }
}

This gives you the benefit to change any service to or from a stateful or singleton service in one place.

Jason Jackson
No, none of the services are stateful, I'd say it really is a per-call sort of thing (to borrow some WCF/webservice terminology)
Jim Anderton
Then I would probably think about doing it with a singleton.
Jason Jackson
+2  A: 

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;
    }
}
Andrew Hare