Dialog-Fenster öffnen.

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Sophus hat geschrieben:Wo in welchem Abschnitt wüsste ich jetzt natürlich nicht :-)
Da Du VB6 kannst, schreibt das doch kurz angedeutet mal hin :-) Mir geht es nämlich wirklich um die logische Stelle innerhalb des großen Ganzen.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Auch in VB6 würde ich erstmal die Form erstellen, Textboxen, Labels und Buttons entsprechend platzieren. Bin ich mit dem Layout zufrieden, springe ich über einen Reiter in den Quellcode. Wenn du dich mal mit DreamWeaver auseinandergesetzt hast, dann weißt du was ich mit dem "springen" meine. Da kann man ja zwischen Web-Ansicht und Quellcode beliebig hin und her springen.

Im Code-Teil würde ich dafür keine Klasse oder gar kein Modul ansetzen. So umfangreich ist ein BMI-Rechner ja auch wieder nicht. Ich würde eine Prozedur basteln. Diese Prozedur würde ich durch ein Click-Ereignis eines Buttons abrufen. Vorher würde ich beim Click-Ereignis prüfen, ob die Textboxen leer sind. Wenn nicht, dann Prozedur aufrufen. Das ganze könnte wie folgt aussehen:
Angenommen ich benennen den Button "Cmd_Berechnen"

Code: Alles auswählen

Sub Cmd_Berechnen_Click()
         If Text1.Text ="" Then
                 Msgbox "Bitte geben Sie eine Zahl ein"
         Else 
                 Call BMI_Rechnung
         End If
End Sub

Sub BMI_Rechnung ()
'Hier kommt dann die Formel hin
'Mit dem Zeichen (') gilt es in VB6 als Kommentar
End Sub
Zuletzt geändert von Anonymous am Freitag 25. April 2014, 19:22, insgesamt 1-mal geändert.
Grund: Quelltext in Code-Tags gesetzt.
BlackJack

@Sophus: Und wie kommt das Ergebnis in die GUI, und wie testet man die Funktion ohne das man eine GUI braucht?
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

In VB6 würde es ohne die Oberfläche nicht gehen. Da starte ich meine Anwendung in der IDE, so dass ich mich nun in einer Laufzeit befinde, und würde das Programm anwenden. Ich würde Zahlen eingeben, und schauen wie das Ergebnis aussieht oder ich würde keine Zahlen eingeben, und die Textboxen leer lassen um zu sehen ob die MessageBox greift und mir sagt, ich solle dich bitte eine Zahl eingeben. So würde ich meinen Code testen.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Jetzt siehst du doch gut, warum Logik und GUI nicht vermischt werden sollten. Üblicherweise werden automatisierte Tests geschrieben, ohne dass ein Benutzer etwas über die GUI eingeben muss. Damit lässt sich nach Änderungen ganz automatisch testen, ob das Programm noch so wie gewübscht läuft. Bzw. so läuft, wie man es mit Tests abgedeckt hat. Normalerweise müssen dutzende Randfälle und diverse normale Szenarios durchgespielt werden. Bei der BMI-Formel könnte man bereits bekannte Werte gegen die Berechnungen testen. Und du möchtest sicher nicht bei jeder Änderung 10 oder mehr Werte in eine GUI eingeben. Wenn du die Logik von der GUI trennst, dann musst du das auch gar nicht. Das ist dann nur noch eine Schleife welche Werte in die Funktion einsetzt und die Ergebnisse mit den Resultaten vergleicht. Wenn du das nicht von umsetzen kannst, dann solltest du (nocht) die Finger von GUIs lassen.
Das Leben ist wie ein Tennisball.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Ehrlich gesagt sehe ich nichts. Mir fehlt wohl der Schritt in die richtige Richtung. Ich verstehe immer noch nicht, wieso beides, Logik und GUI voneinander getrennt werden soll. Was ist an meinem Beispiel denn "verkehrt"? Mal abgesehen davon, dass ich jedesmal mein Programm bei jeder Änderung in die Laufzeit bringe und ständig Werte über die Oberfläche in die Textboxen gebe um zu sehen ob die Ergebnisse richtig seien oder ob sich mein Programm richtig verhält etc.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

EyDu hat es doch schon beschrieben: Man will ja eben nicht für jede Änderung in die GUI und dort zig Sachen eingeben. So etwas erledigt man mit Unit Tests (oder ggf. auch Integration Tests, die man auch gerne *ohne* Gui ausführen will).

Außerdem überlege mal, wie Du die BMI-Rechner Logik als Dienst einrichten kannst; z.B. willst Du die Logik für einen Webservice nutzen. Dazu braucht es keine GUI - die Einbindung der Logik geschieht dabei über irgend eine Webtechnologie. Aber man will die Logik ja deswegen nicht neu schreiben, sondern das etablierte und getestete bereits Vorhandene nutzen.

Oder Du willst - wieso auch immer - von PyQt mal auf Gtk wechseln (also Austausch der GUI-Frameworks). Auch dann ist es doch toll, wenn Du die Logik mitnehmen kannst.

Im übrigen funktionieren viele viele Anwendungen genau so. Die Webkit-Engine bspw. wird in vielen verschiedenen Browsern, die unterschiedlichste GUI-Toolkits einsetzen, benutzt. Wäre die Engine stark an *eine* konkrete GUI gekoppelt, so könnten andere Projekte diese nicht nutzen.

Linux z.B. bietet ein noch globaleres Beispiel: Ex gibt zig verschiedene Desktops für Linux-Systeme - diese nutzen natürlich Funktionen des Kernels, haben aber sonst nichts gemeinsam. Auch das geht nur, weil der Kernel selber absolut keine Kopplung an eine bestimmte (in diesem Falle so gar gar keine!) GUI hat.

Du kannst dafür auch Beispiele aus dem Leben aufgreifen; ein Blu-Ray Player kann so ziemlich an jedem TV-Gerät betrieben werden, solange es einen passenden Stecker gibt. Wäre doch doof, wenn der Player mit der Bildschirmkomponente dermaßen stark gekoppelt wäre, dass man Player X nur mit Gerät X zusammen betreiben kann.

Diese Flexibilität erreicht man nur, wenn man die Logik eben von der GUI entkoppelt, idealer Weise in zwei physisch getrennte Module (Bibliotheken oder wie man solche Einheiten sonst noch so nennt).

Aber um es noch einmal zu betonen: Auch wenn Du nicht planst oder es wirklich niemals dazu kommt, dass Du das ganze ohne diese eine bestimmte GUI betreiben willst, lohnt sich die Trennung eben doch. Alleine wegen der Testbarkeit und des besser strukturierten Codes (Man weiß besser, *wo* man im Gesamtprojekt was finden kann).

Dein Ansatz die Berechnung in eine Prozedur auszulagern, geht ja prinzipiell schon in die richtige Richtung. Veiel Anfänger würden den Berechnungscode direkt in einen Event-Handler schreiben...
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@Sophus: Abgesehen davon ist es nicht verkehrt, aber *genau das* ist halt verkehrt. Man kann dafür keine Testfälle schreiben, man kann die Berechnung nicht ohne GUI ausprobieren, und wiederverwenden kann man die Programmlogik auch nicht. Das mag Dir bei einer Programmlogik die aus einem Einzeiler besteht nicht wichtig erscheinen, aber normale Programme sind ja sehr selten so simpel.

Die übliche Vorgehensweise ist es erst die Programmlogik zu schreiben und zu testen, und danach eine GUI drauf zu setzen. Man kann sich ein GUI-Mockup erstellen um ein Gefühl dafür zu bekommen was die Programmlogik an Operationen anbieten muss, aber die GUI erstellen und dann von dort aus ”in die Tiefe” zu programmieren führt leichter zur Vermischung von GUI und Logik. Ausserdem hat man man beim Top-Down-Ansatz immer das Problem das man nicht auf getesteten Bausteinen aufbauen kann, sondern alles irgendwie parallel und kreuz und quer entwickelt.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Ich denke, jetzt verstehe ich euch, weshalb ich euch nicht verstanden habe. Klingt sehr philosophisch? :-) Nein, in VB6 oder generell in VB braucht man nicht zwangsläufig so stark getrennt betrachtet werden, denn in VB6 kann man nur Windows-Anwendungen schreiben. Niemals wird meine Anwendung ohne Weiteres unter Linux laufen. Auch ist es unmöglich, die Logik die ich in VB6 erstellt habe (nehmen wir mal den BMI-Rechner) kann ich niemals 1:1 in Python übernehmen. Also bin ich so oder so gezwungen wieder neu zu codieren. Sprich, ich muss die Formel, die ich in VB6 erstellt habe in ihrer Grundstruktur beibehalten, jedoch in Python gänzlich neu schreiben. Des Weiteren musste ich keine eigenen Test schreiben, schließlich schreibe ich nur eine Datenbank-Anwendung. Ich arbeite mich da eher sehr klein hoch. Ich versuche also erstmal nur eine kleine Information aus einem Textbox/LineEdit in die Datenbank zu hinterlegen. Wenn ich an einer TextBox erfolg habe, dann nehme ich das Schema, und wende es auf all die anderen Textboxen, die bestimmte Informationen in die Datenbank hinterlegen sollen. Genauso verhält es sich mit Edit und Delete, und später dann mit der Suche und den Abfragen.

Edit: Oder meint ihr die ganze Zeit den Debugger? Also diesen habe ich in VB6 integriert. Da wird mein Quellcode einmal gründlich untersucht, bevor das Programm in seine Laufzeit versetzt wird. Genauso wenn ich gleich direkt eine EXE-Datei erstellen will, wir geschaut, ob im Programmcode ein Fehler in der Logik ist, sprich ob da was nicht zusammenpasst. Und diese stellen werden dann bei uns gelb angezeigt, und die IDE untersagt dann die Laufzeit solange bis keine Fehlermeldungen mehr kommen. Ansonsten bin ich ratlos was ihr meint.
BlackJack

@Sophus: Ich glaube so richtig ist es immer noch nicht angekommen. Es geht nicht darum das auf ein anderes Betriebssystem zu portieren oder gar eine andere Programmiersprache. Es geht darum automatisiert testen zu können, interaktiv in einer Python-Shell Sachen ausprobieren zu können, die Programmlogik auf verschiedene Arten nutzen zu können. Bei so trivialen Sachen wie dem BMI ist der Wert davon vielleicht nicht so leicht einzusehen, und vielleicht hast Du ja auch noch nie etwas nicht-triviales Programmiert, wo man davon profitieren kann. Letztlich schränkt einen VB genau an der Stelle ja auch ein, so dass man zu dem Punkt auch gar nicht kommen kann.

Um mal beim BMI zu bleiben: man muss ja nicht gleich ein komplett anderes GUI-Toolkit verwenden. Vielleicht möchte man die gleiche Logik ja nicht nur verwenden um den aktuellen Wert zu berechnen, sondern auch eine Grafik erstellen bei der der BMI für die gleiche Körpergrösse und verschiedene Massen dargestellt wird, zum Beispiel im Bereich von Unter- bis Übergewicht, damit der Benutzer nicht nur seinen akuellen Wert sieht, sondern auch eine Grafik wo er leicht ablesen kann wo er in dem Spektrum von Möglichkeiten steht und wieviel ihn von einer ”gefährlichen” Grenze noch trennt. Wenn die Berechnungslogik mit den Eingabe- und Anzeigewidgets verwoben ist, kann man das nicht mehr so einfach realisieren.

Mal nebenbei ganz praktisch wie der Quelltext für so einen einfachen BMI-Rechner nach der Mockup-Zeichnung aussehen kann:

Code: Alles auswählen

#!/usr/bin/env python
import sys
from PyQt4 import uic
from PyQt4.QtGui import QApplication


def calculate_bmi(height, weight):
    return weight / height**2


class BMICalculator(object):
    def __init__(self):
        self.ui = uic.loadUi('bmi.ui')
        self.ui.close_button.clicked.connect(self.ui.close)
        self.ui.calculate_button.clicked.connect(self.on_calculate)
        self.ui.show()

    def on_calculate(self):
        size = self.ui.height_input.value()
        weight = self.ui.weight_input.value()
        try:
            result = str(calculate_bmi(size, weight))
        except ZeroDivisionError:
            result = ''
        self.ui.bmi_output.setText(result)
        

def main():
    application = QApplication(sys.argv)
    bmi_calculator = BMICalculator()
    sys.exit(application.exec_())


if __name__ == '__main__':
    main()
Für die im Qt Designer erstelle GUI habe ich keinen Quelltext generiert sondern mittels `PyQt4.uic`-Modul direkt die Designer-Datei geladen. Damit spart man sich den Zwischenschritt Quelltext zu generieren und eine Datei. Denn in dem generierten Quelltext editiert man sowieso nicht, der Quelltext würde dadurch also nicht einfacher oder weniger.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Und genau das findet man in VB selten. Meisten werden Prozeduren in einer Form/in einem Dialog geschrieben. VB hat mehr so die Plug and Play Funktion. Angenommen, ich habe eine Form gebastelt, dann klicke ich doppelt auf die graue Form, und dann lande ich im Quelltext. Nun schreibe ich quasi in dieser Form, und dies gilt dann auch für diese Form. Angenommen, ich will dass auf der Form ein Button bei einem bestimmten Verhalten eines Anwender deaktiviert wird, dann schreibe ich das auch in dieser Form. Man kann auch OOP in VB6 verwenden, aber nur dann, wenn man etwas "verallgemeinern" will und es nicht mehr nur auf einer Form beschränken will. Beispiel, wenn man will, dass die Form oder die Dialoge nicht mehr so eckig sind wie Windows-Fenster, sondern dass die Dialoge einen Kreis bilden soll. Und angenommen ich habe in meinem Projekt 10 Formen, dann schreibe ich eine Klasse, die es möglich macht, dass alle 10 Formen/Dialoge einen Kreis bilden. Aber ansonsten schreibt man sehr häufig in die Form.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Sophus hat geschrieben:Und genau das findet man in VB selten.
Und genau das ist das Problem, welches ich zu Beginn angeprangert habe ;-)

Um mal BlackJacks Quellcode zu ergänzen, habe ich mal zwei Unit Tests mit pytest dafür geschrieben:

Code: Alles auswählen

#!/usr/bin/env python

import pytest

def test_calculate_bmi_with_valid_values_returns_bmi():
    expected = 23.37
    result = calculate_bmi(1.85, 80)
    assert abs(result - expected) < 0.01

def test_calculate_bmi_with_zero_height_raises_exception():
    with pytest.raises(ZeroDivisionError):
        calculate_bmi(0, 1)
Ausgabe:

Code: Alles auswählen

nelson@vitory ~/Source/Python/Snipptes/Forum/BMI % py.test -v bmi.py
======================== test session starts =======================
platform linux -- Python 3.4.0 -- py-1.4.20 -- pytest-2.5.2 -- /usr/bin/python
collected 2 items 

bmi.py:10: test_calculate_bmi_with_valid_values_returns_bmi PASSED
bmi.py:15: test_calculate_bmi_with_zero_height_raises_exception PASSED

====================== 2 passed in 0.01 seconds ===================
Ich kann nun an der Formel Änderungen vornehmen und merke sofort, wenn sich dadurch das Verhalten ändert. Dazu brauche ich dann eben nicht in der GUI selber die beiden Fälle eingeben und testen.

Bei komplexen Problemen ist das um so wertvoller. Zumal man diese Tests sehr leicht in einen automatischen Build-Prozess einbauen kann.

Natürlich ist das BMI Beispiel hier nicht mehr wirklich brauchbar, weil es eben derart simpel ist!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Muss ich denn jedesmal, bei jedem anderen Projekt einen automatisierten Test schreiben? Das hieße ja für mich doppelte Arbeit. Erst schreibe ich mein Programm, und dann einen Test. Und je umfangreicher das Programm wird, desto umfangreicher die automatisierte Tests, die ich dann schreiben muss. Und was mich auch interessiert. Wie verbindet man sein Programm und die GUI? Bleiben wir mal beim BMI. Ich muss ja die Buttons und TextBoxen mit meinem Quellcode verbinden. Denn wenn ein Anwender in der LineEdit eine Zahl reinschreibt, so muss diese Zahl irgendwie vom Quellcode angenommen werden. Also bindet man die GUI wieder mit dem Quellcode?
BlackJack

@Sophus: Du *musst* natürlich keine Unit-Tests schreiben, aber bei Programmen die etwas umfangreicher werden *will* man das. Die Arbeit die Funktionen und Klassen zu testen hat man doch sowieso, also kann man das auch wiederholbar gestalten. Beim „test driven development” schreibt man sogar *erst* den Test, stellt sicher das der fehl schlägt, und schreibt dann den Code.

Wie man die GUI mit dem Code verbindet, habe ich doch in meinem letzten Beitrag gezeigt. Das ist ein lauffähiges Programm. Hier ist die ``bmi.ui`` dazu:

Code: Alles auswählen

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainDialog</class>
 <widget class="QDialog" name="MainDialog">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>210</width>
    <height>129</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>BMI Calculator</string>
  </property>
  <layout class="QVBoxLayout" name="verticalLayout">
   <item>
    <widget class="QWidget" name="widget" native="true">
     <layout class="QFormLayout" name="formLayout_2">
      <property name="fieldGrowthPolicy">
       <enum>QFormLayout::ExpandingFieldsGrow</enum>
      </property>
      <item row="0" column="0">
       <widget class="QLabel" name="height_label">
        <property name="text">
         <string>Height</string>
        </property>
       </widget>
      </item>
      <item row="0" column="1">
       <widget class="QDoubleSpinBox" name="height_input">
        <property name="buttonSymbols">
         <enum>QAbstractSpinBox::NoButtons</enum>
        </property>
        <property name="suffix">
         <string>m</string>
        </property>
        <property name="decimals">
         <number>2</number>
        </property>
        <property name="maximum">
         <double>999.990000000000009</double>
        </property>
        <property name="singleStep">
         <double>0.010000000000000</double>
        </property>
       </widget>
      </item>
      <item row="1" column="0">
       <widget class="QLabel" name="weight_label">
        <property name="text">
         <string>Weight</string>
        </property>
       </widget>
      </item>
      <item row="2" column="0">
       <widget class="QLabel" name="bmi_label">
        <property name="text">
         <string>BMI</string>
        </property>
       </widget>
      </item>
      <item row="2" column="1">
       <widget class="QLineEdit" name="bmi_output">
        <property name="readOnly">
         <bool>true</bool>
        </property>
       </widget>
      </item>
      <item row="1" column="1">
       <widget class="QDoubleSpinBox" name="weight_input">
        <property name="buttonSymbols">
         <enum>QAbstractSpinBox::NoButtons</enum>
        </property>
        <property name="specialValueText">
         <string/>
        </property>
        <property name="suffix">
         <string>kg</string>
        </property>
        <property name="decimals">
         <number>1</number>
        </property>
       </widget>
      </item>
     </layout>
    </widget>
   </item>
   <item>
    <widget class="QWidget" name="widget_2" native="true">
     <layout class="QHBoxLayout" name="horizontalLayout">
      <item>
       <spacer name="horizontalSpacer">
        <property name="orientation">
         <enum>Qt::Horizontal</enum>
        </property>
        <property name="sizeHint" stdset="0">
         <size>
          <width>40</width>
          <height>20</height>
         </size>
        </property>
       </spacer>
      </item>
      <item>
       <widget class="QPushButton" name="calculate_button">
        <property name="text">
         <string>Calculate</string>
        </property>
       </widget>
      </item>
      <item>
       <widget class="QPushButton" name="close_button">
        <property name="text">
         <string>Close</string>
        </property>
       </widget>
      </item>
     </layout>
    </widget>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Sophus hat geschrieben:Muss ich denn jedesmal, bei jedem anderen Projekt einen automatisierten Test schreiben?
Man muss gar nichts - aber man sollte! Unit Tests haben sich in vielen vielen Projekten bewährt. Schau Dir mal erfolgreiche Open Source Projekte an und Du wirst sehen, dass die aller meisten davon Unit Tests (und ggf. andere automatisierte Tests) besitzen. Hier mal am Beispiel Bottle aufgezeigt (ein beliebtes "Micro"-Webframework). Ohne es zu geprüft zu haben, würde ich sagen, dass dort deutlich mehr Zeilen Code für die Tests existieren als für den eigentlichen Code.
Sophus hat geschrieben: Das hieße ja für mich doppelte Arbeit. Erst schreibe ich mein Programm, und dann einen Test.
Man kann auch umgekehrt vorgehen und erst den Test und dann den Code schreiben. Diesen Ansatz nennt man dann Test Driven Development.
Sophus hat geschrieben: Und je umfangreicher das Programm wird, desto umfangreicher die automatisierte Tests, die ich dann schreiben muss.
Letztlich ja. Aber der Vorteil ist, dass Du schnell Feedback bekommst, wenn Du etwas an einer Stelle durch eine Änderung an einer vollkommen anderen Stelle "kaputt" gemacht hast. Das ist bereits bei vermeintlich kleinen Projekten ein enormer Vorteil. Lies Dir doch mal etwas dazu durch :-)
Sophus hat geschrieben: Und was mich auch interessiert. Wie verbindet man sein Programm und die GUI?
Das hat doch BlackJack in seinem Beispiel gezeigt. Du musst einfach in dem Programmteil, der beim Auslösen eines Events aufgerufen wird, einen Aufruf absetzen, der die gewünschte Funktionalität aus Deiner Logik- (auch Domänen-)Schicht aufruft.

Im Beispiel von BlackJack passiert das in ``on_calculate``.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Hellstorm
User
Beiträge: 231
Registriert: Samstag 22. Juni 2013, 15:01

Ich habe mich übrigens damals mit vielleicht 13 Jahren oder so auch mit VB6 befasst, weil es eben so schön einfach war. Ein bisschen was zusammenschieben, per Doppelklick in den Code springen und wenn man dann im fertigen Programm auf einen Knopf drückt, passiert was. Ging alles super einfach.

Ja, gut, aber was war das Problem? Ich habe nicht verstanden, was ich da überhaupt mache. Wusste ich was Objekte sind? Nein. Habe ich versucht das Programm anständig zu strukturieren? Nein. Das mag sicherlich auch an meinem Alter gelegen haben, und auch daran, dass ich mir gar kein anständiges Buch geholt habe, aber wirklich schön war das nicht.

Jetzt bei meinem erneuten Anlauf auf die Programmierung habe ich das etwas sorgfältiger angehen lassen. Erst einmal habe ich ein bisschen Konsolenprogramme geschrieben, aber doch recht schnell gemerkt, dass ich doch irgendwie was mit GUI machen will (ist halt einfach interessanter). Aber da habe ich zumindest schon die Grundlagen alle grob durchgehabt, und auch vor allem erst einmal einfache Qt-Programme ohne den Designer erstellt. Dann war das Dialogfeld halt entweder ganz einfach, oder der Quelltext war für komplexere Dialoge unglaublich unübersichtlich, aber ich habe erst einmal richtig gelernt, was das mit den ganzen Objekten überhaupt soll.

Zwischendurch habe ich dann gemerkt, dass es doch etwas zu unübersichtlich wird, alles im Quelltext zu verwalten, und bin dann deswegen wieder auf den Designer umgestiegen. Aber die grundlegenden Sachen habe ich erstmal geübt.

Also man sollte zumindest einmal grob ein Tutorial durchgearbeitet haben. Nachher die Sachen verfestigen kann man meinetwegen schon mit einer GUI, weil das halt einfach interessanter ist. Was bringen einem Konsolenanwendungen, wenn man für sich selber keinen Einsatzweck hat und dann überhaupt nicht programmieren würde?
Benutzeravatar
Madmartigan
User
Beiträge: 200
Registriert: Donnerstag 18. Juli 2013, 07:59
Wohnort: Berlin

Hellstorm hat geschrieben:Was bringen einem Konsolenanwendungen, wenn man für sich selber keinen Einsatzweck hat und dann überhaupt nicht programmieren würde?
Das ist schnell beantwortet: Jede Anwendung, die ein GUI zur Laufzeit zwingend erfordert, ist "schlecht" geschrieben. In der Trennung von Logik und GUI liegt doch gerade der Sinn. Wenn deine Anwendung diesem Muster folgt, kannst du hinterher ohne Probleme die GUI anpassen bzw. sogar komplett austauschen.

Paradebeispiel Autodesk Maya: Kann im commandline Modus komplett ohne GUI verwendet werden. Sicher ist das für uns stark visuell geprägte Lebewesen unkomfortabel, rein vom Code und seinem Aufbau her aber die wünschenswerte Variante.

Ich habe für unsere Grafiker auch sehr content-lastige Tools geschrieben, da sich aber vieles ähnelt konnte ich viel Code teilen. Wenn das mit den einzelnen GUIs vermischt wäre, könnten wir das Code-Sharing vergessen.
Hellstorm
User
Beiträge: 231
Registriert: Samstag 22. Juni 2013, 15:01

Madmartigan hat geschrieben:
Hellstorm hat geschrieben:Was bringen einem Konsolenanwendungen, wenn man für sich selber keinen Einsatzweck hat und dann überhaupt nicht programmieren würde?
Das ist schnell beantwortet: Jede Anwendung, die ein GUI zur Laufzeit zwingend erfordert, ist "schlecht" geschrieben. In der Trennung von Logik und GUI liegt doch gerade der Sinn. Wenn deine Anwendung diesem Muster folgt, kannst du hinterher ohne Probleme die GUI anpassen bzw. sogar komplett austauschen.
Naja, aber vielleicht möchte man ja gerade GUI-Anwendungen schreiben, um etwas irgendwie grafisch einfach zugänglich zu haben.

Konsolenanwendungen haben doch gerade das Problem, dass sie recht benutzerunfreundlich sind (Nein, erst mit --help alle möglichen Optionen nachschlagen und dann gucken, wie das zu kombinieren ist, ist nicht komfortabel). Wenn man jetzt, insbesondere unter Linux, gerne ein Skript schreiben möchte, was irgendwelche Kommandozeilenprogramme einfach zugänglich macht, dann braucht man dafür doch zwingend eine GUI. Curses usw. ist ja auch nichts anderes als eine GUI, da kann man auch gleich Qt o.ä. verwenden.

Klar ist es sinnvoll, irgendwie ein spektakulär neues Programm auch auf Konsolenebene zu erstellen. Aber macht das der Anfänger? Ich würde sagen, wenn man als Anfänger ein für sich störendes Problem lösen muss, welches wahrscheinlich irgendwie mit der täglichen Arbeit zusammenhängt, dann ist eine GUI nicht verkehrt. Letzten Endes muss der Benutzer die doch selber benutzen.


Als Beispiel: Ich würde mir z.B. gerne einen Tastaturlayouteditor für Linux schreiben (so wie der Keyboard Layout Editor von MS). Das muss ich doch zwangsweise als GUI machen, eben weil das eine Anwendung ist, die etwas vereinfacht. Dass im Programm selber die Logik von der Darstellung getrennt werden sollte ist ja wieder eine andere Sache, das kann man ja auch machen.
BlackJack

@Hellstorm: Dafür kann man in der Konsole häufiger gebrauchte Programme, nach dem man die richtigen Optionen zusammengestellt hat, ganz einfach aus der History wiederholen und erneut ausführen oder vorher die Werte anpassen. Das ist dann bei häufiger gebrauchten Sachen deutlich schneller als wenn man erst eine GUI startet und da jedes mal aufs Neue die Datenfelder ausfüllt. Und man kann die verschiedensten Werkzeuge kombinieren und automatisieren. Was bei GUI-Anwendungen schlechter bis unmöglich ist. Benutzerfreundlich kommt anscheinend auch auf den Benutzer an.

Text-UIs lassen sich auch nicht so leicht durch GUIs ersetzen wenn man die Programme über ein Terminal auf anderen Rechnern ausführt.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Es geht nicht darum, dass die ganze Anwendung zunächst als Konsolenanwendung geschrieben wird, um sie dann später auf eine GUI zu portieren. Das Programm muss jedoch so entworfen sein, dass dies Prinzipiell möglich ist, ohne dass irgendwo im Programm Code verändert werden müsste. Für Anfänger bietet es sich daher an, genau die Zweiteilung einmal zu machen.

Es wurde doch jetzt schon mehrfach gesagt: Wenn das Programm zwingend eine GUI benötigt, wie willst du es dann vernünftig mit (Unit-)Tests abdecken? Testen per Hand ist, ab einer gewissen Komplexität, welche bereits sehr schnell einsetzt, überhaupt keine Option. Es mag natürlich sein, dass du keine Tests schreibst, aber dann machst du etwas Grundsätzliches falsch. Bei Python ist, da Module zu jeder Zeit und von beliebigen Bedingungen abhängig importiert werden können, noch nicht einmal die syntaktische Korrektheit garantiert.

Die Abhängigkeit von einer GUI vereinfach die Entwicklung also gerade nicht. Man kann sich nicht (halbwegs) sicher sein, dass alle Codeteile mal durchlaufen werden und Änderunge am Code zumindest das Verhalten der vorhandenen Tests abdecken. Im Endeffekt führt das ganze dazu, dass die selben Fehler immer und immer wieder gemacht werden und dass mehr Zeit mit Fehlersuche verbracht wird als notwendig.
Das Leben ist wie ein Tennisball.
Antworten