Implémenter le cache global et le singleton
Vous pouvez améliorer les performances de votre code à l’aide de la mise en cache. Les avantages augmentent pour les données ou le code fréquemment utilisé(es). Vous pouvez implémenter la mise en cache globale sur une session client spécifique ou l’appliquer à tous les clients d’un serveur. Dans certains scénarios, vous pouvez utiliser la mise en cache globale pour des paramètres supplémentaires dans une signature de méthode, car les signatures de méthode ne sont pas modifiables avec les extensions.
Important
Vous devez gérer la mise en cache avec soin, car elle impacte la consommation de mémoire. La mise en cache globale stocke les valeurs en mémoire et, en tant que développeur, vous êtes responsable de la mise à jour et de la suppression des données obsolètes du cache. Ignorer le nettoyage de la mise en cache globale peut nuire aux performances.
Les bonnes pratiques relatives à l’implémentation de la mise en cache dépendent de vos cas d’utilisation.
SysGlobalCache et singleton
Les termes SysGlobalCache et singleton désignent un cache de session client unique inaccessible dans d’autres threads système. Le système nettoie ce cache une fois la session client terminée, mais il est recommandé de le nettoyer après l’avoir utilisé.
Vous pouvez créer le cache SysGlobalCache d’une instance de la classe SysGlobalCache, mais nous vous recommandons de le créer depuis les classes système suivantes afin de faciliter le nettoyage :
- Depuis la classe Application à l’aide de la variable système
appl - Depuis la classe ClassFactory à l’aide de la variable système
classFactory - Depuis la classe Info à l’aide de la variable système
Infolog
Toutes les classes système répertoriées ont le globalCache déjà défini et vous pouvez les utiliser.
La classe SysGlobalCache stocke les données sur une clé spécifique et possède plusieurs méthodes couramment utilisées :
Construct: vous permet de créer une instance du cache SysGlobalCache. À l’aide de l’une des classes système, par exemple Application, ClassFactory ou Info, cette méthode crée automatiquement une instance si elle n’existe pas encore.Get: récupère une valeur d’un propriétaire et d’une clé spécifiques.Set: définit une valeur sur un propriétaire et une clé spécifiques.IsSet: vérifie si le cache est défini pour un propriétaire et une clé spécifiques.
Le système stocke les valeurs dans le cache SysGlobalCache à l’aide d’un propriétaire et d’une clé.
L’exemple suivant montre comment vérifier si une valeur existe, obtenir une valeur et définir une valeur à l’aide du cache SysGlobalCache.
internal final class RunnableClass1
{
/// <summary>
/// Class entry point. The system will call this method when a designated menu
/// is selected or when execution starts and this class is set as the startup class.
/// </summary>
/// <param name = "_args">The specified arguments.</param>
public static void main(Args _args)
{
const str mySysGlobalCacheKey = 'MySysGlobalCacheKey';
str mySysGlobalCacheOwner = classStr(RunnableClass1);
SysGlobalCache cache = classFactory.globalCache();
container cacheValue;
if (cache.isSet(mySysGlobalCacheOwner, mySysGlobalCacheKey))
{
cacheValue = cache.get(mySysGlobalCacheOwner, mySysGlobalCacheKey);
}
else
{
cacheValue = ['MyValue'];
cache.set(mySysGlobalCacheOwner, mySysGlobalCacheKey, cacheValue);
}
cache.remove(mySysGlobalCacheOwner, mySysGlobalCacheKey);
}
}
Vous pouvez obtenir le même résultat à l’aide d’une classe Singleton (pour la session utilisateur), à savoir une instance de la classe que le système créé dans la classe. Une utilisation courante de cette instance dans les applications de finances et d’opérations concerne les classes en version d’évaluation, comme l’illustre le code suivant.
/// <summary>
/// When <c>AccountingFinTagFlight</c> is enabled, the uptake of financial tags functionality in the
/// Source Document and Accounting Framework is turned on. This allows documents implementing SDAF
/// to opt into processing of financial tags and provide their values during accounting distribution.
/// </summary>
public final class AccountingFinTagFlight extends Flight
{
private static AccountingFinTagFlight singleton = new AccountingFinTagFlight();
[Hookable(false)]
protected boolean isEnabledByDefault()
{
return false;
}
[Hookable(false)]
public static AccountingFinTagFlight instance()
{
return singleton;
}
}
Dans cet exemple de l’application standard, le système crée une instance de la classe AccountingFinTagFlight, mais une seule fois pour la session utilisateur.
Le cas d’utilisation définit l’approche, et le système utilise le cache SysGlobalCache et le singleton dans l’application standard.
SysGlobalObjectCache
Le cache SysGlobalObjectCache est une mise en cache partagée par serveur sur toutes les sessions utilisateur sur un serveur spécifique.
Le cache SysGlobalObjectCache est un singleton et vous ne pouvez l’utiliser qu’une seule fois dans le système. Son obtention à partir de la classe ClassFactory ou l’initialisation d’un nouveau cache SysGlobalObjectCache fait toujours référence à la première instance créée de la classe SysGlobalObjectCache.
Vous définissez le cache SysGlobalObjectCache sur une étendue, au lieu de l’associer à un propriétaire comme dans le cache SysGlobalCache.
Le but de l’utilisation du cache SysGlobalObjectCache consiste à stocker des valeurs statiques dans un cache pour toutes les sessions, afin que le système n’ait pas besoin de les relire ou de les calculer pour chaque session.
L’exemple suivant des applications de finances et d’opérations illustre une nouvelle instance du cache SysGlobalObjectCache. Cependant, si l’instance est déjà créée, le système fait référence au cache SysGlobalObjectCacheexistant, donc il n’en existe qu’un seul, ou un singleton, dans le système.
public boolean findExternalDescription()
{
boolean found;
container cacheKey;
container cacheValueExistsCheck;
boolean continueProcessing;
SysGlobalObjectCache sysGlobalObjectCacheExistCheck = new SysGlobalObjectCache();
cacheKey = [custVendAccountId, this.parmCustVendItemGroupId(), this.moduleType(), curExt()];
//Check for existence
cacheValueExistsCheck = sysGlobalObjectCacheExistCheck.find(CustVendExternalItemDescription::cacheScopeExistsCheck(), cacheKey);
//We have not checked this combination before
if (cacheValueExistsCheck == conNull())
{
if (CustVendExternalItem::existsForCustVendRelation(custVendAccountId, this.parmCustVendItemGroupId(), this.moduleType()))
{
// at least 1 record available for the customer/vendor group or customer/vendor
continueProcessing = true;
}
else
{
// no record available for the customer/vendor group or customer/vendor
continueProcessing = false;
}
sysGlobalObjectCacheExistCheck.insert(CustVendExternalItemDescription::cacheScopeExistsCheck(), cacheKey, [continueProcessing]);
}
else
{
[continueProcessing] = cacheValueExistsCheck;
}
if (continueProcessing)
{
[found, externalItemId, externalItemFreeTxt, custVendExternalItem] =
CustVendExternalItemDescription::findExternalItemDescription(this.moduleType(), itemId, inventDim,
custVendAccountId,this.parmCustVendItemGroupId());
}
return found;
}
Vous pouvez supprimer toutes les entrées dans le cache SysGlobalObjectCache pour un serveur en exécutant une classe utilisant l’URL suivante : https://[votre URL des applications de finances et d’opérations]/?mi=SysClassRunner&cls=SysFlushAOD.
La classe SysFlushAOD efface tout le cache dans le cache SysGlobalObjectCache.
Classes de contexte
Avec les extensions, vous ne pouvez pas modifier la signature de la méthode. Autrement dit, vous ne pouvez pas ajouter de nouveaux paramètres à une méthode existante.
Remarque
Comme indiqué précédemment, vous pouvez modifier la signature de la méthode avec superposition en ajoutant un nouveau paramètre pour une méthode. Cependant, vous pouvez étendre la signature de la méthode à l’aide d’un contexte Jetable. Lorsque vous implémentez IDisposable sur la classe de contexte, cela vous oblige à avoir une méthode d’élimination à utiliser pour le nettoyage.
L’exemple suivant crée une classe de contexte pour SalesPool avec un paramètre nommé myParameter.
internal final class MySalesPoolContext
{
static MySalesPoolContext salesPoolContext;
public boolean myParameter;
public void new()
{
salesPoolContext = this;
}
public void dispose()
{
salesPoolContext = null;
}
static public MySalesPoolContext current()
{
return salesPoolContext;
}
}
Vous pouvez maintenant ajouter une extension à la méthode find pour la table SalesPool. Vous devez tester le nouveau paramètre que vous avez créé dans la classe de contexte sans modifier la signature de la méthode find, comme suit :
[ExtensionOf(tableStr(SalesPool))]
final class SalesPool_MB500_Extension
{
static SalesPool find(SalesPoolId _salesPoolId,
boolean _forUpdate)
{
SalesPool salesPool = next find(_salesPoolId, _forUpdate);
MySalesPoolContext salesPoolContext = MySalesPoolContext::current();
if (salesPoolContext && salesPoolContext.myParameter)
{
// some code...
}
return salesPool;
}
}
À des fins de test, l’exemple suivant crée une classe exécutable et vous pouvez configurer la variable context parameter pour appeler les méthodes d’élimination pour nettoyer après avoir utilisé la classe.
internal final class MySalesPoolContextTest
{
/// <summary>
/// Class entry point. The system will call this method when a designated menu
/// is selected or when execution starts and this class is set as the startup class.
/// </summary>
/// <param name = "_args">The specified arguments.</param>
public static void main(Args _args)
{
SalesPool salesPool;
MySalesPoolContext mySalesPoolContext = new MySalesPoolContext();
mysalesPoolContext.myParameter = true;
salesPool = SalesPool::find('10');
if (mySalesPoolContext)
{
mySalesPoolContext.dispose();
}
}
}
La création d’une classe de contexte en tant que singleton vous permet de transférer des paramètres sans modifier la signature de la méthode.