Observer in Erlang/Elixir release

When I teach OTP I always show observer application. Observer is a graphical user interface capable of displaying supervision trees and providing information about processes. It is really cool to show how processes get restarted and what structure they follow. It is also suitable for using with production systems too!

Erlang example for teaching purposes

You can start observer by typing this inside Erlang shell.

observer:start().
observer app
observer app

Cowboy and ranch are great examples of using OTP principles in action.

WARNING: You need at least Erlang 18 installed to work with cowboy examples from master.

git clone https://github.com/ninenines/cowboy.git
cd cowboy/examples/rest_hello_world
make run
(rest_hello_world_example@127.0.0.1)1 observer:start().
** exception error: undefined function observer:start/0

You can easily start the example but not observer.

Cowboy uses erlang.mk to build the apps. It automatically pulls dependencies, compiles code and generates a release. Releases are self contained packages that include Erlang. They can be copied to another server and they should run fine even if Erlang is not installed there (as long as the other server has the same CPU architecture). They also strip all unnecessary applications to make the final output lightweight. This includes observer.

Releases are great for deploying to production but for teaching purposes I would like to use observer with the generated release. How can I do that? After running make run for the first time, ebin directory is created. Edit file ebin/rest_hello_world.app like this:

{applications, [kernel,stdlib,cowboy,runtime_tools,wx,observer]},

Those three applications: runtime_tools, wx and observer are all you need to launch observer gui. Just type make run again. For producation systems you probably don’t want to include entire observer with wx widgets. It would be better to leave out the graphical part and just add bare minimum to the release so we can inspect it from outside. Lets do it this time with an Elixir example.

Elixir example for production purposes

We can apply similar trick. Lets build an Elixir release using exrm. After adding it as dependency we can run:

MIX_ENV=prod mix compile
MIX_ENV=prod mix release
rel/my_app_name/bin/my_app_name console

This should result in something like this:

iex(my_app_name@MacBook-Pro-Tomasz)1 Node.get_cookie
:my_app_name
iex(my_app_name@MacBook-Pro-Tomasz)2 :observer.start
** (UndefinedFunctionError) undefined function :observer.start/0 (module :observer is not available)

As before our release stripped all additional stuff. This time instead of adding all three applications needed to start observer, lets only add bare minimum that will enable inspecting running node from outside. Inside mix.exs application section add :runtime_tools:

applications: [:phoenix, :phoenix_html, :cowboy, :logger, :gettext,
               :phoenix_ecto, :postgrex, :runtime_tools]]

Now repeat those three steps:

MIX_ENV=prod mix compile
MIX_ENV=prod mix release
rel/my_app_name/bin/my_app_name console

But this time open another iex console starting completely different Erlang node:

iex --sname watcher --cookie my_app_name
iex(watcher@MacBook-Pro-Tomasz)1 :net_adm.ping :"my_app_name@MacBook-Pro-Tomasz"
:pong
iex(watcher@MacBook-Pro-Tomasz)2 :observer.start
:ok

Now in observer choose from menu Nodes and then my_app_name@MacBook-Pro-Tomasz. Adding just one application to our release (the :runtime_tools) enabled us to connect to our release from outside and start inspecting it! Runtime tools is an application that delivers “low footprint tracing/debugging tools suitable for inclusion in a production system”.

If you want to play with it, try going to Applications tab. You can right click on any process and kill it with arbitrary reason. What happens with children PIDs?

Advertisements

Failing fast and slow in Erlang and Elixir

I am recently teaching programming with Elixir and Phoenix in Kraków. During classes, I saw, that new Erlang and Elixir programmers have problems with concept of “failing fast”, so I’ll explain it with examples, but first I need to show you…

The Golden Trinity of Erlang

Torben Hoffman in many of his webinars about Erlang programming language mentions “The Golden Trinity of Erlang”
ndc-london-2014-thinking-like-an-erlanger-9-638

The three principles are:

  • Fail fast
  • Share nothing
  • Failure handling

There are many articles explaining how sharing nothing is great for concurrency. Failure handling is usually explained when teaching OTP supervisors. But what does it mean to “fail fast”?

Failing fast principle

“Fail fast” principle isn’t exclusive to Erlang. In agile methodologies, it expands to:

  1. don’t be afraid to try something new;
  2. evaluate it quickly;
  3. if it works – stick with it;
  4. if not – abandon it fast, before it sucks too much money/energy.

This business approach translates almost directly to programming practice in Erlang.

Happy path programming

When I write in Erlang, I usually don’t program for errors. I can treat most errors or edge cases as if they don’t exist. For example:

{ok, Data} = file:read_file(Filename),
do_something_with_data(Data)

There is no code for handling situation, where file does not exist or I don’t have permissions to open it. It makes the code more readable. I only specify business logic instead of myriad of edge cases.

Of course, I can match on some errors. Maybe I want to create a file if it doesn’t exist. But in that case it becomes application logic, so my argument about not programming for edge cases still holds.

case file:read_file(Filename) of
  {error, enoent} -> create_file();
  {ok, Data} -> do_something_with_data(Data)
end,

This style of programming is called “happy path programming”. It doesn’t mean, that I don’t anticipate errors. It just means that I handle them somewhere else (by supervision trees and restarting).

Failing fast case study 1 – reading from a file

This style of programming requires the code to fail quickly, when problem occurs. Consider this code:

{_, Data} = file:read_file(Filename),
do_something_with_data(Data)

Reading the file could actually return {error, Reason} and then I treat the Reason atom as Data. This propagates the error further, where it is harder to debug and can pollute state of other processes. Erlang is dynamically typed language, so do_something_with_data/1 can pass atom many levels down the call stack. The displayed error will say, that it can’t treat atom as text and the bug gets tricky to find. Even functions, that are used purely for their side effects should match on something to check, if they worked, so instead of:

file:write_file(FileName, Bytes)

it is usually better to use:

ok = file:write_file(FileName, Bytes)

Failing fast case study 2 – calling gen_server

It is even more important to fail before sending anything wrong to another process. I once wrote about it in this blog post. Sending messages using module interfaces helps keep the damage made by errors contained. Crashing caller instead of server is “quicker”, so it doesn’t contaminate application state. It allows failure handling strategies much simpler than preparing for all possible edge cases. Most of the time those strategies are based on restarting processes with clean state. Processes and computation are cheap and can be restarted, but data is sacred.

Case study 3 – tight assertions

Lets consider another example. A test suite:

ok = db:insert(Value),
Value = hd(db:get(Query))

It tests database code by inserting single value to empty database and then retrieving it. However, if we assume, that the database was empty before test execution, we can make sure, that id doesn’t return anything else. Second line above is equivalent to:

[Value | _] = db:get(Query)

But I can make the assertion stronger by writing:

[Value] = db:get(Query)

It asserts both value and number of elements in the list. Sweet!

“Fail fast” is another example of applying “immediate feedback principle” in programming. It allows happy path programming, which makes programs more readable, but requires treating each line as an assertion. It is easy to do this with pattern matching.

Failing fast and supervision trees = ♥♥♥

Od zera do web crawlera.

Nadeszła nowa era w edukacji.

Internet coraz bardziej pomaga nam w codziennym życiu. Pomaga nam się komunikować, organizować spotkania, dzielić się zdjęciami oraz ciekawymi informacjami. Teraz przychodzi kolej na edukację. W internecie jak grzyby po deszczu wyrastają nowe kursy internetowe. Czy mogą one pomóc nam w nauce? Jakie są plusy, a jakie minusy, gdy porównamy je z nauką w szkole lub czytaniem książek w domowym zaciszu?

W ostatnim semestrze uczestniczyłem w internetowym kursie na temat sztucznej inteligencji: https://www.ai-class.com/

Jestem nim absolutnie zachwycony! Mam wrażenie, że nauczyłem się o wiele więcej niż na wykładach ze studiów, które poruszały podobną tematykę. Dodatkowo, zajęło mi to mniej czasu i było o wiele przyjemniejsze. Na początku nie rozumiałem do końca tego fenomenu. Wykładowcy na studiach prowadzą zajęcia w ciekawy i w miarę zróżnicowany sposób i nie można powiedzieć, żeby w jakiś sposób ustępowali wiedzą, czy talentem pedagogicznym ludziom, którzy prowadzili kurs sztucznej inteligencji.

To o co chodzi?

Chodzi o formę. Czego potrzebuje ludzki mózg, aby szybko i skutecznie przyswajać wiedzę?

  • odpowiedniego tempa nauki
  • częstej symulacji w postaci pytań lub rozwiązywania problemów
  • ram czasowych
  • motywacji

Niestety tempa nauki nie da się dopasować do każdego ucznia w klasie liczącej trzydzieści osób. Niektórzy myślą, że dopasowanie tempa polega na obniżeniu go do poziomu najwolniejszych uczniów. Nic bardziej mylnego! Jeśli coś dzieje się zbyt wolno, to uczeń się nudzi i przyswaja jeszcze mniej. Kursy internetowe rozwiązują ten problem w prosty sposób: dzielą wykład na wiele krótkich filmów, w których dzieje się w miarę dużo. Jeśli uczeń się nudzi, może przewinąć odcinek. Jeśli sobie nie radzi, może obejrzeć kilka razy trudniejszy fragment i spokojnie się nad nim zastanowić.

Wykład jest najsłabszą możliwą formą przekazywania wiedzy, ponieważ nie dostarcza stymulacji. Właściwszym sposobem nauki są ćwiczenia i powtórki. Pytanie rzucone na salę w trakcie wykładu, natychmiast pobudza śpiących studentów. Pytanie uczniów w trakcie lekcji przynosi lepsze skutki niż tylko na początku. Twórcy kursów interenetowych, co kilka minut zadają pytanie, dzięki któremu można upewnić się, czy właściwie rozumiemy kolejną partię materiału.

Szkoła dostarcza czegoś, czego nie mamy ucząc się samodzielnie w domu – ram czasowych. Ramy czasowe dają nam motywację. Musimy nauczyć się na sprawdzian. Trzeba zrobić zadanie domowe. Powinienem skończyć ten projekt za dwa tygodnie. Nie każdy ma na tyle silną wolę, żeby utrzymać dobre tempo nauki bez żadnych czynników zewnętrznych. Obecnie, kursy internetowe dają nam przedział czasu na wysłuchanie lekcji i odrobienie zadań domowych. Dzięki temu, mamy pewną elastyczność. Możemy słuchać wykładów, kiedy jesteśmy wypoczęci, a nie wtedy, kiedy zbiera się grupa osób. Jednocześnie, mamy motywujące ograniczenie.

No i przechodzimy do tematu motywacji. Jakoś tak się utarło, że oceny w szkole są kojarzone negatywnie. Jak coś zrobisz dobrze, to masz piątkę, ale spróbuj się pomylić, to ja Ci to obniżę! System oceniania jest troszkę inny w kursach interentowych. Kiedy odpowiadamy na pytania w trakcie wykładów, nie musimy się martwić. Nie liczą się do końcowej oceny, więc możemy poeksperymentować. Ponadto nie ma problemu z tym, że nauczyciel pomyśli, że jesteśmy głupi, albo powie: “Gdybyś słuchał/a, to byś wiedział/a”. Zadania domowe polegają na zrobieniu zadań podobnych do tych, które rozwiązywało się w trakcie wykładów, ale tym razem właściwe rozwiązania pojawiają się dopiero pod koniec przedziału czasowego. Zbieramy punkty, a im więcej ich uzbieramy, tym lepiej.

Jest jeszcze kilka rzeczy, których nie wymieniłem. Na przykład filmiki stymulują więcej zmysłów niż książki, co również pozwala zapamiętać więcej i na dłużej.

Trochę się rozpisałem, a to po to, aby zachęcić do uczestnictwa w kursach, które sam przetestowałem:

Ostatni z powyższych linków, nie jest typowym kursem, ponieważ nie posiada ram czasowych. Można go traktować trochę, jak bibliotekę z podręcznikami.

Jeśli ktoś kliknął w powyższe linki może zobaczyć, że wszystkie te kursy mają jedną wadę. Są po angielsku. Niestety, w dzisiejszych czasach znajomość języka angielskiego trzeba uznać za coś tak niezbędnego, jak umiejętność czytania i pisania.

Interdyscyplinarność

Dzisiaj na uczelni wysłuchałem wykładu profesora Sloota na temat:

“How to become a specialist when computer science is ubiquitous”

Odpowiadział na to pytanie pokazując nam, nad czym sam pracuje. Według niego najważniejsze jest pracować interdyscyplinarnie. Komputer ma być dla informatyka narzędziem, które wykorzysta przy prowadzeniu badań w dziedzinach nie związanych z informatyką. Według niego, przyszłość stanowi stworzenie nowych w pełni dyskretnych modeli do opisu zjawisk występujących w medycynie, czy też w kontaktach międzyludzkich.

http://staff.science.uva.nl/~sloot/

Wstęp do informatyki

Witam!

Jestem studentem czwartego roku informatyki na wydziale EAIiE na AGH. Mieszkam już czwarty rok w akademiku, gdzie poznałem już masę ciekawych ludzi. Parę dni temu okazało się, że za ścianą mieszka studentka pierwszego roku informatyki. Jedną z pierwszych rzeczy, jakie od niej usłyszałem, było zdanie:

“Na stronie informatyki znalazłam sylwetki absolwentów, którzy pisali <<Już od gimnazjum programuję>> i zastanawiam się teraz, co ja tu właściwie robię?”

Sam zaczynałem podobnie. Lekcje informatyki w liceum, do którego chodziłem, były prowadzone na bardzo marnym poziomie, więc przed rozpoczęciem studiów nigdy nie napisałem żadnego programu. Nie wydaje mi się, żebym miał z tego powodu trudniej na pierwszym roku studiów. Jednak przyszło mi do głowy, że gdybym wiedział kilka bardzo prostych rzeczy (nie dotyczących programowania), to byłoby mi o wiele prościej. Oto one:

  1. Zacznij używać linuxa.
  2. Ucz się przez szybkie, krótkie ćwiczenia.
  3. Zacznij uczyć się konsolowych edytorów: vim oraz emacs.
  4. Matmy ucz się często, a nie długo.
  5. Ucz się wielu rzeczy na pamięć.
  6. Używaj latexa.

Ad 1. Pierwszą dystrybucją linuxa, którą zainstalowałem, był linux Ubuntu. Polecam ją każdemu, kto dopiero zaczyna swoją przygodę z linuxem. Zainstaluj ją, a następnie w miarę możliwości staraj się coraz więcej czynności wykonywać wyłącznie za pomocą tekstowego terminala. Biegłość w posługiwaniu się komendami szybko zaprocentuje. Ja niestety zacząłem używać linuxa jako swojego “głównego” systemu operacyjnego dopiero na drugim roku studiów. Trochę tego żałowałem, bo teraz już wiem, że wiele traciłem i nie byłem tego do końca świadom.

Ad 2. Na pierwszych ćwiczeniach z WDI (tytułowy Wstęp do informatyki) dostaliśmy polecenie: “Na następny raz nauczcie się Pascala”. Wielu z nas w przerażeniu myślało: “Mieli nas tu uczyć programować, a mamy się tego nauczyć sami?”. Programowanie jest trudne, ale uczenie się składni języka programowania nie jest, a o to właśnie chodziło prowadzącym. Znajdź tutorial, który uczy składni Pascala. Zainstaluj pod swoją dystrybucją linuxa kompilator i spróbuj wykonać kilka zadań oznaczonych jako łatwe ze strony: http://pl.spoj.pl/problems/latwe/. Jedno zadanie dziennie da Ci biegłość w składni, która przyda się, kiedy trzeba będzie zapisać algorytm.

Ad 3. Jeśli chcesz pisać dużo na komputerze, musisz nauczyć się pisać wszystkimi palcami, prawda? Wszystkimi palcami pisze się szybciej i nie trzeba zerkać na klawiaturę. Ale często uczenie się pisania wszystkimi palcami mocno nas spowalnia przez pewien okres czasu. Mieliśmy biegłość w używaniu czterech, czy sześciu palców, a tu trzeba się przestawić. Niedługo później piszemy tak szybko jak wcześniej, a potem jeszcze szybciej. Po co ten cały wstęp? Posługiwanie się edytorem konsolowym oraz terminalem jest dość trudne, ale opanowanie tych umiejętności jest bardzo przydatne. A im wcześniej zaczniesz się uczyć, tym szybciej zdobędziesz biegłość.

Ad 4 oraz 5. Osoby, które odpadły na egzaminach z matmy po pierwszym roku naszego kierunku mówią, że uczymy się samej matmy i teorii programowania. Rzeczywiście pierwszy rok jest przesycony matematyką, której sensu na początku nie widać. Wielu z nas nigdy nie policzyło całki powierzchniowej po tym, jak zdali egzamin z analizy. Jednak te podstawy matematyczne często przydają się do zrozumienia bardziej zawiłych konceptów, a w dodatku przedmioty matematyczne stanowią większość punktów ECTS, które można zdobyć na pierwszym roku.

I tu wielu ludzi, którzy mieli świetne wyniki z matury z matematyki wykłada się, ponieważ nie umieją się uczyć matematyki. W liceum najczęściej w ogóle nie musieli, bo to, co powiedział nauczyciel wystarczyło im do zrozumienia tematu. Na studiach matematyki jest więcej i często trzeba nauczyć się wielu rzeczy na pamięć.

“Zwariowałeś? Nie będę rył matmy na pamięć!!!”

Owszem, trzeba zrozumieć to, czego się uczyć, ale na kolokwium nie będzie czasu na wyprowadzanie wszystkich twierdzeń i ich założeń. Niektóre trzeba znać i już. Podobnie jest ze schematami rozwiązywania zadań. Jeżeli chcesz się tego nauczyć, to rób to codziennie. Lepeiej siąść nad tym codziennie po godzinie, niż na 6 godzin dzień przed kolosem. Jeśli lubisz uczyć się w większym gronie, warto zrobić kilka zadań wspólnie. To bardzo pomaga.

Wydrukuj sobie wykłady z matematyki i przejrzyj je pobieżnie przed wykładem. Czas przeznaczony na notowanie przeznaczysz na pierwszą próbę zrozumienia wykładu.

Ad 6. Latex to oprogromawoanie, dzięki któremu pisanie sprawozdań przestanie być uciążliwe. Wklepywanie chorych wzorków do worda można zastąpić o wiele prostszym opisem tego, co chcemy uzyskać. Tej samej składni używają również fora, na których umieszcza się wzory matematyczne.
Mam nadzieję, że te kilka rad komuś się przyda. :) Żadna z wymienionych tutaj rzeczy nie jest niezbędna do zaliczenia studiów. Są to tylko małe tricki ułatwiające życie.