Recientes del blog

Why and how to use UTC

Febrero 13th, 2017 | Opinión, Trucos y Tutoriales

And other intelligent devices and inventions like using UTF-8 whenever can be
used, and why not forget nor close thyself to other formats like official time
or ISO-8859 formats.

Previously it has been written about official time zones. Their use have been
deprecated. They have been ridiculized, as being a standard based upon the
familiarity of a system that was a great advance on its day, but now not only
is not useful, but a drag for technological advance and human health. This is a
literal reading.

What is actually intented is just the internalization that official time is an
arbitrary instrument from a time in which it was necessary to solve several
problems, that today can be solved better using alternative procedures,
therefore its use could be stopped, if we wanted. It will be stopped, when the
proper time for that comes. That internalization, openness of mind, is an
important exercise, came to help overcoming the imminent generational gap
between people already in the workforce today and those who are little
children (native in perpetual war against terrorism, native in mass
surveillance and geolocation, native in ubiquous and ‘of things’ Internet) when
confronting time management problems with a brain different in plasticity.

This internalization does not mean the action to be performed should be
radical, maybe we even prefer anchor to our customs because having crystalized
the part of our brains that manages it, but now already warned in order to be
able to understand the future; in many years from now, people critizicing this
little part of the system.

GMT (Greenwich Meridian Time) is one part of those customs, but special,
different from the remaining. Because, not joining discussion about if it is
technologically a redefinition of UTC or is UTC that is defined as a series of
operations to be performed over GMT, in its essence UTC is like it is very much
because of GMT being like it is, and it is similar because of the time
standardizing process started when the United Kingdom (where Greenwich is) was
the greatest of the great powers.

As introduced, UTC is very important. In the globalized world, time
synchronization is most important than ever before. When UTC does not get used
problems often arise. Think about some potential cases ahead:

The potential average consumer of data from social media companies’ APIs most
probably will not care which is the time of the day information gets published.
We are thinking about this prototypical online news (or whatever) source. Now
think about the typical naive but sophisticated startup focusing on applying
machine learning procedures over data from social media. Companies like this
are kind of a plague and arise in numbers just by scratching the Internet. Say
those are the remaining 20% consumers of social media APIs that actually do
care about local time of publishing. Those kind of initiative needs applying
kind of a procedure to turn moments of airing UTC encoded into local time.

Guess what? Not only publisher local time is missing from social media APIs.
Even though there can be no doubt global social media work embracing UTC
internally, paradoxically UTC is completely missing from their surface APIs.
But UTC is actually a big part of the solution to this problem, no matter the
procedures. Turns out so hated damm and obsolete official time zones,
disrespectfully anti human, can be leveraged for some profit.

Enough about the good part of the good story. There are potential not so
successful cases. Have a look on this one: greeks unexpectedly using local time
(UTC+02:00).

Winter at last came, but the worst is yet to come. Some people in a work group
in Greece send data to another work group, including dates, not labeled with
any time zone. It is assumed that everything is in a corporate environment in
which data comms are obviously using UTC, until the day comes of data having to
be transmitted in real time, discovering with horror data is coming one hour
ahead CET, local time zone of the receivers at that moment, instead of one hour
behind, as would correspond to UTC, which everyone in random company would have
expected as the only reasonable default. So two hours ahead UTC, the time zone
in which is based all business logic core software, zealously tied to UTC
during development.

A comms problem happened, and some people had been sending data in their own
local time, for a while, and that means lost time (pun not intended), if it can
not be recovered. To recover, it has to be taken into account not only time of
people are different from that of other people, but data is also tied to each
implicated time zones and daylight saving schemes, that are driven by
government, so they might not be the same and here human (broad sense)
anarchism joins the play. Even so, this all is the good part of the potentially
bad story.

Now for the bad part of the bad story. A system in Madrid, commissioning a
proposal of routing to a component outsourced or being held to Greece, must
move an autonomous vehicle in Germany, but starts moving with a five minutes
delay. Turns out an engineer supervising the operation has restarted the
application now including a patch to override dates, because the car was
discarding frames it was receiving referencing a future that not even knows
will exist. This would be the last time that team did not use assertions over
data.

All this mess applies to ISO-8859 character encoding sets exactly the same,
with potentially terrorising stories about multiple chaining of badly applied
conversion stages of character encoding. Those would be very similar in
essence to the introduced potential cases.

U.P

Continúa leyendo este artículo

NOTA TÉCNICA #20161200

Diciembre 12th, 2016 | Big Data, Opinión, Trucos y Tutoriales

El título de este artículo debería haber sido EXCLUSIONES EN BASE AL PRODUCTO CARTESIANANO CON LIMITACION POR IGUALDAD DE CLAVE EN PARES DE DOCUMENTOS DE SISTEMAS DE PERSISTENCIA UNIX SIN SINTAXIS SQL, esto parece ser un poco largo para un documento Markdown como título, finalmente se ha abreviado en NOTA TÉCNICA #20161200 porque aunque pierda capacidad descriptiva va a seguir siendo igual de fácil de referenciar, que es de lo que se trata al fin y al cabo la escritura de artículos, aparte de que intentemos hacer algo útil para la mayor cantidad de gente posible y que todos aprendamos algo; y porque la alternativa era escribir en docutils’ reStructuredText o LaTeX, lo que en principio habría sido una formalidad excesiva para un artículo de blog.

En esta breve y sencilla nota tecnica se explica la aplicacion de exclusiones y composicion sin SQL sobre documentos a nivel de interfaz de linea de comandos, lo más genéricamente posible intentando maximizar la compatibilidad y los destinatarios.

Desde los comienzos de la ahora tan de moda ciencia de datos, en el popular modelo relacional las tablas de datos están relacionadas entre sí mediante claves, y debido a que por motivos de uso eficiente de disco los conjuntos de tablas debían de estar normalizados, la relación de tablas de datos entre claves ha venido definiendo unas serie de operaciones muy típica.

Muchas de estas relaciones son muy parecidas o pequeñas variaciones del producto cartesiano de la matemática aritmética matricial, sólo con la única diferencia de que normalmente se hace una limitación en los resultados por igualdades de claves. Por ejemplo con dos tablas que hacen un uso eficiente de recursos de persistencia:

+---------+
| country |
+-----+---+------+------------+---------------+--------------------------+
|  id | code_two | code_three |    short_name |            complete_name |
+-----+----------+------------+---------------+--------------------------+
|   0 |       us |        usa | United States | United States of America |
|   1 |       ca |        can |        Canada |                   Canada |
|   2 |       mx |        mex |        Mexico |    United Mexican States |
| ... |      ... |        ... |           ... |                      ... |
| 314 |       ss |        ssd |   South Sudan |  Republic of South Sudan |
+-----+----------+------------+---------------+--------------------------+

+-------+
|  user |
+-------+---------+------------+
|    id |    name | country_id |
+-------+---------+------------+
|     0 |  Alicia |          2 |
|     1 |     Bob |          0 |
|     2 |    Carl |          1 |
|   ... |     ... |        ... |
|   108 | johndoe |          0 |
|   ... |     ... |        ... |
| 32993 |    Ziva |        314 |
+-------+---------+------------+

+-------+
| video |
+-------+---------+------------------------+--------+
|    id | user_id |                   name | cycles |
+-------+---------+------------------------+--------+
|   ... |     ... |                    ... |    ... |
|     4 |       0 |          star wars kid |    ... |
|   ... |     ... |                    ... |    ... |
|     8 |       1 |      dramatic chipmunk |    ... |
|   ... |     ... |                    ... |    ... |
|    15 |     108 |                badgers |    ... |
|   ... |     ... |                    ... |    ... |
|    16 |       1 |               narwahls |    ... |
|   ... |     ... |                    ... |    ... |
|    23 |       2 | crazy german gamer kid |    ... |
|   ... |     ... |                    ... |    ... |
|    42 |       0 |           keyboard cat |    ... |
|   ... |     ... |                    ... |    ... |
+-------+---------+------------------------+--------+

El uso del espacio es eficiente porque cada video no almacena ningún detalle acerca de su autor/a sino una referencia minimal a su fila correspondiente en otra tabla. Lo mismo para los usuarios respecto de sus países.

Para recuperar más rápidamente el número de videos que tienen los usuarios de una nacionalidad determinada, por poner un ejemplo, o cualquier otro cálculo combinación aritmética y/o algebraica de los datos contenidos en las tablas; se pueden hacer desnormalizaciones, que son operaciones muy interesantes, son la persistencia, o por lo menos el inventariado en el sistema para su posterior recuperación continuada, de una serie de operaciones aritméticas y/o algebraicas sobre otras tablas de datos u otras desnormalizaciones. Suena versátil, ¿verdad? Lo es. Está lejos de permitir todo lo que se le exigía a la ciencia de datos en los años diez del siglo veintiuno, pero ayuda bastante.

screen-shot-2016-09-02-at-18-04-37

La operación de ejemplo que se mencionaba, el número de videos subidos por usuarios de una nacionalidad determinada, podría tener p.e. el siguiente aspecto:

SELECT country.code_three, country.short_name, COUNT(*)
FROM country
JOIN user ON country.id = user.country_id
JOIN video ON user.id = video.user_id
GROUP BY country.id;

Analizándolo por partes, revisamos primero una parte menor de la expresión, ésta es:

SELECT *
FROM country
JOIN user ON country.id = user.country_id
JOIN video ON user.id = video.user_id;

La estrella indica, para entenderlo fácilmente, mostrar todas las columnas. El resultado será el siguiente, se muestra en modo expandido para mejorar su legibilidad:

----------
country.id = 0
country.code_two = 'us'
country.code_three = 'usa'
country.short_name = 'United States'
country.complete_name = 'United States of America'
user.id = 1
user.name = 'Bob'
user.country_id = '0'
video.id = 8
video.user_id = 1
video.name = 'dramatic chipmunk'
video.cycles = ...
----------
country.id = 0
country.code_two = 'us'
country.code_three = 'usa'
country.short_name = 'United States'
country.complete_name = 'United States of America'
user.id = 1
user.name = 'Bob'
user.country_id = '0'
video.id = 16
video.user_id = 1
video.name = 'narwahls'
video.cycles = ...
----------
[...]
----------
country.id = 2
country.code_two = 'mx'
country.code_three = 'mex'
country.short_name = 'Mexico'
country.complete_name = 'United Mexican States'
user.id = 0
user.name = 'Alicia'
user.country_id = '2'
video.id = 42
video.user_id = 0
video.name = 'keyboard cat'
video.cycles = ...
----------
[...]

Se produciría una explosión de combinaciones a consecuencia del uso de la operación de producto cartesiano, sin embargo al existir una limitación de combinaciones por identificación de pares relacionados, el conjunto de salida tiene la misma cardinalidad que el conjunto de entrada de mayor cardinalidad, el cual será probablemente o la tabla de vídeos o la de usuarios, según detalles de la plataforma que no nos interesan, pero no necesariamente en un sistema en inicialización (bootstrap).

Retomando la operación que queríamos introducir:

SELECT country.code_three, country.short_name, COUNT(*) AS videos_ct
FROM country
JOIN user ON country.id = user.country_id
JOIN video ON user.id = video.user_id
GROUP BY country.id;

La salida sería estructuralmente así:

+--------------------+--------------------+-----------+
| country.code_three | country.short_name | videos_ct |
+--------------------+--------------------+-----------+
|                 us |      United States |     78557 |
|                 ca |             Canada |      1728 |
|                 mx |             Mexico |     65537 |
|                ... |                ... |       ... |
|                 ss |        South Sudan |       163 |
+--------------------+--------------------+-----------+

El uso de la agrupación por columna y operaciones sobre columnas de otras tablas relacionadas distintas a la que hospeda a la columna sobre la que se agrupa comprime notablemente los resultados y entrega “nueva información” habitualmente combinación lineal de la información utilizada como base.

En sistemas UNIX desde tiempo inmemorial (al menos desde 2004 en FreeBSD) se puede hacer composiciones (al menos las más simples) en ficheros, sockets, comunicacion entre procesos o cualquier otro flujo de caracteres; sin necesariamente usar SQL; ya que se incluye un programa (join) al efecto.

Para los operadores de los históricos sistemas AIX, HP-UX, etc., finalmente ya en extinción; y para los usuarios de GNU/Linux, GNU/Hurd, BSD o sus derivados (notablemente Darwin); esto no es ninguna novedad. Para algunos usuarios de OS X podría serlo. Ellos pueden reproducir los ejemplos explicados más o menos fácilmente. Para los usuarios y operadores de sistemas Microsoft puede que sea un poco más complicado, pero también deberían poder usando Cygwin.

screen-shot-2016-11-30-at-23-45-23

Sean A y B documentos de alguno de los sistemas de persistencia parte de un sistema computacional, y ficheros, además de documentos, ya que contienen fichas; se piden los elementos de A no componibles con elementos de B (en base a una determinada clave de referencia) en un nuevo documento. La clave para la identificación de la relación, para hacer la composición, será la primera columna en A y la segunda columna en B. Para minimizar la confusión con las letras minúsculas, que van a representar celdas de información en los documentos, usaremos demo0 para referir A y demo1 para B.

$ cat demo0 demo1
a;0;oOo
b;1;bcd
c;0;abc
d;1;ooO
e;1;OOO
r;b;0;0;5;x;x;x
a;c;0;0.0001;-5;yy;y;yyy
$ _

El programa cat sencillamente concatena e imprime los contenidos de todos los documentos cuyo nombre es listado a continuación de la palabra. A modo de demostración, el documentodemo0 tiene cinco filas y tres columnas, mientras que el documento demo1 tiene dos filas y ocho columnas. Más adelante se mencionarán las magnitudes habituales en estudios y procesos de negocio en explotación.

El programa que hace la composición propiamente dicha es join:

$ join -t ';' -2 2 demo0 demo1 | tee demo2
b;1;bcd;r;0;0;5;x;x;x
c;0;abc;a;0;0.0001;-5;yy;y;yyy
$ _

Como paso intermedio adicional para obtener lo que se pide, una forma fácil de proceder es obtener filas con el formato igual que en demo0.

$ awk -F ';' '{ print $1 ";" $2 ";" $3 }' demo2 | tee demo3
b;1;bcd
c;0;abc
$ _

Se obtienen las filas de A deseadas (para ser excluidas de A y así obtener lo que se pide) en el formato exacto en el que se encuentran en A. La explicación que merece este paso no es más que la de que ese programa llamado awk es una de las más utilizadas de entre las múltiples herramientas que existen en UNIX, en donde incluso existen hasta navajas suizas, una de ellas esbusybox.

Si el número de campos es muy elevado, hecho que sucede en la mayor parte de los casos, se usa un procedimiento distinto llamado gensub (que tiene muchos usos posibles, algunos ciertamente arcanos) de esta forma:

$ awk 'BEGIN { f="([^;]+;)" }\
> { print gensub("("f"{0})("f"{3}).*", "\\3", "1")}' demo2 | \
> sed 's/;$//' | tee demo3
b;1;bcd
c;0;abc
$ _

Esta es sin duda la mayor de las dificultades en las que se entra en la nota técnica. Por motivos de que el shell fish gestiona los escapados de distinta forma a otros shell más antiguos (no sabemos si esto ocurre también en zsh porque no lo usamos ni lo hemos usado nunca), si se ejecuta esto en fish habrá que sustituir la secuencia “\\3” por “\\\3”. Básicamente la llamada a gensub (sustitución generalizada) está indicando que se va a hacer una vez la sustitución (tercer argumento) de la tercera parte (segundo argumento) de una expresión regular que contiene varios patrones (definición previa de f y primer argumento) por nada (argumento implícito).

Si se ha conseguido el paso anterior entonces finalmente se puede obtener lo que se pide en un último paso atómico.

$ grep -F -x -v -f demo3 demo0 | tee demo4
a;0;oOo
d;1;ooO
e;1;OOO
$ _

Extracto de man grep, la opción ‘-x’ ordena considerar la coincidencia a nivel de línea, la opción ‘-v’ marca la exclusión (negación de la coincidencia) sobre la inclusión que se hace por defecto, y la opción ‘-f’ indica que los patrones serán tomados de un documento (demo3) del sistema de persistencia de documentos de la máquina.

screen-shot-2016-09-02-at-18-01-42

Resumiendo y generalizando en un programa (script):

+---------------------------+
| join_exclude.sh:          |
+---------------------------+

#!/bin/sh


#   This is free and unencumbered software released into the public
# domain.
#
#   Anyone is free to copy, modify, publish, use, compile, sell, or
# distribute this software, either in source code form or as a compiled
# binary, for any purpose, commercial or non-commercial, and by any
# means.
#
#   In jurisdictions that recognize copyright laws, the author or
# authors of this software dedicate any and all copyright interest in
# the software to the public domain. We make this dedication for the
# benefit of the public at large and to the detriment of our heirs and
# succesors. We intend this dedication to be an overt act of
# relinquishment in perpetuity of all present and future rights to this
# software under copyright law.
#
#   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
#   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
#
#   For more information, please refer to <http://unlicense.org/>


#   KNOWN CAVEATS.
#
#     * Failures are expected for documents not using the same character
#       set encoding as the virtual terminal.
#     * Semicolons are expected as only possible CSV separators


#   This is returned by clean executions.
STATUS_SUCCESS=0

#   Incorrect usage: arguments count errored.
STATUS_ERR_INVALID_ARGUMENTS_CT=1

#   Incorrect usage: wrong argument syntax or semantics.
STATUS_ERR_INVALID_ARGUMENT=2


#   If running on OS X, the `echo` prgoram is being used, because the
# shell builtin might not have the '-n' argument to omit the EOL
# character.
if test `uname` = 'Darwin'
then
  ECHO=`which echo`
else
  ECHO=echo
fi


print_usage () {
  ${ECHO} -n "Use like 'join_usage.sh WORKING_DOC W_DOC_KEY_INDEX "
  ${ECHO} "EXCLUSIONS_DOC E_DOC_KEY_INDEX [OUTPUT_DOC]'"
  ${ECHO} -n '  Key indexes are expected to be in the interval (0, '
  ${ECHO} '#DOC_COLS_CT] for each document.'
}


cell_ct_ck () {
  TMP_DOC_0=`mktemp`
  TMP_DOC_1=`mktemp`
  sed s/[^\;]//g <$1 >${TMP_DOC_0}
  uniq <${TMP_DOC_0} >${TMP_DOC_1}
  wc -l ${TMP_DOC_1} >${TMP_DOC_0}
  ct=`awk '{ print $1 }' ${TMP_DOC_0}`
  rm ${TMP_DOC_0} ${TMP_DOC_1}
  if test ${ct} != '1'
  then
    ${ECHO} -n "Document $1 not well formed? Detected non homogeneous "
    ${ECHO} 'cell count int at least two data rows'.
    exit ${STATUS_ERR_INVALID_ARGUMENT}
  fi
}


col_ct () {
  TMP_DOC_0=`mktemp`
  TMP_DOC_1=`mktemp`
  sed s/[^\;]//g <$1 >${TMP_DOC_0}
  uniq <${TMP_DOC_0} >${TMP_DOC_1}
  wc ${TMP_DOC_1} >${TMP_DOC_0}
  ct=`awk '{ print $3 }' ${TMP_DOC_0}`
  rm ${TMP_DOC_0} ${TMP_DOC_1}
  COL_CT_RETV=${ct}
}


process () {
  TMP_DOC_0=`mktemp`
  TMP_DOC_1=`mktemp`
  join -t ';' -1 $2 -2 $4 $1 $3 >${TMP_DOC_0}
  awk 'BEGIN { f="([^;]+;)" } { print gensub("("f"{0})("f"{'\
"${I_W_DOC_COL_CT}"'}).*", "\\3", "")}' <${TMP_DOC_0} >${TMP_DOC_1} \
2>/dev/null
  sed s/\;$// <${TMP_DOC_1} >${TMP_DOC_0}
  EXCL_LINES_DOC=${TMP_DOC_0}
  # cp ${EXCL_LINES_DOC} ./excl_lines_removeme
  if test $5 = 'OUTPUT_UNSPECIFIED'
  then
    grep -F -x -v -f ${EXCL_LINES_DOC} $1
  else
    grep -F -x -v -f ${EXCL_LINES_DOC} $1 >$6
  fi
  rm ${TMP_DOC_0} ${TMP_DOC_1}
}


if test $# -lt 4 -o $# -gt 5
then
  ${ECHO} 'Bad usage'
  print_usage
  exit "${STATUS_ERR_INVALID_ARGUMENTS_CT}"
else
  if test $# -eq 4
  then
    MODE='OUTPUT_UNSPECIFIED'
  else
    MODE='OUTPUT_SPECIFIED'
  fi
fi

#   Correct number of arguments, do basic argument syntax and semantics
# checking.

INPUT_WORKING_DOC=$1

I_W_DOC_KEY_INDEX=$2

INPUT_EXCLUSIONS_DOC=$3

I_E_DOC_KEY_INDEX=$4

if test ${MODE} = 'OUTPUT_SPECIFIED'
then
  OUTPUT_DOC=$5
fi

if test ! -f ${INPUT_WORKING_DOC} -o ! -f ${INPUT_EXCLUSIONS_DOC}
then
  ${ECHO} 'One of the input documents is not?'
  exit ${STATUS_ERR_INVALID_ARGUMENT}
fi

if test ${MODE} = 'OUTPUT_SPECIFIED'
then
  if test -f ${OUTPUT_DOC}
  then
    ${ECHO} 'The output document exists?'
    exit ${STATUS_ERR_INVALID_ARGUMENT}
  fi
fi

#   Check the number of cells per row is homogeneous per input doc.

cell_ct_ck ${INPUT_WORKING_DOC}

cell_ct_ck ${INPUT_EXCLUSIONS_DOC}

#   Check the requested key indexes are valid to each document.

col_ct ${INPUT_WORKING_DOC}
if test ${I_W_DOC_KEY_INDEX} -le 0 \
    -o ${I_W_DOC_KEY_INDEX} -gt ${COL_CT_RETV}
then
  ${ECHO} -n "Invalid key index ${I_W_DOC_KEY_INDEX} specified for "
  ${ECHO} "document ${INPUT_WORKING_DOC}?"
  print_usage
  exit ${STATUS_ERR_INVALID_ARGUMENT}
fi

I_W_DOC_COL_CT=${COL_CT_RETV}

col_ct ${INPUT_EXCLUSIONS_DOC}
if test ${I_E_DOC_KEY_INDEX} -le 0 \
    -o ${I_E_DOC_KEY_INDEX} -gt ${COL_CT_RETV}
then
  ${ECHO} -n "Invalid key index ${I_E_DOC_KEY_INDEX} specified for "
  ${ECHO} "document ${INPUT_EXCLUSIONS_DOC}?"
  print_usage
  exit ${STATUS_ERR_INVALID_ARGUMENT}
fi

#   Arguments enough good. Process.

if test ${MODE} = 'OUTPUT_SPECIFIED'
then
  process ${INPUT_WORKING_DOC} ${I_W_DOC_KEY_INDEX} \
      ${INPUT_EXCLUSIONS_DOC} ${I_E_DOC_KEY_INDEX} ${MODE} \
      ${OUTPUT_DOC}
else
  process ${INPUT_WORKING_DOC} ${I_W_DOC_KEY_INDEX} \
      ${INPUT_EXCLUSIONS_DOC} ${I_E_DOC_KEY_INDEX} ${MODE}
fi

exit ${STATUS_SUCCESS}

#   END OF SHELL SCRIPT.

AVISO LEGAL: Todo el contenido de este artículo está sometido a las leyes de propiedad intelectual aplicables a bitácoras en Internet en los estados nación soberanos a los que se adhieran potenciales ofendidos y ofensores en la extensión que decidan los tribunales, salvo indicación en contra por parte (join_exclude.sh) – entendiendo el artículo (NOTA TÉCNICA #20161200) como el todo – en extensión restringida y fácilmente identificable, además de perfecta e inequívocamente delimitada por los siguientes 5.395 caracteres (y bytes) a partir de la primera aparición de la secuencia ‘#!/bin/sh‘, incluyendo la secuencia referida e incluyendo espacios en blanco (whitespace) en su definición normalizada según la documentación de Unicode versión 9 (aparentemente sin edición en castellano disponible a fecha de entrega de este texto) como character property, terminando en la secuencia ‘# END OF SHELL SCRIPT‘, en la cual prima en lo sostenible por cada marco jurídico aplicable la voluntad de U.P, otorgante de licencia. El documento ejecutable parte (‘join_exclude.sh‘) ha sido elaborado en su completa extensión por el otorgante de licencia fuera del marco de cualquier relación contractual, en particular laboral, con cualquier persona física o jurídica, en particular Madiva Soluciones S.L., Madiva, fuera de las instalaciones de Madiva (tanto presencial como remotamente (telecommuting)) y del horario u otras obligaciones o responsabilidad laboral del otorgante de licencia para con Madiva, sin que además se haya utilizado ni directa ni indirectamente para su elaboración algún tipo de conocimiento aportado ni directa ni indirectamente por Madiva. El otorgante de licencia es por los motivos mencionados evidentemente el único responsable legítimo de las decisiones sobre el ámbito de publicidad y licenciamiento de parte (‘join_exclude.sh‘). FIN DEL AVISO LEGAL.

Para quien pueda estar leyendo en tiempo contemporáneo a la escritura del artículo y se pueda estar preguntando por qué un programa completamente en inglés en un artículo de una serie en la que se intenta no usar nada el inglés llegando incluso a forzar el límite a justo antes de introducir palabras nuevas no existentes en Español/Castellano. La respuesta es muy sencilla: tiene que ser así y no puede ser de otra manera. No hace falta argumentación porque su obviedad es tal que no se va a entrar en ese nivel de detalle en este artículo. Sólo existe una carta de excepción que se puede (evidentemente sin ser imprescindible) usar para escapar a esta regla: el caso de software militar en algunos de los estados nación de tradición chovinista, como puedan ser Francia, Italia o España, por empezar correctamente la lista con los casos más extremos de esta particularmente absurda y fútil lacra anti internacionalista.

En Madiva utilizamos una versión supervitaminada (quizás que ya no tiene nada que ver e incluso sin ser ya Shell) del documento ejecutable mencionado para extraer conjuntos de entrenamiento y validación a partir de bases de datos en procesos de negocio que incluyen procesamiento y análisis sobre conjuntos masivos de datos (big data). Un caso típico es que el documento que se representa aquí como demo0 sea de varias decenas de columnas y decenas de millones de filas y que el documento representado como demo1 sea de cientos de columnas y cientos de miles de filas.

Programar es difícil. Aparte de que a algunas personas les pueda resultar más fácil que a otras, o lo parezca, quizás la realidad sea más bien que a algunas personas les puede gustar más que a otras o por lo menos parecer más interesante. En cualquier caso, programar sistemas grandes siempre es complicado. No hacerlo es, SIEMPRE, la alternativa más inteligente. Por eso no quieres obligar a aprender a programar a personas a las que no les resulte sin ninguna duda interesante. Por eso tender a incrementar las tasas de software de alto nivel sobre el conjunto de todo el software, siempre que se pueda, ayuda; escribir programas para tareas de procesamiento por lotes (scripts) ha sido durante generaciones una de las técnicas para hacer eso.

Migrar código C/C++ o Java a Perl, Python, Tcl o incluso shell, o mas recientemente Groovy, Scala o Ruby; antiguamente lo era, cuando las cosas eran diferentes a hoy, que la situación normal es la más deseable de escribir todo en alto nivel en un primer momento, en Scala, Ruby, Python o JavaScript, para luego optimizar procedimientos (workflows) reescribiendo servicios críticos puntualmente en Java o C++, u aplicándoles técnicas de optimización de compilación para Python y JavaScript como Cython, asm.js, TypeScript, Dart, etc., o lo que sea aplicable a Scala, Ruby o similares.

Escribir software de integración también es difícil. Si es posible, es mejor usar software que pueda interoperar suavemente usando interfaces perfectamente definidas, como por ejemplo el protocolo de terminal; en vez de perder el tiempo escribiendo módulos de integración de bajo potencial de reutilización y por tanto minorado valor añadido.

screen-shot-2016-09-02-at-18-00-35

Sí puede existir valor añadido en software de integración cuando este sea un producto en sí mismo. Pero descartad el software de integración que sea malo por su esencia (escrito en Java o Ruby es bastante probable que así sea), o por que percibais dejadez de su equipo de mantenimiento de cara a sus obligaciones para con la versión libre (si ya existe) o más aún respecto de la o las versiones restringidas, o cualquier otra razón que os parezca obvia.

Si trabajando con tareas ETL y se plantea empezar a usar Pentaho (un software de integración en particular), y a primeras de cambio ordenando una conexión a un punto final usando HTTPS Pentaho no soporta eso correctamente para todos los tipos de endpoint, la conclusión correcta es que Pentaho es basura. Si no hay el tiempo y las ganas necesarias para hacer una versión heredera (fork) de Pentaho que funcione de una forma mínimamente respetable, habrá que desistir de usar o intentar adoptar Pentaho.

Esto mismo aplica o ha aplicado a otro software tan dispar como pueden ser: nuevas empresas (start-ups) que envejecen sin terminar ni de arrancar apropiadamente ni de pivotar convenientemente ni de morir (por ejemplo Speaky), buena parte del software freemium supuestamente maduro (por ejemplo CARTO, además de Pentaho) con versión abierta, y afecta también a servicios gestionados sin versión abierta como algunas partes de SourceForge, de BitBucket e incluso de GitHub (véase la clásica discusión sobre GitHub en el mirror GitHub de Linux en mayo de 2012; en realidad todos los servicios de hospedaje de código son bastante malos menos GitLab, por supuesto incluyendo a otros productos minoritarios como Launchpad o CodeCommit, que por algo son minoritarios), o sistemas enteros como obviamente las distribuciones de software no libre de Microsoft (que encima seguían siendo de pago cuando se escribió este artículo), pero se podrían encontrar fácilmente argumentos también contra Mac OS, Amazon Linux, o no imaginemos ya acerca de aparentes contrasentidos como Oracle Linux.

Por poner un ejemplo de aroma que fue especialmente doloroso. Si a medidados de 2016 la guía pública de instalación del software todavía no contempla entornos Debian o Red Hat like(CentOS); mal, muy mal, pero dentro de lo horrible es aceptable. Que sólo contemple Ubuntu pero todavía se mencione la versión 12.04 como la más reciente, es una alerta (sólo una, pero con el tiempo aprenderéis a detectar otras) ya bastante más peligrosa de las que se advienen a la revelación de una base de código con déficits severos de inversión; en un nuevo mundo en el que la paquetería se está continuamente reclicando y reentregando via yum/rpm, apt, npm, pip, brew, pacman y el largo etcétera que conocemos los desarrolladores de software. Los desarrolladores del software normal, no otro tipo de gente especializada y anichada como son por ejemplo los desarrolladores de software COBOL o Java.

Es lamentablemente extra cierto en casos de software hecho en España como Speaky, CARTO o Redbooth. Es público y/o notorio en ciertos círculos que todas estas empresas tienen o han tenido problemas de bases de código deficientemente mantenidas. Como “aquí todos somos amiiigos, chico”; no vamos a revelar quien ha arreglado ya sus problemas y quien no. Porque además no se trata de eso, sino de que todos reconozcamos que tenemos un problema. Después ya discutiremos cuánto de causa es por mala financiación, cuánto por problemas de formación y cuánto debido a la naturaleza del capital humano; qué hechos realimentan a qué otros; y cómo solucionarlo. Al final no se trata más que de la apariencia contemporánea de un problema que ha habido durante generaciones. Si seguimos mirando para otro lado se agravará.

Cerrando esta divagación y ya el artículo, que son 4.096 palabras ya; si te parece bien lo que hacemos, o comprendes que en determinadas circunstancias lo hagamos así pero en general discrepas de la forma o el cómo, puede que tengamos un trabajo para ti. O puede que no en este momento, incluso puede que no nunca de ninguna manera. Aún así quizás quieras arriesgarte a darnos una oportunidad (porque, estáte seguro, no son las empresas las que te dan las oportunidades a ti, es al revés), resuelve el reto (http://madivachallenge.appspot.com) y puede que aprendas algo de nosotros. Y puede que no. Nosotros procuraremos aprender de ti incluso si por algún motivo esto pueda acabar siendo lo único que podamos aprender de ti.

Gracias.

U.P

Continúa leyendo este artículo

Continúa leyendo artículos en nuestro blog