Communauté
Développement
5 août 2023
TLDR ; Nous réécrivons Documenso pour passer de nos fondations MVP et créer une base encore meilleure pour le projet. Cette réécriture nous donnera l'opportunité de corriger quelques éléments au sein du projet tout en permettant un processus de développement plus rapide à l'avenir.
Introduction
Chez Documenso, nous créons la prochaine génération d'infrastructure de signature avec un accent sur l'inclusivité et l'accessibilité pour tous. Pour ce faire, nous devons nous assurer que le logiciel que nous écrivons est également inclusif et accessible et pour cette raison, nous avons décidé de prendre un peu de recul et d'effectuer une _rapide_ réécriture.
Bien que nous ayons atteint le statut MVP validé et gagné des clients payants, nous sommes encore assez éloignés de notre objectif de créer une expérience de signature ouverte et de confiance. Pour nous rapprocher de cet avenir, nous devons faire un pas en arrière et nous concentrer sur les fondations du projet pour nous assurer que nous pouvons résoudre tous les éléments que nous avons prévus sur notre page d'accueil actuelle.
Heureusement, ce n'était pas le cas de quelqu'un qui aurait rejoint l'équipe et proposé une réécriture en raison d'un manque de compréhension de la base de code et du contexte qui l'entoure. Avant de rejoindre Documenso en tant que co-fondateur, j'avais passé un temps considérable au sein de la base de code de Documenso et j'avais une compréhension assez intime de ce qui se passait dans l'ensemble. Cette connaissance m'a permis de prendre la décision juste et en même temps difficile de faire une courte pause afin que nous puissions reconstruire nos fondations actuelles pour permettre l'accessibilité et un délai de livraison plus rapide à l'avenir.
Le Raisonnement : TypeScript
Notre principale raison pour la réécriture est de mieux tirer parti des outils et technologies que nous avons déjà choisis, à savoir TypeScript. Bien que Documenso utilise actuellement TypeScript, il n'exploite pas pleinement ses fonctionnalités de sécurité, telles que les génériques et les gardes de type.
La base de code contient actuellement plusieurs instances de types `any`, ce qui est prévisible lorsque l'on travaille dans un domaine inconnu où les modèles d'objets ne sont pas complètement compris avant exploration et expérimentation. Ces `any` ont initialement accéléré le développement, mais sont depuis devenus un frein en raison du manque d'informations de type, combiné au prop drilling. En conséquence, il est nécessaire de passer par beaucoup de contexte pour comprendre la racine de tout problème donné.
La réécriture utilise TypeScript à son plein potentiel, en s'assurant que chaque interaction est fortement typée, à la fois grâce aux outils TypeScript généraux et à l'introduction de Zod, une bibliothèque de validation avec un excellent support TypeScript. Avec ces choix, nous pouvons nous assurer que la base de code est robuste face à divers entrées et états, car la plupart des problèmes seront détectés pendant le temps de compilation et signalés dans l'IDE d'un développeur.
Le Raisonnement : Contrats API plus solides
En accord avec notre modèle de création de contrats fortement typés, nous avons décidé d'utiliser tRPC pour notre API interne. Cela nous permet de partager des types entre notre frontend et backend et d'établir un contrat solide pour les interactions entre les deux. Cela contraste avec les points de terminaison API actuellement non typés dans Documenso, qui sont accessibles en utilisant l'API `fetch` qui elle-même est non typée.
L'utilisation de tRPC réduit considérablement la chance d'échecs résultant de choses banales telles que des changements de forme d'argument ou de réponse lors des mises à jour. Nous avons pris cette décision facilement parce que tRPC est une technologie mature qui ne montre aucun signe de perdre de l'élan de sitôt.
De plus, de nombreux amis de notre communauté open-source ont fait le même choix pour des raisons similaires.
Le Raisonnement : Choisir des technologies excitantes
Bien que nous travaillions déjà avec ce que je considère comme une pile amusante qui comprend Next.js, Prisma, Tailwind, et plus, il n'est un secret pour personne que les contributeurs aiment travailler avec de nouvelles technologies qui les bénéficient dans leur propre carrière et projets.
Pour tirer parti de cela, nous avons décidé d'utiliser Next.js 13 et la nouvelle architecture des composants et actions côté serveur de React. Les composants serveur sont actuellement populaires parmi les développeurs, beaucoup les adorant et les détestant en même temps.
J'ai personnellement travaillé avec des composants et des actions serveur depuis leur première sortie en octobre 2022 et j'ai traité la plupart des accrocs et limitations en cours de route. Maintenant, en juillet 2023, je crois qu'ils se trouvent dans un endroit beaucoup plus stable et sont prêts à être adoptés, avec leurs avantages reconnus par beaucoup.
En choisissant d'utiliser des composants et des actions serveur, nous espérons encourager la communauté à participer plus qu'elle ne le ferait autrement. Cependant, nous choisissons cela uniquement parce que cela est devenu plus mature et stable. Nous ne choisirons pas des éléments qui sont moins susceptibles de devenir la solution de facto à l'avenir, car nous ne souhaitons pas hériter d'une montagne de dettes techniques plus tard.
Le Raisonnement : Permettre un travail concurrent
Une autre raison convaincante pour la réécriture était de modulariser le code efficacement afin que nous puissions travailler sur les fonctionnalités de manière concurrente et sans problème. Cela signifie extraire autant que possible des composants, des gestionnaires d'API et plus et les regrouper dans un ensemble de méthodes et de fonctions qui tentent de se concentrer sur une seule chose.
En effectuant ce travail, nous devrions être en mesure de faire facilement des refactorisations et d'autres changements à diverses parties du code sans nous marcher sur les pieds, ce qui nous accorde également la possibilité de mettre à niveau ou de déprécier des éléments comme nécessaire en respectant le contrat de la méthode précédente.
De plus, cela rend le test beaucoup plus facile car nous pouvons nous concentrer davantage sur les unités de travail plutôt que sur des tests de bout en bout étendus bien que nous visons à avoir les deux, juste pas tout de suite.
Le Raisonnement : Licensing du travail
Une autre raison majeure pour la réécriture est de s'assurer que tout le travail effectué sur le projet par notre équipe interne et les contributeurs externes est licencié d'une manière qui bénéficie au projet à long terme. Avant la réécriture, les contributeurs créaient des requêtes de tirage qui étaient fusionnées sans autre processus en dehors des cycles de révision de code et de test courants.
C'était bien dans la plupart des cas car nous travaillions simplement sur le MVP, mais maintenant que nous évoluons vers un focus infrastructure nous avons l'intention de prendre des clients d'entreprise qui auront besoin d'une licence non-GPLv3, car ses interprétations peuvent être assez nuisibles à l'hébergement privé, pour faciliter cela nous exigerons que les contributeurs signent un accord de licence de contributeur (CLA) avant que leurs modifications ne soient fusionnées, ce qui nous attribuera une licence perpétuelle pour utiliser leur code et le redéclarer comme nécessaire, comme pour l'utilisation ci-dessus.
Bien que certains puissent se raidir à l'idée de signer un CLA, nous voulons offrir une offre d'entreprise convaincante par le biais d'une double licence. Une grande adoption en entreprise est l'un des piliers de notre stratégie et sera essentielle au financement du développement de la communauté et du produit à long terme.
_Veuillez noter que ce qui précède ne signifie pas que nous allons un jour devenir propriétaire, c'est un point dans nos accords d'investisseurs que https://github.com/documenso/documenso restera toujours disponible et open-source._
Objectifs et Non-Objectifs
Réécrire une application est une tâche monumentale que j'ai affrontée et rejetée plusieurs fois au cours de ma carrière. En vieillissant, je deviens plus hésitant à effectuer ces réécritures car je comprends que les systèmes portent beaucoup de contexte et d'histoire. Cela les rend mieux adaptés à un refactoring par morceaux à la place, ce qui évite d'apprendre les leçons du passé encore une fois lors du lancement de la réécriture.
Pour nous assurer que nous ne faisons pas simplement un saut dans le vide, j'ai établi une liste d'objectifs et de non-objectifs pour garder cette réécriture légère et abordable.
Objectifs
Fournir un design et une interface propres pour l'application nouvellement réécrite qui créent un sentiment de confiance et de sécurité au premier coup d'œil.
Créer une base et une architecture stables qui permettront la croissance vers nos éléments de feuille de route futurs (équipes, automatisation, flux de travail, etc.
Créer un système robuste qui nécessite un contexte minimal grâce à des contrats et des typages solides.
Non-Objectifs
Changer le schéma de base de données (nous ne voulons pas rendre la migration plus difficile qu'elle ne doit l'être, donc tous les changements doivent être additifs).
Ajouter trop de fonctionnalités qui n'étaient pas dans le système avant la réécriture.
Supprimer des fonctionnalités qui étaient dans la version antérieure de Documenso, telles que les signatures gratuites (signatures qui n'ont pas de champ correspondant).
Plan de déploiement
Grâce aux contraintes énumérées ci-dessus, notre déploiement sera espérons-le fairly sans douleur, mais pour être prudent, nous prévoyons de faire ce qui suit.
Dans l'environnement de test actuel, créer et signer un certain nombre de documents laissant beaucoup dans divers états d'achèvement.
Déployer la réécriture dans l'environnement de test et vérifier que tous les documents existants et les informations sont récupérables et modifiables sans aucun problème.
Créer un autre ensemble de documents en utilisant la nouvelle réécriture et vérifier que toutes les interactions entre l'édition et la signature fonctionnent comme prévu.
Répéter cela jusqu'à ce que nous atteignions un niveau de confiance général (avec une attente de deux semaines).
Une fois que nous aurons atteint le niveau de confiance souhaité avec notre environnement de test, nous chercherons à déployer la réécriture dans l'environnement de production, en nous assurant d'avoir effectué toutes les sauvegardes requises en cas d'échec catastrophique.
Vous voulez aider ?
Nous travaillons actuellement sur la branche feat/refresh sur GitHub, nous visons à avoir un CLA disponible à signer dans les jours à venir afin que nous puissions commencer à accepter des contributions externes dès que possible. Bien que nous approchions de la phase finale de la réécriture, nous lancerons bientôt quelques primes pour des choses comme Husky et Changesets.
Restez à l'affût de notre https://github.com/documenso/documenso/issues pour rester à jour !