该代码是一个简单的控制台应用程序,用于随机更新汇率。我按照我的训练计划编写了它,并在这段代码中实现了delegate
和event
。版本.NET
- 4.8
代码写得有多糟糕?应该做出哪些改变?
using System;
using System.Collections.Generic;
namespace CryptoBot
{
public class Program
{
public static Dictionary<string, decimal> CryptoValute = new Dictionary<string, decimal>();
public static decimal ForExtemeValue;
private static int _count = 0;
static CryptoPriceMonitor priceMonitor = new CryptoPriceMonitor();
static TraderBot traderBot = new TraderBot(priceMonitor);
public static void PrintColor(string message, ConsoleColor color)
{
Console.ForegroundColor = color;
Console.WriteLine(message);
Console.ResetColor();
}
static void Main(string[] args)
{
CryptoValute.Add("Bitcoin", 50000);
CryptoValute.Add("DogeCoin", 3);
CryptoValute.Add("Ethereum", 1680);
CryptoValute.Add("USDT", 26);
PrintColor("Choose valute: Bitcoin, DogeCoin, Ethereum, USDT", ConsoleColor.Green);
PrintColor("Current Prices:", ConsoleColor.Green);
foreach (var price in CryptoValute)
{
Console.WriteLine(price);
}
string Choose = Console.ReadLine();
while (true)
{
switch (Choose)
{
case "Bitcoin":
ForExtemeValue = CryptoValute["Bitcoin"];
Iterations("Bitcoin");
Choose = Console.ReadLine();
break;
case "DogeCoin":
ForExtemeValue = CryptoValute["DogeCoin"];
Iterations("DogeCoin");
Choose = Console.ReadLine();
break;
case "Ethereum":
ForExtemeValue = CryptoValute["Ethereum"];
Iterations("Ethereum");
Choose = Console.ReadLine();
break;
case "USDT":
ForExtemeValue = CryptoValute["USDT"];
Iterations("USDT");
Choose = Console.ReadLine();
break;
default:
PrintColor("There is no currency on the list.", ConsoleColor.Green);
Choose = Console.ReadLine();
break;
}
}
}
private const int IterationsCount = 1000;
public static void Iterations(string name)
{
string valute;
decimal value;
_count = 0;
valute = name;
value = CryptoValute[name];
while (_count != IterationsCount)
{
_count++;
value = CryptoValute[name];
priceMonitor.UpdatePrice(value, valute);
}
Console.Clear();
PrintColor($"Here are a {IterationsCount} last iterations", ConsoleColor.Green);
PrintColor("Choose valute: Bitcoin, DogeCoin, Ethereum, USDT", ConsoleColor.Green);
PrintColor("Current Prices:", ConsoleColor.Green);
foreach (var price in CryptoValute)
{
Console.WriteLine(price);
}
}
}
public class CryptoPriceMonitor
{
public void UpdatePrice(decimal oldPrice, string name)
{
decimal currentPrice = oldPrice;
PriceChanged?.Invoke(oldPrice, ExtremeValues(currentPrice), name);
}
private Random _random = new Random();
private int _procent;
private const int MaxRandomProcent = 8;
private const int MinRandomProcent = -7;
private decimal ExtremeValues(decimal basePrice)
{
decimal newPrice = basePrice;
decimal maxValue = Program.ForExtemeValue * 100;
decimal minValue = Program.ForExtemeValue - (Program.ForExtemeValue * 90) / 100;
if (basePrice >= maxValue)
{
_procent = _random.Next(MinRandomProcent, 0);
newPrice -= (basePrice * Math.Abs(_procent)) / 100;
return newPrice;
}
if (basePrice <= minValue)
{
_procent = _random.Next(1, MaxRandomProcent);
newPrice += (basePrice * Math.Abs(_procent)) / 100;
return newPrice;
}
else
{
_procent = _random.Next(MinRandomProcent, MaxRandomProcent);
if (_procent > 0)
{
newPrice += (basePrice * Math.Abs(_procent)) / 100;
return newPrice;
}
else
{
newPrice -= (basePrice * Math.Abs(_procent)) / 100;
return newPrice;
}
}
}
public delegate void PriceChangeHandler(decimal oldPrice, decimal newPrice, string valute);
public event PriceChangeHandler PriceChanged;
}
public class TraderBot
{
public TraderBot(CryptoPriceMonitor monitor)
{
monitor.PriceChanged += OnPriceChanged;
}
public void OnPriceChanged(decimal oldPrice, decimal newPrice, string valute)
{
if (newPrice > oldPrice)
{
Program.PrintColor($"Цена повысилась: {oldPrice} -> {newPrice}", ConsoleColor.Green);
RestorPrice(valute, newPrice);
}
else
{
Program.PrintColor($"Цена понизилась: {oldPrice} -> {newPrice}", ConsoleColor.Red);
RestorPrice(valute, newPrice);
}
}
public static void RestorPrice(string valute, decimal value)
{
Program.CryptoValute[valute] = value;
}
}
}
简而言之,从建筑的角度来看,我不会对小细节吹毛求疵。
CryptoValute
——这应该至少是两个独立的类别。例如CryptoCurrency
- 货币本身,在您的情况下,货币除了名称之外没有其他属性(价格不是货币的内部属性,而是外部属性),因此它应该是一个枚举,即enum
。CryptoPrices
- 货币价格存储,是的,里面会有一本字典,但是所有与价格相关的逻辑,例如设置和获取价格、打印所有价格等,都应该隐藏在这个类中RestorPrice
,Iterations
,ExtremeValues
?从名称上看不太清楚它们是什么,它们不是很标准。如果一种方法产生某种动作,那么其名称必须包含动词,并且是典型的动词:Set
,,,等等,Save
而不是名词。Process
Print
DRY
。例如,switch
如果您知道字典具有方法ContainsKey
和,那么这里就不需要了TryGetValue
。代码将会变得短很多。在其他地方,可以通过重构来避免代码重复。鉴于作者最初同意蒸汽,我请求原谅整个后续语气。
真恶心。
让我们把一切都安排好。
什么? 2025年是4.8吗?我们可以在这里进行长时间的讨论,关于让您感受到 dotnet 历史的精神有多么有用,但是在如此落后的框架中向我发送代码以供审查,这表明程序员不够格。找个借口将会很困难。
好吧,这就是古代的精神。我们已经受苦15年了,左边的四个符号都白白浪费了,而你们却继续肆意妄为。
namespace CryptoBot;
并且对于括号之神来说没有多余的括号。首先,为什么
public
外面的人要修改这本词典?其次,再次古语,为什么new
除了括号之外还要写其他内容?第三,字段不能是公共的,更不能是公共且可变的。顺便问一下,您是否开始将业务逻辑推入 Program 类?它只需要启动应用程序,也可以以某种方式停止它,所以请不要在其中存储任何超出此权限的内容。
那些。您觉得写私密可以吗或者不写私密可以吗,这取决于您此刻的感受?这里没有明确的路线,但你要么一直写,要么不再写。
除了它
new
不是简洁的之外,初始化类并使用类而不是接口可能通常没问题,但请记住,您正如履薄冰,依赖倒置原则正在等待惩罚的时刻。这是一个很好的方法,直到你达到哪怕是最轻微的并行性,然后你的控制台将开始着色,混乱地,欢快地,但混乱地。
不仅对货币列表进行硬编码,而且对汇率也进行硬编码?两者都不能嵌入代码中。至少将所有这些放入几个配置文件中。一个用于货币列表,另一个用于报价。
也许我们可以在这里休息一下。我希望它会有用。