Limiter son TAF avec les Design Patterns

Au cours d’un dojo improvisé nous nous sommes intéressés à modifier le programme suivant pour limiter le nombre de tâches en cours en utilisant le plus de design patterns possibles.

Le programme d’origine affiche le nombre de travaux en cours dans la sortie console. Basé sur les timers systèmes, toutes les secondes une nouvelle tâche est lancée. Chaque tâche durant 5 secondes, il y a augmentation du nombre de tâches en cours jusqu’à stabilisation du processus.

class Program
{
    static void Main(string[] args)
    {
        int workInProgress = 0;
        var workGenerator = new System.Timers.Timer();

        workGenerator.Interval = 1000;
        workGenerator.Elapsed += (o, s) =>
            {
                Console.WriteLine("begin work {0}", ++workInProgress);
                System.Threading.Thread.Sleep(5000);
                Console.WriteLine("end work {0}", --workInProgress);
            };

        workGenerator.Start();

        Console.WriteLine("Press any key to terminate");
        Console.ReadLine();

        workGenerator.Stop();
    }
}


Voici une des solutions abordée.

1 – Créer une interface IWorkGenerator pour rendre le programme indépendant de la techno utilisée

public interface IWorkGenerator
{
     double Interval { get; set; }
     event EventHandler Elapsed;
     void Start();
     void Stop();
}

2 – Utiliser le pattern adapter pour adapter le System.Timer à cette nouvelle interface

class SystemTimerAdapter : IWorkGenerator
{
    private System.Timers.Timer timer;

    private void OnTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
    	if (this.Elapsed != null)
    	{
    	this.Elapsed(this, EventArgs.Empty);
    	}
    }

    public event EventHandler Elapsed;

    public double Interval
    {
    	get
    	{
    	return this.timer.Interval;
    	}
    	set
    	{
    	this.timer.Interval = value;
    	}
    }

    public void Start()
    {
    	this.timer.Start();
    }

    public void Stop()
    {
    	this.timer.Stop();
    }

    public SystemTimerAdapter(System.Timers.Timer timer)
    {
    	this.timer = timer;
    	this.timer.Elapsed += OnTimerElapsed;
    }

}

3 – Limiter le nombre de tâches en cours par l’utilisation du pattern decorator

class WorkLimiterDecorator : IWorkGenerator
{
    private IWorkGenerator decorated;
    private int workInProgress;

    private void OnDecoratedElapsed(object sender, EventArgs e)
    {
    	if (this.workInProgress++ < WorkLimit)
    	{
    	if (this.Elapsed != null)
    		this.Elapsed(this, e);
    	}
    	this.workInProgress--;
    }

    public event EventHandler Elapsed;

    public int WorkLimit { get; set; }

    public double Interval
    {
    	get { return this.decorated.Interval; }
    	set { this.decorated.Interval = value; }
    }

    public void Start()
    {
    	this.decorated.Start();
    }

    public void Stop()
    {
    	this.decorated.Stop();
    }

    public WorkLimiterDecorator(IWorkGenerator decorated)
    {
    	this.decorated = decorated;
    	this.decorated.Elapsed += OnDecoratedElapsed;
    	this.workInProgress = 0;
    }
}


Avantages et inconvénients de cette architecture
Avantages

  • L’interface rend le programme indépendant de la rélisation du générateur de tâche
  • Le pattern adapter peut s’appliquer à divers implémentation (thread, événement,…)
  • Le décorateur est indépendant de la rélisation. On limite vraiment le TAF car peut appliquer la limitation à n’importe quelle implémentation de IWorkGenerator :)

Incovénients

  • On réimplémente à chaque fois l’interface. Sur une interface compliquée celà peut être fastidieux.

Remarque
La classe WorkLimiterDecorator doit être thread safe. Une amélioration du code consiste à créer deux méthodes atomiques IncrementAndTest et Decrement.

This entry was posted in architecture, programmation objet and tagged , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>