funktionale zusammenhänge in oop



  • hi,

    angenommen ich habe ein programm, das auf messwerten (~langes array) operiert. nun kann ich z.b. die korrelation von messwerten berechnen. oder eine fouriertransformation. wie stelle ich das in oop-weise am besten dar?

    Array fft(const Array & input);
    

    drückt den funktionalen zusammenhang aus. ich weiß aber nicht, wo ich die funktion fft hinpacken soll, weil der rest des codes in $KLASSE.h und $KLASSE.cpp gegliedert ist. und sowas wie misc_functions.h passt da ästhetisch nicht dazu.

    class FourierTransformator : public Operator
    

    ist dagegen unschön, weil der "FourierTransformator" eigentlich nur eine funktion zur verfügung stellt, und sonst nur ballast ist. da gibt es doch bestimmt eine lehrmeinung zu?



  • Statt eines Arrays solltest du lieber STL-Container benutzen (z.B. std::vector ).

    Wieso erstellst du nicht eine Klasse, die intern den Container verwaltet und auch entsprechende, häufig benutzte Methoden (Fourier-Transformation, Korrelation) nach aussen anbietet?



  • Nexus schrieb:

    Statt eines Arrays solltest du lieber STL-Container benutzen (z.B. std::vector ).

    Wieso erstellst du nicht eine Klasse, die intern den Container verwaltet und auch entsprechende, häufig benutzte Methoden (Fourier-Transformation, Korrelation) nach aussen anbietet?

    das habe ich schon gemacht. "Array" war vielleicht falsch ausgedrückt, nennen wir es "Messwert" (das intern std::vector benutzt, aber das ist nebensächlich). Ich habe auch darüber nachgedacht, z.b. die fourier-transformation in die klasse Messwert zu packen. Das führt (meiner bescheidenen meinung nach) zu einer eierlegenden wollmilchsau von klasse, sollte ich mich entschließen noch mehr transformationen o.ä. hinzuzufügen.



  • Also da gibt es verschiedene Ansätze:
    1. Du kannst die Funktionen in der Klasse anbieten
    2. Du kannst die Funktion global, oder in einem Namespace anbieten, wo es eine überladung für deine Klasse gibt und schlussendlich lediglich mit einem std::vector arbeitet (oder Array, oder was auch immer) und dir lediglich eine Zugriffsfunktion für deine Klasse anbieten. (ev. wäre friend hier auch angebracht).
    3. Du bietest eine Schnittstelle für eine "Standardfunktion" an, was du durch:
    3.1 virtuelle Funktionen erreichen kannst. (was du ja gesagt hast, dass du nicht willst)
    3.2 Funktionszeiger (Member, oder nicht) erreichen kannst.
    3.3. Eine Policy erriechen kannst (siehe: Policy-based Design)

    Ich persönlich würde da am ehesten zu Punkt 1 tendieren. Wenn du jedoch verschiedene Messwert-Klassen hast, die grundsätzlich anderst sind, würde ich da eher zu Punkt 2 tendieren, da du dann keine Code-Verdopplung für immer wieder das gleiche hast.

    Ich als User deiner Klasse möchte eigentlich diese Schnittstelle:

    Messwerte m;
    //m füllen
    
    Andere_Messwerte m2;
    //m2 füllen
    
    Array = m.fft ();
    Array2 = m2.fft ();
    //Arrays ausgeben
    

    oder:

    Messwerte m;
    //m füllen
    
    Andere_Messwerte m2;
    //m2 füllen
    
    Array = fft ( m );
    Array2 = fft ( m2 ); 
    //Arrays ausgeben
    

    Wobei dann fft in etwa so deklariert ist:

    Array fft ( const Array & a)
    {
      //Array erzeugen fft durchführen und zurückgeben
    }
    
    Array fft ( const Messwerte & m)
    {
      return fft ( m.get_data () );
    }
    
    Array fft ( const Andere_Messwerte & m)
    {
      return fft ( m.get_data () );
    }
    

    wobei wir das ganze jetzt noch ein wenig vereinfachen können:
    Du musst lediglich die Schnittstelle get_data für deine Klassen anbieten. (Allenfalls als friend )

    template <class T>
    Array fft ( const T & m)
    {
      return fft ( m.get_data () );
    }
    

    Der ganz klare Vorteil ist, dass der Benutzer deiner Klasse/Funktion auch eine eigene Implementierung von Messwerte haben kann und ebenfalls dein fft benutzen kann. Was durch Punkt 1 nicht (so einfach möglich ist. Er kann eine Umwandlung seiner Klasse in deine machen und dann aufrufen, aber das ist nicht sehr elegant).

    OOP heisst nicht alles in eine Klasse, oder eine Hirarchie zu quetschen. "Freie" Funktionen sind ebenso ein Mittel zur eleganten Programmierung, wie Klassen. Und alles in eine Klasse zu stopfen ist nicht der Sinn.



  • Also ich halte den Ansatz, eine FFT an eine Klasse zu binden für schlecht. Eine FFT ist erstmal relativ losgelöst vom Input zu betrachten und eignet sich für verschiedene Arten von Daten und nicht nur für eine bestimmte Sorte von Messwerten.
    Das spricht also eher für eine freie Funktion. Das gleiche gilt auch für Korrelatoren. Wenn eine FFT noch interne Stati halten muss (z.B. eine Vergangenheit für Überlappungen), dann kann man sie auch als Funktor umsetzen, also als eine Klasse, deren Objekte sich wie Funktionen verhalten.
    Was man vielleicht machen könnte, ist das Interface der Funktionen abhängig vom Input zu gestalten.
    Zum Beispiel hat eine FFT üblichwerweise Eingangsdaten im Zeitbereich und Ausgangsdaten im Frequenzbereich. Man könnte sich also überlegen, ob man einen Datenkontainer bastelt, der Zeitbereichsdaten repräsentiert, und einen der Frequenzbereichsdaten repräsentiert.
    Also z.B. so in etwa (Pseudocode):

    FrequencyDomainData FFT(TimeDomainData data, RadixType fftLength);
    TimeDomainData IFFT(FrequencyDomainData data, RadixType fftLength);
    FrequencyDomainData fastConvolution(FrequencyDomainData data, FrequencyDomainData coefTable);
    TimeDomainData convolution(TimeDomainData data, TimeDomainData coef);
    template<typename DataType> correlation(DataType l, DataType r);
    usw.
    

    Ob das den Aufwand wert ist, muss man selbst entscheiden, jedoch kann das durchaus Vorteile haben.

    Nachtrag:
    C++ ist eben eine hybride Sprache (prozedural und OO). Puristen mögen das als Nachteil sehen, ich finde das sehr vorteilhaft. Eine FFT ist schon vom Grundgedanken her rein funktional.
    Das Gleiche gilt für viele mathematische Funktionen. Sowas muss man nicht in Objekte packen, weil es eigentlich auch von der Abstraktion her wenig Sinn hat.



  • objekt0r schrieb:

    ...korrelation von messwerten berechnen. oder eine fouriertransformation. wie stelle ich das in oop-weise am besten dar? ...

    Warum solltest Du das "oop-isieren" ? OO ist ledigtlich ein spezieller Designansatz, der ein gegebenes Problem besser oder weniger gut abbildet.

    Im konkreten Fall bin ich ziemlich sicher, dass er ihn wneiger gut abbildet.

    Mal zum Vergleich: Warum sollte "korrelation berechnen" ein Objekt sein, wenn "sortiere", "finde Maximum", .... Funktionen sind.

    Nene.... eine Funktion kann man am besten als Funktion implementieren. 😃

    Gruß,

    Simon2.


Anmelden zum Antworten