Hello World entreprise version

By Pyxis

Basic Hello World

The best way to learn a new language is still writing the typical Hello World application. I can not count the number of times I started a new project with this simple application. For example here is the simplest Hello World application that can be done in C#:

After starting Visual Studio and done File → New → Project → Windows Console Application, the remaining thing to do is to complete the Main method.

[csharp title=”Program.cs”]
using System;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
[/csharp]

hello-worldBut this minimalist version of Hello World is no longer sufficient today. See what is missing in this example to make it more complete.

Prerequisites

 

Here’s what you’ll need to run this tutorial:

  • Visual Studio (Cummunity or Professional)
  • A Visual Studio Online accounte

Le code n’est pas tout

While it is interesting to see this code compiles and runs on our computer, this is only the beginning of the story. Writing and running code on its own development environment is easy. All development tools offer a range of features to facilitate this aspect of software development. The complications come later, often at deployment but sometimes earlier than that.

Let’s look at the full application development cycle.

application-cycleNotre exemple Hello World ne concerne que la partie développement de ce processus, mais le plus souvent, les problèmes complexes surviennent au cours des autres étapes. Il est donc impératif de bonifier notre Hello World avec ces étapes.

Pour l’instant, laissons de côté les étapes préalables au développement.

Du code qui sent mauvais

Dans cet exemple de code, si simple soit-il, il y a déjà du code qui sent mauvais. Ce qu’on appelle communément des Code Smells. Voyez-vous ce qui ne va pas ? Comment pouvons-nous tester ce code ?

Vers une version entreprise du Hello World

Pour moi, une première étape serait de sortir la logique d’affaires du Main. Dans ce cas-ci, c’est assez simple :

[csharp title=”Program.cs”]
using System;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
var greeter = new Greeter();
greeter.Hello("World");
}
}
}[/csharp]

[csharp title=”Greeter.cs”]
using System;
namespace HelloWorld
{
public class Greeter
{
public void Hello(string name)
{
Console.WriteLine($"Hello {name}!");
}
}
}[/csharp]

Ce changement ne semble pas significatif mais il nous permet d’avancer vers l’ajout de tests. En plaçant le code dans une classe et une méthode non statique, nous pourront injecter des dépendances pour les tests. Quel est la dépendance à remplacer dans la classe Greeter?

Pour l’instant, la classe Geeter écrit directement dans la console. Bien qu’il soit possible d’intercepter la sortie vers la console, ce n’est pas idéal pour les tests. Allons-y plutôt avec une injection de dépendance. Définissons l’interface à injecter.

[csharp title=”IWriter.cs”]
namespace HelloWorld
{
public interface IReceiver
{
void Say(string text);
}
}[/csharp]

Ensuite, il faut créer une implémentation de cette interface :

[csharp title=”ConsoleWriter.cs”]
using System;
namespace HelloWorld
{
class ConsoleReceiver : IReceiver
{
public void Say(string text)
{
Console.WriteLine(text);
}
}
}[/csharp]

On peut maintenant remplacer l’implémentation dans la classe Greeter :

[csharp title=”Greeter.cs”]
namespace HelloWorld
{
public class Greeter
{
private readonly IReceiver _receiver;
public Greeter(IReceiver receiver)
{
_receiver = receiver;
}
public void Hello(string name)
{
_receiver.Say($"Hello {name}!");
}
}
}[/csharp]

Une chose à noter dans le design orienté objet : il faut bien identifier le type d’objet et sa relation avec les autres. Dans le cas présent, la classe Greeter est clairement une classe de traitement dont la responsabilité est de « saluer ». Mais la classe Greeter ne peux fonctionner toute seule. Elle ne peut pas saluer dans le vide. Il lui faut un récepteur du message. On doit donc lui ajouter cette dépendance pour que le système fonctionne.

Pour garder la fonctionnalité d’origine, on lui injecte une instance de ConsoleReceiver :

[csharp title=”Program.cs”]
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
var greeter = new Greeter(new ConsoleReceiver());
greeter.Hello("World");
}
}
}[/csharp]

Tout est maintenant en place pour faire notre premier test. Dans Visual Studio on choisit File à Add New Project… à Test à Unit Test Project et on nomme le projet « HelloWorld.Tests ».

Pour tester la classe Greeter, il faut se créer un Mock. Un Mock est un objet qui peut prendre la place d’un autre et grâce auquel on peut vérifier le comportement attendu. Donc voici le Mock de IReceiver :

[csharp title=”ReceiverMock.cs”]
namespace HelloWorld.Tests
{
public class ReceiverMock : IReceiver
{
private string _text;
public void Say(string text)
{
_text = text;
}
public string Text
{
get { return _text; }
}
}
}[/csharp]

On peut maintenant écrire le test :

[csharp title=”GreeterTests.cs”]
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace HelloWorld.Tests
{
[TestClass]
public class GreeterTests
{
[TestMethod]
public void Reveiver_should_be_greeted()
{
var receiver = new ReceiverMock();
var greeter = new Greeter(receiver);
greeter.Hello("World");
Assert.AreEqual("Hello World!" + Environment.NewLine, receiver.Text);
}
}
}[/csharp]

Bien que notre Mock remplisse la tâche, ce n’est pas ce qu’on utilise habituellement. Il serait trop coûteux d’écrire tous les mocks nécessaires pour tous les scénarios possibles. On utilise habituellement des librairies. Pour cet exemple, nous utiliserons Moq. Pour ajouter une librairie à notre projet de test, la façon conseillée est d’utiliser Nuget. Nuget est un gestionnaire de dépendances qui utilise un fichier pour conserver la liste des dépendances ajoutées. Ce fichier servira par la suite à réinstaller ces mêmes dépendances lorsque nous compilerons le code sur une autre machine.

Dans Visual Studio, avec un clic droit sur le projet de test, sélectionnez Manage nuget packages… à Browse à Search : moq à Moq by Daniel Cazzulino à Install. Vous remarquerez que le fichier package.config a été ajouté.

[xml title=”Package.config”]
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Castle.Core" version="3.3.3" targetFramework="net461" />
<package id="Moq" version="4.5.21" targetFramework="net461" />
</packages>[/xml]

Maintenant nous pouvons supprimer le fichier ReceiverMock.cs et réécrire le test comme suit :

[csharp title=”GreeterTests.cs”]
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
namespace HelloWorld.Tests
{
[TestClass]
public class GreeterTests
{
[TestMethod]
public void Reveiver_should_be_greeted()
{
var mock = new Mock&amp;amp;amp;lt;IReceiver&amp;amp;amp;gt;();
var greeter = new Greeter(mock.Object);
greeter.Hello("World");
mock.Verify(m =&amp;amp;amp;gt; m.Say("Hello World!"), Times.Once);
}
}
}[/csharp]

Maintenant que nous avons un projet complet avec tests (au moins un), la prochaine étape est d’ajouter ce projet à un système de contrôle de version. Nous utiliserons Git. Avec Visual Studio 2015, il est très facile de créer son repo Git. En bas à droite de la fenêtre, sélectionnez Publish à Git. Cette opération va :

  • Créer un fichier .gitattributes pour modifier la configuration de git;
  • Créer un fichier .gitignore pour exclure tous les fichiers indésirables;
  • Ajouter ces deux fichiers dans un commit;
  • Ajouter tous les fichiers du projet dans un autre commit.
  • Ensuite, pour rendre ces changements disponibles aux autres développeurs et surtout au serveur de build (à venir), il faut publier le repo. Visual Studio propose de publier sur Visual Studio Team Services ou sur GitHub. Nous utiliserons Visual Studio Team Services pour l’instant.

En cliquant sur « Publish Git Repo », Visual Studio prend en charge la création d’un repo sur Visual Studio Team Services, il pousse les changements et associe ce repo remote au repo local en tant que origin. Maintenant, si vous allez voir la section code du projet, vous devez voir votre code à jour sur le serveur TFS Online. On peut alors définir un build. Suivez les instructions suivantes:

Une fois le build créé, on peut demander un nouveau build en cliquant sur Queue new build…

Si tout s’est bien passé, vous devriez avoir un build terminé avec succès. Vous pouvez explorer les différents onglets du résultat de build pour voir des statistiques sur votre projet.

Conclusion

Faire un HelloWorld aujourd’hui demande de réfléchir à tout le processus du cycle de développement logiciel. Cet exemple simple illustre les différentes étapes à réaliser pour y arriver. Le plus important pour assurer la réussite d’un projet est de faire ces étapes dès que possible dans la réalisation du projet. Si elles sont bien intégrées au processus de développement vous réduirez les problèmes à long terme et vous éviterez plus facilement le fameux Works on my machine.

Other Stories You Might Be Interested In

Three tips for dealing with the IT labour shortage

If you’re reading this page, it’s probably because you too have been affected by the new labour shortage “pandemic” that began a few years ago and has been impacting large companies’ information technology recruitment efforts as they attempt to find qualified workers.   The labour shortage has hit the IT sector hard This new pandemic...

Did you know that your technology may be outdated?

Are you overwhelmed with internal requests? Is your IT support team overwhelmed? Are you still able to deliver to your customers? Are your employees frustrated?  Very often, these situations are related to tools that are no longer adequate or to aging technology that no longer meets the changing needs of the company. Eric De Carufel,...

Web development: Why Blazor is the ideal framework?

Blazor. In early November 2018, when it was still an experimental product, I was talking about Blazor at an event we had organized at our office. By the way, I had surprised many colleagues when I revealed at the end that my PowerPoint presentation had been prepared with Blazor. I followed the evolution of this...