elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Curso de javascript por TickTack


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  Java
| | | |-+  Quitar IF
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Quitar IF  (Leído 4,092 veces)
n-utz

Desconectado Desconectado

Mensajes: 165

Babylon es el vampiro!


Ver Perfil
Quitar IF
« en: 24 Febrero 2018, 15:19 pm »

Holas buenas,

Estoy intentando empezar a seguir la filosofía "real devs don't use if's", y me encuentro con códigos en los que no se como quitar el condicional, por eso les traigo uno, a ver si me tiran ideas y me abren un poco más la cabeza:

Código:
public static GregorianCalendar traerFecha (int año, int mes, int dia) {
GregorianCalendar fecha = null;

if (esFechaValida(año, mes, dia))
fecha = new GregorianCalendar(año, mes - 1, dia);

return fecha;
}

Creo que el codigo se entiende bastante bien, tiene nombres predictivos. Se le pasa un año, mes y dia, y te devuelve un GregorianCalendar con la fecha, pero solo si los parametros pasados son correctos (mes del 1 al 12, dia correcto dentro de ese mes, se contempla año bisiesto). Al mes le resto uno porque GregorianCalendar tiene los meses desfazados hacia abajo, el 0 es Enero.

Y les dejo otro de plus, que es justamente el que consume al que llama el código de arriba.

Código:
public static boolean esFechaValida (int año, int mes, int dia) {
int[] meses = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
boolean response = false;

if (esBisiesto(año))
meses[1] = 29;

if (mes >= 1 && mes <= 12)
response = meses[mes - 1] >= dia;

return response;
}

Si pueden tirarme ideas sobre como podria quitar los condicionales buenisimos, también agradecido si me recomiendan lecturas. Estoy yendo de a poco, para mi los casos en donde se pueden aplicar polimorfismo son más fáciles.


En línea

srWhiteSkull


Desconectado Desconectado

Mensajes: 444



Ver Perfil WWW
Re: Quitar IF
« Respuesta #1 en: 25 Febrero 2018, 12:22 pm »

sinceramente es una filosofía absurda, no se donde o quien te ha recomendado eso

como es java podrías prescindir de la función esFechaValida() y simplemente usar un try/catch para GregorianCalendar

otra forma es que la vista o en la entrada que tome el dia,  mes y año restrinja los valores fuera de rango

si te refieres a las operaciones ternarias estos son if


« Última modificación: 25 Febrero 2018, 19:58 pm por srWhiteSkull » En línea

n-utz

Desconectado Desconectado

Mensajes: 165

Babylon es el vampiro!


Ver Perfil
Re: Quitar IF
« Respuesta #2 en: 25 Febrero 2018, 18:10 pm »

Los puristas de OO como los smalltalkers sostienen que se puede programar sin usar un solo condicional, solo objetos enviando mensajes a otros objetos.

Obviamente es un extremo, no busco hacer todo el código fuente sin poner condicionales, pero mientras más evites, mejor. Hay libros que hablan de esto como Clean Code, y plugins de coverages que te calculan la diversidad de flujos debido a condicionales que tiene tu programa. Igualmente, para gustos...

Es un trabajo práctico para la facultad, no hay vista, es solo consola. Y el try-catch para Gregorian como sería? Acabo de crear un objeto con fecha el 30 de Febrero del 2017 y me dejo sin problemas.

Gracias por la respuesta!
En línea

srWhiteSkull


Desconectado Desconectado

Mensajes: 444



Ver Perfil WWW
Re: Quitar IF
« Respuesta #3 en: 25 Febrero 2018, 19:45 pm »

Código
  1.  
  2. ...
  3. try {
  4.   fecha = new GregorianCalendar(año, mes - 1, dia);
  5.  
  6. } catch(Exception e) {
  7.   // codigo para tratar la excepción (opcional)
  8. }
  9. ...
  10.  


Las condiciones siempre estarán presentes pues son la forma menos costosa de reconducir el flujo del programa y muy útiles en la validación de datos. Las excepciones en teoría son para que en el caso de que hubieses previsto todos los escenarios, validando, pudieras resolverlo de una forma elegante ante un imprevisto con un mensajito o similar sin que el programa se interrumpiera. Luego una vez se depura y se resuelve el problema y a sabiendas de que ya no puede repetirse prescindir de esta o mantenerla si se tratara de una parte critica del programa.

El abuso de condiciones tiene por supuesto repercusión en el rendimiento por ello el diseño de un programa debe ser inteligente y previsorio. Normalmente si improvisamos en los desarrollos, lo normal, esto no es importante porque una vez finalizamos podemos pasar a optimizarlo.

https://docs.oracle.com/javase/tutorial/essential/exceptions/handling.html
« Última modificación: 25 Febrero 2018, 19:59 pm por srWhiteSkull » En línea

engel lex
Moderador Global
***
Desconectado Desconectado

Mensajes: 15.514



Ver Perfil
Re: Quitar IF
« Respuesta #4 en: 25 Febrero 2018, 23:49 pm »

no conseguí nada sobre esta "filosofía" (llamemoslo creencia, ya que una folosofia es "conjunto sistemático de los razonamientos expuestos por un pensador" y esto no creo que sea de un "pensador)

if es uno de los elementos más optimizados de la informática, cualquier otra via de toma de decisiones (literalmente 1 ciclo de procesador)

try/catch a pesar de ser "poco costoso" si tiene un esfuerzo porque obliga en runtime a hacer un "mini ambiente virtual" donde las cosas pasen "sin consecuencias" para en caso que falle, no afectar el resto del codigo (por lo menos cambiar valor de variables), si fue exitoso, este ambiente debe cerrarse...

hacerlo por metodos esotericos u objetos usualmente solo empeora el rendimiento y legibilidad, como digo "no ayuda a nadie"...



En línea

El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.
Eleкtro
Ex-Staff
*
Conectado Conectado

Mensajes: 9.788



Ver Perfil
Re: Quitar IF
« Respuesta #5 en: 26 Febrero 2018, 00:08 am »

Y el try-catch para Gregorian como sería?

Si tienes pensado reemplazar condicionales por bloques try/catch con la idea de que así lograrás micro-optimizar el rendimiento... vas muy equivocado, haciendo eso conseguirás precisamente todo lo contrario que si usases un If. En las mismas condiciones, el tiempo total de ejecución de un try/catch es mayor que el de un If, sobre todo si en lugar de controlar una excepción específica lo que controlas es la clase base para todos los tipos de excepciones (clase Exception en Java) debe tomarse aun más tiempo para evaluar. Y en la misma cantidad, el abuso de bloques try/catch es más perjudicial para el rendimiento que el abuso de (anidación o no de) condicionales.

Aparte de que le estarias dando un uso inapropiado, ya que un bloque try/catch sirve para controlar cosas que escapan de tu control dentro del flujo normal de tu programa, y no es el caso.

Igualmente, para gustos...

Esa "filosofía" es de lo más absurdo, y esto no es cuestión de gustos, sino de hechos. No creo que se pueda añadir mucho más a lo que ya te ha explicado todo el mundo, deberías hacer caso a lo que te están advirtiendo y aconsejando los demás compañeros, por que ellos no dicen habladurías, en cambio esa filosofía si, y si te acostumbras a esas habladurías pues estarás siguiendo un mal camino en el ámbito de la programación.

Saludos!
« Última modificación: 26 Febrero 2018, 00:26 am por Eleкtro » En línea

engel lex
Moderador Global
***
Desconectado Desconectado

Mensajes: 15.514



Ver Perfil
Re: Quitar IF
« Respuesta #6 en: 26 Febrero 2018, 02:38 am »

Citar
En las mismas condiciones, el tiempo total de ejecución de un try/catch es mayor que el de un If, sobre todo si en lugar de controlar una excepción específica lo que controlas es la clase base para todos los tipos de excepciones (clase Exception en Java) debe tomarse aun más tiempo para evaluar.

sumemos a esto... tu programas sin if, pero entonces tendrás que rehacer el lenguaje desde 0, ya que de nada vale si tu programas sin if en una librería hecha con ifs XD es como decir "se debe programar en java completamente en español"
En línea

El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.
Orubatosu


Desconectado Desconectado

Mensajes: 2.515


Ver Perfil WWW
Re: Quitar IF
« Respuesta #7 en: 26 Febrero 2018, 14:10 pm »

Solo le veo sentido a esta "filosofía" para buscar opciones alternativas en escenarios donde hay una gran cantidad de toma de decisiones y el resultado es fijo para cada escenario.

En esos casos una alternativa es usar algo parecido a una tabla de verdad, una matriz donde cada "if" corresponda a un numero y obtener el resultado accediendo a la tabla

Por poner un ejemplo simple, imaginemos un "stick" digital con 9 posiciones, donde 0 es reposo y luego cada número corresponde a una dirección (cuadro direcciones y las diagonales). Implementar un cursor en ese escenario puede hacerse mediante nueve preguntas de tipo if-else, o puede resolverse con una matriz de 9 elementos por dos. (matriz bidimensional). El movimiento del cursor puede sacarse de sumar el valor almacenado en la matriz para cada caso.

Este sería un ejemplo sencillo donde se puede evitar el if, pero por lo demás no le veo sentido a insistir en no usar una herramienta legítima. Otro tema sería usar un "goto" que eso si que es aberrante en casi todos los casos.

La idea de la matriz puede ayudarte en muchos casos, pero no en todos
En línea

"When People called me freak, i close my eyes and laughed, because they are blinded to happiness"
Hideto Matsumoto 1964-1998
Serapis
Colaborador
***
Desconectado Desconectado

Mensajes: 3.348


Ver Perfil
Re: Quitar IF
« Respuesta #8 en: 4 Marzo 2018, 20:00 pm »

Si los 'if' fueran ineficaces ni siquiera formarían parte de la lógica... pero es que la lógica se basa exclusivamernte en los condicinales... a nivel 'atómico', son puertas AND, OR y XOR... lo que al final configuran los 'if'... cuando hacemos un if, estamos haciendo una comparación que a nivel de diseño, es una resta, y cuyo resultado arroja uno de 3 valores <0, 0 ó >0. Como resultado uno o más bits del registro de estado del procesador (en los x86), se activa y luego es cuando el programador puede 'test'ear el resultado.

Gran parte de la lógica digital descansa precisamente en esto... y en los saltos (al caso condicionados por el resultado de la comparación).

....

Esto no quiere decir que lo que te han señalado sobre el uso y abuso de 'IF', como que es mala programación no sea correcto, siempre que se entienda sin ambigüedad a que se quiere referir..., y parta ello te expongo claramente el ejemplo de 'no usar + ifs' de los necesarios...

Por ejemplo, en el caso de calcular fechas... dado que es complejo, verificar en concreto si un día, de un mes, de un año cae por ejemplo es tal o cual día ó si es válido (existe dicho día para dicho mes), exige usando IFs, muchas comprobaciones... entonces al caso es que es preferible resolverlo de forma más arítmetica que lógica...

En otras ocasones es haciendo uso de las operaciones lógicas más elementales: AND, OR, XOR qwue al fin y al cabo, bien entendidos son otra forma de condicionales.

Lo que se hace en general es calcular, y al final basta uno solo o dos condiconales.

Una foma sencilla de usar 'If's y no sobrecargar con cada llamada es entender que todos los meses tienen un nínimo de 28 días, luego no es preciso hacer un cácluclo total y abusivo con cada fecha que se llame...

Por claridad creamos una estructura que comprenda los datos precisos.
Código:
Estructura Fecha
    byte día
    byte mes
    entero año
fin estructura

También por claridad, no se consideran (en la función) los casos en que mes, día o año estén fuera de rango...
    Si ((f.año > x) y (f.año < y)) //x,y representan un límite impuesto para el año....
    Si (f.mes > 0) y (f.Mes < 12)  // mes va en el rango 1-12, descartar cualquier otra posibilidad (aunque podría ir en el rango 0-11).
    Si (f.dia > 0) y (f.dia < 32)  // se supone que día está en el rango 1-31

Código:
buleano = Funcion ValidarFecha(fecha f)
  Si (f.dia <= 28)
     devolver TRUE
  Sino
    devolver ValidarFechaAFondo(f)
  Fin si
Fin funcion

Aquí es cuando nos meteríamos en verificar si el día es 29, 30 ó 31 en base al mes y en caso de ser febrero el mes, en si es bisiesto.
Código:
buleano = Funcion ValidarFechaAFondo(fecha f)
    byte mes = f.mes

    Si (mes = 2) // febrero
        Si (f.Dia <30)
            Si AñoEsbisiesto(f.año)
                devolver TRUE
            fin si
         fin si
    Sino
        // el 'ó', es también un condicional... así esta línea tiene 4 condicionales.
        Si (mes = 4) ó (mes = 6) ó (mes = 9) ó (mes = 11)
            Si (f.dia < 31)
                devolver TRUE
            Fin si
        Sino  //enero, marzo, mayo, julio, agosto, octubre y diciembre tienen 31 días.
            devolver TRUE  
        Fin si
    Fin si
    
    devolver FALSE  
Fin Funcion

Por ejemplo: si queremos hacer algo basado en si un mes tiene 30, 31, 28, ó 29 días... sería relativamente sencillo, crear un array... que aunque largo, contuviera ya la solución, así se ahorrarían muchísimos 'IF's, y solo sería preciso una comprobación posterior para el caso de febrero cuando se señale el día 29 y no para 30 y 31

Nota ahora como el siguiente código ahorra mucho código a cambio de ocupar más memoria, con un array...
Código:
  //                                          mes , día
   Array de bytes DiaMesValido(0 a 12, 0 a 2) // el mes 0, no se usa...

Funcion RellenarArrayValido
   // Enero
   DiaMesValido(1,0) = 1   // día 29
   DiaMesValido(1,1) = 1   // día 30
   DiaMesValido(1,2) = 1   // día 31
   // Marzo
   DiaMesValido(3,0) = 1   // día 29
   DiaMesValido(3,1) = 1   // día 30
   DiaMesValido(3,2) = 1   // día 31
   // Mayo
   DiaMesValido(5,0) = 1   // día 29
   DiaMesValido(5,1) = 1   // día 30
   DiaMesValido(5,2) = 1   // día 31
   // Julio
   DiaMesValido(7,0) = 1   // día 29
   DiaMesValido(7,1) = 1   // día 30
   DiaMesValido(7,2) = 1   // día 31
   // Agosto
   DiaMesValido(8,0) = 1   // día 29
   DiaMesValido(8,1) = 1   // día 30
   DiaMesValido(8,2) = 1   // día 31
   // Octubre
   DiaMesValido(10,0) = 1   // día 29
   DiaMesValido(10,1) = 1   // día 30
   DiaMesValido(10,2) = 1   // día 31
   // Diciembre
   DiaMesValido(12,0) = 1   // día 29
   DiaMesValido(12,1) = 1   // día 30
   DiaMesValido(12,2) = 1   // día 31

   // Mes de 29 días: Calcular bisiesto
   // Febrero
   DiaMesValido(2,0) = 255   // día 29
   DiaMesValido(2,1) = 0      // día 30
   DiaMesValido(2,2) = 0      // día 31

   / Meses de 30 días: Abril, Junio, Septiembre y Noviembre
   // Abril
   DiaMesValido(4,0) = 1   // día 29
   DiaMesValido(4,1) = 1   // día 30
   DiaMesValido(4,2) = 0   // día 31
   // Junio
   DiaMesValido(6,0) = 1   // día 29
   DiaMesValido(6,1) = 1   // día 30
   DiaMesValido(6,2) = 0   // día 31
   // Septiembre
   DiaMesValido(9,0) = 1   // día 29
   DiaMesValido(9,1) = 1   // día 30
   DiaMesValido(9,2) = 0   // día 31
   // Noviembre
   DiaMesValido(11,0) = 1   // día 29
   DiaMesValido(11,1) = 1   // día 30
   DiaMesValido(11,2) = 0   // día 31
Fin funcion

// Al inicializar el componente se crea el array (estático) una única vez.
funcion Inicializar
   llamada a la funcion RellenarArrayValido
fin funcion

La función de validación (es la misma que la previa):
Código:
buleano = Funcion ValidarFecha(fecha f)
  Si (f.dia <= 28)
     devolver TRUE
  Sino
    devolver ValidarFechaAFondo(f)
  Fin si
Fin funcion

Y finalmente la función de validación 'a fondo' ahora queda así:
Código:
buleano = Funcion ValidarFechaAFondo(fecha f)
    byte resultado

    resultado = DiaMesValido(f.mes, f.dia - 29)  
    Si (resultado = 1)
        devolver TRUE
    Si (resultado = 255)  // caso de febrero, día 29...
        Si AñoEsbisiesto(f.año)
            devolver TRUE        
        Fin si
    Fin si

    devolver FALSE
fin funcion

Incluso si comparas la primera función (que yo expongo) con tú código, ésta es mucho más óptima, sigue sin necesitar entrar en consideraciones extras si el día es inferior a 29, ya que todos los meses tienen esos días... pero en la 2ª función que expongo...

Como se puede ver, se ha limitado mucho la cantidad de los 'If's usados. Hay otras opciones igualmente aceptables, pero la idea simplemente es la demostrar que el número de condicionales puede ser limitado de diferentes maneras, en el ejemplo mediante el uso de un array pre-configurado con las soluciones...
Ante una miríada de llamadas, se puede ver que solo se va a calcular si el año es bisiesto, tan solo cuando el mes introducido es febrero y el día 29 (tampoco si se indica día 30, ni 31 para febrero), y no con cada fecha que se recibe....

La función AñoEsBisiesto... queda a tu esfuerzo, baste saber que cada 4 años es bisiesto, y que los acabados en 00, no lo son, pero cada 400 años, el que acabe enn 00 si lo es, etc... posiblemente en wikipedia esté bien explicado, si lo precisas...

Otros casos para evitar IFs conllevan usar aritmética, o solucionando casos con AND, OR y XOR (pueden testear varios bits a la vez, en vez de verificar cada caso con un 'if suelto').
« Última modificación: 4 Marzo 2018, 20:03 pm por NEBIRE » En línea

Serapis
Colaborador
***
Desconectado Desconectado

Mensajes: 3.348


Ver Perfil
Re: Quitar IF
« Respuesta #9 en: 4 Marzo 2018, 20:13 pm »

Otro tema sería usar un "goto" que eso si que es aberrante en casi todos los casos.
Es la misma tontería... un goto, es un Jump a nivel ensamblador... es inaceptable evadir su uso.

Lo que hacen los lenguajes de alto nivel es darle estructura a los saltos y delimitar el punto al que salta... por ejemplo para un bucle, simplemente se le permite 'salir del bucle', no saltar a cualquier otro punto si se usa, solo salta fuera dle bucle.
Código:
Bucle para k desde x hasta y
   ...
   Si (k es múltiplo de 7)
        Salir del bucle // es un jump, un goto...
   fin si
Fin bucle

Los goto, fueron condenados, no por el goto en sí, que son imprescindibles, si no porque lo hacían en la misma manera que se usan en ensamblador... un salto incondicional a una dirección específica sin que quede claro, el flujo, algo legítimo en ensamblador, queda sin embargo anodino en un lenguaje de alto nivel... especialmente cuando el programador no tiene/tenía la base suficiente, fabricando código altamente espagueti... (enredado).
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Quitar la ip
Sugerencias y dudas sobre el Foro
65jolu 8 3,972 Último mensaje 4 Noviembre 2008, 00:35 am
por :ohk<any>
¿Como quitar contraseña de bios? Quitar seguridad BIOS.
Seguridad
santiagoogle 2 8,995 Último mensaje 16 Febrero 2011, 16:00 pm
por santiagoogle
quitar DRM
Multimedia
SANSARA 4 4,431 Último mensaje 7 Junio 2012, 20:30 pm
por SANSARA
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines