Développement de bibliothèque: de l'API à la version publique

Regardons les bibliothèques non pas du côté qui nous est le plus familier, c'est-à-dire celui de l'utilisateur, mais du point de vue du développeur de la bibliothèque de développement mobile. Parlons des approches à suivre lors du développement de votre bibliothèque. Nous commençons, bien sûr, par la conception d'une telle API que vous aimeriez utiliser vous-même, ce qui serait pratique. Nous réfléchirons à ce qui doit être pris en compte afin de créer non seulement du code fonctionnel, mais une très bonne bibliothèque, et arriver au point de publier une véritable version publique pour adultes. Asya Sviridenko nous aidera à cet égard, qui partagera son expérience considérable dans le développement de la bibliothèque mobile SpeechKit à Yandex .

Le matériel sera utile non seulement à ceux impliqués dans le développement d'une bibliothèque ou d'un framework, mais aussi à ceux qui souhaitent séparer une partie de leur application dans un module séparé, puis le réutiliser, ou, par exemple, partager leur code avec le reste de la communauté des développeurs en le publiant dans accès public.

Pour tout le monde, l'histoire sera remplie d'histoires authentiques de la vie de l'équipe mobile SpeechKit, donc ça devrait être amusant.


Table des matières


  • SpeechKit minute .
  • Concevoir une API pratique et compréhensible que vous souhaitez utiliser.
  • Développement . Ce qu'il faut ajouter au code pour qu'il fonctionne non seulement et exécute des fonctionnalités, mais qu'il aide également vos utilisateurs.
  • Lancement - ce que vous ne devez pas oublier lorsque vous lancez la version.


SpeechKit minute


Je ne vous demanderai pas si vous avez entendu parler de SpeechKit, car même à l'intérieur de Yandex, tout le monde ne sait pas ce que c'est.

SpeechKit est la porte de toutes les technologies vocales Yandex . Grâce à cette bibliothèque, vous pouvez intégrer des technologies vocales dans votre application: reconnaissance et synthèse vocale, activation vocale.

Vous avez probablement entendu parler de l'assistante vocale Alice - elle travaille uniquement sur la base de SpeechKit. SpeechKit lui-même n'inclut pas la reconnaissance ou la synthèse, cela se produit sur le serveur. Mais c'est grâce à notre bibliothèque que tout peut être intégré dans l'application.

La question suivante est généralement - si tout se passe sur le serveur, que fait la bibliothèque? Pourquoi est-il nécessaire?

La bibliothèque fait beaucoup:

  1. Synchronisation de tous les processus. Par exemple, en utilisant un assistant vocal, un utilisateur clique sur un bouton, dit quelque chose, interrompt l'assistant, fait des demandes - tout passe par la bibliothèque. Pour l'utilisateur de notre bibliothèque c'est transparent, il ne faut pas se soucier de tout ça.
  2. Réseautage Étant donné que tout se passe sur le serveur, vous devez obtenir des données à partir de là, les traiter et les donner à l'utilisateur. SpeechKit peut désormais accéder à plusieurs serveurs différents au sein d'une même connexion réseau: l'un est engagé dans la reconnaissance, l'autre dans l'attribution de sens, le troisième dans la reconnaissance musicale, etc. Tout cela est caché dans la bibliothèque, les utilisateurs n'ont pas à s'en soucier.
  3. Travaillez avec des sources audio. Nous avons affaire à la parole humaine, et le travail avec l'audio se fait également dans SpeechKit. De plus, nous pouvons non seulement écrire à partir d'un appareil standard, mais également recevoir des données de n'importe où. Il peut s'agir d'un fichier ou d'un flux - nous pouvons travailler avec tout cela.

SpeechKit est utilisé dans les équipes internes. Maintenant, il a été intégré par 16 équipes Yandex. Et nous connaissons même plusieurs équipes externes qui l'ont fait aussi.

La conception


Réfléchissons à ce que nous entendons par une application pratique. Habituellement, il s'agit d'un UX réfléchi et compréhensible, la solution à nos problèmes, un fonctionnement stable, etc.

Lorsque nous disons qu'une bibliothèque est pratique, nous voulons tout d'abord dire qu'elle possède une telle API qu'elle est facile à utiliser. Comment y parvenir?

Principes de base


Ce sont certains des aspects que j'ai appris de mon expérience avec SpeechKit.

  • Tout d'abord, n'oubliez pas que vos utilisateurs sont des développeurs .

D'une part, c'est bien, car vous ne pouvez pas expliquer aux utilisateurs ordinaires: "Vous voyez, le backend est avec nous, et donc rien ne fonctionne, et nous allons bien!" Vous pouvez l'expliquer aux développeurs - vous pouvez en expliquer beaucoup aux développeurs!

D'un autre côté, vous obtenez de tels utilisateurs qui en profiteront certainement pour trouver un trou et casser quelque chose si vous le laissez. Nous utilisons tous des bibliothèques et essayons d'en tirer le meilleur parti. Ils prétendent qu'ils ne font que ceci, ceci et cela, et nous pensons: "Non, maintenant nous allons jouer une petite farce ici, nous allons le transmettre et tout sera comme il se doit."

De plus, le fait que les utilisateurs soient des développeurs signifie que vous aurez toujours une montagne de trucs et astuces sur la façon de développer et d'améliorer tout.

Le deuxième point important est parfaitement cohérent avec le premier.

  • Tout ce qui n'est pas autorisé dans votre bibliothèque doit être interdit,
    afin qu'il n'y ait pas d'échappatoires indésirables.

Si vos utilisateurs commencent à faire quelque chose avec la bibliothèque que vous ne vous attendiez pas, c'est un chemin direct vers les bogues et ceux qui sont difficiles à déboguer. Essayez d'utiliser tout ce que le langage donne et la technologie que vous utilisez: publique / privée, finale, obsolète, en lecture seule. Réduisez la portée, interdisez l'héritage et l'utilisation de certaines méthodes, marquez les propriétés qui ne peuvent pas être modifiées - fournissez tout ce qui est possible pour empêcher quelque chose que votre bibliothèque n'est tout simplement pas conçue pour faire.

  • Ne laissez pas d'ambiguïtés dans l'interprétation de l'API de votre bibliothèque.

Si cette classe particulière peut être créée d'une manière, refusez toutes les autres. Si cette propriété ne peut pas être nulle, spécifiez-la explicitement. Dans iOS, il y a nullable / nonnull, initialiseur désigné, la même chose est en Java et Android. Utilisez tout cela pour que l'utilisateur puisse ouvrir le fichier, ouvrir votre classe, le parcourir et comprendre immédiatement ce qui peut être fait et ce qui ne peut pas être fait.

API Case SpeechKit


En utilisant SpeechKit comme exemple, je vais vous expliquer comment nous avons refactorisé la version 2 en version 3. Nous avons beaucoup changé l'API et essayé d'utiliser tous ces principes.

Le besoin s'est fait sentir car l' API était complexe et «théorique» . Il y avait des composants mondiaux qui devaient être appelés en premier - pas appelés - tout ne fonctionnait pas. Des paramètres très étranges ont été définis. L'API était assez «théorique», car SpeechKit faisait à l'origine partie du Navigateur, puis cette pièce a été transférée à la bibliothèque. L'API fonctionnait essentiellement avec les cas utilisés dans Navigator.

Petit à petit, le nombre d'utilisateurs a augmenté et nous avons commencé à comprendre ce dont ils avaient vraiment besoin: quelles méthodes, rappels, paramètres. Ils nous sont venus avec des demandes que l'API ne permettait pas de mettre en œuvre. Cela a été répété maintes et maintes fois, et il est devenu clair que l'API n'était pas à la hauteur. Nous nous sommes donc impliqués dans le refactoring.

Le processus de refactoring a été long (six mois) et douloureux (tout le monde était mécontent) . La principale difficulté n'était pas de prendre une montagne de code et de la réécrire. Il était impossible d'opter simplement pour le refactoring, mais il était nécessaire de prendre en charge toutes les versions actives qui étaient en cours d'utilisation. Nous ne pouvions pas simplement dire à nos utilisateurs: "Les gars, oui, cela ne fonctionne pas pour vous, oui, vous avez besoin de cette fonctionnalité - nous ferons tout dans la version 3, veuillez attendre six mois!"

En conséquence, le refactoring a pris beaucoup de temps, et le processus a été douloureux, ainsi que pour les utilisateurs. Parce qu'au final, nous avons changé l'API sans rétrocompatibilité. Ils sont venus vers eux et ont dit: "Voici un nouveau magnifique SpeechKit, veuillez le prendre!" - ils ont répondu: "Non, nous ne prévoyons pas du tout de passer à votre version 3.0." Par exemple, nous avions une équipe qui est passée à cette version en un an. Par conséquent, pendant une année entière, nous avons pris en charge la version précédente pour eux.

Mais le résultat en valait la peine. Nous avons obtenu une intégration simple et moins de bugs . C'est ce que j'ai mentionné dans les principes de conception de base de l'API. Si vous êtes sûr que votre API est utilisée correctement, il n'y a certainement aucun problème dans cette partie: toutes les classes sont appelées correctement, tous les paramètres sont corrects. Trouver des bogues est beaucoup plus facile, moins de cas où quelque chose pourrait mal se passer.

Vous trouverez ci-dessous un exemple de l'aspect de la classe principale qui traite de la reconnaissance avant la refactorisation.

// SpeechKit v2 @interface YSKRecognizer: NSObject @property (nonatomic, strong, readonly, getter=getModel) NSString* model; @property (nonatomic, assign, getter=isVADEnabled) BOOL VADEnabled; - (instancetype)initWithLanguage:(NSString *)language model:(NSString *)m; - (void)start; - (void)cancel; - (void)cancelSync; @end @interface YSKInitializer: NSObject - (instancetype)init; - (void)dealloc; - (void)start; + (BOOL)isInitializationCompleted; @end extern NSString *const YSKInactiveTimeout; extern NSString *const YSKVADEnabled; @interface YSKSpeechKit: NSObject + (instancetype)sharedInstance; – (void)setParameter:(NSString *)name withValue:(NSString *)value; @end 

Il s'agit d'une classe régulière qui hérite de NSObject. Examinons chacun de ses détails séparément. Il est clair que nous pouvons en hériter, redéfinir certaines méthodes - tout ce qui peut être fait avec NSObject.

Ensuite, lors de la création, deux lignes (langage et modèle) lui sont transmises. Quelles sont ces lignes? Si vous passez dans la langue "Hello, world", alors la sortie sera une traduction, ou quoi? Pas très clair.

De plus, puisque c'est le successeur de NSObject, nous pouvons appeler init, new, etc. dessus. Que va-t-il se passer? Cela fonctionnera-t-il ou attendra-t-il certains paramètres?

Bien sûr, je connais les réponses à ces questions, je connais ce code. Mais les gens qui regardent cela pour la première fois ne comprennent pas du tout pourquoi c'est tout. Même les méthodes avec setter et getter ne ressemblent pas du tout à ce à quoi elles pourraient ressembler dans iOS. Les méthodes start, cancel, cancelSync (et celle qui vient d'annuler - est-ce aSync?) - que se passera-t-il si elles sont appelées ensemble? Beaucoup de questions sur ce code.

Vient ensuite l'objet dont j'ai parlé (YSKInitializer), qui doit être démarré pour que tout fonctionne - c'est généralement une sorte de magie. On peut voir que ce code a été écrit par des développeurs qui n'écrivent pas pour iOS, mais qui sont engagés en C ++.

En outre, les paramètres de ce module de reconnaissance ont été définis via des composants globaux qui ont été transférés vers un autre objet global, et en fait, il était impossible de créer deux modules de reconnaissance différents avec des ensembles de paramètres différents. Et c'était probablement l'un des cas les plus populaires qui ne prenaient pas en charge l'API.

Que v3 est meilleur que v2


Qu'avons-nous obtenu lorsque nous avons refactorisé et passé à la version 3?

  • API entièrement native.

Maintenant, notre API iOS ressemblait à iOS-API, l'API Android ressemblait à Android.

Un point important que nous n'avons pas réalisé immédiatement est que les consignes relatives à la plate-forme sont bien plus importantes que l'uniformité de l'API de votre bibliothèque.

Par exemple, les classes pour Android sont créées à l'aide de constructeurs, car il s'agit d'un modèle très compréhensible pour les développeurs Android. Dans iOS, ce n'est pas si populaire, donc une approche différente est utilisée: nous créons des objets avec une classe spéciale de paramètres.

Je me souviens de la façon dont nous nous sommes longtemps disputés sur ce sujet. Il nous semblait important que le développeur prenne notre code sur iOS ou Android, et la correspondance serait de 99%. Mais ce n'est pas le cas. Mieux, le code sera similaire à la plateforme pour laquelle il est développé.

  • Initialisation simple et intuitive .

Cet objet est nécessaire - voici ses paramètres, créez-les, transférez-les - profitez-en! Autrement dit, aucun paramètre global masqué ne doit être transféré quelque part.

  • Manque de composants mondiaux.

Nous avons jeté des composants mondiaux qui ont dérouté, effrayé et causé beaucoup de questions, même parmi les développeurs de cette bibliothèque, pas seulement les utilisateurs.

Maintenant, la même classe dans la nouvelle version ressemble à ceci (c'est toujours Objective-C - vous ne pouviez pas passer à Swift alors).

 // SpeechKit v3 NS_ASSUME_NONNULL_BEGIN __attribute__((objc_subclassing_restricted)) @interface YSKOnlineRecognizer: NSObject<YSKRecognizing> @property (nonatomic, copy, readonly) YSKOnlineRecognizerSettings *settings; - (instancetype)initWithSettings:(YSKOnlineRecognizerSettings *)s audioSource:(id<YSKAudioSource>)as NS_DESIGNATED_INITIALIZER; + (instancetype)new __attribute__((unavailable("Use designated initializer."))); - (instancetype)init __attribute__((unavailable("Use designated initializer."))); @end NS_ASSUME_NONNULL_END @protocol YSKRecognizing <NSObject> - (void)prepare; - (void)startRecording; - (void)cancel; @end @interface YSKOnlineRecognizerSettings: NSObject<NSCopying> @property (nonatomic, copy, readonly) YSKLanguage *language; @property (nonatomic, copy, readonly) YSKOnlineModel *model; @property (nonatomic, assign) BOOL enableVAD; - (instancetype)initWithLanguage:(YSKLanguage *)l model:(YSKOnlineModel *)m NS_DESIGNATED_INITIALIZER; @end @interface YSKLanguage: YSKSetting + (instancetype)russian; + (instancetype)english; @end 

C'est le successeur de NSObject, mais maintenant nous parlons clairement du fait que vous ne pouvez pas en hériter. Toutes les méthodes caractéristiques de cet objet sont transférées vers un protocole spécial. Il est créé en utilisant les paramètres et audioSource. Maintenant, tous les paramètres sont encapsulés dans un seul objet, qui est transféré spécifiquement ici pour définir les paramètres d'un identificateur spécifique.

De plus, nous avons supprimé le travail avec l'audio d'ici, c'est-à-dire que le reconnaiser n'est plus le composant qui écrit l'audio. Cette composante traite des problèmes de reconnaissance, et n'importe quelle source peut être transférée ici.

Les autres méthodes de création via new ou via init sont interdites, car cette classe nécessite des paramètres par défaut. S'il vous plaît, si vous souhaitez l'utiliser, créez au moins certains paramètres par défaut.

L'essentiel est que ces paramètres qui sont transférés ici sont immuables, c'est-à-dire que vous ne pouvez pas les modifier dans le processus. Pas besoin d'essayer, quand quelque chose est reconnu, de remplacer le modèle ou le langage. En conséquence, nous ne donnons pas aux utilisateurs la possibilité de modifier l'objet avec les paramètres qui ont déjà été transférés.

Macros NS_ASSUME_NONNULL_BEGIN / NS_ASSUME_NONNULL_END afin de souligner que ces paramètres ne peuvent pas être nuls: audioSource ne peut pas être nul - tout doit avoir une valeur spécifique pour fonctionner.

Comme je l'ai dit, les méthodes de démarrage et d'annulation (à gauche cancelSync) ont été déplacées vers un protocole distinct. Il y a des endroits dans la bibliothèque où vous pouvez utiliser non pas notre reconnaiser, mais tout autre. Par exemple, nous utilisons le natif d'Apple, qui implémente ce protocole et dans lequel il peut transférer nos composants.

Les paramètres ici sont NSCopying afin que nous puissions les copier, et ils n'ont pas pu être modifiés dans le processus. En init, les paramètres requis sont la langue, le modèle et NS_DESIGNATED_INITIALIZER. Ce n'est pas un morceau de code identique aux méthodes obsolètes, mais l'idée est claire. Ce sont les paramètres requis avec lesquels les paramètres sont créés. Ils doivent être et doivent être différents de zéro.

Le reste de l'ensemble comprend environ 20 paramètres du module de reconnaissance définis ici. Même les paramètres d'un langage ou d'un modèle sont également des classes distinctes qui ne nous permettent pas de transmettre quelque chose d'abstrait avec lequel nous ne pouvons pas travailler. Autrement dit, nous disons clairement: «S'il vous plaît, ne nous donnez pas quelque chose avec lequel nous ne savons pas travailler. Le compilateur ne vous laissera pas faire cela. »

Nous avons donc parlé de ce que vous pouvez faire avec l'API. Le développement a également ses propres nuances.

Développement


Tout d'abord, la bibliothèque doit faire ce pour quoi vous l'avez écrit - pour bien exécuter ses fonctionnalités. Mais vous pouvez faire de votre code une très bonne bibliothèque. Je propose plusieurs remarques que j'ai collectées lors du développement de SpeechKit.

Le code n'est pas seulement pour vous


Il est absolument nécessaire de collecter des informations de débogage , car vous ne voulez pas que les utilisateurs disent que leur service ne fonctionne pas à cause de votre bibliothèque.

IOS a un niveau d'informations de débogage qui montre quelles informations doivent être collectées. Par défaut, il collectera absolument tout ce qu'il peut trouver: tous les appels, toutes les valeurs. C'est très bien, mais c'est une très grande quantité de données. La définition de -gline-tables-only vous permet de collecter des informations sur les appels de fonction. C'est plus que suffisant pour trouver un problème et le résoudre.

Ceci est inclus dans les paramètres Xcode (Paramètres de construction) et s'appelle le niveau d'informations de débogage. Par exemple, en activant ce paramètre, nous avons réduit la taille du fichier binaire SpeechKit de 600 Mo à 90 Mo. Ce ne sont pas des informations très nécessaires et nous venons de les jeter.

La deuxième chose importante est de cacher les caractères privés . Vous savez tous que chaque fois que vous téléchargez une bibliothèque sur iTunes, vous courez le risque de recevoir un nouvel avertissement indiquant que vous utilisez quelque chose de mal, et que vous n'ajoutez rien. Par conséquent, si vous utilisez des bibliothèques qu'Apple considère comme privées, assurez-vous de les masquer. Cela ne signifie rien pour vous, vous pouvez également travailler avec eux, mais dès que vos utilisateurs essaieront de télécharger l'application avec votre bibliothèque sur iTunes, ils recevront une erreur. Tout le monde ne vous demandera pas de le réparer; la plupart refuseront simplement d'utiliser votre solution.

Évitez les conflits de caractères : ajoutez des préfixes à tout ce que vous avez, à vos classes, aux catégories. Si la bibliothèque a une catégorie UIColor + HEX, assurez-vous que vos utilisateurs ont exactement la même catégorie et lorsqu'ils intégreront votre bibliothèque, ils recevront des conflits de caractères. Et encore une fois, tout le monde ne voudra pas vous le dire et le dire.

Une autre question est lorsque vous utilisez vous-même des bibliothèques tierces dans votre bibliothèque. Il y a quelques nuances qui méritent d'être rappelées. Tout d'abord, si vous utilisez quelque chose qui est apparu dans une version antérieure à votre bibliothèque, n'oubliez pas d'utiliser une liaison faible (Xcode -> Phases de construction -> Lier le binaire aux bibliothèques -> Le statut est activé). Cela vous permet de ne pas tomber si du coup cette bibliothèque ne l'est pas.

La documentation d'Apple explique comment cela fonctionne. Mais une liaison faible ne signifie pas que la bibliothèque ne se chargera pas si elle n'est pas utilisée. Autrement dit, si l'heure de début de l'application est importante pour vos utilisateurs et que vous n'avez pas besoin de la partie de votre bibliothèque qui utilise une bibliothèque tierce et prend du temps pour démarrer, une liaison faible ne vous aidera pas. Avec elle, la bibliothèque se charge toujours, qu'elle soit utilisée ou non.

Si vous souhaitez charger dans le runtime, cela vous aidera à vous débarrasser du problème de lien au démarrage, alors vous devez utiliser dlopen et le chargement dynamique. Cela nécessite beaucoup d'agitation, et vous devez d'abord comprendre si cela a du sens. Facebook a un code assez intéressant pour un exemple de la façon dont ils se sont liés dynamiquement.

Dernier - essayez de ne pas utiliser d'entités globales à l'intérieur . Chaque plate-forme a des composants mondiaux. Il est conseillé de ne pas les faire glisser dans votre bibliothèque. Cela semble évident, car il s'agit d'un objet global, et les utilisateurs de votre bibliothèque peuvent le prendre et le configurer à leur guise. Vous l'utilisez dans votre bibliothèque, vous devez en quelque sorte enregistrer son état, reconfigurer, puis restaurer l'état. Il y a beaucoup de nuances et il y a lieu de se tromper. N'oubliez pas cela et essayez d'éviter.

Par exemple, dans SpeechKit, avant la troisième version, nous avons travaillé avec l'audio à l'intérieur de la bibliothèque, et nous avons explicitement configuré et activé la session audio. Une session audio dans iOS est une chose que toutes les applications ont - ne dites pas que vous n'en avez pas. Il est créé au début, est responsable de l'interaction de l'application et du démon multimédia système, et indique ce que votre application veut faire avec l'audio. Il s'agit d'un objet singleton dans le vrai sens du mot. Nous l'avons calmement pris, configuré selon nos besoins, mais cela a conduit au fait que les utilisateurs avaient des problèmes mineurs comme le changement du volume sonore. Une autre méthode de sessions audio, qui est chargée de définir les paramètres, est assez longue. Cela prend environ 200 ms, et c'est un ralentissement notable lors de l'activation ou de la désactivation.

Dans la troisième version, j'ai joyeusement sorti une session audio de la bibliothèque. Après cela, presque tous les utilisateurs de tous les services qui avaient intégré SpeechKit se sont dit terriblement mécontents. Maintenant, ils devraient savoir qu'il existe une sorte de session audio qui doit être spécialement configurée pour notre SpeechKit.

La conclusion de ceci est la suivante: essayez tout de même de ne pas utiliser des entités globales, mais soyez préparé au fait que vos utilisateurs ne seront pas toujours satisfaits de vos décisions.

Nous le rendons pratique pour les utilisateurs


Comment pouvez-vous aider vos utilisateurs autrement?

  • Ajouter des journaux: différents niveaux, inclusion dynamique .

Le moyen le plus simple consiste à joindre un fichier, pour la présence duquel un mode de débogage méga est lancé. Cela aide vraiment à déboguer dans une situation où vos utilisateurs ont des utilisateurs qui ont une erreur, et vous devez comprendre ce qui s'est exactement passé.

  • Prend en charge toutes les versions du système d'exploitation utilisateur.

N'oubliez pas que lorsque vous parlez de prise en charge des versions dans une bibliothèque, ce n'est pas la même chose que la prise en charge des versions dans une application standard. Dans une application régulière, nous examinons des statistiques selon lesquelles, par exemple, seulement 2% de nos utilisateurs utilisent iOS 8, et cela signifie que vous pouvez arrêter de prendre en charge iOS 8. Dans la bibliothèque, ce n'est pas le cas, ici refuser la version du système d'exploitation signifie abandonner complètement votre utilisateur et tous ses utilisateurs. Cela peut être la moitié de vos utilisateurs en principe.

Par conséquent, vous devez surveiller les versions utilisées par les applications qui utilisent votre bibliothèque, et sur cette base, vous devez déjà déterminer si vous prenez en charge quelque chose ou non. Nous n'avons pas abandonné iOS 7 pendant très longtemps. Il me semble qu'il y avait déjà des gens qui ont abandonné iOS 8 et étaient prêts à abandonner iOS 9. Nous supportions toujours iOS 7 parce que nous avions un navigateur qui, jusqu'à la dernière, gardait tous les utilisateurs et nous avons travaillé en étroite collaboration avec lui et nous ne pouvions pas le laisser dans une telle situation.

Encore une fois, vos utilisateurs ne diront pas: «Désactivons cette fonctionnalité sur la version qui ne la prend pas en charge», non, ils vont simplement supprimer votre bibliothèque et en trouver une qui prend en charge la série complète de versions.

  • Ajoutez un incrément minimal dans les nouvelles versions.

C'est très "pas très" pour les développeurs de bibliothèques. Je veux libérer tout ce qui est prêt pour la sortie. Vous avez créé des fonctionnalités, corrigé des bugs - maintenant, nous allons mettre tout le paquet et le déployer dans la version. La libération est également un processus. Ce n'est pas le cas pour vos utilisateurs. Lorsqu'ils sont en train de tester leur produit et de le préparer pour la sortie, ils ne veulent pas recevoir de vous un assemblage avec de nouvelles fonctionnalités qui nécessitent des tests supplémentaires.

Nous avons vraiment eu des cas où nous avons annulé certaines versions, les avons divisées en parties et les avons déjà déployées en morceaux. Ensuite, les équipes pour lesquelles nous avons implémenté des modifications pourraient prendre exactement la version dans laquelle il y a de petits changements, et pas toutes en même temps.

Ce n'est vraiment pas très pratique pour le développement, mais l'augmentation minimale des versions rendra vos utilisateurs un peu plus heureux.

Il n'y a jamais trop de tests


Cela est vrai à la fois pour une application standard et une bibliothèque. Mais dans le cas de la bibliothèque, il y a des fonctionnalités.

Les autotests , bien sûr, sont nécessaires, mais en plus d'eux, c'est génial d'avoir une application de test pour votre bibliothèque. Cela vous aidera à intégrer ce que vous avez écrit vous-même et à comprendre quels problèmes ou pièges peuvent survenir. Vous pouvez sentir par vous-même ce que sont vos utilisateurs.

Si votre bibliothèque interagit d'une manière ou d'une autre avec le réseau, y compris le chiffrement, il y a au moins quelque chose lié aux données et à la sécurité, donnez-le aux agents de sécurité pour vérification . Vous ne voulez absolument pas être la bibliothèque dans laquelle ils trouvent la vulnérabilité - c'est un stigmate pour la vie. Presque toutes les grandes entreprises ont un service complet qui s'occupe de vérifier la sécurité des produits - donnez-leur-leur. Si vous n'en avez pas, il y a un audit externe . Si vous ne pouvez pas vous permettre l'externe, recherchez les tests sur le réseau, exécutez-les, assurez-vous que votre bibliothèque ne permet pas la fuite de données utilisateur.

La dernière chose qui est très importante dans les tests est dès le début d'essayer d'ajouter des mesures de tout ce qui est possible : temps, consommation d'énergie, tout ce qui est typique de votre bibliothèque particulière. Vous devez toujours le faire à la fin, alors pourquoi ne pas penser aux mesures dès le début.

Cela ne protège pas contre les changements et contre la nécessité d'accélérer la bibliothèque, mais cela aide à comprendre ce qui n'a pas fonctionné. Si vous avez des graphiques, cela vous aidera à surveiller en temps réel les fonctionnalités qui ont ajouté des retards ou augmenté la consommation d'énergie.

Il n'y a presque jamais de temps pour cela, car ce n'est pas la fonctionnalité de la bibliothèque, ce n'est pas pour cela que vous la développez. Mais c'est ce qui vous aide à le maintenir en bon état et de bonne qualité.

Ici, vous pouvez lire comment nous, chez Yandex, mesurons la consommation d'énergie des appareils mobiles. La mesure du temps était une histoire amusante. En tant que développeurs de bibliothèques, il nous est difficile de mesurer le comportement dans des cas spécifiques, car tous les scripts SpeechKit ne sont pas utilisés par toutes les équipes. Pour l'heure, nous avons utilisé notre application de test. Des cas particuliers d'utilisation ont été écrits, par exemple, un module de reconnaissance ou des composants pour la synthèse vocale, chaque étape a été enregistrée et les journaux ont été enregistrés, et en conséquence, des graphiques sympas ont été créés.

Tout irait bien, mais nous travaillons avec l'audio, et pour tout vérifier, dans certains cas, la piste audio joue vraiment. De plus, il est nécessaire de faire beaucoup de mesures, alors ils ont quitté le test pour la nuit: mettez les haut-parleurs, mettez une sorte d'appareil à côté et démarrez les fichiers audio. Le matin, tout s'est éteint, la nuit suivante, cela s'est répété, puis à nouveau. Il ne s'agissait pas du tout de créatures magiques qui se promenaient dans le bureau - juste les nettoyeurs avaient peur. Il y avait vraiment un texte très étrange qui était lu par intervalles.

En conséquence, il a été décidé de faire un banc d'essai local, que nous avons appelé le Cabinet. Il s'agit d'un meuble naturel, uniquement insonorisé. Il contient de nombreux appareils, une batterie de serveurs complète avec des appareils, chacun pouvant être lancé plusieurs fois pendant la journée de travail, car cela ne nuira à personne.

Lancement


Enfin, nous arrivons à la dernière partie importante - c'est le lancement. Le code est écrit, une bonne API est conçue pour le rendre pratique pour les utilisateurs. Comment maintenant publier tout cela dans la version.

Je vais commencer par les versions locales pour les utilisateurs de Yandex. Le schéma ici est le même que pour le développement d'une application régulière: versions régulières, mensuelles ou hebdomadaires.

Le processus comprend les étapes habituelles, mais lors du développement d'une bibliothèque, chacun de ces points a ses propres caractéristiques.

Planification


Pour moi, c'est la partie la plus douloureuse, car la bibliothèque a plusieurs équipes produits. Dans une application régulière, il y a un chef de produit qui définit les tâches que l'équipe priorise et commence à effectuer une à la fois.

S'il existe plusieurs équipes produit, chacune d'entre elles reçoit des demandes qui doivent être traitées en temps réel. Je vais vous conseiller: s'il y a une personne qui sait faire face à une multitude de tâches à venir à un moment donné, essayez de la reprendre dans votre équipe. Parce qu'il doit y avoir quelqu'un entre tous les responsables externes et le développement - celui qui assumera la fonctionnalité de priorisation des tâches.

SpeechKit , , , . , , - . , — . , n . , . , , - .



, , : , , . Agile- .

, , , — . , . !

Scrum . , , , . . « », .

Scrum , , , — — , . . — , - . , ? , : «, , , ». , , - , , Scrum . ! , .

. , , . , . , , , , . , . .

Le soutien


, — , - . , , , , . , . : « 4, 3 — ». , . - , , , , .

. Continuous Integration , , , .



, . .

1. .

. - - , , , . .

. , — , , , , . , , - .

2. .

, , , — , , , , , !

. , . , , -, .

. SpeechKit . , , — , - . — , - .

, . , 4 2, , . , -, , .

. , , , .

. .


, -, . . , , , help , .

. : -, GitHub, , . — , — . , , .

, , - , , ..



, , :

  • . , . - , , .
  • . , . , OpenSource , , , , .
  • . , . , , . . SpeechKit .

Résumé


  • , API.
  • , , .
  • .
  • , - :) - , .

Yandex.SpeachKit GitHub iOS , Android , Mobile SDK.

AppsConf — — 22 23 2019 , , .

. , , .

Source: https://habr.com/ru/post/fr429912/


All Articles