mercredi 1 août 2018

Best practices for passing objects containing data into an interface

Context

I have an abstract class that is using the strategy pattern.

public interface IReader
{
    HashSet<DataSheet> Read(string fullFilePath, HashSet<string> sheetNames, ref string errors);
}

public abstract class AbstractReader : IReader
{
    public virtual HashSet<DataSheet> Read(string fullFilePath, Hashset<string> sheetNames, ref string errors)

    protected virtual void InitializeRowColInfo(string filePath, string sheetName)

    //And some other methods
}

The method read, reads an excel file and takes in required information through its parameters and outputs information to be further processed.

Strategy

To implement the Abstract Reader, I create a new class which overwrites the it. For example,

For files that follow the formatting logic of my abstract class,

public class ConcreteReader1 : AbstractStandardBuildPlanReader
{
}

For files that do not follow the formatting logic of my abstract class,

public class ConcreteReader2 : AbstractStandardBuildPlanReader
{
    protected override void InitializeRowColInfo(string filePath, string sheetName)
}

where I will override the method according to the formatting needs of the file, while the common methods are reused from the abstract class. And the creation method of objects is as such:

public IReader GetReader(string reader){
    if (reader.toUpper().trim().Equals("CONCRETEREADER1"){
        return new ConcreteReader1();
    }
    //Continue else ifs for the other readers
}

Problem: Parameters

However, due to the rigid nature of the parameters that i have included for all methods, whenever a file format that requires additional parameters are needed I cannot reuse my code.

To solve this problem, I can create an object to be passed instead, such as a documentInfo object:

public class DocumentInfo
{
    public string FullReadFilePath { get; set; }
    public HashSet<string> SheetNames { get; set; }
    public string Errors { get; set; }
}

public interface IReader
{
    HashSet<DataSheet> Read(DocumentInfo documentInfo);
}

This way, any additional parameters that are needed can be added into this object without affecting the existing concrete readers and I can get rid of the ref string.

However,

  1. There is an issue of redundancy as any newly added properties to the DocumentInfo object will always be uninitialized and useless for the Readers that do not use them (and also clutter the code).

  2. Also, all my other methods will depend on this object as it contains all information regarding reading (fullFilePath, sheetNames, etc.)

Is there a better way to solve this problem?

Aucun commentaire:

Enregistrer un commentaire