0

I have to do a form in which has several comboboxes. Comboboxes have values represented as Key-Description pairs.

Each Combobox has its values in a separate table Key<string>-Value<string>

How to represent it in a class?
Suppose we have Project (Type and Technology) as "enums", each of them in Type and Technology tables in Database (so its number depends on how many rows in the DB)

class Project {
    public int Id {get; set;}
    public KeyValuePair<string, string> Type {get; set;}
    public KeyValuePair<string, string> Technology {get; set;}
}

or better

class ProjectType { public string Key; public string Value; }
class ProjectTechnology { public string Key; public string Value; }

class Project {
    public int Id {get; set;}
    public ProjectType Type {get; set;}
    public ProjectTechnolgy Technology {get; set;}
}

From the point of view of the separation of concerns probably we should use the second variant, but why to complicate if we could do simple like in the first ?

serge
  • 13,940
  • 35
  • 121
  • 205
  • Are you using WPF? I'm not clear on what you are asking. – Élie Jul 11 '17 at 13:38
  • I use an "ASP.NET Core" Web Application, I ask if I should separate the KeyValuePair in separate classes or not – serge Jul 11 '17 at 13:46
  • Are all types and technologies known? I mean, is it static the number of types and technologies or rather you may have 5 types today and 10 tomorrow? Can someone add a new type or technology? – taquion Jul 11 '17 at 13:56
  • The technologies are a table in the Database... so it depends of how many rows inside – serge Jul 11 '17 at 13:59
  • Yeap quoting you "Suppose we have Project (Type and Technology) as "enums", then the number of rows is fixed, right? Since enums length is fixed – taquion Jul 11 '17 at 14:00
  • this is why I put enums in quotes, there are not hardcoded enums... ) – serge Jul 11 '17 at 14:15
  • And supposedly there are no softcoded enums either... so just no enums, but database-managed lists of options where one `Type` and one `Technology` option is to be selected for each project? – grek40 Jul 11 '17 at 14:17

2 Answers2

1

Suppose we have Project (Type and Technology) as "enums", each of them in Type and Technology tables in Database

Then why not to use enums?

public enum ProjectType
    {
        [Description("Friendly name for type 1")]
        Type1,
        [Description("Friendly name for type 2")]
        Type2,
        [Description("Friendly name for type 3")]
        Type3
    }

And with an extension method like the following you can get the description of a given enum value:

public static string GetEnumDescription<TEnum>(this TEnum item)
        => item.GetType()
               .GetField(item.ToString())
               .GetCustomAttributes(typeof(DescriptionAttribute), false)
               .Cast<DescriptionAttribute>()
               .FirstOrDefault()?.Description ?? string.Empty;

(I got this code frome here, where also is shown how to map enums to tables in the case your are using EF as ORM)

The Description attribute can be used as the display string inside your combobox. This way works if, as you say, the values are fixed, if they are not or they may grow or change then I would say the second approach (creating separate classes) is better following SOLID best practices, in this case I would say that the second approach violates the O and the S in solid, the Open-closed Principle and the Single Responsibility Principle (more on SOLID).

Let's say Types and Technologies may grow or change, and you follow the first approach. Then you violate the S since now your Project class may change if the definition of Type or Technology changes. Supouse that in the future you realize that you must support mutiple languages (eng, esp, ita, etc), then you violate the O since the definition of Type and Technology can not be anymore represented by a KeyValuePair and you will have to figure out how to achieve this and, worst, you will have to modify Project class which should take no care about this.

But if they are fixed values then the enum approach is better since it enforces to use always known values, there is no chance that you can assign to a Project a Type or a Technology that does not exist.

taquion
  • 2,667
  • 2
  • 18
  • 29
  • thanks. As you can remark, the "key" is of string type... My keys can be "0", "1", "A", "kjsdhfjh" etc... so classical enums will not work here... and the other thing it they came from the DB, so the number of items could vary – serge Jul 11 '17 at 14:27
  • Then you can use the name of the enum value as key: enumVal.ToString(); Or the string representation of the int: ((int)enumVal).ToString|(); – taquion Jul 11 '17 at 14:33
  • But if enums are not suitable enough then I recommend the first approach for the reasons I wrote above =) – taquion Jul 11 '17 at 14:34
  • the number of items in a "enum" is not fixed and the keys can be random (unique) strings, int values are just occasionally used... – serge Jul 11 '17 at 14:35
  • I recommend second approach, I made a mistake writing first approach in my last comment – taquion Jul 11 '17 at 15:27
1

This is a matter of opinion and coding style, but here's my take:

The first option (simple KeyValuePair) is less code, but that doesn't neccesarily make it simpler. The second option (creating classes to represent ProjectType and ProjectTechnology) is better, because it is much easier to read.

A further improvement (my opinion again) would be not to name the properties of these two classes "Key" and "Value". Surely these properties represent something more specific than a key and a value? Name it accordingly, making it easier for others to understand what they represent.

Hope that's the kind of answer you needed.

P.S. it's fairly clear what you meant to write, but you forgot to remove the 'int' in

public int KeyValuePair<string, string> Type {get; set;}
public int KeyValuePair<string, string> Technology {get; set;}

and

 public int ProjectType Type { get; set;}
 public int ProjectTechnolgy Technology { get; set;}
kkirk
  • 352
  • 1
  • 7