A colleague did some refactoring and moved a method to a superclass to be able to reuse it from an other child-class, too. The IDE handled that quickly and without any complains.
That method, however, internally referred to a constant which was not moved with the method, i.e. the parent class thus now referred to a constant in one of its child-classes which of course is a no-no!
How can I phrase an ArchUnit rule that prevents such references from parent to members/methods/local classes and enums/etc. in child-classes (or in general: anything in classes further down the hierarchy)?
For direct dependencies, you can use the following custom ArchCondition:
#ArchTest
ArchRule rule = noClasses().should(new ArchCondition<JavaClass>("depend on their children") {
#Override
public void check(JavaClass parentClass, ConditionEvents events) {
parentClass.getDirectDependenciesFromSelf().stream()
.filter(dependency -> dependency.getTargetClass() != parentClass
&& dependency.getTargetClass().isAssignableTo(parentClass.getName()))
.forEach(dependency -> events.add(satisfied(dependency, dependency.getDescription())));
}
});
It can easily be adapted to also catch transitive dependencies such as in this example:
class Parent {
Friend friend;
}
class Friend {
Child child;
}
class Child extends Parent {
}
You can basically replace getDirectDependenciesFromSelf with getTransitiveDependenciesFromSelf:
#ArchTest
ArchRule rule = noClasses().should(new ArchCondition<JavaClass>("depend on their children") {
#Override
public void check(JavaClass parentClass, ConditionEvents events) {
parentClass.getTransitiveDependenciesFromSelf().stream()
.filter(dependency -> dependency.getTargetClass() != parentClass
&& dependency.getTargetClass().isAssignableTo(parentClass.getName()))
.forEach(dependency -> events.add(satisfied(dependency, parentClass.getName()
+ " (transitively) depends on its child: " + dependency.getDescription())));
}
});
FYI: I'm using the following static imports:
import static com.tngtech.archunit.lang.SimpleConditionEvent.satisfied;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
Related
A simplified version of what I'm trying to do in Groovy:
class Animal {
static def echo() {
println this.name // ie "class.name"
}
}
class Dog extends Animal {
}
class Cat extends Animal {
}
Dog.echo()
Cat.echo()
// Output:
// => Animal
// => Animal
//
// What I want:
// => Dog
// => Cat
I think what I'm asking here is: when I call a static method on an object, and
the static method is defined in the object's superclass, is there a way to obtain
the actual type of the object?
A static method is not defined in the object context, but in the class context. You might get confused by the presence of this in the Groovy static method. However, it's only a syntactic sugar that eventually replaces this.name with Animal.class.name.
If you compile the Animal class from your example with a static compilation enabled, you will see that it compiles to the following Java equivalent (result after decompiling the .class file):
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import groovy.lang.GroovyObject;
import groovy.lang.MetaClass;
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
public class Animal implements GroovyObject {
public Animal() {
MetaClass var1 = this.$getStaticMetaClass();
this.metaClass = var1;
}
public static Object echo() {
DefaultGroovyMethods.println(Animal.class, Animal.class.getName());
return null;
}
}
You can see that the following line in the echo method:
DefaultGroovyMethods.println(Animal.class, Animal.class.getName());
operates directly on the Animal class name. So from the echo method perspective, it doesn't matter how many classes extend it. As long as those classes invoke echo method defined in the Animal class, you will always see Animal printed as a result.
And there is even more than that. If you use the following compiler configuration script:
config.groovy
withConfig(configuration) {
ast(groovy.transform.CompileStatic)
ast(groovy.transform.TypeChecked)
}
and then compile the script (let's call it script.groovy) using this configuration option with the following command:
groovyc --configscript=config.groovy script.groovy
then you will see something like this after decompiling the .class file:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import groovy.lang.Binding;
import org.codehaus.groovy.runtime.InvokerHelper;
public class script extends groovy.lang.Script {
public script() {
}
public script(Binding context) {
super(context);
}
public static void main(String... args) {
InvokerHelper.runScript(script.class, args);
}
public Object run() {
Animal.echo();
return Animal.echo();
}
}
You can see that even though you have invoked Dog.echo() and Cat.echo() in your Groovy script, the compiler replaced these calls with the double Animal.echo() invocation. It happened because calling this static method on any other subclass does not make any difference.
Possible solution: applying double dispatch
There is one way to get the expected output - override echo static method in Dog and Cat class. I can assume that your real method may do something more than the exemplary echo method you have shown above, so you might need to call the super echo method from a parent class. But... there are two problems: (1) you can't use super.echo() in the static context, and (2) it doesn't solve the problem, because parent method still operates in the Animal class context.'
To solve this kind of issue you might want to mimic a technique called double dispatch. In short - when we don't have information about the caller in the method that was called, let's allow the caller to pass this information with the method call. Consider the following example:
import groovy.transform.CompileStatic
#CompileStatic
class Animal {
// This is a replacement for the previous echo() method - this one knows the animal type from a parameter
protected static void echo(Class<? extends Animal> clazz) {
println clazz.name
}
static void echo() {
echo(Animal)
}
}
#CompileStatic
class Dog extends Animal {
static void echo() {
echo(Dog)
}
}
#CompileStatic
class Cat extends Animal {
static void echo() {
echo(Cat)
}
}
Animal.echo()
Dog.echo()
Cat.echo()
This may sound like a boilerplate solution - it requires implementing echo method in each subclass. However, it encapsulates the echo logic in the method that requires Class<? extends Animal> parameter, so we can let every subclass to introduce their concrete subtype. Of course, this is not a perfect solution. It requires implementing echo method in each subclass, but there is no other alternative way. Another problem is that it doesn't stop you from calling Dog.echo(Animal) which will cause the same effect as calling Animal.echo(). This double dispatch like approach is more like introducing a shorthand version of echo method which uses the common static echo method implementation for simplicity.
I don't know if this kind of approach solves your problem, but maybe it will help you find a final solution.
I'm writing a Groovy script based on commons-io that monitors some source directory and synchronizes its files with some destination directory.
#Grab(group='commons-io', module='commons-io', version='2.4')
import org.apache.commons.io.monitor.*
import org.apache.commons.io.FileUtils
class BaseSynchronizedFileListener extends FileAlterationListenerAdaptor {
def srcDir
def destDir
/* Given a source file, returns the destination file */
File destination(File file) {
new File(destDir, file.getAbsolutePath() - srcDir.getAbsolutePath())
}
}
class CopyOnWriteListener extends BaseSynchronizedFileListener {
#Override
void onFileChange(File file) {
FileUtils.copyFile(file, destination(file))
}
#Override
void onFileCreate(File file) {
FileUtils.copyFile(file, destination(file))
}
}
class DeleteOnDeleteListener extends BaseSynchronizedFileListener {
#Override
void onFileDelete(File file) {
FileUtils.deleteQuietly(destination(file))
}
}
In addition to straight file copies, I want to support Less->CSS compilation, wherein .less files in the source directory are synchronized with .css files in the destination directory.
#Grab(group='org.lesscss', module='lesscss', version='1.3.3')
import org.lesscss.LessCompiler
class CompileLessOnWriteListener extends BaseSynchronizedFileListener {
def compiler = new LessCompiler()
#Override
File destination(File file) {
File dest = super.destination(file)
new File(dest.parentFile, dest.name - '.less' + '.css')
}
void compile(File less) {
compiler.compile(less, destination(less))
}
#Override
void onFileChange(File less) {
compile(less)
}
#Override
void onFileCreate(File less) {
compile(less)
}
}
The problem I'm encountering is when I attempt to create class DeleteCssOnDeleteLessListener to handle the situation when .less files are deleted (which, in turn, deletes the corresponding .css file) -- the code I need to do this exists in two different inheritance trees.
CompileLessOnWriteListener contains the destination() method
DeleteOnDeleteListener contains the onFileDelete() method to delete the CSS file returned by the destination() method
Is there a "Groovy way" to selectively mixin or inherit methods from both of these classes into a new class?
Or do I just need to bite the bullet and create a common super class for CompileLessOnWriteListener and DeleteCssOnDeleteLessListener?
Update
Changed the implementation. Lets see if i got the idea. You need:
Inherit two methods
"Inherit" constructor
It needs to be an instance of an interface
I think a heavy metaprogramming helps here. We can declare two objects to DeleteCssOnDeleteLessListener delegate methods to, and these objects will be accessing properties from it.
For the interface, i think you are better using the as Interface operator.
Dynamically "inherit" the constructors may get tricky. Since it is only two properties, i've declared them. You can delegate the getProperty/setProperty to one of the other two objects, if you prefer DRYing your code:
class DeleteCssOnDeleteLessListener {
def destDir, srcDir
def onLessDelete(file) {
onFileDelete destination( file )
}
}
class CompileLessOnWriteListener {
def destination(file) {
"destination $file from $srcDir"
}
}
class DeleteOnDeleteListener {
def onFileDelete(file) {
"onFileDelete $file and $destDir"
}
}
def delete = new DeleteCssOnDeleteLessListener(destDir: "dest/dir", srcDir: "src/dir")
def compileLess = new CompileLessOnWriteListener()
def deleteOnDelete = new DeleteOnDeleteListener()
delete.metaClass {
destination = compileLess.&destination
onFileDelete = deleteOnDelete.&onFileDelete
}
compileLess.metaClass.getProperty = { property -> delete.getProperty property }
deleteOnDelete.metaClass.getProperty = { property -> delete.getProperty property }
assert delete.onLessDelete("style.less") == "onFileDelete destination style.less from src/dir and dest/dir"
It's not very "Groovy", in my opinion, nor very efficient looking, but at least this approach solves my problem without having to create a common superclass:
class DeleteCssOnDeleteLessListener extends DeleteOnDeleteListener {
#Override
File destination(File f) {
new CompileLessOnWriteListener(destDir: this.destDir, srcDir: this.srcDir).destination(f)
}
}
I have the impression that closures run as the actual class being called (instead of the implementing super class) and thus break when some variables are not visible (e.g. private in the super class).
For example
package comp.ds.GenericTest2
import groovy.transform.CompileStatic
#CompileStatic
class ClosureScopeC {
private List<String> list = new ArrayList<String>()
private int accessThisPrivateVariable = 0;
void add(String a) {
list.add(a)
println("before ${accessThisPrivateVariable} ${this.class.name}")
// do something with a closure
list.each {String it ->
if (it == a) {
// accessThisPrivateVariable belongs to ClosureScopeC
accessThisPrivateVariable++
}
}
println("after ${accessThisPrivateVariable}")
}
}
// this works fine
a = new ClosureScopeC()
a.add("abc")
a.add("abc")
// child class
class ClosureScopeD extends ClosureScopeC {
void doSomething(String obj) {
this.add(obj)
}
}
b = new ClosureScopeD()
// THIS THROWS groovy.lang.MissingPropertyException: No such property: accessThisPrivateVariable for class: comp.ds.GenericTest2.ClosureScopeD
b.doSomething("abc")
The last line throws a MissingPropertyException: the child class calls the "add" method of the super class, which executes the "each" closure, which uses the "accessThisPrivateVariable".
I am new to groovy, so I think there must be an easy way to do this, because otherwise it seems that closures completely break the encapsulation of the private implementation done in the super class ... this seems to be a very common need (super class implementation referencing its own private variables)
I am using groovy 2.1.3
I found this to be a good reference describing how Groovy variable scopes work and applies to your situation: Closure in groovy cannot use private field when called from extending class
From the above link, I realized that since you have declared accessThisPrivateVariable as private, Groovy would not auto-generate a getter/setter for the variable. Remember, even in Java, private variables are not accessible directly by sub-classes.
Changing your code to explicitly add the getter/setters, solved the issue:
package com.test
import groovy.transform.CompileStatic
#CompileStatic
class ClosureScopeC {
private List<String> list = new ArrayList<String>()
private int accessThisPrivateVariable = 0;
int getAccessThisPrivateVariable() { accessThisPrivateVariable }
void setAccessThisPrivateVariable(int value ){this.accessThisPrivateVariable = value}
void add(String a) {
list.add(a)
println("before ${accessThisPrivateVariable} ${this.class.name}")
// do something with a closure
list.each {String it ->
if (it == a) {
// accessThisPrivateVariable belongs to ClosureScopeC
accessThisPrivateVariable++
}
}
println("after ${accessThisPrivateVariable}")
}
}
// this works fine
a = new ClosureScopeC()
a.add("abc")
a.add("abc")
// child class
class ClosureScopeD extends ClosureScopeC {
void doSomething(String obj) {
super.add(obj)
}
}
b = new ClosureScopeD()
b.doSomething("abc")
There is a simpler way, just make the access modifier (should rename the property really) to protected, so the sub-class has access to the property.. problem solved.
protected int accessThisProtectedVariable
To clarify on your statement of concern that Groovy possibly has broken encapsulation: rest assured it hasn't.
By declaring a field as private, Groovy is preserving encapsulation by intentionally suspending automatic generation of the public getter/setter. Once private, you are now responsible and in full control of how or if there is a way for sub-classes (protected) or all classes of objects (public) to gain access to the field by explicitly adding methods - if that makes sense.
Remember that by convention, Groovy ALWAYS calls a getter or setter when your codes references the field. So, a statement like:
def f = obj.someField
will actually invoke the obj.getSomeField() method.
Likewise:
obj.someField = 5
will invoke the obj.setSomeField(5) method.
I have a class that I've defined, and I have a number of child classes derived from it. The parent class has an enum (let's call it 'Barf'). Each descendant ALSO has an enum with the same name but not the same values. What I'm trying to figure out how to do is write a method in the ancestor class that gets the version of Barf for the actual class of the instantiated object. So if I create an instance of Ancestor, I'd like to have this method process the entries for Ancestor.Barf . If I create an instance of one of the child classes of Ancestor, I'd like to have the method process Childx.Barf values.
Obviously this is going to be a Reflection solution, but my reflection skills are pretty sparse. Any help?
Just for the fun of it, here is a possible approach:
public class Ancestor {
public enum Caffeine {
Tea,
Coffee
}
public void ProcessValues() {
var type = GetType();
var nestedEnums = from t in type.GetNestedTypes()
where t.IsEnum
select t;
var nestedEnum = nestedEnums.Single();
foreach(var val in Enum.GetValues(nestedEnum)) {
Console.WriteLine("Drinking {0}", val);
}
}
}
public class Descendant : Ancestor {
public new enum Caffeine {
Jolt,
RedBull
}
}
// The following prints:
// Drinking Jolt
// Drinking RedBull
Ancestor x = new Descendant();
x.ProcessValues();
Of course, you could achieve the same thing using polymorphism:
public class Ancestor {
public enum Caffeine {
Tea,
Coffee
}
protected virtual Type GetNestedEnum() {
return typeof(Ancestor.Caffeine);
}
public void ProcessValues() {
var nestedEnum = GetNestedEnum();
foreach(var val in Enum.GetValues(nestedEnum)) {
Console.WriteLine("Drinking {0}", val);
}
}
}
public class Descendant : Ancestor {
public new enum Caffeine {
Jolt,
RedBull
}
protected override Type GetNestedEnum() {
return typeof(Descendant.Caffeine);
}
}
As Justin Morgan has pointed out however, having the need for such a construct may be an indication of an underlying design issue in your code.
I have simple Groovy category class which adds method to String instances:
final class SampleCategory {
static String withBraces(String self) {
"($self)"
}
}
I want to use this category in my unit tests (for example). It looks like this:
class MyTest {
#Test
void shouldDoThis() {
use (SampleCategory) {
assert 'this'.withBraces() == '(this)'
}
}
#Test
void shouldDoThat() {
use (SampleCategory) {
assert 'that'.withBraces() == '(that)'
}
}
}
What I'd like to achieve, however, is ability to specify that category SampleCategory is used in scope of each and every instance method of MyTest so I don't have to specify use(SampleCategory) { ... } in every method.
Is it possible?
You can use mixin to apply the category directly to String's metaClass. Assign null to the metaClass to reset it to groovy defaults. For example:
#Before void setUp() {
String.mixin(SampleCategory)
}
#After void tearDown() {
String.metaClass = null
}
#Test
void shouldDoThat() {
assert 'that'.withBraces() == '(that)'
}
Now you have the option to use extension modules instead of categories:
http://mrhaki.blogspot.se/2013/01/groovy-goodness-adding-extra-methods.html
On the plus side Intellij will recognize the extensions. I've just noticed that it doesn't even need to be a separate module as suggested by the link, just add META-INF/services/org.codehaus.groovy.runtime.ExtensionModule to the project:
# File: src/main/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule
moduleName = module
moduleVersion = 1.0
extensionClasses = SampleExtension
The extension class is pretty much defined like a normal category:
class SampleExtension {
static String withBraces(String self) {
"($self)"
}
}
Can be used like:
def "Sample extension"() {
expect: 'this'.withBraces() == '(this)'
}
If you are using Spock there is a #Use annotation that can be used on the specifications. The drawback with that is that Intellij will not recognize it.