<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
   <channel>
      <title>Salamanca</title>
      <description>Pipes Output</description>
      <link>http://pipes.yahoo.com/pipes/pipe.info?_id=tLOI7ucD3hGSdacnQBJ3AQ</link>
      <pubDate>Wed, 04 Nov 2009 20:50:47 -0800</pubDate>
      <generator>http://pipes.yahoo.com/pipes/</generator>
      <geo:lat>48.825751</geo:lat><geo:long>2.38376</geo:long><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
         <title>Alpha 2 : les énumérations [A bord de Salamanca]</title>
         <link>http://feedproxy.google.com/~r/noury/salamanca/~3/Xh8w4F4uagE/index.php</link>
         <description>&lt;p&gt;La &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/index.php?post/2009/07/16/Salamanca-1.0.1-%28alpha-2%29-is-released"&gt;sortie de la version alpha 2 de Salamanca&lt;/a&gt; nous a donné l'occasion de sortir notre équipement pour révision en cale sèche...&lt;/p&gt;
&lt;p&gt;&lt;a rel="nofollow" title="Flickr Commons, USS Ohio Submarine on maintenance, By Mateus" target="_blank" href="http://www.flickr.com/photos/mateus27_24-25/2246125390/"&gt;&lt;img src="http://farm3.static.flickr.com/2180/2246125390_19b4a1449e.jpg" border="0" height="228" width="350"/&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h2&gt;Spécification du cycle de vie d'un projet&lt;/h2&gt;
&lt;p&gt;La principale amélioration apportée par Salamanca alpha 2 étant le support des énumérations dans le modèle entité, nous en avons profité pour revoir et implémenter le cycle de vie d'un projet suivant :&lt;/p&gt;
&lt;p&gt;&lt;img style="border-width:0;" alt="Projet_LifeCycle" src="http://salamanca.nourysolutions.com/bord/public/WindowsLiveWriter/Misejouralpha2_A257/Projet_LifeCycle.png" border="0" height="476" width="200"/&gt;&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Chaque changement de statut est de la responsabilité d'un des interlocuteurs que nous avons déjà spécifié lors de la &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/index.php?post/2009/07/10/Escale-1-%3A-Entiteacute%3Bs-meacute%3Btier"&gt;modélisation de nos entités&lt;/a&gt; :&lt;/p&gt;
&lt;ul&gt; &lt;li&gt;Un client soumet un projet &lt;/li&gt;
&lt;li&gt;Un commercial prend en charge ou annule un projet soumis &lt;/li&gt;
&lt;li&gt;Le client détaille le besoin de son projet pris en charge &lt;/li&gt;
&lt;li&gt;Un consultant prototype un périmètre délimité du besoin &lt;/li&gt;
&lt;li&gt;Le client clôture le projet après livraison du prototype &lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Modélisation avec énumération&lt;/h2&gt;
&lt;p&gt;Pour modéliser le cycle de vie d'un projet, nous avons ajouté l'énumération &lt;code&gt;StatutProjet&lt;/code&gt; dans notre modèle entité et défini chaque statut du cycle en tant que valeur, avec comme type sous-jacent une chaîne de 5 caractères. Nous avons alors ajouté l'attribut &lt;code&gt;Statut&lt;/code&gt; à l'entité &lt;code&gt;Projet&lt;/code&gt; et défini son type comme &lt;code&gt;StatutProjet&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img style="border-width:0;" alt="VS_Model_StatutProjet" src="http://salamanca.nourysolutions.com/bord/public/WindowsLiveWriter/Misejouralpha2_A257/VS_Model_StatutProjet.png" border="0" height="231" width="330"/&gt; &lt;/p&gt;
&lt;p&gt;Pour chaque valeur d'énumération, nous associons à travers le champ Description de ses propriétés la chaîne de caractères "en français" : Soumis, Pris en charge, Détaillée, Prototypé, Clôturé, Annulé.&lt;/p&gt;
&lt;p&gt;On retrouve alors dans le code SQL généré l'insertion de ces valeurs en base :&lt;/p&gt;
&lt;pre class="SQL"&gt;INSERT INTO StatutProjet VALUES('SOUMI', 'Soumis');&lt;br /&gt;INSERT INTO StatutProjet VALUES('ENCHA', 'Pris en charge'); &lt;br /&gt;INSERT INTO StatutProjet VALUES('DETAI', 'Détaillé');&lt;br /&gt;INSERT INTO StatutProjet VALUES('PROTO', 'Prototypé'); &lt;br /&gt;INSERT INTO StatutProjet VALUES('CLOTR', 'Clôturé');&lt;br /&gt;INSERT INTO StatutProjet VALUES('ANNUL', 'Annulé');&lt;/pre&gt;
&lt;h2&gt;Implémentation de l'écran liste des projets&lt;/h2&gt;
&lt;p&gt;Afin d'avoir une vue d'ensemble des projets client, un commercial doit pouvoir visualiser la liste des projets et leur statut dés la page d'accueil de son espace.&lt;/p&gt;
&lt;p&gt;Nous ajoutons donc dans le projet &lt;code&gt;Eproject.Web&lt;/code&gt; :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;un répertoire &lt;code&gt;Espace&lt;/code&gt; qui regroupe les écrans accessibles après ouverture de session &lt;/li&gt;
&lt;li&gt;une page d'accueil &lt;code&gt;Default.aspx&lt;/code&gt; qui affiche une vue d'ensemble selon le rôle utilisateur &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Dans la page d'accueil, nous implémentons la liste des projets à travers :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;un contrôle ASP.NET &lt;code&gt;GridView&lt;/code&gt;affichant les projets sous forme de tableau &lt;/li&gt;
&lt;li&gt;un contrôle ASP.NET &lt;code&gt;SqlDataSource&lt;/code&gt; récupérant les informations directement avec une requête SQL vers la base de données &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pour accéder à la base de données, nous configurons une chaîne de connexion avec l'utilitaire Enterprise Library Configuration de la même façon que pour &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/index.php?post/2009/08/06/Escale-3-%3A-Tests-unitaires"&gt;notre projet de tests unitaires&lt;/a&gt;. Le résultat placé dans le fichier web.config du projet web est le suivant :&lt;/p&gt;
&lt;pre class="XML"&gt;&amp;lt;dataConfiguration defaultDatabase="eProject_ABord" /&amp;gt;&lt;br /&gt;&amp;lt;connectionStrings&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;add name="eProject_ABord" connectionString="Data Source=.&amp;#92;SQLEXPRESS;Initial Catalog=eProject_ABord;Integrated Security=True" providerName="System.Data.SqlClient" /&amp;gt;&lt;br /&gt;&amp;lt;/connectionStrings&amp;gt; &lt;/pre&gt;
&lt;p&gt;Pour alimenter la liste, nous ajoutons des données de test dans la base eProject_ABord avec le script SQL :&lt;/p&gt;
&lt;pre class="SQL"&gt;Declare @client_id uniqueidentifier=newid();&lt;br /&gt;&lt;br /&gt;INSERT INTO Interlocuteurs (Id, Nom, Email) VALUES (@client_id, 'Client test', 'client@test.com'); &lt;br /&gt;INSERT INTO Clients (Id, Societe) VALUES (@client_id, 'Société test');&lt;br /&gt;&lt;br /&gt;INSERT INTO Projets (Client_Id, Nom, Statut_Code) VALUES (@client_id, 'Application DA VINCI', 'SOUMI'); &lt;br /&gt;INSERT INTO Projets (Client_Id, Nom, Statut_Code) VALUES (@client_id, 'Gestion de stocks', 'SOUMI');&lt;br /&gt;INSERT INTO Projets (Client_Id, Nom, Statut_Code) VALUES (@client_id, 'Projet SIGMAT', 'ENCHA'); &lt;br /&gt;INSERT INTO Projets (Client_Id, Nom, Statut_Code) VALUES (@client_id, 'Plateforme YaKa', 'DETAI');&lt;br /&gt;INSERT INTO Projets (Client_Id, Nom, Statut_Code) VALUES (@client_id, 'Fiche PATROL', 'PROTO'); &lt;br /&gt;INSERT INTO Projets (Client_Id, Nom, Statut_Code) VALUES (@client_id, 'MOBILAT', 'CLOTR');&lt;br /&gt;INSERT INTO Projets (Client_Id, Nom, Statut_Code) VALUES (@client_id, 'Projet SPAMMER', 'ANNUL');&lt;/pre&gt;
&lt;p&gt;Dans un fichier de ressource nommé &lt;code&gt;Sql.resx&lt;/code&gt; ajouté au dossier ASP.NET &lt;code&gt;App_GlobalResources&lt;/code&gt;, nous définissons la requête SQL &lt;code&gt;ProjectSelectList&lt;/code&gt; :&lt;/p&gt;
&lt;pre class="SQL"&gt;SELECT p.Id, p.Client_Id, p.Nom, c.Societe, sp.Description&lt;br /&gt;FROM Projets p, Clients c, StatutProjet sp &lt;br /&gt;WHERE&amp;nbsp; p.Client_Id=c.Id AND p.Statut_Code=sp.Code&lt;/pre&gt;
&lt;p&gt;Dans la page web, nous ajoutons le code ASP.NET ci-dessous pour afficher la liste issue de la requête :&lt;/p&gt;
&lt;pre class="XML"&gt;&amp;lt;asp:SqlDataSource ID="ProjetSqlDataSource" runat="server" &lt;br /&gt;ConnectionString="&amp;lt;%$ ConnectionStrings:eProject_ABord %&amp;gt;" ProviderName="&amp;lt;%$ConnectionStrings:eProject_ABord.ProviderName %&amp;gt;" &lt;br /&gt;SelectCommand="&amp;lt;%$ Resources:Sql, ProjetSelectList %&amp;gt;"&amp;gt;&lt;br /&gt;&amp;lt;/asp:SqlDataSource&amp;gt; &lt;br /&gt;&amp;lt;asp:GridView ID="ProjetGridView" runat="server" DataSourceID="ProjetSqlDataSource" DataKeyNames="ID" Width="400px"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Columns&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;asp:BoundField DataField="Id" HeaderText="Id" ReadOnly="True" SortExpression="ID" Visible="False" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;asp:BoundField DataField="Nom" HeaderText="&amp;lt;%$ Resources:SR, ProjetNomLabel %&amp;gt;" /&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;asp:BoundField DataField="Societe" HeaderText="&amp;lt;%$ Resources:SR, ClientSocieteLabel %&amp;gt;" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;asp:BoundField DataField="Description" HeaderText="&amp;lt;%$ Resources:SR, ProjetStatutLabel %&amp;gt;" /&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Columns&amp;gt;&lt;br /&gt;&amp;lt;/asp:GridView&amp;gt; &lt;/pre&gt;
&lt;p&gt;Pour obtenir un "look &amp;amp; feel" homogène dans notre application, nous avons ajouté :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;la page maître &lt;code&gt;Site.Master&lt;/code&gt; liée à une feuille de style CSS placée dans le thème Default du répertoire ASP.NET &lt;code&gt;App_Themes&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;un fichier d'apparence grid.skin également placé dans le thème Default définissant le style par défaut d'un contrôle GridView&lt;/li&gt;
&lt;li&gt;l'option styleSheetTheme="Default" à la directive pages du fichier &lt;code&gt;web.config&lt;/code&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;La page &lt;code&gt;Default.aspx&lt;/code&gt; est transformée en formulaire de contenu web en ajoutant :&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;la directive &lt;code&gt;MasterPageFile="~/Site.master"&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;le code ASP.NET dans un contrôle &lt;code&gt;Content&lt;/code&gt; associé à la région pour le contenu (&lt;code&gt;ContentPlaceHolder&lt;/code&gt;) définie dans la page maître&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt; Nous obtenons ainsi la liste des projets avec leur client et leur statut associés sous la forme suivante :&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;img style="border-width:0;" alt="Ecran Liste des projets client" src="http://salamanca.nourysolutions.com/bord/public/WindowsLiveWriter/Misejouralpha2_A257/ASPNET_ProjetSelectList.png" border="0" height="245" width="415"/&gt; &lt;/p&gt;
&lt;h2&gt;Mise à jour des références Salamanca&lt;/h2&gt;
&lt;p&gt;Le refactoring des bibliothèques réalisé dans la mise à jour alpha 2 de Salamanca nous a permis lors de cette révision de réduire le nombre de références dans notre projet.&lt;/p&gt;
&lt;p&gt;Par exemple, dans le projet &lt;code&gt;Eproject.Model&lt;/code&gt;, nous avions les 4 références suivantes :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Salamanca.Common&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;&lt;code&gt;Salamanca.DataAccess&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;&lt;code&gt;Salamanca.DataAccess.EnterpriseLibrary&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;&lt;code&gt;Salamanca.DataRules&lt;/code&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nous n'avons maintenant plus que 2 références :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Salamanca&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;&lt;code&gt;Salamanca.EnterpriseLibrary.4&lt;/code&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ce passage en "révision" de notre &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/index.php?post/2009/06/22/Pr%C3%A9paration"&gt;équipée&lt;/a&gt; nous a donc permis d'enrichir notre modèle graphique des entités avec la description du cycle de vie d'un projet ainsi que que de l'illustrer simplement à travers l'implémentation d'un écran web accédant directement à la base de données.&lt;/p&gt;
&lt;p&gt;Il est bientôt temps de repartir à l'aventure pour mettre en oeuvre des interactions entre l'application et l'utilisateur à travers des activités métier...&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/noury/salamanca?a=Xh8w4F4uagE:nsHNHKxGkUo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/noury/salamanca?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/noury/salamanca/~4/Xh8w4F4uagE" height="1" width="1"/&gt;</description>
         <guid isPermaLink="false">urn:md5:1f8c06af628b364adca106a54dee5bec</guid>
         <pubDate>Mon, 31 Aug 2009 07:00:00 -0700</pubDate>
      <feedburner:origLink>http://salamanca.nourysolutions.com/bord/index.php?post/2009/08/31/Alpha-2-%3A-les-eacute%3Bnumeacute%3Brations</feedburner:origLink></item>
      <item>
         <title>Contrôle des papiers... [A bord de Salamanca]</title>
         <link>http://feedproxy.google.com/~r/noury/salamanca/~3/9QtoArQSQDM/index.php</link>
         <description>&lt;p&gt;En quittant notre &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/index.php?post/2009/08/06/Escale-3-%3A-Tests-unitaires"&gt;dernière escale&lt;/a&gt;, nos hôtes nous ont demander de présenter des informations validées sur notre &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/index.php?post/2009/06/22/Pr%C3%A9paration"&gt;équipée&lt;/a&gt;. Heureusement, nous avons dans Salamanca une bibliothèque qui permet de vérifier aisément la saisie de données : &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/index.php?post/2008/08/26/Inside-the-libraries-I-%3A-Data-Rules"&gt;Data Rules&lt;/a&gt; !&lt;/p&gt;
&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://www.flickr.com/photos/septuagesima/364638765/" title="London Port Authority, Septuagesima, Flickr"&gt;&lt;img src="http://farm1.static.flickr.com/177/364638765_29e8fa4081_m.jpg" border="0"/&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Pour rendre un système d'information utile et efficace, il ne suffit pas de l'alimenter en données, il faut aussi en assurer la cohérence.&lt;/p&gt;
&lt;p&gt;La première exigence qui en découle est de valider les informations fournies si possible dés leur saisie et avant leur sauvegarde dans la base de données.&lt;/p&gt;
&lt;p&gt;&lt;img title="Salamanca Entity Properties" alt="" src="http://salamanca.nourysolutions.com/bord/public/WindowsLiveWriter/ControleDesPapiers/VS_Entity_Properties.png" align="right"/&gt;&lt;/p&gt;
&lt;p&gt;Dans le &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/index.php?post/2009/07/10/Escale-1-%3A-Entiteacute%3Bs-meacute%3Btier"&gt;modèle entité&lt;/a&gt; dessiné avec Salamanca, on peut associer à chaque attribut des règles de validation prédéfinies en fonction de spécifications métier telles que :&lt;/p&gt;
&lt;ul&gt; &lt;li&gt;valeur par défaut ; par exemple, le statut du projet est "Nouveau" par défaut &lt;/li&gt;
&lt;li&gt;autorisation de la valeur null ; par exemple, un projet doit avoir un nom &lt;/li&gt;
&lt;li&gt;longueur maximum ; par exemple, le nom du projet ne dépasse pas 32 caractères &lt;/li&gt;
&lt;/ul&gt;
Ces propriétés sur les attributs d'une entité constituent le premier niveau de règles métier. Elles sont implémentées non seulement dans la base de données sous forme de contraintes, mais aussi dans la couche objet sous forme d'attributs (au sens .NET) liés aux propriétés de l'objet. Par exemple : &lt;pre&gt;[NotNullRule]&lt;br /&gt;[StringLengthRule(32)]&lt;br /&gt;public string Nom&lt;br /&gt;{&lt;br /&gt;...&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;Profitons d'avoir &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/index.php?post/2009/08/06/Escale-3-%3A-Tests-unitaires"&gt;configuré notre projet de tests&lt;/a&gt; pour valider que ces règles métier sont vérifiées lors de la sauvegarde d'un projet.&lt;/p&gt;
&lt;p&gt;Pour faciliter l'exécution de notre série de tests, nous initialisons chacun avec des données valides pour une instance de Projet défini pour la classe de test :&lt;/p&gt;
&lt;pre&gt;[TestInitialize()]&lt;br /&gt;public void MyTestInitialize()&lt;br /&gt;{&lt;br /&gt; Client c = new Client(DataMappers); &lt;br /&gt; c.Nom = "Jean Dupond";&lt;br /&gt; Projet = new Projet(c, DataMappers);&lt;br /&gt; Projet.Nom = "Mon projet";&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;Pour tester que le nom saisi dépasse la longueur maximale, nous ajoutons un test avec "un nom de projet vraiment trop long" et nous vérifions que&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;la méthode &lt;code&gt;Validate(string propertyName)&lt;/code&gt; d'un objet &lt;code&gt;DomainEntity&lt;/code&gt; renvoit FAUX &lt;/li&gt;
&lt;li&gt;qu'une &lt;code&gt;BrokenRulesException&lt;/code&gt; est levée lorsqu'on sauvegarde une instance non valide &lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;[TestMethod]&lt;br /&gt;[ExpectedException(typeof(BrokenRulesException))]&lt;br /&gt;public void CannotValidateNomNull()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.IsTrue(Projet.Validate());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Projet.Nom = null;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.IsFalse(Projet.Validate("Nom"));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Projet.Save();&lt;br /&gt;} &lt;/pre&gt;
&lt;p&gt;Le code complet de notre classe se résume à la validation d'une série de 3 tests :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;On doit pouvoir sauvegardé une instance de Projet avec un nom valide &lt;/li&gt;
&lt;li&gt;On ne doit pas pouvoir sauvegardé une instance de Projet avec un nom vide (NULL) &lt;/li&gt;
&lt;li&gt;On ne doit pas pouvoir sauvegardé une instance de Projet avec un nom trop long (&amp;gt; 32 caractères) &lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;using Microsoft.VisualStudio.TestTools.UnitTesting;&lt;br /&gt;using Salamanca.DataRules;&lt;br /&gt;using NourY.Eproject.Model;&lt;br /&gt;&lt;br /&gt;namespace NourY.Eproject.Tests.Model&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [TestClass]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class ProjetTest : UnitTestBase, IProjetContainer&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [TestMethod]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [DeploymentItem("..&amp;#92;&amp;#92;eProject_ABord_Tests.mdf")]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void CanSaveAndValidateProjet()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.IsTrue(Projet.Validate());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Projet.Save();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [TestMethod]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [ExpectedException(typeof(BrokenRulesException))]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void CannotValidateNomNull()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.IsTrue(Projet.Validate());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Projet.Nom = null;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.IsFalse(Projet.Validate("Nom"));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Projet.Save();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [TestMethod]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [ExpectedException(typeof(BrokenRulesException))]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void CannotValidateNomTooLong()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.IsTrue(Projet.Validate());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Projet.Nom = "Un nom de projet vraiment trop long";&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Assert.IsFalse(Projet.Validate("Nom"));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Projet.Save();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [TestInitialize()]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void MyTestInitialize()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Client c = new Client(DataMappers);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; c.Nom = "Jean Dupond";&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Projet = new Projet(c, DataMappers);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Projet.Nom = "Mon projet";&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Projet Projet&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { return _Projet; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; set { _Projet = value; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Projet _Projet;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;Les règles de validation sur les attributs des entités s'avère donc non seulement aisées à mettre en place mais également implémentées de manière concise dans la couche objet. Pour valider des champs avec des règles avancées tels qu'une adresse email, un numéro de téléphone ou un code postal, nous pouvons exploité la puissance des &lt;a rel="nofollow" hreflang="en" target="_blank" href="http://en.wikipedia.org/wiki/Regular_expression"&gt;expressions régulières&lt;/a&gt; à travers des règles de type &lt;code&gt;RegexRule&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Cette exploration "forcée" de la bibliothèque DataRule entre deux escales nous ouvre déjà un horizon bien dégagé du côté de la consolidation des données de nos applications métier. A suivre avec leur utilisation dans le cadre d'activités métier...&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/noury/salamanca?a=9QtoArQSQDM:zkvMOtiSy-A:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/noury/salamanca?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/noury/salamanca/~4/9QtoArQSQDM" height="1" width="1"/&gt;</description>
         <guid isPermaLink="false">urn:md5:d9258bfab5b8056fc9a9a466a6665444</guid>
         <pubDate>Wed, 19 Aug 2009 07:01:00 -0700</pubDate>
      <feedburner:origLink>http://salamanca.nourysolutions.com/bord/index.php?post/2009/08/19/Controcirc%3Ble-des-papiers...</feedburner:origLink></item>
      <item>
         <title>Escale #3 : Tests unitaires [A bord de Salamanca]</title>
         <link>http://feedproxy.google.com/~r/noury/salamanca/~3/jX4Bfa9NKfw/index.php</link>
         <description>&lt;p&gt;Nous avons maintenant une &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/index.php?post/2009/07/31/Escale-2-%3A-Base-de-donneacute%3Bes"&gt;base de données à notre disposition&lt;/a&gt;. Mais ne perdons pas de vue le but de notre &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/index.php?post/2009/06/22/Pr%C3%A9paration"&gt;expédition&lt;/a&gt;, ou plutôt l'enchainement de buts : apprendre à utiliser Salamanca afin, &lt;em&gt;in fine&lt;/em&gt;, de mettre en place un processus métier qui produit de la valeur.&lt;/p&gt;
&lt;p&gt;&lt;img style="margin:0 15px 0 0;" src="http://farm1.static.flickr.com/38/76983561_36a94daf8d_m.jpg" align="left"/&gt; &lt;/p&gt;
&lt;p&gt;Mais comme dans la fable du lièvre et de la tortue, nous prenons le temps de mettre en place des bonnes pratiques de développement en cours de route afin d'assurer à la fois la qualité de notre produit et la facilité de sa maintenance. &lt;/p&gt;
&lt;p&gt;L'escale d'aujourd'hui s'attarde sur la mise en place des outils de contrôle de la qualité : les Tests.&lt;/p&gt;
&lt;h2&gt;Contexte&lt;/h2&gt;
&lt;p&gt;Même si nous parlons de tests unitaires, notre intention est plutôt de s'assurer que le code produit est conforme au résultat attendu, par exemple que les règles métier définies sont bien respectées. Dans la terminologie du &lt;a rel="nofollow" target="_blank" href="http://fr.wikipedia.org/wiki/Test_%28informatique%29#Classification_des_tests"&gt;test informatique&lt;/a&gt;, on parle alors de tests fonctionnels (de recette ou encore d'acceptation) par opposition aux tests techniques (unitaires, d'intégration, système, performance, ...).&lt;/p&gt;
&lt;p&gt;Mais dans notre cas, nous nous appuyons sur le &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/fr-fr/library/ms243147.aspx"&gt;framework de test de Visual Studio&lt;/a&gt;. C'est pourquoi nous avons créé le projet &lt;em&gt;Eproject.Tests&lt;/em&gt; lors de la mise en place de la solution (cf &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/index.php?post/2009/06/29/Larguez-les-amarres-%21"&gt;L'application Salamanca&lt;/a&gt;).&lt;/p&gt;
&lt;h2&gt;Configuration&lt;/h2&gt;
&lt;p&gt;Comme l'objet de notre application est de manipuler des données, nous avons besoin d'une base de données dédiée pour les tests qui puisse être recréée à chaque exécution d'un jeu de tests. Pour cela, nous procédons de la même manière que pour la &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/index.php?post/2009/07/31/Escale-2-%3A-Base-de-donneacute%3Bes"&gt;base de données de développement&lt;/a&gt;, avec une étape supplémentaire :&lt;/p&gt;
&lt;ul&gt; &lt;li&gt;création d'une base de données SQL Server 2008 Express &lt;/li&gt;
&lt;li&gt;copie du fichier de base de données dans le projet de tests &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cette procédure peut se traduire sous forme de la commande batch &lt;em&gt;CreateTests.cmd&lt;/em&gt;, placée dans le répertoire &lt;em&gt;Create Scripts&lt;/em&gt; du projet &lt;em&gt;Eproject.Sql&lt;/em&gt; :&lt;/p&gt;
&lt;pre&gt;SET CONNECT_STRING=.&amp;#92;SQLEXPRESS &lt;br /&gt;SET BASE_NAME=eProject_ABord_Tests &lt;br /&gt;SET TestsDir=%CD%&amp;#92;..&amp;#92;..&amp;#92;Eproject.Tests&lt;br /&gt;&lt;br /&gt;sqlcmd.exe -E -X -S %CONNECT_STRING% -v DatabaseName=%BASE_NAME% -i Create.sql&lt;br /&gt;&lt;br /&gt;xcopy "C:&amp;#92;Program Files&amp;#92;Microsoft SQL Server&amp;#92;MSSQL10.SQLEXPRESS&amp;#92;MSSQL&amp;#92;DATA&amp;#92;%BASE_NAME%.mdf" %TestsDir% /y &lt;br /&gt;xcopy "C:&amp;#92;Program Files&amp;#92;Microsoft SQL Server&amp;#92;MSSQL10.SQLEXPRESS&amp;#92;MSSQL&amp;#92;DATA&amp;#92;%BASE_NAME%_log.ldf" %TestsDir% /y&lt;/pre&gt;
&lt;p&gt;Une fois le fichier de base de données copié, nous l'ajoutons dans notre projet ("Afficher tous les fichiers", clic droit sur le fichier, puis "Inclure dans le projet"). &lt;/p&gt;
&lt;p&gt;La configuration de sa chaîne de connexion est facilité par l'utilisation du &lt;em&gt;Data Application Block&lt;/em&gt; du framework &lt;em&gt;Microsoft Enterprise Library&lt;/em&gt; (cf &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/index.php?post/2009/06/29/Larguez-les-amarres-%21"&gt;Pré-requis&lt;/a&gt;). Pour cela, nous utilisons :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;un fichier de configuration &lt;em&gt;app.config&lt;/em&gt; ajouté dans notre projet &lt;/li&gt;
&lt;li&gt;l'utilitaire &lt;em&gt;Enterprise Library Configuration &lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/public/WindowsLiveWriter/Escale3Testsunitaires_9289/VS_Tests_ConnectionString.png"&gt;&lt;img style="border-width:0;" alt="Enterprise Library Configuration" src="http://salamanca.nourysolutions.com/bord/public/WindowsLiveWriter/Escale3Testsunitaires_9289/VS_Tests_ConnectionString_thumbnail.png" border="0" width="500" height="238"/&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;On obtient ainsi le code de configuration suivant :&lt;/p&gt;
&lt;pre class="xml"&gt;&amp;lt;configuration&amp;gt; &lt;br /&gt;&amp;nbsp; &amp;lt;configSections&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /&amp;gt; &lt;br /&gt;&amp;nbsp; &amp;lt;/configSections&amp;gt; &lt;br /&gt;&amp;nbsp; &amp;lt;dataConfiguration defaultDatabase="eProject_ABord_Tests" /&amp;gt; &lt;br /&gt;&amp;nbsp; &amp;lt;connectionStrings&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name="eProject_ABord_Tests" connectionString="data source=.&amp;#92;SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|eProject_ABord_Tests.mdf;User Instance=true" &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; providerName="System.Data.SqlClient" /&amp;gt; &lt;br /&gt;&amp;nbsp; &amp;lt;/connectionStrings&amp;gt; &lt;br /&gt;&amp;lt;/configuration&amp;gt;&lt;/pre&gt;
&lt;h2&gt;Codage&lt;/h2&gt;
&lt;p&gt;Pour pouvoir coder des tests qui manipulent des instances des entités métier que nous avons modélisé, nous aurons besoin d'une collection de &lt;code&gt;&lt;a rel="nofollow" target="_blank" href="http://martinfowler.com/eaaCatalog/dataMapper.html"&gt;DataMapper&lt;/a&gt;&lt;/code&gt;, dont le rôle (tel que je l'ai assimilé) est de servir de point d'ancrage de la couche de persistence, à savoir la gestion du cache et des échanges entre les instances d'objets en mémoire et leur structure de stockage en base de données (cf &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/index.php?post/2008/09/23/QuickStart-%3A-the-Domain-Model"&gt;QuickStart : the Domain Model&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;L'implémentation choisie est d'avoir une classe de base dont tous les tests hériterons. C'est une classe publique contenant une propriété de type &lt;code&gt;DataMapperCollection&lt;/code&gt; avec un getter sous forme de singleton tirant parti des facilités offertes par les bibliothèques &lt;em&gt;Enterprise Library&lt;/em&gt; et &lt;em&gt;DataAccess&lt;/em&gt; pour créer une connexion avec la base de données (configurée par défaut dans app.config) ainsi qu'un mode de cache des données (dans notre cas, elles ne seront pas conservées en mémoire).&lt;/p&gt;
&lt;pre&gt;using System;&lt;br /&gt;using Microsoft.VisualStudio.TestTools.UnitTesting;&lt;br /&gt;using Microsoft.Practices.EnterpriseLibrary.Data;&lt;br /&gt;using Salamanca.DataAccess;&lt;br /&gt;using Salamanca.DataAccess.Collections;&lt;br /&gt;using NourY.Eproject.Model.Mappers.EnterpriseLibrary;&lt;br /&gt;&lt;br /&gt;namespace NourY.Eproject.Tests&lt;br /&gt;{&lt;br /&gt; public class UnitTestBase&lt;br /&gt; {&lt;br /&gt; public UnitTestBase()&lt;br /&gt; {&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; protected DataMapperCollection DataMappers&lt;br /&gt; {&lt;br /&gt; get&lt;br /&gt; {&lt;br /&gt; if (_DataMappers == null)&lt;br /&gt; _DataMappers = Mappers.CreateDataMapperCollection(&lt;br /&gt; DatabaseFactory.CreateDatabase(), &lt;br /&gt; new NoCacheManager());&lt;br /&gt; return _DataMappers;&lt;br /&gt; }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; private DataMapperCollection _DataMappers;&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;&lt;img style="border-width:0;" alt="References" src="http://salamanca.nourysolutions.com/bord/public/WindowsLiveWriter/Escale3Testsunitaires_9289/VS_Tests_References.png" align="right" border="0" width="286" height="222"/&gt; &lt;/p&gt;
&lt;p&gt;Pour pouvoir compiler notre projet, nous avons ajouté les références aux bibliothèques contenant les types utilisés dans notre classe de base :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;DatabaseFactory&lt;/code&gt; dans &lt;code&gt;EnterpriseLibrary.Data&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;&lt;code&gt;NoCacheManager&lt;/code&gt; et &lt;code&gt;DataMapperCollection&lt;/code&gt; dans &lt;code&gt;DataAccess&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;&lt;code&gt;Mappers&lt;/code&gt; dans &lt;code&gt;Eproject.Model&lt;/code&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Voici venu le temps de tester notre configuration à travers un exemple simple : je veux pouvoir sauvegarder le projet nommé "Projet Test" du client nommé "Client Test".&lt;/p&gt;
&lt;p&gt;Nous ajoutons le test unitaire &lt;code&gt;CrudProjetTest&lt;/code&gt; qui hérite de la classe &lt;code&gt;UnitTestBase&lt;/code&gt;. Afin d'avoir une base de données "propre" à chaque exécution, nous l'associons à notre classe de test à travers l'attribut &lt;code&gt;DeploymentItem&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt; [TestClass]&lt;br /&gt; [DeploymentItem("..&amp;#92;&amp;#92;eProject_ABord_Tests.mdf")]&lt;br /&gt; public class CrudProjetTest : UnitTestBase&lt;br /&gt; {&lt;br /&gt; [TestMethod]&lt;br /&gt; public void CanSaveProjet()&lt;br /&gt; {&lt;br /&gt; Client c = new Client(DataMappers);&lt;br /&gt; c.Nom = "Projet Test";&lt;br /&gt; Projet p = new Projet(c, DataMappers);&lt;br /&gt; p.Nom = "Client Test";&lt;br /&gt;&lt;br /&gt; Assert.IsTrue(p.IsModified);&lt;br /&gt; p.Save();&lt;br /&gt; Assert.IsFalse(p.IsModified);&lt;br /&gt; }&lt;br /&gt; }&lt;/pre&gt;
&lt;p&gt;Nous vous invitons à tester cette configuration dont le réel intérêt est à terme de pouvoir valider que l'implémentation des activités métier de notre application s'exécute avec succès et respectent les règles métier définis. Mais avant cela, nous verrons évidemment comment concevoir et coder les activités métier, concept essentiel de Salamanca...&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/noury/salamanca?a=jX4Bfa9NKfw:DYs45LpDZjk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/noury/salamanca?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/noury/salamanca/~4/jX4Bfa9NKfw" height="1" width="1"/&gt;</description>
         <guid isPermaLink="false">urn:md5:16d84ccf58284205719ce80ea185fc4d</guid>
         <pubDate>Mon, 10 Aug 2009 00:47:00 -0700</pubDate>
      <feedburner:origLink>http://salamanca.nourysolutions.com/bord/index.php?post/2009/08/06/Escale-3-%3A-Tests-unitaires</feedburner:origLink></item>
      <item>
         <title>Escale #2 : Base de données [A bord de Salamanca]</title>
         <link>http://feedproxy.google.com/~r/noury/salamanca/~3/udxWQhWrsvQ/index.php</link>
         <description>&lt;p&gt;Pourquoi avoir &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/index.php?post/2009/07/10/Escale-1-%3A-Entiteacute%3Bs-meacute%3Btier"&gt;spécifié, modélisé et généré des entités métier&lt;/a&gt; ?&lt;/p&gt;
&lt;p&gt;Si nous sommes &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/index.php?post/2009/06/15/Embarquement-prochain"&gt;à bord de Salamanca&lt;/a&gt;, c'est car nous voulons informatiser (et améliorer) l'un de nos &lt;a rel="nofollow" target="_blank" href="http://www.commentcamarche.net/contents/qualite/processus.php3"&gt;processus&lt;/a&gt; de travail. L'objectif est de permettre aux acteurs de ce processus de consulter, saisir, évaluer, récupérer ou exploiter les ressources et informations alimentant ce processus dans le cadre d'un enchaînement d'activités. &lt;/p&gt;
&lt;p&gt;C'est d'ailleurs la base de la &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/index.php?post/2008/08/04/6-getting-on-the-tracks"&gt;définition d'une application métier&lt;/a&gt; :&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;"manipuler des données spécifiques à une organisation ou un secteur d'activité".&lt;/p&gt;
&lt;/blockquote&gt; &lt;p&gt;Nous sommes donc en accord avec la ligne de produits ciblée par l'usine Salamanca (ça tombe bien !). Pour cela, un moyen de stocker l'ensemble de ces informations nous est nécessaire. &lt;/p&gt;
&lt;p&gt;Comme Salamanca comprend une &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/index.php?post/2008/08/20/Visiting-Salamanca"&gt;bibliothèque ORM&lt;/a&gt; (mais pas seulement !), l'implémentation du mapping entre notre modèle d'entités métier et le modèle physique des données est pour nous, humble développeur "métier", transparent (même s'il est toujours conseillé d'avoir une compréhension haut niveau des concepts associés).&lt;/p&gt;
&lt;p&gt;Nous nous attarderons donc lors de cette escale uniquement sur l'organisation que nous avons mis en place pour créer (et re-créer) rapidement notre base de données.&lt;/p&gt;
&lt;h2&gt;Organisation&lt;/h2&gt;
&lt;p&gt;Puisque nous disposons du code SQL généré pour la création des tables et des procédures stockées CRUD, autant en profiter. Néanmoins, leur emplacement dans le projet Model et leur liaison au fichier modèle (.tt) assurant leur génération ne permettent pas de les dinstinguer facilement dans notre solution Visual Studio. C'est pourquoi nous avons ajouté le projet &lt;em&gt;Eproject.Sql&lt;/em&gt; de type &lt;em&gt;Projet de base de données&lt;/em&gt; lors de la création de notre solution (tout s'explique !).&lt;/p&gt;
&lt;p&gt;Ainsi, chaque développeur dispose de sa propre base de données de développement à partir d'un schéma placé dans le gestionnaire de versions (conformément aux &lt;a rel="nofollow" target="_blank" href="http://odetocode.com/Blogs/scott/archive/2008/01/30/11702.aspx"&gt;bonnes pratiques&lt;/a&gt;) et "bien rangé" dans l'environnement de travail :&lt;/p&gt;
&lt;ul&gt; &lt;li&gt;&lt;img style="border-width:0;" alt="VS_SolutionExplorer_Sql" src="http://salamanca.nourysolutions.com/bord/public/WindowsLiveWriter/Escale2Basededonnes_F3DB/VS_SolutionExplorer_Sql.png" align="right" border="0" height="64" width="174"/&gt;les scripts de création : dans &lt;em&gt;Create Scripts&lt;/em&gt; &lt;/li&gt;
&lt;li&gt;les scripts de mise à jour : dans &lt;em&gt;Change Scripts&lt;/em&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pour cela, nous ajoutons dans les propriétés du projet &lt;em&gt;Eproject.Model&lt;/em&gt; un évènement après génération (Post-build) afin de copier les fichiers SQL générés dans leur répertoire cible.&lt;/p&gt;
&lt;p&gt;&lt;img title="Ligne de commande apr&amp;#xe8;s g&amp;#xe9;n&amp;#xe9;ration" alt="" src="http://salamanca.nourysolutions.com/bord/public/WindowsLiveWriter/Escale2Basededonnes_F3DB/VS_PostBuildModel_CopySQLFiles.png" border="0" height="86" width="369"/&gt;&lt;/p&gt;
&lt;p&gt;De cette façon, les scripts servant à la création de la base restent synchronisés après chaque mise à jour du modèle, puis compilation du code généré.&lt;/p&gt;
&lt;p&gt;Remarque : la première fois, pensez à ajouter manuellement les fichiers copiés (clic droit sur le répertoire, puis "Ajouter un élément existant...").&lt;/p&gt;
&lt;h2&gt;Automatisation&lt;/h2&gt;
&lt;p&gt;Pour automatiser la création de notre base de données, nous avons besoin :&lt;/p&gt;
&lt;ul&gt; &lt;li&gt;d'un script TRANSACT-SQL pour effacer (si nécessaire) et créer la base &lt;/li&gt;
&lt;li&gt;d'exécuter &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/fr-fr/library/ms162773%28SQL.90%29.aspx"&gt;l'utilitaire sqlcmd&lt;/a&gt; en ligne de commande ou dans un batch (.cmd) &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nous pourrions pousser l'automatisation de la même façon que pour la copie des fichiers SQL en ajoutant un évènement après génération du projet &lt;em&gt;Eproject.Model&lt;/em&gt;. Mais cela efface les données saisies en cours de développement à chaque génération, donc nous préférons nous placer dans le répertoire &lt;em&gt;Create Scripts&lt;/em&gt; et exécuter la commande ci-dessous (dans un batch) uniquement lors d'un changement dans notre schéma :&lt;/p&gt;
&lt;pre&gt;C:&amp;#92;eProject&amp;#92;src&amp;#92;ABordDeSalamanca&amp;#92;Eproject.Sql&amp;#92;Create Scripts&amp;gt;sqlcmd.exe -E -X -S .&amp;#92;SQLEXPRESS -v DatabaseName=eProject_ABord -i Create.sql&lt;/pre&gt;
&lt;p&gt;Comme nous utilisons une base de données SQL Server 2008 Express, notre exemple de script TRANSACT-SQL contient le code suivant :&lt;/p&gt;
&lt;pre class="SQL"&gt;USE master&lt;br /&gt;GO&lt;br /&gt;&lt;br /&gt;IF EXISTS (SELECT * FROM sys.databases WHERE name=N'$(DatabaseName)')&lt;br /&gt;BEGIN&lt;br /&gt; ALTER DATABASE $(DatabaseName)&lt;br /&gt; SET SINGLE_USER&lt;br /&gt; WITH ROLLBACK IMMEDIATE&lt;br /&gt; DROP DATABASE $(DatabaseName)&lt;br /&gt;END&lt;br /&gt;GO&lt;br /&gt;&lt;br /&gt;CREATE DATABASE $(DatabaseName)&lt;br /&gt;GO&lt;br /&gt;&lt;br /&gt;USE $(DatabaseName)&lt;br /&gt;GO&lt;br /&gt;&lt;br /&gt;:reset &lt;br /&gt;:r Tables.sql &lt;br /&gt;:r StoredProcedures.sql &lt;br /&gt;GO&lt;/pre&gt;
&lt;p&gt;Voilà une façon rapide de disposer à tout moment d'une base de données synchronisée avec notre modèle d'entités métier. Et nous verrons lors de notre prochaine escale comment la mise en place de notre projet de tests unitaires en bénéficie...&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/noury/salamanca?a=udxWQhWrsvQ:Vx9r9YVfCwI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/noury/salamanca?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/noury/salamanca/~4/udxWQhWrsvQ" height="1" width="1"/&gt;</description>
         <guid isPermaLink="false">urn:md5:bc86b652aa0b0685d9f28db505a9963c</guid>
         <pubDate>Fri, 31 Jul 2009 01:42:00 -0700</pubDate>
      <feedburner:origLink>http://salamanca.nourysolutions.com/bord/index.php?post/2009/07/31/Escale-2-%3A-Base-de-donneacute%3Bes</feedburner:origLink></item>
      <item>
         <title>Escale #1 : Entités métier [A bord de Salamanca]</title>
         <link>http://feedproxy.google.com/~r/noury/salamanca/~3/UIw-6PMlcWU/index.php</link>
         <description>&lt;p&gt;&lt;img style="margin-left:15px;" alt="Entit&amp;#xe9;s" src="http://www.decoloopio.com/image_base/Img_179.png" align="right" border="0" width="102" height="139"/&gt;&lt;/p&gt;
&lt;p&gt;Nous voilà arrivés au pays des "entités". Mais qui sont-elles ?&lt;/p&gt;
&lt;p&gt;Pour mieux intégrer cette notion d'entité, nous nous référons à sa définition dans le cadre du &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Entity-Relationship_Model#cite_note-0"&gt;modéle entité-relation développé par Dr Peter Chen&lt;/a&gt; : &lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;"une chose qui peut être identifiée distinctement ayant une signification pour une organisation".&lt;/p&gt;
&lt;/blockquote&gt; &lt;h2&gt;Spécification&lt;/h2&gt;
&lt;p&gt;Dans le cadre du service que nous développons, &lt;a rel="nofollow" target="_blank" href="https://eproject.nourysolutions.com"&gt;eProject&lt;/a&gt;, nous voulons mettre en relation les entités suivantes :&lt;/p&gt;
&lt;ul&gt; &lt;li&gt;un projet métier : vue d'ensemble, besoin détaillé et périmètre d'un prototype &lt;/li&gt;
&lt;li&gt;3 interlocuteurs : client, commercial et consultant &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Lors de la définition de notre besoin, nous avons également précisé les règles d'association à travers les spécifications suivantes :&lt;/p&gt;
&lt;ul&gt; &lt;li&gt;Pour consulter NourY Solutions sur mes besoins métier, je veux pouvoir soumettre mon projet ainsi que mes projets ultérieurs en tant qu'interlocuteur client &lt;/li&gt;
&lt;li&gt;Pour piloter la relation clientèle, je prend en charge le suivi de l'avancement des projets de chacun de mes clients en tant qu'interlocuteur commercial &lt;/li&gt;
&lt;li&gt;Pour produire un prototype à partir de l'analyse d'un besoin, je veux pouvoir estimer la charge de travail sur la base de chaque projet en tant qu'interlocuteur consultant &lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Modélisation&lt;/h2&gt;
&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/public/WindowsLiveWriter/Escale1Entitsmtier_1031D/VS_Model_eProject.png"&gt;&lt;img style="border-width:0;" alt="Mod&amp;#xe8;le eProject" src="http://salamanca.nourysolutions.com/bord/public/WindowsLiveWriter/Escale1Entitsmtier_1031D/VS_Model_eProject-small.png" border="0" width="420" height="210"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Une fois les concepts digérés et notre besoin spécifié, Salamanca nous permet de rapidement modéliser le socle de notre métier représenté dans le diagramme ci-dessus.&lt;/p&gt;
&lt;p&gt;Pour cela, nous ouvrons le &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/index.php?post/2008/08/20/Visiting-Salamanca"&gt;modèle SDML&lt;/a&gt; du projet &lt;em&gt;Eproject.Model&lt;/em&gt; de la solution Visual Studio créée lors de &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/index.php?post/2009/06/29/Larguez-les-amarres-%21"&gt;notre départ&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img style="margin-left:15px;" alt="VS_Model_Toolbox" src="http://salamanca.nourysolutions.com/bord/public/WindowsLiveWriter/Escale1Entitsmtier_1031D/VS_Model_Toolbox.png" align="right" border="0" width="165" height="175"/&gt;&lt;/p&gt;
&lt;p&gt;La palette d'éléments mise à disposition dans la boite à outils est d'une aide précieuse pour implémenter notre modèle de 5 entités simplement par glisser-déposer et définition des propriétés des associations : &lt;/p&gt;
&lt;ul&gt; &lt;li&gt;1 &lt;a rel="nofollow" target="_blank" href="http://fr.wikipedia.org/wiki/Composition_%28programmation%29"&gt;composition&lt;/a&gt; entre Client et Projet &lt;/li&gt;
&lt;li&gt;2 associations bidirectionnelles entre Commercial et Client, entre Consultant et Projet&amp;nbsp; &lt;/li&gt;
&lt;li&gt;3 &lt;a rel="nofollow" target="_blank" href="http://fr.wikipedia.org/wiki/H%C3%A9ritage_%28informatique%29"&gt;héritages&lt;/a&gt; : Client, Commercial et Consultant sont tous des Interlocuteurs du Projet &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nous pouvons maintenant définir les attributs soit par glisser-déposer de l'élément "Attribute"&amp;nbsp;à partir de la boîte à outils, soit par clic droit sur l'entité, puis&amp;nbsp;"Ajouter un nouveau Entity Attribute" à partir du menu contextuel.&lt;/p&gt;
&lt;p&gt;Le nom et le type (string par défaut) de l'attribut&amp;nbsp;peuvent être définis directement de manière graphique alors que la fenêtre de "Propriétés" permet également de spécifier des règles validées automatiquement grâce à l'utilisation de l'une des 4 bibliothèques de Salamanca : &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/index.php?post/2008/08/26/Inside-the-libraries-I-%3A-Data-Rules"&gt;Data Rules&lt;/a&gt;.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;La facilité d'intégration de règles métier est l'une des grandes forces de Salamanca, aussi nous lui dédierons bientôt une escapade de découverte avant la prochaine escale !&lt;/p&gt;
&lt;h2&gt;Génération&lt;/h2&gt;
&lt;p&gt;Une fois les attributs et les règles associées définis pour chaque entité, il nous reste qu'à générer le code correspondant par un simple clic sur l'icône "Transformer tous les modèles" présente dans la barre d'outils de la fenêtre "Explorateur de solutions".&lt;/p&gt;
&lt;p&gt;&lt;img style="border-width:0;margin-left:15px;" alt="Code g&amp;#xe9;n&amp;#xe9;r&amp;#xe9;" src="http://salamanca.nourysolutions.com/bord/public/WindowsLiveWriter/Escale1Entitsmtier_1031D/VS_Model_GeneratedCode.png" align="right" border="0" width="253" height="290"/&gt;&lt;/p&gt;
&lt;p&gt;A la fin de la génération, nous obtenons l'ensemble du code de la couche d'accès aux données basé sur la bibliothèque générique de Salamanca dédié à cet usage : &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/index.php?post/2008/09/01/Inside-the-libraries-II-%3A-Data-Access"&gt;Data Access&lt;/a&gt;. Cette couche est constituée :&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;du code SQL de création des tables associées aux entités&lt;/li&gt;
&lt;li&gt;des procédures stockées pour les opérations CRUD sur chaque entité&lt;/li&gt;
&lt;li&gt;des interfaces et classes de mapping entre entités et tables (Data Mappers)&lt;/li&gt;
&lt;li&gt;des ressources liant procédures stockées et méthodes CRUD implémentées dans les Data Mappers&lt;/li&gt;
&lt;li&gt;des interfaces et classes des entités du domaine métier&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;L'avantage évident de cette formule "Modélisation + Génération" est de ne plus avoir à taper du code redondant. Pour preuve, je vous invite à satisfaire votre curiosité et éditer les fichiers générés : on retrouve le même air dans chaque classe avec quelques variations autour du thème...&lt;/p&gt;
&lt;p&gt;Mais le réel instant de bonheur du point de vue du développeur se savoure lors de l'implémentation de demandes d'évolutions telles que l'ajout d'attributs, ou mieux, lors de la modification de relations. Personnellement, j'ai par le passé consommé beaucoup de temps dans la maintenance du code SQL et objet suite aux évolutions inhérentes à tout projet métier.&lt;/p&gt;
&lt;p&gt;Je vous invite donc dés maintenant à faire l'expérience avec le modèle métier de votre projet en cours avant notre prochaine escale : l'automatisation de la mise en place de la base de données.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/noury/salamanca?a=UIw-6PMlcWU:aapMptKxS_A:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/noury/salamanca?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/noury/salamanca/~4/UIw-6PMlcWU" height="1" width="1"/&gt;</description>
         <guid isPermaLink="false">urn:md5:6e525cd5f0bac16116c165d255fe65a2</guid>
         <pubDate>Mon, 27 Jul 2009 08:37:00 -0700</pubDate>
      <feedburner:origLink>http://salamanca.nourysolutions.com/bord/index.php?post/2009/07/10/Escale-1-%3A-Entiteacute%3Bs-meacute%3Btier</feedburner:origLink></item>
      <item>
         <title>Salamanca 1.0.1 (alpha 2) is released [The road to Salamanca]</title>
         <link>http://feedproxy.google.com/~r/noury/salamanca/~3/Ov2D3DbHjEY/index.php</link>
         <description>&lt;p&gt;The second version of Salamanca has just been released : &lt;a rel="nofollow" target="_blank" href="http://salamanca.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=30242"&gt;1.0.1 (alpha 2)&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;&lt;img style="border-right-width:0px;margin:0px auto;display:block;float:none;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="image" border="0" alt="image" src="http://salamanca.nourysolutions.com/road/public/WindowsLiveWriter/Salamanca1.0.1alpha2isreleased_F9F5/image_3.png" width="480" height="296"/&gt;&lt;/p&gt; &lt;p&gt;Changes from the &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/index.php?post/2009/03/12/Salamanca-1.0-%28alpha-1%29-is-released"&gt;previous release&lt;/a&gt; include :&lt;/p&gt; &lt;ul&gt; &lt;li&gt;A complete refactoring of the libraries : all the base classes are now grouped together in a single assembly (&lt;a rel="nofollow" target="_blank" href="http://salamanca.codeplex.com/Wiki/View.aspx?title=DataRules"&gt;Data Rules&lt;/a&gt;, &lt;a rel="nofollow" target="_blank" href="http://salamanca.codeplex.com/Wiki/View.aspx?title=DataAccess"&gt;Data Access&lt;/a&gt; and &lt;a rel="nofollow" target="_blank" href="http://salamanca.codeplex.com/Wiki/View.aspx?title=DataActivities"&gt;Data Activities&lt;/a&gt;), available in 2 editions (.NET Framework and .NET Compact Framework). Additional assemblies are available for the use of external libraries (Enterprise Library).&lt;/li&gt; &lt;li&gt;The concept of enumerations has been added to the &lt;b&gt;SDML&lt;/b&gt; designer.&lt;/li&gt; &lt;li&gt;Many bug fixes.&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;Note that you will have to uninstall the previous version of Salamanca before installing this one.&lt;/p&gt; &lt;p&gt;There are a few things to be noted about the new enumerations :&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Enumerations defined in the SDML can obviously be used as data types for entity attributes.&lt;/li&gt; &lt;li&gt;Enumerations have an underlying type (pretty much &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/sbbt4032.aspx"&gt;like in C#&lt;/a&gt;). This defines how enumerated values will be stored in the database.&lt;/li&gt; &lt;li&gt;An enumeration translates into a lookup table in the database (each tuple matching an enumerated value).&lt;/li&gt; &lt;li&gt;An underlying value must be provided for every enumerated value (this is optional in C#).&lt;/li&gt; &lt;li&gt;The default underlying type for an enumeration is a string (impossible in C#). This allows for the &lt;a rel="nofollow" target="_blank" href="http://stackoverflow.com/questions/371716/what-datatype-do-you-use-for-enumerations-in-sql-server"&gt;use of mnemonics&lt;/a&gt; in the database. Your DBA will thank you for this !&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;And as a conclusion, here is a short list of features that are planned on our roadmap to a final release :&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Multi database provider SQL code generation : we should at least be able to generate code for Oracle systems.&lt;/li&gt; &lt;li&gt;A first pick at a &lt;strong&gt;SAML&lt;/strong&gt; designer. Salamanca looks a lot like (yet) an (other) ORM framework right now, but this is not all there is to it. The ability to design activities (that may use our entities) will bring huge benefits to developers and will show what our vision truly holds.&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;But for now, enjoy this release. And any feedback will be more than welcome !&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/noury/salamanca?a=Ov2D3DbHjEY:_pzyVbPCr98:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/noury/salamanca?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/noury/salamanca/~4/Ov2D3DbHjEY" height="1" width="1"/&gt;</description>
         <guid isPermaLink="false">urn:md5:276d5c64a85e8e78a251fef2723d0815</guid>
         <pubDate>Thu, 16 Jul 2009 08:46:00 -0700</pubDate>
         <category>General</category>
      <feedburner:origLink>http://salamanca.nourysolutions.com/road/index.php?post/2009/07/16/Salamanca-1.0.1-%28alpha-2%29-is-released</feedburner:origLink></item>
      <item>
         <title>Released: 1.0.1 (alpha 2) (Jul 16, 2009) [CodePlex]</title>
         <link>http://feedproxy.google.com/~r/noury/salamanca/~3/eUFN7VtWJA4/ProjectReleases.aspx</link>
         <description>&lt;div&gt;&lt;b&gt;This software is an alpha release and as such it is not suited for use in production (read : critical) environments.&lt;/b&gt;&lt;br&gt;&lt;br&gt;This is the second release of Salamanca as a Software Factory :
&lt;ul&gt;&lt;li&gt;Completely integrated into the Visual Studio 2008 environment (with an installer).&lt;/li&gt;
&lt;li&gt;Documentation integrated in Microsoft Document Explorer (and also available as a separate download).&lt;/li&gt;
&lt;li&gt;Includes a &lt;b&gt;SDML&lt;/b&gt; designer, with code generation :
&lt;ul&gt;&lt;li&gt;Domain entities (.NET Framework 3.5).&lt;/li&gt;
&lt;li&gt;Data mappers (based on Enterprise Library 4.1, .NET Framework 3.5).&lt;/li&gt;
&lt;li&gt;SQL scripts for tables creation and stored procedures for CRUD access (SQL Server 2005, 2008).&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Libraries (&lt;a rel="nofollow" target="_blank" href="http://salamanca.codeplex.com/Wiki/View.aspx?title=DataRules"&gt;Data Rules&lt;/a&gt;, &lt;a rel="nofollow" target="_blank" href="http://salamanca.codeplex.com/Wiki/View.aspx?title=DataAccess"&gt;Data Access&lt;/a&gt; and &lt;a rel="nofollow" target="_blank" href="http://salamanca.codeplex.com/Wiki/View.aspx?title=DataActivities"&gt;Data Activities&lt;/a&gt;), targeting the .NET Framework (2.0, 3.0 and 3.5) and the .NET Compact Framework (2.0 and 3.5) (and also available as a separate download).&lt;/li&gt;&lt;/ul&gt;
&lt;br&gt;Changes from the &lt;a rel="nofollow" target="_blank" href="http://salamanca.codeplex.com/Wiki/View.aspx?title=http://salamanca.codeplex.com/Release/ProjectReleases.aspx?ReleaseId%3d24562"&gt;previous release&lt;/a&gt; include :
&lt;ul&gt;&lt;li&gt;Complete refactoring of the libraries : all the base classes are now grouped together in a single assembly (&lt;a rel="nofollow" target="_blank" href="http://salamanca.codeplex.com/Wiki/View.aspx?title=DataRules"&gt;Data Rules&lt;/a&gt;, &lt;a rel="nofollow" target="_blank" href="http://salamanca.codeplex.com/Wiki/View.aspx?title=DataAccess"&gt;Data Access&lt;/a&gt; and &lt;a rel="nofollow" target="_blank" href="http://salamanca.codeplex.com/Wiki/View.aspx?title=DataActivities"&gt;Data Activities&lt;/a&gt;), available in 2 editions (.NET Framework and .NET Compact Framework). Additional assemblies are available for the use of external libraries (Enterprise Library).&lt;/li&gt;
&lt;li&gt;The concept of enumerations has been added to the &lt;b&gt;SDML&lt;/b&gt; designer.&lt;/li&gt;
&lt;li&gt;Many bug fixes.&lt;/li&gt;&lt;/ul&gt;
&lt;br&gt;&lt;b&gt;Please note that upgrade from the previous version is unsupported.&lt;/b&gt; You will have to uninstall any prior version of Salamanca before installing this version.&lt;br&gt;&lt;br&gt;Related Resources
&lt;ul&gt;&lt;li&gt;Installation &lt;a rel="nofollow" target="_blank" href="http://salamanca.codeplex.com/Wiki/View.aspx?title=Install"&gt;manual&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://salamanca.codeplex.com/Wiki/View.aspx?title=FactoryQuickStart"&gt;Quick Start&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;
&lt;br&gt;Read more in &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/"&gt;our blog&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/noury/salamanca?a=eUFN7VtWJA4:wfmAO1sXbMo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/noury/salamanca?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/noury/salamanca/~4/eUFN7VtWJA4" height="1" width="1"/&gt;</description>
         <guid isPermaLink="false">Released: 1.0.1 (alpha 2) (Jul 16, 2009) 20090716011711P</guid>
         <pubDate>Thu, 16 Jul 2009 06:17:11 -0700</pubDate>
      <feedburner:origLink>http://salamanca.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=30242</feedburner:origLink></item>
      <item>
         <title>Larguez les amarres ! [A bord de Salamanca]</title>
         <link>http://feedproxy.google.com/~r/noury/salamanca/~3/2LmiJHeHuTs/index.php</link>
         <description>&lt;p&gt;Au moment de larguer les amarres, il y a toujours sur le quai un ami ou un passant pour nous demander si rien n'a été oublié et que tout a été chargé...&lt;/p&gt;
&lt;h2&gt;Pré-requis&lt;/h2&gt;
&lt;p&gt;Pour démarrer, nous avons bien sûr téléchargé la dernière &lt;strong&gt;version 1.0 (alpha) de Salamanca&lt;/strong&gt; à l'adresse :&lt;/p&gt;
&lt;p&gt;&lt;a rel="nofollow" title="http://salamanca.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24562" target="_blank" href="http://salamanca.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24562"&gt;http://salamanca.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24562&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Suivant le &lt;a rel="nofollow" target="_blank" href="http://salamanca.codeplex.com/Wiki/View.aspx?title=Install"&gt;manuel d'installation&lt;/a&gt;, nous avons d'abord vérifié que notre équipement contient déjà &lt;strong&gt;Visual Studio 2008 SP1&lt;/strong&gt; dont la version d'évaluation de l'édition Professionnal est téléchargeable à l'adresse :&lt;/p&gt;
&lt;p&gt;&lt;a rel="nofollow" title="http://www.microsoft.com/downloads/details.aspx?familyid=83C3A1EC-ED72-4A79-8961-25635DB0192B&amp;amp;displaylang=fr" target="_blank" href="http://www.microsoft.com/downloads/details.aspx?familyid=83C3A1EC-ED72-4A79-8961-25635DB0192B&amp;amp;displaylang=fr"&gt;http://www.microsoft.com/downloads/details.aspx?familyid=83C3A1EC-ED72-4A79-8961-25635DB0192B&amp;amp;displaylang=fr&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nous avons ensuite téléchargé et installé les &lt;strong&gt;Guidance Automation Extensions (GAX)&lt;/strong&gt; à l'adresse :&lt;/p&gt;
&lt;p&gt;&lt;a rel="nofollow" title="http://www.microsoft.com/downloads/details.aspx?familyid=DF79C099-4753-4A59-91E3-5020D9714E4E&amp;amp;displaylang=en" target="_blank" href="http://www.microsoft.com/downloads/details.aspx?familyid=DF79C099-4753-4A59-91E3-5020D9714E4E"&gt;http://www.microsoft.com/downloads/details.aspx?familyid=DF79C099-4753-4A59-91E3-5020D9714E4E&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Comme nous souhaitons utiliser les facilités offertes par le Data Access Application Block, nous avons aussi téléchargé &lt;strong&gt;Enterprise Library 4.1&lt;/strong&gt; à l'adresse :&lt;/p&gt;
&lt;p&gt;&lt;a rel="nofollow" title="http://www.microsoft.com/Downloads/details.aspx?familyid=1643758B-2986-47F7-B529-3E41584B6CE5" target="_blank" href="http://www.microsoft.com/Downloads/details.aspx?familyid=1643758B-2986-47F7-B529-3E41584B6CE5"&gt;http://www.microsoft.com/Downloads/details.aspx?familyid=1643758B-2986-47F7-B529-3E41584B6CE5&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nous utiliserons également une base de données &lt;strong&gt;SQL Server 2008 Express&lt;/strong&gt; disponible avec l'outil SQL Server 2008 Management Studio Express à l'adresse :&lt;/p&gt;
&lt;p&gt;&lt;a rel="nofollow" title="http://www.microsoft.com/downloads/details.aspx?displaylang=fr&amp;amp;FamilyID=7522a683-4cb2-454e-b908-e805e9bd4e28" target="_blank" href="http://www.microsoft.com/downloads/details.aspx?displaylang=fr&amp;amp;FamilyID=7522a683-4cb2-454e-b908-e805e9bd4e28"&gt;http://www.microsoft.com/downloads/details.aspx?displaylang=fr&amp;amp;FamilyID=7522a683-4cb2-454e-b908-e805e9bd4e28&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;L'application Salamanca&lt;/h2&gt;
&lt;p&gt;Nous voilà parés pour monter &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/index.php?post/2009/06/15/Embarquement-prochain"&gt;à bord de Salamanca&lt;/a&gt;. Notre périple commence par la création de notre application &lt;em&gt;eProject&lt;/em&gt; dans notre environnement de développement Visual Studio.&lt;/p&gt;
&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/public/WindowsLiveWriter/Larguezlesamarres_94B3/VS_SalamancaApplication_4.png"&gt;&lt;img style="border-width:0;" alt="Salamanca Application" src="http://salamanca.nourysolutions.com/bord/public/WindowsLiveWriter/Larguezlesamarres_94B3/VS_SalamancaApplication_thumb_1.png" border="0" width="460" height="313"/&gt;&lt;/a&gt;&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Nous respectons ensuite (presque) les &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/fr-fr/library/ms229043.aspx"&gt;conventions de nommage de mise en majuscule&lt;/a&gt; de notre langage préféré C# dans la définition du nom de domaine de l'application.&lt;/p&gt;
&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/public/WindowsLiveWriter/Larguezlesamarres_94B3/VS_SalamancaApplicationInformation_4.png"&gt;&lt;img style="border-width:0;" alt="Salamanca Application Information" src="http://salamanca.nourysolutions.com/bord/public/WindowsLiveWriter/Larguezlesamarres_94B3/VS_SalamancaApplicationInformation_thumb_1.png" border="0" width="460" height="312"/&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp; &lt;/p&gt;
&lt;p&gt;&lt;img style="border-width:0;" alt="Explorateur de solutions" src="http://salamanca.nourysolutions.com/bord/public/WindowsLiveWriter/Larguezlesamarres_94B3/VS_SolutionExplorer_9.png" align="right" border="0" width="210" height="489"/&gt; &lt;/p&gt;
&lt;p&gt;Nous obtenons ainsi une solution Visual Studio constituée du projet &lt;em&gt;Eproject.Model&lt;/em&gt; de type &lt;em&gt;Bibliothèque de classes&lt;/em&gt; qui nous permettra de modéliser les concepts métier de notre application et de générer l'ensemble du code associé : &lt;/p&gt;
&lt;ul&gt; &lt;li&gt;classes des entités métier &lt;/li&gt;
&lt;li&gt;classes de mapping objet-relationnel (DataMappers) &lt;/li&gt;
&lt;li&gt;scripts SQL de création des tables et procédures stockées de la base de données &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Afin d'avoir les provisions nécessaires à notre voyage, nous ajoutons dés maintenant à la solution Visual Studio les projets pour chaque composant à fabriquer. Notre application Salamanca est alors composée de :&lt;/p&gt;
&lt;ol&gt; &lt;li&gt;&lt;em&gt;Eproject.Model&lt;/em&gt; de type&lt;em&gt; Bibliothèque de classes&lt;/em&gt; pour la modélisation et la génération des entités métier &lt;/li&gt;
&lt;li&gt;&lt;em&gt;Eproject.Sql&lt;/em&gt; de type &lt;em&gt;Projet de base de données &lt;/em&gt;pour la création et maintenance des scripts SQL &lt;/li&gt;
&lt;li&gt;&lt;em&gt;Eproject.Tests&lt;/em&gt; de type &lt;em&gt;Projet de test &lt;/em&gt;pour la création et l'exécution des tests unitaires &lt;/li&gt;
&lt;li&gt;&lt;em&gt;Eproject.Activities &lt;/em&gt;de type &lt;em&gt;Bibliothèque de classes&lt;/em&gt; pour le codage des activités métier &lt;/li&gt;
&lt;li&gt;&lt;em&gt;Eproject.Web &lt;/em&gt;de type &lt;em&gt;Application Web ASP.NET&lt;/em&gt; contenant l'implémentation web des activités ainsi que la définition de la présentation à travers : &lt;ul&gt; &lt;li&gt;une page maître &lt;/li&gt;
&lt;li&gt;un thème ASP.NET &lt;/li&gt;
&lt;li&gt;les ressources de localisation &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Eproject.Setup&lt;/em&gt; de type &lt;em&gt;Projet d'installation Web&lt;/em&gt; pour le déploiement de l'application &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img style="border:0 none;" alt="Structure de base Subversion" src="http://salamanca.nourysolutions.com/bord/public/WindowsLiveWriter/Larguezlesamarres_94B3/SVN_Structure.png" align="right" border="0" width="179" height="209"/&gt; &lt;/p&gt;
&lt;p&gt;Nous ajoutons l'arborescence des fichiers créés à partir de cette structure de base dans notre &lt;a rel="nofollow" target="_blank" href="http://fr.wikipedia.org/wiki/Syst%C3%A8me_de_gestion_de_versions"&gt;gestionnaire de versions&lt;/a&gt; (Subversion) qui sert de référentiel pour l'ensemble de nos codes sources.&lt;/p&gt;
&lt;p&gt;Nous voilà munis d'un équipement bien outillé et d'un bel horizon devant nous.&lt;/p&gt;
&lt;p&gt;&lt;a rel="nofollow" title="Sun behind cloud, by householdriot on flickr" target="_blank" href="http://www.flickr.com/photos/34077396@N00/15072480/"&gt;&lt;img style="margin-right:15px;" alt="Sun behind cloud" src="http://farm1.static.flickr.com/10/15072480_1bb658ef65_m_d.jpg" border="0" width="240" height="180"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Lors de notre prochaine escale, vous verrez comment nous tirons profit du bon vent que nous amène la modélisation des entités et la génération du code associé.&lt;/p&gt;
&lt;p&gt;Tâchons de garder le cap !&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/noury/salamanca?a=2LmiJHeHuTs:fJp3A9PZo8I:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/noury/salamanca?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/noury/salamanca/~4/2LmiJHeHuTs" height="1" width="1"/&gt;</description>
         <guid isPermaLink="false">urn:md5:c423898a41508cfa61a89cdbfed7e2b4</guid>
         <pubDate>Wed, 01 Jul 2009 08:16:00 -0700</pubDate>
      <feedburner:origLink>http://salamanca.nourysolutions.com/bord/index.php?post/2009/06/29/Larguez-les-amarres-%21</feedburner:origLink></item>
      <item>
         <title>Bye bye World! [A bord de Salamanca]</title>
         <link>http://feedproxy.google.com/~r/noury/salamanca/~3/VoVB1CKSBbU/index.php</link>
         <description>&lt;p&gt;Fidèle à la politesse légendaire des outils de développement, nous
commençons donc par une sorte de "Bonjour Monde !" (ça sonne bizarre en
français...) transformé dans notre cas en "Au revoir Monde !" car c'est
un nouvel univers que nous prenons en main avec Salamanca.&lt;/p&gt;
&lt;p&gt;Voici venue l'heure de faire un tour de chauffe et de voir comment se comporte notre embarcation à travers un prototype de &lt;a rel="nofollow" hreflang="fr" target="_blank" href="http://salamanca.nourysolutions.com/bord/index.php?post/2009/06/15/Embarquement-prochain"&gt;notre application web&lt;/a&gt; développée suivant 2 approches :&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;un formulaire ASP.NET&lt;/li&gt;
&lt;li&gt;une question dans une activité Salamanca&lt;/li&gt;
&lt;/ul&gt;
Dans l'application web métier qui sert de fil conducteur à ce carnet de bord, l'utilisateur va principalement manipuler des projets. L'activité initiale à l'origine de l'ensemble du processus a été spécifiée sous la forme suivante :
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;En tant que donneur d'ordre, je veux pouvoir soumettre un projet en ligne afin de décrire un besoin métier en un minimum de temps. &lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt; &lt;h2&gt;Formulaire ASP.NET&lt;/h2&gt;
&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/public/WindowsLiveWriter/ByebyeWorld_99BF/ASPNETFormView.png"&gt;&lt;img style="border-width:0;" alt="ASP.NET FormView" src="http://salamanca.nourysolutions.com/bord/public/WindowsLiveWriter/ByebyeWorld_99BF/ASPNETFormView_thumb.png" align="right" border="0" width="204" height="244"/&gt;&lt;/a&gt; Un formulaire web peut être rapidement assemblé dans Visual Studio à partir d'une table dans une base de données SQL Express et des contrôles ASP.NET &lt;span style="font-size:1em;color:rgb(163, 21, 21);font-family:courier new;"&gt;FormView, SqlDataSource&lt;/span&gt;. &lt;/p&gt;
&lt;pre class="sql" style="font-size:9pt;"&gt;CREATE TABLE Projets(&lt;br /&gt;	Id int IDENTITY(1,1) NOT NULL,&lt;br /&gt;	Titre nvarchar(255) NOT NULL,&lt;br /&gt;	Description ntext NOT NULL,&lt;br /&gt;	...&lt;br /&gt;)&lt;/pre&gt;
&lt;pre class="xml" style="font-size:9pt;"&gt;&amp;lt;asp:FormView ID="_FormView" runat="server" DataKeyNames="Id" DataSourceID="_SqlDataSource"&amp;gt; ...&lt;br /&gt;&amp;lt;/asp:FormView&amp;gt;&lt;br /&gt;&amp;lt;asp:SqlDataSource ID="_SqlDataSource" runat="server" ConnectionString="&amp;lt;%$ ConnectionStrings:Proto %&amp;gt;" &amp;gt; ... &lt;br /&gt;&amp;lt;/asp:Sqldatasource&amp;gt;&lt;/pre&gt;
&lt;p&gt;Grâce à l'environnement et aux outils mis à notre disposition par Microsoft, nous pouvons donc aller très vite pour "assembler" un écran qui pourrait satisfaire l'exigence métier. Par contre, pour satisfaire &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/index.php?post/2009/06/15/Embarquement-prochain"&gt;nos attentes&lt;/a&gt; et disposer d'une application robuste, modulaire et maintenable, c'est moins certain... Par exemple, maintenir toutes les requêtes SQL inclues directement dans la page web s'avère rapidement consommateur d'énergie lorsqu'on fera évoluer le modèle de données.&lt;/p&gt;
&lt;h2&gt;Question Salamanca&lt;/h2&gt;
&lt;p&gt;Ce que nous avons retenu de l'usine à logiciels Salamanca, c'est l'introduction du &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/index.php?post/2008/10/09/QuickStart-%3A-the-Activity"&gt;concept d'activité métier&lt;/a&gt; pour répondre à la problématique de séparation entre &lt;a rel="nofollow" target="_blank" href="http://fr.wikipedia.org/wiki/Architecture_3-Tier#Les_trois_couches"&gt;les 3 couches&lt;/a&gt; : Présentation - Métier - Accès aux données. Une activité s'exécute à partir de données définies dans un &lt;a rel="nofollow" target="_blank" href="http://fr.wikipedia.org/wiki/Programmation_orient%C3%A9e_objet#Mod.C3.A9lisation_objet"&gt;modéle objet&lt;/a&gt; et interagit avec l'utilisateur à travers des questions auxquelles sont associées des écrans.&lt;/p&gt;
&lt;p&gt;Nous avons ainsi conçu le modèle d'activité suivant pour satisfaire l'exigence spécifiée :&lt;/p&gt;
&lt;p&gt;&lt;img style="border-width:0;" alt="Activit&amp;#xe9; Soumettre un Projet" src="http://salamanca.nourysolutions.com/bord/public/WindowsLiveWriter/ByebyeWorld_99BF/SubmitProjetActivity.png" border="0" width="477" height="164"/&gt;&lt;/p&gt;
&lt;p&gt;Dans le diagramme de notre activité ci-dessus, nous avons :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;un état qui pose une question à l'utilisateur : &lt;span style="font-family:courier new;"&gt;AskProjetInfos&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;deux états de traitement : &lt;span style="font-family:courier new;"&gt;CreateProjet, SaveProjet&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;un conteneur des données manipulées : &lt;span style="font-family:courier new;"&gt;Data&lt;/span&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nous verrons lors d'une prochaine escale comment les entités métier constituant les données de l'activité sont modélisées et le code des classes comme des tables associées sont générées.&lt;/p&gt;
&lt;p&gt;Notre but ici est de faire le parallèle avec le prototype de formulaire ASP.NET, donc d'introduire comment est implémentée la présentation du même écran.&lt;/p&gt;
&lt;p&gt;Lors son exécution, l'activité fournit la référence au projet créé dans la question invitant l'utilisateur à saisir les informations de description de son nouveau projet. On peut alors directement lier l'interface homme-machine avec l'instance de l'entité métier chargée de la persistence des informations.&lt;/p&gt;
&lt;p&gt;Plutôt que d'étendre le contrôle &lt;span style="font-size:1em;color:rgb(163, 21, 21);font-family:courier new;"&gt;FormView&lt;/span&gt; pour y inclure la référence à l'entité, nous préférons implémenter un contrôle utilisateur nommé &lt;span style="font-size:1em;color:rgb(163, 21, 21);font-family:courier new;"&gt;ProjetEditor&lt;/span&gt; qui pourrait être généré à l'avenir par notre usine à partir du modèle objet.&lt;/p&gt;
&lt;pre class="xml" style="font-size:9pt;"&gt;&amp;lt;uc1:ProjetEditor ID="_ProjetEditor" runat="server" /&amp;gt;&lt;/pre&gt;
&lt;pre style="font-size:9pt;"&gt;public partial class ProjetEditor : UserControl, IProjetContainer&lt;/pre&gt;
&lt;p&gt;Dans l'écran associé à la question, nous déclarons comme éléments visuels :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;le contrôle utilisateur : &lt;span style="font-size:1em;color:rgb(163, 21, 21);font-family:courier new;"&gt;ProjetEditor&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;deux boutons pour valider ou annuler la saisie : &lt;span style="font-size:1em;color:rgb(163, 21, 21);font-family:courier new;"&gt;NextButton, CancelButton&lt;/span&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;La page ASP.NET implémente également l'interface contenant l'entité à manipuler :&lt;/p&gt;
&lt;pre style="font-size:9pt;"&gt;public partial class ProjetAskInfos : Page, IProjetContainer&lt;/pre&gt;
&lt;p&gt;Et le lien avec le contrôle utilisateur "coule de source" :&lt;/p&gt;
&lt;pre style="font-size:9pt;"&gt;public Projet Projet&lt;br /&gt;{&lt;br /&gt; get { return _ProjetEditor.Projet; }&lt;br /&gt; set { _ProjetEditor.Projet = value; }&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;Il nous reste à brancher le contrôleur qui gère l'exécution de l'activité :&lt;/p&gt;
&lt;pre style="font-size:9pt;"&gt;private IActivityController ActivityController&lt;br /&gt;{&lt;br /&gt; get { return ActivityControllersSessionStack.Instance.Peek(); }&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;Ce qui est fait à chaque chargement de la page :&lt;/p&gt;
&lt;pre style="font-size:9pt;"&gt;protected void Page_Load(object sender, EventArgs e)&lt;br /&gt;{&lt;br /&gt; ActivityController.Execute(); &lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;Enfin, à travers les évènements déclenchés par un clic sur les boutons, le contrôleur assure le passage à l'état suivant ou l'annulation de l'activité :&lt;/p&gt;
&lt;pre style="font-size:9pt;"&gt;protected void NextButton_Click(object sender, EventArgs e)&lt;br /&gt;{&lt;br /&gt; if (Page.IsValid)&lt;br /&gt; ActivityController.Execute(ActivityStateResult.Next);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;protected void CancelButton_Click(object sender, EventArgs e)&lt;br /&gt;{&lt;br /&gt; ActivityController.Execute(ActivityStateResult.Cancel);&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;Nous voilà donc avec une implémentation pour une IHM web de la question qui contient uniquement de la connectique avec les autres couches. Il nous manque encore un branchement, est-ce que vous voyez lequel ?&lt;/p&gt;
&lt;p&gt;Si oui, vous avez gagné... toute notre estime !&lt;/p&gt;
&lt;p&gt;Nous aurons l'occasion d'y revenir mais l'essentiel est d'avoir pu pratiquer à travers ce prototype d'écran la mise en oeuvre du principe de séparation entre la logique métier et la présentation, approche qui nous permet avec le temps de satisfaire notre préoccupation de développer une application modulaire et évolutive.&lt;/p&gt;
&lt;p&gt;Nous sommes maintenant prêts à nous jeter véritablement à l'eau et nous lancer dans l'équipée du développement d'une application métier avec Salamanca. En bon capitaine, nous rendrons bientôt compte des conditions de notre départ dans ce carnet de bord.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/noury/salamanca?a=VoVB1CKSBbU:-jNWSmgXAnc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/noury/salamanca?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/noury/salamanca/~4/VoVB1CKSBbU" height="1" width="1"/&gt;</description>
         <guid isPermaLink="false">urn:md5:a15a8a2c42b42e2be2b645b9228ab3e1</guid>
         <pubDate>Mon, 29 Jun 2009 02:30:00 -0700</pubDate>
      <feedburner:origLink>http://salamanca.nourysolutions.com/bord/index.php?post/2009/06/29/Bye-bye-World%21</feedburner:origLink></item>
      <item>
         <title>Préparation [A bord de Salamanca]</title>
         <link>http://feedproxy.google.com/~r/noury/salamanca/~3/dgz7O78TroA/index.php</link>
         <description>&lt;p&gt;&lt;a rel="nofollow" title="Bacino del Mediterraneo, Antonio Millo, Wikimedia Commons" target="_blank" href="http://commons.wikimedia.org/wiki/File:Millobacinomed.JPG"&gt;&lt;img style="border-width:0;width:249px;height:179px;" alt="Mediteranean map" src="http://upload.wikimedia.org/wikipedia/commons/9/9b/Millobacinomed.JPG" align="right"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Maintenant que nous avons fait connaissance avec l'équipement (Salamanca), l'équipage (votre dévoué capitaine) et l'équipée (mon projet), nous allons préparer notre itinéraire, histoire de ne pas partir pour l'inconnu.&lt;/p&gt;
&lt;p&gt;Plutôt que fixer une destination, nous préfèrons vous embarquer pour une croisière (à vous de voir si elle s'amuse). &lt;/p&gt;
&lt;p&gt;Elle aura pour escales :&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/index.php?post/2009/06/29/Larguez-les-amarres-%21"&gt;Organisation de la solution Salamanca dans Visual Studio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/index.php?post/2009/07/10/Escale-1-%3A-Entiteacute%3Bs-meacute%3Btier"&gt;Génération du code pour le modèle des entités métier&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/index.php?post/2009/07/31/Escale-2-%3A-Base-de-donneacute%3Bes"&gt;Création de la base de données&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/index.php?post/2009/08/06/Escale-3-%3A-Tests-unitaires"&gt;Configuration du projet de tests unitaires&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Conception du modèle et codage d'une activité métier&lt;/li&gt;
&lt;li&gt;Implémentation web d'une activité métier&lt;/li&gt;
&lt;li&gt;Mise en place du déploiement de l'application web&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Une fois cet itinéraire bouclé, nous prévoyons déjà de le réitérer afin d'améliorer notre connaissance du parcours grâce à l'expérience acquise et d'exploiter les évolutions futures de l'équipement.&lt;/p&gt;
&lt;p&gt;Nous serons peut-être aussi amené à dériver vers d'autres rivages au gré des vents rencontrés entre chaque escale.&lt;/p&gt;
&lt;p&gt;N'hésitez pas également à faire part d'autres voies à explorer.&lt;/p&gt;
&lt;p&gt;Mais avant de partir avec ce plan de route, nous allons nous mettre en situation et tester notre "bateau" avec un essai en "eaux calmes" à travers :&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;a rel="nofollow" hreflang="fr" target="_blank" href="http://salamanca.nourysolutions.com/bord/index.php?post/2009/06/29/Bye-bye-World%21"&gt;Prototypage d'un formulaire ASP.NET avec et sans Salamanca&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a rel="nofollow" title="Paquebot La Pallice, Pep.per, Wikimedia Commons" target="_blank" href="http://fr.wikipedia.org/wiki/Fichier:Paquebot_La_Pallice.jpg"&gt;&lt;img style="border-width:0;width:300px;height:137px;margin-right:20px;" alt="Paquebot La Pallice" src="http://upload.wikimedia.org/wikipedia/commons/8/8e/Paquebot_La_Pallice.jpg"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Et pour se mettre en condition, rien de tel qu'un air d'heureux présage.&lt;/p&gt;
 
 
 
 
&lt;p&gt;Georges Brassens - Heureux qui comme Ulysse&lt;/p&gt;
 
&lt;br /&gt;
&lt;a rel="nofollow" style="border-style:none;" target="_blank" href="http://www.deezer.com/track/2420859"&gt;
&lt;img src="http://www.deezer.com/embedded/footer.jpg" alt="free music" title="free music"/&gt;&lt;/a&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/noury/salamanca?a=dgz7O78TroA:o_9nnV9aISs:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/noury/salamanca?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/noury/salamanca/~4/dgz7O78TroA" height="1" width="1"/&gt;</description>
         <guid isPermaLink="false">urn:md5:8ae05c4915b8d507c745a587b2843abf</guid>
         <pubDate>Mon, 22 Jun 2009 08:30:00 -0700</pubDate>
      <feedburner:origLink>http://salamanca.nourysolutions.com/bord/index.php?post/2009/06/22/Pr%C3%A9paration</feedburner:origLink></item>
      <item>
         <title>New blog in town [The road to Salamanca]</title>
         <link>http://feedproxy.google.com/~r/noury/salamanca/~3/NJm-Ul286Lg/index.php</link>
         <description>&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/"&gt;&lt;img style="border-width:0;margin:0 0 0 10px;display:inline;" title="image" alt="image" src="http://salamanca.nourysolutions.com/road/public/WindowsLiveWriter/Newblogintown_DE1D/image_3.png" align="right" border="0" width="240" height="145"/&gt;&lt;/a&gt;Good news (if you understand French, that is) : Pierre just opened a new blog about Salamanca today called &lt;em&gt;&lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/"&gt;A bord de Salamanca&lt;/a&gt;&lt;/em&gt; (and yes, it’s in French). In &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/bord/index.php?post/2009/06/15/Embarquement-prochain"&gt;his first post&lt;/a&gt;, he says he will, as a Salamanca user, share his experience about Salamanca (some bad, but mostly good I hope…). He will also share tips and tricks about using it.&lt;/p&gt;
&lt;p&gt;Now is thus the time to reconsider the use of our Salamanca feeds. If you were a subscriber to this blog feed (&lt;a rel="nofollow" target="_blank" href="http://feeds2.feedburner.com/noury/salamanca"&gt;http://feeds2.feedburner.com/noury/salamanca&lt;/a&gt;), you will also automatically get updates about the new blog (as well as various Salamanca related links as we gather them around the web). If you only want to get updates about this blog (due to an allergy to French, for instance), a new feed is available at the address &lt;a rel="nofollow" target="_blank" href="http://feeds2.feedburner.com/noury/salamanca/road"&gt;http://feeds2.feedburner.com/noury/salamanca/road&lt;/a&gt;. Links on the website will be updated soon.&lt;/p&gt;
&lt;p&gt;Welcome aboard !&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/noury/salamanca?a=NJm-Ul286Lg:so7nlffRJRA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/noury/salamanca?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/noury/salamanca/~4/NJm-Ul286Lg" height="1" width="1"/&gt;</description>
         <guid isPermaLink="false">urn:md5:3fd07396db65488be25ab06c73725497</guid>
         <pubDate>Fri, 19 Jun 2009 06:47:00 -0700</pubDate>
         <category>General</category>
      <feedburner:origLink>http://salamanca.nourysolutions.com/road/index.php?post/2009/06/19/New-blog-in-town</feedburner:origLink></item>
      <item>
         <title>Embarquement prochain [A bord de Salamanca]</title>
         <link>http://feedproxy.google.com/~r/noury/salamanca/~3/HBjffyL7d6s/index.php</link>
         <description>&lt;p&gt;La &lt;a rel="nofollow" hreflang="en" target="_blank" href="http://salamanca.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24562"&gt;version 1.0 (alpha 1)&lt;/a&gt; de l'&lt;a rel="nofollow" hreflang="en" target="_blank" href="http://salamanca.codeplex.com/"&gt;usine à logiciels Salamanca &lt;/a&gt;est sortie il y a maintenant &lt;a rel="nofollow" hreflang="en" target="_blank" href="http://salamanca.nourysolutions.com/road/index.php?post/2009/03/12/Salamanca-1.0-%28alpha-1%29-is-released"&gt;3 mois&lt;/a&gt; et en tant qu'adopteur de la première heure ("Early adopter"), je compte faire partager à travers ce journal de bord les moments de plénitude comme les mauvais grains que je vis grâce à l'utilisation de cet outil.&lt;/p&gt;
&lt;p&gt;Si je fais l'analogie avec une expédition en bateau, c'est que je préfère partir avec une carte et un cap dans ma façon d'aborder mes projets de développement. Je me sens en effet plus comme un poisson dans l'eau dans le rôle d'analyste que dans le rôle de programmeur même si mon CV revendique plusieurs années d'expérience en développement web et mobile sous .NET.&lt;/p&gt;
&lt;p&gt;C'est pourquoi je vais aborder la navigation dans le monde de Salamanca à travers l'un des projets sur lequel je travaille depuis maintenant 6 mois : &lt;a rel="nofollow" hreflang="fr" target="_blank" href="https://eproject.nourysolutions.com"&gt;eProject&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Ce service vise à accélérer la prise de décision lors du lancement d'un projet de développement métier. Il s'appuie sur
un processus défini de production d'un prototype à partir d'une
expression structurée du besoin. L'idée est de mettre entre les mains
du porteur de projet une ébauche de solution pour faciliter le soutien et l'implication des différents intervenants.&lt;/p&gt;
&lt;p&gt;La mise en oeuvre d'un processus répondant à une problématique métier (dans ce cas le lancement d'un projet) entre directement dans la &lt;a rel="nofollow" hreflang="en" target="_blank" href="http://salamanca.nourysolutions.com/road/index.php?post/2008/08/04/6-getting-on-the-tracks"&gt;ligne de produits&lt;/a&gt; définie pour l'usine à logiciels Salamanca : les applications métier.&lt;/p&gt;
&lt;p&gt;J'attends ainsi de Salamanca qu'elle m'aide à
:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;développer, faire évoluer et maintenir sur la
durée (plusieurs années) un service en ligne dédié aux entreprises&lt;/li&gt;
&lt;li&gt;réaliser rapidement (en
1 ou 2 semaines) des prototypes d'application métier&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;C'est dans ce cadre que je souhaite partager publiquement mon
expérience de l'utilisation de &lt;strong&gt;Salamanca&lt;/strong&gt;.&lt;/p&gt;
&lt;strong&gt;Bienvenue à bord !&lt;/strong&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/noury/salamanca?a=HBjffyL7d6s:CC8pf3YO5bI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/noury/salamanca?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/noury/salamanca/~4/HBjffyL7d6s" height="1" width="1"/&gt;</description>
         <guid isPermaLink="false">urn:md5:75e4128333b2c703a65e53c0503218ad</guid>
         <pubDate>Mon, 15 Jun 2009 06:34:00 -0700</pubDate>
      <feedburner:origLink>http://salamanca.nourysolutions.com/bord/index.php?post/2009/06/15/Embarquement-prochain</feedburner:origLink></item>
      <item>
         <title>Released: 1.0 (alpha 1) (Mar 12, 2009) [CodePlex]</title>
         <link>http://feedproxy.google.com/~r/noury/salamanca/~3/HV_d1KW2zgg/ProjectReleases.aspx</link>
         <description>&lt;div&gt;
&lt;b&gt;This software is an alpha release and as such it is not suited for use in production (read : critical) environments.&lt;/b&gt;&lt;br&gt; &lt;br&gt;&lt;b&gt;If you have downloaded this software before March 16th 2009, please take a look at this show stopper : &lt;a rel="nofollow" target="_blank" href="http://salamanca.codeplex.com/WorkItem/View.aspx?WorkItemId=3923"&gt;Cannot find the generated SqlResource resource at run time&lt;/a&gt;&lt;/b&gt;&lt;br&gt; &lt;br&gt;This is the first release of Salamanca as a Software Factory :&lt;br&gt;&lt;ul&gt;
&lt;li&gt;Completely integrated into the Visual Studio 2008 environment (with an installer).&lt;/li&gt;&lt;li&gt;Includes a &lt;b&gt;SDML&lt;/b&gt; designer, with code generation :&lt;/li&gt;&lt;ul&gt;
&lt;li&gt;Domain entities (.NET Framework 3.5).&lt;/li&gt;&lt;li&gt;Data mappers (based on Enterprise Library 4.1, .NET Framework 3.5).&lt;/li&gt;&lt;li&gt;SQL scripts for tables creation and stored procedures for CRUD access (SQL Server 2005, 2008).&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;Updated libraries (&lt;a rel="nofollow" target="_blank" href="http://salamanca.codeplex.com/Wiki/View.aspx?title=DataRules"&gt;Data Rules&lt;/a&gt;, &lt;a rel="nofollow" target="_blank" href="http://salamanca.codeplex.com/Wiki/View.aspx?title=DataAccess"&gt;Data Access&lt;/a&gt; and &lt;a rel="nofollow" target="_blank" href="http://salamanca.codeplex.com/Wiki/View.aspx?title=DataActivities"&gt;Data Activities&lt;/a&gt;) now targeting the .NET Framework (2.0, 3.0 and 3.5) and the .NET Compact Framework (2.0 and 3.5).&lt;/li&gt;
&lt;/ul&gt; &lt;br&gt;Related Resources&lt;br&gt;&lt;ul&gt;
&lt;li&gt;Installation &lt;a rel="nofollow" target="_blank" href="http://salamanca.codeplex.com/Wiki/View.aspx?title=Install"&gt;manual&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://salamanca.codeplex.com/Wiki/View.aspx?title=FactoryQuickStart"&gt;Quick Start&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt; &lt;br&gt;Read more in &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/index.php?post/2009/03/12/Salamanca-1.0-(alpha-1)-is-released"&gt;our blog&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br&gt;
&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/noury/salamanca?a=HV_d1KW2zgg:gL-c1pcrNn0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/noury/salamanca?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/noury/salamanca/~4/HV_d1KW2zgg" height="1" width="1"/&gt;</description>
         <guid isPermaLink="false">Released: 1.0 (alpha 1) (Mar 12, 2009) 20090316050033P</guid>
         <pubDate>Mon, 16 Mar 2009 10:00:33 -0700</pubDate>
      <feedburner:origLink>http://salamanca.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24562</feedburner:origLink></item>
      <item>
         <title>Salamanca 1.0 (alpha 1) is released [The road to Salamanca]</title>
         <link>http://feedproxy.google.com/~r/noury/salamanca/~3/fQwKFrInkkA/index.php</link>
         <description>&lt;p&gt;Great news today : we just released Salamanca &lt;a rel="nofollow" target="_blank" href="http://salamanca.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24562"&gt;1.0 (alpha 1)&lt;/a&gt; !&lt;/p&gt; &lt;div align="center"&gt;&lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/public/WindowsLiveWriter/Salamanca1.0alpha1isreleased_F888/image_2.png"&gt;&lt;img title="image" style="border-top-width:0px;display:block;border-left-width:0px;float:none;border-bottom-width:0px;margin-left:auto;margin-right:auto;border-right-width:0px;" height="296" alt="image" src="http://salamanca.nourysolutions.com/road/public/WindowsLiveWriter/Salamanca1.0alpha1isreleased_F888/image_thumb.png" width="480" border="0"/&gt;&lt;/a&gt;&lt;/div&gt; &lt;p&gt;As promised, this release includes :&lt;/p&gt; &lt;ul&gt; &lt;li&gt;a &lt;b&gt;SDML&lt;/b&gt; designer, and code generation : &lt;ul&gt; &lt;li&gt;Domain entities (.NET Framework 3.5). &lt;/li&gt; &lt;li&gt;Data mappers (based on Enterprise Library 4.1, .NET Framework 3.5). &lt;/li&gt; &lt;li&gt;SQL scripts for tables creation and stored procedures for &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Create,_read,_update_and_delete"&gt;CRUD&lt;/a&gt; access (SQL Server 2005, 2008). &lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;Updated libraries, now targeting the .NET Framework (2.0, 3.0 and 3.5) and the .NET Compact Framework (2.0 and 3.5). &lt;/li&gt; &lt;li&gt;Complete Visual Studio 2008 integration (via an &lt;a rel="nofollow" target="_blank" href="http://salamanca.codeplex.com/Wiki/View.aspx?title=Install"&gt;installer&lt;/a&gt;). &lt;/li&gt; &lt;/ul&gt; &lt;p&gt;There is still a great deal of work to be done, and you should be aware of some limitations for this release :&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Primary keys for the generated entities are &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/system.guid.aspx"&gt;Guid&lt;/a&gt;s (&lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/ms187942.aspx"&gt;uniqueidentifier&lt;/a&gt; on SQL Server). This cannot be changed. &lt;/li&gt; &lt;li&gt;Types for the entities attributes are limited to the following list : &lt;strong&gt;bool&lt;/strong&gt;, &lt;strong&gt;DateTime&lt;/strong&gt;, &lt;strong&gt;float&lt;/strong&gt;, &lt;strong&gt;double&lt;/strong&gt;, &lt;strong&gt;int&lt;/strong&gt;, &lt;strong&gt;long&lt;/strong&gt;, &lt;strong&gt;short&lt;/strong&gt;, &lt;strong&gt;Guid&lt;/strong&gt; and &lt;strong&gt;string&lt;/strong&gt; (by default). &lt;/li&gt; &lt;li&gt;Entities can only be linked by one association at a time. This should cover the vast majority of cases though… &lt;/li&gt; &lt;/ul&gt; &lt;p&gt;You are welcome to play with our brand new Software Factory and give us any feedback about it. I’ll post later about what the future holds for Salamanca.&lt;/p&gt; &lt;p&gt;We hope you will have a pleasant trip !&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/noury/salamanca?a=fQwKFrInkkA:f9W4dqbDNrY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/noury/salamanca?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/noury/salamanca/~4/fQwKFrInkkA" height="1" width="1"/&gt;</description>
         <guid isPermaLink="false">urn:md5:c09160182c8b4911f0a1a177de1a539f</guid>
         <pubDate>Thu, 12 Mar 2009 09:40:00 -0700</pubDate>
         <category>General</category>
      <feedburner:origLink>http://salamanca.nourysolutions.com/road/index.php?post/2009/03/12/Salamanca-1.0-%28alpha-1%29-is-released</feedburner:origLink></item>
      <item>
         <title>Salamanca in words [The road to Salamanca]</title>
         <link>http://feedproxy.google.com/~r/noury/salamanca/~3/SJzSXBHhQfc/index.php</link>
         <description>&lt;p&gt;It is often said that &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/A_picture_is_worth_a_thousand_words"&gt;a picture is worth a thousand words&lt;/a&gt;.&lt;a rel="nofollow" title="Wordle: Salamanca" target="_blank" href="http://www.wordle.net/gallery/wrdl/574093/Salamanca"&gt;&lt;img style="display:inline;margin-left:0px;margin-right:0px;" alt="Wordle: Salamanca" src="http://www.wordle.net/thumb/wrdl/574093/Salamanca" align="right"/&gt;&lt;/a&gt; How about a picture made of words (click on the image to have a larger view) ?&lt;/p&gt; &lt;p&gt;I just gave this blog the &lt;a rel="nofollow" target="_blank" href="http://www.wordle.net/"&gt;Wordle&lt;/a&gt; treatment, and the result is quite cool I think. But the best is that two of the words that stand out the most are '”Data” and “Activity”. These are indeed two concepts that lie at the heart of Salamanca.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/noury/salamanca?a=1nTZw3r4"&gt;&lt;img src="http://feeds.feedburner.com/~f/noury/salamanca?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/noury/salamanca/~4/SJzSXBHhQfc" height="1" width="1"/&gt;</description>
         <guid isPermaLink="false">urn:md5:d055776b696876266c6ec293f4db39d0</guid>
         <pubDate>Mon, 23 Feb 2009 03:01:00 -0800</pubDate>
         <category>General</category>
      <feedburner:origLink>http://salamanca.nourysolutions.com/road/index.php?post/2009/02/23/Salamanca-in-words</feedburner:origLink></item>
      <item>
         <title>Released: 0.9.1 (Jan 28, 2009) [CodePlex]</title>
         <link>http://feedproxy.google.com/~r/noury/salamanca/~3/RC7fsdPjFv8/ProjectReleases.aspx</link>
         <description>&lt;div&gt;
This is a maintenance release for the Salamanca &lt;a rel="nofollow" target="_blank" href="http://www.codeplex.com/salamanca/Wiki/View.aspx?title=Libraries"&gt;libraries&lt;/a&gt; (0.9.0).&lt;br&gt; &lt;br&gt;Issues closed :&lt;br&gt;&lt;ul&gt;
&lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://www.codeplex.com/salamanca/WorkItem/View.aspx?WorkItemId=3713"&gt;Libraries targeting .NET 2.0 depend on EntLib 4.1 (requires .NET 3.5)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt; &lt;br&gt;This release contains a new version of the three &lt;a rel="nofollow" target="_blank" href="http://www.codeplex.com/salamanca/Wiki/View.aspx?title=Libraries"&gt;libraries&lt;/a&gt; (&lt;b&gt;&lt;a rel="nofollow" target="_blank" href="http://www.codeplex.com/salamanca/Wiki/View.aspx?title=DataRules"&gt;Data Rules&lt;/a&gt;&lt;/b&gt;, &lt;b&gt;&lt;a rel="nofollow" target="_blank" href="http://www.codeplex.com/salamanca/Wiki/View.aspx?title=DataAccess"&gt;Data Access&lt;/a&gt;&lt;/b&gt; and &lt;b&gt;&lt;a rel="nofollow" target="_blank" href="http://www.codeplex.com/salamanca/Wiki/View.aspx?title=DataActivities"&gt;Data Activities&lt;/a&gt;&lt;/b&gt;) for the .NET Framework 2.0, the .NET Framework 3.0 and the .NET Compact Framework 2.0. Dependencies for some of these libraries are :&lt;br&gt;&lt;ul&gt;
&lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/aa480453.aspx"&gt;Enterprise Library 3.1 - May 2007&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt; &lt;br&gt;To help you understand how these &lt;a rel="nofollow" target="_blank" href="http://www.codeplex.com/salamanca/Wiki/View.aspx?title=Libraries"&gt;libraries&lt;/a&gt; typically fit together in a business application, we have set up a quick start, split in two parts :&lt;br&gt;&lt;ol&gt;
&lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://www.codeplex.com/salamanca/Wiki/View.aspx?title=QuickStart1"&gt;Part 1&lt;/a&gt; : how to set up a domain model. Based on an overly simple model (1 object, 1 property, 1 database table), we will be able to create our first application, based on our domain model, with virtually no coding.&lt;/li&gt;&lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://www.codeplex.com/salamanca/Wiki/View.aspx?title=QuickStart2"&gt;Part 2&lt;/a&gt; : how to create and implement an activity. Based on the previous domain model, we will implement our first basic activity as an application. We will also show how our activity can easily be unit tested.&lt;/li&gt;
&lt;/ol&gt; &lt;br&gt;Please find more information &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/index.php?post/2009/01/28/First-maintenance-release-:-0.9.1"&gt;in our blog&lt;span&gt;&lt;/span&gt;&lt;/a&gt;.&lt;br&gt;
&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/noury/salamanca?a=RC7fsdPjFv8:5aKaMNdHCRk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/noury/salamanca?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/noury/salamanca/~4/RC7fsdPjFv8" height="1" width="1"/&gt;</description>
         <guid isPermaLink="false">Released: 0.9.1 (Jan 28, 2009) 20090128042855P</guid>
         <pubDate>Wed, 28 Jan 2009 08:28:55 -0800</pubDate>
      <feedburner:origLink>http://www.codeplex.com/salamanca/Release/ProjectReleases.aspx?ReleaseId=22386</feedburner:origLink></item>
      <item>
         <title>First maintenance release : 0.9.1 [The road to Salamanca]</title>
         <link>http://feedproxy.google.com/~r/noury/salamanca/~3/B72XrpPYBHc/index.php</link>
         <description>&lt;p&gt;We discovered &lt;a rel="nofollow" target="_blank" href="http://www.codeplex.com/salamanca/WorkItem/View.aspx?WorkItemId=3713"&gt;an issue&lt;/a&gt; in the current release of the Salamanca libraries (0.9.0) that was important enough to make us deliver a maintenance release : version &lt;a rel="nofollow" target="_blank" href="http://www.codeplex.com/salamanca/Release/ProjectReleases.aspx?ReleaseId=22386"&gt;0.9.1&lt;/a&gt;. You can use these new libraries as a drop in replacement for the old ones.&lt;/p&gt; &lt;p&gt;Note that the issue discovered concerns only the libraries that depend on &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/cc467894.aspx"&gt;Enterprise Library&lt;/a&gt; :&lt;/p&gt; &lt;ul&gt; &lt;li&gt;DataAccess.EnterpriseLibrary : helps to define &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/cc309504.aspx"&gt;Data Access Application Block&lt;/a&gt; based data mappers.&lt;/li&gt; &lt;li&gt;DataRules.EnterpriseLibrary : helps to integrate the &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/cc309509.aspx"&gt;Validation Application Block&lt;/a&gt; with the Salamanca rules library.&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;We previously compiled these libraries against &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/dd203099.aspx"&gt;version 4.1&lt;/a&gt; of Enterprise Library, which requires the .NET Framework 3.5. As our libraries were only supposed to target the .NET Framework 3.0 at best, this introduced a very unwelcome dependency. So the new version is compiled against &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/aa480453.aspx"&gt;version 3.1&lt;/a&gt; of Enterprise Library, which only requires the .NET Framework 2.0.&lt;/p&gt; &lt;p&gt;As for the next release (&lt;a rel="nofollow" target="_blank" href="http://www.codeplex.com/salamanca/Release/ProjectReleases.aspx?ReleaseId=19080"&gt;1.0.0&lt;/a&gt;), these dependencies has been fixed as followed :&lt;/p&gt; &lt;ul&gt; &lt;li&gt;.NET Framework 2.0, 3.0 targeted libraries : depend on Enterprise Library 3.1.&lt;/li&gt; &lt;li&gt;.NET Framework 3.5 targeted libraries : depend on Enterprise Library 4.1.&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;Did I just write about version 1.0.0 ? Here is in two sentences what is to be expected :&lt;/p&gt; &lt;ul&gt; &lt;li&gt;updated libraries, now targeting the .NET Framework 3.5 as well.&lt;/li&gt; &lt;li&gt;our first &lt;strong&gt;SDML&lt;/strong&gt; designer ! Still limited, but entirely functional, with code generation from SQL to C# entities…&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&lt;img title="image" style="border-right:0px;border-top:0px;display:block;float:none;margin-left:auto;border-left:0px;margin-right:auto;border-bottom:0px;" height="314" alt="image" src="http://salamanca.nourysolutions.com/road/public/WindowsLiveWriter/Firstmaintenancerelease0.9.1_F4E1/image_3.png" width="480" border="0"/&gt; &lt;/p&gt; &lt;p&gt;Stay tuned !&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/noury/salamanca?a=GARxLPLK"&gt;&lt;img src="http://feeds.feedburner.com/~f/noury/salamanca?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/noury/salamanca/~4/B72XrpPYBHc" height="1" width="1"/&gt;</description>
         <guid isPermaLink="false">urn:md5:de98efe5efd82918431ce2efd02e5179</guid>
         <pubDate>Wed, 28 Jan 2009 08:25:00 -0800</pubDate>
      <feedburner:origLink>http://salamanca.nourysolutions.com/road/index.php?post/2009/01/28/First-maintenance-release-%3A-0.9.1</feedburner:origLink></item>
      <item>
         <title>Take the S train [The road to Salamanca]</title>
         <link>http://feedproxy.google.com/~r/noury/salamanca/~3/1gOS7h_C25Q/index.php</link>
         <description>&lt;div align="center"&gt;&lt;iframe class="embeddedvideo" src="http://media.imeem.com/m/FQm-jtooJC/aus=false/" type="application/x-shockwave-flash" width="300" height="110"&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;p&gt;I've got some news just before the holidays :&lt;/p&gt; &lt;ul&gt; &lt;li&gt;the Salamanca repository just got itself a new (shorter) URL : &lt;a rel="nofollow" target="_blank" href="http://salamanca.codeplex.com/"&gt;http://salamanca.codeplex.com/&lt;/a&gt;, thanks to &lt;a rel="nofollow" target="_blank" href="http://blogs.msdn.com/codeplex/archive/2008/12/19/codeplex-goes-less-green-for-the-holidays-with-a-new-look.aspx"&gt;the CodePlex guys&lt;/a&gt;. The old one (that I won't write here) remains valid. &lt;/li&gt; &lt;li&gt;as some of you probably already noticed, Salamanca got itself a logo. &lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&lt;img src="http://salamanca.nourysolutions.com/road/public/Salamanca.png" align="right"/&gt;Not so surprisingly, it is a train (the name Salamanca is a reference to &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/The_Salamanca"&gt;The Salamanca&lt;/a&gt;, the first commercially successful locomotive built in 1812). The original design for this picture can be found on the &lt;a rel="nofollow" target="_blank" href="http://openclipart.org/media/files/johnny_automatic/7685"&gt;Open Clip Art Library&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;The &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Art_Deco"&gt;streamline design&lt;/a&gt; of this engine fits well with the concepts of industrialization that are behind our vision of our Software Factory. And it is also a reference to the excellent &lt;a rel="nofollow" target="_blank" href="http://www.streamlinedmodeling.com/"&gt;Streamlined Object Modeling&lt;/a&gt; book. Though our vision of business object implementation differs somewhat from what can be found in this book, their description and analysis of 12 "collaboration patterns" for modeling real-world relationships is an invaluable resource for any person who is involved in modeling activities. As Salamanca users will inevitably be.&lt;/p&gt; &lt;p&gt;Early in the new year to come, you will have the opportunity to exercise your modeling skills on the first version of Salamanca, that will include a SDML graphical designer and code generation. But for now, I've got a train to catch.&lt;/p&gt; &lt;div align="center"&gt;&lt;iframe class="embeddedvideo" src="http://media.imeem.com/m/v1-Mozqwyc/aus=false/" type="application/x-shockwave-flash" width="300" height="110"&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/noury/salamanca?a=G97SzlFo"&gt;&lt;img src="http://feeds.feedburner.com/~f/noury/salamanca?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/noury/salamanca/~4/1gOS7h_C25Q" height="1" width="1"/&gt;</description>
         <guid isPermaLink="false">urn:md5:33f8319b96b178b19bed01676d733b79</guid>
         <pubDate>Fri, 19 Dec 2008 10:58:00 -0800</pubDate>
      <feedburner:origLink>http://salamanca.nourysolutions.com/road/index.php?post/2008/12/19/Take-the-S-train</feedburner:origLink></item>
      <item>
         <title>To Salamanca via Oslo ? [The road to Salamanca]</title>
         <link>http://feedproxy.google.com/~r/noury/salamanca/~3/nXTtyzUzIL0/index.php</link>
         <description>&lt;p&gt;Now that &lt;a rel="nofollow" target="_blank" href="http://www.codeplex.com/salamanca/Wiki/View.aspx?title=Libraries"&gt;our libraries&lt;/a&gt; are functional enough, it is high time we started getting into the modeling part of our software factory. The first step is to define proper syntaxes for our &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Domain_Specific_Language"&gt;DSL&lt;/a&gt;s : the Salamanca Domain Model Language (&lt;strong&gt;SDML&lt;/strong&gt;) and the Salamanca Activity Model Language (&lt;strong&gt;SAML&lt;/strong&gt;).&lt;/p&gt;
&lt;p&gt;In fact, as a proof of concept, we have already tried to define a syntax for our &lt;strong&gt;SDML&lt;/strong&gt;. Based on XML, it would describe the Domain in terms of types, enumerations, domain elements and associations. Here is an example written in this &lt;strong&gt;SDML&lt;/strong&gt; :&lt;/p&gt;
&lt;pre&gt;&amp;lt;dml&lt;br /&gt; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt; xmlns="http://www.nourysolutions.com/salamanca/DML"&lt;br /&gt; xsi:schemaLocation="http://www.nourysolutions.com/salamanca/DML ../Models/dml.xsd"&lt;br /&gt;&amp;gt;&lt;br /&gt; &amp;lt;serializable name="string"&amp;gt;&lt;br /&gt; &amp;lt;native type="string"/&amp;gt;&lt;br /&gt; &amp;lt;sql dbtype="VARCHAR"/&amp;gt;&lt;br /&gt; &amp;lt;/serializable&amp;gt;&lt;br /&gt; &amp;lt;serializable name="Boolean"&amp;gt;&lt;br /&gt; &amp;lt;native type="bool" nullable="false"&amp;gt;&lt;br /&gt; &amp;lt;conversion language="C#"&amp;gt;Convert.ToBoolean({0})&amp;lt;/conversion&amp;gt;&lt;br /&gt; &amp;lt;/native&amp;gt;&lt;br /&gt; &amp;lt;sql dbtype="BOOLEAN"&amp;gt;&lt;br /&gt; &amp;lt;conversion language="C#"&amp;gt;Convert.ToByte({0})&amp;lt;/conversion&amp;gt;&lt;br /&gt; &amp;lt;/sql&amp;gt;&lt;br /&gt; &amp;lt;/serializable&amp;gt;&lt;br /&gt; &amp;lt;serializable name="Chars"&amp;gt;&lt;br /&gt; &amp;lt;native type="string"/&amp;gt;&lt;br /&gt; &amp;lt;sql dbtype="CHAR"/&amp;gt;&lt;br /&gt; &amp;lt;/serializable&amp;gt;&lt;br /&gt; &amp;lt;serializable name="long"&amp;gt;&lt;br /&gt; &amp;lt;native type="long" nullable="false"/&amp;gt;&lt;br /&gt; &amp;lt;sql dbtype="BIGINT"/&amp;gt;&lt;br /&gt; &amp;lt;/serializable&amp;gt;&lt;br /&gt; &amp;lt;serializable name="Date"&amp;gt;&lt;br /&gt; &amp;lt;native type="System.DateTime" nullable="false"/&amp;gt;&lt;br /&gt; &amp;lt;sql dbtype="DATE"/&amp;gt;&lt;br /&gt; &amp;lt;/serializable&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;enum name="RegionType"&amp;gt;&lt;br /&gt; &amp;lt;base name="Chars" size="3" /&amp;gt;&lt;br /&gt; &amp;lt;value name="Department" code="DEP"&amp;gt;Département&amp;lt;/value&amp;gt;&lt;br /&gt; &amp;lt;value name="State" code="STA"&amp;gt;State&amp;lt;/value&amp;gt;&lt;br /&gt; &amp;lt;value name="Land" code="LAN"&amp;gt;Land&amp;lt;/value&amp;gt;&lt;br /&gt; &amp;lt;/enum&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;domain name="Region" shortName="Regions"&amp;gt;&lt;br /&gt; &amp;lt;attribute name="Id" visibility="none" required="true"&amp;gt;&lt;br /&gt; &amp;lt;type name="long"/&amp;gt;&lt;br /&gt; &amp;lt;/attribute&amp;gt;&lt;br /&gt; &amp;lt;attribute name="Name" required="true"&amp;gt;&lt;br /&gt; &amp;lt;type name="string" size="63" /&amp;gt;&lt;br /&gt; &amp;lt;/attribute&amp;gt;&lt;br /&gt; &amp;lt;attribute name="Type" required="true"&amp;gt;&lt;br /&gt; &amp;lt;type name="RegionType" /&amp;gt;&lt;br /&gt; &amp;lt;/attribute&amp;gt;&lt;br /&gt; &amp;lt;key attributes="Id"/&amp;gt;&lt;br /&gt; &amp;lt;/domain&amp;gt;&lt;br /&gt; &amp;lt;domain name="City" shortName="Cities"&amp;gt;&lt;br /&gt; &amp;lt;attribute name="Id" visibility="none" required="true"&amp;gt;&lt;br /&gt; &amp;lt;type name="long"/&amp;gt;&lt;br /&gt; &amp;lt;/attribute&amp;gt;&lt;br /&gt; &amp;lt;attribute name="Name" required="true"&amp;gt;&lt;br /&gt; &amp;lt;type name="string" size="63" /&amp;gt;&lt;br /&gt; &amp;lt;/attribute&amp;gt;&lt;br /&gt; &amp;lt;attribute name="HasPostalOffice"&amp;gt;&lt;br /&gt; &amp;lt;type name="Boolean" /&amp;gt;&lt;br /&gt; &amp;lt;/attribute&amp;gt;&lt;br /&gt; &amp;lt;key attributes="Id"/&amp;gt;&lt;br /&gt; &amp;lt;/domain&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;assoc name="RegionCities" association="composition"&amp;gt;&lt;br /&gt; &amp;lt;end name="Region" target="Region" multiplicity="1"/&amp;gt;&lt;br /&gt; &amp;lt;end name="Cities" target="City" multiplicity="*"/&amp;gt;&lt;br /&gt; &amp;lt;/assoc&amp;gt;&lt;br /&gt;&amp;lt;/dml&amp;gt;&lt;/pre&gt;
&lt;p&gt;Based on this syntax, we would perform numerous transformations (with &lt;a rel="nofollow" target="_blank" href="http://www.w3.org/TR/xslt"&gt;XSLT&lt;/a&gt;) to generate Visual Studio solutions, projects, source files (SQL, C#), resources and even graphical representation of the domain (by driving the excellent &lt;a rel="nofollow" target="_blank" href="http://www.graphviz.org/"&gt;Graphviz&lt;/a&gt;). But we found several drawbacks to this method :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;XSLT code is &lt;a rel="nofollow" target="_blank" href="http://martinfowler.com/bliki/MovingAwayFromXslt.html"&gt;tedious to write&lt;/a&gt; and hard to debug. &lt;/li&gt;
&lt;li&gt;a DSL modification need the manual refactoring of many, hard to maintain files. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And indeed, our code soon became so complex that we had to leave some things out of the generation process, like the implementation of the many to many relationships...&lt;/p&gt;
&lt;p&gt;So I started lately to delve into the &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/bb126235.aspx"&gt;Visual Studio DSL Tools&lt;/a&gt;, armed with my courage, my computer and the &lt;a rel="nofollow" target="_blank" href="http://www.domainspecificdevelopment.com/"&gt;appropriate reference&lt;/a&gt;. And it looks very promising, though somewhat limited for our grand vision. As &lt;a rel="nofollow" target="_blank" href="http://www.clariusconsulting.net/blogs/kzu/archive/2007/01/08/BuildingSoftwareFactoriesToday.aspx"&gt;Daniel Cazzulino wrote&lt;/a&gt; :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The DSL Tools is basically the first step in the road to realizing the full SF vision outlined in The Book. Hence, if you try to build a real-world factory just using DSLs, you will find it fairly incomplete and not supporting typical scenarios such as providing an initial solution structure where you will put your DSLs, etc. The missing features, though, are most probably those that will come (or become unnecessary) as the full vision is implemented. In the meantime, it feels lacking.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Anyway, the first impressions are excellent, and it feels like time invested in designing our DSLs around these tools will be far from being wasted time.&lt;/p&gt;
&lt;p&gt;This is how I felt this morning, when I discovered that Microsoft is just starting to &lt;a rel="nofollow" target="_blank" href="http://www.microsoft.com/soa/products/oslo.aspx"&gt;communicate about a new product&lt;/a&gt;, that they label as a modeling platform, and that is codenamed &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/oslo/default.aspx"&gt;Oslo&lt;/a&gt;. &lt;a rel="nofollow" target="_blank" href="http://msstudios.vo.llnwd.net/o21/presspass/zune/Looking_Ahead_Zune.wmv"&gt;Hear Bill Gates&lt;/a&gt; about it :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It's actually taking the kind of models that you're seeing arising in specific domains, like software management in System Center, or your data design over in SQL, or your process activities over in BizTalk and saying, we need to take all these domains and be able to put them into one model space. In fact, we need to let people create their own domains that aren't just isolated, but that exist in this one modeling space. And that's what Oslo is about.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I could not agree more. Salamanca needs to have domain models and activity models in the same modeling space, simply because a business activity is by essence bound to manipulate business objects : a &lt;strong&gt;SAML&lt;/strong&gt; model is linked to a &lt;strong&gt;SDML&lt;/strong&gt; model.&lt;/p&gt;
&lt;div align="center"&gt;&lt;a rel="nofollow" title="Good Morning, Oslo by Marcus Ramberg, on Flickr" target="_blank" href="http://www.flickr.com/photos/marcusramberg/87810974/"&gt;&lt;img style="border-width:0;margin:2px 10px;" alt="Good Morning, Oslo" src="http://farm1.static.flickr.com/38/87810974_a094d91f5d.jpg" width="500" height="251"/&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;So it looks a lot like Oslo could be the best way to go to Salamanca. That is sure going to be a long journey, but very likely to be an interesting one. For now, I am sticking to my DSL Tools.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/noury/salamanca?a=hNYgUgM0"&gt;&lt;img src="http://feeds.feedburner.com/~f/noury/salamanca?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/noury/salamanca/~4/nXTtyzUzIL0" height="1" width="1"/&gt;</description>
         <guid isPermaLink="false">urn:md5:13362e666aaf24d1fd795289f009bcf0</guid>
         <pubDate>Wed, 29 Oct 2008 05:57:00 -0700</pubDate>
      <feedburner:origLink>http://salamanca.nourysolutions.com/road/index.php?post/2008/10/29/To-Salamanca-via-Oslo</feedburner:origLink></item>
      <item>
         <title>QuickStart : the Activity [The road to Salamanca]</title>
         <link>http://feedproxy.google.com/~r/noury/salamanca/~3/aK_4zRUAyKI/index.php</link>
         <description>&lt;p&gt;Whereas &lt;strong&gt;Data Access&lt;/strong&gt; could be considered as yet another solution to a very common problem (the ORM problem), &lt;strong&gt;Data Activities&lt;/strong&gt; is quite original in its conception and implementation. The concepts involved here are much less refined or complex, but have already proved to be very powerful.&lt;/p&gt;
&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/index.php?post/2008/10/09/public/pix/FindProductListByName.png"&gt;&lt;img style="border-width:0;margin:0 0 2px 10px;" alt="FindProductListByName" src="http://salamanca.nourysolutions.com/road/index.php?post/2008/10/09/public/pix/FindProductListByName.png" align="right" border="0" width="260" height="232"/&gt;&lt;/a&gt;First of all, we have to define an activity in terms of questions and treatments. The simplest activity I could imagine is the following :&lt;/p&gt;
&lt;ul&gt; &lt;li&gt;this activity is about getting a list of products that match a specified name. &lt;/li&gt;
&lt;li&gt;the first state is a question that asks for the name. &lt;/li&gt;
&lt;li&gt;the second (and last) state is a treatment that finds the corresponding states. &lt;/li&gt;
&lt;li&gt;let's add to this a rule that specifies that the name we are looking for should not be empty (nor &lt;code&gt;null&lt;/code&gt;). &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For this activity, we'll reuse the &lt;code&gt;Product&lt;/code&gt; class we have defined in the Domain Model quick start. The proper way to implement this would be to add a &lt;code&gt;FindByName&lt;/code&gt; method to this class and query the database, but we'll do it the &lt;em&gt;Activity&lt;/em&gt; way this time.&lt;/p&gt;
&lt;p&gt;An activity manipulates data. We need a class to store :&lt;/p&gt;
&lt;ul&gt; &lt;li&gt;the name of the Product. &lt;/li&gt;
&lt;li&gt;the list of products matching that name. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is a base class in the &lt;code&gt;Salamanca.DataActivities&lt;/code&gt; that will help us implement the &lt;code&gt;IActivityData&lt;/code&gt; interface :&lt;/p&gt;
&lt;pre&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Collections.ObjectModel;&lt;br /&gt;using Salamanca.DataActivities;&lt;br /&gt;&lt;br /&gt;namespace QuickStart&lt;br /&gt;{&lt;br /&gt; public class Data:&lt;br /&gt; ActivityData&lt;br /&gt; {&lt;br /&gt; private struct Backup&lt;br /&gt; {&lt;br /&gt; public string Name;&lt;br /&gt; public Product[] Products;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; protected override object CreateBackup()&lt;br /&gt; {&lt;br /&gt; Backup ret=new Backup();&lt;br /&gt; ret.Name=_Name;&lt;br /&gt; ret.Products=_Products.ToArray();&lt;br /&gt; return ret;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; protected override void RestoreBackup(object backup)&lt;br /&gt; {&lt;br /&gt; Backup b=(Backup)backup;&lt;br /&gt; _Name=b.Name;&lt;br /&gt; _Products=new List&amp;lt;Product&amp;gt;(b.Products);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public string Name&lt;br /&gt; {&lt;br /&gt; get { return _Name; }&lt;br /&gt; set { _Name=value; }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public IList&amp;lt;Product&amp;gt; Products&lt;br /&gt; {&lt;br /&gt; get { return _Products; }&lt;br /&gt; set { _Products=new List&amp;lt;Product&amp;gt;(value); }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; private string _Name;&lt;br /&gt; private List&amp;lt;Product&amp;gt; _Products=new List&amp;lt;Product&amp;gt;();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;You see there is a bit more than just having a Name and a Products property. When inheriting from &lt;code&gt;ActivityData&lt;/code&gt;, you have to implement two abstract methods that create and restore backups on the data. We won't really need this system in this activity, but data must implement &lt;code&gt;IBackupable&lt;/code&gt; and this is quite straightforward as you can see in the code above.&lt;/p&gt;
&lt;p&gt;Our activity will ask a question. This question is going to be implemented in the UI layer (likely via a &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/system.windows.forms.textbox.aspx"&gt;&lt;code&gt;TextBox&lt;/code&gt;&lt;/a&gt; on Windows Forms), so we need a way to allow it to plug itself into our activity. We do that via a question factory, as follows :&lt;/p&gt;
&lt;pre&gt;using System;&lt;br /&gt;using Salamanca.DataActivities;&lt;br /&gt;using Salamanca.DataActivities.UI;&lt;br /&gt;&lt;br /&gt;namespace QuickStart&lt;br /&gt;{&lt;br /&gt; public abstract class QuestionFactory&lt;br /&gt; {&lt;br /&gt; public abstract Question AskProductName(IActivityController controller);&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;Our question state will need this &lt;code&gt;QuestionFactory&lt;/code&gt; (or, rather, an implementation of it). And I anticipate that our treatment state will need a &lt;code&gt;DataMapperCollection&lt;/code&gt; as we will retrieve all the products from the database via the &lt;code&gt;Product.FindAll&lt;/code&gt; method. These are the dependencies of our activities, and we will group them in a parameter class :&lt;/p&gt;
&lt;pre&gt;using System;&lt;br /&gt;using Salamanca.DataAccess.Collections;&lt;br /&gt;using Salamanca.DataActivities;&lt;br /&gt;&lt;br /&gt;namespace QuickStart&lt;br /&gt;{&lt;br /&gt; public class Parameters:&lt;br /&gt; IQuestionFactoryParameters&amp;lt;QuestionFactory&amp;gt;&lt;br /&gt; {&lt;br /&gt; public Parameters(QuestionFactory factory, DataMapperCollection dataMappers)&lt;br /&gt; {&lt;br /&gt; _QuestionFactory=factory;&lt;br /&gt; _DataMappers=dataMappers;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public DataMapperCollection DataMappers&lt;br /&gt; {&lt;br /&gt; get&lt;br /&gt; {&lt;br /&gt; return _DataMappers;&lt;br /&gt; }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public QuestionFactory QuestionFactory&lt;br /&gt; {&lt;br /&gt; get&lt;br /&gt; {&lt;br /&gt; return _QuestionFactory;&lt;br /&gt; }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; private DataMapperCollection _DataMappers;&lt;br /&gt; private QuestionFactory _QuestionFactory;&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;We are now ready to create our two states. The first one must implement &lt;code&gt;IActivityInitialState&lt;/code&gt;, which is just a marker interface. As a question state, we can simply derive it from the &lt;code&gt;QuestionActivityState&lt;/code&gt; base class. The second state just fills our &lt;code&gt;Data&lt;/code&gt; with a list of products matching the name that was returned by the question :&lt;/p&gt;
&lt;pre&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using Salamanca.DataActivities;&lt;br /&gt;using Salamanca.DataActivities.UI;&lt;br /&gt;using Salamanca.DataRules;&lt;br /&gt;&lt;br /&gt;namespace QuickStart&lt;br /&gt;{&lt;br /&gt; public class FindProductListByName:&lt;br /&gt; QuestionActivityState&amp;lt;Data&amp;gt;,&lt;br /&gt; IActivityInitialState&lt;br /&gt; {&lt;br /&gt; public FindProductListByName(Data data, QuestionFactory factory, DataMapperCollection dataMappers):&lt;br /&gt; base(data, new Parameters(factory, dataMappers))&lt;br /&gt; {&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; protected override IList&amp;lt;IRule&amp;gt; CreateRules()&lt;br /&gt; {&lt;br /&gt; IList&amp;lt;IRule&amp;gt; ret=base.CreateRules();&lt;br /&gt; ret.Add(&lt;br /&gt; new PredicateRule&amp;lt;FindProductListByName&amp;gt;(&lt;br /&gt; "The name must not be empty.",&lt;br /&gt; new Predicate&amp;lt;FindProductListByName&amp;gt;(&lt;br /&gt; delegate(FindProductListByName s) {&lt;br /&gt; return !string.IsNullOrEmpty(s.Data.Name);&lt;br /&gt; }&lt;br /&gt; )&lt;br /&gt; )&lt;br /&gt; );&lt;br /&gt;&lt;br /&gt; return ret;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; protected override void OnInitialized(ActivityStateEventArgs e)&lt;br /&gt; {&lt;br /&gt; Question=((Parameters)Parameters).QuestionFactory.AskProductName(e.Controller);&lt;br /&gt; base.OnInitialized(e);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; protected override IActivityState NextState&lt;br /&gt; {&lt;br /&gt; get { return new FindProductListByNameFindProducts(Data, (Parameters)Parameters); }&lt;br /&gt; }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; internal class FindProductListByNameFindProducts:&lt;br /&gt; ActivityState&amp;lt;Data&amp;gt;&lt;br /&gt; {&lt;br /&gt; public FindProductListByNameFindProducts(Data data, Parameters parameters) :&lt;br /&gt; base(data, parameters)&lt;br /&gt; {&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; protected override ActivityStateResult Handle(IActivityController controller)&lt;br /&gt; {&lt;br /&gt; List&amp;lt;Product&amp;gt; allProducts=new List&amp;lt;Product&amp;gt;(Product.FindAll(((Parameters)Parameters).DataMappers));&lt;br /&gt; Data.Products=allProducts.FindAll(&lt;br /&gt; new Predicate&amp;lt;Product&amp;gt;(&lt;br /&gt; delegate(Product p) {&lt;br /&gt; return p.Name.Contains(Data.Name);&lt;br /&gt; }&lt;br /&gt; )&lt;br /&gt; );&lt;br /&gt;&lt;br /&gt; return ActivityStateResult.Next;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; protected override IActivityState NextState&lt;br /&gt; {&lt;br /&gt; get { return new EndActivityState&amp;lt;Data&amp;gt;(Data); }&lt;br /&gt; }&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;Note in the question state how we enforced our business rule (the name must not be empty).&lt;/p&gt;
&lt;p&gt;Our activity is ready. Or is it ? What we have here is still an abstraction, and we need an implementation for our &lt;code&gt;QuestionFactory&lt;/code&gt;. And that is precisely the magic of it all : we just need a concrete &lt;code&gt;QuestionFactory&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Say, for instance, that we want to test our activity : we need a question factory that automatically provides the &lt;code&gt;Data&lt;/code&gt; with test product names and checks the results. Here is an implementation of this question factory :&lt;/p&gt;
&lt;pre&gt;internal sealed class TestQuestionFactory:&lt;br /&gt; QuestionFactory&lt;br /&gt;{&lt;br /&gt; public TestQuestionFactory(string name)&lt;br /&gt; {&lt;br /&gt; _Name=name;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public override Question AskProductName(IActivityController controller)&lt;br /&gt; {&lt;br /&gt; Question ret=new AnsweredQuestion();&lt;br /&gt; ret.Answering+=new EventHandler&amp;lt;AnswerEventArgs&amp;gt;(&lt;br /&gt; delegate(object sender, AnswerEventArgs e) {&lt;br /&gt; ((Data)e.Data).Name=_Name;&lt;br /&gt; }&lt;br /&gt; );&lt;br /&gt;&lt;br /&gt; return ret;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; private string _Name;&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;Based on this factory, a test would look like this (there are two products containing &lt;em&gt;Queso&lt;/em&gt; in their name in the Northwind database) :&lt;/p&gt;
&lt;pre&gt;[TestMethod]&lt;br /&gt;public void CanFindProductList()&lt;br /&gt;{&lt;br /&gt; Data data=new Data();&lt;br /&gt; ActivityController controller=new ActivityController(&lt;br /&gt; new FindProductListByName(&lt;br /&gt; data,&lt;br /&gt; new TestQuestionFactory("Queso"),&lt;br /&gt; DataMappers&lt;br /&gt; )&lt;br /&gt; );&lt;br /&gt; controller.Execute();&lt;br /&gt;&lt;br /&gt; Assert.IsTrue(controller.HasCompleted);&lt;br /&gt; Assert.AreEqual(2, data.Products.Count);&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;You can see here how an &lt;code&gt;ActivityController&lt;/code&gt; is used to execute an activity. As all answers are automatically provided, our activity is executed from the beginning to the end in one phase. In a Windows Forms application, the execution would stop at the question state to let the user fill a text box in. When a &lt;em&gt;Find&lt;/em&gt; button would be clicked, the controller would be told to resume the activity execution.&lt;/p&gt;
&lt;p&gt;You can find a complete working example, as a Visual Studio 2008 solution, &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/index.php?post/2008/10/09/public/QuicStart2.exe"&gt;here&lt;/a&gt;. The same activity is implemented as a unit test, and as a Windows Forms application (the underlying database is Northwind on SQL Server, for which a data file is included in the downloadable sample).&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/noury/salamanca?a=C6o2uXI1"&gt;&lt;img src="http://feeds.feedburner.com/~f/noury/salamanca?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/noury/salamanca/~4/aK_4zRUAyKI" height="1" width="1"/&gt;</description>
         <guid isPermaLink="false">urn:md5:a651b67bec53494b8b17ccb7e8977637</guid>
         <pubDate>Thu, 09 Oct 2008 02:08:00 -0700</pubDate>
         <enclosure length="630421" url="http://salamanca.nourysolutions.com/road/public/QuickStart2.exe" type="application/octet-stream" />
      <feedburner:origLink>http://salamanca.nourysolutions.com/road/index.php?post/2008/10/09/QuickStart-%3A-the-Activity</feedburner:origLink></item>
      <item>
         <title>QuickStart : the Domain Model [The road to Salamanca]</title>
         <link>http://feedproxy.google.com/~r/noury/salamanca/~3/uOtRGDg5Roo/index.php</link>
         <description>&lt;p&gt;Now that the first release is out, let's start playing with it. The first step is to design our business objects ; we'll eventually have a DSL for this (the &lt;strong&gt;SDML&lt;/strong&gt;), but basic UML will do for now.&lt;/p&gt;
&lt;p&gt;&lt;img style="border-width:0;margin:2px 10px 2px 0;" alt="Quick Start (UML)" src="http://salamanca.nourysolutions.com/road/index.php?post/2008/09/23/public/QS_UML.png" align="left" border="0" height="55" width="115"/&gt;We'll begin with a (very) simple model. Sorry, I could not think of anything more simple ;-) Our application will deal with products, whose sole property is their name.&lt;/p&gt;
&lt;p&gt;The associated database could be created with the following script :&lt;/p&gt;
&lt;pre class="sql" style="clear:both;"&gt;CREATE TABLE Products (&lt;br /&gt; ProductID INT IDENTITY(1, 1) NOT NULL,&lt;br /&gt; ProductName VARCHAR(40) NOT NULL&lt;br /&gt; CONSTRAINT PRIMARY KEY (ProductID)&lt;br /&gt;);&lt;/pre&gt;
&lt;p&gt;Now we can create our Data Access Layer. What we need first is a class to handle the primary key for our product. We have a base class for it, in the &lt;code&gt;Salamanca.DataAccess&lt;/code&gt; namespace :&lt;/p&gt;
&lt;pre&gt;using System;&lt;br /&gt;using Salamanca.DataAccess;&lt;br /&gt;&lt;br /&gt;namespace QuickStart&lt;br /&gt;{&lt;br /&gt; public class ProductPrimaryKey:&lt;br /&gt; PrimaryKey&amp;lt;int&amp;gt;&lt;br /&gt; {&lt;br /&gt; public ProductPrimaryKey():&lt;br /&gt; base()&lt;br /&gt; {&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public ProductPrimaryKey(int key):&lt;br /&gt; base(key)&lt;br /&gt; {&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public static implicit operator ProductPrimaryKey(int key)&lt;br /&gt; {&lt;br /&gt; return new ProductPrimaryKey(key);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public static explicit operator int(ProductPrimaryKey key)&lt;br /&gt; {&lt;br /&gt; return key.Value;&lt;br /&gt; }&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;Then we need a class to be used as a data holder. More specifically, it will be used as a &lt;a rel="nofollow" target="_blank" href="http://martinfowler.com/eaaCatalog/dataTransferObject.html"&gt;Data Transfer Object&lt;/a&gt; :&lt;/p&gt;
&lt;pre&gt;using System;&lt;br /&gt;using Salamanca.DataAccess;&lt;br /&gt;&lt;br /&gt;namespace QuickStart&lt;br /&gt;{&lt;br /&gt; public class ProductDataTransfer:&lt;br /&gt; IDataTransferObject&lt;br /&gt; {&lt;br /&gt; public object Clone()&lt;br /&gt; {&lt;br /&gt; return MemberwiseClone();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public int Id;&lt;br /&gt; public string Name;&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;What remains to be defined is our &lt;a rel="nofollow" target="_blank" href="http://martinfowler.com/eaaCatalog/domainModel.html"&gt;Domain Model&lt;/a&gt; and our &lt;a rel="nofollow" target="_blank" href="http://martinfowler.com/eaaCatalog/dataMapper.html"&gt;Data Mapper&lt;/a&gt;. To avoid too tight coupling between both, we'll define an interface that will have to be implemented by a product related Data Mapper :&lt;/p&gt;
&lt;pre&gt;using System;&lt;br /&gt;using Salamanca.DataAccess;&lt;br /&gt;using Salamanca.DataAccess.Collections;&lt;br /&gt;&lt;br /&gt;namespace QuickStart&lt;br /&gt;{&lt;br /&gt; public interface IPersonMapper:&lt;br /&gt; IDataMapper&lt;br /&gt; {&lt;br /&gt; Product Find(ProductPrimaryKey key, DataMapperCollection dataMappers);&lt;br /&gt; DomainModelKeyedCollection&amp;lt;Product&amp;gt; FindAll(DataMapperCollection dataMappers);&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;For a starter, we'll only need two methods :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;one to get a specific product instance from the data backend. &lt;/li&gt;
&lt;li&gt;one to get all the products form the data backend. The &lt;code&gt;DomainModelKeyedCollection&lt;/code&gt; returned can be used a regular &lt;code&gt;Collection&lt;/code&gt;, as well as a &lt;code&gt;Dictionary&lt;/code&gt; where products are indexed with their primary keys. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now we're ready to define our Domain Model :&lt;/p&gt;
&lt;pre&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using Salamanca.DataAccess;&lt;br /&gt;using Salamanca.DataAccess.Collections;&lt;br /&gt;using Salamanca.DataRules;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;namespace QuickStart&lt;br /&gt;{&lt;br /&gt; public class Product:&lt;br /&gt; DomainModel&amp;lt;ProductPrimaryKey, ProductDataTransfer&amp;gt;&lt;br /&gt; {&lt;br /&gt;&lt;br /&gt; public Product():&lt;br /&gt; base()&lt;br /&gt; {&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public Product(DataMapperCollection dataMappers):&lt;br /&gt; base(dataMappers)&lt;br /&gt; {&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; protected override ProductPrimaryKey CreateId()&lt;br /&gt; {&lt;br /&gt; return new ProductPrimaryKey(Data.Id);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public static Product Find(ProductPrimaryKey key, DataMapperCollection dataMappers)&lt;br /&gt; {&lt;br /&gt; return ((IProductMapper)dataMappers[typeof(Product)]).Find(key, dataMappers);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public static IList&amp;lt;Product&amp;gt; FindAll(DataMapperCollection dataMappers)&lt;br /&gt; {&lt;br /&gt; return ((IProductMapper)dataMappers[typeof(Product)]).FindAll(dataMappers);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; internal void SetId(int id)&lt;br /&gt; {&lt;br /&gt; Data.Id=id;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; [StringLengthRule(40)]&lt;br /&gt; [NotNullRule]&lt;br /&gt; public string Name&lt;br /&gt; {&lt;br /&gt; get&lt;br /&gt; {&lt;br /&gt; Load(true);&lt;br /&gt; return Data.Name;&lt;br /&gt; }&lt;br /&gt; set&lt;br /&gt; {&lt;br /&gt; if (Data.Name!=value)&lt;br /&gt; {&lt;br /&gt; Data.Name=value;&lt;br /&gt; RaisePropertyChanged("Name");&lt;br /&gt; }&lt;br /&gt; }&lt;br /&gt; }&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;As you can see, this is quite straightforward : just inherit from &lt;code&gt;Salamanca.DataAccess.DomainModel&lt;/code&gt;, override &lt;code&gt;CreateId&lt;/code&gt; and add your properties. The static methods have just been defined here for convenience. Also, note the attributes above the &lt;code&gt;Name&lt;/code&gt; property, that define our first business rules.&lt;/p&gt;
&lt;p&gt;Final step : define a Data Mapper for our product. We'll choose the ADO .NET based abstract implementation that is found in the &lt;code&gt;Salamanca.DataAccess.Data&lt;/code&gt; namespace as a base :&lt;/p&gt;
&lt;pre&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Data;&lt;br /&gt;using System.Data.Common;&lt;br /&gt;using Salamanca.DataAccess;&lt;br /&gt;using Salamanca.DataAccess.Collections;&lt;br /&gt;using Salamanca.DataAccess.Data;&lt;br /&gt;&lt;br /&gt;namespace QuickStart&lt;br /&gt;{&lt;br /&gt; public partial class ProductMapper:&lt;br /&gt; DataMapper&amp;lt;Product , ProductDataTransfer ProductPrimaryKey&amp;gt;,&lt;br /&gt; IProductMapper&lt;br /&gt; {&lt;br /&gt; public ProductMapper(DbConnection connection, ICacheManager cacheManager):&lt;br /&gt; base(connection, DomainModelCreator.CreateDefault&amp;lt;Product&amp;gt;(), cacheManager)&lt;br /&gt; {&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public DomainModelKeyedCollection&amp;lt;Product&amp;gt; FindAll(DataMapperCollection dataMappers)&lt;br /&gt; {&lt;br /&gt; IDbCommand[] commands=new IDbCommand[1];&lt;br /&gt; &lt;br /&gt; commands[0]=Connection.CreateCommand();&lt;br /&gt; commands[0].CommandType=CommandType.Text;&lt;br /&gt; commands[0].CommandText="SELECT ProductID, ProductName FROM Products";&lt;br /&gt; &lt;br /&gt; return Load(commands, dataMappers);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; protected override IList&amp;lt;IDbCommand&amp;gt; CreateSelectCommands(ProductPrimaryKey key)&lt;br /&gt; {&lt;br /&gt; IDbCommand[] commands=new IDbCommand[1];&lt;br /&gt; &lt;br /&gt; commands[0]=Connection.CreateCommand();&lt;br /&gt; commands[0].CommandType=CommandType.Text;&lt;br /&gt; commands[0].CommandText="SELECT ProductName FROM Products WHERE ProductID=@Id";&lt;br /&gt;&lt;br /&gt; IDbDataParameter p=commands[0].CreateParameter();&lt;br /&gt; p.ParameterName="@Id";&lt;br /&gt; p.DbType=DbType.Int32;&lt;br /&gt; p.Value=key.Value;&lt;br /&gt; p.Direction=ParameterDirection.Input;&lt;br /&gt; commands[0].Parameters.Add(p);&lt;br /&gt; &lt;br /&gt; return commands;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; protected override IList&amp;lt;IDbCommand&amp;gt; CreateDeleteCommands(ProductDataTransfer data)&lt;br /&gt; {&lt;br /&gt; IDbCommand[] commands=new IDbCommand[1];&lt;br /&gt; &lt;br /&gt; commands[0]=Connection.CreateCommand();&lt;br /&gt; commands[0].CommandType=CommandType.Text;&lt;br /&gt; commands[0].CommandText="DELETE FROM Products WHERE ProductID=@Id";&lt;br /&gt; &lt;br /&gt; IDbDataParameter p=commands[0].CreateParameter();&lt;br /&gt; p.ParameterName="@Id";&lt;br /&gt; p.DbType=DbType.Int32;&lt;br /&gt; p.Value=data.Id;&lt;br /&gt; p.Direction=ParameterDirection.Input;&lt;br /&gt; commands[0].Parameters.Add(p);&lt;br /&gt; &lt;br /&gt; return commands;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; protected override IList&amp;lt;IDbCommand&amp;gt; CreateInsertCommands(ProductDataTransfer data)&lt;br /&gt; {&lt;br /&gt; IDbCommand[] commands=new IDbCommand[1];&lt;br /&gt; &lt;br /&gt; commands[0]=Connection.CreateCommand();&lt;br /&gt; commands[0].CommandType=CommandType.Text;&lt;br /&gt; commands[0].CommandText="INSERT INTO Products (ProductName) VALUES(@ProductName)";&lt;br /&gt; &lt;br /&gt; IDbDataParameter p=commands[0].CreateParameter();&lt;br /&gt; p.ParameterName="@Name";&lt;br /&gt; p.DbType=DbType.String;&lt;br /&gt; p.Value=data.Name;&lt;br /&gt; p.Direction=ParameterDirection.Input;&lt;br /&gt; commands[0].Parameters.Add(p);&lt;br /&gt; &lt;br /&gt; return commands;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; protected override IList&amp;lt;IDbCommand&amp;gt; CreateUpdateCommands(ProductDataTransfer data)&lt;br /&gt; {&lt;br /&gt; IDbCommand[] commands=new IDbCommand[1];&lt;br /&gt; &lt;br /&gt; commands[0]=Connection.CreateCommand();&lt;br /&gt; commands[0].CommandType=CommandType.Text;&lt;br /&gt; commands[0].CommandText="UPDATE Products SET ProductName=@Name WHERE ProductID=@Id";&lt;br /&gt; &lt;br /&gt; IDbDataParameter p=commands[0].CreateParameter();&lt;br /&gt; p.ParameterName="@Name";&lt;br /&gt; p.DbType=DbType.String;&lt;br /&gt; p.Value=data.Name;&lt;br /&gt; p.Direction=ParameterDirection.Input;&lt;br /&gt; commands[0].Parameters.Add(p);&lt;br /&gt; &lt;br /&gt; p=commands[0].CreateParameter();&lt;br /&gt; p.ParameterName="@Id";&lt;br /&gt; p.DbType=DbType.Int32;&lt;br /&gt; p.Value=data.Id;&lt;br /&gt; p.Direction=ParameterDirection.Input;&lt;br /&gt; commands[0].Parameters.Add(p);&lt;br /&gt; &lt;br /&gt; return commands;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; protected override ProductDataTransfer GetDataTransferObject(IList&amp;lt;IDataRecord&amp;gt; records)&lt;br /&gt; {&lt;br /&gt; ProductDataTransfer data=new ProductDataTransfer();&lt;br /&gt;&lt;br /&gt; int ord=records[0].GetOrdinal("ProductID");&lt;br /&gt; if (!records[0].IsDBNull(ord))&lt;br /&gt; data.Id=records[0].GetInt32(ord);&lt;br /&gt;&lt;br /&gt; ord=records[0].GetOrdinal("ProductName");&lt;br /&gt; if (!records[0].IsDBNull(ord))&lt;br /&gt; data.Name=records[0].GetString(ord);&lt;br /&gt; &lt;br /&gt; return data;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; protected override void OnInserted(Product domainModel, IList&amp;lt;IDbCommand&amp;gt; commands)&lt;br /&gt; {&lt;br /&gt; IDbCommand command=Connection.CreateCommand();&lt;br /&gt; command.CommandType=CommandType.Text;&lt;br /&gt; command.CommandText="SELECT @@IDENTITY";&lt;br /&gt; command.Transaction=commands[0].Transaction;&lt;br /&gt; &lt;br /&gt; domainModel.SetId(Convert.ToInt32(command.ExecuteScalar()));&lt;br /&gt; &lt;br /&gt; base.OnInserted(domainModel, commands);&lt;br /&gt; }&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;
&lt;p&gt;That's it : derive from &lt;code&gt;DataMapper&lt;/code&gt; and fill the gaps with pure ADO .NET code. You can already understand that this is where code generation will greatly improve the developer productivity.&lt;/p&gt;
&lt;p&gt;Our Data Access Layer is now complete : we can build a simple application based on it. The only (?) tricky thing is that you will need to create an instance of &lt;code&gt;DataMapperCollection&lt;/code&gt;. For our sample, simply use this code :&lt;/p&gt;
&lt;pre&gt;DataMapperCollection _DataMappers=new DataMapperCollection();&lt;br /&gt;_DataMappers.Add(typeof(Product), new ProductMapper(Connection, new NoCacheManager()));&lt;/pre&gt;
&lt;p&gt;It creates a new collection based on a prexisting &lt;code&gt;Connection&lt;/code&gt;, and our data is simply not cached in memory.&lt;/p&gt;
&lt;p&gt;You can find a complete working example, as a Visual Studio 2008 solution, &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/index.php?post/2008/09/23/public/QuickStart.exe"&gt;here&lt;/a&gt;. As you can see, we can build a simple application that integrates our Domain Model in a very few lines of code, with business rules validation (the underlying database is Northwind on SQL Server, for which a data file is included in the downloadable sample).&lt;/p&gt;
&lt;div style="text-align:center;"&gt;&lt;img style="border-width:0;margin:2px 10px;" alt="Quick Start Sample" src="http://salamanca.nourysolutions.com/road/index.php?post/2008/09/23/public/QuickStart1.png" border="0" height="287" width="392"/&gt;&lt;/div&gt;
&lt;p&gt;Next time, we will create our first activity. Stay tuned !&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/noury/salamanca?a=LvZULTIF"&gt;&lt;img src="http://feeds.feedburner.com/~f/noury/salamanca?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/noury/salamanca/~4/uOtRGDg5Roo" height="1" width="1"/&gt;</description>
         <guid isPermaLink="false">urn:md5:8c5b5ab5abcdf51e493555e82f2c81c5</guid>
         <pubDate>Tue, 23 Sep 2008 07:32:00 -0700</pubDate>
         <enclosure length="613276" url="http://salamanca.nourysolutions.com/road/public/QuickStart.exe" type="application/octet-stream" />
      <feedburner:origLink>http://salamanca.nourysolutions.com/road/index.php?post/2008/09/23/QuickStart-%3A-the-Domain-Model</feedburner:origLink></item>
      <item>
         <title>First public release [The road to Salamanca]</title>
         <link>http://feedproxy.google.com/~r/noury/salamanca/~3/Yyv3ChluST8/index.php</link>
         <description>&lt;p&gt;Today is the day when Salamanca hits its first public release, tagged 0.9.0. You can &lt;a rel="nofollow" target="_blank" href="http://www.codeplex.com/salamanca/Release/ProjectReleases.aspx?ReleaseId=12866"&gt;download it here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This first release consists of the binaries for the three sets of libraries (&lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/index.php?post/2008/08/26/Inside-the-libraries-I-%3A-Data-Rules"&gt;Data Rules&lt;/a&gt;, &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/index.php?post/2008/09/01/Inside-the-libraries-II-%3A-Data-Access"&gt;Data Access&lt;/a&gt; and &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/index.php?post/2008/09/08/Inside-the-libraries-III-%3A-Data-Activities"&gt;Data Activities&lt;/a&gt;), for the three following environments :&lt;/p&gt;
&lt;ul&gt; &lt;li&gt;.NET Framework 2.0&lt;/li&gt;
&lt;li&gt;.NET Framework 3.0&lt;/li&gt;
&lt;li&gt;.NET Compact Framework 2.0&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is also (some) documentation with (some) sample code. Work on this matter is obviously still in progress, but you can find more complete sample code &lt;a rel="nofollow" target="_blank" href="http://www.codeplex.com/salamanca/SourceControl/ListDownloadableCommits.aspx"&gt;in the source code&lt;/a&gt;. Check for the Northwind&amp;nbsp; projects, that are used for our unit tests, based on the &lt;a rel="nofollow" target="_blank" href="http://codeplex.com/SqlServerSamples"&gt;Northwind sample database&lt;/a&gt;. They are quite complete at this stage and are used to demonstrate what generated code could look like.&lt;/p&gt;
&lt;p&gt;The future looks bright, and there is a lot of very interesting work to be done (most of which has already been introduced in this blog). The following list is unordered and incomplete :&lt;/p&gt;
&lt;ul&gt; &lt;li&gt;Migration to Visual Studio 2008, and .NET Framework 3.5 compatibility.&lt;/li&gt;
&lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://www.codeplex.com/unity"&gt;Unity&lt;/a&gt; integration.&lt;/li&gt;
&lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/netframework/aa904594.aspx"&gt;LINQ&lt;/a&gt; integration.&lt;/li&gt;
&lt;li&gt;JSON serialization.&lt;/li&gt;
&lt;li&gt;ASP .NET AJAX integration.&lt;/li&gt;
&lt;li&gt;WPF integration.&lt;/li&gt;
&lt;li&gt;A Domain Model designer, an Activities designer, and related code generation, the whole thing being integrated into Visual Studio : a true and real Software Factory.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you want to hit the road with us, you are more than welcome. For the time being, Salamanca has never been so close. Olé!&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/noury/salamanca?a=wZF2fQ8h"&gt;&lt;img src="http://feeds.feedburner.com/~f/noury/salamanca?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/noury/salamanca/~4/Yyv3ChluST8" height="1" width="1"/&gt;</description>
         <guid isPermaLink="false">urn:md5:d43fdda2331affa931e5e72bd9c7d344</guid>
         <pubDate>Tue, 16 Sep 2008 07:45:00 -0700</pubDate>
      <feedburner:origLink>http://salamanca.nourysolutions.com/road/index.php?post/2008/09/16/First-public-release</feedburner:origLink></item>
      <item>
         <title>Inside the libraries (III) : Data Activities [The road to Salamanca]</title>
         <link>http://feedproxy.google.com/~r/noury/salamanca/~3/bQvhRpLUwTI/index.php</link>
         <description>&lt;p&gt;&lt;strong&gt;Data Activities&lt;/strong&gt; defines the base classes that help us implement our architectural pattern, centered around business activities. All the concepts developed in this context owe a lot to the vision and the ideas of &lt;a rel="nofollow" target="_blank" href="http://www.amazon.fr/Livres/s?ie=UTF8&amp;amp;rh=n%3A301061%2Cp_27%3AYves%20Darmaillac&amp;amp;field-author=Yves%20Darmaillac"&gt;Yves Darmaillac&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We define an activity as a part of a business process. All the business process parts that are involved in a business application define this application activities. An activity is a &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Finite_state_machine"&gt;finite state machine&lt;/a&gt;, comprising two kinds of states :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;treatment states : those require no external data (think user interaction). For instance, a treatment state can perform an action on our domain model (create a new reservation), or directly on the data (calculate booking fees). All a treatment state needs to perform its action is data. &lt;/li&gt;
&lt;li&gt;question states : those do require external data. For instance, a question state can ask for data for a domain model instance (fill reservation details), or it can ask for a specific domain model instance (pick up your seat). Usually, a question is answered via user interaction (but not necessarily, like in the case of unit tests where answers can be automated). &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The golden rule here is to make sure that all the application behavior is defined in terms of activities. Treatments are by definition self-sufficient and generic. Questions define abstractions that have to be implemented by the HMI layer. In effect, such abstractions can be implemented by all kinds of presentation technologies (console applications, Windows Forms, ASP .NET, WPF...) with no impact on the business logic.&lt;/p&gt;
&lt;p&gt;&lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/public/DataActivitiesInterfacesBasics.png"&gt;&lt;img style="border-width:0;margin:2px 0 2px 10px;" alt="Basics" src="http://salamanca.nourysolutions.com/road/public/DataActivitiesInterfacesBasics.png" align="right" border="0" height="260" width="242"/&gt;&lt;/a&gt;The fundamental interfaces defined in this library are :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;IActivityState&lt;/code&gt; is an interface implemented by an activity state, and treatment states in particular. &lt;code&gt;IQuestionActivityState&lt;/code&gt; is a specialization that is implemented by a question state. &lt;/li&gt;
&lt;li&gt;&lt;code&gt;IActivityData&lt;/code&gt; is implemented by an activity data holder type : it holds the data that is manipulated by a specific activity. &lt;/li&gt;
&lt;li&gt;&lt;code&gt;IActivityParameters&lt;/code&gt; is implemented by an activity parameters holder type. An activity parameter could be seen as an immutable activity data. &lt;/li&gt;
&lt;li&gt;&lt;code&gt;IActivityController&lt;/code&gt; is implemented by an activity controller. Such a class is essential to the activity execution : it initiates the activity, terminates it and controls all the state transitions in between. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All the states must be validated before transition : this is achieved via the integration of &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/index.php?post/2008/08/26/Inside-the-libraries-I-%3A-Data-Rules"&gt;Data Rules&lt;/a&gt;. The library defines base implementations for all these interfaces, and helpful classes to implement questions in specific presentation technologies (so far Windows Forms and ASP .NET).&lt;/p&gt;
&lt;p&gt;Activities are at the core of our architecture : they manipulate data and act as a separation of concerns between the business logic and the presentation. In the future, we will be able to design our activities via our own DSL (&lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/index.php?post/2008/08/20/Visiting-Salamanca"&gt;SAML&lt;/a&gt;), and have base implementations (and best practices) for questions in other technologies such as WPF or ASP .NET AJAX.&lt;/p&gt;
&lt;p&gt;I would like to finish with an analogy that might confuse some readers, but hopefully enlighten others : &lt;a rel="nofollow" target="_blank" href="http://members.tripod.com/diabetics_world/lillys_rdna_insulin.htm"&gt;&lt;img style="border-width:0;margin:2px 10px 2px 0;" alt="image" src="http://salamanca.nourysolutions.com/road/public/rna.jpg" align="left" border="0" height="169" width="260"/&gt;&lt;/a&gt;I like to think of a business activity as a &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Translation_%28biology%29"&gt;RNA translation&lt;/a&gt; process, which is part of the &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Protein_biosynthesis"&gt;protein biosynthesis&lt;/a&gt;. The elements involved in this process are :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/MRNA"&gt;mRNA&lt;/a&gt; template. It holds the code for a specific protein. This code has a start and an end, and has to be followed in order. This is our finite state machine, each &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Codon"&gt;codon&lt;/a&gt; being seen as a state. &lt;/li&gt;
&lt;li&gt;a &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Ribosome"&gt;ribosome&lt;/a&gt;. This is the protein "factory". It "reads" the &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Codon#RNA_codon_table"&gt;codons&lt;/a&gt; one by one and performs an action on each of them : add the corresponding &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Amino_acid"&gt;amino acid&lt;/a&gt; to the chain that will become our protein. This is our activity controller. &lt;/li&gt;
&lt;li&gt;the &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Protein"&gt;protein&lt;/a&gt;. This is the result of the entire process. This could be seen as our data. &lt;/li&gt;
&lt;/ul&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/noury/salamanca?a=dzoAb7Bi"&gt;&lt;img src="http://feeds.feedburner.com/~f/noury/salamanca?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/noury/salamanca/~4/bQvhRpLUwTI" height="1" width="1"/&gt;</description>
         <guid isPermaLink="false">urn:md5:25715f54f95048c5d74b8e8a7bde9257</guid>
         <pubDate>Mon, 08 Sep 2008 08:47:00 -0700</pubDate>
      <feedburner:origLink>http://salamanca.nourysolutions.com/road/index.php?post/2008/09/08/Inside-the-libraries-III-%3A-Data-Activities</feedburner:origLink></item>
      <item>
         <title>Inside the libraries (II) : Data Access [The road to Salamanca]</title>
         <link>http://feedproxy.google.com/~r/noury/salamanca/~3/1kNm4rBmlM4/index.php</link>
         <description>&lt;p&gt;This one is simple : &lt;strong&gt;Data Access&lt;/strong&gt; is an &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Object-relational_mapping"&gt;Object-Relational Mapping&lt;/a&gt; (ORM) library. As such, it owes a lot to the experience of &lt;a rel="nofollow" target="_blank" href="http://www.nourysolutions.com/"&gt;NourY Solutions&lt;/a&gt; in the field of data management. But our ability to structure this experience and put it into words has been greatly enhanced by the remarkable work of &lt;a rel="nofollow" target="_blank" href="http://www.martinfowler.com/"&gt;Martin Fowler&lt;/a&gt;. Many concepts in use in this library are described in his book &lt;a rel="nofollow" target="_blank" href="http://martinfowler.com/eaaCatalog/"&gt;Patterns of Enterprise Application Architecture&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;There are many .NET &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/List_of_object-relational_mapping_software#.NET"&gt;ORM libraries out there&lt;/a&gt;. As evoked &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/index.php?post/2008/08/20/Visiting-Salamanca"&gt;before&lt;/a&gt;, we don't believe "one size fits all" applies when it comes to ORM ; the mismatch between the object world and the relational one is so huge that it can only be solved by specific solutions under specific sets of constraints. &lt;strong&gt;Data Access&lt;/strong&gt; has been designed with these constraints in mind :&lt;/p&gt; &lt;ul&gt; &lt;li&gt;integration with &lt;strong&gt;&lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/index.php?post/2008/08/26/Inside-the-libraries-I-%3A-Data-Rules"&gt;Data Rules&lt;/a&gt;&lt;/strong&gt;. &lt;/li&gt; &lt;li&gt;easy serialization of business object instances (XML for use in Web Services, &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Json"&gt;JSON&lt;/a&gt; for Ajax applications...). &lt;/li&gt; &lt;li&gt;persistence backend abstraction : business objects should easily be persisted against any database backend, like a standard RDBMS solution (Sql Server, Oracle, SQLite...), or a web service, or even a flat file. &lt;/li&gt; &lt;li&gt;the developer always has to be in control : for instance, no on-the-fly SQL generation (though this could be added later as an option). &lt;/li&gt; &lt;li&gt;easy code generation (we want to build a Software Factory, after all !). &lt;/li&gt; &lt;/ul&gt; &lt;p&gt; This library is organized around 4 interfaces :&lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/public/wlw/InsidethelibrariesIIDataAccess_CD63/Basics.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;margin:0px 0px 2px 10px;border-right-width:0px;" height="380" alt="Basics" src="http://salamanca.nourysolutions.com/road/public/wlw/InsidethelibrariesIIDataAccess_CD63/Basics_thumb.png" width="236" align="right" border="0"/&gt;&lt;/a&gt; &lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;code&gt;IDomainModel&lt;/code&gt; : is implemented by a &lt;a rel="nofollow" target="_blank" href="http://martinfowler.com/eaaCatalog/domainModel.html"&gt;Domain Model&lt;/a&gt;. There is also an abstract class (&lt;code&gt;DomainModel&lt;/code&gt;) that can be used as a base implementation for your business objects. It provides &lt;strong&gt;Data Rules&lt;/strong&gt; implementation, serialization, and UI integration (through the implementation of the standard &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/system.componentmodel.idataerrorinfo.aspx"&gt;&lt;code&gt;IDataErrorInfo&lt;/code&gt;&lt;/a&gt;, &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/system.componentmodel.ieditableobject.aspx"&gt;&lt;code&gt;IEditableObject&lt;/code&gt;&lt;/a&gt; and &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx"&gt;&lt;code&gt;INotifyPropertyChanged&lt;/code&gt;&lt;/a&gt; interfaces). &lt;/li&gt; &lt;li&gt;&lt;code&gt;IDataMapper&lt;/code&gt; : is implemented by a &lt;a rel="nofollow" target="_blank" href="http://martinfowler.com/eaaCatalog/dataMapper.html"&gt;Data Mapper&lt;/a&gt;, which basically provides the persistence backend abstraction. The library provides base implementation for persistence based on standard ADO .NET, Enterprise Library &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/cc309504.aspx"&gt;Data Access Application Block&lt;/a&gt; or Web Services.&lt;/li&gt; &lt;li&gt;&lt;code&gt;IDataTransferObject&lt;/code&gt; : this interface is implemented by a &lt;a rel="nofollow" target="_blank" href="http://martinfowler.com/eaaCatalog/dataTransferObject.html"&gt;Data Transfer Object&lt;/a&gt;. It is used to hold the data of a Domain Model, to transfer it between a Domain Model and a Data Mapper and to serialize our Domain Models.&lt;/li&gt; &lt;li&gt;&lt;code&gt;IPrimaryKey&lt;/code&gt; : is implemented by custom &lt;a rel="nofollow" target="_blank" href="http://martinfowler.com/eaaCatalog/identityField.html"&gt;Identity Field&lt;/a&gt;s types.&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;A DSL to design our Domain Models would look a lot like a &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Class_diagram"&gt;class diagram&lt;/a&gt;. And it does actually ;-) (more on that later).&lt;/p&gt; &lt;p&gt;Our plans in the future for this library are :&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://www.codeplex.com/unity"&gt;Unity&lt;/a&gt; integration.&lt;/li&gt; &lt;li&gt;Ability to serialize trees of objects.&lt;/li&gt; &lt;li&gt;JSON serialization.&lt;/li&gt; &lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://www.microsoft.com/windowsserver2003/technologies/management/powershell/default.mspx"&gt;Powershell&lt;/a&gt; integration.&lt;/li&gt; &lt;li&gt;&lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/ms141026.aspx"&gt;SSIS&lt;/a&gt; integration.&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;Next time will be the time to introduce &lt;strong&gt;Data Activities&lt;/strong&gt;.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/noury/salamanca?a=auY5Umea"&gt;&lt;img src="http://feeds.feedburner.com/~f/noury/salamanca?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/noury/salamanca/~4/1kNm4rBmlM4" height="1" width="1"/&gt;</description>
         <guid isPermaLink="false">urn:md5:bcf696d8d3f3b2780aa2cc4b9fe7552f</guid>
         <pubDate>Mon, 01 Sep 2008 08:59:00 -0700</pubDate>
      <feedburner:origLink>http://salamanca.nourysolutions.com/road/index.php?post/2008/09/01/Inside-the-libraries-II-%3A-Data-Access</feedburner:origLink></item>
      <item>
         <title>Inside the libraries (I) : Data Rules [The road to Salamanca]</title>
         <link>http://feedproxy.google.com/~r/noury/salamanca/~3/7PYkRvkNOkc/index.php</link>
         <description>&lt;p&gt;Now is the time to delve a bit more into the libraries that lie at the core of our factory. On top of them lie &lt;strong&gt;Data Rules&lt;/strong&gt;.&lt;/p&gt; &lt;p&gt;First of all, note that this library owes a lot to the work of &lt;a rel="nofollow" target="_blank" href="http://www.paulstovell.com/"&gt;Paul Stovell&lt;/a&gt;, and that most of the concepts discussed here can be found in &lt;a rel="nofollow" target="_blank" href="http://www.codeproject.com/KB/cs/DelegateBusinessObjects.aspx"&gt;this article&lt;/a&gt; of his.&lt;/p&gt; &lt;p&gt;So &lt;strong&gt;Data Rules&lt;/strong&gt; is a validation framework. The goal here is to handle invalid data in your custom types a bit like &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/kx9x2fsb.aspx"&gt;&lt;code&gt;DataSet&lt;/code&gt; does&lt;/a&gt; : instead of throwing an exception every time invalid data is affected to it, it records whether the data it is containing is valid or not; and if not, why. This allows for much smoother UI integration (that is what &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/system.windows.forms.errorprovider.aspx"&gt;&lt;code&gt;ErrorProvider&lt;/code&gt;&lt;/a&gt; and &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/system.componentmodel.idataerrorinfo.aspx"&gt;&lt;code&gt;IDataErrorInfo&lt;/code&gt;&lt;/a&gt; are all about).&lt;/p&gt; &lt;p&gt;This library is organized around 2 interfaces :&lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/public/wlw/InsidethelibrariesIDataRules_F7B4/Basics.png"&gt;&lt;img style="border-right:0px;border-top:0px;margin:2px 0px 2px 10px;border-left:0px;border-bottom:0px;" height="380" alt="Basics" src="http://salamanca.nourysolutions.com/road/public/wlw/InsidethelibrariesIDataRules_F7B4/Basics_thumb.png" width="234" align="right" border="0"/&gt;&lt;/a&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;code&gt;IValidatable&lt;/code&gt; is here to help the developer define a custom type that has such a behavior. A validatable type is one for which any instance can be validated against a specified set of rules. In &lt;strong&gt;Data Access&lt;/strong&gt;, our business objects are validatable : you can always know whether data is valid or not, and why. And if you try to persist an invalid business object, you will get an exception. &lt;/li&gt; &lt;li&gt;&lt;code&gt;IRule&lt;/code&gt; is an interface implemented by a validation rule. A rule can be specific to a property of your custom type (is it &lt;code&gt;null&lt;/code&gt; ?), or not (for rules that involve many properties for instance). The description of a rule contains a message that can be displayed to the end user (like "This field is required"). &lt;/li&gt; &lt;/ul&gt; &lt;p&gt;The library predefines a set of useful rules (like &lt;code&gt;NotNullRule&lt;/code&gt;, &lt;code&gt;StringLengthRule&lt;/code&gt;, &lt;code&gt;RegexRule&lt;/code&gt;...). These rules can also be specified as attributes. And there is an adapter that allows to integrate the &lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/cc309509.aspx"&gt;Enterprise Library Validation Application Block&lt;/a&gt; in &lt;strong&gt;Data Rules&lt;/strong&gt;.&lt;/p&gt; &lt;p&gt;As previously stated, &lt;strong&gt;Data Rules&lt;/strong&gt; is used by &lt;strong&gt;Data Access&lt;/strong&gt; to add validation capability to our business objects. It is also used by &lt;strong&gt;Data Activities&lt;/strong&gt; to enforce business rules in our data flow.&lt;/p&gt; &lt;p&gt;In the future, we can imagine to create our &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Domain_Specific_Language"&gt;DSL&lt;/a&gt; to design our rules, and why not store some of them in a configuration file.&lt;/p&gt; &lt;p&gt;Next time, I will try to summarize the vast subject of &lt;strong&gt;Data Access&lt;/strong&gt;.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/noury/salamanca?a=R1WYLgJP"&gt;&lt;img src="http://feeds.feedburner.com/~f/noury/salamanca?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/noury/salamanca/~4/7PYkRvkNOkc" height="1" width="1"/&gt;</description>
         <guid isPermaLink="false">urn:md5:218b2d6f78fcf49321b4aab0b334ff9e</guid>
         <pubDate>Tue, 26 Aug 2008 06:27:00 -0700</pubDate>
      <feedburner:origLink>http://salamanca.nourysolutions.com/road/index.php?post/2008/08/26/Inside-the-libraries-I-%3A-Data-Rules</feedburner:origLink></item>
      <item>
         <title>Visiting Salamanca [The road to Salamanca]</title>
         <link>http://feedproxy.google.com/~r/noury/salamanca/~3/Eb9Md_GT1ak/index.php</link>
         <description>&lt;p&gt;Fundamentally, Salamanca is designed around three sets of libraries :&lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/public/wlw/2f9d465189b6_1075A/Architecture.png"&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px;" height="250" alt="Architecture" src="http://salamanca.nourysolutions.com/road/public/wlw/2f9d465189b6_1075A/Architecture_thumb.png" width="260" align="right" border="0"/&gt;&lt;/a&gt; &lt;/p&gt; &lt;ol&gt; &lt;li&gt;&lt;strong&gt;Data Access&lt;/strong&gt; is the easiest to explain in a few words : think of it as (yet) an (other) &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Object-relational_mapping"&gt;Object-Relational Mapping&lt;/a&gt; (ORM) library. Why another ? We believe that there is not nor will ever be a perfect solution for this problem ; call us "&lt;a rel="nofollow" target="_blank" href="http://blogs.tedneward.com/2006/06/26/The+Vietnam+Of+Computer+Science.aspx"&gt;ORM limitations acceptors&lt;/a&gt;". Our belief is that an ORM solution has to be designed to fulfill a specific set of issues under a specific set of constraints (which definitely sounds like &lt;a rel="nofollow" target="_blank" href="http://www.softwareproductlines.com/"&gt;a product line&lt;/a&gt; to me). After all, if you want to go &lt;a rel="nofollow" target="_blank" href="http://www.paulstovell.com/blog/orm-its-time-to-do-some-real-work"&gt;around and around in circles without going anywhere&lt;/a&gt;, you are more likely to win the race with a formula one car. If you want to drive home, you will be better off with a standard commercial car : it has been designed for average roads, and priced accordingly. This library will help us handle business specific data in a &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Data_access_layer"&gt;Data Access Layer&lt;/a&gt; (DAL). &lt;/li&gt; &lt;li&gt;&lt;strong&gt;Data Activities&lt;/strong&gt; is a library that helps define the business data lifecycle into a specific layer. The latter is a &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Finite_state_machine"&gt;state machine&lt;/a&gt; which lies at the core of our architecture : it manages business data, drives the HMI, and as such acts as a perfect (?) &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Separation_of_concerns"&gt;separator of concerns&lt;/a&gt;. &lt;/li&gt; &lt;li&gt;&lt;strong&gt;Data Rules&lt;/strong&gt; is a validation framework. It will be used to implement our business rules in our activities transitions and our data. &lt;/li&gt; &lt;/ol&gt; &lt;p&gt;These libraries represent the fundamental abstractions around which our applications will be built. Best practices can be documented around their use, that can be written with our own &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Domain-specific_programming_language"&gt;Domain Specific Languages&lt;/a&gt; (DSLs). We have defined two DSLs so far :&lt;/p&gt; &lt;ol&gt; &lt;li&gt;&lt;strong&gt;SDML&lt;/strong&gt; (Salamanca Domain Modeling Language) : this language will help us structure our data in order to implement our DAL. But more than that, it will help us create reusable states for our activities, or reusable component for data edition (&lt;a rel="nofollow" target="_blank" href="http://msdn.microsoft.com/en-us/library/system.windows.forms.usercontrol.aspx"&gt;user controls&lt;/a&gt; in Windows Forms for instance). Its representation is very close to a &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Class_diagram"&gt;UML Class Diagram&lt;/a&gt;. &lt;/li&gt; &lt;li&gt;&lt;strong&gt;SAML&lt;/strong&gt; (Salamanca Activities Modeling Language) : this will help us define our activities. Activities reuse concepts defined in a SDML model. Its representation is inspired by the &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/BPMN"&gt;Business Process Modeling Notation&lt;/a&gt; (BPMN). &lt;/li&gt; &lt;/ol&gt; &lt;p&gt;Implementing an application with our libraries once the models are properly defined should be quite straightforward. So straightforward that we will be gain a lot by creating two tools that will greatly enhance our productivity :&lt;/p&gt; &lt;ol&gt; &lt;li&gt;A &lt;strong&gt;Modeler &lt;/strong&gt;: a graphical tool that will help us visually model our application and serialize it in SDML and SAML formats. &lt;/li&gt; &lt;li&gt;A &lt;strong&gt;Generator&lt;/strong&gt; : a tool that will implement our best practices and take our model as input, in SDML and SAML formats, and generate our C# code. Though it is imaginable to generate a whole functioning application, the developer will have the possibility to customize the generated code to make it more usable, or implement parts that could not be modeled. Usually, developers will ... develop a usable HMI on top of the generated code. &lt;/li&gt; &lt;/ol&gt; &lt;p&gt;As for now, the libraries are quite in an advanced state, the DSLs definition is in progress and the tools are part of our to do list.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/noury/salamanca?a=B0fKlZNi"&gt;&lt;img src="http://feeds.feedburner.com/~f/noury/salamanca?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/noury/salamanca/~4/Eb9Md_GT1ak" height="1" width="1"/&gt;</description>
         <guid isPermaLink="false">urn:md5:a15d4838b2fd5547ef7ad5ee2766fa9c</guid>
         <pubDate>Wed, 20 Aug 2008 08:31:00 -0700</pubDate>
      <feedburner:origLink>http://salamanca.nourysolutions.com/road/index.php?post/2008/08/20/Visiting-Salamanca</feedburner:origLink></item>
      <item>
         <title>Getting on the tracks [The road to Salamanca]</title>
         <link>http://feedproxy.google.com/~r/noury/salamanca/~3/UEX9fC3jw4U/index.php</link>
         <description>&lt;p&gt;So, if Salamanca &lt;a rel="nofollow" target="_blank" href="http://salamanca.nourysolutions.com/road/index.php?post/2008/07/29/4-a-first-glimpse-of-salamanca"&gt;is a software factory&lt;/a&gt;, what is the product line associated with it? The answer is simple : business applications.&lt;/p&gt;
&lt;p&gt;Alright, I think I can be more specific than this. In our context&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;a business application is a software that handles business specific data while implementing parts of business specific processes (which we will call activities) and enforcing business specific rules.&lt;/p&gt;
&lt;/blockquote&gt; &lt;p&gt;There are a few things we can infer from this definition :&lt;a rel="nofollow" target="_blank" href="http://www.imdb.com/title/tt0030252/"&gt;&lt;img style="border:0 none;margin:10px 0 10px 10px;" alt="Hotel Du Nord" src="http://salamanca.nourysolutions.com/road/public/wlw/Gettingonthetracks_1046C/hoteldunord.jpg" align="right" border="0" width="186" height="244"/&gt;&lt;/a&gt; &lt;/p&gt;
&lt;ul&gt; &lt;li&gt;to handle business specific data, we will deal with a database backend ; more often than not a real &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Relational_database_management_system"&gt;RDBMS&lt;/a&gt; like Sql Server or Oracle, but also possibly a web service or even a simple file (XML, CSV...). For instance, a hotel room booking application would be built upon a proper database, with structured data such as the rooms, their rates, their vacancies...&lt;/li&gt;
&lt;li&gt;the data lifecycle has to be integrated into well defined activities. At all times, from the state that we know the system is in, there are only a few well known actions that can be taken. Without this concept, an application like Excel would fit into our definition. For instance, a basic activity involving a hotel room and a customer would be : book, then check in, then check out.&lt;/li&gt;
&lt;li&gt;rules must be enforced at all times. Some of them are specific only to some piece of data, some others can be also specific to&amp;nbsp; a specific activity. For instance, a booking date in the system cannot be anterior to the date the hotel was built : this is a general rule. But for new reservations, the same booking date has to be in the future : this is a rule that applies to the same data, but that is specific to the activity called "book a room in the hotel".&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Our vision with Salamanca is to be able to design a business application in terms of data, activities and rules and be able to generate a complete and functional (if not user-friendly) software.&lt;/p&gt;
&lt;p&gt;But we also want to leave the developer at the center of our factory. There are many libraries and tools (think of code generators) out there in the field that work very well, provided you respect their predicates (data structure, software architecture...). But in real life, you almost always have to adapt your code to business specific conditions : already existing databases, specific procedures, architecture... Applications built with Salamanca must be open to adaptations by developers. Think only of the &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/User_interface"&gt;HMI&lt;/a&gt; : would you use a software exclusively designed by automated tools ? I know I would not.&lt;/p&gt;
&lt;p&gt;Through the concept of activities, which I will elaborate on more in another post, we also created a new way to clearly separate the concerns of presentation from the core application, which we found to be very promising so far. Once created the core of your business application (data handling, activities and rules), you could develop your HMI layer in any (.NET related) technology you like : &lt;a rel="nofollow" target="_blank" href="http://windowsclient.net/"&gt;Windows Forms&lt;/a&gt;, &lt;a rel="nofollow" target="_blank" href="http://windowsclient.net/"&gt;Windows Presentation Foundation&lt;/a&gt;, &lt;a rel="nofollow" target="_blank" href="http://www.asp.net/"&gt;ASP .NET&lt;/a&gt;... Or in all of them. Or, maybe wiser, you could develop part of your application as an ASP .NET application, and part of it as a Windows Forms application (on &lt;a rel="nofollow" target="_blank" href="http://www.microsoft.com/windowsxp/tabletpc/default.mspx"&gt;Windows TabletPC&lt;/a&gt; or &lt;a rel="nofollow" target="_blank" href="http://www.microsoft.com/windowsmobile/en-us/default.mspx"&gt;Windows Mobile&lt;/a&gt; for instance), while reusing the same set of core libraries with your business specific data, activities and rules.&lt;/p&gt;
&lt;p&gt;I really hope I made you want to know more about it. In future posts, I will talk about our libraries, our models and our tools. Stay tuned !&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/noury/salamanca?a=rtd1RFGi"&gt;&lt;img src="http://feeds.feedburner.com/~f/noury/salamanca?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/noury/salamanca/~4/UEX9fC3jw4U" height="1" width="1"/&gt;</description>
         <guid isPermaLink="false">urn:md5:8174afdcbce0e2971ce710fd5edac0b2</guid>
         <pubDate>Mon, 04 Aug 2008 11:35:00 -0700</pubDate>
      <feedburner:origLink>http://salamanca.nourysolutions.com/road/index.php?post/2008/08/04/6-getting-on-the-tracks</feedburner:origLink></item>
      <item>
         <title>A first glimpse of Salamanca [The road to Salamanca]</title>
         <link>http://feedproxy.google.com/~r/noury/salamanca/~3/R6u6SEvUE0s/index.php</link>
         <description>&lt;p&gt;Welcome to the team blog of Salamanca!&lt;/p&gt; &lt;p&gt;Salamanca is a business applications &lt;a rel="nofollow" target="_blank" href="http://www.softwarefactories.com/"&gt;software factory&lt;/a&gt;. The goal is to enable developers to create business oriented applications in a more efficient, reliable and coherent way through a specific set of libraries, models and tools. To make it short, we define a business application as a software that handles business specific data (you can think of it as a low scale enterprise application). Salamanca is designed to help managing the whole life cycle of business data : storage, display, edition, validation, processing... More on that later.&lt;/p&gt; &lt;p&gt;Salamanca is an open-source project, hosted on &lt;a rel="nofollow" target="_blank" href="http://www.codeplex.com/salamanca"&gt;CodePlex&lt;/a&gt;. Its name is a reference to &lt;a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/The_Salamanca"&gt;The Salamanca&lt;/a&gt;, the first commercially successful locomotive built in 1812.&lt;/p&gt; &lt;p&gt;We are delighted to have you on board, and we hope we will have a pleasant trip together ;-)&lt;/p&gt; &lt;div align="center"&gt;&lt;iframe class="embeddedvideo" src="http://www.youtube.com/v/Sp5pQV7DLKk&amp;hl=en&amp;fs=1&amp;rel=0" type="application/x-shockwave-flash" width="425" height="344"&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/noury/salamanca?a=TQEMGcmQ"&gt;&lt;img src="http://feeds.feedburner.com/~f/noury/salamanca?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/noury/salamanca/~4/R6u6SEvUE0s" height="1" width="1"/&gt;</description>
         <guid isPermaLink="false">urn:md5:e8c32f1ab920457691bf8fb1e8f94f10</guid>
         <pubDate>Tue, 29 Jul 2008 03:30:05 -0700</pubDate>
      <feedburner:origLink>http://salamanca.nourysolutions.com/road/index.php?post/2008/07/29/4-a-first-glimpse-of-salamanca</feedburner:origLink></item>
   </channel>
</rss><!-- fe3.pipes.re3.yahoo.com uncompressed Wed Nov  4 20:50:43 PST 2009 -->
