# dynamisches singleton...



## ruutaiokwu (13. Mai 2011)

hallo zusammen,

habe eine art "dynamisches" singleton entwickelt, bei dem man in der getInstance-funktion argumente mitgeben kann. die instanzen werden intern in einer hashmap gespeichert, daneben verwende ich das "gewöhnlche" single check idiom, welche die einträge der map prüft, ob bereits instanziert ist...

wie nennst sich ein solches pattern? ist das immer noch ein singleton? ein arbeitskollege hat was von "prototype" gemeint...? stimmt das so?


danke & grüsse,
jan


----------



## maki (13. Mai 2011)

Ein Singleton ist es definitiv nicht mehr, sprichst ja von "Instanzen" ... ein Prototype IMHO aber auch nicht, hört sich eher nach einer Factory an.

Wenn du uns vom Code verrätst könnte man vielleciht mehr sagen.

Es mag zwar stimmen, dass man oft Pattern verwendet ohne es zu wissen, aber nicht jeder Code ist immer ein Pattern.


----------



## SlaterB (13. Mai 2011)

es ist eine Factory, mit der Singleton-/ Cache-Artigkeit, dass bei bekannten Parametern das schon bekannte Objekt zu diesen Parametern zurückgegeben wird,
mehr gibts charakteristisches nicht zu sagen, die Implementierung ist doch relativ egal?


----------



## KSG9|sebastian (20. Mai 2011)

Hört sich nach gar keinem Pattern an sondern nach einer Möglichkeit Objekte global bekannt zu machen (...um evtl. schlechtes Design der Anwendung auszugleichen...)


----------



## ruutaiokwu (20. Mai 2011)

sollte eine dynamische java.util.Properties-geschichte werden:


```
Properties properties1 = PropertiesHandler.getPropertiesInstance(properties_file_jndi_path);
```

jede properties_file_jndi_path-konfiguration hat man max. 1 instanz


intern wird eine HashMap verwendet, und dort wird mit .contains(...) auf properties_file_jndi_path geprüft, wenn nicht vorhanden wird es angelegt, und per HashMap.get(...) zurückgegeben, andernfalls nur zurückgegeben.

weisst du, wie sich eine WeakHashMap verhalten würde ("weak references"), könnte es dort der fall sein, dass die einträge (mit der zeit, aber wann genau?) entfernt werden, bei "nicht-gebrauch", besser gesagt bei "nicht-mehr-gebrauch"...?

gruss, jan


----------



## Wildcard (20. Mai 2011)

> weisst du, wie sich eine WeakHashMap verhalten würde ("weak references"), könnte es dort der fall sein, dass die einträge (mit der zeit, aber wann genau?) entfernt werden, bei "nicht-gebrauch", besser gesagt bei "nicht-mehr-gebrauch"...?


Bei einer WeakHashMap würde ein Eintrag verschwinden wenn der *Key* nicht mehr hart referenziert wird. Ein String als Key wäre also zB denkbar ungeeignet.


----------



## ruutaiokwu (25. Mai 2011)

hallo zusammen,



*@KSG9|sebastian:* "(...um evtl. schlechtes Design der Anwendung auszugleichen...)"

was ist für dich die definition von einem schlechten design? findest du es besser, konstanten wie properties oder den logger in allen instanzierten klassen quasi "weiterzureichen", z.b. über den konstruktor?


grüsse, jan


----------



## Landei (25. Mai 2011)

Da haben sich schon schlauere Leute als wir den Kopf drüber zerbrochen. Abstrakte Factories sind eine Notlösung, "State of the Art" ist Dependency Injection in der einen oder anderen Form (Spring, Guice, EJB...). Sorry, deine Idee ist jedenfalls schon ausprobiert und für schlecht befunden worden.


----------



## ruutaiokwu (25. Mai 2011)

hallo landei,

"Abstrakte Factories sind eine Notlösung"

mein konstrukt ist eine factory, je nach situation könnte man das ganze auch abstrakt machen... und: nein, für mich ist das keine notlösung, warum werde ich unten begründen...

"State of the Art" ist Dependency Injection in der einen oder anderen Form (Spring, Guice, EJB...)."

warum immer so kompliziert? na ja, ejb ist eh ein spezialfall... und meine fragen beziehen eher auf generelle sachen. (ejb kann man schliesslich nicht für alles einsetzen, entspr. app. server vorausgesetzt!)


meine begründung:

warum sollte man für solch triviale sachen (logger, properties) gleich ein framework mit 15 mb grösse einsetzen? wenn ich etwas entwickle, was auch immer, z.b.

- eine generische library
- ein framework nach ioc-prinzip (sollte dir bezügl. dependency injection ein begriff sein)
- eine gui- oder konsolenapplikation
- eine webapplikation
- etc.


welche kaum ein halbes mb gross ist, finde ich das "ein wenig" unverhältnismässig. mit kanonen auf spatzen schiessen halt. irrational, finde ich irgendwie.

und z.b. die properties immer per konstruktor weiterzureichen finde ich auch nicht optimal, na ja, wer's braucht...

...oder in jeder klasse die Properties-klasse neu instanzieren, und die name-value-pairs neu einlesen usw. na ja, kann man immerhin "schön" copy/pasten...;-)


"Sorry, deine Idee ist jedenfalls schon ausprobiert und für schlecht befunden worden."

logische erklärung / begründing dafür?


gruss, jan


----------



## Noctarius (25. Mai 2011)

Die Gründe wurden doch schon genannt.


----------



## ruutaiokwu (25. Mai 2011)

@Wildcard: bezügl. key nicht mehr hart referenzieren: könnte das was sein, um eine referenz zur argumentvariable 'canumber' zu verhindern?

->


```
public static Object blablabla(final int canumber)
    {
        int lnumber = 1;

        switch (canumber)
        {
            case -1:
                lnumber = 1 + (~lnumber);
                break;
        }
         

        // variable lnumer wird nach der rückgabe von nichts mehr referenziert ("local scope")
        // falls die WeakHashMap über diese für den key // verwendet, wird der entsprechende eintrag in der WeakHashMap nach dem aufruf von System.gc(); und System.runFinalization(); gelöscht...
```


----------



## ruutaiokwu (25. Mai 2011)

@noctarius: "State of the Art", oder was...?


----------



## Landei (25. Mai 2011)

Seit ich Dependency Injection benutze (Guice in meinem Fall, und diese Kanone ist nicht 15 MB groß, sondern 865 KB, sofern man _alles_ nimmt), sind meine Anwendungen "automatisch" besser gegliedert, es geht gar nicht anders. Meine Klassen kümmern sich mehr um ihre _eigenen_ Aufgaben, statt sich durch irgendwelche Objektgraphen zu hangeln. Trotzdem ist jede einzelne Klasse für sich auch ohne DI verwendbar, was z.B. fürs Testen wichtig ist.

Natürlich hat jeder das Recht, seine eigenen Fehler zu machen und seine eigenen Räder zu erfinden. Viel Spaß dabei!


----------



## Wildcard (26. Mai 2011)

jmar83 hat gesagt.:


> @Wildcard: bezügl. key nicht mehr hart referenzieren: könnte das was sein, um eine referenz zur argumentvariable 'canumber' zu verhindern?


Ich verstehe nicht was du hier vorhast...

Im Übrigen kann ich mich nur meinen Vorrednern anschließen, Dependency Injection ist das richtige Werkzeug


----------



## ruutaiokwu (26. Mai 2011)

hier kann man sehen, dass die instanzen für die keys der WeakHashMap ins "nirvana" zeigen, somit also nicht teil eines objektnetzes sind. (ausser dem WeakHashMap-internen!)

-> Wolfgang Rinser - Grundlagen der Software-Herstellung


nun müsste es doch in diesem beispiel der fall sein, dass NIE hart referenziert wurde? oder sehe ich was falsch?


harte ref:


```
String str = "key1";
Map<String, String> whm = new WeakHashMap<String, String>();
whm.put(str,"key1_value");
// die nächsten 2 zeilen sind sinnlos, da die variable str hart referenziert wurde und noch nicht bereinigt ist...
System.gc(); 
System.runFinalization();
System.out.println("immer noch gleich: "+whm.toString());
```



keine (NIE!) harte ref:


```
Map<String, String> whm = new WeakHashMap<String, String>();
whm.put("key1","key1_value");
System.gc(); 
System.runFinalization();
System.out.println("weak map ist jetzt leer: "+whm.toString());
```


(code habe ich nicht ausprobiert)


nun habe ich "dagegen" folgendes überlegt, das vorherige beispiel war nur mit primitive types (int)... da verhält es sich ja schon wieder ein wenig anders...



```
public static Object blablabla(final Integer argumentNumber)
    {
        int localNumber = 1;
 
        switch (argumentNumber.intValue())
        {
            case -1:
                localNumber = 1 + (~lnumber);
                break;
        }


        // ab hier nur noch localNumber für die WeakHashMap verwenden
        Map<Integer, String> map  = new WeakHashMap<Integer, String>();
        map.put(new Integer(localNumber), "blablabla")
        ...........................................
```


(habe was gegen auto-boxing!)

die idee dahinter ist, dass localNumber nicht auf argumentNumber "zeigt", des weiteren sind in diesem beispiel nur die werte 0 und 1 erlaubt. durch das switch/case versuche ich, die werte von argumentNumber der localNumber zuzuweisen, jedoch ENTKOPPELT.

und da am ende der funktion die variable localNumber eh "weggeputzt" wird, besteht auch keine harte referenz mehr darauf, da es sich um eine rein lokale variable handelt, welche im methodenrumpf erstellt wurde.

irgendwie habe ich das komische gefühl im hinterkopf, dass ich mir das ganze komplett falsch vorstelle...


----------



## Wildcard (26. Mai 2011)

> irgendwie habe ich das komische gefühl im hinterkopf, dass ich mir das ganze komplett falsch vorstelle...


Das Gefühl habe ich auch.
Dein Beispiel oben macht sowieso keinen Sinn weil String Literale gar nicht abgeräumt werden. Das nächste Beispiel mit Integer ist auch sehr gefährlich wegen Autoboxing and Integer Cache.
Was du mit der WeakHashmap zu erreichen versuchst ist mir ebenfalls schleierhaft. Wenn du meinst eine weichere Referenz zu benötigen dann beschäftige dich mit Weak- Soft- und PhantomReference.
Du solltest in einer Applikation ausserdem überhaupt nicht System.gc() und System.runFinalization() aufrufen, lass das die VM alleine entscheiden.
Weiterhin bin ich mir nicht sicher ob dir klar ist das ein local scope sehr billig ist und der Speicher praktisch sofort nach verlassen des Scopes wieder freigegeben werden kann. Eine WeakReference in einem lokalen Scope macht daher absolut gar keinen Sinn.


----------



## ruutaiokwu (26. Mai 2011)

"Was du mit der WeakHashmap zu erreichen versuchst ist mir ebenfalls schleierhaft."

soweit nichts, nur eine übung. wie immer, wenn ich etwas neues lernen will, "learning by doing" halt...


danke für die aufklärung!


gruss, jan


----------



## Noctarius (26. Mai 2011)

jmar83 hat gesagt.:


> hier kann man sehen, dass die instanzen für die keys der WeakHashMap ins "nirvana" zeigen, somit also nicht teil eines objektnetzes sind. (ausser dem WeakHashMap-internen!)
> 
> -> Wolfgang Rinser - Grundlagen der Software-Herstellung



Alleine, dass der gute Mann sich auf die finalize Methode verlässt macht sämtliche Aussagen sehr fragwürdig. Kein vernünftiger Entwickler im Bereich Java (mit ein wenig Erfahrung im Thema GC) würde dazu raten. Es gibt weder eine Gewähr dafür ob und wann diese Methode aufgerufen wird (außer wie bei ihm erzwungen über runFinalization).




jmar83 hat gesagt.:


> ```
> public static Object blablabla(final Integer argumentNumber)
> {
> int localNumber = 1;
> ...



Man darf ja guten Gewissens was gegen Auto-Boxing haben aber man sollte trotzdem Integer.valueOf(int) nutzen, Begründung steht in der Javadoc. Integer (Java Platform SE 6). Zusätzlich zu den Gründen im Javadoc kann eine Instanz zum Wert x öfter ausgegeben werden und muss nicht zwanghaft jedesmal neu instanziert werden, was ziemlich hässliche Nebeneffekte beim Vergleichen haben kann.
Irgendwie werden deine Ansichten immer wieder gepaart mit scheinbar fehlendem Hintergrundwissen oder Interesse sich für bestehende Pattern / Methoden zu erwärmen / interessieren.


----------



## ruutaiokwu (26. Mai 2011)

morgen zusammen!

*@noctarius:* danke für den tipp mit Integer.valueOf(int), den nehme ich - wie gewohnt sonst beratungsresistent - gerne an!

folgendes habe ich dazu zu sagen, schweift zwar vom eigentlichen thema ab:

ja, ich setze, falls passend SELBST auch immer statische methoden ein, z.b. wenn in der methode keine members in spiel kommen... für was unnötig eine klasse instanzieren...???


bsp.: 

(was members betrifft ist  RETURN_ESCAPE_SEQUENCE eine absolute ausnahme, weil es sich um eine konstante handelt... wenn (mehrmals) geschreiben wird, na ja, der letzte gewinnt halt dann -> stat. members sind mit "vorsicht zu geniessen" und eigentlich ein "unding" und zu vermeiden... ausser es handelt sich um konstanten...)


```
package string;

import java.io.StringWriter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

public class MyStringUtil
{
    public static final String RETURN_ESCAPE_SEQUENCE;

    static
    {
        RETURN_ESCAPE_SEQUENCE = System.getProperty("line.separator");
    }

    private MyStringUtil()
    {

    }

    public static final CharSequence getMultipleReturnEscapeSequences(final int quantity)
    {
        String ret = "";

        for (int cnt = 0; cnt < quantity; cnt++)
        {
            ret = ret + MyStringUtil.RETURN_ESCAPE_SEQUENCE;
        }

        return ret;
    }

    public static String getValue(String content, final String name)
    {
        final int pos = MyStringUtil.getIndexAfterKeywordAndWhitespaces(content, name);

        for (int cnt = pos; cnt < content.length(); cnt++)
        {
            final char c = content.charAt(cnt);

            if (c == ' ')
            {
                content = content.substring(pos, cnt);
                break;
            }
        }

        return content;
    }

    public static boolean stringIsEmptyOrNull(final String caString)
    {
        if (!((caString == null) || (caString.intern() == "")))
        {
            return false;
        }

        return true;
    }

    public static String setNullStringToEmpty(String aString)
    {
        if (aString == null)
        {
            aString = "";
        }

        return aString;
    }

    // replace method for small strings, <= 512 bytes...
    public static String replaceSmallString(final String orig, final String search, final String replace)
    {
        final int cap = replace.length() > search.length() ? orig.length() + (replace.length() - search.length()) * 20 : orig.length();
        final StringWriter out = new StringWriter(cap);

        int prev = 0;
        CharSequence okPart;

        for (int i = orig.indexOf(search); i != -1; i = orig.indexOf(search, prev))
        {
            okPart = orig.subSequence(prev, i);
            out.append(okPart).append(replace);
            prev = i + search.length();
        }

        if (prev < orig.length())
        {
            okPart = orig.subSequence(prev, orig.length());
            out.append(okPart);
        }

        return out.toString();
    }

    private static int[] initNext(final String pat)
    {
        final int[] next = new int[pat.length()];
        int i = 0;
        int j = -1;
        next[0] = j;

        while (i < pat.length() - 1)
        {
            while ((j >= 0) && (pat.charAt(i) != pat.charAt(j)))
            {
                j = next[j];
            }

            i++;
            j++;
            next[i] = j;
        }

        return next;
    }

    public static int getIndexBeforeKeyword(final String text, final String pat)
    {
        final int[] next = MyStringUtil.initNext(pat);
        int i = 0;
        int j = i;

        while (i < text.length())
        {
            while ((j >= 0) && (pat.charAt(j) != text.charAt(i)))
            {
                j = next[j];
            }

            i++;
            j++;

            if (j == pat.length())
            {
                return i - pat.length();
            }
        }

        return -1;
    }

    public static int getIndexAfterKeywordAndWhitespaces(final String text, String pat)
    {
        pat = pat.trim();
        int pos = MyStringUtil.getIndexAfterKeyword(text, pat);

        if (text.length() > pos)
        {
            while (true)
            {
                pos++;
                if (text.charAt(pos) != ' ')
                {
                    break;
                }
            }
        }

        return pos;
    }

    public static int getIndexAfterKeyword(final String text, final String pat)
    {
        int pos = MyStringUtil.getIndexBeforeKeyword(text, pat);

        if (pos != -1)
        {
            pos = pos + pat.length();
        }

        return pos;
    }

    public static int getTokenPosition(final String aTokenizedString, final String aToken)
    {
        int lPosition = 0;

        final StringTokenizer lStringTokenizer = new StringTokenizer(aTokenizedString);

        while (lStringTokenizer.hasMoreTokens())
        {
            lPosition++;

            if (lStringTokenizer.nextToken(",").trim().intern() == aToken.trim().intern())
            {
                break;
            }
        }

        return lPosition;
    }

    public static String removeToken(final int aDelimiterPosition, final String aTokenizedString)
    {
        int lCounter = 0;

        String lToken = "";

        final StringTokenizer lStringTokenizer = new StringTokenizer(aTokenizedString, ",");

        final int lQuantityOfTokens = lStringTokenizer.countTokens();

        while (lStringTokenizer.hasMoreTokens())
        {
            if (lCounter > (aDelimiterPosition - 1))
            {
                lToken += lStringTokenizer.nextToken().trim();

                if (lCounter < (lQuantityOfTokens - 1))
                {
                    lToken += ", ";
                }
            }
            else
            {
                lStringTokenizer.nextToken(",");
            }

            lCounter++;
        }

        return lToken;
    }

    public static int countTokens(final String str, final char token)
    {
        int ret = 0;

        if (MyStringUtil.stringIsEmptyOrNull(str))
        {
            return ret;
        }

        final StringTokenizer st = new StringTokenizer(str);

        while (st.hasMoreTokens())
        {
            st.nextToken(",");
            ret++;
        }

        return ret;
    }

    public static String myToString(final Object object)
    {
        Class<?> c = null;

        try
        {
            c = Class.forName(object.getClass().getCanonicalName());
        }
        catch (final Exception e)
        {
            // never thrown --> this.getClass().getCanonicalName() can't be a non-existing class...
        }

        final Field field[] = c.getDeclaredFields();
        final List<String> classFields = new ArrayList<String>(field.length);

        for (final Field element : field)
        {
            element.setAccessible(true);

            final String cf = element.toString();
            final String fieldName = cf.substring(cf.lastIndexOf(".") + 1);

            Object value = null;

            try
            {

                value = element.get(object);
            }
            catch (final Exception e)
            {
                e.printStackTrace();
            }

            classFields.add(fieldName + " = " + value);
        }

        return classFields.toString();

    }
}
```

(...des weiteren sind solche konstrukte ziemlich threadsicher!)

...meiner meinung nach gibt es keinen vernünftigen grund, sowas objektorientiert zu lösen, auch ein singleton wäre hier SICHER NICHT die lösung...

manche "oo-hardliner" sind sicher der meinung, static wenn möglich generell zu vermeiden... 

ich sehe das eher situativ...


----------



## ruutaiokwu (26. Mai 2011)

hier ist, glaube ich, ein besseres beispiel:

Code Instructions: Weak Object Pools with WeakHashMap

hier ist der key der map auch wirklich eine "variable", welche auf eine instanz zeigt... und nicht, wie im anderen bsp., direkt mit new "hinein-instanziert" wird...

anschliessend die String-variable auf eine nullinstanz setzen, und System.gc() (-> wohl eher rein zu demonstrationszwecken) aufrufen. aha, so geht das, alles klar...


----------



## schalentier (26. Mai 2011)

jmar83 hat gesagt.:
			
		

> manche "oo-hardliner" sind sicher der meinung, static wenn möglich generell zu vermeiden...



Ich wuerd sagen, die Mehrheit ist dieser Meinung. Aber diese Diskussion gabs hier auch schon mehrfach ;-) Den Hauptgrund hast du schon selbst genannt, man sollte statische Membervariablen vermeiden. Das geht aber nur, indem man alle Zustandsvariablen als Parameter uebergibt. Sieht man in deinem Code auch gut. 

Aber:


Landei hat gesagt.:


> Natürlich hat jeder das Recht, seine eigenen Fehler zu machen und seine eigenen Räder zu erfinden. Viel Spaß dabei!



Full Ack!


----------



## ruutaiokwu (26. Mai 2011)

"Natürlich hat jeder das Recht, seine eigenen Fehler zu machen und seine eigenen Räder zu erfinden. Viel Spaß dabei!"

sehe ich ähnlich. und das ist auch gut so, dass dem so sei! sonst wäre wohl kaum platz für innovationen vorhanden... (wobei ich mein stück code jetzt nicht als innovation bezeiche!)


----------



## ruutaiokwu (27. Mai 2011)

"Ich wuerd sagen, die Mehrheit ist dieser Meinung."

also dann wäre sowas besser?



```
String str = "das_ist_der_string";
MyStringUtil myStringUtil = new MyStringUtil();
myStringUtil.setString(str);

String out = MyStringUtil.method1(arg1, arg2);
```

...und jedes mal, wenn ich damit einen neuen string bearbeiten will,

muss ich

a.) erneut setString(String) aufrufen

oder

b.) das ganze MyStringUtil neu instanzieren (falls man KEINE setString(String)-methode hätte, den string stattessen im konstruktur mitgibt, wäre dass ein muss...)


...da können mir irgendwelche oo-puristen erzählen was sie wollen, es geht nicht darum, IMMER alles objektorientiert zu machen, sondern situativ das richtige. und alles static im MyStringUtil zu machen, ist von mir aus gesehene situativ das richtige. (wie gesagt, für mich zumindest)

oo ist von mir aus gesehen gut und recht, aber für solche "technischen" helferklassen? na ja...

...fachliche teile einer geschäftliche applikation, für sowas liebe ich objektorientierung:

z.b.


```
Order salesUnitOrder = new SalesUnitOrder();
Order partnerOrder = new PartnerOrder();
```


..."Order" ist eine schnittstelle oder abstr. klasse, für die instanzierung könnte man auch eine abstr. factory machen.

-> DORT IST FÜR MICH OBJEKTORIENTIERUNG ANGEBRACHT: wenn es z.b. darum geht, gewisse "konstellationen" aus der realen welt objekorientiert zu modellieren...


----------



## Noctarius (27. Mai 2011)

c) Die Methode einfach Thread-Safe machen, ergo den String direkt mit in method1 als Parameter mitgeben und Classfelder vermeiden (außer für unveränderliche Werte).


----------



## Gast2 (27. Mai 2011)

Naja... *reine* Utility Klassen nach dem Utility pattern - Wikipedia, the free encyclopedia sollten meiner Meinung nach (auschließlich) static Methoden anbieten. Ist ja im bei der offiziellen API auch so (z.B. z.B. Arrays, Collections usw).


----------



## Noctarius (27. Mai 2011)

Diese sollten dann aber auch final oder abstract sein und einen privaten Constructor mitbringen um den Utility-Pattern zu entsprechen


----------



## Gast2 (27. Mai 2011)

Ja, richtig. Grade das Beispiel MyStringUtils ist halt da ein klassischer Kandidat für.


----------



## ruutaiokwu (27. Mai 2011)

@Noctarius: "Diese sollten dann aber auch final oder abstract sein und einen privaten Constructor mitbringen um den Utility-Pattern zu entsprechen"

-> da bin ich mir nie so ganz sicher, was ich alles machen soll:

privater konstruktor -> nicht instanzierbar, und nicht vererbbar -> nur wegen des konstruktors (das sollte man sowieso machen bei einer solchen klasse!)

final -> nicht vererbbar, verhinderung geschieht "klassen-mässig" (also per final-deklaration)

abstract -> nicht insanzierbar, "klassen-mässig" (also per abstract-deklaration)


final oder abstract sind für micht eher optional... wenn überhaupt: dann eher final würde ich sagen, wenn zu 100% nur stat. methoden drin sind...

was meint ihr dazu?


----------



## ruutaiokwu (27. Mai 2011)

"wenn überhaupt: dann eher final würde ich sagen, wenn zu 100% nur stat. methoden drin sind..."

angenommen das wäre nicht der fall, und es hätte n nichts-statische methoden drin, und aus diesem grund würde ich nicht final, sondern abstrakt deklarieren weil ich z.b. folgenes machen will:

(MyStringUtil2 erbt von der abstr. klasse MyStringUtil)



```
MyStringUtil myStringUtil2 = new MyStringUtil2();
```


...sowas würde wiederum auch nicht gehen, wenn der konstruktor private ist. dann dürfte der konstruktor nicht private sein...

warum also die kombination aus priv. konstruktor & abstr. klasse? quasi für die "totale" absicherung/restriktion??


----------



## Noctarius (27. Mai 2011)

In diesem Fall haben abstract und final die selbe Wirkung. Durch den privaten Konstruktor kannst du auch bei abstract die Klasse nicht ableiten. Du kannst nämlich keinen Super-Konstruktor aufrufen.


----------



## schalentier (27. Mai 2011)

Ich seh in diesem Stueckel Code kein ernsthaftes Problem:

```
String str = "das_ist_der_string";
MyStringUtil myStringUtil = new MyStringUtil();
myStringUtil.setString(str);

String out = MyStringUtil.method1(arg1, arg2);
```

Man koennte aber z.B. mit Guice schreiben:


```
@Singleton
public class MyStringUtil {
...
}

public void MyTestClass {
   @Inject private MyStringUtil stringUtil;
   public void foo() {
      stringUtil.setString("test");
      stringUtil.method1(...);
   }
}
```

Aber bei zustandslosen und aller Wahrscheinlichkeit nach nicht veraenderbaren Methoden kann man in diesem Fall natuerlich auch statische nehmen. Dein Beispiel allerdings ist nicht zustandslos (glaub ich). Ich seh da Strings, Tokens und Patterns. Kann man das nicht irgendwie sinnvoll in eine Klasse Scanner oder so packen? Allein der Name 'Util' sollte imho sehr vorsichtig verwendet werden, denn meistens zeugt das von einem Designfehler (it smells).


----------



## ruutaiokwu (27. Mai 2011)

@schalentier, nicht böse gemeint:

ja, man kann auch mit kanonen auf spatzen schiessen (-> guice) oder es komplizierter als notwendig machen (-> die zu instanzierende variante)


"Aber bei zustandslosen und aller Wahrscheinlichkeit nach nicht veraenderbaren Methoden kann man in diesem Fall natuerlich auch statische nehmen. Dein Beispiel allerdings ist nicht zustandslos (glaub ich)."

was ist eine zustandslose / nicht veränderbare methode?


"Ich seh da Strings, Tokens und Patterns."

spielt doch keine rolle, welche konkrete funktionalität die klasse implementiert? was hat das mit dem eigentlichen thema zu tun?

"Allein der Name 'Util' sollte imho sehr vorsichtig verwendet werden, denn meistens zeugt das von einem Designfehler (it smells)."

wer hat dir denn diesen unsinn (sorry!) beigebracht? irgend ein (möchtegerne)-java enterprise application-architect/consultant-was-auch-immer der direkt von der uni kommt, oder ein wirtschaftsinformatiker und vermeintlicher oo-spezialist, der noch nie selbst was entwickelt hat? 

(selbst versuche ich eher ingenieurs-mässig (-> lösungsorientiert, strukt. vorgehensweise, einsatz ensprechender werkzeuge...) software zu entwickeln, bin aber selbst keiner, hand auf's herz..)


----------



## schalentier (27. Mai 2011)

jmar83 hat gesagt.:


> ja, man kann auch mit kanonen auf spatzen schiessen (-> guice) oder es komplizierter als notwendig machen (-> die zu instanzierende variante)


Natuerlich, man kann auch aktuelle Entwicklungen ignorieren und einfach mit Java 1.4 entwickeln. Geht alles.



jmar83 hat gesagt.:


> was ist eine zustandslose / nicht veränderbare methode?



Ich meine eine seiteneffektlose Methode in einer zustandslosen Klasse. Z.B. Math.sin(..).



jmar83 hat gesagt.:


> spielt doch keine rolle, welche konkrete funktionalität die klasse implementiert? was hat das mit dem eigentlichen thema zu tun?



Deine Methoden da brauchen immer irgendwelche Parameter (text, pat, tokenizedString, etc.). Das sind Zustaende, die du per Parameter in die Methoden reingeben muss, weil du statische Methoden benutzt und diese damit nicht als Instanzvariablen speichern kannst. Wie benutzt du die Methoden? Ich vermute, an der Stelle, wo du die benutzt ist weiterer Code, den man auch direkt in einer sinnvoll benannten (!=Util) Klasse haette verstecken koennen (Information Hiding).



jmar83 hat gesagt.:


> wer hat dir denn diesen unsinn (sorry!) beigebracht? irgend ein java enterprise application senior-architect/consultant-was-auch-immer der direkt von der uni kommt, oder ein wirtschaftsinformatiker und vermeintlicher oo-spezialist, der noch nie selbst was entwickelt hat?



Sei mir nicht boese, aber dein Code Beispiel ist ziemlich unverstaendlich. Wenn du besser werden moechtest, hilft es manchmal, Kritik anzunehmen. Du kannst auch mal kurz erklaeren, was deine Klasse MyStringUtil macht (machen soll), dann kann ich dir evtl. zeigen, wie ich es gemacht haette. Moeglicherweise koennen wir so beide was lernen.


----------



## Gast2 (27. Mai 2011)

@jmar83 bist nicht eher du der consultant, da beratungsresistent  ? 

Ich weiß gar nicht was du gegen DI hast? Viele neuen Frameworks/Spec usw. bringen sogar ein schon eines von Haus aus mit. JEE6,e4,virgo etc.


----------



## schalentier (27. Mai 2011)

Wenigstens bin ich nich der einzige mit meiner These:
Anti-Patterns and Worst Practices ? Utils Class | Chris Missal's Blog


----------



## ruutaiokwu (27. Mai 2011)

@SirWayne: "Ich weiß gar nicht was du gegen DI hast? Viele neuen Frameworks/Spec usw. bringen sogar ein schon eines von Haus aus mit. JEE6,e4,virgo etc."

wenn ich eine so simple, generische und wiederverwendbare klasse schreibe, will ich abhängkeiten reduzieren, und nicht ein 900kb grosses framework dazu mitliefern müssen! (also wenn möglich die sache NUR mit den java-eigenen klassen realisieren!)

grundsätzlich habe ich nichts dagegen di, z.b. in einem komplexen bussiness-logic-layer oder so...

@schalentier: die klasse heisst nicht "Utils" oder "Util", sondern MyStringUtil (das "My"-könnte man weglassen, es gibt aber in gewisse libraries klassen, welche bereits "StringUtil" heissen. und das gibt ein "entscheidungsproblem" bei "organize imports" unter eclipse...)

StringUtil oder MyStringUtil ist für mich ein "sprechender name" -> generische string-operationen-klasse...

NIEMALS würde ich eine klasse "Util", "Factory" oder "Singleton" nennen! ohne überheblich wirken zu wollen: owas sollte einem aber quasi "im instinkt" sein, also das sollte man nirgendwo lesen müssen!

anwendungbeispiele:


```
if(MyStringUtil.stringIsEmptyOrNull(str))
{
...
}
```

*oder*


```
String potentiallyEmptyString = MyStringUtil.setNullStringToEmpty(potentiallyNullInstanceString);
```

oder 



```
@Override
public String toString()
{
   return MyStringUtil.myToString(this);
}
```


----------



## schalentier (27. Mai 2011)

Die drei Codebeispiele deines letzten Posts wuerde ich in der Tat in eine Util-Klasse auslagern. Evtl. gleich noch umfangreicher gefasst (z.B. CompareUtils, mit Methoden wie: isEmpty (akzeptiert auch andere Datentypen als String), areAllEmpty( String ... str ), isNull( ... ) usw). 

Ich hab mich mit meinen Aussagen eher auf die anderen Methoden bezogen (die mit den Tokens, Patterns und Keywords). 



jmar83 hat gesagt.:


> StringUtil oder MyStringUtil ist für mich ein "sprechender name" -> generische string-operationen-klasse...



Fuer mich ist ein sprechender Name, wenn ich sofort erkennen kann, was die Klasse/Methode macht. StringUtil kann alles machen, daher ist es definitiv nicht sprechend. 

Lies mal den Blogeintrag, den ich verlinkt habe, denk nochmal drueber nach und sprich mal mit nem (evtl. erfahrenerem) Kollegen drueber. Wenn du dann immer noch der Meinung bist, MyStringUtil waere ein guter Name, dann kann ichs auch nicht aendern -> mir auch egal.


----------



## Gast2 (27. Mai 2011)

Was ich nicht versteht ist warum du überhaupt in ein Forum schreibst wenn du die tipps dann eh ignorierst ...


----------



## ruutaiokwu (27. Mai 2011)

@schalentier:

"Fuer mich ist ein sprechender Name, wenn ich sofort erkennen kann, was die Klasse/Methode macht. StringUtil kann alles machen, daher ist es definitiv nicht sprechend.

Lies mal den Blogeintrag, den ich verlinkt habe, denk nochmal drueber nach und sprich mal mit nem (evtl. erfahrenerem) Kollegen drueber. Wenn du dann immer noch der Meinung bist, MyStringUtil waere ein guter Name, dann kann ichs auch nicht aendern -> mir auch egal. "


ja, der name könnte besser sein, da hast du recht...


@SirWayne: die diskussion ist sowieso "ausgeartet", und hat eigentlich gar nix mehr mit dem ursprünglichen thema zu tun...

werde den thread jetzt schliessen (danke für die teilname an der diskussion!), und wünsche euch ein schönes wochende!


grüsse, jan


----------



## Gast2 (27. Mai 2011)

@jmar83

Kannst du dir bitte mal angewöhnen [noparse]





> [/noparse] zu verwenden? Deine Art andere zu quoten ist verdammt schlecht zu lesen.


----------



## ruutaiokwu (27. Mai 2011)

ja, sicher, kein problem...


----------



## KSG9|sebastian (31. Mai 2011)

Huch, nette Diskussion hier:

jmar, warum kommst du in ein Forum und stellst Fragen wenn du dann jegliche Antwort ignorierst?


Du gehst hier Leute an mit Sprüchen wie "frag mal einen erfahrenen Kollegen", es ne gute Nummer. Vor allem weil man aus sämtlichen von deinen Beiträgen, Zitaten, Kommentaren und Vorschlägen erkennt das du (sorry) absolut keine Ahnung von Anwendungsarchitektur/Design hast, weder von großen noch von kleinen Anwendungen.

Deine final-static-util-helfer-sonstwas-Klassen stellst du zu guter letzte dann noch als widerverwendbar dar.

1) DI/IoC macht in jeder Anwendung Sinn. Ist eine Anwendung zu klein als das es Sinn macht diese Patterns/Technologien zu verwenden dann ist das Ding keine Anwendung sondern eher ein typisches Entwickler-Hilfs-Tool was per Definition schnell programmiert ist um einfach seinen Zweck zu erfüllen

2) Sämtliche deiner Lösungen (Properties im Konstruktor, statische Factory u.s.w.) wurden schon viele Jahre lang versucht und einfach als schlecht befunden. Genau dafür gibt es DI. Der wesentliche Vorteil davon ist, wie schon geschrieben, dass du deine Anwendung automatisch vernünftiger aufbaust weil du nur Abhängigkeiten schaffst wo sie unbedingt benötigt werden. Statische Klassen/Werte werden meist dazu mißbraucht an Stellen verwendet zu werden an die sie nicht hingehören. Bei DI überlegst du dir dreimal ob da jetzt eine @Inject-Annotation ran gehört, verwendest du es einfach irgendwo im Code stört es weniger.

3) MyStringUtil - mir graut es beim lesen. Wenn einer unserer Entwickler sowas tut gibt es gleich mal ärger.
Man muss nicht noch die 500ste Version von StringUtil erfinden. 
My-HauMichKlassen, das absolute Grauen der Softwareentwicklung. Ich weiß nicht wer auf die Idee gekommen ist, aber es ist einfurchbarer Trend. Man könnte ja alle eigenen Klassen mit einem "My"-Prefix versehen, dann sieht man ja sofort welche Klassen selber geschrieben sind. Dazu noch nennt man jede Variable my-Irgendwas, und schon ist das Chaos perfekt.
Dein Argument mit "generische String Hilfsklasse" taugt einfach nicht. Dann nenne ich meine Klasse "MyUtil" -> eine generische Hilfsklasse. Solche Dinge wie "Hashcode-Helper" und ähnliches finde ich ja durchaus in Ordnung. Aber dann gibt es eine ganz klare Zuständigkeit für die Klasse.

4) Vielleicht redest *du* mal mit erfahrenen Kollegen bevor du hier irgendwelche Leute anmachst...scheinbar fehlt dir hier das Wissen um in der Diskussion mithalten zu können


----------

