Eigene Funktionen

Hallo,

ich hatte das auf dem Community-Day gegenüber Christoph schon mal angesprochen, will es jetzt aber doch nochmal forcieren ;-)

Ich wünsche mir die Möglichkeit Funktionen zu schreiben - die dann nicht nur im selben Step in der selben Spalte nutzbar sind, sondern überall (nachdem sie definiert wurden).

Das macht die Wartung später einfacher. Bisher schreibe ich mir halt das Freemarker-Script, kopiere es in jede Spalte, und passe dann überall x-mal die entsprechenden Variablen/Spaltennamen an. Wenn ichs irgendwo übersehe, stimmen meine Ergebnisse natürlich nicht.

Beispiel aus der Praxis: im Flow SH_Kalkulation werden viele gleichförmige Berechnungen für mehrere Spalten ausgeführt, z.B. in Step 67:

Code Spalte FINAL_Amazon_MAX:

<#if (Result_Amazon_MAX_Modus?lower_case == "prozent")>
  ${Result_Amazon_MAX_Prozent}
<#elseif (Result_Amazon_MAX_Modus?lower_case == "betrag")>
  ${Result_Amazon_MAX_Betrag}
<#elseif (Result_Amazon_MAX_Modus?lower_case == "uvp")>
  ${NUM_UVP}
<#else>
  UNKNOWN_MODE
</#if>

Code Spalte FINAL_Webshop:

<#if (Result_Webshop_Modus?lower_case == "prozent")>
  ${Result_Webshop_Prozent}
<#elseif (Result_Webshop_Modus?lower_case == "betrag")>
  ${Result_Webshop_Betrag}
<#elseif (Result_Webshop_Modus?lower_case == "uvp")>
  ${NUM_UVP}
<#else>
  UNKNOWN_MODE
</#if>

Statt dessen würde ich gerne eine Funktion in diesem Stil schreiben:

function getFinalPrice (Modus, Prozent, Betrag, UVP) {
  if ($Modus == "prozent") {
    $this_column = $Prozent
  }
  else if ($Modus == "betrag") {
    $this_column = $Betrag
  }
  else if ($Modus == "uvp") {
    $this_column = $UVP
  }
  else {
    $this_column = "UNKNOWN_MODE"
  }
}

Pseudocode, ihr versteht was ich meine...


Mein Spalteninhalt wird dann deutlich kürzer und übersichtlicher, in etwa:

getFinalPrice(Result_Webshop_Modus, Result_Webshop_Prozent, Result_Webshop_Betrag, NUM_UVP)

Das ist ein Einzeiler (ok, ist am Ende jedes Script, aber genau das macht es noch unübersichtlicher), ich änder da nur noch die Argumente, und fertig.

--------------------


Falls das irgendwann mal kommen sollte (ist klar dass das kein Simpelfeature ist...), hätte ich noch eine Bonus-Anregung:

Ich übergeb jetzt ja hier trotzdem vier Argumente. Wenn ich Spaltennamen geschickt wähle, mir mit Stringoperationen andere Spaltennamen generieren könnnte, und dann auf alle Spalten auch ohne dass sie Argumente sind frei zugreifen könnte, könnte man das ganze noch simpler gestalten. Beispiel:

function getFinalPrice (Type) {
  if (Result_{$Type}_Modus == "prozent") {
    $this_column = Result_{$Type}_Prozent
  }
  else if (Result_{$Type}_Modus == "betrag") {
    $this_column = Result_{$Type}_Betrag
  }
  else if (Result_{$Type}_Modus == "uvp") {
    $this_column = $UVP
  }
  else {
    $this_column = "UNKNOWN_MODE"
  }
}

Jetzt könnte ich getFinalPrice("Webshop") aufrufen, und würde das selbe Ergebnis erhalten. Das wäre ein Träumchen =)


Grüße Daniel

Hallo Daniel,

danke für die Erinnerung. Wir haben da bereits ein internes Ticket aber pushen das jetzt noch mal und besprechen das dann in einem der nächsten Planungen.




Kurzes Lebenszeichen: Wir haben heute mit ersten Planungen und internen Besprechungen begonnen. D.h. ein Kollege beginnt jetzt mit den Planungen und ersten Schritten für dieses Feature.

Wieder ein kurzes Lebenszeichen:

Die Arbeiten sind jetzt schon recht weit fortgeschritten. Hier mal ein Eindruck aus der Entwicklung.


Man kann sog. "Snippets" im Backend pflegen. Das können aktuell Freemarker <#function> und <#macro> sein.



Diese kann man dann im Mapper auswählen und einfügen.



und dann ausführen.




Da das Feature sehr tief im System angesiedelt ist dauert es aber sicher noch ein paar Wochen mit polieren, Tests, QA, Doku usw.


Super das das anläuft, freut mich.


Early-Feature-Request: eine Variable die den (alten) Zellwert enthält. So kann ich Zellen in Abhängigkeit von was auch immer entweder nullen, oder den alten Wert erhalten. Und kann die Formel in andere Spalten kopieren ohne dass sie bricht.


Grüße Daniel

Kannst du das vielleicht mal am Beispiel erklären? Was für einen "alten" Zellwert meinst du. Du hast ja immer die Parameter, die du in die Funktion reingeben musst. Die werden ja nicht verändert. Die Funktion gibt dir einen Wert zurück.


Hier mal ein Beispiel, wie es sein wird.


${brandname} / ${my.meineFunctionUpperCase(brandname)}

Ergebnis: "Tolle Marke" / "TOLLE MARKE"


Mit anderen Worten: Die Funktion kann nur mit den Parametern arbeiten, die du hinein gibts.


Wir schlagen aber vor, dass wir erstmal die Funktionen releasen (passiert in den nächsten Tagen) und dann am konkreten Beispiel diskutieren. Aktuell hat das neue Feature ausser uns ja noch niemand gesehen :)



Nehmen wir an cell.value ist immer der Wert der konkreten Zelle.
Dann kann ich mir eine Funktion schreiben:

function cleanCell(wert) {
  if (isNumber(wert)) {
    return wert;
  } else {
    return 0;
  }
}

Und habe damit sicher eine Zahl in meiner Zelle stehen und bekomme nie wieder den Fehler dass ich ?number auf einen Wert angewendet hätte der keine Zahl ist.

Wenn ich cleanCell(cell.value) aufrufen könnte kann ich die Funktion in alle Spalten copypasten ohne sie anpassen zu müssen. Alternativ müsste ich in jede Zelle cleanCell(Spaltenname) schreiben und den Spaltennamen ständig anpassen...

Aber natürlich: released ihr erstmal das Feature (wenn ihr soweit seid)! Wollte euch nichts vorweg nehmen, nur meinen Gedanken irgendwo festhalten bevor er wieder weg ist ;-)

Grüße Daniel

PS: Ein cell.title o.ä. für den Spaltentitel wäre auch nett. Ordentliche Spaltenbenennung vorausgesetzt kann die Funktion damit selbst erkennen "wo" sie eingesetzt wird, und ihr Verhalten anpassen.

cell.value geht schon jetzt über Skripting Funktion und

${value!}




D.h. sobald die Funktionen verfügbar sind könntest du ein


${my.cleanCell(value!)}


in die Skripting Funktion packen.



cell.title geht über den "Aktueller Spaltentitel" beim Plus-Button.


${_currentTitle!}




Ah super, da sieh an. Hatte mich damit nicht in der Tiefe auseinander gesetzt.

Dann freu ich mich auf das erste Release! Grüße Daniel

Kurze Zwischenfrage:

Deine von dir genannte Funktion (cleanCell), die dir immer eine Zahl oder 0 liefert: die klingt sinnvoll und wir würden so eine Funktion auch als Standardfunktion entwickeln. Dann musst du diese nicht selbst bauen.


Vom Naming her wären die Vorschläge:

  • toNumber
  • number
  • ensureNumber
  • asNumber


Feedback willkommen.


Zusatzfrage: Hättest du noch so ein paar "typische" Aufräumfunktionen, die du häufig selbst baust? Also möglichst allgemeine Dinge, die man universell einsetzen kann, so wie dein Beispiel. Wenn ja, dann immer her damit.

Die eigenen Funktionen gehen gerade live und werden in den nächsten Stunden deployed. Auf Backend-Servern ist es schon drauf.


Handbuch hier.


Happy Testing :)

Die Snippets finde ich super, grade schon eins erstellt. Eine Anregung habe ich dazu auch noch.

Mein erste Gedanke (nach dem Erstellen eines Snippets) war, eine Diskussion für "General-Purpose"-Snippets zu erstellen. Dort kann dann jeder seine Snippets der Allgemeinheit zur Verfügung stellen oder die Snippets der anderen durchstöbern und sich inspirieren lassen (oder den Code von anderen klauen).

Dazu vermisse ich aber ein Feature, und zwar Im-/Export eines Snippets von/nach ...(JSON?). Denke, der Grund ist nachvollziehbar. Ohne Import-Funktion ist das Teilen von Snippets mit viel Copy-Paste verbunden.

Möglicherweise habt ihr das ja bereits geplant, Feature ist ja grade erst erschienen. Dachte, ich spreche es aber mal an.


Vielleicht macht es auch Sinn, dafür einen eigenen Foren-Bereich zu erstellen. Dann kann man für jedes Snippet einen eigenen Thread erstellen.

Ein Thread ist m.M.n. nicht wirklich gut geeignet für mehrere parallele Diskussionen, durch Fehlen einer Zitatfunktion bzw. Verweis auf frühere Posts. Da verliert man schnell den Überblick. Außerdem passt das nicht wirklich gut in den Fragen & Antwort-Bereich.

Ist natürlich nur ein Vorschlag und hängt stark davon ab, wie aktiv die Community sich beteiligen wird.



Ps.: Nur so am Rande, mit den Snippets ist das jetzt natürlich deutlich hübscher zu lösen.


Den Fehler mit ?number auf leere Strings anwenden, bin ich mit folgender Formel immer umschifft:

("0" + value!)?number 

Klappt natürlich nur, wenn das Feld nie Text enthält sondern nur Zahlen.

Hallo Gustav,


danke für deine Anregungen. Also ein Import/Export ist noch geplant - fehlt einfach nur im ersten Wurf, da wir erstmal die Basisfunktionalität sicher stellen wollen.


Der eigenen Forenbereich klingt gut. Könntest du das vielleicht nochmal als separates Thema aufmachen? Also quasi eine Art Umfrage-Thread, für so ein neues Unterforum. Interessant wäre, wie man das nennt und ob es generell ein Forum wäre, wo man Dinge für die Allgemeinheit "teilt". Das wichtigste für die Community ist ja dann, das mal einer anfängt :)

Hallo Synesty,


Ich finde das neue Feature super, ich habe auch bereits ein paar Test weise bei uns angelegt.

ich fände es echt cool, wenn man Workspace-übergreifende Snippets hätte.

Wir haben bei uns recht viele Workspaces, da wäre es praktisch, wenn man nicht für jeden Workspace die selben Snippets neu anlegen müsste.


Viele Grüße

Stefan

Hallo Stefan,

wir dachten uns, dass das von euch kommt ;) Ja, wir haben schon begonnen ein Konzept dafür zu erarbeiten. Ist aber ein größerer Brocken, da nicht nur Snippets "global" sein sollen.

Wir halten euch hier auf dem Laufenden. Zuerst wird es einen Import/Export geben. Der löst zwar noch nicht komplett dein Problem, aber macht es etwas einfacher.


PS: Habe grade darüber nachgedacht, wie ich mein Snippet durch die Funktion ersetzen würde, wenn sie denn live geht. Dafür muss ich ja jede Stelle finden, wo ich mein Snippet aufrufe. Habt ihr da bereits sowas ähnliches wie "Referenzierende Flows anzeigen" beim DataStore geplant? Das man auf einer Seite alle Aufrufe von einem Snippet sehen kann?

Möchte nochmal hierauf zurückkommen. Kommt eigentlich aus https://synesty.freshdesk.com/support/discussions/topics/11000031422, ist hier aber vermutlich besser aufgehoben.

Ist so eine Auflistung der Aufrufe im Rahmen des Möglichen? Ohne wird es schwierig, eine obsolete Funktion zu löschen. Man weiß ja nicht, welche Flows die Funktion benutzen und kaputt gehen, wenn die Funktion fehlt. Dadurch wäre man gezwungen, die Funktion als "Altlast" zu behalten.


Im Falle von der deduplicate-Funktion ist das ja noch nicht kritisch, ist aber schonmal ein gutes Beispiel. Ich weiß ja noch, wo die eigene Funktion überall eingesetzt wurde. Ohne dieses Wissen müsste ich auf Fehlersuche gehen, nachdem ich mein eigenes Snippet gelöscht habe.

Wir haben das "Referenzierende Flows anzeigen" bereits für den aktuellen Sprint eingeplant. Kommt also innerhalb der nächsten 2 Wochen.


Die Snippet-Referenzsuche ist jetzt live.
Im Snippet rechts oben gibt es einen Button "Zeige Referenzen im Workspace". Dieser durchsucht alle Flows im aktuellen Workspace nach der Verwendung des Snippets.