Desarrollo de bibliotecas: de API a lanzamiento público

Miremos las bibliotecas no desde el lado que nos es más familiar, es decir, desde el usuario, sino desde el punto de vista del desarrollador de la biblioteca de desarrollo móvil. Hablemos sobre los enfoques que se deben seguir al desarrollar su biblioteca. Comenzamos, por supuesto, diseñando una API tal que usted mismo quisiera usar, lo cual sería conveniente. Pensaremos en lo que debe tenerse en cuenta para hacer no solo un código que funcione, sino una biblioteca realmente buena, y llegaremos al punto de lanzar un lanzamiento público real para adultos. Asya Sviridenko nos ayudará en esto, quien compartirá su considerable experiencia en el desarrollo de la biblioteca móvil SpeechKit en Yandex .

El material será útil no solo para aquellos involucrados en el desarrollo de una biblioteca o marco, sino también para aquellos que desean separar una parte de su aplicación en un módulo separado y luego reutilizarla o, por ejemplo, compartir su código con el resto de la comunidad de desarrolladores al publicarlo en acceso publico.

Para todos los demás, la historia estará llena de historias genuinas de la vida del equipo móvil SpeechKit, por lo que debería ser divertido.


Contenido


  • SpeechKit minuto .
  • Diseñando una API conveniente y comprensible que quieras usar.
  • Desarrollo . Qué agregar al código para que no solo funcione y realice funciones, sino que también ayude a sus usuarios.
  • Lanzamiento : lo que no debe olvidar cuando lanza el lanzamiento.


SpeechKit minuto


No le preguntaré si escuchó sobre SpeechKit, porque incluso dentro de Yandex, no todos saben lo que es.

SpeechKit es la puerta a todas las tecnologías de voz de Yandex . Con esta biblioteca, puede integrar tecnologías de voz en su aplicación: reconocimiento y síntesis de voz, activación por voz.

Probablemente escuchaste sobre la asistente de voz Alice, ella solo trabaja sobre la base de SpeechKit. SpeechKit en sí no incluye reconocimiento o síntesis, sucede en el servidor. Pero es a través de nuestra biblioteca que todo se puede integrar en la aplicación.

La siguiente pregunta suele ser: si sucede todo en el servidor, ¿qué hace la biblioteca? ¿Por qué es necesario?

La biblioteca hace mucho:

  1. Sincronización de todos los procesos. Por ejemplo, al usar un asistente de voz, un usuario hace clic en un botón, dice algo, interrumpe al asistente, hace solicitudes, todo pasa por la biblioteca. Para el usuario de nuestra biblioteca esto es transparente, no deben preocuparse por todo esto.
  2. Redes Como todo sucede en el servidor, debe obtener datos desde allí, procesarlos y entregárselos al usuario. SpeechKit ahora puede ir a varios servidores diferentes dentro de la misma conexión de red: uno está dedicado al reconocimiento, el otro está en la asignación de significado, el tercero está en el reconocimiento de música, etc. Todo esto está oculto dentro de la biblioteca, los usuarios no necesitan preocuparse por ello.
  3. Trabaja con fuentes de audio. Estamos tratando con el habla humana, y el trabajo con audio también ocurre dentro de SpeechKit. Además, no solo podemos escribir desde un dispositivo estándar, sino también recibir datos desde cualquier lugar. Puede ser un archivo o una secuencia; podemos trabajar con todo esto.

SpeechKit se usa en equipos internos. Ahora ha sido integrado por 16 equipos de Yandex. E incluso sabemos sobre varios equipos externos que también hicieron esto.

Diseño


Pensemos en lo que queremos decir con una aplicación conveniente. Por lo general, esta es una experiencia de usuario reflexiva y comprensible, la solución a nuestros problemas, operación estable, etc.

Cuando decimos que una biblioteca es conveniente, en primer lugar queremos decir que tiene una API que es fácil de usar. ¿Cómo lograr esto?

Principios básicos


Estos son algunos de los aspectos que he aprendido de mi experiencia con SpeechKit.

  • En primer lugar, recuerde que sus usuarios son desarrolladores .

Por un lado, es bueno, porque no explicas a los usuarios comunes: "Verás, el backend está con nosotros y, por lo tanto, nada funciona, ¡y estamos bien!" Puede explicárselo a los desarrolladores, ¡puede explicarles mucho a los desarrolladores!

Por otro lado, obtienes esos usuarios que definitivamente aprovecharán la oportunidad de encontrar un agujero y romper algo si lo dejas. Todos usamos bibliotecas e intentamos aprovecharlas al máximo. Afirman que solo están haciendo esto, esto y esto, y estamos pensando: "No, ahora jugaremos una pequeña broma aquí, la pasaremos y todo será como debería".

Además, el hecho de que los usuarios sean desarrolladores significa que siempre tendrá una montaña de consejos y trucos sobre cómo desarrollar y cómo mejorar todo.

El segundo punto importante es totalmente consistente con el primero.

  • Todo lo que no esté permitido en su biblioteca debe estar prohibido,
    para que no haya lagunas no deseadas.

Si sus usuarios comienzan a hacer algo con la biblioteca que no esperaba, esta es una ruta directa a los errores y aquellos que son difíciles de depurar. Trate de usar todo lo que el lenguaje le da y la tecnología que usa: público / privado, final, obsoleto, de solo lectura. Reduzca el alcance, prohíba la herencia y el uso de algunos métodos, marque las propiedades que no se pueden cambiar: proporcione todo lo posible para evitar algo para lo que su biblioteca simplemente no está diseñada.

  • No permita ambigüedades en la interpretación de la API de su biblioteca.

Si esta clase particular se puede crear de una manera, niegue todas las demás. Si esta propiedad no puede ser nula, especifíquela explícitamente. En iOS hay un inicializador designado nulo / no nulo, lo mismo ocurre en Java y Android. Use todo esto para que el usuario abra el archivo, abra su clase, lo revise e inmediatamente comprenda qué se puede hacer y qué no se puede hacer.

Case SpeechKit API


Usando SpeechKit como ejemplo, le diré cómo refactorizamos la versión 2 a la versión 3. Cambiamos mucho la API e intentamos usar todos estos principios.

La necesidad surgió porque la API era compleja y "teórica" . Había componentes globales que debían llamarse primero, no llamarse, no todo funcionó. Se establecieron configuraciones muy extrañas. La API era bastante "teórica", porque SpeechKit era originalmente parte del navegador, y luego esta pieza fue llevada a la biblioteca. La API esencialmente funcionó con los casos utilizados en Navigator.

Poco a poco, el número de usuarios creció y comenzamos a comprender lo que realmente necesitaban: qué métodos, devoluciones de llamada, parámetros. Nos llegaron con solicitudes que la API no permitió implementar. Esto se repitió una y otra vez, y quedó claro que la API no estaba a la altura. Entonces nos involucramos en la refactorización.

El proceso de refactorización fue largo (medio año) y doloroso (todos estaban descontentos) . La principal dificultad era no tomar una montaña de código y reescribirla. Era imposible simplemente refactorizar, pero era necesario admitir todas las versiones activas que estaban en uso. No podríamos simplemente decirles a nuestros usuarios: "Chicos, sí, no funciona para ustedes, sí, necesitan esta función: haremos todo en la versión 3, ¡esperen seis meses!"

Como resultado, la refactorización tomó mucho tiempo, y el proceso fue doloroso, y también para los usuarios. Porque al final, cambiamos la API sin compatibilidad con versiones anteriores. Se acercaron a ellos y dijeron: "Aquí hay un nuevo y hermoso SpeechKit, ¡tómalo!" - respondieron: "No, no tenemos planes de actualizar a su versión 3.0 en absoluto". Por ejemplo, tuvimos un equipo que cambió a esta versión dentro de un año. Por lo tanto, durante todo un año apoyamos la versión anterior para ellos.

Pero el resultado valió la pena. Obtuvimos una integración simple y menos errores . Esto es lo que mencioné en los principios básicos de diseño de la API. Si está seguro de que su API se está utilizando correctamente, definitivamente no hay problemas en esta parte: todas las clases se llaman correctamente, todos los parámetros son correctos. Encontrar errores es mucho más fácil, menos casos en los que algo puede salir mal.

A continuación se muestra un ejemplo de cómo se veía la clase principal que se ocupa del reconocimiento antes de refactorizar.

// 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 

Esta es una clase regular que hereda de NSObject. Consideremos cada uno de sus detalles por separado. Está claro que podemos heredar de él, redefinir algunos métodos en él, todo lo que se puede hacer con NSObject.

Luego, al crear, se le pasan dos líneas (lenguaje y modelo). ¿Qué son estas líneas? Si pasa el idioma "Hola, mundo", entonces la salida será una traducción, ¿o qué? No muy claro.

Además, dado que este es el sucesor de NSObject, podemos llamar a init, new, etc. Que va a pasar ¿Funcionará o esperará algunos parámetros?

Por supuesto, sé las respuestas a estas preguntas, conozco este código. Pero las personas que miran esto por primera vez no entienden por qué esto es todo. Incluso los métodos con setter y getter no miran en absoluto cómo podría ser en iOS. Los métodos start, cancel, cancelSync (y el que simplemente cancela, ¿es aSync?), ¿Qué sucederá si se convocan juntos? Muchas preguntas a este código.

Luego viene el objeto del que hablé (YSKInitializer), que debe iniciarse para que todo funcione, generalmente es algún tipo de magia. Se puede ver que este código fue escrito por desarrolladores que no escriben para iOS, pero están comprometidos con C ++.

Además, la configuración de este reconocedor se estableció a través de componentes globales que se transfirieron a otro objeto global, y de hecho fue imposible crear dos reconocedores diferentes con diferentes conjuntos de parámetros. Y este fue probablemente uno de los casos más populares que no admitía la API.

Que v3 es mejor que v2


¿Qué obtuvimos cuando reestructuramos y cambiamos a la versión 3?

  • API completamente nativa.

Ahora nuestra API de iOS se parecía a la API de iOS, la API de Android se parecía a Android.

Un punto importante que no nos dimos cuenta de inmediato es que las pautas de la plataforma son mucho más importantes que la uniformidad de la API de su biblioteca.

Por ejemplo, las clases para Android se crean utilizando constructores, porque este es un patrón muy comprensible para los desarrolladores de Android. En iOS, esto no es tan popular, por lo que se utiliza un enfoque diferente: creamos objetos con una clase especial de configuraciones.

Recuerdo cómo discutimos durante mucho tiempo sobre este tema. Nos pareció importante que el desarrollador tomara nuestro código en iOS o Android, y la coincidencia sería del 99%. Pero esto no es así. Mejor, el código será similar a la plataforma para la cual se está desarrollando.

  • Inicialización simple e intuitiva .

Este objeto es necesario: aquí están sus configuraciones, créelos, transfiéralos: ¡obtenga ganancias! Es decir, no hay configuraciones globales ocultas que deban transferirse a alguna parte.

  • Falta de componentes globales.

Descartamos componentes globales que confundieron, asustaron y causaron muchas preguntas incluso entre los desarrolladores de esta biblioteca, no solo los usuarios.

Ahora la misma clase en la nueva versión se ve así (sigue siendo Objective-C, entonces no puedes cambiar a Swift).

 // 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 

Este es el sucesor de NSObject, pero ahora estamos hablando claramente del hecho de que no puede heredar de él. Todos los métodos que son característicos de este objeto se transfieren a un protocolo especial. Se crea usando la configuración y audioSource. Ahora todas las configuraciones están encapsuladas en un solo objeto, que se transfiere específicamente aquí para establecer las configuraciones para un reconocedor específico.

Además, eliminamos el trabajo con audio de aquí, es decir, el explorador ahora no es el componente que escribe audio. Este componente trata los problemas de reconocimiento, y cualquier fuente puede transferirse aquí.

Se prohíben otros métodos de creación a través de new o init, porque esta clase necesita una configuración predeterminada. Por favor, si desea usarlo, cree al menos algunas configuraciones predeterminadas.

Lo principal es que las configuraciones que se transfieren aquí son inmutables, es decir, no puede cambiarlas en el proceso. No es necesario intentar, cuando se reconoce algo, reemplazar el modelo o el idioma. En consecuencia, no les damos a los usuarios la oportunidad de cambiar el objeto con la configuración que ya se ha transferido.

Macros NS_ASSUME_NONNULL_BEGIN / NS_ASSUME_NONNULL_END para enfatizar que esta configuración no puede ser nula: audioSource no puede ser nulo; todo debe tener algún valor específico para que funcione.

Como dije, los métodos de inicio y cancelación (cancelSync a la izquierda) se trasladaron a un protocolo separado. Hay lugares en la biblioteca donde puede usar no nuestro explorador, sino cualquier otro. Por ejemplo, utilizamos el nativo de Apple, que implementa este protocolo y al cual puede transferir nuestros componentes.

La configuración aquí es NSCopying para que podamos copiarla y no se puedan cambiar en el proceso. En init, los parámetros requeridos son idioma, modelo y NS_DESIGNATED_INITIALIZER. Este no es un código idéntico a los métodos obsoletos, pero la idea es clara. Estos son parámetros obligatorios con los que se crean las configuraciones. Deben ser y no deben ser cero.

El resto del conjunto es de aproximadamente 20 configuraciones del reconocedor que se establecen aquí. Incluso la configuración de un idioma o modelo también son clases separadas que no nos permiten transmitir algo abstracto, con el que no podemos trabajar. Es decir, decimos claramente: “Por favor, no nos des algo con lo que no sabemos cómo trabajar. El compilador no te permitirá hacer esto ".

Entonces, hablamos sobre lo que puede hacer con la API. El desarrollo también tiene sus propios matices.

Desarrollo


En primer lugar, la biblioteca debe hacer lo que usted escribió para realizar bien su funcionalidad. Pero puede hacer que su código sea una biblioteca realmente buena. Propongo varios comentarios que recopilé durante el desarrollo de SpeechKit.

El código no es solo para ti


Es absolutamente necesario recopilar información de depuración , ya que no desea que los usuarios digan que su servicio no funciona debido a su biblioteca.

IOS tiene un nivel de información de depuración que muestra qué información debe recopilarse. Por defecto, recopilará absolutamente todo lo que pueda encontrar: todas las llamadas, todos los valores. Esto es genial, pero es una gran cantidad de datos. Establecer -gline-tables-only le permite recopilar información sobre llamadas a funciones. Esto es más que suficiente para encontrar un problema y solucionarlo.

Esto se incluye en la configuración de Xcode (Configuración de compilación) y se denomina nivel de información de depuración. Por ejemplo, al activar esta configuración, redujimos el tamaño del archivo binario SpeechKit de 600 MB a 90 MB. Esta información no es muy necesaria y la descartamos.

La segunda cosa importante es ocultar personajes privados . Todos saben que cada vez que carga una biblioteca en iTunes, corre el riesgo de recibir una nueva advertencia de que está usando algo incorrecto, no agregando algo. Por lo tanto, si usa bibliotecas que Apple considera privadas, asegúrese de ocultarlas. Esto no significa nada para usted, también puede trabajar con ellos, pero tan pronto como sus usuarios intenten cargar la aplicación con su biblioteca en iTunes, recibirán un error. No todos le pedirán que lo arregle; la mayoría simplemente se negará a usar su solución.

Evite conflictos de caracteres : agregue prefijos a todo lo que tenga, a sus clases, a categorías. Si la biblioteca tiene una categoría UIColor + HEX, asegúrese de que sus usuarios tengan exactamente la misma categoría, y cuando integren su biblioteca, recibirán conflictos de caracteres. Y nuevamente, no todos querrán decírtelo y decirlo.

Otra pregunta es cuando usted mismo utiliza bibliotecas de terceros en su biblioteca. Hay un par de matices que vale la pena recordar. En primer lugar, si usa algo que apareció en una versión anterior a su biblioteca, no olvide usar Vinculación débil (Xcode -> Fases de compilación -> Enlace binario con bibliotecas -> El estado está activado). Esto le permite no caerse si de repente esta biblioteca no lo es.

La documentación de Apple detalla cómo funciona esto. Pero un enlace débil no significa que la biblioteca no se cargará si no se usa. Es decir, si la hora de inicio de la aplicación es importante para sus usuarios, y es posible que no necesite la parte de su biblioteca que utiliza una biblioteca de terceros y toma tiempo para comenzar, los enlaces débiles no lo ayudarán. Con él, la biblioteca aún se carga si se usa o no.

Si desea cargar en tiempo de ejecución, esto ayudará a deshacerse del problema del enlace al inicio, entonces debe usar dlopen y carga dinámica. Esto requiere mucho alboroto, y primero debes entender si esto tiene sentido. Facebook tiene un código bastante interesante para un ejemplo de cómo se vincularon dinámicamente.

Por último, intente no utilizar entidades globales dentro . Cada plataforma tiene algunos componentes globales. Es recomendable no arrastrarlos a su biblioteca. Esto parece obvio porque es un objeto global, y los usuarios de su biblioteca pueden tomarlo y configurarlo como quieran. Lo usa en su biblioteca, necesita guardar de alguna manera su estado, reconfigurarlo y luego restaurarlo. Hay muchos matices y hay dónde cometer un error. Recuerda esto y trata de evitarlo.

Por ejemplo, en SpeechKit, antes de la tercera versión, trabajamos con audio dentro de la biblioteca, y configuramos y activamos explícitamente la sesión de audio. Una sesión de audio en iOS es algo que todas las aplicaciones tienen, no digas que no tienes una. Se crea al principio, es responsable de la interacción de la aplicación y el demonio de medios del sistema, y ​​dice lo que su aplicación quiere hacer con el audio. Este es un objeto singleton en el verdadero sentido de la palabra. Lo tomamos con calma, lo configuramos como lo necesitábamos, pero esto llevó al hecho de que los usuarios tenían problemas menores como cambiar el volumen del sonido. Otro método de sesiones de audio, que se encarga de establecer la configuración, es bastante largo. Tarda unos 200 ms, y esta es una desaceleración notable en la activación o desactivación.

En la tercera versión, alegremente saqué una sesión de audio de la biblioteca. Después de eso, casi todos los usuarios de todos los servicios que tenían integrado SpeechKit dijeron que estaban terriblemente descontentos. Ahora deberían saber que hay algún tipo de sesión de audio que debe configurarse especialmente para nuestro SpeechKit.

La conclusión de esto es esta: de todos modos, trate de no usar entidades globales, pero esté preparado para el hecho de que sus usuarios no siempre estarán contentos con sus decisiones.

Lo hacemos conveniente para los usuarios.


¿De qué otra forma puedes ayudar a tus usuarios?

  • Agregar registros: diferentes niveles, inclusión dinámica .

La forma más fácil es adjuntar un archivo, para cuya presencia se inicia un modo de mega depuración. Realmente ayuda a hacer la depuración en una situación en la que sus usuarios tienen usuarios que tienen un error, y necesita comprender qué sucedió exactamente.

  • Admite todas las versiones del sistema operativo del usuario.

Recuerde que cuando habla del soporte de versiones en una biblioteca, no es lo mismo que el soporte de versiones en una aplicación normal. En una aplicación normal, observamos estadísticas que, por ejemplo, solo el 2% de nuestros usuarios usan iOS 8, y eso significa que puede dejar de admitir iOS 8. En la biblioteca, no es así, aquí rechazar la versión del sistema operativo significa abandonar completamente a su usuario y a todos sus usuarios. Esto puede ser la mitad de sus usuarios en principio.

Por lo tanto, debe controlar qué versiones utilizan las aplicaciones que usan su biblioteca y, basándose en esto, ya debe concluir si admite algo o no. No abandonamos iOS 7 durante mucho tiempo. Me parece que ya había personas que abandonaron iOS 8 y estaban listas para abandonar iOS 9. Todavía admitíamos iOS 7 porque teníamos un navegador que hasta el último mantenía a todos los usuarios y trabajamos estrechamente con él y no pudimos dejarlo en tal situación.

Una vez más, sus usuarios no dirán: "Desactivemos esta funcionalidad en la versión que no lo admite", no, simplemente eliminarán su biblioteca y encontrarán una que sea compatible con toda la serie de versiones.

  • Agregue un incremento mínimo en nuevas versiones.

Esto es muy "no muy" para los desarrolladores de bibliotecas. Quiero lanzar todo lo que está listo para el lanzamiento. Realizó funciones, corrigió errores: ahora colocaremos todo el paquete y lo lanzaremos al lanzamiento. La liberación también es un proceso. Esto no es así para sus usuarios. Cuando están en el proceso de probar su producto y prepararlo para su lanzamiento, no quieren recibir de usted un conjunto con nuevas características que necesitan pruebas adicionales.

Realmente tuvimos casos en los que retrocedimos algunos lanzamientos, los dividimos en partes y los desplegamos en pedazos. Entonces, los equipos para los que implementamos cambios podrían tomar exactamente la versión en la que hay pequeños cambios, y no todos a la vez.

Esto realmente no es muy conveniente para el desarrollo, pero el incremento mínimo en las versiones hará que sus usuarios estén un poco más felices.

Nunca hay demasiadas pruebas


Esto es cierto tanto para una aplicación regular como para una biblioteca. Pero en el caso de la biblioteca nuevamente, hay características.

Las pruebas automáticas , por supuesto, son necesarias, pero además de ellas es genial tener una aplicación de prueba para su biblioteca. Le ayudará a integrar lo que escribió usted mismo y comprender qué problemas o dificultades pueden surgir. Puedes sentir por ti mismo cuáles son tus usuarios.

Si su biblioteca de alguna manera interactúa con la red, incluye cifrado, hay al menos algo relacionado con los datos y la seguridad, déselo a los guardias de seguridad para su verificación . Absolutamente no quieres ser la biblioteca en la que encuentran la vulnerabilidad, es un estigma para la vida. Casi todas las grandes empresas tienen un departamento completo que se ocupa de verificar la seguridad de los productos, dárselos. Si no tiene uno, hay una auditoría externa . Si no puede pagar lo externo, busque las pruebas en la red, ejecútelas y asegúrese de que su biblioteca no permita la fuga de datos de los usuarios.

Lo último que es muy importante en las pruebas es, desde el principio, intentar agregar medidas de todo lo que sea posible : tiempo, consumo de energía, todo lo que es típico de su biblioteca en particular. Todavía tiene que hacer esto al final, entonces, ¿por qué no pensar en las mediciones desde el principio?

Esto no protege contra cambios y la necesidad de acelerar la biblioteca, pero ayuda a descubrir qué salió mal. Si tiene gráficos, esto ayudará en el monitoreo en tiempo real de qué funcionalidad agrega demoras o aumenta el consumo de energía.

Casi nunca hay tiempo para esto, porque esta no es la funcionalidad de la biblioteca, no es para lo que la está desarrollando. Pero esto es lo que le ayuda a mantenerlo en buenas condiciones y de buena calidad.

Aquí puede leer cómo nosotros, en Yandex, medimos el consumo de energía de los dispositivos móviles. Sobre las mediciones de tiempo fue una historia divertida. Como desarrolladores de bibliotecas, es difícil para nosotros medir el comportamiento en casos específicos, porque no todos los scripts de SpeechKit son utilizados por todos los equipos. Hasta el momento, utilizamos nuestra aplicación de prueba. Se escribieron casos especiales de uso, por ejemplo, un reconocedor o componentes para la síntesis de voz, se grabó cada paso y se guardaron registros, y como resultado, se construyeron gráficos geniales.

Todo estaría bien, pero trabajamos con audio, y para verificarlo todo, en ciertos casos la pista de audio realmente se reproduce. Además, es necesario hacer muchas mediciones, por lo que dejaron la prueba por la noche: coloque los altavoces, coloque algún tipo de dispositivo al lado e inició los archivos de audio. Por la mañana todo se apagó, la noche siguiente se repitió, y luego otra vez. No se trataba en absoluto de algunas criaturas mágicas que caminaban por la oficina, solo los limpiadores estaban asustados. Realmente había un texto muy extraño que se leía a intervalos.

Como resultado, se decidió hacer un banco de pruebas local, al que llamamos Gabinete. Este es un gabinete natural, solo insonorizado. Contiene muchos dispositivos, toda una granja con dispositivos, cada uno de los cuales se puede lanzar muchas veces durante la jornada laboral, porque no dañará a nadie.

Lanzamiento


Finalmente llegamos a la última parte importante: este es el lanzamiento. El código está escrito, una buena API está diseñada para que sea conveniente para los usuarios. Cómo ahora lanzar todo esto en libertad.

Comenzaré con lanzamientos locales para usuarios dentro de Yandex. El esquema aquí es el mismo que en el desarrollo de una aplicación regular: lanzamientos regulares, mensuales o semanales.

El proceso consta de las etapas habituales, pero al desarrollar una biblioteca, cada uno de estos puntos tiene sus propias características.

Planificacion


Para mí, esta es la parte más dolorosa, porque la biblioteca tiene varios equipos de productos. En una aplicación normal, hay un gerente de producto que establece tareas que el equipo prioriza y comienza a hacer una a la vez.

Si hay varios equipos de productos, cada uno de ellos recibe solicitudes que deben procesarse en tiempo real. Daré un consejo: si hay una persona que sabe cómo hacer frente a una multitud de tareas en un momento, trate de recogerlo en su equipo. Porque debe haber alguien entre todos los gerentes externos y el desarrollo, el que asumirá la funcionalidad para priorizar las tareas.

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



, , : , , . Agile- .

, , , — . , . !

Scrum . , , , . . « », .

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

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



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

. Continuous Integration , , , .



, . .

1. .

. - - , , , . .

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

2. .

, , , — , , , , , !

. , . , , -, .

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

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

. , , , .

. .


, -, . . , , , help , .

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

, , - , , ..



, , :

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

Resumen


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

Yandex.SpeachKit GitHub iOS , Android , Mobile SDK.

AppsConf — — 22 23 2019 , , .

. , , .

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


All Articles