niedziela, 12 kwietnia 2015

W głąb Value Classes,Warsztaty ze ScalaCheck,Scalar

Temat pojawił się na warsztatach : Czy jeśli klasa rozszerza AnyVal i się wywali w Runtimime to co dokładnie będzie widać w stacktrace? Czy będzie informacja o tym, ze to była klasa czy też będzie tam widniał typ prymitywny?

Odpowiedź na tak postawione pytanie brzmi "Tak, masz rację, teraz mnie zostaw w spokoju"

Labolatorium

Na początek przygotujmy aparaturę badawczą

class Domenowa(val s:String) extends AnyVal
Ćwiczenie pierwsze - zrobić aby coś się wywaliło. Wrzućmy granat w środek :
val d=new Domenowa(null)
"Exception in thread "main" java.lang.NullPointerException
 at com.wlodar.nauka.oop.Domenowa$.hashCode$extension"
Zaraz zajrzymy pod mikroskop ale najpierw jeszcze jedna wypierdółka :
class Domenowa(val s:String) extends AnyVal{
    null.toString
  }

I tu się tego nie spodziewałem :
Error:(18, 10) this statement is not allowed in value class
    null.toString
         ^
Wygląda na to, ze ValueClasses w ogóle nie mogą mieć konstruktorów.
To jeszcze inaczej :
class Domenowa(val s:String) extends AnyVal{
    def logic=null.toString
}
I się wywaliło :
Exception in thread "main" java.lang.NullPointerException
 at com.wlodar.nauka.oop.Domenowa$.logic$extension

Pod oscyloskop go

Po kompilacji mamy tka naprawdę dwie klasy. Ta Domenowa$ nie pojawia się gdy nie rozszerzamy AnyVal
-rw-rw-r-- 1 pawel pawel 1875 kwi 12 21:22 Domenowa.class
-rw-rw-r-- 1 pawel pawel 1170 kwi 12 21:22 Domenowa$.class

javap Domenowa

public final class com.wlodar.nauka.oop.Domenowa {
  public static boolean equals$extension(java.lang.String, java.lang.Object);
  public static int hashCode$extension(java.lang.String);
  public static java.lang.String logic$extension(java.lang.String);
  public java.lang.String s();
  public java.lang.String logic();
  public int hashCode();
  public boolean equals(java.lang.Object);
  public com.wlodar.nauka.oop.Domenowa(java.lang.String);
}

javap Domenowa$

public final class com.wlodar.nauka.oop.Domenowa$ {
  public static final com.wlodar.nauka.oop.Domenowa$ MODULE$;
  public static {};
  public final java.lang.String logic$extension(java.lang.String);
  public final int hashCode$extension(java.lang.String);
  public final boolean equals$extension(java.lang.String, java.lang.Object);
}

Strzelam, że kiedy wywoływana jest metoda logic na klasie Domenowej to gdzieś tam pod spodem ten string ze środka jest przekazywany do tego logic$extension(java.lang.String). Jest jedna instancja Domenowa$, ValueClasses nie maja pól to nei ma stanu i to wszystko tak działa (chyba). Postanowiłem zdekompilowac kod z opcja -c by zobaczyć bytecoda
 public final java.lang.String logic$extension(java.lang.String);
    Code:
       0: aconst_null
       1: invokevirtual #18                 // Method java/lang/Object.toString:()Ljava/lang/String;
       4: areturn

Po czym się zastanowiłem po co właściwie chce go zobaczyć jak i tak się na tym nie znam?

To może jednak prościej

Potwórzmy kilka identycznych klas.
class Domenowa(val s:String) extends AnyVal{
    def logic=this.toString()
  }

println(new Domenowa("abc"))
    println(new Domenowa("abc"))
    println(new Domenowa("abc"))
    println(new Domenowa("abc"))
    println(new Domenowa("abc2"))
    println(new Domenowa("abc2"))
    println(new Domenowa("abc").logic)
    println(new Domenowa("abc").logic)
com.wlodar.nauka.oop.Domenowa@17862
com.wlodar.nauka.oop.Domenowa@17862
com.wlodar.nauka.oop.Domenowa@17862
com.wlodar.nauka.oop.Domenowa@17862
com.wlodar.nauka.oop.Domenowa@2d9410
com.wlodar.nauka.oop.Domenowa@2d9410
com.wlodar.nauka.oop.Domenowa@17862
com.wlodar.nauka.oop.Domenowa@17862
I cuda. Jak jest ten sam string to i jest ta sama referencja. Jeśli dla eksperymentu usuniemy extends AnyVal to już to nie działa. Czyli tu nie działa przez co udowadniamy , że ogólnie mechanizm jak taki działa.
class Domenowa(val s:String){
    def logic=this.toString()
  }

com.wlodar.nauka.oop.Domenowa@48140564
com.wlodar.nauka.oop.Domenowa@58ceff1
com.wlodar.nauka.oop.Domenowa@7c30a502
com.wlodar.nauka.oop.Domenowa@49e4cb85
com.wlodar.nauka.oop.Domenowa@2133c8f8
com.wlodar.nauka.oop.Domenowa@43a25848
com.wlodar.nauka.oop.Domenowa@3ac3fd8b
com.wlodar.nauka.oop.Domenowa@5594a1b5
wracamy do class Domenowa(val s:String) extends AnyVal{ def logic=this.toString() } Znowu zdekompiluje bytecod Domenowa$ (sam nie wiem po co).
 public final java.lang.String logic$extension(java.lang.String);
    Code:
       0: new           #16                 // class com/wlodar/nauka/oop/Domenowa
       3: dup
       4: aload_1
       5: invokespecial #19                 // Method com/wlodar/nauka/oop/Domenowa."":(Ljava/lang/String;)V
       8: invokevirtual #23                 // Method java/lang/Object.toString:()Ljava/lang/String;
      11: areturn

i niby tutaj jest instrukcja new, która tworzy klasę domenową. Według dokumentacji to alokuje nową instancję a jednak sprawdzaliśmy, że tak się nie dzieje. Co umacnia mnie w przekonaniu, ze na bytecodzie Javy się nie znam.
http://docs.scala-lang.org/overviews/core/value-classes.html

Najbliższe spotkania i warsztaty ze Scalacheck

W Maju/Czerwcu przyjedzie Damian Warszawski z Touka z warsztatem o Javie8 :
"
żeby się nie zastanawiać za długo to moja propozycja warsztatu: 

Intro to java8 workshop: 
agenda: 
Lambda Expressions 
Stream API 
DateTime package 

W ciągu tygodnia przygotuje repo na githubie i przygotuje krótki opis warsztatu.
"

I jeszcze jakoś na początku maja Cezary Draus który też pracuje w Touku (oraz pociągu relacji Łódź-Warszawa) zrobi warsztaty z intellij.

W tym wszystkim jedyny rozsądny termin w jaki mogę się wcisnąć z warsztatami to 20 kwietnia : Scalacheck i Property Based Testing - Warsztaty

Będą trzy iventy w tygodniu ale damy radę.

Scalar

W końcu laptop wygląda jak laptop do programowania :
Muszę sobie załatwić drugi zestaw na komputer w pracy zanim mi ktoś nie przylepi naklejek : "Sharepoint,Excel,Outlook,Ms Project,UML "
Konferencja była fajna i dłuższej relacji pisać nie będę bo ludzie później nie kumają dowcipów i rzucają kamieniami w okna :D Było fajnie i tyle.

niedziela, 29 marca 2015

Traity ortogonalnie i nieortogonalnie

"Wiem, że nie wiem" to tzw. poziom świadomej niekompetencji kiedy miejsce ignorancji zastępują pytania bez odpowiedzi.

I takie właśnie pytanie pojawiło się na ostatnim warsztacie - jak dobrze zmodyfikować zachowanie klasy przy pomocy Traita tak by ona nic o tym nie wiedziała. Na miejscu niestety nie udało mi się odpowiedzieć ale teraz mamy drugą szansę.

Ortogonalne

Ortogonalne to to samo co prostopadłe ale brzmi mądrzej. W tym przypadku nie ma modyfikacji zachowania klasy jako takiej ale Trait dodaje zupełnie nową funkcjonalność - tutaj logowanie.

abstract class Actor {
    def receive(s:String):Unit
}

//wersja oryginalna
class EchoActor extends Actor {
    override def receive(s:String)=println(s"echo $s")
}

//wersja z mixinem
class EchoActor extends Actor with Logging{
    override def receive(s:String)={
        logger.log(s)
        println(s"echo $s")
    }
}


trait Logging{
    class Logger{
        def log(s:String)=println(s"LOGGING : $s")
    }
    val logger=new Logger
}

 new EchoActor().receive("message")

I teraz pytanie jak to zrobić by dodać to logowanie ale bez modyfikacji EchoActor?

Podejście pierwsze - self type

Trzeba trochę eksperymentować w życiu i nie zrażać się tym, że czasem nie wychodzi. Bo teraz to co napiszę nie zadziała.

//ten kawalek/mechanizm "self:Actor=> " nazywa się "self-type" i daje traitowi
//wiedzę, z jaką klasą będzie zmiksowany
trait NonOrthogonalLogging1{self:Actor=>
    
    def cosTam(){
      self.receive("aaa")
    }
//chociaz nie dziedziczymy po aktorze to trzeba dać override bo inaczej będzie się walić przy miksowaniu    
    override def receive(m:String):Unit={
      println(s"INFO : ${m}")
//nie można tutaj użyć super bo teoretycznie dziedziczymy z AnyRef
      self.receive(m)
    }
  }

//no i koniec końców nic niespodziewanego się nie dzieje, "self.receive" wywołuje metodę z traita a nie z klasy i cały program się zapętla.
val echo=new EchoActor() with NonOrthogonalLogging1
echo.receive("test")

Podejście drugie - dziedziczenie klasy abstrakcyjnej

trait NonOrthogonalLogging2 extends Actor{self:Actor=>
    
//to jest dziwne, trzeba dać abstract bo inaczje kompilator sie pluje, ze receive z nadklasy jest abstract.
    abstract override def receive(m:String):Unit={
      println(s"INFO : ${m}")
      super.receive(m)
    }
  }
  
  class EchoActor extends Actor{
    def receive(m:String)=println(s"ECHO ${m}")
  }

   //no i to już działa
   val echo=new EchoActor() with NonOrthogonalLogging2
   echo.receive("test")

//INFO : test
//ECHO test

Oczywiście, jeśli ktoś wie jak to zrobić lepiej niech śmiało da znać.

Warsztat

Na warsztat http://www.meetup.com/Java-User-Group-Lodz/events/221347512/ zapisało się 25 osób +15 jest na liście oczekujących co daje 40 osób zainteresowanych nauką Scali. Fajnie, że ludzie są zmotywowani do nauki Scali i to także motywuje mnie, żeby robić te warsztaty.

Niedawno na EDX był kurs szczęścia- dosłownie kurs szczęścia EDX : Science of hapiness. - bazujący na ciekawym dziale psychologii czyli Psychologii pozytywnej. Motyw działalności w lokalnych społecznościach pojawiał się tam dosyć często.

Więcej można o tym poczytać sobie też tutaj : http://www.actionforhappiness.org/10-keys-to-happier-living/local-community/details. Interakcje społeczne zwiększają nasilenie wytwarzania oksytocyny, która jest hormonem antagonistycznym do kortyzolu co generalnie poprawia nastrój i tak dalej.

poniedziałek, 23 marca 2015

Warsztaty,insulina i dźwignia emocjonalna

W zeszłym tygodniu odbyły się trzy eventy edukacyjne.
Mam z nich foty.
Foty można podzielić na dwa rodzaje
Foty z logiem
Foty bez loga
Można umieścić foty bez loga - są one przyjemne i nic poza tym
Można umieścić foty z logiem
Być może stworzą one dodatnie sprzężenie zwrotne pomiędzy jednostką generującą wartość edukacyjną a firmą, która czerpie wartość marketingową
Co może doprowadzić do nasilenia tego procesu
Co jest dobre
Ale
O firmie słyszałem, gdzie na spotkaniu ludzi z krwią w kolorze błękitu (w to uwierzyli bo sami sobie nawciskali kitu)
Decyzja zapadła by wszelka forma dzielenia się treścią z internetem byłą centralnie kontrolowana
W czasie gdy na twitterze idzie 1000 branżowych tweetów na sekundę
Centralne sterowanie
W czasie gdy w net leci 100000 lajków an sekundę
Centralne sterowanie
POWO-KU*WA-DZENIA

Wracając do edukacji

Jeszcze raz dzięki dla Marcina Grzejszcza­ka i Lukasza Szczęsnego za warsztat z mikroserwisów. Poznaliśmy wiele fajnych narzędzi.

Dzięki dla Marka Śmigielskiego za prezentację o Dockerze :

I warsztaty ze scali :

Najbliższy czas

  • Chyba największym wydarzeniem w kwietniu na JUGu będzie występ Jacka Laskowskiego : meetup
  • Ale nie zapomnijmy o innych. 9 kwietnia Marcin Korniluk opowie o Material Design in Practice : meetup (trzeba kalendarz uaktualnić)
  • Pod koniec kwietnia (w Końcu) warsztat! Piotr Zalewski z Cybercom i Grails. Już jest komplet 20 osób także ta technologia też się cieszy zainteresowaniem : meetup
  • A za tydzień pyknę podstawy OOP w Scali. Myślałem, ze gdzieś będę jechał a chyba nie będę : meetup

Pizza na warsztatach

Pizza jest łatwa w obsłudze logistycznej ale na dłuższą metę trzeba znaleźć inne źródło żywienia.
http://www.kuchnia-kuchnia.pl/pl4/teksty1037/wplyw_jedzenia_na_reakcje_hormonalne_organizmu

Niedobór glukozy określany jest jako hipoglikemia lub niski poziom cukru we krwi, powoduje on zmęczenie psychiczne, wywołuje senność która występuje zwłaszcza po spożyciu posiłku lub napoju bogatego w węglowodany. Wątroba nie może jednak tak po prostu uzupełnić glukozy korzystając ze zmagazynowanych zapasów. Zbyt gwałtowne wydzielanie insuliny następujące po spożyciu tych posiłków, uniemożliwia uzupełnienie we krwi glukozy, a to powoduje „wyłączanie się” mózgu.

Wykres na czerwono to niezdrowe nawyki żywieniowe większości ludzi, u których w diecie dominują cukry proste występujące w przetworzonej żywności jak batoniki czy słodkie napoje. Do teog coś było ze wzmacniaczami smaku i tłuszczami trans zawartymi właśnie w pizzy. Zdaje się, że one w długim okresie zwiększają insulinoodporność komórek czy coś takiego. W każdym razie jeśli ktoś ma niski poziom glukozy we krwi to po takiej pizzy pewnie jebnie się spać.

Alternatywnie można jako źródło cukrów używać węglowodanów złożonych jak ryżu brązowego, kaszy itd. Węglowodany złożone są trawione dużo dłużej przez co nie powodują nagłego wyrzutu insuliny. Do tego błonnik z surówki może przedłużyć cały proces trawienia rozciągając wyrzut insuliny. No i gdy poziom glukozy jest na optymalnym poziomie kolejne posiłki nie powinny powodować senności.

Można jeszcze spojrzeć na to : http://pawelwlodarski.blogspot.com/2012/07/bazodanowy-model-hipotezy-insulinowej.html.

Dźwignia emocjonalna

I na koniec technika motywacyjna do nauki, która zwie się "dźwignią emocjonalną"(emotional leverage) i została zaczerpnięta od światowej sławy mówcy motywacyjnego - Tonego Robinsa.

Jakkolwiek ponieważ nie mogę znaleźć żadnego linku, więc może to się inaczej nazywało i nie był to Tony Robins. W każdym razie idea jest prosta.

  1. Mamy sytuację 1: w której aby dokonać zmiany należy włożyć weń pewien wysiłek. Ponieważ działa Homeostaza,strefa komfortu, lenistwo itd., więc o zmianę trudno
  2. Dążymy do sytuacji 2 : w której utrzymanie obecnego stanu wymaga od nas więcej energii aniżeli dokonanie zmiany
Brzmi bardzo abstrakcyjnie, więc przykład - ten będzie dobry dla introwertyków.

Strach przed podejściem do obcej osoby. Podejście (zmiana) to wydatek energetyczny. Pozostanie w danym miejscu - Homeostaza - oszczędzanie energii.

Teraz wyobrażmy sobie, że ktoś tak sprytnie szturcha tę obcą osobę w ramię, że ona myśli iż to my zrobiliśmy
W tej sytuacji jest tak dziwnie i niezręcznie, że tak naprawdę nie zrobienie niczego wymaga od nas więcej wysiłku niż powiedzenie czegokolwiek. I tak dochodzimy do sytuacji, gdzie zmiana jest łątwiejsza w wykonaniu aniżeli pozostanie w status-kło.

Podobną technikę można wykorzystać by zmotywować siebie do wystąpień publicznych bądź to przez deklaracje, ze to zrobimy (wtedy wycofanie się to dodatkowy wysiłek psychiczny). Bądź też dajemy znajomej osobie 1000 złotych i może ona oddać nam je tylko po wystąpieniu.

W wersji HARDCORE ta technika kołczingu i motywacji zaprezentowana jest w poniższym filmiku od sekundy 0:48 do gdzieś tak 2:00.

Udanej zabawy.

poniedziałek, 2 marca 2015

Warsztaty - wstęp do OOP w Scali plus ogólnie o nauce

GitBooks - bardzo dobre do umieszczania ćwiczeń

Znalazłem fajna stronkę do umieszczania kawałków kodu do warsztatów. Linki poniżej i teraz już nie będę miał stresu, ze jak wysyłam namiary to tylko po to by nabijać ilość odwiedzin na blogu

Kolejne spotkania JUG

W środę są warsztaty z programowania wielowątkowego w scali. 15 osób było na waitliście także zwiększyłem limit do 30 osób. Będzie to wyjście poza strefę komfortu, która do tej pory wynosiła "do 15 osób". Link na Meetupie

W czwartek Śmigło prezentuje Dockera : Docker na Meetupie

W sobotę Marcin Grzejszcza­k robi Hackaton z Mikroserwisów : Mikroserwisy na Meetupie

Do tego są nowe wpisy na blogu JUGa : http://blog.juglodz.pl/ Dodałem też swoja recenzję swojego wystąpienia z końca lutego : http://blog.juglodz.pl/2015/03/26022015-obsuga-sytuacji-wyjatkowych.html

Zabawa i nauka

Z zainteresowania warsztatami ze Scali widzę, że sam języka staje się popularny wśród tutaj w Łodzi to jednak nadal duża grupa zapewne zastanawia się "po co mi to?". W tych okolicznościach należy się skupić na przystępności i prostocie języka aniżeli na jakichś kosmicznych funkcjonalnościach.

Do tego warsztaty muszą być prowadzone w sposób na tyle interesujący aby ludzi nie kusiło wchodzenie na fejsa. Także nie tylko sama zawartość warsztatu jest ważna
Za moich czasów na nudnym wykładzie można było grać tylko w statki - teraz można zestawić serwer call of duty z komórki
Do tego ludzie idą na niego zmęczeni po pracy czy szkole - MA BYĆ INTERESUJĄCO!

Warsztaty i Fotki jako budowa społęczności

O tutaj mamy definicję community --> Community a social group of any size whose members reside in a specific locality,

1000 lat temu to było proste bo ludzie całe życie mieszkali w jednym miejscu. Teraz miejsce jest "efemeryczne" i jedyny sposób na zakotwiczenie jakiejś tożsamości czasowo-przestrzennej to porobienie fotek. Tak to piszę bo czasem ktoś narzeka na robienie fotek.

Fotki są potrzebne do budowy społeczneści skupionej wokół wspólnej nauki:

Dalsza Nauka

W dalszej kolejności przejdziemy do opanowania mechaniki FP w Scali czyli zrozumiemy czemu czasem są dwie pary nawiasów i dlaczego raz funkcja jest deklarowana z klamerkami a raz z nawiasami. Później można przejść do programowania Funkcyjnego jako takiego. w miedzy czasie pojawi się opcja na naukę konkretnych narzędzi jak Akka i może uda się chociaż na chwilę coś z Playa. Plus może coś z BigData będzie.

Trzeba się uczyć bo inaczej tylko Cobol zostanie.
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

niedziela, 22 lutego 2015

Te i przyszłe warsztaty ze scali

Na horyzoncie są warsztaty Play+Akka, sama Akka, więcej Scali, programowanie funkcyjne oraz do tego uwaga - BigData i moze jakieś Machine Learning. Ale najpierw Wspomnienia po ostatnich warsztatach.

Dodatek do warsztatów pierwszych

W opisie do zajęć : Opis do zajęć z wątków były wątki, kolejki, egzekutory i forkjoiny ale zapomniałem dodać najfajniejsze czyli Java8 i Scala :

Dzięki nowemu api w Javie 8 implementacja prostych przekształceń na wielu wątkach jest banalna :

public static void main(String[] args) {
  OptionalInt result = IntStream.range(0, 100)
  .parallel() //1
  .map(e -> e * 2)
  //.map(e ->{System.out.println("thread : "+Thread.currentThread().getName());return e;}) //2
  .reduce(Integer::sum);
  
  result.ifPresent(System.out::println);
 }
  1. Ta jedna linia wystarczy aby obliczenia odbywały się w wielu wątkach
  2. Na dowód można sobie odkomentować tężę linijkę i zobaczyć, że w konsoli pojawią się różne wątki z domyślnej puli
thread : ForkJoinPool.commonPool-worker-7
thread : ForkJoinPool.commonPool-worker-2
thread : ForkJoinPool.commonPool-worker-1
thread : ForkJoinPool.commonPool-worker-4
thread : ForkJoinPool.commonPool-worker-4
thread : ForkJoinPool.commonPool-worker-3
thread : ForkJoinPool.commonPool-worker-6
9900

I Scala dla porównania. Jest trochę mniej tekstu i przez to raczej czytelniej.

def main(args: Array[String]) {
    val result=(1 to 100)
    .par //1
    .map(_*2)
    //.map(e=>{println(s"thread : ${Thread.currentThread()}");e}) //2
    .sum
    
    println(result)
  }
thread : Thread[ForkJoinPool-1-worker-5,5,main]
thread : Thread[ForkJoinPool-1-worker-11,5,main]
thread : Thread[ForkJoinPool-1-worker-3,5,main]
thread : Thread[ForkJoinPool-1-worker-9,5,main]
thread : Thread[ForkJoinPool-1-worker-3,5,main]
thread : Thread[ForkJoinPool-1-worker-9,5,main]
thread : Thread[ForkJoinPool-1-worker-9,5,main]
thread : Thread[ForkJoinPool-1-worker-9,5,main]
9900

Dlaczego warto się uczyć - ekonomia

To co widzimy powyżej to charakterystyka diody półprzewodnikowej (chyba, bo już 15 lat nie lutowałem). Poza tym, że jest dioda jest podstawowym składnikiem przemysłu elektronicznego to również koncepcja napięcia przebicia pełni rolę doskonałej metafory tegoż przemysłu.

Generalnie chodzi o to, że społeczność czy ogólnie pojęci programiści muszę w danym ekosystemie wygenerować odpowiednie "napięcie edukacyjne" zanim nastąpi przebicie ciekawych projektów. Jeśli np. będą chętni na zlecenie do Łodzi projektów w Scala,Play czy Akka to kto to zrobi jak mało kto umie? Dlatego też systematyczna edukacja, chociaż na początku wydaje się nie przynosić żadnych rezultatów (tak do 0,6-0,7 Volta jeśli dobrze pamiętam) może być kurą, która rozwiąże dylemat tego co było pierwsze..

Dlaczego warto się uczyć - psychologia

W przypadku nauki rzeczy, która nie przynosi nam natychmiastowych profitów mamy do czynienia z tzw. efektem odroczonej gratyfikacji Psychologia Współczesna - odroczona gratyfikacja. Generalnie sposobem najłatwiejszym do polecenia i jednocześnie najtrudniejszym do wdrożenia to "się zmusić". Bardzo pomaga np. siłka jako trening powtarzalnego wysiłku.

Plus przyda się świadomość efektu, który powszechnie nazywa się słomianym zapałem. To ma miejsce wtedy kiedy np. przewidujemy, że jak tylko usiądziemy do nauki Scali to od razu stanie się coś magicznego albo wtedy gdy bo jednej serii z hantlem spodziewamy się przyrostu bicepsa do 45 cm. Po pierwszym szoku od rzeczywistości umysł rewaluuje bilans zysk i strat i stwierdza, że jednak lepiej usiąść przed monitorem/tv i żyć życiem postaci z seriali czy gier komputerowych. Ponownie trzeba znaleźć sposób by się jakoś zmusić do wysiłku.

Dlaczego warto się uczyć - socjologia

Niektórzy ludzie wydaja się być bardzo zmotywowani poprzez rzeczy, które mogą wrzucić na fejsa i zebrać lajki. Gdyby tylko udało się jakoś powiązać ten mechanizm z faktem nauki czegokolwiek... (oczywiście nie chodzi tutaj o mechanizmy używane przez fejsbukowe aplikacje próbujące sztucznie wygenerować autolans poprzez broadcast informacji, ze ktoś w jakiejś grze zdobył odznakę czy level - co jest kurwa zwyczajnie żenujące. )

Kolejne warsztaty

W planach było zrobienie drugiej części warsztatów z wielowątkowości jakkolwiek są ciekawsze tematy :

  • Play+Akka - marzec/kwiecień
  • Scala i Obiektówka jakiej jeszcze nie widzieliście - marzec/kwiecień
  • Programowanie funkcyjne - to będzie niedługo być/ nie być
  • I kolejna ciekawa rzecz Scala/Akka + DDD. Na manningu są trzy MEAPy an ten temat.To się teraz podobno nazywa DDDD z Distributed na początku. kolejne D to będzie Double Distributed. I tak najlepszą nazwę miał język do programowania radzieckich głowic atomowych CCCP++.
  • I ogromny dosłownie temat na koniec - BigData. Pojawiają się coraz to ciekawsze narzędzia a Spark ma tak wygodną konsolę, ze można poprowadzić warsztaty bez pracochłonnej konfiguracji.

I na koniec kilka ćwiczeń, które były przeznaczone na drugą część warsztatów z wielowątkowości. Na razie do samodzielnej pracy a w przyszłości może coś się z tego zorganizuje. W java.util.concurrent można znaleźć wiele ciekawych klas rodem ze startreka jak np.Phasery.

Konstrukcje

Podobno większość rzeczy z tych ćwiczeń trzeba było kiedyś przy pomocy wait/notify robić ale tego nie pamiętam - za młody jestem.

ThreadLocal

ThreadLocal zapisuje dane w kontekście konkretnego wątku i inne wątki się w te dane nie wcinają. Patrzymy na przykład.

object ThreadLocalExercise {

  val statistics=new ThreadLocal[List[Int]]{
    override def initialValue()=List()
  }
  
  def main(args: Array[String]) {
    val ts=Vector.tabulate(3)(i=>new Worker(s"worker ${i}"))
    ts.foreach(_.start())
    ts.foreach(_.join())
  }
  
  class Worker(n:String) extends Thread{
    override def run()={
      val r=new Random()
      gatherStatistics(r)
      displayStatistics
      cleanStatistics //1
    }

    def gatherStatistics(r: java.util.Random) = {
       (1 to 3).foreach{i=>
        val v=r.nextInt(10)
        val l=statistics.get()
        println(s"thread ${n} is adding value ${v}")
        statistics.set(v::l)
        }
    }
    
    def displayStatistics=println(s" worker ${n} has ${statistics.get}")
    def cleanStatistics=statistics.remove()
  }
}

  1. To dosyć ciekawy moment. Otóż okazuje się, że nie czyszcząc ThreadLocal można doprowadzić do wycieku pamięci na serwerze gdzie dany wątek wróci do puli i będzie za chwilę obsługiwał inny request
    • http://avasseur.blogspot.com/2003/11/threadlocal-and-memory-leaks.html
    • http://frankkieviet.blogspot.com/2006/10/classloader-leaks-dreaded-permgen-space.html
    • http://frankkieviet.blogspot.com/2006/10/how-to-fix-dreaded-permgen-space.html
Rozwiązaniem może być użycie WeakReference
val statistics=new ThreadLocal[WeakReference[List[Int]]]{
    override def initialValue()=new WeakReference(List())
  }

CountDownLatch

Pejzaż poniżej przedstawia koncepcję działania CountDownLatch. Wątki wywołujące await grzecznie czekają aż coś zwolni blokadę - a blokad jest tyle jaka cyferka na początku czyli w naszym przypadku dwie

object CountDownLatchExercise {

  def main(args: Array[String]) {
    val cl=new CountDownLatch(2)
    
    val c1=new Controller(5,cl)
    val c2=new Controller(6,cl)
    
    val rockets=(1 to 10).map(new Rocket(_,cl))
    rockets.foreach(_.start)
    
    c1.start()
    c2.start()
    
    rockets.foreach(_.join)
  }
  
  class Rocket(n:Int,cl:CountDownLatch) extends Thread{
    
    private val r=new Random()
    
    override def run()={
      TimeUnit.SECONDS.sleep(r.nextInt(4))
      println(s"przygotowania rakiety ${n}")
      cl.await()
      println(s"start rakiety ${n}")
    }
  }
  
  class Controller(sleep:Int,cl:CountDownLatch) extends Thread{
    override def run()={
      TimeUnit.SECONDS.sleep(sleep)
      println(s"kontroler zwolniony po ${sleep} sekundach")
      cl.countDown()
    }
  }
}
I wynik :
przygotowania rakiety 5
przygotowania rakiety 6
przygotowania rakiety 4
przygotowania rakiety 2
przygotowania rakiety 8
przygotowania rakiety 3
przygotowania rakiety 10
przygotowania rakiety 7
przygotowania rakiety 1
przygotowania rakiety 9
kontroler zwolniony po 5 sekundach
kontroler zwolniony po 6 sekundach
start rakiety 6
start rakiety 2
start rakiety 3
start rakiety 4
start rakiety 9
start rakiety 5
start rakiety 1
start rakiety 7
start rakiety 10
start rakiety 8

Bariera

Dzieło poniżej pokazuje, iż wątki czekają aż wszystkie odhaczą się w barierze (t1), potem ruszają dalej itd. Do tego po każdej kolejce barman dolewa wódy.

object CyclicBarrierExercise {

  def main(args: Array[String]) {
    val b=new CyclicBarrier(5,new Runnable{
      def run={
        println("barman dolewa wódy")
      }
    })
    
    
    val threads=Vector.tabulate(5)(i=>new Shot(b,i+1)).map(new Thread(_))
    threads.foreach(_.start())
    
  }
  
  class Shot(b:CyclicBarrier,i:Int) extends Runnable {
    def run(): Unit = {
      println(s"wątek ${i} pierwsze kolejka")
      b.await()
      println(s"wątek ${i} druga kolejka")
      b.await()
      println(s"wątek ${i} trzecia kolejka")
      b.await()
      println(s"wątek ${i} do dna")
    }
  }
}
wątek 2 pierwsze kolejka
wątek 1 pierwsze kolejka
wątek 3 pierwsze kolejka
wątek 5 pierwsze kolejka
wątek 4 pierwsze kolejka
barman dolewa wódy
wątek 3 druga kolejka
wątek 4 druga kolejka
wątek 5 druga kolejka
wątek 1 druga kolejka
wątek 2 druga kolejka
barman dolewa wódy
wątek 2 trzecia kolejka
wątek 1 trzecia kolejka
wątek 4 trzecia kolejka
wątek 5 trzecia kolejka
wątek 3 trzecia kolejka
barman dolewa wódy
wątek 3 do dna
wątek 1 do dna
wątek 5 do dna
wątek 4 do dna
wątek 2 do dna


poniedziałek, 26 stycznia 2015

Warsztaty o programowaniu wielowątkowym z Javy ale w Scali (chyba część pierwsza)

Poniżej materiał do warsztatów uczących używania mechanizmów wielowątkowych dostępnych w Javie aleee programować będziemy w Scali. Kiedy się odbędzie warsztat? Warsztat odbędzie się w momencie jego dobycia. Pewnie w przyszłym miesiącu.

Celem warsztaty będzie zapoznanie uczestników (którzy w założeniu nie stykają się z problemami wielowątkowości na co dzień) z ewolucją którą przeszła Java do wersji 1.7 - (java.util.concurrent, fork-join i takie tam.) Jednocześnie nie zarzucając słuchaczy zbyt wielką listą szczegółów.

Aby upiec dwie pieczenie na jednym ruszcie - będziemy przy okazji uczyć się Scali. To trochę jak nauka angielskiego poprzez tłumaczenie najnowszego wydania "Świata Dorsza" na tenże język.

Na warsztat przygotuję jakieś próbki kodu tak aby uczestnicy nie musieli pisać wszystkiego od początku. Kod będzie kompletny np. w 70% i nauka odbywać będzie się poprzez uzupełnienie brakujących fragmentów z towarzyszącym niezwykle krytycznym procesem wyciągania wniosków.

Po co uczyć się "starych" mechanizmów wielowątkowości jeśli ostatnio różne nowe rozwiązania działają na wyższym poziomie abstrakcji? No po to aby wiedzieć dlaczego one działają na wyższym poziomie abstrakcji i dlaczego w ogóle działają.

W jakieś wielkie i wyczerpujące opisy w tym artykule się nie bawiłem bo wszystko omówimy sobie w trakcie warsztatu.

Pojedyncze wątki na start

object SingleThreadExample {

  def main(args: Array[String]) {
    val r=new Thread(new MyRunnable("Interfejs"))
    val t=new MyThread("Klasa")
    
    r.start()
    t.start()
    
    r.join() //czekamy na zakończenie obydwu watków
    t.join()
  }
  
  class MyThread(m:String) extends Thread {
      override def run=println(s"Jestem w watku : ${m}")
  }  
  
  class MyRunnable(m:String) extends Runnable {
    def run = println(s"Jestem w runnable : ${m}")
  }
}
Nauka :
  • Runnable to interfejs ale w Scali nie ma słowa kluczowego implements.
  • Kiedy damy s przed stringiem to można wygodnie wstawiać weń zmienne
  • Na końcu dajemy join aby główny wątek main nie skończył się przed wątkami badanymi

Kilka wątków dla współpracy

W tym przykładzie tworzymy kilka wątków, które współpracują ze sobą sumując wybrane elementy z tablicy i następnie wyliczają ostateczną sumę. Takie MapReduce dla ubogich. Z przykładu można się także nauczyć ciekawego sposobu inicjalizacji kolekcji poprzez "tabulate" a także trochę deklaratywnych transformacji tychże kolekcji.

A i w ScalaIDE działa już generowanie metod w traitach przy pomocy ctrl+1.

object CoupleThreeadsCooperation {

  def main(args: Array[String]) {
    val n=100
    val v=Vector.tabulate(n)(i=>i*2) //1
    
    val runnables=(0 to n/10).map(i=>new Summarizer(i*10,v)) //2
    val threads=runnables.map(new Thread(_)) //2
    threads.foreach(_.start()) //3
    threads.foreach(_.join)  //3
    
    val sum=runnables.map(_.result).sum //4
    println(sum)
  }
  
  class Summarizer(startIndex:Int,v:Vector[Int]) extends Runnable {
    
    private var _result:Int=0 // 5
    
    def run(): Unit = {
      val dataForThread=v.slice(startIndex, startIndex+10)
      println(s"summarizing elements ${startIndex} : ${startIndex+10} - ${Thread.currentThread().getName}") //6
      _result=dataForThread.sum
    }
    
    def result=_result //5
  }
}
  1. Używamy wektora bo tam wydajniej dostać się do danego elementu z indexem "i" także "slice" też pewnie działa szybciej
  2. Zamiast dziwnymi pętlami przetwarzamy dane lamdami.
  3. Podobnie można zażądać wywołania konkretnej metody an wszystkich elementach
  4. Przy tej linii w ramach odpowiedniego czasu i chęci słuchaczy można wspomnieć jak to jest zrobione, że dla kolekcji intów mamy metodę sum
  5. Jest stan i jest mutable :(
  6. Na potrzeby ćwiczenia walimy tekst zwykłym println

Kilka wątków - rywalizacja

Tym razem zobaczymy dlaczego programowanie wielowątkowe może nie działać. Uruchamiamy 100 wątków, każdy zwiększa stan licznika o 1- powinno być 100 - powinno a nie jest.

object CoupleThreadsWithGlobalState {

  private var global=0
  
  def main(args: Array[String]) {
    val workers=Seq.fill(100)(new Worker()) //1
    workers.foreach(_.start)
    workers.foreach(_.join)
    
    println(s"global na końcu ${global}")
  }
  
  class Worker extends Thread{
    override def run=global=global+1
  }
}
  1. "Seq" - tutaj tak przy okazji skąd się wzięło Seq - zerknijcie tutaj - Scala - Hierarchia kolekcji

Locki

object CoupleThreadsWithGlobalStateGuardedByLocks {

  private var global=0
  private val monitor=new Object() //1 pokazać przykład ze złym monitorem
  
  def main(args: Array[String]) {
    val workers=Seq.fill(100)(new Worker())
    workers.foreach(_.start)
    workers.foreach(_.join)
    
    println(s"global na końcu ${global}")
  }
  
  class Worker extends Thread{
    override def run=monitor.synchronized{  //1
    	  global=global+1 
      }
  }
}
  1. W scali nie ma słowa kluczowego synchronized. Jest za to metoda na AnyRef, która robi to samo

Atomic Integer

AtomicInteger wykorzystuje specjalne instrukcje procesora, który w jednym cyklu może wykonać dwie operacje w sposób atomowy. Procesory robi się z krzemu, a krzem uzyskuje chyba z piasku. W Afryce i Azji działają gangi, które nielegalnie przemycają piasek - ale wracając do przykładu zastosowanie AtomicInteger bardzo uprościło kod

object CoupleThreadsWithGlobalStateGuardedByLocks {

  private val global=new AtomicInteger(0)
  
  def main(args: Array[String]) {
    val workers=Seq.fill(100)(new Worker())
    workers.foreach(_.start)
    workers.foreach(_.join)
    
    println(s"global na końcu ${global}")
  }
  
  class Worker extends Thread{
    override def run=global.incrementAndGet()
  }
}

Producent konsument - kolejka

Tutaj trochę dłuższy przykład. Tym razem do trzech współpracujących wątków dodajemy kolejkę, na której blokują się wątki producenta i konsumenta w zależności czy kolejka jest pusta czy pełna.

object ProducerConsumerQueue {

  def main(args: Array[String]) {
    val q: BlockingQueue[Int] = new LinkedBlockingQueue(3) //1
    val p1 = new Thread(new Producer(q))
    val p2 = new Thread(new Producer(q))
    val c = new Thread(new Consumer(q))

    p1.start()
    c.start()
    p2.start()
  }

  class Producer(q: BlockingQueue[Int]) extends Runnable {

    private val r = new Random()

    @tailrec  //3
    final def run(): Unit = {
      val v = r.nextInt(10)
      q.put(v)       //2
      println(s"producing ${v} :  queue size ${q.size}")
      TimeUnit.SECONDS.sleep(3)
      run() //3
    }
  }

  class Consumer(q: BlockingQueue[Int]) extends Runnable {
    def run(): Unit = {
      while (true) {
        val v = q.take() //2
        println(s"consumed ${v} :  queue size ${q.size}")
        TimeUnit.SECONDS.sleep(2)
      }
    }
  }
}
  1. Kolejkę ustawiamy na 3 elementy aby się "zapchała" w trakcie pracy
  2. put i take blokują wątek w oczekiwaniu na rezultat
  3. A to taki eksperyment - teoretycznie zastąpiliśmy popularną pętlę "while(true)" rekurencją - chyba działa

Executory

W poniższym ćwiczeniu nie będziemy już tworzyć wątków z palca lecz użyjemy dodanych do Javy5 "Executorów" (lub po polsku Egzekutorów lub poprawnie po angielsku Executors)

object ExecutorsExample {

  def main(args: Array[String]) {
    val e=Executors.newFixedThreadPool(3) //1
    
    (1 to 100).foreach{i=>
      println(s"run task ${i}") //2
      e.submit(new Task())
    }
    e.shutdown()
  }
  
  class Task extends Runnable {
    def run(): Unit = {
      println(s" running thread ${Thread.currentThread().getName}") //2
      TimeUnit.SECONDS.sleep(2)
    }
  }
}
  1. Inicjalizujemy pulę złożoną z trzech wątków
  2. I tutaj w logach zobaczymy, iż pomimo tego, że chcemy wykonania się 100 wątków to tylko trzy jadą w jednej chwili.
run task 93
run task 94
run task 95
run task 96
run task 97
run task 98
run task 99
run task 100
 running thread pool-1-thread-1
 running thread pool-1-thread-3
 running thread pool-1-thread-2
 running thread pool-1-thread-1
 running thread pool-1-thread-3
 running thread pool-1-thread-2

Callable

Tutaj zrobimy jeszcze raz to ćwiczenie, w którym watki liczą sumę elementów kolekcji. Drogi czytelniku zauważ, że tym razem nie ma potrzeby przechowywania żadnego stanu w wątkach ani nic takiego gdyż używamy Callable , które zwyczajnie zwraca rezultat.

object CalablesExample {

  def main(args: Array[String]) {
    val n=100
    val v=Vector.tabulate(n)(i=>i*2)
    val e=Executors.newFixedThreadPool(5)
    
    val callables=(0 to n/10).map(i=>new Summarizer(i*10,v))
    val futures=callables.map(e.submit(_))
    val result=futures.map(_.get).sum
    
    println(result)
    e.shutdown() //1
    e.awaitTermination(10, TimeUnit.SECONDS)
  }
  
  class Summarizer(startIndex:Int, v:Vector[Int]) extends Callable[Int] {
    
    def call(): Int = {
      val dataForThread=v.slice(startIndex, startIndex+10)
      println(s"summarizing elements ${startIndex} : ${startIndex+10} - ${Thread.currentThread().getName}") //6
      dataForThread.sum
    }
    
  }
}
  1. Pamiętajcie wyłączać po sobie światło.

Fork Join

I na koniec bonus z Javy7 - ForkJoin Framework - charakteryzuje się tym, że wątki sobie zabierają pracę jak nic nei robią.

object ForkJoinExample {

  def main(args: Array[String]) {
    val n = 100
    val v = Vector.tabulate(n)(i => i * 2) //1

    val t = new Task(v, 0, v.length)
    val p = new ForkJoinPool() //3
    p.execute(t) 

    p.shutdown()
    p.awaitTermination(10, TimeUnit.SECONDS)
    println(s"result ${t.get}")
  }

  import ForkJoinTask._ //4

  class Task(is: Seq[Int], start: Int, end: Int) extends RecursiveTask[Int] { //5
    def compute(): Int = {
      println(s"calculating ${start} - ${end}")
      if (end - start < 10)
        is.slice(start, end + 1).sum
      else {
        val mid = (start + end) / 2
        val t1 = new Task(is, start, mid)
        val t2 = new Task(is, mid + 1, end)
        invokeAll(t1, t2) //6
        t1.get() + t2.get() //7
      }
    }
  }
}
  1. Tutaj jakieś dane w kolekcji podobnie jak w poprzednich przykładach
  2. Tu był krzyż a teraz już go nie ma
  3. Nowy typ puli - FooooorkJoin
  4. To jest ciekawe , będziemy wykorzystywać statyczne metody z ForkJoinTask i w scali trzeba je niezależnie zaincludować (przynajmniej w ScalaIDE by działało.)
  5. Nowy typ klas do rozdziedziczenia - RecursiveTask[
  6. Statyczna klasa, która wywołuje pod-taski. Jak widać to my musimy zadbać o to by stworzyć ich odpowiednią ilość (i jakość).
  7. Na koniec suma i koniec

Podsumowanie

Jak już wspominałem w jakieś wielkie i wyczerpujące opisy się nie bawiłem bo wszystko omówimy sobie w trakcie warsztatu. Jeśli zajęcia się spodobają to na pewno będziemy je powtarzać i materiał uzupełniać.

To by było tyle jeśli chodzi o cześć pierwszą a w kolejnych : ThreadLocal,Semafory,Phasery,Lacze, Bariery, ThreadFactory i inne takie. A później(Albo w międzyczasie) jakieś najnowsze rozwiązania jak Akka i coś z JAvy8.

Oczywiście sam biorę udział w procesie edukacji, także jeśli ktoś znajdzie błędy w przykładach niech śmiało daje znać.

wtorek, 6 stycznia 2015

Szczęśliwej nauki w nowym roku

Nowy rok Bla bla bla postanowienia sratatata silna wola hejkumkeikum porady .

(Nie)racjonalni agenci

Chcę nauczyć się noweje technologii | schudnąć | dopakować | zmienić coś w swoim życiu.

Chcesz czy "musisz"? Różnica jest istotna i wręcz krytyczna do zrozumienia jak coś w sobie zmienić.

Zazwyczaj ("zazwyczaj") ludzie chcą/zmuszają się gdy:

  • (1) chcą grać w gry komputerowe
  • (2) starają się nauczyć nowego języka bo to może zaprocentować czymś tam w przyszłość. Mają postanowienie, że się nauczą ale jednocześnie mają ochotę porobić coś innego.
  • (1) chcą pić browary - trudno mi sobie wyobrazić sytuację, gdzie ktoś ma postanowienie noworoczne - "będę pić przynajmniej 2 browary dziennie chociaż nie mam ochoty"
  • (2) starają się ćwiczyć regularnie - chociaż woleliby posiedzieć i pooglądać filmy
Wytłumaczyć dlaczego te czynności z "1" wychodzą dla większości łatwiej niż te z "2" można na wysokim poziomie humanistyczno-psychologicznym - ot wystarczy zerknąć na taki model Dorosły,Rodzic i Dziecko. Kiedyś używałem tego do zmotywowanie siebie do treningów krav magi po tym jak dostałem kilka razy z rzędu bęcki na mieście - ale ten model jest tak ogólny jak ...(tutaj można wstawić żart z dowolną ogólną metodyką, która mówi "rób tak i nie pytaj dlaczego")

Zanim pójdziemy dalej zastanówmy się czym się różni granie w gry(na PC) od zwykłego programowania?

  1. Granie w gry - siadasz, masz przed sobą maszynę z pewnym ustawieniem bitów a pamięci. Klikasz myszkę, naciskasz klawiaturę i zapisujesz nowe ustawienie bitów w pamięci
  2. Programowanie- siadasz, masz przed sobą maszynę z pewnym ustawieniem bitów a pamięci. Klikasz myszkę, naciskasz klawiaturę i zapisujesz nowe ustawienie bitów w pamięci
Gdzie więc tkwi różnica?

Hamowanie

Co może nie być oczywiste na pierwszy rzut oka - obydwa powyższe obrazki przedstawiają mózg :). Z tyłu mózgu (w uproszczeniu) znajdują się pierwotne zaś z przodu nowożytne moduły - a jeśli to złe nazwy to w duchu personifikacji nazwijmy je "Staruch" i "Nowak".

Staruch towarzyszy nam od zarania ewolucji i to on ma misję "przetrwaj i rozmnażaj(się)". To on chce natychmiastowej gratyfikacji w postaci węglowodanów prostych, "low hanging frutów" czy tudzież innych łatwych natychmiastowych zysków. To on także każe nam siedzieć i nie wychylać się bo wtedy czujemy się komfortowo. Co bardzo ważny co okaże się póżniej krytyczne Nie ma poczucia czasu jako takiego. Staruch potrafi działać w ramach grupy doskonale rozumiejąc, że jeśli może łatwo i szybko pokonać smoka to zostanie się bohaterem w swoim domu

Nowak pojawił się niedawno i myśli abstrakcyjnie. Rozumie, że on za miesiąc czasu to także on. Że wybory z dnia dzisiejszego mają swoje konsekwencje w przyszłości i że czasami coś co jest nieintuicyjne tu i teraz ma swój sens "kiedyś". A i jeszcze jedno - Nowak wcale nie kontroluje starucha choć chce tak myśleć. To staruch ma więcej doświadczenia w zarządzaniu rdzeniem kręgowym, hormonami i podobnymi mechanizmami. Zawsze gdy Staruch wygrywa spór Nowak może albo czuć się źle albo wkręcić sobie, że on tak naprawdę to lubi dużo jeść/pić/palić a ten odpoczynek mu się zwyczajnie należał a ten koleś, któremu zajął miejsce parkingowe na pewno albo jest zły i mu się należało albo pewnie cwaniak jakiś i mu się no właśnie - należało.

Takie rzeczy niestety się dzieją gdy rozwijamy system bez refaktoringu :(

A jeśli komuś się nie podoba ta metafora to polecam Thninking fast and slow

Notka -Trochę mechaniki

Na mój obecny stan wiedzy w mózgu działa masa niezależnych procesów, które wykorzystują te same materiały do pracy (i znów na obecny stan wiedzy to będzie głównie wapń i coś tam jeszcze). Dlatego też istnieje skończony czas w jaki Nowak może się przeciwstawiać Staruchowi a proces nazywa się Hamowaniem.Np. Staruch chce sobie splunąć a Nowak go powstrzymuje bo przy Policji to tak ryzykownie. Czas ten skraca się po nieprzespanej nocy na skutek zalegania odpadów bio-chemicznych w mózgu (czy coś w ten deseń)

Relacje

Sytuacja 1 - koncepcja hedonistyczna

Staruch chce cukrów bo cukry były dobrym pożywieniem w czasach flinstonów, Nowak chce cukru bo to przyjemne. Staruch chce grać bo w swoim prostym rozumieniu świata zyskuje bogactwa/status/nowy dywan w simsach a z organizmu nie dochodzą żadne sygnały jako by to było męczące. Nowak chce grać bo to przyjemne. Czy ta sytuacja jest dobra czy zła? Generalnie wielu ludzi tak idzie przez życie niektórzy są szczęśliwi inni nie - Szczęście=Rzeczywistość-Oczekiwania.

Ta sytuacja może również wiązać się z czymś raczej pozytywnym. Np. możemy się uzależnić od dobrego samopoczucia po skończonym treningu a po miesiącu odpoczynku od cukrów i przetworzonej żywności nawet jedzenie brukselki może kojarzyć się z przyjemnością

Sytuacja 2 - Konflikt

Staruch chce grać a Nowak chce obejrzeć prezentację o Springu. Staruch chce obejrzeć film a Nowak chce iść na siłkę bo sobie zrobił postanowienie noworoczne. To jest dosyć nieprzyjemny stan z którego można się uwolnić techniką "fake it till you make it" - czyli jakoś zmusić Starucha do robienia czegoś aż mu się to spodoba lub wkręcić starucha, że robienie tego czegoś jest przyjemne- zaraz więcej o tym.

W tym przypadku ma miejsce tzw. "słomiany zapał". Czyli sytuacja gdy Nowak wkręcił Starucha wizualizacjami o tym jak po dwóch tygodniach rozpiętek będzie miał klatę ala Arnold - atu kicha i do tego trzeba jeszcze jakąś dietę utrzymywać - Staruch mówi - "Siadaj i oglądaj film w nie będziesz mi tutaj farmazony w głowie generował"

Sytuacja 3 - Inspiracja podstawowa

Przejdźmy na poziom abstrakcji wyżej - co tak naprawdę "motywuje starucha"? Przez ostatnie kilka milinoów lat dojrzewał on w grupach do 150 osobników gdzie wzajemne relacje i hierarchie decydowały o tym czy żyjesz/nie żyjesz. Jeśli zrobiłeś salto i jednym uderzeniem zabiłeś mamuta zostajesz bohaterem i grupa instynktownie "coś jest ci winna". Jeśli zrobiłeś salto i zabiłeś mamuta ale nikt tego nie widzi to pewnie nikt ci nie uwierzy.

Żarcia było mało, ludzie jakoś funkcjonowali nie jedząc 7 małych dobrze zbilansowanych posiłków dziennie. Nie wiem czy mamuty miały gluten czy nie ale raczej nikt o diecie nie myślał.

Czy nauka nowego języka może jakoś zająć miejsce widowiskowego poskromienia mamuta?

  • Przede wszystkim zabicie mamuta dostarczyło mięsa dla gromady. Niech mięso stanowi pewno wartość. Ucząc się języka możesz potencjalnie zwiększyć swoje szanse na zatrudnienie ale tutaj znowu może pojawić się konflikt bo Staruch woli grać w gry. Sytuacja będzie inna gdy już jesteśmy w miejscu gdzie jest dosyć prosta relacja pomiędzy "nauka języka"~"Profit" - pamiętajmy, ze Staruch ma proste pojmowanie świata. Można również uczyć się języka by nauczyć innych tego języka by oni więcej zarabiali - bardziej abstrakcyjne i trudniejsze do realizacji.
  • No i też w kontekście tego punktu trudniej zmotywować siebie do nauki języka dla samego siebie aniżeli do nauki języka gdy można się tym przed kimś pochwalić - i to w sposób pozytywny pomagając np. na forum.

Sytuacja 4 - Inspiracja wyższych celów

Ponieważ ludzki umysł szuka wszędzie przyczyny i skutku toteż wiele dziwnych rzeczy robiono w imię różnych abstrakcyjnych idei. Pamiętam z lekcji języka polskiego, że jakiś koleś przesiedział 14 lat na drzewie w imię lepszego życia po życiu. Generalnie słowo klucz to "wyższa Idea" czy w imię "wyższej idei spotka mnie coś dobrego". Nie znam dokładnej mechaniki ale jeśli komuś uda się to rozgryźć to zapewne i tędy wiedzie droga do spełnienia postanowień noworocznych.

Sytuacja 1b - antyhedonizm

Tak jak Staruch i Nowak mogą robić przyjemne odczucia tak mogą wspólnie nie lubić nieprzyjemnych. Np. można pobić swój rekord życiowy na setkę gdy gonią nas łysi na mieście. Ewentualnie nie lubimy wychodzić na niekonsekwentnych także jedna słynna technika mówi podziel się planami ze znajomymi - ten miecz ma dwa końce gdyż z drugiej strony "mienie w dupie" tego co myślą o nas inni jest ważnym składnikiem samorozwoju

Sytuacja 6 - Inspiracja braku celów - Nihilizm Egzystencjalny

To jest dosyć ciekawy przypadek - być może na pewnym poziomie rozwoju gdy zagłuszeniu ulegnie naturalna ignorancja a rzeczy oczywiste przestaną napędzać codzienność, wtedy Staruch sam sobie zada pytanie "przetrwać i rozmnażać - ale po co?". Nowak spyta "co robimy?" , "- no chyba szukamy?".

Może to się zakończyć głęboką depresją ale również niezwykłą motywacją w kierunku szeroko pojętych poszukiwań i nowych doświadczeń. Temat trudny ale niektóre postacie przewijające się przez ten nurt maja fajne cytaty :

  • "Ludzie ro­zumieją mnie tak słabo, że nie ro­zumieją na­wet moich narze­kań na to, że mnie nie rozumieją." - Soren Kierkegaard
  • "To niezwykłe, jak można kłamać, przyznając sobie rację." - Jean-Paul Sartre
  • "Życie można zro­zumieć, pat­rząc nań tyl­ko wstecz. Żyć jed­nak trze­ba naprzód." - Soren Kierkegaard
  • "Wszyscy jesteśmy tutaj, aby jeść i pić dla zachowania naszego drogocennego istnienia, a nie ma nic, nic, żadnej racji istnienia." - Jean-Paul Sartre
  • "Człowiek zaw­sze czu­je się czymś więcej niż tym, co osiągnął, więc co­kol­wiek by osiągnął, w niczym nic może zna­leźć uko­jenia, za­dowo­lenia, szczęścia." - Soren Kierkegaard
I tak ogólnie : Nihilizm egzystencjalny

Za długie motyla noga - TL;DR - szbka technika - obcy z przyszłości

  1. Artykuł - Neurologia prokrastynacji
  2. W skrócie - Skany mózgu pokazują, że nasze szare komórki nie traktują "nas tu i teraz" i "nas w przyszłości" jako tę samą osobę. "Ja z przyszłości" i "trzecia osoba z tu i teraz" generują te same reakcje.
  3. Należy stworzyć połączenie poprzez wizualizacje, medytacje i tego typu techniki dzięki czemu Staruch zrozumie, że krzywdząc siebie z przyszłości krzywdzimy siebie
I jeszcze jeden trik na deadlajny : http://www.nytimes.com/2015/01/04/business/if-you-want-to-meet-that-deadline-play-a-trick-on-your-mind.html