lunes, junio 30, 2014

Oracle Instaclient SQL Plus en Ubuntu

Probablemente algunos (como yo) requieren tener instalado SQL Plus de Oracle en sus equipos sin tener que instalar Oracle completo. Para que funcione correctamente hay que hacer algunas cosas, y aquí les explico cuales son para que se ahorren algunos dolores de cabeza.

Paso a paso

  1. Descargar el InstaClient: Oracle es "algo" quisiquilloso cuando se trata de sus herramientas, así que la opción es buscar en Google o navegar directamente en el sitio de esta empresa.
  2. Descomprimir InstaClient: Típicamente habrán descargado el archivo comprimido. Cuando se trata de herramientas que requieren instalación manual yo las dejo en la carpeta /opt

  3. Configurar variables de ambiente: Estas son varias, así que creé un script que las setea y des-setea según corresponda:
unset NO_PROXY
unset UBUNTU_MENUPROXY
unset no_proxy

unset ORACLE_HOME
export LD_LIBRARY_PATH=/opt/instantclient_12_1
para la versión 11_2 es análogo pero tendrán que poner la carpeta que corresponde.

Finalmente ejecutar SQL Plus: Fácil y bonito, desde la misma ruta
./sqlplus
 Y eso debiera funcionar.

Bonus: Si quieren ejecutar  una conexión para administrar una base de datos remota (y poder reiniciar la base con un shutdown abort, por ejemplo) el comando es:
./sqlplus 'usuario/clave'@IP_de_la_BD/SID as sysdba

obviamente cambiando los datos acorde.

lunes, junio 16, 2014

Emprendimiento busca desarrollador: Aquí hay un problema

Hace poco les contaba algunas apreciaciones personales respecto a los emprendimientos TI. Hoy les quiero comentar, queridos y honorables lectores, un par de problemas que he notado, cuando los mismos chicos que ayudaba con su emprendimiento comienzan su búsqueda de  desarrolladores.

Cito el aviso (y omito los enlaces para proteger a los "inocentes"):
Chicos estamos buscando a un desarrollador para que se convierta en nuestro CTO . Aquí mayor información ... [link]
Somos un NUEVO EMPRENDIMIENTO y estamos en busca de un DESARROLLADOR Back-end, idealmente con conocimientos de Front-end, nos encontramos en el desarrollo del M.V.P.

Lenguajes: PHP, Java, Ruby on Rails, CoffeeScript y bases de datos como MySql, Mongodb.

Si eres Entusiasta, Emprendedor y te gusta la Música, contactanos para concretar una reunión!

Buscamos alguien que llegue a ser nuestro socio, por ahora no hay dinero de por medio pero si un gran Proyecto.

Start Small - THINK BIG!
Lo primero que me llama la atención del aviso es el tipo de requerimientos que se solicita:
  • PHP
  • Java
  • Ruby on Rails
  • CoffeeScript
  • Bases de datos como MySql, MongoDB
Personalmente aún no me ha tocado ver un proyecto en el cual converjan PHP, Java y RoR, por lo que se me hace que fue producto de una búsqueda en Google de que lenguajes y tecnnologías son los más utilizados en los emprendimientos.
Con las bases de datos me sucede algo similar.

Lo no tan bueno de considerar en el aviso una variedad de tecnologías es que refleja poca claridad respecto de que se necesita en términos informáticos.

Lo segundo que me llama la atención es lo que se busca:
  • Un socio y CTO

CTO es el nombre de fantasía para "el informático" del equipo (Chief Technology Officer, que le dicen) y todas las siglas de CEO, CDO, etc. son las denominaciones de moda de las startups para los puestos "gerenciales". A proposito ¿no que estaban buscando desarrollador? ¿CTO desarrollador? ¿Existe eso?

Esto por si mismo no es tan terrible, salvo que se suma a lo tercero qeu me llama la atención:
por ahora no hay dinero de por medio pero si un gran Proyecto.
El problema aquí es que el CTO al ser "EL informatico del equipo", va a ser además quien se haga cargo de las definiciones técnicas, y de buena parte de la implementación, si es que no toda.

Mano en el corazón: ¿Trabajarían gratis?, considerando que por muy emprendimiento que sea igual hay que cumplir con los plazos que se hayan definido.

Y sigo viendo problemas, el "gran Proyecto" es una calificación absolutamente subjetiva para una idea que no se conoce a priori.
Decir inmediatamente que no hay dinero mata al instante el posible interés de buena parte de los potenciales candidatos. No le da tiempo al emprendimiento de venderles su excelente idea y proyecto, y convencerlos que realmente vale la pena tomar el riesgo de formar parte de este equipo.

¿Cómo mejoraría el aviso?

  1. Eliminar el exceso de honestidad. OK, sabemos que no hay dinero, pero no es estrictamente necesario mencionarlo, sobretodo si quieres darle la oportunidad a tu emprendimiento de convencer a los candidatos. Sin tener conocimientos formales en marketing, creo no equivocarme al pensar que el objetivo es vender la idea, convencer que es buena. Si no motivas a tus "clientes" (en este caso candidatos al puesto de desarrollador) dificilmente van a "comprar" tu idea.
  2. Eliminar la promesa de CTO. Se ve bonito, pero ¿qué buscan? ¿Desarrollador o CTO o ambas?... ¿han evaluado la compatibilidad real de ambos cargos?
    Aparte, y esta es opinión 100% personal, ser CTO de un emprendimiento que aún no se concreta es ponerse un título de papel higiénico, se deshace con agua. No es algo que pondría en mi LinkedIn.
  3. Ser claro en las especialidades requeridas para postular. Un profesional que maneje esta variedad de tecnologías no es un profesional barato, y posiblemente tampoco tenga demasiado tiempo disponible para dedicar a la filantropía, ergo no muy compatible con emprendimientos donde no haya un incentivo monetario.

jueves, junio 05, 2014

AngularJS UI Router, resolve & Unknown service provider ERROR

La noche de ayer me quedé en la oficina terminando de corregir algunos aspectos de una aplicación. Una aplicación móvil híbrida con AngularJS, Angular UI Router y Bootstrap. El código estaba bien, pero uno de mis controladores estaba gatillando el error Unknown service provider.

Angular UI Router  permite conceptualizar una aplicación web como una máquina de estados.
Cada acción que se realiza puede ser un estado separado, y cada estado, desde el enfoque de desarrollo que estamos adoptando, tiene sus propias vistas.
A su vez, cada vista esta manejada por su propio controlador, y eventualmente antes de cargarse puede requerir que resuelva determinada petición (resolve).

Ejemplificando con código:

app.config(function ($stateProvider, $urlRouterProvider) {
    $urlRouterProvider
          .when('/', '/login')
          .otherwise('/');


    $stateProvider
        .state('login', {
            url: '/login'
            , views: {
                'login': {
                    templateUrl: 'include/login.include.html'
                    , controller: 'loginCtrl'
                }
            }
            , onEnter: function() {
                loggedin = false;
                localStorage.setItem('loggeduser', null);
            }
        })
        .state('plan', {
            url: '/plan'
            , views: {
                'menu': {
                    templateUrl: 'include/menu.include.html'
                    , controller: 'menuCtrl'
                } 

                , 'plan': {
                    templateUrl: 'include/plan.include.html'
                    , controller: 'planCtrl'

                }
                , 'client': {
                    templateUrl: 'include/client.include.html'
                    , controller: 'clientCtrl'
                    , resolve: {
                        clients: ['pouchWrapper', function(pouchWrapper){
                            var cliMap = function(doc){
                                if(doc.dbtable === 'cli'){
                                    emit(doc, null);
                                }
                            }

                            // Rescata el listado de clientes desde un repositorio local
                            return pouchWrapper.retrieveList(cliMap);
                        }]
                    }                  
                }            }           
            , onEnter: function($location) {              
                if(!loggedin){
                    console.log('No ha ingresado al sistema');                                       
                    $location.path('/logout');
                }
            }
        }) ;

});

Si se dan cuenta algunas plantillas (template) tienen indicado cual es su correspondiente controlador (controller).

Y en el controlador clientCtrl

app.controller('clientCtrl', ['$scope', '$location', 'clients', 
    function($scope, $location, clients){
        // ... aqui va mucho código
    }]);

El problema es que estando bien codificada la máquina de estados, y cargando cada vista como correspondía, AngularJS reportaba el error Unknown service provider para clients, sin indeicar origen del error ni líneas de referencia (es una maravilla depurar código a ciegas :-/ ).
Después de mucho buscar y leer en la Wiki y sección de Issues del Github de Angular UI Router, llegué a un post en StackOverflow (lo siento, perdí el enlace  original), donde explicaban que
el error se genera cuando el estado tiene el controlador referenciado tanto en la configuración como dentro de la plantilla.


En la plantilla include/client.include.html

<div data-ng-controller="clientCtrl">
    <!-- ... aquí va el contenido de la plantilla para el bloque client -->
</div>


El error lo he destacado en negrita, el controlador o está referenciado en la configuración del estado, o está referenciado dentro de la plantilla, pero NO en ambos.

Después de ver la solución, y corregir el problema (eliminando la referencia al  controlador en la plantilla) es entendible lo que está sucediendo. Si recuerdan, el controlador recibe como tercer parámetro clients (que es lo indicamos en el atributo resolve del estado, que queremos resolver antes de desplegar) . Al poner la referencia directamente en la plantilla, clients queda vacío, ergo Unknown service provider.