Code Red > .NET

How to validate a property of a struct ?

<< < (3/4) > >>

Grrr1337:

--- Quote from: MickD on January 06, 2019, 03:03:25 PM ---I see no reason to use a struct in this case, especially given the amount of different data types and validation required.

--- End quote ---

So I understand that normally a constructor/method overloading should be used instead ?
But if so, when we have to do a bit more complex checks to validate each provided property,
then wouldn't that overwhelm our code, since we have to repeat the same validation checks for every method overload ?
I mean that the technique in the suggestion from your reply #1 looks alot better.
Include new thought: Maybe the good practice is 1 private method that validates all of the public constructor overloads ? - that opposites everything I wrote above ^^

Although looking at the bigger picture - there would be no reason to validate the properties on every newly created instance,
rather the validation should occur within the 'Add' method.



--- Quote from: MickD on January 06, 2019, 03:03:25 PM ---You can then wrap the Employee in a 'Employees' class that would hold the list of Employee and would create the ID when adding a new Employee.

Something like this perhaps?

--- Code - C#: ---class Employee{  ...} class Employees {  ...} 
--- End quote ---

Didn't thought that the ID should be generated (which makes sense for the user/caller). *misled by the exercise's requirement*



--- Quote from: MickD on January 06, 2019, 03:03:25 PM ---I think structs are handy and lightweight when you need something like a coordinate or similar where there is a small group of similar data. If you need to do work on coordinates then it would be easier to create a class so you can do vector calculations etc.
You very rarely see structs in the wild :)

--- End quote ---

I've seen them used within types like 'Pixel', '2dPoint' / '3dPoint' or 'Color', although I'm not experienced enough so thanks for confirming! :)


BTW this is what ended up with, thanks to you :


--- Code - C#: ---struct Employee{   // Per MickD's suggestion, I could validate the properties within the struct, like so:  private string _name;  public string Name  {    get { return _name; }    set    {      if (String.Equals(value, String.Empty))      {        // cap it and continue (or throw exception?):              }      else { _name = value; }    }  }  // public string Name;  public string Surname;  public byte age;  public char sex;  public uint ID;} class Employees{  public List<Employee> ListEmployees  {    get { return employees; }    // set { employees = value; }  }  private List<Employee> employees = new List<Employee>();  public int Add(Employee employee)  {    uint empID = employee.ID;    if (empID == 0)     {      return -3; // throw no ID 'exception'      /* Or generate an ID:        employee.ID = employees.Last().ID + 1;        empID = employee.ID;      */    }    if(employees.Any())    {      foreach (Employee e in employees)      {        if(e.ID == empID)        {          return -1;        }      }    }    if (27560000 < empID && empID < 27569999)    {      employees.Add(employee);      return 1;    }    else { return -2; }    // return 0;  }  //.. I could use some overloads for 'Add' :  /*    public void Add (string Name)     public void Add (string Name, string Surname)     public void Add (string Name, string Surname, char sex)    etc...  */}
Sample test:

--- Code - C#: --- class Program{  static void Main()  {    Employees MyEmployees = new Employees();    Employee[] myArray =     {      new Employee { Name = "Alex", Surname = "Smirnoff", age = 19, sex = 'M', ID = 27560001 },      new Employee { Name = "Brian", Surname = "Johnson", age = 25, sex = 'M', ID = 27560002 },      new Employee { Name = "Chad", Surname = "Brown", age = 23, sex = 'M', ID = 27560003 },      new Employee { Name = "Derek", Surname = "Williams", age = 34, sex = 'M', ID = 27560004 },      new Employee { Name = "Eric", Surname = "Cartman", age = 41, sex = 'M', ID = 27560005 },      new Employee { Name = "Fernando", Surname = "Thomas", age = 31, sex = 'M', ID = 27560002 }, // Duplicate ID      new Employee { Name = "George", Surname = "Thompson", age = 46, sex = 'M', ID = 27570000 }, // Out of range ID      new Employee { Name = "Harry", Surname = "Robinson", age = 38, sex = 'M', ID = 27560006 },      new Employee { Name = "Ivan", Surname = "Taylor", age = 50, sex = 'M', ID = 27550000 }, // Out of range ID      new Employee { Name = "Jack", Surname = "Green", age = 37, sex = 'M', }, // NO ID    };        Console.WriteLine("\n\n*** Validation Results: \n");    foreach (Employee e in myArray)    {      switch (MyEmployees.Add(e))      {        case -1: { Console.WriteLine("Duplicate ID: {0} {1}", e.Name, e.Surname); break; }        case -2: { Console.WriteLine("Out of range ID: {0} {1}", e.Name, e.Surname); break; }        case -3: { Console.WriteLine("No ID: {0} {1}", e.Name, e.Surname); break; }        default: break;      }    }        Console.WriteLine("\n\n*** Employees: \n");    foreach (Employee e in MyEmployees.ListEmployees)    {      Console.WriteLine("{0} {1}, ID: {2}", e.Name, e.Surname, e.ID);    }      }}

MickD:
You shouldn't need overloaded constructors, one would do (that asks for all values as you have).

The exercise requirement of creating an Employee is a bit out of context to the lesson (not that I really read it :) ) in that it's trying to teach using the right types, not business logic. In the real world you would probably have a user form or web site form to fill in this data and that's where I would do the parsing and validation (behind each text box) before I even create an Employee.
The ID wouldn't be part of this form and would most likely be created when storing the Employee data to the database by creating an auto-incremented Primary Key.

When you add the Employee to the db you would get back the ID from the db and you can assign it then via property setter if you still need to use the Employee class for a bit.

In light of all that you could probably just use a struct as all your logic is handled elsewhere and there's no calculations or other real methods required within the class :)

Grrr1337:

--- Quote from: MickD on January 07, 2019, 01:38:33 PM ---You shouldn't need overloaded constructors, one would do (that asks for all values as you have).

The exercise requirement of creating an Employee is a bit out of context to the lesson (not that I really read it :) ) in that it's trying to teach using the right types, not business logic. In the real world you would probably have a user form or web site form to fill in this data and that's where I would do the parsing and validation (behind each text box) before I even create an Employee.
The ID wouldn't be part of this form and would most likely be created when storing the Employee data to the database by creating an auto-incremented Primary Key.

When you add the Employee to the db you would get back the ID from the db and you can assign it then via property setter if you still need to use the Employee class for a bit.

In light of all that you could probably just use a struct as all your logic is handled elsewhere and there's no calculations or other real methods required within the class :)

--- End quote ---


Exactly - I was curious about what happens in the real world for a such common scenario.
Due my little amount C-language experience, one of the first things I did was to check out various source codes (what they look like),
by decompiling some assemblies on my PC or from blogs on the internet.
The impression I had was that there was no 'defensive programming' and very rarely I could find a conditional kword like 'if'.
So purely calculations/execution and almost no validation, which makes the whole asembly shorter and cleaner.. but again where the heck is the validation?!
Now making some conclusions from your comment, the validation must be happening within the form assembly.. so everything else is just execution.
Or for short "Validate Inputs -> Compute/Execute -> Output" :)

MickD:
Yeah, structuring your code can take some getting used to and OOP can lead you down some wrong paths given some of the example code you are given to learn with.
Some say you should do business logic in your 'object' and keep the UI simple but is validation business logic or UI logic??
You need to think about how you would decouple your UI from your data objects or even languages, to keep it simple to do this it makes sense to keep validation in the UI.

Another way is to have helper classes that work on Employee classes rather than build a huge Employee class. For instance, would you calculate an Employee's tax or benefits within the employee class or does it make more sense to have a class that does this based on basic employee data?
As there can be many 'types' of employee (i.e. boss, janitor, CEO) it might seem logical to put these methods into a base class and override them for each new type but that becomes a maintenance nightmare real quick. Better to update one helper class to deal with a slightly different type than have to update all of your other types (not the best example but hopefully you see the potential problem).

But again, it depends....generally I like to have simple 'data' classes and then have classes that work on them, especially if you are storing these objects in a db it can make things easier. Think about how you would save all of these different types of employees in a db, you wouldn't have tables for each different type so why create new classes for each, just have a 'type' or 'role' field and you're done.

It's Alive!:
I like to use assert, and test in debug mode… System.Diagnostics.Debug.Assert( … );   
It compiles out for release builds and you don’t get the performance hit..
When in doubt, program defensively, if you need if statements … use them .

look at the color struct in system.windows.forms for examples

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version