Steven
Steven6 min czytania

Spokojne oprogramowanie: jak zabiliśmy migający przełącznik i nauczyliśmy czat mówić, w jakim jest trybie

Dwa niewielkie wydania GeekBye, bez żadnej sztandarowej funkcji — tylko przełącznik w ustawieniach, który przestał migać, i asystent czatu, który wreszcie mówi ci, czy odpowiedział w trybie spotkania, czy w trybie kodowania. Oto ile naprawdę kosztuje „spokojne oprogramowanie", jeden szczegół po drugim.

Produkt
Projektowanie
Inżynieria
Wydania GeekBye
Spokojne oprogramowanie: jak zabiliśmy migający przełącznik i nauczyliśmy czat mówić, w jakim jest trybie

Nie każde wydanie to opowieść wojenna. Niektóre to po prostu lista drobnych, niemal niewidocznych rzeczy, które po cichu były nie tak — takich, które niczego nie wywracają, ale sprawiają, że aplikacja wydaje się odrobinę mniej godna zaufania, odrobinę nerwowa, odrobinę nie-twoja. GeekBye v2.0.3 i v2.0.5 były dwoma takimi wydaniami. Żadnych nowych funkcji. Tylko spokój.

„Spokojne oprogramowanie" brzmi jak nastrój. W rzeczywistości to stos konkretnych decyzji. Oto trzy z nich.

Przełącznik, który nie mógł się zdecydować

Był sobie przełącznik w ustawieniach — ten, który steruje odzyskiwaniem dźwięku — który migał, gdy go kliknąłeś. Włączasz go, i przez ułamek sekundy pokazywał włączony, potem cofał się do wyłączony, a potem się ustalał. Maleńkie wizualne zacięcie, ale oko je wychwytuje i odczytuje jako aplikacja nie jest pewna, co robi.

Przyczyną jest klasyczny wyścig interfejsu zwany optymistyczną aktualizacją. Kiedy klikasz przełącznik, aplikacja ma dwie opcje: zaczekać, aż ustawienie faktycznie się zapisze, i dopiero wtedy zaktualizować przełącznik (poprawnie, ale sprawia wrażenie ospałości), albo przełączyć go natychmiast i zapisać w tle (sprawia wrażenie natychmiastowości). GeekBye robiło to drugie — przełączało natychmiast — ale dodatkowo ponownie odczytywało zapisaną wartość, gdy ta wróciła. Sekwencja wyglądała więc tak: klikasz, przełącznik optymistycznie przeskakuje na włączony, chwilę później dociera prawdziwa zapisana wartość i przez jedną klatkę te dwie się nie zgadzały, a przełącznik widocznie odbijał.

Rozwiązaniem jest sprawienie, by wartość optymistyczna i wartość potwierdzona zgadzały się czysto — przełącznik trzyma się stanu, który wybrałeś, i przestaje sam siebie kwestionować, gdy zapis się potwierdzi. Przy okazji v2.0.3 przeszło mało efektowną korektę tekstów: opis odzyskiwania dźwięku został skrócony, by pasował do sąsiednich wierszy, a formułowanie ustawień stało się bardziej ludzkie. Nic z tego nie jest funkcją. Wszystko to jest różnicą między panelem ustawień, który sprawia wrażenie zbudowanego inżyniersko, a takim, który sprawia wrażenie dopieszczonego.

Samouczek, który nie chciał odejść

Samouczki dla nowych użytkowników są przydatne dokładnie raz. Problemem jest ta jednorazowość: kiedy już go zobaczyłeś, nakładka wdrożeniowa, której nie da się zamknąć, staje się bałaganem, który sygnalizuje ta aplikacja wciąż uważa cię za nowicjusza. v2.0.3 naprawiło oba końce tego problemu — przewodnik po produkcie można teraz ukryć, a jeśli naprawdę chcesz go z powrotem, jest przycisk Odtwórz samouczek ponownie. Pokaż go, gdy pomaga, zejdź z drogi, gdy nie pomaga, i pozwól użytkownikowi przywołać go na jego warunkach. Uszanowanie tego, że użytkownik nie jest już nowicjuszem, to własna, mała forma spokoju.

Asystent, który nie chciał powiedzieć, jak myśli

To jest ten, który naprawdę miał znaczenie, i łączy się z głębszym problemem, który od jakiegoś czasu ścigaliśmy.

Asystent GeekBye odpowiada inaczej w zależności od kontekstu. Na spotkaniu „co o tym myślisz?" powinno dostać konwersacyjną odpowiedź świadomą kontekstu spotkania. W sesji kodowania te same słowa powinny dostać odpowiedź techniczną. Backend przepuszcza więc pytanie przez właściwą ramę — nazwijmy to trybem spotkania lub trybem kodowania — i ta rama naprawdę zmienia odpowiedź, którą otrzymujesz.

Kłopot: aplikacja nigdy nie mówiła, który tryb odpowiedział. Więc gdy asystent dawał odpowiedź w stylu kodowania na pytanie konwersacyjne — albo odpowiadał na pytanie o kod tak, jakbyś sobie gawędził — wyglądało to, jakby AI po prostu się myliła. Nie myliła się; była w innym trybie, a ty nie miałeś jak tego dostrzec. Ukryty stan sprawiał, że poprawne zachowanie wyglądało na zepsute. (Sama logika trybów to większy kawał pracy — orkiestrator, który decyduje, jak odpowiadać na pytania niezwiązane z kodem podczas sesji kodowania — ale nic z tego nie jest ci przydatne, jeśli nie możesz zobaczyć decyzji, którą podjął.)

v2.0.5 dodało do czatu etykietę trybu tylko do odczytu: małą etykietkę pokazującą, czy asystent odpowiedział w trybie spotkania, czy w trybie kodowania. „Tylko do odczytu" to cała istota — to nie jest przełącznik, który ustawiasz, to okno na decyzję, którą system już podjął. Przestajesz zgadywać, dlaczego odpowiedź wydaje się nietrafiona; widzisz ramę, z której pochodzi.

Szczegół, który sprawia, że etykieta jest szczera

Oto wybór inżynierski wart przekazania dalej, bo to właśnie taka rzecz odróżnia doklejony wskaźnik od godnego zaufania.

Informacja o trybie przychodzi z backendu jako część strumieniowanej odpowiedzi — mała ramka mode w strumieniu zdarzeń wysyłanych przez serwer. Ale starszy klient sprzed tej funkcji nie wiedziałby, czym jest ramka mode; w najlepszym razie ją zignoruje, w najgorszym wyrenderuje coś zniekształconego. Dlatego klient ogłasza swoją zdolność: wysyła nagłówek żądania mówiący wiem, jak pokazać etykietę trybu, a backend wysyła ramkę mode wyłącznie do klientów, którzy go przysłali. Stare klienty nigdy nie otrzymują sygnału, którego nie potrafią obsłużyć; nowe klienty dostają dokładnie tę ramkę, o którą poprosiły.

To uścisk dłoni oparty na jednym nagłówku, i to jest różnica między „dodaliśmy funkcję" a „dodaliśmy funkcję, nie psując nikomu, kto jeszcze się nie zaktualizował". Ta sama runda przeglądu dopięła resztę zachowania: etykieta czyści się przy resecie i gdy zmienia się kontekst rozmowy (nieaktualna etykieta trybu to jej własne małe kłamstwo) i pokazuje się wyłącznie w widoku czatu, gdzie jest jej miejsce.

Czego nauczyły nas dwa wydania „bez funkcji"

  1. Nerwowość jest sygnałem zaufania. Migający przełącznik, odbijający się suwak, etykieta, która wisi o klatkę za długo — żadne z nich nie jest błędem w sensie awarii, ale każde szepcze ta aplikacja nie do końca panuje nad sytuacją. Spokój to brak tych szeptów, a zdobywasz go jeden warunek wyścigu po drugim.
  2. Ukryty tryb sprawia, że poprawne zachowanie wygląda jak błąd. Asystent robił właściwą rzecz i był za nią obwiniany, wyłącznie dlatego, że użytkownik nie widział ramy. Kiedy twój system podejmuje niewidoczną decyzję, która zmienia wynik, pokaż tę decyzję — etykieta tylko do odczytu jest często całym rozwiązaniem.
  3. Nowe funkcje powinny być niewidoczne dla klientów, którzy nie mogą z nich skorzystać. Uścisk dłoni oparty na nagłówku zdolności sprawia, że sygnał trybu dociera tylko do klientów, którzy potrafią go wyrenderować. Wsteczna kompatybilność to nie sprawdzenie wersji doklejone później; to klient mówiący, co rozumie, i serwer szanujący tę odpowiedź.

To są wydania, o których nikt nie pisze nagłówków w changelogu, i to w dużej mierze dzięki nim GeekBye v2 sprawia takie wrażenie, jakie sprawia. Po wydanie, na którym zbudowano ten spokój, zajrzyj do tego, ile naprawdę wymaga wersja druga (v2.0.0). Po pracę nad niezawodnością obok niego — dzień, w którym nasza aplikacja zaDDoSowała samą siebie (v2.0.1) oraz dlaczego twój notatnik AI przestaje nagrywać w połowie spotkania (v2.0.9).

Powiązane artykuły

Jedna zmienna CSS, pięć rund review i toolchain Swift, który skłamał
Steven
Steven6 min czytania

Jedna zmienna CSS, pięć rund review i toolchain Swift, który skłamał

GeekBye v2.0.7 uczyniło całą nakładkę regulowanie przezroczystą — co brzmi jak jednolinijkowa zmiana w CSS i absolutnie nią nie było. Prawdziwa historia to to, co wychwyciło code review: dwie powierzchnie, które odmawiały gaśnięcia, pasek nagrywania, który wyglądał źle przy tej samej przezroczystości, oraz skompilowany plik binarny, który skakał o 672 bajty, bo nasza własna dokumentacja podała recenzentowi błędną wersję Swift.

Inżynieria
Projektowanie
Kompilacja
Twoja aplikacja na Maca dostaje dostęp do mikrofonu — i zapomina o nim przy każdym uruchomieniu
Steven
Steven5 min czytania

Twoja aplikacja na Maca dostaje dostęp do mikrofonu — i zapomina o nim przy każdym uruchomieniu

GeekBye poprosił o dostęp do mikrofonu, przyznałeś go, i zadziałało. Następne uruchomienie: zniknął. A aplikacja w ogóle nie pojawiła się w Ustawieniach systemowych → Mikrofon. Winowajcą była funkcja bezpieczeństwa macOS, po cichu uruchamiająca aplikację ze ścieżki, która znika — oto diagnoza i naprawa jednym kliknięciem.

macOS
Uprawnienia
Inżynieria
Transkrypcja na żywo, gdy firewall blokuje WebSockety
Steven
Steven4 min czytania

Transkrypcja na żywo, gdy firewall blokuje WebSockety

Sieci firmowe uwielbiają przepuszczać HTTPS i po cichu zabijać upgrade’y WebSocketa. To niepostrzeżenie psuje transkrypcję w czasie rzeczywistym. GeekBye v2.0.8 automatycznie przełącza się na czysto-HTTPS transport — a jego wydanie ujawniło błąd, który uczyniłby całą funkcję bezużyteczną.

Transkrypcja
Sieci
Inżynieria