24. Mai 2008

Weblin Whiteboard oder: User finden alles

Jemand hat das Whiteboard in weblin entdeckt und User erschreckt. Das Whiteboard kann einfache Grafiken auf Webseiten produzieren, die dann alle im Raum sehen. Kommt man zu spät in den Raum, sieht man es nicht, weil es nur wie Chat als Message vorbeisaust. Wenn es keinen Protokollbot gibt, der die Messages speichert und wieder abspielt, sind die Whiteboard-Messages transient (flüchtig). Die Grafik liegt über allen anderen Fenstern, so dass man den Eindruck bekommt, dass sie auf allen Seiten ist. Ist sie aber nicht, sondern nur in dem Raum wo sie gemacht wurde. Übrigens wenn es nervt: Rechtsklick auf den Rand, oben steht wer es gemacht hat und unten steht "Löschen".

Der Whiteboard Code ist in weblin noch drin und eigentlich nicht erreichbar. Aber natürlich zu Debugzwecken dann doch. Das zeigt wieder mal, dass User alles finden. Security by Obscurity hat keine Chance.

Es gibt einfach so wahnsinnig viele User, die sich so engagiert mit dem Thema befassen. Die kennen das System oft besser als Entwickler. Entwickler benutzen das System weniger, als User. Natürlich kennen Entwickler den Teil den sie gemacht haben sehr gut, aber Entwickler sind trotzdem meistens keine Poweruser. Entwickler kennen die Theorie, User die Praxis. Entwickler programmieren einzelne Features und bedenken dabei manchmal auch Zusammenhänge. Aber User erkennen Muster im Verhalten von Software, die die Entwickler nicht explizit programmiert haben. Vielmehr sind entstehen Wechselwirkungen mehrerer Features, die sich durch sehr intensive Beschäftigung zu einem Muster verbinden.

Das gilt genauso für Games, wo diese Bedienungsmuster im High-End Bereich ein wichtiger Teil des Gameplays werden. Das gilt auch für alle anderen Programme, wie in diesem Fall weblin, mit denen sich User intensiv und lange beschäftigen. Manche Leute lernen das Programm einfach durch intensive Benutzung seiner Features, andere durch Analyse von Code, Protokoll und Reaktionen.

Weiter so Leute, zeigt den Entwicklern was "Wisdom of the Crowds" heisst.

RSS-Feeds: eine Fehlentwicklung - warum XMPP besser gewesen wäre

Ich bin ja wirklich ein Fan von RSS-Feed-Readern. Inzwischen besuche ich gar keine Blogs mehr, sondern lese nur noch die Feeds im Reader. Echt toll, dass die Nachrichten zu mir kommen, statt dass ich alle Websites abklappern muss.

Schade nur...

...dass die Nachrichten gar nicht zu mir kommen, sondern dass meine Software sie abholen muss. Ich muss zwar nicht alle Websites abklappern, aber mein RSS-Client schon. Der schaut ständig nach ob es was neues gibt (polling). Dabei sollt er eigentlich benachrichtigt werden. Der Begriff RSS-Feed ist glatt gelogen. RSS-Feeds sollten RSS-Fetch heißen. Nochmal: Die Nachrichtenquelle sollte eine Nachricht an meinen Reader schicken, statt dass mein Reader alle 10 Minuten nachschaut ob etwas neues da ist. Traffoc-mässig echt eine Schweinerei und nur im Zeitalter von Torrent und Videodownloads gerade noch tragbar.

Diese Fehlentwicklung liegt natürlich daran, dass der ganze RSS-Mechanismus auf Web-Technologien aufbaut, die wegen HTTP per se nur Request-Response können. Dabei gibt es etablierte Technologien mit denen man einen echten News-Feed aufbauen könnte, z.B. XMPP/Jabber.

Was besser gewesen wäre

Bei XMPP ist mein Client ständig mit meinem Server verbunden. Andere Server können jederzeit zu meinem Server Kontakt aufnehmen und dieser schickt dann alles an mich weiter. Wenn ich einen News-Feed haben will, dann registriere ich mich mit meiner Adresse bei der Nachrichtenquelle. Die Nachrichtenquelle schickt mir dann immer eine Mitteilung, dass etwas neues da ist (mit Titel und Zusammenfassung). Mein Reader zeigt es mir sofort (!) an und ich kann die Nachricht lesen. Kein "Pollen", keine Verzögerung, kein unnötiger Traffic.

Jetzt mal ehrlich...

...RSS ist Really Stupid Syndication. Diese Art von News-Pollen gehört in den Mülleimer der Geschichte. Die Zeit ist reif für ein Message-basiertes News-System. Die Technik ist verfügbar: XMPP und andere IM.

Aber inzwischen gibt es so viel Content der die schlechte alte Technik benutzt, dass wir noch lange damit leben werden müssen. Und mit Web-basierten RSS-Readern entspannt sich auch die Lage beim Traffic, weil ein Betreiber (z.B. Google) die Feeds für alle gemeinsam abfragt. Und wenn es komplizierter gewesen wäre, dann hätte es sich vielleicht nicht so durchgesetzt und es wäre weniger Content verfügbar.

Lesen Sie auch bald wieder hier: "Web und Request-Response: eine Fehlentwicklung - warum ein Mesh und Messaging besser gewesen wäre".

23. Mai 2008

Simple Remote Procedure Call - Response Format

SRPC-Response Format is an extension to SRPC. It specifies a request parameter which selects a response format.
This is primarily intended for the REST variant of SRPC where the SRPC parameters are in the request URI and the result is the response body. Usually, the response body carries a data structure. But it is not clear in which format the data is encoded. A "Format" parameter in the request can select if the response is encoded as XML, JSON, WDDX, etc.

  1. Format=<one of: json, php, wddx, xml, yaml, etc.>

Example:

  1. Format=xml

XML Example: HTTP query:

  1. C: GET /srpc.php?Method=GetPrices&Symbol=GOOG&Date=1969-07-21&Format=xml HTTP/1.1

HTTP response (with a sample XML as a the result value):

  1. S: HTTP/1.1 200 OK
  2. S: Content-type: text/xml
  3. S:
  4. S: <?xml version="1.0"?>
  5. S: <prices>
  6. S: <price time="09:00">121.10</price>
  7. S: <price time="09:05">121.20</price>
  8. S: </prices>

JSON Example: HTTP query:

  1. C: GET /srpc.php?Method=GetPrices&Symbol=GOOG&Date=1969-07-21&Format=json HTTP/1.1

HTTP response (with a sample JSON as the result value):

  1. S: HTTP/1.1 200 OK
  2. S: Content-type: application/json
  3. S:
  4. S: {
  5. S: "prices": [
  6. S: { "time": "09:00", "value": "121.10" },
  7. S: { "time": "09:05", "value": "121.20" }
  8. S: ]
  9. S: }

12. Mai 2008

Wege aus der kleinen Coderkrise

Jeder Coder kennt die kleine Krise, wennn man zu lange an einem Programmierproblem hängt, dass eigentlich schnell erledigt sein sollte. Manchmal ist es ein Algorithmus, der sich nicht schön in geschlossener Form ausdrücken lassen will. Manchmal ist es eine Lösung die sich standhaft weigert auch alle Grenzfälle abzudecken. Manchmal ist es eine Komplexität, die sich nicht beherrschen lässt. Die Lösung der Krise wäre für den Coder ein Riesenschritt, für den Rest der Welt nicht. Meistens ist es sogar so, dass der Rest der Welt das Problem nicht sieht, weil es "nicht wirklich ein Problem sei kann" oder es "am Ende ja sowieso geht, wozu also aufregen?". Trotzdem bereitet es dem Coder schlaflose Nächte, Haareraufen, Hirnzermartern, Überstunden.

Im Nachhinein gesehen ist die Lösung dann doch meistens entweder "ziemlich einfach", "offensichtlich" oder "ein Hack". Jedenfalls ist es gelöst. Der Coder ist glücklich. Aber sonst interessiert sich keiner dafür.

OK, das war bisher nur Gerede. Diese zwei Absätz helfen keinem. Damit das ganze noch Hand und Fuss bekommt also hier meine Lösungsansätze. Natürlich hängt die konkrete Lösung sehr stark vom Problem hab. Deshalb hier nur Lösungsstrategien, keine Lösungen. Wie immer bei "Patterns": bitte keine Wunder erwarten. Hier steht nur was der vernünftige Coder eh' schon immer gemacht hat.

Wolfspel'z Wege aus der kleinen Coderkrise:

1. Display State

Short: Replace the display of state transitions with a display of the state.

Description: If a system has a complex state and if the state is displayed, then state transitions can be shown by changing the display according to the state transition. But sometimes there are too many possible transitions, similar, but different transitions, transition variants, so that changing the display to reflect the change of the model might be too complicated. Also: testing is very difficult, because all transitions (e.g. by user input) must be tested. If anything changes, then testing all transitions must be repeated. It is difficult to keep a the display consistent with the model, because changes are applied to both. They do not depend on each other. A model-view architecture surely helps, but introducing MVC might be a disruptive architecture change. So, the simpler solution is to redraw the complete display on each model change. If a state transition changes the model, then just repaint the screen.

Variant: If repainting is not feasible, e.g. in case of HTML user interfaces, then rearranging all elements to reflect the model's state is equivalent.

Comments: The downside of this approach is that it might be bad for performance. Applicability depends, but it might give you time for a real solution, especially if there is a deadline. (Let performance issues come back as a bug report :-)

Example:
If the code reads:
model.changeSomething();
display.showChanges();
model.changeSomethingElse();
display.showOtherChanges();


Change it to:
model.changeSomething();
display.showAll();
model.changeSomethingElse();
display.showAll();


2. Perturbation Theory

Short: If special cases prevent a closed solution, then treat them separately.

Description: An algorithmic solution might be difficult, because of context dependencies, special cases, or edge cases. They can make the algorithm complex. Complex algorithms are not good. algorithms should fit on a small page. A solution is to create the core algorithm as if there were no special cases. Then fix the remaining cases separately. A typical solution then starts with the core algorithm. If that is understood and tested, then work around it. The core algorithms could be followed by an additional code section that "fixes" wrong results of the core for special cases. There can ba multiple consecutive such fix-sections. Try to identify the core and then classes of deviations from the core. Then make all individual code sections starting with the core. Do not try to mix special cases into the core algorithm.

Comment: This approach is known as Perturbation Theory in physics. The first order solution is linear and understandable. Higher order solutions add special detail, but are more difficult to comprehend. Therefore they are split fom the first order and added later when the first order works.

3. Simplification

Short: Reduce complexity if possible.

Description: Structure is usually a good thing. But structure also makes solutions more complex. A single layer of hierarchy might make a problem just the bit too complex for the coder to understand it easily enough to derive a simple solution. If you strip away complexity, then you use features or potential features. Even features you might need or find cool or need in the future or might need in the future. Ask yourself: could it be simpler? The answer "no" is forbidden, because anything can be simpler even though you might loose something. The question is: do you loose something that you really need NOW. It might be, that you can even generalize and undo the simplification later. The problem is now. It must be solved now. Do not solve future problems. Just try not to inhibit future extensions while doing the simple thing.

Application:
Ask:
- could it be simpler? - the answer is "yes, but..."
- what would be missing?
- does it hurt now?
- does it hurt later? if yes, does it damage the structure so sverely, that it can not be fixed later.
Typical questions:
- is the hierarchy required, could it be flat? (remember XML-namespaces? XML is simple, namespaces build on top of flat names.)
- do I really need the full implementation or is a solid API with a fake implementation behind good enough?
- does it really have to be a dynamic registry or could we hardwire the modules and just pretend to use a dynamic list?

Then, get rid of it.

4. Start Over

Short: Throw it away and do it again (applies only to small pieces).

Description: Sometimes we produce much code over time. Sometimes very quickly, because a problem has many special cases. Sometimes code accumulates slowly. Anyhow, the result is not understood anymore with all side effects. Each additional feature which must be added, can be a nightmare. Either for the coder who wants to guarantee that "the old mess + the new feature" is still working or for the user who gets random behaviour occasionally. All these are symptoms for a system that is out of control. The same applies to algorithms. This is about solving small problems, not about systems. In case of systems there is no easy way to redo everything. But algorithms and few pages of implementation can be recreated. A new implementation might even get rid of the ballast that was added, but is not used anymore.

Comment: Start Over is a valid last resort to comply to the holy principle of "understand what you are doing". You must completely understand what you are coding and what it does to the data and to users. If you do not understand what you are changing or trying to fix, then you should make it so that you understand, even if that means to write it again in your own words.

Application:
Select code, copy to temp file, press delete.
Kids: do not try this at home.

5. Be Quick

Short: Do not spend much time on the solution. Find a solution quickly.

Description: Do not spend more than 30 minutes on a single algorithm. Do not think too long about a solution. They do not pay you for thinking. They pay you for coding. Programmers spend their time writing I/O, error handling, initialization, synchronization, testing. There is no time to brood for hours, because there is so much else to to. Maybe you can find a solution instead of squeezing it out. A similar problem has already been solved. There is a library for it. There is a software pattern. There is a similar service, that must have had a similar problem. Find the similarity and find out how they have done it.

Application:
Generalize your problem. What is the core of it. What are you really doing. Abstract from your class names and marketing labels. Then try Google.

6. Problem Elimination

Short: Change the problem, if the solution is too difficult

Description: There are all kinds of difficult problems. Most can be reduced to a series of smaller problems. But some withstand reduction, because "everything depends on everything else" and "a small change makes a big difference somewhere else", especially if the "somewhere else" is the marketing department. If a problem has too many (or unclear) requirements, then it might end up in a complex solution after a long time that does not benefit anyone, especially not future coding performance. A complex solution is an indication for a difficult problem. The possibility to create a good code structure indicates a good problem. On the other hand, the lack of a cool code solution indicates lack of a good problem. The problem might not be understood. Simplify the problem. Check what you really need. Use external solution proposals as a description of the real problem, rather than an implementation guideline. Re-create the real problem and make up your own solution.

Comment: It might be necessary to convince the product owner that what she really wants is something different than she talked about.

Application:
Analyze proposed solutions.
Find the core of the problem or find a better problem.
Convince them to change the task.

_happy_coding()

10. Mai 2008

Schach mit Google Docs

Man kann ein ge-share-tes Google Spreadsheet als Schachbrett benutzen. Alle (beide) Teilnehmer können live sehen was der andere macht.

Gezogen wird mit "Ausschneiden" und "Einfügen". Auf farbige Schachfelder verzichten wir deshalb lieber, sonst kopiert man den Hintergrund mit.

Die Spieler sind als weblins da und können chatten. Das wäre sogar in Google Docs gegangen mit "Chat about this spreadsheet". Aber Sprechblasen sind netter.

9. Mai 2008

weblin.lite Bookmarklet

This bookmarklet toggles weblin.lite for the current page. It en-lite-ns the current page by adding a URL prefix. If the page is already en-lite-ned, then it removes the prefix. You can add it to your browser as a bookmark.

Bookmarklet: weblin.lite


For those who are interested, this is the code:

var s = new String(top.document.location);
var p = 'http://lite.weblin.com/';
if (s.substr(0, p.length) == p) {
s = s.substr(p.length);
var b = false;
while (!b && s.length != 0) {
if (s.substr(0,1) == '?') {
b = true;
}
s = s.substr(1);
}
var n = s.search(/&weblin\.lite&/);
if (n != -1) {
s = s.substr(0, n);
}
top.document.location = s;
} else {
top.document.location = p + '?' + s + '&weblin.lite&referer=bookmarklet';
}



_happy_coding()

7. Mai 2008

Twitteraktivität

Meine Twitteraktivität.

Sieht nach ausreichend Schlaf aus, aber das Mittagessen ist etwas unregelmässig.

6. Mai 2008

IM Protokolle: eine Fehlentwicklung - warum SMTP besser gewesen wäre

Ich bin ja wirklich ein Freund von XMPP als Instant Message Protokoll. Und ich finde auch IM als Dienst mit all seinen Anwendung von Status Updates, über Chat bis Unified Messaging ganz toll.

Aber: dafür hätte man keine neuen Protokolle gebraucht. SMTP mit ein paar kleinen Erweiterungen hätte völlig ausgereicht. Messaging ist ja sozusagen die Kernkompetenz von SMTP. Dafür wäre sicher kein neues Protokoll nötig gewesen. Was sind Status Updates anderes als Messages? Chat: Messages mit einer Thread-ID. SMTP kann beliebige Content-types: text, HTML usw. Das hat HTTP schließlich von SMTP gelernt. Wie wir alle wissen kann SMTP sogar multipart messages (MIME). Das muss ein IM Protokoll erst mühsam nachmachen.

Um hier mal mit Mythen und Halbwahrheiten aufzuräumen:

IM ist schneller als Email

EMail ist nur deshalb langsam weil mein Email-Reader nur alle 5 Minuten die Email abholt. Würde er seine TCP Verbindung zum Mailserver stehen lassen, dann könnte der Server immer sofort die Email an den Client weiterleiten. Sozusagen COMET für SMTP. Wenn es bei HTTP geht, dem Prototyp eines Request/Response-Protokolls, dann geht es auch bei SMTP. Noch besser: jeder sollte einen SMTP Server im Email-Client haben und der Company-Server forwarded einfach live an den Client. SMTP Messages gehen meistens 3 Hops: Sender -> lokaler Server -> entfernter Server -> Empfänger. Das ist genau die gleiche Topologie wie bei XMPP.

IM ist SPAM-resistenter als Email

Nur manche IM Systeme sind SPAM-resistenter und zwar deshalb, weil das Gesamtsystem in einer Hand ist. z.B. können bei zentraler Registrierung Accounts gebannt werden. Oder weil sie Dialback und Sender-Authentifizierung machen. Das ist aber nicht das Protokoll, sondern das Gesamtsystem. Ein Emailsystem mit Sender-Auth, Dialback und Benutzern, die nicht alles glauben ist genauso gut oder schlecht SPAM-resistent wie IM.

Mit SMTP kann man nur Emails verschicken

SMTP kapselt alles was man will. Alle MIME-Typen (MIME! klingelts?), vor allem auch XML. Auf XML sind ja ein paar IM Protokolle mächtig stolz. Mit beliebigem XML in SMTP lassen sich auch beliebige Daten übertragen. Es gibt sogar einen SMTP Network-Layer in .NET zum Transport von SOAP-XML als Remote Procedure Call. Natürlich hätte man auch ein bisschen Status-XML übertragen können. Oder Subscriptions, Notifications, Requests, Responses, und alles was man sich nur wünschen kann.

Warum SMTP besser ist (gewesen wäre)

SMTP ist hochentwickelt im Vergleich zu IM Protokollen. Und das sogar immer noch obwohl IM nun schon über 10 Jahre alt ist.

SMTP ist einheitlich während die IM-Welt zersplittert ist.

SMTP hat Offline Storage eingebaut. Manche IM Protokolle mussten das erst wieder erfinden.

Die SMTP Infrastruktur war schon weltweit operativ, robust und verstanden. Es wäre nicht notwendig gewesen neue Software zu machen, zu betreiben, kennen zu lernen.

Meine IMs würden automatisch archiviert, wie Emails. Es gäbe da keinen Unterschied. GMail hat das gerade wieder erfunden.

Es gibt Web-basierte Email-Reader, sehr praktisch im Urlaub. Auch das haben die IMs wieder erfunden (z.B. Meebo), aber warum ist das überhaupt separat. Ach ja, GMail hat GTalk mit eingebaut. Schade, dass sie überhaupt was einbauen mussten.

Was notwendig gewesen wäre

Um SMTP noch ein bisschen leichter zu machen hätte man z.B. SMTP Pipelining verwenden können. Pipelining befreit SMTP von den 4 Round-Trips. Nicht dass es wirklich wichtig wäre.

Eine Art SMTP-COMET oder einfach ein SMTP-Server für Jedermann.

Jetzt mal ehrlich...

...meine Kommunikationsanwendung ist Thunderbird oder Outlook. Die Buddyliste gehört in Thunderbird. Sie sollte identisch mit dem Adressbuch sein. Ein Adressbuch mit Online-Status. Und kurze Email heißen dann IM.

Trotzdem gibt es XMPP und andere IM Protokolle. Und dabei wird es auch bleiben. Lesen Sie auch bald wieder hier: "RSS-Feeds: eine Fehlentwicklung - warum XMPP besser gewesen wäre".