ssg31415926
ssg31415926

Reputation: 1077

How to apply DRY to iterating code over different classes

I have various classes preparing results with matching format: a List where the objects are List where the objects are List. This is required by the target app.

The source data comes from various systems. Here's one:

var results = new List<object>();

using (var csvReader = new CsvReader(exportFilePath))
{
    csvReader.ValueSeparator = '$';
    var header = csvReader.ReadHeaderRecord();

    foreach (var record in csvReader.DataRecords)
    {
        var nameValuePairs = new List<object>();

        foreach (var column in header.Values)
        {
            var nameValuePair = new List<object>(2);
            nameValuePair.Add(column);
            nameValuePair.Add(record[column]);

            nameValuePairs.Add(nameValuePair);
        }

        results.Add(nameValuePairs);
    }
}

return results;

and that is probably the cleanest form. Here's another:

var results = new List<object>();

var searchRootPath = "LDAP://OU=Standard Users Accounts,OU=...,DC=local";
var filter = "(&(objectClass=user)(objectCategory=person))";
var propertiesToLoad = new string[] { "sAMAccountName", "employeeNumber", 
    "mail", "telephoneNumber"};
using (var searchRoot = new DirectoryEntry(searchRootPath))
using (var ds = new DirectorySearcher(searchRoot, filter, propertiesToLoad, SearchScope.OneLevel))
{
    ds.PageSize = 100;

    using (var src = ds.FindAll())
    {
        foreach (SearchResult sr in src)
        {
            var propertyNameValuePairs = new List<object>();

            foreach (var property in propertiesToLoad)
            {
                var propertyNameValuePair = new List<object>(2);
                propertyNameValuePair.Add(property);
                if (sr.Properties[property].Count == 0)
                    propertyNameValuePair.Add("<not set>");
                else
                    propertyNameValuePair.Add(sr.Properties[property][0].ToString());

                propertyNameValuePairs.Add(propertyNameValuePair);
            }

            results.Add(propertyNameValuePairs);
        }
    }
}

return results;

As you can see, the structure is repeated but the way of getting the data is different. E.g in the former, it's record[column] but in the latter it's sr.Properties[property][0].ToString() (with the complication of the whole 'if' statement); plus the differences in loading the data. Is Template Method the best approach or am I missing something?

Upvotes: 0

Views: 64

Answers (1)

jgauffin
jgauffin

Reputation: 101166

Provide custom iterators which returns a Name/Value object.

So that you can use them like:

UserCsvReader csvReader = new UserCsvReader();
while (csvReader.Read())
{
    users.Add(csvReader.Current.Name, csvReader.Current.Value);
}

In that way you get classes which is only responsible of providing the data. The actual processing (in this case add it to a list) is done by the caller.

Upvotes: 2

Related Questions