-2

I have interface and its implementations:

public interface SyntaxConstruction{
    public String parseFromString(String str);
}
public class Copy implements SyntaxConstruction{
    public String parseFromString(String str){ //impl };
}


public class Set implements SyntaxConstruction{
    public String parseFromString(String str){ //impl };
}

I also have the following class:

public class Parser{

    private static List<SyntaxElement> elementPrototypes; //should maintain the list of all implementation's prototypes


    static{
        //Initializing list with prtotypes of all possible SyntaxConstruction's implementations
    }
    public static List<SyntaxElement> parse(String str){ 
        //getting syntax elements from str
    }
}

Now we add a new implementation, say

public class Values implements SyntaxConstruction{
    public String parseFromString(String str){ //impl };
}

If the user who add the class don't update the elementPrototypes list it may lead to hardly-catched bugs. I'd like to make them be awared of updating the list safely?

user3663882
  • 6,957
  • 10
  • 51
  • 92
  • What should he update there? `elementPrototypes` isn't even intialized, so we don't know what it contains :(. If it should contain every implementation, then don't let someone "fill" it and do it yourself by using reflection: http://stackoverflow.com/questions/347248/how-can-i-get-a-list-of-all-the-implementations-of-an-interface-programmatically – Tom May 22 '15 at 12:22
  • @Tom Couldn't you look at updated question? – user3663882 May 22 '15 at 12:23
  • 2
    Writing a new implementation breaks the existing functionality? Smells like bad design. – fabian May 22 '15 at 12:24
  • @user3663882 Couldn't you post your question, _after_ you added all necessary information? – Tom May 22 '15 at 12:25
  • @fabian Not breaks, but doesn't allow Parse just added syntax constructions. – user3663882 May 22 '15 at 12:25
  • 2
    @user3663882 Side note: why are `elementPrototypes` and `parse` static? Do you understand that **static** breaks "good OO design"; and makes a lot of things (like decent unit testing) much harder? – GhostCat May 22 '15 at 12:28
  • @Jägermeister Because I don't need in the instance of Parser to parse Strings. – user3663882 May 22 '15 at 12:29
  • 2
    @user3663882 Ah, that means you are not writing unit tests for your code. Too bad. – GhostCat May 22 '15 at 12:31
  • @Jägermeister How do you know that? – user3663882 May 22 '15 at 12:39
  • 1
    @user3663882 Well, unless you turn to PowerMock and nasty nasty practices ... you must have a very hard time testing classes that use your Parser (unless all your unit tests expect that the Parser does something "real" and never needs mocking). In other words: your Parser, at it is right now, is definitely not written in an "easy-to-test" way. Thus my (probably premature) conclusion is: you are not into easy, solid unit tests. – GhostCat May 22 '15 at 12:43

1 Answers1

2

You could use an abstract implementation that "register" itself (in constructor) into Parser's elementPrototypes, something like:

public abstract class BaseSyntaxConstruction implements SyntaxConstruction {
    protected BaseSyntaxConstruction() {
        Parser.addElementPrototype(this);
    }
}

public class Copy extends BaseSyntaxConstruction {
    public String parseFromString(String str){ 
        // impl 
    }
}

Note that you could also use reflection to "detect" SyntaxConstruction implementations


Following your comment, I think you might want to use an enum here to store implementations, no need to instantiate, no need to register (see values()):

enum SyntaxConstruction {
    COPY {
        @Override
        public String parseFromString(String str){ 
            // impl 
        }
    },
    // ...

    ;

    public abstract String parseFromString(String str) 
}
  • The idea is good, but that could be easily bypassed by not using the abstract class. But I don't know if such behaviour should be considered and prohibited. – Tom May 22 '15 at 12:28
  • You can remove the interface and use the abstract class with a `parseFromString` abstract method => no bypass –  May 22 '15 at 12:31
  • So, the instance are going to be adde only when we try to instantiate them? Maybe I should put, say `Parser.addElementPrototype(new Copy());` into a static initializer? – user3663882 May 22 '15 at 12:31
  • An abstract class without an interface? Isn't this considered a code smell? :P. But yes, this is a possible way. – Tom May 22 '15 at 12:32