Есть ли лучший способ доступа к сервисам бизнес-логики в веб-приложении? - PullRequest
4 голосов
/ 18 декабря 2008

Есть ли лучшая практика для создания экземпляра / вызова службы уровня бизнес-логики в веб-приложении? У меня есть большое количество сервисов, которые я продолжаю создавать, а затем использовать только для одного вызова метода.

Должны ли они быть реализованы в качестве поставщиков? Или, может быть, доступ из единого?

Пример кода:

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

Очевидно, что это намного сложнее, я просто не знаю, делаю ли я что-то не так, создавая новые экземпляры этих сервисов повсюду.

Ответы [ 4 ]

3 голосов
/ 18 декабря 2008

Я всегда считаю, что лучше иметь слабую связь между уровнями приложений, поэтому я рекомендую вам ввести некоторую степень абстракции между кодом клиента службы (ProductService) и кодом, который его вызывает.

Во многих случаях (я не уверен, что это ваш случай) любая команда может получить доступ к любому другому уровню приложения в виде продукта. Другими словами, другая команда может владеть бизнес-уровнем и потенциально может внести критические изменения в код вашего уровня.

Я бы порекомендовал вам создать фабрику клиентских сервисов для создания экземпляров клиентских объектов и возвращать настраиваемые типы интерфейсов из вашей фабрики, которые предоставляют только выбранные вами элементы. Это обеспечивает не только слабую связь, но и гибкость настройки и настройки ваших клиентских объектов в центральном месте.

Хватит говорить, вот код:

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;
    }
}
3 голосов
/ 18 декабря 2008

Я бы остерегался сингла. Его часто злоупотребляют в местах, где это не всегда нужно. Вы должны использовать только синглтон, если за один раз должен быть только один экземпляр этого класса. В этом примере вы использовали бы синглтон, только если вы хотите одновременно выполнять только одно действие Ship ().

Один шаблон, который мне нравится использовать, - это создание частного поля только для чтения для сервисов в классе, который может выглядеть следующим образом:

public ShippingController
{
    private readonly ProductService productService;

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

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

По крайней мере, таким образом, вы не связаны каким-либо решением, вы можете создать глобальный ProductService, который будет использоваться во всем приложении, или вы можете создать новый экземпляр и передать его таким образом, чтобы у вас было лучшее обоих миров.

То, какой путь лучше, зависит от вашей ситуации. Тщательно продумайте, какие именно требования предъявляются к использованию вашего сервиса, и выполните его соответствующим образом.

2 голосов
/ 18 декабря 2008

Для простого веб-приложения, который я хотел бы задать, я бы задал вопрос: является ли какая-либо конкретная служба с состоянием между вызовами (включая объект подключения к БД и т. Д.)?

  • Да) Создание экземпляра за звонок
  • Нет) Использовать услугу Singleton

Если служба поддерживает состояние между вызовами, тогда она не является поточно-ориентированной. Если между вызовами не поддерживается какое-либо состояние, значит, это так. В конечном итоге вы должны думать о безопасности потоков. Работает ли одна служба со многими клиентами, звонящими ей одновременно?

В любом случае, вы реализуете его, я бы использовал шаблон фабрики, чтобы достичь уровня полиморфизма и отделить создание службы от реализации. Рассмотрим следующий код psuedo-C #:

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

Это дает вам возможность изменить любую услугу на службу с отслеживанием состояния или одноразовую службу в одном месте или на нее.

2 голосов
/ 18 декабря 2008

Я сделал и то, и другое. Это зависит от того, какую цель вы пытаетесь достичь. Если вы пытаетесь увеличить краткость своего кода, поможет одноэтапная / статическая ссылка на службу, которую вы пытаетесь вызвать.

Services.ProductService.Ship(aProduct)

Однако вы должны помнить, что все, что вы помещаете в синглтон, не являющееся естественным синглтоном, создает искусственное узкое место. Если создание / утилизация ваших услуг не требует значительных ресурсов (не будет, если они содержат только бизнес-логику), я бы продолжал делать то, что вы делаете.

Кроме того, создание архитектуры, в которой она вам действительно не нужна, усложняет выполнение кода. Это все решение суда.

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...