L'application mobile indépendante de 10 ans
Bonjour, je suis Taylor Hughes . Je suis ingénieur logiciel. J'ai livré des applications et créé des équipes sur Facebook, Google, Clubhouse et un tas de start-ups entre les deux.
Nous avons créé une application de partage de photos appelée Cluster en 2013 . Il a été lancé sur l'App Store il y a 10 ans le mois prochain. À l'époque, il y avait beaucoup de concurrents , avec plus de lancement apparemment chaque jour.
En 2015, nous avons compris que Cluster n'allait pas devenir un produit d'un milliard d'utilisateurs. Nous avons essayé un million de stratégies différentes, et nous n'avons jamais pu amener la croissance là où elle devait être pour un rendement de la taille d'un capital-risque. Mais l'application a lentement trouvé de nouveaux utilisateurs et de nombreuses personnes se sont connectées avec leurs proches à l'intérieur de l'application, y compris nos propres familles . Nous avons donc travaillé dur pour que cela continue.
Le cluster est toujours vivant aujourd'hui, et la plupart de ses concurrents d'origine n'existent plus (y compris les poids lourds comme Facebook Moments et Dropbox Carousel ). Plus de 4 millions de personnes ont partagé près de 150 millions de photos et de vidéos au cours de la dernière décennie sur la plateforme. Nous avons vu des groupes de familles et d'amis à long terme rester sur l'application pendant 10 ans, et des milliers d'utilisateurs à long terme utilisent encore l'application presque tous les jours.
Au fil des ans, nous avons dû maintenir le logiciel original de Cluster, mettre à niveau et modifier lentement les parties centrales de l'application pour corriger les bogues, réduire les coûts et essayer de gagner suffisamment d'argent pour maintenir l'entreprise en vie. Nous avons ajouté un moyen d'imprimer des livres photo (2016) et un modèle d'abonnement App Store (2022). Nous avons migré entre les comptes AWS et déplacé certains services vers GCP. Nous avons corrigé les bogues des nouveaux SDK tiers et effectué des mises à niveau majeures de la plate-forme dans les six langues. (Python, Go, JavaScript, Swift, Objective-C et Java.)
Et une grande partie du code original reste! Mais nous avons appris beaucoup de leçons précieuses dans la construction de logiciels à long terme.
Où nous avons été, et où nous sommes maintenant
Le backend original en 2013 était un monolithe Python 2.7, exécutant Django 1.4 avec une base de données Postgres. À l'époque, j'utilisais fabric pour déployer avec git sur des AMI personnalisées sur EC2. L'été dernier, j'ai effectué la mise à niveau vers Python 3 et nous utilisons Elastic Beanstalk sur de toutes nouvelles instances EC2 Graviton. Nous déployons maintenant avec CodePipeline.
En ce qui concerne les applications mobiles, l'application iOS d'origine a été construite avec le SDK iOS 6.0. Je pense qu'Android a ciblé 3.x, Honeycomb. Je me souviens très bien d'avoir dû faire face à la version iOS 7 - rappelez-vous comment tout est devenu plat tout d'un coup? (Peut-être que vous ne le faites pas.) Notre objectif SDK minimum actuel est iOS 14, et nous utilisons un mélange sur mesure de Swift (date de sortie originale : juin 2014) et Objective-C. L'application Android est en retard, mais nous reviendrons pour l'améliorer dès que possible.
Alors, qu'est-ce qui a résisté à l'épreuve du temps ?
Les optimisations ne valent souvent pas la peine d'être maintenues
L'une des plus grandes leçons concerne ma propre croissance en tant qu'ingénieur au cours de la dernière décennie : la nouveauté et l'optimisation sont les ennemis d'un code durable et à long terme.
En 2013, j'ai entendu parler de la façon dont Instagram a réussi à partager vos photos très rapidement. Ils ont cette astuce : lorsque vous choisissez une photo et que vous commencez à jouer avec des filtres, ils téléchargent déjà la photo en arrière-plan . Alors, quand vous appuyez enfin sur "Publier", boum ! La photo semble s'afficher instantanément. Comme c'est génial.
Alors, bien sûr, j'ai construit ça aussi. J'ai construit le système pour télécharger les photos après les avoir choisies, mais avant de cliquer sur "Publier", et je l'ai rendu encore plus complexe en superposant de manière à télécharger d' abord des images réduites , pour rendre les messages initiaux encore plus rapides . J'ai rendu le système de notifications super complexe pour créer des notifications agrégées parfaites - bien mieux que simplement "Taylor a téléchargé une nouvelle photo". J'ai fait encoder les téléchargements de vidéos à la volée , car cela rendait les téléchargements de vidéos plus rapides sur les connexions mobiles. (Au prix d'une toute nouvelle langue à prendre en charge pour toujours.)
Tout cela devenait vraiment fastidieux à maintenir, surtout quand ce n'était pas moi qui maintenais l'application. Pendant plusieurs années, je n'ai pas pu m'impliquer en raison de conflits d'intérêts avec mes employeurs, et Cluster était maintenu par des ingénieurs incroyables qui l'aimaient comme moi.
La complexité de ce code n'a pas augmenté de manière significative la valeur de Cluster pour ses utilisateurs , donc quand il s'est finalement cassé ou est devenu confus, cela ne valait pas la peine d'être corrigé.
Les trucs trop complexes, les trucs qui étaient agréables à avoir, qui étaient un peu fantaisistes ou sur mesure – tout cela a été arraché.
Le téléchargeur est basique maintenant, il commence juste à télécharger des photos lorsque vous appuyez sur "Publier" et affiche une barre de progression comme il aurait probablement dû l'être à l'origine. Les vidéos sont juste encodées après que nous ayons reçu le fichier complet. Les notifications sont plus simples et moins sujettes aux conditions de course.
Chaque dépendance majeure accélère la disparition de votre code
Qu'est-ce qui a changé depuis 2013 dans le monde du développement ? Pas grand-chose, non ? !
Python et les plates-formes mobiles elles-mêmes sont probablement les changements à grande échelle les plus évidents - nous avons vécu pour voir le coucher du soleil de Python 2 et avons parcouru plus de 8 versions majeures d'iOS. Mais au-delà de ceux-ci, nous avons également du code dans Go et du code dans Node.js, qui ont tous deux connu de nombreux changements importants depuis 2014/2015. (Certaines applications Web de Cluster s'exécutent sur une interface Node.js personnalisée - encore une fois, à quoi pensais-je ?)
Au fil des ans, nous avons dû reconstruire le processus d'exécution et de déploiement pour chacun de ces principaux langages - Python (applications Django et Celery), Golang et Node.js - et chacun d'eux ajoute une autre dimension au temps et à la complexité de la maintenance continue.
Mais les dépendances tierces sont bien pires que les langages et frameworks de base.
Les SDK tiers, en particulier pour l' authentification , ont probablement été la pire cible mobile. Le SDK Google est devenu le SDK Google+ et est maintenant le SDK de connexion Google ; le SDK Facebook a été complètement vidé. ( Re-gonfler les sessions Facebook ? J'ai arraché ça.) Crashlytics est devenu Twitter Fabric et fait maintenant partie de Google Firebase. Apple a mis fin à son horrible service de notifications push binaires et l'a remplacé par l'étrange solution HTTP/2 actuelle. Nous avons même dû implémenter Apple Sign-In, qui manque cruellement de documentation.
Les intégrations tierces sont les pires. Choisissez vos partenaires tiers avec le plus grand soin.
Qu'est-ce qui a le moins changé ? La technologie « ennuyeuse ». Postgres et Redis ne nécessitaient aucun détournement pour continuer à fonctionner. Même Django lui-même a causé très peu de problèmes lorsque je suis passé de Django 1.5 à Django 4.0 en juin 2022 - j'ai à peine eu à toucher à mes vues Django ! La plupart des modifications de Django concernaient la configuration et le routage, et la chose la plus difficile était de migrer les anciennes données de session Django 1.5 vers le format Django 4.0 moderne afin que les utilisateurs ne soient pas déconnectés pendant la migration.
Dans le client, la logique principale de ViewController est essentiellement inchangée, mais j'ai dû réécrire l'intégralité du flux de connexion en raison de tous les nouveaux SDK tiers.
Les tests d'intégration sont une bouée de sauvetage
Le cluster dispose d'un ensemble de tests d'intégration très coûteux, qui tentent d'exécuter la pile complète, y compris les appels à une instance locale de Google App Engine (!). Le harnais de test lance littéralement Google App Engine local et partage l'URL avec la suite de tests, qui émet des appels contre lui. C'est des bananes.
Ces tests sont lents et horribles selon les normes modernes - la suite complète prend quelques minutes à exécuter. Mais ils ont été une aubaine absolue alors que je continue à maintenir cette base de code, car ils exécutent la majeure partie du code de base qui fait fonctionner l'application.
La migration Python 3, notamment le passage de str à bytes, a été un grand coup de pouce. Mais c'était aussi assez simple : exécutez 2to3 , exécutez cette suite géante de tests et corrigez les échecs.
En fait, les endroits qui ont le plus cassé après la migration étaient les endroits où nous n'avions pas fait de tests . Bien sûr! Si je n'avais pas eu de tests, j'aurais été complètement foutu.
À part : Construire pour le long terme ou lancer un MVP
Dans un sens, construire pour le long terme semblerait aller à l'encontre des objectifs de type "lean startup" de lancement et d'itération sur un MVP aussi rapidement que possible. MVP signifie lancer quelque chose de hacky et simple, mais construire sur le long terme semble être le contraire de lancer quelque chose de hacky.
Mais je pense que les deux objectifs sont en fait très bien alignés :
- Concentrez-vous sur la création de solutions simples qui résolvent les problèmes réels et urgents des utilisateurs, de manière usée.
- Utilisez des logiciels et des plates-formes éprouvés, stables et qui ne changent pas trop avec le temps.
- Intégrez uniquement des tiers lorsque cela est absolument nécessaire pour résoudre ces problèmes réels et urgents.
(Une chose qui diffère certainement est l'optimisation des performances et des coûts d'exécution : régler l'application pour qu'elle fonctionne raisonnablement bien pour les principaux points de terminaison, configurer la mise à l'échelle automatique, configurer le stockage de fichiers glacier, etc. n'est pas quelque chose à perdre du temps lorsque vous validez un concept.)
Emballer
Quand j'ai construit Cluster, je n'aurais jamais imaginé qu'il fonctionnerait encore en 2023. Ou s'il fonctionnait toujours, je pensais que ce serait un énorme succès, et nous aurions tout réécrit en C++ ou quoi que ce soit de toute façon.
Mais l'application survit, et je pense que c'est en partie parce que nous avons un noyau solide de code simple qui permet à l'application de fonctionner. Maintenant que nous nous sommes débarrassés d'une partie de la complexité de la mise en œuvre d'origine, je suis convaincu que nous serons en forme en 2033 !
Comme le poste? Retrouvez-moi sur Twitter, @taylorhughes !
![Qu'est-ce qu'une liste liée, de toute façon? [Partie 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































