Specialized vs. Generic Interfaces?
Hi,
I am new to these forums, please let me know if this is already part of a FAQ or not the appropriate place to ask this question.
When designing an interface, would you recommend specialized or Generic Interfaces?
As I am not sure if makes any sense, here are the two thinkings I have to define a myObject.getExportOptions()
method that would return the ExportOptions that can be applied (i.e. "setCharacterDelimiter" for CSV export, "setHeader" for PDF, HTML....)
Option 1:
the code looks like:
myObject.setExportMode(MICROSOFT_EXCEL);
myExportOptions = (ExportOptionsExcel) myObject.getExportOptions();
where the getExportOptions() would be defined as
ExportOptions getExportOptions();
with the ExportOptions interface _only_ defining all the common export options to all the export methods (PDF, Excel, HTML, Text...). And then to get to the export options that are specific to an export format, you would have to cast the object to a specific interface which extends the "generic" interface.
Option 2:
the code looks like:
myObject.setExportMode(MICROSOFT_EXCEL);
myExportOptions = myObject.getExportOptions();
where the getExportOptions() would be defined as
ExportOptions getExportOptions();
with ExportOptions defining all the export options accross all the export methods (PDF, Excel, HTML, Text...). But if you tried to call the ".setExcelFormat(EXCEL_95)" method when the ExportMode is set to "TEXT_ONLY" then an exception would be raised (maybe something like "ExceptionNotApplicableToExportFormat").
I did not find any document describing the prefered method of building this.... Any idea?
Thanks,
MonLand.
[1762 byte] By [
MonLanda] at [2007-10-2 8:57:20]

> I am new to these forums, please let me know if this
> is already part of a FAQ or not the appropriate place
> to ask this question.
This is definitely not in the FAQ and is definitely an appropriate question for this forum.
> Option 1:
>the code looks like:
> myObject.setExportMode(MICROSOFT_EXCEL);
> myExportOptions = (ExportOptionsExcel)
> l) myObject.getExportOptions();
Um, what's the point? Why even bother defining an interface or lookup if you always hardcode a cast o the class. If you were going to do this, how is it any better than hardcoding references to the ExportOptionsExcel class.
> Option 2:
>the code looks like:
> myObject.setExportMode(MICROSOFT_EXCEL);
> myExportOptions =
> = myObject.getExportOptions();
>
> where the getExportOptions() would be defined as
> ExportOptions getExportOptions();
> with ExportOptions defining all the export options
> accross all the export methods (PDF, Excel, HTML,
> Text...). But if you tried to call the
> ".setExcelFormat(EXCEL_95)" method when the
> ExportMode is set to "TEXT_ONLY" then an exception
> would be raised (maybe something like
> "ExceptionNotApplicableToExportFormat").
I don't understand the last part. Why doesn't ExportOptions tell you what the valid options are? Have you defined an ExportFormat class? You could put the export() method in that class and then the users would not be able to choose an invalid export option.
I think I was not clear enough in my first message. Let me try to re-explain with a little bit more details (and more pseudo-code).
Option 1:
myReport.setExportMode(MICROSOFT_EXCEL);
ExportOptions myExportOptions = myObject.getExportOptions();
myExportOptions.setExportFileName("myReport"); // This would be common to any "export format"
Now, for the "Excel" specific parameters, I would have to cast the options:
ExportOptionsExcel myExcelExportOptions = (ExportOptionsExcel) myExportOptions;
myExcelExportOptions.setExcelFileFormat(EXCEL_97);
From the implementation point of view, I can have one "generic" ExportOption class/interface that contains all the common export properties. In addition, three or more classes that implement the specific export settings (one for Text_ONLY; one for MICROSOFT_EXCEL; one for PDF.....). From the developer point of view, to be able to set the "specific" properties, they have to know what interface to cast the export options to (because in the background, the reportObject class would create/return the "right" export options based on the export format that was set).
Option 2:
This time the ExportOptions is a much more generic interface and declares everything. But an exception is raised if I am trying to set parameters that don't make sense:
myReport.setExportMode(MICROSOFT_EXCEL);
ExportOptions myExportOptions = myObject.getExportOptions();
myExportOptions.setExportFileName("myReport"); // This would be common to any "export format"
myExportOptions.setExcelFileFormat(EXCEL_97);
Now, if I was to do:
myReport.setExportMode(TEXT_ONLY);
ExportOptions myExportOptions = myObject.getExportOptions();
myExportOptions.setExportFileName("myReport"); // This would be common to any "export format"
myExportOptions.setExcelFileFormat(EXCEL_97);
This last line would raise an exception (let's say "UnsupportedProperty") because the Text mode does not support the ExcelFileFormat property.
From the implementation point of view, I can have three or more classes that implement the "ExportSettings" interface (one for Text_ONLY; one for MICROSOFT_EXCEL; one for PDF.....). But from the developer point of view, it does not matter with class gets used.
Why I am asking: I am currently facing a design that looks like Option 1 and I can not figure out why this has to be that complex to use. Very hard to document if you replicate that design everywhere in a large API with a large number of objects/interfaces; you never know what to cast the object to; you never can guess what method you are looking for because you have to look at the definition of 3 or 4 interface at the minimum to see if you see something that fits your needs. So I am trying to understand if this is because it is much easier to implement that Option 2.
I see the following drawback for Option 2: If you need to add an extra property to one of the export format, you probably have to update the "generic" interface, the "generic" implementation of that interface, and each "specific" implementation to reflect that new property.
Thanks a lot for your time!
MonLand
> Option 1:
I'll basically repeat what I said before about this. This design has a bad smell. The term 'specialized interface' is somewhat oxymoronic. The whole point of an interface is to specify commonalities. How many implementations of ExportOptionsExcel do you expect to have?
> Option 2:
Option 2 is better but only marginally. I suggest a completely different approach. For brevity I am not specifying access modifiers.
class Report
{
List<FileFormat> formatOptions()
{
// return a list filled with FormatOption objects
}
}
interface FileFormat
{
String name();
List<ExportOption> options();
}
interface ExportOption
{
String getName();
void apply();
}
This is a very thin example, you can expand on it as necessary but I hop it get's the point across. The interfaces make no assumptions about how the classes are going to be defind. The allows you to add more implementations without changing any code that uses these interfaces (ideally). Neither of your options above do this.