My team's using rust. HALP!
My team's using rust. HALP!
Dis, c'est quoi un·e CTO?
Alignement
Vision globale des projets, m'assurer que les gens bossent dans le même sens même s'ils n'ont pas toutes les infos
Priorités
Priorités, pour permettre de l'autonomie choix des technos en plus
Facilitateur·ice
Enlever les obstacles pour que les gens avancent sur leurs projets sans avoir à se poser de questions
Architecte
toujours en collaboration avec l'équipe
Historique Clever
Je suis arrivé en cours de route, pas mal de choix techniques déjà faits.
Java Java Java
Cœur en java
Scala, Scala? Java.
Premières tentatives d'intégrer du scala, finalement restage sur java et réintégration dans l'API principal
Ruby
utilisé comme langage de script sur les VMs. Common practice à l'époque.
NODE ALL THE THINGS
Réécriture d'un orchestrateur from scratch. À l'époque pile la plus simple pour de l'évenementiel. Alternative à ruby pour le scripting
Scala. A lot
Toutes les nouvelles briques web en scala.
(plus les à côtés)
haskell, elixir, a little bit of go.
Ça a l'air un peu inefficace ça, non?
pas tant que ça en fait, c'est des briques indépendantes, et à chaque fois on commence petit. On n'a jamais réécrit une brique pour le plaisir.
Donc vous arrêtez scala?
scala a toute sa place comme pile web pas en compétition avec rust sur la partie API web
Ben pourquoi pas go alors?
le système de type c'est fait pour aider. Même si rust et go n'ont pas les mêmes buts, rust répond mieux que go sur le marché de go (déso, pas déso).
Déploiement facile
Pour nous le déploiement d'une app web c'est vraiment pas un problème en revanche on doit outiller les instances et on a besoin de petits binaires faciles à packager et sans dépendances système
"system" language
utile dans le cadre de sozu en particulier: proche du métal. permet de travailler proprement sur la perf
Rust && Scala, main dans la main
même approche de la programmation: modélisation propre à l'aide du système de types découpage en fonctions, implem itérative ???
/ unimplemented!
. Élimination des problèmes de serde à la fin du monde
TDD, anyone?
Make invalid states unrepresentable. Dans le cas de rust ça inclut aussi les data races
case class Peer(
cidrs: List[String],
pubkey: String,
endpoint: String,
keepalive: Int)
sealed trait WgCommand
case class InitConfig(…)
extends WgCommand
case class SetPeer(peer: Peer)
extends WgCommand
case class RemovePeer(pubkey: String)
extends WgCommand
pub struct Peer {
pub cidrs: Vec<String>,
pub pubkey: String,
pub endpoint: String,
pub keepalive: u32,
}
struct Rgb (i8, i8, i8)
pub enum WgCommand {
InitConfig(String, String, String, u32),
SetPeer(Peer),
RemovePeer(String)
}
command match {
case InitConfig(
ip,
pub, priv,
port) => …
case SetPeer(peer) => …
case RemovePeer(pub) => …
}
match cmd {
WgCommand::InitConfig(
ip, pubkey, privkey,
port) => …,
…
}
trait Bidule {
def abstractMethod(t: String): String
def concrete(t: String): String =
abstractMethod(t)
}
case class Machin(a: Int) extends Bidule
case class Truc(a: Int) {
def yolo = a + 42
}
pub trait ProxyClient {
fn front_socket(&self) -> &TcpStream
…
}
pub struct Truc {
pub a: u32,
}
impl Truc {
fn new() -> Truc {
Truc { a: 0 }
},
fn yolo(&self) -> u32 {
self.a + 42
}
}
let a = Truc::new();
let b = &a.yolo();
pub trait FromStr {
type Err;
fn from_str(s: &str) ->
Result<Self, Self:Err>
}
impl FromStr for Bool {
type Err = ParseBoolError;
fn from_str(s: &str) -> {
...
}
}
#[derive(Debug,PartialEq,Eq)]
pub struct {
…
}
customDerive
all the things
def myShinyMethod(t: String): String =
???
fn myShinyFunction(t: &str) -> String {
unimplemented!()
}
def doThing(p: Param):
Either[Error, Value] = …
fn do_thing(p: &Param) ->
Result<Value, Error> {
…
}
?
for {
res1 <- op1() // yay scala 2.12,
// thanks Simon!
res2 <- op2(res1)
} yield res2
fn do_things() -> Result<Value, Error> {
let res1 = op1()?;
let res2 = op2(res1)?;
Ok(res2)
}
Not monadic, only for errors
Et le fonctionnel dans tout ça?
Le modèle mémoire de rust est super top, mais assez limitant quand on a l'habitude de scala
Persistent data structures :/
difficile sans GC. Pas si utile que ça finalement grâce au borrow checker
L'impératif, ça passe en fait
avec le borrow checker ça permet d'isoler la mutabilité, et ça passe à peu près en fait. d'ailleurs en scala c'est toléré tant que ça s'échappe pas. Mais en scala c'est dur à prouver (cf la mutabilité de List)
Closures :/
Pour des pures lambdas c'est pas gênant, mais dès qu'on close over un bout de contexte, le borrow checker s'excite
Async :/
Futures. Code encore piégeux, event loop à gérer explicitement. Design pas encore bien fixé, modifications à attendre. Le multithread est jouable dans certains cas, encore une fois grâce au borrow checker
Unboxing & spécialisation
Pas mal de restrictions sur les génériques à cause de l'unboxing, boulot sur la spécialisation. Grosses questions sur l'inférence de type de retour
ipml trait
to the rescue
impl trait
=> abstract boxed / unboxed types not ready yet
No HKTs yet
en cours de discussion https://github.com/rust-lang/rfcs/pull/1598 premier pas
def mapTwice[A, F[_]: Functor](
v: F[A],
f: A => A
): F[A] = {
…
}
Strings. Encore pire qu'en haskell
static str
&str
String
[u8]
[u8,4]
Vec<u8>
C'est normal
On rajoute plus d'invariants, donc le compilo va vérifier plus de choses, mais la contrepartie c'est que plus de programmes légaux vont être refusés. On a donc un tradeoff entre plus de sécurité (moins de corner cases à gérer) et une diminution dans ce qu'on peut faire sans être emmerdé. Bénéfice relatif, tout dépend du projet, de l'équipe, …
Ça vaut le coup de me mettre à rust?
Pour apprendre
C'est toujours bien d'apprendre un nouveau langage basé sur des concepts nouveaux.
Un autre regard sur des concepts du fonctionnel
Il y a pas mal de features des langages fonctionnels qui ne sont pas fondamentalement fonctionnelles et qui ont du sens dans un contexte impératif.
Faire du système / bas niveau en douceur
C'est jouable et moins dangereux qu'en C, du coup ça permet de déstresser
Pour du web?
Pour remplacer des déploiements scala, bof sauf si contraintes particulières. Rien de bien folichon en templating, piles web pas encore bien stables. Je garde mon play, même avec de la DI :-)
Contraintes de déploiement fortes
RAM dépendances, système de déploiement
Exposer simplement une lib C
La FFI en rust c'est quand même plus simple que JNI Routage propre, typage des requêtes, interface sympa. C'est toujours mieux qu'un shell out dégueu
Lib bas niveau / haute perf
Plutôt pertinent pour les langages interprétés qui ont tendance à tomber en C pour avoir des perfs (node, python, ruby). Sur la JVM c'est plutôt rare #JNI
Pour du tooling à déployer sur des machines en support d'une appli principale. Fat binary, small footprint
Rust is a better go than go
Rust répond mieux que go aux use cases principaux de go. Pas vraiment grâce à sa gestion de la mémoire, juste parceque le tooling est mieux et que le langage est plus expressif.
Code métier à déployer dans le browser
Très bon fit avec webasm, vu qu'il n'y a pas de runtime. Gros focus de la communauté rust en ce moment
Recap
Langage très intéressant Tradeoffs plus violents que d'habitude Frustrant quand on est habitué à tout boxer et qu'on a un GC