views:

64

answers:

2

I'm writing a program to do a search and export the output.
I have three primary objects:

  • Request
  • SearchResults
  • ExportOutput

Each of these objects links to its precursor.

Ie: ExportOutput -> SearchResults -> Request

Is this ok? Should they somehow be more loosely coupled?

Clarification:

Processes later on do use properties and methods on the precursor objects.

Ie:

SendEmail(output.SearchResults.Request.UserEmail, BODY, SUBJECT);

This has a smell even to me. The only way I can think to fix it is have hiding properties in each one, that way I'm only accessing one level

MailAddress UserEmail
{
  get { return SearchResults.UserEmail; }
}

which would yeild

SendEmail(output.UserEmail, BODY, SUBJECT);

But again, that's just hiding the problem. I could copy everything out of the precursor objects into their successors, but that would make ExportOutput really ugly. Is their a better way to factor these objects.

Note: SearchResults implements IDisposable because it links to unmanaged resources (temp files), so I really don't want to just duplicate that in ExportOutput.

+2  A: 

If A uses B directly, you cannot:

  • Reuse A without also reusing B
  • Test A in isolation from B
  • Change B without risking breaking A

If instead you designed/programmed to interfaces, you could:

  • Reuse A without also reusing B - you just need to provide something that implements the same interface as B
  • Test A in isolation from B - you just need to substitute a Mock Object.
  • Change B without risking breaking A - because A depends on an interface - not on B

So, at a minimum, I recommend extracting interfaces. Also, this might be a good read for you: the Dependency Inversion Principle (PDF file).

SingleShot
"Test A in isolation from B" - this isn't true, you just need to use a mocking framework that lets you mock any kind of class. The fact that many cannot do that is a deficiency in them. OO design should not have to be constrained or bent just because of test framework limitations - just find a better framework!
Pavel Minaev
Also, "change B without risking breaking A" will be the same with and without extracted interfaces - adding new members isn't a breaking change for direct class access, and removing would be a breaking change even with an interface.
Pavel Minaev
@Pavel: regarding "change B without risking breaking A", if A is intimately tied to B, and you make an implementation change to B, it is possible to introduce a bug to A (from the point of view of a user of A).
SingleShot
A: 

Without knowing your specifics, I would think that results in whatever form would simply be returned from a Request's method (might be more than one such method from a configured Request, like find_first_instance vs. find_all_instances). Then, an Exporter's output method(s) would take results as input. So, I am not envisioning the need to link the objects at all.

Anon