septiembre 2007 - Posts
Buenas
interesantes news from BHarry's blog; se he liberado la version de Septiembre de 2007 de las Power Tools para Team Foundation Server. El detalle de las novedades se puede leer aquí, pero básicamente posee 2 novedades:
- TFS Work Item Templates
Esta herramienta permite automatizar el "rellenado" de los campos de los WorkItems de Team Foundation Server, creando plantillas con los campos predefinidos con valor y luego creando WorkItems a partir de estas plantillas.
- TFS Best Practices Analyzer
Esta herramienta permite analizar instancias de Team Foundation Server y detecta en las mismas posibles errores de configuración, fallos de instalación, etc.
La descarga se puede realizar desde http://msdn2.microsoft.com/en-us/teamsystem/aa718351.aspx y espero ansioso volver a mostrar estas novedades para ver que impacto tienen en proyectos ya existentes.
Saludos @ Home
El Bruno

Buenas,
una pregunta que usualmente muchas personas se hacen cuando comienzan un nuevo proyecto de desarrollo, suele estar relacionada con la utilización/creación de Factorias de Software.
No conozco a casi ningún desarrollador que no aproveche alguna de las factorías existentes, pero creo que antes de embarcarnos en la 2da opción (creación de una SF) debemos tener varios aspectos en cuenta. En este post no hablaré sobre la teoría que subyace las Software Factories, sino que comentaré mi experiencia personal trabajando en un proyecto para la creación de las mismas.
Comencemos por la definición de una Software Factory:
“A software factory is a structured collection of related software assets. When a software factory is installed
in a development environment, it helps architects and developers predictably and efficiently create high-quality instances of specific types of applications.”
Microsoft Patterns and Practices
In software engineering and enterprise software architecture, a software factory is defined as a software organization structured such that software projects are built in discrete work centers. Work centers generally represent, or specialize in, certain software disciplines such as architecture, design, construction, integration, test, maintenance, packaging, release, etc. Much like a true manufacturing facility, software factories require clearly defined product creation and management processes. By utilizing the fundamentals of industrial manufacturing - standardized components, specialized skill sets, parallel processes, and a predictable and scalable consistency of quality – a true Software Factory can achieve a superior level of application assembly even when assembling new or horizontal solutions. Industrialization of the software process can provide benefits in terms of economies of scale, geographic distribution, load leveling, and rigorous product and process control. Software factories have gained recent popularity as a cost-efficient way to reduce the time it takes to develop, create and/or construct software solutions.
Wikipedia
En otras palabras, y enfocándonos desde el punto de vista de un developer; podemos describir a una Software Factory como una o más herramientas que automarizan la creación de artefactos para resolver un problema de un dominio específico. Por lo general, las Software Factory generan código, pero también pueden generar documentacion, scripts, guidelines, etc.
El proceso de desarrollo de una Software Factory, es un proceso complicado y que difiere mucho al proceso clásico de creación de una pieza de software. Por ejemplo; en Avanade estamos distribuidos globalmente, y el número de empleados crece año a año. Como la mayoría de los proyectos son desarrollos basados en tecnologías Microsoft; existe un área de I+D en Seattle que se dedica a la creación de Assets/Activos para que los demás equipos en el mundo seamos más productivos y tal vez más eficientes. Desde mi punto de vista de usuario/developer de estos activos, pienso que algunos son muy poco aplicables pero también estoy muy contento con otros (Aca.Net/Enterprise Library es un buen ejemplo).
Dónde
Este tipo de apuestas por parte de una empresa, supone el primer filtro para decidir quienes van a apostar por la construcción de una Software Factory. La misma supone un coste adicional para una empresa. Entre otras cosas, porque los resultados de la aplicación de la misma no son visibles inmediatamente.
Es necesario ser concientes que la creación de una Software Factory como proyecto tiene las siguientes características:
- Suele ser mas largo que un proyecto común de desarrollo, generalmente 2 ó 3 veces más largos .
- El ROI sobre el mismo, se puede esperar después de la 5ta o 6ta implantación de la SF.
- Identificar este tipo de proyectos, requiere una gran visión de negocios; ya que el resultado final del mismo deberá ser implementado en 5 o mas proyectos para ser rentables.
- Además de la inversión para la creación de la Software Factories, es necesario tener en cuenta otra inversión posterior para la formación de los profesionales que utilicen los assets que involucra la Software Factories.
Cuando
Si trabajas como consultor, seguramente cada tanto pensarás en automatizar algún tipo de proceso repetitivo que realizas en diferentes proyectos. Sin embargo, una Software Factory es algo más que un asset que se pueda reutilizar en varios proyectos.
- Para comenzar a construir una Software Factories necesitamos tener un alto conocimiento sobre el dominio específico de la aplicación sobre la que trabajará los assets de nuestra Software Factory.
- Cuando sin llegar a ser una factoría completa, tengamos una serie de assets que nos ayudan en el proceso de desarrollo; y se presente la oportunidad para empaquetar los mismos, es un buen momento.
- Cuando nuestro negocio requiera un tipo de implementación frecuente que puede ser automatizada de forma organizada.
Cómo
Si después de realizar una evaluación, finalmente nos decidimos por la construcción de una serie de herramientas que puedan conformar una Software Factory; este pequeño diagrama puede ilustrar una primera aproximación para ver como gestionar el ciclo de vida de la misma.

Como podemos ver a diferencia de un proceso estandar de desarrollo, una Software Factory comienza a madurar luego de generar un producto a partir de la misma. Un detalle muy importante es que por lo general, este tipo de proyectos son proyectos muy ágiles y dinámicos que constantemente están madurando y adaptándose a las nuevos cambios del dominio donde trabajan. Además siempre es conveniente que estén basados en una implementación de referencia sobre la que se basarán las diferentes implementaciones de una versión específica de la Software Factory.
Actualmente, Visual Studio 2005 posee muchos recursos para la construccion de este tipo de proyectos. Visual Studio Extensibility Developer Center es un punto de referencia imprescindible para comenzar a conocer como extender las herramientas que posee Visual Studio. Particularmente creo que un buen punto para comenzar es conocer:
Además un recurso imprescindible puede ser Visual Studio Extensibility Guided Tour.
Saludos @ La Finca y happy factoring
El Bruno
Buenas
después de unas semanas complicadas jugando con el Nanocóptero y cuando comienzo a cerrar los pendientes con las Domain Specific Language Tools, me queda tiempo para probar un par de cervezas con los amigos algunas de las novedades de Microsoft Visual Studio 2008. En este caso uno de los 4 pilares fundamentales del desarrollo que posee Microsoft Visual Studio 2008: Code Metrics.
Esta nueva herramienta permite a los desarrolladores generar métricas para sobre proyectos y soluciones de Visual Studio para analizar la "complejidad" de los mismos. Los resultados se realiza sobre 5 tipos diferentes de análisis: Maintainability Index, Cyclomatic Complexity, Depth of Inheritance, Class Coupling, and Lines of Code (donde los datos del primer análisis surgen de una fórmula sobre los resultados de los 4 restantes).
Pues bien, si te gusta la informática seguramente conocerás los conceptos sobre los que se basan las métricas de código, pero lo interesante es ver como está integrado dentro de Microsoft Visual Studio 2008. Para esto, pensé en escribir un poco de código para una mini demo, pero después me decanté por utilizar un poco de código ya escrito, y tal vez uno de los más populares para los desarrolladores .Net: Enterprise Library 3.1.
El proceso de análisis tarda un poco, teniendo en cuenta la cantidad de código que posee EntLib, no es de extrañar. Y tampoco es de extrañar los excelentes resultados que da el mismo; todos los assemblies con un nivel de mantenibilidad muy alto (all greens) y salvo excepciones detalles como el Core.Design la complejidad ciclomática es muy buena:
Sobre el panel Code Metrics, sobre los resultados obtenidos, es posible realizar algunos filtros por algunos de los análisis realizados para analizar más en detalle esta información:
Finalmente, si queremos realizar un análisis más detallado, es posible exportar los resultados a la herramienta de BI más popular para el desktop: Microsoft Excel.
Por ejemplo, el siguiente gráfico muestra los diferentes resultados del análisis realizado sobre cada uno de los assemblies de Enterprise Library 3.1 y si alguien está interesado en ver todo el detalle puede descargar el archivo excel desde aquí.
Nota: llama la atención la cantidad de código que tiene el Logging AppBlock, versus el Exception Handling AppBlog, entre otras cosas.
Pues bien, una gran incorporación para Microsoft Visual Studio 2008 y una nueva gran herramienta para nosotros los desarrolladores, que nos permitirá perfeccionar un poco más el resultado de nuestro trabajo diario.
Saludos @ Home
El Bruno
Buenas
se están por cumplir 2 años de mis primeros acercamientos a OpenXml y todavía no hay un SDK decente en el mercado para el procesamiento de los documentos del nuevo Microsoft Office 2007.
Ojo, esto tiene su lado bueno. Si tienes algún enemigo al que le desees lo peor, le puedes aconsejar que trabaje con el Microsoft SDK for OpenXml; pero ten cuidado porque asi empiezan las vendettas y después de esto solo queda comenzar una guerra de familias que no acabará hasta que una de las dos se extermine o hasta que se apruebe como estandar el OpenXml.
Por suerte existe una web para desarrolladores con mucha información: http://openxmldeveloper.org/. Gracias a la misma me he encontrado con un WordPad editor de archivos docx, con su código fuente incluido que, como un primer acercamiento a una aplicacion OpenXml viene muy bien. Se trata de OpenXml Writer:
Si están interesados en comenzar a trabajar con documentos OpenXml, esta aplicacíon demuestra con un código muy simple como realizar las tareas más comunes para trabajar con docs docx.
Si desoués de esto, siguen interesados en trabajar con OpenXml, esperen a la 2da versión del Microsoft SDK for OpenXml; ... ;)
Saludos @ La Finca
El Bruno
Buenas,
lamentablemente no puedo escribir mucho acerca de lo que estoy haciendo con Domain Specific Language Tools, pero cada tanto trato de dejar algún pequeño tip o tutorial sobre las mismas para que un problema o una tarea que suele tardar un día o mas en solucionarse, se pueda realizarse en minutos. No me considero un usuario experto, pero si admito que las estoy utilizando/presionando bastante hasta ver adonde llega el SDK de Visual Studio 2005 y las propias Domain Specific Language Tools. Como cualquier herramienta en su primera versión, en este momento el concepto al que tratan de acercarnos es muy interesante; pero lamentablemente la implementación es un poco pobre en algunos aspectos, la distribución por ejemplo.
Es por eso que el equipo encargado de Domain Specific Language Tools se ha movido del grupo Team Architect al equipo de Visual Studio (donde por naturaleza deberían pertenecer). Además al ser parte nativa del shell de Visual Studio, no será necesario el SDK de Visual Studio para el desarrollo de DSLs, estarán mucho más integradas dentro de Visual Studio.
Sin embargo la nueva versión de VS, Microsoft Visual Studio 2008 no implementará grandes cambios con respecto a las DSL Tools actuales, solo la inclusión dentro del IDE, algunos fixs importantes del SDK y por fin un improvement para la gestion de los path entre elementos del modelo.
Para los cambios importantes, en cuanto a diseño, implementacion y maduración del modelo de creación de DSLs deberemos esperar hasta Rosario, o ¿porque no? utilizar las propias Domain Specific Language Tools para crear una nueva versión de las Domain Specific Language Tools.
Saludos @ Home
El Bruno
PD: se que crear código que se cree a si mismo da un poco de miedo porque es un step close a los robots que aprenden a aprender, y a partir de allí queda muy poco para un futuro apocalíptico donde los robots se muevan como en este video.
Buenas,
siguiendo con la lista de las tareas más comunes que realizamos o aunque sea tratamos cuando trabajamos con las Domain Specific Language Tools es agregar un menú personalizado dentro del IDE de Visual Studio 2005.
Como siempre el mejor lugar para poder encontrar una referencia es MSDN, pero sin embargo no existe un ejemplo end-to-end para poder completar esta tarea. Es por esto que el siguiente tutorial, partirá desde el último ejemplo de un proyecto DSL para la gestión de Proyectos y Usuarios, y sobre el diseñador agregaremos un menú contextual que muestre información sobre el o los elementos seleccionados.
Tutorial
- Trabajaremos sobre el proyecto DslPackage.
- Editar el archivo DslPackage \\ CtcComponents \\ Commands.ctc
(es conveniente refrescar algunos conociemientos de hace algun tiempo para comprender la sintaxís de este archivo, pero siempre es bueno volver a la fuente) - Después de la sección de los includes, agregamos 2 #defines para referenciar nuestro nuevo elemento del menú.
- El primer elemento definirá un id unívoco para el menú y el segundo elemento identificará al ícono que se le asignará al menú.
#define displaySelectedItemInformation 0x801
#define IconDslMenu guidOfficeIcon:msotcidMergeToDocument
- Para la imagen del menú he utilizado uno de los 7000 iconos disponibles que trae Office y que podemos encontrar en el archivo "..\Program Files\Visual Studio 2005 SDK\2007.02\VisualStudioIntegration\Common\Inc\office10\msobtnid.h", incluido dentro de la definición del archivo Commands.ctc. De este archivo he seleccionado la entrada 159 que representa al Label: "&Merge to Document"
- Dentro de la sección BUTTONS_BEGIN agregamos la definición para la creación de nuestro menú.
BUTTONS_BEGIN
GENERATED_BUTTONS
// Add additional button definitions here.
// Command, Parent Group, Priority, Image, Type, Visibility, Text;
//guidCmdSet:displaySelectedItemInformation, guidCmdSet:grpidContextMain, 0x0100, OI_NOID, BUTTON, DIS_DEF, "&Display Selected Item Information";
guidCmdSet:displaySelectedItemInformation, // Command ID
guidCmdSet:grpidContextMain, // Group ID
0x0100, // Priority
IconDslMenu, // Icon ID
BUTTON, // Button Type
0, // Flags
"&Display Information", // Command Text
"&Display Information", // Menu Text
"Display Selected Item Information", // ToolTip Text
"Display Selected Item Information", // Command Well Text
"DisplayImformation", // English Command Name
"DisplayImformation"; // Localized Command Name
BUTTONS_END
la definición de cada nuevo elemento que querramos agregar se comprende de una serie de valores que identifican el elemento, el elemento superior, la prioridad, el icono del mismo, el tipo de elemento, la visibilidad, y el texto. La definición completa de los elemento en esta sección se explica en el MSDN en este link.
- A continuación editamos el archivo DslPackage \\ GeneratedCode \\ Package.tt; y modificamos la definición de los menues que agregaremos incrementando el parametro contador como la cantidad de menúes que queremos agregar. En este caso es igual a 1:
[VSShell::ProvideMenuResource(1000, 1)]
- Transformamos todos los templates desde el Solution Explorer (o alguna ruta alternativa)
- Agregamos una nueva clase al proyecto llamada Dsl15CommandSet.partial.cs. Este archivo implementará una clase parcial para la clase Dsl15CommandSet.
- Dentro de esta clase agregaremos una constante que represente nuestro menú y que coincida con el valor del menu que creamos en el Commands.ctc. Por ejemplo:
#region Command ID constants
// Must be unique within this DSL.
// Must equal the values defined in Commands.ctc
private const int displaySelectedItemInformation = 0x801;
#endregion
- Sobreescribiremos la función GetMenuCommands(), donde agregaremos un nuevo menu referenciado al id que creamos en el paso anterior. Para la creación del CommandId utilizo un helper llamado CustomCommandId():
/// <summary>
/// Register event handlers for menu commands. Called once when the DSL designer starts.
/// </summary>
/// <returns></returns>
protected override IList<System.ComponentModel.Design.MenuCommand> GetMenuCommands()
{
// Get the commands defined in the generated code.
global::System.Collections.Generic.IList<global::System.ComponentModel.Design.MenuCommand> commands = base.GetMenuCommands();
CommandID cmdId = CustomCommandId(displaySelectedItemInformation); // Unique Id for this command
// Add command handlers for menu items to change an Association's sort.
// Each command has two handlers:
// OnStatus... which determines whether the command should appear on the menu
// OnMenu... which performs the command
DynamicStatusMenuCommand displaySelectedItemMenu =
new DynamicStatusMenuCommand(
new EventHandler(OnPopUpMenuDisplayAction),
new EventHandler(OnPopUpMenuClick), cmdId);
displaySelectedItemMenu.Text = "&Display Selected Item Information";
// add new PopUpMenu
commands.Add(displaySelectedItemMenu);
// Registration of more command handlers if required go here...
return commands;
}
/// <summary>
/// Helper to create local CommandIDs.
/// The integer ID is qualified with a Guid for this DSL, so as to ensure
/// the ID is unique in the system.
/// </summary>
/// <param name="command">Command number within this language</param>
/// <returns></returns>
private CommandID CustomCommandId(int command)
{
return new CommandID(new Guid(Constants.Dsl15CommandSetId), command);
}
- Finalmente debemos agregar 2 EventHandlers para gestionar la visibilidad del elemento en tiempo de ejecución (OnPopUpMenuDisplayAction) y para gestionar el evento Click del mismo (OnPopUpMenuClick). En el evento Click recorreremos la lista de elementos seleccionados y crearemos un string con el contenido de los mismos para mostrarlo en un MessageBox.
#region Handlers for New PopUpMenu
internal void OnPopUpMenuDisplayAction(object sender, EventArgs e)
{
MenuCommand command = sender as MenuCommand;
// The popmenu command is always visible
command.Visible = true;
command.Enabled = true;
}
internal void OnPopUpMenuClick(object sender, EventArgs e)
{
MenuCommand command = sender as MenuCommand;
StringBuilder sb = new StringBuilder();
foreach (object selectedObject in this.CurrentSelection)
{
sb.AppendLine("Selected Object: " + selectedObject.ToString());
}
System.Windows.Forms.MessageBox.Show(sb.ToString());
}
#endregion
- Compilamos la solución y cuando ejecutamos la misma podremos ver, si desplegamos el menu contextual sobre el diseñador la nueva opción:
- Si seleccionamos los 3 elementos de usuario y presionamos el menú que recién hemos creado veremos el mensaje con la información de los elementos seleccionados:
Proyecto de ejemplo
El proyecto de ejemplo se puede descargar desde aquí y un pequeño video para mostrar el resultado final del proyecto.
Video: DSL - Add new menu item
Saludos @ Home
El Bruno
Buenas,
las enfermeras siguen poco contentas conmigo; un hospital es un lugar donde no se puede hacer mucho ruido (casi nada creo); y eso crea un ambiente bastante aburrido. Para matar este aburrimiento decidí traer uno de los últimos juguetes que me regalo mi chica: el Nanocóptero (además me han prohibido publicar los videos del nanocóptero en una persecución cuerpo a cuerpo con uno de mis gatos)
Pero bueno, unas fotos en la pieza del hospital puedo mostrar:
Bases de un juguete complejo
Para aquellas personas como yo que no tenemos mucho mundo arriba, los secretos de la aerodinámica son algo complejos. Gracias a mi padre que es físico me entero que en realidad la base es que:
La fuerza vertical que eleve un avión o helicóptero tendrá que ser igual o mayor que la fuerza de su peso.
En el Nanocóptero el paso del aire para crear sustentación se consigue impulsando las alas circularmente, es decir creando un fuerza vertical para abajo. Además se utiliza el rotor de cola para dar estabilidad horizontal al mismo. Con esta base y después de jugar un rato, pude controlar muy precariamente los movimientos del nanocóptero.
Introducing Mobile
Y aquí comenzó el desafío, aquellos que sean detallistas habrán notado que además del nanocóptero, mi Dell Latitude D620 me hacía compania; eso significa Visual Studio, acceso a internet y ganas de probar algo nuevo.
Como el control del nanocóptero se comunica con el mismo a través de infrarrojos, y mi PDA tiene un control de infrarrojos, supuse que tal vez el .Net Compact Framework me podía ayudar a realizar algo tan simple como un pequeño soft para controlar el nanocoptero desde la PDA.
Dentro de MSDN podemos encontrar mucha información al respecto, por ejemplo la librería de referencia central: Infrared Connections.
Sin embargo después de tirar algunas líneas las enfermeras me quitaron el nanocóptero descubrí que la librería incluida en el .Net Compact Framework solo soporta el estandar IrDA (a seguir leyendo, ahora cambiamos desde MSDN a http://www.irda.org/), y parece que el nanocóptero como viene de China tiene su propia idiosincracia.
Sin embargo he dejado preparados las siguientes líneas para completar cuando me respondan los fabricantes del nanocóptero con las especificaciones técnicas del mismo:
1 Imports System.Net
2 Imports System.Net.IrDAEndPoint
3 Imports System.Net.Sockets
4 Imports System.IO
5
6 Public Class Form1
7 Dim irClient As IrDAClient
8 Dim irServiceName As String = "IrDANanocopteroTest"
9 Dim irDevices() As IrDADeviceInfo
10 Dim buffersize As Integer = 256
11
12 ''' <summary>
13 ''' Moves the nanocopter.
14 ''' </summary>
15 Public Sub MoveNanocopter()
16 irClient = New IrDAClient()
17
18 ' coneccion al IrDA
19 If Not GetInfraredDevice() Then Exit Sub
20
21 irClient.GetStream()
22
23 ' stream para enviar datos
24 Dim fs As Stream
25 fs = New MemoryStream(1024)
26
27 ' obtener un stream para la comunicacion ...
28 Dim baseStream As Stream = irClient.GetStream()
29
30 ' COMPLETE ...
31
32 ' dispose
33 fs.Close()
34 baseStream.Close()
35 irClient.Close()
36
37 End Sub
38
39 ''' <summary>
40 ''' Gets the infrared device.
41 ''' </summary>
42 ''' <returns>True if the connection was successful</returns>
43 Private Function GetInfraredDevice() As Boolean
44 Dim connected As Boolean = True
45
46 ' obtiene el dispositivo infrarrojo
47 irDevices = irClient.DiscoverDevices(1)
48
49 ' valida si se pudo conectar al dispositivo de infrarojos
50 If irDevices.Length = 0 Then
51 MsgBox("No remote infrared devices found.")
52 connected = False
53 End If
54 Try
55 Dim irEndP As New IrDAEndPoint(irDevices(0).DeviceID, irServiceName)
56 Dim irListen As New IrDAListener(irEndP)
57 irListen.Start()
58 irClient = irListen.AcceptIrDAClient()
59 MsgBox("Nanocoptero conectado !!!")
60
61 Catch ex As Exception
62 Dim msg As String = String.Format("No se pudo conectar al dispositivo: {0}", ex.ToString())
63 MsgBox(msg)
64 connected = False
65 End Try
66
67 ' retorna el estado de la conexion
68 Return connected
69 End Function
70
71 End Class
Pues bien, la persona que dijo la frase: "nunca subestimes el poder del aburrimiento" ... tenia mucha pero mucha razón.
(creo que fueron Ricardo Varela y Chema Alonso en el CodeCamp del 2006)
Saludos @ Hospital
El Bruno
Buenas
Buenas
existen pocas cosas más aburridas que un hospital, tal vez las espesas reuniones de gerentes alrededor de las 19:00; pero bueno este tiempo sirve para empezar a sacar post del folder Draft y no seguir jugando con la Wii porque a las enfermeras no les cae bien.
Antes de comenzar con la generación de artefactos utilizando las Domain Specific Language Tools, me gustaría dejar un pequeño tip que permite agregar una imagen de fondo a un modelo creado con las Domain Specific Language Tools (otra de las features que pienso que falta en el SDK, pero que ya ha sido solicitado para la nueva versión)
Para comenzar parto del ejemplo que dejé en mi último post sobre DSLs, y después de completar un poco el mismo con algunos elementos nuevos quiero cambiar el siguiente editor por uno con este background.
Tutorial
- Agregamos una imagen como un recurso a nuestro proyecto. (para simplificar un poco el código he agregado la imagen como un recurso, pero se puede implementar de varias formas diferentes)
- Seleccionar el elemento que representa al diagrama, Dsl15Diagram y cambiar la propiedad Generate Double Derived: True.
- Generamos el código para reflejar nuestros cambios en el modelo.
- Agregamos una nueva clase al proyecto Dsl llamada Dsl15Diagram.partial.cs y agregamos el siguiente código a la misma. Dentro del método InitializeShapeFields() agregamos un nuevo Shape del tipo ImageField y configuramos al mismo definiendo que no pueda tomar foco ni ser seleccionado, y sus márgenes:
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.VisualStudio.Modeling.Diagrams;
using ElBruno.Dsl15.Properties;
namespace ElBruno.Dsl15
{
public partial class Dsl15Diagram
{
/// <summary>
/// Initialize shape decorator mappings. This is done here rather than in individual shapes because decorator maps
/// are defined per diagram type rather than per shape type.
/// </summary>
/// <param name="shapeFields"></param>
protected override void InitializeShapeFields(IList<Microsoft.VisualStudio.Modeling.Diagrams.ShapeField> shapeFields)
{
base.InitializeShapeFields(shapeFields);
// add backgroung image to the designer
ImageField backgroundImage = new ImageField("background", Properties.Resources.fondo);
backgroundImage.DefaultFocusable = false;
backgroundImage.DefaultSelectable = false;
backgroundImage.DefaultVisibility = true;
shapeFields.Add(backgroundImage);
// define Background Image margins
backgroundImage.AnchoringBehavior.Clear();
backgroundImage.AnchoringBehavior.SetTopAnchor(AnchoringBehavior.Edge.Top, -1.5);
backgroundImage.AnchoringBehavior.SetLeftAnchor(AnchoringBehavior.Edge.Left, 0);
}
}
}
- Compilamos la solución y ejecutamos nuevamente. Podremos ver el editor como lo muestra la siguiente imagen:
Tip simple pero efectivo. El código de ejemplo se puede descargar desde aquí.
Saludos @ Hospital
El Bruno
Buenas
después del minipost de hace unos días sobre la utilización de String.IsNullOrEmpty en el desarrollo de aplicaciones; alguien me preguntó porque String vs StringBuilders. Ya se que este no es un tema nuevo y que seguramente mucha gente lo conoce, pero para los que no estén al tanto, un consejo: "ojo con el enfoque que le dan a sus aplicaciones si tienes un proceso de cadenas string muy intensivo".
¿Porqué digo esto? porque en .Net los string son objetos rígidos, es decir, no es posible concatenar strings dentro del objeto strings. Si bien podemos utilizar la función Concat(), para cada nuevo String que procesamos, el string original se destruye y uno nuevo se crea en su lugar.
Como siempre la mejor forma de demostrarlo en con código, y para esto rescato una clase que hace muchísimo escribí para una demo:
1 class Program
2 {
3 /// <summary>
4 /// Mains the specified args.
5 /// </summary>
6 /// <param name="args">The args.</param>
7 static void Main(string[] args)
8 {
9 // 1000 operations
10 TestString(1000);
11 TestStringBuilder(1000);
12
13 // 5000 operations
14 TestString(5000);
15 TestStringBuilder(5000);
16
17 // 10000 operations
18 TestString(10000);
19 TestStringBuilder(10000);
20
21 // 50000 operations
22 TestString(50000);
23 TestStringBuilder(50000);
24
25 // 100000 operations
26 TestString(100000);
27 TestStringBuilder(100000);
28
29 Console.WriteLine("Finish process test ...");
30 Console.ReadKey();
31 }
32
33 /// <summary>
34 /// Tests the string.
35 /// </summary>
36 /// <param name="count">The count.</param>
37 public static void TestString(int count)
38 {
39 DateTime dtStart = DateTime.Now;
40 string ret = string.Empty;
41 for (int i = 0; i < count; i++)
42 {
43 ret += i.ToString();
44 }
45 DateTime dtEnd = DateTime.Now;
46 TimeSpan tsDif = dtEnd - dtStart;
47 Console.WriteLine(string.Format("For {0} operations Using Strings: {1} seconds", count, tsDif.Seconds.ToString()));
48 }
49
50 /// <summary>
51 /// Tests the string builder.
52 /// </summary>
53 /// <param name="count">The count.</param>
54 public static void TestStringBuilder(int count)
55 {
56 DateTime dtStart = DateTime.Now;
57 StringBuilder sb = new StringBuilder();
58 for (int i = 0; i < count; i++)
59 {
60 sb.Append( i.ToString() );
61 }
62 DateTime dtEnd = DateTime.Now;
63 TimeSpan tsDif = dtEnd - dtStart;
64 Console.WriteLine(string.Format("For {0} operations Using StringBuilder: {1} seconds", count, tsDif.Seconds.ToString()));
65 }
66 }
67
Como pueden ver, esta aplicación de Consola crea y concatena strings en un determinado numero de ocasiones y durante el proceso, toma los tiempos de inicio y fin para poder tener la diferencia de los mismos. El output de la consola es bastante explícito en cuando a las relaciones
For 1000 operations Using Strings: 0 seconds
For 1000 operations Using StringBuilder: 0 seconds
For 5000 operations Using Strings: 0 seconds
For 5000 operations Using StringBuilder: 0 seconds
For 10000 operations Using Strings: 0 seconds
For 10000 operations Using StringBuilder: 0 seconds
For 50000 operations Using Strings: 10 seconds
For 50000 operations Using StringBuilder: 0 seconds
For 100000 operations Using Strings: 55 seconds
For 100000 operations Using StringBuilder: 0 seconds
Finish process test ...
Saludos @ Madrid
El Bruno
Buenas
si trabajar con proyectos de bases de datos con Visual Studio Team Edition for Database Professionals, y has probado las opciones de deploy de este tipo de proyectos, seguramente habrás tenido la necesidad de inicializar algunas tablas con datos, luego de crear la base de datos en el Deploy. Pues bien, una de las formas de realizar esta acción es uitilizar los Data Generation Plans incluidos en cada proyecto, pero tal vez si ya tienes tu base de datos con datos de ejemplo, te interese replicar los mismos.
El siguiente tutorial demuestra como crear un proyecto de BD utilizando AdventureWorks y como generar un deploy del mismo con parte de los datos de ejemplo.
Tutorial
1. Crear un nuevo proyecto de base de datos para Microsoft SQL Server 2005 llamado AdventureWorksDeploy.
2. Importar el Schema de AdventureWorks, deplegando el menu contextual sobre el proyecto y seleccionado Import Database Schema.
3. Crear una nueva conexión hacia AdventureWorks e importar el Schema.
4. Desde las propiedades del proyecto, configurar la base de datos de destino para el Deploy. En este caso lo haré sobre mi servidor local y sobre una nueva base de datos llamada AdventureWorksDeploy. Además debemos marcar la opción Always re-create database.
5. Una vez configurada la base de datos de deploy realizamos un deploy para que la misma se cree con las tablas vacías, desplegando el menú contextual sobre el proyecto y seleccionando la opción Deploy. Verificamos que en el servidor de datos se haya creado una nueva base datos: AdventureWorksDeploy.
6. Lanzamos el comparador de datos desde el menu Data // Data Compare // New Data Comparison, seleccionando AdventureWorks y AdventureWorksDeploy como bases de datos para comparar.
7. Sunpogamos que solo queremos insertar los datos de la tabla Production.ProductModel, seleccionamos la misma y seleccionamos la opcion Export to Editor.
8. La comparación de datos ha creado un script para la generación de datos, que entre otras cosas deshabilita las claves y relaciones de las tablas, deshabilita los Identity para la insercion de datos, serializa los campos binarios a base64, etc.
9. Dentro del proyecto crearemos una nueva carpeta llamada SampleData.
10 . Dentro de esta carpeta agregamos un nuevo sql script llamado Production.sql. Copiamos el contenido del script para la generación de datos dentro de este archivo y lo grabamos.
11. Editamos el archivo \Scripts\Post-Deployment\Script.PostDeployment.sql y agregamos la siguiente instrucción al final del mismo:
:r ..\..\SampleData\Production.sql
esta instrucción incluye el archivo Production.sql en la ejecución del PostDeploy script.
13. Nuestro archivo debe quedar con el siguiente contenido o similar:
/*
Post-Deployment Script Template
--------------------------------------------------------------------------------------
This file contains SQL statements that will be appended to the build script
Use SQLCMD syntax to include a file into the post-deployment script
Example: :r .\filename.sql
Use SQLCMD syntax to reference a variable in the post-deployment script
Example: :setvar TableName MyTable
SELECT * FROM [$(TableName)]
--------------------------------------------------------------------------------------
*/
:r .\Permissions.sql
:r .\RoleMemberships.sql
:r .\RulesAndDefaults.sql
:r .\DatabaseObjectOptions.sql
:r .\Signatures.sql
-- =================================
-- ADD SAMPLE DATA
-- =================================
:r ..\..\SampleData\Production.sql
14. A continuación realizamos un nuevo deploy de la base de datos y veremos que en la base de datos creada AdventureWorksDeploy en la tabla Production.ProductModel están los datos de ejemplo.
Conclusión
Las herramientas que posee Visual Studio Team Edition for Database Professionals nos permiten crear y desplegar muy fácilmente bases de datos SQL Server. Siguiendo los pasos del tutorial podemos agregar más tablas en la comparación y generar un script para la inserción de datos, o tal vez generar varios scripts para la inserción de datos separando los mismos por algún criterio en particular. Por ejemplo:
Descarga del proyecto de ejemplo (gracias geeks.ms)
SkyDrive
Saludos @ Home & happy db deploying
El Bruno
Buenas
si después de trabajar mucho con las Domain Specific Language Tools te encuentras con un Visual Studio 2005 con demasiadas opciones para agregar nuevos ítems a un proyecto, es momento de eliminar la información que "sobra".
En mi caso tengo demasiados items; producto de sobredosis de fiestas y cervezas numerosas pruebas hasta comprender los intricados secretos de las Domain Specific Language Tools:
Pues bien, estos "items sobrantes" están registrados en el registro de Windows para la instancia Experimental Build de Visual Studio(nota mental: no repetir en público que en el registro de windows hay cosas registradas). La ruta donde se encuentran es: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\8.0Exp y además los templates se encuentran en las carpetas de proyecto de Visual Studio.
Por suerte el proceso para eliminar estos items es muy simple: desde el menu inicio de Windows, seleccionamos
- Visual Studio 2005 SDK
- 2007.02
- Tools
- Reset the Visual Studio Experimental Hive
y listo nuestra instancia experimental de Visual Studio quedará limpia y lista para seguir con nuestras pruebas.
Para los más curiosos que estén interesados en conocer que hace este comando, esta es la instrucción que se ejcuta:
"C:\Program Files\Visual Studio 2005 SDK\2007.02\VisualStudioIntegration\Tools\Bin\VsRegEx.exe" GetOrig 8.0 Exp
Saludos @ Home
El Bruno

Buenas
estaba comentando con unos compañeros la utilización de String.IsNullOrEmpty en las aplicaciones para mejorar la performance de las mismas (sumado al uso de StringBuilder, etc.); cuando mi proyecto de ejemplo de Consola de C# se estrelló estrepitosamente contra la memoria de Windows.
Después de buscar un rato la solución (y pensando que el error era mío), me encuentro con este bug de C# (yes C# no VB):
Null Exemption caused by JIt optimisation around String.IsNullOrEmpty
<