myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » Code-Reviews » [Review | Frage] Vorgehen bei komplexer Datenverarbeitung
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

[Review | Frage] Vorgehen bei komplexer Datenverarbeitung

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
Killerkrümel Killerkrümel ist männlich
myCSharp.de-Mitglied

Dabei seit: 12.08.2008
Beiträge: 166
Entwicklungsumgebung: Visual Studio 2017
Herkunft: Hamburg


Killerkrümel ist offline

[Review | Frage] Vorgehen bei komplexer Datenverarbeitung

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Community,

es gibt einen zu nutzenden RestService, welcher mir eine Objecthierarchie mit bis zu 100 Objekten ala

List<Container>=> 
Container => 
    List<ContainerItem> => 
    ContainerItem => 
        List<Item> => 
        Item

wiedergibt, von denen Ich u.U. sogar die einzelne Items, auch bestimmte Items brauche.
Daher überlege ich mir gerade, wie ich die Datenaufarbeitung am besten realisieren könnte.
Folgende Überlegung:

C#-Code:
public class CLAPFactory : IFactory
    {
        public readonly Container<IAnalyticalActivityP> _activityContainer;
        private readonly Container<IAnalyticalElementaryTaskRecord> _aetrContainer;

        public CLAPFactory()
        {
            _activityContainer = new Container<IPersistableData>();
            _aetrContainer = new Container<IPersistableData>();
        }

        public void Persist<TPersistableData>(IList<TPersistableData> collection) where TPersistableData : IPersistableData
        {
            foreach (var data in collection)
            {
                _activityContainer.Add(data.Key, (IAnalyticalActivityP)data);
            }
        }

        public void Persist<TPersistableData>(TPersistableData data) where TPersistableData : IPersistableData
        {
            _activityContainer.Add(data.Key, (IAnalyticalActivityP)data);
        }

        public TPersistableData LoadableData<TPersistableData>(string key) where TPersistableData : IPersistableData
        {
            if (typeof(TPersistableData) == typeof(IAnalyticalActivityP))
                return (TPersistableData)_activityContainer[key];

            if (typeof(TPersistableData) == typeof(IAnalyticalElementaryTaskRecord))
                return (TPersistableData)_activityContainer[key];

            return default(TPersistableData)
        }
    }

    public interface IFactory
    {
        void Persist<TPersistableData>(IList<TPersistableData> collection) where TPersistableData : IPersistableData;

        void Persist<TPersistableData>(TPersistableData data) where TPersistableData : IPersistableData;

        TPersistableData LoadableData<TPersistableData>(string key) where TPersistableData : IPersistableData;
    }

C#-Code:
public class Container<TPersistableData> : Dictionary<string, TPersistableData> where TPersistableData : IPersistableData
    {
        public Container()
        {
        }

        public Container(int capacity) : base(capacity)
        {
        }

        public Container(IEqualityComparer<string> comparer) : base(comparer)
        {
        }

        public Container(int capacity, IEqualityComparer<string> comparer) : base(capacity, comparer)
        {
        }

        public Container(IDictionary<string, TPersistableData> dictionary) : base(dictionary)
        {
        }

        public Container(IDictionary<string, TPersistableData> dictionary, IEqualityComparer<string> comparer) : base(dictionary, comparer)
        {
        }

        protected Container(SerializationInfo info, StreamingContext context) : base(info, context)
        {
        }
    }

Wie kann ich verhindern, für jedes TPersistableData-INterface eine eigene Interfaceabfrage zu machen?
(vgl. If(typeof)[...])

Ist dies überhaupt der richtige Ansatz?

Dieser Beitrag wurde 3 mal editiert, zum letzten Mal von Killerkrümel am 20.06.2018 15:22.

20.06.2018 15:20 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
witte
myCSharp.de-Mitglied

Dabei seit: 03.09.2010
Beiträge: 848


witte ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Schau dir mal das Entwurfsmuster Visitor an.
20.06.2018 15:25 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 13.575
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von Killerkrümel:
es gibt einen zu nutzenden RestService, welcher mir eine Objecthierarchie mit bis zu 100

Zitat von Killerkrümel:
Ist dies überhaupt der richtige Ansatz?

Prinzipiell ist es eine Bad Practise große, komplexe Objekte mit REST anzunehmen, oder zurück zu geben.
Daher sind Navigation Properties auch nicht Teil der Rückgaben von OData oder anderen Hypermedia-Protokollen wie GraphQL oder Siren.
Das wiederum lässt den Schluss zu, dass Du überhaupt keinen REST sondern einfach einen simplen Json-Service schreibst; denn das schlanke Navigieren über Objekte durch Url-Segmente fällt bei Dir ja flach.

Ich hab sehr viel mit APIs und API Design zutun und noch keinen Grund gefunden, wirklich solche großen Objekte über eine API zurück geben zu müssen.
Was genau ist der Grund, dass es hier der Fall ist?
20.06.2018 15:31 Beiträge des Benutzers | zu Buddylist hinzufügen
Killerkrümel Killerkrümel ist männlich
myCSharp.de-Mitglied

Dabei seit: 12.08.2008
Beiträge: 166
Entwicklungsumgebung: Visual Studio 2017
Herkunft: Hamburg

Themenstarter Thema begonnen von Killerkrümel

Killerkrümel ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von Abt:
Das wiederum lässt den Schluss zu, dass Du überhaupt keinen REST sondern einfach einen simplen Json-Service schreibst; denn das schlanke Navigieren über Objekte durch Url-Segmente fällt bei Dir ja flach.
[...]
Was genau ist der Grund, dass es hier der Fall ist?

Hallo Abt,

Ich muss einen Service aufrufen, welcher basierend auf einer ID eine Struktur als JSON zurückgibt, die oben definiert ist (Exemplarisch):

Eine Liste aus Containern
Jeder Container hat eine Liste aus SubContainern.
Jeder SubContainer hat eine Liste aus SubContainerEigenschaften
Jede ContainerEigenschaft kann, muss aber nicht, eine Liste aus SubEigenschaften enthalten

Es können 1-n Container vorkommen
Es können 1-n SubContainer vorkommen
Es können 1-n SubContainerEigenschaften vorkommen
Es können 0-n SubEigenschaten vorkommen.

Stell es dir am besten wie eine Fertigungsprozesskette vor:

Auto ist der Container.
    Türenmontieren ist ein SubContainer
        Fenster-vorne ist eine SubContainerEigenschaft
            Fensterfarbe ist eine SubEigenschaft
            [...]   

        Fenster-hinten ist eine SubContainerEigenschaft
        [...]

    Karosserie montieren ist ein SubContainer
    [usw...]

ich brauche in der Anwendung nun zugriff auf die FensterFarbe, von
denen es wie gesagt 0-4 geben kann.


P.S.:
Ich kann die Antwort des Services nicht ändern/anpassen, ich muss den kommenden json string nutzen.

Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von Killerkrümel am 20.06.2018 16:04.

20.06.2018 15:57 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Killerkrümel Killerkrümel ist männlich
myCSharp.de-Mitglied

Dabei seit: 12.08.2008
Beiträge: 166
Entwicklungsumgebung: Visual Studio 2017
Herkunft: Hamburg

Themenstarter Thema begonnen von Killerkrümel

Killerkrümel ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

@ Witte - die Idee mit dem VisitorPattern ist interessant.
Jedoch habe ich es entweder Missverstanden, oder es ist für meinen Ansatz nicht hilfreich. Der Kerngedanke des Patterns ist es ja, den Verarbeitungsalgorithmus von Objekten zu trennen (IMO)
Jedoch will ich nichts verarbeiten, sondern möglichst zuverlässig und schnell an einzelne Eigenschaften der SubObjekte herankommen.
21.06.2018 09:28 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 13.575
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Ich versteh es vermutlich immer noch nicht... (und evtl. bin ich nicht der Einzige..)

Worum geht es Dir denn? Was meinst Du mit "schnell und zuverlässig an Eigenschaften" kommen?
Geht es Dir um die Serialiserung der Json-Antwort, oder willst Du den Wert haben?

Reden wir hier von einer rekursiven Herarchie und ein Container ist das gleiche wie ein SubContainer, oder sind das zwei verschiedene Objekte(/Klassen) ?
21.06.2018 10:59 Beiträge des Benutzers | zu Buddylist hinzufügen
Killerkrümel Killerkrümel ist männlich
myCSharp.de-Mitglied

Dabei seit: 12.08.2008
Beiträge: 166
Entwicklungsumgebung: Visual Studio 2017
Herkunft: Hamburg

Themenstarter Thema begonnen von Killerkrümel

Killerkrümel ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Abt,

vielen Dank vorab für deine Mühen.

Zitat von Abt:
Worum geht es Dir denn?

- Zugriff auf die Unterschiedlichen Elemente der Kette

Zitat von Abt:
Was meinst Du mit "schnell und zuverlässig an Eigenschaften" kommen?
Geht es Dir um die Serialisierung der Json-Antwort, oder willst Du den Wert haben?

- Eventuell ist dies das gleiche. Ich möchte auf Werte innerhalb der Kette zugreifen

Zitat von Abt:
Reden wir hier von einer rekursiven Hierarchie und ein Container ist das gleiche wie ein SubContainer, oder sind das zwei verschiedene Objekte/Klassen) ?

- Nein, Der Container ist ein eigenes Objekt, der SubContainer auch, also verschiedene Klassen.



Mir geht es darum, mit möglichst wenig Aufwand auf Elemente und ihre Werte innerhalb der "Produktionskette" zugreifen zu können.


Ich versuche es nochmal anders:
Gegeben sei diese Struktur:

Container C
	C.Name
	C.ID
	C.SubContainer	
		SubContainer SC
		SC.Name = SC1
		SC.ID
		SC.[...]
		SC.SubContainerEigenschaftenListe<SubContainerEigenschaft>
		
			SubContainerEigenschaft SCE_Name
			SCE.Wert
			SCE.[...]
			SCE.SubContainerEigenschaftDeffinitionsListe<SubContainerEigenschaftDeffinition>
				
				SubContainerEigenschaftDeffinition SCED
				SCED.Typ = String
				
			SubContainerEigenschaft SCE_Datum
			SCE.Wert
			SCE.[...]
			SCE.SubContainerEigenschaftDeffinitionsListe<SubContainerEigenschaftDeffinition>
				
				SubContainerEigenschaftDeffinition SCED
				SCED.Typ = Date
				
			SubContainerEigenschaft SCE_Ergebnis
			SCE.Wert
			SCE.[...]
			SCE.SubContainerEigenschaftDeffinitionsListe<SubContainerEigenschaftDeffinition>
				
				SubContainerEigenschaftDeffinition SCED
				SCED.Typ = Double
				
		SubContainer SC
		SC.Name = SC2
		SC.ID
		SC.[...]
		SC.SubContainerEigenschaftenListe<SubContainerEigenschaft>
		
			SubContainerEigenschaft SCE_Name
			SCE.Wert
			SCE.[...]
			SCE.SubContainerEigenschaftDeffinitionsListe<SubContainerEigenschaftDeffinition>
				
				SubContainerEigenschaftDeffinition SCED
				SCED.Typ = String
				
			SubContainerEigenschaft SCE_Datum
			SCE.Wert
			SCE.[...]
			SCE.SubContainerEigenschaftDeffinitionsListe<SubContainerEigenschaftDeffinition>
				
				SubContainerEigenschaftDeffinition SCED
				SCED.Typ = Date
				
			SubContainerEigenschaft SCE_Ergebnis
			SCE.Wert
			SCE.[...]
			SCE.SubContainerEigenschaftDeffinitionsListe<SubContainerEigenschaftDeffinition>
				
				SubContainerEigenschaftDeffinition SCED
				SCED.Typ = Double
				
			[usw]

Wie komme ich möglichst flexibel an die SubContainerEigenschaft Name des Elementes SC2, ohne die gesammte Kette iterieren zu müssen?

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Killerkrümel am 21.06.2018 15:50.

21.06.2018 15:46 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 13.575
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Also egal was Du machst: hellsehen wird Dein Code auch nicht können.
Die Eierlegende-Wollmilchsau gibts nicht ;-)

Du kannst Dir natürlich eine Reflection Methode bauen, damit Du zB schreiben kannst
MyReflectionMethods.GetPropValue("SubContainers.Name", "SC2")
Ist dann einfach - aber halt nicht flexibel.

Ansonsten würde ich mir eben ganz simpel ein paar Erweiterungsmethoden bauen, die das für mich abstrahieren.
Kann man super über funktionale Umsetzung, Expression Tree und Co mit wenig Code umsetzen.

Ich hab aktuell was ähnliches vor mir; geht um Produktionsanlagen, die Produktionslinien haben, und darin wiederum Maschinen, deren Bauteile und Eigenschaften.
Also auch eine "tiefere Hierarchie" - aber da ist ganz simpel eine Schleife drüber auf Linq-Basis bzw. die Dictionaries für den Direktzugriff.
Reicht völlig aus, ist sauber testbar und für jeden ohne Black Magic erweiter/wartbar.
21.06.2018 16:45 Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als ein Jahr.
Der letzte Beitrag ist älter als ein Jahr.
Antwort erstellen


© Copyright 2003-2020 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 01.04.2020 04:25