How to Code User-Typed Console info with SOLID Principles

Mitchelln11

Active member
Joined
Apr 10, 2020
Messages
39
Programming Experience
Beginner
I recently completed an small assessment that reads a CSV sheet, then adds to it. This is a C# console app. I'm still learning, and at this point, I can achieve MVP, but it is lacking in SOLID principles or 4 pillars of OOP.

Here is a working method for retrieving a first name from a user:
C#:
public string AddFirstName()
{
     Console.WriteLine(Environment.NewLine + "Please Type in the client's first name. Then hit enter after.");
     enrolled.FirstName = Console.ReadLine().Trim();
     return enrolled.FirstName;
}

However, I need similar functionality when asking for a last name. That makes me believe I should use something like an abstract class/inheritance where I can re-use a method to ask for and save a value.
How would I convert this to an abstract class?
Is this even the right approach?
Any help is appreciated.

I did start with a parent class:
C#:
public abstract class GetConsoleInfo
{
     public abstract string UserLogInfo();
}

And the separate class inheriting the parent:
C#:
public class GetFirstName : GetConsoleInfo
{
     CsvData enrolled = new CsvData();
     FirstCharUpper first = new FirstCharUpper();

     public string firstNameUpper;

     public override string UserLogInfo()
     {
         Console.WriteLine(Environment.NewLine + "Please Type in the client's last name. Then hit enter after.");
         string firstName = Console.ReadLine();
         firstNameUpper = first.FirstUpper(firstName.Trim());
         enrolled.FirstName = firstNameUpper;
         return enrolled.FirstName;
     }
 }
 
There's already a class for interacting with the console. It's the Console class. You don't need another one. Having a method to prompt the user for some input might make sense, but that would go in your Program class, e.g.
C#:
private string GetPromptedInput(string prompt)
{
    Console.WriteLine(prompt);
    
    return Console.ReadLine().Trim();
}
You might then have a Client class and populate it like so:
C#:
var client = new Client();

client.GivenName = GetPromptedInput("Please enter the client's given name.");
client.FamilyName = GetPromptedInput("Please enter the client's family name.");
You might wrap that code in another method named GetClient or the like.

You need to consider the entities, both physical and abstract, that you need to represent as types in your application. A thing that gets a first name is not something that you need to represent. A client is.
 
Yes, that GetPromptedInput() in a perfect example of the Open/Closed principle to give us the O in SOLID, but how will you now reconcile that with the I (Interface independence) by having a class that gets the client information?

Personally, I think that good object oriented programming simply a matter of not violating any of the SOLID principles. It is not necessarily about implementing all of the principles if you don't need it at that time. If you can accomplish the task where only some of the five principles are used (and not violate any of the unused principles), then you are following even higher priority programming principles: KISS and YAGNI.

Admittedly, this does bite me in the butt from time to time. Often I would first write code without the 'D' in SOLID to just have SOIL. This ends up becoming a big pile of dirt -- or mud, because when the bugs come in, it doesn't just rain, it pours. I'll have to go back and add in the Dependency injection to make my code more testable, as well as, support the Open/close principle even more.
 
There's already a class for interacting with the console. It's the Console class. You don't need another one. Having a method to prompt the user for some input might make sense, but that would go in your Program class, e.g.
C#:
private string GetPromptedInput(string prompt)
{
    Console.WriteLine(prompt);
   
    return Console.ReadLine().Trim();
}
You might then have a Client class and populate it like so:
C#:
var client = new Client();

client.GivenName = GetPromptedInput("Please enter the client's given name.");
client.FamilyName = GetPromptedInput("Please enter the client's family name.");
You might wrap that code in another method named GetClient or the like.

You need to consider the entities, both physical and abstract, that you need to represent as types in your application. A thing that gets a first name is not something that you need to represent. A client is.

-----
Response:
So would I stay away from abstract classes?
Also, do I have to put the message prompt in the program class? I was taught to keep as much out of there as possible.
 
OK, I got it working with this:

Method to start the prompt
C#:
public string AddFirstName()
{
     var prompt = enrolled.FirstNamePrompt;
     enrolled.FirstName = info.GetPromptedInput(prompt);
}

Method asking for Input - from your code (jmcilhinney) -Thank you
C#:
public class GetConsoleInfo
{
     public string GetPromptedInput(string prompt)
     {
          Console.WriteLine(prompt);
          return Console.ReadLine().Trim();
     }
}

And I assigned the prompt text with getters and setters

So the first method is grabbing the prompt
Then assigning the resulting return value from the GetPromptedInput() method.

Is that about right? This does work. Just not 100% that it's the cleanest code possible.

Either way, I appreciate the help.
 
Why would an object intended to store information about a thing care about the prompt to display to the user to get that data? The prompt is purely a presentation consideration. It's nothing to do with the model.
 
@Mitchelln11 : Basically, what @jmcilhinney is pointing out in post #6 is that you are not following the S in SOLID.
 
Back
Top Bottom