Automated way to Extract Interfaces from a Java Class - java

I've got a collection of concrete Classes which define an API, and I would like to extract the Interface of these classes (ie: essentially the type hierarchy and public methods) from the actual implementation of the API.
So for example if one of the public classes in the API is
public class Foo extends Bar {
/* some fields which I don't care about */
public void method() {
/* implementation here */
}
public void otherMethod() {
/* implementation goes here */
}
/* some non public methods which I don't care about */
}
I would like to break into an interface and an implementation
ie
public interface FooInterface extends BarInterface {
public void method();
public void otherMethod()
}
public class Foo implements FooInterface {
/* etc etc */
}
and
Is there a tool I can use to do this separation in automated way, or am I going to have to roll my own program to do the job? It needs to be a tool that requires minimal interaction.

I found the solution!
Eclipse, has support for refactoring scripts, the scripts are in xml yet not very human friendly but I have generated the scripts anyway that makes eclipse perform all the refactoring.
For details of eclipse script refactoring, look here and use eclipse to generate a few examples for you so you know what the script should look like

Many IDEs, like IntelliJ, have an "Extract Interface" command which performs a refactoring for you: http://www.jetbrains.com/idea/features/refactoring.html#Extract_Interface

javap, a tool in the JDK, will get you most of what you want. However, be prepared for it to not handle some things correctly - sorry, I forget what, maybe annotations, inner classes, something like that.
If embedding javap in you own Java app would help, you can do something like this:
import sun.tools.javap.Main;
...
void javap(String className) throws IOException
{
bos = new ByteArrayOutputStream();
ourOut = new PrintStream(bos);
PrintStream oldOut = System.out;
System.setOut(ourOut);
String[] params = new String[] {"-public", className};
Main.main(params);
System.setOut(oldOut);
String str = bos.toString();
}
This requires the Sun JDK tools.jar in the classpath.

I'm pretty sure you'll have to roll your own tool to do this job; it's not something that many developers would use, and those who did use it wouldn't use it often. Extract Interface, to be done right, really needs intelligence (the real kind) guiding it. A tool that blindly extracted all public & protected elements, and blindly built an interface hierarchy to mirror an implementation hierarchy, is far from smart, and the end product wouldn't be pretty. Developing the (artificial) intelligence to make good decisions about what to include and what to lead out - that would be a useful tool, but I confess unimaginably difficult for me. What current IDEs offer - guided assistance - is probably the best compromise. Cheer up; it's massively less tedious than doing every step by hand!

Related

IntelliJ and built in Java Function Interface

My Spring components implement java.util.function.Function. The idea behind this is to force a functional style with small encapsulated functions.
#Component
public class MyFunction implements Function<In, Out> {
public Out apply(In in) { .... }
}
// example usage
#RestController
public class MyApi {
private MyFunction f;
public void foo() {
someList.stream()
.map(f)
. // whatever
}
}
Two problems arise with IntelliJ 2018.1:
"Find Usages" offers a choice to find usages of the base method. If I accidentally hit "Yes", IntelliJ finds a zillion usages and slows down until it almost freezes. Well, I should definitely select "No" here, but it is still a small issue.
Using the function in a Stream (e.g. filter) with "Method Reference" (as IntelliJ suggests) is even more problematic. Using "Find Usages" and selecting "No" will not show the "real" usage(s) im looking for. This makes it hard to navigate in the code.
This leads me to my questions: Is it a good practice to use the built-in Function Interface or should I write my own Function without declaring it as a FunctionalInterface? Do you consider the mentioned problems as an IntelliJ bug? Are there workarounds you know of?
Your approach seems valid to me, yet I try to avoid directly implementing Function as much as possible. The main reason is: naming.
I can understand that if a class has a meaningful name (e.g. InOutMapFunction), you might not feel the need for the method to have a meaningful name too. Still, I prefer names like InOutMapper.mapInToOut to InOutMapFunction.apply.
Besides, if you can think of more than one InOutMapper, make it an interface and let the component implement it.
Some may believe it's not worth to create your own functional interfaces if they "correspond" to the existing ones, but I hardly ever regret it, especially that in real uses cases, this impacts readability a lot, e.g. compare:
SomeParticularTypeContextFinder, and
Function<SomeParticularType, SomeParticularTypeContext>.
Here's how I'd implement your example:
#Component
public class PlainInOutMapper implements InOutMapper {
#Override
public Out mapInToOut(In in) { .... }
}
#FunctionalInterface
interface InOutMapper {
Out mapInToOut(In in);
}
// example usage
#RestController
public class MyApi {
private List<In> someList;
private InOutMapper mapper;
public void foo() {
someList.stream()
.map(mapper::mapInToOut)
. // whatever
}
}
You can limit the scope of the search via the 'Find Usages Settings' (default on Windows: CTRL+ALT+SHFT+F7)
The settings apply to the search via ALT+F7 as well as the Mouse Wheel Click one. Maybe limiting it to your current module does the trick?

Intellij/ Java - identify calls to annotated methods

I need to be able to identify calls to methods with specific annotations in Intellij Idea 13, during compile time or by using static code analysis, like calls to #Deprecated methods are identified.
I have looked into doing a structural search in idea, these are supported in static code analysis, and am able to identify method calls from there, but I can't find a way to limit these to calls to method with annotations.
For example
public class A {
#Foo
public void foo(){
// do something...
}
public void bar() {
// do something else....
}
}
public class main {
public static void main(String... args){
A a = new A();
a.foo(); // <---- should be highlighted
a.bar();
}
}
You can by defining your own structural search template like this:
#Foo
$ReturnType$ $Method$($ParameterType$ $Parameter$);
save it e.g. as "methods annotated with #Foo"
and then do a structural search for
$expression$
with the filter reference=methods annotated with #Foo
(to add filter to $Expression$ hover with the mouse over it and then there will be a popup asking you if you want to edit filters and then you add a reference filter)
You could do this in IDEA (which would involve using IDEA's internal interfaces; I don't know offhand which ones give access to annotations).
Depending on your use case, another alternative would be to use an external tool such as the Checker Framework. The advantage is that it is externally supported and has a lot of existing functionality, so there would be less of your own code to write and maintain. Additionally, other people who don't use IDEA would be able to run the analysis. The disadvantage is that there would be less tight integration with the IDE; you would need to configure IDEA to run the analysis, which is straightforward.

Shall we avoid writing static methods in our java code for better testability?

I was prefer using static methods in my java code, since I think they are "functional""stateless" and has less side-effect. So there may be some helper classes and methods like this:
public class MyHelper {
public static Set<String> array2set(String[] items) { ... }
public static List<String> array2list(String[] items) { ...}
public static String getContentOfUrl(String url) {
// visit the url, and return the content of response
}
}
public class MyApp {
public void doSomething() {
String[] myarray = new String[]{ "aa","bb"};
Set<String> set = MyHelper.array2set(myarray);
String content = MyHelper.getContentOfUrl("http://google.com");
}
}
But my friend says we should avoid defining such static utility methods, since we call them directly in our code, it will be hard to mock them or test them if they have external dependencies. He thinks the code should be:
public class ArrayHelper {
public Set<String> array2set(String[] items) { ... }
public List<String> array2list(String[] items) { ...}
}
public class UrlHelper {
public String getContentOfUrl(String url) {
// visit the url, and return the content of response
}
}
public class MyApp {
private final ArrayHelper arrayHelper;
private final UrlHelper urlHelper;
public MyApp(ArrayHelper arrayHelper, UrlHelper urlHelper) {
this.arrayHelper = arrayHelper;
this.urlHelper = urlHelper;
}
public void doSomething() {
String[] myarray = new String[]{ "aa","bb"};
Set<String> set = arrayHelper.array2set(myarray);
String content = urlHelper.getContentOfUrl("http://google.com");
}
}
In this way, if we want to write unit tests for MyApp, we can just mock the ArrayHelper and UrlHelper and pass them to the constructor of MyApp.
I agree totally about the UrlHelper part of his opinion, since the origin static code make MyApp untestable.
But I have a little confused about the ArrayHelper part, since it doesn't depend on any external resources and the logic will be very simple. Shall we avoid using static methods at this case too?
And when to use static methods? Or just avoid using it as much as possible?
update:
We are using "TDD" in our development, so the testability of a class often is the most important concern for us.
And I just replace the word "functional" with "stateless" in the first sentence since the that's real what I meant.
You'll probably never want to mock a method that converts an array to a list (or set), and this method doesn't need any state and doesn't depend on any environment, so a static method looks fine to me.
Just like the standard Arrays.asList() (which you should probably use).
On the other hand, accessing an external URL is typically the sort of thing that you want to be able to mock easily, because not mocking it would
make the test an integration test
require to have this external URL up every time you run your tests, which you probably can't guarantee
require to have this external URL return exactly what you want it to return in your test (including errors if you want to test the event of an error).
Just beware of one disease very common amongst Java "experts": overengineering.
In your specific example, you either do or don't have a mockability issue. If you had an issue, you wouldn't be asking general questions, therefore I conclude you don't have an issue at the moment.
The general argument is that static methods are simpler and therefore the preferred choice, whenever there is a choice. A would-be instance method must first prove itself of needing to be an instance method.
If this was my project, I would defer any makeovers into instance methods until such a moment where the need for that became clear and present.
Static means you can call the method without instantiating the class. Its good if you want to package your code into a class and you have a function that just does some logic or something basic.
Just don't use a static function to try and edit member variables in the class (obviously).
Personally I think its fine to use the static function, since it is stateless.
Static methods should be used by answering the question "is this method a functionality of a specific instance?".
You shouldn't decide about a static method according to tests, you should do it according to design. Your examples doesn't need an instance because it makes no sense. So static is the better choice. You can always wrap these methods inside specific tester classes to do your tests.
The only situation in which a self-contained functionality is not static is just when you want to provide multiple implementation, so that you are forced to avoid static because you need inheritance.
I often use static methods:
for factory methods (explicitly named constructors)
to provide a functional layer above an object-oriented layer, to compose the objects
and sometimes for general-purpose functions (Apache Commons has many good examples of this)
I never use "singletons" (static objects) and methods that refer to static objects because they are a complete headache to test and reuse. I also avoid hardcoding anything into a static method that could feasibly need to be changed. Sometimes I will provide multiple methods - one with all the dependencies as parameters and others, with fewer parameters, that call the more flexible method with some default (hardcoded) values.
java.lang.Math is static which is a good example. I thought statics are not beeing garbage collected and should be avoided if possible.
No.
As mentioned by Peter Lawrey in the comment for the question, Java is all about object oriented programming. While certain functional aspects are doable and being put into eg. Java 8, at its core Java is not functional. static breaks so much of the benefits of learning how to do modern Java - not to mention all kinds of not-fun-at-all scoping problems - that there's no purpose to use them unless you're some kind of a Java wizard who really knows what happens when you use that magical keyword.
You are not a wizard. Java is not functional. If you want to be a wizard, you can learn. If you want to program in functional fashion, look into hybrid languages such as Scala or Groovy or alternatively explore the fully functional world, eg. Clojure.

How to override methods of a class instantiated with ClassLoader

I want to create an object of a class, and override some of it's methods. eg:
Foo bar = new Foo(){
public void fighters(){
//some stuff
}
};
The problem is: the name of the class is stored in a String.
My obvious move was to create a new instance using the Constructor.newInstance(Object o) method, like this:
Class c = cl.loadClass("com.pom.Foo");
Foo f = (Foo) (c.getDeclaredConstructor(String.class).newInstance("Hello!"));
Although this piece of code successfully creates a new instance of the class, I don't know how to override it's methods now.
Any suggestions?
I think you have a few options, none of them nice and all stink to high heaven of an architectural issue with how you're addressing the problem you're presented with.
Delegating Wrapper
Create a DelegaingFoo class that looks like this:
class DelegatingFoo {
Callable callMe;
public DelegatingFoo(Callable callMe) {
this.callMe = callMe;
}
public void fighters(){
calLMe.call();
}
};
Instanciate this instead, passing in a Callable object into the constructor as you are above. this disjoints the code you want to run from the bit that injects it.
Use a JVM language
Compile to something that can be run through javax.script, such as BeanShell, Groovy, etc. Depending on what you're ultimately doing, this may be a viable option.
Customised Classloader
If you have the option of using an alternative class loader (which presents it's own issues), which is something that would be fraught with it's own issues, and create something really quite complex. If you decide to consider this seriously, then looking at something like the OSGi class loading framework may give you some clues (it may even, at a stretch, be suitable).
Bytecode Manipulation
There are a few libraries which will help with bytecode munging / interception / generation / alteration on the fly:
BECL - http://commons.apache.org/bcel/
CGLib - http://cglib.sourceforge.net/
WARNING
It should be noted that all the above are hacks, with increasing depravity as you go down them. I would get my architecture peer reviewed ASAP as I would put money on there being a cleaner & clearer approach to what you're doing.
Remember, code you write should be easier to read - otherwise you're creating a maintenance headache for yourself (or future project owners).

Question on the nature of inherited Java classes

So I think I have a pretty basic question. Say there's an open source Java program called com.cow.moo that you include in your project com.bee.buzz.
moo has a bunch of great classes, most of which you don't want to touch, but there are a couple you do. Now at this point, the best thing to do would be to extend the classes you want to modify, right? (I know there's been a lot said of extends vs. implements, but none of these classes are interfaces, so that's kind of out of the question.)
My question is, say this is the class in moo:
package com.cow.moo;
public class Milk {
private float currentMilk;
public int getMilk() { /* Stuff */ }
public float convertToGallons (float liquid) { /* More Stuff */ }
}
Now, say I want to just use getMilk in my new class that extends Milk. However, getMilk in Milk relies on private variables (like currentMilk) and other functions I won't be including (like convertToGallons.) Will I have to include those other variables and functions if I want my new function to work correctly? I don't want to heavily modify the function, just add a little bit to it. What's the best way to do this?
Tips in general in building off a larger project would be useful, too. I figure it won't even take five seconds for some of the Java experts here to come up with an answer. Thanks for your time.
The general recommendation is to favor composition over inheritance.
Say, you have an interface and an existing implementation that mostly fits you needs, like
public interface MilkProvider { public float getMilk(); }
public class Milk implements MilkProvider { // same as you example }
and need another custom implementation, you could code it like that:
public class MyMilk implements MilkProvider {
private MilkProvider milk;
public MyMilk(int someValue) {
milk = new Milk(someValue); // unfortunatly we can't get rid of a depencency
// to the concrete class because we need to create
// something. An existing factory could help, but
// but usually there's none implemented.
}
public float getMilk() {
float result = milk.getMilk();
// do somethink with the result
return float;
}
}
Now, say I want to just use getMilk in my new class that extends Milk. However, getMilk in Milk relies on private variables (like currentMilk) and other functions I won't be including (like convertToGallons.) Will I have to include those other variables and functions if I want my new function to work correctly?
You won't have to include the public functions and variables. The core concept of inheritance is that, as a subclass, you get all of your parent class's public (and protected) members included in your subclass for free. So your subclass (let's say HoneyMilk) can call convertToGallons right from the get-go.
Overriding getMilk in this case is a lot trickier, since it relies on a private variable (which your subclass cannot access). My advice is to shift your mindset from treating the class as a "white box" to a "black box". What I mean by that is that you should implement your overridden version of getMilk as if you weren't actually able to see Milk's source code. While it may seem like a roundabout solution (I mean, why can't I just go tweak this line here?!), this will force you to implement your subclass using only what the parent class exposes publicly. It also heavily emphasizes the importance of abstraction, which is absolutely crucial to utilize when developing large-scale projects.
I think in this case better solution will be polymorphism (static polymorphism), or you can use reflection (do not use this way) to reach to the private variable.
You can extend the class and access instance variables throught method accessors (getters & setters) if they are public.
You can use AOP (Aspect Oriented Programming) to change your moo classes at runtime without changing its sources.
Consider too read some Composition vs. Inheritance topics.
Hope this will help you.
You won't be able to use private class members unless you use Java reflection which will be kind of ugly. If I were you (and the changes are not too heavy, in which case I'd fork the original project), I'd look at modifying the code at runtime or statically using aspect weaving (aspect oriented programming). AspectJ may look as if it had a sharp learning curve, but it's a great tool to have in your toolbox and perfectly matches your needs here.

Categories