Esta es una historia sobre el código fuente de Doom 3 y de lo hermoso que es. Sí, hermoso. Permitidme que me explique: después de lanzar mi videojuego —Dyad— me tomé un pequeño descanso. Al mes o así de holgazanear, pensé en extraer las partes del motor gráfico de mi juego para un nuevo proyecto pero, como el código fuente era un lío espantoso, me puse a buscar proyectos donde orientarme en la organización de dicho código. Fue cuando encontré un artículo sobre el código fuente de Doom 3, así que me puse a revisarlo.
|
etiquetas: belleza , código fuente , doom 3 , john carmack
if ( x ) {
} else {
}
y no así
if ( x )
{
}
else
{
}
JODEROS! LO SABÍA, ME DECIAIS QUE PROGRAMABA COMO UN RETRASADO MENTAL, JODEROS TODOS!!! ya tengo el aval de idSoftware.
Si, lo siento si me he excedido pero llevo alrededor de 6 años programando y no dejan de decirme que el estilo de mis condicionales es estúpido. Lo he pasado muy mal en mi vida como programador...
He estado revisando y hasta la estructura de la solución es buena.
Y no me refiero a que tengan gustos diferentes a mi. Me refiero que hacen artículos que no tienen ni pies ni cabeza.
La terrorífica y oscura atmósfera que lo rodeaba todo causó sensación en su época. Y su I.A. también causó sensación.
Saben de algún juego que utilice el motor del doom 3 (IDtech4 ) que este para jugar en linux ??
68 if (waitingOnKey) { // Sin espacios tras los paréntesis
108 if ( waitingOnKey ) { // Hay espacios tras los paréntesis
Y ese error se repite bastante. Además he visto sitios donde utilizan tabulaciones y sitios donde utilizan espacios, con lo que descuadra.
En definitiva: todo es mejorable
¿Soy un hereje sin educación en formateo de código? ¿O alguien practico?
astyle.sourceforge.net/
Seguiré echando un vistazo al artículo, pero parece que para él, un código "bello" es un código bien formateado. El formato del código es importante, está claro, pero la belleza de un código fuente está en el diseño.
Y me ha parecido ver lo que es básicamente un "getter". Si pones un getter estás exponiendo los datos de tu clase, y cargándote la encapsulación, que es uno de los fundamentos de la programación orientada a objetos. Algunos (la mayoría) piensan que por poner un campo privado y un getter público están cumpliendo con la encapsulación...
Yo prefiero hacerlo a mano. Pero sea a mano o sea con una herramienta, creo que es importante la coherencia de formato. Facilita bastante la legibilidad.
if ( x ) {
} else {
}
y no así
if ( x )
{
}
else
{
}
JODEROS! LO SABÍA, ME DECIAIS QUE PROGRAMABA COMO UN RETRASADO MENTAL, JODEROS TODOS!!! ya tengo el aval de idSoftware.
Si, lo siento si me he excedido pero llevo alrededor de 6 años programando y no dejan de decirme que el estilo de mis condicionales es estúpido. Lo he pasado muy mal en mi vida como programador...
#25 Eso lo tengo visto por costumbres del lenguaje más que por otra cosa, yo también soy partidario de las llaves en la misma linea, eso sí, para los sibaritas eres un hereje
Normalmente cada lenguaje de programación tiene unos estándares explícitos o por convención.
Y siento decirte que un if-else es casi siempre un síntoma de mal diseño y casi siempre hay una solución mejor.
#27 Es muy dificil que crees un portal web o proyecto entero y no metas un else. Búscame un proyecto de más de 100,000 lineas donde no veas un else para condicionales muy triviales. I DARE YOU!
#26 No se pueden mezclar tabulaciones con espacios, es horrible. Además, yo uso tabulaciones de 4 espacios. Y en Python si metes menos o más de 4 ni siquiera funciona
#30 Tres????... secundo a #32
#31 Evidentemente, uso de tabulador: Golpe de Remo, los hombres de verdad usan espacios para tabular.
Por otra parte, el 90% de los proyectos de 100.000 líneas o más se podrían escribir en una cuarta parte de líneas. El diseño del 90% de proyectos es malo, que otros lo hagan mal no es excusa.
#36 digo yo que dependerá de la complejidad de un proyecto, ¿no?. Obviamente todo código puede reducirse de tamaño. Pero eso es irte al comodín facil de la programación, y es que rara vez hay personas que gastan un 40% de su tiempo en optimizar su código
#25 Yo también pongo los condicionales como dices. Ahora bien, sí que suelo separar cosas o dejar líneas en blanco para mejorar la legibilidad. Por ejemplo, entre dos bloques if consecutivos dejo una línea en blanco. No creo que eso sea un problema ni que haga el código más "feo".
#25 A mí me gusta el condicional terciario de c++, por lo menos para una línea
No he podido dejar de leerlo hasta llegar a la última página....¡y no os podéis imaginar qué final tan sorprendente!!
Nadie nunca averiguará que el asesino es Jack el forastero (L.Luthiers dixit)
Yo hablo de diseño. Una aplicación bien diseñada y que siga a rajatabla los fundamentos de la POO (si hablamos de POO) tendrá menos líneas que una hecha "a lo loco".
#45 C++ es multiparadigma, puedes mezclar. Hacer un juego basado 100% en objetos es un error (por el rendimiento).
Espero que os duelan los ojos. Pero ESE fallo lo he visto muchas veces, y me da vomitera.
#37 Evidentemente, se da por hecho que se modifica el editor para cambiar las tabulaciones por espacios, que piensas que soy como esos del Frente Popular Judáico a los que hay que explicarle algo tan básico??
Fight!
#8 Dependerá de la dificultad del algoritmo que estés haciendo.
¿Y eso por qué? No conozco ningún lenguaje de programación que no tenga condicionales (¡incluso Haskell tiene!).
Si fueran malos ya los habrían quitado (como se ha hecho con los GOTOs o los bucles for estilo C/C++).
Si tienes una clase Préstamo, el campo con la cantidad no le interesa a ninguna otra clase. Si quieres hacer una operación con un Préstamo, todo lo que tenga que ver con la cantidad se debe realizar en la propia clase, porque es la clase que entiende de préstamos y la responsable de los mismos.
¿Que quieres aumentar un préstamo? Creas otra instancia de Préstamo con la cantidad a aumentar (que se la pasas en el constructor) y tienes en tu clase Préstamo un método aumentar_préstamo, que toma otro Préstamo, los suma y devuelve una nueva instancia de Préstamo.
Préstamo incial = Préstamo.new(10000)
Préstamo aumento = Préstamo.new(2000)
Préstamo final = inicial.aumentar_préstamo(aumento)
Voilà. En la variable final tendrás tu Préstamo de 12.000, valor al que nadie que no sea un Préstamo tiene acceso.
#55 Yo no lo uso. Pero no tiene por qué ser malo. Por ejemplo un goto end en una función puede simplificar las cosas.
Podría haberse traducido parte de esa belleza en el juego... porque vaya decepción después del DOOM 2, este es el peor de todos sin duda, una chusta que no aguanté jugando ni 3 días.
No me lo digas.
class Préstamo {
private double cantidad;
public Préstamo(double cantidad) {this.cantidad = cantidad;}
public double getCantidad(return this.cantidad);
public void setCantidad(double cantidad) {this.cantidad = cantidad;}
}
Préstamo préstamo = new Préstamo(10000);
préstamo.setCantidad(préstamo.getCantidad() + 2000);
¿Me equivoco?
Con respecto a esto:
"Si sólo la clase Préstamo debe conocer ese dato no debería ser accesible, pero yo puedo querer encapsular algo para tratarlo de una determinada forma, no para que no se pueda modificar."
No he entendido nada.
Me cabreaba mucho lo de las llaves abajo. En Coritel me obligaban a ponerlo así como norma de estilo interna... Una estupidez, vamos.
Pues los GOTO y los bucles for estilo for(inicialización, condición, incremento) no suelen existir en los lenguajes que no tienen a C como influencia directa.
por más que te hayan comido la cabeza, goto es una sentencia más y es perfectamente válida
Muchas gracias por enseñarme que hay mundo más allá del académico. Lo que tú deberías saber es que hay mundo más allá de C/C++.
Yo siempre escribo:
if (condition) {
code1;
} else {
code2;
}
¿Acaso es el único paradigma que permite diseñar bien?
#22 Es "posible" que lo hagan así para generar un código mas rápido, aun programando en C siempre tengo el ASM en mente.
El arquitecto no va a coger los ladrillos de la obra hecha (del mismo modo que los ladrillos que forman el Doom, forman el Doom y no otro juego) pero lo que si va a hacer, si ha realizado un detalle constructivo de la fachada donde están esos ladrillos y ha resultado ser eficiente, fácil de ejecutar, resuelve bien los encuentros, etc. es reutilizar esa solución, ese detalle constructivo (ese código fuente) o el modo que le llevó a hacer ese diseño, a otra obra.
Eso de que lso ladrillos forma el Doom y no otro juego es una verdad a medias. No son ladrillos, son mas bien herramientas, y con ellas, si juntas arte y gameplay tienes un juego.
Dios, no puedo creer que digas eso en público.
Por ejemplo, un tratamiento básico de un mensaje de respuesta:
if (messageResponse.hasError()) {
hazLoQueSeaConElError(messageResponse.getError());
else {
sigueLaEjecucion;
}
Para ese caso muchos lenguajes emplean try/catch
fabiensanglard.net/
Donde se analiza el código de los Quake I, II y III y los Doom I, II, III; así como otros juegos, como el código del Another World.
Creo que mi código es bastante limpio, mi secreto:
** Definir o seguir los/tus patrones de diseño que sean.
** Seguir estándares.
** Código autocomentado siempre que se pueda.
** Comentar siempre las funcionalidades correctamente, sin vaguerias o errores funcionales, ni siquiera con faltas de ortografía. Muy propias cuando se comenta código.
** Reducir métodos al mínimo.
** Correcto nombramiento de los métodos y variables.
** Repasar y rehacer tu código, creando nuevas clases, eliminando o reduciendo si es mejorable o colisiona con los patrones de diseño.
** Clases y métodos con visibilidad correcta.
** Siempre es posible(no dependencias de terceros etc) acabar tus funcionalidades del todo, jamás parcialmente, tratar de cerrarlas, eso ocurre cuando se pasan todos los test necesarios cubriendo toda casuistica y funcionalidades, se cumple con lo que dice el DT, si lo hubiere, se cumple con los estándares, patrones de diseño y las auditarías de código ya sean externas o definidas por tu equipo. Si no se corre el peligro del síndrome del 90% lo que ocurre cuando esta todo casi acabado pero no acaba nunca.
** Dedicar tiempo suficiente a los que menos saben, o los mas nuevos, enseñando y tratando de que corrijan sus errores, dejando que se peguen con el código pero sin dejarles solos. Repasar su código y mostrar errores. Solo así harán un código correcto.
** Asignar a cada miembro del equipo tareas que entren dentro de los margenes de sus capacidades, contratos o cualificaciones.
** Exigencias dentro de los margenes de lo humanamente posible y del horario laboral. Las prisas, al final casi siempre son contraproducentes. Bien porque se haga mal el trabajo o bien quemar al personal, lo que desemboca en discusiones, estreses y malos rollos. Obviamente, esto repercute en la calidad del código y esto ultimo al final desemboca en errores funcionales y problemas en mantenimientos o evolutivos.
** Coherencia en los tiempos de desarrollo, si como jefe tienes que decir que no puede estar a los de arriba, hay que decirlo, se explica, te comes el marron y ya está. Bajo mi experiencia mentir o comprometerse a cosas imposibles es también peor a la larga, obviamente repercute completamente en la calidad del código. También aplica a los programadores; esos que dicen "eso en día y medio lo tengo" y luego tardan 8 y la siguiente vez estiman lo mismo. Hay que entender que en los equipos siempre hay gente excesivamente positiva y gente excesivamente pesimista que se llevan las manos a la cabeza por cualquier cosa. Ni una cosa ni otra. Hay que tratar de hacer entender que el positivo tiene una responsabilidad con sus compromisos y que el pesimista no puede estar cargando al mundo con frases apocalípticas en plan "esto no va a salir nunca". En programación, realismo con margen para intangibles, siempre.
** Ser bastante exigente con todo lo anterior, contigo mismo y si mandas, con los demás.
Si reduces los libros de Clean Code 'solo' a esto, ya ganas muchísimo. Pero los que programamos ya sabemos que 'solo' esto, no se cumple casi nunca.
aun recuerdo lo de DiscountForCoupon y CouponForDiscount dos clases que median iguales con el mismo numero de métodos y los de mi equipo confundiéndose casi todo el rato
Por ejemplo, si hay que evaluar el riesgo del cliente, ¿cómo sumas la cantidad de dinero que tiene asignado en préstamos?
De hecho, ¿qué información expone esa clase Prestamo al exterior, es una clase autista de la que nadie depende para nada?