C
Chris Uppal
Rhino said:Going through this thought process again has made me change my mind! As I
wrote the preceding paragraph, I realized that it still bothered me to
pass
parameters that were being ignored and that this bothered me more than
having overloaded versions of the writeEmploymentHistory() method.
I think that the underlying problem here is that you are making the same
decision in two different places, and that is mucking-up the structure of your
code.
Basically, what you have is a framework for generating CVs. Your framework
code -- in the abstract ResumeWriter superclass "drives" the process, and the
"pluggable" code (implemented as concrete subclasses of ResumeWriter)
implements the actual formatting. That's fair enough as far as it goes (though
I'll mention that it has a distinctly procedural flavour to my mind [*]). But
the problem comes when you try to decide /what/ data to print. You are
attempting to make that decision in the driver (which is not unreasonable), but
then you hit the problem that that decision can only be made with knowledge of
the capabilities of the concrete document format (HTML has tables, ASCII text
does not). So although you /want/ your driver to abstract away from the
details of the concrete representation, in this case it cannot do so. So you
end up with the "knowledge" about how the employment history is represented in
two different places. In one place (in the driver) you select which of the two
methods to invoke (the simple or complete versions). In another place (in the
various subclasses) you duplicate that knowledge by the choice of which of the
two method to provide a real implementation for.
([*] I can talk more about that if you are interested.)
In this case, that's (IMO) because you are trying to make the "driver" do too
much. If it did not know about the details of /what/ data was shown in an
employment history then there would be no problem. More specifically still, if
it did not /choose/ what data to display and pass that to the implementation
method, then there would be no problem. I understand that the reason you have
been lead to this position is to avoid the code duplication that would
otherwise occur, but that is leading you astray (I think). Code duplication is
not -- in itself -- bad. It's only bad when code is duplicated that is
/necessarily/ the same in both places. That's to say if one version changed
then the other /must/ change too. And in this case, the code duplication is
accidental rather than necessary -- it's only an accident that (say) the PDF
generator will display the same data as the HTML generator. So the fact that
the PDF generator and HTML generator use the same accessors to find the
employment history is not in itself an indicator of a problem. (Although there
is probably scope for factoring out some utility code which can be shared
between them).
Just because there is common code in (some of) the concrete subclasses does
/not/ mean that you must move that code into the driver. Certainly you should
consider whether it is appropriate to do so, but that decision should be based
on whether that code should reasonably be expected to live in the driver --
whether it is part of the design of the driver-- the question is not whether it
/can/ but whether it /must/.
Oh, by the way, I would take the large number of parameters (six) to this
method to be another hint that the design is ill-balanced. If the driver code
were not trying to do too much, then it would not be extracting all that data
from the raw input, and so would not need to pass it to the writing methods.
-- chris