[{"data":1,"prerenderedAt":697},["ShallowReactive",2],{"authors":3,"article-2022-03-10-introduction-du-bus-dentreprise-chez-indy":331},[4,23,35,48,61,73,85,98,111,124,136,148,161,173,185,197,209,221,233,245,258,270,282,295,307,319],{"id":5,"title":6,"body":7,"description":11,"extension":14,"meta":15,"name":16,"navigation":17,"path":18,"readingTime":19,"seo":20,"stem":21,"__hash__":22},"authors\u002Fauthors\u002Falexandre-guillon.md","Software Engineer",{"type":8,"value":9,"toc":10},"minimark",[],{"title":11,"searchDepth":12,"depth":12,"links":13},"",2,[],"md",{},"Alexandre Guillon",true,"\u002Fauthors\u002Falexandre-guillon",1,{"title":6,"description":11},"authors\u002Falexandre-guillon","4tf48mjyjFNqItOHaulICbrjeCyMag1o6801uHeTz98",{"id":24,"title":6,"body":25,"description":11,"extension":14,"meta":29,"name":30,"navigation":17,"path":31,"readingTime":19,"seo":32,"stem":33,"__hash__":34},"authors\u002Fauthors\u002Falexis-ablain.md",{"type":8,"value":26,"toc":27},[],{"title":11,"searchDepth":12,"depth":12,"links":28},[],{},"Alexis Ablain","\u002Fauthors\u002Falexis-ablain",{"title":6,"description":11},"authors\u002Falexis-ablain","_SIAtB7f-39e5t3GiJof81NP47s6MGo2n4gaHkTy1uQ",{"id":36,"title":37,"body":38,"description":11,"extension":14,"meta":42,"name":43,"navigation":17,"path":44,"readingTime":19,"seo":45,"stem":46,"__hash__":47},"authors\u002Fauthors\u002Faxel-shaita.md","Engineering Manager",{"type":8,"value":39,"toc":40},[],{"title":11,"searchDepth":12,"depth":12,"links":41},[],{},"Axel Shaïta","\u002Fauthors\u002Faxel-shaita",{"title":37,"description":11},"authors\u002Faxel-shaita","fK0argUhsBkWLjpTAhY13oYLVzQthcEYkCEdtHWmIgE",{"id":49,"title":50,"body":51,"description":11,"extension":14,"meta":55,"name":56,"navigation":17,"path":57,"readingTime":19,"seo":58,"stem":59,"__hash__":60},"authors\u002Fauthors\u002Fbaptiste-faure.md","Head of Talent Acquisition",{"type":8,"value":52,"toc":53},[],{"title":11,"searchDepth":12,"depth":12,"links":54},[],{},"Baptiste Faure","\u002Fauthors\u002Fbaptiste-faure",{"title":50,"description":11},"authors\u002Fbaptiste-faure","ELisToYtcgHmgdVWZkCclTPV6exZtfyXqhpx1jjbJHs",{"id":62,"title":6,"body":63,"description":11,"extension":14,"meta":67,"name":68,"navigation":17,"path":69,"readingTime":19,"seo":70,"stem":71,"__hash__":72},"authors\u002Fauthors\u002Fbenjamin-bouillot.md",{"type":8,"value":64,"toc":65},[],{"title":11,"searchDepth":12,"depth":12,"links":66},[],{},"Benjamin Bouillot","\u002Fauthors\u002Fbenjamin-bouillot",{"title":6,"description":11},"authors\u002Fbenjamin-bouillot","tbhCFZyfTt7ZM5b5YgqQ2nhgnSTl8BweaQQryc87fHo",{"id":74,"title":37,"body":75,"description":11,"extension":14,"meta":79,"name":80,"navigation":17,"path":81,"readingTime":19,"seo":82,"stem":83,"__hash__":84},"authors\u002Fauthors\u002Fcedric-nicoloso.md",{"type":8,"value":76,"toc":77},[],{"title":11,"searchDepth":12,"depth":12,"links":78},[],{},"Cédric Nicoloso","\u002Fauthors\u002Fcedric-nicoloso",{"title":37,"description":11},"authors\u002Fcedric-nicoloso","ibSoh4VZYiWYTuLOnZTedaAfcnvet1Q9H7ogW0LgorY",{"id":86,"title":87,"body":88,"description":11,"extension":14,"meta":92,"name":93,"navigation":17,"path":94,"readingTime":19,"seo":95,"stem":96,"__hash__":97},"authors\u002Fauthors\u002Fdavid-touzet.md","Staff Engineer",{"type":8,"value":89,"toc":90},[],{"title":11,"searchDepth":12,"depth":12,"links":91},[],{},"David Touzet","\u002Fauthors\u002Fdavid-touzet",{"title":87,"description":11},"authors\u002Fdavid-touzet","dHWwnQxb1Ubt-WwXWEODGEo9AFoq1cJUhfg3kdnYSBM",{"id":99,"title":100,"body":101,"description":11,"extension":14,"meta":105,"name":106,"navigation":17,"path":107,"readingTime":19,"seo":108,"stem":109,"__hash__":110},"authors\u002Fauthors\u002Feloise-chizat.md","Data Engineer",{"type":8,"value":102,"toc":103},[],{"title":11,"searchDepth":12,"depth":12,"links":104},[],{},"Eloïse Chizat","\u002Fauthors\u002Feloise-chizat",{"title":100,"description":11},"authors\u002Feloise-chizat","Utd72Vm9qT4hh2ZbFi6a2_nXw5Wb494Ed_HL1ra5yw8",{"id":112,"title":113,"body":114,"description":11,"extension":14,"meta":118,"name":119,"navigation":17,"path":120,"readingTime":19,"seo":121,"stem":122,"__hash__":123},"authors\u002Fauthors\u002Femmanuel-auclair.md","Staff engineer",{"type":8,"value":115,"toc":116},[],{"title":11,"searchDepth":12,"depth":12,"links":117},[],{},"Emmanuel Auclair","\u002Fauthors\u002Femmanuel-auclair",{"title":113,"description":11},"authors\u002Femmanuel-auclair","MtsA8THNLEn0dTtYEIQaGwDuf7MjQL55IOeei5gugEg",{"id":125,"title":6,"body":126,"description":11,"extension":14,"meta":130,"name":131,"navigation":17,"path":132,"readingTime":19,"seo":133,"stem":134,"__hash__":135},"authors\u002Fauthors\u002Fhoreb-parraud.md",{"type":8,"value":127,"toc":128},[],{"title":11,"searchDepth":12,"depth":12,"links":129},[],{},"Horeb Parraud","\u002Fauthors\u002Fhoreb-parraud",{"title":6,"description":11},"authors\u002Fhoreb-parraud","ajjsnUX4ohZI-ghMdbb92q_taWDkKXVZSLZXoAeLQtg",{"id":137,"title":37,"body":138,"description":11,"extension":14,"meta":142,"name":143,"navigation":17,"path":144,"readingTime":19,"seo":145,"stem":146,"__hash__":147},"authors\u002Fauthors\u002Fhugo-contreras.md",{"type":8,"value":139,"toc":140},[],{"title":11,"searchDepth":12,"depth":12,"links":141},[],{},"Hugo Contreras","\u002Fauthors\u002Fhugo-contreras",{"title":37,"description":11},"authors\u002Fhugo-contreras","2nc3VMu9ASq9Z6Pwx2-7-Ye991Pww4p-UEDBQFfjF-Q",{"id":149,"title":150,"body":151,"description":11,"extension":14,"meta":155,"name":156,"navigation":17,"path":157,"readingTime":19,"seo":158,"stem":159,"__hash__":160},"authors\u002Fauthors\u002Fjulien-tassin.md","Head of Engineering",{"type":8,"value":152,"toc":153},[],{"title":11,"searchDepth":12,"depth":12,"links":154},[],{},"Julien Tassin","\u002Fauthors\u002Fjulien-tassin",{"title":150,"description":11},"authors\u002Fjulien-tassin","iUIHI7SITje38Jh9X9uvYs4-VsHx4eCdt6hAlyLFG_o",{"id":162,"title":6,"body":163,"description":11,"extension":14,"meta":167,"name":168,"navigation":17,"path":169,"readingTime":19,"seo":170,"stem":171,"__hash__":172},"authors\u002Fauthors\u002Flaurent-renard.md",{"type":8,"value":164,"toc":165},[],{"title":11,"searchDepth":12,"depth":12,"links":166},[],{},"Laurent Renard","\u002Fauthors\u002Flaurent-renard",{"title":6,"description":11},"authors\u002Flaurent-renard","5BP7Ed-pt1SQHjh0UJ1XUrlLTcdlFaDoKBCP4deHq8A",{"id":174,"title":6,"body":175,"description":11,"extension":14,"meta":179,"name":180,"navigation":17,"path":181,"readingTime":19,"seo":182,"stem":183,"__hash__":184},"authors\u002Fauthors\u002Fleo-martin.md",{"type":8,"value":176,"toc":177},[],{"title":11,"searchDepth":12,"depth":12,"links":178},[],{},"Léo Martin","\u002Fauthors\u002Fleo-martin",{"title":6,"description":11},"authors\u002Fleo-martin","eYxCHkRgbGDV7shKdTA9s7Tu0zGV4yDGFoKR5MHQntY",{"id":186,"title":6,"body":187,"description":11,"extension":14,"meta":191,"name":192,"navigation":17,"path":193,"readingTime":19,"seo":194,"stem":195,"__hash__":196},"authors\u002Fauthors\u002Floic-bousquet.md",{"type":8,"value":188,"toc":189},[],{"title":11,"searchDepth":12,"depth":12,"links":190},[],{},"Loïc Bousquet","\u002Fauthors\u002Floic-bousquet",{"title":6,"description":11},"authors\u002Floic-bousquet","ko12qZwiGL8XNjAoy9oWypPkIjr29Pbq7vhdtgldqeQ",{"id":198,"title":6,"body":199,"description":11,"extension":14,"meta":203,"name":204,"navigation":17,"path":205,"readingTime":19,"seo":206,"stem":207,"__hash__":208},"authors\u002Fauthors\u002Floic-poullain.md",{"type":8,"value":200,"toc":201},[],{"title":11,"searchDepth":12,"depth":12,"links":202},[],{},"Loïc Poullain","\u002Fauthors\u002Floic-poullain",{"title":6,"description":11},"authors\u002Floic-poullain","oRIyJhFRTqxy5dLCYQ2OnYZ1DB-gLDUM-85vTSYuTF0",{"id":210,"title":100,"body":211,"description":11,"extension":14,"meta":215,"name":216,"navigation":17,"path":217,"readingTime":19,"seo":218,"stem":219,"__hash__":220},"authors\u002Fauthors\u002Fmaud-lelu.md",{"type":8,"value":212,"toc":213},[],{"title":11,"searchDepth":12,"depth":12,"links":214},[],{},"Maud Lélu","\u002Fauthors\u002Fmaud-lelu",{"title":100,"description":11},"authors\u002Fmaud-lelu","MMbsCKuE41OMHusrl12FIEsI-Trx7l8Nn_ANhvj2_y4",{"id":222,"title":37,"body":223,"description":11,"extension":14,"meta":227,"name":228,"navigation":17,"path":229,"readingTime":19,"seo":230,"stem":231,"__hash__":232},"authors\u002Fauthors\u002Fnicolas-poirier.md",{"type":8,"value":224,"toc":225},[],{"title":11,"searchDepth":12,"depth":12,"links":226},[],{},"Nicolas Poirier","\u002Fauthors\u002Fnicolas-poirier",{"title":37,"description":11},"authors\u002Fnicolas-poirier","dXrJkYo8az4SN_D23aYc3fQ7z8s1dR2a0lt1ogjAjJs",{"id":234,"title":37,"body":235,"description":11,"extension":14,"meta":239,"name":240,"navigation":17,"path":241,"readingTime":19,"seo":242,"stem":243,"__hash__":244},"authors\u002Fauthors\u002Fraphael-sauget.md",{"type":8,"value":236,"toc":237},[],{"title":11,"searchDepth":12,"depth":12,"links":238},[],{},"Raphaël Sauget","\u002Fauthors\u002Fraphael-sauget",{"title":37,"description":11},"authors\u002Fraphael-sauget","Uri9bcq0QDuxRA0PbBoNtu7p_5L3dALu4kzcXVW0xyM",{"id":246,"title":247,"body":248,"description":11,"extension":14,"meta":252,"name":253,"navigation":17,"path":254,"readingTime":19,"seo":255,"stem":256,"__hash__":257},"authors\u002Fauthors\u002Fromain-koenig.md","Co-funder & Head of innovation",{"type":8,"value":249,"toc":250},[],{"title":11,"searchDepth":12,"depth":12,"links":251},[],{},"Romain Koenig","\u002Fauthors\u002Fromain-koenig",{"title":247,"description":11},"authors\u002Fromain-koenig","uyS8--eG2_ezyqRABcJnMJmQKKuSArhPWd14aUvFeEw",{"id":259,"title":37,"body":260,"description":11,"extension":14,"meta":264,"name":265,"navigation":17,"path":266,"readingTime":19,"seo":267,"stem":268,"__hash__":269},"authors\u002Fauthors\u002Fromaric-juniet.md",{"type":8,"value":261,"toc":262},[],{"title":11,"searchDepth":12,"depth":12,"links":263},[],{},"Romaric Juniet","\u002Fauthors\u002Fromaric-juniet",{"title":37,"description":11},"authors\u002Fromaric-juniet","4Zb2artgT-eo-PHLXi3xi4d5t7s6PfhUxeSfXIikSUY",{"id":271,"title":6,"body":272,"description":11,"extension":14,"meta":276,"name":277,"navigation":17,"path":278,"readingTime":19,"seo":279,"stem":280,"__hash__":281},"authors\u002Fauthors\u002Fstanyslas-bres.md",{"type":8,"value":273,"toc":274},[],{"title":11,"searchDepth":12,"depth":12,"links":275},[],{},"Stanyslas Bres","\u002Fauthors\u002Fstanyslas-bres",{"title":6,"description":11},"authors\u002Fstanyslas-bres","Xa0SahETuiN4q1jrmR2ych3moAqcZ2LbU7vSfEt2RuU",{"id":283,"title":284,"body":285,"description":11,"extension":14,"meta":289,"name":290,"navigation":17,"path":291,"readingTime":19,"seo":292,"stem":293,"__hash__":294},"authors\u002Fauthors\u002Ftalent-acquisition.md","Talent Acquisition",{"type":8,"value":286,"toc":287},[],{"title":11,"searchDepth":12,"depth":12,"links":288},[],{},"Équipe Talent Acquisition","\u002Fauthors\u002Ftalent-acquisition",{"description":11},"authors\u002Ftalent-acquisition","doDfE76txftQ4wIiKjJoDmSpyzSKk0tzlgVAp6-opAY",{"id":296,"title":6,"body":297,"description":11,"extension":14,"meta":301,"name":302,"navigation":17,"path":303,"readingTime":19,"seo":304,"stem":305,"__hash__":306},"authors\u002Fauthors\u002Fvictor-borg.md",{"type":8,"value":298,"toc":299},[],{"title":11,"searchDepth":12,"depth":12,"links":300},[],{},"Victor Borg","\u002Fauthors\u002Fvictor-borg",{"title":6,"description":11},"authors\u002Fvictor-borg","-Za-JweoiP6hyclue_WkxMXdRUDTczPGlJf6AZckjUc",{"id":308,"title":6,"body":309,"description":11,"extension":14,"meta":313,"name":314,"navigation":17,"path":315,"readingTime":19,"seo":316,"stem":317,"__hash__":318},"authors\u002Fauthors\u002Fvirgil-roger.md",{"type":8,"value":310,"toc":311},[],{"title":11,"searchDepth":12,"depth":12,"links":312},[],{},"Virgil Roger","\u002Fauthors\u002Fvirgil-roger",{"title":6,"description":11},"authors\u002Fvirgil-roger","DfVFe5j0bCgXeEr381ZYOM5DP4m-pWb93J9-m_muKJ0",{"id":320,"title":6,"body":321,"description":11,"extension":14,"meta":325,"name":326,"navigation":17,"path":327,"readingTime":19,"seo":328,"stem":329,"__hash__":330},"authors\u002Fauthors\u002Fyukan-zhao.md",{"type":8,"value":322,"toc":323},[],{"title":11,"searchDepth":12,"depth":12,"links":324},[],{},"Yukan Zhao","\u002Fauthors\u002Fyukan-zhao",{"title":6,"description":11},"authors\u002Fyukan-zhao","LRPHugtAJnWHsmHxy9_SR5Zas_C5p-GR_uHEs1Fhk_E",{"id":332,"title":333,"author":334,"body":335,"date":684,"description":685,"extension":14,"lang":686,"meta":687,"navigation":17,"path":688,"published":17,"readingTime":689,"seo":690,"stem":691,"tags":692,"__hash__":696},"articles\u002Farticles\u002F2022-03-10-introduction-du-bus-dentreprise-chez-indy.md","Introduction du bus d'entreprise chez Indy","romain-koenig",{"type":8,"value":336,"toc":673},[337,341,344,347,350,353,364,367,370,379,385,388,391,394,397,400,403,406,409,414,417,420,426,436,441,444,452,455,469,472,475,483,486,489,506,509,517,520,523,526,531,537,540,549,552,555,563,566,577,585,588,596,599,604,607,615,618,621,629,632,635,640,642,645,648,650,656,664,667,670],[338,339,340],"p",{},"Récemment, chez Indy nous avons pris la décision d'ajouter un bus d'entreprise à la stack technique.",[338,342,343],{},"Nous allons passer en revue certaines des raisons qui nous ont poussé à faire ce choix.",[338,345,346],{},"Contexte : L'équipe tech et product est désormais composée de 39 personnes dont 32 développeurs.",[338,348,349],{},"Cette décision n'est pas forcément facile à prendre car elle introduit de la complexité nouvelle\ndans la stack technique. Ainsi que des techniques et des pratiques pour lesquelles la plupart des\ndéveloppeurs de l'équipe ne sont pas encore familiers.",[338,351,352],{},"Néanmoins après avoir réfléchi à la question et à la connaissance des personnalités qui forment\nl'équipe, je pense que c'est la voie de la scalabilité pour la boîte. Ce ne sera peut-être pas votre\ncas, donc je partage notre prise de décision et je ferai une suite d'articles sur l'adoption de\ncette pratique après quelques mois puis après un an.",[354,355,357,363],"h2",{"id":356},"fils-conducteurs",[358,359],"a",{"href":360,"rel":361},"https:\u002F\u002Fgithub.com\u002FGeorgesTech\u002Fblog-content\u002Fblob\u002Fmain\u002FBlog\u002FIntroduction%20du%20bus%20d'entreprise.md#fils-conducteurs",[362],"nofollow","Fils conducteurs",[338,365,366],{},"Pour expliquer comment l'architecture évolue, on peut citer nos fils conducteurs, et résumer la\nsituation actuelle.",[338,368,369],{},"Nous avons un monolithe principal (Indy) sur lequel se trouvent les règles métiers, qui sert de\nbackend à notre frontend et qui synchronise aussi un petit régiment d'outils externes. Ces outils ne\nsont pas liés à notre produit principal mais participent au bon fonctionnement de l'entreprise,\nnotamment la synchronisation de nos différents CRM.",[371,372,374,378],"h3",{"id":373},"historique",[358,375],{"href":376,"rel":377},"https:\u002F\u002Fgithub.com\u002FGeorgesTech\u002Fblog-content\u002Fblob\u002Fmain\u002FBlog\u002FIntroduction%20du%20bus%20d'entreprise.md#historique",[362],"Historique",[338,380,381],{},[382,383],"img",{"alt":11,"src":384},"\u002Fimages\u002Fhistorique.gif",[338,386,387],{},"L'app a commencé simplement avec une connection Indy \u003C-> Intercom. Intercom est l'outil utilisé par\nnos care pour faire la relation client. La première intégration demandée a été de remonter des\ninformations du client sur Intercom comme : L'utilisateur est-il abonné ? A-t-il terminé sa clôture,\ndans quel régime fiscal se trouve-t-il ?",[338,389,390],{},"Puis nous avons eu une intégration Gsheet avec l'équipe marketing qui sortait des données d'Intercom\nà des fins d'analyses. Synchro au début manuelle qui est passé automatique.",[338,392,393],{},"Un peu plus tard, nous avons intégré le CRM de l'équipe Sales : pipedrive, ici aussi nous avons du\nremonter des informations du produit vers Pipedrive pour simplifier le travail des Sales en\nautomatisant certaines actions sur pipedrive. Mais ici la relation est à double sens car nous\ndevions récupérer des informations sur le commercial pour l'équipe marketing, ça remontait alors\ndans l'application pour aller dans Intercom pour aller ensuite dans GSheet (!).",[338,395,396],{},"\u002F!\\ Premier warning d'architecture ici : L'app Indy servait d'intermédiaire pour synchroniser\npipedrive et notre BI de l'époque, code qui ne servait pas du tout l'intention originelle de l'app\nqui était de servir le client, c'était du code d'entreprise pur.",[338,398,399],{},"Puis nous avons ajouté Metabase qui aggrège les données des différents CRM ainsi que les données de\nl'application dans un outil qui sert à faire de la visualisation de données et de la BI.",[338,401,402],{},"Avec la croissance, on a continué à empiler les intégrations : Ringover pour des besoins sales, puis\nTrello pour de l'automatisation produit.",[338,404,405],{},"Nous avons continué avec des app internes qui manipulent l'API de CRM pour des besoins internes\n(autour de l'affectation d'Intercom), des intégrations entre nos CRM : Intercom et Pipedrive car des\ndonnées de l'un étaient nécessaires dans l'autre.",[338,407,408],{},"Et le dernier ajout Slack qui s'intègre avec quasiment tous les autres services pour avoir nos infos\ndans notre outil de communication.",[338,410,411],{},[382,412],{"alt":11,"src":413},"\u002Fimages\u002Fwell_that_escalated_quickly.jpeg",[338,415,416],{},"Le schéma devient vite complexe et il devient difficile pour un développeur, même ancien, de\ncomprendre le flux de données et d'expliquer tout ce qu'il se passe sur notre système d'information.",[338,418,419],{},"Et ce schéma ne montre pas toute l'intégration de monitoring de l'application et des intégrations !\nCe n'était pas très gênant au début, mais cette complexité a conduit à des régressions.",[338,421,422],{},[423,424,425],"strong",{},"Un fil conducteur sera alors : Le besoin d'être en mesure d'expliquer le sens des flux de\ndonnées.",[427,428,429,433],"ul",{},[430,431,432],"li",{},"Avoir une architecture plus explicite et systématique au niveau des synchros",[430,434,435],{},"Que le sens de circulation des données soit plus explicite et systématique aussi",[338,437,438],{},[423,439,440],{},"Un autre fil conducteur sera alors : Être en capacité de facilement rajouter une synchro sur le SI\nexistant sans modifier le produit comptable et les autres services",[338,442,443],{},"Typiquement si demain on ajoute un nouveau CRM, il doit pouvoir écouter les évènements existants,\nfaire sa propre synchro et en cas de crash, le faire sans impacter les autres services. En\nparticulier le produit où se trouvent les clients.",[371,445,447,451],{"id":446},"exemple-déchec-suite-à-cet-état",[358,448],{"href":449,"rel":450},"https:\u002F\u002Fgithub.com\u002FGeorgesTech\u002Fblog-content\u002Fblob\u002Fmain\u002FBlog\u002FIntroduction%20du%20bus%20d'entreprise.md#exemple-d%C3%A9chec-suite-%C3%A0-cet-%C3%A9tat-",[362],"Exemple d'échec suite à cet état :",[338,453,454],{},"Certaines API de nos CRM nous imposent un rate limit, ce qui n'est pas problématique au début mais\navec la croissance de la boite on vient toucher ce rate limit inévitablement et une fois atteint, la\nplupart de nos requêtes échouent et notre synchronisation est perdue. C'est arrivé et le début du\ndébug fut long et fastidieux car nous avions plein d'intégrations avec ce CRM, chacune plus ou moins\nbien monitorée. Il était alors difficile de trouver l'intégration qui posait problème et qui\nexplosait le rate limit :",[427,456,457,460,463,466],{},[430,458,459],{},"Était-ce notre application principale ?",[430,461,462],{},"Était-ce les ZAP (de Zapier) mis en place ?",[430,464,465],{},"Était-ce son intégration avec un autre CRM ?",[430,467,468],{},"Était-ce les jobs journaliers ? etc...",[338,470,471],{},"Une fois trouvé, comment respecter ce rate limit ? Comment le répartir sur les différentes\nintégrations ? Alors qu'elles n'ont pas la même criticité, qu'elles ne sont pas actives au même\nmoment dans la journée, est-ce qu'il faut mettre en place une pile etc...",[338,473,474],{},"Nous avons perdu quelques semaines à résoudre ce point-là.",[371,476,478,482],{"id":477},"volonté-de-changer",[358,479],{"href":480,"rel":481},"https:\u002F\u002Fgithub.com\u002FGeorgesTech\u002Fblog-content\u002Fblob\u002Fmain\u002FBlog\u002FIntroduction%20du%20bus%20d'entreprise.md#volont%C3%A9-de-changer",[362],"Volonté de changer",[338,484,485],{},"Ces problématiques sont assez classiques dans l'industrie et il existe beaucoup de littérature sur\nle sujet. Après nous être renseigné, nous avons décidé d'agir et de nous aligner sur ce qui se fait\nde manière générale sans chercher à être trop original.",[338,487,488],{},"Avec la croissance de la base de code et de l'équipe, nos drivers architecturaux (et humains) sont\ndorénavant :",[427,490,491,496,501],{},[430,492,493],{},[423,494,495],{},"Découplage et autonomie des squads",[430,497,498],{},[423,499,500],{},"Pas d'erreur sur le produit principal",[430,502,503],{},[423,504,505],{},"Garder la volonté d'extension rapide de notre produit et SI",[338,507,508],{},"=> Il faut découpler ce qui peut l'être quitte à échanger un peu de complexité et introduire de\nnouvelles technologies. Les synchros propres à une squad et qui ne font pas partie du produit\ncomptable sont des bons candidats.",[371,510,512,516],{"id":511},"alléger-notre-codebase-principale",[358,513],{"href":514,"rel":515},"https:\u002F\u002Fgithub.com\u002FGeorgesTech\u002Fblog-content\u002Fblob\u002Fmain\u002FBlog\u002FIntroduction%20du%20bus%20d'entreprise.md#all%C3%A9ger-notre-codebase-principale",[362],"Alléger notre codebase principale",[338,518,519],{},"Pourquoi sortir du code ? Retirer du code sans impacter nos fonctionnalités a toujours l'avantage de\nle rendre plus simple avec une interface exposée aux bugs plus faible. Il en va de même pour les\ndépendances, car la plupart des synchros viennent avec leur SDK et dépendances. L'envie de sortir le\ncode de ces synchros, qui pèse dans la codebase du produit principal, s'est fait ressentir suite à\ndes expériences parfois douloureuses sur les problématiques citées plus haut. Pour alléger le code\ndu dépôt principal et du monolithe, ainsi qu'alléger ses dépendances, nous avons décidé de sortir le\ncode qui n'était pas vital à notre métier : la compta.",[338,521,522],{},"Ceci permet d'avoir des équipes qui travaillent sur des dépôts différents pour du code qui a un but\net une criticité complètement différentes, les laissant faire leur choix d'architecture, de CI et de\nprocess.",[338,524,525],{},"Je voulais aussi un découplage maximal, c'est pourquoi la solution d'appeler des services\ndirectement en HTTP ne me plaisait pas. Le pattern pub\u002Fsub est tout indiqué ici et est largement\ndiscuté dans la littérature, ce qui nous a amené assez rapidement sur cette proposition :",[338,527,528],{},[382,529],{"alt":11,"src":530},"\u002Fimages\u002Farchitecture-bus-et-events.png",[338,532,533],{},[534,535,536],"em",{},"Tous les services ne sont pas représentés...",[338,538,539],{},"Le BUS fait office de SPOF (single point of failure), mais si le BUS tombe il n'y a pas d'impact sur\nle service pour les clients finaux.",[541,542,544,548],"h4",{"id":543},"impacts-sur-le-respect-de-solid",[358,545],{"href":546,"rel":547},"https:\u002F\u002Fgithub.com\u002FGeorgesTech\u002Fblog-content\u002Fblob\u002Fmain\u002FBlog\u002FIntroduction%20du%20bus%20d'entreprise.md#impacts-sur-le-respect-de-solid",[362],"Impacts sur le respect de SOLID",[338,550,551],{},"Le principe SRP (Single Responsibility Principle) est mieux respecté, il est plus facile de faire\névoluer chaque petit module. Si l'API d'intercom change, on change le service en question et pas\nl'application de comptabilité, de même pour les autres services cloud.",[338,553,554],{},"Le principe OCP (Open\u002FClosed Principle) est mieux respecté aussi. Si demain on veut ajouter un\nservice, on peut le rajouter comme consumer du BUS sans toucher au reste du SI.",[371,556,558,562],{"id":557},"gestion-de-la-donnée-nécessaire-aux-services-externes",[358,559],{"href":560,"rel":561},"https:\u002F\u002Fgithub.com\u002FGeorgesTech\u002Fblog-content\u002Fblob\u002Fmain\u002FBlog\u002FIntroduction%20du%20bus%20d'entreprise.md#gestion-de-la-donn%C3%A9e-n%C3%A9cessaire-aux-services-externes",[362],"Gestion de la donnée nécessaire aux services externes",[338,564,565],{},"Une question se pose alors : comment envoyer sur le bus la donnée métier nécessaire aux applications\nde synchronisation de nos CRM ? Typiquement, lors d'un event user\u002Fsubscribe par exemple, le nom de\nl'event et l'ID de l'utilisateur en soit ne suffisent pas. Le service pipedrive ou Intercom qui\nécoute sur le bus va vouloir que de la donnée soit attachée à l'évènement. Il existe alors trois\nsolutions :",[427,567,568,571,574],{},[430,569,570],{},"Base de données partagée",[430,572,573],{},"en PULL : les services appellent le produit principal à travers le réseaux",[430,575,576],{},"en PUSH : le produit envoie la donnée sur le bus",[541,578,580,584],{"id":579},"_1-shared-database",[358,581],{"href":582,"rel":583},"https:\u002F\u002Fgithub.com\u002FGeorgesTech\u002Fblog-content\u002Fblob\u002Fmain\u002FBlog\u002FIntroduction%20du%20bus%20d'entreprise.md#1-shared-database-",[362],"1. Shared database :",[338,586,587],{},"Très rapidement écarté car cela ne sert à rien de découpler le code s'il reste couplé par le schéma\nde base de données. Ce modèle est trop fragile et bug-prone.",[541,589,591,595],{"id":590},"_2-pull-le-service-va-chercher-linformation-par-api",[358,592],{"href":593,"rel":594},"https:\u002F\u002Fgithub.com\u002FGeorgesTech\u002Fblog-content\u002Fblob\u002Fmain\u002FBlog\u002FIntroduction%20du%20bus%20d'entreprise.md#2--pull-le-service-va-chercher-linformation-par-api-",[362],"2. PULL Le service va chercher l'information par API :",[338,597,598],{},"Dans ce modèle, on essaye de garder le produit principal le plus simple possible en envoyant un\névènement technique sans données métiers (uniquement des IDs). C'est au CRM en question de savoir\nquelles données il désire et d'aller les récupérer en interrogeant, par exemple, une simple API CRUD\nqui expose lesdites données.",[338,600,601],{},[382,602],{"alt":11,"src":603},"\u002Fimages\u002Fbus-data-v2.png",[338,605,606],{},"Avantages :",[338,608,609,610,614],{},"Le code de l'émetteur de l'event reste simple. On ne fait pas apparaître une\nfonction ",[611,612,613],"code",{},"buildEvent"," qui va aggréger des données qui, de première abord, n'ont rien à voir avec le\ncas d'utilisation car c'est une spécifité de l'app de sync d'un CRM.",[338,616,617],{},"Désavantages :",[338,619,620],{},"Nous avons des routes qui sont potentiellement utilisées par des clients (l'interface) ou des apps\ninternes. Il faut pouvoir les monitorer pour savoir si elles sont toujours utilisées ou non.\nBeaucoup de données transitent par le réseau donc il y a plus de risques d'erreur.",[541,622,624,628],{"id":623},"_3-push-la-data-est-formatté-par-georges-puis-accroché-à-lévènement",[358,625],{"href":626,"rel":627},"https:\u002F\u002Fgithub.com\u002FGeorgesTech\u002Fblog-content\u002Fblob\u002Fmain\u002FBlog\u002FIntroduction%20du%20bus%20d'entreprise.md#3--push-la-data-est-formatt%C3%A9-par-georges-puis-accroch%C3%A9-%C3%A0-l%C3%A9v%C3%A8nement",[362],"3. PUSH La data est formatté par Georges puis accroché à l'évènement",[338,630,631],{},"Ici la donnée est formattée dans l'émetteur directement puis attachée à l'event pour être envoyée\nsur le bus. Les modules n'ont pas à aller interroger l'émetteur pour récupérer des données\nsupplémentaires.",[338,633,634],{},"L'enjeu ici est de ne pas polluer le cas d'utilisation d'une route métier avec l'agrégation de\ndonnée qui serait un enjeu non fonctionnel, juste une spécificité de nos outils de sync.",[338,636,637],{},[382,638],{"alt":11,"src":639},"\u002Fimages\u002Fbus-data-v3.png",[338,641,606],{},[338,643,644],{},"Possible de retrouver un cas d'utilisation simple débarassé des fonctions buildEvent (qui ne seront\npas dans le même fichier).",[338,646,647],{},"On évite les appels de nos app vers Georges et les appels API qui partent dans tous les sens et qui\nsont dur à monitorer.",[338,649,617],{},[338,651,652,653,655],{},"Un peu plus de discipline dans le code de l'émetteur . On veut éviter que la fonction\nde ",[611,654,613],{},", celle qui va aggréger des données métiers nécessaires à nos outils mais non\nnécessaires au cas d'utilisation soit dans la route de ce dernier. Ceci peut être accompli avec des\névènements internes et un pattern Observer (voir futur billet de blog).",[354,657,659,663],{"id":658},"conclusion",[358,660],{"href":661,"rel":662},"https:\u002F\u002Fgithub.com\u002FGeorgesTech\u002Fblog-content\u002Fblob\u002Fmain\u002FBlog\u002FIntroduction%20du%20bus%20d'entreprise.md#conclusion",[362],"Conclusion",[338,665,666],{},"Je peux avoir des squads spécialisées sur le produit comptable qui n'ont pas connaissance des outils\ninternes de la boîte !",[338,668,669],{},"Je peux avoir des squads spécialisées sur la maintenance de nos outils internes sans connaissance\nsur le produit comptable au-delà des données qui les intéressent (celle qui transitent sur le BUS).",[338,671,672],{},"L'enjeu, ici, est désormais de définir et respecter un contrat de données qui va passer sur le BUS.\nCela peut être le rôle du CTO (qui est inter-squads), d'une personne de l'équipe data, d'un OPS. Le\nrôle étant de faire respecter ce contrat et vérifier la cohérence des données qui passent sur le\nBUS, (c'est-à-dire donner la spécification des buildEvents).",{"title":11,"searchDepth":12,"depth":12,"links":674},[675,683],{"id":356,"depth":12,"text":363,"children":676},[677,679,680,681,682],{"id":373,"depth":678,"text":378},3,{"id":446,"depth":678,"text":451},{"id":477,"depth":678,"text":482},{"id":511,"depth":678,"text":516},{"id":557,"depth":678,"text":562},{"id":658,"depth":12,"text":663},"2022-03-10","Récemment, chez Indy nous avons pris la décision d’ajouter un bus d’entreprise à la stack technique.","fr",{},"\u002Farticles\u002F2022-03-10-introduction-du-bus-dentreprise-chez-indy",11,{"title":333,"description":685},"articles\u002F2022-03-10-introduction-du-bus-dentreprise-chez-indy",[693,694,695],"Tech","Scalabilité","Architecture","i0Y5VorTD88p3brFa-dZ5TRZXv7U71xaNeeX7xlwDjE",1778159244034]