views:

52

answers:

1

In the project there are two data sources: one is project's own database, another is (semi-)legacy web service. The problem is that admin part has to keep them in sync and manage both so that user doesn't have to know they're separate (or, do know, but they do not care).

Here's an example: there's list of languages. Both apps - project and legacy - need to use them. However, they both add their own meaning. For example, project may need active/inactive, and legacy will need language code.

But admin part has to manage everything - language name, active/inactive, language code. When loading, data from both systems has to be merged and presented, and when saved, data has to be updated in both systems.

Thus, what's the best way to represent this separated data (to be used in the admin page)? Notice that I use ASP.NET MVC / NHibernate.

  1. How do I manage legacy data?
    • Do I connect admin part to legacy web service external interface - where it currently only has GetXXX() methods - and add the missed C[R]UD methods?
    • Or, do I connect directly to legacy database - which is possible since I do control it.
  2. Where do I do split/merge of data - in the controller/service layer, or in the repository/data layer?
    • In the controller layer I'll do "var viewmodel = new ViewModel { MyData = ..., LegacyData = ... }; The problem - code cluttered with legacy issues.
    • In the data layer, I'll do "var model = repository.Get(id)" and model will contain data from both worlds, and when I do "repository.Save(entity)" it will update both data sources - in local db only project specific fields will be stored. The problems: a) possible leaky abstraction b) getting data from web service always while it is only need sometimes and usually for admin part only
      • a modification, use ICombinedRepository<Language> which will provide additional split/merge. Problems: still need either new model or IWithLegacy<Language, LegacyLanguage>...
  3. Have a single "sync" method; this will remove legacy items not present in the project item list, update those that are present, create legacy items that are missed, etc...

Well, to summarize the main issues:

  • do I develop CRUD interface on web service or connect directly to its database (which is under my complete control, so that I may even later decide to move that web service part into the main app or make it use the main db)?
  • do I have separate classes for project's and legacy entities, thus managed separately, or have project's entities have all the legacy fields, managed transparently when saved/loaded?

Anyway, are there any useful tips on managing mostly duplicated data from different sources? What are the best practices?

In the non-admin part, I'd like to completely hide the notion of the legacy data. Which is what I do now, behind the repository interfaces. But for admin part it's not that clear or easy...

+1  A: 

What you are describing here seems to warrant the need for an Anti-Corruption Layer. You can find solutions related to this topic here: http://stackoverflow.com/questions/909264/ddd-anti-corruption-layer-how-to

When you have two conceptual Bounded Contexts, but you're only using DDD for one of them, the Anti-Corruption layer comes into play. When reading from your data source (performing a get operation [R]), the anti-corruption layer will translate your legacy data into usable objects for your project. When writing to your data source (performing a set operation [CUD]), the anti-corruption layer will translate your DDD objects into objects understood by your legacy code.

Whether or not to use the existing Web Service depends on whether or not you're willing to change existing code. Sticking with DRY practices, you don't want to duplicate what you already have. If you want to keep the Web Service, you can add CUD methods inside the anti-corruption layer without impacting your legacy application.

In the anti-corruption layer, you will want to make use of adapters and facades to bring together separate classes for your DDD project and the legacy application.

The anti-corruption layer is exactly where you handle splitting and merging.

Let me know if you have any questions on this, as it can be a somewhat advanced topic. I'll try to answer as best I can.

Good luck!

Kevin Swiber
While I know about the Anti-Corruption layer and you described what is needed quite nice (links are useful, too), the main issue here is that it's not quite legacy; I have full access to it, I can add/tweak interfaces (keeping compatibility), and even can have access to DB and change its schema! So I wonder if it's better to avoid A-CL (which I currently use for read-only access).
queen3
@queen3 I see. You have to ask yourself if tweaking those interfaces will impact the expressed domain of the legacy system in a negative way. It sounds like you have two Bounded Contexts to keep intact. One Model To Rule All Domains is an anti-pattern (IMHO). You don't want to end up with a legacy system that doesn't quite reveal its true intention through code. Even if you refactored the legacy system to be more DDD, it may still express the domain differently and still require the A-CL. In short, my advice is: if you need two Bounded Contexts, keep the A-CL.
Kevin Swiber