In my application I use some icons. Where should I store the path of the directory containing those icons ?
The icons are used in different classes so it doesn't really make sense to store them in one of those classes in particular.
I read that global variables are evil, but is it acceptable to use a class (eg Commons) containing only public static final fields to store this king of data ? What solution is used in professional applications ?
Global Constants
As others state, global constants don't have the same negative connotation as global variables. Global variables make a program difficult to debug and maintain because of uncontrolled modifications. Global constants (public static final) don't create the same problem
Nevertheless, object-orientation is about binding code close to its data to enhance understandability and maintainability. You still have to find the right balance between storing global configuration values in a global class vs keeping data close to the code that will use it.
It is probably also worth reminding here that, because the compiler may inline some constants, if you change a constant value, you may have to recompile and redeploy more than just the class that contains the constants.
Externalizing Values
You also asked about what professional apps do. Its not uncommon for those apps to make these types of values, like files paths, externally configurable. It depends on how likely the value is to change (i.e. how likely your app will move or your code will be used in another app) and how convenient or easy it is to recompile and redeploy the code with new values. If you do choose to make some values externally configurable, you still may want to encode default values for those items in the code.
Here are some ways to externalize those values and some links to get you started. This is of course not an exhaustive list:
System properties so you can specify them on the command line
Property files [See StackOverflow Q - How to use java property files?]
Resource Bundles [See StackOverflow Q - How to load a resource bundle from a file resource?]
Global variables are evil (since they make it nearly impossible to figure out who modifies what), but constants aren't evil. public static final String fields are fine, since they can't be modified.
I would recommend to include them (the icons) with your class files in a jar, say a folder called resources and only the icon loader needs to know the resources folders name within your jar.
You are referring to constants, not global variables, so don't worry about them being evil - they are not, because they don't change.
if they are used by one class - place them in that class
if they are used by multiple classes in one package - place them in a special class
if they are used by multiple classes and they logically belong somewhere, place them there.
Have in mind that in case these "constants" are actually configurable, you'd better pass a Configuration object to methods that need it. Well, you may have the static somewhere, but from testability point of view it is a must to inject them / pass them.
Global variables are not the same as global constants. The reason global variables are bad is because they can be changed anywhere in the code and it is very hard to track down errors that result from a global variable not being in the expected state. Global constants will always be in their expected state because they can never be changed inadvertently.
In general I would suggest that this particular case be a packaging problem and to not reference the items as files on the file system, but rather as elements in the classpath, and load them via a classloader. This requires setting their location in the classpath of your application.
Then there should only be one class that knows how to retrieve these icons, and all other code asks that class for the icons it needs.
Related
I have a jar in the servlet. This jar has a variable called 'projectDirecotry'. Logically, I want the 'projectDirectory' to hold different values for each user. Since the variable is made static, I face race condition here. I know it is a bad design to use static variables but I dont have any control over the source code of this jar. I found that the scope of the static variable is limited to the classloader. I'm just wondering if it is possible to create a different classloader to this jar for each user so that the static variable is no longer shared by the users.
Any member variable in a servlet is discouraged, because there typically will be only one servlet object ever. All of the state needs to go into the request/response objects, not in the servlet.
It sounds like you have to run buggy code, are not able/allowed to fix it, but still should make it work. The way to make it work is to fix the original code, not to muck with classloading mechanics or anything else.
Run!
If you don't, and somehow magically fix this issue: Where there is a fundamental bug of this class, there are more. In the end, you will be the one who is blamed for any future misfunction, because you built an absolute nonstandard infrastructure.
Imagine the next problem to be a performance problem. Or another member variable, XSS, CSRF. The probability is high, if you're now struggling with a static variable in a servlet.
Fix it at the root, or run away. Resist any second-class workaround, for any price.
Given the way String pool works for a given piece of code why is it preferred to create a separate file for storing the constants?
String str = "test";
Suppose, the String "test" is used over 50 times in the entire application. Why is recommended to store this in a constants file. Now ,the way string pool works should actually create only one object if it doesn't exist in the pool and then share the references of this object to other places as and when needed. Then why to create a separate constant file to store constants?
The major importance comes with internationalisation, having a strings file means you have a few places in which you have to search for translatable text.
Consider the case when your app becomes a hit and it's being shipped outside of the locale in which it was developed, with a unified strings file, you just have to do a simple conversion of the file content, while with other methods you will have to search every single file and replace every single instance before your application is barely usable to people in different locales.
A very good example is the android resource system for strings. If you keep strings in specific files, it's easier managing them and translating them.
Following advantages you get
Code duplication is avoided across the project. The defined string is constant across the project and can be reused in multiple places
If user want to modify the string value across the codebase, he/she has to change only one place in the file.
Strings don’t clutter up your project code, leaving it clear and easy to maintain
If you want to support localization/i18 support in other languages, then it will be highly useful. Putting strings in resource files makes it much easier to provide separate translations of each string for different languages.
You need some storage for this literals (not only file and etc.) for simple reasons: if you need to change the value of this literal, then you will change it only in one place. For this reasons exists 2 main solutions:
use constant class with public static final Object CONSTANT fields.
use external storage (for example, file)
First case has 2 problems: at first, if you change this values, you will need to recompile project. at second, if this variables used by some frameworks you need to pass this arguments directly in your code. Also, when you need to support of i18n, you could obtain problems with managing right variants.
But when you use external storages, only what you need is implement parser for your storage (I mean json, xml, db and so on). Some frameworks already implement this feature, so you don't need to make this work.
Howevere, you mustn't do it, but it's just really good practice.
Simple: because code duplication is the root of all evil.
Constants are less about performance than about maintaining an application in the long run. As soon as some "property" is used with the same meaning in different places - you want to make sure that all usages are based on the very same definition. So that when updates are necessary, only one line of code needs to be adapted. And not 50, with an ever growing chance of missing to update one or the other occurrence.
Because everything has its place and there's a place for everything. If it's a constant string that, hopefully, will never change and it's used application-wide then logic dictates it (and things like it) should be defined separately for both maintenance and code readability concerns.
That is because if anyone want to make changes in this string in future, then you don't need to search it in whole project. Just make changes in constants file.
I am working on a Java 2D game for which I am using AWT graphics, a JFrame and a JPanel. I would like to know where I should store some non-final but globally accessible (I need to be able to read/change these variables from every other Object/Class) variables to coordinate e.g. the width and height of the game's panel, which I want to be able to change in a little settings menu within the game.
At the moment, I am storing these variables in a separate interface which most of my other classes implement, but this means I cannot change the variables as they are all final.
As I see it I have two options:
Put all these variables as static, non-final ones in my main game class and access them via Game.PanelWidth
OR
Create a separate class just for these variables and access them like this: Variables.PanelWidth, where "Variables" would be that new class' name.
Which method is better, or should I use a completely different approach?
Without going through your code, it's hard to provide a specific response.
General recommendations:
At the moment, I am storing these variables in a separate interface which most of my other classes implement, but this means I cannot change the variables as they are all final.
It's not a good idea to use inheritance to access your settings. For this reason alone I think either of the options you're considering is an improvement as it uses composition instead of inheritance.
You should consider applying the Single Responsibility Principle.
Who is responsible for managing your game's settings? Maybe a Properties object.
Who is responsible for constructing such an object? Maybe the main method.
If you apply this principle, hardly any of your classes should require access to the PanelWidth property.
Specific recommendations:
Java provides a Properties class. This class is both thread safe and easy to use when loading/storing properties to files.
From the Javadoc:
This class is thread-safe: multiple threads can share a single Properties object without the need for external synchronization.
Rather than creating a static properties object, consider constructing the properties object in the main method (basically, poor-man's dependency injection)
The choice is largely up to you and should be driven by a balance between complexity and the actual needs of the application.
The interface you mentioned is a known anti-pattern Constant Interface - generally frowned upon because you litter the inheritance tree and namespace everywhere with information that should remain encapsulated. It does work though and in small projects it may be acceptable.
A separate class is a better approach, it solves at least the namespace litter. Make its constructor final to prevent accidental subclassing.
Generally, static members can work in small projects, but it can turn out to be impossible in case the project grows and it turns out that the variables aren't really application global, but only use-case global. Refactoring such a case can create a lot of work later.
Using an actual instance of the "global" settings class prevents this from the start, the cost is that you need to pass the instance around to where it needs to be accessed (e.g. as constructor parameter).
Next is threading and the issue of communicating changes to those global variables. Unless your application is running in a single thread (that would be the case in a purely event driven swing application), you cannot simply make changes to values and expect the change to take effect properly at every dependency site (imagine just having read panelWidth, but before you can read panelHeight new dimensions are set). You need a way to prevent these situations. So simple members are out. You'll want get/set methods that ensure only complete information is read and that writes of related values are atomic.
The atomicity can be ensured by encapsulating related values into a composite object, e.g.: Instead of panelWidth, panelHeight you have a panelDimension. No getters/setters for the individual values, are provided. You can only get the entire Dimension (for reads) or replace it with a new dimension (for writes). The actual member can be either volatile, of the AtomicReference variety or protected by making getter/setter synchronized.
To properly communicate changes to every dependency site, you may need some notification mechanism, so either the entire global state or individual parts of it may need the ability to register listeners and notify those listeners on changes (again threading issues are to be considered, since listener callbacks are usually implemented on the thread making the change, which may need consideration in the listener called).
I'm in the middle of a massive refactoring project, the code has a 5000 line main class which was injected into everything, stored everything and had all of the common code.
I'm no expert on analysis and design but I've separated out things to the best of my ability and I'm about 80% through refactoring the classes that depend on the main class to use the new classes I've created.
There are some types of data which are initialised when the application starts and accessed by pretty much everything throughout the life of the application. For instance there is a Config class which holds hundreds of parameters.
The approach I've taken is to create several singletons the two most central are GUIData and ClientData. GUIData contains a reference to the mainframe of the application and clientdata maintains references to the config and other similar classes.
This allows me to call ClientData.getInstance().getConfig().getParam("param") from anywhere in the code but I don't feel like this is the best approach.
I considered individual static classes instead of these data singletons which contain instances of the classes but some of the classes do need constructors.
I've been googling on and off for a week trying to find a better way to do this but somehow I always end up on threads talking about database caching
Immutable (configuration) instances provide "thread-safe application-wide data access".
Typesafe's config (as suggested in a comment by Brian Kent) does exactly that.
Note that this does not involve static classes or singletons. Static classes and singletons may serve your purposes now,
but they could prove bothersome in the future. They can be handy ofcourse, but try limiting their use.
Initialization will have to be done after reading and parsing the configuration data. It is typically done at application startup, before other processing threads are started. The initialization will have to validate the configuration data as much as possible in order to fail fast and terminate the program if the configuration data is no good.
Having a lot of configuration data bundled together can create "hidden lines of communication". E.g. you update one value and the application fails because it required updates to other values as well. It's perfectly fine to put all configuration data in one file and load it from there, but your application (with hundreds of configuration options) should divide the configuration data in sets that are used by different parts of your application. This improves isolation, helps unit-testing and makes it possible to change the application in the future without getting too many nasty surprises.
There are two ways to use a set of configuration data:
from within an object call a singleton Settings.getInstance().getConfigForThisModule().
provide each object that uses configuration data with the configuration data via the constructor or via setConfig(ConfigForThisModule config).
The first approach depends on a convention not to call Settings.getInstance().getConfigForACompletelyUnrelatedModule() which could be a weakness. The second approach is more in line with "dependency injection" and could be more future proof.
You could mix both approaches while you are refactoring, just make sure to be consistent (e.g. only use the singleton approach for configuration data that is used in all parts of the application).
To further improve your design for using the configuration data, keep the following (likely) future functional requirement in mind: when the configuration file is updated, configuration data is reloaded and used in the application. Most logging frameworks manage to support this functional requirement without affecting the performance of multi-threaded applications. Among other things, it requires the following of your application:
if the new configuation data is no good, the program is not terminated but an error is logged instead and the old configuration data remains in use. Your initialization procedure will need to handle both "load at fresh start" and "reload" scenarios. The main thing to take away from this is that your initialization procedure needs to be re-usable and should not affect other (running) parts of your application (isolation, again).
long-lived objects may not keep a local copy of configuration data or a reference to an instance of ConfigForThisModule, instead Settings.getInstance()... (or some other method that can return an updated instance) should be called regurarly.
replacing old configuration with new configuration may not result in errors. Technically, replacing the configuration is as simple as updating an AtomicReference with a new configuration instance returned with Settings.getInstance().... But this is also where the isolation of the configuration data sets are tested: there should be no problem using an old set in one module and a new set in another module at the same.
Configuration data can be seen as a sort of "global state". With that in mind, further design points on what to do and what to avoid (partially blatantly copied to this answer) are discussed in the following two questions:
Why is Global State so Evil?
How are globals any different from a database?
Sorry, the question is a bit vague, are you looking to store the config or the cached objects used by other parts of your program ?
Since you have 100s of params, start with splitting up the config into manageable blocks
1) Split up your configuration parameters into logical blocks that have 1:1 correspondence with a simple properties file -its going to take some time
2) These property files must be externalized so that you can change them at any point in time, make sure that you pass in the base location via a env variable to the program
3) Write a utility class (singleton) that wraps Apache commons configuration to hold your config. (read *.properties from the base location and merge the properties into one configuration object) this must be done before any threads are kicked off.
4) Refer to the configuration param in your code using config.getXXXX() methods
Apache commons config also has ability to reload the config when your properties file changes on the filesystem.
Once this is done, use a DI container like Spring or Guice to cache the configured objects.
If it's just String property values you need, you don't even need a class for that - a global facility exists for you already: System.getProperties()
All you need do is first load the property values on start up:
System.setProperty("myKey", "myValue"); // see below how load properties from a file
Then read it anywhere in your code:
String myValue = System.getProperty("myKey");
or
String myValue = System.getProperty("myKey", "my desired default");
If your container doesn't support property loading out of the box, to load properties from an external file that looks like this:
key1=value
key2=some other value
etc...
you can use this code:
Files.lines(Paths.get("path/to/file"))
.filter(line -> !line.startsWith("#") || !line.contains("=")) // ignore comment/blank
.map(line -> line.split("=", 2)) // split into key/value
.forEach(split -> System.setProperty(split[0], split[1])); // load as property
you can use the Java Properties class util, basically its a HashTable
reference : https://docs.oracle.com/javase/7/docs/api/java/util/Properties.html
you create a file fileName.properties and store your data in key value pairs, for example:
username=your name
port=8080
then you load it into Properties Object and get the data like the following:
Properties prop = new Properties();
load the file...
String userName = prop.getProperty("username")
String port = prop.getProperty("port")// you can parse it to int if needed
what i suggest is to create a property file for each type of configuration like:
clientData.properties
appConfig.properties
you can follow this simple tutorial
http://www.mkyong.com/java/java-properties-file-examples/
My problem is that I'm working on a project that requires me to run multiple instances of someone elses code which has many static attributes/variables, which causes all the instances to share those resources and, well, crash. I can run multiple instances of this other person's program if I create a .jar file off of it and open it multiple times by running the .jar in windows, but running calling the "main" method multiple times in my code (which is what I need to do) won't work.
I thought about creating a .jar and using Runtime.getRuntime().exec( "myprog.jar" ); to call the program multiple times, but that won't work for me since I have to pass an instance of my object to this new program and I don't think this solution would allow for that.
PS: This is also posted in the Sun forums, so I`ll post the answer I get there here or the answer I get here there naturally giving proper credit once I this is solved =P.
Remember that a static element in Java is unique only in the context of a classloader (hierarchy); a class is uniquely identified in a JVM by the tuple {classloader, classname}.
You need to instantiate isolated classloaders and load the jar using that class loader. Each loaded class (and thus statis elements) are unique in their classloader and will not interfere with one another.
I'd say you have three alternatives:
Refactor the legacy application so that it doesn't use static attributes. If you can do this, this may be the best solution in the long term.
Continue with your approach of launching the legacy application in a separate JVM. There are a number of ways that you can pass (copies of) objects to another JVM. For example, you could serialize them and pass them via the child processes input stream. Or you could stringify them and pass them as arguments. In either case, you'll need to create your own 'main' class/method that deals with the object passing before calling the legacy app.
I think you should be able to use classloader magic to dynamically load a fresh copy of the legacy application each time you run it. If you create a new classloader each time, you should get a fresh copy of the legacy application classes with a separate set of statics. But, you have to make sure that the legacy app is not on your main classpath. The problem with this approach is that it is expensive, and you are likely to create memory leaks.
The description is a little confusing.
If you are running the code multiple times, you are running multiple independent processes, each running in its own JVM. There is no way that they are actually sharing the values of their static fields. Java doesn't let you directly share memory between multiple VMs.
Can you elaborate more (ideally with examples and code) what the attributes are defined as and what kind of failures you are getting? This may be completely unrelated to them being static.
In particular, what exactly do you mean by shared resources? What resources are your programs sharing?
The proper approach was already suggested - using custom ClassLoaders. Another thing comes to my mind, which might seem ugly, but will probably do, and is a bit more object-oriented approach.
The legacy code is used for its operations, and it incorrectly uses static instead of instance variables. You can fix that using inheritance and reflection:
create (or reuse) an utility class that copies instance variables to static ones
extend the classes in question and provide the same instance variables as the static ones
override all methods. In the overriding methods use the utility to copy the state of the current object to the static variables, and then delegate to (call) the super methods.
Then start using instance of your class, instead of the legacy ones. That way you will simulate the proper behaviour.
Have in mind this is NOT thread-safe.