Search code examples
c#.netservicesolid-principles

Were do I pass code for further processing from a service?


Student here, I REALLY tried to google this probably simple question, but can't find a good answer, perhaps I just don't know the right terms to google and if so I am sorry!

I am trying to figure out the best practises to passing a JSON string forward into the system after a service have received the data, for example into a parser and then continuing to work with the object.

Today the way we are being taught to write services the function could look something like this.

private void ReceiveData(string json)
{
    var parser = new JsonParser();
    var normalizer = new Normalizer();
    var dataHandler = new DataHandler();

    var data = normalizer.Normalize(parser.Parse(json));
    dataHandler.Handle(data);
}

But to me this looks like the service is violating the single responsibility principle because now it is not only set to receive the data but also that it is parsed, normalized and handled. Is this the correct way because it does not feel right to me to do it this way?

//AssaultBetty


Solution

  • I have to disagree with kienct89, breaking this method down further is overkill. Your method's responsibility is to receive data, but all actions within the method fall under the category of receiving data.

    You could break down the class by declaring an interface for data parsing.

    public interface IDataParser
    {
        string ParseData(string input);
    }
    

    Then, you can create your data handler and JSON data parser which implements this interface.

    public class JsonDataParser : IDataParser
    {
        public string ParseData(string input)
        {
            //Convert the input to JSON.
        }
    }
    
    public class DataHandler
    {
        private IDataParser _parser;
    
        public DataHandler(IDataParser parser)
        {
            _parser = parser;
        }
    
        public void ReceiveData(string data)
        {
            //Convert the data to the desired format.
            string result = _parser.ParseData(data);
        }
    }
    

    The ideas around this approach is that by programming using interfaces, your data handler class is no longer tied to a specific implementation of parsing data. Perhaps in the future you may want to parse the data to a CSV format instead of JSON, in which case you simply provide your data handler a different parser implementation.

    Here's an example usage:

    JsonDataParser jsonParser = new JsonDataParser();
    DataHandler myDataHandler = new DataHandler(jsonParser);
    
    myDataHandler.ReceiveData("Le toucan has arrived.");
    

    As I mentioned before, DataHandler is not tied to a specific implementation so you could pass in a CsvDataParser instead, without having to change anything inside your DataHandler.

    Anyway, I still believe this is a bit overkill. Sure, this helps your code to be more adaptive to changing requirements, more agile if you will. However, for what you need, I believe that your current approach more than fits the bill.