My question is rather theoretical:
Lets say I have Java 8 project using static and default methods in interfaces. I need to get rid of them because I am porting the code to Java 7 (lets say it is an Android app prior to Android N).
How to do that? I know there is Retrolambda plugin for that and I successfully use it. But I am thinking about "pure" solution done by altering the code. What are the options?
I know I can remove static and default methods from interface and put them into abstract class that implements this interface and then alter the code wherever there is reference to that interface (this is what Retrolambda does, if I understood the process correctly).
My teacher had indicated it can be done just by "suitable change in interface definition" without using additional class. But so far I failed in finding the solution. I tried putting implementations directly into target classes but that caused a series of troubles in my particular project.
Anyone have some idea or clue I am missing?
I think it is at first questionable that you actually used such a thing in your Java8 project. Interface should remain without implementations. Default methods were introduced mainly for APIs backward compatibility(if method has to be added to Interface from previous versions and you can't afford to force users of API to change their code and you don't like creating InterfaceV2). Not for "daily usage".
I think when porting, you should just export the methods to the static *Util classes. This way you can reuse it and you are not breaking the main principle of Interface.
Related
If we have an interface which is being implemented by large number of classes in our application, and we need to add a method to the interface, What is the recommended way to do it?
Would the approach differ if we are using older version of java (let's say 1.5) vs if we are using newer version of java (let's say 1.8).
This won't be a popular answer, but it seems right to me that the operation you envisage is a difficult one.
Interfaces define a service contract between different sub-systems. Changing that contract should be more difficult that changing an implementation. Java 8 introduced "default" methods on interfaces, which converts the interface from being a strict contract, to a kind of abstract base class. I guess it might take some of the sting out of changing interfaces, but I think it's right that developers should feel that sting.
In fact, in an ideal world, all interfaces would be agreed in advance, and there should never be a need to change one. I guess that's impractical, but I see no need to make it easy.
The short answer, I think, is that if you change an interface, you should reflect on what changes are needed in all the implemented classes, grit your teeth, and get on and make them.
you should always follow the principle of "Open for extension Close for modification"
if u add a new method the repercussions will be in all the Classes implementing it , U have to implement the method to all (be it java 5 or 8 until its a default method), so better
Create a new interface and the needful classes should extend it
we need to add a method to the interface
Well then there's no way around it. Without any context for what you're adding and why, I'll take your word for it that you do need to. Make sure that's actually the case.
Java 5: add the method. Fix all the classes implementing it.
You can consider adding a default to a new abstract base class which implements the interface, and make all implementations extend that. Then if you're in the same situation in the future you'll have an easier time.
Java 8: add a default method
I am attempting to add functionality to my class, CustomList, which extends JList. Now all of the current usages of CustomList call the non-overridden method setModel(Listmodel<E> lm) from JList. I am stuck on an older version of Java, Java 1.6, which does not allow me to directly override this method due to erasure problems. All of my research has brought me to the conclusion that I must rename this method and replace all the current usages with the newly named method.
What I would like to do is give some warning to other people working with CustomList that they need to call this method rather than JList.setModel(ListModel<E> lm). I am unsure of how to locally deprecate a native method for my project.
A simple example outlining my new method is shown below:
public class CustomList<E> extends JList {
private ArrayList list;
public void newSetModel (ListModel<E> lm){
super.setModel(lm);
list = new ArrayList<Boolean> (lm.getSize());
}
}
Please note that I cannot simply make JList generic in the extends to allow an override since I am stuck with Java 1.6
There is no sane way to do that in Java.
Ideally, you have a build / CI process, and in that you can use tools for Policy Enforcement. Look at Checkstyle & PMD, perhaps one of them will allow you to blacklist a specific method call.
Failing that, you can use a low-level technology like asm or aspectj to write your own check, but it won't be easy. Or you can go old school and write a test that parses source files and looks for the bad method call, but that's very error-prone.
I'd say your best bet is letting your other team members know. Do you guys do code reviews? You should.
I'm taking over an old project. Now I have some classes in the flavor of own util class overriding a util class of external library. E.g.:
public final class StringUtilsXXX extends org.apache.commons.lang3.StringUtils {
}
These classes are not overriding any methods of the extended class at all (and never will be in the future). I find it confusing, that most calls on the own implementation are just delegating to the super class. Is this bad practice?
Yes. This is bad practice. The argument for why is that it tightly couples your own classes to a third party library. I'm sure the reason your predecessor did this, is so that if he needed to some day replace commons-lang, he would only have to change one piece of the code. He probably did this because of frustration from upgrading from lang2 to lang3.
The way he should have done this, would have been to create a StringUtil interface, and write different implementations of this (you could have a StringUtil which was implemented using lang2, one that used lang3 and even maybe a fallback implementation that was implemented from scratch. (if you needed some string handling not provided by either, or if you needed to compile some versions with an older Java version, or whatever).
Normally not needed if you are not overriding anything or adding any data or method member in subclass. However, for future placeholder, this may be used.
It will not hurt for now. But using (has a) StringUtils should be preferred over extending it, if no additional behavior is provided.
If there is an interface available for StringUtils and you are pointing your implementation (extending class instance using it) then it might still make some sense from maintainability point of view (that again depends on how you are instantiating it).
I don't consider it as a bad practice necessarily. There are cases that you may not want to rely on the API of an external library, and you might want to build a wrapper layer between the client (your) code and the external library. The reason doing this would be that you have control of the API of the wrapper contrary to the API of the external library.
I guess what he really did, from the pattern standpoint, is a decorator. I don't know anything about this particular library (because I'm a .net dev) and does it expose interfaces that he should implement instead but I would rephrase the question to:
Is it fine to create decorators on 3rd party libraries or should we make adapters instead.
As far as I see it, adapters are the right answer. But there is something more that puzzles me here: shouldn't we always try as hard as we can not to break contract when upgrading our project we give away to others? Did "they" have to introduce new namespace?
If they did, should we blame our colleges for hacking code to maintain project despite someone else's doubtful ideas/solutions?
No.. This is a bad practice. Suppose tomorrow org.apache.commons.lang3.StringUtils changes something (removes a method. Though it is unlikely, it can still happen with other classes especially with custom classes), imagine the impact it would have on your code. You are actually tightly coupling your methods with org.apache.commons.lang3.StringUtils.
After comming from Ruby world, I'm having little problems doing TDD in Java. The biggest issue is when I have application that is just communicating with external API.
Say I want to just fetch some data from Google Calendar, or 5 tweets from some Twitter user and display it.
In Ruby, I don't have any problems, because I can monkey-patch the API library in tests directly, but I have no such option in Java.
If I think about this in terms of MVC, my model objects are directly accessing the API through some library. The question is, is this bad design? Should I always wrap any API library in some interface, so I can mock/stub it in Java?
Because when I think about this, the only purpose of that interface would be to simulate (please don't kill me for saying this) the monkey-patch. Meaning that any time I use any external resource, I have to wrap each layer in interface that can be stubbed out.
# do I have to abstract everything just to do this in Java?
Twitter.stub!(:search)
Now you might say that I should always abstract away the interface, so I can change the underlying layer to anything else. But if I'm writing twitter app, I'm not going to change it to RSS reader.
Yes, I can add for example Facebook and then it would make sense to have interface. But when there is no other resource that can be substituted for the one I'm using, than I still have to wrap everything in interfaces to make it testable.
Am I missing something, or is this just a way to test in the Java world?
Using interfaces is just generally good practice in Java. Some languages have multiple inheritance, others have duck typing, Java has interfaces. It's a key feature of the language, it lets me use
different aspects of a class in different contexts and
different implementations of the same contract without changing client code.
So interfaces are a concept you should embrace in general, and then you would reap the benefits in situations like this where you could substitute your services by mock objects.
One of the most important books about Java best practices is Effective Java by Joshua Bloch. I would highly suggest you to read it. In this context the most important part is Item 52: Refer to objects by their interfaces. Quote:
More generally, you should favor the use of interfaces rather than
classes to refer to objects. If appropriate interface types exist, then parameters, return values, variables, and fields should all be declared using interface
types. The only time you really need to refer to an object’s class is when you’re
creating it with a constructor.
And if you take things even further (e.g. when using dependency injection), you aren't even calling the constructor.
One of the key problems of switching languages is that you have to switch the way of thinking too. You can't program language x effectively while thinking in language y. You can't program C effectively without using pointers, Ruby not without duck typing and Java not without Interfaces.
Wrapping the external API is the way I would do this.
So, as you already said, you would have an interface and two classes: the real one and the dummy implementation.
Yes, it may seem unreasonable from the perspective of some services indeed being specific, like Twitter. But, this way your build process doesn't depend on external resources. Depending on external libraries isn't all that bad, but having your tests depend on actual data present or not present out there on the web can mess up the build process.
The easiest way is to wrap the API service with your interface/class pair and use that throughout your code.
I understand that what you want are Mock objects.
As you described it, one of the ways one can generate "test versions" of objects is by implementing a common interface and using it.
However, what you are missing is to simply extend the class (provided that it is not declared final) and override the methods that you want to mock. (NB: the possibility of doing that is the reason why it is considered bad form for a library to declare its classes final - it can make testing considerably harder.)
There is a number of Java libraries that aim in facilitating the use of Mock objects - you can look at Mockito or EasyMock.
Mockito is more handy and like your ruby mocks.
You can "monkey-patch" an API in Java. The Java language itself does not provide specific means to do it, but the JVM and the standard libraries do. In Ruby, developers can use the Mocha library for that. In Java, you can use the JMockit library (which I created because of limitations in older mocking tools).
Here is an example JMockit test, equivalent to the test_should_calculate_value_of_unshipped_orders test available in Mocha documentation:
#Test
public void shouldCalculateValueOfUnshippedOrders()
{
final Order anOrder = new Order();
final List<Order> orders = asList(anOrder, new Order(), new Order());
new NonStrictExpectations(Order.class)
{{
Order.findAll(); result = orders;
anOrder.getTotalCost(); result = 10;
}};
assertEquals(30, Order.unshippedValue());
}
Is there anything out there (for Java specifically) that allow you to automatically test the behavior of an interface? As an example, let's say I have a bunch of tests for the Comparable interface, that should apply to anything that implements Comparable. What I'd like is to be able to include "ComparableTests" automatically in the test fixtures for any of my classes which implement Comparable. Bonus points if this would work with generic interfaces.
I know the .NET framework mbUnit has something similar, and when you're using something like TestNG's generator functions you could set up a test fixture for Comparable and have the generator create an instance of each of your classes that implement Comparable. But I'd rather have it be automatic, and located at the test fixture for each of my classes (since I'll already have them around for testing other parts of that class).
Clarification: I could definitely build something like this. I was asking if there was anything out there that already enabled this.
Based on your last paragraph, what you're trying to do is inject some 'extra methods' into unit testing since you're already testing a specific class. I do not know of a testing harness that allows you to attach tests based on the hierarchy of a class.
However, with your own suggestion of using TestNG for building something similar, I think you might be very close. You could very well incorporate some base code that adds your class to a list of 'default test classes', which are in turn tested if they implement a specific interface.
Still, regarding the general case, I think you're out of luck, since the Java type system is one-way, you can only (easily) find out what interfaces a class implements, not the other way around. Furthermore, the problem is 'where to stop looking': if you have a test that checks all your comparable implementers, do you want it to check the validity of String's one too, since that is in your Java environment?
Try this
http://www.xmlizer.biz/java/classloader/ClassList.java
In .NET it would be pretty simple to set up a method that looks through an assembly and identifies each class's inheritance/implementation hierarchy. I'm sure you could do it in Java, too, if you research the Java reflection API.
You could then create an array of ITargetInterfaces and call a test method on each one.
One way would be to search through the jar file for all the .class files (or search through the classes directory), use the Class.forName() method to load the class file and check MyInterface.class.isAssignableFrom(myClass).
This wouldn't deal easily public inner static classes (you could parse the class file name), but would never work with private inner classes or anonymous inner classes.