patterncsharpMinor
Display Loading Text with Spinner in Console
Viewed 0 times
spinnerwithconsoletextloadingdisplay
Problem
Here is my approach to creating a loading text spinner in the console. I did what I thought was best in designing the class, which means there is probably a lot of room for feedback.
The class is below, along with it's usage inside a Utils class. You can also find it here on github if that's easier.
Concerns
I have posted a question on StackOverflow regarding thread-safety/other issues regarding the Task API, since my first usage of it is surely wrong.
Post-writing the code, I also considered returning strings from the Task instead of forcing it to be Console output, but did not implement this functionality.
I am primarily interested in your feedback concerning the code style and general design. Pointers on the asynchrony are welcome, but not mandatory for a good answer.
Layout
Code
ConsoleLoadingText.cs
```
namespace Knoble.Utils
{
///
/// A class that represents a possibily infinitely looping load screen.
/// It displays a product name, loading text, and spinner that spins for a given delay.
///
public class ConsoleLoadingText
{
public const string DefaultProductName = "";
public const string DefaultLoadingText = "Loading...";
public const int DefaultMillisecondsDelay = 250;
static string[] spinner = { "|", "/", "-", "\\" };
readonly string produ
The class is below, along with it's usage inside a Utils class. You can also find it here on github if that's easier.
Concerns
I have posted a question on StackOverflow regarding thread-safety/other issues regarding the Task API, since my first usage of it is surely wrong.
Post-writing the code, I also considered returning strings from the Task instead of forcing it to be Console output, but did not implement this functionality.
I am primarily interested in your feedback concerning the code style and general design. Pointers on the asynchrony are welcome, but not mandatory for a good answer.
Layout
ConsoleLoadingText: class to encapsulate functionality.- Constants
- Defaults for
ProductName,LoadingText, andMillisecondsDelay
- Array of spinner pieces
- Constructors
- Chained together constructors allow you to provide some or all of the data, relying on defaults to fill in the gaps. They all delegate to one constructor which does the work.
- Methods
Displayreturns a Task which, when run, does the display work
Stopstops the display
Utils: Utility class- Methods
CreateLoadingcreates an instance of theConsoleLoadingTextclass with the parameters passed in; uses optional parameters for maximum flexibility
Code
ConsoleLoadingText.cs
```
namespace Knoble.Utils
{
///
/// A class that represents a possibily infinitely looping load screen.
/// It displays a product name, loading text, and spinner that spins for a given delay.
///
public class ConsoleLoadingText
{
public const string DefaultProductName = "";
public const string DefaultLoadingText = "Loading...";
public const int DefaultMillisecondsDelay = 250;
static string[] spinner = { "|", "/", "-", "\\" };
readonly string produ
Solution
Your constructors are really weird. You require all of the variables, but you still offer separate constructors which accept just a few parameters and you also have a helper class which utilises only the full ctor. It makes more sense to have a single constructor with no additional overloads.
If you want to build objects parameter per parameter you should look at the builder pattern reference.
But if that wasn't your intention just leave this constructor :
Code style
Naming
But why is only this variable special ? I don't see any reason why only this variable would have
Modifiers
I prefer having all of my members with explicit access modifiers.
If you want to build objects parameter per parameter you should look at the builder pattern reference.
But if that wasn't your intention just leave this constructor :
public ConsoleLoadingText(string productName, string loadingText, int millisecondsDelay)
{
if (productName == null)
throw new ArgumentException(nameof(productName));
if (loadingText == null)
throw new ArgumentException(nameof(loadingText));
if (millisecondsDelay < 0)
throw new ArgumentException(nameof(millisecondsDelay));
this.productName = productName;
this.loadingText = loadingText;
this.millisecondsDelay = millisecondsDelay;
}Code style
Naming
@continue that's a weird name looking at the @ a underscore would be more appropriate But why is only this variable special ? I don't see any reason why only this variable would have
@ at the beginning. You should be consistent in your variable naming, you either make all of them start with underscore or none of them. This makes reading long classes easier, because once you get used to specific convention, you can tell the modifiers of that variable just by looking at the name.Modifiers
I prefer having all of my members with explicit access modifiers.
spinner can be a readonly variable and you can use a verbatim string there for the last argument :private static readonly string[] spinner = { "|", "/", "-", @"\" };Code Snippets
public ConsoleLoadingText(string productName, string loadingText, int millisecondsDelay)
{
if (productName == null)
throw new ArgumentException(nameof(productName));
if (loadingText == null)
throw new ArgumentException(nameof(loadingText));
if (millisecondsDelay < 0)
throw new ArgumentException(nameof(millisecondsDelay));
this.productName = productName;
this.loadingText = loadingText;
this.millisecondsDelay = millisecondsDelay;
}Context
StackExchange Code Review Q#152159, answer score: 5
Revisions (0)
No revisions yet.