I am trying to clean up a static function. Let me provide a template of this function here. It is a static function and is used only in two places in the code base one where the isClient is true and another where isClient is false.
public static void validate(BLangFunction resource, DiagnosticLog dlog, boolean resourceReturnsErrorOrNil,
boolean isClient) {
if (!resourceReturnsErrorOrNil) {
dlog.logDiagnostic(Diagnostic.Kind.ERROR, resource.pos, "Invalid return type: expected error?");
}
switch (resource.getName().getValue()) {
case WebSocketConstants.RESOURCE_NAME_ON_OPEN:
case WebSocketConstants.RESOURCE_NAME_ON_IDLE_TIMEOUT:
validateOnOpenResource(resource, dlog, isClient);
break;
case WebSocketConstants.RESOURCE_NAME_ON_TEXT:
validateOnTextResource(resource, dlog, isClient);
break;
case WebSocketConstants.RESOURCE_NAME_ON_BINARY:
validateOnBinaryResource(resource, dlog, isClient);
break;
case WebSocketConstants.RESOURCE_NAME_ON_PING:
case WebSocketConstants.RESOURCE_NAME_ON_PONG:
validateOnPingPongResource(resource, dlog, isClient);
break;
case WebSocketConstants.RESOURCE_NAME_ON_CLOSE:
validateOnCloseResource(resource, dlog, isClient);
break;
case WebSocketConstants.RESOURCE_NAME_ON_ERROR:
validateOnErrorResource(resource, dlog, isClient);
break;
default:
dlog.logDiagnostic(Diagnostic.Kind.ERROR, resource.pos,
"Invalid resource name " + resource.getName().getValue() + " in service ");
}
}
The problem with this code is that the dlog variable is passed to all the other called functions as well as the isClient variable. And the resourceReturnsErrorOrNil is used in only one place.
I thought of refactoring the code to have non-static functions so that dlog can be a class variable and there could be two classes one for client and other for service with all the common code in a super class. Then I thought that this function is used only in two places and should we have instance classes for these?
The source code of this function can be found here.
What would be the best way to refactor based on the clean code principles?
Then I thought that this function is used only in two places and should we have instance classes for these?
That really depends on your goal. I agree, the current code is far from ideal. And the things you outlined all make sense. So, to answer your question: yes, if you think it will be helpful to the quality of your code base, having an "instance" class that only gets used in two places is perfectly fine.
The other thing to carefully look at: maybe there is a way to get rid of that switch. You could for example use a map (key: your constants, value: some Functional interface ... that makes the corresponding validation).
The method should be made non static. This way, you can utilize dependency injection for the logging feature.
Related
I'm trying to create Unit tests for a project. In my project I have a Menu Class, and a VerticalOptions Class.
My menu class has a private VerticalOptions object and a public handleInput method.
When I call my menu's handleInput(key) method, depending on the key I give it it'll do different things, namely call different methods of my VerticalOptions object.
I want to make a unitTest to see if the methods being called are the correct ones, how can I do that?
I've tried adding a Mockito spy to my menu, however since I want to test if the method being called was the method in the private VerticalOptions object, it doesn't really work.
I've also tried putting the spy on the VerticalOptions object, after getting it with a getVerticalOptions method, but it also doesn't work.
public void handleInput(InputKey key)
{
switch (key) {
case S:
case DOWN:
optionsInterface.cycleDown();
break;
case W:
case UP:
optionsInterface.cycleUp();
break;
case SPACE:
case ENTER:
optionsInterface.select();
break;
default:
break;
}
}
#Test
public void testInput() {
MainMenu menu = new MainMenu(game);
VerticalButtonInterface buttonInterface = menu.getOptionsInterface();
VerticalButtonInterface spy = spy(buttonInterface);
menu.handleInput(InputKey.DOWN);
verify(spy, times(1)).cycleDown();
}
This is the test failure I got:
Wanted but not invoked:
verticalButtonInterface.cycleDown();
-> at MenuTest.testInput(MenuTest.java:60)
Actually, there were zero interactions with this mock.
I will give you an alternative view on this. I have seen a lot of people going down the wrong path and when you do that, everything else becomes hard to do / test, which is exactly what you are doing now.
Start here, what are you trying to achieve?
I want to test and make sure that a certain method is called ...
Is this a good thing? What is a unit test not meant to have? That is deep knowledge of the code.
Why? Because every time you make slight changes to the code, you'll have to change the test because of this deep knowledge. if you have 1000 tests, you're in for a hard road.
Ok, so we now know what the problem is, so how do we solve it? Well, first let's make sure we can have a test without deep knowledge of the code.
How do we do that? Well, imagine that your code adds an extra step, a flag which sets a state. You might have a flag which stores a resulting state ...
you have 3 methods you want to call, so you will need 3 different states, so create a variable which reflects that, be it a string, or an enum or whatever else makes you happy.
For example sake, let's say we create a string with 3 possible values: cycleDown, cycleUp and select.
your code starts to look something like :
public string handleInput(InputKey key)
{
String state = determineState(key);
SomeType someResult = executeActionForState(state);
}
public String determineState(string key)
{
String state = "";
switch (key) {
case S:
case DOWN:
state = "cycleDown";
break;
case W:
case UP:
state = "cycleUp";
break;
case SPACE:
case ENTER:
state = "select";
break;
default:
break;
}
return state;
}
public void executeActionForState(string state)
{
if ( state == "cycleup" ) {
}
etc etc
}
Now, I may not necessarily code your example like this, this is a bit forced, it depends on what other things you're doing with the code, but this is meant to show how you separate functionality from UI aspects.
I can easily test the state method, I can change its code and I wouldn't have to change the test, because the test would look at the inputs and outputs and not how things are achieved.
Unit testing is about functionality, it's about having simple tests that don't need to change once created. Verifying that a method has been called doesn't give you anything worthwhile, because you don't know what that method does later.
UI stuff you can test in other ways, unit testing is only about correct functionality. If you do not make this separation clear then you will have trouble maintaining your tests, it will become harder and harder until you give up.
You would test that you get the correct state, then you test that cycleUp method does something correct based on your requirements and that's how you know each part works in isolation. Later on you start looking at integration tests, Automated UI tests, but those are different things. Keep unit testing for what it's meant to do, keep it simple, keep it not tied to other code and then everything becomes simple. You won't need to mock much, you won't need to worry too much about complex setups and you won't need to change your tests every time something in the code changes.
Now, to address the final part of the question, private methods, you test them by observing their outputs. You must have something public in your class that changes when a private method is called. So test that.
So is this faster:
for (int i = 0; i < example.length; i++) {
switch (i) {
case 0: return example.field0;
case 1: return example.field1;
case 2: return example.field2;
case 3: return example.field3;
case 4: return example.field4;
case 5: return example.field5;
case 6: return example.field6;
case 7: return example.field7;
case 8: return example.field8;
case 9: return example.field9;
case 10: return example.field10;
}
}
Or this:
for (int i = 0; i < example.length; i++) {
return example.class.getField("field" + i);
}
I just want to know because it seems a bit tedious doing the first one and I do not want to repeat lots of lines of code that are basically doing the exact same thing.
What exactly is field0...field10? Depending on the relation between these fields, you might want to organize them in an appropriate data structure.
Do you have 11 fields of the same type and (besides their index) the same meaning, like the x-coordinates of the points of a line. Then an Array or a List might be the correct data structure.
Do these 11 fields cover the same aspect of the object and could be considered to belong together but can be named individually, like e.g. metadata of a document. The you might use a map (as "Hovercraft Full Of Eels" suggests) or put them into their own object. If you put the fields into a map, you might want to use an enumeration as key.
Are these 11 fields basically independent of each other? Then please don't try to access them together but write a getter and setter per field.
"Tedious" and "many lines of code" is not a good guide. It may be a sign of a bad design that should be corrected (see above). Otherwise there's usually a workaround in your favorite IDE. Creating setters and getters should only be a click away!
Please use reflection only if there's no other way. For examples see How could Reflection not lead to code smells?. Reflection in Java has quite a few drawbacks: bad performance, complex and difficult to get right. The main argument against reflection is IMHO that the compiler and IDEs are not made for reflection. You rename field<x> to metadata<x>? The refactoring will not change [...] getField("field" + i); and the compiler will not complain!
But to answer the actual question: Reflection is most likely a lot slower than direct Java code.
I have written a method based that returns different types based on the result of a switch condition. I am not able to get different return type based on the cases.
public Object callCommonMethod(char key, Customer customer)
throws SFWException, ServiceException, CloneNotSupportedException {
switch (key) {
case 'C':
performGetCDBProfile(customer.getWizardNum());
dbData=true;
break;
case 'U':
performUpdate(cdbProfileInfo);
break;
case 'D':
updateCDBProfile(cdbProfileInfo);
break;
case 'W':
updateWebProfile(customer);
break;
case 'M':
ObjectMappingService.mapInfoToEDO(cdbProfileInfo);
break;
}
return customer;
}
How can I implement that performGetCDBProfile(customer.getWizardNum()); returns cdbProfileInfo obj, performUpdate(cdbProfileInfo); and updateCDBProfile(cdbProfileInfo); are methods that don't have return type, and updateWebProfile(customer); returns customer object.
A method can only be declared to return one type. You can return different subtypes, but the compiler will only know at compile time that you're returning your declared base class.
Normally this isn't a problem if your subtypes are strongly related and your calling code can act on either type without knowing what your actual type is (this is the essence of polymorphism) e.g.
Vehicle v = getBusOrCar();
v.drive();
If you can't do something useful like the above (e.g. you're returning an Object since that's the most common base type), then that to me is a code smell. Is your method doing two different things ?
If you want to optionally return something or nothing, you can always return your object (a Customer type?) or null, check for the null upon receipt/prior to usage. Another possiblity is to return an Optional container, and consequently the API indicates that you may get an object back.
Either way, it still seems to me that perhaps your method has a variety of responsibilities. Perhaps your switch statement should delegate more functionality to another method/class for each case, and so you wouldn't need to return an object and act on it then ?
If you have a method and it looks like it should return objects of different entities, types - then something's definitely wrong with your architecture.
Most probably, your method breaks the single responsibility principle.
Do not implement interface with the common method or create any other hacks. Change the logic of invocation. Remember: Abstractions should not depend upon details.
Split your method up. Why would someone return Customer object or cdbProfileInfo in a single method?
If you are going to call this method from a single place with different keys, then how are you going to work with results of different types? If you are going to call this method with different keys from different places - then, you can simply split this method up.
It is a bad practice to return Object and check its instance in the calling method.
Even then if you still want to achieve your goal, Why cant you return null in those 2 cases where the method doesnt have anything to return? (not recommeneded)
While starting to build an application, I stared using a switch case block with only five cases to be considered. Later when the build progressed, more cases came into picture and that started creating problems. I know I might have designed it wrongly at the first place, but if such things come as a change how do I effectively approach this? An example is given below
Starting with this
switch case 1: /*do function1()*/ break;
case 2: /*do function2()*/ break;
Later, a 100 cases come in
switch case 1: /*do function1()*/ break;
case 2: /*do function2()*/ break;
....
case 100: /*do function100()*/ break;
I am sure that converting these cases into 100 if conditions is not going to be a very good approach, so is there a way this can be done?
Please consider that the functions given in the code above are simple mathematical functions for now.
Consider an interface like this:
public interface MyFunction {
public void compute();
}
and a Map with the previous interface as values:
Map<Integer,MyFunction> myFunctionsMap = new HashMap<>();
You need to initialize the map with all of you functions:
myFunctionsMap.put(1,new MyFuntion() {
#Override
public void compute() {
/*do function1()*/
}
});
for each of your functions, the syntax might be a bit heavy with anonymous classes, you can implement you functions in separate classes and use them as well.
Now instead of the switch, you simply use the map:
myFunctionsMap.get(theValueSwitched).execute();
Depending of how you initialize the map, the values of the keys and how you use it, you might want to check myFunctionsMap.contains(theValueSwitched) (this would be your default case if you have one).
Edit: Java 8 shorter syntax would be myFunctionsMap.put(1,() -> {/*do function1()*/});
You could name your methods something like method1, method2, method3 , etc .. and use reflexion to call them, using you variable. You wouldn't have a lengthy switch, that way.
I have no ideas if that is efficient or not, though.
Here's a neat exemple, from wikipedia's reflection page.
Object foo = Class.forName("complete.classpath.and.Foo").newInstance();
// Alternatively: Object foo = Foo.class.newInstance();
Method m = foo.getClass().getDeclaredMethod("hello", new Class<?>[0]);
m.invoke(foo);
hope that helps
For example:
3 methods exist
"map1method,
map2method,
map3mehtod"
and I want to call the right one depending on what the integer 'activemap' has currently stored in it.
I could do an If statement
"If (activemap == 1)
map1method;
elseif (activemap ==2)
..."
But is there a possible way of using the integer more efficiently?
Like a "map(activemap)method"
Also could I also call a specific array in a batch of them in the same fashion.
This is all in java by the way.
It is possible via reflection but I would urge you to stay away from that approach. Why not have all three methods built into one? One option would be to use a switch statement to handle the various cases:
void mapMethod(int activemap) {
switch (activemap) {
case 1:
// map1method
break;
case 2:
// map2method
break;
case 3:
// map3method
break;
default:
break;
}
}
Now, you can call
mapMethod(activemap)
If you want to take the reflection approach instead (which as I said I don't think you should), you can do something along the lines of
String methodName = "map" + activemap + "method";
MyClass.class.getDeclaredMethod(methodName).invoke(null);
A switch statement would be slightly easier to read:
switch(activemap) {
case 1: map1method(); break;
case 2: map2method(); break;
}
You could use reflection to build the method name up at runtime, but that wouldn't be simpler. Reflection is a lot of code.
The most effective way to do this is to either create an enum to represent the different calls and use the int as a lookup for the enum value, or if that's not possible, to use a switch statement. You can use reflection to accomplish what you're talking about (look up a method at runtime based on its name), but it's less efficient and more cumbersome than either of those options.
You can do it using Reflection, It will be something like this:
java.lang.reflect.Method method;
method = myObject.getClass().getMethod("map+"activemap"+method", param1.class, param2.class, ..);
method.invoke(object, arg1, arg2,...);