-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Promote Atto parser as a module #601
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good so far, only minor nitpicking from my side
@JSExportTopLevel("Cron") | ||
object Cron { | ||
@FunctionalInterface | ||
trait Parser { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: don't think we need the @FunctionalInterface
annotation here, as it's meant for Java interaction only and don't expect anybody trying to implement their own parsers in Java, considering the return type is Either
.
Also, for more FP-idiomatic style, the trait could be defined as:
type Parser = String => Either[Error, CronExpr]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, I had a warning (promoted as compilation error on CI) asking me to put this annotation.
I can change it for a type definition if it matters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did the change here b1a5571
Do you have an opinion about the migration path for users? |
I would simply make the new Atto parser the default but making it such that source code backwards compatibility is maintained. Meaning that a bumping the cron4s version downstream doesn't require any code changes. However, at least for one or two versions, keep the legacy scala-parser-combinators implementation, which could be simply enabled by having an extra parameter in the This will in fact break binary compatibility so may require a major version bump. i.e.: 0.5.x |
That seams fair.
This one is more a problem. My main goal is to be able to remove the dependency to However, I can make Atto the default and put the scala-parser-combinators version in another module and document how to use it. I'm not sure which problem it solves though.
Ok. |
I don't think that keeping the old parser solves any problem in particular more than potentially prevent it. While it's great that we have tests that we can use to validate both implementations there may be some cases in which the behavior of each the two parsers still differs somehow and I find it polite towards end users to be able to opt out of the new parser, at least in the next version. In following versions the old parser (and opt-out flag) would be removed altogether. I don't mind if the old parser is moved to its own module or kept as is, probably the former is a cleaner implementation. If in a separate module it could also be argued that now the end user needs to choose which parser to use by importing the specific parser module (instead of using a flag to opt-out). However I personally put priority on end user experience and still believe that having a default parser is a much better experience as a consumer of the library, also it allows to a smooth version upgrade: imagine an scenario in which Scala Steward creates an upgrade PR in someone else's repo, if the PR fails due to missing dependencies other users are less likely to look deeply into it and upgrade. Regarding dragging around the dependency on Scala parser combinators, there are ways to make it in the use site, for example if we mark it with I mean, the usage of flag is not a hard requirement, just a quick idea thrown out. I'm open to there strategies that allow end users to opt-out of the new parser, just would like it to be documented and not being super-complicated to do. |
Thank you for your detailed reply. I thing that making Atto the default implementation and putting parser-combinators version in its own module fulfill your end user requirement : for most users, the upgrade will just work, and for people wanting the previous parser, they import the dependency and explicitly instantiate the parser. I will have a look next week and propose a non-draft PR. |
f3db4ec
to
071b36e
Compare
@alonsodomin I updated the PR. Now the I have a (hopefully) last problem: Atto does not have a native version, so I can't build a native I can have some version specific code in |
Hello, specifying different dependencies for each target platform is super easy, you need to use Regarding this refactoring, need to sit through it, as a start not a big fan of it, or even the naming Let's look at the codebase in funcional point of view: The parser itself doesn't depend on all of the classes/traits that have been moved. In fact it should only require the types defined in the My preferred approach would be to make a clean cut between what is required to construct the There is an extra issue I see: the |
Thanks for your feedback.
That would work for me
You probably misread, it's actually
Well, that's another way to do it. I opted for the explicit approach : the user uses If you think the implicit solution is better, let me know and I'll implement it. |
As far as I understand, there's no ADT-like to express Cron expressions. The parsers are instantiating some Implementing this plan would require to:
It's should not be too hard but before I dive into it, do you think there's a better plan? |
ae24bcc
to
737bdc5
Compare
With the last commit, we now have a |
83e6cb7
to
873b26b
Compare
@alonsodomin Did you have the chance to review my last proposal for this PR? |
@mbaechler just took a quick look and it doesn't look bad at all, I like much more than the previous iteration. I have a few observations though, mostly nitpicking:
Other than that, great job on this refactoring! 👍 |
All comments have been handled, you can check one more time @alonsodomin |
LGTM 👍 |
it's still possible to use the parser-combinateor Cron parsing by depending on `cron4s-parserc` articfact an use `cron4s.parserc.Cron`
…is parser of choice
a44a084
to
ea71d52
Compare
This PR moves the current parser (using parser-combinators) into a new module and makes it possible to implement other parsers.
Then it moves atto parser as a module and checks that parser tests are giving the same outputs with both parsers.
This PR is a draft because there's a difficult choice to make.
At this point, users have to add a new dependency (
parserc
) to their projects to useCron
class as previously.There are two solutions.
1/
We could accept that change and write a nice migration documentation, even write a scala steward rule. After all, it's just an additional dependency to add.
2/
The other solution I can see is to rename
core
intoeven-more-core
and changecore
to be an aggregate ofeven-more-core
andparserc
.This solution creates two new dependencies for our users but it would be transparent to them.
We would then just have to find a decent name for
even-more-core
.@alonsodomin What do you think?