Aprendiendo .NET sobre la marcha (v)


<<Aprendiendo .NET sobre la marcha (iii)
<<Aprendiendo .NET sobre la marcha (iv)

Continuando con la construcción de nuestra primera aplicación incluyendo unidades de pruebas, y ya explicados algunos términos más procedemos a crear los siguientes enumeración y métodos:

public enum eOpciones {
  Nada = 0,
  Salir = 1,
  Perimetro = 10,
  Area = 20,
  AreaLateral = 30,
  AreaTotal = 40,
  Volumen = 50
};

public double Triangulo(double _base, double _altura) {
  return _base * _altura / 2;
}

public double Triangulo(double _base, double _ladoA, double _ladoB) {
  return _base + _ladoA + _ladoB;
}

public double Rectangulo(double _base, double _altura, eOpciones _opcion) {
  if (_opcion == eOpciones.Area)
    return _base * _altura;
  else if (_opcion == eOpciones.Perimetro)
    return 2 * (_base + _altura);
  else
    return 0;
}

La enumeración nos facilitará el uso de constantes al agruparlas, mientras que los métodos llamados "Triangulo" implementan el cálculo de área y perímetro por medio de la sobrecarga. Para el rectánculo, dado que para calcular su superfice y perímetro usamos los mismos argumentos, le agregamos un parámetro que indique lo que deseamos calcular.

Ahora, aprovechamos estos tres métodos para construir otras funciones para calcular cosas más complejas:

public double Trapecio(double _baseMayor, double _baseMenor, double _altura) {
  return Triangulo((_baseMayor + _baseMenor), _altura);
}

public double PoligonoRegular(int _numLados, double _Lado, double _apotema) {
  return Triangulo(_Lado, _apotema) * _numLados;
}

public double PrismaPoligonal(int _numLados, double _Lado, double _apotema, double _altura, eOpciones _opcion) {
  double resultado = 0D;
  switch (_opcion) {
    case eOpciones.AreaLateral:
      resultado = _Lado * _numLados * _altura;
    break;
    case eOpciones.AreaTotal:
      resultado = (_Lado * _numLados * _altura) + (2 * PoligonoRegular(_numLados, _Lado, _apotema));
    break;
    case eOpciones.Volumen:
      resultado = PoligonoRegular(_numLados, _Lado, _apotema) * _altura;
    break;
    default:
      resultado = 0;
    break;
  }
  return resultado;
}

public double PiramidePoligonal(int _numLados, double _Lado, double _apotema, double _altura, double _alturaCara, eOpciones _opcion) {
  double resultado = 0D;
  switch (_opcion) {
    case eOpciones.AreaLateral:
      resultado = _numLados * Triangulo(_Lado, _alturaCara);
    break;
    case eOpciones.AreaTotal:
      resultado = _numLados * Triangulo(_Lado, _alturaCara) + PoligonoRegular(_numLados, _Lado, _apotema);
    break;
    case eOpciones.Volumen:
      resultado = PrismaPoligonal(_numLados, _Lado, _apotema, _altura, eOpciones.Volumen) / 3;
    break;
    default:
      resultado = 0;
    break;
  }
  return resultado;
}

Aquí podemos observar que utilizamos métodos previamente definidos, además de usar switch para la selección de una opción. Nuevamente, procedemos a construir las unidades de pruebas para nuestros nuevos métodos y verificar que los cálculos funcionen correctamente.

El siguiente código es el conjunto de pruebas para estos métodos (tratando de ser lo más preciso posible y no inventando datos al azar)

double apotema = 2.5 / Math.Tan(36 * Math.PI / 180);
[TestMethod()]
public void TrianguloTest() {
  var resultado = (new Program()).Triangulo(2, 2);
  Assert.IsTrue(resultado.Equals(2), string.Format("Error de cálculo: {0}", resultado));
  Console.WriteLine(string.Format("Superficie: {0}", resultado));
}

[TestMethod()]
public void TrianguloTest1() {
  var resultado = (new Program()).Triangulo(3, 4, 5);
  Assert.IsTrue(resultado.Equals(12), string.Format("Error de cálculo: {0}", resultado));
  Console.WriteLine(string.Format("Perímetro: {0}", resultado));
}

[TestMethod()]
public void RectanguloTest() {
  var resultado = (new Program()).Rectangulo(4, 2, Program.eOpciones.Perimetro);
  Assert.IsTrue(resultado.Equals(12), string.Format("Error de cálculo: {0}", resultado));
  Console.WriteLine(string.Format("Perímetro: {0}", resultado));
  resultado = (new Program()).Rectangulo(4, 2, Program.eOpciones.Area);
  Assert.IsTrue(resultado.Equals(8), string.Format("Error de cálculo: {0}", resultado));
  Console.WriteLine(string.Format("Superficie: {0}", resultado));
}

[TestMethod()]
public void TrapecioTest() {
  var resultado = (new Program()).Trapecio(4, 2, 3);
  Assert.IsTrue(resultado.Equals(9), string.Format("Error de cálculo: {0}", resultado));
}

[TestMethod()]
public void PoligonoRegularTest() {
  var resultado = (new Program()).PoligonoRegular(5, 5, apotema);
  Assert.IsTrue(Math.Round(resultado, 2).Equals(43.01), string.Format("Error de cálculo: {0}", resultado));
}

[TestMethod()]
public void PrismaPoligonalTest() {
  var resultado = (new Program()).PrismaPoligonal(5, 5, apotema, 10, Program.eOpciones.Volumen);
  Assert.IsTrue(Math.Round(resultado, 2).Equals(430.12), string.Format("Error de cálculo: {0}", resultado));
}

[TestMethod()]
public void PiramidePoligonalTest() {
  var resultado = (new Program()).PiramidePoligonal(5, 5, apotema, 10, 0, Program.eOpciones.Volumen);
  Assert.IsTrue(Math.Round(resultado, 2).Equals(143.37), string.Format("Error de cálculo: {0}", resultado));
}

Muy bien, ya que terminamos nuestros métodos y nos aseguramos que funcionen, es hora de agregar a nuestra aplicación de consola su código para que trabaje correctamente.

eOpciones menuItem = eOpciones.Nada;
            string opcion = string.Empty;
            Program prog = new Program();
            double _ladoA = 0D, _ladoB = 0D, _ladoC = 0D;
            int _numLados = 0;
            while (menuItem != eOpciones.Salir) {
                Console.Clear();

                foreach (var item in Enum.GetNames(typeof(eOpciones))) {
                    Enum.TryParse(item, out menuItem);
                    if (menuItem != eOpciones.Nada)
                        Console.WriteLine(string.Format("[{0}] {1}", (int)menuItem, item.Replace("_", " ")));
                }

                Console.Write("Opción a ejecutar: ");
                Enum.TryParse(Console.ReadLine(), out menuItem);

                switch (menuItem) {
                    case eOpciones.Perimetro:
                        Console.WriteLine("[1] Triángulo\n[2] Rectángulo");
                        opcion = Console.ReadLine();
                        if (opcion == "1") {
                            Console.Write("Lado A: ");
                            double.TryParse(Console.ReadLine(), out _ladoA);
                            Console.Write("Lado B: ");
                            double.TryParse(Console.ReadLine(), out _ladoB);
                            Console.Write("Lado C: ");
                            double.TryParse(Console.ReadLine(), out _ladoC);
                            Console.WriteLine("Resultado: {0}", prog.Triangulo(_ladoA, _ladoB, _ladoC));
                        } else if (opcion == "2") {
                            Console.Write("Lado A: ");
                            double.TryParse(Console.ReadLine(), out _ladoA);
                            Console.Write("Lado B: ");
                            double.TryParse(Console.ReadLine(), out _ladoB);
                            Console.WriteLine("Resultado: {0}", prog.Rectangulo(_ladoA, _ladoB, menuItem));
                        } else {
                            Console.WriteLine("Opción no válida.");
                        }
                        break;
                    case eOpciones.Area:
                        Console.WriteLine("[1] Triángulo\n[2] Rectángulo\n[3] Trapecio\n[4] Polígono regular");
                        opcion = Console.ReadLine();
                        if (opcion == "1") {
                            Console.Write("Lado A: ");
                            double.TryParse(Console.ReadLine(), out _ladoA);
                            Console.Write("Lado B: ");
                            double.TryParse(Console.ReadLine(), out _ladoB);
                            Console.WriteLine("Resultado: {0}", prog.Triangulo(_ladoA, _ladoB));
                        } else if (opcion == "2") {
                            Console.Write("Lado A: ");
                            double.TryParse(Console.ReadLine(), out _ladoA);
                            Console.Write("Lado B: ");
                            double.TryParse(Console.ReadLine(), out _ladoB);
                            Console.WriteLine("Resultado: {0}", prog.Rectangulo(_ladoA, _ladoB, menuItem));
                        } else if (opcion == "3") {
                            Console.Write("Base mayor: ");
                            double.TryParse(Console.ReadLine(), out _ladoA);
                            Console.Write("Base menor: ");
                            double.TryParse(Console.ReadLine(), out _ladoB);
                            Console.Write("Altura: ");
                            double.TryParse(Console.ReadLine(), out _ladoC);
                            Console.WriteLine("Resultado: {0}", prog.Trapecio(_ladoA, _ladoB, _ladoC));
                        } else if (opcion == "4") {
                            Console.Write("Número de lados: ");
                            int.TryParse(Console.ReadLine(), out _numLados);
                            Console.Write("Tamaño de los lados: ");
                            double.TryParse(Console.ReadLine(), out _ladoA);
                            Console.Write("Apotema: ");
                            double.TryParse(Console.ReadLine(), out _ladoB);
                            Console.WriteLine("Resultado: {0}", prog.PoligonoRegular(_numLados, _ladoA, _ladoB));
                        } else {
                            Console.WriteLine("Opción no válida.");
                        }
                        break;
                    case eOpciones.AreaLateral:
                    case eOpciones.AreaTotal:
                    case eOpciones.Volumen:
                        Console.WriteLine("[1] Prisma\n[2] Pirámide");
                        opcion = Console.ReadLine();
                        if (opcion == "1") {
                            Console.Write("Número de lados: ");
                            int.TryParse(Console.ReadLine(), out _numLados);
                            Console.Write("Tamaño de los lados: ");
                            double.TryParse(Console.ReadLine(), out _ladoA);
                            Console.Write("Apotema: ");
                            double.TryParse(Console.ReadLine(), out _ladoB);
                            Console.Write("Altura del cuerpo geométrico: ");
                            double.TryParse(Console.ReadLine(), out _ladoC);
                            Console.WriteLine("Resultado: {0}", prog.PrismaPoligonal(_numLados, _ladoA, _ladoB, _ladoC, menuItem));
                        } else if (opcion == "2") {
                            Console.Write("Número de lados: ");
                            int.TryParse(Console.ReadLine(), out _numLados);
                            Console.Write("Tamaño de los lados: ");
                            double.TryParse(Console.ReadLine(), out _ladoA);
                            Console.Write("Apotema: ");
                            double.TryParse(Console.ReadLine(), out _ladoB);
                            Console.Write("Altura del cuerpo geométrico: ");
                            double.TryParse(Console.ReadLine(), out _ladoC);
                            double _alturaCara = 0D;
                            if (!menuItem.Equals(eOpciones.Volumen))
                                double.TryParse(Console.ReadLine(), out _alturaCara);
                            Console.WriteLine("Resultado: {0}", prog.PiramidePoligonal(_numLados, _ladoA, _ladoB, _ladoC, _alturaCara, menuItem));
                        } else {
                            Console.WriteLine("Opción no válida.");
                        }
                        break;
                    default:
                        if (!menuItem.Equals(eOpciones.Salir))
                            Console.WriteLine("Opción no válida.");
                        break;
                }
                Console.ReadLine();
            }

Ahora procedemos a ejecutar nuestra aplicación y veremos que funciona completamente. Con esto terminamos nuestro primer proyecto. En siguientes entregas planearemos un nuevo proyecto y lo desarrollaremos, será una aplicación de escritorio con Formularios Windows.

Agradezco los comentarios que puedan hacerme, así como el que se suscriban para recibir noticias y, si consideran útil, compartir mi blog.

Comentarios

Entradas populares