Skip to content
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

Converting Stryker4S into Stryker4JVM supporting Scala and Kotlin #1522

Open
YVbakker opened this issue Mar 15, 2024 · 2 comments
Open

Converting Stryker4S into Stryker4JVM supporting Scala and Kotlin #1522

YVbakker opened this issue Mar 15, 2024 · 2 comments

Comments

@YVbakker
Copy link

This was attempted in PR #1291 , but failed due to a complicated git history and lack of momentum.

The goal of this issue is to track the progress on this issue, that is blocking for almost all feature development of stryker4s and the future stryker4jvm kotlin & java projects.

In order to attract more developers and / or momentum, the following should be considered:

  • Build tooling uses Maven, unless otherwise necessary. (e.g. for the build tool implementations)
    • Because Maven is the most compatible with everything, and there is currently a lot of Maven knowledge around (@infosupport HQ)
  • Programming language used is Java, unless otherwise necessary. (e.g. for the existing core, and the language interface implementations)

The basic premise of this refactor is the following:

  • Add a language interface
    • The language interfaces can be written in their own respective language (e.g. Kotlin in Kotlin)
  • Add a build tool interface
    • Build each build tool specific implementation with the respective build tool. (e.g. Gradle w/ Gradle)
  • The common interfaces will be Java for compatibility / interop.

It has been proposed to use ServiceLoaders to load the language interface implementations dynamically into the core at runtime, so that the order of compilation and / or build orchestration is greatly simplified.

StrykerJVM proposal

This was referenced Mar 15, 2024
@hugo-vrijswijk
Copy link
Member

Some things to consider:

Because Maven is the most compatible with everything, and there is currently a lot of Maven knowledge around (https://github.com/infosupport HQ)

I don't think this is necessarily a good reason to use Maven as the main build tool. In the proposed architecture, a lot of code is still Scala. Which means to get up and running with most of the code you'd have to do a lot of switching between build tools. IMO, it makes more sense to use the build tool that's used for most code wherever possible, and only step outside of it when there is no other option (like for build tool plugins).

Programming language used is Java, unless otherwise necessary. (e.g. for the existing core, and the language interface implementations)

I think you underestimate how much code the existing core is 😅. The idea for Stryker4JVM came from the observation that most of the code in Stryker4s (and other Stryker flavours) is not language-specific, but deals with build tools, finding files and code to mutate, managing processes, reporting, etc. This code already exists, and IMO is a very good fit for Scala. For example, the reporter api is expressed as a fs2 Pipe, files are mutated through a fs2.Stream, processes are cats-effect Resources. These are all concepts that don't translate very well to other languages.

I think the least amount of work would be to create a separate language-interface module. That module would have the minimal interfaces needed for language-specific work. I.e. going through text and returning a list of mutants, instrumenting mutants into a new file, etc. It shouldn't have to know anything about reading files from disk, logging, reporting, etc.

The "build tool interface" already exists, in stryker4s-core. The proposed image doesn't fit, as the build tool is the "application" using the core libraries. Since the build tools always have a dependency on core, they always have a dependency on Scala. So, IMO, there's not much benefit to extracting this out to a separate module. There could be some interop advantages to having these in Java, but currently these also rely on very Scala-specific types and libraries. For example, the main entrypoint for a plugin is implementing the abstract class stryker4s.run.Stryker4sRunner which, simplified, has this API:

abstract class Stryker4sRunner {
  def resolveTestRunners(tmpDir: Path): Either[NonEmptyList[CompilerErrMsg], NonEmptyList[Resource[IO, stryker4s.run.TestRunner]]]
}

Which can return a (non-empty) list of compile errors, or Resource's of test-runners, which handle creating and finalization very nicely. This pattern works quite nicely as is, would be difficult to translate to pure Java, and IMO not worth changing anything about.

My suggestion would be something like this:

image

This is closer to the current codebase, only the language interface would have to be extracted (though not to be underestimated!). Not shown are other current modules like api (only contains Logger) and testkit (shared testing code).

Lastly, I'm very excited to get Stryker4JVM running! It will be a big effort either way, but greatly expands the Stryker umbrella ☂️. I do think we have to be careful to also think about the current user base. Stryker4s has around 25.000-35.000 downloads per month. Ideally, the migration to Stryker4jvm should be as smooth as possible. I'm hesitant to put a lot of Java/Maven in Stryker4jvm since I wouldn't call myself a Java developer nowadays. There are no maintainers, contributors or users of Stryker4s at Info Support, and I think it's important to keep the current user base in mind.

@jjkester
Copy link

jjkester commented May 8, 2024

If you'd ask me, for this change we should change the least amount possible. But also focus on maintainability. If we can get some build orchestration working that manages everything without relying too much on assumptions (like having built some subproject first) that would be amazing. Everything else that may be an improvement can be discussed later.

Personally I think this change will aid in getting people enthousiastic about contributing since it can open up a lot of possiblities (many different things people can work on) without the perceived hurdle of having to get familiar with the complete code base and the Scala language. For example, a Java implementation can be built with just Java and a basic understanding of the process.

I think the diagram you suggested is more or less what @YVbakker meant (actually, I created that diagram, hoping to recreate our earlier diagram from memory and apparently failing at that).

After having a chat about this issue with @YVbakker and @Giovds we think the best approach might be to set a goal and split up the work into manageable chunks that can be merged independently. Not necessarily to allow for parallelising the work, but more to avoid the issue we had last time (long running feature branches that become impossible to merge) and avoiding the hurdle of such a big task (personally really feel that one which does not motivate to get started on it).

Maybe it is best to have a (virtual) sit-down and prepare the work as GitHub issues, maybe even in a Project? Don't think we need to know everything upfront, but if we have some idea more issues can be added as we come to them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants