Out Of Bounds Exception!

Mi lugar de irreflexión y algo de programación

Los códigos WTF: Reloaded

Sabíamos que este día llegaría: el día en que volvería a tener material para tratar este interesante tema de los códigos sangraojos, quemaneuronas, matagatitos…

El caso es que vuelvo a tener trabajo y dado que en todas las empresas siempre hay algún proyecto marrón/con-código-hecho-hasta-por-el-de-recursos-humanos, he decidido dedicar otra entrada a estas pequeñas perlas que algunos programadores nos dejan preparadas para nuestro regocijo y deleite personal.

Algo que me dió la primera sensación de deja vu con mi otro trabajo fue las comprobaciones-null sin sentido, y dado que a simple vista ya vi unas cuantas, hice una búsqueda del texto “==null” en el proyecto…

Quitando las copias del repositorio, se nos quedan en la mitad: 135 comprobaciones. Ahora vamos a quitar las que realmente son útiles: a ojo de buen cubero he descartado unas (vamos a ser generosos) 50, por lo que nos quedan 85. ¿Os parecen pocas?

Tengamos ahora en cuenta, obviando su utilidad, que la comentaré luego, cuántas veces se llama a las funciones que las tienen: onDraw, onAccuracyChanged, onSensorChanged… por mencionar sólo algunas. Y ¿qué tienen de especial estas funciones? Que se llaman bastante a menudo (de hecho onDraw se llamará MUCHAS veces por segundo: cada vez que repintemos la pantalla)

En lo referente a la utilidad, espero que este par de fragmentos lo aclaren totalmente:

protected void onDraw(Canvas canvas) {
    	if (canvas==null) return;

public Matrix(Matrix m) {
        if (m==null) throw new NullPointerException();

        set(m.a1,m. a2, m.a3, m.b1, m.b2, m.b3, m.c1, m.c2, m.c3);
}

¿Hace falta decir más? Por si acaso, lo aclaro: en el primer caso tenemos el modo paranoico-on donde comprobamos hasta lo más básico; en el segundo caso es mucho más divertido, en vez de dejar ejecutar y que pegue el NullPointerException el método solito, mejor vamos a forzarlo, ¡que es más diver! 😀 (SERIOUSLY).

Vale, quizá yo sea un poco maniático y hacer alguna que otra comprobación inútil (en este caso, bastantes) en un if no sea para tanto… ¿no? Vamos a comprobarlo:

Cada if tarda una media de 40ns (en un iMac con un procesador i5 a 2.5 GHz), lo cual hace que tengamos que ejecutar 25000 ifs (sí, son muchos) para tener un delay de un milisegudo.

Ahora tengamos en cuenta que estamos en un sistema operativo móvil, donde aparentemente (yo soy el primer sorprendido) un if tarda una media de 600ns en un tablet Asus Transformer TF101 (procesador Dual-core 1 GHz Cortex-A9) y unos bonitos 1200ns de media en un “anticuado” Nexus One (procesador 1 GHz Qualcomm Scorpion).

Con lo cual la cosa cambia bastante, concretamente a 1ms cada 1666 ifs para el Asus y a 1ms cada ¡833 ifs! Esos ya no son tantos, ¿eh?

Vale, ahora calculemos cuántas veces se puede llamar al método onDraw en una aplicación normalita: pongamos unos 60 cómodos fps, lo cual implica que el método se va a llamar 60 veces cada segundo, habiendo unos 50 ifs que se llaman en este o en otros métodos (llamados por el onDraw), hace que cada segundo, haya 3.6ms de delay en inútiles comprobaciones.

Siendo realistas no es mucho, pero los datos son aproximados, quizá de igual teniendo 50 comprobaciones inútiles, pero hay que tener en cuenta también otros terminales menos potentes, métodos que ya se tomen su tiempo para dibujar la interfaz, muchas más comprobaciones (se han dado casos, si), etc.

Con lo cual, no hace falta que empeceis a quitar ifs de vuestras aplicaciones, pero sí que es bueno tener en cuenta el coste de cada llamada en funciones de dibujado.

Dejando a un lado las cuentas de la abuela, sigo con algunos ejemplos más divertidos:

public abstract class PaintableObject {
    private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

    public PaintableObject() {
        if (this.paint==null) {
            this.paint = new Paint();
            this.paint.setTextSize(16);
            this.paint.setAntiAlias(true);
            this.paint.setColor(Color.BLUE);
            this.paint.setStyle(Paint.Style.STROKE);
        }
    }

Pos mu’ bien

——-

Este es que es “por si acaso”, no vaya a ser que los arguments vayan con retaso, ¡oiga!

@Override
public void onActivityCreated(Bundle savedInstanceState) {
	super.onActivityCreated(savedInstanceState);
	if(getArguments()!=null){
		whatever=(Whatever) getArguments().get(Constants.KEY_Whatever);
		updateWhatever(whatever);
	}
	
}

public void updateWhatever(Whatever whatever){
	whatever=(Whatever) getArguments().get(Constants.KEY_Whatever);
	if(whatever!=null && whatever.getId()!=null)
	(...)
}

———–

Este es de un linear layout en un xml sin el atributo orientation (por defecto es horizontal). Entonces cada vez que se pinta, ¡pues le cambiamos la orientación! Así de simple.

    
<LinearLayout
        android:id="@+id/apartado_row_llContent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="26dp"
        android:layout_marginRight="26dp"
        android:paddingTop="5dp"/>
(...)

parent.setOrientation(LinearLayout.VERTICAL);

————–

Por si acaso explico que isChecked() y setChecked(boolean) son un “getter” y “setter” de la misma variable.

new OnClickListener() {

	@Override

	public void onClick(View v) {

		if (twitter.isChecked()) {
	
			if (!loggedTwitter) {
	
				ShareUtils.showTwitterAuthDialog(...)
	
			} else {
	
				twitter.setChecked(true);
	
			}
	
		} else {
			twitter.setChecked(false);
	
		}
	}
}

wat?

————

Este último es mi favorito, aunque es una chorrada como una casa xD

moverAguja((loc.getSpeed() * 3600) / 1000);

Es que las fracciones no se le daban bien en el cole.

Anuncios

Una respuesta a “Los códigos WTF: Reloaded

  1. Mario Vilas 29 noviembre, 2012 en 13:56

    Jejejejeje 🙂

    Ojo que el último quizas no sea una burrada sino una forma de evitar errores de redondeo…

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: