Archivo de la etiqueta: Visual Basic

interfaces


Cuando se trata de generalizar nuestro código, existe otra forma posible de hacer esto, que tiene algunas diferencias en cuanto a su implementación, pero además ciertos usos que nos permiten definir mecánicas, inclusive con actores esto es programadores, externos que usen otros desarrollos.

Es el caso de las interfaces. Por definirlo brevemente, un interfaz es ni más ni menos, un contrato que debemos cumplir nuestro código.

La diferencia fundamental entre un interfaz y una clase base, es que la interfaz en sí misma no contiene código de ejecución. Sencillamente lo que hace este definir cómo se verán los objetos desde fuera.

A diferencia de lo que sucede con una clase base, un objeto definido por nosotros, puede implementar varias interfaces distintas, mientras que sólo puede heredar de una clase base.

Esto ha llevado a muchas discusiones teóricas, dado que en varios entornos se pretenden heredades de múltiples clase base. Aun cuando esto podría ser útil en ciertos y determinados casos, desde mi punto de vista, esto hace que el mantenimiento de ese código resulte mucho más dificultoso.

Llegado el caso de pretenderse heredar de múltiples clases, lo que debiera hacerse es definir en cascada las herencias, de modo tal de poder implementar código del más básico hasta el más especializado, y no hacer que se hereden desde clases base distintas.

Así, en el ejemplo que estábamos utilizando, la clase Vegetal que hereda de la clase SerVivo, podría a su vez ser heredada, por una clase Árbol.

Esta podría definir nueva propiedades, como tipo de raíces, formato de la hoja, cantidad ramificaciones, etc. Y luego tendríamos otras clases que al heredar de Árbol, también estarían heredando en forma indirecta de Vegetal y también de SerVivo.

Uso de Interfaces

Una cosa distinta son las interfaces. Un interfaz es, en definitiva, una especificación de algo que se debe cumplir, esto es, que cada clase  que implementa dicha interfaz, obligatoriamente debe exponer todos y cada uno de los miembros que la interfaz define.

Es en ese sentido que decimos que la interfaz es un contrato. Al existir, una biblioteca de código que conozca la interfaz, podrá acceder a cualquiera de sus métodos, aún sin tener una referencia directa, de la biblioteca de clases que implementa dichos métodos.

Esto se suele utilizar, cuando no podemos tener conocimiento claro o relación directa, con el conjunto de código con el cual vamos a tratar.

Imaginemos que por ejemplo, estamos creando un proceso, que necesita utilizar datos obtenidos de distintos orígenes, y que no sabemos a ciencia cierta, ni cuáles serán, ni cómo serán implementados.

O mejor aún, que estamos creando un componente, que sea capaz de realizar ciertas tareas, y que luego otra programadores pueden utilizar, en futuras aplicaciones o implementaciones de los orígenes de datos.

Inclusive a futuro, otro programadores de otras empresas, podrían implementar sus propios orígenes de datos sin tener que referenciar todo nuestro código, bastando sencillamente que conocieran las interfaces correctas.

Así, las interfaces podrían definirse en una biblioteca, que podría entregarse a cualquier programador externo, para que haga sus propias implementaciones de orígenes de datos, que luego nuestro componente o aplicativo pudiese utilizar sin mayores inconvenientes.

Criterios de definición de un interfaz.

Estos son los criterios básicos para la definición de cualquier interfaz.

  • No contiene código ejecutable.
  • No se pueden definir alcances: todos los miembros declarados en un interfaz son en forma predeterminada, públicos.
  • Se pueden definir tanto propiedades como métodos; si la propiedad es de sólo lectura o sólo escritura quedará consignado en la declaración del interfaz, y luego las clase que implemente solo podrán exponer estos métodos.
  • En la declaración se podrán utilizar tipo de datos personalizados, como podrían ser enumeraciones, clases personalizadas, estructuras, etc. Sin embargo, en dicho caso será conveniente, que estos tipos de datos se encuentran declarados en la misma biblioteca de clases que las interfaces, para mantenerlas aisladas del resto de los componentes, y así poder distribuirlos sin mayores inconvenientes.

Ejemplo.

El siguiente ejemplo muestra cómo sería la interfaz IVida, que se correspondería con nuestra clase base de SerVivo, si quisiéramos definir sus miembros aisladamente de la clase base.

Por convención, se suele definir el nombre de una interfaz, comenzando con I mayúscula.

VB

Public Interface IVida
    Sub Nacer()
    Sub Crecer()
    Sub Reproducir()
    Sub Morir()
    Sub GenerarEnergía()
End Interface

CS

 

interface IVida
{
    void Nacer();
    void Crecer();
        
    void Reproducir();
    void Morir();
        
    void GenerarEnergía();
}

Implementando la interfaz

 

Una vez definida un interfaz, cualquier clase que quiera indicar que cumple este contrato, deberá implementar la interfaz.

Como suele suceder, diferentes lenguajes de programación, utilizan distintos mecanismos para indicar esto. Para Visual Basic existe una palabra reservada, implements, mientras que el C#, se define exactamente igual que una herencia esto es, indicando después del nombre de declaración de la clase, el caracter dos puntos (:) y el nombre de la interfaz o interfaces que se implementan,  separados por comas. En el caso que además de implementar interfaces, se quisiera heredar de otra clase, el César la clase de la cual se hereda debe estar inmediatamente luego del carácter dos puntos.

Así quedaría entonces, la clase vegetal heredando de SerVivo e implementando IVida.

VB

Public Class Vegetal
    Inherits SerVivo
    Implements IVida
    Private Sub Fotosíntesis() Implements IVida.GenerarEnergía
    End Sub
End Class

CS

public class Vegetal : SerVivo,IVida
{
   
    private void Fotosíntesis() 
    {
    }
    void IVida.GenerarEnergía()
    {
        Fotosíntesis();
    }

Deberíamos resaltar que, mientras en Visual Basic la implementación de cada miembro de la interfaz es declarativa, utilizando la palabra reservada “Implements”, en C# la implementación se hace por coincidencia de nombre. Es por eso que, en VB, el método FotoSíntesis puede implementar directamente el GenerarEnergía de la interfaz, mientras que en C# se necesitan ambos métodos, y hacer la llamada en cascada.

Finalmente, un método que Implementa una interfaz en Visual Basic, puede ser privado (y por tanto, solo visible desde la interfaz), mientras que, nativamente, en C# debe cumplir con el alcance.

Sin embargo, como se ve en el ejemplo, el método que implementará interfaz, puedas hacerlo implícitamente, utilizando sólo el nombre del método, o como en este caso, explícitamente antecediendo al nombre del método, el nombre de la interfaz seguido por un punto.

Al hacer la llamada en cascada, el método que realmente posee el código, en nuestro ejemplo FotoSíntesis, queda declarado  igualmente como privado, con lo cual estamos obteniendo el mismo resultado final.

Son sencillamente, diferentes formas de hacer la misma cosa.

En la siguiente publicación, comenzaremos a utilizar combinatoria as de estas características, en un conjunto de bibliotecas que nos permitan realizar finalmente, tareas útiles.

Hablemos de Herencia (2)


Ya hemos visto en Hablemos de Herencia, los conceptos básicos de este tema.

Analicemos entonces como queda el código de lo ya definido, y algunas variantes al respecto.

Ser vivo.

Por recordar, esta era su representación gráfica.

image

Y así quedaría el código:

VB

Public MustInherit Class SerVivo
    Public Sub Nacer()
    End Sub
    Public Sub Crecer()
    End Sub
    Public Sub Reproducir()
    End Sub
    Public Sub Morir()
    End Sub
    Public MustOverride Sub GenerarEnergía()
End Class

CS

public abstract class SerVivo
{
    public void Nacer()
    {
    }
    public void Crecer()
    {
    }
    public void Reproducir()
    {
    }
    public void Morir()
    {
    }
    public abstract void GenerarEnergía();
}

Como vemos, la clase se declara como que debe heredarse (MustInherit en VB, abstract en C#), y luego se definen los distintos métodos.

El método que debe codificarse en las clases derivadas, se declara como MustOverride (VB), abstract (C#).

Presta atención que, en C#, el mismo término significa cosas distintas, dependiendo del entorno. No es muy común, pero a veces pasa.

En ambos casos, los métodos que deben codificarse en los descendientes, no tienen cuerpo (No hay End Sub en VB, ni llaves en C#, donde termina con punto y coma).

Las clases derivadas.

image

VB

Public Class Vegetal
    Inherits SerVivo
    Public Overrides Sub GenerarEnergía()
        Fotosíntesis()
    End Sub
    Private Sub Fotosíntesis()
    End Sub
End Class

CS

public class Vegetal : SerVivo
{
    public override void GenerarEnergía()
    {
        Fotosíntesis();
    }
    private void Fotosíntesis()
    {
    }
}

Como vemos, ese método “no implementado” en la clase base, se debe terminar de definir en las clases derivadas (“sobre escribirse”).

En ambos lenguajes, la definición es casi idéntica.

En Visual Studio, al definir que una clase hereda de otra, el entorno te indica “como error” que deben escribirse esos métodos y hasta se ofrece a generarte el esquema base Sonrisa

Se indica que una clase hereda por distintos mecanismos, según el idioma.

En Visual Basic, se declara taxativamente que hereda “Inherits” de otra clase.

En C#, ese concepto se “entiende” porque luego de la declaración de la clase, se sigue con dos puntos, y el nombre de la clase que se hereda.

A partir de aquí, se podrá seguir heredando para cubrir, progresivamente, mayores especializaciones y características.

Lo interesante, es que cualquier modificación de una clase base, se reflejará (en realidad, se “heredará”), en cualquiera de sus derivadas.

Esto de la herencia, en definitiva, nos permite “comprometer” que nuestro código se vea siempre de la misma forma, en todas las clases derivadas/heredadas. Aún cuando una clase heredada presente más miembros, si la “vemos” como una clase base, siempre encontraremos los mismos métodos.

Una clase vegetal vista como ser vivo

Una clase animal vista como ser vivo

Pero hay otra forma de “comprometer” tu código para cumplir un convenio.

Eso es tema de la siguiente publicación.

Encapsular en tus clases


Cualquier conjunto de instrucciones que crees, deben estar necesariamente dentro de un miembro (member). Estos conjuntos de código deben estar contenidos en algún archivo que representa una unidad de código.

En Visual Basic, existen los módulos, que pueden cumplir esta función. (En realidad, esto se hereda de las primeras implementaciones del lenguaje, donde los miembros que se utilizaban como genéricos, podían estar en módulos globales).

Por herencia, esa funcionalidad sigue existiendo para el .Net Framework, pero C# no dispone de esa forma de contenedor. Para C# solo existen clases.

Esto no es ni malo, ni bueno.

Si se convierte un módulo de VB, a C#, basta con definir una clase como estática… y lo demás será igual (bueno, los miembros también deben declararse como estáticos).

Por otra parte, en el propio Visual Basic, también es posible declarar métodos estáticos.. pero no tiene la funcionalidad de clase estática.. para ello, ya tiene el módulo.

Considera que, una clase estática, podría ser como una biblioteca (y aclaro, es biblioteca NO “librería” Sonrisa ), de tus funciones personalizadas “de uso directo”. Por ejemplo, si haces muchos programas financieros, podrías tener métodos estáticos para cálculos de interés, de amortización etc.

Sin embargo, en muchas otras oportunidades, una clase podrá representar una entidad de tu problemática y en dicho caso, podrás considerarlas como plantillas para crear distintas ocurrencias de dichas entidades.

Pero, en definitiva, una clase es una plantilla (template), que contiene código relacionado. 

En ella, los miembros podrán ser de distinto tipo:

Propiedades

Representan los “atributos” de cada entidad (instancia). Por ejemplo, si quiero representar un color, podría definir una clase que exponga las propiedades Rojo, verde y azul.

Definirlas como propiedades, permite que se puede ejecutar código dentro de ellas. Así, cuando se le asigna un valor, establecer un cálculo, o validar que el valor esté dentro de un determinado rango.

O asignar un valor predeterminado cuando  otro código reclama el valor.

Estamos entonces definiendo que, en realidad una propiedad es una combinatoria de dos miembros: el de asignar el valor, y el de obtener el valor.

VB

        Private m_Rojo As Integer
        Public Property Rojo() As Integer
            Get
                Return m_Rojo
            End Get
            Set(ByVal value As Integer)
                m_Rojo = value
            End Set
        End Property

CS

        int m_Rojo = 0;
        public int Rojo
        {
            get
            {
                return m_Rojo;
            }
            set
            {
                m_Rojo = value;
            }
        }

 

Si embargo, se puede obviar una de las dos partes.

Dejar la propiedad como de solo lectura.

VB

        Private m_Rojo As Integer
        Public ReadOnly Property Rojo() As Integer
            Get
                Return m_Rojo
            End Get
        End Property

CS

        int m_Rojo = 0;
        public int Rojo
        {
            get
            {
                return m_Rojo;
            }
        }

 

Dejar la propiedad como de solo  escritura

VB

        Private m_Rojo As Integer
        Public WriteOnly Property Rojo() As Integer

            Set(ByVal value As Integer)
                m_Rojo = value
            End Set
        End Property

CS

        int m_Rojo = 0;
        public int Rojo
        {
            set
            {
                m_Rojo = value;
            }
        }

 

O definir la propiedad sin asignar código específico.

VB

Public Property Rojo As Integer

CS

        public int Rojo { get; set; }

Campos.

Son formas especiales de propiedades, que se basan en simplemente definir la variable, su tipo y su “exposición” (que nivel de otros objetos pueden utilizarlo).

Por lo demás, son variables dentro de la clase.

        Public Verde As Integer

        public int Verde;

Métodos.

Son conjuntos de código para ejecutar.

Podemos sub clasificarlos entre los que no retornan ningún valor (procedimientos), y los que si retornan un valor (funciones).

En C#, en realidad, todos retornan un valor (o sea, son funciones). Pero en el caso de no necesitar que retorne nada, se declara el tipo que se retorna como void.

 

        Sub HacerAlgo()

        End Sub
        Function RetornarAlgo() As Integer

        End Function

        public void HacerAlgo()
        {
        }
        public int RetornarAlgo()
        {
        }

Así mismo, un método admite que se le pasen argumentos:

        Sub HacerAlgo(argumento As String)

        End Sub

        public void HacerAlgo(string argumento)
        {
        }

Los argumentos pueden ser opcionales, en cuyo caso, se requiere que se le asigne un valor predeterminado. además, una vez que se declara un argumento como opcional, todos los que siguen deben serlo.

        Sub HacerAlgo(Optional argumento As String = "Valor")

        End Sub

        public void HacerAlgo(string argumento="Valor")
        {
        }

O declarar un conjunto de argumentos de los que no se conoce la cantidad. En este caso, se declara como vector, arreglo (Array), para que se asignen todos los que hagan falta.

        Sub HacerAlgo(ParamArray argumentos() As String)

        End Sub

        public void HacerAlgo(params string[] argumentos)
        {
        }

Dejamos para más adelante, definir otras cosas, como los eventos.

Pero con estos elementos, ya podremos empezar a crear cosas útiles.

Dando vueltas.. (Repitiendo :))


Sigamos con esto de la lógica. Imaginemos que tenemos que repetir una tarea determinada cantidad de veces (como las tablas de multiplicar).

Tomemos ese ejemplo. Digamos, la tabla del 15 (de las otras imagino, te sabrás varias de memoriaSonrisa ).

Si dibujamos el proceso (imaginando la tabla de los primeros 20 valores), sería algo así:

Diagrama Tabla de Multiplicar

En principio, esto podría codificarse “literalmente”:

 VB

    Private Sub Tabla()
        Dim Contador As Integer = 1
        Dim Resultado As Integer
Seguir:
        If Contador > 20 Then
            Exit Sub
        End If
        Resultado = Contador * 15
        Print(Resultado)
        Contador = Contador + 1
        GoTo Seguir
    End Sub

 

CS

        private void Tabla()
        {
            int Contador = 1;
            int Resultado = 0;
        Seguir:
            if (Contador > 20)
            {
                return;
            }
            Resultado = Contador * 15;
            Print(Resultado);
            Contador = Contador + 1;
            goto Seguir;
        }

Nota: la sentencia Print en C# no existe. ahora vemos como se hace esto en realidad para probar.

Mejor un bucle.

Los lenguajes de programación implementan formas sintácticas optimizadas para estas cosas; los bucles For.

 

 VB

    Private Sub Tabla()
        Dim Resultado As Integer
        For Contador As Integer = 1 To 20
            Resultado = Contador * 15
            Debug.WriteLine(Resultado)
        Next
    End Sub

CS

        private void Tabla()
        {
            int Resultado = 0;
            for (int Contador = 1; Contador <= 20; Contador++)
            {
                Resultado = Contador * 15;
                Debug.WriteLine(Resultado);
            }
        }

La sintaxis de for admite indicar además los “pasos” en los que se ejecutan las  repeticiones, pudiendo hacerse en pasos de más de una unidad (de a dos, de a tres, etc.), o inclusive, en reversa (Indicando el paso como un valor negativo y el valor de inicio mayor que el final)

        For Contador As Integer = 20 To 1 Step -1

            for (int Contador = 20; Contador >= 1; Contador -= 1)

Repitiendo sin contar.

A veces es necesario hacer tareas por  cada uno de los elementos de un conjunto. Por supuesto se podrían contar cuantos son y meterlos dentro de un for.  Pero existe una sintaxis específica para esto, que podríamos parafrasear como “por cada uno de estos cosos…”

VB

        For Each elemento In estalista

        Next

CS

            foreach (elemento in estalista)
            {
                
            }

Repitiendo (mientras haga falta).

Esta sería la otra forma posible de repetición. Mientras se cumpla una condición se debe realizar la tarea.

Esto se realiza con dos palabras reservadas (Do y Loop), donde una (y solo una) de ellas lleva adosada la condición con la expresión While  o la expresión  Until que determinan el “mientras” o el “hasta que”.

VB

       Do While condición

        Loop
        '
        Do Until condición

        Loop
        Do

        Loop While condición
        '
        Do

        Loop Until condición

CS

            while (condición)
            {
            }
            //
            while (!(condición))
            {
            }
            //
            do
            {
            } while (condición);
            //
            do
            {
            } while (!(condición));

Poner la condición en el inicio condiciona si la tarea se realiza o no, ANTES de comenzar.

En cambio,  si la condición está en la instrucción final, significará que al menos una vez se hará, antes de evaluar la condición.

Mejorando la toma de decisiones


Ya vimos como se puede “traducir” de un proceso lógico, a sentencias en los lenguajes más comunes.

Sin embargo, esto, muy lineal, puede mejorarse utilizando las ventajas de los lenguajes. De eso va la publicación de hoy. Distintas formas de establecer lógica.

Los operadores lógicos.

La primera opción de mejora que tenemos, es la de combinar decisiones lógicas entre si: Esto es si tengo que preguntarme, por ejemplo, el tema de los meses:

image

En la publicación anterior, utilizamos 4 sentencias “if”, una detrás de otra. ¡Y sus respectivas acciones!  1530413_690331531007178_1565415261_n

Sin embargo, podríamos encadenar las comparaciones, como diciendo: “si el mes es 4, o es 6, o es 9, o es 11…” y para eso sirven los operadores lógicos.

Esta tabla contiene los más comunes.

Operador VB C# Detalles
Y And & Si ambas condiciones se cumplen
Y también AndAlso && Si la primera se cumple se evalúa la segunda
O Or | Si una u otra
O sino OrElse || Si la primera se cumple, no se llega a evaluar la segunda
O Excluyente Xor ^ Solo una de las condiciones ha de ser verdadera
NO Not ! Negación de la condición

Entonces, la codificación del ejemplo de la publicación, quedaría:

VB

        If mes < 1 
            OrElse mes > 12 
            OrElse día < 1 
            OrElse día < 1 
            OrElse día > 31 
            Then
            EsVálida = False
            Return EsVálida
        End If

CS

            if (mes < 1 || 
                mes > 12 || 
                día < 1 || 
                día < 1 || 
                día > 31)
            {
                EsVálida = false;
                return EsVálida;
            }

Encadenado de condiciones

A veces, no es cuestión de juntar condiciones, sino de establecer acciones dependiendo de distintas condiciones.

Si pasa esto, entonces hago a, pero si no pero pasa esto otro, entonces hago esto otro. A eso, lo podríamos denominar, “decisiones en cascada”.

Si la condición es if, y la acción por el opuesto es else, pero a su vez debo preguntar otra cosa, debería poner uno dentro del otro (anidado). Por ejemplo:

        If condición1 Then
        Else
            If condición2 Then

            End If
        End If

Sin embargo, existen sentencias más precisas para esto:

VB

        If condición1 Then

        ElseIf condición2 Then

        End If

CS

            if (condición1)
            {

            }
            else if (condición2)
            {
            }

Selectores de valor

A veces, las decisiones pasan por coincidencias de una variable con ciertos valores y de acuerdo a ello, se toman distintas acciones (como con los meses de 30 días, por ejemplo).  Para ello existen los “selectores de valor”. En ellos, se permite agrupar sentencias por ciertos valores específicos (uno o más), y además, se da la opción de realizar acciones cuando ninguno coincide.

VB

        Select Case variable
            Case valor1
                acción1()
            Case valor2
                acción2()
            Case valor3
                accion3()
            Case Else
                accionExcluyente()
        End Select

CS

            switch (variable)
            {
                case valor1:
                    acción1();
                    break;
                case valor2:
                    acción2();
                    break;
                case valor3:
                    accion3();
                    break;
                default:
                    accionExcluyente();
                    break;
            }

Los selectores posibilitan además, que una misma acción se aplique a varios valores:

VB

        Select Case variable
            Case valor1, valor2
                acción2()
            Case valor3
                accion3()
            Case Else
                accionExcluyente()
        End Select

CS

            switch (variable)
            {
                case valor1:
                case valor2:
                    acción2();
                    break;
                case valor3:
                    accion3();
                    break;
                default:
                    accionExcluyente();
                    break;
            }

A veces, se puede hacer “trampa” con los selectores.  EL ejemplo de la validación de fecha es un buen caso: hay varios motivos distintos por los cuales una fecha puede ser inválida. Entonces, se puede codificar, dentro del Select, todas ellas. Pero … estamos comparando días y meses… son cosas distintas (“cerdos con velocidad al cuadrado”, decía mi padre Sonrisa ).  Pero funciona.

VB

        Dim EsVálida As Boolean = True
        ' Selecciona cualquier caso que resulte verdadero
        Select Case True
            Case día < 1, día > 31, mes < 1, mes > 12
                EsVálida = False
            Case mes = 4, EsVálida = 6, mes = 9, mes = 11
                EsVálida = día < 31
            Case mes = 2
                If año Mod 4 = 0 Then
                    EsVálida = día < 30
                Else
                    EsVálida = día < 29
                End If
        End Select

CS

¡No Funciona!  En C# no se admite…

Una Nota:  Cuando una condición hace que la salida sea un valor verdadero o falso, no es necesario “encerrarlo” en un if. Como en la sentencia EsVálida = día < 30.

También, si debes preguntar si una variable contiene verdadero o falso, no cometas el error de preguntar si la variable es igual a verdadero. Más pasos del procesador para obtener el mismo resultado.

O sea, las dos sentencias que siguen, son idénticas… pero la de abajo es un poquito más rápida (se notará con muchos usos, no con uno solo).

VB

        If condición = True Then

        End If
        If condición Then

        End If

CS

            if (condición == true)
            {
            }
            if (condición)
            {
            }

En la próxima,  hablaremos de bucles y repetidores.

Pero… ¿Que es un programa?


Acostumbrados estamos a usar programas de todo tipo.

Pero la pregunta del título no es tan fácil de responder.

Los programas, como es obvio, evolucionaron, pero si podemos decir que hay algo básico que sigue siendo cierto:

Un programa es una sucesión de acciones.

Antaño, cuando programar no era tan sencillo (ni barato Sonrisa ), era necesario tener bien claro cada paso. Un programa podían ser de cientos de líneas… o sea cientos de tarjetas perforadas… que si había un error, habría que re codificar. Tiempo, costo, etc.

Por eso, se diseñó una metodología para esquematizar el programa y hacer pruebas de su funcionalidad previas a cualquier codificación.

La diagramación lógica.

Se basa en esquematizar un proceso paso a paso. Hay diseños estándar para representar los distintos tipos de actividades.

image 

Los “terminadores” (Inicio y fin), establecen precisamente eso, los extremos del proceso.

Las acciones, como se ve en el diagrama, se representa por rectángulos.

Por supuesto, a estas alturas, nadie usa diagramación lógica para programar. 

Sin embargo, en este blog haré uso de ellos; de cuando en vez,  echaré mano a ellos, para contarte mejor de que va algo.

Ejemplo simple (y, de paso, sentencias de control de flujo).

Si bien ahora el .Net Framework es capaz de hacer matemática de fechas (en realidad, desde bastante antes, lenguajes como Visual Basic, o los dBase, ya lo tenían), hubo épocas en que las fechas se debían ingresar en campos separados (día, mes y año), y luego validarla adecuadamente. Insisto, no es una problemática actual pero sirve para equiparar diagramas y códigos.

Aunque parezca simple, se lleva varios pasos.

  • El mes no puede ser menor de uno.
  • El mes no puede ser mayor que doce.
  • El día no puede ser menor de uno
  • El día no puede ser mayor que 31
  • Si el mes es abril, junio, setiembre o noviembre, el día no debiera ser mayor que 30.
  • Si el mes es febrero, no debiera ser mayor que 28, excepto si el año es bisiesto, que no podrá ser mayor que 29.

image

Bueno, como se ve, los rombos simbolizan preguntas (en realidad, toma de decisión lógica). No existe un “estándar” para indicar las salidas, aunque suelen marcarse con “si y no”. En el diagrama, usé colores, que también sirve.

La sentencia de decisión lógica.

En definitiva, es una pregunta:

SI sucede esto ENTONCES hacemos esto.

VB

        If condición Then
            acción()
        End If

CS

            if (condición)
            {
                acción;
            }

En ocasiones, es cuestión de tomar acciones alternativas, dependiendo del valor lógico, como la decisión del año bisiesto:

image

VB

        If Bisiesto Then
            If Día > 29 Then
                acción()
            End If
        Else
            If Día > 28 Then
                acción()
            End If
        End If

CS

            if (Bisiesto)
            {
                if (Día>29)
                {
                 acción;           
                }
            }
            else
            {
                if (Día > 28)
                {
                    acción;
                }
            }

En conclusión, el diagrama completo (exceptuando que en realidad las variables no existen), sería

VB

        EsVálida = True
        If Mes < 1 Then
            EsVálida = False
            Return EsVálida
        End If
        If Mes > 12 Then
            EsVálida = False
            Return EsVálida
        End If
        If Día < 1 Then
            EsVálida = False
            Return EsVálida
        End If
        If Día < 1 Then
            EsVálida = False
            Return EsVálida
        End If
        If Día > 31 Then
            EsVálida = False
            Return EsVálida
        End If
        If Mes = 4 Then
            If Día > 30 Then
                EsVálida = False
                Return EsVálida
            End If
        End If
        If Mes = 6 Then
            If Día > 30 Then
                EsVálida = False
                Return EsVálida
            End If
        End If
        If Mes = 9 Then
            If Día > 30 Then
                EsVálida = False
                Return EsVálida
            End If
        End If
        If Mes = 11 Then
            If Día > 30 Then
                EsVálida = False
                Return EsVálida
            End If
        End If
        If Mes = 2 Then
            Bisiesto = (Año Mod 4 = 0)
            If Bisiesto Then
                If Día > 29 Then
                    EsVálida = False
                End If
            Else
                If Día > 28 Then
                    EsVálida = False
                End If
            End If
        End If
        Return EsVálida

CS

            EsVálida = true;
            if (Mes < 1)
            {
                EsVálida = false;
                return EsVálida;
            }
            if (Mes > 12)
            {
                EsVálida = false;
                return EsVálida;
            }
            if (Día < 1)
            {
                EsVálida = false;
                return EsVálida;
            }
            if (Día < 1)
            {
                EsVálida = false;
                return EsVálida;
            }
            if (Día > 31)
            {
                EsVálida = false;
                return EsVálida;
            }
            if (Mes == 4)
            {
                if (Día > 30)
                {
                    EsVálida = false;
                    return EsVálida;
                }
            }
            if (Mes == 6)
            {
                if (Día > 30)
                {
                    EsVálida = false;
                    return EsVálida;
                }
            }
            if (Mes == 9)
            {
                if (Día > 30)
                {
                    EsVálida = false;
                    return EsVálida;
                }
            }
            if (Mes == 11)
            {
                if (Día > 30)
                {
                    EsVálida = false;
                    return EsVálida;
                }
            }
            if (Mes == 2)
            {
                Bisiesto = (Año % 4 == 0);
                if (Bisiesto)
                {
                    if (Día > 29)
                    {
                        EsVálida = false;
                    }
                }
                else
                {
                    if (Día > 28)
                    {
                        EsVálida = false;
                    }
                }
            }
            return EsVálida;

NOTA: Este código dista de ser óptimo y NO debe usarse como ejemplo…. solo es útil para entender la lógica. Ya veremos otras versiones.

Hasta la próxima.