views:

183

answers:

3

I believe you must be familiar with this idiom, which is sort of java's excuse for closures

//In the "Resource Manager" class
public void process(Command cmd){
  //Initialize
  ExpensiveResource resource = new ExpensiveResource();
  //Use
  cmd.execute(resource);
  //Release / Close
  resource.close();
}

//In the Client class...
manager.process(new Command(){

  public void execute(ExpensiveResource res){
    //Do things with the resource
  }
});

I used this idiom/pattern a lot but recently I tried to test it, and It's giving me a headache...

How do you get to test in isolation the ResourceManager and the Client classes? I found that this tight-couples them so much that you cannot do it easily.

Ideas are appreciated.

Regards

A: 

Don't use anonymous inner classes much (if at all). Aside from being difficult to test, they are virtually impossible to reuse without copy and paste.

Most of the time, making them full classes allows more flexibility and improves your OO design (adding more classes almost always improves your design).

By the way, as you mentioned closures also have the same problem--difficult to reuse.

Bill K
If closures lead to less code reuse (rather than more) in your code, you're just using them wrong; but there's nothing wrong about them as such. In fact, if anything, any framework centered around closures typically leads to dramatic increase in code reuse (because you can reuse the same algorithms with different predicates, etc). Ditto for anonymous classes.
Pavel Minaev
I'm with Pavel... I really miss closures while working in Java
Pablo Fernandez
Please explain how the item that you are passing in as a closure can be reused. I can write straight OO code to gain as much reuse as a closure, but I can't figure out how to reuse that snippit that I am passing in, but maybe that's where closures are superior to anonymous inner classes--I use them regularly and can tell you there is virtually no way to reuse the code you are passing in anonymously.
Bill K
PS. I can reuse the algorithm with or without a closure--the question is, how do I reuse the predicate?
Bill K
Oh, before you say "They are supposed to be short and you shouldn't need to replicate them", let's give a simple example. Suppose your predicates are comparators passed to a sorting routine and you change the format of the data you are sorting. If you had made a class for comparisons, you could change it in one place and know it's changed all across your code. If ANYONE decided to place the test inline instead of use your class, or if it was so easy that you just decide to inline it wherever you need to compare, you're screwed.
Bill K
If it's necessary to re-use the code in closures then it probably should be in a class, like you say. But there are times where the code is unique, short and useless as a class. To quote Pavel: "If closures lead to less code re-use you're just using them wrong".
I agree with Pavel as well, but many people are using them wrong. They get into the habit of using closures as listeners and never rethink it. Most closures I've seen (more than half) in my career would be better written as classes, so although his quote is correct--it doesn't help much, and I stand by my statement that they are generally misused. I never once said they couldn't be used correctly. Even in best case, they don't save much code anyway--the name of a class (twice).
Bill K
+4  A: 

I think that anonymous classes should be so small and simple that testing the structure including/using them should be good enough.

If you have something so complicated, big, important that you feel the need to test it make it a full class.

Janusz
+1  A: 

If you don't want to make the anonymous type a real type you can test, consider moving the code in its execute() function into another function that you can test. The anonymous type then becomes a humble object (http://xunitpatterns.com/Humble%20Object.html).

edit but you should continue finding a way to test the code in the anonymous function.

In a typesafe language like C#, this can be done by having the anonymous code call a virtual member function. The test specializes the class by overriding the virtual function call, checking it is called.

In a nontypesafe language like Javascript, the member function called is already virtual. So rather than create a derived type, you can overwrite the called member function with a recorded version.

Frank Schwieterman