What do i do if need to change a libraries functionality - java

I have a class in a Java Library(open-m3u) that I need to change just slightly.
The functionality is easy to implement on my own without using the library. The library is open-source so i have access to all of its code. The class is made in such a way that inheriting it or even changing that small part is not possible. My question is should I copy that class and all the classes that it depends on and put them in my own code base and change the functionality or should implement the functionality myself. Or is there another option?

The functionality is easy to implement on my own without using the
library.
IMHO, then that's the way to go. Your other options are:
Build the functionality around the library: you say that's not possible in your case.
Create a branch of the library in your own source control system. That means you'll have to keep that repository in sync with the library maintainers, which means a permanent burden. And you have to check what the library's license says about forking.
Copy the relevant parts into your code base and do the modifications there. Then you won't profit from future enhancements or bug fixes, but still have to maintain code that was created and architected by someone else, and doesn't exactly fit your requirements. And you have to check what the library's license says about copying parts into a foreign code base.
They all have their drawbacks.
As a general remark: in 25 years of professional software development, I've seen both successful usages of external libraries as well as complete failures. Some times, we invested more time into evaluating existing libraries (and then finding out that nothing matched) than we needed for implementing the project-specific solution on our own.
And every library you can do without, makes config management and rollout easier.

Decorator pattern allows you to add new functionality to existing object.
If java library you use has any class like this:
public class LibraryClass implement ILibraryInterface {
public void someMethod() {
...
}
}
Then you can create Decorator class:
public class LibraryClassDecorator implement ILibraryInterface {
private LibraryClass libObj;
public LibraryClassDecorator(LibraryClass libObj) {
this.libObj = libObj;
}
public void someMethod() {
libObj.someMethod();
// here you can do whatever you want.
// Add some additional logic
// transform result value if there is some
}
}
Note: you have to implement the same interface to follow Liskov substitution principle

A solution will be to make a class that extends the one you wanna change and overide the part you wanna change

Related

Why hide a class implementation?

I'm stuck on this concept.
This is part of an explanation I saw on a site:
Hiding the Implementation
A primary consideration in object-oriented design is separating the things that change from the things that stay the same.
This is particularly important for libraries. Users (client programmers) of that library must be able to rely on the part they use, and know that they won't need to rewrite code if a new version of the library comes out. On the flip side, the library creator must have the freedom to make modifications and improvements with the certainty that the client code won't be affected by those changes.
This can be achieved through convention. For example, the library programmer must agree to not remove existing methods when modifying a class in the library, since that would break the client programmer's code. The reverse situation is thornier, however. In the case of a field, how can the library creator know which fields have been accessed by client programmers? This is also true with methods that are only part of the implementation of a class, and not meant to be used directly by the client programmer. But what if the library creator wants to rip out an old implementation and put in a new one? Changing any of those members might break a client programmer's code. Thus the library creator is in a strait jacket and can't change anything.
But I can't imagine a real situation where this can happen.
Can someone show me a practical example of this in real life?
This is how I imagine this:
public void print(String message)
{
System.out.println(message);
}
What difference does it make if a library client knows this implementation or not?
The implementation is not really hidden from view. Especially since most libraries out there that you will use are open source. "Hidden", in this case, refers to anything that is not part of the public API. The public API of a library consists of the public methods and fields that a library exposes. Once a library releases a version, it should continue to support the public API on future versions. Anything else is considered hidden and users of that library cannot rely on that "hidden code" being there in future version of that library.
EDIT:
But how could the client rely on code if it was not hidden, for example?
So lets say that a library comes out with a method that looks like this
public void doSomething(CharSequence x);
This is considered not hidden because it is public. Me as a user of that method is expecting it to exist in future versions of that library. So I am expecting that the input to that method is a CharSequence. If the author of that library wants to change that to String then that would be wrong. They should not change that CharSequence to a String because the users of the previous version are expecting CharSequence and switching it to a String might have negative consequences when the previous users of the library upgrade to the new version. In this case, the code might not compile.
So basically, if it is not hidden (aka part of the public API) then the author should not make any changes to the public API that would make previous versions of the library to not work.
This comes up all the time and there are ways around it. For example, when log4j upgraded to version 2, their changes were so dramatic that their API had to break and hence created a whole new library called log4j 2. So its a completely different library with different package names. It is not a new version of the old library, its a new library with similar name.
As a contrast to that, take a look at the Java SE's HashTable class. This is old class that should not be used anymore. But Java has a strict rule that the old public API of previous versions must still be supported in new versions. So Java cannot do what log4j did.
Another example is Spring. Spring tries to follow the approach that Java did, in that you only need to update the version and your old code should work. But Spring does deprecate parts of its public API. It will remove old classes and methods that are public but that it really does not want people to use anymore. In this case, me as a user of Spring might find it hard to upgrade from version 1 to version 4, for example. Mainly because some of the public API might have been deprecated.
So here I have given three different ways library writers have tackled this situation.
1) Side steps the old version and create a whole new library. E.g. Log4j.
2) Be strict and always support old public AIP's. E.g. Java.
3) Slowly deprecate old public API methods or classes. E.g. Spring.
Me as a user of these libraries would prefer that old public API be supported. I have used all three of those examples. I have had to work with old HashTable classes on legacy code I was upgrading to Java 8 and was happy that it was still supported. I have felt the pain of upgrading from log4j 1 to log4j 2. I have also upgraded Spring on a complicated project and have had adverse affects that needed to be troubleshooted. I can tell you that being strict to your old public API's is easiest on the users of said library.
There are many examples in the real world for this. For instance, if you consider buying a grocery previously v/s buying a grocery now. Or building a house previously v/s building a house now.
As time goes on the implementation changes of anything, but still the end result is same like bought grocery or built house. So, the library must have methods like buyGrocery() or buildHouse(), the implementation of which keeps on changing, but the user of the library still calls the same methods to attain the end results. Hope this answered your query.
Cheers!
Say for example, you're working with a LinkedList of names, and you make a utility method to print all the names in the list:
public void print(LinkedList<String> names)
{
for (String name : names)
System.out.println(name);
}
This works, but it limits you to only using a LinkedList. What if for some reason, some other code that you have runs slowly with a LinkedList, so you change it to an ArrayList? Well, now you have to go and change this method too.
public void print(ArrayList<String> names)
{
for (String name : names)
System.out.println(name);
}
But within this method, it doesn't matter if it is a LinkedList or an ArrayList, as long as you can iterate over it. This is where you want to hide the implementation details from your code, by using an interface:
public void print(Iterable<String> names)
{
for (String name : names)
System.out.println(name);
}
Now, you don't even have to pass in a List - you could pass in a HashSet, and it would still work. So, from your original qoute:
A primary consideration in object-oriented design is separating the things that change from the things that stay the same
The things that change, in this case, would be how you iterate over the collection, represented by the ArrayList and LinkedList implementations.
The thing that stays the same is the fact that you can iterate over the collection, which is what the Iterable interface represents.
A simple example could be if a log method was used for logging errors. Maybe first all it did was print to the console. Then later you wanted to write errors to a file:
public void log(String message)
{
// write to file
}
Then later you decided to write to a database or make a remote call:
public void log(String message)
{
// make network call
}
As long as the implementation is hidden, clients can continue calling log() and nothing will break because you did not change the method signature.
You can also have multiple implementations of this method by extracting an interface, as shown by #tima.

importing a library as a package private

I know we can create a package private class in java. So the class is Internal and only accessible in the specified module:
class MyPackagePrivateClass
{
...
}
Now I am developing an android library which i named LibraryA and I wish to use an existing LibraryB in my own LibraryA. How is it possible to prevent user of LibraryA from using the LibraryB directly?
Is there any concept like package private library or anything like that?
Update (For those who ask 'why do I need this?')
In LibraryB there are methods like this:
public QueryBuilder select(String... columns);
But I strongly am of the view that we should use Type-Safe Enum pattern and prevent users from passing strings to these methods(Considering maintenance and refactoring issues). So I decided to wrap those methods in LibraryA:
public TypedQueryBuilder select(Column... columns) {
queryBuilder = queryBuilder.select(toString(columns));
return this;
}
Therefore users of my library should use the Typed methods I provided (Column is a type safe enum here). But if they have access to the original method they may use those instead and I tend to forbid this.
In Java, with polymorphism, you can't hide a public method of an extended class.
I think that you could archive your goal with Facade Pattern: hide all the complex logic and, in this case, control the access and, if needed, implements some interfaces.
Jigsaw project tries to reach the same goal. But it can take long enough to wait until it would be ported to Android. Until then the best solution IMO is to use package private methods. User will be able to understand that he shouldn't use these methods.
Anyway it's impossible to ultimately forbid library user to do certain things, because one can use reflection or substitute class to get rid of nasty restrictions. But it's possible to encourage user not to do certain things - that's what can be done.
Make a jar file out of library B and import it in library A.
https://stackoverflow.com/a/1051705/6897626

Providing extensions points in a Web application

We have a product with standard functionality and our clients also customize the product to their requirements. But currently they make changes in the core product code.
I want to know the approaches that can be used to make a j2EE application extensible or customizable.
To elaborate this, read below:
for example: consider below class:
Class A{
public void doSomething(Object o){
// standard product functionality goes here.
// due to client customizations. client code also goes here.
}
}
In above class, client has added the code to the core product code. Ideally the product code should not be modified based on open-closed principle.
Currently we dont directly allow client to add code in the method but provide customization points as below.
Class A{
public ClassAExtension ext;
public void doSomething(Object o){
// standard product functionality goes here.
// client code goes in doClientCustomizations();
ext.doClientCustomizations(Object o);
}
}
So now client uses "ClassAExtension" class to override the behaviour. However, this approach is still not that elegant and makes the product code more cluttered with such customization points.
What different approaches or frameworks are available to do such things in a more elegant and efficient way?
First thing you should do is to clearly separate the code being the standard product and the extensions by using separate packages and deployment artefacts (so having a JAR for your core and a JAR for the extensions).
Sticking to basic Java mechanisms, you could for example specify hook methods in your component, which don't do anything by default, but could be overridden by an customized component extending the core component.
A small side note: Don't use the term J2EE anymore if not having to maintain ancient applications.

Using shared class libraries internally, but not providing access to them in released SDK

After some research I cannot come across the best approach for this. There will be certain color classes that I would like to share amongst multiple projects. Let's call one of them EncryptedColor. Since it is used across multiple projects I don't want multiple copies of it in existence of course. Otherwise I would need to make sure that an update in one location would need to be updated everywhere. However, these classes are needed in some released SDKs that we provide to customers.
How could I design it such that I can use these classes but not provide them with the classes that they don't need access to from their SDK. I don't want useless classes to become visible and flood the smaller subset of classes that they really need to be seeing.
A couple approaches I have thought of so far but aren't quite ideal:
Try and use a doclet structure that hides the calls within the javadoc such as doclava. Javadoc has not fully implemented its own hiding mechanism yet. As I understand this doesn't keep the functions from being visible, but it was mentioned in one spot that you would need reflection to use the calls. I don't see how just the javadoc does that so I must have been missing something.
Android has designed themselves it seems to force reflection from some #hide attributes included in methods that they have in source code. But from the sounds of it, the system hides those and then uses a different jar when it is loading to make those visible at launch time. Probably not useful here.
If I were to keep shared classes in the same package name I could access default and protected members, but...then I am keeping all my classes that use these in the same package name. Not quite ideal either, but it could be done in that manner if I needed to. Might get out of hand with large quantities of shared resources.
What approaches are taken typically in situations such as these? I haven't liked my findings and thought process thus far.
Short answer : you can't hide/remove these classes as they are needed at runtime by your application.
In my opinon, you have 3 alternatives :
Change the classes access to "package private". Yes, doing that doesn't make it impossible to access them, but these classes won't be accessible directly.
Remove the classes and create an API. You want to hide the logic ? Remove it and provide it through a REST API for instance. Depending or your architecture, it could be difficult or impossible.
Create all the instance of these classes in a dynamic way, with Class.forName, using Spring or as in #Steve K answer, with Java's ServiceLoader. As a result, you will be able to remove these classes from the main jar and make them more private, in a way. Again, classes will be here but a little less accessible.
My suggestion that could work would be to implement your color classes as a service using the Java ServiceLoader
You make an interface for your color classes, and implementations can be called using the ServiceLoader class. Then you simply separate your color classes into two packages - a public package you can jar up and distribute with your SDK, and a private package for those classes you want to be internal. The ServiceLoader will find all the color classes available so long as the jar files are in your project's classpath.
For example, if your color classes (as an example) had a common interface like this:
public interface MyAppColor {
public int getRed();
public int getGreen();
public int getBlue();
public int getAlpha();
public void setRed(int red);
public void setGreen(int green);
public void setBlue(int blue);
public void setAlpha(int alpha);
public boolean isValid();
public void doSomething(Object arg);
}
Then you could have a bunch of implementing classes in a jar file, with a service descriptor file included in the jar at the path:
META-INF/services/com.my.app.MyAppColor
The text of that file is simply the list of classes in the jar that implement the interface - one per line:
com.my.app.MyPublicAppColor
com.my.app.MyEncryptedPublicAppColor
com.my.app.MyOtherPublicAppColor
etc. Then all you have to do is make a factory for instantiating the correct type, which could be as simple as this:
public class MyAppColorFactory {
private static ServiceLoader<MyAppColor> serviceLoader = ServiceLoader.load(MyAppColor.class, null);
public static MyAppColor get(String className){
if (className != null){
for (MyAppColor c : serviceLoader){
if (className.equals(c.getClass().getName())){
return c;
}
}
}
return null;
}
}
Deploying only needed code:
- Use Only The Needed Source In Development (1) (2)
Since you have an entire library and many deployments which each use different components, the easiest way to do what you suggest is to use only the sources that you need; not a single library. You can ignore the unused sources. This will only ship the needed code.
- Make The Library "Package Private"
This will allow the access only for the public components of the library and everything else will not be callable. But, it will still ship all the code.
- Create an API as a REST SDK
This will require web access, not desirable for performance code {any code really}. You will ship no sdk code with this method.
- Obfuscate the code
Easy with the correct tools. Obfuscation will change the class and method names in production code to gibberish. This will make the library basically unusable to anyone but you. This will ship all the code but it will be obfuscated
- Native API
You can compile java to machine code and use it in production or as the api. You can also create the api in a native language {not desirable}.

Easily switching between two different implementations of a java library?

I am currently working on a project that uses a third party library to manage hardware.
I wish to create a substitute library that presents the same interface, but instead of controlling actual hardware just presents a nice fake GUI. Preferably this can be done just by replacing the jar.
The problem is that all of the third party code is in the namespace edu.edu.wpi.first.wpilibj, and of course the namespace for my library is going to be very different.
Is there any way of easily switching implementations between the two libraries providing the same interface in java?
Yes, there are design patterns to do that.
You can look into Strategy pattern.
Even better you can look into Dependency injection.
You can use Google Guice as container and based on your configuration, at runtime, your implementation can switch between using N libraries.
At the end of the day, you need to wrap those libraries around some abstraction.
here is an example:
interface ISomeOperation{
void process();
}
class ThatUsesTheWPILIBJ implements ISomeOperation{
void process(){
//use library here
}
}
class ThatUsesYourMock implements ISomeOperation{
void process(){
//use your mock here
}
}
public YourUIClass{
private ISomeOperation _operatingClass;
public YourUIClass(ISomeOperation operatingClass){
_operatingClass = operatingClass;
}
public void render(){
_operatingClass.process();
}
}
Now all you need to do is wiring. Look at google guice configuraion.
Yes. ServiceLoader.
It allows to switch implementations by puting jar in classpath (or by some configuration).
But it does not help with existing code. (But once done, switching to any other implementation is easy.
Its easy to library that uses it, but if library does not use it, it can be hard to introduce service loading. You would need to create service-loading wrapper. And if another library uses the original library, you would need to change and recompile it too.
Another approach would be puting it in same package as original library and mirror its public interface. But that is ugly.

Categories

Resources