Java: Parameter traversal? - java

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.

Related

Can the compiler verify a generic type of an object through a generic method?

First of all, sorry for the bad title. I don't know how to describe the problem in a few words (maybe not even in many)...
I am refactoring some settings in our system to be more abstract. The current solution has multiple tables in the DB, one for each settings area. In order to add a new setting, you'll need to extend the schema, the hibernate class, all transfer object classes, getters/setters, etc. I felt that this is violating OCP (open-closed principle), thus the refactoring.
I've spent some time coming up with ideas on how to implement such an abstraction. My favourite idea so far is the following:
1 enum for each settings area
1 enum value for each setting
Each setting is a SettingsDefinition<T> class using a generic type
A SettingsService is using static get/set methods with generic types
So for example, a settings area could be:
public enum SettingsABC{
A(new SettingDefinition<Integer>("A", 123)),
B(new SettingDefinition<String>("B", "Hello")),
C(new SettingDefinition<Boolean>("C", false));
private SettingDefinition settingDefinition;
SettingsABC(SettingDefinition settingDefinition) {
this.settingDefinition = settingDefinition;
}
public SettingDefinition getDefinition() {
return settingDefinition;
}
}
Where the SettingDefinition is the following:
public class SettingDefinition<T> {
private String name;
private T defaultValue;
public SettingDefinition(String name, T defaultValue) {
this.name = name;
this.defaultValue = defaultValue;
}
public String getName() {
return name;
}
public T getDefaultValue() {
return defaultValue;
}
}
And the service to get/set the values would be:
public class SettingsService {
public static <T> T getSetting(SettingDefinition setting) {
// hit db to read
// return value
}
public static <T> void setSetting(SettingDefinition setting, T value) {
// hit db to write
}
}
And the consumer would look something like this:
String value = SettingsService.getSetting(SettingsABC.B.getDefinition());
SettingsService.setSetting(SettingsABC.A.getDefinition(), 123);
My problem is that I cannot enforce a compiler type check between the generic type of the SettingDefinition inside SettingsABC and the generic type of get/set methods of the service. So in essence, I can do this:
Integer value = SettingsService.getSetting(SettingsABC.B.getDefinition());
Where B's definition is of type String.
Also, I can do this:
SettingsService.setSetting(SettingsABC.A.getDefinition(), "A");
Where A's definition is an Integer.
Is there any way to use generics to force these two different generic types match?
You can convert the enum to the class:
public final class SettingsABC<T> {
public static final SettingsABC<Integer> A =
new SettingsABC<>(new SettingDefinition<>("A", 123));
public static final SettingsABC<String> B =
new SettingsABC<>(new SettingDefinition<>("B", "Hello"));
public static final SettingsABC<Boolean> C =
new SettingsABC<>(new SettingDefinition<>("C", false));
private final SettingDefinition<T> settingDefinition;
// private constructor, so nobody else would instantiate it
private SettingsABC(SettingDefinition<T> settingDefinition) {
this.settingDefinition = settingDefinition;
}
public SettingDefinition<T> getDefinition() {
return settingDefinition;
}
}
This way individual constants will be typed. Now you can use the type arguments for SettingService as well:
public static <T> T getSetting(SettingDefinition<T> setting) {
...
}
public static <T> void setSetting(SettingDefinition<T> setting, T value) {
...
}
Although it's not an enum anymore, it can be used mostly in the same way. If you need other methods which are usually available in enum, you can mimic them like this:
public String name() {
return settingDefinition.getName();
}
#Override
public String toString() {
return settingDefinition.getName();
}
// and so on

Stateless Template method implementation

Let's say I have a Strategy interface :
public interface Strategy {
void perform();
}
And a template method to implement it :
public abstract class AbstractStrategy implements Strategy {
#Override
public void perform() {
String firstInfo = doStuff();
String secondInfo = firstDelegationToImplementor(firstInfo);
String thirdInfo = processSecondInfo(secondInfo);
String fourthInfo = secondDelegationToImplementor(thirdInfo);
finalProcessing(fourthInfo);
}
private void finalProcessing(String fourthInfo) {
//TODO automatically generated method body, provide implementation.
}
protected abstract String secondDelegationToImplementor(String thirdInfo);
protected abstract String firstDelegationToImplementor(String firstInfo);
private String processSecondInfo(String secondInfo) {
return "thirdResult";
}
private String doStuff() {
return "firstResult";
}
}
And I have a concrete subclass of that :
public class ConcreteStrategy extends AbstractStrategy {
private String firstInfo;
#Override
protected String secondDelegationToImplementor(String thirdInfo) {
return someMoreProcessing(firstInfo, thirdInfo);
}
private String someMoreProcessing(String firstInfo, String thirdInfo) {
return null;
}
private String someProcessing(String firstInfo) {
return null;
}
#Override
protected String firstDelegationToImplementor(String firstInfo) {
this.firstInfo = firstInfo;
return someProcessing(firstInfo);
}
}
But due to the fact that it needs to remember some intermediate result in between the method calls it is not stateless. Stateless classes have several advantages, they are automatically thread safe for instance.
So the question is : how can I make ConcreteStrategy stateless, while taking advantage of the template method?
(edit) Clarification : the published methods of both the interface and the template method class cannot change.
(note, I have solved this question already and will answer it myself, but I'll give others a chance to solve it)
Ok here's the answer I have come up with when I faced this :
public class StatelessConcreteStrategy implements Strategy {
#Override
public void perform() {
new ConcreteStrategy().perform();
}
}
StatelessConcreteStrategy is stateless. It has all the benefits any other stateless class has, and by delegating the perform() to a new ConcreteStrategy instance, it gets to use the template method pattern, and is able to 'remember' any data it wants to in between method calls.
In fact you'll most likely want to inline ConcreteStrategy to an inner or even anonymous inner class.

Refactoring predecessor code

I'd like to ask for help and some suggestion how to refactor source code which I receive.
Here is pseudocode of my method:
public void generalMethod(String type) {
InputParameters params = new InputParameters();
if (type.equals("someKey1"){
decodeSomeKey1(params);
} else if (type.equals("someKey2"){
decodeSomeKey2(params);
} else if (type.equals("someKey3"){
decodeSomeKey3(params);
} else if (type.equals("someKey4"){
etc...
}
}
}
All methods have the same input parameters. In first step I created new interface and created for each method separate class which implements created interface.
interface ISomeInterfaceDecoder {
void decode(InputParameters params);
}
class DecodeSomeKey1 implements ISomeInterfaceDecoder {
#Override
public void decode(InputParameters params) {
// some implementation
}
}
class DecodeSomeKey2 implements ISomeInterfaceDecoder {
#Override
public void decode(InputParameters params) {
// some implementation
}
}
Then I created factory class as follows:
class Factory {
ISomeInterfaceDecoder getDecoder(String type) {
if (type.equals("someKey1"){
return new DecodeSomeKey1();
} else if (type.equals("someKey2"){
return new DecodeSomeKey2();
} else if (type.equals("someKey3"){
return new DecodeSomeKey3());
} else if (type.equals("someKey3"){
etc...
}
}
}
}
After these changes the code looks like this:
class SomeClass {
Factory factory = new Factory();
public void generalMethod(String type) {
InputParameters params = new InputParameters();
ISomeInterfaceDecoder decoder = factory.getDecoder(type);
decoder.decode(params);
}
}
Code of this method looks better but...
This method is called very very often. Each time a new instance of the given class is created. This can cause performance problems. So, I think it's not good approach to this problem.
Can you give me some suggestion how I should to refactor this code?
Thanks in advance for help.
Instead of having a key as a String, make it an enum. Then in the enum you can implement the decode() method like this:
public enum MyKeyEnum {
VALUE1 {
public void decode(InputParameters ip) {
// do specific decoding for VALUE1
}
},
VALUE2 {
public void decode(InputParameters ip) {
// do specific decoding for VALUE2
}
}
...
;
public abstract void decode(InputParameters ip);
}
Now in the calling code you can do something like this:
public void generalMethod(MyKeyEnum type) {
InputParameters params = new InputParameters();
type.decode(params);
}
The advantage is that all the decode methods are in 1 enum, you dont need a specific class for each of the decoders. Also when a new value is added to the enum, you cannot forget to implement the decode method (or it will not compile).
Can you give me some suggestion how I should to refactor this code?
I see no mention of automated regression testing, and that would be my first step, to put in a test suite (via, say, JUnit or TestNG) before going further.
After that, I'd perhaps introduce a Map of String keys to Decoder objects.
But put the test framework in first. Otherwise you'll never really know if you've introduced bugs or different modes of operation.
Introduce caching/singletons in your factory, that you only return an algorithm once. Also, make your factory a singleton.
Create a static Map<String, ISomeInterfaceDecoder> where you map the identifier to algorithms executing the call which means no factory class and no algorithm instantiation. Works only, if you have stateless algorithms.

Generic Type From Enum & The Builder Pattern

I'm trying to create a builder pattern that uses generics to provide type checking on some of the methods. Currently I have the following working:
ParameterBuilder.start(String.class).setName("foo").setDefaultValue("Hello").build();
ParameterBuilder.start(Integer.class).setName(bar).setDefaultValue(42).build();
ParameterBuilder.start(Boolean.class).setName(bar).setDefaultValue(false).build();
Using the code:
public class ParameterBuilder<T> {
private String name;
private T defaultValue;
public static <T2> ParameterBuilder<T2> start(Class<T2> type) {
return new ParameterBuilder<T2>();
}
// Other methods excluded for example
}
So the type of the input for the setDefaultValue method is defined by what's passed into the start method, just as I want.
But now I want to extend what's being passed into start() to contain a little more information. Essentially I want to pass in a "type" for the parameters I creating. Sometimes these parameters will be things like "email", "url" etc. The default value will still be of a known type (String in those cases), so I'd like to have something like:
ParameterBuilder.start(EMAIL).setName("email").setDefaultValue("foo#bar.com").build();
ParameterBuilder.start(URL).setName("website").setDefaultValue("http://www.somewhere.com").build();
Where at the moment EMAIL & URL are enums, containing amongst other things - the class of the default value. But if I go down this route, how would I instantiate the parameter builder?
public static <T2> ParameterBuilder<T2> start(ParameterType paramType) {
Class<T2> type = paramType.getTypeClass();
// How do I instantiate my ParameterBuilder with the right type?
}
If it can't be done using enums (which I can see being the case), does anyone have a suggestion for a different solution?
I think you need one enum per class type (I don't see how you could have one enum cover several types and keep the thing working). In that case, a common generic interface could do what you want. You can then create some sort of factory to provide the enum constants if that helps.
This compiles:
static interface ParameterType<T> {}
static enum ParameterTypeEnum implements ParameterType<String> { EMAIL; }
public static void main(String[] args) {
ParameterBuilder
.start(ParameterTypeEnum.EMAIL)
.setName("email")
.setDefaultValue("foo#bar.com")
.build();
}
public static class ParameterBuilder<T> {
private String name;
private T defaultValue;
public static <T2> ParameterBuilder<T2> start(ParameterType<T2> paramType) {
return new ParameterBuilder<T2>();
}
ParameterBuilder<T> setName(String name) {
this.name = name;
return this;
}
ParameterBuilder<T> setDefaultValue(T defaultValue) {
this.defaultValue = defaultValue;
return this;
}
void build() {}
}
I'm not sure the context in what you want to use this, but I think the following might be an option.
You can follow the Open/Closed principle and create an interface Parameter and have one implementation per type. The benefit of this, is that you don't need to add a new enum value for each new Parameter you want. You can later pass the class to ParameterBuilder rather than the enum and the ParameterBuilder and Parameter would work together to build what you need.
So ParameterBuilder.start() could return an instance of the specific Parameter and the parameter might have different methods depending on the type of parameter.
I don't think this answer is really good, but hopefully can give you a hint in how to build a potential solution for your context.
You could create an object hierachie for these Email and Url types
public class DefaultType {
protected String name;
protected String defaultValue;
//some constructor
}
public class EmailType extends DefaultType {
...
}
public class URLType extends DefaultType {
...
}
then the parameter builder could look something like this:
public static ParameterBuilder start(DefaultType type) {
ParameterBuilder builder = new ParameterBuilder(type);
builder.setType(type);
return builder;
}
Then you could call it like this:
ParameterBuilder.start(new EmailType("name","value");...
does this help or dont you want to go in this direction?

How to avoid inner classes returning values via a single element array?

I've needed to get a value back from an anonymous inner class. Inner classes can only close over final variables, of course, which leads to this horrible workaround:
public String sampleMethod(){
final String[] output = new String[1];
findResult(new SampleOperation(){
#Override
private void perform(){
output[0] = "result";
}
});
return output[0];
}
private void findResult(SampleOperation op){
op.perform();
}
private static interface SampleOperation {
void perform();
}
Obviously a simplified example; here the class is easily removable, but the principal of the problem is there. If there is a dependency further down (inside findResult(), such as a latch that needs triggered) then unwrapping such a class becomes impractical.
Wrapping the final array means it's accessible, but this has one of the worst smells I've ever come across.
Is there a sane way to get a return type from such a delegate? (i.e. Not use this?)
The problem here is that SampleOperation.perform returns void. Just make it return String (or be generic) and it's fine:
public String sampleMethod(){
return findResult(new SampleOperation(){
#Override
private String perform() {
return "result";
}
});
}
private String findResult(SampleOperation op){
return op.perform();
}
private static interface SampleOperation {
String perform();
}
Ultimately, whenever you're thinking about "I need to get a value back" you should be thinking about a value being returned from a method.
Better pattern for this is using callback interface:
final ResultSender<String> sender = ...;
findResult(new SampleOperation(){
#Override
private void perform(){
sender.send("result");
}
});
The variable sender is still final here, but at least the pattern is reusable and you do not have to create array based work-around.

Categories

Resources