Как бороться со сквозными проблемами в OO Application?Использовать синглтон?Внедрение зависимости?Какие? - PullRequest
5 голосов
/ 19 августа 2010

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

У меня вопрос: должен ли я проектировать это как некий Ambient Context (в данном случае Singleton), или я должен попытаться придумать другой способ приспособиться к этому?

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

Как люди обычно справляются с этим? Есть ли какие-либо другие методы, которые могут помочь с этим? АОП может быть?

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

Спасибо

Ответы [ 6 ]

3 голосов
/ 19 августа 2010

Как вы предлагаете, Аспектно-ориентированное программирование (AOP) разработано именно для такого рода вещей, поэтому я, безусловно, проверю это.

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

1 голос
/ 19 августа 2010

Независимо от того, реализуете ли вы его как синглтон, я все же рекомендую передавать его с помощью внедрения зависимостей.Я также рекомендую вам не реализовывать что-либо как singleton самостоятельно и переходить к инфраструктуре DI, предоставляя вам одноэлементный контекст, который подойдет любая библиотека IOC первого класса.

1 голос
/ 19 августа 2010

Что я сделал с AOP:


public abstract aspect AutoInjectAspect<T> {

    /**
     * Implemented by the concrete class to decide what value to return.
     * @param joinPoint
     * @return
     */
    abstract public T getInjectedValue(JoinPoint joinPoint);

    protected pointcut autoInjectField() : get(@AutoInject T *);

    /**
     * override the "get" of the otherwise null value with the 
     *   value to be injected
     * @return the injected field
     */
    T around(): autoInjectField() {
        return getInjectedValue(thisJoinPoint);
    }
}

А потом сделал конкретный аспект:


public aspect SLF4jLoggerInjector extends AutoInjectAspect<Logger> {
    @Override
    public Logger getInjectedValue(JoinPoint joinPoint) {
        Class classInjected = joinPoint.getStaticPart()
                .getSignature().getDeclaringType();
        Logger logger = LoggerFactory.getLogger(classInjected);
        return logger;
    }
}

Затем создайте аннотацию "@AutoInject" и поместите ее в поле, в которое вы хотите вставить.

При этом вы можете также использовать контейнерный маршрут МОК.

1 голос
/ 19 августа 2010

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

public class SomeClassThatDoesStuff
{
    private static readonly ILog log = 
          LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

    public void DoStuff()
    {
         log.Info("Doing something");
    }
}

Ваш глобальный временной класс может показаться похожим типом сквозной задачи, и яподходил бы так же

Я согласен, что делать это с DI будет утомительно и не очень прагматично.

1 голос
/ 19 августа 2010

Если всем это нужно, и это единственный в своем роде (точно так же, как журнал, который вы упомянули), это определенно одиночка.

0 голосов
/ 19 августа 2010

Я думаю, что вы правы, что некоторые типы просто не подходят для внедрения в конструктор;и иногда вам нужно отслеживать какой-то один контекст в более широком смысле, чем внутри набора объектов.

Когда я сталкиваюсь с этой проблемой, я часто создаю Singleton, но у меня есть логический вызов инициализацииструктура внедрения зависимостей, чтобы сделать фактическую реализацию.Это приводит к связыванию с определенным статическим методом (а некоторые будут против этого) - но в то же время я свободен изменять реализацию всякий раз, когда мне это нравится (и, возможно, для некоторых типов есть другая реализация в тестовом проекте,или что-то).И я получаю преимущество, заключающееся в том, что нет необходимости передавать очень общий тип между всеми конструкторами объектов.

Конечно, вы должны делать это только тогда, когда тип действительно , необходимый во многих местах.В противном случае используйте обычный инжектор конструктора.Точно, когда «все в порядке», решать вам.

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