# Wird Gentoo komplizierter?

## TheSmallOne

Hi,

mich würde mal eure Meinung interessieren.

Ich nutze Gentoo jetzt seit vielen Jahren, doch ich habe in letzter Zeit immer mehr das Gefühl, das es zunehmend komplizierter wird.

Früher konnte man problemlos ein emerge -Du @world ausführen – klar, es gab immer mal wieder ein paar Zirkel-Abhängigkeiten, oder USE-Flags, die ein manuelles Eingreifen erforderten. Meist hat man dann einfach ein Paket bewusst deinstalliert, welches dann beim Update als Abhängigkeit wieder neu installiert wurde, aber alles in allem keine großen Aufwände und auch immer bloß Einzelfälle.

Inzwischen kann ich jedoch kein World-Update mehr ausführen, ohne dass es irgendwelche Probleme gibt. Entweder ein Fehler wegen irgendwelcher Maskierungen, oder irgendwelche Python-Target-Geschichten. Es läuft einfach nicht mehr so problemlos wie „früher“.

Heute konnte ich z.B. nach dem sync nichtmal problemlos ein Portage-Update selbst einspielen, ohne dass es zu einer langfristigen Angelegenheit wurde.

Geht es euch auch so, oder habe ich einfach nur eine ungewöhnliche Installation?

----------

## Tyrus

Also ich hab eigentlich nicht das Gefühl des es komplizierter geworden ist.

Allerdings waren die News zu Python und jetzt heute wieder zu mpc in Zusammenhang mit dem gcc nicht so hilfreich.

Also aktuelles Beispiel - für den mpc wird nigendwo gesagt das die problematische Version 4 noch unstable ist. Das heisst in meinem Fall, ich muss gar nix machen, mich vielleicht später erinnern. 

Für mich verwirrt die News erstmal, mehr weil man denkt, man müsse selber auch irgendwas was tun.

Grundsätzlich klappt bei mir aber das "emerge --ask --verbose --update --newuse --changed-deps --deep world" in der letzten Zeit eher besser als früher. *hust*

Das "--changed-deps" hab ich jetzt aber extra noch dazugenommen, weil ich festgestellt habe, des es leider immer wieder vorkommt, das Ebuilds ohne einen Versionssprung geändert werden, und man davon nix mitbekommt.

----------

## ChrisJumper

Die Migration ist schwierig. Jetzt nicht Python, aber ein Wechsel von  openrc zu systemd. Grub Lagcy zu Grub 2. Setzt man ein neues System auf, geht es geschmeidig wie eh und je finde ich.

Mit der Zeit muss man aufräumen, vielleicht mal die Daten migrieren oder auf komplett neue Architekturen wechseln.

Das einzige was mich regelmäßig stört ist wenn zu viele Unstable Pakete drin sind oder zu viele Overlays. Oder sich das Gefühl breit macht die aktuellen Pakete kommen zu spät. Stellenweise ist das wohl auch so, weshalb ein Overlay es etwas bequemer macht.

Aber man kann es dem Stable-Zweig nicht vorwerfen wenn dort erst mal getestet werden muss.. oder gar den Maintainern die Tester fehlen. In den meisten Fällen hilft aber ein Blick in den Bug-Tracker oder hin zu den Github-Issues/Readme Dateien in den Overlays.

Mit dem älter werden wirkt immer alles komplizierter. Im Grunde haben auch die Migrationen immer funktioniert ohne das es Datenverlust gab oder ich mich aus gesperrt hab. Aber neues und ungewohntes ist immer ein kleiner Ballance-Akt mit der Angst vor einem kleinen Fall. Am besten nimmt man sich dafür einfach ein wenig Zeit, hat trotzdem Backups und macht es wirklich nur wenn man Lust drauf hat.

Neben Pearl, QT oder zuletzt der Umstellung bei 

```
[I] x11-base/xorg-proto

     Verfügbare Versionen:   2018.4 **9999

     Installierte Versionen: 2018.4(00:00:00 20.04.2018)

     Startseite:             https://cgit.freedesktop.org/xorg/proto/xorgproto/

     Beschreibung:           X.Org combined protocol headers
```

Hatte ich auch ein wenig zu Kämpfen.

Auf einem anderen System auch mit einer Virtual Box Version, wegen dem Xorg-Proto. Stellenweise wirkte es so als seien die Ebuilds noch nicht auf die Verwendung von Xorg-Proto umschrieben und haben immer wieder mal andere Abhängigkeiten rein gezogen. Aber in dem Fall hilft dann Warten oder Zeitweise ein eigenes lokales Overlway erstellen wo man die Ebuilds anpasste.

----------

## toralf

 *TheSmallOne wrote:*   

> Hi,
> 
> mich würde mal eure Meinung interessieren.
> 
> Ich nutze Gentoo jetzt seit vielen Jahren, doch ich habe in letzter Zeit immer mehr das Gefühl, das es zunehmend komplizierter wird.

 Was für eine Vorlage  für eine altersdiskrinimierende Bemerkung  :Wink: 

- Aber nun ernsthaft:

m.E. wird Gentoo nicht unbedingt komplizierter, aber erwachsener. Dazu gehört, daß Portage der wachsende Paketanzahl, kombiniert mit immer komplexer werdenden Abhängigkeiten zwischen diesen, gerecht werden will. Denn früher war Portage eher ignorant (==jugendlich), wenn es um die Feinheiten von USE-Flag-Abhängigkeiten ging. Und heutzutage macht Portage dann nicht irgendwie weiter, sondern stoppt mit  (zugegebenermaßen oftmals schwer zu lesenden) Fehlermeldungen.

----------

## mike155

 *Quote:*   

> ich habe in letzter Zeit immer mehr das Gefühl, das es zunehmend komplizierter wird. 
> 
> 

 

Ich glaube nicht, dass es komplizierter wird. ich habe vielmehr den Eindruck, dass es bei Gentoo manchmal ruhigere Phasen und manchmal stürmische Phasen gibt. 

Die Pakete, bei denen es Probleme gibt, wechseln. Wenn ich mich richtig erinnere, waren früher (vor 10+ Jahren) Updates von Perl sehr aufwändig, dafür waren Updates von Python einfach. Jetzt ist genau andersherum... Python ist u.a. deshalb so kompliziert, weil wir mehrere Versionen gleichzeitig installieren müssen. Aber das ist nicht die Schuld der Gentoo Entwickler, sondern die Schuld der Python Entwickler. Ich sehne den Tag herbei, an dem auf allen meinen Rechnern nur noch eine Version von Python installiert ist! Ich habe das bisher nur auf einem einzigen Server geschafft.

----------

## Tyrus

Sowas ist einfach nur unschön:

```

mithrandir@luthien ~ $ diff "/mnt/backup/Gentoo-System/usr/portage/games-arcade/supertux/supertux-0.5.1.ebuild" /usr/portage/games-arcade/supertux/supertux-0.5.1.ebuild 

1c1

< # Copyright 1999-2017 Gentoo Foundation

---

> # Copyright 1999-2018 Gentoo Foundation

4a5,6

> 

> : ${CMAKE_MAKEFILE_GENERATOR:=ninja}

34a37

>       "${FILESDIR}"/${PN}-0.5.1-ninja.patch

41c44

<       sed 's@logo_dev@logo@' \

---

>       sed -e 's@logo_dev@logo@' \

46a50

> 

53d56

<               -DUSE_DEBUG="$(usex debug)"

54a58

>               -DUSE_SYSTEM_PHYSFS=ON

56d59

< 

58,65d60

< }

< 

< src_compile() {

<       cmake-utils_src_compile

< }

< 

< src_install() {

<       cmake-utils_src_install

```

Da ist der Ebuild einfach im Stillen geändert worden. 

Ich hab dann den Rebuild gemacht und es ja es gab gleich einen Compilefehler. Der Ebuild verwendet jetzt das System-Physfs. Nur die stable Version war nicht mehr geeignet und ich musst auf die unstable 3er Version.

Gut hab ich also gemacht. Das Paket baut sauber neu. Aber dann beim revdep-rebuild gehts weiter.

Zwei weitere Pakete muss ich auch aktualisieren. media-libs/sdl-sound lies sich aber mit dem neuen dev-games/physfs-3.0.1-r1 nicht mehr baun. Und da blieb nur das per USE-Flag abzuschalten. 

Es wäre wirklich schön gewesen wenn hier wenigstens eine neuen Version für games-arcade/supertux erzeugt worden wäre.

Ohne das "--changed-deps" hätte das alles wahrscheinlich erstmal eine Weile unerkannt weitergeschlummert.

----------

## artbody

Also ich denke, dass es nicht Gentoo an sich ist was komplexer wird, sondern die einzelnen Programme incl. aller extrem Developer lastiger Docus.

Dann, dass es derzeit so einen Trend gibt, immer alles neu zu erfinden.

Schönstes Beispiel dürfte derzeit Enlightenment WM E16 als Orginal  UND der gesamte neuen Schöpfung "Enlightenment WM" E17,18,..22,...xxxxx zu sein.

Die verdienen in meinen Augen den LINDI (Linux Disaster Preis)

Warum :

E16 

Kernpunkte 

1. Man klicke auf den Hintergrund egal wo und hat das Menu an der Position (alles gesparte Mauskilometer)

2. 3dimensionales array für virtuelle Bildschirme   :Idea:  (also x*y*n)

1996 man beachte

3. man fahre mit der Maus an den Bildschirmrand und befindet sich im nächsten virtuellen Fenster !! 1996 !! 

ich hatte damit nie Probleme noch Abstürze - ein WM ohne viel Overhat

Dann Enlightenment 17,18,..22...xxxxxx 

Alles neu alles GIGA, toll hier und mega dort , aber als erstes flog das 3D Array  für virtuelle Bildschirme raus, also nur noch 2dimensional   :Crying or Very sad: 

dann widgets hier und dort , dateimanager usw , der OVERHAT (aus Alu mit Löcher) wude mit der Zeit immer größer.

DIE FRECHHEIT an der Sache ist gerade aktuell

Man verwende einen tollen Namen für etwas ABSOLUT NEUES, klemmt sich an den Orginal Enlightenment dran UND bezeichnet diesen dann als den ALTEN welcher jetzt sogar aus dem Portage Tree rausflog weil zwei VÖLLIG verschiedene Softwarepakete über Slots nicht mehr zu handeln waren.  :Rolling Eyes: 

22 Jahre Enlghtenment E16 und jetzt ist es ein inoffizielles Overlay   :Evil or Very Mad:   :Twisted Evil:   :Evil or Very Mad:   :Embarassed: 

https://bugs.gentoo.org/656020

----------

## mv

 *toralf wrote:*   

> Portage der wachsende Paketanzahl, kombiniert mit immer komplexer werdenden Abhängigkeiten zwischen diesen, gerecht werden will

 

Nein. Die Zahl der Pakete in Gentoo hat im Gegenteil sogar abgenommen, und die Abhängigkeiten sind auch nicht viel anders als früher.

Was sich geändert hat, ist, dass es einige Entwickler hip fanden, Funktionalität, die zurecht in Extra-Tools wie revdep-rebuild, perl-updater oder python-updater ausgelagert war, als komplizierte Abhängigkeiten mit subslots und USE-flags auszudrücken, also das zugehörige NP-vollständige Problem der Abhängigkeitsauflösung zu vergrößern und damit den Paketmanager und Benutzer zu überfordern.

Bei Perl wurde das ganze noch mit Sachverstand gemacht, aber python nach minor-Versionen zu slotten und Pakete nur für die jeweilige Minor-Version zu kompilieren, ließ schon jedes Maß an Realismus vermissen und zwingt den Benutzer, entweder Dutzende von Paketen in überflüssigen Versionen zu installieren oder bei jedem minor-Upgrade massiv manuell einzugreifen. Wenn das dann noch mit anderen Problemen aus subslot-Abhängigkeiten zussamenstößt und vielleicht gar noch mit einem echten Bug in den Abhängkeiten, ist man schnell aufgeschmissen.

----------

## mv

 *mike155 wrote:*   

> [Aber das ist nicht die Schuld der Gentoo Entwickler, sondern die Schuld der Python Entwickler.

 

Python:2 und Python:3 sind sehr verschieden; da ergibt es schon Sinn.

Zusätzliche Slots für Minor-Versionen sind ausschließlich die Schuld der Gentoo-Entwickler: Man muss nicht wegen jedem Furz, der nicht ganz abwärtskompatibel ist, einen neuen Slot aufmachen. Die Perl-Entwickler in Gentoo machen vor, wie man das vernünftig handhaben kann: Obwohl viele Perl-4-Programme unter perl-5.26 nicht ohne Änderung laufen, wurde da noch nie ein neuer Slot erzwungen.

----------

## artbody

python target   :Rolling Eyes: 

Ja python ist schon eine etwas anstrengende peinliche Nummer

Angefangen beim Einrücken ohne erzwungenes Ende bei

```
 

while..

 if .....

   if ...

  if ...

 else

  or what indent

 
```

was erwartet man von solchen  :Question: 

Satzzeichen wie Punkt, Komma usw

schaffen Klarheit, in jedem Text  :Laughing: 

Mich wundert ja, dass die Pythonleute, in ihren Docu's, Satzzeichen verwenden.  :Wink: 

```

#!/usr/local/bin/perl

 $num = 20;

while ($num < 30) {

        if ($num > 25) {

     print "num is $num\n";

}

    ++$num;

}

```

unschön aber funktioniert trotzdem 

 :Laughing: 

aber ein guter Editor kann daraus wohl formatierten Code machen, was bei Python ja ausgeschlossen ist.

----------

## mv

 *artbody wrote:*   

> Angefangen beim Einrücken ohne erzwungenes Ende

 

Das finde ich gar nicht so schlimm, denn man rückt ja außer für Debugging-Zeilen ohnehin korrekt ein.

Was ich schlimmer finde, sind die Style-Regeln: Einrücktiefe 4 (wenn ohnehin erwartet wird, dass man den Code mit try/except vollstopfen muss) + 80-Zeichenlimit + noch viel mehr Einrücken bei den Zeilenumbrüchen. In typischen Programmen steht dann der Code am rechten Rand wortweise untereinander oder kann manchmal gar nicht Style-konform geschrieben werden.

 *Quote:*   

> 
> 
> ```
> if .....
> 
> ...

 

Dangling else ist kein python-spezifisches Problem, und außer Einrücktiefe (oder noch übler: Klammerzählen) gibt es da in keiner Sprache was Schönes. Selbst natürliche Sprachen tun sich damit extrem schwer.

 *Quote:*   

> unschön aber funktioniert trotzdem 

 

Wenn Du solchen Code als Patch in einem meiner Projekte einreichst, bekommst Du ihn um die Ohren gehauen.  :Wink: 

Der einzige Vorteil von Zeichen+Einrücken ist, dass die Redundanz eine Verifikationsmöglichkeit schafft. Der gcc macht das inzwischen mit geeigneten Optionen.

Aber da haben die Python-Leute schon recht: Der Mensch verlässt sich auf die optische Einrückung; einen Strichpunkt mehr/weniger übersieht er leicht.

----------

## mike155

 *mv wrote:*   

> Dangling else ist kein python-spezifisches Problem, und außer Einrücktiefe (oder noch übler: Klammerzählen) gibt es da in keiner Sprache was Schönes. Selbst natürliche Sprachen tun sich damit extrem schwer. 

 

Code mit geschachtelten if/else Blöcken ist auch für Menschen schwer lesbar - und eine häufige Fehlerursache! Für mich gibt es nichts Schlimmeres, als Code-Review von Programmen, bei denen der Entwickler mehrere if/else Ebenen geschachtelt hat...

Dabei kann man beim Programmieren geschachtelte if/else Blöcke (und häufig auch else) vermeiden: wenn man Funktionen verwendet und sich an die Regel hält: keine Funktion mehr als 30-50 Zeilen - ergibt sich das fast von selbst.

----------

## Yamakuzure

 *mike155 wrote:*   

> Dabei kann man beim Programmieren geschachtelte if/else Blöcke (und häufig auch else) vermeiden: wenn man Funktionen verwendet und sich an die Regel hält: keine Funktion mehr als 30-50 Zeilen - ergibt sich das fast von selbst.

 Die Regel ist recht geläufig, und die am zweithäufigsten gebrochene.  :Wink:  (Gleich nach "Kommentiere deinen Code!" und knapp for "Benutze niemals 'goto'!"  :Laughing: )

Aber Spaß beiseite, mehrfach geschachtelte If-Else-Blöcke sind in der Tat ein Fluch. Für mich heißt das meistens, dass der/die Autor/in keinen Plan hatte, sondern drauflosschrieb und dann erweiterte. Ebenfalls ohne Plan. Wegschmeißen und neu schreiben ist in den allermeisten Fällen die sauberste Lösung.

Naja... und zur Not tut es immernoch die Kombination aus AStyle und, zumindest unter Windoofs, Viasfora (Rainbow Braces (Wer vim benutzt kennt vielleicht das "Rainbow Parentheses" plugin...)).

----------

## mv

 *mike155 wrote:*   

> Dabei kann man beim Programmieren geschachtelte if/else Blöcke (und häufig auch else) vermeiden: wenn man Funktionen verwendet

 

Da bin ich anderer Ansicht: Funktionen haben mit if-else nichts zu tun. Außerdem bin ich nicht der Ansicht, dass an if-else etwas schlechtes 

 *Quote:*   

> keine Funktion mehr als 30-50 Zeilen

 

Diese Regel ist für C/C++ genauso weltfremd wie der Python-Style. Künstliches Ausplitten in Funktionen sorgt nur dafür, dass massenweise Parameter übergeben werden. In Python ist das in diesem Fall anders, weil innere Funktionen auf die Variablen der äußeren zugreifen dürfen. Aber innere Funktionen sind auch nicht schön.

----------

## mike155

 *mv wrote:*   

> Funktionen haben mit if-else nichts zu tun.
> 
> 

 

Bitte? Die beiden wichtigsten Refactoring-Regeln zur Vermeidung von komplizierten geschachtelten if/else-Blöcken haben mit Funktionen zu tun:

Wenn in einem then- oder else-Block längerer Code steht (und evtl. weitere if/else-Anweisungen): überlege, den Code in eine eigene Funktion auszugliedern. Das reduziert zwar nicht die Zahl der if/else-Anweisungen, erhöht aber die Lesbarkeit.

Nutze "early return". Diese Technik reduziert die Anzahl der else-Blöcke erheblich und erhöht dadurch die Lesbarkeit. "Early return" ist natürlich nur möglich, wenn man mit Funktionen arbeitet. Das hört sich für Java/C/C++-Programmier vielleicht trivial an, weil die sowieso mit Funktionen arbeiten  :Smile: . Aber wenn man ein Script hat, das von oben nach unten runterprogrammiert wurde und in dem keine oder nur wenige Funktionen verwendet werden (und davon gibt's mehr als genug),  muss man den Code erst mal in Funktionen unterteilen, damit man "early return" nutzen kann. 

Wen es interessiert: ein Beispiel in C++ für diese Technik gibt es hier: https://arne-mertz.de/2016/12/early-return/.

Bevor Missverständnisse aufkommen: das heißt nicht, dass man die o.g. Regeln immer anwenden sollte oder dass "else" immer schlecht ist. Man muss jeden Einzelfall betrachten. Manchmal helfen die o.g. Regeln, manchmal nicht...

----------

## mv

 *mike155 wrote:*   

> Das reduziert zwar nicht die Zahl der if/else-Anweisungen

 

Eben.

 *Quote:*   

> Nutze "early return"

 

Auch das hat mit Funktionen nur bedingt zu tun: break/continue läuft auf das selbe hinaus.

Für Beides gibt es gute Einsatzmöglichkeiten, aber es sind Stilmittel, die man möglichst vermeiden sollte, weil sie i.W. ein verkapptes "goto" sind und die Programmlogik verschleiern.

Besonders deutlich wird das, wenn man im Nachhinein feststellt, das man z.B. noch eine Resource (etwa eine Latte von malloc/new, mutexes o.ä.) benötigt und diese in allen Fällen freigegeben werden soll: Weil kein gemeinsamer "Treffpunkt" des Codes vorhanden ist, muss man die Resourcenfreigabe ev. in jedem Teil erneut handhaben, oder doch die versteckten "goto"s wieder entfernen.

Klar, in C++ behilft man sich da mit Temporärobjekten, und der Compiler kümmert sich in jedem Zweig darum, deren Destruktor aufzurufen, aber wenn man nur wegen solchen Programmierstils neue Objekte einführen muss, hat man möglicherweise etwas falsch gemacht. In C wäre man da ohenhin verratzt. Außerdem lässt sich nicht alles in ein Objekt binden: Je nach Programm sind möglicherweise am Ende des Blocks noch ganz andere Folgearbeiten notwendig.

----------

## mike155

 *Quote:*   

> Besonders deutlich wird das, wenn man im Nachhinein feststellt, das man z.B. noch eine Resource (etwa eine Latte von malloc/new, mutexes o.ä.) benötigt und diese in allen Fällen freigegeben werden soll: Weil kein gemeinsamer "Treffpunkt" des Codes vorhanden ist, muss man die Resourcenfreigabe ev. in jedem Teil erneut handhaben, oder doch die versteckten "goto"s wieder entfernen. 

 

Dia Aufgabe, dass man Ressourcen wieder freigeben muss, taucht in der Tat häufig auf. Ich löse diese Aufgabe typischerweise durch eine zweite Funktion:

```
function a

{

    1) Initialisieren  open(), malloc(), Synchronisationsobjekte, usw

    2) Funktion b aufrufen, die die eigentliche Aufgabe erledigt. Wenn in b Exceptions auftreten können, erfolgt der Aufruf in einem try/eval Block.

    3) Cleanup: close(); free(), mutexes,  Synchronisationsobjekte, usw

}

function b

{

    Job erledigen

}

```

Dann ich kann ich mich in der Funktion b ganz auf meinen Job konzentrieren und meinen Algorithmus implementieren. In b muss ich mir keine Gedanken über Ausführungspfade oder die Freigabe von Ressourcen machen. Bei Bedarf kann ich mit return zurückspringen. Ergebnis sind relativ kurze Funktionen, die gut lesbar sind. Meines Erfahrung nach führt das zu stabilen Programmen: der Cleanup-code in Funktion a wird auf jeden Fall durchlaufen. Ein weiterer Vorteil ist, dass init- und cleanup-code in der Funktion a direkt untereinander steht. Dadurch sieht man Fehler schneller, als wenn init- und cleanup-Code noch durch weiteren Code getrennt wird.

----------

## franzf

 *mike155 wrote:*   

>  *Quote:*   Besonders deutlich wird das, wenn man im Nachhinein feststellt, das man z.B. noch eine Resource (etwa eine Latte von malloc/new, mutexes o.ä.) benötigt und diese in allen Fällen freigegeben werden soll: Weil kein gemeinsamer "Treffpunkt" des Codes vorhanden ist, muss man die Resourcenfreigabe ev. in jedem Teil erneut handhaben, oder doch die versteckten "goto"s wieder entfernen.  
> 
> Dia Aufgabe, dass man Ressourcen wieder freigeben muss, taucht in der Tat häufig auf. Ich löse diese Aufgabe typischerweise durch eine zweite Funktion:
> 
> ```
> ...

 

Aber speziell mutexes sind so angewandt ziemliche Performancefresser da sie während der gesamten function b blockieren. MMn. sollten die wirklich so eng wie möglich um den kritischen Teil liegen damit man möglichst viel parallel werkeln kann.

Ja, man kann eine function c einführen, die den parallel ausführbaren Teil enthält und nur darum die mutexes legen. Wird aber mit der Zeit ziemlicher Wust zu managen. Und beißt sich evtl. dann auch mit Speicher- und Filemanagement.

Generell finde ich das hier etwas zu theoretisch. Lass doch den Maddin unsauberen Code schreiben. Solange sein eix (und der ganze andere "Wust"  :Wink: ) funktioniert ist das doch in Ordnung, oder?

----------

## doedel

 *mv wrote:*   

>  *mike155 wrote:*   Das reduziert zwar nicht die Zahl der if/else-Anweisungen 
> 
> Eben.
> 
>  *Quote:*   Nutze "early return" 
> ...

 

Dann muss ich aber nochmal das forward-goto in Raum werfen, was in manchen fällen durchaus legitim ist.

Pseudocode:

```

function init_system() {

  init_console();

  ret = init_io();

  if(ret) goto outhere_nocleanup;

  ret = init_keyboard();

  if(ret) goto outhere;

  ret = init_mouse();

  if(ret) goto outhere;

  ....

  ....

outhere:

  cleanup_init();

outhere_nocleanup:

  return;

```

----------

## Yamakuzure

 *mv wrote:*   

>  *mike155 wrote:*   Das reduziert zwar nicht die Zahl der if/else-Anweisungen 
> 
> Eben.
> 
>  *Quote:*   Nutze "early return" 
> ...

 Hört, hört!

Und jetzt eine Anekdote dazu:

Als ich bei meinem vorherigen Arbeitgeber Anfing, das war im Jahre 2008, fand ich viele "goto"-Anweisungen in den vorhanden C-Quelltexten.

Als braver Befürworter und Unterstützer der "Benutze niemals goto!"-Regel, habe ich mit dem Hauptautor (mein Chef) darüber gesprochen.

Er forderte mich heraus: Sein Argument ist, dass ein "goto" hier die eleganteste Lösung sei. Ich solle versuchen eine eleganter ohne "goto" zu finden.

Ergebnis: Ging nicht. Zumindets nicht in C. In C++ wäre es kein Problem gewesen, dort gibt es Destruktoren, aber in C endete jeder Versuch, die "goto"s weg zu bekommen, in lächerlich breiten if-else-Verschachtelungen, idotischem Auslagern von Code-Schnippseln in Funktionen, oder eben schwer auffindbaren "early returns".

 *doedel wrote:*   

> Dann muss ich aber nochmal das forward-goto in Raum werfen, was in manchen fällen durchaus legitim ist.

 

Und genau darum handelte es sich in besagtem C-Code. Wie gesagt, in C++ gibt es Destruktoren, da benötigt man sowas nicht (kaum), aber in C ist der Ansatz gerne eine Hilfe um ein durchaus elegantes (und vor allem gut lesbares) Design zu bekommen.

Erkenntnis daraus: Programmierregeln und "Best Practices" sind prima als Orientierungshilfe, sollten aber nicht wie eine Zwangsjacke getragen werden.

----------

## mike155

Ich mag es, wenn ich ein Programm bzw. eine Funktion einmal von oben nach unten lese - und dann weiß, was es/sie tut. Alles was dabei stört, versuche ich zu vermeiden.

Den von doedel gezeigten Code finde ich aber nicht optimal. Ich musste ihn mehrfach lesen, bis ich wusste, was es mit den "gotos" auf sich hat und was das Programm eigentlich tun soll. Wenn ich es richtig verstanden habe, soll der Code folgendes machen:

1) als erstes wird init_io() aufgerufen. Wenn der Aufruf scheitert, soll die Funktion zurückkehren

2) dann werden die einzelnen Devices der Reihe nach initialisiert. Wenn eine Initialisierung scheitert, soll abgebrochen werden und die Funktion soll zurückkehren.. Vorher soll aber auf jeden Fall noch cleanup_init() aufgerufen werden

3) Wenn alle Devices initialisiert werden können, soll auch cleanup_init() aufgerufen werden (wundert mich, aber steht so in dem Programm)

Ich würde versuchen, das auch so im Code so zu zeigen - damit es jeder sofort sieht, ohne dass er erst Ausführungspfade analysieren muss. Mein Code würde also vermutlich folgendermaßen aussehen:

```
# return value: 0: SUCCESS, !=0: ERROR 

function init_system() {

  init_console();

  ret = init_io();

  if ( ret ) {

     return ret;

  }

  ret = init_devices();

  cleanup_init();

}

function init_devices() {

  ret = init_keyboard();

  if ( ret ) {

      return ret;

  }

  ret = init_mouse();

  if ( ret ) {

      return ret;

  }

  ...

}
```

Der Code ist "goto"-frei und die maximale if-Tiefe ist 1.

----------

## franzf

Wobei du jetzt vor einem kleinen Problem stehst:

Dein Code nimmt bei den "..." an, dass es sich um Initialisierung weiterer Devices handelt.

Ich denke da wird durchaus anderer Code stehen, das sollte dann in init_system rein.

Von jetzt an hast du aber init_cleanup vorm return auszuführen.

Und zwar jedesmal wenn ret !=0.

Also entweder bei jedem neuen init_... ret-check+cleanup+return, oder alles in verschachtelte if-Blöcke.

MMn. nimmt sich das nicht so viel. Ich mag goto ja auch nicht aber in dem Fall versteht man was passiert, vor allem sind es klare Sprünge und nicht quer hin und her im Code.

(Und irgendwie finde ich die dauernden if ret return ret unästhetisch  :Wink: )

----------

## mv

Das ist alles etwas Praxisfern: Die Funktionen init_mouse() usw in mike155's code liefern typischerweise (häufig mehrere) lokale Variablen zurück, mit denen man dan im Code und auch zum Deinizialisieren arbeiten will.

Klar: Möglicherweise kann man diese ganze Funktion in eine Klasse kapseln und die lokalen Variablen in Klassenvariablen transformieren.

Je nachdem ist das aber vielleicht nicht sinnvoll, und es sollte wirklich eine Standalone-Funtion sein, die halt nur sehr viele lokale Variablen hat.

In dem Moment wird die ganze Zerlegung in Teilfunktionen sehr problematisch, weil man dann eben jeweils Dutzende von Variablen hin- und zurückübergeben muss.

(Nein, das Kapseln dieser Variablen in eine künstliche Klasse/Struktur, deren Zweck die Anwenung in i.W. einer einzigen "aufgesplitteten" Funkltion ist, macht das Ganze eher noch chaotischer).

Es gibt eben halt nun mal Funktionen, die von ihrer Natur her lang sind.

Ob man diese mit forward-goto's übersichtlicher gestaltet, wage ich zu bezweifeln. gotos können in solchen Fällen natürlich minimal effiizienter sein (aber vielleicht auch nicht, weil implizit irgendwelche rewinds notwendig sein können). Ich bleibe dabei: Nur zu vermeidung von "else" sind weder Subfnuktionen noch gotos höchstens dann zweckmäßig, wenn man sich dadurch nichttrivialen duplizierten Code in verschiedenen else-Teilen spart. (Und auch in dem Fall sollte man vielleicht lieber über eine zusätzliche boolesche Variable nachdenken, die man am Ende abfragt, statt gotos/Subfunktionen zu benutzen).

Klar: Solange den Subfunktionen (fast) keine lokalen Parameter übergeben werden, und sie wirklich etwas logisch eigentsändiges tun,, sind Subfunktionen natürlich immer zweckmäßg, auch weil sid die Hauptfunktion kürzer machen. Aber das gilt unabhängig von if... else... -Fragen.

Edit: Erklärung zu gotos verlängert.Last edited by mv on Sat Jul 21, 2018 7:01 am; edited 1 time in total

----------

## mv

 *franzf wrote:*   

> Lass doch den Maddin unsauberen Code schreiben. Solange sein eix (und der ganze andere "Wust" ;)) funktioniert

 

Ich verwehre mich stark gegen die Behauptung, unsauberen Code zu schreiben. Gerade in Projekten wie chessproblem, knapsack, oder osformat habe ich mir sehr viel Gedanken nicht nur über die öffentlichen Interfaces sondern auch über den Codeaufbau selbst gemacht. Wenn Du da der Meiinung bist, ich würde unsauber programmieren, verweise bitte auf konkrete Stellen.

Mit eix ist es naturgemäß schwieriger: Erstens hatte ich da schon vielen vorgefertigen Code geerbt, und dann werden von Zeit zu Zeit neue Features (bei portage oder manchmal auch bei eix) eingeführt, die so gar nicht zur internen Programmlogik passen. Typisches Beispiel ist das Herausnehmen von profile-Zeilen mit "-..." bei denen ein Textvergleich zutreffen muss (obwohl eix aus Effiziengründen, die Zeilen natürlich ganz anders konvertiert). Oder die Tatsache, dass die Behandlung von KEYWORDS="-*" oder ACCEPT_KEYWORDS="-*" früher eine vollkommen andere Logik erforderte als jetzt KEYWORD=""; insbesondere auch, was die Auswirkungen auf eix-eigene Features wie eix-test-obsolete angeht. Häufig wäre einfach ein totales Umstruktieren großer Klassen angemessen, aber das war nie praktikabel. Deswegen strotzt eix (in moderner Terminologie) inzwischen von Adapter- Bridge- und Facade-Patterns, die alle nicht vorhanden wären, wenn man eix nur für das aktuelle Portage neu schreiben würde. Aber weil nie abzusehen ist, welche Features die nächste EAPI bringen wird, muss eix zwangsläufig immer eine Behelfsbaustelle bleiben...

----------

## franzf

 *mv wrote:*   

>  *franzf wrote:*   Lass doch den Maddin unsauberen Code schreiben. Solange sein eix (und der ganze andere "Wust" ) funktioniert 
> 
> Ich verwehre mich stark gegen die Behauptung, unsauberen Code zu schreiben. Gerade in Projekten wie chessproblem, knapsack, oder osformat habe ich mir sehr viel Gedanken nicht nur über die öffentlichen Interfaces sondern auch über den Codeaufbau selbst gemacht. Wenn Du da der Meiinung bist, ich würde unsauber programmieren, verweise bitte auf konkrete Stellen.

 

Martin, ich behaupte nicht dass du dreckigen Code schreibst. Ich wollte nur dezent darauf hinweisen, dass du durchaus Erfahrung hast und in deinem Softwarefundus einiges an nützlichen Tools steckt, die man als Gentooaner kennt und schätzt.

----------

## mike155

 *Quote:*   

> Projekten wie chessproblem, knapsack, oder osformat 
> 
> 

 

Ich habe mal in den Quellcode reingeschaut. Meines Erachtens sieht das gut aus - geradezu mustergültig  :Smile:  Und ich finde es prima, dass mv seinen Code auch veröffentlicht!

Wer mal schlechten Code sehen will, kann sich die Funktionen pass() und retrieve() in https://github.com/dellelce/wuftpd/blob/master/src/ftpd.c ansehen. Ich musste vor vielen Jahren eine Erweiterung dafür schreiben - das war eine Herausforderung! Das Ergebnis von dieser Art zu programmieren kann man sich hier ansehen: https://www.cvedetails.com/vulnerability-list/vendor_id-38/product_id-55/Washington-University-Wu-ftpd.html.

----------

## mv

 *mike155 wrote:*   

> Meines Erachtens sieht das gut aus

 

 :Embarassed: 

 *Quote:*   

> Wer mal schlechten Code sehen will, kann sich die Funktionen pass() und retrieve() in https://github.com/dellelce/wuftpd/blob/master/src/ftpd.c ansehen.

 

Wenn man so systemnah sein muss, dass man viele #ifdef's braucht, macht das nie Spaß. Bei eix ist src/various/drop_permissions.cc oder die Funktion normalize_path/NORMALIZE_PATH aus src/eixTk/filenames.cc so ein (Albtraum-)Fall. Aber wenn es halt auf vielen Systemen mit dem selben Source-Code gehen soll, bleibt nicht viel anderes übrig als solches Gemurckse.

----------

## schmidicom

@Thema

Ich finde schon das es Bereiche gibt in denen Gentoo nicht wirklich einfacher geworden ist, wenn es zum Beispiel um den 32bit-Support auf einer 64bit-Installation geht.

Bitte nicht falsch verstehen, ich finde das neue System mit der Umgebungsvariable ABI_X86 eigentlich ziemlich gut. Vor allem muss man dadurch die 32bit-Teile nicht mehr als vorkompiliertes Paket hin nehmen.

Aber die nachträgliche Umstellung ist die reinste "Error: circular dependencies:"-Hölle.

Es wäre echt schön wenn Portage irgendwann mal lernen würde solche Abhängigkeiten selber zu lösen ohne das man dafür das halbe System auseinander nehmen muss.

----------

## mv

 *schmidicom wrote:*   

> Es wäre echt schön wenn Portage irgendwann mal lernen würde solche Abhängigkeiten selber zu lösen

 

Kann es ja im Prinzip: Du brauchst nur die entsprechenden Einträge aus Deinem /etc/portage/package.use entfernen und portage seine Vorschläge schreiben zu lassen (die Optionen dafür weiß ich jetzt nicht auswendig). Ob es zweckmäßig ist, das grundsätzlich nicht über package.use zu regeln, sondern portage bestimmte USE-flags nur automatisch entscheiden zu lassen - das hat viele Vor- und Nachteile, die ich jetzt nicht alle diskutieren will. Einer der Hauptnachteile wäre jedenfalls die Geschwindigkeit von emerge, denn ohne die "Hints" aus package.use müsste portage die Dendency-Hölle bei jedem Aufruf alleine lösen, und die ist halt ihrem Wesen nach NP-vollständig. Natürlich könnte man die "Hints" aus Disk cachen, aber das hat auch wieder Nachteile. In jedem Fall müsste ein großer Teil von portage neu implementiert werden. Aber daran führt auf längere Sicht vermutlich ohnehin kein Weg vorbei. Nur will es niemand machen...

----------

## mike155

 *Quote:*   

> wenn es zum Beispiel um den 32bit-Support auf einer 64bit-Installation geht. 

 

Die Frage ist natürlich, ob Du den 32 Bit Support überhaupt noch brauchst! Vor einigen Jahren brauchte man 32 Bit Support, aber seit ca. 3 Jahren geht es auch gut ohne.

Brauchst Du 32 Bit Support? 

Wenn nicht, dann schmeiß ihn einfach raus. Ich habe alle meine Server vor 3 Jahren auf 64 Bit only umgestellt - und es bisher kein einziges Mal bereut. Das Compilieren einiger Pakete geht schneller und es gibt keinen Ärger mehr mit den 32 Bit Paketen.

----------

## mv

 *mike155 wrote:*   

> Brauchst Du 32 Bit Support?

 

Wer irgendwelche Legacy-Anwendungen für wine hat, kommt nicht drum herum.

----------

## nisto

 *mike155 wrote:*   

>  *Quote:*   wenn es zum Beispiel um den 32bit-Support auf einer 64bit-Installation geht.  
> 
> ... dann schmeiß ihn einfach raus ...

 

Moin.

Wie gehe ich da am besten vor?

----------

## Yamakuzure

 *mv wrote:*   

>  *mike155 wrote:*   Brauchst Du 32 Bit Support? 
> 
> Wer irgendwelche Legacy-Anwendungen für wine hat, kommt nicht drum herum.

 Nicht unbedingt Legacy. Selbst modernste Software wird gerne als 32bit-Anwendung geliefert. Warum sollte ein Softwareherstellung auch für WIN64 entwickeln, wenn WIN32 bis zum jüngsten Tag unterstützt werden wird?

Von dem Umstand mal abgesehen, dass verwendete Bibliotheken von Drittanbieter gerne nur für 32bit vorliegen, und dann hast du den Salat.

----------

## mike155

 *Quote:*   

> Moin.
> 
> Wie gehe ich da am besten vor?
> 
> 

 

Wenn ich mich richtig erinnere, geht es folgendermaßen:

Folgende Anweisungen müssen einwandfrei durchlaufen

```
emerge --update --deep --newuse -pv @world

emerge --depclean
```

Mit 

```
eselect profile list 

eselect profile set ...
```

wählt uns setzt man ein no-multilib Profil. Ich verwende beispielsweise "default/linux/amd64/17.0/no-multilib"

Wegen des kranken Profil-Konzepts fehlen jetzt sehr wahrscheinlich einige USE-Flags - das hängt davon ab, welches Profil man vorher hatte. Man kann folgendes eingeben:

```
emerge --update --deep --newuse -pv @world
```

und sich aus der Ausgabe die USE-Flags raussuchen, die fehlen. Die fehlenden USE-Flags kann man von  Hand in make.conf oder - wenn man feiner unterteilen will - in package.use eintragen. 

Ein erneuter Aufruf von "emerge --update --deep --newuse -pv @world" sollte dann nur noch Pakete anzeigen, die wegen des Wechsels von multilib nach no-multilib compiliert werden müssen - und keine, die wegen Änderungen bei den USE-Flags neu compiliert werden müssen.

Jetzt kann man "emerge --update --deep --newuse @world" laufen lassen. Einige Pakete werden neu compiliert, dabei verschwindet der 32 Bit Support.

 Zum Schluss kann man noch den Support für 32 Bit Binaries in der Kernel-Config deaktivieren und einen neuen Kernel bauen.

Der Weg zurück von no-multilib nach multilib ist deutlich schwieriger. Einige Quellen verweisen darauf, dass es nur mit einer Neu-Installation geht. Mit Google findet man auch ein paar Anleitungen, wie es geht - aber das ist nicht ganz einfach.

----------

## Erdie

Ich bin ja schon lange dabei, sehe mich aber mehr als Linux Poweruser. Programmiert habe ich nicht sehr viel und entsprechend wenig Erfahrung. Aus User Sicht habe ich nicht das Gefühl, dass es komplizierter geworden ist. Oder sagen wir mal so: Situationen, bei denen ich das Gefühl hatte, nicht mehr weiterzukommen, sind seltener geworden. Ich bin nach wie vor mit Gentoo zufrieden. Immer, wenn ich mich mit anderen Systemen auseinandersetzen muß (vor allem Ubuntu in der Firma), weiß ich zu schätzen, was ich an Gentoo habe.

Der Ansatz, ein System möglichst lange leben zu lassen, ist bei den meisten Systemen nicht mehr im Fokus. Heute gilt Ex- und Hopp. Gentoo ist die große Ausnahme und das macht es sehr wertvoll.

----------

## mv

Zur Ergänzung von mike155s Hinweisen:

Wenn es Dir nur um die Vermeidung der USE-Abhängigkeiten geht, ist es nicht notwendig, auf no-multilib profile umzustellen:

no-multilib bedeutet, dass eben selbst die toolchain (genauer: gcc und glibc) nur die 64-Bit-Bibliotheken bauen (während diese sonst immer die 32-Bit Bibliotheken "mit"-bauen).

Die 32-Bit-Bibliotheken der Toolchain brauchen nicht sehr viel Platz und auch nicht lange zum kompilieren, aber wie mike155 schrieb: Einmal auf no-multilib umgestellt, kommst Du praktisch nicht mehr zurück.

Zum "Testen", ob Du ohne multilib auskommst, einfach alle "ABI_X86: 32"- bzw. "abi_x86_32"-Einträge in der packag.use entfernen (und ev. ABI_X86="-32 64" in der make.conf setzen). Danach das übliche 

```
emerge -NaDu --with-bdeps=y @world
```

Edit: Nicht vergessen: Wenn Du Windows-Programme mit wine benutzt und nicht ganz sicher bist, dass diese 64-Bit sind, unbedingt diese danach testen. Auch alte DOS-Programme (dosbox o.ä.) werden nach der Umstellung natürlich nicht mehr gehen.

----------

## Yamakuzure

 *mv wrote:*   

> Auch alte DOS-Programme (dosbox o.ä.) werden nach der Umstellung natürlich nicht mehr gehen.

 *seufz* Ich werde sicher niemals auf MoO2 verzichten können...

----------

