Johnny B.: wie organisiert ihr euren Quellcode?

Hallo geehrtes Forum,

mich interessiert mal eine allgemeine Frage zum Programmieren. Mir ist aufgefallen, daß ich einen nicht unerheblichen Teil meiner Zeit beim Programmieren damit verbringe, im Editor ineffektiv hin- und herzuscrollen.

Meine Scripte haben einen grundsätzlich grob gleichen Aufbau:
1. Module laden
2. Initialisieren der Variablen, etc.
3. 'Start'-Teil mit Verzweigungen anhand der übergebenen Parameter
   (möglichst kurz)
4. Subroutinen, die abarbeiten, was getan werden soll

Das Buch "Perl Best Practices" hat mir schon sehr geholfen, aus meinem früheren Kauderwelsch lesbare, übersichtlich formatierte und ausreichend kommentierte Programme zu machen. Über den grundsätzlichen Aufbau eines Scripts wird dort allerdings nicht viel gesagt. Wenn ich mir Modul-Quellcodes anschaue, sind die meistens im OO-Stil programmiert. Das würde ich zwar auch gerne können, aber noch schnall ich das nicht wirklich.

Aber unabhängig davon sind in den OO-Quellcodes auch haufenweise Subs. Egal wie man programmiert, ich vermute jeder hat dieselben Herausforderungen, sich und seinen Code zu organisieren - hin- und herscrollend auf der Suche nach der Stelle, die nun gerade für das zuständig ist, was geändert werden soll.

Daher mal frisch in die Runde gefragt: wie macht ihr das? Gibt es Lösungen, die einem das Leben leichter machen können?

Bin schon ganz gespannt auf die Antworten...
Besten Gruß
JOhnnY

  1. moin,

    der Aufbau ist bei mir auch so, ganz oben die Erforderlichkeiten, dann ein paar etwaige globale Varablen, dann die Kontrollstruktur und dann die subs.

    Aber unabhängig davon sind in den OO-Quellcodes auch haufenweise Subs. Egal wie man programmiert, ich vermute jeder hat dieselben Herausforderungen, sich und seinen Code zu organisieren - hin- und herscrollend auf der Suche nach der Stelle, die nun gerade für das zuständig ist, was geändert werden soll.

    Ein pratischer Editor bietet die Möglichkeit, Textmarken zu setzen, da bist Du mit einem Griff in die Tastatur schnell zur Stelle. Es gibt nunmal auch Scripts mit einigen tausend Zeilen und Code in Module auszulagern lohnt sich nicht immer. Das Auslagern lohnt sich auf jeden Fall, wenn:

    eine Funktion mindestens in zwei verschiedenen anderen Scripts gebraucht wird,
      globale Variablen in mehreren Scripts gebraucht werden.

    Zum Auslagern gibt es die Möglichkeit ein Modul zu schreiben oder eine Library. Ersteres beginnt mit package, ein Modul ist die Klasse für OOP. Auch wenn Du ein Modul nur als Sammlung von Subroutinen schreibst, erstellst Du eine Klasse und definierst im ISA-Array wozu die Klasse gehört (ISA: gesprochen als "is a ...").

    Eine reine Funktionssammlung, unabhängig von OOP ist in einer Library besser aufgehoben.

    Schönen Tag euch!
    Horst Haselnuss

  2. Ich denke, es ist an der Zeit für dich, probeweise für ein paar Wochen auf eine IDE umzusatteln. http://padre.perlide.org/screenshots.html Wenn dir das zusagt, ist das der bessere Schritt, als immer wieder fehlenden Merkmalen von Texteditoren hinterherzujagen.

    Meine Scripte haben einen grundsätzlich grob gleichen Aufbau:

    Tausche die Reihenfolge von 3. und 4. aus. Im Archiv gibt's auch die ausschweifende Erklärung dazu, aber ich kann's nicht mehr finden.

    OO-Stil programmiert. Das würde ich zwar auch gerne können, aber noch schnall ich das nicht wirklich.

    Danach sollte der Groschen gefallen sein: http://perl.plover.com/Hello/ Minimale Beispiele sind dem Themenverständnis enorm förderlich.

    Aber unabhängig davon sind in den OO-Quellcodes auch haufenweise Subs.

    Ja, das Schlüsselwort ist das gleiche, aber lasse dich nicht davon täuschen. Bei Perl liegt der Unterschied in der Invokation, dieser ermöglicht die simple Codewiederverwe(?:nd|rt)ung mittels Unterklassen. (Nicht-OO-Module sind in der Hinsicht so schmerzlich… aber über das Thema erzähle ich ein anderes Mal.) Ihn erkennt man typischerweise so:

      
        # Methodeninvokation  
        $object_instance->foo(1,2,3);  
        sub foo { my ($self, @params) = @_;}  
      
        # Funktionsinvokation  
        $package_name::foo(1,2,3);  
        sub foo { my (@params) = @_;}  
    
    

    In beidem Falle ist @params ≡ qw(1 2 3). Achte mal darauf, wenn du das nächste Mal fremde Quellen liest.

    1. Hallo CPAN,

      Ich denke, es ist an der Zeit für dich, probeweise für ein paar Wochen auf eine IDE umzusatteln. http://padre.perlide.org/screenshots.html Wenn dir das zusagt, ist das der bessere Schritt, als immer wieder fehlenden Merkmalen von Texteditoren hinterherzujagen.

      Liest sich sehr spannend. Ich werde mich bei Gelegenheit einarbeiten!

      Grazie!
      JOhnnY

    2. Hallo CPAN,

      Ich denke, es ist an der Zeit für dich, probeweise für ein paar Wochen auf eine IDE umzusatteln. http://padre.perlide.org/screenshots.html Wenn dir das zusagt, ist das der bessere Schritt, als immer wieder fehlenden Merkmalen von Texteditoren hinterherzujagen.

      Sieht wirklich super aus. Die Funktionsübersicht rechts schafft gleich Ordnung, das Highlighting sieht echt prima aus, also ich hätte schon große Lust, damit zu arbeiten. Was mir allerdings schmerzlich fehlt, ist eine FTP-Verzeichnis-Funktion. Ich weiß schon, das soll man eigentlich nicht, aber momentan arbeite ich noch direkt auf dem Server. Die Datenbankanbindung ist mir offline bisher nicht gelungen und zudem bin ich der Einzige, der mit den Scripten arbeitet, insofern kann ich damit noch ganz gut leben. Gibt es solch eine Funktion im Padre irgendwo versteckt? Ich habe nichts finden können und auch Google hat mich nicht schlauer gemacht (als Suchbegriff taugt 'FTP' auch nicht viel).

      Meine Scripte haben einen grundsätzlich grob gleichen Aufbau:
      Tausche die Reihenfolge von 3. und 4. aus. Im Archiv gibt's auch die ausschweifende Erklärung dazu, aber ich kann's nicht mehr finden.

      Wonach soll ich suchen? Diese Erklärung täte mich interessieren.

      Besten Gruß
      JOhnnY

      1. FTP-Verzeichnis-Funktion [...] Gibt es solch eine Funktion im Padre irgendwo versteckt?

        Im Changelog steht, seit Version 0.50 ist FTP dabei. Ich kann keinen Support geben, am besten fragst du die Leute selber: #padre auf dem MagNET, irc://irc.perl.org/padre

        Tausche die Reihenfolge von [Subs] und [sonstigem Gedöns] aus.
        Diese Erklärung täte mich interessieren.

        Grund 1: Wenn du Variablen auf gewisse Art im File-Scope (oberste Ebene) deklarierst, gelten sie für nachfolgende/einschließende† Subs. (Hausaufgabe: programmiere zwei Arten in Beispielprogrammen, die trotz use strict; use warnings FATAL => 'all'; funktionieren.) Das verleitet zum schlechten Programmierstil, Zustand zu verstecken. Richtig stattdessen ist es, Parameter immer explizit zu übergeben sowie Werte immer mit return() zurückzugeben.

        † Experten dürfen sich für den Fall einschließende Sub (»closure«) über diese Regel hinwegsetzen.

        Grund 2: Wenn du zuerst Subs deklarierst und dann erst später im Quellcode namentlich‡ aufrufst, funktioniert das immer garantiert. Der umgekehrte Fall gilt nicht immer. Bei Metaprogrammierung tut sich ein Programmierer leicht in die Situation, wo Perl sinngemäß sagt: "Funktion xyz? Kenn'sch nich." und er schier verzweifeln mag, weil sie doch eindeutig da steht…! (Die meisten Leute fangen dann an, mit BEGIN-Blocks umherzumurksen, wo schon die richtige Platzierung von Subs reichen würde.)

        Aber man muss gar nicht einen Abstecher in diese Gefilde höherer Ordnung machen, um einen stark verwandten Effekt wahrzunehmen, probier mal:

          
        sub foo { die "I'm fooing to death!" }  
        foo;  
        
        

        Und dann vertausche die Zeilen.

        ‡ Experten erkennen, dass dies des Pudels Kern ist.

        Ich habe deinen anderen Thread gelesen. Du musst wirklich OO anfangen; damit vermeidest du die überwiegenden Anzahl der Fälle, globale/geteilte Variablen benutzen zu müssen. Hole dir getrost Rat von Angesicht zu Angesicht: http://perlmongers.de/ http://conferences.yapceurope.org/gpw2010/

        1. Hallo CPAN,

          FTP-Verzeichnis-Funktion [...] Gibt es solch eine Funktion im Padre irgendwo versteckt?
          Im Changelog steht, seit Version 0.50 ist FTP dabei. Ich kann keinen Support geben, am besten fragst du die Leute selber: #padre auf dem MagNET, irc://irc.perl.org/padre

          Ohauerha. Padre ist mir ein paar Mal direkt abgestürzt. Warum auch immer. Nicht gut. Auf der Suche nach Alternativen stolpere ich über Notepad++, dann stoße ich auf einen Vergleich von Notepad++ mit PSPad und in diesem Vergleich lese ich dann, daß PSPad eine Funktion namens "Code Explorer" hat. Diese Funktion zeigt alle Subs an und damit geht für mich die Sonne auf. Genau sowas habe ich mir beim Eröffnen des Threads erhofft: eine Strukturierung, mit deren Hilfe ich in etwas ausladenerem Quellcode schneller die Stelle finde, die ich suche, ohne meine Augen durch permanentes wildes Herumscrollen zu malträtieren. In manchen alten Scripten finde ich mich anhand dieses Schnell-Scroll-Bildes immer noch zurecht. Aber ich konnte mir nicht vorstellen, daß es nicht doch etwas Schlaueres gibt. Schlauer wäre in diesem Fall gewesen, sich mit dem Funktionsumfang von PSPad näher zu beschäftigen. Denn der konnte das die ganze Zeit, ich hab's nur nicht gewußt. <klatsch_an_kopf>

          Richtig stattdessen ist es, Parameter immer explizit zu übergeben sowie Werte immer mit return() zurückzugeben.

          Das war der Grund für das Eröffnens des anderen Threads mit dem Datenbankhandle. So soll man es tun. Zurückgeben brauche ich das Handle aber doch eigentlich nicht?

          sub foo { die "I'm fooing to death!" }
          foo;

          Das sieht auch so schon böse aus: foo();  
          Wie auch immer: ich werde zukünftig 3 und 4 vertauschen. :)  
            
            
          
          > Ich habe deinen anderen Thread gelesen. Du musst wirklich OO anfangen; damit vermeidest du die überwiegenden Anzahl der Fälle, globale/geteilte Variablen benutzen zu müssen. Hole dir getrost Rat von Angesicht zu Angesicht: http://perlmongers.de/ http://conferences.yapceurope.org/gpw2010/  
          
          Danke für den Hinweis.  
            
          Auf meinem Weg zu besserem Programmierstil konnte ich bisher immer kleine Schritte gehen: das erste Mal use strict anwenden war so ein Schritt. Ich dachte bis dato, ich würde das niemals anschalten können, weil mich daraufhin tausende Fehlermeldungen überschwemmten, die ich alle nicht verstand. Ohne use strict war die Welt doch so schön einfach...  
            
          Dann kam das Buch "Perl Best Practices", für mich eine Offenbarung. Vorher lag mein Augenmerk darauf, möglichst kurzen Code zu produzieren, indem ich möglichst abgekürzte Variablennamen wie z.B. $emvorag2ohne, möglichst wenig Leerzeichen und -zeilen und überhaupt möglichst kompakte Anweisungen verwendete, das Ganze natürlich gänzlich unkommentiert. In dem Wust fand ich mich nur leider oftmals selber nicht mehr gut zurecht. In diesem Buch nun wurde mir Schritt für Schritt erklärt, wie man es \_richtig\_ macht. Genial. Genau das hatte ich gesucht.  
            
          Ein weiterer Schritt war die Verwendung von Modulen. Ich hatte immer Probleme damit, Module zu installieren. Darüber hinaus hatte ich aber noch mehr Probleme zu verstehen, wie ich die Module benutzen sollte. Die Beschreibungen im CPAN sind ja oft sehr knapp gehalten und ich hatte damals noch nie eine Referenz auf irgendwas gesetzt oder damit gearbeitet. Aber ohne Referenzen zu kennen versteht man da wirklich nicht mehr viel. Ich habe damals über die immer wiederkehrenden Sprüche über faule Perl-Programmierer, die Module benutzen, nur den Kopf schütteln können: zuerst das Ganze verwirrende Installationsgezeugsel, dann diese superknappen wirren Beschreibungen mit maximal einem kleinen Beispiel und das soll einfacher sein, als die benötigte Funktionalität eben schnell selbst zusammenzuzimmern?  
            
          Dazwischen kamen noch Datenbanken, die ich zuerst auch gemieden habe. Es geht doch auch alles mit kommaseparierten Textdateien, auf die mittels selbstgeschriebenen Lese- und Schreibroutinen zugegriffen wird. Harharhar. Das ist doch viel einfacher als sich in dieses ganze Datenbank-Verwaltungs-Einrichtungs-Neuland einzulernen. Naja, also heute sehe ich das inzwischen auch ein wenig anders - mehr noch stehe ich staunend davor, wie mithilfe von Data::Table, CGI::Formbuilder und SQL::Abstract mit lächerlich geringem Aufwand durchaus komplexe Sachen entstehen.  
            
          Der nächste Schritt wird dann wohl das Meistern von objektorientierter Programmierung sein. Tatsächlich hatte ich es mir für mein aktuelles Projekt bereits fest vorgenommen. Doch andererseits will ich ja auch vorankommen und produktiv sein. Also habe ich es vorerst zurückgestellt. Das Arbeiten mit Modulen und die Verwendung einiger erstaunlich mächtiger mySQL-Befehle waren erstmal Neuland genug.  
            
          Ich habe mir das Buch "Einführung in Perl Objekte, Referenzen und Module" (O'Reilly) schon vor längerem gekauft und gelesen. Der Groschen ist trotzdem noch nicht gefallen. Wenn ich das richtig verstehe, geht auch nur ENTWEDER ODER, also prozedual oder objektorientert programmieren? Ich verspreche mir durch OO eine noch viel stabilere Programmstruktur und einen deutlich besseren Überblick über ein Projekt. Ich glaube, daß sich die einzelnen Elemente durch OO viel besser zusammenführen lassen und sich einige der immer wiederkehrenden Würgarounds für noch eine Ausnahme und noch einen Sonderfall viel besser in die Struktur einbringen lassen.  
            
          Mir scheint jedoch, dies ist kein \_kleiner\_ Schritt. Ich muß dazu komplett umdenken, die Sache ganz anders angehen. Im Endeffekt hat es sicherlich viele Vorteile. Hast du vielleicht noch eine weitere Buchempfehlung für mich? OO für Dummies halt als eine Art Einsteigerbuch?  
            
          Besten Gruß  
          JOhnnY
          
          1. Zurückgeben brauche ich das Handle aber doch eigentlich nicht?

            Richtig, mir ging es nur darum, </archiv/2010/3/t195945/#m1312229> ③ zu vermeiden.

            Wenn ich das richtig verstehe, geht auch nur ENTWEDER ODER, also prozedual oder objektorientert programmieren?

            Im Prinzip ja, aber pauschal nein. Ein gewitzter Programmierer kann ein objektorientertes Interface zur Bequemlichkeit für den Benutzer mit einem prozeduralen umhüllen:

              
            package Zonk;  
              
            sub new { ... return bless ... }  
            sub methode1 { my ($self) = @_; ... kompliziertes zeug }  
              
            sub bequem_und_schnell {  
                my (@param) = @_;  
                return __CLASS__  
                    ->new       # Konstruktor mit Defaults  
                    ->methode1(@param);  
            }  
              
            =head1 SYNOPSIS  
              
                use Zonk;  
                my $z = Zonk->new(dies und das und noch viel mehr);  
                $z->methode1(blah); # flurbelt das Flummox mittels "blah"  
                # oder  
                Zonk::bequem_und_schnell(blah); # flurbelt das Flummox mittels "blah"  
              
            
            

            Oder umgekehrt ein prozedurales mit einem objektorienterten umhüllen; dies wird häufig so gemacht, wenn "stimmt_das_so" eine XS-Funktion ist:

              
            package Narf;  
              
            sub stimmt_das_so {  
                return 1; # jawoll.  
            }  
              
            sub new {  
                my ($class) = @_;  
                return bless {} => $class;  
            }  
              
            sub check {  
                my ($self) = @_;  
                return stimmt_das_so;  
            }  
              
            =head1 SYNOPSIS  
              
                use Narf;  
                Narf::stimmt_das_so; # diesen Aufruf vermeiden, besser:  
                Narf->new->check;  
            
            

            OO-Experten können zwei Gründe nennen, warum das Umhüllen, so wie ich es auf die Schnelle dargelegt habe, schädlich ist.

            Hast du vielleicht noch eine weitere Buchempfehlung für mich?

            http://www.effectiveperlprogramming.com/ auf der rechten Seite. Diese neue zweite Ausgabe ist zwar noch nicht veröffentlicht, kommt aber sehr bald.

            1. Hallo CPAN,

              Im Prinzip ja, aber pauschal nein. Ein gewitzter Programmierer kann ein objektorientertes Interface zur Bequemlichkeit für den Benutzer mit einem prozeduralen umhüllen:
              Oder umgekehrt ein prozedurales mit einem objektorienterten umhüllen; dies wird häufig so gemacht, wenn "stimmt_das_so" eine XS-Funktion ist:

              oho. Nulpenalarm. Ich hab mir Deine Beispiele wiederholt angeschaut, aber ich blick nichts. Nichts. Grausam. Ist wie wenn mich wer auf finnisch anspricht. Pfffffftttt.

              Hast du vielleicht noch eine weitere Buchempfehlung für mich?
              http://www.effectiveperlprogramming.com/ auf der rechten Seite. Diese neue zweite Ausgabe ist zwar noch nicht veröffentlicht, kommt aber sehr bald.

              Danke! Ich hab mir die erste Ausgabe auf deutsch bestellt. Hört sich spannend an.

              Ystävällisin terveisin
              JOhnnY