lunes, 30 de septiembre de 2013

Aprendiendo Dart (I)


Es difícil evolucionar a la velocidad de la tecnología, pero hay que intentar hacerlo. Puede que Dart sea en algún tiempo una alternativa en el mundo de la web frente al famoso JavaScript, entonces vamos a aprender un poco de éste.

Palabras reservadas:
abstract continue factory import return try
as default false in set typedef
assert do final is static var
break dynamic finally library super void
case else for new switch while
catch export get null this with
class external if operator throw
const extends implements part true
Variables:

En Dart las variables se declaran así: 

var numero = 1;

O así:
int numero = 1;

Para el primer caso la variable es dinámica; para el segundo la variable es apta para números enteros, esto permite que herramientas como compiladores y editores le ayuden durante el desarrollado a evitar errores en su programa.

Finales y Constantes:

A diferencia de JavaScript, Dart permite variables finales y constantes así:
final String name_bob = 'Bob';

final name = 'Bob';

const PI = 3.141594;


Tipos:

  • dynamic: Tipo dinámico de datos
    • var x = 1;
  • int: Tipo numérico de datos, almacena números enteros. Hereda de la clase num.
    • var x = 1;
  • double: Tipo numérico de datos, almacena números con doble precisión (punto flotante) de 64 bits  . Hereda de la clase num.
    • var x = 1;
  • String: Tipo de datos para cadenas de texto, usa codificación UTF-16. Permite usar comillas dobles o simples, además de que cuando ponen tres comillas (dobles o sencillas) al principio y final de cada cadena permiten cadenas multilínea: 
    • String cadena1 = "Hola Mundo!!!";
      String cadena2 = 'Hola Nuevo Mundo!!!';
      String cadena3 = """Esta cadena
      permite multiples
      lineas en una cadena""";
      String cadena4 = '''Y esta cadena
      Tambien permite
      varias lineas''';
      
  • Booleans: Tipo de datos de valores de verdad, tiene dos literales, true y false, además  a diferencia de JavaScript cualquier valor diferente a true es falso: 
    • boolean b = true;
      if(b){
          print(b);
      }
      
  • Lists: Tipo para colección de datos
    • List lista = new List();
      List lista = [1,2,3,4];
  • Maps: Tipo de datos para arreglos asociativos (llave:valor), permite la asignación de nuevos valores en tiempo de ejecución de la misma manera que JavaScript
    • Map mapa = {"Hola":"Mundo"};
      mapa["Nuevo_Valor"]="No Toques mi Código";
      
Ésta fue una muy breve introducción al lenguaje, todo fue extraído de la documentación oficial del lenguaje. espero que les guste y continuaremos en una próxima ocasión.

sábado, 28 de septiembre de 2013

El molde de la taza, Java y las interfaces


Es fácil hacer  en Java un programa con un par de clases, sin embargo la potencia de un lenguaje como éste se ve a la hora de usar la artillería orientada a objetos. En general hay conceptos complejos dentro de la programación orientada a objetos, y dos que especialmente no son muy fáciles de entender, las interfaces y las clases abstractas, esta vez explicaré qué es una interfaz.


Hagamos un molde
¿Un molde?, ¿Qué tiene que ver un molde y una interfaz?. Es extraña la manera en que comparo esto, pero si nos detenemos a pensarlo un poco puede que sea claro. Una interfaz es una estructura de datos que contiene la definición (también se le llama contrato) de los métodos que debería tener una clase o su descendencia pero éstas no tienen lógica alguna, es decir, una interfaz es una guía de cómo debería lucir una clase, pero no es propiamente la implementación de la misma, es decir, es el molde de cómo debería ser una clase, a continuación veamos un ejemplo de esto: 

// Ejemplo de Interfaces
interface MoldeTaza{
    public void Servir(Object contenido);
    public void Vaciar();
}
// fin

Como vemos en el ejemplo se crea la interfaz y a su vez en esta se declaran los métodos, pero no se escribe el contenido de los mismos, únicamente se pone un punto y coma para reemplazar el cuerpo del método. Ahora bien, después de tener nuestro molde vamos a crear cosas con el.
// Ejemplo de Interfaces
class TazaDeCafe implements MoldeTaza{

    Object contenido;

    @Override
    public void Servir(Object contenido){
        this.contenido = contenido;
        System.out.println("El café esta servido...");
    }

    @Override
    public void Vaciar(){
        this.contenido = null;
        System.out.println("Se ha terminado el café...");
    }

}
// fin

Como vemos en el código anterior la clase TazaDeCafe implementa la interfaz MoldeTaza (Los métodos de las interfaces no se heredan, se implementan), es decir, los métodos que se describieron en la interfaz se reescriben con el cuerpo que corresponde de acuerdo a la clase, además se pone la anotación Override, que especifíca que el método no es propio de esta clase puesto que la primera vez que se escribió fue en una clase padre o en un interfaz que ha sido implementada. 

Y ¿Para qué usar moldes?
Tal vez una de las cosas más complejas de las interfaces no son en sí cómo hacerlas, lo que realmente las hace complejas es saber cuándo y por qué usarlas. Para entender esto debemos partir de un caso de prueba. Supongan que están haciendo un juego de ajedrez, todos sabes que hay un tablero en el cual hay varios tipos de fichas, todas estas son diferentes, se mueven diferente, se ven diferentes, pero al fin y al cabo no dejan de ser fichas. Este seria un caso ideal para usar interfaces, con una interfaz ficha definiremos todas las posibles acciones que tiene una ficha y cómo debe responder el tablero ante los objetos que implementan ésta interfaz, pero a la hora de hacer una ficha específica como el Caballo se especificarán la manera en que debe ejecutar las acciones este objeto.

Espero que les sea de utilidad.

jueves, 26 de septiembre de 2013

En el blanco. Dart, otra opción para la web


Hasta el momento la mejor y única opción para desarrollar aplicaciones web es JavaScript, y con la flamante puesta en marcha de Html5 las dudas al respecto son cada vez menos, sin embargo hace ya casi dos años Google trajo a la luz un lenguaje con el que esperaba entregar una nueva alternativa, Dart.

¿Qué es Dart?
Dart (inicialmente Dash) es un lenguaje programación que no tiene como objetivo reemplazar JavaScript, pero sí ofrecer una alternativa más moderna. Dart es un lenguaje orientado a objetos, muy similar a java en muchos aspectos pero con la posibilidad de ser tan dinámico como JavaScript, es tipado pero tiene un tipo especial llamado dynamic, el cual permite crear variables sin especificar su tipo, tal como en JavaScript.

Chromium incluye una máquina virtual para ejecutar Dart, Google anunció que proveerá máquina virtual a sus competidores para permitir que usen el lenguaje en otros navegadores y además de esto existe la posibilidad de compilar los programas de Dart a JavaScript.

A probar puntería
Muy bien, ahora probemos un poco esto, primero es necesario descargar el sdk de Dart, pueden hacerlo desde éste lugar, el cual trae consigo eclipse y una versión ligera de Chromium, después de esto crean un nuevo proyecto, puede ser web o para una aplicación de consola (línea de comandos), el siguiente código muestra un poco del lenguaje:
// Inicio del ejemplo
// tets.dart
import 'dart:html';


class Auto{
  var _name; // variable privada tipo dynamic
  
  void setName(var nombre){
    this._name = nombre;
  }
  
  String toString(){
    return _name;
  }
  
  void clicked(Object o){
    window.alert("Hola, Soy un Chevette...");
  }
  
}

void main() {
  Auto chevette = new Auto();
  chevette.setName("Chevette");
  query("#auto")..text = "Auto: ${chevette.toString()} "
  ..onClick.listen(chevette.clicked);
}
// Fin

A nivel de lenguaje no hay mucha diferencia entre Dart y otros lenguajes imperativos orientados a objetos como Java, para hacer comentarios se usa la secuencia "//", las llaves, los paréntesis y más, pero hay cosas que hacen de éste un lenguaje que simplifican el desarrollo de una aplicación, como la eliminación de las palabras reservadas public y private, características de los lenguajes orientados a objetos, en éste todo es público por defecto y se convierten en privados cuando el nombre inicia con "_".
Como vemos en el código anterior existe una clase llamada Auto, ésta tiene un atributo privado llamado _name, y hay un método para cambiar el valor de _name, y hay un método que retorna un objeto tipo cadena que retorna el contenido de la variable _name. Además de esto podemos modificar el DOM mediante la orden query, ésta fue importada de la librería html de Dart y de una manera muy similar a la de JQuery obtenemos elementos con un id específico mediante el carácter '#'.
Dart al igual que Java, C y C++ usa el método main para iniciar el programa.
Una de las cosas extra es que Dart permite hacer múltiples operaciones sobre el mismo elemento del dom mediante el operador '..' , un ejemplo claro es el contenido del método main.

A continuación el código HTML que acompaña el código anterior:

<!-- Inicio del ejemplo -->
<!DOCTYPE html>

<html>
  <head>
    <meta charset="utf-8">
    <title>Test</title>
    <link rel="stylesheet" href="test.css">
  </head>
  <body>
    <h1>Hello world from Dart!</h1>
    
    <div id="auto">      
    </div>
    
    <script type="application/dart" src="test.dart"></script>
    <script src="packages/browser/dart.js"></script>
  </body>
</html>
<!-- Fin del ejemplo -->

Hacer esto no es complejo y gracias al IDE que provee la página web del proyecto,  éste IDE permite escribir un proyecto, depurarlo y finalmente generar todo el código JavaScript.

Interesante propuesta de Google, tendremos que esperar para ver qué ocurre con éste prometedor lenguaje.

miércoles, 28 de agosto de 2013

Mi propio navegador web en Android

En uno de los artículos anteriores hicimos un navegador web con Python y PySide, así que en esta entrada vamos a hacer algo parecido con Android.

Primero lo primero, un nuevo  proyecto
Creamos un nuevo proyecto de Android, éste debe tener una actividad principal sobre la cual trabajaremos, en este caso el nombre de la actividad es Inicio.

Ahora, el diseño
En la carpeta layout abrimos el layout asociado a la actividad principal, en este caso su nombre es activity_inicio.xml

El layout debe tener un EditText para la url de  destino, y un WebView así:

Además de esto es necesario editar el archivo XML del menú, para poner los botones atrás y adelante.

Y final mente el código en Java:
public class Inicio extends Activity {

    ProgressDialog progressBar;
    private int progressBarStatus = 0;
    private Handler progressBarHandler = new Handler();
    EditText txtUrl = null;

    public final String HOME = "http://notoquesmicodigo.blogspot.com/";

    private class MiWebViewClient extends WebViewClient {

        private void iniciaCarga(WebView v) {
            if(progressBar==null){
                progressBar = new ProgressDialog(v.getContext());
            }
            if (progressBar != null && !progressBar.isShowing()) {
                progressBar.setTitle("Espere...");
                progressBar.setMessage("Cargando página...");
                progressBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);
                progressBar.setCancelable(false);
                pbShow();
                progressBarStatus = 0;
                runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                    progressBarHandler.post(new Runnable() {
                    public void run() {
                        try {
                             progressBar
                              .setProgress(progressBarStatus++);
                        } catch (Exception e) {
                        }
                      }
                     });
                    }
                });
            }
        }

        private void pbCancel() {
            try {
                progressBar.cancel();
            } catch (Exception e) {
                Log.e("ERROR", e.getMessage());
            }
        }

        private void pbShow() {
            try {
                progressBar.show();
            } catch (Exception e) {
                Log.e("ERROR", e.getMessage());
            }
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            iniciaCarga(view);
            if (txtUrl != null) {
                txtUrl.setText(url);
            }
            super.onPageStarted(view, url, favicon);
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            pbCancel();
        }
    }

    private class MiChromeWebViewClient extends WebChromeClient {

    }

    WebView wv_pagina;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_inicio);
        wv_pagina = (WebView) findViewById(R.id.wv_pagina);
        txtUrl = (EditText) findViewById(R.id.txtUrl);
        wv_pagina.clearHistory();
        wv_pagina.clearCache(true);
        wv_pagina.setWebViewClient(new MiWebViewClient());
        wv_pagina.setWebChromeClient(new MiChromeWebViewClient());
        wv_pagina.getSettings().setJavaScriptEnabled(true);
        runOnUiThread(new Runnable() {

            @Override
            public void run() {
                wv_pagina.loadUrl(HOME);
            }
        });

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_inicio, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (wv_pagina != null) {
            switch (item.getItemId()) {
            case R.id.menu_back:
                if (wv_pagina.canGoBack()) {
                    wv_pagina.goBack();
                }
                break;
            case R.id.menu_forward:
                if (wv_pagina.canGoForward()) {
                    wv_pagina.goForward();
                }
                break;
            }
            return true;
        } else {
            return super.onOptionsItemSelected(item);
        }
    }

}

Ahora bien, debemos tener en cuenta varias cosas:

  • Para que nuestro navegador no lance otro de los navegadores del celular (como Chrome por ejemplo) debemos crear clases propias que hereden de WebViewClient y WebChromeClient.
  • La mayor parte del código esta en la clase MiWebViewClient para el ProgressDialog que usamos.
  • En la clase MiWebViewClient sobrecargamos los métodos onPageStarted y onPageFinished para poder lanzar el ProgressDialog y cambiar la URL en la caja de texto de la dirección.
  • En el evento onOptionsItemSelected ponemos los eventos de atrás y adelante filtrando los elementos menu_back y menu_forward.
El resultado es éste:


El código esta disponible en GitHub, si tiene alguna duda pueden preguntar en los comentarios.

martes, 27 de agosto de 2013

Consoleando (III)

En artículos pasados he intentado mostrar un poco de las potencia de la consola, pero en realidad la potencia de la consola de los sistemas basados en Unix está en la posibilidad de tener muchísimos pequeños programas que se enlazan de manera mutua para hacer una labor compleja, por éste motivo existen las tuberías o Pipes.

Entre un Tubo...
El uso de tuberías o Pipes permite que el usuario ejecute un proceso y con la información de salida de éste alimente un nuevo proceso, de esta manera se pueden encadenar de manera sucesiva la cantidad de tareas que se desee. El operador encargado de las tuberías es la barra vertical ( | ), ésta es usada en otros lenguajes como el operador de bits OR, para el caso de bash ésta se usa como operador de tubería.

Y, ¿Cómo se usa?
Su uso es sencillo: Basta con separar los procesos con la barra vertical ( | ), lo cual hará que la salida del primer proceso ejecutado sea la entrada del segundo proceso, así:
ps -ef | grep root
En éste ejemplo podemos ver dos instrucciones:
La primera es ps con el argumento -ef, de ésta manera se hace una lista de todos los procesos existentes y muestra muchos de los datos relevantes del proceso, entre estos el comando con el que fue lanzado.
La segunda instrucción es grep con el argumento root, ésta instrucción filtra todas las líneas que contengan la palabra root, de manera que al unir ambas tareas mediante una tubería se mostrarán todos los procesos que contengan la palabra root, es decir, se filtrarán los procesos del usuario root y aquellos que en la línea de comandos tengan ésta palabra.

Un ejemplo más
¿Cómo cerrar un proceso de acuerdo al nombre?, esa es una de las tareas que podrían ser automatizadas. Por ejemplo, si hacemos una aplicación cliente-servidor que internamente usa la instrucción fork (ésta instrucción crea copias del proceso original) podríamos eliminar todas las instancias de la aplicación mediante el uso de las siguientes instrucciones:

  • ps : Lista todos los procesos de la máquina.
  • grep : Filtra las aplicaciones de acuerdo a un patrón especificado.
  • awk : Permite hacer operaciones sobre cadenas, como separarlas por palabras (tokenizarlas) y más.
  • xargs : Pasa los parametros que recibe mediante la tubería a una instrucción especificada.
  • kill : Termina una aplicación.
y las instrucciones se encadenarían así (en una sola línea):

ps -ef | grep NombreProceso | grep -v grep | awk '{print $2}' | xargs kill

La anterior secuencia de comandos y tuberías funciona así:

  1. ps -ef : Lista todos los procesos de la máquina.
  2. grep NombreProceso : Filtra todos los procesos que contengan la subcadena NombreProceso.
  3. grep -v grep : Quita las líneas que contengan la cadena grep (para que no se incluya el proceso del filtro anterior).
  4. awk '{print $2}' : Entrega únicamente el segundo token de cada línea, para éste caso es el número de identificación de cada proceso.
  5. xargs kill : Ejecuta el comando kill sobre cada uno de los números de proceso entregados.
Una de las grandes ventajas de la consola es que mediante el uso de tuberías se pueden automatizar procesos complejos de administración de máquinas y demás.

Espero que les sea de utilidad.