大家好。我正在学习 C#。编写了一个控制台应用程序来检查平面上和空间中两点之间的距离。一切正常,我没有注意到任何错误,但我修复了那些。请尽可能评价。如果你做错了什么,戳你的鼻子。现在我真的需要这个。
static void Main(string[] args)
{
char selection;
Double x1, x2, y1, y2, z1, z2, distance;
Console.WriteLine("1. Расстояние между двумя точками на плоскости.");
Console.WriteLine("2. Расстояние между двумя точками в пространстве.");
Console.WriteLine("Выберите нужный пункт (1 или 2):");
selection = Convert.ToChar(Console.ReadLine());
switch (selection)
{
case '1':
Console.Write("Введите координаты x1: ");
x1 = Convert.ToDouble(Console.ReadLine());
Console.Write("Введите координаты x2: ");
x2 = Convert.ToDouble(Console.ReadLine());
Console.Write("Введите координаты y1: ");
y1 = Convert.ToDouble(Console.ReadLine());
Console.Write("Введите координаты y2: ");
y2 = Convert.ToDouble(Console.ReadLine());
distance = Math.Sqrt(Math.Pow(x2 - x1, 2) + Math.Pow(y2 - y1, 2));
Console.WriteLine($"Расстояние между двумя точками на плоскости равно {distance}");
Console.ReadKey();
break;
case '2':
Console.Write("Введите координаты x1: ");
x1 = Convert.ToDouble(Console.ReadLine());
Console.Write("Введите координаты x2: ");
x2 = Convert.ToDouble(Console.ReadLine());
Console.Write("Введите координаты y1: ");
y1 = Convert.ToDouble(Console.ReadLine());
Console.Write("Введите координаты y2: ");
y2 = Convert.ToDouble(Console.ReadLine());
Console.Write("Введите координаты z1: ");
z1 = Convert.ToDouble(Console.ReadLine());
Console.Write("Введите координаты z2: ");
z2 = Convert.ToDouble(Console.ReadLine());
distance = Math.Sqrt(Math.Pow(x2 - x1, 2) + Math.Pow(y2 - y1, 2) + Math.Pow(z2 - z1, 2));
Console.WriteLine($"Расстояние между двумя точками в пространстве равно {distance}");
Console.ReadKey();
break;
default:
Console.WriteLine("Вы ввели неверный символ");
Console.ReadKey();
break;
}
}
}
}
有一个现成的exe,但是这里没有办法附加。如果是这样,您可以在此处下载。
当您编写程序、编写代码时,对代码质量、样式和结构的要求可能会有所不同,这取决于许多因素。这就像写一部小说——如果你正在写一个短篇小说,那么你就不必担心人物生活的宇宙、每个人的动机以及其他事情。如果你正在写一部伟大的作品,那么你将不得不预见一切,一个虚构世界的规律,这个世界将发生的事件,你作品的不同部分将紧密交织在一起,作品的整体复杂性会增加.
我将尝试更详细地解释这一点。如果您不打算开发应用程序,即您发送的代码是最终版本并且您永远不需要对其进行更改,那么一切都井井有条,您的几行代码就可以了。如果您解决课程作业或仅解决培训问题,就会发生这种情况。
现在让我们想象一下,我们正在编写一个庞大的公司系统的一部分(即,最令人困惑的选项之一),可能有什么要求,可以改变什么?
因此,首先引起您注意的是您使用代码中的点进行操作 - 二维和三维。在您拥有的当前版本中,一个点由 2 或 3 个变量 - 坐标表示。每次需要存储一个点时,都将其存储为一组变量。对于一个简单的应用程序,这并不重要。对于企业来说 - 这很糟糕,因为
因此,如果是公司应用程序,我要做的第一件事是选择 2 个实体 - 2d 和 3d 点。它可能看起来像这样:
现在,手头有点,我们进一步阅读任务 - 我们需要能够找到点之间的距离。您在 main 函数中正确执行此操作,但我们正在编写一个公司系统 - 这意味着您的应用程序将经过多年开发,也就是说,肯定在某个地方、某个时候、也许另一个程序员需要完全相同的功能 - 计算距离点之间。因此,建议为此编写一个函数。但是这个函数去哪里了?对于最简单的操作,我将创建一个单独的类来处理点或几何图元。我会将类和方法本身设为静态,因为计算点之间的距离是一种在未来不太可能改变的算法,无论我们的应用程序逻辑如何变化。
接下来,问题是——我们如何理解我们的方法是正确的?此外,在我们之后编写代码的程序员可能会意外或故意更改我们的公式,使程序无法使用。如何降低这种风险?这就是自动测试发挥作用的地方(在 Google 中搜索的关键字是单元测试、单元测试)。例如,这里有几个使用 NUnit 框架的测试
那么我们有什么?我们有积分,我们有一个经过验证的计算距离的方法。此外,我们需要能够从用户那里读取这些点。也就是说,我们需要一个函数来读取一个点(2d 和 3d)。随着您获得开发经验,您将开始了解某些功能的代码职责等。例如,从控制台读取一个点是一个函数,理论上它不会与点本身的逻辑、距离计算的逻辑或一般的几何运算有任何交叉。也就是说,从控制台读取一个点是一个绝对独立的功能,所以我将为此创建一个单独的类。原则上,我会将我们需要的所有与控制台的交互添加到这个类中。
请注意,该类本身不是静态的,它实现了我们编写的接口。这是有目的的,因为在未来,如果我们不仅要从控制台读取点,而且还要从数据库或 Web 服务或其他一些数据源读取点,那么很容易编写几个从控制台读取只是一种选择的接口的实现。然后,我们将能够运行我们的脚本,同时不仅从控制台读取数据。这也将有助于我们测试我们的场景。
所以,我们有一个读点器,下一步是什么?接下来,我们有一个带有选择的主要场景和 2 个独立场景,在一个场景中我们读取 2d 点,在另一个场景中 - 3d。让我们以 3 个函数的形式来表示。不要忘记这些脚本是一个单独的功能,与我们代码的其他部分没有任何联系,所以我将把它分成一个单独的类。
请注意,脚本并不确切知道它们从哪里读取以及从哪里写入值。这个脚本类只传递了一个接口。如何使用它?让我们编写入口点的逻辑:
我们在这里看到,在程序执行的最开始,我们只是准备了我们需要的类并运行它们。这一点,当我们刚刚启动并运行系统时,称为组合根。这里没有逻辑,只有必要的类的准备和它们的启动。
看来,还有什么可以补充的?但这还不是全部!问题出现了——我们如何确保我们的逻辑、我们的脚本正常工作?答案很明显,我们需要一个脚本测试。这就是我们的stsknaria不知道他们从哪里读取以及他们在哪里写入他们的值的事实将帮助我们。
让我们编写我们自己的与用户交互的模拟,例如,这个
如您所见,在这个类的帮助下,我们将能够在没有人为干预的情况下运行我们的逻辑和测试。也就是说,我们可以编写逻辑测试并运行它们,从而表明我们的逻辑工作正常。这是 2 个测试的示例,第一个测试模拟无效的用户输入,第二个是具有 2 维点的简单脚本。
结果,在所有的手势之后,我们有了一个易于扩展和测试的程序。是的,它需要更多的文本,但它的一个单独部分很容易阅读,它的用途很明显,扩展了功能(例如,不是从控制台读取输入数据,而是从数据库或其他地方读取数据) ) 可以很快完成,并且正确性程序的工作是通过测试来证明的。
参考文献:
如何编写代码:
Оганизация кода и паттерны
Тестирование
Другая литература по c#