Stało się to co miało się stać, czyli o left-pad

Kilka dni temu w świadku javascriptowym wybuchła „bomba”. Zaczęło się niewinnie, bo firma o nazwie Kik poprosiła Azera Koçulu, by raczył wycofać z repozytorium npm swój pakiet o nazwie Kik.

Fakap 1

W czasach obecnych należy zastanowić się czy sławetny javascript drink name nie powinien być jakoś znormalizowany i tworząc aplikację nie powinieneś wystąpić o notarialne potwierdzenie, że „google nie zwraca informacji o produktach pod marką hitler.js”. Generalnie sprawa pokazuje jak chore są współczesne prawa autorskie.

—-

Sprawa toczyła się dalej i prawnicy uderzyli bezpośrednio do ludzi od npm, a ci usunęli co mięli usunąć. Koçulu oczywiście się wkurzył i miał rację. W proteście wycofał wszystkie swoje pakiety z npma. Co samo w sobie jest rozsądnym posunięciem, bo pomimo posiadania praw do Kik, ktoś inny postanowił zarządzać pakietem bez jego zgody.
I tu pojawił się problem…

JavaScript ma za niski próg wejścia

Jako technologia, język, zestaw frameworków. Obecnie programowanie w JS ogranicza się do dobierania odpowiedniego zestawu zależności połączeniu ich za pomocą innych zależności i w efekcie otrzymujemy „aplikację”. Paradoksalnie niewiele ma to wspólnego z programowaniem. Bliżej temu do procesu produkcyjnego, w którym mam określony katalog części, znamy poszczególne kroki procesu, oraz z góry wiemy jaki będzie efekt końcowy.
Prowadzi to jednak do znacznie poważniejszego problemu – przestaliśmy umieć kodować. Serio. To powoduje, że stając wobec prostego problemu zaczynamy panicznie szukać biblioteki, która ten problem rozwiąże za nas. Czas potrzebny na odnalezienie takiego narzędzia i integrację (konflikty nazw np.) będzie wielokrotnie większy niż samodzielne napisanie rozwiązania. Ma to też jeszcze inne przykre konsekwencje…

Casus left-pad

Koçulu zabierając swoje zabawki z piaskownicy pod nazwą npm zabrał też coś co nazywa się left-pad. Jest to prosty, ale nie trywialny, kawałek kodu, który uzupełnia String z lewej określonym znakiem do określonej długości.
Jak pisałem nie jest to trywialny kawałek kodu, ale prosty. W Javie możemy napisać go tak:

Listing 1. Left-pad w javie

public class App {
	public static void main(String[] args) {
		System.out.println(leftpad("m m", 2, '@'));
	}

	static String leftpad(String s, int nb, char pad) {
		return Optional.of(nb - s.length())
				.filter(i -> i > 0)
				.map(i -> String.format("%" + i + "s", "").replace(" ", pad + "") + s)
				.orElse(s);
	}

}

Problem polega na tym, że ludzie zamiast dopisać kawałek kodu zaczęli korzystać z zależności. W momencie gdy zależność zniknęła z repozytorium posypał się kod w ogromnej ilości aplikacji.

Fakap 2

Przy okazji okazało się, że pakiety npm nie są, co do zasady, podpisywane. Choć istnieje taka możliwość to ludzie z niej nie korzystają. Zatem w momencie gdy zniknęły pakiety Koçulu dość szybko zostały one zastąpione innymi o tej samej nazwie. Co jest w środku? Nikt tego nie wie.

—-

Efektywnie posypały się buildy i od rana opsi mają sajgon, bo w czasach gdy stawiamy na szybkie wdrożenie każdy wysypany build jest problemem.

Inżynieria oprogramowania jest OK

Spójrzmy na ten problem z innego punktu. Jednym z założeń inżynierii oprogramowania jest zmniejszanie ilości samodzielnie wytworzonego kodu. W efekcie powinniśmy tworzyć kod, który jest łatwy do ponownego użycia. Ma to też sens w kontekście filozofii hackerskiej, która mówi, że publikujemy rozwiązanie problemu po to by inni mogli poświęcić swój czas na rozwiązywanie innych problemów.

Rzecz w tym, że w świecie JS doszło do wypaczenia idei hackerskiej. Obecnie jako bibliotekę traktuje się pojedynczą funkcję. W efekcie średnia aplikacja potrafi dociągnąć dziesiątki tysięcy plików. Ciekawą analizę tego problemu znajdziecie na blogu Haney Codes .NET.

Podsumowanie

Na zakończenie chciałbym podzielić się jeszcze dwoma przemyśleniami. Pierwsze z nich dotyczy obecnego statusu projektu npm. Twórcy powinni na natychmiast zmienić podejście do modułów. Na pewno najważniejszym i obowiązkowym elementem powinno być wymuszenie podpisywania pakietów. Jeżeli chcesz się dzielić swoim kodem to podpisz swoje dzieło 🙂 Kolejnym elementem jest stworzenie jakiegoś mechanizmu weryfikacji i oceny bibliotek tak by można było uniknąć sytuacji gdzie byle funkcja urasta do miana frameworku 😉

Drugie to przemyślenie dotyczące samego języka javascript. Jak widać tworzenie języka, który ma bardzo ubogą bibliotekę standardową jest złym pomysłem. Podobne odczucie mam w stosunku do możliwości streamów Javy 8, którym brakuje wielu rzeczy.

Cóż, świat nie jest doskonały i należy starać się go naprawić, ale jak już to się robi to warto robić to w sposób przemyślany.

6 myśli na temat “Stało się to co miało się stać, czyli o left-pad

  1. Czy zamiast tych cudów z formatowaniem, replace, no i filtrowaniem aby przejsc z Some na None (gdy input string nie porzebuje paddingu) nie latwiej:
    IntStream.range(0, nb – s.length()).
    mapToObj(x -> String.valueOf(pad)).
    collect(Collectors.joining(„”)) + s;

  2. @jmilkiewicz, można też tak i jest nawet lepiej. BTW, widać, że mało IntStream używam i nie wyrobiło mi się jeszcze odpowiednie połączenie.

  3. Napisałeś o budowaniu aplikacji w JavaScript tak, jakby w Java nie było frameworków, bibliotek i tego typu rzeczy, jednak nie widziałem systemów, które nie korzystałby właśnie z tego, że w większości są wyłącznie gluecodem zależności.

  4. @Dawid, ale w Javie nie robi się biblioteki (sic!), której kod wygląda tak:

    var toString = {}.toString;
    
    module.exports = Array.isArray || function (arr) {
      return toString.call(arr) == '[object Array]';
    };

    Problem polega nie na tworzeniu bibliotek, ale na granulacji ich odpowiedzialności.

    ps. link do tego wytworu https://github.com/juliangruber/isarray

  5. Problem w tym, że pisząc swoją wersję leftpad połowa programistów zrobiłaby wersję powolną i najeżoną błędami, a druga połowa wersję super zoptymalizowaną, ale za to kompletnie nieczytelną (i do tego zapewne również mniej lub bardziej zabugowaną). Na dodatek podczas code review dostaliby ochrzan, że wynajdują koło na nowo, zamiast wykorzystać sprawdzone, otwarte rozwiązania – „don’t repeat yourself” i „not invented here” to powszechnie znane antywzorce.

  6. > code review dostaliby ochrzan, że wynajdują koło na nowo, zamiast wykorzystać sprawdzone, otwarte rozwiązania

    Nadal to samo. Nie chodzi o to, że masz możliwość wykorzystania czyjegoś kodu. Jednak „one function is not library”. JS ma tą wadę, że jego API jest bardzo ubogie i to powoduje, że trzeba napisać dużo kodu narzędziowego. Jednak w świecie normalnych języków takie rozwiązania narzędziowe grupuje się w większe zestawy i dopiero to wypuszcza jako bibliotekę.

    Swoją drogą zauważ, że w moim poprzednim komentarzu podałem kod do „biblioteki”, która sprawdza czy obiekt jest tablicą. I nie jest to primaaprilisowy żarcik. Okazuje się, że nagle z jakiegoś niezrozumiałego powodu część programistów JS nie potrafi prostego ifa napisać bez użycia biblioteki! To już przypomina dowcip o hindusie, co nie potrafił zamienić dwóch zmiennych miejscami bez użycia SO.

Napisz odpowiedź

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax