Conversation
chrisjamiecarter
left a comment
There was a problem hiding this comment.
Hey @m1chael888 👋,
Excellent work on your Drinks Info project submission 🎉!
I have performed a peer review. Review/ignore any comments as you wish.
Your code demonstrates solid understanding of C# fundamentals and software architecture principles. The use of dependency injection, separation of concerns (Controllers/Services/Views), and the Spectre.Console library for a polished UI are particularly impressive. The project structure is clean and follows good practices.
Project-Wide Patterns:
-
Critical Bug in Extensions.cs - The GetDescription method will crash when an enum value has no DescriptionAttribute
-
Blocking Async Pattern - Using
.Resultinstead ofawaitin DrinksService -
Silent Failures - API errors return empty lists without any indication of what went wrong
-
Namespace Syntax - As per the academy's code-conventions, use file-scoped namespaces. From C# 10, we are able to remove the block/braces and save on level of indentation, optimising space and improving readability.
Critical Issue:
- The
Enums.Extensions.GetDescriptionmethod has a bug that will throwIndexOutOfRangeExceptionwhen an enum value lacks a Description attribute. The fallback should returnvalue.ToString()instead of accessingattributes[0].
Please fix the 🔴 critical bug in Enum.Extensions.cs, as it could cause a runtime crash. Once that's addressed, this is an excellent submission that demonstrates good architectural practices!
Please fix any 🔴 items, as they block approval. Commit and push your changes, then leave me a comment when done! 🔧
Thanks,
@chrisjamiecarter 👍
| { | ||
| return attributes[0].Description; | ||
| } | ||
| return attributes[0].Description; |
There was a problem hiding this comment.
🔴 Potential IndexOutOfRangeException Bug
💡 The GetDescription method has a logic error. When no DescriptionAttribute is found, it still tries to access attributes[0].Description, which will throw an IndexOutOfRangeException. Fix by returning the enum name instead:
if (attributes.Length > 0)
{
return attributes[0].Description;
}
return value.ToString();| @@ -0,0 +1,19 @@ | |||
| using DrinksInfo.m1chael888.Controllers; | |||
|
|
|||
| namespace DrinksInfo.m1chael888.Infratrstructure | |||
There was a problem hiding this comment.
🟠 Folder Name Typo
💡 The folder is named "Infratrstructure" instead of "Infrastructure". Consider renaming it to maintain professionalism and avoid confusion.
| { | ||
| var client = new RestClient(_drinkClient); | ||
| var request = new RestRequest("list.php?c=list"); | ||
| var response = client.ExecuteAsync(request); |
There was a problem hiding this comment.
🟠 Blocking Async Call
💡 Using .Result on an async operation blocks the thread and can cause deadlocks in certain scenarios. Prefer await for async operations:
var response = await client.ExecuteAsync(request);Remember to mark the method as async and return Task<List<Category>>.
| private readonly string _drinkClient = "https://www.thecocktaildb.com/api/json/v1/1/"; | ||
| public List<Category> GetCategories() | ||
| { | ||
| var client = new RestClient(_drinkClient); |
There was a problem hiding this comment.
🟠 RestClient Instantiation in Method
💡 Creating a new RestClient instance on every method call is inefficient. Consider injecting IRestClient as a singleton or creating it once in the constructor for better performance and resource management.
| var request = new RestRequest("list.php?c=list"); | ||
| var response = client.ExecuteAsync(request); | ||
|
|
||
| if (response.Result.StatusCode == System.Net.HttpStatusCode.OK) |
There was a problem hiding this comment.
🟠 Silent Failure on API Error
💡 When the API returns a non-OK status code, the method silently returns an empty list. Consider throwing an exception or logging the error so callers can handle failures appropriately.
| { | ||
| public class Drink | ||
| { | ||
| public string strDrink { get; set; } |
There was a problem hiding this comment.
🟡 Nullable Property Warnings
💡 The model properties generate CS8618 nullable warnings. Consider initializing them or marking them as nullable:
public string strDrink { get; set; } = string.Empty;
// OR
public string? strDrink { get; set; }| { | ||
| Console.OutputEncoding = Encoding.UTF8; | ||
|
|
||
| var collection = new ServiceCollection(); |
There was a problem hiding this comment.
🟢 Dependency Injection Setup
⭐ Great use of Microsoft.Extensions.DependencyInjection! This shows good understanding of dependency injection principles and makes the application testable and maintainable.
| MainMenuOption ShowMainMenu(); | ||
| void ShowAccessError(string msg); | ||
| } | ||
| public class DrinksView : IDrinksView |
There was a problem hiding this comment.
🟢 Clean UI Implementation
⭐ Excellent use of Spectre.Console for building a polished console UI! The SelectionPrompt usage with custom converters creates a professional user experience.
| { | ||
| private IDrinksView _drinksView; | ||
| private IDrinksService _drinksService; | ||
| public DrinksController(IDrinksView tableView, IDrinksService drinksService) |
There was a problem hiding this comment.
🟢 Separation of Concerns
⭐ Nice separation between controller logic and view logic. The controller handles user choices while delegating display responsibilities to the view - this follows the MVC pattern well.
|
|
||
| namespace DrinksInfo.m1chael888.Enums | ||
| { | ||
| public static class MainMenuEnums |
There was a problem hiding this comment.
🟢 Enum with Descriptions
⭐ Good use of the DescriptionAttribute pattern for displaying user-friendly text in the UI. This keeps display logic separate from the enum values themselves.
|
Thanks for another great review! I've committed the requested critical change and taken your advice on making other changes like the namespace syntax, handling empty api call returns, etc. Please let me know if anything looks off. Thanks again |
chrisjamiecarter
left a comment
There was a problem hiding this comment.
Again @m1chael888 great updates!
Approving.
Thanks :)