Refactoring classes that use global variables - java

I'm working on some classes that get part of their configuration from global variables, e.g.
class MyClass {
public void MyClass(Hashtable<String, String> params) {
this.foo = GlobalClass.GLOBALVAR.get("foo");
this.bar = GlobalClass.GLOBALVAR.get("bar");
this.params = params;
}
}
This is bad for a couple of reasons, GLOBALVAR talks to a database to get some of the variables and this makes it really hard to make unit tests. The other problem is that I have many (dozens) of classes that inherit from MyClass, so I can't easily change the constructor signature.
My current solution is to create an additional default constructor and setter methods for params, foo and bar.
class MyClass {
// Other code still here for backwards compatibility.
public void MyClass() {
// Do nothing much.
}
public void setParams(Hashtable<String, String> params) {
this.params = params;
}
public void setFoo(Foo foo) {
this.foo = foo;
}
public void setBar(Bar bar) {
this.bar = bar;
}
}
Any ideas on a good way to refactor this, besides the way I did it? My other thought would be to use a factory method, but I'm afraid I'll run into polymorphic substitution problems.

I think I would start by doing the following. It let's your existing code work without modification, and allows you to add new constructors to the subclasses as you can. Once all of the subclasses have the new constructor, and all of the calls to the old constructors are gone, you can get rid of the GlobalClass and the constructors that use it. You can also then, hopefully, work on cleaning up the GLOBALVAR (the Car class in my code).
import java.util.Hashtable;
class MyClass
{
private final Foo foo;
private final Bar bar;
private final Hashtable<String, String> params;
public MyClass(final Hashtable<String, String> params)
{
this(params, GlobalClass.GLOBALVAR);
}
// added constructor
public MyClass(final Hashtable<String, String> params,
final FooBar fooBar)
{
this.foo = fooBar.getFoo();
this.bar = fooBar.getBar();
this.params = params;
}
}
class MySubClass
extends MyClass
{
public MySubClass(final Hashtable<String, String> params)
{
super(params);
}
// added constructor
public MySubClass(final Hashtable<String, String> params,
final FooBar fooBar)
{
super(params, fooBar);
}
}
// unchanged
class GlobalClass
{
public static Car GLOBALVAR;
}
// added interface
interface FooBar
{
Foo getFoo();
Bar getBar();
}
class Car
// added implements
implements FooBar
{
private Foo foo = new Foo();
private Bar bar = new Bar();
public Object get(final String name)
{
if(name.equals("foo"))
{
return (foo);
}
if(name.equals("bar"))
{
return (bar);
}
throw new Error();
}
// added method
public Foo getFoo()
{
return ((Foo)get("foo"));
}
// added method
public Bar getBar()
{
return ((Bar)get("bar"));
}
}
// unchanged
class Foo
{
}
// unchanged
class Bar
{
}

I think you should introduce an interface to put a layer of abstraction between the global variable collection and its consumers.
interface GlobalVars {
String get(String key);
}
You should introduce a constructor with limited scope, probably package-private
MyClass(GlobalVars globals, Map<String, String> params) {
// create the object
}
And then provide public static factory methods to use this constructor.
public static MyClass newMyClass(Map<String, String> params) {
return new MyClass(GlobalClass.GLOBAL_VAR, params);
}
With this design you can pass in a mock implementation of GlobalVars in a unit test from within the same package by explicitly invoking the constructor.
Addendum: Since params seems to be a required field, I would definitely make it final and avoid the approach where you add mutators to overwrite them.
private final Map<String, String> params;
Also, make a defensive copy to prevent l33t h4x.
this.params = Collections.unmodifiableMap(params);

Your class should take all of its dependencies in the constructor. It's a good idea to make it impossible to create an invalid or uninitialized instance of classes. Make foo and bar private and final, and set them in the constructor.

A slight variation on your approach would be to have an object of type GLOBALVAR in the class and use that instead of the actual global (that refactoring should be a simple search/replace). You can default the new variable to the actual global variable and provide an override for testing.

This GlobalClass.GLOBALVAR should be chopped up up into logical units. That way it would be easier to make mock objects for the unit tests. For example in my CAD/CAM metal cutting application I have a MaterialList, a SheetSizeList, PartNestingParameters, etc.
I don't have a huge list of variables stuff into one giant AppParameter class. They all hang off a ShopStandards object. For Unit Test involving a specific PartNestingParmeters I will just go ShopStandards.PartNestingParmeters = new MockPartNestingParameterTest114(). The test will run not realizing that the Part Nesting Parameters are a mockup. Plus this save me from having to doing dozens of assignments just to get the ShopStandard setup correctly for the test.
We have even more automated where many of the Mock load from files saved during the test run during initial development.

Since you mention that you have the freedom to modify the class hierarchy.
Change the base MyClass ctor to take in 3 parameters params, foo and bar. Comment out the GlobalVar references and simply cache passed in values
Compile.. this should throw up a bunch of compile errors - no ctor which takes 1 parameter.
Fix each one to pass in GlobalVar.get("foo") and GlobalVar.get("bar"). Get it to build.
Refine: Now minimize hits to the DB by lazy load and caching the foo and bar values. Expose via some property on GlobalVar.

Related

Java: Parameter traversal?

I have this code:
public class Compiler {
public void compile(String template, Object o, Object params) {
//...
context(o, params);
//...
}
private void context(Object o, Object params) {
//...
substitue(o, params);
//...
}
private void substitue(Object o, Object params) {
//...
print(params);
//...
}
private void print(Object params) {//use parameter params here, only here
//...
System.out.println(params);
//...
}
}
As you can see, the parameter params is used only in the print method, not in compile, context or substitue. The problem is adding the params to the signature of all the methods down to print.
In general, when I'm facing this problem I refactor my code like the following :
public class Compiler {
public void compile(String template, Object o, Object params) {
//...
new InnerCompiler(template, o, params).compile();
//...
}
private static class InnerCompiler {
private final String template;
private final Object o;
private final Object params;
InnerCompiler(String template, Object o, Object params) {
this.template = template;
this.o = o;
this.params = params;
}
private void compile() {
//...
context();
//...
}
private void context() {
//...
substitue();
//...
}
private vois substitue() {
//...
print();
//...
}
private void print() {
//...
System.out.println(this.params);
//...
}
}
}
This is a very basic example to illustrate the case of passing a parameter to all the methods even if it is not used by the method itself but by the next one (or deeper).
I'm looking for the name of this problem (maybe an anti-pattern). In the title I've put (Parameter traversal) but it could be wrong or it means another thing.
The first version of your code where you were passing parameters repeatedly down through the call-stack is referred to as "tramp data". You can read about it in a similar question on the Software Engineering site. What I think you're trying to do is to use Dependency Injection. I say "trying" because you're not injecting your dependencies into the Compiler instance, itself.
Instead, I would argue that what you're actually using is a really small version of the Bounded Context pattern. By this, I mean that your InnerCompiler class is a bounded context as described in Domain-Driven Design and might be more aptly named: CompilerContext. That being said, bounded contexts are usually domain level constructs that you are using to encapsulate complicated service-level data sets. A set of three parameters don't usually merit the term "bounded context", but that threshold is pretty subjective IMO, and you might be oversimplifying your code here for the sake of an easily understandable MCVE.
To use the DI pattern in a more standard form, I would change your code to something like the following:
public class Compiler {
private final String template;
private final Object o;
private final Object params;
Compiler(String template, Object o, Object params) {
this.template = template;
this.o = o;
this.params = params;
}
public void compile() {
//...
context();
//...
}
private void context() {
//...
substitute();
//...
}
private void substitute() {
//...
print();
//...
}
private void print() {
//...
System.out.println(this.params);
//...
}
}
This achieves what you're doing right now, without resorting to an artificial inner class.
Note that if you truly need something like a compiler to be used as a singleton as you have in your version of the code, consider using a CompilerFactory class with a newCompiler() method which would call the constructor and inject the dependencies.
I hope this answers your question. I know that this answer isn't a pattern out of the Design Patterns book by the Gang of Four, but IMO none of the patterns in that book truly reflect your code or your intent.
What you are trying to do seems to me to change parameter passing to global state.

Test a factory of a 3rd party class

My application uses a third party jar (no access to source, etc.) I have a factory that creates an object (call it Foo) correctly from settings, i.e.
public FooFactoryImpl implements FooFactory {
private final Settings settings;
private final OtherDependency other;
#Inject
public FooFactoryImpl(Settings settings, OtherDependency other) {
this.settings = settings;
this.other = other;
}
public Foo create(String theirArg) {
Foo newFoo = new Foo(theirArg); // there is no no-arg constructor
// This isn't exactly the way I do it but this is shorter and close enough
newFoo.setParamOne(settings.get("ParamOne"));
newFoo.setParamTwo(settings.get("ParamTwo"));
// etc.
}
}
I would like to unit test this factory using Mockito - make sure the created object is configured correctly. But of course, I run into this problem; that is, because my factory calls new, I can't inject a spy.
One possible solution is to introduce something like:
public FooFactoryDumb implements FooFactory {
public Foo create(String theirArg) {
return new Foo(theirArg);
}
}
And then something like:
public FooFactoryImpl implements FooFactory {
#Inject #Dumb private FooFactory inner;
// snip, see above
public create(String theirArg) {
Foo newFoo = inner.create(theirArg);
// etc.
}
}
This seems like a lot of boilerplate code just to enable unit testing. It smells bad to me, but I might be wrong. Is there a better way?
There is a similar but simpler way to do it: add a protected method to your factory to create a Foo:
protected Foo create(String theirArg){
return new Foo(theirArg);
}
then in your tests of your Factory, create a Test Double of your FactoryImpl and override the create method:
private class FooFactoryImplTestDouble extends FooFactoryImpl{
...
#Override
protected Foo create(String theirArg){
//create and return your spy here
}
}
Create a new class:
public class FooFactory3rd {
public Foo create3rdParty(String theirArg) {
return new Foo(theirArg);
}
}
Then change your class to:
public FooFactoryImpl implements FooFactory {
private final Settings settings;
private final OtherDependency other;
private final FooFactory3rd fooFactory3rd;
#Inject
public FooFactoryImpl(Settings settings, OtherDependency other, FooFactory3rd fooFactory3rd) {
this.settings = settings;
this.other = other;
this.fooFactory3rd = fooFactory3rd;
}
public Foo create(String theirArg) {
Foo newFoo = fooFactory3rd.create3rdParty(theirArg);
// This isn't exactly the way I do it but this is shorter and close enough
newFoo.setParamOne(settings.get("ParamOne"));
newFoo.setParamTwo(settings.get("ParamTwo"));
// etc.
}
}
And in your test code:
Foo fooMock = mock(Foo.class);
FooFactory3rd fooFactory3rdMock = mock(FooFactory3rd.class);
when(fooFactory3rdMock.create3rdParty(any(String.class)).thenReturn(fooMock);
FooFactoryImpl fooFactoryImpl = new FooFactoryImpl(settings, other, fooFactory3rdMock);
fooFactoryImpl.create("any string");
This way, you can inject your fooMock. When you call fooFactoryImpl.create("any string"), your mocked Foo is called under the cover.
Or if you want to go further clean, don't even need the constructor arg of FooFactory3rd. Just declare
private final FooFactory3rd fooFactory3rd = new FooFactory3rd();
And in your test, use reflection to change it to the mocked FooFactory3rd.
Well, it turns out that I had to use PowerMock anyway because the third party's methods were final. Since I'm already using PowerMock, I realized I can just do this:
#Before
public void setUp() throws Exception {
Foo toReturn = PowerMockito.mock(Foo.class);
PowerMockito.whenNew(Foo.class).withAnyArguments().thenReturn(toReturn);
}
And then I don't have to touch my original class at all.
Note: If you do this, you have to prepare both classes for PowerMock, i.e. do
#PrepareForTest( { Foo.class, FooFactoryImpl.class } )
Take a step back and think about what the contract of FooFactoryImpl is. It is that it must create a fully functional Foo, whatever that means. So if the contract of a Foo is that it does X, Y and Z, then the contract of a FooFactoryImpl is that it creates objects that do X, Y and Z.
This is a case for the kind of test in which the SUT consists of more than one class. I don't care whether you call this a unit test, an integration test, a subsystem test, a collaboration test, or some other name. The point is that the only meaningful test of FooFactoryImpl is a test that tests Foo as well. Instead of writing a test class for Foo alone, write a test class that tests the two classes jointly.
So, if the contract of Foo is to do X, Y and Z, then your test cases will do the following things with a FooFactoryImpl.
Call create and test that the created object does X.
Call create and test that the created object does Y.
Call create and test that the created object does Z.
I believe this is the only sensible way to attack this problem. The hard part is coming up with a convincing name for the test class.

Java: Access Fields without knowing their names. ("Save reference")

I need to get a Field (or a list of Fields) without knowing it's name.
I.e: for a custom entitymanager i'd like to be able to do Method Calls like this:
cem.getEntities(MyEntity.class, ParamMap) where the ParamMap should be of the Type Map<Field, Object>.
What i can do at the moment is something like this:
Map<Field, Object> params = new HashMap<Field, Object>();
params.put(MyEntity.class.getDeclaredField("someFieldName"), 20);
List<MyEntity> entitysWithSomeFieldNameEquals20 = cem.getEntities(MyEntity.class, params);
Im trying to avoid the usage of querys, because it should work "generic" in the first place, but also be independent from Strings. (They are error-prone). The Entity Manager therefore uses reflection to determine the table and column names, he needs to use.
However, I STILL need to use
MyEntity.class.getDeclaredField("someFieldName")
which will simple move the error-prone string "out" of the entity manager...
What i'm trying to achieve would be something like this:
MyEntity.class.getDeclaredField(MyEntity.class.fields.someFieldName.toString())
So, no matter what the actual field is named, it can be referenced in a save way and refactoring will refactor all the field-access calls, too.
I'm not sure if this is possible. I could go with a (encapsuled) enum for ALL entities, but I hope, that theres a more generic way to achieve this.
Edit:
One good solution seems to be the usage of constants:
public class MyEntity{
private static string SOME_FIELD = "some_field_name_in_database";
#Column(name = SOME_FIELD);
private String someField;
}
...
Map<String, Object> params = new HashMap<String, Object>();
params.put(MyEntity.SOME_FIELD, matchValue);
List<MyEntity> result = eem.getEntities(MyEntity.class, params);
This at least reduces the usage of the string to exactly one location, where it can be maintained and changed without affecting any other file. But im still searching for a solution without constants, so the contants don't need to be synchronized with the available fields :-)
Ok, this is just an idea, which is not easy to implement, but it could work.
Suppose MyEntity looks like this:
public class MyEntity {
private String foo;
private String bar;
public String getFoo() { return this.foo; }
public void setFoo(String foo) { this.foo = foo; }
public String getBar() { return this.bar; }
public void setBar(String bar) { this.bar = bar; }
}
and there is an interface:
public interface Pattern {
public Class<?> getEntityClass();
public Map<Field, Object> getFields();
}
and there is a method, which takes a class and generates a pattern object, which is an instance of the given class:
public class PatternFactory {
public <T> T createPattern(Class<T> klass) {
// magic happens here
}
}
The requirement for the emitted instance would be that it should implement the Pattern interface, such that the method getFields returns only the fields which were explicitly set. GetEntityClass should return the entity class. Then the custom entity manager could be implemented like this:
public class EntityManager {
public <T> Collection<T> getEntities(T pattern) {
if (!(pattern instanceof Pattern))
throw new IllegalArgumentException();
Class<?> klass = ((Pattern) pattern).getEntityClass();
Map<Field, Object> fields = ((Pattern) pattern).getFields();
// fetch objects here
}
}
Then you could use it like this:
PatternFactory pf = // obtain somehow
EntityManager em = // obtain somehow
MyEntity pattern = pf.createPattern(MyEntity.class);
pattern.setFoo("XYZ");
pattern.setBar(null);
Collection<MyEntity> result = em.getEntities(pattern);
In this case pattern.getFields would return a map with two entries.
The difficulty here lies, of course, in the implementation of the createPattern method, where you will have to emit bytecode at run-time. However, this is possible and can be done.

Handling more than 7 Parameters

I have a public class, which needs 7 parameters to be passed down. At the moment, I am able to make 3 of them being passed to constructor and another 4 to a public method in the class . Like this:
Public Class AClass{
private XClass axClass;
private String par4;
private String par5;
private String par6;
private String par7;
public AClass(String par1, String par2, String par3){
aXClass = new XClass(par1,par2,par3);
}
public execute(String par4,String par5, String par6, String par7){
//this is needed because they are used in other private methods in this class
this.par4 = par4;
this.par5 = par5;
this.par6 = par6;
this.par7 = par7;
//call other private methods within this class.
//about 7 lines here
}
}
My question is, is this the right way to ask client of the class to passing in paramters?
There shouldn't be anything stopping you from passing 7 parameters to a constructor, if that's what you want. I don't know if there's a maximum number of parameters that can be passed to a method in Java, but it's certainly higher than 7 if there is a max.
When you create a class and its public methods, you're creating an interface on how to use and access that class. So technically what you've done so far is correct. Is it the "right way" to ask the client of a class to pass in arguments? That's up to you, the designer of the interface.
My first instinct when I saw 7 parameters being passed was to silently ask "Is there some relationship between some or all of these parameters that might mean they'd go together well in a class of their own?" That might be something you address as you look at your code. But that's a question of design, not one of correctness.
I'd go for the Builder Pattern instead of many constructor parameters as suggested by
Effective Java Item 2: Consider a builder when faced with many constructor parameters
Here's a simple class to illustrate:
public class Dummy {
private final String foo;
private final String bar;
private final boolean baz;
private final int phleem;
protected Dummy(final Builder builder) {
this.foo = builder.foo;
this.bar = builder.bar;
this.baz = builder.baz;
this.phleem = builder.phleem;
}
public String getBar() {
return this.bar;
}
public String getFoo() {
return this.foo;
}
public int getPhleem() {
return this.phleem;
}
public boolean isBaz() {
return this.baz;
}
public static class Builder {
private String foo;
private String bar;
private boolean baz;
private int phleem;
public Dummy build() {
return new Dummy(this);
}
public Builder withBar(final String bar) {
this.bar = bar;
return this;
}
public Builder withBaz(final boolean baz) {
this.baz = baz;
return this;
}
public Builder withFoo(final String foo) {
this.foo = foo;
return this;
}
public Builder withPhleem(final int phleem) {
this.phleem = phleem;
return this;
}
}
}
You would instantiate it like this:
Dummy dummy = new Dummy.Builder()
.withFoo("abc")
.withBar("def")
.withBaz(true)
.withPhleem(123)
.build();
The nice part: you get all the benefits of constructor parameters (e.g. immutability if you want it), but you get readable code too.
Can't you just make a class/hashmap that stores these parameters and pass this to the function?
public excute(Storageclass storageClass){
//this is needed because they are used in other private methods in this class
this.par4 = storageClass.getPar4();
this.par5 = storageClass.getPar5();
this.par6 = storageClass.getPar6();
this.par7 = storageClass.getPar7();
//or
this.storageClass = storageClass;
}
I don't really see the problem with that.
In any case you could create a "Request" object or something like this:
class SomeClass {
private String a;
private String b;
....
public SomeClass( Request r ) {
this.a = r.get("a");
this.b = r.get("b");
...
}
public void execute( Request other ) {
this.d = other.get("d");
this.e = other.get("d");
...
}
}
See also: http://c2.com/cgi/wiki?TooManyParameters
Without knowing the use of the child class, I can say that there is nothing inherently wrong with what you have done.
Note though that you have to declare
private XClass axClass;
in the variables of your AClass.
However, you say 'I am able to make....' Does this mean there is some problem with declaring this another way?
I don't care for it much, because an object should be 100% ready to be used after its constructor is called. It's not as written in your example.
If the parameters passed into the execute method can simply be consumed, and that's the method of interest for clients, I see no reason for them to be data members in the class.
Without knowing more about your ultimate aims it's hard to tell. But I would re-think this implementation.
If you're planning on introducing an AClass.someMethod() that needs to know par4-7 without requiring you to have called AClass.excute(), then clearly you should be passing the parameters in the constructor.
On the other hand: if you can construct an instance of this object with only par1-3 and do something meaningful with it besides call excute() then it makes sense to allow the object to be constructed with fewer than the full seven parameters.
Yet my own aesthetic is to try and limit the number of "modes" that an object can be in which make certain methods work and others fail. So ideally, a fully-constructed object is ready to run any method the programmer might call. I'd worry about the design issue more than be too concerned about the sheer number of parameters to the constructor.
But as others have pointed out, sometimes there is a natural grouping of these parameters which can deserve objects of their own. For instance: in many APIs instead of passing (x, y, width, height) all over the place they use rectangle objects.
As others already wrote, it is technically correct to pass 7 parameters, although not very 'user-friendly', if you can say so.
Since you didn't write much about this class, I can suggest one small thing: in constructor you're just creating XClass object, so it would be sane to create this object before and pass it as a single parameter.
Something like this:
...
XClass aXClass = new XClass(par1, par2, par3);
AClass aClass = new AClass(aXClass);
...
And this is the constructor:
public AClass(XClass aXClass) {
this.aXClass = aXClass;
}

java thread safe code + an atomic method question

I have a class Manager that is going to be accessed by multiple threads at the same time, I want to know if I did it the right way ?
also I think I need RemoveFoo to be atomic, but I'm not sure
public class Manager
{
private ConcurrentHashMap<String, Foo> foos;
//init in constructor
public RemoveFoo(String name)
{
Foo foo = foos.Get(name);
foo.RemoveAll();
foos.Remove(name);
}
public AddFoo(Foo foo)
{...}
}
public class Foo
{
private Map<String,Bar> bars;
//intialize it in constructor
//same for RemoveBar
public void AddBar(Bar bar)
{
synchronized(this)
{
bars.put(bar.id, bar);
}
}
public void RemoveAll()
{
synchronized(this)
{
//some before removall logic for each one
bars.remove(bar.id, bar);
}
}
}
public class Bar
{}
You do not need synchronised methods as you are using a ConcurrentHashMap, however be aware that Foo foo = foos.Get(name) could return null as another thread could already have removed the entry from the map.
Members can be declared as Map<String, Foo> foos, but must be initialsed as foos = new ConcurrentHashMap<String, Foo>;
RemoveFoo could be problematic. I suggest to use:
Foo foo = foos.remove (name);
if (foo != null) foo.removeAll();
instead. This makes sure that the map doesn't change between get() and remove().
In Foo, it's enough to synchronize on bars instead of the whole instance. But that's just a minor optimization.
Declare RemoveFoo(String) as synchronized:
public synchronized void RemoveFoo(String name) {
…
}
Also, be advised of the following:
method names should be lower case, e.g. removeFoo instead of RemoveFoo. This is not C#. :)
Every method needs a return type: public removeFoo() is not a valid method declaration, it needs to be public void removeFoo().
If you use a concurrentHashMap in Foo like
private Map<String,Bar> bars = new ConcurrentHashMap<String, Bar>();
maybe you can do away with the synchronization in Foo as well.
I am not sure what you are going to do on Foo and Bar, but it looks like a pattern of deallocation.
If they are not referenced by others, just call foos.Remove(name); and let GC engine handle the deallocation.

Categories

Resources