Betrachten wir die Bibliotheken nicht von der Seite, die uns am vertrautesten ist, dh vom Benutzer, sondern aus der Sicht des Entwicklers der mobilen Entwicklungsbibliothek. Lassen Sie uns darüber sprechen, welche Ansätze bei der Entwicklung Ihrer Bibliothek verfolgt werden sollten. Wir beginnen natürlich damit, eine solche API zu entwerfen, die Sie selbst verwenden möchten, was praktisch wäre. Wir werden darüber nachdenken, was berücksichtigt werden muss, um nicht nur funktionierenden Code, sondern eine wirklich gute Bibliothek zu erstellen, und eine echte öffentliche Veröffentlichung für Erwachsene zu veröffentlichen.
Asya Sviridenko wird uns dabei helfen und ihre beachtlichen Erfahrungen bei der Entwicklung der mobilen SpeechKit-Bibliothek in
Yandex teilen.
Das Material ist nicht nur für diejenigen nützlich, die an der Entwicklung einer Bibliothek oder eines Frameworks beteiligt sind, sondern auch für diejenigen, die einen Teil von ihrer Anwendung in ein separates Modul trennen und ihn dann wiederverwenden oder beispielsweise ihren Code mit dem Rest der Entwicklergemeinschaft teilen möchten, indem sie ihn veröffentlichen öffentlicher Zugang.
Für alle anderen wird die Geschichte mit echten Geschichten aus dem Leben des mobilen SpeechKit-Teams gefüllt sein, also sollte es Spaß machen.
Inhalt
- SpeechKit Minute .
- Entwerfen einer praktischen, verständlichen API, die Sie verwenden möchten.
- Entwicklung . Was Sie dem Code hinzufügen müssen, damit er nicht nur funktioniert und Funktionen ausführt, sondern auch Ihren Benutzern hilft.
- Starten - was Sie beim Roll-Release nicht vergessen sollten.
SpeechKit Minute
Ich werde nicht fragen, ob Sie von SpeechKit gehört haben, denn selbst in Yandex weiß nicht jeder, was es ist.
SpeechKit ist die Tür zu allen Yandex-Sprachtechnologien . Mit dieser Bibliothek können Sie Sprachtechnologien in Ihre Anwendung integrieren: Spracherkennung und -synthese, Sprachaktivierung.
Sie haben wahrscheinlich von der Sprachassistentin Alice gehört - sie arbeitet nur auf der Basis von SpeechKit. SpeechKit selbst enthält keine Erkennung oder Synthese, sondern erfolgt auf dem Server. Über unsere Bibliothek kann jedoch alles in die Anwendung integriert werden.
Das Folgende ist normalerweise die Frage: Wenn alles auf dem Server passiert, was macht die Bibliothek? Warum wird es benötigt?
Die Bibliothek macht viel:
- Synchronisation aller Prozesse. Mit einem Sprachassistenten klickt der Benutzer beispielsweise auf eine Schaltfläche, sagt etwas, unterbricht den Assistenten, stellt Anforderungen - alles geht durch die Bibliothek. Für den Benutzer unserer Bibliothek ist dies transparent, er sollte sich darüber keine Sorgen machen.
- Vernetzung Da alles auf dem Server geschieht, müssen Sie Daten von dort abrufen, verarbeiten und dem Benutzer übergeben. SpeechKit kann jetzt zu mehreren verschiedenen Servern innerhalb derselben Netzwerkverbindung gehen: Einer befasst sich mit der Erkennung, der andere mit der Zuweisung von Bedeutungen, der dritte mit der Musikerkennung usw. Dies ist alles in der Bibliothek versteckt, Benutzer müssen sich darüber keine Sorgen machen.
- Arbeiten Sie mit Audioquellen. Wir haben es mit menschlicher Sprache zu tun, und die Arbeit mit Audio findet auch in SpeechKit statt. Darüber hinaus können wir nicht nur von einem Standardgerät aus schreiben, sondern auch Daten von überall empfangen. Es kann eine Datei oder ein Stream sein - wir können mit all dem arbeiten.
SpeechKit wird in internen Teams verwendet. Jetzt wurde es von 16 Yandex-Teams integriert. Und wir kennen sogar einige externe Teams, die dies ebenfalls getan haben.
Design
Lassen Sie uns darüber nachdenken, was wir unter einer praktischen Anwendung verstehen. Normalerweise ist dies eine durchdachte und verständliche UX, die Lösung für unsere Probleme, ein stabiler Betrieb usw.
Wenn wir sagen, dass eine Bibliothek praktisch ist, meinen wir zunächst, dass sie eine solche API hat, dass sie einfach zu verwenden ist. Wie erreicht man das?
Grundprinzipien
Dies sind einige der Aspekte, die ich aus meinen Erfahrungen mit SpeechKit gelernt habe.
- Denken Sie zunächst daran, dass Ihre Benutzer Entwickler sind .
Einerseits ist dies gut, da Sie normalen Benutzern nicht erklären können: "Sie sehen, das Backend ist bei uns, und daher funktioniert nichts, und es geht uns gut!" Sie können es den Entwicklern erklären - Sie können den Entwicklern viel erklären!
Auf der anderen Seite erhalten Sie solche Benutzer, die definitiv die Gelegenheit nutzen, ein Loch zu finden und etwas zu brechen, wenn Sie es verlassen. Wir alle nutzen Bibliotheken und versuchen, das Beste aus ihnen herauszuholen. Sie behaupten, dass sie nur dies, dies und das tun, und wir denken: "Nein, jetzt spielen wir hier einen kleinen Streich, wir geben ihn weiter und alles wird so sein, wie es sollte."
Die Tatsache, dass Benutzer Entwickler sind, bedeutet außerdem, dass Sie immer eine Menge Tipps und Tricks zur Entwicklung und Verbesserung haben.
Der zweite wichtige Punkt stimmt voll und ganz mit dem ersten überein.
- Alles, was in Ihrer Bibliothek nicht erlaubt ist, sollte verboten werden.
damit es keine unerwünschten Schlupflöcher gibt.
Wenn Ihre Benutzer anfangen, etwas mit der Bibliothek zu tun, das Sie nicht erwartet haben, ist dies ein direkter Pfad zu Fehlern und solchen, die schwer zu debuggen sind. Versuchen Sie, alles zu verwenden, was die Sprache und die von Ihnen verwendete Technologie bietet: öffentlich / privat, endgültig, veraltet, schreibgeschützt. Reduzieren Sie den Umfang, verbieten Sie die Vererbung und die Verwendung einiger Methoden, markieren Sie Eigenschaften, die nicht geändert werden können - bieten Sie alles Mögliche, um zu verhindern, dass Ihre Bibliothek einfach nicht dafür ausgelegt ist.
- Lassen Sie keine Unklarheiten bei der Interpretation der API Ihrer Bibliothek zu.
Wenn diese bestimmte Klasse auf eine Weise erstellt werden kann, verweigern Sie alle anderen. Wenn diese Eigenschaft nicht null sein kann, geben Sie sie explizit an. In iOS gibt es nullable / nonnull, als Initialisierer bezeichnet, das gleiche gilt für Java und Android. Verwenden Sie all dies, damit der Benutzer die Datei öffnen, Ihre Klasse öffnen, sie durchgehen und sofort verstehen kann, was getan werden kann und was nicht.
Case SpeechKit API
Am Beispiel von SpeechKit werde ich Ihnen erklären, wie wir Version 2 auf Version 3 umgestaltet haben. Wir haben die API stark geändert und versucht, all diese Prinzipien zu verwenden.
Der Bedarf entstand, weil die
API komplex und „theoretisch“ war . Es gab globale Komponenten, die zuerst aufgerufen werden mussten - nicht aufgerufen - alles funktionierte nicht. Es wurden sehr seltsame Einstellungen vorgenommen. Die API war ziemlich „theoretisch“, da SpeechKit ursprünglich Teil des Navigators war und dieses Teil dann in die Bibliothek gebracht wurde. Die API funktionierte im Wesentlichen mit den in Navigator verwendeten Fällen.
Allmählich wuchs die Anzahl der Benutzer und wir begannen zu verstehen, was sie wirklich brauchten: welche Methoden, Rückrufe, Parameter. Sie kamen mit Anfragen zu uns, die die API nicht implementieren ließ. Dies wurde immer wieder wiederholt und es wurde klar, dass die API nicht standhielt. Also haben wir uns mit Refactoring beschäftigt.
Der Refactoring-Prozess war lang (ein halbes Jahr) und schmerzhaft (alle waren unglücklich) . Die Hauptschwierigkeit bestand darin, keinen Berg Code zu nehmen und ihn neu zu schreiben. Es war unmöglich, einfach ein Refactoring durchzuführen, aber es war notwendig, alle aktiven Versionen zu unterstützen, die verwendet wurden. Wir konnten unseren Benutzern nicht einfach sagen: "Leute, ja, es funktioniert nicht für Sie, ja, Sie benötigen diese Funktion - wir werden alles in Version 3 tun, bitte warten Sie sechs Monate!"
Infolgedessen dauerte das Refactoring lange, und der Prozess war schmerzhaft, und auch für die Benutzer. Denn am Ende haben wir die API ohne Abwärtskompatibilität geändert. Sie kamen zu ihnen und sagten: "Hier ist ein neues schönes SpeechKit, bitte nimm es!" - Sie antworteten: "Nein, wir haben überhaupt keine Pläne, auf Ihre Version 3.0 zu aktualisieren." Zum Beispiel hatten wir ein Team, das innerhalb eines Jahres auf diese Version umgestellt hat. Deshalb haben wir ein ganzes Jahr lang die vorherige Version für sie unterstützt.
Aber das Ergebnis hat sich gelohnt. Wir haben
eine einfache Integration und weniger Fehler . Dies habe ich in den grundlegenden Entwurfsprinzipien der API erwähnt. Wenn Sie sicher sind, dass Ihre API korrekt verwendet wird, gibt es in diesem Teil definitiv keine Probleme: Alle Klassen werden korrekt aufgerufen, alle Parameter sind korrekt. Das Auffinden von Fehlern ist viel einfacher, weniger Fälle, in denen etwas schief gehen könnte.
Im Folgenden finden Sie ein Beispiel dafür, wie die Hauptklasse, die sich mit Erkennung befasst, vor dem Refactoring aussah.
Dies ist eine reguläre Klasse, die von NSObject erbt. Betrachten wir jedes Detail einzeln. Es ist klar, dass wir davon erben und einige Methoden darin neu definieren können - alles, was mit NSObject möglich ist.
Beim Erstellen werden dann zwei Zeilen (Sprache und Modell) an sie übergeben. Was sind diese Zeilen? Wenn Sie die Sprache "Hallo Welt" eingeben, ist die Ausgabe eine Übersetzung, oder was? Nicht sehr klar.
Da dies der Nachfolger von NSObject ist, können wir außerdem init, new usw. darauf aufrufen. Was wird passieren? Wird es funktionieren oder wird es auf einige Parameter warten?
Natürlich kenne ich die Antworten auf diese Fragen, ich kenne diesen Code. Aber Leute, die sich das zum ersten Mal ansehen, verstehen überhaupt nicht, warum das alles ist. Selbst Methoden mit Setter und Getter sehen überhaupt nicht so aus, wie es in iOS aussehen könnte. Die Methoden start, cancel, cancelSync (und die, die gerade abgebrochen werden - ist es aSync?) - was passiert, wenn sie zusammen aufgerufen werden? Viele Fragen zu diesem Code.
Als nächstes kommt das Objekt, über das ich gesprochen habe (YSKInitializer), das gestartet werden muss, damit alles funktioniert - es ist im Allgemeinen eine Art Magie. Es ist ersichtlich, dass dieser Code von Entwicklern geschrieben wurde, die nicht für iOS schreiben, sondern sich mit C ++ beschäftigen.
Ferner wurden die Einstellungen für diesen Erkenner durch globale Komponenten festgelegt, die auf ein anderes globales Objekt übertragen wurden, und tatsächlich war es unmöglich, zwei verschiedene Erkenner mit unterschiedlichen Parametersätzen zu erstellen. Und dies war wahrscheinlich einer der beliebtesten Fälle, in denen die API nicht unterstützt wurde.
Als v3 ist besser als v2
Was haben wir bekommen, als wir überarbeitet und auf Version 3 umgestellt haben?
Jetzt sah unsere iOS-API wie eine iOS-API aus, die Android-API wie Android.
Ein wichtiger Punkt, den wir nicht sofort erkannt haben, ist, dass die Plattformrichtlinien viel wichtiger sind als die Einheitlichkeit der API Ihrer Bibliothek.
Beispielsweise werden Klassen für Android mithilfe von Buildern erstellt, da dies für Android-Entwickler ein sehr verständliches Muster ist. In iOS ist dies nicht so beliebt, daher wird ein anderer Ansatz verwendet: Wir erstellen Objekte mit einer speziellen Klasse von Einstellungen.
Ich erinnere mich, wie wir uns lange über dieses Thema gestritten haben. Es schien uns wichtig, dass der Entwickler unseren Code auf iOS oder Android verwendet, und die Übereinstimmung würde 99% betragen. Aber das ist nicht so. Besser, der Code ähnelt der Plattform, für die er entwickelt wird.
- Einfache und intuitive Initialisierung .
Dieses Objekt wird benötigt - hier sind seine Einstellungen, erstellen Sie sie, übertragen Sie sie - Gewinn! Das heißt, es gibt keine versteckten globalen Einstellungen, die irgendwo übertragen werden müssen.
- Mangel an globalen Komponenten.
Wir haben globale Komponenten herausgeschmissen, die selbst unter den Entwicklern dieser Bibliothek, nicht nur unter den Benutzern, verwirrten, verängstigten und viele Fragen stellten.
Jetzt sieht dieselbe Klasse in der neuen Version so aus (es ist immer noch Objective-C - Sie konnten dann nicht zu Swift wechseln).
Dies ist der Nachfolger von NSObject, aber jetzt sprechen wir klar über die Tatsache, dass Sie nicht davon erben können. Alle für dieses Objekt charakteristischen Methoden werden in ein spezielles Protokoll übertragen. Es wird mit Einstellungen und audioSource erstellt. Jetzt sind alle Einstellungen in einem einzigen Objekt zusammengefasst, das speziell hier übertragen wird, um die Einstellungen für einen bestimmten Erkenner festzulegen.
Darüber hinaus haben wir die Arbeit mit Audio von hier entfernt, dh der Aufklärer ist jetzt nicht die Komponente, die Audio schreibt. Diese Komponente befasst sich mit Erkennungsproblemen, und jede Quelle kann hier übertragen werden.
Andere Erstellungsmethoden über new oder init sind verboten, da für diese Klasse Standardeinstellungen erforderlich sind. Wenn Sie es verwenden möchten, erstellen Sie mindestens einige Standardeinstellungen.
Die Hauptsache ist, dass die hier übertragenen Einstellungen unveränderlich sind, dh Sie können sie dabei nicht ändern. Sie müssen nicht versuchen, das Modell oder die Sprache zu ersetzen, wenn etwas erkannt wird. Dementsprechend geben wir Benutzern nicht die Möglichkeit, das Objekt mit den bereits übertragenen Einstellungen zu ändern.
Makros NS_ASSUME_NONNULL_BEGIN / NS_ASSUME_NONNULL_END, um hervorzuheben, dass diese Einstellungen nicht null sein dürfen: audioSource darf nicht null sein - alles muss einen bestimmten Wert haben, damit es funktioniert.
Wie gesagt, die Start- und Abbruchmethoden (cancelSync left) wurden in ein separates Protokoll verschoben. Es gibt Stellen in der Bibliothek, an denen Sie nicht unseren Aufklärer, sondern jeden anderen verwenden können. Zum Beispiel verwenden wir Apples native, die dieses Protokoll implementiert und in die unsere Komponenten übertragen werden können.
Die Einstellungen hier sind NSCopying, damit wir sie kopieren können, und sie konnten dabei nicht geändert werden. In init sind die erforderlichen Parameter Sprache, Modell und NS_DESIGNATED_INITIALIZER. Dies ist kein Code, der mit veralteten Methoden identisch ist, aber die Idee ist klar. Dies sind erforderliche Parameter, mit denen Einstellungen erstellt werden. Sie müssen und müssen ungleich Null sein.
Der Rest des Sets besteht aus ca. 20 Einstellungen des Erkenners, die hier eingestellt werden. Sogar die Einstellungen einer Sprache oder eines Modells sind separate Klassen, die es uns nicht ermöglichen, etwas Abstraktes zu vermitteln, mit dem wir nicht arbeiten können. Das heißt, wir sagen klar: „Bitte geben Sie uns nichts, mit dem wir nicht arbeiten können. Der Compiler lässt Sie das nicht zu. “
Wir haben also darüber gesprochen, was Sie mit der API tun können. Die Entwicklung hat auch ihre eigenen Nuancen.
Entwicklung
Zuallererst sollte die Bibliothek das tun, wofür Sie sie geschrieben haben - um ihre Funktionalität gut auszuführen. Aber Sie können Ihren Code zu einer wirklich guten Bibliothek machen. Ich schlage mehrere Bemerkungen vor, die ich während der Entwicklung von SpeechKit gesammelt habe.
Der Code ist nicht nur für Sie
Es ist unbedingt erforderlich
, Debug-Informationen zu
sammeln , da Benutzer nicht sagen sollen, dass ihr Dienst aufgrund Ihrer Bibliothek nicht funktioniert.
IOS verfügt über eine Debug-Informationsebene, die anzeigt, welche Informationen gesammelt werden müssen. Standardmäßig sammelt es absolut alles, was es finden kann: alle Aufrufe, alle Werte. Das ist großartig, aber es ist eine sehr große Datenmenge. Wenn Sie -gline-tables-only festlegen, können Sie Informationen zu Funktionsaufrufen sammeln. Dies ist mehr als genug, um ein Problem zu finden und zu beheben.
Dies ist in den Xcode-Einstellungen (Build-Einstellungen) enthalten und wird als Debug-Informationsebene bezeichnet. Durch Aktivieren dieser Einstellung haben wir beispielsweise die Größe der SpeechKit-Binärdatei von 600 MB auf 90 MB reduziert. Dies sind keine sehr notwendigen Informationen und wir haben sie einfach weggeworfen.
Die zweite wichtige Sache ist,
private Charaktere zu
verstecken . Sie alle wissen, dass jedes Mal, wenn Sie eine Bibliothek in iTunes hochladen, die Gefahr besteht, dass Sie eine neue Warnung erhalten, dass Sie etwas falsch verwenden und nichts hinzufügen. Wenn Sie Bibliotheken verwenden, die Apple als privat betrachtet, müssen Sie sie daher unbedingt ausblenden. Dies bedeutet für Sie nichts, Sie können auch mit ihnen arbeiten. Sobald Ihre Benutzer jedoch versuchen, die Anwendung mit Ihrer Bibliothek auf iTunes hochzuladen, wird eine Fehlermeldung angezeigt. Nicht jeder wird Sie bitten, das Problem zu beheben. Die meisten werden sich einfach weigern, Ihre Lösung zu verwenden.
Vermeiden Sie Zeichenkonflikte : Fügen Sie Präfixe zu allem hinzu, was Sie haben, zu Ihren Klassen, zu Kategorien. Wenn die Bibliothek eine Kategorie UIColor + HEX hat, stellen Sie sicher, dass Ihre Benutzer genau dieselbe Kategorie haben. Wenn sie Ihre Bibliothek integrieren, erhalten sie Zeichenkonflikte. Und wieder wird nicht jeder es Ihnen sagen und sagen wollen.
Eine andere Frage ist, wann Sie selbst Bibliotheken von Drittanbietern in Ihrer Bibliothek verwenden. Es gibt einige Nuancen, an die man sich erinnern sollte. Wenn Sie etwas verwenden, das in einer älteren Version als Ihrer Bibliothek angezeigt wurde, vergessen Sie zunächst nicht, die
schwache Verknüpfung zu verwenden (Xcode -> Phasen erstellen -> Binär mit Bibliotheken verknüpfen -> Status ist aktiviert). Dies ermöglicht es Ihnen, nicht zu fallen, wenn diese Bibliothek plötzlich nicht mehr ist.
In der Dokumentation von Apple wird detailliert beschrieben, wie dies funktioniert. Eine schwache Verknüpfung bedeutet jedoch nicht, dass die Bibliothek nicht geladen wird, wenn sie nicht verwendet wird. Wenn die Startzeit der Anwendung für Ihre Benutzer wichtig ist und Sie möglicherweise nicht den Teil Ihrer Bibliothek benötigen, der eine Bibliothek eines Drittanbieters verwendet und dessen Start einige Zeit in Anspruch nimmt, hilft Ihnen eine schwache Verknüpfung nicht. Damit lädt die Bibliothek immer noch, ob sie verwendet wird oder nicht.
Wenn Sie zur Laufzeit laden möchten, wird dies dazu beitragen, das Verbindungsproblem beim Start zu beseitigen. Dann müssen Sie dlopen und dynamisches Laden verwenden. Dies erfordert viel Aufhebens, und Sie müssen zuerst verstehen, ob dies sinnvoll ist. Facebook hat einen ziemlich
interessanten Code für ein Beispiel, wie sie dynamisch verknüpft sind.
Zuletzt -
versuchen Sie, keine globalen Entitäten zu verwenden . Jede Plattform hat einige globale Komponenten. Es ist ratsam, sie nicht in Ihre Bibliothek zu ziehen. Dies scheint offensichtlich zu sein, da es sich um ein globales Objekt handelt und Ihre Bibliotheksbenutzer es nach Belieben konfigurieren können. Wenn Sie es in Ihrer Bibliothek verwenden, müssen Sie den Status irgendwie speichern, neu konfigurieren und dann den Status wiederherstellen. Es gibt viele Nuancen und es gibt einen Ort, an dem man einen Fehler machen kann. Denken Sie daran und versuchen Sie zu vermeiden.
In SpeechKit haben wir beispielsweise vor der dritten Version mit Audio in der Bibliothek gearbeitet und die Audiositzung explizit eingerichtet und aktiviert. Eine Audiositzung in iOS ist so etwas, wie es jede Anwendung hat - sagen Sie nicht, dass Sie keine haben. Es wird zu Beginn erstellt, ist für die Interaktion zwischen der Anwendung und dem Systemmediendämon verantwortlich und gibt an, was Ihre Anwendung mit Audio tun möchte. Dies ist ein Singleton-Objekt im wahrsten Sinne des Wortes. Wir haben es ruhig aufgenommen und nach Bedarf eingerichtet, aber dies führte dazu, dass Benutzer kleinere Probleme wie das Ändern der Lautstärke hatten. Eine andere Methode für Audiositzungen, die für die Einstellung der Einstellungen verantwortlich ist, ist ziemlich lang. Es dauert ungefähr 200 ms, und dies ist eine merkliche Verlangsamung der Aktivierung oder Deaktivierung.
In der dritten Version habe ich freudig eine Audiositzung aus der Bibliothek gezogen. Danach sagten fast alle Benutzer aller Dienste, in die SpeechKit integriert war, dass sie schrecklich unglücklich waren. Jetzt sollten sie wissen, dass es eine Art Audiositzung gibt, die speziell für unser SpeechKit konfiguriert werden muss.
Die Schlussfolgerung daraus lautet: Versuchen Sie trotzdem, keine globalen Entitäten zu verwenden, sondern seien Sie darauf vorbereitet, dass Ihre Benutzer mit Ihren Entscheidungen nicht immer zufrieden sind.
Wir machen es bequem für Benutzer
Wie können Sie Ihren Benutzern sonst noch helfen?
- Protokolle hinzufügen: verschiedene Ebenen, dynamische Einbeziehung .
Am einfachsten ist es, eine Datei anzuhängen, für deren Vorhandensein ein Mega-Debug-Modus gestartet wird. Es ist wirklich hilfreich, das Debuggen in einer Situation durchzuführen, in der Ihre Benutzer Benutzer haben, die einen Fehler haben, und Sie müssen verstehen, was genau passiert ist.
- Unterstützt alle Betriebssystemversionen des Benutzers.
Denken Sie daran, dass die Versionsunterstützung in einer Bibliothek nicht mit der Versionsunterstützung in einer regulären Anwendung identisch ist. In einer regulären Anwendung sehen wir uns Statistiken an, nach denen beispielsweise nur 2% unserer Benutzer iOS 8 verwenden. Dies bedeutet, dass Sie die Unterstützung von iOS 8 einstellen können. In der Bibliothek bedeutet dies nicht, dass die Ablehnung der Betriebssystemversion bedeutet, dass Sie Ihren Benutzer und alle seine Benutzer vollständig verlassen. Dies kann im Prinzip die Hälfte Ihrer Benutzer sein.
Daher müssen Sie überwachen, welche Versionen von den Anwendungen verwendet werden, die Ihre Bibliothek verwenden, und auf dieser Grundlage sollten Sie bereits feststellen, ob Sie etwas unterstützen oder nicht. Wir haben iOS 7 lange Zeit nicht aufgegeben. Es scheint mir, dass es bereits Leute gab, die iOS 8 verlassen haben und bereit waren, iOS 9 aufzugeben. Wir haben iOS 7 weiterhin unterstützt, da wir einen Browser hatten, der bis zum letzten Mal alle Benutzer behielt und wir arbeiteten eng mit ihm zusammen und konnten ihn in einer solchen Situation nicht zurücklassen.
Auch hier werden Ihre Benutzer nicht sagen: "Lassen Sie uns diese Funktionalität für die Version deaktivieren, die sie nicht unterstützt." Nein, sie werden einfach Ihre Bibliothek entfernen und eine finden, die die gesamte Versionsreihe unterstützt.
- Fügen Sie in neuen Versionen ein minimales Inkrement hinzu.
Dies ist sehr "nicht sehr" für Bibliotheksentwickler. Ich möchte alles veröffentlichen, was zur Veröffentlichung bereit ist. Sie haben Funktionen erstellt und Fehler behoben. Jetzt werden wir das gesamte Paket bereitstellen und es für die Veröffentlichung bereitstellen. Release ist auch ein Prozess. Dies gilt nicht für Ihre Benutzer. Wenn sie gerade dabei sind, ihr Produkt zu testen und für die Veröffentlichung vorzubereiten, möchten sie von Ihnen keine Baugruppe mit neuen Funktionen erhalten, die zusätzliche Tests erfordern.
Wir hatten wirklich Fälle, in denen wir einige Veröffentlichungen zurückgesetzt, in Teile geteilt und bereits in Teilen ausgerollt haben. Dann könnten die Teams, für die wir Änderungen implementiert haben, genau die Version übernehmen, in der es kleine Änderungen gibt, und nicht alle auf einmal.
Dies ist für die Entwicklung nicht sehr praktisch, aber das minimale Inkrementieren der Versionen macht Ihre Benutzer ein bisschen glücklicher.
Es gibt nie zu viele Tests
Dies gilt sowohl für eine reguläre Anwendung als auch für eine Bibliothek. Aber auch im Fall der Bibliothek gibt es Funktionen.

Natürlich sind
Autotests erforderlich, aber außerdem ist es großartig, eine
Testanwendung für Ihre Bibliothek zu haben. Es wird Ihnen helfen, das, was Sie selbst geschrieben haben, zu integrieren und zu verstehen, welche Probleme oder Fallstricke auftreten können. Sie können selbst fühlen, was Ihre Benutzer sind.
Wenn Ihre Bibliothek irgendwie mit dem Netzwerk interagiert, Verschlüsselung enthält, gibt es zumindest etwas in Bezug auf Daten und Sicherheit. Geben Sie es den
Sicherheitskräften zur
Überprüfung . Sie wollen absolut nicht die Bibliothek sein, in der sie die Verwundbarkeit finden - es ist ein Stigma fürs Leben. Fast alle großen Unternehmen haben eine ganze Abteilung, die sich mit der Überprüfung von Produkten auf Sicherheit befasst - geben Sie sie ihnen. Wenn Sie noch keine haben, gibt es
eine externe Prüfung . Wenn Sie sich das Externe nicht leisten können, suchen Sie die Tests im Netzwerk, führen Sie sie aus und stellen Sie sicher, dass in Ihrer Bibliothek keine Benutzerdaten verloren gehen.
Das Letzte, was bei Tests sehr wichtig ist, ist von Anfang an,
Messungen von allem hinzuzufügen,
was möglich ist : Zeit, Stromverbrauch, alles, was für Ihre spezielle Bibliothek typisch ist. Am Ende müssen Sie dies noch tun. Warum also nicht von Anfang an über Messungen nachdenken?
Dies schützt nicht vor Änderungen und vor der Notwendigkeit, die Bibliothek zu beschleunigen, hilft jedoch herauszufinden, was schief gelaufen ist. Wenn Sie Diagramme haben, hilft dies bei der Echtzeitüberwachung, welche Funktionen Zeitverzögerungen oder erhöhten Stromverbrauch hinzugefügt haben.
Dafür ist fast nie Zeit, da dies nicht die Funktionalität der Bibliothek ist, sondern nicht das, wofür Sie sie entwickeln. Aber das ist es, was Ihnen hilft, es in gutem Zustand und in guter Qualität zu halten.
Hier können Sie lesen, wie wir in Yandex den Energieverbrauch mobiler Geräte messen. Über Zeitmessungen war eine lustige Geschichte. Als Bibliotheksentwickler ist es für uns schwierig, das Verhalten in bestimmten Fällen zu messen, da nicht alle SpeechKit-Skripte von allen Teams verwendet werden. Bis dahin haben wir unsere Testanwendung verwendet. Spezielle Anwendungsfälle wurden geschrieben, zum Beispiel ein Erkenner oder Komponenten für die Sprachsynthese, jeder Schritt wurde aufgezeichnet und Protokolle wurden gespeichert, und als Ergebnis wurden coole Grafiken erstellt.
Alles wäre in Ordnung, aber wir arbeiten mit Audio, und um alles zu überprüfen, wird in bestimmten Fällen die Audiospur wirklich abgespielt. Darüber hinaus müssen viele Messungen durchgeführt werden, damit sie den Test für die Nacht verlassen können: Stellen Sie die Lautsprecher auf, stellen Sie ein Gerät daneben und starten Sie die Audiodateien. Am Morgen ging alles aus, am nächsten Abend wiederholte es sich und dann wieder. Es ging überhaupt nicht um magische Kreaturen, die im Büro herumliefen - nur die Reinigungskräfte hatten Angst. Es gab wirklich einen sehr seltsamen Text, der in Abständen gelesen wurde.
Infolgedessen wurde beschlossen, einen lokalen Prüfstand herzustellen, den wir Kabinett nannten. Dies ist ein natürlicher Schrank, nur schallisoliert. Es enthält viele Geräte, eine ganze Farm mit Geräten, von denen jedes während des Arbeitstages mehrmals gestartet werden kann, da es niemanden verletzt.
Starten
Schließlich kommen wir zum letzten wichtigen Teil - dies ist der Start. Der Code ist geschrieben, eine gute API wurde entwickelt, um es für Benutzer bequem zu machen. Wie jetzt all dies in Release veröffentlichen.
Ich beginne mit lokalen Releases für Benutzer in Yandex. Das Schema hier ist das gleiche wie bei der Entwicklung einer regulären Anwendung: regelmäßige, monatliche oder wöchentliche Veröffentlichungen.

Der Prozess besteht aus den üblichen Phasen, aber bei der Entwicklung einer Bibliothek hat jeder dieser Punkte seine eigenen Eigenschaften.
Planung
Für mich ist dies der schmerzhafteste Teil, da die Bibliothek mehrere Produktteams hat. In einer regulären Anwendung gibt es einen Produktmanager, der Aufgaben festlegt, die das Team priorisiert und nacheinander ausführt.
Wenn es mehrere Produktteams gibt, erhält jedes von ihnen Anforderungen, die in Echtzeit verarbeitet werden müssen. Ich werde einen Rat geben: Wenn es eine Person gibt, die weiß, wie man mit einer Vielzahl von Aufgaben umgeht, die gleichzeitig kommen, versuchen Sie, sie in Ihrem Team aufzunehmen. Weil es zwischen allen externen Managern und der Entwicklung jemanden geben muss, der die Funktionalität für die Priorisierung von Aufgaben übernimmt.
SpeechKit , , , . , , - . , — . , n . , . , , - .
Entwicklung
, , : , , . Agile- .
, , , — . , . !
Scrum . , , , . . « », .
Scrum , , , — — , . . — , - . , ? , : «, , , ». , , - , , Scrum . ! , .
. , , . , . , , , , . , . .
Unterstützung
, — , - . , , , , . , . : « 4, 3 — ». , . - , , ,
, .
—
. Continuous Integration , , ,
.
, . .
1.
.—
. - - , , , . .
. , — , , , , . , , - .
2.
., , , — , , , , , !
. ,
. , , -, .
—
. SpeechKit . , , — , - . — , - .
,
. , 4 2, , . , -, , .
—
. , , , .
. Das. Im Ernst
, -, .
. , , , help , .

. : -, GitHub, , . — , — . , , .
, , - , , ..
, , :
- . , . - , , .
- . , . , OpenSource , , , , .
- . , . , , . . SpeechKit .
Zusammenfassung
Yandex.SpeachKit GitHub
iOS ,
Android ,
Mobile SDK.
AppsConf — — 22 23 2019 , , .
. , , .