12 factor app z wykorzystaniem serwisów AWS

Krzysztof Kempiński
Aug 24 · 13 min read

W ramach podcastu “Porozmawiajmy o IT” miałem okazję porozmawiać z Patrykiem Ziemkowskim o zastosowaniu praktyk 12 factor app z wykorzystaniem serwisów AWS.

Posłuchaj naszej rozmowy w wersji audio 🎧 👇

Cześć! Mój dzisiejszy gość to absolwent Politechniki Poznańskiej, profesjonalnie Head of Development 32-osobowego teamu front end, back end developerów Apptension, a prywatnie tata małego franka. Mówi o sobie, że jest prostym, typowym informatykiem, którego w wolnym czasie pochłaniają gry. Ostatnio Wiedźmin 3.

Moim i Waszym gościem jest Patryk Ziemkowski.

Cześć, Patryk! Bardzo mi miło gościć Cię w podcaście!

Cześć, tez mi miło tutaj być!

Dzisiaj porozmawiamy sobie o temacie nieco bardziej techniczny, mianowicie o wykorzystaniu Twelve Factor-App, tego podejścia czy też zespołu, zbioru praktyk z wykorzystaniem konkretnie serwisów AWS.

Na początku Patryk, zapytam jak każdego mojego gościa. Czy słuchasz podcastów? Jeśli tak, to może masz jakieś ulubione?

Muszę przyznać, że nie słucham konkretnie jakiegoś podcastu, nie ma na pewno czegoś, co bym śledził na bieżąco. Zdarza mi się jak czegoś potrzebuję, czyli szukam czegoś związanego z nową technologią i chciałbym się dowiedzieć więcej, to wtedy czegoś przesłuchać. Zdarzyło mi się też słuchać Twój podcast, także ciesze się, że w ogóle tutaj jestem, bo podobał mi się ten podcast, którego słuchałem.

Poza tym prywatnie czasem słucham podcastów, głównie związanych z rodzicielstwem ostatnio. To nic informatycznego, więc zostawię to na boku.

Myślę, że możemy przejść do wyjaśnienia dla słuchaczy czym w ogóle jest Twelve Factors-App?

Chciałbym na to spojrzeć z perspektywy developera, twórcy aplikacji, ale też ról, które towarzyszą wytwarzaniu oprogramowania. SysOps , DevOps, ale również klient końcowy, czy jakiekolwiek korzyści w ogóle płyną z tego podejścia dla klienta końcowego?

Powiem swoimi słowami — byłaby to uniwersalna lista dobrych praktyk, które powinniśmy czy moglibyśmy stosować w naszych aplikacjach, systemach, które develop ujemy celem spowodowania, że będą skanowalne, łatwo deployowane na różnego rodzaju rozwiązania chmurowe, AWS w Heroku. Wspominam tutaj Heroku, bo tak naprawdę to oni są oryginalnie autorem tego Twelve Factor-App. Sami to pierwsi zaprezentowali. Nie wiem dokładnie, w którym roku, wydaje mi się, że w 2015, ale mogę się mylić. Wtedy widziałem pierwsze video z tym związane, ale to widać jeszcze wcześniej.

Też wywodzi się ze środowiska Ruby on Rails i Heroku było swego czasu naturalną platformą do hostowania aplikacji bądź do hobbystycznej, bądź klienckich i pamiętam, że faktycznie Heroku po raz pierwszy zaczął mówić o takim podejściu.

Rozumiem, że to targetowało wówczas developerów. Natomiast teraz w tym ciągu wytwarzania oprogramowania mamy DevOpsów i na końcu klienta końcowego.

Czy przychodzą Wam do głowy właśnie jakieś korzyści albo zyski, które też te grupy mają?

Rozumiem, że dla programisty, dla developera może to być jakiś sposób, żeby ujednolicić wytwarzanie oprogramowania. Takie ujednolicenie powoduje, że jak nowa osoba dołącza do teamu, to też łatwiej pewne praktyki podłapać.

Ale co z działem DevOps, co z klientem końcowym? Czy dla tych grup Twelve Factors-App ma jakieś znaczenie?

Jasne. Zacząłbym od grupy klientów, bo w zasadzie my wywodząc się z software house czy prowadząc tę techniczną stronę głównie, kiedy ewoluował nasz stack technologiczny i kiedy dotarliśmy do tego Twelve Factor-App mówiliśmy o tym, co otrzymuje klient, na drugim miejscu developerów, chociaż nie powiedziałbym, że dużo dalej to jest.

Jeśli chodzi o klientów, to przede wszystkim to na co patrzą to buzzword wielki i skalowalność, czyli to, że możemy rzeczywiście uruchamiać aplikację wspierającą wielu, wielu użytkowników i jeśli potrzebujemy więcej, to z relatywną łatwością dodawać możliwość wsparcia większej liczby użytkowników. To jest na pewno jeden z zamysłów, którego ma doprowadzać wykorzystania Twelve Factor-App.

Jeśli chodzi o klientów, to przede wszystkim to na co patrzą to buzzword wielki i skalowalność, czyli to, że możemy rzeczywiście uruchamiać aplikację wspierającą wielu, wielu użytkowników i jeśli potrzebujemy więcej, to z relatywną łatwością dodawać możliwość wsparcia większej liczby użytkowników. To jest na pewno jeden z zamysłów, którego ma doprowadzać wykorzystania Twelve Factor-App.

Drugą rzeczą to łatwość integracji z Continuous Delivery szeroko pojętym, które przede wszystkim zysk dla klienta ma taki, że jakiekolwiek zmiany, jakie potrzebuje, jakieś naprawdę błędów, jakieś nowe funkcje do zaimplementowania są wdrożone szybko i nie ma jakiegoś bardzo długiego cyklu, procesu oczekiwania na to, żeby przetestować, wrzucić nową wersję aplikacji, też stawianie nowych środowisk nie trwa bardzo długo, tylko jest relatywnie krótkie.

Wszystko sprowadza się do tego, żeby szybko iterować. Tak naprawdę jest podsumowaniem dobrych praktyk, które pozwalają na pełnię zaimplementowania tego podejścia Agile. Trochę nie chciałem używać tego słowa, ale ten cały extreme programming — o to trochę chodzi.

To jest z perspektywy klienta. Spytałeś o DevOpsów — jeśli chodzi o nas, to my staramy się nie wyróżniać osobnej roli DevOpsa, osobnego silosa w firmie, do którego przekazuje się ten deployment. To jest to, że Twelve Factor-App pozwala na to, żeby wciągnąć tego DevOpsa, te kompetencje do zespołu. Żeby to był jednak zamknięty zespół, który posiada w sobie pełne kompetencje do tego, żeby zbudować coś i to odpalić, również na serwerze. I trochę o to chodzi, że kontrakt między developerami, DevOpsami jest jaśniejszy, możemy odpalać aplikacje w bardzo podobnym, jak nie tym samym środowisku zarówno na środowiskach lokalnych, jak i na środowiskach produkcyjnych, co ostatecznie zdecydowanie upraszcza pracę jednej, drugiej części zespołu developerskiego.

Wiem, że bardzo dużo firm rozdziela, także tutaj rzeczywiście duży zysk na to, że pojęcie u mnie działa, pojawia się zdecydowanie rzadziej.

A z perspektywy software house jak Apptension? Czy takie podejście coś daje, jakieś zyski, korzyści? Na coś się przekłada, czy też raczej widzicie w tym tylko i wyłącznie praktykę developerską?

Przekłada się — to jest bardzo mocno powiązane. Dobre praktyki developerskie bardzo szybko przekładają się na zyski dla klienta, ale jeśli chodzi typowo o perspektywę software house’u, to warto byłoby wspomnieć o tym, że często projekty, które wykonuje software house, które wykonujemy są w jakiś sposób później klientowi poddawane. Czyli robimy całkowite hand off produktu, zdarzy się, że klient buduje wtedy jakiś swój własny zespół, który musi przejąć taki projekt.

To jest to jak ze wszystkimi, dobrymi praktykami, jeśli się rzeczywiście za nimi podąża, to przekazanie takiego projektu do kolejnego zespołu developerskiego jest znacznie ważniejsze. Też samo zastosowanie Twelve Factor-App to jest coś, do czego to jest zrobione.

To jest to jak ze wszystkimi, dobrymi praktykami, jeśli się rzeczywiście za nimi podąża, to przekazanie takiego projektu do kolejnego zespołu developerskiego jest znacznie ważniejsze. Też samo zastosowanie Twelve Factor-App to jest coś, do czego to jest zrobione.

Dążyliśmy z Michałem bardzo długo, kolejnymi iteracjami, ulepszając z projektu na projekt ten nasz stack osiągnęliśmy w którymś momencie ten Twelve Factor-App nawet nie tyle, co starając się to robić, tylko „Ej! Spełniliśmy to!”, nawet nie zauważyliśmy. Wychodząc z założenia, że kod, który chcemy przekazać klientowi zamykając projekt czy przekazując zespołowi jest kompletny i posiada w sobie wszystko, łącznie z continuous integration, continuous deployment.

To podejście stosowania tych 12 dobrych praktyk pozwala nam na to. Na to, byśmy mogli aplikację taką kompletną klientowi przekazać i nie ma sytuacji, w której klient dostaje projekt i nagle totalnie nie wie, co dalej z nim zrobić albo pohakowane są jakieś rzeczy po całym projekcie, co powoduje, że musi zatrudnić jakiegoś super drogiego SysOpsa, który będzie to w jakiś sposób odkopywał i wynajdywał co tam się zadziało. To jest w jakiś sposób przewidywalne. Przynajmniej taką mamy nadzieję, taki jest nasz zamiar i tak staramy się te aplikacje wytarzać.

Jasne. To podejście czy też ten zbiór dobrych praktyk faktycznie wywodzi się z Heroku, czyli z takiej platformy passowej, ale obecnie jest dość szeroko stosowane w różnego typu chmurach publicznych. Stąd moje pytanie do Was: czy na ten moment rozwoju software developmentu, jakim jesteśmy, żeby zastosować Twelve Factor-App trzeba mieć aplikację w chmurze czy to nie jest wymóg?

Nie, nie trzeba, chociaż przyznam, że nie mam dużego doświadczenia z hostowaniem czegoś poza chmurą, chyba że powiemy coś o prostych GS-ach, DigitalOcean albo jakiś leanold.

Wciąż traktuję to jako rozwiązania chmurowe, ale jeśli mówimy o takich rozwiązaniach typowo in-house’owych, jakieś serwery ustawione w firmie, jest to też jak najbardziej możliwe, ponieważ może postawić lokalnie jakąś platformę Kubernetesa czy nawet korzystać z Docker Compose’a, które są w dużej części, właśnie — to jest zaleta tego Twelve Factor-App, że on pozwala w jakiś sposób doprowadzić do tego, żeby aplikacja była do dopalenia gdziekolwiek.

Można pójść krok dalej w przypadku rozwiązań mocno cloudowych, WS, poprowadzić do vendor lock-ina i to się kłóci, ale niekoniecznie Twelve Factor-App akurat rozwiązuje ten problem. Tutaj doprowadza do tego, żeby aplikacja była w jakiś sposób przenaszalna, łatwa do odpalenia na środowiskach agnostycznie, o.

Jasne, rozumiem. Myślę, że warto też powiedzieć, że te dobre praktyki nie tyczą się stricte kodu w rozumieniu jak wzorce projektowe, prawda? Nie powiedzą nam bezpośrednio jakich praktyk użyć do zbudowania danej funkcjonalności, ale bardziej się tyczą tego, w jaki sposób uruchamiać, konstruować elementy tej aplikacji, żeby dało się później całość takiego ekosystemu skalować.

Agnostyczność, o której tutaj mówiłeś — zastanawiam się, czy to tyczy się tez języka i frameworka, czy to jest w jakiś sposób to, który język do projektu, jaki framework wybieramy może wpłynąć na to, że będziemy albo nie będziemy w stanie spełnić tych praktyk? Czy to jest jakoś ze sobą powiązane?

Nie, w żaden sposób Twelve Factor-App nie wymienia, nie, narzuca wykorzystania żadnego języka. Przykłady najróżniejsze, jeśli chodzi o pierwsze prezentacje Heroku, wydawało mi się, że są głównie w Javie, my pracujemy w Pythonie, używamy Timescripta, Node’a, także w zasadzie cokolwiek ktoś chciałby użyć, to może.

Myślę, że to dobrze świadczy. Warto też wspomnieć o tym, nie wiem, czy można nazwać ot manifestem, ale powiedzmy coś, co zbiera te zasady, jest nawet wersja polskojęzyczna Twelve Factor — zbiór tych wszystkich zasad, gdzie można je dokładnie przeczytać, natomiast zastanawiam się, czy to jest trochę jak ze Scrumem, że mówimy, że go mamy w momencie, kiedy według definicji spełniamy wszystkie założenia, bo kiedy coś pomijamy, to już właściwie jest to trochę wątpliwe, czy z Twelve Factor-App jest podobnie? Albo musimy wszystkie zasady spełniać, albo nie jesteśmy kompatybilni. Czy też możemy sobie tylko wybrać te elementy, które są w naszym projekcie zasadne, istotne, mają jakiś wpływ i dowolnie sobie to wybierać z tej palety?

Powiedziałbym, że nie trzeba spełniać wszystkich, z tym trzeba bardzo ostrożnie, zanim ktoś mocno się przyczepi tych słów. Powiem, jak to wyglądało u nas. My wprowadzaliśmy te punkty, części Twelve Factor-App w jakimś czasie i doszliśmy do momentu, w którym nasz stack, w którym projekty, które wykonujemy spełniają wszystkie te punkty.

Wykonywaliśmy te projekty w trakcie, które niekoniecznie wszystko spełniało, bo jeszcze nie potrafiliśmy, nie mieliśmy wystarczającej wiedzy czy też odpowiednio wybranych narzędzi, żeby to wszystko spełniać. Także jak najbardziej, da się z tym pracować. Zaletą jest to, że jeśli spełniamy wszystkie, to będziemy w pełni z tego korzystać. Wszystkie plusy otrzymamy i zdecydowanie ta aplikacja będzie wyższej jakości. Trudno byłoby powiedzieć, że spełniamy 50%, otrzymujemy jakieś 50% jakości, ale jak najbardziej są elementy, których jeśli nie spełniamy, to nie jest nic naprawdę strasznego. Trzeba myśleć o dobrych praktykach i o standardach jak o czymś, co musimy spełniać i inaczej mamy grzech i koniec, pójdziemy do piekła, tylko po prostu, jeśli stosujemy dobre praktyki, to możemy się spodziewać, że dług technologiczny, który będzie się wytwarzał w trakcie projektu będzie mniejszy i dążyć do tego, żeby spełniać jak najwięcej.

Jeśli znajdziemy jakąś praktykę, która w pewnym sensie koliduje z tym, co jest wymienione w Twelve Factor-App, ale lepiej działa dla nas, to jak najbardziej warto je stosować, bo to jest wszystko dla ludzi. Tak samo, jak kod, który piszemy. Wybieramy jakieś pewne standardy i czy to będą taby czy spacje, to już tam nie ma większego znaczenia dla samej aplikacji, ma to znaczenie dla ludzi.

Jeśli łatwiej jest nam pracować z wszystkimi, weźmy wszystkie. Jeśli chcemy jakichś kilka sobie powymieniać na coś innego, jeśli jest to możliwe, to jak najbardziej.

Czyli im więcej, tym lepiej, bo to się po prostu nam przysłuży, przysłuży się projektowi. Ale właśnie — to według mnie bardzo rozsądne podejście jest takie, że w sposób iteracyjny też możemy do tego podchodzić, nie musimy od razu wszystkiego, możemy wybrać to, co jest dla nas najistotniejsze i później sukcesywnie ewentualnie implementować pozostałe praktyki. Super.

Tak. My wybraliśmy sobie to, że na pewno chcemy mieć continuous integration, taki sposób. I chcemy spowodować wypchnięcie czegoś na repozytorium, jakiegoś frencha, doprowadziło do deploymentu środowiska devovego. Następnie, żebyśmy mogli to samo zrobić na QA czy tam stage’u, na produkcji. I wychodząc z tego założenia coraz bardziej rozwijaliśmy, dochodziliśmy do pewnego momentu, w którym — Okej, to mamy, teraz jakieś porządnie zrobiony continuous integration, to dodajmy sobie jakieś secrety, to w takim razie w jaki sposób robić to bezpiecznie. To samo się tak nabudowuje i w pewnym momencie osiągamy te wszystkie 12 punktów i niekoniecznie trzeba lecieć z tą historią w jakiś sposób czy jakiś plan wypracowywać sobie, jeśli co my to weźmiemy na warsztat, poznamy, przeczytamy, będziemy mieć to z tyłu głowy.

Sądzę, że i tak dojdziemy od tego etapu, w pewnym momencie nawet przypadkowo, co — jak przyznałem wcześniej, było naszą sytuacją, gdzie to jest coś, co poznaliśmy, rzeczywiście przyjęliśmy do siebie i pracowaliśmy, i rozwijaliśmy nasz stack i nagle się okazało, że nikt tego nie zweryfikował, a jednak już mamy i możemy tylko już ulepszyć dalej detale.

Właśnie, bo to nie są odrealnione zasady, tylko zbiór patyk, które są często stosowane mimowolnie. Wiele zespołów to stosuje, bo to są w naszej branży dobre praktyki, nie wiedząc nawet, że one wchodzą w skład tej listy.

Wszystkie te punkty można przeczytać na stornie 12factor.net — przeczytam, żebyśmy wiedzieli, o czym mówimy.

Pierwsza zasada — code base — jedno źródło kodu, śledzone systemem kontroli wersji, wiele wdrożeń, druga — zależności, jawnie zadeklaruj, wydziel zależności. Trzecia — konfiguracja, przechowuj konfigurację w środowisku.

Czwarta — usługi wspierające, traktuj je jako przydzielone zasoby. Buduj, publikuj, uruchamiaj, oddzielaj etap budowania od uruchamiania. Szóste — procesy, uruchamiaj aplikację jako jeden lub więcej bezstanowych procesów.

Siódme — przydzielanie portów, udostępniaj usługi przez przydzielanie portów, ósme — współbieżność, skaluj poprzez odpowiednio dobrane procesy. Później jest jeszcze zbywalność, dziesiąta — jednolitość środowisk, jedenasta — stosuj logi i dwunasta — zarządzanie aplikacją odbywa się również przez jednorazowe procesy.

Podoba mi się, jak to przeczytałeś, bo brzmiało to, jak 12 przykazań.

Tak, coś w tym jest, faktycznie. Myślę, że tu mielibyśmy zamkniętą pierwszą część tego naszego dzisiejszego podcastu, takie wprowadzenie trochę do Twelve Factor-App, pokazanie szerszej perspektywy, w jaki sposób można to wykorzystać poprzez developerów, jak to może się przysłużyć klientom końcowym.

Chciałbym przejść do drugiej części, w której powiemy, jak te zasady możemy wykorzystać precyzyjnie na AWS. Jakie dobre praktyki czy jakie zasady Wy wypracowaliście implementując albo dostosowując Wasze aplikacje do tego zestawu zasad?

Oczywiście nie przejdziemy przez wszystkie z tych zasad, myślę, że wybierzemy sobie najistotniejsze albo przynajmniej w mojej opinii te, które najłatwiej można wdrożyć z wykorzystaniem AWS-a.

Chciałbym zacząć od konfiguracji. Dlaczego warto sekrety, konfigurację aplikacji z wykorzystaniem usług AWS-owych trzymać?

Jeśli chodzi konkretnie o ten punkt, to co jest w nim najistotniejsze to jest to, że wszystkie wartości, ta konfiguracja jest dostarczana do aplikacji za pomocą zmiennych środowiskowych. Te zmienne środowiskowe można w różny sposób zdefiniować, ale zanim przejdziemy do konkretu, jak to można rozwiązać na AWS, to warto byłoby porozmawiać na ten temat, dlaczego w ogóle zmiennych środowiskowych i do czego to doprowadza.

To, co jest bardzo istotne z naszej perspektywy, to jest to, że możemy oczywiście mieć środowiska zdeploywane do testowania. Będąc software housem, startupem, firmą, która otrzymuje swój produkt — to co jest istotne, to jest to, że oddając kolejne iteracje, dodając kolejne funkcje, ktoś musi je gdzieś przetestować. Zazwyczaj siedzi szereg testerów w zespole, który albo odpala manualne testy albo odpala testy automatyczne i musi gdzieś to wykonać.

To, co jest bardzo istotne z naszej perspektywy, to jest to, że możemy oczywiście mieć środowiska zdeploywane do testowania. Będąc software housem, startupem, firmą, która otrzymuje swój produkt — to co jest istotne, to jest to, że oddając kolejne iteracje, dodając kolejne funkcje, ktoś musi je gdzieś przetestować. Zazwyczaj siedzi szereg testerów w zespole, który albo odpala manualne testy albo odpala testy automatyczne i musi gdzieś to wykonać.

Najpierw środowisko QA, później stage’owe, później produkcyjne i to, co jest ważne, powtarzane wielokrotnie, to jest to, żeby środowiska były do siebie jak najbardziej podobne. Praktycznie takie same. Jedyne, czym się różniły, to konfiguracją.

Jednym ze sposobów na to, żeby móc odpalać różne serwisy, różne kontenery z różnymi konfiguracjami, moglibyśmy wstrzykiwać do nich jakieś pliki. Jest w repozytorium plik z secretami, do czego to może doprowadzić? Jest to niebezpieczne, wszystko może gdzieś wyciec, jest to plain textem trzymane, nawet jeśli mamy prywatne repozytorium na GtiHubie, wciąż jest to trzymane plain textem, więc w zasadzie każde włamanie na GitHuba, wyciągnięcie tych repozytoriów doprowadza do utraty wszystkich secretów. Wiemy, że raczej nie jest to najlepszy pomysł.

Stąd właśnie zmienne środowiskowe, które są tym — czymś, co ma konfigurować dane środowisko i to, co jest u nich super, to jest to, że możemy je dostarczać z zewnątrz w jakiś sposób do danego. Budujemy powiedzmy jakiś obraz, dockera i możemy go odpalić ze zmiennymi środowiskowymi, dowolnymi, w różnych wersjach. Czyli ten sam obraz budujemy raz, odpalamy go na QA, stagingu i produkcji, i dostarczamy do nich zmienne środowiskowe, czyli przetestowanie czegoś na jednym środowisku łatwo pozwala pchnąć to dalej, do kolejnego środowiska bez konieczności ponownego budowania tego w jakiś sposób, także znacznie zwiększa to poczucie bezpieczeństwa, że rzeczywiście to, co zostało przetestowane, to zostało wypchnięte na produkcji.

Jeśli chodzi o AWS, z którego głównie my korzystamy. Są dwie możliwości na dostarczenie czegoś do zmiennych środowiskowych, zależnie oczywiście od tego, co wykorzystujemy do samego deploymentu, ale w przypadku elastic container service’u, jest to np. secret’s manager. To jest serwis AWS-owy, który pozwala zatrzymać wartości po jakimś kluczu, które są zaszyfrowane za pomocą klucza KMS. Ten klucz powoduje, że w momencie, kiedy są trzymane na wejściu, są zaszyfrowane.

Nikt, kto nie a dostępu do tego klucza nie może sobie tego odszyfrować. W jaki sposób wprowadzamy to do aplikacji? Większość serwisów AWS, które służą do jakiegoś deploymentu mają możliwość po prostu po to, że jak dodamy im jakieś prawa do tego, czy to na przywiązanie tego secretu danego swojego kontenera i automatyczne odszyfrowanie go tylko w momencie, kiedy startuje aplikacja, nawet gdy podglądamy sobie co tam się dzieje w tym kontenerze, ta wartość nigdy tam nie jest wypisana, ona dopiero podczas uruchomienia wewnątrz tego kontenera się znajduje.

Druga, która często jest wykorzystywana np. w przypadku server lessowych, jest Parameter Store, z system’s managera. One również są zaszyfrowane KMS-em, ale trochę się różni tym, że w momencie, kiedy są wstrzykiwane do lambdy to one nie są odczytywane w środku w Lambdzie, tylko w momencie deploymentu, czyli powiedzmy, że ktoś, kto ma dostęp do samej funkcji Lambdy jest w stanie sobie to przeczytać. To są dwa, główne bieguny możliwości na to, jak dostarczyć taki konflikt i to, co jest super, to że definiując jedną taką zmienną, jedną wartość, możemy ją dostarczyć zarówno do Lambdy czy do kontenera NCS-a, Pinstocka, jakby ktoś chciał, także jest to centralne miejsce, z którego pobieramy te wartości.

👉 Czytaj dalej na: https://porozmawiajmyoit.pl/poit-128-12-factor-app-z-wykorzystaniem-serwisow-aws/

kkempin’s dev blog

Dev and life blog. Thoughts about programming, design patterns, Ruby and life.

Krzysztof Kempiński

Written by

IT expert. Ruby on Rails/iOS/Elixir programmer. Blogger. Podcaster.

kkempin’s dev blog

Dev and life blog. Thoughts about programming, design patterns, Ruby and life.