Programmarchitektur - Frage zum Design

  • 10 Antworten
  • Neuester Beitrag
Diskutiere Programmarchitektur - Frage zum Design im Android App Entwicklung im Bereich Betriebssysteme & Apps.
H

HerrFatalVonError

Neues Mitglied
Hallo zusammen,

ich bin relativ neu in der App-Entwicklung, also seid nicht zu streng mit mir.
Zum Sachverhalt:

Ich besitze 4 Klassen:

Plan
Workout
Übung
Satz

Satz ist jeweils Teil von Übung. Mehrere Übungen sind teil eines Workouts und mehrere Workouts sind teil eines Plans.Struktur.jpg

Momentan besitzt jede Klasse ihre eigenen Methoden um verschiedene Parameter zu berechnen. Zum Beispiel Workout besitzt calculateTime.
Bei dieser Methode werden die Satzzeiten (Aus der klasse Satz), welcher ihr angehören zusammenaddiert.

Jetzt würde ich gerne jedesmal wenn ich einen Satz hinzufüge (Diese Methode befindet sich in der Übungsklasse) automatisch die Zeit für den Workout berechnen,
allerdings besitzt die Klasse Übung ja keine referenz zu der klasse Workout. Sie ist nur über ein ArrayList in ihr gespeichert. Das selbe gilt dann nach oben hin für den Plan bezogen auf die Workouts usw.

Wenn ich der Klasse Übung die Referenz seiner Klasse Plan mitgebe (um die Planmethode in der Klasse Übung auszuführen) bekomme ich probleme beim Serialisieren und speichern über SharedPreferences.

Zu meiner Frage:
Macht es vom Design her Sinn, dass alle Klassen ihre eigenen Methoden besitzen ? Somit quasi immer zur Laufzeit jeder Klasse ihre Methoden zum updaten ausführen, oder macht es mehr Sinn die Klassen als reine Daten-Schablonen zu nutzen und eine "Handler" Klasse zu erstellen, welche diese Arbeit übernimmt.

StrukturH.jpg

Ein weiterer Gedanke war das jede Klasse eine Innere Klasse der anderen ist. Quasi eine Riesen Plan Klasse... Dann hätte jede untergeordnete Klasse die Referenz der untergeordneten Klassen allerdings geht mir dann die Übersicht verloren.

Wie wird sowas professionel erstellt ?

Gruß,
FatalVonError
 
swa00

swa00

Moderator
Teammitglied
@HerrFatalVonError

hallo und herzlichst willkommen im Forum.

Ehrlich gesagt musste ich deinen Beitrag mehrfach lesen, um zu verstehen , wo dein "Problemchen" ist :)
Es ist ein klassisches OOP (Nicht) Wissen - also nicht tragisch.

Jetzt würde ich gerne jedesmal wenn ich einen Satz hinzufüge (Diese Methode befindet sich in der Übungsklasse) automatisch die Zeit für den Workout berechnen,
Wenn sich also in Klasse A etwas geändert hat , möchtest du das der Klasse B mitteilen, damit die einen Job macht.
Nun , dazu gibt es unter Android viele Möglichkeiten : Listener/Callbacks, Broadcast, Singleton usw. usw.

Ich würde an deiner Stelle damit beginnen , in dem du dir in der Hauptklasse jeweils neue Instanzen der
verschiedenen Subklassen erstellst und jede Subklasse mit einem Listener ausstattest.
Sobald die Klasse A etwas getan hat, teilt sie das der Hauptklasse via Callback mit, die dann wiederum
in der Klasse B eine public Methode auslöst.


Code:
KlasseA _klasseA = new KlasseA();
KlasseB _klasseB = new KlasseB();
_klasseA.setOnStatusListener (new KlasseA.setOnStatusListener()
{
  @override
  public void BinFertig()
  {
    _klasseB.MachDiesundDas();
  }
}
_klasseA.MachZuerstWas ();

Macht es vom Design her Sinn, dass alle Klassen ihre eigenen Methoden besitzen ?
Wäre Blödsinn - Für kleinere Operationen , die du in in allen Subklassen immer wieder mal benötigst, kannst du dir wiederum
separate Klassen erstellen und jeweils nach Bedarf eine eigene Instanz erstellen.

Innerhalb jeder Klasse :
Code:
KlasseAddiere addiere = new KlasseAddiere();   addiere.ZaehlZusammen(10,20);

Wenn ich der Klasse Übung die Referenz seiner Klasse Plan mitgebe (um die Planmethode in der Klasse Übung auszuführen) bekomme ich probleme beim Serialisieren und speichern über SharedPreferences.
Möchtest du "global" Daten/Methoden klassenübergreifend verarbeiten/zugreifen , solltest Du eine Singleton Klasse
mit einer eindeutigen Instanz implementieren - ggf. auch mit Listener.

Hinweis Dazu : Statische Variablen (wie z.b. in C, PHP etc.) , die über den gesamten Zeitraum zur Verfügung stehen,
gibt es unter Android nicht. Android kann jederzeit den dazu benötigten Speicher freigeben.
Siehe auch hierzu die Schlüsselwörter LifeCycle / GarbageCollector.

Zum Schluss möchte ich dir für das OOP Basiswissen noch ein wenig Literatur empfehlen :
Rheinwerk Computing :: Java ist auch eine Insel - Inhaltsverzeichnis
 
Zuletzt bearbeitet:
H

HerrFatalVonError

Neues Mitglied
Hallo @swa00,

wow, ersteinmal Danke das du dir für eine ausführliche Antwort Zeit genommen hast ☺

Habe mich einwenig eingelesen und das Listener/Callback Model ist genau das was ich gesucht habe. Merke auch das ich mir mehr Basiswissen aneignen sollte...😅

Habe allerdings noch ein paar Design Fragen bei denen du mir einen kleinen Stupser geben könntest.

1) Für die Übungen habe ich die SQLit Datenbank implementiert, was auch ganz gut klappt. Allerdings habe ich über 100
Übungen und jede besitzt ein eigenes Bild. In der Datenbank habe ich den ImagePath der Bilder hinterlegt, welche in einem Assetfolder hinterlegt sind und über Picasso in das ImageView geladen werden.
Ist dieser Weg sinnvoll oder bekomme ich später (wenn ich die Datenbank fülle) perfomanceprobleme? Wie würdest du das handeln ?

2) Ich würde gerne Pläne auch in einer Datenbank speichern, allerdings habe ich bisher keinen einfachen Weg gefunden Baumstrukturen in SQLite aufzubauen (Bild meines Ausgangsposts). Denke momentan darüber nach Pläne als BLOB in SQLite zu speichern, allerdings müsste ich die Datenbank dann jedesmal über die App erstellen. Würde gerne unabhängig von der App die SQLite Datenbank füllen können z.B. über CSV Dateien (bezogen auf BLOB inahlt). Was empfiehl sich da ?

3) Singleton. Macht es Sinn benutzeinstellungen beim App start über sharedPref in einen Singleton zu laden und dann nur mit diesem SIngeton zu arbeiten und nur bei Änderungen die JSON zu aktualisieren ?

Vielen dank im Voraus!

Schönen Gruß!
 
Zuletzt bearbeitet:
swa00

swa00

Moderator
Teammitglied
Ist dieser Weg sinnvoll oder bekomme ich später (wenn ich die Datenbank fülle) perfomanceprobleme? Wie würdest du das handeln ?
Ja bekommst du - wegen dem Cache - Verwende dazu die Library Glide

Zu 2) Habe ich noch nicht umgesetzt - Sorry
Zu 3) Yupp, nimm eine SingleTon und mach das darin - Setze ich auch so um
 
H

HerrFatalVonError

Neues Mitglied
Hallo @swa00,

ich habe wie von dir vorgeschlagen jeder Klasse einen Listener verpasst und über Callback die public Methoden ausgeführt. Das funktioniert erst einmal soweit, ABER:

Nachdem ich die Plan-Klasse (das Object in welchem die Listener implementiert sind) über SharedPrefs speicher und wieder lade verlieren die Klassen die Referenz zu den listener und ich bekomme eine NullPointerException.

Gibt eine Möglichkeit die Listener mit zu Serialisieren oder sollte ich nur den Plan Status (Was wurde gemacht ect.) speichern und bei jedem Appstart laden und das Planobject neu erzeugen und der Runtime zur Verfügung stellen ?

Grüße
 
swa00

swa00

Moderator
Teammitglied
Nein , wie oben schon geschrieben : Nimm eine SingleTon zum Lesen und Speichern der SharedPreferences.
Dazu baust du dir Getter/Setter/Globale Variablen.

In der MainActivity erstellst du dir EINE Instanz der SingleTon und greifst in jetzt in den SubClasses auf diese Instanz zu.
 
Zuletzt bearbeitet:
H

HerrFatalVonError

Neues Mitglied
Tut mir leid ich verstehe nicht genau wie du das meinst 🤗

Also soll ich quasi den Plan als SingleTon serialisieren und mir gehen dann beim laden nicht die referenzen der Listener verloren ?

Sorry, ich bin noch am lernen.
 
J

jogimuc

Stammgast
Gibt eine Möglichkeit die Listener mit zu Serialisieren oder sollte ich nur den Plan Status (Was wurde gemacht ect.) speichern und bei jedem Appstart laden und das Planobject neu erzeugen und der Runtime zur Verfügung stellen ?
Hallo du kannst keine Instanz in den Pref speichern. Die Instanz eines Objektes ist beim erstellen also beim neu starten der App immer anders.

Also soll ich quasi den Plan als SingleTon serialisieren und mir gehen dann beim laden nicht die referenzen der Listener verloren ?
Die werden dir bei einen kompletten APP oder Activity Neustart immer verloren gehen.
Auch die Instanz der Singelton Klasse wird nach dem beenden und App Neustart anders sein.
Eine Referenz kannst du nicht in den ShPref speichern nur den Inhalt den Wert auf den die Ref zeigt.
 
Zuletzt bearbeitet:
H

HerrFatalVonError

Neues Mitglied
@jogimuc
und das ist der Grund weswegen die Listener nicht mehr funktionieren. Das habe ich soweit verstanden. Also wäre jetzt der richtige Weg ein neues Objekt zu erzeugen, welches "funktionierende" Listener besitzt und die Daten aus dem gespeicherten in dieses neue Objekt zu übertragen ?

Bzw. ich könnte eine Methode schreiben die bei Appneustart die Listener neu initialisiert... ?

Bin total verwirrt -.-
 
Zuletzt bearbeitet:
J

jogimuc

Stammgast
Wenn du zu Laufzeit neue Objekte erstellt musst du die nach dem beenden der APP und Neustart auch wider erstellen. Du kannst dir nur die in dem Objekt gespeicherten Daten speichern nicht die Ref auf das Objekt.
Das ist ja ein dynamisch vergebener Speicher der nach dem beenden freigeben wird.

Wenn du also in deiner Klasse "Plan" 10 Objekte von Klasse "Übung" zur Laufzeit erstellst.
Dann die App beendest und neu startest musst auch wider die 10 Objekte erstellen und in den Objekten auch wider die alten Daten laden.
Beitrag automatisch zusammengefügt:

Gibt eine Möglichkeit die Listener mit zu Serialisieren oder sollte ich nur den Plan Status (Was wurde gemacht ect.) speichern und bei jedem Appstart laden und das Planobject neu erzeugen und der Runtime zur Verfügung stellen ?
das sind eigentlich zwei fragen.
den ersten teil würde ich mit nein beantworten,
den zweiten nach dem oder mit ja.

Also wäre jetzt der richtige Weg ein neues Objekt zu erzeugen, welches "funktionierende" Listener besitzt und die Daten aus dem gespeicherten in dieses neue Objekt zu übertragen ?
Ja
 
Zuletzt bearbeitet:
H

HerrFatalVonError

Neues Mitglied
Hallo @swa00 und @jogimuc

danke für eure super Hilfe.
Habe den aktuellen Plan als SingleTon implementiert und speicher diesen auch als SharedPref ab.
Habe eine Methode in den einzelnen SubClassen geschrieben um die Listener zu initialisieren. Diese Methode rufe ich jeweils beim laden des Plans auf. Das klappt! 😃

Keine Ahnung ob das der common way ist aber es funzt.
Kann geschloßen werden, was nicht heißt, dass ich nicht in Zukunft mit neuen tollen Fragen um die Ecke kommen werde 😈

Grüße!
 
Zuletzt bearbeitet:
Ähnliche Themen - Programmarchitektur - Frage zum Design Antworten Datum
2