Ostatnio na portalu embedded.com zaczęła pojawiać się seria artykułów omawiających 10 najczęstszych problemów w projektach embedded napisana przez Jacka Gannsle. Pierwszym omówionym zagadnieniem były złudne oszczędności (link  tutaj). Czytając artykuł zgadzałem się praktycznie z każdym słowem, bo sam obserwuję to samo praktycznie od początku kariery zawodowej. Z resztą nie jest to coś specyficznego tylko dla systemów embedded, czy branży IT, Krótkowzroczne podejście do oszczędności jest chyba ogólnoświatowym standardem i objawia się na wielu płaszczyznach. We wpisie postaram się rozwinąć tę myśl, chociaż będę się trzymał przykładów z IT.

Płatny soft i toole

Jack Gansle zaczął od softu i tooli, to ja zacznę tak samo. Biblioteki i frameworki do wszystkiego są bardzo popularne, szczególnie w językach wyższego poziomu. O nowych frameworkach w JavaScripcie powstała nawet pijacka gra. W systemach embedded nie używa się bibliotek na taką skalę, ale jak możemy, to chętnie oszczędzimy czas używając gotowego kodu. Tylko pod jednym warunkiem – musi być darmowy. Nawet te 30$, które przy łącznym budżecie projektu są niczym okazują się zwykle barierą nie do przejścia.

Ktoś kiedyś zauważył, że developerzy zarabiają na życie pisząc programy, ale niechętnie płacą za soft napisany przez innych. Lepiej codziennie się trochę pomęczyć i oszczędzić kilka złotych. Tak samo zachowują się całe firmy z branży IT. Jednak jak się chwilę zastanowimy, od razu widzimy, że to bez sensu – pensja developera jest wysoka i jeśli traci on codziennie czas na coś, co mógłby robić program – koszty zwrócą się bardzo szybko. Przy okazji to ciekawe, że zakup jakiegoś fizycznego sprzętu np. monitora przychodzi nam dużo łatwiej.

Jednak w kwestii płacenia za soft prawdziwą wisienką na torcie jest zaawansowany (a przez to często drogi) kod. Skoro tyle kosztuje komercyjny soft, lepiej sami go napiszmy od zera. W branży embedded są dwa koronne przykłady – pisanie własnego RTOSa i własnego stosu TCP/IP. To jest najkrótsza droga, żeby zakopać się na lata w czymś niezwiązanym bezpośrednio z prawdziwym produktem! W linkowanym na początku artykule możemy przeczytać, że 20-40$ to średnia cena jednej linii kodu w komercyjnym projekcie wliczając pensje, management i całą infrastrukturę. Więc jeśli mamy zapłacić 10000$ za RTOSa działającego od ręki i z supportem producenta, który ma 10KLOC (kilo lines of code), nagle okazuje się, że to jak za darmo.

Układy elektroniczne

Jeżeli chodzi o projektowanie hardware, sytuacja jest podobna jak z RTOSami i stosami TCP. Kiedy widzimy cenę jakiegoś scalaka, nie możemy się z nią pogodzić. Co wtedy robimy? Projektujemy własne układy (najczęściej przy okazji przerzucając część sterowania na soft). Może to być sterownik silników, wzmacniacz, jednak najczęściej chodzi o bardziej zaawansowane elementy np. dla toru RF. Przy produkcji idącej w setki tysięcy egzemplarzy faktycznie ma to sens. Każdy oszczędzony w ten sposób cent widocznie zmniejsza koszty. Jeśli jednak na początek planujemy tylko kilka tysięcy sztuk nie ma szans, aby to się opłacało. Już sam koszt mandayów jest dużo większy. A przecież jeszcze dochodzą kolejne aspekty. Czas wymagany na dodatkową pracę oddala nas od wypuszczenia produktu na rynek. Co więcej, osoby u nas w firmie nie muszą być ekspertami akurat z tej wąskiej dziedziny, a twórcy dedykowanego scalaka czy modułu owszem. Oznacza to, że stracimy dodatkowy czas i pieniądze na prototypy i nieudane próby, a końcowe rozwiązanie i tak będzie miało gorsze parametry.

Początkowe planowanie

Planowanie projektu to kolejny obszar fikcyjnych oszczędności, które okazują się bardzo drogie. Dobrze oddaje to poniższy cytat:

Panuje ogólne przeświadczenie, że czas nie spędzony nad kodem jest czasem straconym. Efekt potęguje źle rozumiany Agile, który przecież bardziej ceni działający soft niż dokumentację i planowanie. Dlatego siadamy do ficzerów zanim dobrze przemyślimy architekturę, a nawet zbierzemy wszystkie wymagania. Dzięki temu niby oszczędzamy czas, bo szybciej otrzymujemy pierwsze rezultaty, które ładnie wyglądają na wykresach, ale nie niosą realnej wartości. Później co kilka tygodni musimy robić wielki redesign, bo znowu zapomnieliśmy o jakimś wymaganiu i nie da się tego zrealizować w istniejącej architekturze. Co więcej nawet gdy wady systemu staną się już widoczne i uciążliwe, nie będzie czasu ich naprawiać. Ta praca nie da od razu spektakularnych rezultatów i lepiej skupić się na czymś przynoszącym od razu widoczny efekt. Toż to czysty programistyczny populizm! Czy naprawdę dla tych nic nie znaczących słupków na wykresach warto ryzykować powodzenie całego projektu?

Dobre praktyki i usprawnienia

Z początkowym planowaniem trochę wiążą się również dobre praktyki. Najlepiej by było już na początku pomyśleć jakie techniki, czy toole chcielibyśmy, albo nawet musimy stosować. Pisanie testów jednostkowych, czy dokumentacji równolegle z kodem jest ogromną oszczędnością czasu. Continuous integration, smoke testy, czy testy wyższych poziomów również wnoszą wartość już we wczesnych fazach projektu. Często jednak chcemy być chytrzy – skupmy się tylko na kodzie produkcyjnym, resztę dorobi się później.  Przez to dokumentacja i testy są niepełne, a ich pisanie to udręka. Jest to szczególnie bolesne, kiedy wymagana szczegółowość testów i dokumentacji jest z góry narzucona np. w normach safety-critical czy w jakiś innych wymaganiach dotyczących jakości. Wtedy wiemy od początku, że nie ma od nich ucieczki i zostawiając tą pracę na koniec strzelamy sobie w stopę.

Często jednak projekt już trwa i mamy pomysł na jakieś usprawnienia. Może to być TDD, code review, automatyzacja, czy cokolwiek innego. Najczęściej takie pomysły są odkładane w nieskończoność. Przecież nie mamy na to teraz czasu, brakuje nam rąk do pracy i w ogóle nie ma na to pieniędzy. W imię tych krótkotrwałych zysków pozbawiamy się możliwości dużo większych oszczędności. Nie bez przyczyny te praktyki są polecane przez ekspertów i coraz popularniejsze.

Co może z tym zrobić developer?

Ostateczna decyzja nie zależy do nas, tylko do managementu. Dlatego nie mamy na nią bezpośredniego wpływu. Powinniśmy zdawać sobie sprawę z tych ukrytych kosztów, umieć je identyfikować i o nich informować. Jako developerzy mamy najczęściej większą wiedzę techniczną od managerów. Oni z kolei bardziej skupiają się na aspektach biznesowych. Więc to my musimy uświadamiać o technicznych konsekwencjach pewnych decyzji (albo ich braku). Swoje tezy powinniśmy poprzeć rzeczowymi argumentami, najlepiej posługując się właśnie językiem biznesowym. Warto zrobić research i mieć poparcie w  analizach, case study i wypowiedziach autorytetów.

Przekonanie zespołu i bezpośredniego przełożonego jeszcze nie oznacza sukcesu. Na ścieżce decyzyjnej może być więcej osób i każdy może ją zablokować. Oczywiście każda przekonana osoba jest sojusznikiem w dalszej dyskusji, ale całość może kosztować wiele czasu i nerwów. Wprowadzanie zmian to długotrwały proces. Trzeba być cierpliwym, drążyć temat przy wielu okazjach. Może w końcu się uda. Jeżeli nie, to jedynie będziemy mieli okazję później stwierdzić „A nie mówiłem”, jednak marne to pocieszenie.