2023-11-20
What’s a Linked List, Anyway?
Publicado por
flikxxi
en
10:57
0
comentarios
Etiquetas: linked lists, programacion, programing
2015-10-06
15 Sorting Algorithms in 6 Minutes
Visualization and "audibilization" of 15 Sorting Algorithms in 6 Minutes. Sorts random shuffles of integers, with both speed and the number of items adapted to each algorithm's complexity. The algorithms are: selection sort, insertion sort, quick sort, merge sort, heap sort, radix sort (LSD), radix sort (MSD), std::sort (intro sort), std::stable_sort (adaptive merge sort), shell sort, bubble sort, cocktail shaker sort, gnome sort, bitonic sort and bogo sort (30 seconds of it). More information on the "Sound of Sorting" at http://panthema.net/2013/sound-of-sorting/
Publicado por
flikxxi
en
13:22
0
comentarios
Etiquetas: EN, programacion
2014-04-07
Android App Polishing: Customizing Soft Keyboard Action Button
How to add an action button to a soft keyboard in Android by Cyril Mottier
Android App Polishing: Customizing Soft Keyboard Action Button
Publicado por
flikxxi
en
10:27
0
comentarios
Etiquetas: android, EN, link, programacion, url
2013-03-26
Cómo instalar el sdk de android en /opt para todos los usuarios en GNU/Linux
Estoy reinstalando todo en mi ordenador de escritorio actual (epi) (yo uso el abecedario a nombrarlos, como los huracanes, aunque tiene alguna letra más en el interior). Estoy instalando el SDK de Android y me gusta instalado en /opt, por lo que he descargado y descomprimido usando tar, mv, chown, ... entonces me quedé atascado en que los permisos de ejecución/búsqueda (x) eran sólo para el propietario. Luego, utilizando man chmod encontré la manera correcta de hacerlo.
cd /opt sudo tar xvzf /home/franci/Descargas/android-sdk_r21.1-linux.tgz sudo chmod +r -R android-sdk-linux/ sudo chmod +X -R android-sdk-linux/
lo nuevo (no lo conocía antes de leer la páginas man de chmod) es +X, le indica a chmod que expanda el atributo de ejecución/búsqueda si uno de los tres grupos de permisos lo tiene.
Ahora todos los usuarios pueden utilizarlo.
Publicado por
flikxxi
en
13:12
0
comentarios
Etiquetas: android, development, ES, GNU/Linux, programacion
How to install android sdk in /opt for everyone in GNU/Linux
I'm reinstalling everything in my current desktop computer (epi) (I use the alphabet to name them, like hurricanes, althought it has some more letter inside). I'm installing android SDK and I like it installed on /opt, so I downloaded it and unpacked using tar, mv, chown, ... then I got stuck when excution/search permits (x) was only for owners. Then using man chmod I found a way to do it the right way.
cd /opt sudo tar xvzf /home/franci/Downloads/android-sdk_r21.1-linux.tgz sudo chmod +r -R android-sdk-linux/ sudo chmod +X -R android-sdk-linux/
the new thing (I didn't know before reading chmod man page) is +X, it says to chmod to expand execution/search attribute if one of the three groups have it.
Now everyone can use it.
Publicado por
flikxxi
en
13:10
0
comentarios
Etiquetas: android, development, EN, GNU/Linux, programacion
2012-07-31
Java Desktop.mailto Error
Few days ago I found a Java bug, in Ubuntu 12.04
Java Version: Sun JavaSE 6 and Oracle JavaSE 7
Operative System: Ubuntu 12.04
You can find more info, and follow the bug here.
Hace algunos dias encontre un bug en Java, en Ubuntu 12.04
Versión de Java: Sun JavaSE 6 y Oracle JavaSE 7
Sistema Operativo: Ubuntu 12.04
Puedes encontrar más información , y seguir el bug aquí,
Publicado por
flikxxi
en
14:09
0
comentarios
Etiquetas: bug, EN, ES, java, programacion
2012-06-30
Howto activate LogCat in Huawei U8650
If you are a programmer you maybe have found the same problem in Huawei U8650, there is no LogCat, you plug and unplug, look everywhere, everything is fine, it's just there is no LogCat. You can try to view the log with this command
adb logcat
You get the following error
Unable to open log device '/dev/log/main': No such file or directory
There is an easy solution, open the hidden menu by one of the following options
- Type the Dial (as calling) the code
*#*#2846579#*#* - Execute in the commandline
adb shell am start -a android.intent.action.MAIN -n com.android.settings/com.android.settings.TestingSettingsHW
Once the configuration menu is open go to ProjectMenu->3. Background setting->2. Log setting->Log switch and select the option "LOG on"
Now go to ProjectMenu->3. Background setting->2. Log setting->->Log level setting and select "VERBOSE" or the desired level.
Now you need to reboot the device, that can be done by the command
adb reboot
To deactivate just rever the changes.
It could be necessary to modify the options of the following screen
ProjectMenu->3. Background setting->7. Dump&Log
Not in my case.
Happy hacking!!!
Publicado por
flikxxi
en
0:41
0
comentarios
Etiquetas: android, EN, programacion
Como activar LogCat en el Huawei U8650
Si eres programador tal vez te has encontrado con el mismo problema que yo con mi Huawei U8650, no hay LogCat, enchufas y desenchufas miras por todos lados, todo está bien, simplemente no hay LogCat. Puedes intentar ver el log con el siguiente comando
adb logcat
Obteniendo el siguiente error
Unable to open log device '/dev/log/main': No such file or directory
La solución es sencilla, abrir un menú oculto mediante una de estas dos opciones
- Marcar en el Dial (como si fuese una llamada) el código
*#*#2846579#*#* - Ejecutar en la línea de comandos el comando
adb shell am start -a android.intent.action.MAIN -n com.android.settings/com.android.settings.TestingSettingsHW
Una vez abierto el menú de configuración vamos a ProjectMenu->3. Background setting->2. Log setting->Log switch y seleccionamos la opción "LOG on".
Ahora vamos a ProjectMenu->3. Background setting->2. Log setting->Log level setting y seleccionamos "VERBOSE" o el nivel deseado.
Ahora necesitamos reiniciar el teléfono, puede hacerse mediante el comando
adb reboot
Para desactivarlo sólo es necesario revertir los cambios.
Podría ser necesario modificar las opciones de la siguiente pantalla
ProjectMenu->3. Background setting->7. Dump&Log
Aunque en mi caso no ha sido necesario.
¡¡¡Happy hacking!!!
Publicado por
flikxxi
en
0:29
0
comentarios
Etiquetas: android, ES, programacion
2012-02-29
Using ADB over WiFi
| -Rooting the device if not rooted yet |
| -Install Wifi ADB |
| -Push "Turn on" button to get the exact command |
| -Allow super user permits if a emerging screen ask for it |
| -Execute the command "adb connect 192.168.1.36:5555" |
| -Push "Turn off" button to deactivate the aplication |
| -Get the machine IP ie: 192.168.1.35 |
| -Run the emulator, and you'll find the port 5555 in the window's title puerto 5555 or any other if there is more than one device. |
| -Run the command "adb connect 192.168.1.35:5555" with the given IP and port. |
As Richard Stallman would say ¡Happy coding!
Publicado por
flikxxi
en
11:19
0
comentarios
Etiquetas: android, EN, programacion
Cómo usar ADB sobre Wifi
| -Rootear el dispositivo si no lo está |
| -Instalar Wifi ADB |
| -Pulsar el boton "Turn on" para obtener la orden exacta |
| -Permitir permisos de super usuario si nos sale la ventana emergente |
| -Ejecutar el comando "adb connect 192.168.1.36:5555" |
| -Pulsar el boton "Turn off" para desactivar la aplicación |
| -Obtener la IP del equipo ej: 192.168.1.35 |
| -Lanzar el emulador, en el título de la ventana veremos el puerto 5555 u otro si hay más de un dispositivo |
| -Ejecutar el comando "adb connect 192.168.1.35:5555" teniendo en cuenta la IP y el puerto anteriores |
Como diría Richard Stallman ¡Happy coding!
Publicado por
flikxxi
en
10:59
0
comentarios
Etiquetas: android, ES, programacion
2011-12-06
onSaveInstanceState llamado dos veces
Pero esto sólo funciona si lo rotas despacio, si lo rotas dos veces justo cuando la activity está restaurándose seguirás teniendo el mismo problema.
Publicado por
flikxxi
en
11:24
0
comentarios
Etiquetas: android, ES, programacion
onSaveInstanceState called twice
But it only works if you rotate slowly, if you rotate it twice just when the activity is restoring state you'll still have the same problem.
Publicado por
flikxxi
en
11:13
0
comentarios
Etiquetas: android, EN, programacion
2011-01-01
Java Puzzlers - Scraping the Bottom of the Barrel
Josh Bloch and Bob Lee present 7 Java code puzzlers, code seeming to produce some result, but actually producing something unexpected. They explain why is that, showing the correct solution. 
http://www.infoq.com/presentations/Java-Puzzlers
Publicado por
flikxxi
en
12:00
0
comentarios
Etiquetas: EN, java, programacion, video
2010-12-14
Joshua Bloch - Performance Anxiety
Publicado por
flikxxi
en
23:31
0
comentarios
Etiquetas: EN, programacion, video
2010-11-07
Understanding Soft, Weak and Phantom References
Publicado por
flikxxi
en
13:11
0
comentarios
Etiquetas: EN, java, programacion
2010-08-16
Adding a jar to an Android project in Netbeans
If you add a jar to an Android project in Netbeans, it will compile but classes included in that jar won't be included in apk package.
there is a solution to this problem, add these lines in build.xml file
<target name="-pre-jar">
<copy todir="${build.classes.dir}">
<fileset file="${file.reference.YOURJAR.jar}" />
</copy>
</target>
change YOURJAR for the apropiate value that you will find in project.properties
in my case I've found
file.reference.core.jar=../core/dist/core.jar
so I've added these lines
<target name="-pre-jar">
<copy todir="${build.classes.dir}">
<fileset file="${file.reference.core.jar}" />
</copy>
</target>
Publicado por
flikxxi
en
12:16
0
comentarios
Etiquetas: android, EN, java, programacion
2010-08-11
Java Basics, Java Notes and Kode Java
Looking for an example of how shuffle the elements of an array in java, I've found these useful webpages, where you can find tons of examples.
Java Basics
Java Notes
Kode Java
Publicado por
flikxxi
en
22:46
0
comentarios
Etiquetas: EN, java, programacion
2010-07-16
State of the Lambda by Brian Goetz
Borrowed from State of the Lambda by Brian Goetz, 6 July 2010
This is an updated proposal to add lambda expressions (informally,
"closures") to the Java programming language. This sketch is built on
the straw-man proposal made by Mark Reinhold in December
2009.
- Background; SAM classes
The Java programming language already has a form of closures:
anonymous inner classes. There are a number of reasons these are
considered imperfect closures, primarily:- Bulky syntax
- Inability to capture non-final local variables
- Transparency issues surrounding the meaning of return, break,
continue, and 'this' - No nonlocal control flow operators
It is not a goal of Project Lambda to address all of these issues.
The standard way for Java APIs to define callbacks is to use an
interface representing the callback method, such as:public interface CallbackHandler
{
public void callback(Context c);
}The CallbackHandler interface has a useful property: it has a single
abstract method. Many common interfaces and abstract classes have
this property, such as Runnable, Callable, EventHandler, or
Comparator. We call these classes SAM classes.The biggest pain point for anonymous inner classes is bulkiness. To
call a method taking a CallbackHandler, one typically creates an
anonymous inner class:foo.doSomething(new CallbackHandler()
{
public void callback(Context c)
{
System.out.println("pippo");
}
});The anonymous inner class here is what some might call a "vertical
problem": five lines of source code to encapsulate a single statement.
Astute readers will notice that the syntax used for examples in this
document differ from that expressed in the straw-man proposal. This
does not reflect a final decision on syntax; we are still
experimenting with various candidate syntax options. - Lambda expressions
Lambda expressions are anonymous functions, aimed at addressing the
"vertical problem" by replacing the machinery of anonymous inner
classes with a simpler mechanism. One way to do that would be to add
function types to the language, but this has several disadvantages:
- Mixing of structural and nominal types;
- Divergence of library styles (some libraries would continue to use
callback objects, while others would use function types).So, we have instead chosen to take the path of making it easier to
create instances of callback objects.Here are some examples of lambda expressions:
{ -> 42 }
{ int x -> x + 1 }The first expression takes no arguments, and returns the integer 42;
the second takes a single integer argument, named x, and returns x+1.Lambda expressions are distinguished from ordinary statement blocks by
the presence of a (possibly empty) formal parameter list and the ->
token. The lambda expressions shown so far are a simplified form
containing a single expression; there is also a multi-statement form
that can contain one or more statements. - SAM conversion
One can describe a SAM type by its return type, parameter types, and
checked exception types. Similarly, one can describe the type of a
lambda expression by its return type, parameter types, and exception
types.Informally, a lambda expression e is convertible-to a SAM type S if
an anonymous inner class that is a subtype of S and that declares a
method with the same name as S's abstract method and a signature and
return type corresponding to the lambda expressions signature and
return type would be considered assignment-compatible with S.The return type and exception types of a lambda expression are
inferred by the compiler; the parameter types may be explicitly
specified or they may be inferred from the assignment context (see
Target Typing, below.)When a lambda expression is converted to a SAM type, invoking the
single abstract method of the SAM instance causes the body of the
lambda expression to be invoked.For example, SAM conversion will happen in the context of assignment:
CallbackHandler cb = { Context c -> System.out.println("pippo") };In this case, the lambda expression has a single Context parameter,
has void return type, and throws no checked exceptions, and is
therefore compatible with the SAM type CallbackHandler. - Target Typing
Lambda expressions can only appear in context where it will be
converted to a variable of SAM type; the type of 'this' inside the
lambda expression is (a subtype of) the SAM type to which the lambda
expression is being converted. So the following code will print
"Yes":Runnable r = { ->
if (this instanceof Runnable)
System.out.println("Yes");
};
r.run();The following use of lambda expressions is forbidden because it does
not appear in a SAM-convertible context:Object o = { -> 42 };In a method invocation context, the target type for a lambda
expression used as a method parameter is inferred by examining the set
of possible compatible method signatures for the method being invoked.
This entails some additional complexity in method selection;
ordinarily the types of all parameters are computed, and then the set
of compatible methods is computed, and a most specific method is
selected if possible. Inference of the target type for lambda-valued
actual parameters happens after the types of the other parameters is
computed but before method selection; method selection then happens
using the inferred target types for the lambda-valued parameters.The type of the formal parameters to the lambda expression can also be
inferred from the target type of the lambda expression. So we can
abbreviate our callback handler as:CallbackHandler cb = { c -> System.out.println("pippo") };as the type of the parameter c can be inferred from the target type
of the lambda expression.Allowing the formal parameter types to be inferred in this way
furthers a desirable design goal: "Don't turn a vertical problem into
a horizontal problem." We wish that the reader of the code have to
wade through as little code as possible before arriving at the "meat"
of the lambda expression.The user can explicitly choose a target type by specifying a type
name. This might be for clarity, or might be because there are
multiple overloaded methods and the compiler cannot correctly chose
the target type. For example:executor.submit(Callable<String> { -> "foo" });If the target type is an abstract class, it is an open question as to
whether we want to permit an argument list so a constructor other than
the no-arg constructor can be used. - Lambda bodies
In addition to the simplified expression form of a lambda body, a
lambda body can also contain a list of statements, similar to a method
body, with several differences: the break, return, and continue
statements are not permitted, and a "yield" statement, whose form is
similar to to the return statement, is permitted instead of a return
statement. The type of a multi-statement lambda expression is
inferred by unifying the type of the values yielded by the set of
yield statements. As with method bodies, every control path through a
multi-statement lambda expression must either yield a value, yield no
value, or throw an exception. Expressions after a yield statement are
unreachable.The complete syntax is given by:
lambda-exp := "{" arg-list "->" lambda-body "}"
arg-list := "(" args ")" | args
args := arg | arg "," args
arg := [ type ] identifier
lambda-body := expression | statement-list [ ";" ]
statement-list := statement | statement ";" statement-list - Instance capture
Once the target type of a lambda expression is determined, the body of
a lambda expression is treated largely the same way as an anonymous
inner class whose parent is the target type. The 'this' variable
refers to the SAM-converted lambda (whose type is a subtype of the
target type). Variables of the form OuterClassName.this refer to the
instances of lexically enclosing classes, just as with inner classes.
Unqualified names may refer to members of the SAM class (if it is a
class and not an interface), or to members of lexically enclosing
classes, using the same rules as for inner classes.For members of lexically enclosing instanaces, member capture is
treated as if the references were desugared to use the appropriate
"Outer.this" qualifier and Outer.this is captured as if it were a
local final variable. - Local variable capture
The current rules for capturing local variables of enclosing contexts
in inner classes are quite restrictive; only final variables may be
captured. For lambda expressions (and for consistency, probably inner
class instances as well), we relax these rules to also allow for
capture of effectively final local variables. (Informally, a local
variable is effectively final if making it final would not cause a
compilation failure.)It is likely that we will not permit capture of mutable local
variables. The reason is that idioms like this:int sum = 0;
list.forEach({ Element e -> sum += e.size(); });are fundamentally serial; it is quite difficult to write lambda bodies
like this that do not have race conditions. Unless we are willing to
enforce (preferably statically) that such lambdas not escape their
capturing thread, such a feature may likely cause more trouble than it
solves. - Exception transparency
A separate document on exception transparency proposes our strategy
for amending generics to allow abstraction over thrown checked
exception types. - Method references
SAM conversion allows us to take an anonymous method body and treat it
as if it were a SAM type. It is often desirable to do the same with
an existing method (such as when a class has multiple methods that are
signature-compatible with Comparable.compareTo().)Method references are expressions which have the same treatment as
lambda expressions (i.e., they can only be SAM-converted), but instead
of providing a method body they refer to a method of an existing class
or object instance.For example, consider a Person class that can be sorted by name or by
age:class Person
{
private final String name;
private final int age;
public static int compareByAge(Person a, Person b) { ... }
public static int compareByName(Person a, Person b) { ... }
}
Person[] people = ...
Arrays.sort(people, #Person.compareByAge);Here, the expression #Person.compareByAge is sugar for a lambda
expression whose formal argument list is copied from the method
Person.compareByAge, and whose body calls Person.compareByAge. This
lambda expression will then get SAM-converted to a Comparator.If the method being referenced is overloaded, it can be disambiguated
by providing a list of argument types:Arrays.sort(people, #Person.compareByAge(Person, Person));Instance methods can be referenced as well, by providing a receiver
variable:Arrays.sort(people, #comparatorHolder.comparePersonByAge);In this case, the implicit lambda expression would capture a final
copy of the "comparatorHolder" reference and the body would invoke
the comparePersonByAge using that as the receiver.We may choose to restrict the forms that the receiver can take, rather
than allowing arbitrary object-valued expressions like
"#foo(bar).moo", when capturing instance method references. - Extension methods
A separate document on defender methods proposes our
strategy for extending existing interfaces with virtual extension
methods.
Publicado por
flikxxi
en
0:19
0
comentarios
Etiquetas: EN, java, lambda, programacion
2010-07-07
The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)
http://www.joelonsoftware.com/articles/Unicode.html
Some phrases from the article:
It does not make sense to have a string without knowing what encoding it uses
How do we preserve this information about what encoding a string uses? Well, there are standard ways to do this. For an email message, you are expected to have a string in the header of the form
Content-Type: text/plain; charset="UTF-8"
For a web page, the original idea was that the web server would return a similar Content-Type http header along with the web page itself -- not in the HTML itself, but as one of the response headers that are sent before the HTML page.
Publicado por
flikxxi
en
19:36
0
comentarios
Etiquetas: EN, programacion
2010-06-07
Los Riesgos de las Universidades-Java
Antes de que empieces déjame presumir, después de que con 14 años mi cerebro quedase dañado por un curso de verano de MSX BASIC, conseguí recuperarme a causa de no tener ordenador con el que practicar. Hasta que a los 18 años me compré mi primer ordenador (un 486 2MB de RAM y 120MB de disco duro lo mejorcito de la epoca) con mis ahorros obtenidos como camarero. Lo usé para practicar C que aprendí practicando en papel con un libro "C Manual de referencia de Herbert Schildt". La única dificultad de C es la compresión de los punteros, conseguido esto, lo demás es trivial. Como dice el artículo, el desconocimiento de los punteros es generalizado en las nuevas generaciones de programadores. Aunque los filtros siguen ahí, pero ahora las "purgas" las hacen las "crisis" y los "ascensos".
Los Riesgos de las Universidades-Java
por Joel Spolsky Jueves 29 de diciembre de 2005
Chicos perezosos.
¿Qué pasó con el trabajo duro?
Un seguro indicio de mi decadencia hacia la senilidad son mis continuas quejas y lamentos sobre “los chicos de hoy”, y cómo ya no quieren o no pueden hacer cosas difíciles.
Cuando yo era un muchacho, aprendí a programar con tarjetas perforadas. En esos tiempos si cometías un error, no tenías ninguna de esas modernas funciones como la tecla “backspace” para corregirlo. Tenias que tirar la tarjeta y empezar todo de nuevo.
Cuando empecé a entrevistar programadores en 1991, les dejaba usar generalmente cualquier lenguaje que quisieran para resolver los problemas de programación que les planteaba. El 99% de las veces, ellos elegían C.
Ahora ellos tienden a elegir Java.
No me malinterpreten: no hay nada malo con Java como lenguaje de implementación.
Un momento, quiero rectificar eso último. No digo, en este artículo en particular, que haya algo de malo con Java como lenguaje de implementación. Hay un montón de cosas mal con Java, pero tendrán que esperar hasta otro artículo.
En cambio, lo que quiero decir es que Java no es, generalmente, un lenguaje de programación lo suficientemente difícil para que pueda ser usado para distinguir entre excelentes programadores y programadores mediocres. Puede ser un buen lenguaje para trabajar, pero ese no es el tema de hoy. Puedo ir incluso mas allá y decir que el hecho de que Java no sea lo suficientemente difícil es una característica, no un bug, pero que tiene ese problema.
Si puedo ser atrevido, diría que en mi humilde experiencia han sido dos las cosas tradicionalmente enseñadas en las universidades como parte de la carrera de Ciencias de la Computación (CS) las que mucha gente nunca llega realmente a comprender: punteros y recursión.
En aquellos tiempos lo normal era empezar la universidad con un curso de estructuras de datos, con listas enlazadas, tablas hash y, por qué no, con un uso intensivo de punteros. Esos cursos eran frecuentemente usados como filtros: eran tan difíciles que cualquiera que no pudiera soportar el desafío mental de un grado en CS se daría por vencido, lo que era bueno, porque si piensas que los punteros son difíciles, espera hasta intentar probar cosas en teoría de punto fijo.
Todos esos chicos que lo habían hecho muy bien en la secundaria escribiendo juegos de “pong” en BASIC para su Apple II, iban a la universidad, tomaban el curso CompSci 101, sobre estructuras de datos, y cuando llegaban al asunto de los punteros, sus cerebros estallaban completamente; y lo próximo de lo que tenías noticias es que estaban especializándose en Ciencias Políticas, porque la escuela de leyes parecía ser una mejor idea. He visto todo tipo de de índices de deserción en CS y usualmente están entre el 40% y el 70%. Las universidades tienden a ver esto como un derroche; yo creo que es sólo la poda necesaria de gente que no va a ser feliz o exitosa en una carrera de programación.
El otro curso difícil para muchos jóvenes estudiantes de CS era el curso donde aprendías programación funcional, incluyendo programación recursiva. MIT puso una barrera muy alta en esos cursos, creando un curso obligatorio (6.001) y un libro de texto (Estructura e Interpretación de Programas de Computadora de Abelson y Sussman, el cual era usado en docenas o quizás cientos de carreras de CS prestigiosas como el estándar de facto para la introducción a las Ciencias de la Computación. (Puedes, y deberías echarle una ojeada a la antigua versión de las clases en línea).
La dificultad de esos cursos es asombrosa. En la primera clase has aprendido casi todo Scheme, y ya has sido introducido a la función de punto fijo que toma otra función como parámetro. Cuando me esforzaba en pasar un curso similar, CSE121 en Penn, observaba cómo muchos sino la mayoría de los estudiantes simplemente no lo lograba. La materia era muy difícil. Inclusive escribí un largo email de lloriqueando a mi profesor diciendo que “simplemente no era justo”. Alguien en Penn debe haberme escuchado (o a alguno de los otros llorones), porque ese curso se dicta ahora con Java.
Desearía que no hubiesen escuchado.
Aquí radica el quid del debate. Años de lloriqueo de estudiantes perezosos como yo, combinados con quejas de la industria acerca de cuan pocos graduados en CS salen de las universidades americanas, han pagado su precio, y en la ultima década un gran numero de otrora perfectamente buenas universidades se han vuelto 100% Java. Esta de moda, a los reclutadores que usan “grep” parece gustarles, y, lo mejor de todo, no hay nada lo suficientemente difícil en Java como para filtrar aquellos programadores sin la parte del cerebro que entiende punteros y recursión. Así es que la deserción es menor, y los departamentos de ciencias de la computación tienen mas alumnos y mayores presupuestos y todo está bien.
Los afortunados chicos de esas Universidades-Java nunca van a toparse con raros fallos de segmentación tratando de implementar tablas hash basadas en punteros. Nunca se van a volver locos tratando de empaquetar cosas en bits. Nunca tendrán que ocupar sus cabezas en cómo en un lenguaje puramente funcional, el valor de una variable nunca cambia, y aun así, ¡cambia todo el tiempo! ¡Una paradoja!
Ellos no necesitan esa parte del cerebro para obtener un 4 en la materia.
¿Soy sólo uno de esos viejos cascarrabias anticuados, vanagloriándose acerca de cuán duro era sobrevivir a todas esas dificultades?
Rayos, en 1900, el Latín y el Griego eran asignaturas requeridas en la universidad, no porque sirvieran de algún propósito, sino porque de alguna manera eran considerados un requisito obvio de la gente educada. De cierta manera mi argumento no es diferente del argumento expuesto por la gente pro-Latín: “[El Latín] entrena tu mente. Entrena tu memoria. Desembrollar una sentencia en Latín es un excelente ejercicio del pensamiento, un verdadero acertijo intelectual y una buena introducción al pensamiento lógico”, escribe Scout Barrer. Pero ya no puedo encontrar una sola universidad que requiera Latín. ¿Son los punteros y la recursión el Latín y el Griego de las ciencias de la computación?
Ahora, admito que programar con punteros no es necesario en el 90% del código escrito en la actualidad, y de hecho es totalmente peligroso en el código de producción. OK. Está bien. Y que la programación funcional no es muy empleada en la práctica. De acuerdo.
Pero todavía sigue siendo importante para algunos de las tareas más excitantes en programación. Sin punteros, por ejemplo, nunca serías capaz de trabajar en el Kernel de Linux. No puedes entender una sola línea del código de Linux, o de hecho, de cualquier sistema operativo, sin realmente entender punteros.
Sin entender programación funcional, no podrás inventar MapReduce, el algoritmo que hace Google tan masivamente escalable. Los términos Map y Reduce vienen de Lisp y la programación funcional. MapReduce es, en retrospectiva, obvio para cualquiera que recuerde de su clase equivalente a 6.001 que los programas puramente funcionales no tienen efectos colaterales y por ende son trivialmente paralelizables. El simple hecho que Google inventara MapReduce, y no Microsoft, dice algo del por qué Microsoft está aun jugando a lograr que funcionen algunas características básicas de búsqueda, mientras Google se ha movido ya al siguiente problema: construir Skynet^H^H^H^H^H^H, la mayor supercomputadora masivamente paralela del mundo. Simplemente no creo que Microsoft entienda completamente cuan retrasados están en ese campo.
Pero mas allá de la importancia a simple vista de los punteros y la recursión, su valor real radica en que construir grandes sistemas requiere del tipo de flexibilidad mental que adquieres aprendiéndolos, y de la actitud mental que necesitas para no huir de los cursos en donde son enseñados. Punteros y recursión requieren cierta habilidad para razonar, para pensar en abstracciones, y más importante, para ver un problema en diversos niveles de abstracción simultáneamente. Por lo tanto, la habilidad para entender punteros y recursión esta directamente correlacionada con la habilidad de ser un gran programador.
No hay nada en grado académico 100% Java que realmente descarte a los estudiantes que carecen de la agilidad mental para tratar con esos conceptos. Como empleador, he visto que las Universidades 100% Java han empezado a producir en serie una buena cantidad de graduados quienes simplemente no son lo suficientemente listos para trabajar como programadores en nada mas sofisticado que “Sólo Otra Aplicación Contable en Java”, aunque se las han arreglado para colarse a través de la (ahora simplificada) carrera. Esos estudiantes nunca sobrevivirían al 6.001 del MIT o al CS 323 en Yale y, francamente, esa es una razón por la cual, como empleador, un título en CS del MIT o Yale tiene más peso que uno de Duke, que recientemente se hizo 100%-Java, o de Penn, donde remplazaron Scheme y ML por Java tratando de enseñar la materia que casi nos mata a mis compañeros y a mi, CSE121. No es que no quiera contratar chicos listos de Duke o Penn, lo hago, es sólo que es mucho más difícil para mí darme cuenta de cuáles son. Yo estaba acostumbrado a decir que los chicos listos eran aquellos que podían desmenuzar un algoritmo recursivo en segundos, o implementar funciones de manipulación de listas enlazadas usando punteros tan rápido como podían escribir en la pizarra. Pero con graduado sde Universidades-Java, no puedo saber si padecen esos problemas a causa de haber sido mal educados o si los padecen porque realmente carecen de esa parte del cerebro que van a necesitar para ser buenos programadores en el trabajo. Paul Graham los llama “Blub Programmers“.
Ya es bastante malo que las Universidades-Java fallen en filtrar los chicos que nunca van a ser buenos programadores, algo que las universidades podrían justificablemente decir que no es su problema. Después de todo es la industria, o al menos los reclutadores-que-usan-grep, quien está pidiendo a gritos que se enseñe Java.
Pero las Universidades-Java fallan también en entrenar las mente de los chicos para ser hábiles, ágiles y lo suficientemente flexibles para lograr buen diseño de software (y no me refiero al “diseño” OO, donde gastas incontables horas acomodando tu jerarquía de objetos, o preocupándote de “problemas” superfluos como “tiene-un” vs. “es-un”). Necesitas entrenamiento para pensar en las cosas a varios niveles de abstracción simultáneamente, y ese tipo de pensamiento es exactamente lo que necesitas para diseñar excelentes arquitecturas de software.
Puedes estar preguntándote si la enseñanza de programación orientada a objetos (OOP) es un buen sustituto de los punteros y la recursión para el filtrado. La respuesta rápida: no. Sin debatir acerca de los meritos de la OOP, simplemente no es lo suficientemente difícil para filtrar a los programadores mediocres. OOP en las universidades consiste básicamente en memorizar un puñado de términos de vocabulario como “encapsulacion” y “herencia” y tomar exámenes del tipo “multiple-choice” acerca de las diferencias entre polimorfismo y sobrecarga. No más difícil que memorizar fechas destacadas y nombres en una clase de historia, la OOP tiene desafíos mentales inadecuados para espantar a los estudiantes de primer año. Cuando te enfrentas con un problema de OOP, tu programa aun funciona, sólo que es algo difícil de mantener. Supuestamente. Pero cuando te enfrentas a un problema con punteros, tu programa produce línea Fallo de segmentación y no tienes ni la menor idea de lo que está pasando, hasta que te paras, tomas una fuerte bocanada de aire y tratas de forzar tu mente a trabajar en dos diferentes niveles de abstracción simultáneamente.
Los reclutadores-que-usan-grep, de hecho, son ridiculizados aquí, y por un buen motivo. Nunca he conocido alguien que pueda usar Scheme, Haskell y punteros en C, que no pueda entender Java en dos días, y crear mejor código en Java que gente con cinco años de experiencia en Java. Pero trata de explicar eso al zombie de Recursos Humanos.
¿Pero que hay de la misión del compromiso con las CS de las facultades de CS? ¡Ellas no son escuelas vocacionales! No debería ser su trabajo entrenar gente para trabajar en la industria. Eso queda para los terciarios y los programas de capacitación del gobierno para trabajadores desplazados, dirán. Ellas se suponen que están para dar a los estudiantes las herramientas fundamentales para vivir sus vidas, no para prepararlos para sus primeras semanas de trabajo. ¿No es cierto?
Aun así, las CS son demostraciones (recursión), algoritmos (recursión), lenguajes (cálculo lambda), sistemas operativos (punteros), compiladores (cálculo lambda), y entonces la conclusión es que la Universidad-Java que no enseña C y no enseña Scheme, tampoco está enseñando realmente ciencias de la computación. Tan inútil como el concepto de currificación de funciones puede serle al mundo real, es un obvio prerrequisito para un graduado en CS. No puedo entender por qué los profesores en las comisiones curriculares de las facultades de CS han permitido que sus programas sean embrutecidos a tal punto que no sólo no pueden producir programadores operativos, sino que ya ni siquiera pueden producir graduados en CS que puedan obtener PhDs y puedan competir por sus puestos de trabajo. Oh, esperen. No importa. Quizás entienda.
Si volvemos en el tiempo y analizamos las discusiones que tomaron lugar en el mundo académico durante el “Gran Levantamiento Java”, encontraremos que la mayor preocupación fue que Java no era lo suficientemente simple para ser usado como un lenguaje de enseñanza.
Mi Dios, pensé, ¡están tratando de embrutecer la curricula aun mas! ¿Por que mejor no le llevamos la comida a la boca a los estudiantes? Dejemos que los ayudantes de cátedra den los exámenes por ellos también, entonces nadie se cambiara a Estudios Americanos. ¿Cómo se supone que alguien aprenderá algo si la curricula ha sido cuidadosamente diseñada para hacer todo más fácil de lo que ya es? Parece haber una comisión de trabajo (PDF) intentando idear un subconjunto simple de Java que pueda ser enseñado a estudiantes, produciendo documentación simplificada que esconde cuidadosamente toda esa basura EJB/J2EE de sus tiernas mentes, de manera tal que no tengan que preocupar sus cabecitas con otras clases que no necesiten para resolver sus aun más fáciles problemas de CS.
La interpretación mas compasiva de por qué las facultades CS son tan entusiastas en embrutecer sus clases es porque ello les dará más tiempo para enseñar verdaderos conceptos de CS, así no necesitaran dos clases enteras para esclarecer a los alumnos las diferencias entre, digamos, un int y un Integer en Java. Bueno pero si ese fuera el caso, 6.001 tiene la respuesta perfecta: Scheme, un lenguaje de enseñanza tan simple que el lenguaje entero puede enseñarse a estudiantes brillantes en unos 10 minutos; entonces puedes gastar el resto del semestre enseñando puntos fijos.
Fiu…
Voy a regresar a los unos y ceros.
(¿Te tocaron unos? ¡Bastardo suertudo! A nosotros nos tocaron todos ceros.)
Esta traducción está basada en la versión disponible en el Wiki de Joel Spolsky, corregida y adaptada por Javier Smaldone.
Publicado por
flikxxi
en
21:01
0
comentarios
Etiquetas: ES, programacion
