• les dernières technologies innovantes en cours de développement ou en phase de lancement sur le marché.
  • les critiques de produits technologiques populaires, tels que les téléphones intelligents, les ordinateurs portables, les tablettes, les écouteurs, les caméras, etc.
  • des conseils sur la façon de rester en sécurité en ligne, notamment en ce qui concerne la protection de la vie privée, la sécurité des données et la prévention des escroqueries en ligne.
  • les dernières nouvelles et mises à jour dans le monde de la technologie, y compris les fusions et acquisitions, les partenariats, les changements de direction, etc.
Affichage des articles dont le libellé est Event Sourcing. Afficher tous les articles
Affichage des articles dont le libellé est Event Sourcing. Afficher tous les articles

mercredi 29 mars 2023

Event Sourcing en Java: Comment stocker et reconstruire l'état d'un système avec fiabilité


L'Event Sourcing est une technique de développement de logiciels qui a gagné en popularité ces dernières années en raison de sa capacité à améliorer la résilience et la scalabilité des systèmes. En utilisant cette technique, un développeur peut stocker l'état d'un système en enregistrant une séquence d'événements plutôt que de stocker uniquement l'état actuel. Dans cet article, nous allons examiner comment implémenter l'Event Sourcing en Java en utilisant un exemple concret.


Qu'est-ce que l'Event Sourcing ?


L'Event Sourcing est une approche de développement de logiciels dans laquelle l'état du système est stocké sous forme de séquence d'événements. Chaque événement représente une modification de l'état du système à un moment précis. En utilisant cette technique, les développeurs peuvent facilement récupérer l'état du système à n'importe quel moment en rejouant simplement les événements.


Cette approche a plusieurs avantages. Tout d'abord, elle offre une résilience accrue. En enregistrant chaque événement, le développeur peut facilement retracer l'historique de toutes les modifications apportées au système. Cela facilite également la détection et la correction des erreurs. De plus, l'Event Sourcing offre une scalabilité améliorée, car il est facile de partitionner les événements pour les stocker dans différents emplacements.


Comment implémenter l'Event Sourcing en Java ?


En Java, l'Event Sourcing peut être implémenté en utilisant une base de données NoSQL. Les bases de données NoSQL sont particulièrement bien adaptées à cette approche car elles offrent une flexibilité accrue par rapport aux bases de données relationnelles traditionnelles.

Exemple concret

Pour illustrer comment implémenter l'Event Sourcing en Java, prenons l'exemple d'un système de réservation de vols.

1. Créer des événements

Pour chaque action effectuée dans le système de réservation de vols, nous créons un événement correspondant. Par exemple, lorsque nous créons une nouvelle réservation, nous créons un événement "ReservationCreatedEvent". Chaque événement est représenté par une classe Java qui contient les informations nécessaires pour décrire l'action effectuée.

Exemple de classe d'événement

public class ReservationCreatedEvent {
private UUID reservationId;
private String passengerName;
private String flightNumber;

public ReservationCreatedEvent(UUID reservationId, String passengerName, String flightNumber) {
	this.reservationId = reservationId;
	this.passengerName = passengerName;
	this.flightNumber = flightNumber;
}

// getters and setters
}

2. Stocker les événements

Pour stocker les événements, nous utilisons une base de données NoSQL telle que Cassandra. Nous créons une table "Reservations" qui contient une colonne "events" de type liste. Pour ajouter un nouvel événement à une réservation, nous pouvons utiliser la méthode "saveEvent" de notre repository.

Exemple de repository

public class ReservationRepository {
private static final String INSERT_EVENT_QUERY = "UPDATE Reservations SET events = events + ? WHERE id = ?";
private static final String SELECT_EVENTS_QUERY = "SELECT events FROM Reservations WHERE id = ?";

private final Session session;

public ReservationRepository(Session session) {
	this.session = session;
}

public void saveEvent(UUID id, Object event) {
	session.execute(INSERT_EVENT_QUERY, id, toJson(event));
}

public List getEvents(UUID id) {
	ResultSet result = session.execute(SELECT_EVENTS_QUERY, id);
	Row row = result.one();
	List events = new ArrayList<>();
	if (row != null) {
		List<JsonNode> jsonNodes = row.getList("events", JsonNode.class);
		jsonNodes.forEach(jsonNode -> events.add(fromJson(jsonNode)));
	}
	return events;
}

private JsonNode toJson(Object object) {
	ObjectMapper mapper = new ObjectMapper();
	return mapper.valueToTree(object);
}

private Object fromJson(JsonNode jsonNode) {
	try {
		ObjectMapper mapper = new ObjectMapper();
		Class<?> clazz = Class.forName(jsonNode.get("type").asText());
		return mapper.treeToValue(jsonNode, clazz);
	} catch (ClassNotFoundException | JsonProcessingException e) {
		throw new RuntimeException(e);
	}
}
}

3. Rejouer les événements

Pour récupérer l'état actuel d'une réservation, nous devons rejouer tous les événements associés à cette réservation. Pour ce faire, nous pouvons utiliser la méthode "getEvents" de notre repository pour récupérer tous les événements associés à une réservation, puis les rejouer dans l'ordre chronologique pour reconstruire l'état actuel de la réservation.

Exemple de méthode pour récupérer l'état actuel d'une réservation

public class ReservationService {
private final ReservationRepository reservationRepository;

public ReservationService(ReservationRepository reservationRepository) {
	this.reservationRepository = reservationRepository;
}

public Reservation getReservation(UUID id) {
	List events = reservationRepository.getEvents(id);
	Reservation reservation = new Reservation(id);
	events.forEach(event -> {
		if (event instanceof ReservationCreatedEvent) {
			reservation.createReservation((ReservationCreatedEvent) event);
		} else if (event instanceof ReservationCancelledEvent) {
			reservation.cancelReservation((ReservationCancelledEvent) event);
		}
		// add more else-if clauses for other types of events
	});
	return reservation;
}
}

Dans cet exemple, la classe "Reservation" représente l'état actuel d'une réservation. Lorsque nous rejouons les événements associés à une réservation, nous utilisons les méthodes "createReservation" et "cancelReservation" pour mettre à jour l'état de la réservation en fonction des événements.

Avantages de l'Event Sourcing

L'Event Sourcing présente plusieurs avantages par rapport aux méthodes traditionnelles de développement de logiciels:

  • Réversibilité: En stockant tous les événements qui se produisent dans un système, nous pouvons facilement revenir en arrière en rejouant simplement les événements dans l'ordre inverse.
  • Reconstruction de l'état: En rejouant tous les événements associés à une entité, nous pouvons reconstruire son état actuel de manière fiable.
  • Facilité de mise à l'échelle: En stockant les événements dans une base de données NoSQL, nous pouvons facilement mettre à l'échelle horizontalement en ajoutant des nœuds à notre cluster.
  • Meilleure traçabilité: En enregistrant tous les événements qui se produisent dans un système, nous pouvons facilement retracer l'historique de toutes les actions effectuées.

Conclusion

L'Event Sourcing est une technique de développement de logiciels puissante qui peut être utilisée pour construire des systèmes fiables, évolutifs et traçables. En utilisant l'Event Sourcing en Java, nous pouvons facilement stocker tous les événements qui se produisent dans un système, récupérer l'état actuel de ce système en rejouant ces événements, et profiter des avantages que cette approche offre.

Les 6 pratiques de développement Java

  1. Programmation Orientée Objet (POO) : La POO est une approche de développement logiciel qui consiste à créer des objets qui contiennent des données et des méthodes. Les objets peuvent interagir les uns avec les autres pour accomplir des tâches spécifiques.
  2. Architecture hexagonale : Aussi connue sous le nom de "Ports and Adapters", cette approche consiste à séparer les couches applicatives et les dépendances externes (comme les bases de données ou les API) en utilisant des interfaces clairement définies. Cela permet de faciliter la maintenance et la flexibilité de l'application.
  3. Test Driven Development (TDD) : Le TDD est une approche de développement qui consiste à écrire des tests avant de coder la logique de l'application. Cela permet de s'assurer que le code est bien testé et de minimiser les erreurs.
  4. Programmation fonctionnelle : La programmation fonctionnelle est une approche de développement qui se concentre sur les fonctions plutôt que sur les objets. Elle utilise des fonctions pures, c'est-à-dire des fonctions qui n'ont pas d'effets de bord et qui ne modifient pas l'état de l'application, pour améliorer la lisibilité et la maintenabilité du code.
  5. Event Sourcing : L'Event Sourcing est une approche de stockage de données qui consiste à enregistrer toutes les actions (événements) qui modifient l'état de l'application. Cela permet de reconstruire l'état de l'application à partir des événements et de faciliter la gestion des transactions et de la concurrence.
  6. CQRS (Command Query Responsibility Segregation) : Cette approche consiste à séparer les opérations d'écriture (commandes) des opérations de lecture (requêtes) en utilisant des modèles de données différents. Cela permet de simplifier la gestion de l'état de l'application et d'améliorer les performances.

Ces approches peuvent être utilisées seules ou combinées pour créer des applications robustes et maintenables en Java.