7

I'm building an application that is responsible for reading data from files and displaying them in charts. The whole application is responsible for manipulating data from files, which means I have to use different parts of the same object in almost every part of my project. Charts need actual data, list of opened files needs names and states of data, etc. On top of that my application uses MEF, so others can add new functionality and modify current modules.

My biggest problem is how to separate that data, so each layer of my application has access only to part of that data that is required for it to work. What I mean by data is:

  1. Name of file
  2. Guid Id
  3. List<IColumn> data or byte[] data
  4. Additional future variables

I decided to use across my application IDocument. This is my custom representation of one file that can be read and displayed in chart. Each IDocument must have an Id and Name because every computer file has a name. This has all the information that is needed for a simple list of files that were imported into the application. But it doesn't have the actual data that I want to display, so I use NoSQL database for storing IDocumentData that has List<IColumn> Columns that I can throw into a chart. IColumn has only List<object> Rows which basically mimics a table.

So I seperated my file into IDocument and IDocumentData, now how do I keep track of which data belongs to which document? I get IDocumentData from IReader module and I get IWizardData from IFileImporterWizard module. I was thinking about creating some kind of builder that would assign the same Id to IDocument and IWizardData(contains importated Name and Id) and when I would want to access data I would pass Id from IDocument. Is this a good approach?

So for example:

public class DocumentBuilder {

  private IDocumentFactory _documentFactory;
  private IDocumentDataRepository _documentDataRepository;

  public DocumentBuilder(IDocumentFactory documentFactory, IDocumentDataRepository documentDataRepository)
  {
     _documentFactory = documentFactory;
     _documentDataRepository = documentDataRepository;
  }

  public IDocument Build(IWizardData wizardData, IDocumentData documentData) 
  {
      var document = _documentFactory.Create();
      document.Id = wizardData.Id;
      documentData.Id = wizardData.Id;

      _documentDataRepository.Add(documentData);
      return document;
  }
}

So my thinking looks like this: Open File wizard returns IWizardData(name, filePath) -> IReader returns IDocumentData(List<IColumn> columns) -> DocumentBuilder builds IDocument and saves data

EDIT:

So I figured out how to separate business and data layers by creating

interface IDocument : IDocumentData, IDocumentInformation 

IDocumentInformation has a name and other information. IDocumentData has Id and DataTable Data { get; set; }. I can save IDocumentData and IDocumentInformation separately and still have Id that is the same for both of them.

I decided to change IColumn and List<object> Rows, because I hope DataTable will cause less problems. Although I'm still wondering if DataTable is a good choice, because it will probably decrease performance when loading data. I thought that it would be a good idea to load from NoSQL only a couple of records and then add them to chart and loop it until the end.

So now IFileWizard returns IDocumentInformation, IReader takes IDocumentInformation and returns IDocumentData and then they get combined.

Naming these things takes some time, because they all use parts of the same object, but seeing IFileWizard returning IDocumentInformation is a little bit weird. On the other hand in order to make them easily interchangeable I would have to declare even more common interfaces and create interface IFileWizardResult:IInfo and have interface IDocumentInformation:IInfo and then return IFileWizardResult and cast it to IInfo, etc. I don't know if this is too much decoupling or not. I want this application to be easily scalable, but making a lot of interfaces not always means better decoupling.

  • Why is it so important that each layer can only access what they need and no more? – Bart van Ingen Schenau Dec 10 '16 at 14:09
  • 2
    I think that it is a good practice to keep things separated, so it's more difficult to break application. So for example my chart won't be able to delete document, because it knows only about the data. – FCin Dec 10 '16 at 14:20
  • 1
    Separation of concern is good practice, in general. – Mister Positive Dec 12 '16 at 15:43
  • 2
    I'm not sure I understand the question; do you want to have a single implementation which looks different to each layer? In that case you probably want to implement multiple interfaces (IFileInfo, IChartDataSource, IDeletableDocument,etc) on the same implementation and pass the object as that type of interface to the layer in question. Then each layer only sees a specific aspect of the underlying implementation. If it's something else you need, updating the question to be clearer would help - "Is this a good approach" is a very broad question :) – Stephen Byrne Dec 12 '16 at 17:29
  • @StephenByrne You might consider posting that as an answer. – Adrian Dec 15 '16 at 19:55
2

The answer to your question depends primarily on two factors:

The overall complexity of the application

To be extreme, if you are simply writing a script to process a bunch of files, you would probably be going overboard having multiple layers to your application in the first place.

On the other hand, if you are writing a full blown enterprise application, separating layers and data representation between these layers will guarantee long term maintainability and stability of the application.

There are many variations and trade offs between these layers.

The differences in representation needed by each layer

On one hand, you could have an application that needs JSON format all the way through, from client to data storage. If there are no future requirements predicted that might change that, you can use JSON on the client, process the JSON in the business layer and write the JSON to a file or a NoSQL database.

On the other hand, every layer might best work with a different format. Let's say your storage requirements might be binary files, so you would have to read that out on the data layer and convert it into sensible objects that can be processed by the business layer and then that business layer would process and summarize the data an turn it into charts. Just by the virtue of that it would make sense to have a different representation.

There are many variations in between, but in your case it sounds like the latter is the case, but if you have the choice you might also review storing your data in a format that is more useful to the other layers.

Notes on the Presentation Layer

In practice I have learned to pretty much always give the Presentation Layer it's own model, separate from what the datastore and the business layer use. This is for multiple reasons:

  1. The presentation layer should not perform any business logic. However, if the model does not match what is to be shown you start finding funny pieces of business logic creeping into the presentation code.

  2. Typesafe Languages like C# and Java are many times easier to refactor than templating languages and JavaScript. Thus if you tightly couple into such languages, you will loose much of the benefit of having used a typesafe language in the first place.

  3. From what I have seen user interface technology still changes drastically, in the last 7 years I have gone from Flash/Flex to plain JS to jQuery, to Backbone to React. In other words the UI has seen many more rewrites than the backend code. Again, if you are loosely coupled this is much easier to deal with.

  • I thought about using a single data storage (NoSQL) and sharing it via Dependency Injection, this way I have less work to do and still have my decoupling. Also this way I can pass data from database to e.g. chart in 2-3 lines of code without any external classes and additional logic. Only repository and chart. Presentation is something that worries me more, because if I want to let people change the way things are displayed I have to expose properties to them in an easy to access way, and also store any changes that they make to styles. – FCin Dec 21 '16 at 8:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.