´

May 2012 - Artículos

Como aumentar el tiempo de carga de nuestras web – los iframe

 

Articulo tomado de mi blog

Como aumentar el tiempo de carga de nuestras web – los iframe

-------------------------

El tiempo de carga de nuestros sitios web es un tema complejo, abordarlo completamente fácilmente podría ser tema de un solo blog… y no hablemos de las diferencias entre hacerlo con plataformas .Net o LAMP o lo que sea. Es un tema largo.

Así que siempre hay que abordarlo desde lo más grande hasta lo más pequeño. En la web moderna es frecuente encontrarse con iframes puesto que la integración con diversos servicios como redes sociales, mapas y demas gadgets suele hacerse por medio del tag <iframe> , lo cual en resumen es un marco que despliega contenidos alojados en otra web.

El problema con los iframes es que funcionan de manera síncrina, es decir nuestra web esta cargando normalmente, encuentra un iframe y comienza a cargarlo, solo cuando el iframe es cargado por completo continua la carga de los demas elementos de nuestra web.

Lo ideal entonces es hacer que la carga de éstos iframe sea asincónica o bien dilatarla para que inicien su carga solo cuando todo nuestro sitio haya sido desplegado, esto lo podemos hacer manipulando alguno de los eventos de carga de la pagina y luego escribiendo los tag del iframe dinámicamente.

Este es un código de prueba de un iframe

1
<iframe id="gmap" name="gmap" width="100%" height="400" src="http://www.otraweb.com"></iframe>

Para cargarlo dinamicamente lo primero que haremos es envolverlo dentro de un nuevo div al cual llamaremos “#map-container”

1
2
3
<div id="map-container">
<iframe id="Iframe1" name="gmap" width="100%" height="400" src="http://www.otraweb.com"></iframe>
</div>

Ahora haremos la parte del evento de carga de la página, a mi me gusta hacerlo con JQuery, pero ya sabes que puedes hacerlo con lo que desees. Colocamos el código dentro del evento ready de JQuery. El código es como sigue:

1
2
3
4
5
6
$(window).load(
    function()
    {
        $("#map-container").html(/*CONTENIDO AQUI*/);
    }
);

Así que ahora tomamos todo el contenido del tag <iframe> y lo enviamos como parámetro:

1
2
3
4
5
6
7
$(window).load(
    function()
    {
        var iframeString ='<iframe id="Iframe2" name="gmap" width="100%" height="400" src="http://www.otraweb.com"></iframe>';
        $("#map-container").html(iframeString);
    }
);

Y eso es todo, en adelante el tiempo de carga de tu página es independiente del tiempo de carga de los iframe ;) .

 

El control RichEditBox no muestra le formato de los documentos RTF aunque esten bien formados – Metro – Windows 8 – C#

 

Artículo tomado de mi blog

http://juank.black-byte.com/csharp-richeditbox-rtf-metro-formato/

------------------

Algunas veces cuando cargamos documentos RTF en un RichEditBox nos llevamos la no muy grata sorpresa de que aunque se muestra el texto correctamente los formatos aplicados a este, como color, negrita, itálica, etc. no son tenidos en cuenta.

Podemos abrir los RTF en editores comoWordpad y allí se muestran correctamente. Este problema se debe a que el controlRichEditBox no esta preparado en todo momento para aplicar dichos formatos, razón por la cual no es recomendable asignar el texto del documento hasta no estar 100% seguro de que el control ha cargado en su totalidad, por ende se debe evitar cargar texto en este control en el constructor de su clase contenedora, y en su lugar hacerlo en el evento Loaded, ejemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
    <common:LayoutAwarePage
    x:Name="pageRoot"
    x:Class="Test.GroupDetailPage"
    xmlns:local="using:Test"
    xmlns:data="using:Test.Data"
    xmlns:common="using:Test.Common"
    mc:Ignorable="d">
    <RichEditBox x:Name="Richtest" Loaded="LoadedEventHandler"/>
</common:LayoutAwarePage>

Este es el code Behind

1
2
3
4
5
6
private void LoadedEventHandler(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
    var cadena = @"{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033{\colortbl;\red255\green0\blue0;}{\cf1 Hello World }{\b nice text}{\par}}";
 
    rich.Document.SetText(TextSetOptions.FormatRtf, cadena);
}

 

Mostrar colores de documentos RTF al cargarlos en un RichEditBox – Metro – Windows 8 – C#

artículo tomado de mi blog

http://juank.black-byte.com/csharp-metro-mostrar-colores-rtf-richeditbox/

-----------------

Cuando cargamos documentos RTF en un RichEditBox esperamos que el formato siempre sea el adecuado, sin embargo en ocasiones, especialmente cuando nos entregan los RTF extraidos en una base de datos o en otros formatos diferentes de RTF, nos encontramos con que los textos coloreados no son procesados

EL color dentro de un archivo RTF se encuentra demarcado por medio de los ‘tag’ {\cf# donde # es un numero de color. De esta forma si buscamos dentro de un texto coloreado con RTF podemos encontrar un código como el que se ve a continuación:

1
{\cf1 Hola Mundo} \b nice text\b0

Donde cf1 hace referencia a un color determinado. Retomando el planteamiento inicial es posible en algunos escenarios que el texto sea mkjostrado sin el formato de color, esto se debe a que RTF requiere que se establezca previamente una paleta de colores que indique, por ejemplo, a que color equivale cf1.

Para ello, justo al inicio del documento establecemos la ‘etiqueta’ \colortbl la cual contiene una lista de entradas, donde cada una de estas entradas representa un color, la siguiente muestra una lista de 2 colores definidos, el azul y el rojo.

1
2
3
{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033
{\colortbl ;\red0\green0\blue255;\red255\green0\blue0;}
}

Este color creado en nuestra ‘paleta de colores’ puede ser referido en cualquier parte del documento como cf1, de tal forma si deseamos escribir “Hola Mundo” en color azul y rojo basta con hacer lo siguiente:

1
2
3
4
{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033
{\colortbl ;\red0\green0\blue255;\red255\green0\blue0;}
{\cf1 Hola}{\cf2 Mundo}
}

Si envias el documento (o sea la cadena de texto con la información) dentro de estos tag entonces al cargar la información dentro del RichEditBox debes asegurarte de indicarle el formato que debe aplicar, ejemplo:

1
2
3
4
5
string cadena = @"{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033
{\colortbl ;\red0\green0\blue255;\red255\green0\blue0;}
{\cf1 Hola}{\cf2 Mundo}
}";
MyRichEditBox.Document.SetText(TextSetOptions.FormatRtf, cadena);

De esta forma los documentos RTF cargados mostraran sus colores adecuadamente en un RichEditBox.

RichEditBox muestra caracteres extraños al abrir documento RTF C# – Windows 8 – Metro

Tomado de mi blog:

http://juank.black-byte.com/csharp-richeditbox-rtf-metro/

-------------------

En algunas ocasiones necesitamos cargar documentos RTF en un RichEditBox no direcamente desde archivo sino de otras fuentes, en estas ocasiones es común encontrarnos conque nuestro RTF se muestra de la siguiente manera

1
{\cf1 Hola Mundo} \b nice text\b0

Es decir nuestro RTF muestra el código pero el RichEditBox no es capaz de interpretarlo, este error se debe principalmente a que no se ha indicado el encabezado estandard de un documento RTF. Todo documento RTF debe estar contenido dentro de los siguintes tag omo mínimo:

1
{\rtf1 CONTENIDO }

Sin embargo es recomendable incluir información relacionada con la versión del documento, quedando de esta manera:

1
{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033 CONTENIDO }

Si envias el documento (o sea la cadena de texto con la información) dentro de estos tag entonces al cargar la información dentro del RichEditBox debes asegurarte de indicarle el formato que debe aplicar, ejemplo:

1
2
string cadena = @"{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033 Hello World\par}";
MyRichEditBox.Document.SetText(TextSetOptions.FormatRtf, cadena);

De esta forma ya no apreceran carácteres ‘basura’ el cargar tus datos RTF en un RichEditBox

Visual C# – Cómo tener un archivo de configuración más limpio

Articulo tomado de mi blog:

http://juank.black-byte.com/csharp-archivo-configuracion-limpio/

-----------------

o Como reducir el archivo de configuración usando múltiples archivos .config

Como programadores siempre tenemos que lidiar con archivos de configuración, en mi opinión una hermosa forma de deshacernos de complejidad innecesaria en el código y desde luego una manera muy cool de crear aplicaciones fléxibles.

Sin embargo en aplicaciones de tipo empresarial comenzamos a tener detestables problemas con estos archivos. El notable aumento de complejidad en su estructura se convierte en una bomba de tiempo para el mantenimiento de las aplicaciones, es común encontrase con archivos de configuración que se miden en cientos de lineas y a veces en miles.

Cómo tener un archivo de configuración más limpio?

Por fortuna existe un mecanismo muy útil, a continuación les muestro un archivo de configuración que si bien no es uno precisamente enorme, ya comienza a mostrar problemasde legibilidad, en esta ocasión generados por la configuración de Unity Application Block , hablaremos de el en otro momento.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
  </configSections>
      <typeAliases>
        <!-- Lifetime manager types -->
        <typeAlias alias="singleton"
             type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager,
                   Microsoft.Practices.Unity" />
        <typeAlias alias="external"
             type="Microsoft.Practices.Unity.ExternallyControlledLifetimeManager,
                   Microsoft.Practices.Unity" />
        <!-- User-defined Lifetime manager types -->
        <typeAlias alias="web_session"
            type="Traversal.Utilities.Web.WebSessionLifetimeManager,
                   Traversal" />
        <!-- Tipos para Domain.Core -->
        <typeAlias alias="IDataContextWrapper"  type="Domain.Core.Data.IDataContextWrapper`1, Domain.Core" />
        <typeAlias alias="IParameterManager"    type="Domain.Core.Repositories.IParameterManager, Domain.Core" />
        <typeAlias alias="ILocalizationManager" type="Domain.Core.Repositories.ILocalizationManager, Domain.Core" />
 
        <typeAlias alias="ContextWrapperSTE"    type="Domain.Core.Data.ContextWrapperSTE`1, Domain.Core" />
        <typeAlias alias="ContextWrapperEF"     type="Domain.Core.Data.ContextWrapperEF`1, Domain.Core" />
        <typeAlias alias="ParameterManager"     type="Domain.Core.Repositories.ParameterManager, Domain.Core" />
        <typeAlias alias="LocalizationManager"  type="Domain.Core.Repositories.LocalizationManager, Domain.Core" />
 
        <!-- Tipos para oplkjsdfkpwe.Core -->
        <typeAlias alias="IEnteManager"          type="Domain.wsldckm.Repositories.IEnteManager, Domain.oplkjsdfkpwe" />
        <typeAlias alias="IEquipoManager"        type="Domain.wsldckm.Repositories.IEquipoManager, Domain.oplkjsdfkpwe" />
        <typeAlias alias="IEstadioManager"       type="Domain.wsldckm.Repositories.IEstadioManager, Domain.oplkjsdfkpwe" />
        <typeAlias alias="IEventoManager"        type="Domain.wsldckm.Repositories.IEventoManager, Domain.oplkjsdfkpwe" />
        <typeAlias alias="IPartidoManager"       type="Domain.wsldckm.Repositories.IPartidoManager, Domain.oplkjsdfkpwe" />
        <typeAlias alias="ITagManager"           type="Domain.wsldckm.Repositories.ITagManager, Domain.oplkjsdfkpwe" />
        <typeAlias alias="ITipoFormacionManager" type="Domain.wsldckm.Repositories.ITipoFormacionManager, Domain.oplkjsdfkpwe" />
        <typeAlias alias="ITorneoEtapaManager"   type="Domain.wsldckm.Repositories.ITorneoEtapaManager, Domain.oplkjsdfkpwe" />
        <typeAlias alias="ITorneoNominaManager"  type="Domain.wsldckm.Repositories.ITorneoNominaManager, Domain.oplkjsdfkpwe" />
        <typeAlias alias="ITorneoManager"        type="Domain.wsldckm.Repositories.ITorneoManager, Domain.oplkjsdfkpwe" />
 
        <typeAlias alias="EnteManager"           type="Domain.wsldckm.Repositories.EnteManager, Domain.oplkjsdfkpwe" />
        <typeAlias alias="EquipoManager"         type="Domain.wsldckm.Repositories.EquipoManager, Domain.oplkjsdfkpwe" />
        <typeAlias alias="EstadioManager"        type="Domain.wsldckm.Repositories.EstadioManager, Domain.oplkjsdfkpwe" />
        <typeAlias alias="EventoManager"         type="Domain.wsldckm.Repositories.EventoManager, Domain.oplkjsdfkpwe" />
        <typeAlias alias="PartidoManager"        type="Domain.wsldckm.Repositories.PartidoManager, Domain.oplkjsdfkpwe" />
        <typeAlias alias="TagManager"            type="Domain.wsldckm.Repositories.TagManager, Domain.oplkjsdfkpwe" />
        <typeAlias alias="TipoFormacionManager"  type="Domain.wsldckm.Repositories.TipoFormacionManager, Domain.oplkjsdfkpwe" />
        <typeAlias alias="TorneoEtapaManager"    type="Domain.wsldckm.Repositories.TorneoEtapaManager, Domain.oplkjsdfkpwe" />
        <typeAlias alias="TorneoNominaManager"   type="Domain.wsldckm.Repositories.TorneoNominaManager, Domain.oplkjsdfkpwe" />
        <typeAlias alias="TorneoManager"         type="Domain.wsldckm.Repositories.TorneoManager, Domain.oplkjsdfkpwe" />
      </typeAliases>
      <containers>
        <container name="WebContainer">
          <types>
            <!-- Tipos para Domain.Core -->
            <type type="IParameterManager" mapTo="ParameterManager" />
            <type type="ILocalizationManager" mapTo="LocalizationManager" />
            <type type="IDataContextWrapper" mapTo="ContextWrapperEF">
              <lifetime type="web_session" />
            </type>
            <!--
              <type type="IDataContextWrapper" mapTo="ContextWrapperSTE">
                <lifetime type="web_session" />
              </type>-->
            <!-- Tipos para oplkjsdfkpwe.Core -->
            <type type="IEnteManager"           mapTo="EnteManager"         />
            <type type="IEquipoManager"         mapTo="EquipoManager"       />
            <type type="IEstadioManager"        mapTo="EstadioManager"      />
            <type type="IEventoManager"         mapTo="EventoManager"       />
            <type type="IPartidoManager"        mapTo="PartidoManager"      />
            <type type="ITagManager"            mapTo="TagManager"          />
            <type type="ITipoFormacionManager"  mapTo="TipoFormacionManager"/>
            <type type="ITorneoEtapaManager"    mapTo="TorneoEtapaManager"  />
            <type type="ITorneoNominaManager"   mapTo="TorneoNominaManager" />
            <type type="ITorneoManager"         mapTo="TorneoManager"       />
          </types>
        </container>
 
        <container name="StandAloneContainer">
          <types>
            <type type="IParameterManager" mapTo="ParameterManager" />
            <type type="ILocalizationManager" mapTo="LocalizationManager" />
            <type type="IDataContextWrapper"  mapTo="ContextWrapperEF" >
              <lifetime type="singleton" />
            </type>
          </types>
        </container>
      </containers>
    </unity>
 
  <appSettings>
    <add key="UnitySection" value="unity"/>
    <add key="UnityContainer" value="WebContainer"/>
  </appSettings>
  <connectionStrings>
    <add name="CoreContext"
    connectionString="metadata=res://Data.Core/DataCoreModel.csdl|res://*/DataCoreModel.ssdl|res://*/DataCoreModel.msl;
                        provider=System.Data.SqlClient;provider connection string=&quot;
                        data source=reveverv.database.windows.net;initial catalog=rrvr;
                        persist security info=True;user id=erverver;password=erverver;
                        multipleactiveresultsets=True;application name=EntityFramework&quot;"
                        providerName="System.Data.EntityClient" />
    <add name="wdsefreContext" connectionString="metadata=res://Data.Core/erverModel.csdl|res://*/ervercvModel.ssdl|res://*/erverv.msl;
                                provider=System.Data.SqlClient;provider connection string=&quot;
                                data source=erfververv.database.windows.net;initial catalog=rverv;
                                persist security info=True;user id=erververv;password=dfvdfv;
                                multipleactiveresultsets=True;application name=EntityFramework&quot;"
                                providerName="System.Data.EntityClient" />
 
    <add name="ApplicationServices"
         connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnetdb.mdf;User Instance=true"
         providerName="System.Data.SqlClient" />
  </connectionStrings>
 
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
 
    <authentication mode="Forms">
      <forms loginUrl="~/Account/Login.aspx" timeout="2880" />
    </authentication>
 
    <membership>
      <providers>
        <clear/>
        <add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="ApplicationServices"
             enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false"
             maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10"
             applicationName="/" />
      </providers>
    </membership>
 
    <profile>
      <providers>
        <clear/>
        <add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ApplicationServices" applicationName="/"/>
      </providers>
    </profile>
 
    <roleManager enabled="false">
      <providers>
        <clear/>
        <add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="ApplicationServices" applicationName="/" />
        <add name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider" applicationName="/" />
      </providers>
    </roleManager>
 
  </system.web>
 
  <system.webServer>
     <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
 
</configuration>

Toda sección posee un atributo configSource en el cual se puede indicar la ruta donde se encuentra definido el XML, asi que podemos extraer toda la sección de Unity en un archivo Unity.config , incluyendo la etiqueta y sus atributos, y el archivo de configuración quedaria de la siguiente forma, bastante más legible y manteniendo toda su funcionalidad.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
  </configSections>
  <unity configSource="Unity.config"  />
 
  <appSettings>
    <add key="UnitySection" value="unity"/>
    <add key="UnityContainer" value="WebContainer"/>
  </appSettings>
  <connectionStrings>
    <add name="CoreContext"
    connectionString="metadata=res://Data.Core/DataCoreModel.csdl|res://*/DataCoreModel.ssdl|res://*/DataCoreModel.msl;
                        provider=System.Data.SqlClient;provider connection string=&quot;
                        data source=reveverv.database.windows.net;initial catalog=rrvr;
                        persist security info=True;user id=erverver;password=erverver;
                        multipleactiveresultsets=True;application name=EntityFramework&quot;"
                        providerName="System.Data.EntityClient" />
    <add name="wdsefreContext" connectionString="metadata=res://Data.Core/erverModel.csdl|res://*/ervercvModel.ssdl|res://*/erverv.msl;
                                provider=System.Data.SqlClient;provider connection string=&quot;
                                data source=erfververv.database.windows.net;initial catalog=rverv;
                                persist security info=True;user id=erververv;password=dfvdfv;
                                multipleactiveresultsets=True;application name=EntityFramework&quot;"
                                providerName="System.Data.EntityClient" />
 
    <add name="ApplicationServices"
         connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnetdb.mdf;User Instance=true"
         providerName="System.Data.SqlClient" />
  </connectionStrings>
 
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
 
    <authentication mode="Forms">
      <forms loginUrl="~/Account/Login.aspx" timeout="2880" />
    </authentication>
 
    <membership>
      <providers>
        <clear/>
        <add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="ApplicationServices"
             enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false"
             maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10"
             applicationName="/" />
      </providers>
    </membership>
 
    <profile>
      <providers>
        <clear/>
        <add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ApplicationServices" applicationName="/"/>
      </providers>
    </profile>
 
    <roleManager enabled="false">
      <providers>
        <clear/>
        <add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="ApplicationServices" applicationName="/" />
        <add name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider" applicationName="/" />
      </providers>
    </roleManager>
 
  </system.web>
 
  <system.webServer>
     <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
 
</configuration>

Y desde luego ese mismo atributo lo podemos usar en todas las secciones que superen un tamaño pequeño.

Enjoy it!

Galardonado como Microsoft MVP Visual C# 2012 – 4to año consecutivo

Artículo original de mi blog

http://juank.black-byte.com/varios-galardonado-como-microsoft-mvp-visual-c-2012-4to-ano-consecutivo/

------------

Hola,
hace un mes fui galardonado MVP por 4to año consecutivo. He tardado en hablar al respecto más que nada porque ando atravesando una etapa de mi vida  bastante compleja en lo que a nivel laboral se refiere, sobrabundancia se podría llamar, y eso me ha obligado a reducir muchos de los espacios que tenía antes disponibles para todas estas actividades.

Tras 4 años es muy difícil no repetirse, eso o tengo muy mala imaginación.

Gracias a todos porque lograr esto no es fácil requiere del apoyo de muchos nerds o geeks como yo ;) .

con algo de suerte el año que viene puede que sea nombrado de nuevo, y  de seguro tendre algo muy interesante para escribir.

Hasta pronto.

 

Se necesitan programas para hacer programas

 

Artículo original de mi blog

http://juank.black-byte.com/sistemas_operativos-necesitan-programas-para-hacer-programas/

------------

Me preguntaron con que programa, se hacen los programas que hacen programas?

Si nos ponemos a pensar, parece ser un ciclo infinito, una paradoja. Se necesitan programas para hacer programas.

Pero este tema repasando un poco de historia es mucho más fácil de entender.

No pretendo en este artículo hacer un informe detallado y preciso de la historia de los lenguajes de programación, simplemente aportare los elementos mínimos para resolver esta paradoja: “ Se necesitan programas para hacer programas ”.

En un principio siempre se programaba en lenguaje de máquina, el lenguaje de maquina son opcodeslenguajes de 1ra generación, es decir solo números en código binario, cada instrucción [opcode] tiene un equivalente mas nemotécnico en ensamblador, es decir por cada instrucción[numero de instrucción] que entiende el procesador existe una palabra que la representa y es mas fácil de recordar, esto es el lenguaje ensamblador.

Así que inicialmente se hicieron programas en opcode que al ‘ensamblarlos’ generaban un archivo binario con códigos de maquina. Ensamblador es entonces un lenguaje de 2da generación.

 

Después vinieron los lenguajes de 3ra generación: cobol y fortran por ejemplo, que con una instrucción podían representar varias instrucciones de Ensamblador, sin embargo los programas siguieron creciendo y hacer software se hizo difícil, así que se genero la necesidad de tener lenguajes que permitieran reusar más código y que fueran más fácil de entender, que estuvieran mejor estructurados.

Así nació el lenguaje C, luego de que Ritchie se diera cuenta de la gran cantidad de instrucciones repetitivas y de la enorme complejidad del software, decidió crear un lenguaje donde cada palabra representara varias instrucciones y estas además pudieran ser agrupadas de manera lógica(funciones) en componentes reutilizables. También pensó en que todas estas virtudes no deberían ser una limitante para manejar instrucciones de maquina a bajo nivel así que incluyo los apuntadores para acceso directo a memoria y le dio al lenguaje la capacidad de incluir fragmentos de ensamblador cuando fuera necesario,así creo los while, los if y los for del lenguaje C, las funciones. etc. C es uno de los lenguajes de 3ra generación, de hecho el lenguaje más popular de esa generación que incluso hoy día con nuevas generaciones y formas de hacer las cosas sigue vigente aunque ha cedido mucho terreno (casi todo) a C++.

 

Desde 3ra generación en adelante hay algunas variantes adicionales pero este es el resumen.

En los lenguajes 4ta generación tenemos lenguajes aún más orientados a objetos, con otras características que permiten que el desarrollador se preocupe más en el ‘que debo hacer‘ que en el ‘como se hace‘, por ello tenemos lenguajes con memoria administrada como Java, C# y Visual Basic entre otros que abstraen gran parte de las complejidades de la máquina en pro de enfocarse en el resultado.

Finalmente los lenguajes de 5ta generación, enfocados en gran parte a la inteligencia artificial pero no únicamente a ello, ya que también se ha abierto espacio para los lenguajes híbridos, como es el caso de C# que hoy día es POO pero también tienesentencias dinámicas funcionales que le dan un comportamiento muy similar a los lenguajes de 5ta generación.

F# es un lenguaje de 5ta generación así como Lisp y Prolog estos últimos con un intenso uso en temas de inteligencia artificial.

Con esto queda resuelta la paradoja de Se necesitan programas para hacer programas. Los primeros programas creados se hicieron directamente en lenguaje de máquina, y según el software se fue haciendo más complejo se generó la necesidad de tener programas que permitieran escribir de forma más natural, inicialmente ensamblador donde cada instrucción del lenguaje equivalía a una instrucción de la máquina, y luego con lenguajes de nivel superior donde una instrucción correspondía a muchas instrucciones de la maquina, esa tarea de traducir de un lenguaje más ‘natural’ al lenguaje de máquina sed hace por medio de programas llamados compiladores, los cuales no solo traducen sino que analizan el conjunto del programa escrito para escribir la misma versión del programa en lenguaje de máquina con tan pocas instrucciones como sea posible.

Como se darán cuenta no todo tiempo pasado fue mejor, cosas tan habituales el día de hoy como procesar el evento clic de un botón pueden tener tras de sí miles de instrucciones ya en el lenguaje de máquina, instrucción es que antes debían escribir los desarrolladores una y otra vez.

Por suerte los ingenieros y desarrolladores hemos sido muy ingeniosos y aunque el resto de la industria se ha dedicado a mejorar a costa de funcionalidades más y más complejas hemos sabido jugar nuestras fichas, hemos mejorado nuestras herramientas con nuestros propios programas y hoy día hacemos en un clic lo que antes nos tomaba semanas, o incluso meses.