# Codequalitaet



## Gast (14. Nov 2007)

Hallo anhand dieses Beispiel eine kleine Frage zum Thema Codequalitaet


```
public static double Wertemin (double z[]) {      
    int min = 0; 
    for (int i = 1; i < z.length; i++) { 
        if (z[i] < z[min])  { 
             min = i; 
        } 
    } 
    return z[min]; 
}
```


```
private static boolean isNotMin(Double currentMin,Double number) {
    return currentMin == null || currentMin > number;
}

public static Double min( double numbers[] )
  {
    Double result = null;
    for( double number : numbers )
    {
      if(isNotMin(result,number))
      {
        result = number;
      }
      else
      {
        // nothing to do
      }
    }
    return result;
}
```

Welcher dieser beiden Versionen ist verstaendlicher ? besser ? sinnvoller ? etc....

oder anders ausgedrueckt welche wuerdet Ihr empfehlen...

ps: Das in der ersten Version bei einem leeren Array eine Exception entsteht ist nicht relevant...


----------



## SlaterB (14. Nov 2007)

die erste, was in 10 Zeilen zu behandeln ist wird durch Pseudo-Objektorientierung nur schlimmer

aber Operationen klein schreiben!

und längere Variablennamen + Kommentare schaden in Version 1 auch nicht,
die schickere for-Schleife + Hilfsvariable für min auch nicht, warum die Anzahl der Arrayzugriffe ohne Not verdoppeln?


----------



## Gast (Version2) (14. Nov 2007)

> wird durch Pseudo-Objektorientierung nur schlimmer



Jede "Bedingung" sollte in eine eigene Methode ausgelagert werden. Dies ermoeglicht die fachliche Benennung der Bedingung (in diesem Fall isNotMin) und ermoeglicht so, dass der Leser NICHT zuerst die Bedingung verstehen muss, sondern sofort sieht welche Bedeutung sie hat.

Dies koennte zwar auch durch einen Kommentar erfolgen. Allerdings stoeren Kommentare im Normalfall den Lesefluss und machen den Kode unübersichtlicher.

Ist diese Begreundung sinnvoll ?


----------



## SlaterB (14. Nov 2007)

was heißt schon sinnvoll..,
es ist eine Art der Programmierung, die ein bestimmtes Konzept konsequent verfolgt, ja,

aber ich persönlich habe a) sowas noch nie gesehen, würde b) beim Lesen verrückt werden und glaube c) dass man damit bei größeren Sachen als solchen Mini-Programmen untergeht 
 :bae:


----------



## Guest (14. Nov 2007)

Gast (Version2) hat gesagt.:
			
		

> Jede "Bedingung" sollte in eine eigene Methode ausgelagert werden



jede? wer sagt das? isNotMin? pff was heißt das? ist nicht minimum? welcher parameter, der erste oder zweite?
ich find a<b verständlicher! man sell es mit der modularisierung auch nicht übertreiben.

ein (a<b&&c==a)||x>3 würde sinn machen, aber in diesem fall find ich auch die erste variante besser.


----------



## Marede (14. Nov 2007)

In Sachen Codequalität kann man sich auch immer gerne das Checkstyle-Plugin für Eclipse anschauen. Hier findet man eine automatisierte Unterstützung schon während der Code-Eingabe, die darüber hinaus auch noch persönlich angepasst werden kann.


----------



## Beni (14. Nov 2007)

Ich möchte hier auch ein Performanceargument einbringen:
Die zweite Version benötigt n neue Objekte, und macht n zusätzliche Methodenaufrufe. Das benötigt einiges an Zeit.

("No premature optimization" hat schon seine Berechtigung, aber wenn man zwei ähnlich übersichtliche Varianten hat, gibt es keinen Grund die langsamere zu wählen.)

Zu


> Jede "Bedingung" sollte in eine eigene Methode ausgelagert werden. Dies ermoeglicht die fachliche Benennung der Bedingung (in diesem Fall isNotMin) und ermoeglicht so, dass der Leser NICHT zuerst die Bedingung verstehen muss, sondern sofort sieht welche Bedeutung sie hat.


Man kanne es auch übertreiben... wer Probleme hat ein "<" zu verstehen, dem hilft auch eine zusätzliche Methode nicht :wink:


----------



## maki (15. Nov 2007)

Warum denn nicht sortieren?

```
public static Double min(double numbers[]) {
		
    Arrays.sort(numbers);
		
    return numbers[0];
}
```


----------



## Marco13 (15. Nov 2007)

_Jede "Bedingung" sollte in eine eigene Methode ausgelagert werden. _

Jo, aber dan bitte konsequent. Also nicht

```
private static boolean isNotMin(Double currentMin,Double number) {
    return currentMin == null || currentMin > number;
}
```
sondern

```
private static boolean isNotMin(Double currentMin,Double number) 
{
    return or(isNull(currentMin), isLarger(currentMin, number))
} 

private static boolean or(boolean a, boolean b) 
{
    return a || b;
} 
private static boolean isNull(Object x) 
{
    return x == null;
} 
private static boolean isLarger(Double a, Double b) 
{
    return a > b;
}
```

Mal im ernst: Wenn ich die zweite Version sehen würde, würde ich sie dem Autoren um die Ohren hauen. Überflüsigen Methode, Ineffizent, Umständlich, und sowas wie

```
else
      {
        // nothing to do
      }
```
ist ja mal mega- :autsch: 


@maki: Sortieren dauert im Worst case O(n^2), die Minimumsuche aber nur O(n).


----------



## Saxony (15. Nov 2007)

Marco13 hat gesagt.:
			
		

> @maki: Sortieren dauert im Worst case O(n^2), die Minimumsuche aber nur O(n).



Hiho,

hier mal mein Senf dazu.

Wenn häufig gesucht werden muss, aber das Feld sich selten ändert, so ist es doch besser dieses jedes Mal zu sortieren bei Änderungen.

Sortierung: Worst Case O(n²), Best Case O(n*log(n))

Danach dauert eine Suche nur noch im Mittel: O(log*log(n)) ujnd im schlechtesten Fall: O(log(n))

Zur Sortierung eignet sich ein Quicksort, bei großen Feldern ist ein Mix aus Quick- und Insertionsort die beste Wahl.

[edit]
Aso falls jetzt einer fragt ab wann ein Feld groß ist, oder noch besser, was die beste Wahl des Pivotelementes bei Quicksort ist, den verweise ich auf eine schier unüberschaubare Menge manifestartiger Literatur zu diesen Themen.
[/edit]

bye Saxony


----------



## lhe (15. Nov 2007)

Der leere Else - Case ist gar nicht so ungewöhnlich. 
Ich habe auch mal für eine Firma gearbeitet, die genau das in den Coding Conventions vorgeschrieben hat. 
Den Sinn habe ich nicht wirklich verstanden, jedoch sagte man mir, daß dies beweisen würde, daß der Programmierer
sich Gedanken um einen evtl. Else - Case gemachte hätte 

Ansonsten würde ich gefühlsmäßig auch Variante a bevorzugen, denn man muß einfach nicht jeden Mist
modularisieren. Dabei kommt in großen Projekten nur unverständlicher Murcks raus und der Programmierer, der
das mal debuggen darf, wird zum Code-Hopper 

Gruß
lhe


----------



## maki (15. Nov 2007)

> @maki: Sortieren dauert im Worst case O(n^2), die Minimumsuche aber nur O(n).


Solange die Performance nicht nachprüfbar ein Problem darstellt, hat man sie gefälligst zu ignorieren und den einfachsten Code zu schreiben der möglich ist.

Frühzeitige Optimierung ist die Wurzel allen übels.


----------



## SlaterB (15. Nov 2007)

wieso dauert Sortieren im Worst-Case n^2?
ist Quicksort nicht garantiert n log n oder habe ich bei den zahllosen Abhandlungen über sowas elementares wie die x bekannten Sortieralgorithmen nicht richtig aufgepasst?

@maki: nene, das ist ein abgeschlossenes Gebiet, was für sich mit minimalen Aufwand extrem optimiert werden kann ohne jeden Aufwand oder Nachteil für andere Gebiete, in diesem Fall spricht nie etwas gegen optimieren,


----------



## tfa (15. Nov 2007)

SlaterB hat gesagt.:
			
		

> wieso dauert Sortieren im Worst-Case n^2?
> ist Quicksort nicht garantiert n log n oder habe ich bei den zahllosen Abhandlungen über sowas elementares wie die x bekannten Sortieralgorithmen nicht richtig aufgepasst?



Nein, wenn bei Quicksort das Pivot-Element wiederholt unglücklich gewählt wird, entartet der Algorithmus zu O(n²).
Es gibt aber Verfahren, die garantiert O(n*log n) sind, z.B. das in Array.sort(Object[]) verwendete Insertion-Sort.


----------



## SlaterB (15. Nov 2007)

also Worst-Case im Sinne von theoretischen Zufall und nicht von z.b. umgekehrter Sortierung?


----------



## tfa (15. Nov 2007)

Das ist alles abhängig von der Wahl des Pivot-Elements. Wenn Du z.B. immer das erste Element auswählst, dauert eine sortierte Liste O(n²). Am besten man nimmt ein Element aus der Mitte oder ein zufälliges.


----------



## Gast(Version2) (15. Nov 2007)

Beispiel:



> Der leere Else - Case ist gar nicht so ungewöhnlich.
> Ich habe auch mal für eine Firma gearbeitet, die genau das in den Coding Conventions vorgeschrieben hat.
> Den Sinn habe ich nicht wirklich verstanden, jedoch sagte man mir, daß dies beweisen würde, daß der Programmierer
> sich Gedanken um einen evtl. Else - Case gemachte hätte



Dies ist eine Begruendung fuehr die leere Else Bedingung!

Fehlende Else Bedinungen sind eine sehr haeufige Fehlerquelle. Untersuchung aus dem Jahr 1978 (zugegeben sehr alt aber eindrucksvoll):

17 Prozent der ifs hatte einen else Zweig. Aber 50 bis 80 Prozent haetten fachlich einen else Zweig aufweisen muessen...

Deswegen die Verpflichtung sich ueber den else Zweig Gedanken zu machen und dies auch im Kode zu dokumentieren durchaus berechtigt.

Also wer Argumente gegen diese Begruendung bei steuern kann; Gerne... Aber bitte nicht das ist mega scheisse oder ist nicht performant. Performance ist immer ein Totschlagargument, denn dann sollte man gleich Assembler programmieren ist ja schliesslich deutlich performanter als Java....



> denn man muß einfach nicht jeden Mist modularisieren.



Wieso nicht ? Wenn die Modularisierung zum Verstaendnis des Code beitraegt ?



```
private static boolean isNotMin(Double currentMin,Double number) 
{ 
    return or(isNull(currentMin), isLarger(currentMin, number)) 
} 

private static boolean or(boolean a, boolean b) 
{ 
    return a || b; 
} 
private static boolean isNull(Object x) 
{ 
    return x == null; 
} 
private static boolean isLarger(Double a, Double b) 
{ 
    return a > b; 
}
```

Sorry habe einen wichtigen Teil der Code Convention weggelassen

Es geht nicht darum alle boolschen Ausdruecke in eigene Methoden auszulagern sonder "nur" die Bedinungen die in Schleifen und Verzweigungen auftretten. Somit ist der obige Code nach den Bedingungen nicht sinnvoll. Allerdings wird es wahrscheinlich auf folgenden Code herauslaufen, da object == Null, vermutlich sehr haeufig vorkommt und isLarger auch.


```
private static boolean isNotMin(Double currentMin,Double number) { 
    return isNull(currentMin) || isLarger(currentMin,number); 
} 

private static boolean isNull(Object object) {
    return object == null;
}

private boolean isLarger(Double number1,Double number2) {
    return number1 > number2;
}
```

Zum Thema grosses Projekt. Der obigie Codestyle wurde in einem Projekt mit etwa 20 Mann Jahren eingesetzt. Kein Grosses aber auch kein kleines Projekt. Nach anfaenglicher starker Gegenwehr, wie auch hier, waren am Ende ALLE ueberzeugt, dass der Style sinnvoll.

Deswegen mein Rat probierts doch einfach mal aus. ihr werdet feststellen, dass insbesondere das Auslagern der Bedingungen dazu fuerht sich genau zu ueberlegen, welche Bedeutung die Bedingung eigentlich hat und was im Else Zweig passieren soll... Uebrigens ein Argument fuers Auslagern...  :wink:


----------



## Saxony (15. Nov 2007)

tfa hat gesagt.:
			
		

> Es gibt aber Verfahren, die garantiert O(n*log n) sind, z.B. das in Array.sort(Object[]) verwendete Insertion-Sort.



Das Verfahren heißt genau *Introsort* und ist, wie ich weiter oben schon geschrieben hatte, ein Mix aus Quicksort und einem anderen Sortieralgorithmus, welcher anhand einer Bewertungsfunktion zum Zuge kommt.

Bei Arrays.sort() wird hierbei zum Quicksort der Insertionsort verwendet, welcher bei (Teil)Feldlängen < 7 seine Arbeit verrichten darf.

bye Saxony


----------



## Saxony (15. Nov 2007)

Hmm,

wieso machstn nicht gleich alles double?
Das verhindert (un)kontrolliertes Autoboxing. Zudem reicht dann ein enfaches > zum Vergleich.
Und man kann es mit Java < 1.5 nutzen.

bye Saxony


----------



## lhein (15. Nov 2007)

Gast(Version2) hat gesagt.:
			
		

> Dies ist eine Begruendung fuehr die leere Else Bedingung!



Ja, zweifelsohne. Aber nur dann, wenn man den Entwickler für ein dummes Individuum hält.
Klar kannst Du ihn dazu zwingen, leere else-Cases zu programmieren, aber ich behaupte mal (und weiss es auch aus eigener Erfahrung), daß es dann auch genug Leute geben wird, die einfach den leeren Else-Case hincoden, aber nicht drüber nachdenken, ob das ausreichend ist.



			
				Gast(Version2) hat gesagt.:
			
		

> Fehlende Else Bedinungen sind eine sehr haeufige Fehlerquelle. Untersuchung aus dem Jahr 1978 (zugegeben sehr alt aber eindrucksvoll):
> 17 Prozent der ifs hatte einen else Zweig. Aber 50 bis 80 Prozent haetten fachlich einen else Zweig aufweisen muessen...
> Deswegen die Verpflichtung sich ueber den else Zweig Gedanken zu machen und dies auch im Kode zu dokumentieren durchaus berechtigt.


Siehe meinen obigen Kommentar. Einen leeren Else-Case zu coden ist nicht die Versicherung gegen Bugs.



			
				Gast(Version2) hat gesagt.:
			
		

> > denn man muß einfach nicht jeden Mist modularisieren.
> 
> 
> Wieso nicht ? Wenn die Modularisierung zum Verstaendnis des Code beitraegt ?


Das tut sie aber schon im obigen Fall nicht wirklich. 



			
				Gast(Version2) hat gesagt.:
			
		

> Es geht nicht darum alle boolschen Ausdruecke in eigene Methoden auszulagern sonder "nur" die Bedinungen die in Schleifen und Verzweigungen auftretten. Somit ist der obige Code nach den Bedingungen nicht sinnvoll. Allerdings wird es wahrscheinlich auf folgenden Code herauslaufen, da object == Null, vermutlich sehr haeufig vorkommt und isLarger auch.
> 
> 
> ```
> ...


Und dann noch einen Methodennamen in Form einer Verneinung zu wählen (isNotMin), trägt zum Unverständnis noch das übrige bei. Warum hier nicht einfach die Methoden der Klasse Math genommen wurden ist auch nicht einleuchtend.
Eine eigene Methode für bla == null zu schreiben, sorry wenn ich das jetzt so sage, ist m.E. so sinnfrei wie es eben nur sein könnte.



			
				Gast(Version2) hat gesagt.:
			
		

> Zum Thema grosses Projekt. Der obigie Codestyle wurde in einem Projekt mit etwa 20 Mann Jahren eingesetzt. Kein Grosses aber auch kein kleines Projekt. Nach anfaenglicher starker Gegenwehr, wie auch hier, waren am Ende ALLE ueberzeugt, dass der Style sinnvoll.
> 
> Deswegen mein Rat probierts doch einfach mal aus. ihr werdet feststellen, dass insbesondere das Auslagern der Bedingungen dazu fuerht sich genau zu ueberlegen, welche Bedeutung die Bedingung eigentlich hat und was im Else Zweig passieren soll... Uebrigens ein Argument fuers Auslagern...  :wink:



Da muß ich ganz ehrlich sagen, daß ich froh bin, so ein Monster nicht warten zu müßen.
Und um einen Entwickler zum Denken zu bewegen, sollte es nicht notwendig sein, ihn zum XtremeModularisierer zu verdammen. Modularität ja, aber bitte nur da, wo es auch wirklich Sinn macht. Einzeiler auszulagern gehört m.E. nur sehr selten zu dieser Gattung "sinnvoll".

Grüße
lr


----------



## Gast (Version2) (15. Nov 2007)

> Einzeiler auszulagern gehört m.E. nur sehr selten zu dieser Gattung "sinnvoll".




```
public void bla(String s) {
    if (s != null && !s.trim.equals("")) { // So oder in Varianten hundert mal programmiert...)
        // bla
    } else {
        // bla
    }
}
```

obwohl Einzeiler koennte doch folgendes besser sein oder ?


```
// in einer Klasse StringHelper
public static boolean isEmpty(String s) {
    return s != null && !s.trim.equals("");
}

public void bla(String s) {
    if (StringHelper.isEmpty(s)) {
        // bla
    } else {
        // bla
    }
}
```

Ein Beispiel fuer sinnvolles auslagern...

Ein weiteres Argument fuers auslagern. Der fachliche Ablauf in einer Methode ist schnell und sehr einfach zu überblicken. Es langt z.B. beim die Debuggen einfach die Bedingung zu evaluieren, um zu testen ob sie richtig ist. (Intellij kann so was, ob eclipse das auch beherrscht weiss ich nicht). Falls eine Bedingung fehlerhaft ist kann diese gezielt(!) debugt werden und insbesondere auch relativ einfach fachlich getestet werden.




> Und dann noch einen Methodennamen in Form einer Verneinung zu wählen (isNotMin), trägt zum Unverständnis noch das übrige bei. Warum hier nicht einfach die Methoden der Klasse Math genommen wurden ist auch nicht einleuchtend.



Korrekt Verneinung sollten vermieden werden. Aber sind manchmal nicht zu umgehen. Insbesondere wenn der If Zweig nicht leer sein darf (anderer Teil des Code Guides).

Math wurde nicht benutzt, da es sich um ein konstruiertes sehr einfaches Bsp. handelt...




> Eine eigene Methode für bla == null zu schreiben, sorry wenn ich das jetzt so sage, ist m.E. so sinnfrei wie es eben nur sein könnte.



Im Rahmen der vorgenommenden Spezifikationen und Richtlinien ist es die logische Konsequenz, d.h. wenn man keine Ausnahmen zulassen moechte ist dies ein notwendiges übel.


----------



## SlaterB (15. Nov 2007)

> StringHelper.isEmpty(s)

so eine Operation verwende ich auch,
es gibt selbstverständlich sinnvolle Anwendungen

> Verneinung sollten vermieden werden. Aber sind manchmal nicht zu umgehen. Insbesondere wenn der If Zweig nicht leer sein darf 

um bei obigen Beispiel zu bleiben, ich verwende sehr oft

if (!StringHelper.isEmpty(s)) { 
}

wäre dir das auch schon nicht mehr akzeptabel?
Hilfsoperationen immer positiv formulieren, Negation mit !


> wenn man keine Ausnahmen zulassen moechte ist dies ein notwendiges übel.

was gegen die vorgenommende Spezifikationen spricht


----------



## Saxony (15. Nov 2007)

SlaterB hat gesagt.:
			
		

> um bei obigen Beispiel zu bleiben, ich verwende sehr oft
> 
> if (!StringHelper.isEmpty(s)) {
> }



Rüschdüsch! Ich bastel meine If Bedingung auch immer so, dass ich den Hauptteil im IF Block abarbeite und deshalb meist gar kein else Block mehr brauche.

bye Saxony


----------



## Guest (15. Nov 2007)

> > StringHelper.isEmpty(s)
> 
> so eine Operation verwende ich auch,
> es gibt selbstverständlich sinnvolle Anwendungen
> ...



Es gibt tatsaechliche eine Methode 


```
public static boolean isNotEmpty(String s) {
    return !isEmpty(s);
}
```

Begruendung:

Es hat sich leider gezeigt das ein "!" sehr leicht uebersehen werden kann... Ausserdem im Sinne der Spezifikation ist auch dies zwingend...

Aber auch fachlich sinnvoll denn machmal kann man einen Ausdruck nicht einfach verneinen, um die richtige fachliche Verneinung zu erhalten. Sprich der Entwickler soll sich aktiv damit auseinandersetzen, ob die Verneinung wirklich nur "!" ist oder ob es komplexer ist.

Das Argument das ein Entwickler das einfach hinschreibt trifft natuerlich auch hier zu. Es hat sich in der Praxis aber bisher nur selten gezeigt. Insbesondere in Stresssituatioen neigt man allerdings dazu.


----------



## lhein (15. Nov 2007)

Gast (Version2) hat gesagt.:
			
		

> > Einzeiler auszulagern gehört m.E. nur sehr selten zu dieser Gattung "sinnvoll".
> 
> 
> 
> ...



In dem Fall gebe ich Dir natürlich recht, aber das ist bei mir nicht unter Kategorie Einzeiler geführt, auch 
wenn Du es in eine Zeile geschrieben hast. 
Ein klassischer Einzeiler ist:

```
if (objectA != null)
```
.
Ich bin jedenfalls kein Freund von bildschirmfüllenden if-Bedingungen, da sind wir uns denke ich beide einig.
In solchen Fällen gehört ausgelagert.

Gruß
lr


----------



## SlaterB (15. Nov 2007)

Anonymous hat gesagt.:
			
		

> Es hat sich leider gezeigt das ein "!" sehr leicht uebersehen werden kann...


diese Einstellung kann ja nur dazu führen, das ! im gesamten Projekt zu verbieten,

und das bei einem solchen elementaren Bestandteil der Sprache..,
so entfernt man sich immer mehr vom normalen Java, genau wie sich die Baden-Württenberger vom Hochdeutsch entfernen,
ist auch eine Sprache und in Baden-Württenberg versteht man sich,
aber lebensfähig in Gesamtdeutschland ist man damit eher nicht


----------



## tfa (15. Nov 2007)

Saxony hat gesagt.:
			
		

> tfa hat gesagt.:
> 
> 
> 
> ...



Ich schrieb Array.sort(Object[]), dort wird ein modifiziertes Merge-Sort -- nicht Quicksort -- verwendet (Insertion-Sort war falsch, keine Ahnung, wie ich darauf gekommen bin). Bei einigen anderen Sortier-Routinen (die für die primitiven Datentypen) wird in der Tat ein Quicksort verwendet. Dies macht man, da das Sortiererfahren hier nicht unbedingt stabil sein muss (im Gegensatz zu Object[]), was Introsort auch nicht ist.


----------



## Gast(Version2) (15. Nov 2007)

> Ich bin jedenfalls kein Freund von bildschirmfüllenden if-Bedingungen, da sind wir uns denke ich beide einig.
> In solchen Fällen gehört ausgelagert.



Das Problem an der Sache ist, dass die meisten Entwickler die ich bisher kenngelernt habe eher dazu neigen viel zu spaet auszulagern. Des wegen diese "harten" Regelungen. Damit der Entwickler klare Strukturen hat.

Zu "!" und "== null" und "!= null" etc.. Natuerlich ist das auf den ersten Blick hoest ungewoehnlich. Aber hier mal etwas zum Nachdenken. Der unterschied zwischen == null und == null.


```
...
Person person = getPerson(id)
if (person == null) {
....
```

Eigentlich wird hier nicht auf null geprueft sondern es fehlt eine Methode


```
...
if (existPerson(id)) {
....
```

2. Beispiel

```
public void bla(Person person) {
    if (person == null) {
    ...
}
```


```
public void bla(Person person) {
    if (ObjectHelper.isAssigned(person)) {
....
```

Beides Mal wird eigentlich auf == null geprueft. Es gibt aber erhebliche fachliche Unterschiede.


----------



## SlaterB (15. Nov 2007)

auch dieses Beispiel ist verständlich, auch ich benutzt sehr oft contains(objekt) statt get(object) == null,
eine weltbekannte Buchstabenfolge in Java, ein Standard, kein Argument für deine Seite


----------



## Gast Version2 (15. Nov 2007)

Hab gerade festgestellt das natuerlich


```
Person person = getPerson(id) 
if (person == null) { 
....
```


```
... 
if (existPerson(id)) { 
....
```

was anderes ist. (Verneinung fehlt)  Aber die Intention sollte klar sein...


----------



## lhein (15. Nov 2007)

Gast(Version2) hat gesagt.:
			
		

> ```
> ...
> Person person = getPerson(id)
> if (person == null) {
> ...



Das sehe ich ein wenig anders. Die Aussage der Methode existsPerson(id) ist schlicht nicht eindeutig.
Was würde diese Methode denn im Falle einer Exception zurückliefern? true oder false?
Viel mehr müßte der Code so aussehen:


```
Person person = null;
if (storage.isPersonExisting(id))
{
    person = storage.getPerson(id);
    if (person == null) 
    {
         ....person konnte wegen exception nicht ermittelt werden....handling folgt
    }
}
else
{
    ...person existiert nicht im storage...fehlermeldung
}
```

Du kannst in der einen Methode einfach nicht zwei fachliche Aspekte unterbringen, es sei denn Du betreibst es über das kontrollierte Werfen und Weitergeben of aussagekräftigen Exceptions.

Aber das ist nur meine Meinung, andere sehen das vielleicht auch anders 

Gruß
lr


----------



## maki (15. Nov 2007)

existsPerson(id) wird eindeutigerweise eine true oder false liefern, ansonsten braucht jemand einen Englischkurs.

Eine Exception wäre möglich wenn zB. die DB nicht gefunden wird und dann gibt's ja auch keinen Rückgabewert.
Allerdings sollte es keine Exception geben wenn die Person nicht gefunden wird, ist ja schliesslich keine Ausnahme wenn man schon fragt ob's die gibt sondern eine mögliche gültige Antwort  

Ob getPerson(id) eine Exception wirft wenn die Person nicht existiert ist Frage der Definition, würde sagen ja wenn es schon eine existsPerson(id) Methode gibt, besserer Code.
Fange ja schliesslich auch keine IndexOutOfBoundException wenn ich durch ein Array/Collection iteriere sondern prüfe vorher ob's Sinn ergibt ein next() aufzurufen.


----------



## Gast (Version2) (15. Nov 2007)

Erstmal Danke an alle die sich bisher vernueftig an dieser Diskussion beteiligt haben.

Meine Intention war es Argumente gegen bzw. fuer den Code Style zu erhalten und mir selbst nochmal bewusst zu machen, wieso ich diesen Code Still verwende bzw. verwenden lasse...

Ein abschliessendes Argument fuer die strikte Auslagerung in Methoden.


Bedingungen sind haeufig fachliche Bedingugen (Ausnahme technische Infrastruktur z.B. DB Zugriffe etc.).
Sprich die Umsetzung von fachlichen Aspekten in Code.

goldene Regel:
Jede fachliche Regel (Bedingung etc.) sollte lediglich genau einmal gecodet werden. Die Vorteile liegen auf der Hand. Wartbarkeit etc.

Ich hoffe da kann jeder zustimmen...

Folge:
Es muss zwangslaeufig, wenn die Bedingungen wiederverwendet werden sollen eine irgendwie geartete Auslagerung erfolgen. Dies sollte natuerlich klar geregelt sein.

Fazit:

Wenn ein Entwickler auf die Auslagerung verzichtet und ein anderen Entwickler z.B. an der Object Schnittstelle nachschaut, ob die von ihm benoetigte Bedingung schon existiert wird er sie nicht finden, weil Sie irgendwo in den tiefen des Codes versteckt ist. Also wird er sie doppelt implementieren. Was das fuer Auswirkungen auf den Code hat kann sich glaube ich jeder vorstellen. Insbesondere bei fachlichen Aenderungen...

Also steht fuer mich fest: 

Lieber einmal zuviel auslagern als einmal zu wenig....


----------



## Saxony (15. Nov 2007)

Yep,

ich trinke aber lieber ein Lager. 

bye Saxony


----------



## SlaterB (15. Nov 2007)

wie bei dem contains bzw. exists-Beispiel ziehst du schon wieder ungebührliche Beispiele heran,

nur weil es Sinn macht, dass ein Auto Räder hat, kann man doch nicht sagen, dass jedes Fortbewegungsmittel (auch Schuhe) Räder brauchen,

nur weil es völlig richtigerweise bei emptyString, exists und fachlichenen Regeln Auslagerungen gibt,
ist das Konzept isNull(x) statt x == null doch nicht besser begründet,

die angegeben Beispiele machen Sinn, nicht nur in deinem Stil, nicht nur in Java, nicht nur beim Programmieren, nicht nur auf dem Planeten Erde

trotzdem kann man isNull(x) oder isNotMin(x,y) als gekünzelten Schwachsinn bezeichnen


----------



## Marco13 (15. Nov 2007)

maki: _Solange die Performance nicht nachprüfbar ein Problem darstellt, hat man sie gefälligst zu ignorieren und den einfachsten Code zu schreiben der möglich ist. _

In mancher Hinsicht (bzw. in den meisten Hinsichten) stimmt das. Aber NICHT in diesem Fall. Es ist in diesem Fall sogar absolut unsinnig. Man sollte auf keinen Fall eine einfache Aufgabe dadurch lösen, dass man eine (in bezug auf die asymptotische Laufzeit) VIEL schwerere Aufgabe löst, nur weil man bei der Lösung der schweren Aufgabe die Lösung der einfachen Augabe mitgeliefert bekommt  :noe:  (Kein Mensch würde auf die hinrissige Idee kommen, eine Minimumsuche über eine Sortierung zu lösen, wenn Java nicht netterweise die Methode Arrays.sort anbieten würde...)

Knuth's "premature optimization" ist etwas anderes: Man sollte nicht irgendwelche krampfig-unverständlichen Sachen schreiben, weil sie vielleicht 3% schneller sind als die verstänliche Lösung. Optimiert wird das, wovon der Profiler sagt, dass es optimiert werden muss. Das heißt aber nicht, dass man sich beim Schreiben nicht um Laufzeiten scheren oder sich nicht über eine gute (angemessene!) Lösung des Problems Gedanken machen sollte.



Saxony: _Wenn häufig gesucht werden muss, aber das Feld sich selten ändert, so ist es doch besser dieses jedes Mal zu sortieren bei Änderungen. _

Das ist klar. Hat aber keinen Einfluss auf die Aussage, die ich gemacht hatte. Sortieren dauert im allgemeinen länger, aber immer _mindestens_ genauso lange, wie die Minimumsuche. (Man könnte ja auch erwähnen: Wenn sich immer nur sehr wenige Elemente ändern, ist Bubblesort besser als Quicksort. Aber von Sonderfällen war ja erstmal nicht die Rede)



Zu der Frage, welche if-Abfragen man in eine Methode packt und welche nicht: Ich finde, das muss man von Fall zu Fall entscheiden. (Dass mein Witz(!) mit dem extrem-Methoden-Aufdröseln auch noch ernsthaft in Erwägung gezogen wurde, beunruhigt mich etwas). 
In diesem speziellen Fall mal eine an die Verfechter der Methoden-Lösung gerichtete Frage: Welchen Vorteil hat es, die Methode "isNotMin" o.ä. in eine einzelne Methode zu packen? Eine Methode, die nur aus EINER Zeile besteht, und nur in EINER anderen Methode aufgerufen wird, macht IMHO keinen Sinn.

Wenn man sich so eine Methode ansieht....

```
/** 
 * Returns 'true' if the given 'currentMin' is null, or if the given 'number' is
 * greater than the given 'currentMin'
 *
 * @param currentMin Double The current minimum value
 * @param number Double The number to compare with the currentMin
 * @returns 'true' if the given 'currentMin' is null, or if the given 'number' is
 * greater than the given 'currentMin'
 */
private static boolean isNotMin(Double currentMin,Double number) 
{
    return currentMin == null || currentMin > number;
}
```
und sich beim drüberlesen und nachvollziehen erstmal spontan fragt: "Warum packt jemand so einen Scheiß in eine eigene Methode?", dann in der "min"-Methode nachsieht und erkennt, wofür die gut sein soll, sich dann aber noch fragen muss, was das mit dem Double und der null-Abfrage für einen Zweck hat, und ob die min-Methode vielleicht auch 'null' zurückliefern kann usw., dann ist das Argument "Man sieht schneller, was dort gemacht wird" schon hinfällig - und dann wäre mir eine klare, einfache Methode wie

```
/** 
 * Returns the minimum element of the given array
 * (+vorbedinungen...)
 *
 * @param z double The array whose minumum element will be returned
 * @returns the the minimum element of the given array
public static double Wertemin (double z[]) 
{ 
...
}
```
doch deutlich lieber....


----------



## maki (15. Nov 2007)

> In mancher Hinsicht (bzw. in den meisten Hinsichten) stimmt das. Aber NICHT in diesem Fall. Es ist in diesem Fall sogar absolut unsinnig. Man sollte auf keinen Fall eine einfache Aufgabe dadurch lösen, dass man eine (in bezug auf die asymptotische Laufzeit) VIEL schwerere Aufgabe löst, nur weil man bei der Lösung der schweren Aufgabe die Lösung der einfachen Augabe mitgeliefert bekommt noe.gif (Kein Mensch würde auf die hinrissige Idee kommen, eine Minimumsuche über eine Sortierung zu lösen, wenn Java nicht netterweise die Methode Arrays.sort anbieten würde...)


Sorry Marco13, aber das sehe ich anders.

Performance Optimierungen dieser Art sind imho in 90% der Fälle rein akademischer Natur ohne wirklich die Performance zu verbessern, intellektuelle Selbstbefriedigung eben. Klar machst Spass, aber bringen tut's meistens nix und wichtig ist es schon mal gar nicht, echte Probleme gibt's dafür meistens genügend.

Wenn man natürlich vorher genau weiss, das diese Methode sehr häufig für sehr große Arrays aufgerufen wird, ist es nicht verkehrt sich darüber gedanken zu machen.
Aber wenn diese Optimierung nicht getestet und die Laufzeiten nicht verglichen werden, glaubt man doch nur die Performance verbessert zu haben ohne es wirklich zu wissen -> Hirnrissig 

Davon abgesehen denke ich bei begriffen wie "Minimum" immer sofort an Vergleichen, Größer/kleiner, Reihenfolge, etc. -> Sortierung ist imho nicht abwegig.

Dazu kommt das Arrays.sort() teil der Standard API ist und solange es keine guten Gründe gibt davon abzuweichen, sollte man auch nicht abweichen.

Ein Beispiel das ich bereits so erlebt habe:
Ein selbstgeschriebenes Java Framework das seine eigene "performante" String Implementierung hatte (mutables), komischerweise gab's nach der Umstellung auf standard Strings keine messbaren nachteile, nur weniger Code zum warten.


----------



## SlaterB (15. Nov 2007)

wenn dir ohne Gegenargument ein besseres Programm nicht gefällt,
dann ist das eine Ansicht, der man nicht mehr logisch widersprechen kann, 
aber an Knuth's "premature optimization" (von Marco13 zitiert) solltest du dann nicht mit deinem Satz
'Frühzeitige Optimierung ist die Wurzel allen übels' erinnern,
sondern eher deine persönliche Sondermeinung ausdrücken 

du würdest wohl auch eine Queue in einer ArrayList bauen und ja nie sowas schräges wie eine LinkedList erfinden.. 
(wenn es sie nicht schon gäbe)


wozu eigentlich HashMap und sich über komplizierten hashCode() Gedanken machen? Liste mit contains gibts ja auch..


----------



## maki (15. Nov 2007)

> wenn dir ohne Gegenargument ein besseres Programm nicht gefällt,
> dann ist das eine Ansicht, der man nicht mehr logisch widersprechen kann,


Ich dachte eigentlich das ich Argumente gebracht hätte die meine Position erklären SlaterB.



> aber an Knuth's "premature optimization" (von Marco13 zitiert) solltest du dann nicht mit deinem Satz
> 'Frühzeitige Optimierung ist die Wurzel allen übels' erinnern,
> sondern eher deine persönliche Sondermeinung ausdrücken


Meine "persönliche Sondermeinung" muss ja nicht zwangsläufig falsch sein.

Aber werfen wir doch einen Blick auf das Original von Knuth, vielleicht fällt dir ja etwas auf:


> There are many senses in which a program can be
> "good," of course. In the first place, it's especially good
> to have a program that works correctly. Secondly it is
> often good to have a program that won't be hard to
> ...



Tatsache ist doch, das es bis jetzt weder den Beweis gibt, das Arrays.sort() wirklich zu Performanceverlust führt, noch das die "performante" Lösung wirklich auch performant ist.

Messen ist der einzige Weg, alles andere ist "aberglauben".



> du würdest wohl auch eine Queue in einer ArrayList bauen und ja nie sowas schräges wie eine LinkedList erfinden..
> (wenn es sie nicht schon gäbe)


Nee, würde ich nicht.
Wenn's keine LinkedList gäbe, sollte man eine schreiben 



> wozu eigentlich HashMap und sich über komplizierten hashCode() Gedanken machen? Liste mit contains gibts ja auch..


Warum implementierst du dann nicht deine eigene, "gute" hashCode() Methode wo doch schon lange klar ist das die Standard Methode so "unperformant" ist???


----------



## SlaterB (15. Nov 2007)

> jetzt weder den Beweis gibt, das Arrays.sort() wirklich zu Performanceverlust führt, noch das die "performante" Lösung wirklich auch performant ist. 

wenn du es nicht glaubst, dir allgemeiner Menschenverstand und O(n log n) vs O(n) nicht reichen,
dann solltest du wirklich sortieren und damit zufrieden sein,

bisher war deine Argumentation ja eher, dass es schneller ist, aber diese Geschwindigkeit die zwei Zeilen nicht wert sind
('Performance Optimierungen dieser Art sind imho in 90% der Fälle rein akademischer Natur', 'wichtig ist es schon mal gar nicht')

wenn du nun aber gar bezweifelst, dass es schneller ist, dann braucht man nicht weiter drüber nachdenken,
dich davon zu überzeugen ist mir die Mühe nicht wert

-------

bei deinem Blick fällt mir nix auf, außer dass es die Meinung von Marco13 genau widergibt:
viel Programmieraufwand + unleserlichen Code für 3% Geschwindigkeit wäre Quatsch,
<->
ein logisch einfaches simples Verfahren in 3 Zeilen statt ein einzelner Aufrufes, der eine Zeile spart aber den Rechner tausende unnötige Operationen ausführen lässt, ist sinnvoll

> Wenn's keine LinkedList gäbe, sollte man eine schreiben 

dann bist du in inkosequent, in diesem Fall auf der richtigen Seite,
dann weiß ich auch nicht weiter

> Warum implementierst du dann nicht deine eigene, "gute" hashCode() Methode wo doch schon lange klar ist das die Standard Methode so "unperformant" ist???

weder finde ich hashCode() schlecht noch wußte ich bisher, dass sie unperformant ist?


----------



## maki (15. Nov 2007)

> wenn du es nicht glaubst, dir allgemeiner Menschenverstand und O(n log n) vs O(n) nicht reichen,
> dann solltest du wirklich sortieren und damit zufrieden sein,


Der allgemeine Menschenverstand neigt dazu, Details auszulassen, die unter Umständen wichtig sind.
Wie groß ist denn das Array?

Vielleicht sollten Leute mehr profilen, nur um zu sehen, was ihre sog. Optimierung wirklich gebracht hat.

Könnte dir auch ein Beispiel nennen, in dem Strings per plus aneinanderzuhängen schneller ist, als Stringbuilder/Stringbuffer zu verwenden, besser lesbar ist es auch noch.



> bisher war deine Argumentation ja eher, dass es schneller ist, aber diese Geschwindigkeit die zwei Zeilen nicht wert sind
> ('Performance Optimierungen dieser Art sind imho in 90% der Fälle rein akademischer Natur', 'wichtig ist es schon mal gar nicht')


Gind davon aus, dass es wahrscheinlich schneller wäre, der Aufwand aber nicht lohnt, solange nicht klar ist, das man die Performance auch wiklich verbessert -> messen

Es als "Hirnrissig" zu bezeichnen die sort Methode einzusetzen ist imho wirklich daneben, solange man keine reproduzierbaren Ergebnisse hat die das auch belegen.



> wenn du nun aber gar bezweifelst, dass es schneller ist, dann braucht man nicht weiter drüber nachdenken,
> dich davon zu überzeugen ist mir die Mühe nicht wert


Das es theoretich zwar schneller laufen würde ist klar, ob es in der Praxis einen Unterschied macht ist eine andere Frage.




> bei deinem Blick fällt mir nix auf, außer dass es die Meinung von Marco13 genau widergibt:
> viel Programmieraufwand + unleserlichen Code für 3% Geschwindigkeit wäre Quatsch,
> <->
> ein logisch einfaches simples Verfahren in 3 Zeilen statt ein einzelner Aufrufes, der eine Zeile spart aber den Rechner tausende unnötige Operationen ausführen lässt, ist sinnvoll


Beim ersten Punkt stimme ich voll zu, beim zweiten lässt sich das aber nicht pauschal beantworten.

Der Threadtitel ist Codequalität, dass lässt sich so definieren:
1. Richtig funktionierender Code
2. Wartbarer Code
3. Performanter Code

Oft wird die Reihenfolge durcheinander gebracht.

Übrigens war es Beni, der als erstes das Argument brachte:


> ("No premature optimization" hat schon seine Berechtigung, aber wenn man zwei ähnlich übersichtliche Varianten hat, gibt es keinen Grund die langsamere zu wählen.)


Daraufhin kam meine Frage: "Warum denn nicht sortieren?"



> weder finde ich hashCode() schlecht noch wußte ich bisher, dass sie unperformant ist?


Bloch hat es in "Effective Java" mal kurz angerissen:



> ```
> // Lazily initialized, cached hashCode
> private volatile int hashCode = 0; // (See Item 48)
> public int hashCode() {
> ...


Speziell bei Strings scheint dieses vorgehen nicht optimal zu sein, aber für mich reichts allemal 


Was ich rüberbringen wollte war folgendes: Es mag sicherlich "besser" sein nicht zu sortieren, ob dieses "besser" auch in der Realität sich besser auswirkt als zu sortieren, ist nicht bewiesen.

Ich hoffe Marco13 hat meine Aussage nicht als persönlichen Angriff aufgefasst, falls doch war es sicher nicht so gemeint.


----------



## SlaterB (15. Nov 2007)

> Wie groß ist denn das Array? 
> Vielleicht sollten Leute mehr profilen, nur um zu sehen, was ihre sog. Optimierung wirklich gebracht hat. 

inwiefern ist hier denn die Größe wichtig?
bei kleinen Arrays siehts für sort auch nicht rosig aus,
da überwiegt allein schon der schwerfällig Anlauf, 
Arrays.sort() klont das Array, führt zahllose Unteroperation aus, erstellt zahllose lokale Variablen, Laufvariablen usw

tausende Dinge laufen unnötig im Hintergrund ab,

dagegen steht eine einzelne Schleife und 1-2 lokale Variablen,
der gesamte Ablauf in 3-4 Zeilen Code,

kürzer, schneller, ressourcenschonender, in jeder Hinsicht optimal


----------



## maki (15. Nov 2007)

> inwiefern ist hier denn die Größe wichtig?
> bei kleinen Arrays siehts für sort auch nicht rosig aus,
> da überwiegt allein schon der schwerfällig Anlauf,
> Arrays.sort() klont das Array, führt zahllose Unteroperation aus, erstellt zahllose lokale Variablen, Laufvariablen usw


Wenn es sich um große Datenmengen handelt und diese Methode sehr häufig aufgerufen wird, lohnt es sich darüber Gedanken zu machen, ansonsten eher nicht.
Aber solange nicht gemessen wurde, reden wir hier nur über Kopfgeburten.

Eine Methode die nur 3 mal am Tag benutzt wird zu optimieren macht wirklich nur Sinn, wenn sie vorher eindeutig zu langsam war.
Ob es sonst nun 10 Microsekunden sind oder gar 60 macht ansonsten keinen Unterschied, weder subjektiv noch objektiv.


----------



## SlaterB (15. Nov 2007)

du schwankst immer hin und her,
was du da zitierst habe ich geantwortet, weil du Randbedingungen ins Spiel brachtest 
('Der allgemeine Menschenverstand neigt dazu, Details auszulassen, die unter Umständen wichtig sind. 
Wie groß ist denn das Array?')

aber gut, vielleicht meintest du damit nicht, dass sort() bei kleinen Arrays besser dasteht, 
sondern dass die Arrays so klein sind, dass es egal ist was man benutzt,
dann wäre die Diskussion in der Richtung in der Tat nutzlos

bleibt noch deine Grundaussage 'Eine Methode die nur 3 mal am Tag benutzt wird zu optimieren'
was nun Interpretation ist,

für mich sind diese 3-4 Zeilen keine aufwändige Programmierung, nichts was man im Sinne des Bären Knuts als 'Optimierungsarbeit' 
bezeichnen müsste,

es ist ganz einfach die natürliche Wahl, so wie man für ein Queue kurz überlegt und dann LinkedList statt ArrayList wählt,
auch dort mag es egal sein, aber was spricht dagegen?,
es ist einfach falsch hier von verschenkter Arbeit zu sprechen, das programmiert sich doch von selbst

um wieder bei Beni zu sein:



> wenn man zwei ähnlich übersichtliche Varianten hat, gibt es keinen Grund die langsamere zu wählen.



es sei denn natürlich, du siehst 




> double min = z[0];
> for (int i = 1; i < z.length; i++) {
> if (z_ < min)  {
> min = z;
> ...


_
als schwierigen Code an, den man eine halbe Stunde erarbeiten und besser noch testen müsste,
dann passt das langsam, dann lieber beim sort() bleiben  :bae: (gemein, ich weiß)_


----------



## maki (15. Nov 2007)

> du schwankst immer hin und her,


Ne, ich glaub wir vestehen uns grad nur nicht richtig.



> aber gut, vielleicht meintest du damit nicht, dass sort() bei kleinen Arrays besser dasteht,
> sondern dass die Arrays so klein sind, dass es egal ist was man benutzt,
> dann wäre die Diskussion in der Richtung in der Tat nutzlos


Ganz genau, jetzt verstehen wir uns wieder.



> bleibt noch deine Grundaussage 'Eine Methode die nur 3 mal am Tag benutzt wird zu optimieren'
> was nun Interpretation ist,
> 
> für mich sind diese 3-4 Zeilen keine aufwändige Programmierung, nichts was man im Sinne des Bären Knuts als 'Optimierungsarbeit'
> ...


_
Ich seh ja ein es kein großer Aufwand ist und selbst der Code nicht groß oder unverständlich ist, allerdings ist es sicherlich auch kein kapitaler Fehler, da eine zugegebenermaßen überproportionierte aber bereits vorhande Standardfunktion zu benutzen.

Da brauch mir dann keine Gedanken machen in wieviele Methoden ich das aufbrechen will und Bugs kann ich schon mal gar keine einbauen 

Abgesehen davon ist Performance ist massiv überbewerted.
Leute vergessen gerne das die Hardware preise so niedrig sind, das oft ein neuer Rechner billiger kommt als ein Entwickler der optimiert._


----------



## Marco13 (16. Nov 2007)

Langsam wirken die Rechtfertigungsversuche trotz der zitierten schlauen Bücher ziemlich hilflos. Jetzt fehlt nurnoch das Argument: "Java ist ja sowieso SO langsam, da kommt's auf so ein kleines 'sort' auch nicht mehr an"  :lol: 

Aber erstmal kurz zu dem hashCode-Geplenkel: Ich nehme an, SlaterB's Aussage bezog sich nicht darauf, dass hashCode ineffizient ist (und was mit der geposteten Hashfunktion ausgedrückt werden sollte, ist mir auch nicht ganz klar) sondern eher darauf, dass man ja keine Hashsets oder HashMaps braucht: Das kann man ja alles über ArrayListen abbilden. Ein contains hat auf einer ArrayList zwar O(n), und bei einer HashSet nur O(1), aber ... die Laufzeit ist ja egal :wink:

Und das ist auch der Kern meiner Kritik: Unter "premature optimization" würde man (ich) eher sowas verstehen, wie etwa die min-Methode nicht so zu schreiben

```
int min = z[0];
for (int i = 1; i < z.length; i++) 
{
    if (z[i] < min) 
    {
        min = z[i];
    }
}
return z[min];
```
sondern so

```
double min = z[0];
for (int i = 1; i < z.length; i++) 
{
    min = Math.min(min, z[i]);
}
return min;
```
um die überflüssigen Arrayzugriffe zu sparen. (Wobei das imho garnicht mal so "premature" wäre - die Bedingung ist ganz toll in eine Methode ausgelagert, es ist übersichtlicher, und behandelt NaNs richtig...  :roll: )

Was aber dafinitiv NICHT in den Bereich der premature optimization fällt, ist die Wahl des richtigen Algorithmus für die Lösung eines Problems. Und Sortieren für eine Minimumsuche ist in diesem Sinne mit Sicherheit "falsch". (Oder meinst du, D.E.Knuth hätte einen 500-Seiten-Hardcode-Mathe-Wälzer über Sorting and Searching verfasst, wenn er der Meinung wäre, man könnte "einfach alles irgendwie sortieren (so, wie es die API eben gerade anbietet)"?

Oder anders forumiert: Eine Minimumsuche über eine simple Schleife (und NICHT über eine Sortierung) zu implementieren ist für mich keine Optimierung, sondern selbstverständlich.


----------



## Saxony (16. Nov 2007)

Marco13 hat gesagt.:
			
		

> ```
> int min = z[0];
> for (int i = 1; i < z.length; i++)
> {
> ...



Ähm hier am Ende doch nur return z 



			
				Marco13 hat gesagt.:
			
		

> ```
> double min = z[0];
> for (int i = 1; i < z.length; i++)
> {
> ...



Ich würde sogar noch folgendes einbauen:


```
double min = z[0];
final int len = z. length;
for (int i = 1; i < len; i++) 
{
    min = Math.min(min, z[i]);
}
return min;
```


bye Saxony


----------



## Gast (16. Nov 2007)

> Der Threadtitel ist Codequalität, dass lässt sich so definieren:
> 1. Richtig funktionierender Code
> 2. Wartbarer Code
> 3. Performanter Code
> ...



Das kann ich so nur absolut bestaetigen.

Mal ein Praxisbeispiel:

Es ging darum etwa 40000 Kunden zu verwalten. Bestellungen erstellen usw.

Der fachliche Code wurde großteils in Java implementiert. Leider kam jemand auf die absolute Topidee aufgrund der Datenmengen doch auch Storedprozedure in bestimmten Bereichen einzusetzen.

Das fuehrte dazu das ein Teil der Fachlichkeit sowohl in SQL als auch Java gekodet wurde. Erschwerend kam hinzu das die fachlichen Anforderungen sich durchaus von einem auf den anderen Tag geaendert haben. Dies fuehrte zu einem nicht mehr wartbaren Mix aus Java und Sql bzw. PL/SQL....

Der Hohn an der Sache... Wir haben uns dann mal hingesetzt und eine der angeblich mit java so langsamen Prozesse in Java ohne auf irgendwelche performanten Strukturen zu achten codiert. Ergebnis der Prozess lief etwa eine Stunde. Mit Stored Prozedure etwa 40 Minuten .... und sollte einmal taeglich ablaufen.... MEHR FAELLT MIR ZUM THEMA PERFORMANCE IST JA SO WICHTIG NICHT EIN!!!!!!!!!!!!

Sprich das Projekt wurde fuer 20 Minuten Laufzeit eines Prozesses gegen die Wand gefahren....

Wenn das Performace Problem auftritt, dann kann man es auch loesen ohne dafuer irgendwelche komischen Verrenckungen machen zu muessen...

Wie jemand anderes schon sagte: Meist gibt es genuegend andere Probleme zu loesen als die Performance...


----------



## der JoJo (16. Nov 2007)

mann sollte sich dennoch bei so kleinen ELEMENTAREN methoden wie der beispiel methode gedanken über performance machen, weil eine performance steigerung nach abschluss eines Projektes schwerer ist (und schlimmeren code prodoziert) als einfach während der entwicklung ein klein wenig darauf zu achten.

Wenn man immer mit der einstellung "Performance ist erstmal egal" rann geht, steht man am ende des Projektes unter umständen vor dem riesigen problem jede funktion nochmal durchgehen zu müssen, um solche performance schlucker wie die beispielmethode zu finden und zu beheben.


----------



## maki (16. Nov 2007)

@Marco13


> Langsam wirken die Rechtfertigungsversuche trotz der zitierten schlauen Bücher ziemlich hilflos. Jetzt fehlt nurnoch das Argument: "Java ist ja sowieso SO langsam, da kommt's auf so ein kleines 'sort' auch nicht mehr an" icon_lol.gif


Vielleicht gibt's ja doch noch Hoffnung für dich...

Bis jetzt ist dein einziges Argument: Performance

Richtig?

Ich vertrete die Meinung: Performance ist Nebensache.


> Was aber dafinitiv NICHT in den Bereich der premature optimization fällt, ist die Wahl des richtigen Algorithmus für die Lösung eines Problems. Und Sortieren für eine Minimumsuche ist in diesem Sinne mit Sicherheit "falsch". (Oder meinst du, D.E.Knuth hätte einen 500-Seiten-Hardcode-Mathe-Wälzer über Sorting and Searching verfasst, wenn er der Meinung wäre, man könnte "einfach alles irgendwie sortieren (so, wie es die API eben gerade anbietet)"?


Wie gesagt, ich sehe das nicht als "falsch".
Lasse mich aber gerne jederzeit durch reproduzierbare Tests (am besten realistische) vom Gegenteil belehren.

Bis dahin sehe ich das als reines Scheinargument, die zwar theoretisch einen Unterschied machen würden, in der Praxis aber nicht zum tragen kommt.
An einer Uni wäre es natürlich ein "riesen" Fehler nicht den performantesten Algo einzusetzen.

Lass mich das konkretisieren: Wenn diese Methode ein zentrales Element darstellt welche oft und für jede mögliche größe von (double)Arrays eingesetzt wird, ist deine Lösung besser, ansonsten nicht, nur aufwändiger.

Die Methode ist nicht groß, trotzdem ist eigener Code immer aufwändiger als bestehenden zu verwenden, allein die Testcases wären größer als die eigentliche Methode.


@der JoJo


> mann sollte sich dennoch bei so kleinen ELEMENTAREN methoden wie der beispiel methode gedanken über performance machen, weil eine performance steigerung nach abschluss eines Projektes schwerer ist (und schlimmeren code prodoziert) als einfach während der entwicklung ein klein wenig darauf zu achten.
> 
> Wenn man immer mit der einstellung "Performance ist erstmal egal" rann geht, steht man am ende des Projektes unter umständen vor dem riesigen problem jede funktion nochmal durchgehen zu müssen, um solche performance schlucker wie die beispielmethode zu finden und zu beheben.


Wenn ich das so lese, bin ich mir sicher das du nicht für Geld programmierst, und wenn doch, dann noch nicht lange...

Ich habe in meinen 7+ Jahren Beruferfahrung kein einziges Projekt gesehen, das wegen der "schlechten" Performance fehlgeschlagen ist, weder hier noch in Übersee.

Zuerst kommt (richtige funktionsweise vorrausgesetzt) die Struktur, wenn diese gut ist, kann man jederzeit die Performance verbessern.

Ob diese Methode wirklich die Performance beeinflusst, lässt sich ohne testen sowieso nicht sagen.


----------



## der JoJo (16. Nov 2007)

maki hat gesagt.:
			
		

> Wenn ich das so lese, bin ich mir sicher das du nicht für Geld programmierst, und wenn doch, dann noch nicht lange...



zugegeben, ich programmiere erst seit 3 Jahren, aber ich beschäftige mich mit 3D Enginen entwicklung und kann daher sagen, das bei kleinen methoden die sehr häufig gerufen werden eine vorzeitige optimierung viel arbeit erspart.


----------



## RicoSoft (16. Nov 2007)

Mal so nebenbei: Wenn ich eine Methode habe, von der ich von vornhinein weiss, dass sie 20 Mio. mal aufgerufen wird, dann werd ich die ganz sicher optimieren. Man sollte Knuth nicht immer so schnell zitieren, ohne nicht auch seine ganzen Werke gelesen zu haben und dieses berühmte Zitat so frei im Raum stehen zu lassen.

Zurück zum Thema Codequalitaet: mir gefallen natürlich die ersten paar Zeilen um Welten besser, v.a. die korrigierte Version davon (vom Originalposter). Einfacher zu lesen, sehr einfach zu warten und definitiv sowieso unbrauchbar -- weil es dafür mit Sicherheit schon andere gibt, die das schon mal gemacht haben und man das folglich einfach von einer Library (auch die gigantische API der JDK muss man doch in der Zwischenzeit zu grossen Teilen als Library betrachten) reinnehmen kann.

Ich würde mehr Wert auf kurze, übersichtliche Klassen / Methoden legen, als darauf, alles auszucodieren. Auch sehr interessant ist sicherlich das definieren von pre-/post-conditions. Sowas kann man sehr schön kommentieren und mit Hilfe von Assertions oder ähnlichem sehr einfach überwachen.

Beim Codebeispiel 1 heisst es ja zum Beispiel, dass z nicht null sein kann, dann könnte man ja im Code ein 
	
	
	
	





```
assert z != null
```
 machen.

Und zu den gescheiterten Projekten anhand der Performance: Wenn die Projekte früher schon scheitern, dann wären sie vielleicht daran dann auch noch gescheitert. Man sollte nicht die Gründe für ein Scheitern nehmen, und sagen, dass sie darum an etwas anderem nicht gescheitert sind. Da wird eine Aussage umgekehrt, die so nicht umkehrbar ist. Man muss da sehr aufpassen. Die Projekte scheitern meistens zwar an Management und Terminproblemen anderer Art, aber sie kommen erst gar nie in ein Stadium, dass man so eine Aussage machen könnte.


----------



## maki (16. Nov 2007)

> zugegeben, ich programmiere erst seit 3 Jahren, aber ich beschäftige mich mit 3D Enginen entwicklung und kann daher sagen, das bei kleinen methoden die sehr häufig gerufen werden eine vorzeitige optimierung viel arbeit erspart.


OK, im Bereich 3D ist Performance sehr wichtig, dafür werden manchmal sogar Darstellungsfehler in Kauf genommen, wie früher(immer noch?) zB. bei NVIDIA.

Für "normale" Anwendungen dagegen spielt es wirklich nur noch eine untergeordnete Rolle. Fachliche Fehler sind dagegen kaum verzeihbar, da hast du dann mal schnell ein richtiges Drama am Hals wenn's schlecht läuft.


----------



## Marco13 (16. Nov 2007)

Naja. Es geht (mir) nicht um frühe (oder vorzeitige) Optmierungen. Und auch nicht darum, ob ein Programm nur 40 oder 60 Minuten braucht. Es geht auch nur bedingt um Performance. Es geht (und ich weiß, dass du das jetzt als Anlaß zur gegen-Kritik sehen wirst) nicht zuletzt ganz einfach ums _Prinzip_.

Diejenigen, die bestimmte (meintetwegen "akademsiche") Qualitätsansprüche an ihre Software stellen, werden mich verstehen. Diejenigen, die (im Gegensatz zu mir) ausschließlich in der freien Wirtschaft (d.h. für die Industrie) arbeiten, werden mich vielleicht auch verstehen, aber AUCH den anderen Standpunkt, dass man eben manchmal was Hacken (sorry: "besonders kurz schreiben") muss, um Zeitvorgaben einzuhalten (ob sich DAS in diesem Beispiel lohnt, ist eine andere Frage). 

Bisher wissen wir nicht, wie groß die übergebenen Arrays sind. Wir können davon ausgehen, dass sie klein sind, und die Aufgabe lösen, indem wir 2 Zeilen code schreiben und "sort" verwenden. Oder wir können universell einsetzbaren, vorausschauenden, und (in bezug auf die Laufzeit) _optimalen_ Code schreiben, indem wir eine simple Schleife verwenden. Wenn die Arrays klein sind, ist die Schleife nicht nachteilhaft, sondern bringt einen vernachlässigbaren Vorteil. Wenn die arrays groß sind, bringt die Schleife u.U. einen DEUTLICHEN Vorteil, und man erspart sich den einen oder anderen Profilerlauf....

Bestimmte Dinge sehe ich eben als selbstverständlich an. Dazu gehört dass man
1. nicht sinnlos (Arbeits)Zeit verschwendet, indem man "besonders optimierten" Code schreibt, der keinen Vorteil bringt
2. nicht sinnlos (Rechen)Zeit verschwendet, indem man den Rechner sinnlosen Müll berechnen läßt
Vielleicht werden die beiden Punkte (in der Industrie und im nicht-industriellen Bereich, aber auch von Person zu Person)  unterschiedlich gewichtet. Aber ich würde die Minimumsuche ebenowenig über eine Sortierung lösen, wie etwa die Enthaltenseinsabfrage bei einem Array über "Arrays.asList(array).contains(objekt)". In beiden Fällen schreibt man eine Schleife, und gut ist. 



			
				maki hat gesagt.:
			
		

> Für "normale" Anwendungen dagegen spielt es wirklich nur noch eine untergeordnete Rolle. Fachliche Fehler sind dagegen kaum verzeihbar, da hast du dann mal schnell ein richtiges Drama am Hals wenn's schlecht läuft.



Fachliche Fehler? Zum Beispiel, wenn jemand diese praktische Funktion benutzt, um sich das minimale Element eines Arrays bestimmen zu lassen, und sich dann wundert, warum sein komplettes Programm nur Mist ausspuckt? Bis man herausgefunden hat, das so eine unverfängliche, triviale Funktion wie die Minimumsuche, die ja garantiert nur einmal durch den Array laufen muß, bewirkt, dass der übergebene Array nachher _sortiert_ ist, kann eine Weile ins Land gehen, und die eine oder andere Deadline verstreichen......... 

Fang' jetzt aber bitte nicht an mit array.clone() - dadurch wird es nicht besser, sondern noch schlechter.


----------



## maki (16. Nov 2007)

> Bestimmte Dinge sehe ich eben als selbstverständlich an. Dazu gehört dass man
> 1. nicht sinnlos (Arbeits)Zeit verschwendet, indem man "besonders optimierten" Code schreibt, der keinen Vorteil bringt
> 2. nicht sinnlos (Rechen)Zeit verschwendet, indem man den Rechner sinnlosen Müll berechnen läßt


Beim ersten Punkt gebe ich dir Recht, beim zweiten bin ich der Meinung, das Rechenzeit nichts mehr kostet(speziell da Rechner sich die meiste Zeit nur lageweilen und auf Usereingaben warten), wenn's wirklich zu lange dauert, kann man immer noch optimieren.



> Fachliche Fehler? Zum Beispiel, wenn jemand diese praktische Funktion benutzt, um sich das minimale Element eines Arrays bestimmen zu lassen, und sich dann wundert, warum sein komplettes Programm nur Mist ausspuckt? Bis man herausgefunden hat, das so eine unverfängliche, triviale Funktion wie die Minimumsuche, die ja garantiert nur einmal durch den Array laufen muß, bewirkt, dass der übergebene Array nachher sortiert ist, kann eine Weile ins Land gehen, und die eine oder andere Deadline verstreichen.........


Nun, das ist ein guter Grund den ich akzeptiere, ohne wenn und aber.


----------

