none
Сервисный слой весь из синглетонов. Чего ожидать? RRS feed

  • Общие обсуждения

  • День добрый!

     Недавно столкнулся с довольно-таки объемным веб-проектом.

    У которого все как у всех, только вот сервисные классы представляют синглетоны унаследованный от абстрактного сервисного класса.

    Каждый класс покрывает собой определенную часть бизнес-логики.

    Обычно это все через Dependency Injection реализовывается, а тут так.

    Причем все довольно складно, единственное, что в каждом классе прописано типа (аля копипаст):

     private static ServiceText instance;
            public static ServiceText Instance
            {
                get { return instance ?? (instance = new ServiceText()); }
            }

    И еще: конструкторы - public.

    Вопросы:

    1) где подвох?

    2) какого негатива ожидать от дальнейшего ведения проекта?

    • Изменен тип YatajgaEditor 4 апреля 2015 г. 17:43
    3 апреля 2015 г. 6:11

Все ответы

  • Самое первое – нет безопасности при многопоточности. Второе жёсткая привязка инстацирования объектов, хотя абстрагироваться и применять агрегацию не всегда бывает нужно.

    "какого негатива ожидать от дальнейшего ведения проекта?" - нельзя ответить на данный вопрост не зная проекта и его будущих требований, всё крайне относительно.


    Сделаем содержимое сообщества лучше, вместе!

    3 апреля 2015 г. 6:26
    Модератор
  • А как в этом проекте обстоит дело с модульным тестированием? Полагаю, что очень плохо.

    Подвох синглтонов и статических методов именно в их тестировании.

    Без полного или хотя бы хорошего покрытия тестами тяжело рефакторить проект и добавлять новые возможности.

    3 апреля 2015 г. 7:51
  • Про тесты вообще отдельная песня!

    Тестами покрыты практически все методы сервисного слоя, если это так можно назвать.

    Как это выглядит:

    1) Отдельный тест-проект, ну в принципе как у всех.

    2) На каждый сервисный класс свой класс модульного теста, все удобно, все по папочкам, как и полагается.

    3) В модульных тестах тестируются практически все методы сопряженного с ним класса. Где к объекту обращаются через Instance, где-то вызывает напрямую (он же открыт) конструктор (особенно где нужно передать какие-то аргументы конструктору)

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

    Вообще все очень как-то свободно. Вот это напрягает. И подход немного неожиданный - все-таки привык к DI.

    3 апреля 2015 г. 8:32
  • Продолжаю анализировать код.

    Такое ощущение, что автору претило пользоваться DI, а писать new {ClassName}() каждый раз было лень.

    3 апреля 2015 г. 9:46
  • "В модульных тестах тестируются практически все методы сопряженного с ним класса. Где к объекту обращаются через Instance, где-то вызывает напрямую (он же открыт) конструктор (особенно где нужно передать какие-то аргументы конструктору)" - будет немлохо увидеть немного более полное описание класса.

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


    Сделаем содержимое сообщества лучше, вместе!

    3 апреля 2015 г. 10:00
    Модератор
  • >>>будет неплохо увидеть немного более полное описание класса.

    Ну класс для работы с текстом я показывал и его псевдосинглетон (конструктор не закрыт). Дальше там идут нестатические  конструктор и методы для работы со строками. Класс весьма объемный.

    Интересен класс другой, класс авторизации и работы с пользователями. Выглядит он примерно так:

     public class ServiceAccount : AbstractService
        {
            protected HttpContextBase CurrentHttpContext { get; set; }
            public IAuthenticationManager AuthenticationManager { get; private set; }
            public UserManager<ApplicationUser> UserManager { get; private set; }
            public UserStore<ApplicationUser> UserStore { get; private set; }
    
    
            public static ServiceAccount GetInstance(HttpContextBase httpContextApp = null)
            {
                return new ServiceAccount(httpContextApp);
            }
    
    
            public ServiceAccount(HttpContextBase httpContextApp = null)
            {
                InitUserServices(httpContextApp);
            }
    
    protected void InitUserServices(HttpContextBase httpContextApp=null)
            {
                UserStore = new UserStore<ApplicationUser>(CreateCurrentContext());
                UserManager = new UserManager<ApplicationUser>(UserStore);
                UserManager.UserValidator = new UserValidator<ApplicationUser>(UserManager) { AllowOnlyAlphanumericUserNames = false };
                UserManager.UserTokenProvider = new EmailTokenProvider<ApplicationUser, string>();
    
                if(httpContextApp!=null)
                    AuthenticationManager = httpContextApp.GetOwinContext().Authentication;
            }
    
    
    // далее идут методы для авторизации, и работы с пользователями
    
    }

    Здесь вообще нет как такового синглетона. Каждый раз статический метод отдает новый объект класса.

    Вызывается статический метод в контроллере для работы с пользователями Initialize - возращаемый экземпляр присваивается Свойству контроллера. С этим свойствам ведется работа во всех экшенах.

    >>>

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

    >>>

    Вы имеете в виду асинхронные экшены в контроллере?

    3 апреля 2015 г. 11:48
  • Не внушает оптимизма зависимость от HttpContextBase в сервисном слое.

    "Вы имеете в виду асинхронные экшены в контроллере?" нет асинхронность тут непричём. Обычный режим работы.


    Сделаем содержимое сообщества лучше, вместе!

    4 апреля 2015 г. 17:42
    Модератор
  • >>>Не внушает оптимизма зависимость от HttpContextBase в сервисном слое.

    Согласен, но благо там можно проигнорировать этот аргумент и все методы, кроме 3х (методы авторизации) - будут работать.

    Хотя все равно можно запутаться.

    >>>Обычный режим работы.

    А не подскажите где можно об этом почитать?

    Про одновременный вход в секцию инициализации. Тут обнаружился пробел в знаниях.

    6 апреля 2015 г. 7:40