-2

Our team has been slowly refactoring code to implement SOLID practices and enforce better naming conventions. We have run into a problem where we have an enum that is currently named the same thing as another class we need to create -- "Department."

Right now, we have an enum that represents the different departments, for example:

Department.HumanResource
Department.InformationTechnology

This allows us to use that enum to quickly refer to departments based on a friendly name rather than an underlying integer ID in situations like this:

Employee.IsInDepartment(Department.InformationTechnology)

It's not a "Type" or "Status" or something like that which is a common way to name enums. We thought maybe something like "DepartmentName" but that felt a little strange, because the department class will have the "Name" property, and this enum should also be a property on the Department class.

I realize naming is subjective, so I want to pose the questions:

Are we looking at this from the wrong perspective? Is there another way to accomplish this that we are overlooking?

Jeremy
  • 169
  • 1
  • 2
  • 10
  • Actually that does look like a department type to me. – juharr Apr 10 '15 at 17:35
  • Your question is getting downvoted because the title doesn't actually reflect what you're asking, and your question could be made clearer. Try "Create an enum similar to name property" and phrasing your question more succinctly. – Kjata30 Apr 10 '15 at 17:48
  • Look at how Microsoft solved this with System.Drawing.KnownColor and System.Drawing.Color.FromKnownColor. I've seen this in many places throughout the .NET framework. It may spark some ideas :) – Biscuits Apr 10 '15 at 17:49
  • @Kjata30: I completely forgot to rename the question after changing what I asked (because of the subjectivity of just naming). Thanks for pointing that out. I will rename the question -- my apologies! – Jeremy Apr 10 '15 at 18:07

5 Answers5

1

Since you mentioned wanting to have the "enum" be a representation of functional classes (but not necessarily have the class' data loaded every time you use the reference), you might consider an approach like this. It would enable the code to feel like an enum, function like a class, but not make any unnecessary trips to the data store to fill properties until they're needed.

public class Department
{
  public int ID { get; private set; }

  //follow this pattern for property values that need to be populated from a data store.
  private string name;
  public string Name
  {
     get{ EnsureLoad(); return name; }
     set{ EnsureLoad(); name = value; }
  }

  public static Department HR{ get{ return GetEmptyDepartment( 1 ); } }
  public static Department IT{ get{ return GetEmptyDepartment( 2 ); } }

  private static Department GetEmptyDepartment(int departmentId)
  {
       return new Department()
       {
           ID = departmentId
       };
  }

  private void EnsureLoad()
  {
     //if not loaded
     //lazy load properties using the ID property against the data store.
  }
}
Colin
  • 4,025
  • 21
  • 40
  • This is similar to what we're doing now, actually, for the "enum." Our department IDs are actually not integers due to legacy systems, so I implemented the type safe enum pattern to make our "enum." Right now it only has a private constructor and the only way to get an instance of it is by requesting the public property or casting the ID as a Department type. Your approach looks like a hybrid between what I implemented and just an informational class like I described in the OP. – Jeremy Apr 10 '15 at 18:20
  • Seems workable then, though it still might be worth considering getting rid of the enum in favor of class instances, as above, because it sounds like the enum has little meaning outside of the class instance, thus it's redundant. The properties/keys of the class can be whatever, the important takeaway is the conceptual approach. Just an idea/possibility to chew on. – Colin Apr 10 '15 at 18:26
  • 1
    We liked your suggested technique and have decided to eliminate the enum. I like the idea of supporting lazy loading -- the concern I have is that I do not want the class to know about how to query the database or to be strongly coupled with the class that is responsible for querying the database. We will create a DepartmentRepository class that is responsible for this part. Do you have any thoughts on this or suggested resources to utilize? Thanks! – Jeremy Apr 10 '15 at 20:31
  • Cool! My opinion on tight-coupling in this circumstance, is that it's arguably an acceptable compromise if you don't have a practical reason to swap out the data access provider in the future. You'll have achieved logical separation of the responsibilities if EnsureLoad() calls Repository.Load(this) even if there's no physical separation. You could alternately discover the data access provider via a service locator pattern, or raise a RequestLoad event listened for by a loader class or something, but doing so might be overkill and add too much complexity for too little benefit. – Colin Apr 10 '15 at 21:04
0

In all those cases (it pops up a lot, though your example is extremely flawed) I generally name the enum as <thing>Type, or in your case DepartmentType. It can be argued whether or not it's 100% correct, but it easily gets the point across.

As to why that's flawed, the actual list of departments should be coming from a database because this list evolves over time. You don't want to keep recompiling your project every time you add a new department in your enterprise.

Blindy
  • 65,249
  • 10
  • 91
  • 131
  • The latter paragraph seems like an assumption. If the OP knows the departments are unlikely to change frequently, the code is actually more readable, discoverable and potentially less error prone by passing in an enum value vs. a string (which can be a practically infinite range of invalid values). – Colin Apr 10 '15 at 17:44
  • It wouldn't be a string, it would be an integer key, a foreign key into the departments table. – Blindy Apr 10 '15 at 17:48
  • That would be even worse in terms of readability and discoverability. What does department 2 mean? You don't know! What does "HR" mean? You kind of know, but it's not guaranteed to be a valid value (e.g. maybe you meant "Human Resources") and you can't be sure what is valid without knowledge of the available options in the database. By contrast, it's immediately clear what Department.HumanResources means and it's easy to tell what the available valid options are via intellisense for the enum. – Colin Apr 10 '15 at 17:54
  • Actually I can look up and ask anyone what department 5020 is, it's on our paychecks. Also in all our databases, reports, everything. I can't say as much about your enum value. – Blindy Apr 10 '15 at 18:03
  • If I, as a new developer at your company, have no familiarity with your business and code (or if I have a poor memory, which I do), I have no idea what 5020 means. I still don't, given the information you posted. However, if I asked you to work with Department.HumanResources in code, you know exactly what that means without me having to explain anything because the code is self-documenting. No memorization of database keys required. – Colin Apr 10 '15 at 18:13
  • As @Colin pointed out, this is basically a constant list. It is in our database and the ID behind the enum matches the database value. Based on the previous two or three years, the enum might have to be updated once a year for a department change, perhaps less. – Jeremy Apr 10 '15 at 18:46
-1

Sorry this is DepartmentType and also the approach for best practices in naming conventions whether you like it or not, you have a concrete class and this MUST BE NAMED AS Department if you want to follow best practices, that leaves us with the enum that has to be DepartmentType following best practices in naming conventions, so since you need both class and enum, i would implement it like this:

Create Enum:

public enum DepartmentType {IT, HR,..... }

in the Department class, add that Enum as property as well:

public Class Department
{
  public Name {get;set;}
  .
  .
  .

  public DepartmentType {get;set;}

}

Now you can use DepartmentType enum whether you have department object or you want to use it as plain in any method.

EDIT

Another way is to get rid of the Enum and create static int values in your Department Class:

   public class Department
    {
       Public string Name {get;set;}
       ...
       ...
       ...
       public static readonly int IT = 1;
       public static readonly int HR = 2;
     }

so now you can use it as Department.IT , Department.HR,..... without the need to instantiate an object of Department class, in short its used like Enum.

YazX
  • 444
  • 4
  • 12
-1

It depends. What are you looking to accomplish with the enum? If you're looking to key off of different department types irrespective of what the department happens to be named, then having enum DepartmentType makes perfect sense. For example:

if (department.Name == "Information Technology")

can be bad if your IT department's name has changed but you still want to perform the same actions on that department. However,

if (department.Type == DepartmentType.InformationTechnology)

doesn't care what the name of the department is; as long as it represents an IT department, your application still works.

Also, as mentioned in other answers, if you're looking to uniquely identify a department you really want to be using its primary key. You can still gain readability in your code by assigning static readonly fields to your class:

public static readonly int InformationTechnology = 1;

which lets you access IDs without referring to the number explicitly:

if (department.Id = Department.InformationTechnology)

although the downside to this approach is that you still have to recompile your code when a new Id is added if you want to continue checking without magic integers.

Kjata30
  • 721
  • 7
  • 20
-1

Use consts inside your class:

public class Department
{

     //Property to hold the department ID
     public int DepartmentID{ get; set; }

     public const int HumanResources = 1;
     public const int InformationTechnology = 2;
     //And so on..

}

Then if the Employee.IsInDepartment expects an int you can use:

Employee.IsInDepartment(Department.HumanResources)...
Gusman
  • 14,905
  • 2
  • 34
  • 50