Bonjour,
Je me suis au web depuis 2006, d'abord avec
ASP.NET classique jusqu'en 2012, comme je venais de monde winform et que j'étais sensibilisé aux approches MVC, j'utilisais une sorte de pattern MVP, où le code-behind de la page ne faisait rien à part déléguer au contrôleur.
Depuis 2012, j'ai basculé sur
ASP.NET MVC 3 Razor, qui me semble beaucoup mieux car il a l'avantage de gérer ce pattern MVC de façon native. Sur ce projet, nous utilisions NHibernate, et il y a des choses que je n'aimais pas, comme le fait d'utiliser directement les entités comme view model, ce qui amenait parfois des problèmes de performances (des actions JsonResult pour des callbacks AJAX qui se retrouvait à sérialiser toute la BD à cause d'une entité client qui est reliée à tout le monde, ou le fait que la vue Razor déclenchait beaucoup d'accès BD via le lazy loading, d'où un côté trompeur d'une action contrôleur qui répond rapidement alors qu'en fait il y a problème de perf cachée dans la vue razor associéé).
Je préférerais donc une architecture où les view models sont de simples "DTO"s, qui sont mappés depuis les entités via AutoMapper (ou un outil concurrent type Value Injector, qui a l'avantage d'être plus personnalisable).
Depuis Octobre, je dois bosser sur une nouvelle appli, mais comme mon projet prend du retard à démarrer, j'ai du temps pour réfléchir sur une nouvelle archi... suite à
ALT.NET j'ai pas mal entendu parler de CQRS, et le blog Los Techies de Jeremy Bogard, l'auteur de AutoMapper en parle aussi, dans un de ses posts il décrit une architecture avec des contrôleurs "anémiques" qui se contentent de déléguer leur travail à des Query ou des Commandes (par contre contrairement aux archi CQRQ classiques, on ne met pas en place de choses compliquées comme l'event sourcing ou l'asynchronisme). J'avais commence à mettre une place une telle architecture sur mon POC, avec un bus en mémoire (plus simple que Rabbit MQ ou NServiceBus), qui me semblait d'ailleurs assez proche de ce qu'a présenté Thomas Jaskula à la dernière conf DDD avec Vaugh Vernon. En même temps, je réfléchissais au mapping avec AutoMapper, j'ai voulu mette en place un système efficace pour les recherches où il y a souvent des tris (ORDER BY) des filtres (WHERE critere = ) et des projections (SELECT x,y,z), et avoir un système pour que la couche données puisse tout faire en SQL, tout en gardant une couche présentation propre qui ne travaille qu'avec les DTOs et ne connait même pas l'existence des entités sous-jascentes (ainsi on est pas dépendant de NHibernate, que l'on pourrait remplacer par Entity Framework voir MongoDb, RavenDB de l'event sourcing avec des vues dénormalisées...).
J'ai un code prototype qui fait cela, avec un pattern Specification (pattern du bouquin DDD) et un visiteur qui traduit les Specification<Dto> en Specification<Entité> en se basant sur les correspondances enregistrées dans AutoMapper (qui lui-même s'auto-configure d'après des conventions de nommages). J'ai pas eu le temps de le finir, mais le but était de la brancher sur la grille Kendo, afin d'avoir une grille qui n'est bindée que sur des DTOs mais qui travaille de façon efficace puisque toute les opérations (tri, filtrage...) seraient réalisée en SQL et non en mémoire via Linq-To-Object.
Dans le même temps, j'avais pas mal entendu parler des frameworks javascript, KnockOut d'abord, mais on m'a aussi dit le plus grand bien de Angular JS, plus adapté au SPA. J'ai commencé à creuser cette piste, et j'ai alors découvert qu'une grande partie de ce que fait MVC ne sert plus à rien aujourd'hui : Razor traduit des ViewModel en HTML, mais ça de nos jour Javascript sait faire aussi. Avec Angular, on a aussi du routage comme dans Razor (avec NG-Route) voir potentiellement mieux avec UI-Router. Enfin, le bundling d'
ASP.NET est sympa (notamment avec les modules nuget qui permettent de gérer les transformations LESS, SASS, Coffeescript...) mais avec des tâches GRUNT, on pourrait sans doutes faire cela aussi, à la compilation en plus.
Bref, je m'oriente vers une solution où la couche présentation est entièrement déportée sur le client via une SPA, le contenu web deviendrait purement statique (on pourrait le distribuer via un CDN), avec éventuellement des tâches de bundling, de minification, réalisée à la compilation (Grunt et Node.JS ?). Il y a quand même une limite : javascript est non typé, et je viens du C# donc je n'aime pas. C'est un langage assez pourri d'ailleurs (lire Javascript The Good Part de Douglas Crawford, pour voir tout les pièges de ce langage, et notamment le fait que c'est le seul langage ou indenter à la Kernigan et Ritchie, plutôt qu'en ANSI peut faire planter l'application). Donc j'ai cherché à améliorer cela, j'ai vu que pas mal de gens compensait le côté non sûr du langage par une rigueur lors du dévleoppmeent avec du TDD, des outils tels que Karma (le NCrunch du Javascript), j'ai regardé du côté de DART, et puis finalement opté pour TypeScript, parce que je suis Microsoft d'une part et qu'il me semble avoir une meilleur interopabilité avec le code Javascript existant
Depuis 2 semaines que développent en TypeScript avec Angular, je me rend compte petit à petit de ce que disait Rui, pouvoir avoir un feedback rapide parce qu'il n y a pas de compilation c'est important, et finalement Visual Studio n'est peut-être pas l'outil le plus adapté. A terme, quand j'aurais le temps, j'essairais de dégager VS et de le remplacer par WebStorm de JetBrain (je suis fan de Resharper donc j'ai un à priori positif), peut -être aussi dégager mes scripts de build MSBUILD en XML (qui ont toujours été l'horreur à débugger), et les remplacer par des tâches GRUNT pour pouvoir utiliser tout les outils de Node.JS (j'utilise Require.JS donc il me faudrait un bundler, concateneur de fichiers).
Pour la couche serveur, il s'agirait d'une simple API Rest, je pense utiliser la WebAPI. Je ne vois pas trop l'intérêt d'utiliser les outils alternatifs que préconise Rui (c'est à peu près le seul truc où je ne suis pas d'accord avec lui :) ), comme ServiceStack ou Nancy. Autant WCF était une usine à gaz, plutôt destinée à SOAP et mal adapté au REST, et là ces outils se justifiaient, autant depuis la WebAPI je ne suis pas sûr qu'ils apportent quelque chose de suffisant pour justifier l'usage d'une techno "exotique" et donc moins connue, moins supportée.
Pour ma couche Rest, je pense utiliser une approche à la CQRS, avec une API sous forme de commandes et de requête. C'est là que mes lectures sur CQRS peuvent m'être utile, car certains nomment cette architecture à base de web service REST, WOA (Web Oriented Architecture) pour dire que c'est la suite de SOA. Et un des inconvénient, c'est que REST contrairement à SOAP ne gère pas les transactions atomiques. Donc si l'on expose son API sous forme CRUD, on risque les problèmes classiques (du type je débite un compte, mon appli plante et l'autre compte n'a pas encore été crédité, de l'argent à disparu dans la nature). C'est la raison pour laquelle je pense que les outils type WCF Data Services, qui exposent automatiquement une BD via entity framework en web services, me semblent buggé. Avec une approche CQRS, chaque commande représente une transaction métier (ex : Commande = Transfert d'argent du compte A vers B), donc pas de problème "d' acidité".
Bon enfin, en bref, j'ai beaucoup d'idée mais ça en reste en stade du POC (voir dans ma tête pour l'instant)..
Stéphane JUTIN