views:

44

answers:

1

Hello
My question is best illustrated with some code. Please browse through the code and read the question at the end.

enum PropertySourceEnum {
    DEFAULT,
    CALCULATED,
    USER,
    UNKNOWN
}

enum PropertyValidityEnum {
    ERROR,
    WARNING,
    OK
}

class WorkerProperty <T>{
    private T value;
    private PropertyValidity validity;
    private PropertySourceEnum source;

    public WorkerProperty(T value) {
        this.value = value;
        this.source = PropertySourceEnum.UNKNOWN;
        this.validity = new PropertyValidity(PropertyValidityEnum.WARNING,
                "Unverified");
    }

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }

    public PropertySourceEnum getSource() {
        return this.source;
    }

    public void setSource(PropertySourceEnum source) {
        this.source = source;
    }

    public PropertyValidity getValidity() {
        return this.validity;
    }

    public void setValidity(PropertyValidity validity) {
        this.validity = validity;
    }

}

class PropertyValidity {
    private final PropertyValidityEnum state;
    private final String message;

    public PropertyValidity(PropertyValidityEnum state, 
            String message) {
        this.state = state;
        this.message = message;
    }
}

class DefaultingService {
    // Using reflection iterate through all the properties
    // and if property source is UNKNOWN or was previous DEFAULTED
    // then see if the database has an appropriate value for it
    // set it to that value and set its source to "DEFAULTED"
}

interface Rule {
    public void fire(Worker w);
}
class ValidationWorkerAge implements Rule {

    @Override
    public void fire(Worker w) {
        // is the worker's age > 16 < 85
        // if age is not set set the validity to ERROR, "required field" 
        int age = (int) w.age.value;
        if (age <= 16) {
            PropertyValidity pv = new PropertyValidity(PropertyValidityEnum.ERROR,
                    "Worker too young");
            w.age.setValidity(pv); 
        } else if (age > 75) {
            PropertyValidity pv = new PropertyValidity(PropertyValidityEnum.ERROR,
            "Worker too old");
            w.age.setValidity(pv); 
        } else {
            PropertyValidity pv = new PropertyValidity(PropertyValidityEnum.OK,
            "OK");
            w.age.setValidity(pv); 
        }

    }

}

class ValidationService {
    // Has a Tree of validation rules and traverses the tree fire()ing each rule
    // along the way

}

class CheckWorkerAgeConsistency implements Rule {

    @Override
    public void fire(Worker w) {
        // if both age and dateOfBirth are set
        // Check that worker age = today().year - dateofBirth.years()
        // or dateofBirth.years() = today().year - age

        // if only DateOfBith is set then calculate age and mark its source as CALCULATED
        // if only age is set then calculate DateOfBith and mark its source as CALCULATED
        // if neither is set do nothing
    }

}


class ConsistencyService {
    // Has a Tree of consistency rules and traverses the tree fire()ing each rule
    // along the way
}

// ---------------------- // Worker Implementation

class Worker1 {
    WorkerProperty<Long> id;
    WorkerProperty<String> name;
    WorkerProperty<String> surname;
    WorkerProperty<Integer> dateOfBirth;
    WorkerProperty<Integer> age;
}

class Manager1 extends Worker1 {

}

// plus other types of worker

// ---------------------- // Alternative Worker implementation

class Worker2 {
    Long id;
    PropertyValidity id_validity;
    PropertySourceEnum id_source;

    String name;
    PropertyValidity name_validity;
    PropertySourceEnum name_source;

    String surname;
    PropertyValidity surname_validity;
    PropertySourceEnum surname_source;

    Integer dateOfBirth;
    PropertyValidity dateOfBirth_validity;
    PropertySourceEnum dateOfBirth_source;

    Integer age;
    PropertyValidity age_validity;
    PropertySourceEnum age_source;
}

class Manager2 extends Worker2 {

}

// plus other types of worker

My question is:
Given the above, how should Worker be implemented. Should I implement Worker as shown in the class Worker1 or Should I implement Worker as shown in Worker2?
Thanks and kind regards

+2  A: 

You may want to consider using JSR 303 Bean Validation for validation. Hibernate Validator is one implementation of this.

Certainly using some ideas from JSR 303 would be good e.g. instead of the WorkerProperty container in Worker1 or PropertyValidity in Worker2, you could consider using Annotations instead.

jamie mccrindle