Optimieren, need help



  • Das ist die dämlichste Idee, die ich seit langem gesehen habe. Du rennst total am Problem vorbei. Natürlich kann man das machen, was du da zeigst, man kann sich aber auch ein Loch ins Knie boren und warme Milch reinkippen.

    Ich will nicht wählen müssen, welcher Container verwendet wird. ICh will das das feststeht.

    Ich will einfach schreiben

    Foo foo;
    
    foo. neMethode ();
    

    Ich will niemals mit verschiedenen Containern arbeiten. Foo hat eine einzige ganz bestimmte Aufgabe. Am Anfang war mir allerdings noch nicht klar, ob std::vector der richtige Container zum lösen des Problems innerhalb von Foo war. Trotzdem habe ich einfach mal einen std::vector verwendet.
    Nun kann ich und alle meine Kollegen Foo bereits verwenden, da es ja schon läuft. Dann beim ausbauen, refaktorisieren, optimieren oder sonstwas fällt mir auf, dass std::vector eine schlechte Wahl war und ersetze ihn durch std::list und passe gegebenen falls ein paar der Methoden von Foo an.

    Bei deinem Vorschlag müsste ich und alle meine Kollegen den gesammten Code überarbeiten überall, wo bisher Foo stand muss jetzt Foo<int, std::list> hin. Das ist unmengen unnütze Arbeit und zudem total hässlich und unübersichtlich.



  • @Helium: Schonmal std::stack angeschaut?

    MfG Jester



  • stack ist ein Container, wie quque auch. Er kann mit einem anderen Container parametrisiert werden.

    Das ist eine ganz andere Situation. Bei stack geht es um eine allgemeine Struktur, die ich an die jeweilige Situation anpassen möchte. Bei meinem "Foo" geht es um ein Teil des Projekts, der in der Form überall im Projekt Verwendung findet.
    Wenn ich nun merke, das die Struktur in der Form viel zu langsam oder viel zu speicherraubend ist, dann will ich sie einfach ändern können. Dadurch ist mein Projekt dann dementsprechend schneller oder weniger speichrraubend. Und ich will nur eine stelle ändern müssen, nicht das ganze Projekt.



  • Wenn du mal genau hinkuckst, du musst nicht wählen, welchen Container du benutzen willst, du kannst auch einfach den Default-Wert (in diesem Fall std::list) nehmen.



  • Helium schrieb:

    Bei meinem "Foo" geht es um ein Teil des Projekts, der in der Form überall im Projekt Verwendung findet.

    Wußte ich nicht. Dachte immer Foo sei "hier beliebiges hindenken".



  • es ist eh selten eine gute idee. vorher einen ganz unpassenden container zu wählen. am besten ist, man wählt vorher einen, der schon recht genau passt. einen, dessen schnittstellen paßt.
    und den kann man später austauschen, weil man von anfang an damit rechnete, ihn auszutauschen. insbesondere meine ich damit, daß man zwar ne std::map mal benutzt, weil's gerade so einfach ist, aber von der eigenschaft, daß sie beim durchiterieren ihre keys sortiert darbringt, keinen gebrauch macht.
    und schwupps, hat man die möglichkeit, viele andere datenstrukturen zu nehmen. hashtables natürlich. skip-lists. und vor allem die ganen kombinationen, damit beginnt der spaß ja erst richtig.



  • Ja, ja, schon klar - aber wenn man den Kram nicht konkretisieren will, gibts ja noch den Default-Wert. Aber es kann schon sinnvoll sein, den Datentyp zu parametrisieren - je nach Gelegenheit kann ein ganz anderer Datentyp vorteilhaft sein. Stell dir vor, du brauchst Foo an zwei Stellen des Programms. Das eine mal kannst du vorher feststellen, wie viele Werte du kriegst, das andere Mal hast du nicht die geringste Ahnung. Das eine Mal hättest du gerne nen Vektor, das andere mal nen Baum (auch wenn volkard mich dafür jetzt wahrscheinlich wieder verbal verprügeln wird 😉 ). Und da bist du mit reiner OOP ziemlich aufgeschmissen.



  • Solche Datenstrukturen wirst du aber selten anfinden, es sei denn es geht gerade (wie bei std::stack und den anderen STL-Containern) darum ganz allgemein zu sein.

    class Base {
    public:
       virtual void add (Foo const & foo) = 0;
    };
    
    class Impl1 : public Base {
    public:
       void add (Foo const & foo)
       {
          container.push_back (foo);
       }
    private:
       std::vector<Foo> container;
    };
    
    class Impl2 : public Base {
    public:
       void add (Foo const & foo)
       {
          container.insert (foo);
       }
    private:
       std::set<Foo> container;
    };
    

    Du siehst, reine OO. und dennnoch kann ich in verschiedenen Situationen verschiedene Ddatenstrukturen verwenden. Und ich habe dieses bekloppte Beispiel nur geschreiben, um dich zu ärgern. :p



  • 0xdeadbeef schrieb:

    Das eine mal kannst du vorher feststellen, wie viele Werte du kriegst, das andere Mal hast du nicht die geringste Ahnung. Das eine Mal hättest du gerne nen Vektor, das andere mal nen Baum (auch wenn volkard mich dafür jetzt wahrscheinlich wieder verbal verprügeln wird 😉 ). Und da bist du mit reiner OOP ziemlich aufgeschmissen.

    erstmal die verlanten prügel: *patsch*

    kann nicht nachvollziehen, warum die anzahl den wunsch nach baum erzeugt. ne hashtable kann genauso wachsen wie ein baum. die mit verkettung im überlaufbereich (also die inzwischen normalen) können auch in grenzen recht nett schrumpfen.

    ich halte nix davon, fette universalschnittstellen zu bauen, wo mal ein baum, mal ne hashtable, mal ein array und mal ne liste drunterliegen und alle strukturen bietet sort, find, remove, insert und iteratoren an. hätte man sowas, könnte man natürlich fein drauflosprogrammieren und erst am ende vor der haustür des kunden noch schnell entscheiden, welche datenstruturen man nimmt. aber vielleicht könnt ihr mich ja auch her von eurem modernen stil überzeugen.



  • Warst du nicht derjenige, der meinte, man sollte sich je nach Problem eigene Datenstrukturen bauen, um die Performance zu steigern? Hier hast du die perfekte Möglichkeit, dir je nach Problem eine auszusuchen und die Interfaces quasi vom Speichermanagement abzukapseln - und das alles ohne overhead. Ravioli-Code par excellence.

    @Helium: Ich finde das ziemlich umständlich, und vom Laufzeitverhalten her ist es grausam. virtual void ad...bah. Nehmen wir (um dem Beispiel mal ein bisschen Sinn einzuhauchen) an, std::set hätte tatsächlich keine push_back-Methode, dann schreib ich trotzdem immer noch lieber

    template <template<typename t> class container_t> class Foo {
    private:
      cointainer_t<Bar> container;
    
    public:
      inline void add(const Bar &bar) { container.push_back(bar); }
    };
    
    template<> void Foo<std::set>::add(Bar &bar) { container.insert(bar); }
    

Anmelden zum Antworten