ioBroker.javascript icon indicating copy to clipboard operation
ioBroker.javascript copied to clipboard

Refactoring common/global Scripte

Open uwe72 opened this issue 10 months ago • 4 comments

@GermanBluefox Ich würde mir wünschen, dass der JS-Adapter es besser unterstützt redundant freien Code zu schreiben. Aktuell ist dies nur möglich den Code, welcher an mehreren Stellen verwendet werden soll, in ein "Global"-Script zu packen. Dieser "Global-Script" Code wird dann ja in alle "Common-Scripte" reinkopiert, ob er dort benötigt wird oder nicht. Zudem wird die JS-Script Instanz nicht ausgewertet.

Dieses Konzept/diese Architektur ist nicht optimal, insbesondere wenn man viel in JS/Typescript macht.

Aktuell behelfe ich mir so, dass ich Code auf der Filesystem auslagere und in den common-Scripten wo ich ihn benötige referenziere: https://forum.iobroker.net/topic/78632/info-auslagerung-von-global-scripten-ins-filesystem/1

Die Scripte sollten aber nicht im Filesystem liegen, sondern sollten auch innerhalb der JS-Instzanz gepflegt werden können.

Also eigentlich genauso wie jetzt, d.h. es müsste den Bereich global-Scripte geben. Aber statt einfach nur alles von dort in die common-Scripte zu kopieren, müsste es so sein, dass man in jedem Common-Script per import/require Statement den Code aus Global referenzieren kann und eben nur dort, wo man den Code auch benötigt. Idealerweise sollte man auch bei den GlobalScripten, andere Global-Scripte referenzieren können. So wie man dies in OOP eigentlich macht,

Das Ganze für JavaScript, wie auch für TypeScript.

uwe72 avatar Dec 20 '24 10:12 uwe72

Erstell dafür doch gern mal ein Konzept.

  • Wo pflegt man die Scripts genau (wie soll das heißen)
    • Diese Scripts kann man ja dann (logischerweise) nicht starten oder stoppen, richtig?
  • Wie sieht der require Pfad aus, damit man genau weiß, dass es aus diesem Bereich kommt
  • Was passiert, wenn so ein Script geändert wird? Starten dann alle Scripts neu, welches dieses referenzieren?

Das wird ja beliebig komplex.

klein0r avatar Dec 20 '24 11:12 klein0r

Option 1.) In der einfachsten Version bleibt alles wie es ist. D.h. es gibt global Scripte, welche sich gleich Verhalten wie aktuell mit der einzigen Ausnahme, dass sie eben nicht automatisch in jedes Common-Script reinkopiert werden. Sie werden nur reinkopiert wenn im Common-Script per require oder import das "Global-Script" eingebunden wird, z.B. import "my_global_script". Die Importfunktionalität existiert nur bei Common-Scripten

Option 2.) Wie Option 1 mit dem Unterschied, dass auch in einem Global-Script ein anderes "Global-Script" per Import eingebunden werden kann

Option 3.) Zusätzlich zu Common und Global, ein neuer Bereich "Re-Use" Scripte oder ähnliches. Diese Scripte können in Common-Scripte importiert werden. Global-Scripte verhalten sich wie heutzutage.

Option 4.) Wie Option 3 mit dem Unterschied, dass auch in einem Re-Use-Script ein anderes "Re-Use-Script" per Import eingebunden werden kann

Option 5.) Eine der vorherigen Optionen, aber feingranularers importieren von Code: Statt ganzer Scripte zu importieren (Option 1-4) könnte man das Ganze importieren auf Funktionen oder Klassen machen. D.h. z.B. import "sendCurrentGardenCameraSnapshotToTelegram"

Bei allen Optionen: Wenn sich ein Script ändert, wo anderswo referenziert wird, muss auch das Script, welches ein geändertes Script referenziert, neu geladen werden. So wie heutzutage auch, wenn sich ein Global-Script ändert. Dann müssen ja auch alle Common-Scripte neu geladen werden.

Frage von oben "Diese Scripts kann man ja dann (logischerweise) nicht starten oder stoppen, richtig?" --> Doch kann man auch stoppen und starten, analog den heutigen Global-Scripten, die kann man ja auch starten und stoppen. Wenn es gestoppt ist, wird es eben trotz import-Statement nicht eingebunden oder es wird ein Fehler geworfen. Könnte mit beidem leben. Wenn es einfacher ist, müssten diese "reuse" Scripte auch nicht gestartet und gestoppt werden können.

uwe72 avatar Dec 20 '24 18:12 uwe72

Mein Senf aka Input:

a) Das Verhalten für existierende Umgebungen darf sich nicht verändern. Ergo müssen Skripte die sich jetzt in Global befinden weiterhin unverändert vor allen anderen Skripten eingefügt werden.

b) Skripte die per "require" eingebunden werden sollten daher entweder in einen neuen, namentlich fixierten Ordner liegen müssen oder das "require" Statement kann den vollen Pfad incl. Ordner spezifizieren,

c) Ein automatischer Restart aller Skripte die ein verändertes Skrip includieren ist m.E. nicht notwendig. Wenn ich im Filesystem ein Script ändere werden laufende Prozesse die dieses Skript verwenden auch nicht automatisch neu gestartet. Ein Neustart kann daher, muss aber m.E. nicht erfolgen (-> Aufwandsabschätzung)

d) Es besteht derzeit bereits die Möglichkeit Skripte ins Filesystem zu spiegel. Wenn man diese Funktion mandatory macht, sprich Skripte werden immer auch im Filesystem abgelegt, könnte es funktionieren die standardmäßigen Funktionen import / require zum Includieren zu verwenden. Die Verwaltung und das Editieren würden dabei im JS Adapetr bleiben. Müsste man testen.

e) Zu den optionen im letzten COmment: Option1) ist m.E. nicht umsetzbar, da dies einen super-breaking-change bedeuten würde. Anpassungen an einer Vielzahl von Skripten wäre notwendig. Option 2) ist m.E. nicht umsetzbar, da Option 1) m.E. nicht akzeptabel ist. Option 3) und 4) OK nur wenn sinnvoll möglich mit freier Namenswahl (der Wunsch kommt sonst 2 Wochen später eh nach... Option 5) Bei Verwendung der normalen Require / Import Funktion würde sich das m.E. implizit ergeben.


P.S. Wenn ich mir Punkt d) so durchdenken ... geht das nicht ev schon jetzt OHNE Codeänderungen?

mcm1957 avatar Dec 21 '24 15:12 mcm1957

Am Ende wäre ich bei der Idee da irgendwie "Module" einzuführen. Als neuen "Skript"-Bereich neben Globals. Damit ist es mal getrennt.

Für diese "Modules" müsste es dann eine definition geben wie genau die aussehen müssen - am Ende ähnlich wie Module in JS ... also das was man braucht muss man "exportieren" und so. Also Wie es halt in JS ist. Nur so kann man interne Logik haben vs exportierter. Das ganze dann auch mit TS und "Building" zu machen wird bissl challenging aber ok.

Dann müsste man das ganze im Filesystem spiegeln und in einer STruktur (ein verzeichnis pro Modul oder so) ablegen.

Man müsste sowas wie "localRequire()" oder "localImport" definieren was die Namen dieser Module nimmt und lokal umschreibt ( einmal für den Fall das sich Module untereinander referenzieren und einmal für "Skripte referenzieren" weil das ggf dann anders aussehen muss.

... Am Ende coole Idee, und einiges an Aufwand das sauber und mit allen edge cases hinzubekommen das das dann sauber in der VM/Sandbox vom JavaScript Adapter läuft.

Das wären meine 5cents dazu

Apollon77 avatar Jan 02 '25 16:01 Apollon77