bez
bez

Reputation: 187

How to do different types of object state validation

I need to provide records to the caller from one or two different data sources and either within a specified date range or year range.

My dilemma is should I use overloaded methods or a Request object with state validation logic.

So either:

public List<Record> getRecords (Date fromDate, Date toDate, boolean dataSourceARequired, boolean dataSourceBRequired)

public List<Record> getRecords (int fromYear, int toYear, boolean dataSourceARequired, boolean dataSourceBRequired)

or something like this:

public List<Record> getRecords(Request request)

where Request would look something like:

public class Request{

private final Date fromDate;
private final Date toDate;
private final int fromYear;
private final int toYear;
private final boolean dataSourceARequired;
private final boolean dataSourceBRequired;



public Request(Date fromDate, Date toDate, boolean dataSourceARequired, boolean dataSourceBRequired){

    if (fromDate == null) {
        throw new IllegalArgumentException("fromDate can't be null");
        }
     if (toDate == null) {
        throw new IllegalArgumentException("toDate can't be null");
        }
    if (!dataSourceARequired && !dataSourceBRequired){
        throw new IllegalStateException ("No data source requested");
        }
     if (fromDate.after(toDate)){
         throw new IllegalStateException ("startDate can't be after    endDate");
        }

     this.fromDate = fromDate;
     this.toDate = toDate;
     this.dataSourceARequired = dataSourceARequired;
     this.dataSourceBRequired = dataSourceBRequired;
     this.fromYear = -1;
     this.toYear = -1;

}


 public Request(int fromYear, int toYear, boolean dataSourceARequired, boolean dataSourceBRequired){

    if (fromYear > toYear) {
        throw new IllegalArgumentException("fromYear can't be greater than toYear");
        }
    if (!dataSourceARequired && !dataSourceBRequired){
        throw new IllegalStateException ("No data source requested");
        }

     this.dataSourceARequired = dataSourceARequired;
     this.dataSourceBRequired = dataSourceBRequired;
     this.fromYear = fromYear;
     this.toYear = toYear;
     this.fromDate = null;
     this.toDate = null;

}

}

Or is there another way?

Upvotes: 0

Views: 322

Answers (2)

Maurice Perry
Maurice Perry

Reputation: 9651

Another solution: Use a DateRange class with two constructors:

public class DateRange {
    final Date start;
    final Date end;

    public DateRange(Date start, Date end) {
        this.start = start;
        this.end = end;
    }

    public DateRange(int startYear, int endYear) {
        this(yearBegining(startYear), yearBegining(endYear));
    }

    ...
}

Upvotes: 0

rghome
rghome

Reputation: 8819

You should not use the second case as it breaks the rule that every class should have a single well-defined responsibility. Here, your class is responsible for both detailed date ranges and year date ranges. If you added more criteria this class would grow into something monstrous.

So you can use the first method and many people do.

If you want to create classes to encapsulate request data you should create a base abstract class or interface and then have a different type of request subclass for each type of criteria that you could use. For example:

public interface Request {
    execute();
}

public class YearRangeRequest implements Request {
    int fromYear;
    int toYear;

    public execute();

... etc

Upvotes: 1

Related Questions