1
\$\begingroup\$

I have a list of rule names coming from .xml file. These rule names needs to be validated against rule names in database (Validator.cs). If valid, then Id of these rule names are used to fetch user data from database (ExportService.cs).

I am using a Dictionary object to save name, Id pair from database -

Validator.cs

var rulesDictionary = new Dictionary<string, string>();
while (sqlDataReader.Read())
{
    string ruleName = sqlDataReader["NAME"].ToString();
    string ruleLink = sqlDataReader["LINK"].ToString();
    rulesDictionary.Add(ruleName, ruleLink);
}

The values coming from XML file are validated against this dictionary as -

ExportService.cs

if (DepositRulesDictionary.ContainsKey(xmlRuleName1) == false)
{
     //log error
}

If all the values are valid, then this dictionary is further used to pass 'ruleLink' values in ExportService.cs.

I used Dictionary object in this instance as it returns O(1) result for validating XML file values.

My XML file is not going to be very big, so efficiency is not a major concern right now.

My question is what is more recommended -

  • Dictionary<string, string> object or
  • List<T> where T is having two properties of Name and Link.

For scalability and unit-testability?

| improve this question | | | | |
\$\endgroup\$
  • \$\begingroup\$ Why do you use a ´sqlDataReader´? Please don't write ADO.NET, instead use Dapper. Also, considering you seem to need the value belonging to a key, don't use ContainsKey but use TryGetValue. \$\endgroup\$ – BCdotWEB Mar 29 at 19:13
  • \$\begingroup\$ This might be more on-topic over at SoftwareEngineering, but before posting there please follow their tour, and read "What topics can I ask about here?", "How do I ask a good question?" and "What types of questions should I avoid asking?". \$\endgroup\$ – BCdotWEB Mar 29 at 19:14
  • \$\begingroup\$ @BCdotWEB: Dapper is useful, and the OP should certainly consider it. But I wouldn't be so quick to dismiss the use of raw ADO.NET out-of-hand without understanding the broader context of the OP's application. For this case per se, Dapper might streamline this into a single line, but I'm not sure it's buying them all that much. Regardless, it's not really relevant either way to the OP's question. \$\endgroup\$ – Jeremy Caney Apr 9 at 20:51
1
\$\begingroup\$

I think you are too concerned with the implementation right now.

The last part of the question

... recommended ... for scalability and unit-testability?

is the most important one.

Let's imaging you were to write the test for this feature. You would start off by designing the API that the user of the functionality would ultimately consume. Secondly as far as the tests go ... they could careless how it is implemented 'under the hood' it only cares that it meets the requirements performance just being on possible requirement. Many times asymptotic complexity doesn't even play a critical role unless n is large. Take for example Strassen matrix multiplication it is only practical for larger matrices.

For scalability I'm assuming you mean maintainability and extensibility. The best way to achieve that is to use the dependency inversion principle (DIP) so that you are not depending on either a list or a dict but instead on the correct abstraction.

One possible abstraction is that the rules represent a validation.

interface IValidator<T>
{
   bool IsValid(T item);
}

Your test would look as follows.

[Test]
void NoRulesEverythingIsFalse()
{
    var rules = new Rules();
    Assert.False(rules.IsValid(""));
}

[Test]
void SingleRule()
{
    var rules = new Rules(new[] 
    {
        new LinkedRule("abc", "Only abc is allowed.")
    });
    Assert.True(rules.IsValid("abc"));
    Assert.AreEqual(
        rules.GetLinkForRule("abc"),
        "Only abc is allowed.");
    Assert.False(rules.IsValid("123"));
}

Now with this you can implement it however you want as long as your test pass. Feel free to add a performance test if it is required.

// LinkedRule.cs
struct LinkedRule {
    string Rule { get; set; }
    string Link { get; set; }
}
// Rules.cs
class Rules : IValidator<string>
{
    private Dictionary<string, LinkedRule> RulesToLinks { get; }

    public RuleValidator(IEnumerable<LinkedRule> linkedRules)
    {
        RulesToLinks = linkedRules.ToDictionary(
            x => x.Rule);
    }

    public bool IsValid(string rule) =>
        RulesToLinks.Keys.Contains(rule);

    public string GetLinkForRule(string rule) => RulesToLinks[rule];

    // ...
}

| improve this answer | | | | |
\$\endgroup\$

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.