IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Apple lance Pkl, un langage de programmation open-source de type configuration en tant que code

Le , par Jade Emy

96PARTAGES

10  0 
Apple a lancé Pkl, un nouveau "langage de configuration intégrable" open source, dans l'espoir d'alléger les tâches de configuration, qu'elles soient petites ou grandes, simples ou complexes, ad hoc ou répétitives.

Lancé le 1er février 2024 dans sa version 0.25, l'équipe du géant de la technologie a fourni une "visite rapide" du langage dans un texte publié sur le site Web de documentation de Pkl. Selon cette présentation, Pkl est conçu autour d'une structure de valeurs clés, d'une manière proche de JSON, plutôt que d'instructions impératives comme beaucoup d'autres langages de programmation traditionnels. Apple a conçu Pkl pour se spécialiser dans la configuration, avec quelques caractéristiques de qualité de vie soignées pour faire tourner les têtes. En effet, Pkl prend en charge les listes de propriétés JSON, XML et YAML dès le lancement pour générer des fichiers de configuration statiques.

Voici la présentation de Pkl par Apple :

[QUOTE]Présentation de Pkl, un langage de programmation pour la configuration

Nous sommes ravis d'annoncer la première version open source de Pkl (prononcé Pickle), un langage de programmation pour la production de configuration.

Lorsque l'on pense à la configuration, il est courant de penser à des langages statiques tels que JSON, YAML, ou Property Lists. Bien que ces langages aient leurs propres mérites, ils ont tendance à ne pas être à la hauteur lorsque la configuration devient de plus en plus complexe. Par exemple, leur manque d'expressivité signifie que le code est souvent répété. En outre, il peut être facile de commettre des erreurs de configuration, car ces formats ne fournissent aucune validation propre.

Pour remédier à ces lacunes, les formats sont parfois améliorés par des outils auxiliaires qui ajoutent une logique spéciale. Par exemple, s'il est nécessaire de rendre le code plus " DRY ", une propriété spéciale est introduite pour comprendre comment résoudre les références et fusionner les objets entre eux. Ou encore, il est nécessaire de se prémunir contre les erreurs de validation ; une nouvelle méthode est donc créée pour valider une valeur de configuration par rapport à un type attendu. Très vite, ces formats deviennent presque des langages de programmation, mais des langages difficiles à comprendre et à écrire.

À l'autre extrémité du spectre, un langage à usage général peut être utilisé à la place. Des langages comme Kotlin, Ruby ou JavaScript deviennent la base des DSL qui génèrent des données de configuration. Bien que ces langages soient extrêmement puissants, ils peuvent être difficiles à utiliser pour décrire la configuration, car ils ne sont pas axés sur la définition et la validation des données. En outre, ces DSL ont tendance à être liés à leurs propres écosystèmes. Il est difficile d'utiliser un DSL Kotlin comme couche de configuration pour une application écrite en Go.

Nous avons créé Pkl parce que nous pensons que la configuration est mieux exprimée comme un mélange entre un langage statique et un langage de programmation polyvalent. Nous voulons prendre le meilleur des deux mondes ; fournir un langage qui est déclaratif et simple à lire et à écrire, mais amélioré avec des capacités empruntées aux langages à usage général. Lorsque vous écrivez Pkl, vous pouvez utiliser les caractéristiques du langage auxquelles vous vous attendez, comme les classes, les fonctions, les conditionnelles et les boucles. Vous pouvez construire des couches d'abstraction et partager du code en créant des paquets et en les publiant. Plus important encore, vous pouvez utiliser Pkl pour répondre à de nombreux types de besoins de configuration. Il peut être utilisé pour produire des fichiers de configuration statiques dans n'importe quel format, ou être intégré en tant que bibliothèque dans une autre application en cours d'exécution.

Nous avons conçu Pkl avec trois objectifs principaux :

  • Assurer la sécurité en détectant les erreurs de validation avant le déploiement.
  • S'adapter aux cas d'utilisation les plus simples comme les plus complexes.
  • Être un plaisir à écrire, grâce à nos meilleures intégrations IDE.


Une visite rapide de Pkl

Nous avons créé Pkl pour que sa syntaxe soit familière aux développeurs et qu'il soit facile à apprendre. C'est pourquoi nous avons inclus des fonctionnalités telles que les classes, les fonctions, les boucles et les annotations de type.

Par exemple, voici un fichier Pkl (module) qui définit un schéma de configuration pour une application web imaginaire.

NOTE : Ce fichier définit des types et non des données. Il s'agit d'un modèle courant dans Pkl, que nous appelons "template".

Application.pkl
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
module Application 
 
/// The hostname that this server responds to. 
hostname: String 
 
/// The port to listen on. 
port: UInt16 
 
/// The environment to deploy to. 
environment: Environment 
 
/// The database connection for this application 
database: Database 
 
class Database { 
  /// The username for this database. 
  username: String 
 
  /// The password for this database. 
  password: String 
 
  /// The remote host for this database. 
  host: String 
 
  /// The remote port for this database. 
  port: UInt16 
 
  /// The name of the database. 
  dbName: String 
} 
 
typealias Environment = "dev"|"qa"|"prod"
Et voici comment les données de configuration peuvent être définies :

localhost.pkl
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
amends "Application.pkl" 
 
hostname = "localhost" 
 
port = 3599 
 
environment = "dev" 
 
database { 
  host = "localhost" 
  port = 5786 
  username = "admin" 
  password = read("env:DATABASE_PASSWORD") 
  dbName = "myapp" 
}
Il est facile de créer des variations des mêmes données de base en les modifiant. Par exemple, imaginons que nous voulions exécuter quatre bases de données localement, en tant que sidecars. Ceci utilise un générateur de for pour produire quatre variations, chacune modifiant la base db et spécifiant un port différent.

sidecars.pkl
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import "Application.pkl" 
 
hidden db: Application.Database = new { 
  host = "localhost" 
  username = "admin" 
  password = read("env:DATABASE_PASSWORD") 
  dbName = "myapp" 
} 
 
sidecars { 
  for (offset in List(0, 1, 2, 3)) { 
    (db) { 
      port = 6000 + offset 
    } 
  } 
}
Les programmes Pkl peuvent être facilement convertis en formats courants.

  • YAML

    Code : Sélectionner tout
    1
    2
    $ export DATABASE_PASSWORD=hunter2 
    $ pkl eval --format yaml sidecars.pkl
    Code : Sélectionner tout
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    sidecars: 
    - username: admin 
      password: hunter2 
      host: localhost 
      port: 6000 
      dbName: myapp 
    - username: admin 
      password: hunter2 
      host: localhost 
      port: 6001 
      dbName: myapp 
    - username: admin 
      password: hunter2 
      host: localhost 
      port: 6002 
      dbName: myapp 
    - username: admin 
      password: hunter2 
      host: localhost 
      port: 6003 
      dbName: myapp
  • JSON

    Code : Sélectionner tout
    1
    2
    $ export DATABASE_PASSWORD=hunter2 
    $ pkl eval --format json sidecars.pkl
    Code : Sélectionner tout
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    { 
      "sidecars": [ 
        { 
          "username": "admin", 
          "password": "hunter2", 
          "host": "localhost", 
          "port": 6000, 
          "dbName": "myapp" 
        }, 
        { 
          "username": "admin", 
          "password": "hunter2", 
          "host": "localhost", 
          "port": 6001, 
          "dbName": "myapp" 
        }, 
        { 
          "username": "admin", 
          "password": "hunter2", 
          "host": "localhost", 
          "port": 6002, 
          "dbName": "myapp" 
        }, 
        { 
          "username": "admin", 
          "password": "hunter2", 
          "host": "localhost", 
          "port": 6003, 
          "dbName": "myapp" 
        } 
      ] 
    }
  • XML

    Code : Sélectionner tout
    1
    2
    $ export DATABASE_PASSWORD=hunter2 
    $ pkl eval --format xml sidecars.pkl
    Code : Sélectionner tout
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    <?xml version="1.0" encoding="UTF-8"?> 
    <root> 
      <sidecars> 
        <Database> 
          <username>admin</username> 
          <password>hunter2</password> 
          <host>localhost</host> 
          <port>6000</port> 
          <dbName>myapp</dbName> 
        </Database> 
        <Database> 
          <username>admin</username> 
          <password>hunter2</password> 
          <host>localhost</host> 
          <port>6001</port> 
          <dbName>myapp</dbName> 
        </Database> 
        <Database> 
          <username>admin</username> 
          <password>hunter2</password> 
          <host>localhost</host> 
          <port>6002</port> 
          <dbName>myapp</dbName> 
        </Database> 
        <Database> 
          <username>admin</username> 
          <password>hunter2</password> 
          <host>localhost</host> 
          <port>6003</port> 
          <dbName>myapp</dbName> 
        </Database> 
      </sidecars> 
    </root>


Validation intégrée

La configuration est une question de données. Et les données doivent être valides.

Dans Pkl, la validation est réalisée à l'aide d'annotations de type. Et les annotations de type peuvent optionnellement avoir des contraintes définies sur elles.

Voici un exemple qui définit les contraintes suivantes :

  • age doit être compris entre 0 et 130.
  • name ne doit pas être vide.
  • zipCode doit être une chaîne de cinq chiffres.


Person.pkl
Code : Sélectionner tout
1
2
3
4
5
6
7
module Person 
 
name: String(!isEmpty) 
 
age: Int(isBetween(0, 130)) 
 
zipCode: String(matches(Regex("\\d{5}")))
Une contrainte défaillante provoque une erreur d'évaluation.

alessandra.pkl
Code : Sélectionner tout
1
2
3
4
5
6
7
amends "Person.pkl" 
 
name = "Alessandra" 
 
age = -5 
 
zipCode = "90210"
L'évaluation de ce module échoue :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ pkl eval alessandra.pkl 
–– Pkl Error –– 
Type constraint `isBetween(0, 130)` violated. 
Value: -5 
 
5 | age: Int(isBetween(0, 130)) 
             ^^^^^^^^^^^^^^^^^ 
at Person#age (file:///Person.pkl) 
 
5 | age = -5 
          ^^ 
at alessandra#age (file:///alessandra.pkl) 
 
106 | text = renderer.renderDocument(value) 
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
at pkl.base#Module.output.text (https://github.com/apple/pkl/blob/0.25.0/stdlib/base.pkl#L106)
Les contraintes sont des expressions arbitraires. Cela vous permet de créer des types qui peuvent exprimer n'importe quel type de contrôle pouvant être exprimé dans Pkl. Voici un exemple de type qui doit être une chaîne de caractères de longueur impaire et dont la première lettre correspond à la dernière.

Code : Sélectionner tout
name: String(length.isOdd, chars.first == chars.last)

Partage de paquets

Pkl permet de publier des paquets et de les importer comme dépendances dans un projet. Cela permet de partager facilement du code Pkl qui peut être utilisé dans d'autres projets.

Il est facile de créer ses propres paquets et de les publier comme des versions GitHub, ou de les télécharger où l'on veut.

Les paquets peuvent être importés via l'URI absolu :

Code : Sélectionner tout
1
2
3
4
5
import "package://pkg.pkl-lang.org/pkl-pantry/pkl.toml@1.0.0#/toml.pkl" 
 
output { 
  renderer = new toml.Renderer {} 
}
Ils peuvent également être gérés comme des dépendances d'un projet. L'utilisation d'un projet permet à Pkl de résoudre les conflits de version entre les différentes versions d'une même dépendance au sein d'un graphe de dépendance. Cela signifie également que vous pouvez importer des paquets sous un nom plus simple.

PklProject
Code : Sélectionner tout
1
2
3
4
5
amends "pkl:Project" 
 
dependencies { 
  ["toml"] { uri = "package://pkg.pkl-lang.org/pkl-pantry/pkl.toml@1.0.0" } 
}
myconfig.pkl
Code : Sélectionner tout
1
2
3
4
5
import "@toml/toml.pkl" 
 
output { 
  renderer = new toml.Renderer {} 
}
Un ensemble de paquets sont maintenus par nous, l'équipe de Pkl. Il s'agit notamment de

  • pkl-pantry - une monorepo qui publie de nombreux paquets différents.
  • pkl-k8s - modèles pour définir les descripteurs Kubernetes.


Liaisons linguistiques

Pkl peut produire de la configuration en tant que sortie textuelle, et il peut également être intégré en tant que bibliothèque dans d'autres langages grâce à nos liaisons linguistiques.

Lorsqu'il est lié à une langue, le schéma Pkl peut être généré sous forme de classes/structures dans la langue cible. Par exemple, l'exemple Application.pkl ci-dessus peut être généré en Swift, Go, Java et Kotlin. Pkl inclut même des commentaires de documentation dans le langage cible.

[LIST][*]Swift
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import PklSwift 
 
public enum Application {} 
 
extension Application { 
    public enum Environment: String, CaseIterable, Decodable, Hashable { 
        case dev = "dev" 
        case qa = "qa" 
        case prod = "prod" 
    } 
 
    public struct Module: PklRegisteredType, Decodable, Hashable { 
        public static var registeredIdentifier: String = "Application" 
 
        /// The hostname that this server responds to. 
        public var hostname: String 
 
        /// The port to listen on. 
        public var port: UInt16 
 
        /// The environment to deploy to. 
        public var environment: Environment 
 
        /// The database connection for this application 
        public var database: Database 
 
        public init(hostname: String, port: UInt16, environment: Environment, database: Database) { 
            self.hostname = hostname 
            self.port = port 
            self.environment = environment 
            self.database = database 
        } 
    } 
 
    public struct Database: PklRegisteredType, Decodable, Hashable { 
        public static var registeredIdentifier: String = "Application#Database" 
 
        /// The username for this database. 
        public var username: String 
 
        /// The password for this database. 
        public var password: String 
 
        /// The remote host for this database. 
        public var host: String 
 
        /// The remote port for this database. 
        public var port: UInt16 
 
        /// The name of the database. 
        public var dbName: String 
 
        public init(username: String, password: String, host: String, port: UInt16, dbName: String) { 
            self.username = username 
            self.password = password 
            self.host = host 
            self.port = port 
            self.dbName = dbName 
        } 
    } 
}
[*]Go

Application.pkl.go
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package application 
 
type Application struct { 
	// The hostname that this server responds to. 
	Hostname string `pkl:"hostname"` 
 
	// The port to listen on. 
	Port uint16 `pkl:"port"` 
 
	// The environment to deploy to. 
	Environment Environment.Environment `pkl:"environment"` 
 
	// The database connection for this application 
	Database *Database `pkl:"database"` 
}
Database.pkl.go
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Code generated from Pkl module `Application`. DO NOT EDIT. 
package application 
 
type Database struct { 
	// The username for this database. 
	Username string `pkl:"username"` 
 
	// The password for this database. 
	Password string `pkl:"password"` 
 
	// The remote host for this database. 
	Host string `pkl:"host"` 
 
	// The remote port for this database. 
	Port uint16 `pkl:"port"` 
 
	// The name of the database. 
	DbName string `pkl:"dbName"` 
}
environment/Environment.pkl.go
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Code generated from Pkl module `Application`. DO NOT EDIT. 
package Environment 
 
import ( 
	"encoding" 
	"fmt" 
) 
 
type Environment string 
 
const ( 
	Dev  Environment = "dev" 
	Qa   Environment = "qa" 
	Prod Environment = "prod" 
) 
 
// String returns the string representation of Environment 
func (rcv Environment) String() string { 
	return string(rcv) 
}
[*]Java

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.lang.Object; 
import java.lang.Override; 
import java.lang.String; 
import java.lang.StringBuilder; 
import java.util.Objects; 
import org.pkl.config.java.mapper.Named; 
import org.pkl.config.java.mapper.NonNull; 
 
public final class Application { 
  /** 
   * The hostname that this server responds to. 
   */ 
  public final @NonNull String hostname; 
 
  /** 
   * The port to listen on. 
   */ 
  public final int port; 
 
  /**...
La fin de cet article est réservée aux abonnés. Soutenez le Club Developpez.com en prenant un abonnement pour que nous puissions continuer à vous proposer des publications.

Une erreur dans cette actualité ? Signalez-nous-la !

Avatar de unanonyme
Membre éclairé https://www.developpez.com
Le 06/02/2024 à 9:37
C'est une bonne initiative, en principe, en action ça à l'air sympa,
surtout l'intégration native multi langages, c'est vraiment bien pensé.
J'ai dans l'idée que ça fera son trou.

En pratique, on verra dans 5 ans le genre de propriétés émergente
que fera apparaître le déploiement à l'échelle d'une telle innovation.
Spoiler, on a pas fini d'innover.
1  0 
Avatar de dglaude
Futur Membre du Club https://www.developpez.com
Le 07/02/2024 à 21:06
Est-ce qu'un nouveau langage peut naître et être utilisé alors que ChatGPT ou CoPilote ne peut aider les programmeurs?
Est-ce que l'IA a déjà révolutionner le codage au point d'être un frein à l'innovation?
0  0