Pergunta

I am trying to refactor a huge chunk of our software, and it requires to set up a factory. However, I am not sure where lies its responsibility.

(PS: The code below is shown simply as an illustration and may not be perfectly designed, please do not unleash hell on it :()


Should the factory only return the correct instance to its parent ?

public class UsingFactory {
      public String getToken(ModelEnum parameter)    {
          Tokenizer tokenizer = MyFactory.getTokenizer(parameter);
          return tokenizer.getToken();
      }
}

public static class MyFactory    {
      public Tokenizer getTokenizer(ModelEnum parameter)   {
            // return whatever Tokenizer needed
      }
}

Or could it already return a token ?

public class UsingFactory {
      public String getToken(ModelEnum parameter)    {
          return MyFactory.getToken(parameter);
      }
}

public static class MyFactory    {
      public String getToken(ModelEnum parameter)   {
            Tokenizer tokenizer = getTokenizer(parameter);
            return tokenizer.getToken();
      }
}

I can't see whether of them is the best, even if the first option seems, to me, to apply better to SRP. Could this factory be in charge of returning a String token directly, or should it first return the instance of the correct Tokenizer class ?

Foi útil?

Solução

Some tips that could help you out to decide.

  1. Decide what you want the Factory to produce: tokens or tokenizers.

  2. Then change the name MyFactory to something more descriptive. TokenFactory or TokenizerFactory (based on your previous decision).

Still doubtful? Keep it simple. Segregate concerns.

As you said, option #1 is the more canonical implementation of a factory of the two. So far so good. While option #2; well, some may argue that it violates the factory's main responsibility. However, as @Neil's answer says, it depends on what you really want the factory to produce (hence the tips). Right now is open to interpretation.

If I'm allowed to suggest, if I had to choose, I would start by breaking the ambiguity changing the factory's name to TokenizerFactory. Then, I would go option #1 because its logic remains true the definition of a factory. The second is something else.

Additionally, to easier the tokens retrieving, I would do it from a different component. Say, a utility class (to mention any).

public static class TokenUtils{
   private TokenUtils(){}
   public static final String retrieveToken(ModelEnum parameter){
      return new MyTokenizersFactory().getTokenizer(parameter).getToken();
   }
}

Or as a regular class

public class ModelEnumTokenRetriever implements TokenRetriever<ModelEnum> {
   private final ModelEnumTokenizersFactory tokenizerFactory;
   private ModelEnumTokenRetriever(ModelEnumTokenizersFactory tokenizerFactory){
      //assert tokenizerFactory is not null
      //then
      this.tokenizerFactory = tokenizerFactory;
   }
   public static final String retrieveToken(ModelEnum parameter){
      return new tokenizerFactory.getTokenizer(parameter).getToken();
   }
}

This way, both responsibilities, how to obtain tokenizers and how to obtain tokens are segregated.

The segregation allows us to tie the rest of the source code to one or another based on the needs.


Note: Note that KIS is not always synonym of less code. Usually, good practices lead us to write more code, but easier to understand or easier to read. Mine is one possible approach of the many. We have to find the approach that best adapts to our needs

Outras dicas

So what you're asking is should you write a TokenFactory or a TokenizerFactory? Both are ultimately being used for the scope of producing tokens, but one would require an additional step.

Is that a bad thing? No, it entirely depends on what you're trying to accomplish. Does Tokenizer do something other than provide a token? If so, what? The reason I ask is because if it has other functionality, there is a certain logic towards having a TokenizerFactory, since you're effectively modularizing the creation of Tokenizer instances throughout your program, not only in the place where you need tokens.

If on the other hand, you only need to create tokens, then I believe that what you need is a TokenFactory, and not a TokenizerFactory (I humbly disagree with Laiv's answer here in this specific instance that you'd necessarily need an additional class). The factory becomes slightly more complex, but it removes what would otherwise be an unnecessary step towards retrieving the token. And in the general case, an overly complicated means of creating a token might merit its own class, but I would argue that this is not your case.

Please note that this solution should not be considered if you think this may change in the future, but it would seem to me that your Tokenizer class is not likely going to do anything other than return tokens.

A Factory of any kind should only create an instance of an object. The method is often called Create to make that obvious.

I would suggest to use the first example.

Please consider also WHY you are using a factory in general. Considering you are refactoring a huge code base.

In your example using a factory does not make sense at all. It actually adds a dependency to MyFactory to UsingFactory. Now UsingFactorydepends on Tokenizer AND MyFactory. When you use new Tokenizer() directly you will have one dependency less.

Be aware! Depending on concrete classes is bad practice in general, but this is off topic now.

Licenciado em: CC-BY-SA com atribuição
scroll top