Могу ли я вызвать вызовы make runtime решили в Java? - PullRequest
2 голосов
/ 14 января 2011

Я знаю, что есть функция вызова, которая делает вещи, я в целом заинтересован в "правильности" использования такого поведения. Моя проблема заключается в следующем: У меня есть объект Service ведьма содержит методы, которые я считаю службы. То, что я хочу сделать, это изменить поведение этих служб без последующего вмешательства. Например:

class MyService {

      public ServiceResponse ServeMeDonuts() {
      do stuff...
      return new ServiceResponse();

}

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

Поэтому я прихожу и добавляю что-то в свой реестр, сообщая системе, что «NewClient» ведет себя по-другому. Поэтому я сделаю что-то вроде этого:

public interface Behavior {
    public void preExecute();
    public void postExecute();
}

public class BehaviorOfMyService implements Behavior{
      String method;
      String clientType;

      public void BehaviorOfMyService(String method,String clientType) {
              this.method = method;
              this.clientType = clientType;
      }

      public void preExecute() {

        Method preCall = this.getClass().getMethod("pre" + this.method + this.clientType);
        if(preCall != null) {
            return preCall.invoke();
        } 
           return false;
      }

      ...same for postExecute();
     public void preServeMeDonutsNewClient() {
           do the stuff...
     }
}

когда система сделает что-то подобное

if(registrySaysThereIs different behavior set for this ServiceObject) {
      Class toBeCalled = Class.forName("BehaviorOf" + usedServiceObjectName);
      Object instance = toBeCalled.getConstructor().newInstance(method,client);
      instance.preExecute();
      ....call the service...
      instance.postExecute();
      ....
}

Меня не особо интересует правильность кода, как правильность мышления и подхода. На самом деле я должен делать это на PHP, который я считаю поп-музыкой программирования, которую я должен «петь» по коммерческим причинам, хотя я и играю в POP, я действительно хочу петь по книге, так что отложу свои или менее вдохновляющая аналогия. Я действительно хочу узнать ваше мнение по этому вопросу, потому что это практическая необходимость и технический подход.

Спасибо

Ответы [ 3 ]

1 голос
/ 14 января 2011

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

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

Это просто еще один пример ухудшения кода из-за страха сломать что-то, что работает.В конце концов, любое изменение может потенциально сломать вещи, и, пройдя через болезненные искажения, чтобы каким-то образом изолировать изменения от "хорошего" кода и, тем не менее, заставить их работать, закончится только страданием.

1 голос
/ 14 января 2011

Хороший случай для применения Аспектно-ориентированное программирование .С помощью AOP вы можете прикрепить aspects к событиям или методам для обработки дополнительной логики до или после события.

Здесь есть хорошие примеры AOP , а также примеры для Java here

Этот пример использования aspectwerkz очень похож на ваш случай, в основном добавляя обработчики post и pre для выполнения службы.

I'mне совсем знаком с AOP в PHP, но есть некоторые проекты, которые вы можете использовать, например .

0 голосов
/ 14 января 2011

Вам нужен прокси-сервер, с помощью которого вы определяете некоторое дополнительное поведение независимо от объекта, который проксируется.Например:

public class ServiceHandler implements InvocationHandler {
    private final Object target;

    public static Object createProxy(Object target) {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), 
            target.getClass().getInterfaces(), new ServiceHandler(target));
    }

    public ServiceHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable {
        // define preexecute behaviour
        Object result = method.invoke(target, args);
        // define postexecute behaviour
        return result;
    }
}

Затем вы будете использовать его следующим образом:

    public static void main(String[] args) {
        Service serviceImpl = new ServiceImpl();
        Service service = (Service) ServiceHandler.createProxy(serviceImpl);
        // use service
    }
...