Parser::parse functions and ParseContext is member of state, allowing for default constructor#770
Conversation
|
Thank you - this was interesting. I think it is difficult to find the right balance between explicit (and typically verbose) and simple to use. Without really thinking it through my instinctive reaction is to go for the explicit and verbose solution; and come on - we are paid to do this! Seriously I guess the important question is to what extent it is simple/possible to misunderstand the API and use it incorrectly. If the API can easily be used wrong[1] I think explicit is good. For the current PR I do not think the API is easily misunderstood; so in this case I guess simplicity should win. But I will let the PR linger here for some time, and invite other developers to voice an opinion on the general matter. To take it one step further I think this PR should be updated with the same default behavior for the [1]: Of course if possible the best thing would be to fix the API. |
|
Inspired by @jokva, and in the same line of simplification - we could create static methods which instantiate and subsequently discard a parser: Deck Parser::createDeck( const std::string& inputFile , ParseContext parseContext = ParseContext()) {
Parser parser;
return parser.parseFile( inputFile , parseContext );
}
EclipseState Parser::createState(const std::string& inputFile , ParseContext parseContext = ParseContext()) {
auto deck = Parser::createDeck( inputFile , parseContext );
return EclipseState( deck , parseContext );
} |
Actually it starts with a (0) create parser. |
| namespace Opm { | ||
|
|
||
| EclipseState::EclipseState(std::shared_ptr<const Deck> deck, const ParseContext& parseContext) : | ||
| EclipseState::EclipseState(std::shared_ptr<const Deck> deck, const ParseContext parseContext) : |
There was a problem hiding this comment.
It's pretty pointless to pass something as a const copy (because the copy is local anyway, and modifications won't bubble outwards).
Free function - they only use the public interface of |
Well - the suggestion to use a static method was all about namespacing. |
|
(This is to the discussion about simple free or static methods for simplifying opm-parser usage.) One idea could be to have a facade class for all things the parser creates. Essentially you'd give it the deck filename and ParseContext (with default) as a constructor argument and it creates the Parser, Deck and Eclipsestate. These objects (and the EclipseGrid) are then available by simple accessor methods. It would make for a simple one-stop solution while simultaneously being flexible enough for any application. What do you think? |
|
It doesn't need |
I agree with @jokva here - when "the harm is done" we don't really neither the
Actually the |
|
So an EclipseState constructor taking filename and optional ParseContext? That sounds quite nice actually. There are parts of the code that need direct Deck access and could not use this, although the need is reduced for every little part that gets into the EclipseState. |
In principle yes; whether it is a static method on the Parser (my favorite), an |
| DeckConstPtr deck = parser->parseFile("testdata/integration_tests/IOConfig/RPTRST_DECK.DATA", parseContext); | ||
| EclipseState state( deck , parseContext ); | ||
|
|
||
| auto state = Parser::parse("testdata/integration_tests/IOConfig/RPTRST_DECK.DATA"); |
There was a problem hiding this comment.
@joakim-hove This is perhaps the most typical example where such a parser function could be nice to have.
There was a problem hiding this comment.
I don't like the name of the method (parse()): IMO this name applies to parsing in-memory data as equally as to parsing files, network resources and god knows what. what's wrong with parseFile(), parseString(), etc?
There was a problem hiding this comment.
Nothing wrong, but the main reason I chose parse was because there are already functions with the names you mention, with the same input parameters, but different return value. One possibility would be to hijack these names, but I think they are very widely used; DeckPtr parseFile and DeckPtr parseString etc.
There was a problem hiding this comment.
I think parse() is a way too generic name (and IMO it is also unclear that it returns an EclipseState while Parser::parse*() returns Deck objects). That said, I nowadays see myself primarily as a downstream user of opm-parser, so I don't have a real problem with it...
|
I just want to stress again that this is not ready to be merged and (for the moment) intended for educational purposes. |
Sure. PS: you can update the PR description at the very top! |
| }; | ||
|
|
||
| EclipseState(std::shared_ptr< const Deck > deck , const ParseContext& parseContext); | ||
| EclipseState(std::shared_ptr< const Deck > ); |
There was a problem hiding this comment.
Since this constructor is new, can we use Deck& over std::shared_ptr< Deck >?
There was a problem hiding this comment.
I am not sure, but I can try. It would imply that EclipseGrid can be constructed from a reference. I don't think it is impossible, but I don't know how far that would propagate. Investigating now.
There was a problem hiding this comment.
EclipseGrid and EclipseState now have constructors accepting references to Deck instead of shared_ptr's.
It took some refactoring; I had to tweak the constructors of NNC, Schedule, and InitConfit to accept Deck& instead of DeckPtr as well.
But all in all, I think this is a good change that we should cherry-pick if we don't want this entire PR.
There was a problem hiding this comment.
Since this constructor is new, can we use
Deck&overstd::shared_ptr< Deck >?
don't forget to mark it explicit. (that's also a good idea in its current form.)
* EclipseState now copies input ParseContext and keeps it as member * Made the argument (ParseContext) default as ParseContext() * Now you can make a new EclipseState with only deck as argument * Removed test that tested address equality of ParseContext objects
ParseContext is member of state, allowing for default constructor