Windows Api Diskussion
StartSeite | Neues | TestSeite | ForumSeite | Teilnehmer | Kategorien | Index | Hilfe | Einstellungen | Ändern
von WirdCppVonMicrosoftForciert
Kontext: Das komplizierte (oder als kompliziert empfundene) Windows-API wurde in ein Application Framework eingepackt, um den Umgang wenigstens etwas komfortabler zu machen, oder um Entwickler an die Entwicklungsumgebung von Microsoft und damit im Umkehrschluss auch wieder an die Plattform MS Windows zu binden.
Zur Sache: Statt die komplizierten Dinge nur zu verpacken, hätte man auch das API verbessern und vereinfachen können. Das wäre aus meiner Sicht (als WindowsEntwickler) vernünftiger gewesen. Egal, ob man dann darüber ein OO Framework stülpt, oder nicht. -- HelmutLeitner
- Das führt zurück zu der Disskussion WasIstKompliziert. Verglichen mit GEM, diversen X-Toolkits und dem Java-API finde ich das Windows-API nicht ungewöhnlich kompliziert (oder unkompliziert). Dass das etwas ist, was in einem engen Zusammenhang mit C++ als Entwicklungswerkzeug steht bezweifle ich. -- KurtWatzka
- Ich sehe einen großen Unterschied zwischen der Komplexität von C++ und der Komplexität des Windows C API. C++ ist komplex, weil man damit komplexe Dinge tun kann und weil es eine Vielfalt an Konzepten gibt. Dagegen hat die Komplexität des Windows API hat sehr viel mit Inkonsistenz und mangelhafter Dokumentation zu tun. Es gibt im WindowsApi? keine komplexen Vorgänge, aber sehr viele komplexe Interfaces. Wenn es scheinbar mehrere Wege gibt, dann ist trotzdem meist nur ein Weg gangbar, die anderen haben Labyrinth-Character. Meiner Meinung nach kann es kaum ein API mit schlechterem Design geben als das Windows C API. -- hl
- Ein konkretes Beispiel würde für mich verständlicher machen, wodurch das Windows API sich in der Komplexität seiner Schnittstellen von anderen APIs mit ähnlichem Funktionsumfang und ähnlicher Zielsetzung unterscheidet. -- kw
- Ich erinnere mich noch vage daran, wie man in VisualCpp? einen Tooltip zu einem Widget anzeigt (vage == bitte ggf korrigieren, wenn jemand es genauer weiss). Man musste dem Fenster, das das Widget enthält, sagen, dass man Tooltip-Anzeigen-Events mitgeteilt kriegen will. In der Event-Verarbeitungs Funktion musste man dann das gewünschte Tooltip-Event in der case-Abfrage berücksichtigen. Die beiden int-Parameter, die der Event-Funktion übergeben werden, musste man dann mit geeigneten Macros beharken, um daraus magisch einen Zeiger auf das Widget zu kriegen, zu dem der Tooltip angezeigt werden soll. In das zweite Argument, mit dem die Event-Funktion aufgerufen wurde, muss man dann den Zeiger auf den auszugebenden Text eintragen und mit einem bestimmten Code aus der Ereignisbehandlung zurückkehren. Zeitgleich oder schon vorher hatte Borlands CppBuilder? einfach eine Eigenschaft namens Tooltip für jedes Widget, wo ich den Text eintragen konnte... -- RobertWenner?
Es ist grundsätzlich nicht einfach, APIs zu diskutieren und zu kritisieren, weil der Programmierer keine Handhabe gegen den Hersteller des API besitzt. Er ist normalerweise nicht Auftraggeber und das API wurde meist nicht zur Erfüllung einer bestimmten Spezifikation erstellt. Der Programmierer erhält das API "as is". Weiters sind die APIs meist Bestandteil von vermarkteten Produkten und jede Kritik wird reflexartig abgewehrt: "its not a bug, its a feature". Es gibt meines Wissens auch kein Regelwerk für die Gestaltung von APIs, auf das man sich als Benutzer berufen könnte.
Es soll auf dieser Seite auch nicht darum gehen, Stimmung gegen Microsoft oder das Windows API zu machen. Eine Diskussion über das Windows API im speziellen könnte aber dazu führen, einen schärferen Blick für die Stärken und Schwächen von APIs zu entwickeln und von eigenen und fremden APIs mehr Qualität zu erwarten. Schlechte APIs sind eine Quelle von Fehlern und eine Senke für unproduktive Arbeitszeiten.
Was könnten berechtigte API Kritikpunkte sein:
- Fehlerhafte Implementierungen
- Unvollständige Funktionalität
- Fehlende oder falsche Dokumentation
- Unnötige Komplexität
- Inkonsistenz
- ...
Was könnten unberechtigte API Kritikpunkte sein:
- Notwendige Designentscheidungen (Sprachauswahl, Objekthierarchie vs Einzelobjekte, ...)
- Fehlende Unterstützung für bestimmte Standards (z. B. Grafikformate)
- ...
Abstraktion von Zeichenwerkzeugen im GDI
Beispielsweise finde ich das GDI mit seiner Abstraktion von Zeichenwerkzeugen recht gelungen. Code für Systeme, bei denen einzelne Eigenschaften der Grafikausgabe über mehrere Funktionsaufrufe getrennt einzustellen sind führen zu deutlich unübersichtlicherem Code in Anwendungsprogrammen. Mich hat diese Abstraktion einst dazu gebracht, einen ähnliche Abstraktion auf das GEM-VDI aufzusetzen. Das Freigabeproblem für die "Zeichenwerkzeuge" ist der Preis, der in einer prozeduralen Umgebung für so eine Abstraktion zu zahlen ist. -- kw
- Ich gebe dir Recht, dass der Bereich der Zeichenfunktionen im Windows API relativ gut gelöst ist. -- hl
Mangelnde Implementierung des Objektcharacters
Viele Elemente des Windows API haben klaren Objektcharacter: Pen, Brush, Bitmap, Dc, Window ... Es wäre also zu erwarten, dass es für die Erzeugung, Zerstörung sowie den Zugriff und die Änderung von Eigenschaften dieser Objekte *einfache* prozedurale Schnittstellen gibt. Das ist jedoch nicht der Fall. Nur einige Beispiele:
| PenSetColor(hpen,color)
hbitmap=BitmapCreateFile(filename)
WindowSetBorderType(hwnd,type) |
|
|
Warum sollte man das Zeichenwerkzeug Pen nicht wiederverwenden, eine Bitmap nicht auch aus einem eigenständigen File lesen, Window-Eigenschaften nicht auch nach der Erzeugung verändern?
Das obige mag harmlos und unbedeutend klingen, aber alleine das Objekt Window verfügt z. B. über ca. 70-100 Eigenschaften, die weder klar aufgelistet noch mit entsprechenden Accessor-Funktionen zugänglich sind. Es existiert eine unübersichtliche Ansammlung verschiedener Mechanismen, um Windows-Eigenschaften zu lesen und teilweise auch zu verändern. Alleine dieses Chaos im Kern des Windows API ist unentschuldbar, weil es durch entsprechende Funktionen beseitigt werden kann, wie es auch jeder - mit erheblichem Arbeitsaufwand - tut, der länger direkt mit dem Windows API arbeitet.
-- hl
- Den Wunsch, die Farbe eines Stiftes zu verändern hatte ich bisher nicht. Das Attribut "Farbe" eines Stiftes gehört für mich auch zu seiner Identität, und der rote und der blaue Stift sind für mich zwei Objekte, die in meiner Programmlogik auch zu verschiedenen Zwecken verwendet werden.
- Eine einfachere Bitmap-Lade-Funktion erhöht die Bequemlichkeit. Dass das Laden vom Bitmaps in eine leichter zu benutzende Hülle eingepackt werden sollte, wenn das Laden eines Bitmaps eine häufige Operation ist, sehe ich ein. Den Kritikpunkt "Mangelnde Implementierung des Objektcharakters" sehe ich da nicht. Das Fehlen einer solchen Funktion ist eine Lücke, die jeder, der diese Operation braucht, selbst schliessen muss.
- Für das Fenster gilt für mich das gleiche wie für den Stift: Der "Stil" des Fensters ist Teil seiner Identität. Ein praktisches Beispiel, bei dem "Stil" eines Fensters während dessen Lebensdauer geändert werden sollte (in einem Anwendungsprogramm, nicht in einem Resourceneditor) würde mich interessieren.
Objektcharakter implementieren bedeutet für mich nicht, dass jedes Attribut eines Objekts für den Anwender setzbar ist. Es bedeutet für mich, dass ein Objekt einen Zustand, ein Verhalten und eine Identität hat. Durch die Identität unterscheiden sich auch Objekte mit dem gleichen Verhalten im gleichen Zustand.
Anstattt "Mangelnde Implementation des Objektcharakters" würde ich sagen: Nicht alle Attribute sind auch während der Lebensdauer eines Objekts auf einfache Weise schreibbar. Ob diese Art von Zugriff wünschenswert ist, ist eine andere Frage.
-- kw
Den Wunsch ... hatte ich bisher nicht. Ich schon. Was nun? Ist es in dieser Frage relevant, dass unterschiedliche Entwickler - ist ja kein Wunder - unterschiedliche Bedürfnisse haben? Ist es erforderlich, die Berechtigung von Bedürfnissen nachzuweisen? Und wenn ja, was könnte die Richtschnur sein, nach der die Berechtigung eines Wunsches zu beurteilen wäre? --hl
- Es geht nicht darum, ob der Wunsch berechtigt ist, sondern darum, dass eine für manche Entwickler sinnvolle Operation nicht unterstützt wird. Diesen Mangel bzw. diese Lücke zu "Mangelnde Implemenatation des Objektcharakters" zu machen und damit einen grundlegenden Entwurfsfehler aus der fehlenden Operation zu machen ist das was micht stört. Es ist eben nicht Prinzip eines Objekts, dass alle Attribute nachträglich änderbar oder setzbar sind. Dass zusätzliche prozedurale Schnittstellen für viele Zweck angenehm wären ist eine andere Sache. Wenn der Kritikpunkt heisst: "Zu schmale prozedurale Schnittstelle" dann sollte er nicht mit "Mangelnde Implementation des Objektcharakters" umschrieben werden. -- kw
Unter "Mangelnder Implementierung des Objektcharakters" verstehe ich, wenn zwar die Änderung einer Objekteigenschaft möglich ist, dies aber in einer verdeckten Form passiert, z.B. beim Setzen der Fensterprozedur
| void WindowSetProcedure(HWND hwnd,...proc)
{
SetWindowLong(hwnd,GWL_WNDPROC,(LPARAM)(WNDPROC)proc);
} |
|
|
Es geht mir nicht nur darum, ob etwas geht oder nicht, sondern darum wie die Funktionalität angeboten wird.
Die Frage, was Objektcharacter ist, habe ich versucht, auf der Seite ObjektOrientiertesDenken anzudiskutieren. Meiner Meinung ist die abfrag- und änderbare Objekteigenschaft der Normalfall, Einschränkungen bedürfen einer technischen Rechtfertigung. -- hl
...Bitmap-Ladefunktion... Es ist in höchstem Maße ärgerlich, dass eine Funktionalität die vorhanden ist (um Bitmaps aus dem Resourcenfile zu laden), nicht in hinlänglich allgemeiner Form zur Verfügung gestellt wird, um damit auch direkt Bildfiles zu lesen. Diese Funktion zu ergänzen heißt redundanten Code zu erzeugen. Man könnte es vergleichen, wie wenn in C zwar printf/fprintf vorhanden wäre, aber sprintf fehlen würde.
...nicht...auf einfache Weise...wünschenswert? Nur um es noch einmal festzuhalten: fast alle Window-Eigenschaften sind änderbar. Manchmal bedarf es der Hartnäckigkeit, manchmal auch detektivischer Fähigkeiten. In der Kompliziertheit der notwendigen Vorgangsweise vermag ich keinen Vorteil zu erblicken. Entweder lasse ich etwas zu, oder nicht, das ist eine Entscheidung die Sinn macht. Etwas auf komplizierte Weise zuzulassen ist ein denkbares Modell in einer ambivalenten Bürokratie, aber nicht in der SoftwareEntwicklung. -- hl
- Wenn etwas auf irgendeine undokumentierte Weise geht, dann muss es nicht unbedingt in Folgeversionen weiter unterstützt werden. Wenn es für eine Operation eine definierte Schnittstelle gibt, dann hat eine Nutzer dieser Schnittstelle ein Recht, die weitere Unterstützung dieser Schnittstelle in zukünftigen Versionen zu erwarten. Bist Du sicher, dass diese hartnäckig und unter Anwendung detektivischer Fähigkeiten erschlossenen "undokumentierten Schnittstellen" Bestandteil des Windows-API sind? -- kw
- Ich spreche nicht von undokumentierten Schnittstellen, sondern nur von dokumentierten Funktionen des offiziellen Win32 API. Trotzdem gibt es Funktionen wie DestroyWindow(hwnd), die einfach zu handhaben sind und Funktionen wie SetWindowLong(), deren potentielle Einsatzmöglichkeiten sich erst "detektivisch" erschließen. -- hl
- Das Setzen der Fensterfunktion mit SetWindowLong ist nichts, was als zwischen verschiedenen Windows-Versionen portable Lösung für diese Operation angeboten wird. Bei SubclassWindow aus windowsx.h wäre es dagegen das Problem von Microsoft, sich eine neue Lösung auszudenken, wenn dass Setzen der Fensterfunktion in einer zukünftigen Windowsversion nicht mehr auf diese Weise funktionieren sollte. Beim Übergang von einer Windowsversion zur nächsten wurden solche Eingriffe in die WINDOW-Datenstruktur ja schon gelegenlich geändert.
- SetWindowLong, SetWindowWord, SetClassLong und SetClassWord und die entsprechenden Get-Funktionen sind meiner Meinung nach wirklich Entwurfsfehler. Wenn die Notwendigkeit für ein Anwendungsprogramm besteht, auf die darüber zugänglich gemachten Fenstereigenschaften lesend oder schreibend zuzugreifen, dann sollte das über API-Funktionen, nicht über Makros in windowsx.h oder über einen Offset zu einem nur intern bekannten Zeiger geschehen. Dieser Aspekt des Windows-API ist wohl eine Bestätigung für die Regel, dass schlechte Provisorien sehr langlebig sein können. -- kw
...macro SubclassWindow... Hier beginnen sich nun die Qualitätsprobleme aufzuschaukeln. Sicher wäre dieses Macro an sich ein Schritt in die richtige Richtung. Aber:
- Es ist vergleichsweise schlecht dokumentiert. Z. B. ist es im Index der API-Referenz nicht enthalten. Es erscheint nicht als würde sich MS zur Dauerhaftigkeit dieses Macros verpflichten.
- Wenn, dann müsste dieses Macro auch wie eine Funktion behandelt und am besten in der Funktionsreferenz dokumentiert werden.
- Es tut nicht, was der Name sagt. Wenn der Programmierer ein Subclassing erreichen will, muss er wesentlich mehr tun, als nur dieses Macro zu verwenden.
- Es ist unsinnig, diese Funktionalität als Macro zu implementieren. Dafür spricht nur die Vermeidung einer zusätzlichen Aufrufsebene, dies spielt aber bei einer Funktion, die normalerweise maximal einmal pro Window aufgerufen wird, keine Rolle.
- Zusätzlich fällt bei allen Spekulation über Versionskompatibilitäten auf, dass MS keinen Mechanismus installiert hat (wie Java "depricated ..."), eine Modernisierung geordnet vorzunehmen.
Vermutlich sind damit noch nicht einmal alle Aspekte dieses Debakels beleuchtet, aber ich lass das mal so stehen.
Nur für die Perspektive, das obige ist kein zentraler, eher nur ein zufällig herausgegriffener Kritikpunkt, wie es vielleicht noch 200-1000 andere im Windows-API geben mag. Typisch ist aber - egal wohin man schaut - die Schludrigkeit und das mangelnde Qualitätsbewusstsein in Implementierung und Dokumentation. --hl
KategorieDiskussion
StartSeite | Neues | TestSeite | ForumSeite | Teilnehmer | Kategorien | Index | Hilfe | Einstellungen | Ändern
Text dieser Seite ändern (zuletzt geändert: 28. Mai 2003 15:28 (diff))