miércoles, 31 de diciembre de 2014

Recomendaciones para el desarrollo de aplicaciones móviles híbridas

Existe la concepción de que las aplicaciones híbridas elaboradas con HTML son notablemente más lentas que las aplicaciones nativas. Es cierto que debido a las capas extra de abstracción, y al soporte limitado a HTML 5, existe cierto costo de desempeño en las aplicaciones híbridas. Sin embargo, muchas veces este costo se hace notable debido a debilidades en el diseño de la aplicación, aspectos sin afinar o depurar en su estructura, y carencia de optimizaciones que en conjunto podrían mejorar notablemente la experiencia del usuario, y hacer que la brecha con una aplicación nativa se vuelva casi invisible.

A continuación listo algunas recomendaciones que ayudarán a optimizar el desempeño de una app híbrida:

  • Uso de imágenes PNG y JPG. Cuando se usan imágenes e la web, surge la pregunta: ¿qué formato de imagen debo usar? En términos generales, es recomendable utilizar imágenes PNG para logos e íconos, cuando estos sean de múltiples colores y compuestos principalmente de figuras geométricas y texto, ya que este tipo de imagen permite mostrar estos detalles con una excelente calidad, y además permite el uso de transparencias. Por otra parte, se recomienda el uso de imágenes JPG para fotografias, dibujos u otro tipo de imágenes que muestren una amplia gama de tonos y colores, ya que esta clase de gráficos no requieren bordes lisos ni definidos, y además este formato permite mostrar las tonalidades con un tamaño de archivo pequeño. Pueden utilizarse otros formatos, pero estos dos son los que presentan la mejor combinación de calidad y tamaño de archivo, y además son soportados por HTML desde versiones previas.
  • Optimización de imágenes. Antes de utilizar imágenes, es necesario comprimirlas, y además reducirlas al tamaño (ancho X alto) mínimo posible, pero sin sacrificar demasiado la calidad. Si la aplicación está destinada a dispoitivos de múltiples tamaños, puede ser conveniente tener las imágenes en múltiples tamaños, y mostrarlas dependiendo de la pantalla del dispositivo. Está de más decir que usualmente los dispositivos más grandes (tablets) poseen mejor hardware que los de tamaño menor (smartphones), y pueden mostrar imágenes de mayor tamaño con un menor costo en el desempeño. Adicional a esto, cuando son íconos pequeños, se recomienda el uso de sprites, que básicamente son archivos de imágenes que contienen múltiples imágenes dentro de sí, y que son "recortadas" y mostradas mediante CSS.
  • Usar fuentes en lugar de imágenes para los íconos, si el diseño de estos se basa principalmente en figuras geométricas, y son de un solo color. Ello debido a que las fuentes son básicamente imágenes vectoriales, y los visores web pueden dibujarlos sin mayor inconveniente. Además, al ser vectoriales, pueden ajustarse a cualquier tamaño, y verse siempre de la misma forma, a diferencia de las imágenes que se pueden ver demasiado afiladas o borrosas si se reducen o aumentan de tamaño. En este sentido incluso son preferibles a los sprites. Existen varias fuentes que porporcionan una generosa cantidad de íconos cuyas figuras se basan en acciones comunes, como Font Awesome y Ionicons. Pero si estas colecciones no contienen todos los íconos que usted desea, o usted posee íconos propios para añadir a su aplicación, existen técnicas para convertirlos a imágenes vectoriales, y posteriormente a fuentes que pueden ser añadidas a la aplicación híbrida o incluso su propio sitio web. Adicionalmente, son ua alternativa al uso de imágenes vectoriales SVG, las cuales noe son soportadas en las plataformas más antiguas.
  • Efectos CSS. Para animaciones, efectos y ajustes en el despliegue de elementos en la aplicación, se recomienda el uso de transiciones, transformaciones y otras propiedades CSS, ya que son más rápidas y fáciles de implementar que mediante Javascript, y usualmente presentan un mejor desempeño. Sin embargo el soporte de las distintas transiciones está supeditado a la versión del sistema operativo del dispositivo móvil, por lo que es necesario verificar esto.
  • Reducir elementos DOM. Al maquetar una aplicación HTML, se recomienda utilizar la menor cantidad de elementos posible, y eliminar los nodos del DOM que ya no se usen. Cada elemento dentro del DOM ocupa memoria, y requiere recursos para su dibujado, incluso aunque no sea visible, por lo que al disminuir la cantidad de estos, ahorramos recursos.
  • Seleccionar cuidadosamente el framework a utilizar. Existen distintos frameworks para el desarrollo de aplicaciones híbridas HTML, que proporcionan funcionalidades por defecto, lo cual permite agilizar el desarrollo, tales como JQuery Mobile, Sencha Touch, App Framework, PhoneJS, Onsen UI, Ionic Framework, etc. Sin embargo, es necesario tener en cuenta el costo que estos pueden causar en el desempeño, así como el soporte que poseen para los distintos sistemas operativos. Además es necesario sopesar la curva de aprendizaje, ya que un framework mal usado puede llevar a fugas de memoria, uso excesivo de recursos y reducción en general del desempeño de las aplicaciones.
  • Verificar el soporte de tecnologías HTML, CSS y Javascript, para las plataformas objetivo. Esto es necesario para no minar la experiencia del usuario, al poseer funcionalidades que solamente son visibles en ciertas plataformas, pero que presentan fallas o incluso no existen en otras. Unas excelentes herramienta en línea para verificar esto es caniuse.com y W3 Schools, ya que poseen un listado bastante completo de elementos HTML, CSS y Javascript, así como los navegadores/plataformas que los soportan.
Al prestar un poco de atención en estos distintos puntos de optimización, se pueden crear aplicaciones híbridas con una experiencia para el usuario igual o incluso mejor al de aplicaciones nativas.

¿Qué otros aspectos cree usted que pueden tomarse en cuenta para mejorar el desempeño de las aplicaciones híbridas? Compártalos en la sección de comentarios.

lunes, 22 de diciembre de 2014

Contenido de DevExpress Round Panel en Razor

Si ya han usado el Round Panel de Developer Express para MVC, habrán notado lo tedioso que es poner el contenido de este, ya que según el ejemplo que brindan en la documentación oficial, debe establecerse mediante una cadena de caracteres:

@Html.DevExpress().RoundPanel(settings => {
       settings.Name = "roundPanel";
       settings.ShowHeader = true;
       settings.HeaderText = "ASP.NET MVC";

       settings.SetContent(@"<h4>Lorem Ipsum</h4>
<p><span class="inicio">Lorem ipsum</span> dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</p>");
    }).GetHtml()

Esto deja de lado las facilidades que brinda Razor como motor de vista, que permite integrar el código HTML con C# de forma fácil y legible. Además, se vuelve más complicado a medida necesitamos añadir más componentes, o controles más complejos dentro de él. Sin embargo, existe una solución práctica para esta situación: el uso de helpers.

La sintaxis @helper permite crear métodos de ayuda re-usables dentro de las vistas, los cuales permiten encapsular código fuente y HTML utilizando la sintaxis de Razor.

Mediante la sintaxis @helper, podemos colocar el contenido del panel dentro de una función helper separada;
@helper ContenidoPanel() {
    <h4>Lorem Ipsum</h4>
    <p><span class="inicio">Lorem ipsum</span> dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</p>
}
Y luego renderizarlo dentro del panel, siempre en la misma vista, así:
@Html.DevExpress().RoundPanel(settings => {
       settings.Name = "roundPanel";
       settings.ShowHeader = true;
       settings.HeaderText = "ASP.NET MVC";
       settings.SetContent(ContenidoPanel().ToHtmlString());
    }).GetHtml()
O así:
@Html.DevExpress().RoundPanel(settings => {
       settings.Name = "roundPanel";
       settings.ShowHeader = true;
       settings.HeaderText = "ASP.NET MVC";
       settings.SetContent(() => ContenidoPanel().WriteTo(ViewContext.Writer));
    }).GetHtml()

Esto facilita la legibilidad del código, y además permite definir un contenido mucho más complejo, utilizando todas las facilidades que Razor puede brindar.

martes, 9 de diciembre de 2014

Aplicaciones híbridas para móviles

Hace poco más de un año empecé a desarrollar aplicaciones móviles, y por mi experiencia previa con sitios web, opté por el desarrollo de aplicaciones HTML híbridas en lugar de nativas, para hacer el desarrollo más rápido. Pero veamos...

¿Qué son las aplicaciones híbridas?

Las aplicaciones móviles comúnmente conocidas como híbridas son aplicaciones desarrolladas utilizando tecnologías web del lado del cliente (HTML, Javascript, CSS), pero que se instalan en los dispositivos móviles, y pueden acceder a las funcionalidades de hardware de este a través de APIs provistas por frameworks especiales (como Phonegap/Cordova, Sencha).
Estas aplicaciones usualmente se muestran en un componente visor de web provisto nativamente por el sistema operativo del móvil, los cuales proveen las funcionalidades de un navegador web relativamente moderno (soporte para HTML5 y CSS3).

¿Cuáles son sus ventajas?

La principal ventaja de las aplicaciones híbridas es que se basa en tecnologías web ampliamente conocidas, las cuales existen desde hace largo tiempo y han crecido y mejorado a lo largo de su desarrollo. Esto proporciona una sola interfaz de programación para multiples plataformas, a través del uso de frameworks especiales como Phonegap/Cordova, que porporcionan la infraestructura necesaria para crear de forma automática las respectivas aplicaciones nativas que encapsulan el contenido web, además de proveer APIs que estandarizan y simplifican el acceso a las funcionalidades del dispositivo.
El uso  de tecnologías web también ahorra la curva de aprendizaje de los desarrolladores que ya poseen conocimiento en el área, lo que puede facilitar y agilizar el desarrollo de aplicaciones móviles. También permite reducir el costo de contratar personal especializado en el área móvil para cada sistema operativo móvil del mercado (iOS, Android, Windows 8, Tizen, etc.), ya que cada plataforma hace uso de distintas herramientas y lenguajes de programación.
Adicionalmente, y como apreciación personal, el desarrollo de interfaces de usuario es más fácil, personalizable y escalable con el uso de HTML5 y CSS3, que son tecnologías especializadas para la presentación de la información. Y la disponibilidad de media queries en CSS facilitan el diseño responsivo, que permite adaptar la vista a la gran variedad de pantallas y resoluciones de dispositivos que existen en el mercado.

¿Existen desventajas?

Hasta acá todo parecía felicidad, ¿verdad? Lo cierto es que como en toda tecnología, existen desventajas que hay que tomar en cuenta. La principal desventaja que presentan las aplicaciones híbridas es la capa extra de virtualización que existe: la aplicación en realidad está corriendo sobre una aplicación nativa, en última instancia. Esto se traduce en una disminución en el desempeño de la aplicación, en contraparte de las aplicaciones nativas, lo cual se hace más notorio a medida disminuyen las características del hardware.
Sumado a esto está el hecho de que se depende del componente visor de web disponible en la versión del sistema operativo, lo cual puede disminuir aún más el desempeño, y disminuir el soporte de componentes HTML5 e instrucciones CSS. Además, hay que recordar que los desarrolladores del visor web no tenían como objetivo inicial perfeccionarlo para la ejecución de aplicaciones híbridas.
También, a pesar de que los frameworks especiales como Phonegap/Cordova, Sencha Touch y otros cuentan con una extensa API y plugins para el acceso al hardware (cámara, GPS, bluetooth, etc.) y funciones especiales del sistema operativo (acceso a archivos, identificación, almacenamiento, etc.), aún hay partes para los cuáles no existe un soporte completo (como servicios de fondo asíncronos entre otros).
Finalmente, hay que tomar en cuenta también el aspecto de la seguridad. En agosto de este año (2014) se emitió un comunicado por parte de Apache Cordova informando de vulnerabilidades en su framework, que obligaron al lanzamiento de una nueva versión menor de este para solucionar estas debilidades. Con esto no quiero decir que las aplicaciones híbridas sean inseguras, ni que las nativas sean seguras, ya que en realidad toda pieza de software puede presentar vulnerabilidades, mientras hayan humanos que las hagan y ataquen. Simplemente es que al existir una capa de abstracción más entre las aplicaciones, se abre la posibilidad a más puntos de ataque que hay que defender.

¿Ser o no ser?

Vamos a la pregunta del millón: ¿desarrollo una aplicación nativa o híbrida?. Creo que hay muchas respuestas posibles y válidas para esta pregunta, pero al menos personalmente, estos son los aspectos que tomo en cuenta para decidir si desarrollar una aplicación híbrida o no:
  • ¿Es una aplicación intensamente gráfica? Si lo es demasiado, es mejor utilizar la tecnología que presente un mejor desempeño, y en este caso, al menos hasta el momento, la mejor alternativa es una aplicación nativa. Pero si es una aplicación no tan gráfica, como por ejemplo una app informativa, o incluso hasta un juego ligero en 2D, entonces una aplicación híbrida puede ser una buena opción.
  • ¿El sistema operativo y hardware objetivo es viejo o reciente? A medida es más nuevo, se brinda un mayor soporte a las tecnologías web y aplicaciones híbridas. Si es más viejo, habría que evaluar si soporta o no las características que tengamos en mente para nuestra aplicación.
  • ¿Puedo acceder a todas las funcionalidades que necesito? Tomando como base que una aplicación nativa puede acceder al 100% de funcionalidad disponible, habría que investigar y evaluar si el framework que utilizaré para mi aplicación posee las funciones que requiero, o aunque no las posea, es posible desarrollarlas y añadirlas (y por supuesto cuento con el tiempo para hacerlo).
  • ¿Tengo poco tiempo y solo conozco tecnologías web/nativas? Creo que es el punto de menor relevancia de los mencionados, pero lo suficientemente importante para tener en consideración. ¿Por qué? Porque tanto el desarrollo de aplicaciones nativas como el uso de frameworks para aplicaciones híbridas posee su curva de aprendizaje. Además, el desarrollo de aplicaciones híbridas requiere siempre cierto conocimiento de las herramientas nativas subyacentes, principalmente para la preparación del entorno de desarrollo (SDKs, dispositivos de prueba, depuración, etc.). Y por qué no, esta prodría ser una buena oportunidad de aprender una tecnología y alternativa de desarrollo que no conocía, ya sea nativa (si viene del entorno web) o híbrida (si ya posee experiencia en el desarrollo nativo).

jueves, 6 de noviembre de 2014

WP - SQL Server Snippets – Tablas con columna autonumérica

Este primer snippet consiste en una consulta para obtener las tablas de la base de datos en uso (es decir, la base de datos seleccionada actualmente), que poseen una columna autonumerada (IDENTITY), incluyendo el nombre de dicha columna.

La consulta en T-SQL es la siguiente:

USE [BASE_DATOS]
GO
 
SELECT
TABLA.object_id                                    AS object_id,
SCHEMA_NAME(TABLA.schema_id) + '.' + TABLA.name    AS tabla,
COLUMNA.name                                    AS columna_identity
FROM sys.tables TABLA
INNER JOIN sys.columns COLUMNA ON COLUMNA.object_id=TABLA.object_id
WHERE TABLA.type='U'
AND TABLA.name NOT LIKE 'sys%'
AND COLUMNA.is_identity = 1
ORDER BY SCHEMA_NAME(TABLA.schema_id), TABLA.name

A modo de una pequeña descripción, básicamente lo que se hace es consultar las tablas del sistema sys.tables (que contiene información de las tablas), y sys.columns (que contiene información de las columnas). Ambas tablas se unen a través del object_id de la tabla.

Luego, en la cláusula WHERE se filtran los resultados para solamente incluir tablas creadas por el usuario (tipo “U” y que no inicien con “sys”, para descartar la tabla sys.diagrams), y de dichas tablas solamente tomar las columnas con la propiedad IDENTITY (is_identity = 1). Cabe señalar que una tabla en SQL Server puede tener solamente una columna IDENTITY, por lo que la consulta no devolverá más de una fila por tabla.

Nótese además que se obtiene el nombre del esquema de la tabla, a través de la función SCHEMA_NAME, y se concatena con el nombre de la tabla, para obtener el nombre completo de la tabla dentro de la base de datos.

Finalmente, y de forma opcional, se ordenan los resultados por esquema y nombre de tabla, para que se muestren de la misma forma que se muestran en el explorador de objetos del SQL Server Management Studio.

Hasta donde he probado, el script funciona para SQL Server 2005 – 2012.

Espero que les sea de utilidad. Saludos, y como dicen por allí, “happy coding!”.

WP - Atributo de MVC para filtrar acciones para solicitudes AJAX

Esta entrada ha sido reposteada por error, pero utilizando Gists para mejor legibilidad del código, acá: http://itsouvenirs.blogspot.com/2018/01/wp-atributo-de-mvc-2-para-filtrar.html

Ya llevo un par de meses trabajando con ASP.NET MVC Framework 2, y debo decir que me ha encantado. Y sé que van por la versión 4, pero en el trabajo contamoscon Visual Studio 2008, así que hay que aprovechar lo que se tiene, y debo decir que en realidad no es poco.

En esta ocasión quiero mostrar una forma de crear un atributo de filtrado para acciones que deben ser ejecutadas solamente mediante solicitudes Ajax. Esto es útil para acciones que deseamos utilizar exclusivamente para estas solicitudes, y que queremos que el usuario común tenga acceso a ellas solamente a través de esta forma, mediante alguna interacción con la interfaz de usuario (UI), por ejemplo.

Primero, es necesario encontrar una forma de identificar que el tipo de solicitud es XML HTTP request, que es la clase de solicitudes que se hacen mediante AJAX. El objeto HttpRequest del que disponemos en una aplicación ASP.NET no cuenta con un método propio para identificar este tipo de solicitud, por lo que es necesario trabajar un poco en esta parte. Para ello, crearemos un método de extensión que se encargue de verificar esto. El método que presento a continuación es prácticamente una copia de la respuesta de Charlino a la pregunta de StackOverflow titulada How to check if request is ajax or not in codebehind – ASP.NET Webforms, que a su vez se basa en el código fuente del MVC Framework (que es open source, o código libre, por cierto).

using System;
using System.Web;
 
namespace MiProyectoMVC.Extensiones
{
    public static class HttpRequestExtensions
    {
        public static bool IsAjaxRequest(this HttpRequest request)
        {
            if (request == null)
            {
                throw new ArgumentNullException("Request es nulo");
            }
 
            return (request["X-Requested-With"] == "XMLHttpRequest") || ((request.Headers != null) && (request.Headers["X-Requested-With"] == "XMLHttpRequest"));
        }
    }
}
Como puede observarse, el método revisa directamente el encabezado del request, para verificar el tipo de solicitud. Si el tipo de solicitud es XMLHttpRequest, devuelve verdadero, y falso en caso contrario.

Actualización: Existe un método de extensión para la clase HttpRequestBase en el espacio de nombres System.Web.Mvc, con el mismo nombre y funcionalidad que el del método propuesto (IsAjaxRequest). Podría usarse este en vez de crear una nueva extensión, solamente incluyendo el espacio de nombres System.Web.Mvc.

Teniendo este método disponible, podemos proceder a crear el atributo de filtro. Este es un atributo de filtro convencional, por lo que será descendiente o derivado de la clase ActionFilterAttribute. Como se observa a continuación, el atributo es bastante simple:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using MiProyectoMVC.Extensiones;
 
namespace MiProyectoMVC.Controllers.Atributos
{
    public class XmlHttpRequestAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (!filterContext.HttpContext.Request.IsAjaxRequest())
            {
                //Si no es solicitud Ajax, mostramos a una página de error completa
                filterContext.Result = new ViewResult() { ViewName = "Error" };
            }
            base.OnActionExecuting(filterContext);
        }
    }
}
Como puede observarse, todo el proceso de verificación se realiza sobrecargando el método OnActionExecuting, que se ejecuta justo antes de proceder a ejecutar la acción. Acá hacemos uso del método de extensión para verificar si la solicitud (request) es de tipo Ajax, y si no lo es, devolvemos como resultado una vista completa, que bien puede ser una página de error personalizada. Cabe mencionar que digo vista completa porque el resultado a generar es un ViewResult. Dado que sabemos que no es una solicitud Ajax, lo común no sería devolver una vista parcial, sino una página completa (.aspx). También, en vez de devolver de una sola vez la página de error, podríamos redireccionar hacia otra acción que consideremos conveniente, a través de un RedirectResult.

Finalmente, decoramos la acción que deseamos filtrar con el atributo que hemos creado, de la siguiente manera:

//...
 
namespace MiProyectoMVC.Controllers
{
    public class EjemploController : Controller
    {
        // ...
 
        [XmlHttpRequest]
        public ActionResult IndexPartial()
        {
            //...
            return PartialView("IndexPartial");
        }
 
        //...
    }
}
Acá les dejo un enlace que encontré por allí, que tiene varios ejemplos de atributos de filtro de acciones bastante interesantes, que puede que les sean de utilidad: Creating Custom Action Filters in ASP.NET MVC


NOTA: Aunque este atributo fue elaborado y probado en MVC Framework 2, de igual forma es aplicable para las versiones 3, 4 y 5 (posiblemente) del framework.


Cualquier comentario será bien recibido, y como dicen por allí, Happy coding!

martes, 4 de noviembre de 2014

WP - Resposive Web Design

La ventaja y objetivo de los diseños responsivos (Responsive Web Design, RWD) es que la página web se pueda ver bien desde dispositivos con casi cualquier resolución (smartphones, tablet, netbooks, PCs, televisores). He de comentar que desde hace algunos años quise hacer algo así sin éxito, pero no conocí este término de RWD hasta que hace un par de meses leí un post de  en TechRepublic, titulado "How to get started with Responsive Web Design". Les recomiendo los artículos de este señor sobre desarrollo web, ya que incluyen nuevos conceptos y ejemplos prácticos en este ámbito. Que Dios les bendiga.

Publicado originalmente el 20/09/2012, en http://itsouvenirs.wordpress.com/type/aside/
Como dato curioso, esta entrada la publiqué al cambiar el tema de mi blog de Wordpress a uno responsivo, llamado "Twenty Eleven".

lunes, 3 de noviembre de 2014

Extraer archivo de base de datos desde dispositivo Android

Para extraer los archivos de base de datos (y en realidad cualquier otro archivo), podemos hacerlo utilizando las herramientas del SDK de Android, ya sea desde la línea de comandos, o haciendo uso del File Manager proporcionado por el Android Device Monitor.

Extraer base de datos desde línea de comandos

Para extraer archivos desde un dispositivo conectado a la computadora o emulador activo, se hace uso del comando adb pull. Si hay un solo dispositivo conectado, se hace de la siguiente manera:

adb pull /data/data/[mi.paquete.app]/databases/[mibasedatos.db] C:\ruta\destino

En donde el primer parámetro es la ruta complete del archive a extraer del dispositivo, que en este caso es la base de datos; y el segundo parámetro es la ruta destino dentro de la computadora. El segundo parámetro es opcional, y si no se especifica, el archivo extraído se guarda en el directorio actual.

Si hay varios dispositivos Android conectados a la computadora, debe especificarse adicionalmente el serial del dispositivo, de la siguiente manera:

adb -s [serial] pull /data/data/[mi.paquete.app]/databases/[mibasedatos.db] C:\ruta\destino

En donde [serial] corresponde al serial específico del dispositivo. Cabe mencionar que para consultar los seriales de los dispositivos conectados, se puede hacer ejecutando el comando:

adb devices

El serial del dispositivo aparece en la primera columna a la izquierda, al ejecutar el comando.

Extraer base de datos usando el Android Device Monitor

Para extraer el archivo de base de datos usando el File Explorer del Android Device Monitor, basta con seleccionar el dispositivo en la barra de dispositivos del monitor, ubicar y seleccionar el archivo en la ficha del File Explorer, y presionar el botón  (Pull a file from the device), ubicado en la parte superior derecha de la ficha.



Luego de esto se nos muestra una ventana de diálogo en la que solamente hay que indicar el nombre del archivo y el directorio destino.

Aunque esta forma parezca la más fácil, puede resultar no serlo, debido a que en algunos casos la carpeta data no puede ser vista desde el File Explorer, debido a que no posee los permisos necesarios.

miércoles, 15 de octubre de 2014

Encontrar base de datos SQLite en dispositivo android

Cuando se está trabajando en una aplicación de Android que hace uso de una base de datos SQLite, puede resultar necesario buscar el archivo de esta dentro del sistema de archivos del dispositivo en el que se están realizando pruebas, ya sea para verificar si esta se creó correctamente, si los datos se están almacenando, entre otras cosas.

La base de datos de cada aplicación se ubica en la siguiente ruta dentro del dispositivo:

/data/data/[mi.paquete.app]/databases/

En donde [mi.paquete.app] es el nombre del paquete principal de nuestra aplicación Android. En dicho directorio se almacena el archivo de la base de datos en sí, que posee el nombre especificado en el constructor de la clase SQLiteOpenHelper. También puede contener el “rollback journal” de la base de datos, que posee el mismo nombre, pero añadiendo el prefijo “-journal”. Por ejemplo, si la base de datos se llama “BDPrueba.db”, entonces los archivos que encontraremos serían “BDPrueba.db”, y posiblemente “BDPrueba.db-Journal”.



¡La carpeta data está vacía!

Si estamos usando el File Explorer del Android Device Monitor/DDMS para consultar los archivos del dispositivo Android, en algunos casos puede resultar que el directorio /data en apariencia no posee ningún contenido. Sin embargo, esto sucede debido a que esta carpeta no posee los permisos necesarios para ver su contenido.



Si esto sucede, lo que hay que hacer es otorgar los permisos necesarios para acceder a los archivos. Esto se puede hacer en dispositivos rooted y emuladores a través del ADB Shell, para entrar en modo terminal a nuestro dispositivo.

Para iniciar el ABD Shell, se ejecuta el siguiente comando en la terminal:

adb shell

Si hay varios dispositivos conectados, es necesario indicar el serial del dispositivo, de la siguiente forma:

adb -s [serial] shell

En donde [serial] es el serial del dispositivo deseado.

El serial del dispositivo se puede obtener ejecutando el comando adb devices
El serial del dispositivo aparece en la primera columna a la izquierda, al ejecutar el comando.
El serial del dispositivo aparece en la primera columna a la izquierda, al ejecutar el comando.

Una vez estando en la terminal del dispositivo, se deben iniciar modo super-usuario (usuario root):

$ su

Luego, hay que ejecutar el siguiente comando, para otorgar permiso completo de acceso a la rama de carpetas y archivos para todos los usuarios:

# chmod 777 /data /data/data /data/data/[mi.paquete.app] /data/data/[mi.paquete.app]/databases /data/data/[mi.paquete.app]/databases/*

Finalmente, para salir de la terminal:

#exit
$exit

Puede que no sea necesario otorgar control total sobre las carpetas, habría que probar cuáles serían los permisos mínimos dependiendo de lo que se necesite hacer con los archivos.

jueves, 18 de septiembre de 2014

WP - Diseño web - Ventana DIV simple 1


¡Hola nuevamente! Tenía un rato de no escribir por acá, pero es que han sucedido varias cosas en los últimos meses... mis disculpas por ello. En realidad desde hace algún tiempo quería mostrar una forma de hacer ventanas con DIV, basándome en el diseño que utilizamos para nuestro proyecto de graduación. Luego de organizar un poco mis ideas, decidí hacer  una serie de posts en donde explicara como hacer una ventana DIV, e ir mejorando el diseño en cada uno de ellos. Este es el primer post de la serie.

En esta ocasión quiero mostrar una forma sencilla de crear una ventana modal a partir de elementos DIV dentro de una página web. Una ventana modal consiste en una ventana que mantiene el foco respecto a las demás en una aplicación o sistema. En este caso, la ventana modal mantendrá el foco con respecto al resto de la página web.

Por el momento, la estructura de la ventana modal consistirá en dos elementos DIV. El primero de ellos será la ventana en sí. El segundo servirá para cubrir toda la página web, oscureciéndola, dando así la apariencia de que el resto de la página web está deshabilitada. Además, al estar encima del resto de elementos de la página, impedirá que los usuarios puedan hacer clic sobre éstos, dando el efecto de modalidad. Este DIV será conocido como DIV de fondo en el resto de este post. Está de más mencionar que el único DIV que estará sobre este fondo será el DIV de la ventana modal.

Partes de ventana DIV.
Partes de ventana DIV.

Esta ventana modal será manejada como una "clase" Javascript, con el objetivo de que más adelante podamos manejar múltiples ventanas modales dentro de una misma página web, como objetos. Por otra parte, el diseño completo de la ventana se manejará por separado, desde un archivo CSS.

Primeramente, esta es la definición de la clase VentanaDiv, contenida en el archivo ventanadiv.js:

function VentanaDiv(idventana, idfondo) {
  //Obteniendo las referencias a los DIV que utilizaremos
  this.ventana = window.document.getElementById(idventana);
  this.fondo = window.document.getElementById(idfondo);

  //Creando funciones para manipular la ventana
  this.mostrar
    = function() {
        this.fondo.style.visibility = 'visible';
        this.ventana.style.visibility = 'visible';
      };
  this.ocultar
    = function() {
        this.fondo.style.visibility = 'hidden';
        this.ventana.style.visibility = 'hidden';
      };
}
 Como puede observarse, en la primera parte de esta clase se obtienen las referencias a los DIV que se utilizarán para la ventana. Esto implica que los DIV deben existir ya dentro de la estructura DOM de la página web. Las referencias a los objetos se guardan en variables con ámbito global dentro de la clase, y se utilizan para mostrar u ocultar los DIV, en las funciones mostrar() y ocultar(), respectivamente. Éstos métodos han sido definidos dentro de la misma función constructor, y como puede observarse, lo único que hacen es mostrar u ocultar los DIV.

Luego, tenemos la hoja de estilos CSS, que define la forma en que se mostrarán los DIV dentro del sitio web:


/* Clase CSS que define el fondo oscuro */
div.fondoventana
{
    /* Para que el DIV aparezca oculto inicialmente */
    visibility:hidden;

    /* Para que el DIV cubra toda el área de la página web */
    position:fixed;
    top:0px;
    left:0px;
    width:100%;
    height:100%;

    /* Fondo negro con opacidad del 60%, que da un efecto de transparencia */
    background-color:#000000;
    /* Opacidad para Internet Explorer */
    filter:alpha(opacity=60);
    /* Opacidad en CSS3 estándar */
    opacity:0.6;

    /* Este índice debe ser mayor que el del resto de los demás elementos de la página web, para que aparezca sobre ellos */
    z-index:9;
}

/* Clase CSS que define el formato de la ventana */
div.ventana
{
    /* Para que el DIV aparezca oculto inicialmente */
    visibility:hidden;

    /* Para que la ventana aparezca centrada en la página web, con un tamaño de 300x160 píxeles */
    position:fixed;
    left:50%;
    margin-left:-150px;
    top:50%;
    margin-top:-80px;
    width: 300px;
    height:160px;

    /* Borde gris de la ventana */
    border-width:5px;
    border-color:#999999;
    border-style:solid;

    /* Color de la ventana */
    background-color:#FFFFFF;

    /* Espacio de 10 píxeles desde el borde de la ventana hasta el texto interno */
    padding:10px;

    /* Este índice debe ser mayor que el del fondo, para que la ventana esté sobre él */
    z-index:10;
}
Como puede observarse, se han definido dos clases CSS, una de ellas para el DIV fondo y otra para el DIV ventana. Se han usado clases con el objetivo de que las características definidas en la hoja de estilo puedan utilizarse en varios elementos de la página web, en caso de que quiera tenerse más de una ventana en ella.

Por otra parte, en este ejemplo sencillo las propiedades principales de la ventana ya están predefinidas: la ubicación, color, tamaño e índices verticales de los DIV ventana y fondo. Nótese que el índice z del fondo debe ser superior al de los demás elementos de la página, para poder aparecer sobre ellos y cubrirlos. El único elemento con índice z superior es el del DIV de la ventana, ya que debe aparecer por encima del fondo.

Cabe mencionar también que las posiciones de ambos DIV son fijas (position:fixed;). Esto se debe a que su posición debe estar fija con respecto a la ventana que lo contiene, y no debe afectar las posiciones de los demás elementos de la página. El DIV de fondo estará extendido en toda la ventana del explorador web, y el DIV ventana estará centrado. También debe observarse que la propiedad visibility:hidden sirve para indicar que ambos DIV estarán ocultos al abrirse la página web.

Algo que considero importante mencionar es que las características CSS aplicadas a un elemento de la página web se heredan a sus hijos. Por ello, podemos colocar cualquier cosa dentro del DIV de la ventana, confiando que esto se ocultará y mostrará cuando la ventana lo haga (a menos, claro, que estableciéramos características especiales para estos elementos).

Finalmente, se tiene el código fuente de la ṕágina web:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
    <title>Ventana DIV 1 - Ventana DIV simple</title>

    <!-- Importando archivos CSS y Javascript - Inicio -->
    <link rel="stylesheet" type="text/css" href="ventanadiv.css" />
    <script language="javascript" type="text/javascript" src="ventanadiv.js" ></script>
    <!-- Importando archivos CSS y Javascript - Fin -->
  </head>
  <body>
    <!-- Contenido de la página web - Inicio -->
    <h1>Ejemplo de ventana DIV 1</h1>
    <br />
    <a href="#" onclick="ventana.mostrar()">Haga click aquí para mostrar la ventana</a>
    <!-- Contenido de la página web - Fin -->

    <!-- DIV de fondo - Inicio -->
    <div id="divfondo"></div>
    <!-- DIV de fondo - Fin -->

    <!-- DIV de ventana - Inicio -->
    <div id="divventana">
      <p>
        <center><h3>Ventana modal</h3></center>
        <br />Bienvenido a mi primera ventana modal web.
      </p>
      <p><center><a href="#" onclick="ventana.ocultar()" >Cerrar</a></center></p>
    </div>
    <!-- DIV de ventana - Fin -->
  </body>
  <script type="text/javascript" >
    //Creación de la ventana
    var ventana = new VentanaDiv("divventana", "divfondo");
  </script>
</html>
Primeramente es necesario incluir los archivos CSS y Javascript que hemos creado especialmente para las ventanas, en el encabezado del documento. Luego de ello, en el cuerpo de la página web se ha colocado el contenido a mostrar, y después de este, los DIV de fondo y ventana. En realidad, en este diseño sencillo no importa donde se coloquen estos DIV, ya que como se dijo anteriormente, al inicio ambos estarán ocultos, y luego se mostrarán de forma fija en la ventana, por lo que no afectarán la ubicación de los demás elementos, al menos de forma visible para el usuario.

Algo muy importante que hay que recalcar es el script ubicado al final del documento. Este script es el encargado de crear el objeto VentanaDiv a partir de la clase Javascript, y que permite el funcionamiento de ésta. Se ha ubicado al final del documento debido a que la estructura DOM del sitio web se va creando conforme al orden de los elementos en el documento HTML (es decir, de izquierda a derecha y de arriba hacia abajo), y es necesario que los DIV ya existan para que el constructor de la clase VentanaDiv pueda obtener sus referencias. Por ello es de suma importancia que este script se ubique después de los DIV en el documento HTML.

Hay que notar que aunque la variable ventana se declara e instancia al final del documento, su ámbito (por así decirlo) abarca todo el documento, una vez que su declaración ha sido procesada. Por ello puede observarse que se hace referencia a ella en los dos hipervínculos que están en el cuerpo de la página web. Éstos hipervínculos no referencian a ninguna página web (por ello solo tienen el # en su propiedad HREF), sino que en el evento onclick de estos se han colocado las invocaciones a los métodos mostrar() y ocultar() de la ventana DIV, para ejecutarlos al momento de dar clic derecho sobre ellos. Esta de más decir que el hipervínculo que invoca al método mostrar()se ubica en el cuerpo visible de la página web, mientras que el hipervínculo que ejecuta el método ocultar() se ubica dentro de la ventana DIV.

Y voilá, tenemos nuestra primera ventana DIV en funcionamiento.
Ventana DIV en funcionamiento.
Ventana DIV en funcionamiento.
Esto es todo por hoy. En los siguientes artículos mostraré como crear métodos para permitir establecer el tamaño de la ventana mediante código javascript, así como incluir un botón de cierre y efecto de sombra para ésta.
Que Dios les bendiga.

Referencias


Publicado originalmente el 18/08/2012, en http://itsouvenirs.wordpress.com/2012/08/18/diseno-web-ventana-div-simple-1/.

miércoles, 17 de septiembre de 2014

WP - Consejos de programación 1 - Don’t be WET, stay DRY

En esta ocasión quiero iniciar una serie de consejos de programación que considero importantes a nivel de eficiencia, orden y -por que no decirlo – estética. Estos consejos se basan en algunas prácticas que he observado durante los pocos años de mi carrera. Algunas de esas prácticas son buenas, mientras que otras son las que quisiera evitar. También se basan en cosas interesantes que he encontrado en uno que otro artículo por el Internet (de esos artículos donde la gente gustan hablar de temas con acrónimos de 3 o 4 letras).

Iniciaré la serie compartiendo algo acerca del principio de desarrollo de software conocido como DRY (inglés: seco), que significa Don’t Repeat Yourself. Creo que ya saben más o menos por donde va la cosa, pero antes de definir el término, haré una pequeña introducción.

Introducción

Algo que he visto muchas veces es que cuando se quieren añadir nuevos elementos a una aplicación (ventanas, controles de usuario, funciones), y estos son muy similares a elementos ya existentes, lo que hacen los programadores es copiar y pegar el código fuente correspondiente a dichos elementos, y hacer las modificaciones en la copia de acuerdo a los nuevos requerimientos. Esta técnica es vulgarmente conocida en nuestro medio como “copy-paste”, y también es aplicable a la técnica que usan los estudiantes cuando buscan sus tareas en Wikipedia, El Rincón del Vago, Taringa, o Yahoo respuestas, en el peor de los casos (aceptémoslo, todos hemos aplicado esta técnica alguna vez, jejeje…)

Considero que esta una práctica muy arraigada debido a que esto se considera la forma más rápida de incluir nuevos elementos en una aplicación. Pero si se analiza cuidadosamente, al final no resulta ser la forma más rápida, porque:
  • Al crear un nuevo elemento a partir de la copia de uno ya existente, implica que es necesario cambiar parte del código fuente, para cambiar o añadir la funcionalidad deseada. También hay que tener particular cuidado con aquellos parámetros que han sido “quemados” (hard-coded) dentro de la aplicación.
  • El resultado es una aplicación con una gran cantidad de código fuente, lo que también deriva en la existencia de varios archivos desorganizados y desperdigados en la carpeta que contiene el proyecto.
  • Si se requiere cambiar una funcionalidad principal que se ha repetido en todos los elementos copiados, esta modificación debe hacerse en cada uno de ellos.

Definición de DRY y WET

Basta de hacer catarsis, procederé a definir los conceptos más formalmente. En la “ingeniería de software”, el término DRY, o “Don’t Repeat Yourself”, se refiere a reducir la repetición de información de cualquier tipo. El principio DRY dicta: “Cada pieza de conocimiento debe tener una representación única, no ambigua y autoritaria dentro de un sistema”. El término fue acuñado por Andy Hunt y Dave Thomas en su libro “The Pragmatic Programmer”. Eric Raymond hace referencia a un término equivalente, llamado SPOT (“Single Point Of Truth”) en su libro “The Art Of Unix Programming”. Cabe destacar que el término no se limita a código fuente ni datos, sino a un sistema cualquiera. Tampoco se refiere necesariamente a no repetir código fuente en un sistema informático, sino que este tenga una fuente única dentro del sistema.

El término contrario a este es WET (inglés: mojado), al cual se le han dado muchos significados: “We Enjoy Typing”, “Write Everything Twice”, “We Edit Terribly”, etc. Obviamente, significa que existen “piezas de conocimiento” con múltiples representaciones, que podría traducirse como tener la misma información repetida varias veces.

Ventajas de DRY

Ustedes se preguntarán por qué tomarse la molestia de aplicar este principio, si han vivido felizmente con la técnica de copy-paste por mucho tiempo, a tal punto que ya tienen práctica con la mano izquierda para hacer las secuencias de teclas Ctrl+C y Ctrl+V. Pues bueno, las ventajas que yo he observado de primera mano en las aplicaciones que he visto son las siguientes:
  • Toda elemento (función, método, procedimiento, clase) e información dentro de la aplicación posee un origen único, por lo que si se requiere modificar la funcionalidad principal de alguno de ellos, debe hacerse en un solo punto.
  • La cantidad de código fuente se reduce.
  • El desglose de funcionalidades permite el manejo de múltiples capas. Esto también permite una organización más clara de los archivos de código fuente.
  • El trabajo de añadir nuevos elementos basados en elementos anteriores se reduce, ya que no implicará copiar y modificar código fuente para satisfacer los nuevos requerimientos, sino más bien reutilizar elementos y funcionalidades ya existentes. En el mejor de los casos, solo será necesario invocar los elementos ya existentes, con parámetros distintos, para obtener los resultados requeridos.

Desventajas de DRY

A pesar de todo, y como todo en esta vida, DRY posee algunas desventajas que hay que tener en cuenta:
  • Muchas veces se requerirá de análisis profundo para encontrar una forma aceptable de centralizar todos los elementos de un sistema. La construcción de este kernel para la aplicación puede tomar algo de tiempo.
  • En algunos casos, la solución centralizada será menos eficiente en tiempo de ejecución que la solución repetitiva. Un buen ejemplo de ello es cuando una consulta muy utilizada en una base de datos relacional (digamos de SQL Server) se coloca en una función de usuario para poderla usar varias veces. La función por si sola puede ser eficiente, pero al intentar utilizarla dentro de otras consultas, puede ser más lento y pesado que si la consulta no hiciera uso de ella.
  • Dejar de lado el hábito de copy-paste, jejeje…

Cómo implementar el principio DRY

Dicho lo anterior, ahora os describiré algunas técnicas que os pueden ayudar a implementar el concepto de DRY en vuestros programillas:
  • Refinamiento del sistema en partes individuales con funcionalidades específicas y diferenciadas (técnicas top-down y bottom-up). Como me decían en la materia Programación Estructurada, “hay que reducir el problema en problemas más pequeños” (o algo así).
  • Agrupar elementos y funcionalidades similares, a  nivel de archivos y directorios, así como a nivel de código fuente.
  • Si se observa que una funcionalidad o elemento se repite más de una vez, o bien que es son muy parecidos a otra funcionalidad o elemento existente, entonces centralizarlos en un solo lugar. Por ejemplo, en la programación orientada a objetos, si se tienen por ejemplo las clases Profesor y Estudiante con propiedades y métodos similares, lo mejor sería que los elementos comunes los heredaran de una clase padre (Persona, por ejemplo).
  • En el caso de programación orientada a objectos, hacer uso de la herencia, clases abstractas, interfaces, y otros elementos que nos permiten centralizar la funcionalidad e información en clases, y hacer uso extensivo de ellas.
  • Hacer uso de Frameworks, los cuáles brindan funcionalidades comunes a toda aplicación. También incluyen generadores de código fuente, que construyen automáticamente elementos de uso común en base a características específicas. Ejemplo de ello es el Generador de Formularios del Framework para PHP llamado Symfony, que genera formularios web a partir de la definición del modelo de una base de datos.

¿Generadores de código fuente?

En este momento podría surgir la duda de por qué usar un generador de código fuente, si estos podrían generar código repetitivo. Si bien esto es cierto, no se salen del principio de DRY, ya que en realidad el código fuente generado automáticamente ha sido construido a partir de un mismo origen: el generador de código fuente. Esto implica que si se hace uso del mismo generador, este construirá el mismo código fuente en cualquier momento si se proporcionan las mismas condiciones para su generación.

Observaciones finales

El principio DRY nos presenta facilidades y ventajas con respecto a WET, ya que a la larga pueden facilitarnos el trabajo al reducir el tiempo de programación reutilizando elementos y funcionalidades ya existentes. Sin embargo, el llevar un sistema a una estructura DRY puede llevar tiempo de análisis, y muchas veces no será perfecto. Pero a pesar de esta desventaja, considero que vale la pena hacer el intento, ya que a la larga nos facilitará el trabajo a nosotros mismos quienes desarrollamos una aplicación, así como a los colegas que se encargarán de extender nuestro sistema informático en un futuro.

Los invito a escribir sus comentarios y opiniones acerca de este tema.



Publicado originalmente el 16/08/2012, en http://itsouvenirs.wordpress.com/2012/08/16/consejos-de-programacion-1-dont-be-wet-stay-dry/.

WP - Cinnamon 1.3.1 en Fedora 16

En esta ocasión mostraré como instalar Cinnamon en Fedora 16, que es una variante de escritorio desarrollada originalmente para Linux Mint, y basada en Gnome 3 y Mutter como decorador de ventanas. Cabe mencionar que la versión Live de Fedora 16 viene con Gnome 3 como escritorio por defecto, el cual, en lo personal, me parece bastante creativo y un poco más eficiente que las primeras versiones de Unity de Ubuntu.

Para instalar Cinnamon, lo primero que debe hacerse es añadir el repositorio de éste para Fedora, en YUM. Puede hacerse desde la línea de comandos así:

$ su
# curl http://repos.fedorapeople.org/repos/leigh123linux/cinnamon/fedora-cinnamon.repo -o /etc/yum.repos.d/fedora-cinnamon.repo

Luego, para proceder a su instalación, ejecutamos:

# yum install cinnamon

Finalmente, solo basta cerrar nuestra sesión y volver a ingresar, eligiendo ahora a Cinnamon como escritorio. Para ello se da click en el botón sesión, y se selecciona el escritorio a utilizar.

Selección de escritorio Cinnamon durante el inicio de sesión.
Vista del escritorio Cinnamon en Fedora 16.


Publicado originalmente el 27/03/2012, en http://itsouvenirs.wordpress.com/2012/03/27/cinnamon-1-3-1-en-fedora-16/.

martes, 16 de septiembre de 2014

WP - Habilitar tarjeta Broadcom Wireless en Fedora 16

Luego de instalar Fedora 16 en mi computadora, una DELL Inspiron 1525, me encontré con el inconveniente de que la tarjeta de red inalámbrica no funcionaba, debido a que el sistema operativo no incluye ni provee controladores para esta tarjeta de red. Esto se debe a la filosofía de Fedora, de proporcionar solamente software libre, y hasta el momento los controladores que existen para esta tarjeta de red son propietarios.

Sin embargo, existe una alternativa: paquetes kmod o akmod, que son módulos de kernel para controladores. Éstos pueden obtenerse vía internet (conectando la computadora con un cable de red, claro está), desde el repositorio RPMFUSION. La otra opción es descargar los paquetes desde el sitio web http://mirror.liberty.edu/pub/rpmfusion/nonfree/fedora/releases/16/Everything/x86_64/os/

Si se decide utilizar el repositorio RPMFUSION vía Internet, es necesario incluir el repositorio correspondiente en YUM, así:

$ su
# yum localinstall --nogpgcheck http://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-stable.noarch.rpm http://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-stable.noarch.rpm
# yum update

Luego de ello, tenemos la opción de usar paquetes kmod o akmod. Los kmod son paquetes precompilados que sirven como interfaz entre el kernel y los controladores, propios de una versión de kernel específica. Los akmod son paquetes que compilan kmod "al vuelo", al momento de iniciar el sistema operativo, de acuerdo al kernel que se esté utilizando.

Si se desean usar kmod, primeramente debemos obtener la lista de módulos disponibles, de acuerdo a la versión del kernel que se posea:

# yum list kmod-wl-\*

Los módulos poseen en medio de su nombre la versión del kernel a la que corresponden. Si por ejemplo se desea el kmod para el kernel 3.2.9, entonces se debe proceder a instalar el paquete kmod-wl-3.2.9-1.fc16.i686.i686, así:

# yum install kmod-wl-3.2.9-1.fc16.i686.i686

Si, por otra parte, se desea instalar un akmod, procedemos a instalar la versión más reciente, de la siguiente forma:

# yum install akmod-wl

Finalmente (independientemente de si elegió usar kmod o akmod), procedemos a instalar el controlador correspondiente a la tarjeta de red, en su versión más reciente:

# yum install broadcom-wl

Luego reiniciamos la computadora, para que el módulo respectivo sea cargado en el kernel en ejecución, luego de lo cual ya debería funcionar adecuadamente nuestra tarjeta de red Broadcom, detectando las redes disponibles en la zona.

Instalación sin conexión a Internet

El título no es del todo cierto, ya que es necesario descargar los paquetes correspondientes desde el sitio web http://mirror.liberty.edu/pub/rpmfusion/nonfree/fedora/releases/16/Everything/x86_64/os/ Debe buscarse y descargarse el paquete kmod-wl en la versión correspondiente al kernel que se utiliza, o la versión akmod-wl más reciente, según la alternativa. También es necesario descargar la versión más reciente o más apropiada del controlador broadcom-wl. Luego, se proceden a instalar los paquetes con permisos de administrador, y se reinicia la computadora, para activarlos, y poder hacer uso de la tarjeta de red inalámbrica.

Referencias


Enlaces de interés


Publicado originalmente el 10/03/2012, en http://itsouvenirs.wordpress.com/2012/03/10/habilitar-tarjeta-broadcom-en-fedora-16/.

viernes, 12 de septiembre de 2014

Cambiar tiempo de espera para ejecución de comandos en NHibernate vía código

Las consultas ejecutadas con NHibernate tienen un tiempo de espera predeterminado de 30 segundos. Sin embargo puede que este tiempo no sea suficiente para ejecutar algunos comandos o consultas complejas.

Para cambiar el tiempo de espera a nivel global a través de la configuración NHibernate vía código, se puede establecer el valor de la propiedad command_timeout al momento de configurar la fábrica de sesiones, de la siguiente manera:

NHibernate.Cfg.Configuration configuracion;

// Inicialización de configuración de NHibernate
// ...

// Estableciendo nuevo tiempo de espera (como cadena, en segundos)
configuracion.SetProperty(NHibernate.Cfg.Environment.CommandTimeout, "150");

// Creando fábrica de sesiones
ISessionFactory fabricaSesiones = configuracion.BuildSessionFactory();

Con esto se configura la fábrica de sesiones para que cada vez que ejecute comandos sobre la base de datos utilice el tiempo de espera especificado. El tiempo de espera se indica en segundos, ya que de acuerdo a la documentación es el que se asigna por defecto a los IDbCommand generados por NHibernate para las operaciones en la base de datos, y el tiempo de espera para estos se especifica en segundos.

De momento solo lo he probado en NHibernate 3, específicamente la versión 3.3.1.4000, por lo que no estoy seguro si existe en versiones previas, aunque es muy probable.
Con la tecnología de Blogger.