Tech Archives - Ekino FR

TezDev 2023 : It’s rollups time !

The more a blockchain grows, the more scalability limits become a painful issue. As the number of transactions increase, so does the gas price and the time for a transaction to be finalized. To prevent this issue, one common solution is horizontal scaling via a L2 rollup solution. Since the Mumbai upgrade, the Tezos protocol implements smart optimistic rollups. It’s a new feature (March 29, 2023) implemented in an original and unprecedented way in all web3 ecosystem. Needless to say that smart rollup is currently a hot topic in tezos ecosystem. Unsurprisingly, the TezDev 2023 conference that took place the 21 July in Paris, was mainly focused on rollup. It was the occasion to get a deep insight into this technology and get some glimpse of the future evolutions. In this article, we are going to talk about some interventions.

TezDev conference

p.s. : In this article we are not going to dive into deep technical aspects of rollups functioning. For more detailed informations on how tezos smart rollup works, you can check Tezos documentation.

Rollups on Tezos

Contrary to rollup solutions developed on other blockchains, tezos rollup is said to be enshrined in the protocol which means it’s not implemented via smart contracts (like on Ethereum for example) but directly by the protocol. On Tezos, rollups are first class citizens, each one having it’s own address beginning with « sr1 ». This is more cost-efficient and future proof than smart contract implementation. It also enable more use cases since rollups are not limited by smart contract’s limitations. This is why the prefix « smart » is added to « smart optimistic rollup ».
By aillor, rollups are permissionless: : Every one can deploy a rollup node and defend it’s version of the rollup state by stacking 10k XTZ. Also every one can originate a new rollup by providing, among other thing, a web assembly (WASM) kernel responsible for input/output communication with L1 and rollup state update.
Developers are free to implement arbitrary logic in kernel as long as it remains compliant with the PVM (Proof-generating Virtual Machine) associated to the rollup. PVMs are provided by Tezos protocol and are used during the refutation game to check which one of the committed states is correct.

The cofounder of Tezos talks about rollups

Arthur Breitman created Tezos with his wife, Kathleen Breitman, in 2018. During the TezDev conference, he shared his thoughts about Tezos rollups (not exhaustive list):

The first thing one think when talking about rollups is scalability. However, if smart optimistic rollups aims at leveraging Tezos scalability by reaching a throughput of 1 million transactions per second (TPS) ; performance is not the only benefit rollups. The Tezos rollup technology is not only about throughput but also about interoperability. More precisely, interoperability beetween development languages and tools. Indeed, since the kernel of a rollup is expected to be written in WASM, developers are free to implement kernel in any language that compile to web assembly: C, C++, Rust, Go, EVM…
This diversity of language allows to cover a large panel of developers around the world. It allows, to a certain extend, to work with the Tezos blockchain without knowing Michelson. It also removes the need to create and maintain specific language and tools (IDE, framework, …) for rollups.

He also explained why Tezos rollups shouldn’t be seen and used through an app chain paradigm. The idea of app chain is to launch a new rollup instance for each new app to have app specific chains (like on Cosmos for example). Arthur Breitman argues that such conception make communication between app harder. Moreover, reasons for which a project may want to setup an app chain ; such as don’t having to shares chain’s resources with other apps or the ability to develop in a language the team master ; are already fulfilled by smart optimistic rollups. Indeed, there is going to be rollups compatible with a large panel of languages. In addition, as rollup provide high scalability, there shouldn’t be concerns about sharing chains resources with other apps.
However, setting up a rollup for a single app may still be pertinent for some specific cases

Finally, he said that in the future, the goal is to create, in addition to other rollups, a big UHT (Ultra High Throughput) rollup that is going to be compatible with a lot of language : Michelson, EVM, Rust, …
It would allow atomic call between smart contracts written is different languages which would avoid latency from hopping between rollups.
There would be solutions to migrate projects in UHT rollup from other rollups.

Some rollups in development

Tezos Gaming

Jean Schmitt, lead developer at Ubisoft, presented the Hashcraft exploration game where players can discover and claim islands. It’s the first blockchain prototype game developed by the Strategic Innovation Lab of Ubisoft (they also developed other games having web3 components such as Rabbids, One Shot League or Quartz).
They upgraded Hashcraft using Tezos unity SDK. They developed a rollup in Rust to benefit from high throughput and low fees, but also to be able to implement new features, such as better player input validation process, that couldn’t be achieved via smart contracts.

When EVM and Michelson make peace

Pierrick Couderc and Valentin Chaboche, software engineers at Nomadic Lab, presented Etherlink, an EVM compatible smart rollup on Tezos. The kernel has been built in Rust. It uses the Rust implementation of EVM : SputnikVM
This rollup could be the entry point into the Tezos world for EVM developers. Indeed, Etherlink is compatible with all EVM tools: EVM wallet, Remix, …

Conclusion

Thanks to it’s inbuilt governance system, Tezos has smoothly and efficiently integrated optimistic rollups into its protocol. ZK rollups may be added in next upgrades.
If you couldn’t attend TezDev conference or for more informations on the topic, you can check tezos youtube channel (the conference interventions may be posted there next days)


TezDev 2023 : It’s rollups time ! was originally published in ekino-france on Medium, where people are continuing the conversation by highlighting and responding to this story.

Pragmatic form development in React

If there is a thing that almost all user-facing softwares have in common, it is forms. They are the way users interact with applications and thus are a central part of most products, and it is especially true for web applications. With the rise of modern JavaScript frameworks, a lot of common issues have been made […]

Lire la suite de Pragmatic form development in React

À propos de Go

Go (généralement appelé Golang) est un langage de programmation open-source créé par Google en 2009. Sa conception visait à offrir une alternative simple et performante aux langages de programmation existants tels que C++ et Java. Go se caractérise par une syntaxe concise et facile à lire, une gestion efficace de la mémoire et une compilation rapide. Il a été conçu pour être simple à apprendre, facile à utiliser et efficace en termes de performances. La question qui se pose alors est de savoir si le Go peut être utilisé dans un projet de création ou de modification de plateforme digitale.

Est-ce qu’il est suffisamment facile à apprendre et à utiliser pour continuer à se propager dans les stacks techniques des entreprises ? Golang est-il un langage pertinent pour créer une plateforme digitale ?

Les apports de Go pour une plateforme digitale

Go est un langage en croissance rapide, avec une communauté active et un écosystème en développement constant. Il y a une grande quantité de bibliothèques et d’outils disponibles pour les développeurs, ce qui facilite la création d’applications.

Cet aspect communautaire très important facilite l’apprentissage du langage et sa prise en main. De plus, les retours de la communauté sont souvent pris en compte dans les mises à jour du langage, ce qui en fait un langage toujours d’actualité et en accord avec sa communauté. Pour les utilisateurs venant du langage tel que le C, Java ou Python, Go est un langage facile à apprendre grâce notamment à la syntaxe simple et concise du langage.

Google, en créant Golang, a eu pour idée de créer un langage qui se combine parfaitement à une infrastructure cloud comme Google Cloud Platform peut proposer. Dans ce type d’architecture cloud ou encore service-to-service, Golang est parfait pour effectuer une tâche rapide simple et sans prendre beaucoup de ressources.

Ainsi, pour des applications à haute performance et à grande échelle, avec une gestion de la concurrence et de la répartition du travail des différents services ainsi que la performance des micros-services, Golang permet de faire grandir sa plateforme digitale sur un marché qui a tendance à grandir en termes de nombre requêtes utilisateur ou même de complexité algorithmique.

De nombreuses entreprises de premier plan utilisent Go pour développer des logiciels de backend et d’autres types d’applications.

Il est notamment utilisé par de nombreux produits et services Google, dont Google Search, Google Maps et Google App Engine.

Netflix aussi utilise Go pour développer ses services de diffusion en continu et pour gérer ses infrastructures de données.

Un autre exemple est Docker : l’outil de conteneurisation, très populaire, a été écrit en grande partie en Go.

C’est aussi le cas de Dropbox qui utilise Go pour développer certaines de ses applications de backend.

SoundCloud, la plateforme de partage de musique en streaming, utilise Go pour développer ses services de backend.

Les exemples ne manquent pas avec d’autres entreprises pouvant être citées comme Uber, The New York Times et Twitch. Ceci montre à quel point le langage Go est pluridisciplinaire, ainsi n’importe quel type de plateforme digitale peut être créé grâce à Golang, que ce soit sur le cloud, sur un CD ou encore simplement sur Github.

Du côté d’ekino, un projet en Golang est au cœur de l’entreprise. Ce projet s’appelle Staff et a pour but de gérer toutes les habilitations des collaborateurs. Ainsi, Staff fait le lien entre toutes les plateformes SaaS au sein d’ekino. Le projet possède une architecture dirigée par les événements, ce qui signifie que lorsqu’une action spécifique est effectuée, comme la mise à jour d’un utilisateur, tous les autres services ekino sont synchronisés sans avoir à faire d’opération manuelle. 

Golang est donc un choix naturel au vu de la multiplication des plateformes digitales qui sont sur le cloud actuellement.

Quels challenges devons-nous anticiper en utilisant Go pour la création de ma plateforme digitale ?

Chaque choix technologique implique des arbitrages. Ainsi, et bien que Go présente de nombreux avantages pour les entreprises, il reste des défis à relever lors de l’adoption de cette technologie.

Il peut notamment être difficile de trouver des développeurs expérimentés dans ce domaine. Les entreprises peuvent alors avoir besoin de former leurs employés existants ou de recruter de nouveaux développeurs pour adopter Go. Une solution pour remédier à cela est par exemple de faire appel à une expertise externe afin de sous-traiter une partie des développements tout en faisant monter en compétence les développeurs de l’équipe.

À première vue, on pourrait juger d’un manque de bibliothèques de développement et d’outils disponibles pour les développeurs go. Mais l’évolution rapide du langage avec notamment les dernières versions go1.18 et go1.20 a apporté ce dont les développeurs avaient besoin, ce qui permet de répondre à cette problématique (par exemple la gestion de la mémoire est désormais meilleure que dans les premières versions, et l’utilisation des méthodes génériques dans le code est dorénavant possible).

Adopter Go peut entraîner un changement de la culture de développement dans une entreprise. Il peut être nécessaire de changer les processus existants, les outils et les pratiques pour s’adapter au style de développement de Go. Cela dépend de l’état actuel de la culture d’entreprise, mais Golang a tendance à mieux être appréhendé par les équipes avec une culture d’entreprise agile et qui pratique l’amélioration continue. En effet, Go est un langage open source, il vit donc de sa communauté et on en tirera au mieux parti en ayant une vision assez globale de ce que permet ce langage et de ce qu’il apportera à l’entreprise.

Il est important de noter que ces défis ne sont pas insurmontables, mais ils doivent être pris en compte lors de la décision d’adopter Go. Les entreprises doivent évaluer leurs propres besoins et ressources pour déterminer si Go est une technologie adaptée pour eux et comment ils peuvent surmonter ces défis.

De plus, Golang est un langage qui attire de plus en plus et qui a vocation à s’installer de manière pérenne dans le paysage technologique des entreprises, ceci est notamment visible sur les sondages StackOverFlow :

Le classement des langages de programmation les plus populaires en 2021, selon Stack Overflow. © Stack Overflow

La montée en flèche de la popularité de Go prouve que c’est un choix très intéressant pour les entreprises qui cherchent à construire des systèmes à haute performance et à grande échelle, comme les services web, les systèmes de miroir de données ou encore les systèmes de traitement de données. Cependant, là où il reste le roi est pour la conception d’une plateforme numérique sur le cloud. Il peut être utilisé à sa pleine puissance que ce soit en termes de performance, d’algorithmie complexe ou encore en termes de devOps.

Résumé de l’enquête Go Developer Survey 2020
Résumé de l’enquête Go Developer Survey 2020 (source : https://go.dev/blog/survey2020-results)

Il est à noter également que les développeurs qui se mettent à Go se retrouvent à vouloir continuer à l’utiliser dans d’autres contextes (pour faire de la veille technologique par exemple), et ceux ne travaillant pas avec commencent à se former par eux-mêmes.

Ainsi, adopter Go pour effectuer une plateforme numérique peut apporter de nouveaux défis de recrutement, mais aussi des opportunités. Il peut être difficile de trouver des personnes déjà expérimentées en Go mais ceux qui s’y intéressent ont soif d’apprendre et veulent continuer à utiliser ce langage. Au vu du nombre de personnes voulant utiliser Go au travail, cela est également un bon élément d’attractivité pour recruter de nouveaux profils voulant travailler avec un langage actuel.

Quels impacts économiques sont liés à l’utilisation de Go ?

En adoptant Go pour le développement de leurs applications, les entreprises peuvent améliorer la productivité de leurs équipes de développement et obtenir des performances supérieures. Cela peut ainsi réduire les coûts de production et d’hébergement, et ainsi avoir un impact significatif sur la rentabilité de l’entreprise et contribuer à sa croissance.

Go est particulièrement adapté aux applications à haute concurrence et à grande échelle. Il inclut des outils qui permettent de gérer efficacement le nombre de demandes de l’application et de répartir le travail sur plusieurs processeurs par exemple. Sur un marché où les plateformes digitales ont tendance à absorber de grands volumes d’appels et de données, Golang s’en sort très bien pour réaliser ces tâches.

Pour reprendre l’exemple d’une grande entreprise, Netflix utilise Go pour développer plusieurs de ses services de backend, notamment ses services de recommandation et ses services de gestion des abonnements. Go est particulièrement bien adapté à ces tâches car il offre de bonnes performances et une facile scalabilité, ce qui est crucial pour une entreprise comme Netflix qui gère des millions d’abonnés et de requêtes de lecture en continu. Netflix utilise Go pour développer un service de recommandation appelé “Performance and Capacity Metrics”, qui collecte des données sur les performances et la capacité de ses différents systèmes et services. Ce service utilise Go pour traiter et analyser ces données en temps réel, et pour produire des rapports et des alertes en cas de problèmes de performances.

Récemment, Netflix a lancé le projet Moneta, qui a permis au projet Rend Proxy de voir le jour. Rend Proxy est un projet écrit en Golang qui a pour but de faire la mise en cache de données (la copie de fichier dans un emplacement de stockage temporaire afin de pouvoir y accéder plus rapidement). Rend Proxy repose sur l’utilisation des goroutines pour gérer la concurrence. En effet, Rend proxy doit gérer des dizaines de milliers de connexions simultanées. L’ensemble des outils de tests et de monitoring permet d’assurer la qualité et la robustesse du projet. L’architecture du projet est modulaire, ce qui permet une grande flexibilité dans les changements à apporter au projet, qu’il s’agisse de maintenance ou de nouvelles fonctionnalités.

Le sujet Rend Proxy est un sujet open source disponible sur le github de Netflix.

Alors, Go ou no Go ?

Golang est un langage assez récent dans la stack technique des grandes entreprises mais il reste un langage très répandu dans les start-ups. Ainsi, il va y avoir de nombreux profils de développeurs Golang qui ont soif de créer et d’apprendre sur le marché ou en recherche de stabilité dans leur emploi. La pluridisciplinarité du langage permet ainsi aux développeurs de pouvoir travailler dans n’importe quel domaine. C’est pourquoi adopter Go et la culture Go en entreprise est un nouveau défi afin de pouvoir réaliser de manière pérenne sa plateforme digitale d’aujourd’hui ou de demain.

Le langage a déjà été validé par de nombreuses entreprises quelle que soit leur taille et cela est amené à évoluer et à grandir. Alors est-ce le bon moment de franchir le pas et d’adopter Go ?

Au vu des étapes de création d’une plateforme digitale, ce langage est un atout car il permet de créer, déployer et maintenir la plateforme digitale de bout en bout. Tout cela en permettant à chacun de comprendre, d’apprendre et d’évoluer. C’est un langage facile à apprendre (d’où son utilisation en start up) mais compliqué à maîtriser (d’où son adoption lente dans les grandes entreprises). Ainsi, vaut-il mieux laisser le train passer ? Ou aurez-vous le courage de prendre un billet pour partir à l’aventure de Golang ? 

A proposition for relevant tests in your front-end application

Preamble: As you can see in the title, this article does not claim that the following strategy IS the good one. Coding is very subjective and as of now, I don’t see a consensus among developers on how to implement useful and relevant tests on a front-end application. This article is merely a proposition on […]

Lire la suite de A proposition for relevant tests in your front-end application

Symfony UUID, Doctrine and type-hinting: everything you should know

And why you should look at how everything work under the hood

Image from Joshua Woroniecki on Pixabay

In this article, we will talk about wrong type-hinting and how using Doctrine ORM can lead to some unexpected behavior. We’ll start from finding of the bug, then trying to understand why it happens and finally trying to resolve it.

The beginning

First, let’s set the technical context and everything you need to know to understand the rest of the article.

The tech stack is a classic one: Symfony 6.2, Doctrine ORM with PostgreSQL, PHPUnit and finally Foundry.

Now, let me introduce you the base code we’ll need:

namespace AppEntity;

use DoctrineORMMapping as ORM;

#[ORMEntity]
#[ORMHasLifecycleCallbacks]
final class Member
{
#[ORMId]
#[ORMColumn(type: 'uuid', unique: true)]
#[ORMGeneratedValue(strategy: 'CUSTOM')]
#[ORMCustomIdGenerator(class: 'doctrine.uuid_generator')]
public string $id;

#[ORMColumn(type: 'datetime_immutable')]
public DateTimeImmutable $createdAt;

#[ORMColumn(type: 'datetime_immutable')]
public DateTimeImmutable $updatedAt;

#[ORMPrePersist]
public function prePersist(): void
{
$this->createdAt = $this->createdAt ?? new DateTimeImmutable();
$this->updatedAt = $this->createdAt;
}

#[ORMPreUpdate]
public function preUpdate(): void
{
$this->updatedAt = new DateTimeImmutable();
}
}
namespace AppEntity;

use DoctrineORMMapping as ORM;

#[ORMEntity]
class Message
{
#[ORMId]
#[ORMColumn(type: 'uuid', unique: true)]
#[ORMGeneratedValue(strategy: 'CUSTOM')]
#[ORMCustomIdGenerator(class: 'doctrine.uuid_generator')]
public string $id;

#[ORMManyToOne(targetEntity: Member::class)]
#[ORMJoinColumn(nullable: false)]
public Member $author;
}

For the sake of simplicity, I use public fields. The real code use the good old getter/setter methods.

Nothing really fancy with those snippets.

We have an entity Member that represents a kind of user in our application. It has 3 simple fields: id, createdAt and updatedAt. This entity has Doctrine callback on prePersist and preUpdate events.

The second entity Message has two fields: id and author. This entity represents a simple message in the application.

The investigation

In our functionnal tests, assertions like this failed:

self::assertSame($member, $message->author)

Because $member->updatedAt is different from $message->getAuthor->updatedAt, even we don’t modified $member in the tests.

After investigations, we found that preUpdate doctrine event is fired even if we don’t modify $member. Our first guess was that Foundry fires the event, but we had no idea why and when.

The first step was to find a minimal block of code to reproduce the issue. So then it is easier to understand why the issue is produced.

After some time, we managed to reduce the code to the following snippet:

$member = MemberFactory::createOne()->object();

MessageFactory::createOne([
'author' => $member
]);

self::assertEquals($member->createdAt, $member->updatedAt);

The snippet uses some Foundry functionnalities, especialy the createOne method.

So we need to get rid of it, and translate the Foundry code to plain Doctrine instructions. And after reading the code of Foundry and lot of trials and errors, the following minimal code reproduces the issue with only doctrine calls.

$member = new Member();

$recommendationrequest = new Message();
$recommendationrequest->author = $member;

$em = $this->getEntityManager()

$em->persist($member);
$em->flush();

$em->refresh($member);

$em->persist($recommendationrequest);
$em->flush();

self::assertEquals($member->createdAt, $member->updatedAt);

Now, we try to find which line produces the bug. It appears when we call the refresh method the event is fired. So we answer to the question when.

Let’s find now why!

A quick and simple way to find it, is to dump the event received in preUpdate method. Let see what we found:

^ DoctrineORMEventPreUpdateEventArgs^ {#185
-objectManager: DoctrineORMEntityManager^ {#109 …11}
-object: AppEntityMember^ {#312
+id: "1edac68e-0f54-6828-b519-0b4d85d941b5"
+createdAt: DateTimeImmutable @1676380196 {#167
date: 2023-02-14 13:09:56.0 UTC (+00:00)
}
+updatedAt: DateTimeImmutable @1676380196 {#169
date: 2023-02-14 13:09:56.0 UTC (+00:00)
}
}
-entityChangeSet: & array:1 [
"id" => array:2 [
0 => SymfonyComponentUidUuidV6^ {#549
#uid: "1edac68e-0f54-6828-b519-0b4d85d941b5"
toBase58: "4oz2m7gHUaB5R1EjB45meL"
toBase32: "0YVB38W3TMD0MBA68B9P2XJGDN"
time: "2023-02-14 13:09:56.910084 UTC"
}
1 => "1edac68e-0f54-6828-b519-0b4d85d941b5"
]
]
}

So according the entityChangeSet Doctrine find that the id type has changed from SymfonyComponentUidUuidV6 to string. Then Doctrine fires the event.

The resolution

How to solve it and why this happens?

We found that the event is fired because the id type is changed. But why?

Let’s see what’s happening when we first create the member entity:

 AppEntityMember^ {#630
+id: "1edae008-54be-67ae-a260-d1c92065d6bf"
+createdAt: DateTimeImmutable @1676555277 {#609
date: 2023-02-16 13:47:57.793062 UTC (+00:00)
}
+updatedAt: DateTimeImmutable @1676555277 {#609}
}

The id field is a string, as we expected. But doctrine.uuid_generator returns an Uuid object. So this object must be able to be cast down to a string. And the answer is yes, Uuid inherits from SymfonyComponentUidAbstractUid which implements a __toString function.

And then, to save the data to the database, Doctrine will call the convertToDatabaseValue of AbstractUiType (which is inherit by Uuid class) which will re-cast our string to a new Uuid object and then to a string.

Here the snippet of convertToDatabaseValue function:

public function convertToDatabaseValue($value, AbstractPlatform $platform): ?string
{
$toString = $this->hasNativeGuidType($platform) ? 'toRfc4122' : 'toBinary';

if ($value instanceof AbstractUid) {
return $value->$toString();
}

if (null === $value || '' === $value) {
return null;
}

if (!is_string($value)) {
throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'string', AbstractUid::class]);
}

try {
return $this->getUidClass()::fromString($value)->$toString();
} catch (InvalidArgumentException) {
throw ConversionException::conversionFailed($value, $this->getName());
}
}

source: https://github.com/symfony/symfony/blob/feeeaf5295f4a42477262ed7143c76d886ba0f55/src/Symfony/Bridge/Doctrine/Types/AbstractUidType.php#L65

Everything happens in the return instruction. $value is converted to AbstractUuid then converted to string.

If we resume what happen during the creation of the member entity:

  • doctrine.uuid_generator return a freshly generated Uuid object
  • This object is cast down to a string by AbstractUiType

After the creation, refresh function is called on the entity, here what happens:

  • Doctrine compares the current value of id which is a string to the PHP value obtain after calling convertToPHPValue of AbstractUuid class. It was what we obtain from the PreUpdateEventArgs argument from preUpdate method !
  • Then the id field is updated with the string value and the event preUpdate is fired

Code of convertToPHPValue:

public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?AbstractUid
{
if ($value instanceof AbstractUid || null === $value) {
return $value;
}

if (!is_string($value)) {
throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'string', AbstractUid::class]);
}

try {
return $this->getUidClass()::fromString($value);
} catch (InvalidArgumentException $e) {
throw ConversionException::conversionFailed($value, $this->getName(), $e);
}
}

source: https://github.com/symfony/symfony/blob/feeeaf5295f4a42477262ed7143c76d886ba0f55/src/Symfony/Bridge/Doctrine/Types/AbstractUidType.php#L43

Sequence diagram to understand why doctrine dectect a change

Finally, as we deeply understand what happens, we can fix our code. The fix is simple: we have to change the type-hinting of id from string to Uuid|string.

End of the journey

As simple as the resolution is, keep in mind the investigation of this kind of bug take roughtly 2–3 months, dealing with day-to-day dev tasks.

This article tries to hightlight that with a good undestanding of how works Doctrine, this bug could be prevent. But we have to keep in mind, this is with this kind of experience we improve ourself and the most important is to have a good debug method to solve those bugs.

About ekino

The ekino group has been supporting major groups and start-ups in their transformation for over 10 years, helping them to imagine and implement their digital services and deploying new methodologies within their project teams. A pioneer in its holistic approach, ekino draws on the synergy of its expertise to build coherent, long-term solutions.

To find out more, visit our website — ekino.com.


Symfony UUID, Doctrine and type-hinting : everything you should know was originally published in ekino-france on Medium, where people are continuing the conversation by highlighting and responding to this story.

Comment utiliser la combinaison pour créer une condition if-else dans RxJS

TL;DR Nous verrons dans cet article sous forme d’interview l’utilité de l’opérateur de combinaison merge pour faire une condition if-else dans RxJS Introduction Moi, c’est Omar, ingénieur front chez Ekino. Souvent, lorsque je démarre un projet RxJS existant, je constate que les développeurs respectent le principe de la programmation réactive via l’utilisation d’observables et d’opérateurs RxJS […]

Lire la suite de Comment utiliser la combinaison pour créer une condition if-else dans RxJS
Photo by Unseen Studio on Unsplash

After participating in the conference Sauve un-e dev, écris un doc ! (by Sarah HAÏM-LUBCZANSKI) at AFUP’s forum, I learned about the importance of project documentation. Thanks to this presentation, I acquired skills to write documentation better than ever before.

In this article, I will introduce 3 steps of writing documentation that I suggest keeping in mind, and then I will show you some cases that I used daily.

Steps for writing a documentation :

Writing a documentation can be broken down into 3 principal steps :

  1. Structure: First, the edition of our documentation can be divided into 3 parts: What, Why, and How.

What: Introduce what kind of issue it is and what the issue is.

Why: Talk about the need for writing down this documentation, by listing things such as its context and objectives.

How: Explain the details of how the problem has been resolved

2. Explain in detail: in this step, we should complete our documentation according to the structure we created in the previous step.

To show you what I mean, we can create a README.md file or any other kind of documentation support to show the procedure of how to install a project step by step. We can also add some code examples to make it easier to understand.

3. Improve: It’s necessary to improve our documentation along with all the changes that happen during the project’s life.

Different ways to write documentation for an IT project

There’re various ways to write documentation. On this occasion, I will introduce 3 ways that I use regularly as a novice engineer.

1. Write documentation directly into the code

It’s possible to document our code by adding comments. But, pay attention to this! According to the book “Clean Code: A Handbook of Agile Software Craftsmanship” by Robert C. Martin, we shouldn’t add useless comments:

“Good Comments

Some comments are necessary. But keep in mind, the only truly good comment is the comment you found a way not to write.

Informative Comments

It’s useful to provide basic information with a comment.”

This quote teaches us that we should rewrite our code more correctly and make it more understandable, instead of commenting on incomprehensible code. For example, we can name our variables or our functions based on their purpose. Additionally, we can use abstraction or split them into methods with a single responsibility.

However, sometimes certain cases need to be commented on, such as explaining mathematical algorithmic cases, bug cases, legal cases, and so on.

To give you an idea, here is the code in PHP for validating a postal code :

private const FRENCH_POSTAL_CODE_REGEX = '/^(?:0[1–9]|[1–8]d|9[0–8])d{3}$/';

/**
* Valid examples: "33000", "76000" and "04700"
* Invalid examples: "33 000", "a3000", "76abc" and "0a7e1"
*/
preg_match(self::FRENCH_POSTAL_CODE_REGEX, $postalCode);

In this example, I use the constant “FRENCH_POSTAL_CODE_REGEX” for a given regular expression pattern, but its purpose may not be immediately obvious from its content. Therefore, it’s meaningful to add a comment with some valid and invalid cases of this regular expression.

As human beings, sometimes we forget the reasons why we added certain codes as time goes by. A comment can be useful to remind us of that.

In this case, there’re also different kinds of comments that we can use. For example:

  • @TODO” is used to remind us that there is still something that needed to be added or improved.
  • @deprecated” is used to remind us that we should not use certain methods or classes because they will be abandoned soon.

2. To write a related documentation during the code review

As developers, we use the Git system almost every day, however, we may be unaware of the importance of writing good code reviews on our MRs(Merge Requests) or PRs(Pull Requests).

To begin with, the title is the core of an MR/PR, and a good title helps us understand the proposed changes directly and quickly.

So, the question is, how can we format a good title for it?

First of all, I recommend the notion of Conventional Commit to all of you. This notion guides us on how to format our commit messages, and the rules mentioned there provide us with some ideas on how to format the title of our code reviews.

Besides, we should find out what kind of MR/PR it is and what its context is. For instance, the keyword “feat” is related to a new feature, and “fix” is for patching a bug. Then, we can add a scope to the title to show more details.

Here’re 2 examples:

  • feat(api)” : with the scope “api”, we know that it is related to a feature of an Api.
  • chore(dependency) ”: scope “dependency” shows us that it is for a change of version for a dependency.

After defining the type of MR, we should continue with the second part of the title to describe its details. It should be understandable for everyone even if they aren’t developers.

Let’s suppose that we have a feature to sort companies by their priority. Here we have 3 options, what do you think, which one is more evident?

  • option 1 : feat(entity): add $sortBy to entity Company
  • option 2 : feat(entity): add property $sortBy to sort companies by ascending order.
  • option 3: feat(search): allow to sort companies by label in ascending order

From my point of view, option n°1 is quite technical, we know that it is a feature for adding a new property “$sortBy” into the Company entity. It’s clear for developers but not easy enough to understand for people who do not work in IT.

Based on Option 2, it is apparent that the new property “$sortBy” is for sorting companies. However, it’s important to note that some individuals may not be familiar with the term “property”, which makes the feature less accessible to them.

On the contrary, option n°3 shows us that the new feature is created to sort companies by ascending order without using any technical words. This title is so clear that almost everyone can understand the objective of this feature.

Regarding the content of an MR/PR, we can introduce the context in its description and we can also add some screenshots to show the changes we made.

Sometimes we may forget some formatting rules, which are decided by our team, during our code review, and we may see some errors due to this. Don’t worry! There’s a tool called Danger JS which is used in a CI job and we can configure it in different ways for our needs. It will send us a warning message automatically once an MR doesn’t respect a rule so that we can prevent those issues.

Here is an example of a Danger JS job in my project in the CI “prepare” stage:

Another example of a warning message sent by the Danger JS job is when it alerts us to an error in the naming of the title, and suggests that we should rename it to adhere to the naming convention.

Comments made during code review serve as a form of documentation, which conserves exchanges amongst the team of developers. To effectively format comments and feedback, we can use conventional comments standards.

Firstly, we can introduce the type of comment with a single label, such as “question” to request a clarification or confirmation from the owner for a particular issue, or “suggestion” for proposing some improvements to the current code.

Additionally, we can include a decoration next to the label to provide additional organization to the comment. For example, “suggestion(non-blocking)” could be used to propose a non-essential improvement that does not hinder the approval of an MR/PR.

3. Writing a documentation after having resolved a bug

At this point, you may be wondering why it’s necessary to write documentation about how to resolve a bug.

In my opinion, this type of documentation can serve as a reference for project members who are not aware of the existence of the bug. Providing context and important information can help them understand why the bug occurred and how it was fixed.

Additionally, documenting how a bug was fixed can be a useful resource for other developers who may face the same problem or even those who encounter similar issues in the future. By documenting the steps which are taken to resolve the bug, we can help others to fix the same issue more quickly.

Now, after understanding the importance of documenting bug fixes, the next question will be: “How to write this kind of documentation?”.

During the conference, the speaker talked about the notion of Developer Loop”, modeled by Kelsey Hightower for the case when developers face bugs.

According to this concept, the documentation can be split into 4 steps:

  1. Understand why and how the problem shows up
  2. Try to search for an existing solution
  3. Prove to ourselves or our team how the solution works
  4. Publish the solution

Conclusion

Documentation serves as a powerful means of communication with both present and future audiences, including yourself! So it’s necessary to spend time doing it well. And don’t forget to improve the documentation if needed!

There’re other types of documentation of a project that I haven’t mentioned in this article:

  • ADR(Architecture Decision Record) : a type of documentation to introduce and explain an architectural decision of a project. This documentation includes the context, different possible solutions to the problem, the final decision the team has chosen, and its related consequences.
  • README.md file : a documentation that provides a tutorial for users on how to install or use a project.
  • Wiki : a kind of documentation for internal communication within a team. For example, we can write a wiki documentation to explain some technical features of different roles of a project.

Thanks for taking the time to read through this article. Hopefully it provided you with some valuable insights ! If you are interested, feel free to explore ekino’s website to learn more about our work.


Importance of a documentation was originally published in ekino-france on Medium, where people are continuing the conversation by highlighting and responding to this story.

Ça Twig ou bien ?

Ça Twig ou bien ? Photo by Jonathan Borba on Unsplash J’aimerais évoquer avec toi un sujet passionnant l’Abstract Syntax Tree (AST) ainsi que la notion de Visitor fréquemment associée. Je vais te présenter un REX, sur une implémentation dédiée, dans le cadre du développement d’un connecteur à POEditor, qui fera la part belle à l’ami Benjamin […]

Lire la suite de Ça Twig ou bien ?

Retour sur la conférence de Benoit Viguier, présentée le 13 octobre 2022 dans le cadre du forum PHP de l’AFUP.

Benoit Viguier a débuté sa conférence par une des problématiques les plus courantes dans l’informatique : celle de normaliser un processus, créer un standard qui soit unique pour tout le monde. En effet, très souvent, en voulant créer un standard qui regroupe et améliore l’existant, on en arrive à un énième standard qui se perd parmi tous les autres.

Pourquoi avoir eu besoin de se pencher sur la création d’un nouveau standard ? Dans un monde où les micro-services sont de plus en plus utilisés par rapport aux architectures monolithiques et les échanges entre différents services se multiplient, il est devenu parfois compliqué pour les développeurs de s’y retrouver dans différentes configurations d’outils. Ce constat est d’autant plus présent dans tout ce qui concerne les métriques et autres outils d’analyse.

BD ironique de xkcd sur le trop grand nombre de standards en informatique
Trop de standards tuent les standards ?

A priori, ça ne sera pas le cas d’Open Telemetry, qui se veut être un nouveau standard pour l’échange de données entre nos applications et les outils d’alerting — et nous allons voir pourquoi il est prometteur.

Les outils de monitoring

Mais tout d’abord, une petite piqure de rappel sur les termes principaux utilisés dans ce domaine. Commençons par la définition de monitoring : il doit nous permettre de répondre à plusieurs questions — “est-ce que ça marche” et “pourquoi ça ne marche pas” ?

Nous avons déjà tous eus à dépanner un bug en production — et bien que les outils soient là, comme LiipMonitor ou Blackfire, il n’existe pas pour le moment de norme adoptée de tous pour régulariser le processus d’échange d’informations entre nos applications et ces services, ni entre ces services eux-mêmes.

Il faut bien différencier les principaux domaines du monitoring :

Les Analytics :

Surtout lié au côté front et orienté business, les analytics simples nous apportent des données comme les visites sur notre site, mais ne vont pas vraiment être utiles en cas de panne, et sont orientées business plutôt que technique.

Image d’un dashboard Matomo
Exemple d’un dashboard d’analytics avec Matomo

Les sondes HTTP

Elles ne sont pas intrusives, marchent partout et sont simples à mettre en place avec des scénarios variés. Mais d’un autre côté ne nous apportent pas énormément d’informations à défaut d’écrire beaucoup de scénarios différents.

Exemple d’un sonde HTTP
Sonde HTTP qui mesure le temps d’exécution selon l’emplacement de l’utilisateur

Les métriques

Les métriques, l’outil le plus visuel, agrège différentes informations sous forme de graphiques ou tables, ce qui rend possible d’observer l’évolution de notre application dans le temps. On entend souvent parler de “Golden Metrics” — qui sont définies par la performance, la charge, et les erreurs. En contrepartie, ces métriques donnent peu d’informations sur les raisons elles-mêmes des erreurs, ne pouvant que servir comme un des outils de surveillance.

Exemple d’un dashboard de metrics
Exemple d’un dashboard de metrics avec des données diverses

Les logs

C’est l’outil qui nous apporte le plus d’informations et le plus de détails avec le plus de simplicité, pouvant venir de pratiquement toutes les sources de notre appli — mais l’envers du décor est que le volume de données est parfois trop grand, ce qui rend complexe la recherche d’informations vraiment pertinentes.

Exemple d’un dashboard de logs, Kibana
Exemple de monitoring de logs avec Kibana

Le tracing

Enfin, le tracing, pouvant être vu comme un rayon X des processus de nos applications. Un exemple qui nous est familier est la partie “Execution timeline” dans l’onglet “Performance” dans la debug bar de Symfony, où on peut voir exactement quels services ont été appelés lors de l’exécution d’une requête, avec des données précises sur le temps que chaque processus a mis pour s’exécuter en entier. Couplé aux logs, cet outil apporte plus de contexte à nos problèmes éventuels.

Exemple de tracing HTTP
Exemple de tracing d’une requête HTTP

La promesse d’Open Telemetry

OpenTelemery apporte une solution unifiante. Elle propose une API indépendante du langage et du service d’analyse utilisé, qui sera un standard pour tous. Lors de la création de ce standard, 3 piliers principaux de la télémétrie ont été choisis — les logs, les métriques et les traces.

Ce nouveau standard a donc pour objectif de normaliser le transfert de données depuis notre application vers les APM (Application Performance Management), en rassemblant toutes les informations concernant les mesures depuis notre application, pour ensuite être envoyées aux APM pour analyse. Mais comment ce procédé est mis en place ?

Un collecteur proxy

La partie centrale de la structure d’Open Telemetry est le collecteur, qui fait office de proxy entre les applis de monitoring et notre backend.

Ce collecteur rassemble la logique qui décide si le backend est prêt ou non à recevoir des données. Surtout pour que les métriques ne fassent pas casser la production — il faut en effet dissocier les deux, car si nos outils de métrique cassent, on ne souhaite pas que cela ait un effet de bord sur nos applications en production.

Ce collecteur est pour le moment écrit en Go mais pourrait à terme être traduit dans d’autres langages.

Schema du collecteur d’OTel
Schéma représentant le fonctionnement du collecteur d’OTel

Etat d’avancement

Pour le moment, les APIs et SDKs pour le tracing et les métriques sont en état “stable”, et encore en état “brouillon” pour les logs.

Comme protocole de transport, Open Telemetry utilise gRPCS et HTTP, ainsi que le protocole Protobuf de Google (non disponible pour le PHP pour le moment) pour les payloads binaires encodés.

Un standard déjà existant depuis peu et recommandé par le W3C, le trace-context, définissant les en-têtes HTTP pour propager les informations de contexte qui permettent des scénarios de traçage parmi différents services, afin de transmettre par exemple la trace d’une erreur d’une API à une autre sera également adopté par OTel.

Sur le GitHub d’OTel, on retrouve beaucoup de dépôts divisés par langage où se trouvent les différentes implémentations du standard traduits, mais également des dépôts dédiés à l’amélioration générale d’OT, dont un que j’ai trouvé très intéressant, l’OpenTelemetry Enhancement Proposal, où dans chaque issue des propositions variées sont faites sur le futur du standard.

Open Telemetry apporte donc un standard pour les domaines principaux de la télémétrie à la façon dont php-fig apporte les PSR pour la langue PHP par exemple. En ce moment, NewRelic, Datadog ou encore Google travaillent déjà dessus ensemble, et le protocole devrait être rapidement adapté par d’autres grands acteurs de l’informatique.

En plus d’apporter beaucoup d’informations sur ce nouveau standard et de le populariser, cette conférence a permis de faire un état des lieux sur ces outils qui nous servent pour avoir une représentation de notre travail de développeurs, et surtout nous aider dans les moments difficiles quand notre code ou configuration casse — sans eux nous serions quand même bien embêtés.

Si le sujet vous a intéressé, je vous conseille de jeter un coup d’œil à la démo d’OTel ou encore à OTel en PHP.

Sources des images :


Les outils de monitoring actuels et la promesse d’Open Telemetry was originally published in ekino-france on Medium, where people are continuing the conversation by highlighting and responding to this story.

Write dynamic email templates like a breeze with MJML in React

Writing good looking emails is usually not the first task of your product backlog, but eventually, every product ends up needing it. If you ever looked up at what an email’s source code looks like, you wouldn’t even consider writing it in plain HTML (really, you can’t be that crazy)… <!– […] –><!–[if mso | IE]><table role="presentation" […]

Lire la suite de Write dynamic email templates like a breeze with MJML in React