We are developing a platform, where many developers will be writing their own ETL applications that use a vendor's API that is then submitted for execution onto the platform. We want to constrain developers from just dong their own thing when writing a Main class (that would normally just use the vendor's API), in order to promote some strongly-held conventions. The (large) organisation has a culture of people doing their own thing which over years has resulted in some pretty nasty architecture, so we'd like to impose some best practice conventions that can be enforced by way of CI/CD which will help foster code sharing. The alternative will be a reversion-to-the-norm free for all, which we are desperate to avoid.
How do we determine what the main class of an application is? How can we test for this? We'd like to define either an abstract class or interface that the developers make use of, which will define some up-front promises that the developers must abide by (or else the tests will fail). We can't modify the vendor's code.
So, more concretely, currently we have:
public class MyNastyFreeForAll {
public static void main(String[] ) {
//...
}
}
Is there a way of detecting/enforcing something like:
public class MyConventionEnforcingClass implements/extends MyConventions {
public static void main(String[] ) {
//...
}
}
i.e. test that the main class for the application uses something derived from MyConventions
?
Ideally, I want to run the test using Spock.
Alternatively, is there a better way to achieve this aim? Code reviews in an organisation this size amongst lots of separate teams with no central control/hierarchy just isn't going cut it, I'm afraid.
EDIT TO REFLECT INPUT FROM COMMENTS:
At its heart, this is a people problem. However, the people number in their 1000s and cultural change will not happen overnight. It will not happen simply by educating, documenting and influencing and thereby hoping that people will do the right thing. I am looking for a technical solution that can gently steer our developers into doing the right thing - they can always subvert this if they wish, but I want to require them to go out of their way to do so if they want to do this. It is because I am seeking a technical solution that I am posting on SO, not seeking guidance on how to drive cultural change on another site.
EDIT TO PROVIDE MCVE:
Here's an example using an abstract class. It would be nice to validate (at compile or test time) that the main class derives from MyConventions
. If a user wants to actively subvert this, then so be it - you can lead a horse to water and all that - but I'm trying to make it easier for end-users to do the right thing than to not do the right thing. Simply giving them a class that does the boilerplate for them is not likely to suffice, as these users like to do their own thing and would likely ignore you, so there should be some form of light-touch technical enforcement. There is no attempt to impose convention on doProcessing()
but the same principles could be used to add pre- and post- methods etc to achieve this.
If there is another way of achieving this aim then I'd be very interested in ideas.
// MyNastyFreeForAll.java
// written by end-user
public class MyNastyFreeForAll {
public static void main(String[] args) {
MyNastyFreeForAll entrypoint = new MyNastyFreeForAll();
entrypoint.doBoilerplate();
entrypoint.doProcessing();
}
private void doBoilerplate() {
// lot of setup stuff here, where the user can go astray
// would like to provide this in a class, perhaps
// but we need to be able to enforce that the user uses this class
// and doesn't simply try to roll their own.
System.out.println("Doing boilerplate my own way");
}
private void doProcessing() {
// more things that the user can misuse
System.out.println("Doing doProcessing my way");
}
}
// MyConventions.java
// written by team that knows how to set things up well/correctly
public abstract class MyConventions {
public void doBoilerplate() {
System.out.println("Doing boilerplate the correct way");
}
public abstract void doProcessing();
}
// MyConventionsImpl.java
// written by end-user
public class MyConventionsImpl extends MyConventions {
public static void main(String[] args) {
MyConventions entrypoint = new MyConventionsImpl();
entrypoint.doBoilerplate();
entrypoint.doProcessing();
}
public void doProcessing() {
System.out.println("Doing doProcessing my way");
}
}