Desarrollo Implementación Codificación de Software

Anuncio
Desarrollo
Implementación
Codificación de Software
(... if (a == b) then ...)
Universidad de los Andes
Demián Gutierrez
Enero 2011
¿Por qué ser buen programador? (Codificador)
Pregunta:
¿Cuál es el riesgo menos tomado en consideración en la industria de
software?
Respuesta:
Los programadores incompetentes. Hay estimados que el número de
programadores requeridos en los EEUU excede los 200.000, esto es
un número enteramente engañoso, ya que no es un problema de
cantidad, es un problema de calidad. Un mal programador puede
fácilmente crear dos nuevos trabajos al año. Contratar más malos
programadores sólo incrementará nuestra aparente necesidad de
programadores. Si tuviéramos más buenos programadores y
pudiéramos identificarlos más fácilmente, seguramente necesitaríamos
en total menos programadores y no más.
David Parnas
Citado en Julio 21, 2009 de:
http://www.codinghorror.com/blog/2009/07/nobody-hates-software-more-than-software-developers.html
(traducción libre)
Después de 10 años de carrera, he descubierto que la
programación en el fondo, es lo menos importante... y sin
embargo, por ejemplo...
Kent Beck, en relación al XP, entre muchas otras cosas
geniales, dice que:
1) hay que abrazar (¿aceptar?) el cambio como algo que
forma parte integral del negocio de software (¿de nuestras
vidas?)
2) Hay que tener coraje (co!0n3$) para, entre muchas otras
cosas, poder hacer refactors, ajustar al vuelo la arquitectura
del software si es necesario, etc, etc...
y para ésto último... hay que ser buen programador...
¿Por qué ser buen programador? (Codificador)
En resumen: ¡Odio el software, odio el código! Y en especial el que
desarrollo yo mismo, sobre todo por que sé lo difícil que es lograr
que funcione y que funcione bien. Puede sonar extraño, pero es una
actitud natural e inclusive saludable para un desarrollador de
software. Es una característica común, una marca de iniciación que
usted encontrará que la gran mayoría de los programadores
comparten.
De hecho, creo que se puede diferenciar a un programador
competente de uno incompetente en una entrevista con la siguiente
pregunta: – ¿Cuál es el peor código que usted ha visto
recientemente? – Si la respuesta no es de inmediato y sin titubear la
siguiente: – El mío – Entonces usted debería terminar la entrevista
inmediatamente y decirle al candidato que lo siente, pero que aún no
odia al software lo suficiente, que quizá en unos años si lo sigue
intentando.
Jeff Atwood
Julio 21, 2009
http://www.codinghorror.com/blog/2009/07/nobody-hates-software-more-than-software-developers.html
(traducción libre)
¿Tipos de
Lenguajes de
Programación?
Use la herramienta más adecuada para el
problema a resolver...
Bajo Nivel / Alto Nivel
Ruby
C
Código de
Máquina
Python
Otros...
C++
Otros...
Ensamblador
Hardware
Perl
Mas Trabajo / Menos Trabajo (Programador)
Más Complejidad / Menos Complejidad
PHP
Cerca del hardware / Lejos del hardware
Java
Menor Abstracción / Mayor Abstracción
Lenguajes de Programación
Alto Nivel vs Bajo Nivel
Paradigma Imperativo vs Declarativo
Programación Imperativa:
En la programación imperativa se describe paso a paso
un conjunto de instrucciones que deben ejecutarse
para variar el estado del programa y hallar la solución,
es decir, un algoritmo en el que se describen los pasos
necesarios para solucionar el problema
Programación Declarativa:
En la programación declarativa las sentencias que se
utilizan lo que hacen es describir el problema que se
quiere solucionar, pero no las instrucciones necesarias
para solucionarlo
(El sueño de todo programador...)
Programación Imperativa o por Procedimientos
Los programas imperativos son un conjunto de instrucciones
(generalmente secuenciales) que le indican al computador cómo
realizar una tarea
La implementación de hardware de la mayoría de computadores
es imperativa; prácticamente todo el hardware de los
computadores está diseñado para ejecutar código de máquina,
que es nativo al computador, escrito en una forma imperativa
Ejemplo:
01.02.03.04.-
A = CalcularA()
B = CalcularB()
C = (A + B) / 2
Imprimir(C)
PHP
C/C++
Java
Pascal
Perl
etc...
Programación Funcional
Los programas escritos en un lenguaje funcional están
constituidos únicamente por definiciones de funciones
Se verifican ciertas propiedades como la transparencia
referencial (el significado de una expresión depende únicamente
del significado de sus subexpresiones), y por tanto, la carencia
total de efectos laterales
No existen asignaciones de variables ni construcciones
estructuradas como la secuencia o la iteración (lo que obliga en
la práctica a que todas las repeticiones de instrucciones se
lleven a cabo por medio de funciones recursivas)
Quicksort in Haskell
qsort [ ]
= [ ]
qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (>= x) xs)
Ejemplo tomado de: http://www.haskell.org/haskellwiki/Introduction
Programación Funcional
Quicksort in C
// To sort array a[] of size n: qsort(a,0,n-1)
void qsort(int a[], int lo, int hi) {
int h, l, p, t;
}
if (lo < hi) {
l = lo;
h = hi;
p = a[hi];
do {
while ((l < h) && (a[l] <= p))
l = l+1;
while ((h > l) && (a[h] >= p))
h = h-1;
if (l < h) {
t = a[l];
a[l] = a[h];
a[h] = t;
}
} while (l < h);
a[hi] = a[l];
a[l] = p;
qsort( a, lo, l-1 );
qsort( a, l+1, hi );
}
Los programas escritos
utilizando el paradigma
funcional son mucho más
concretos, concisos, y en
teoría mucho más fáciles de
comprender y desarrollar
Programación Funcional
Functional programs are often easier to understand. You should be able
to understand the program without any previous knowledge of either
Haskell or quicksort. The same certainly cannot be said of the C
program. It takes quite a while to understand, and even when you do
understand it, it is extremely easy to make a small slip and end up with
an incorrect program.
Quicksort in Haskell
qsort [ ]
= [ ]
qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (>= x) xs)
The first line reads: "When you sort an empty list ([]), the result is
another empty list". The second line reads: "To sort a list whose first
element is named x and the rest of which is named xs, sort the
elements of xs that are less than x, sort the elements of xs that are
greater than or equal to x, and concatenate (++) the results, with x
sandwiched in the middle."
Programación Funcional
Algunos tutoriales de haskell
http://www.haskell.org/haskellwiki/Tutorials
http://book.realworldhaskell.org/
http://learnyouahaskell.com/chapters
Otros lenguajes de programación funcionales
Haskell
Puros:
Hibridos:
Scala
(JavaVM)
Toman elementos del
paradigma funcional:
Miranda
LIsp
Scheme
Ocaml
Standar ML
ML
Erlang
Perl
Python
Ruby
etc...
Programación Lógica
Consiste en el uso de lógica matemática para programar
computadores
La mayoría de los lenguajes de programación lógica se basan en
la teoría lógica de primer orden
Se definen una serie de hechos y un conjunto de reglas que
relacionan o restringen estos hechos
Luego, es posible hacer consultas sobre los hechos y las reglas
definidas
Se suele utilizar en el desarrollo de sistemas expertos,
demostración automática de teoremas y reconocimiento de
lenguaje natural
Programación Lógica
las aves vuelan
los pingüinos no vuelan
<== regla
<== regla
"pichurri" es un ave
"sandokan" es un perro
"alegría" es un ave
<== hecho
<== hecho
<== hecho
una mascota vuela si es
un ave y no es un pingüino <== regla
¿"pichurri" vuela?
==> Si
¿qué mascotas vuelan?
==> pichurri, alegria
Programación Lógica
mother_child(trude, sally).
father_child(tom,
father_child(tom,
father_child(mike,
sibling(X, Y)
sally).
erica).
tom).
:- parent_child(Z, X), parent_child(Z, Y).
parent_child(X, Y) :- father_child(X, Y).
parent_child(X, Y) :- mother_child(X, Y).
?- sibling(sally, erica).
Yes
?- father_child(tom, Child)
Child = sally
Child = erica
Lenguajes de Programación
¿Programación Orientada a Objetos?
¿Programación Orientada a Objetos?
La Programación Orientada a Objetos (POO u OOP
según sus siglas en inglés) es un paradigma de
programación que usa objetos y sus interacciones
para diseñar aplicaciones y programas de
computadora. Está basado en varias técnicas,
incluyendo herencia, modularidad, polimorfismo y
encapsulamiento.
Su uso se popularizó a principios de la década de
1990. Actualmente son muchos los lenguajes de
programación que soportan la orientación a objetos
¿Críticas a la Programación Orientada a Objetos?
Esté abierto a nuevos paradigmas de
programación...
No se vuelva fanático de una herramienta o
de un paradigma en particular, pero...
Algunas herramientas ofrecen ciertas
ventajas sobre otras dependiendo del
problema a atacar
(y si no me cree, trate de atornillar un tornillo
con un martillo)
algunos modelos
de compilación y
ejecución
...entienda como funciona la herramienta
que usa...
Lenguajes de Programación
¿Modelo de Ejecución?
Programa
(Código
Fuente)
Hace el análisis léxico,
semántico del código
fuente y lo va
ejecutando a medida
que lo va leyendo
Interprete
Hardware
(CPU, Memoria,
etc.)
Lenguajes de Programación
Modelo de Ejecución
Programa
(Código
Fuente)
Esto se ejecuta
directamente sobre el
computador (sobre el
hardware)
Compilador
El compilador traduce el
programa desde el código
fuente (el lenguaje en el
que se escribe) al código
de máquina que es el
lenguaje que entiende el
hardware
Programa
(Código de
Máquina)
Hardware
(CPU, Memoria,
etc.)
Lenguajes de Programación
Modelo de Ejecución
Programa
(Código
Fuente)
Compilador
Programa
(Rep.
Intermedia)
El compilador traduce el
programa desde el código
fuente (el lenguaje en el que se
escribe) a una representación
intermedia (o código de
máquina virtual) que es el
lenguaje que entiende el
interprete o máquina virtual
El interprete corre sobre
un hardware real y ejecuta
(interpreta) la
representación intermedia
del programa (lo que lo
hace más rápido que si
fuera completamente
interpretado
Interprete
(Máquina
Virtual)
Hardware
(CPU,
Memoria, etc.)
Lenguajes de Programación
Modelo de Ejecución
Programa
(Código Fuente
Lenguaje A)
Traductor
Luego el lenguaje B
puede seguir cualquiera
de los modelos de
ejecución presentados en
las láminas anteriores
Programa
(Código Fuente
Lenguaje B)
El traductor toma un
programa escrito en un
lenguaje A y lo transforma
a un lenguaje B
Interprete o
Compilador
(Cualquiera de las
estrategias
Anteriores)
De la importancia de tener buenas
herramientas (relacionado con IDEs también)
Excusas... para no trabajar (mientras se compila algo)
(O de porqué las herramientas y la compilación incremental
entre otras cosas son importantes)
Cortesía de: xkcd (Google it)
depuración
Si usted no sabe depurar...
...entonces no sabe programar
¿De donde vienen los términos “bug” o
“debug”?
El origen del término “bug” (y “debug”) en el mundo de la programación.
Esta es una foto de la anotación original en el cuaderno de mantenimiento del computador
Harvard Mark II (1947)
Fuente: http://en.wikipedia.org/wiki/Software_bug
Depuración
¿Cómo Depurar?
¿Cómo depurar?
¿Depurador? ¿Debugger?
¿Salida Estandar?
¿Logs?
¿Hacking?
¿Leer código fuente de terceros?
¿Lectura e interpretación de errores?
¿Excepciones?
¿Es un bug o un feature?
¿Bugtrackers?
etc...
documentación
del Código Fuente
"Any fool can write code that a computer can understand.
Good programmers write code that humans can understand."
Martin Fowler, Refactoring: Improving the Design of Existing Code
Código auto-documentado vs
documentación del código fuente
¿Qué comentar en el código fuente?
Escriba comentarios sólo para código que es difícil de
entender
Procure no escribir código que sea difícil de entender
Si encuentra que tiene que documentar en exceso cierto
pasaje de código, entonces es posible que exista una forma
de escribir mucho mejor y de forma más legible dicho
pasaje
No trate de optimizar antes de tiempo
(Generalmente lleva a código difícil de entender)
No trate de generalizar antes de tiempo
(Generalmente lleva a código difícil de entender)
¿Qué comentar en el código fuente?
Muchas veces es importante documentar el por qué el
código está haciendo algo sobre el “qué” o el “cómo”
está haciendo el código
El “qué” está haciendo el código debería resultar
evidente en el mismo código (Código auto
documentado), mientras que el “por qué” lo está
haciendo no siempre resulta evidente.
Procure documentar por medio de la estructura
(arquitectura / patrones / diseño) y las abstracciones
utilizadas en el software
¿Código auto-documentado?
Every comment in a program is like an apology to the
reader. "I'm sorry that my code is so opaque that you
can't understand it by looking at it". We just have to
accept that we are not perfect but strive to be perfect
and go right on apologizing when we need to.
In my own personal experience, there are very few
"normal" coding situations where you absolutely need
comments. Basically everything else is a matter of
structuring your system so that a coder can
comprehend the structures in use and the choices
which drove the system to use those particular
structures.
Tomado de: http://stackoverflow.com/questions/209015/self-documenting-code
Código documentado vs auto-documentado
float a, b, c; a=9.81; b=5; c= .5*a*(b^2);
const float gravitationalForce = 9.81;
float timeInSeconds = 5;
float displacement = (1 / 2) * gravitationalForce * (timeInSeconds ^ 2);
/* compute displacement with Newton's equation x = Vo*t + 1/2*a*t*t */
const float gravitationalForce = 9.81;
float timeInSeconds = 5;
float displacement = (1 / 2) * gravitationalForce * (timeInSeconds ^ 2);
const float a = 9.81; // gravitational force
float b = 5; // time in seconds
// multiply the time and gravity together to get displacement.
float c = (1/2)*a*(b^2)
/**
* Gets the value of id.
*
* @return the vaue of id.
*/
public int getId() {
return id;
}
/**
* Sets the value of id.
*
* @id the new vaue of id.
*/
public void setId(int id) {
this.id = id;
}
Evite el exceso de
comentarios o los
comentarios
innecesarios
Mejor...
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
Documentación... problemas del exceso...
Los inconvenientes de comentar más de lo necesario...
The Commentator
(Un chiste sobre el exceso de documentación)
Fuente: http://www.cenqua.com/commentator/
The Commentator
(Un chiste sobre el exceso de documentación)
Fuente: http://www.cenqua.com/commentator/
Estilos de
Codificación
Convenciones
¿Buen Código?
¡¡¡Escriba código claro!!!
El código ofuscado déjelo para proteger su
propiedad intelectual o para el
“International Obfuscated C Code Contest”
http://en.wikipedia.org/wiki/International_Obfuscated_C_Code_Contest
¿Buen Código?
#define _ -F<00||--F-OO--;
int F=00,OO=00;main(){F_OO();printf("%1.3f\n",4.*-F/OO/OO);}F_OO()
{
_-_-_-_
_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
¿Qué utilidad
_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_
podría tener
_-_-_-_-_-_-_-_
ofuscar código?
_-_-_-_
}
Calcula el valor de PI
(bueno... casi...)
¿Buen Código?
¡¡¡Evite el código espagueti!!!
Si le gusta la pasta disfrútela en la mesa,
no en la pantalla del computador...
¿Buen Código?
¡¡¡Mal
síntoma!!!
f1 : while (true) {
f2 : while (true) {
if (true) {
// do something here
for (int i = 0; i < 10; i++) {
if (true) {
// do a bit of other thing
break f2; // spaghetti???
}
// finish whatever you were doing
} // this bracket closes what???
// out of the loop (which one?)
} else {
while (true) {
// You don't have a clue, do you?
if (true) {
for (int j = 0; j < 10; j++)
// Damn it, which while is this breaking
break; // Spaghetti???
} else {
continue f1; // Spaghetti???
}
}
} // while (true)
} // while (true)
// resemblance with MS Win code is pure coincidence
while (true) {
// Ohhh no, we are doomed!!!
}
}
Niveles de indentación
¡¡¡Reduzca en lo posible
los niveles de indentación!!!
Si le gusta la pasta disfrútela en la mesa,
no en la pantalla del computador...
¿Buen Código?
if (true) {
if (true) {
if (true) {
if (true) {
if (true) {
// something
}
}
} else {
if (true) {
if (true) {
// something
}
}
}
} else {
// something
}
}
¡¡¡Mal
síntoma!!!
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
for (int k = 0; k < 10; k++) {
for (int l = 0; l < 10; l++) {
for (int m = 0; m < 10; m++) {
// something
}
}
}
}
for (int j = 0; j < 10; j++) {
for (int k = 0; k < 10; k++) {
for (int l = 0; l < 10; l++) {
for (int m = 0; m < 10; m++) {
// something
}
}
}
}
}
¡¡¡Mal
síntoma!!!
public DataObject getDtaByKey(DataObject getDO) {
if (getDO != null) {
DataObject curDO = dtaObjectByKey.get(createKey(getDO));
if (curDO != null && curDO != getDO) {
throw new IllegalArgumentException( //
"curDO != null && curDO != getDO : " + //
createKey(getDO));
}
}
}
return curDO;
return null;
public DataObject getDtaByKey(DataObject getDO) {
if (getDO == null) {
return null;
}
GTFO!
DataObject curDO = dtaObjectByKey.get(createKey(getDO));
if (curDO != null && curDO != getDO) {
throw new IllegalArgumentException( //
"curDO != null && curDO != getDO : " + //
createKey(getDO));
}
}
return curDO;
public DataObject getDtaByKey(DataObject getDO) {
if (getDO == null) {
return null;
}
GTFO!
DataObject curDO = dtaObjectByKey.get(createKey(getDO));
if (curDO != null && curDO != getDO) {
throw new IllegalArgumentException( //
"curDO != null && curDO != getDO : " + //
createKey(getDO));
}
}
return curDO;
Menos Indentación
protected void clientMouseReleased(MouseEvent evt) {
if (draggedPaintable == null) { // GTFO
return;
}
GTFO!
if (dx == 0 && dy == 0) { // GTFO
return;
}
MoveCommand moveCommand = new MoveCommand(draggedPaintable, dx, dy);
moveCommand.redoCommand();
undoList.add(moveCommand);
redoList.clear();
draggedBasePoint = null;
draggedPaintable = null;
dx = 0;
dy = 0;
}
repaint();
Menos Indentación
Niveles de indentación
¡¡¡Aprenda a manejar errores
(excepciones) de forma
adecuada!!!
No deje el manejo de errores / excepciones
para el final, se sorprendería lo complejo que
puede ser añadir un buen manejo de errores
a un código que no fue pensado para soportar
esa característica
// throws no exception, exceptions are handled inside the method
private void doSomeNastyThingThatMightCrash() {
try {
BufferedReader br = new BufferedReader(
new FileReader("somefile.txt"));
while (doIt) {
String somedata;
somedata = br.readLine();
System.err.println(somedata);
while (somedata != null) {
// etc...
}
}
}
} catch (Exception e) {
e.printStackTrace();
// ---------------// Handle Exception
// ---------------}
// does not handle exceptions, exceptions are handled by the caller
private void failsafeDoSomeNastyThingThatMightCrash() throws Exception {
BufferedReader br = new BufferedReader(new FileReader("somefile.txt"));
while (doIt) {
String somedata;
somedata = br.readLine();
System.err.println(somedata);
}
}
while (somedata != null) {
// etc...
}
// throws no exception, exceptions are handled inside the method
private void doSomeNastyThingThatMightCrash() {
try {
failsafeDoSomeNastyThingThatMightCrash();
} catch (Exception e) {
e.printStackTrace();
// ---------------// Handle Exception
// ---------------}
}
Más sobre manejo de excepciones:
http://java.sun.com/docs/books/tutorial/essential/exceptions/index.html
http://onjava.com/pub/a/onjava/2003/11/19/exceptions.html
http://tutorials.jenkov.com/java-exception-handling/index.html
Niveles de indentación
¡¡¡Elimine y tenga bajo
control los números y los
literales “mágicos”!!!
Creame... aún no encuentro nada mágico
(en el sentido literal) en la programación.
Mucha lógica y nada de magia.
public class Main extends JFrame {
public Main() {
setLayout(new BorderLayout());
}
}
Client client = new Client();
add(client, "Center");
add(initTopPanel(), "North");
setDefaultCloseOperation(3);
setSize(640, 480);
setVisible(true);
float timeInSeconds = 5;
float displacement = (1 / 2) * 9.81 * (timeInSeconds ^ 2);
¿Qué números o literales “mágicos” aprecia usted?
public class Main extends JFrame {
public static final int WIDTH = 640;
public static final int HEIGHT = 480;
public Main() {
setLayout(new BorderLayout());
}
}
Client client = new Client();
add(client, BorderLayout.CENTER);
add(initTopPanel(), BorderLayout.NORTH);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(WIDTH, HEIGHT);
setVisible(true);
public staic final float GRAVITY = 9.81;
//... other class members, code, etc
float timeInSeconds = 5;
float displacement = (1 / 2) * GRAVITY * (timeInSeconds ^ 2);
Niveles de indentación
DRY:
Don't Repeat Yourself
¡NO! ¡No se Repita a Usted Mismo!
(Evite el Copy/Paste)
recuerde que hacer copy/paste NO es
reusar código
float result
// ...
float otherResult
// ...
float andAgain
// ...
float boring
= (1 / 2) * CONST_VAL *
(timeX ^ 2) / boom;
= (1 / 2) * CONST_VAL *
(timeY ^ 2) / blabla;
= (1 / 2) * CONST_VAL *
(dingdong ^ 2) / enough;
= (1 / 2) * CONST_VAL * (threelittle ^ 2) / pigs;
byte[] someArray;
for (int i = 0; i < someArray.length; i++) {
someArray[i] = someByteValue;
}
// ...
byte[] otherArray;
for (int i = 0; i < otherArray.length; i++) {
otherArray[i] = otherByteValue;
}
// ...
byte[] youGotTheIdeaArray;
for (int i = 0; i < youGotTheIdeaArray.length; i++) {
youGotTheIdeaArray[i] = youGotTheIdeaByteValue;
}
public float calcResult(float time, float oops) {
return (1 / 2) * CONST_VAL * (time ^ 2) / oops;
}
// ---------------------------------------float result
= calcResult(timeX,
boom);
// ...
float otherResult = calcResult(timeY,
blabla);
// ...
float andAgain
= calcResult(dingdong,
enough);
// ...
float boring
= calcResult(threelittle, pigs);
public void initByteArray(byte[] array, byte initVal) {
for (int i = 0; i < array.length; i++) {
array[i] = initVal;
}
}
// ---------------------------------------byte[] someArray;
initByteArray(someArray, someByteValue);
// ...
byte[] otherArray;
initByteArray(otherArray, otherByteValue);
// ...
byte[] youGotTheIdeaArray;
initByteArray(youGotTheIdeaArray, youGotTheIdeaByteValue);
// ---------------------------------------// Not so bad...
// ---------------------------------------String sql = "SELECT * FROM foo WHERE name='" +
nameVarFromUI + "' AND phone='" +
phoneFromUI + "' AND something = '" +
stFromUI + "'";
// ---------------------------------------// Better...
// ---------------------------------------String sql = "SELECT * FROM foo WHERE name=" +
filterQuoteString(nameVarFromUI) + " AND phone=" +
filterQuoteString(phoneFromUI) + " AND something = " +
filterQuoteString(stFromUI);
// ---------------------------------------// Much Better!!!
// ---------------------------------------String sql =
"SELECT * FROM foo WHERE name = {0} AND phone = {1} AND something = {2}";
sql = MessageFormat.format(sql, nameVarFromUI, phoneFromUI, stFromUI);
// Know your language and the best ways to do things!
Niveles de indentación
Programación a la
Defensiva
Los demás van a tratar de chocarlo...
¡así que es mejor que usted trate de no
chocar!
/**
* @param x A string used to calculate bla bla...
*
null values are not allowed.
* @param a An integer used to calculate bla bla.
*
Valid values range between 10 and 100 (inclusive).
* @return The “all mighty” calculated float.
*
Return value must be between 1000 and 2000 (inclusive).
*/
public float someAlgorithm(String x, int a) {
// bla bla run the algorithm
// What happens if any of the arguments is wrong?
// Crash? Cryptic message?
float result = ...; // something
}
// What happens if calculated result is wrong
// The caller crashes?
// A bug “who knows were and how far away from this” happens?
return result;
/**
* @param x A string used to calculate bla bla...
*
null values are not allowed.
* @param a An integer used to calculate bla bla.
*
Valid values range between 10 and 100 (inclusive).
* @return The “all mighty” calculated float.
*
Return value must be between 1000 and 2000 (inclusive).
*/
public float someAlgorithm(String x, int a) {
if (x == null) {
throw new IllegalArgumentException(
"x null values are not allowed"); // Defensive exception
}
if (a < 10 && a > 100) {
throw new IllegalArgumentException(
"a valid values range between 10 and 100 (inclusive)"); // Defensive exception
}
// bla bla run the algorithm
float result = ...; // something
if (result < 1000 && result > 2000) {
throw new IllegalStateException(
"return value must be between 1000 and 2000 (inclusive) " +
"oops, you found a bug, result was: " + result); // Defensive exception
}
return result;
}
Niveles de indentación
Use algún tipo de
mecanismo de Logging
Imprima cadenas sólo cuando las necesite
public synchronized void initFacade(String schedId, String hibeCfg) //
throws SchedulerException {
System.out.println(
"[INFO] Initializing Facade (id/cfg): " + schedId, hibeCfg);
if (hibeCfg == null) {
System.out.println("[INFO] Initializing Hibernate");
hibeCfg = CledaConnector.getInstance().getDefaultHibernateCfg();
}
SchedulerFacade schedulerFacade = schedulerFacadeById.get(schedId);
if (schedulerFacade != null) {
System.out.println(
"[WARN] Facade for the given Id is already initialized: " + schedId);
return;
}
schedulerFacade = new SchedulerFacade(schedId, hibeCfg);
schedulerFacadeById.put(schedId, schedulerFacade);
schedulerFacade.start();
}
System.out.println("[INFO] Facade was correctly initialized");
Tomado y adaptado de CledaScheduler
private static final Logger log = Logger.getLogger( //
SchedulerFactory.class.getName());
public synchronized void initFacade(String schedId, String hibeCfg) //
throws SchedulerException {
log.info("Initializing Facade (id/cfg): " + schedId, hibeCfg);
if (hibeCfg == null) {
log.info("Initializing Hibernate");
hibeCfg = CledaConnector.getInstance().getDefaultHibernateCfg();
}
SchedulerFacade schedulerFacade = schedulerFacadeById.get(schedId);
if (schedulerFacade != null) {
log.warn("Facade for the given Id is already initialized: " + schedId);
return;
}
schedulerFacade = new SchedulerFacade(schedId, hibeCfg);
schedulerFacadeById.put(schedId, schedulerFacade);
schedulerFacade.start();
}
log.info("Facade was correctly initialized");
Tomado y adaptado de CledaScheduler
log4j.rootLogger=ERROR, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%p] %d{mm:ss.SSS} (%F:%M:%L) %m%n
log4j.logger.org.hibernate=ERROR
log4j.logger.com.minotauro.cleda.task.core=DEBUG
log4j.logger.com.minotauro.cleda.task.test=DEBUG
log4j.logger.com.minotauro.cleda.task.core.WaitNotifySupport=INFO
Tomado y adaptado de CledaScheduler
¿Buen Código?
¡¡¡Sea coherente y
consistente!!!
¿Es mucho pedir?
public void doSomething(
String xxx, WeirdObject swo, UserData ud);
public void doSomethingElse(
WeirdObject swo, UserData ud, String xxx, int e);
public void moreWorkHere(
double extra2, UserData ud, int e, WeirdObject swo, String xxx);
public void otherMethod(
UserData ud, WeirdObject swo, String xxx);
public void grrAgain(
WeirdObject swo, String xxx, UserData ud);
¿Qué está mal aquí?
public void doSomething(
String xxx, WeirdObject swo, UserData ud);
public void otherMethod(
String xxx, WeirdObject swo, UserData ud);
public void grrAgain(
String xxx, WeirdObject swo, UserData ud);
public void doSomethingElse(
String xxx, WeirdObject swo, UserData ud, int e);
public void moreWorkHere(
String xxx, WeirdObject swo, UserData ud, int e, double x);
¿Mejor?
¿Buen Código?
¡Mantenga sus paquetes,
clases y métodos en un
tamaño razonable!!!
¿Qué es razonable?
¿Buen Código?
La definición de razonable puede variar de
contexto en contexto, pero:
1 servidor (de un juego)
1 sola clase
9000 lineas de código
~17 funciones con un promedio de 500 LDC
cada función
(¡¡¡Eso no es razonable!!!)
¿Buen Código?
En lo personal, para Java, creo qué clases con
un promedio de 500 LDC y no más de 2000 (En
casos muy extremos está bien). Los métodos
deberían tener entre 1-30 LDC, aunque algunos
programadores quizá pensarían que 30 LDC es
demasiado...
En cuanto a los paquetes, no se preocupe por
la cantidad de clases por paquete, preocúpese
más por tener una adecuada estructura de
paquetes que refleje la arquitectura del
software, mantenga la cohesión y refleje el
acoplamiento entre las distintas clases del
proyecto
http://pmd.sourceforge.net/
PMD scans Java source code and looks for potential problems like:
Possible bugs - empty try/catch/finally/switch statements
Dead code - unused local variables, parameters and private methods
Suboptimal code - wasteful String/StringBuffer usage
Overcomplicated expressions - unnecessary if statements, for loops that could be while
loops
Duplicate code - copied/pasted code means copied/pasted bugs
http://checkstyle.sourceforge.net/
Checkstyle can check many aspects of your source code. Historically it's main
functionality has been to check code layout issues, but since the internal architecture
was changed in version 3, more and more checks for other purposes have been
added. Now Checkstyle provides checks that find class design problems, duplicate
code, or bug patterns like double checked locking.
Analizador de potenciales problemas de código fuente
en Java
Formato del Código (Esto es importante al
momento de usar Control de Versiones y Código
Fuente) ¿Por qué?
Convenciones de Nombres
Convenciones/Reglas de Codificación
Lo importante de las convenciones es que
TODOs los miembros del equipo de desarrollo las
apliquen y que TODOs las apliquen de forma
consistente y a lo largo de TOOD el código (¿Es
mucho pedir?)
Refactoring
y sobre codificación:
Refucktoring
http://freeworld.thc.org/root/phun/unmaintain.html
Lenguaje de
Programación
vs
Plataforma
¿Portabilidad?
Lenguaje,
Plataforma,
Programador...
¿Documentación?
Del lenguaje y
la plataforma
La importancia de la documentación...
(No sólo del lenguaje sino de la plataforma)
Aprenda a usar los
distintos tipos de
herramientas
disponibles para
desarrollar software
Entornos de
Desarrollo Integrados
(IDEs)
El que diga que puede trabajar sin un
IDE no sabe lo que es desarrollar software...
(mi humilde opinión)
¿Su IDE soporta su estilo de codificación?
¿Tiene un depurador?
¿Soporta auto-completación?
¿Vi o Emacs vs Eclipse? (LOL!!!)
Control de Versiones y
Control de Código Fuente
Si usted no usa control de código fuente...
...entonces no puede trabajar en equipo
(Inclusive me atrevería a decir que tampoco puede trabajar sólo)
Recuerde que para usar un sistema de Control de Versiones y
Código Fuente no sólo necesita un servidor que provea el
servicio adecuado, sino que también necesita un buen cliente
CVS, SVN, Hg (Mercurial), Git, Bazaar, Visual Source Safe, entre
otros...
http://en.wikipedia.org/wiki/Comparison_of_revision_control_software
Issue Tracking
Bug Tracking
http://flyspray.org/
http://www.mantisbt.org/
http://www.atlassian.com/software/jira/ (Propietario)
(etc...)
Otras Herramientas: Foros, Wikis, Chat (Para trabajar),
Herramientas de Planificación y Gestión, Groupware, Gestión
de Requerimientos, etc...
En general, sobre las herramientas:
Use las mejores herramientas que el dinero pueda comprar, o
si les gusta el software libre, las mejores herramientas de
Software Libre que pueda encontrar
Siempre busque y evalúe herramientas nuevas (tanto de tipos
que ya conoce como de tipos completamente nuevas), eso le
permitirá constantemente descubrir nuevas formas de hacer
las cosas, mejores herramientas, etc
Tome en cuenta la forma
en la que evoluciona la
tecnología en el tiempo
Comprenda la verdadera razón de ser y el verdadero
alcance de la tecnología que está utilizando. Tenga
cuidado de los “Buzz-Words” (AJAX, SOA, BPMN, etc)
o de las soluciones tecnológicas “apocalípticas” (¿El
fin de los tiempos? Esas que proponen la solución a
todos los problemas de la humanidad)
No estoy diciendo que AJAX, SOA, BPMN sean
tecnologías/conceptos “malos”, simplemente estoy
diciendo que en principio se “sobre-estimaron” y no se
las puso en su correcto lugar (ver gráfico siguiente)
Evolución de una tecnología
(Visibilidad vs Tiempo)
Esto explica muchas cosas en cuanto a los patrones de uso de
una tecnología, en especial en el mundo del software
(Para FRAMEWORKS y COMPONENTES)
Aunque aplica para lenguajes de programación...
¡Evite el Fanatismo!
Por más graciosas que puedan pareces
las siguientes imágenes en la práctica
el fanatismo sólo trae problemas
Use las mejores herramientas disponibles,
las que estén acordes al contexto y las
que su presupuesto pueda pagar
¡Parches!
¿Qué son, cuándo usarlos y cuándo arreglarlos?
Gracias
¡Gracias!
Descargar