views:

21

answers:

2

I have legacy Reporting Engine class that is responsible for 50+ reports with a single method CreateReport(Guid reportId, ReportParams params);

Reports require 12+ of different parameter types (Guid, int, bool, enumerations) and their combination. For example:

  • Report #1: No parameters are required
  • Report #2: 2 Booleans (checkboxes populate by user)
  • Report #3: Guid (personId) & integer (year to start with)
  • Report #4: Guid (personId) & PersonType (enumeration)

ReportParams is a class with 12+ properties and arrays that are populated before calling the method. But most of them are unused per call. Report Engine class checks that appropriate properties are populated and uses strong type information access.

Everything was ok until I decided to make reporting engine WCF friendly. Every time I add new parameter type I have to rebuild server, update proxy (that leads to clients reinstall), and make sure that ReportParam structure is converted correctly between WCF-friendly version and Reporting Engine version.

I wonder how to minimize all this conversions, checks, client reinstallations e.t.c. May be I shall refactor ReportParam to XML document? It will make proxy stable, ReportParams wcf friendly, but I'll have to refactor strong type information access in the Report Engine class.

What will you suggest?

A: 

I'm not exactly clear on your issue, but let me not stop that in my insatiable quest for rep.

First thing, I'd definitely suggest placing a "firewall" between the reporting code and the WCF code. You should treat your WCF code as a facade, insulating it from changes to your reports as much as possible. If your reporting engine requires a change, you can rewrite the server code without messing with client code.

Next thing is that I'd get rid of the idea that you can generically serve up X number of reports via a single call. You should expose every report as a separate call, each having a signature which takes in the exact number and type of arguments the report requires.

But, you ask, what happens when the report changes, or a new report must be added? You cannot (i.e., should not under any circumstances) version interfaces, and your service contract IS an interface. Therefore, as reports change, you must mark the OLD report method as obsolete. Add the updated method (as well as methods for new reports) to a NEW service contract that will be served along side of the old one. If people try to use the old report method, either attempt to make due (apply reasonable defaults to those arguments not provided) or throw an exception. If a report changes drastically to the point where a client reinstall is required, consider adding the updated report as a new one.

Adding updated reports and/or new reports becomes a simple matter of dropping a new binary on the server and changing the .config file.

Will
Yes, WCF service is a facade. But does one method is so bad really? Old clients know nothing about new reports Ids and can't use them. New clients can use old ids, but as new version of the same report is ready it's just a new report id. Reports are marked with 2 dates between them they are actual.
Andrew Florko
+1  A: 

Do you control both ends of the WCF communication??

In that case:

  • put your service contract (interface) and data contracts into a class library assembly
  • share that assembly between server and client
  • on the client, use ChannelFactory<T> and factory.CreateChannel() to manually create the communication channel

In this setup, you make the change to the data contract once, rebuild your service and client, and you're done. No messy "Update Service Reference" etc.

marc_s