Best approach to test several similar classes in spock test? - java

I have a lot of similar classes (actually it is different types of events with one parent class). It is about 30 classes already and the number will be growing. Every class has its own logic to process, but there several fields that are exists in every class. I want to be sure every event's flow is taking care of common fields. It is become more complex, because of adding new event types and adding new flows. The best approach will be to create some dynamic test that will be checking common fields are processed. Saying 'dynamically' I mean the ability of the test automatically discover new classes and put them into the test pack. We are using spock, but it is not possible to dynamically generate 'where' section of test. I come with quite a strange approach that is not working, but illustrate my idea:
def "dynamic test"() {
given:
def classes = methodToGetListOfEventClass()
when:
for(Class clazz : classes) {
ParentEvent event = clazz.getDeclaredConstructor().newInstance() as ParentEvent
service.sendEvent(event)
}
}
then:
for(Class clazz : classes) {
ParentEvent event = clazz.getDeclaredConstructor().newInstance() as ParentEvent
1 * sendExternalEvent("someId", event.getClass().getName(), Collections.emptyMap())
//check common fields exists
}
}
}
}
So I just try to create an instance of every class, pass it into the event handler and check created external event has all common fields set. It looks ugly and does not work. Is any suggestion on how to implement such a dynamic test?

You can use dynamic data pipes. Here is a simple example, based on your pseudo code and the limited information you provided. Because you did not say if you use Spock 1.3 or 2.x, I made sure that the example works on 1.3, too.
Given a situation as follows (all Groovy code, but the classes under test can be Java ones, too):
interface Event {
void init()
void sendExternalEvent(String id, String className, Map options)
}
class Service {
void sendEvent(Event event) {
event.sendExternalEvent("123", event.class.name, [:])
}
}
abstract class BaseEvent implements Event {
private static final Random random = new Random()
private static final String alphabet = (('A'..'Z') + ('0'..'9')).join()
protected int id
protected String name
#Override
void init() {
id = 1 + random.nextInt(100)
name = (1..10).collect { alphabet[random.nextInt(alphabet.length())] }.join()
}
}
class FirstEvent extends BaseEvent {
#Override
void sendExternalEvent(String id, String className, Map options) {}
String doFirst() { "first" }
}
class SecondEvent extends BaseEvent {
#Override
void sendExternalEvent(String id, String className, Map options) {}
String doSecond() { "second" }
}
class ThirdEvent extends BaseEvent {
#Override
void sendExternalEvent(String id, String className, Map options) {}
int doThird() { 3 }
}
You can implement your dynamic test for BaseEvent subclasses like this:
import spock.lang.Specification
import spock.lang.Unroll
class DynamicBaseClassTest extends Specification {
#Unroll("verify #className")
def "basic event class functionality"() {
given:
def service = new Service()
def event = Spy(baseEventClass.getConstructor().newInstance())
when:
event.init()
then:
// '.id' and '.name' should be enough, but on Spock 2.1 there is a problem
// when not explicitly using the '#' notation for direct field access.
event.#id > 0
event.#name.length() == 10
when:
service.sendEvent(event)
then:
1 * event.sendExternalEvent(_, event.class.name, [:])
where:
baseEventClass << getEventClasses()
className = baseEventClass.simpleName
}
static List<Class<? extends BaseEvent>> getEventClasses() {
[FirstEvent, SecondEvent, ThirdEvent]
}
}
Try it in the Groovy web console.
The notable things are:
where:
baseEventClass << getEventClasses()
The data pipe is declared to call a data provider method, just like in your example. What getEventClasses() does, is totally up to you: return a fixed list, scan the classpath or whatever.
def event = Spy(baseEventClass.getConstructor().newInstance())
The spy is necessary to have both the real behaviour for the class under test - you do not want to mock it, of course - and the ability to verify interactions on it later:
then:
1 * event.sendExternalEvent(_, event.class.name, [:])
BTW, if you are unfamiliar with #Unroll, it makes the spec look like this in an IDE or a test report:

Related

Is it appropriate to use reflection to create a list of objects of all subclasses?

In my program, different features are divided into different modules, potentially hundreds of modules,
each module is a subclass of an abstract Module class
which look something like this
public abstract class Module {
public final String name;
public Module(String name){
this.name = name;
}
public abstract void execute();
}
with subclasses that look like this
public class Mod1 extends Module{
public Mod1() {
super("Mod1");
}
#Override
public void execute() {
//Do something
}
}
and I need to make a list of instances of all modules but doing it like this is kinda tedious since my program might have hundreds of modules and it might be hard to debug(I might miss a few lol)
private static final List<Module> MODULES = new ArrayList<>();
public void init(){
MODULES.add(new Mod1());
MODULES.add(new Mod2());
MODULES.add(new Mod3());
MODULES.add(new Mod4());
MODULES.add(new Mod5());
}
so I think using reflection might be the way to go but after a quick google search, I see many people don't like reflection in production code, so I come here to ask if this is an appropriate case to use reflection or is there any reason or design change to avoid using reflection in this particular case
edit: the list will be used stuff like rendering modules in gui or calling execute method of the module from other user interface like command(simply find the module with matching name and execute it)
note: this is not how my code actually look like but a highly simplified version that give a similar idea
For a minimal-effort approach, java provides the built-in class java.util.ServiceLoader.
With this class you can obtain all available implementations of a service class (in this case Module) like
ServiceLoader moduleLoader = ServiceLoader.load(Module.class);
for (Module mod : moduleLoader) {
System.out.println(mod.name);
}
Note that I highlighted the term available in the previous sentence. In fact, the ServiceLoader implementation does not perform any advanced class-hierarchy lookup, instead it relies on a specific resource file named equal to the canonical name of the Module class.
META-INF/services/com.example.project.Module
com.example.project.impl1.Module1
com.example.project.impl2.Module2
Where each line of the file references an available implementation of Module.
Now, ServiceLoader is an implementation of the java SPI specification, which does not necessarily have to qualify perfectly for your use case. However, since its idea of service loading and providing is rather simple, you can easily build your own variant.
public class JsonServiceLoader<S> {
private Class<S> service;
private Map<String, String> serviceIdentifiers;
public static <T> JsonServiceLoader load(Class<T> service, ClassLoader cl) {
Map<String, String> serviceIdentifiers = new HashMap<>();
String name = "META-INF/json-services/" + service.getCanonicalName();
// TODO check for null references where necessary
for (Enumeration<URL> resources = cl.getResources(name); resources.hasMoreElements();) {
try (InputStream resource = resources.next().openStream()) {
for (Map.Entry<String, String> identifier : parseJson(resource).entrySet()) {
serviceIdentifers.merge(
identifer.getKey(),
identifer.getValue(),
(value1, value2) -> throw new ServiceConfigurationError(
"duplicate service identifier '" + identifier.getKey() + "'"
);
);
}
}
}
return new JsonServiceLoader<>(service, serviceIdentifiers);
}
private static Map<String, String> parseJson(InputStream resource) {
// TODO parse JSON data from the given stream using your favourite JSON facility
/*
* If you want to use a different style of resources, e.g. XML, this is the only
* location you have to change (you might want to rename 'json-services' though).
*/
return new HashMap<>();
}
private JsonServiceLoader(Class<S> service, Map<String, String> serviceIdentifiers) {
this.service = service;
this.serviceIdentifiers = serviceIdentifiers;
}
public Set<String> getServiceIdentifiers() {
return Collections.unmodifiableSet(serviceIdentifiers.keySet());
}
public S getService(String name) {
String className = serviceIdenfiers.get(name);
if (null == className) {
throw new IllegalArgumentException("invalid service identifier '" + name + "'");
}
// TODO improve error handling
try {
return service.cast(Class.forName(className).newInstance());
} catch(Exception exc) {
throw new ServiceConfigurationError("could not load service '" + name + "'", exc);
}
}
}
Your JSON resources could look like
META-INF/json-services/com.example.project.Module
{
"Mod1" : {
"class" : "com.example.project.impl1.Module1"
},
"Mod2" : {
"class" : "com.example.project.impl2.Module2"
}
}
allowing future extensions.
At this point, the Module class also does not need to know its name (the class member name) anymore, since you can always ask the service loader for an appropriate instance. (If you do so at some place in your code, you will already know for which name you just asked.) If so desired, you can also add more logic to this JsonServiceLoader, such as caching.
Ultimately, it all depends on how much information you want to process around your Module and how much of this information you want the Module implementations to handle and how much of it you want the service framework to handle.
Perhaps you can pass the list into the constructor of the parent class and add subclass itself to the list in the constructor method.
Just like this
public abstract class Module {
public final String name;
public Module(String name, List<Module> list) {
this.name = name;
list.add(this);
}
public abstract void execute();
}
private static final List<Module> MODULES = new ArrayList<>();
public void init(){
new Mod1(MODULES);
}

How to implement a Java method, that will call another method, based on the name of the calling class?

We have a Java class, WebCenterGrid. This class is full of methods to do things in a grid such as finding a row, finding a cell value, sorting a column. We have several classes that use this class. The classes using it all refer to different grids, but the functionality is the same.
The only thing that differs is how to create the grid. Some classes do a search which populates the grid (search also refreshes). Some do an updateList() to update the grid, etc.
I would like to add a method to WebCenterGrid to refresh the grid. The problem is as I said each method has a different name.
I somehow want to pass into WebCenterGrid the name of a method to call to do the refresh. I have done some searches and found something about lambda which I did not really understand.
I haven't used C++ in a while but there was some way to pass a method into those methods. This class is in Java not C++, but is there some sort of understandable equivalent?
public class WebCenterGrid {
....
....
public void refresh(Method meth) {
meth();
}
}
Basically, there are two ways.
One is to use reflection, this means: relying on runtime type information, commonly derived from raw strings. Like saying: I have some object of class X, and I want to invoke the method named "doTheFoo()" on that object.
See here for all the glory details.
A slightly better way is to use the MethodHandle class, instead of the "raw" reflection Method class. See here for handles.
But then: reflection is happening at runtime. Your code compiles fine, but if you get any detail wrong, it blows up at runtime.
Thus I suggest looking into lambdas, based on Function, see here.
Instead of having a Method parameter, accept an Interface, and the implementation will define what will be called.
You can use lambdas here as well if you'll define your interface as Functional Interface.
Example:
public class Main {
public static void main(String[] args) {
act(new Run());
act(new Swim());
// Passing a body of the function you want to execute
act(() -> System.out.println("walking"));
}
public static void act(Action action) {
action.act();
}
}
#FunctionalInterface
interface Action {
void act();
}
class Run implements Action {
#Override
public void act() {
System.out.println("running");
}
}
class Swim implements Action {
#Override
public void act() {
System.out.println("swimming");
}
}
Output:
running
swimming
walking
If you have predefined refresh logic, you can create association resolver based on mapping which will help you to define proper service based on some conditions.
public class Main {
static Map<ActionType, Action> actionResolver = new HashMap<>();
// Static init is just for brevity sake
static {
actionResolver.put(ActionType.RUN, new Run());
actionResolver.put(ActionType.WALK, new Walk());
actionResolver.put(ActionType.SWIM, new Swim());
}
public static void main(String[] args) {
act(ActionType.RUN);
act(ActionType.WALK);
act(ActionType.SWIM);
}
public static void act(ActionType actionType) {
Action action = actionResolver.get(actionType);
if (action == null)
throw new IllegalArgumentException("ActionType was not registered");
action.act();
}
}
enum ActionType {
RUN,
SWIM,
WALK
}
Output is the same as above.
Well, since we can't see any of your code, I'll suggest the following solution, that's based on my personal assumption about how your code works.
Please keep in mind that this method is not so scale-able and pretty inefficient if you have 100 different ways of creating grids.
However, if you have (e.g. 3) types of such ways for example, you can use constants!
See below:
public class WebCenterGrid {
//Declare constants with meaningful names for grid creation (add more as you like)
public static final int DEEP_COPY=1, SEARCH=2, REBUILD=3;
public void makeDeepCopy(){
//implementation goes here..
}
public void searchAndPopulate(){
//implementation goes here..
}
public void rebuildGrid(){
//implementation goes here..
}
public void refresh(int operation) {
switch(operation) {
//based on 'operation', call appropriate method!
case DEEP_COPY: this.makeDeepCopy(); break;
case SEARCH: this.searchAndPopulate(); break;
case REBUILD: this.rebuildGrid(); break;
//you can have a default operation for any parameter that is not
//in the list of our defined constants(i.e. the number 143)
default: simpleRefresh(); break;
}
}
}
So what makes the above solution work?
Basically, when you call refresh(int operation) from one of your other classes, you need to pass an int as a parameter. That integer is one of the constants defined at the very top of the class. According to which constant was passed, the switch case will determine which method to call.
EXAMPLE (Let's say that AwesomeGridCreator is a class that when it calls refresh(), in order to update a grid, it has to do a search and then populate the grid (like you mention in your question).
We name an integer (for simplicity) SEARCH_POPULATE and we give it ANY value we want. For example 286.
We can then use that constant from any other class, because we don't care what its value is (in this case 286, but the functionality it provides when calling refresh().
public class WebCenterGrid {
/*some code here*/
public static final int SEARCH_POPULATE = 286; //integer value doesn't matter
public void refresh(int operation) {
switch(operation) {
case SEARCH_POPULATE: this.searchAndPopulate(); break;
}
/*...some other code here, we don't care..*/
}
Then, at the 'calling' class:
public class AwesomeGridCreator{
//some code here
WebCenterGrid wcg = new WebCenterGrid();
//The parameter that we pass below (2), will make the refresh() method call
//the method that we defined in our switch cases ('searchAndPopulate()').
wcg.refresh(wcg.SEARCH_POPULATE);
}

how to determine if a method has been overriden?

Consider the following scenario:
I am working on a framework that allows users to subclass a particular abstract class provided by the framework, which will allow them to insert their own functionality into the flow of the application.
For example a class like this:
public class MyAbstractClass {
protected String step1(String input) {
// default implementation
}
public final void process(MyObject objct) {
// some steps
String someData = step1(object.getInput());
// some more steps
}
}
Now, in a newer version of the framework, I want to change the step1 method to use some object (which can be converted to the argument of the current step1 method) as a parameter. However, I do not want to break the code for the users who have already extended this class.
I am currently planning to do it this way:
public class MyAbstractClass {
private boolean isOldStep1Overriden = true;
protected String step1(MyObject input) {
String oldValue = step1(input.getInput());
if (isOldStep1Overriden) {
// the method has been overriden - some logic here to handle this (assume this logic is known)
} else {
// the method has not been overriden - ignore the old value and carry out the new default processing
}
}
#Deprecated
protected String step1(String input) {
// default implementation
isOldStep1Overriden = false;
}
public final void process(MyObject objct) {
// some steps
String someData = step1(object);
// some more steps
}
}
Are there any other ways to implement such a use case?
The following options are also on hold :
Create a new abstract class for the new implementation - This would prevent existing users from getting the new features without modifying their code.
Use reflection - I would prefer not to, if possible
EDIT: Some more relevant background information:
The framework in question is actually an application which is deployed to a shared location, and users (developers) of this framework submit extensions to be installed in it. So the application itself could be upgraded without the developers of the extensions having made any changes to their code. To take an example of a similar system, consider firefox and its addons - both developed by separate teams, and firefox can be updated without the addon developer's knowledge.

How to test the interaction between a method and its two helpers?

I have the following structure of my Java code:
public MyClass {
// some class variables
...
private void process() {
private MyObject obj;
...
obj = createHelper();
...
messageHelper(obj, "One of several possible strings");
...
messageHelper(obj, "Another call with a different string");
...
}
private MyObject createHelper {
MyObject obj = new MyObject();
// some Setter calls
...
return obj;
}
private void messageHelper (MyOject obj, String message) {
...
}
}
I would like to test, that based on properties obj (that I would like to specify), messageHelper() receives the right string. In other words I need to control the result of one method and have access to the parameters of the other.
I'm still very shaky with all this Mock/Stub/Spy stuff.
It seems to me that I need to Spy on MyClass, stub CreateHelper() with a "manually" created object and not sure what for intercepting call parameters for messageHelper().
Also I noted that Wiki cautions against using Spies:
Think twice before using this feature. It might be better to change
the design of the code under specification.
So what would an appropriate Spocky way to accomplish the task?
Slightly Refactored Code: (5/5/14)
public MyClass {
// some class variables
private messageSevice = new messageService();
...
private void process() {
private MyObject obj;
...
obj = new MyObject(parameters ...);
...
if (someCondition) {
messageService.produceMessageOne(obj);
}
...
if (otherCondition) {
messageService.produceMessageTwo(obj);
{
...
}
}
public class MessageService implements IMessageService {
private final static MSG_ONE = "...";
private final static MSG_TWO = "...";
...
public void produceMessageOne(MyObject obj) {
produceMessage(obj, MSG_ONE);
...
}
public void produceMessageOne(MyObject obj) {
produceMessage(obj, MSG_TWO);
}
private void produceMessage(MyObject obj, String message) {
...
}
}
I would greatly appreciate if someone suggests the way it should be tested with Spock.
The caution you're referring to is rightfully there. There's a very good correlation between testable code and good design (I recommend watching this lecture from Michael Feathers to understand why http://www.youtube.com/watch?v=4cVZvoFGJTU).
Using spies tends to be a heads up for design issues since it usually arises from the impossibility of using regular mocks and stubs.
It's a little hard to predict from your example, since you're obviously using pseudo names, but it seems that the design of the MyClass class violates the single responsibility principle (http://en.wikipedia.org/wiki/Single_responsibility_principle), since it does processing, creation and messaging (3 responsibilities).
If you're willing to change your design, so that the processing class (MyClass) will do only processing, you'll be providing another class that does the creation (MyObjectFactory), and yet another class that does the messaging (MyObjectMessager) either through a constructor, setter methods or by dependency injection.
Using this new design, you can create an instance of the class you're testing (MyClass), and pass it mock objects of both the factory and messaging classes. Then you'll be able to verify whatever you want on both.
Take a look at this example (using Mockito):
public class MyClassTest {
#Test
public void testThatProcessingMessagesCorrectly() {
MyObject object = mock(MyObject.class);
MyObjectFactory factory = mock(MyObjectFactory.class);
when(factory.createMyObject()).thenReturn(object);
MyObjectMessager messager = mock(MyObjectMessager.class);
MyClass processor = new MyClass(factory, messager);
processor.process();
verify(factory).createMyObject();
verify(messager).message(EXPECTED_MESSAGE_1);
verify(messager).message(EXPECTED_MESSAGE_2);
...
verify(messager).message(EXPECTED_MESSAGE_N);
}
...
}
Here's a Spock example (untested, double check before using ...):
public class MyClassSpec extends Specification {
def "check that the right messages are produced with the expected object"() {
given:
def messageService = Mock(IMessageService)
def testedInstance = new MyClass()
testedInstance.setMessageService(messageService)
when:
testedInstance.process()
then:
1 * messageService.produceMessageOne(_)
1 * messageService.produceMessageTwo(_)
}
}
If you're a hammer, every problem is a nail
I'd like to call exception-to-the-rule here and say that sometimes stubbing private methods - necessitating spies - can be both correct and useful.
#eitanfar is most likely accurate in his analysis of the function, and 95% of the time this is the case, but as with most things - I believe - not always.
This is for those of us who believe they have an exception but get the usual "code smell" argument.
My example is a complex argument validator. Consider the following:
class Foo {
def doThing(...args) {
doThing_complexValidateArgs(args)
// do things with args
}
def private doThing_complexValidateArgs(...args) {
// ... * 20 lines of non-logic-related code that throws exceptions
}
}
Placing the validator in it's own class IMO seperates the concern too much. (a FooMethodArgumentValidator class?)
Refactoring out the validation arguably significantly improves readability of the doThing() function.
doThing_complexValidateArgs() should not be public
The doThing() function benefits from the reability of a simple call validateArgs(...) and maintains encapsulation.
All I need to be sure of now is that I have called the function within the parent one. how can I do that? well - correct me if I'm wrong - but in order to do that, I need a Spy().
class FooSpec extends Specification {
class Foo {
def doThing(...args) {
doThing_controlTest(args)
doThing_complexValidateArgs(*args)
// do things with args
}
def doThing_controlTest(args) {
// this is a test
}
def private doThing_complexValidateArgs(...args) {
// ... * 20 lines of code
}
}
void "doThing should call doThing_complexValidateArgs" () {
def fooSpy = Spy(Foo)
when:
fooSpy.doThing(1, 2, 3)
then:
1 * fooSpy.doThing_controlTest([1,2,3]) // to prove to ya'll we got into the right method
1 * fooSpy.invokeMethod('doThing_complexValidateArgs', [1, 2, 3]) // probably due to groovy weirdness, this is how we test this call
}
}
Here is my real life example I used for a static private method:
#SuppressWarnings("GroovyAccessibility")
#ConfineMetaClassChanges(DateService) // stops a global GroovySpy from affecting other tests by reseting the metaclass once done.
void "isOverlapping calls validateAndNormaliseDateList() for both args" () {
List list1 = [new Date(1L), new Date(2L)]
List list2 = [new Date(2L), new Date(3L)]
GroovySpy(DateService, global: true) // GroovySpy allows for global replacement. see `org.spockframework.mock.IMockConfiguration#isGlobal()`
when:
DateService.isOverlapping(list1, list2)
then:
1 * DateService.isOverlapping_validateAndNormaliseDateList('first', list1) // groovy 2.x currently allows private method calls
1 * DateService.isOverlapping_validateAndNormaliseDateList('second', list2)
}

What is the Best Way to Extend Functionality?

I've run into a situation in which I was to extend the functionality of a given class, but I'm not sure of the best way to go about this. I started by invoking functionality "upwards" and have now switched to "downwards", but I see issues with both. Let me explain what I mean. First, the "upwards" approach:
public class ParentValidator
{
public void validate() {
// Some code
}
}
public class ChildValidator extends ParentValidator
{
#Override
public void validate() {
super.validate();
// Some code
}
}
public class GrandchildValidator extends ChildValidator
{
#Override
public void validate() {
super.validate();
// Some code
}
}
This functions perfectly well, but it requires that I always remember to place super.validate() in my method body or the logic in the parent class(es) won't be executed. In addition, extension in this manner can be considered "unsafe" due to the fact that a child class could actually replace/modify the code defined in the parent class. This is what I call invoking methods "upwards" because I'm invoking methods from higher level classes as I go.
To counter these shortfalls, I decided to make ParentValidator.validate() final and have it invoke a different method. Here's what my code was modified to:
public class ParentValidator
{
public final void validate() {
// Some code
subValidate();
}
protected void subValidate() {}
}
public class ChildValidator extends ParentValidator
{
#Override
public final void subValidate() {
// Some code
subSubValidate();
}
protected void subSubValidate() {}
}
public class GrandchildValidator extends ChildValidator
{
#Override
public void subSubBalidate() {
// Some code
subSubSubValidate();
}
protected void subSubSubValidate();
}
This is what I was referring to when I say that I'm calling downwards as each class invokes methods on classes "down" the inheritance chain.
Using this approach, I can be guaranteed that the logic in the parent class(es) will be executed, which I like. However, it doesn't scale well. The more layers of inheritance I have, the uglier it gets. At one level, I think this is very elegant. At two levels, it starts to look shoddy. At three or more, it's hideous.
In addition, just as I had to remember to invoke super.validate() as the first line of any of my children's validate methods, I now have to remember to invoke some "subValidate" method at the end of any of my parent's validate methods, so that didn't seem to get any better.
Is there a better way to do this type of extension that I haven't even touched on. Either of these approaches have some serious flaws and I'm wondering if there's a better design pattern I could be using.
In what you describe as your first approach you are using simple inheritance, your second approach is closer to what the Gang of Four [GoF] called a Template Method Pattern because your parent class is using the so-called Hollywood Principle: "don't call us, we'll call you".
However, you could benefit from declaring the subvalidate() method as abstract in the parent class, and by this, make sure all subclasses are forced to implement it. Then it would be a true template method.
public abstract class ParentValidator
{
public final void validate() {
//some code
subValidate();
}
protected abstract void subValidate() {}
}
Depending on what you are doing there are other patterns that could help you do this in a different manner. For instance, you could use a Strategy Pattern to peform the validations, and by this favoring composition over inheritance, as suggested before, but a consequence is that you will need more validation classes.
public abstract class ParentValidator
{
private final ValidatorStrategy validator;
protected ParentValidator(ValidatorStrategy validator){
this.validator = validator;
}
public final void validate() {
//some code
this.validator.validate();
}
}
Then you can provide specific validation strategies for every type of Validator that you have.
If you want to get the best of both worlds you might considering implementing the solution as a Decorator Pattern where subclasses can extend the functionality of a parent class and still stick to a common interface.
public abstract class ValidatorDecorator implements Validator
{
private final Validator validator;
protected ParentValidator(Validator validator){
this.validator = validator;
}
public final void validate() {
//some code
super.validate(); //still forced to invoke super
this.validator.validate();
}
}
All patterns have consequences and advantages and disadvantages that you must consider carefully.
I'd prefer to 1) program against interfaces, and 2) opt for composition over inheritance. This is how I have done. Some people like it, some do not. It works.
// java pseudocode below, you'll need to work the wrinkles out
/**
* Defines a rule or set of rules under which a instance of T
* is deemed valid or invalid
**/
public interface ValidationRule<T>
{
/**
* #return String describing invalidation condition, or null
* (indicating then that parameter t is valid */
**/
String apply(final T t);
}
/**
* Utility class for enforcing a logical conjunction
* of zero or more validatoin rules on an object.
**/
public final class ValidatorEvaluator
{
/**
* evaluates zero or more validation rules (as a logical
* 'AND') on an instance of type T.
**/
static <T> String apply(final T t, ValidationRule<T> ... rules)
{
for(final ValidationRules<T> v : rules)
{
String msg = v.apply(t);
if( msg != null )
{
return msg; // t is not valid
}
}
return null;
}
}
// arbitrary dummy class that we will test for
// i being a positive number greater than zero
public class MyFoo
{
int i;
public MyFoo(int n){ i = n; }
///
}
public class NonZeroValidatorRule implements ValidatorRule<MyFoo>
{
public String apply(final MyFoo foo)
{
return foo.i == 0 ? "foo.i is zero!" : null;
}
}
// test for being positive using NonZeroValidatorRule and an anonymous
// validator that tests for negatives
String msg = ValidatorEvaluator.apply( new MyFoo(1),
new NonZeroValidatorRule(),
new ValidatorRule<MyFoo>()
{
public String apply(final MyFoo foo)
{
return foo.i < 0 ? "foo.i is negative!" : null;
}
}
);
if( msg == null )
{
\\ yay!
...
}
else
{
\\ nay...
someLogThingie.log("error: myFoo now workie. reason=" + msg );
}
More complex, non-trivial evaluation rules can be implemented this way.
The key here is that you should not use inheritance unless there exists a is-a relationship. Do not use it just to recycle or encapsulate logic. If you still feel you need to use inheritance, then don't go overkill trying to make sure that every subclass executes the validation logic inherited from the superclass. Have implementations of each subclass do an explicit execution on super:
public class ParentValidator
{
public void validate() { // notice that I removed the final you originally had
// Some code
}
}
pubic class ChildValidator extends ParentValidator
{
#Override
public void validate() {
// Some code
super.validate(); // explicit call to inherited validate
// more validation code
}
}
Keep things simple, and don't try to make it impossible or fool-proof. There is a difference between coding defensively (a good practice) and coding against stupid (a futile effort.) Simply lay out coding rules on how to subclass your validators. That is, put the onus on the implementors. If they cannot follow the guidelines, no amount of defensive coding will protect your system against their stupidity. Ergo, keep things clear and simple.
I prefer to using composition over inheritance if your subSubSubValidate is related general functionality. You can extract new class and move it there than you can use it without inheritance in the other classes.
There is also
"Favor 'object composition' over
'class inheritance'." (Gang of Four
1995:20)
maybe a look at the visitor pattern may help you to develop your pattern.
Here are some information on it : http://en.wikipedia.org/wiki/Visitor_pattern

Categories

Resources