Changes between Version 18 and Version 19 of squeak_faq


Ignore:
Timestamp:
10/16/2013 11:59:30 AM (11 years ago)
Author:
willi.mueller
Comment:

Method and class formatting

Legend:

Unmodified
Added
Removed
Modified
  • squeak_faq

    v18 v19  
    4040=== Wie werden Grafiken im Image verwendet? ===
    4141
    42 Der Dreh und Angelpunkt ist hier die Klasse Form. Die Basis von Form ist die "Squeak Canvas", eine Bitmap, die Bilder enthält, oder auf der gezeichnet werden kann. Diese Objekte können dann in !ImageMorphs verwendet werden. Bei größeren oder vielen Bildern lohnt ein Blick auf die Klassenseite von Form. Da gibt es eine Methode, die aus einer Datei direkt ein Form-Objekt lädt. Ähnliches findet sich auch auf den Klassenseiten von den Klassen PNGReadWriter, JPEGReadWriter, GIFReadWriter und weitere für spezielle Bildformate.
    43 
    44 Mit Klassen wie !FileDirectory oder !FileUrl kann im Dateisystem navigiert werden. Hierbei gilt es auch zu bedenken, dass die "Pathdelimiter" der Betriebssysteme unterschiedlich sein können (/ oder \).
     42Der Dreh und Angelpunkt ist hier die Klasse `Form`. Die Basis von `Form` ist die "Squeak Canvas", eine Bitmap, die Bilder enthält, oder auf der gezeichnet werden kann. Diese Objekte können dann in !ImageMorphs verwendet werden. Bei größeren oder vielen Bildern lohnt ein Blick auf die Klassenseite von Form. Da gibt es eine Methode, die aus einer Datei direkt ein Form-Objekt lädt. Ähnliches findet sich auch auf den Klassenseiten von den Klassen `PNGReadWriter`, `JPEGReadWriter`, `GIFReadWriter und weitere für spezielle Bildformate.
     43
     44Mit Klassen wie `FileDirectory` oder `FileUrl` kann im Dateisystem navigiert werden. Hierbei gilt es auch zu bedenken, dass die Trennzeichen in den Pfaden je nach Betriebssystem unterscheidlich sind: "\" bei Windows, Linux und OSX benutzen "/"). Für Plattformunabhängigkeit könnt ihr `FileDirectory>>slash` oder `FileDirectory class>>slash` benutzen (siehe [#platform-path-separator Plattformunabhängige Dateizugriffe])
    4545
    4646Bilder können auch im Image gespeichert werden. Das hat den Vorteil, das ihr die Bilder über Monticello verwalten könnt und so alle Teammitglieder über das Repository die aktuellen Bilder bekommen.
    47 Der große Nachteil ist, dass ihr die Größe des Images aufbläht. Wenn trotz ihr trotz dieses Nachteils Bilder in Methoden und damit im Image speichern wollt, könnt ihr Array-Repräsentationen gewinnen. Dazu laded ihr das Bild, wie oben beschrieben, zuerst in eine Form und aus dieser erzeugt ihr dann das Array (siehe. z.B. `Form>>storeOn`).
    48 
    49 Es gibt in Squeak den !ImageReadWriter als abstrakte Klasse und dazu verschiedene Implementierungen für z.B. BMP und PNG (PNGReadWriter, BMPReadWriter). Auf Klassenseite von !ImageReadWriter findet sich dann auch `ImageWriter `class>>formFromFileNamed`:`, was in der konkreten Implementierung genutzt werden kann.
     47Dazu speichert ihr die Bilder in Methoden, die Array-Repräsentationen der Grafiken zurückgeben. Dazu laded ihr das Bild, wie oben beschrieben, zuerst in eine Form und aus dieser erzeugt ihr dann das Array (siehe. z.B. `Form>>storeOn`).
     48
     49Es gibt in Squeak den `ImageReadWriter` als abstrakte Klasse und dazu verschiedene Implementierungen für z.B. BMP und PNG (`PNGReadWriter`, `BMPReadWriter`). Auf Klassenseite von `ImageReadWriter` findet sich dann auch `ImageWriter class>>formFromFileNamed:`, was in der konkreten Implementierung genutzt werden kann.
    5050
    5151
    5252=== Welche Dateiformate für Bilder sind für Squeak geeignet? ===
    5353
    54 Benutzt hier am besten PNG, JPG oder BMP. Zum Einlesen bietet sich dann beispielweise die !ReadWriter Klassen an. Übrigens können Forms auch mit Transparenz umgehen.
     54Benutzt hier am besten PNG, JPG oder BMP. Zum Einlesen bietet sich dann beispielweise die `ReadWriter` Klassen an. Übrigens können Exemplare der Klasse `Form` auch mit Transparenz umgehen.
    5555
    5656
    5757=== Können !ImageMorph bzw. deren enthaltene Form mit Alphatranparenz umgehen? Wie können ganze Morphs ausgeblendet werden? ===
    5858
    59 Verwendet die Methode hide, um einen Morph sofort ohne Fade Out zu verstecken. Denkt bitte daran, dass ausgeblendete Morphs dennoch im Speicher verbleiben. Eine Squeak-Methoden-Suche nach "alpha" (eine Nachricht, die wahrscheinlich Konstrukte haben wird, bei denen man eine Transparenz einstellen kann) liefert eine Klasse namens: !AnimAlphaBlendingCanvas.
     59Verwendet die Methode `Morph>>hide`, um einen Morph sofort ohne fade out zu verstecken. Denkt bitte daran, dass ausgeblendete Morphs dennoch im Speicher verbleiben. Eine Squeak-Methoden-Suche nach `alpha` oder `alpha:` (eine Nachricht, die wahrscheinlich Konstrukte haben wird, bei denen man eine Transparenz einstellen kann) liefert eine Klasse namens: `AnimAlphaBlendingCanvas`.
    6060
    6161=== Wie schaffe ich es, dass ein Morph nicht mehr verschiebbar ist? ===
     
    6666=== Unser Spiel basiert auf Stepping und ruckelt!?! Was können wir tun? ===
    6767
    68 Das Stepping Model von Morphic ist relativ einfach und basiert auf einem Prozess, welcher alle stepping Methoden ausführt, wenn ihre stepTime abgelaufen ist. Im Umkehrschluss heißt das aber auch je mehr #step Methoden, je häufiger aufgerufen werden, desto mehr Zeit wird zwischen einzelnen Schritten benötigt (da mehr berechnet wird). Die #stepTime gibt dabei einen Wunschwert an, nach dem die #step Methode wieder aufgerufen werden soll. Nun kann es aber sein, dass die step Methoden soviel zu tun haben (oder andere Prozesse), dass die Überprüfung nur alle 50 ms ausgeführt wird und somit kann eine Zeit von 33 ms nicht garantiert werden. Allerdings wird durch die beschriebene Bewegung eine explizite #runStepMethods Message an die Welt gesendet, welcher die Abarbeitung aller #steps triggered. Das heißt der UI Prozess löst bei seiner Reaktivierung eine neu Berechnung aus.
    69 
    70 Also kommen wir zu möglichen Lösungen:
    71 
    72 In Preferences gibt es eine Option "higher performance" diese sorgt  für ein häufigeres updaten des UI Prozesses, dass könnte ggf. helfen.
    73 
    74 
    75 
    76 Anstatt häufig kleine Schritte auszuführen, kann  ggf. eine größere Schrittweite die Animation flüssiger wirken lassen.
    77 
    78 
    79 Eine richtige Game Loop  implementieren (Design Pattern für Spiele), welche abhängig von der verstrichenen Zeit die Animation berechnet und somit immer gewährleistet, dass unabhängig von der Performance die Animation zu einem Zeitpunkt überall gleich weit ist (ruckelnd oder nicht). Dann würdet ihr komplett auf das Stepping Protokoll verzichten.
     68==== Wieso stepping zu langsam sein kann ====
     69
     70Das Stepping Model von Morphic ist relativ einfach und basiert auf einem Prozess, welcher alle stepping Methoden ausführt, wenn ihre `Morph>>stepTime` abgelaufen ist. Im Umkehrschluss heißt das aber auch je mehr `Morph>>step` Methoden je häufiger aufgerufen werden, desto mehr Zeit wird zwischen einzelnen Schritten benötigt (da mehr berechnet wird). Die `#stepTime` gibt dabei einen Wunschwert an, nach dem die `#step` Methode wieder aufgerufen werden soll. Nun kann es aber sein, dass die `#step` Methoden soviel zu tun haben (oder andere Prozesse), dass die Überprüfung nur alle 50 ms ausgeführt wird und somit kann eine Zeit von 33 ms nicht garantiert werden. Allerdings wird durch die beschriebene Bewegung eine explizite `#runStepMethods Message an die Welt gesendet, welcher die Abarbeitung aller steps auslöst. Das heißt der UI Prozess löst bei seiner Reaktivierung eine neu Berechnung aus.
     71
     72==== Lösungen ====
     73
     741. In Preferences gibt es eine Option "higher performance" diese sorgt für ein häufigeres updaten des UI Prozesses, dass könnte ggf. helfen.
     75
     762. Anstatt häufig kleine Schritte auszuführen, kann ggf. eine größere Schrittweite die Animation flüssiger wirken lassen.
     77
     783. Die wahrscheinlich schnellste Alternative ist, eine Game Loop zu implementieren (Design Pattern für Spiele), welche abhängig von der verstrichenen Zeit die Animation berechnet und somit immer gewährleistet, dass unabhängig von der Performance die Animation zu einem Zeitpunkt überall gleich weit ist (ruckelnd oder nicht). Dann würdet ihr komplett auf das Stepping Protokoll verzichten.
    8079
    8180
     
    132131Bei größeren oder vielen Bildern lohnt ein Blick auf die Klassenseite von Form.
    133132Da gibt es eine Methode, die aus einer Datei direkt ein Form-Objekt lädt.
    134 Ähnliches findet sich auch auf den Klassenseiten von den Klassen PNGReadWriter, JPEGReadWriter, GIFReadWriter und weitere für spezielle Bildformate.
     133Ähnliches findet sich auch auf den Klassenseiten von den Klassen `PNGReadWriter`, `JPEGReadWriter`, `GIFReadWriter` und weitere für spezielle Bildformate.
    135134
    136135
    137136Mit Klassen wie !FileDirectory oder !FileUrl kann im Dateisystem navigiert werden.
    138137Hierbei gilt es auch zu bedenken, dass die "Pathdelimiter" der Betriebssysteme unterschiedlich
    139 sein können (/ oder \, ). Für Plattformunabnhängigkeit könnt ihr `GRPlatform>>pathSeparator`.
     138sein können (/ oder \, ). Für Plattformunabhängigkeit könnt ihr `GRPlatform>>pathSeparator` benutzen.
    140139
    141140
     
    146145
    147146
    148 Das Speichern von Bildern im "Quellcode"/Image hat den einfachen Vorteil, dass ihr sie mit allen Teammitgliedern mit Hilfe des Monticello Source Code Repository teilen könnt. Bei externen Dateien muss leider ein anderer Weg (z.B. SVN) genutzt werden. Dennoch würden wir externe Dateien immer bevorzugen (welche nur bei Bedarf geladen und im Image gecached werden), da sie das Image klein halten. Unser Plan gegen Ende des Semester ist es alle Projekte in ein Image zu laden, daher ist es auch hier sinnvoll eure Resourcen extern im Dateisystem zu halten. Denkt bitte auch daran einen Unterordner für euer Projekt innerhalb des Squeak Verzeichnisses zu nutzen.
     147Das Speichern von Bildern im "Quellcode"/Image hat den einfachen Vorteil, dass ihr sie mit allen Teammitgliedern mit Hilfe des Monticello Source Code Repository teilen könnt. Bei externen Dateien muss leider ein anderer Weg (z.B. Dropbox, Git, SVN) genutzt werden. Dennoch würden wir externe Dateien immer bevorzugen (welche nur bei Bedarf geladen und im Image gecached werden), da sie das Image klein halten. Unser Plan gegen Ende des Semester ist es alle Projekte in ein Image zu laden, daher ist es auch hier sinnvoll eure Resourcen extern im Dateisystem zu halten. Denkt bitte auch daran einen Unterordner für euer Projekt innerhalb des Squeak Verzeichnisses zu nutzen.
    149148
    150149
     
    170169=== Wie kann ich das mouseDown-Event an den Owner weiterleiten? ===
    171170
    172 Falls der Owner alle Mouse-Down-Events seiner Kinder abfangen soll, ist #mouseDownPriority die bessere Lösung. Bei #rejectsEvent: müsste jeder mögliche Submorph-Typ modifiziert werden. Dies würde Code-Duplikation bedeuten.
     171Falls der Owner alle Mouse-Down-Events seiner Kinder abfangen soll, ist `#mouseDownPriority die bessere Lösung. Bei `#rejectsEvent:` müsste jeder mögliche Submorph-Typ modifiziert werden. Dies würde Code-Duplikation bedeuten.
    173172
    174173
     
    255254
    256255
    257 2.) Du kannst in Squeak jeder Klasse #allInstances senden und bekommst dann eine Liste, die alle Objekte der Klasse enthält. An diese Liste können dann mit dem Collection Protocol (z.B. #do:) Nachrichten an alle Objekte geschickt werden. Somit kannst du die Objekte bearbeiten oder mittels stopStepping zum Stillstand bringen.
     2562.) Du kannst in Squeak jeder Klasse `#allInstances` senden und bekommst dann eine Liste, die alle Objekte der Klasse enthält. An diese Liste können dann mit dem Collection Protocol (z.B. `#do:`) Nachrichten an alle Objekte geschickt werden. Somit kannst du die Objekte bearbeiten oder mittels stopStepping zum Stillstand bringen.
    258257
    259258
     
    270269=== Wie bindet man das eigene Projekt in den Objects Explorer ein? ===
    271270
    272 1.) !ObjectsTool erstellt die angezeigten Kategorien in dem es einfach alle Morphklassen nach einem bestimmten Selektor durchsucht und nur diese hinzufügt. Man benötigt also einen Morph und zwar den Morph, der das Spiel darstellt (z.B. !BlyPacmanApp).
    273 2.) Auf der Klassenseite des Morphs wird eine Kategorie "parts bin" benötigt und in dieser eine Methode #descriptionForPartsBin. Das ist der Hook für !ObjectsTool.
     2711.) `ObjectsTool` erstellt die angezeigten Kategorien in dem es einfach alle Morphklassen nach einem bestimmten Selektor durchsucht und nur diese hinzufügt. Man benötigt also einen Morph und zwar den Morph, der das Spiel darstellt (z.B. `BlyPacmanApp`).
     2722.) Auf der Klassenseite des Morphs wird eine Kategorie "parts bin" benötigt und in dieser eine Methode `#descriptionForPartsBin. Das ist der Hook für `ObjectsToo`.
    274273
    275274{{{
     
    282281}}}
    283282
    284 Dabei kann mit einem vierten Parameter auch ein Beispielbild angegeben werden (siehe z.B. AudioChatGUIdescriptionForPartsBin, self ... sampleImageForm:). Ansonsten wird ein kleines Icon automatisch erstellt.
     283Dabei kann mit einem vierten Parameter auch ein Beispielbild angegeben werden (siehe z.B. `AudioChatGUIdescriptionForPartsBin`, self ... sampleImageForm:). Ansonsten wird ein kleines Icon automatisch erstellt.
    2852843.) Damit sollte der Morph in dem !ObjectsTool erscheinen. Allerdings kann es sein, dass der Morph nicht richtig initialisiert wird (z.B. das Extent nicht stimmt).
    286285
    287 Wenn man ein Objekt aus dem !ObjectsTool zieht, wird der jeweiligen Klasse #newStandAlone als Nachricht gesendet. Die Methode dazu sieht wie folgt aus.
     286Wenn man ein Objekt aus dem !ObjectsTool zieht, wird der jeweiligen Klasse `#newStandAlone` als Nachricht gesendet. Die Methode dazu sieht wie folgt aus.
    288287{{{
    289288newStandAlone
     
    292291}}}
    293292
    294 Während Morph #initializeToStandAlone einfach auf #initialize zurückführt, überschreiben andere Morphs die Methode (z.B. !PasteUpMorph) und setzen z.B. die Größe. Falls das der Fall ist, kann man die #initializeToStandAlone einfach überschreiben:
     293Während Morph `#initializeToStandAlone` einfach auf `#initialize` zurückführt, überschreiben andere Morphs die Methode (z.B. !PasteUpMorph) und setzen z.B. die Größe. Falls das der Fall ist, kann man die `#initializeToStandAlone` einfach überschreiben:
    295294
    296295{{{
     
    327326
    328327
    329 === Wie werden plattformunabhängige Datei-Zugriffe realisiert? ===
    330 
    331 Unabhängige Trennzeichen bekommt ihr mit den Methoden: #separator, #pathSeparator, #separatorString.
     328=== Wie werden plattformunabhängige Datei-Zugriffe realisiert? === #platform-path-separator
     329
     330Unabhängige Trennzeichen bekommt ihr mit den Methoden: `#separator`, `#pathSeparator`, `#separatorString`.
    332331Ebenso kapselt die Klasse URI alle notwendigen Plattform-Mappings.
    333332
     
    335334=== Gibt es in Squeak so etwas wie eine !FileDialog Klasse? ===
    336335
    337 Helfen kann euch hier die Klasse !FileList.
     336Helfen kann euch hier die Klasse `FileList`.
    338337
    339338
     
    346345=== Objekte als Text klassenseitig abspeichern ===
    347346
    348 Zum Serialisieren von Objekten gibt es in Squeak die Methoden #storeOn: bzw #readFrom:
     347Zum Serialisieren von Objekten gibt es in Squeak die Methoden `#storeOn:` bzw `#readFrom:`
    349348
    350349Hier der Code dazu:
     
    388387Die WAFileLibrary ist nicht dafür gedacht als eine langfristige Lösung zu fungieren. Sie ist eine einfache Art Dateien bereitzustellen. Aber sowohl durch ihre Ablage der Daten im Image als auch der vergleichsweise langsamen Zugriffszeit auf diese Daten sollte sie immer nur temporär benutzt werden. Sie hat aber auch Vorteile, wie z.B. den leichten Austauschen von Dateien über Monticello. Bessere Lösung um auf statische Dateien zuzugreifen findet ihr ebenso im Tutorial (selbes Kapitel weiter unten).
    389388
    390 Bei deinem Beispiel würde an der Klasse AClassName die Methode #fooBar aufgerufen werden. Hier dispatcht Seaside ein wenig mit Meta-Programming. Aber dieses Schema ist konstant und kann über den File Upload Dialog soweit umgangen werden, dass ihr die Klasse gar nicht anfassen braucht. Zum Hochladen von Dateien habe ich bereits in einer vergangenen Mail auf der Liste etwas geschrieben, da hier das Tutorial nicht mehr aktuell ist.
     389Bei deinem Beispiel würde an der Klasse `AClassName` die Methode `#fooBar` aufgerufen werden. Hier dispatcht Seaside ein wenig mit Meta-Programming. Aber dieses Schema ist konstant und kann über den File Upload Dialog soweit umgangen werden, dass ihr die Klasse gar nicht anfassen braucht. Zum Hochladen von Dateien habe ich bereits in einer vergangenen Mail auf der Liste etwas geschrieben, da hier das Tutorial nicht mehr aktuell ist.
    391390
    392391Durch die begrenzten Möglichkeiten der WAFileLibrary sind Unterordner so weit ich weiß nicht möglich aber ggf. wurde das in der neuen Seaside Version auch geändert.
     
    567566Das kommt sehr auf eure Netzwerkimplementierung an. Nutz ihr ein Standardprotokoll, so sollte die verwendete Bibliothek im Allgemeinen auch entsprechende Methoden bereitstellen. Häufig sind diese transparent, so dass die Methoden automatisch gerufen werden, sobald ein neuer Request eintrifft. Um Beispiele dafür zu sehen, schaut euch einmal im Image den WAListener an, welcher den Webserver für Seaside implementiert. Dort wird auch gezeigt wie man Prozesse "forked" um mehrere Requests gleichzeitig zu behandeln.
    568567
    569 Von dem Ansatz die ganze Sache in Morphic und dessen #step Methode abzubilden, raten wir schlichtweg ab. Der Grund: die #step Methode ist nur scheinbar parallelisiert und sollte eine Methode auf `SocketStream>>isDataAvailable` warten, steht das ganze System. Ihr müsste also auf jeden Fall mit mehreren Prozessen arbeiten. Dafür verwendet ihr wie gesagt die `fork`-methode.
     568Von dem Ansatz die ganze Sache in Morphic und dessen `#step` Methode abzubilden, raten wir schlichtweg ab. Der Grund: die `#step` Methode läuft nicht parallel. Sollte eine Implementierung von `#step` auf `SocketStream>>isDataAvailable` warten, steht das ganze System. Ihr müsste also auf jeden Fall mit mehreren Prozessen arbeiten. Dafür verwendet ihr wie gesagt die `fork`-methode.
    570569
    571570Um das Warten zu realisieren, schaut euch die Klasse Delay an.
     
    588587Das Cryptography package sollte alle notwendigen Funktionen liefern.
    589588Dort habt ihr eine MD5 Klasse. Folgt dem Beispiel in der Methode
    590 #hashStream:. Aber Achtung, [http://de.wikipedia.org/wiki/MD5 MD5] ist sehr unsicher, da sehr leicht Kollisionen gefunden werden können.
     589`#hashStream:`. Aber Achtung, [http://de.wikipedia.org/wiki/MD5 MD5] ist sehr unsicher, da sehr leicht Kollisionen gefunden werden können.
    591590Seaside nutzt deswegen üblicherweise den SHA Algorithmus. Diesen könnt ihr bereits in eurem Image finden unter der Klasse `SecureHashAlgorithm`. Dort schaut euch einfach die Methoden unter dem 'public' Protokoll an.
    592591
     
    603602'abc' , Character tab , 'abc'
    604603}}}
    605 da `String>>`,` die Nachricht #asString an seinen Parameter sendet. Unterschiedlich sieht das nur aus wenn man es per print it (cmd/strg + p) ausgibt, da tab halt je nach Position in unterschiedlicher Länge gerendert wird. Die Strings sind aber gleich (im Sinne von #=).
     604da `String>>,` die Nachricht `#asString` an seinen Parameter sendet. Unterschiedlich sieht das nur aus wenn man es per print it (cmd/strg + p) ausgibt, da tab halt je nach Position in unterschiedlicher Länge gerendert wird. Die Strings sind aber gleich (im Sinne von `#=`).
    606605
    607606Bedenkt bitte, dass ihr bei sehr komplexen String Konkatenationen besser auf Streams zurückgreifen solltet: