2023-06-02
UML du project Scuba Calendar #dev
UML (Unified Modeling Language) relations
-
Inheritance (
<|--): This is a relationship where one class inherits all the attributes and behaviors of another class. The class being inherited is called the "parent" or "superclass," and the class doing the inheriting is called the "child" or "subclass." Inheritance is a way to form new classes using classes that have already been defined. -
Composition (
*--): This is a "whole/part" relationship where the part cannot exist independently of the whole. If the whole is deleted, the part is also deleted. An example could be a "Car" class and an "Engine" class. The engine can't exist without the car. -
Aggregation (
o--): This is also a "whole/part" relationship, but the part can exist independently of the whole. If the whole is deleted, the part is not necessarily deleted. An example could be a "Team" class and a "Player" class. If the team is dissolved, the player can still exist. -
Association (
-->): This is a relationship between two classes that are connected in some way, but there is no ownership implied. An example could be a "Teacher" class and a "Student" class. They are associated because a teacher can teach a student, but neither "owns" the other. -
Link (Solid) (
--): This is a simple relationship between instances of classes. It's used to show that there's a connection, but it doesn't specify the nature of the connection. -
Dependency (
..>): This is a relationship where a change in one class could affect another class. It often signifies that one class depends on another for its operation. For example, a "Customer" class might depend on a "ShoppingCart" class to keep track of purchases. -
Realization (
..|>): This is a relationship where one class implements the behavior specified by another class or interface. The class that provides the actual implementation is said to "realize" the interface or abstract class. -
Link (Dashed) (
..): This is a weaker form of the solid link. It's often used to show dependencies or associations that are not as strong as with a solid link. It can also be used to show relationships that are not always present or are conditional in some way.
UML diagram
The Firestore implementation #dev
-
Structure de collection de documents : Firestore organise les données en collections de documents. Chaque document peut contenir des sous-collections. Vos entités "Company", "Profile", "User", "Espace", "Booking" et "Planing" pourraient être des collections à part entière, avec chaque instance étant un document.
-
Relations entre les collections : Firestore n'a pas de support intégré pour les relations entre les collections, ce qui est différent des bases de données relationnelles classiques. Les relations sont généralement gérées en stockant les identifiants des documents liés. Par exemple, un document User pourrait avoir des champs "companyID" et "profileID" pour relier l'utilisateur à une Company et un Profile spécifiques. De même, User pourrait également avoir des champs "espaceIDs" et "bookingIDs" qui sont des listes d'identifiants de documents pour relier l'utilisateur à plusieurs Espaces et Bookings.
-
Données dénormalisées : L'un des principes de Firestore est de dénormaliser vos données. Cela signifie que vous pourriez dupliquer certaines données pour optimiser vos lectures. Par exemple, si vous affichez souvent le nom de la Company et le Profile avec chaque User, vous pourriez inclure ces champs directement dans le document User. Cela peut augmenter la vitesse de lecture, mais rend les mises à jour plus complexes car vous devez mettre à jour les informations à plusieurs endroits.
-
Indexation : Firestore indexe automatiquement tous les champs de document pour des requêtes rapides. Cependant, si vous prévoyez d'effectuer des requêtes complexes (par exemple, des requêtes combinant des filtres sur plusieurs champs), vous devrez créer des index composites.
-
Sécurité : Assurez-vous de mettre en place des règles de sécurité appropriées pour protéger vos données. Firestore vous permet de contrôler qui peut lire et écrire dans vos collections et documents à un niveau très granulaire.
DocumentReference vs CollectionReference
DocumentReference et CollectionReference sont deux types d'objets dans Firestore qui font référence à un document et à une collection, respectivement.
-
DocumentReference: C'est une référence à un document dans une collection de Firestore. Il peut être utilisé pour lire, écrire ou écouter l'emplacement du document. Le document auquel il fait référence n'a pas besoin d'exister - il peut simplement être un emplacement pour un futur document.
-
CollectionReference: C'est une référence à une collection dans Firestore. Il peut être utilisé pour créer de nouveaux documents dans la collection ou pour interroger la collection pour obtenir des documents.
L'une des principales différences entre les deux est donc leur utilisation :
- Vous utilisez une
DocumentReferencelorsque vous souhaitez effectuer une opération sur un document spécifique. - Vous utilisez une
CollectionReferencelorsque vous souhaitez effectuer une opération sur une collection, comme ajouter un document à la collection, ou interroger tous les documents dans la collection.
What's the difference between using a DocumentReference in Firestore and using just the id?
A Reference contains the entire path to a document, whereas a simple string ID has no context. Granted, you could just store the path as a string instead, but for convenience (and ease of use in custom objects) it can be useful to have the entire Reference object stored.
Code implementation
Dans Firestore, vous pouvez choisir entre le stockage des relations entre les entités et la dénormalisation des données. La dénormalisation peut entraîner une réduction du nombre de requêtes nécessaires, mais augmente la complexité lors de la mise à jour des données.
- Collection "Users" : Chaque document représente un utilisateur avec un identifiant unique (
ID) et peut contenir d'autres informations sur l'utilisateur telles quename,emailetrate. Les documents "User" contiennent des références aux documents "Espace" et "Booking" correspondants. De plus, chaque document "User" aurait deux champs pour stocker les informations de "Company" et "Profile" respectivement. C'est parce que dans votre diagramme, un utilisateur est composé d'une entreprise et d'un profil.
class User {
final String id;
final String name;
final String email;
final double rate;
final DocumentReference company;
final DocumentReference profile;
final CollectionReference espace;
final CollectionReference booking;
User({this.id, this.name, this.email, this.rate, this.company, this.profile, this.espace, this.booking});
}
- Collection "Espaces" : Chaque document représente un espace avec un identifiant unique (
ID). Chaque document "Espace" contient des informations supplémentaires telles quename,typeetquantity. Chaque document "Espace" a une sous-collection "Planing".
class Espace {
final String id;
final String name;
final String type;
final int quantity;
final DocumentReference planning;
Espace({this.id, this.name, this.type, this.quantity, this.planning});
}
- Collection "Bookings" : Chaque document représente une réservation avec un identifiant unique (
ID). Chaque document "Booking" contient des informations supplémentaires telles quename,equipmentetquantity. Chaque document "Booking" a une sous-collection "Planing".
class Booking {
final String id;
final String name;
final String equipment;
final int quantity;
final DocumentReference planning;
Booking({this.id, this.name, this.equipment, this.quantity, this.planning});
}
- Sous-collection "Planing" : Chaque document représente un planing associé à un "Espace" ou une "Booking". Il contient des informations supplémentaires telles que
nameetdate.
class Planing {
final String id;
final String name;
final DateTime date;
Planing({this.id, this.name, this.date});
}
- Classes "Company" et "Profile" : Ces deux classes seraient utilisées pour stocker les informations de "Company" et "Profile" respectivement dans chaque document "User".
class Company {
final String id;
final String name;
Company({this.id, this.name});
}
class Profile {
final String id;
final String name;
Profile({this.id, this.name});
}
Intégration de Firestore Authentification
Firebase Auth est un service qui peut authentifier les utilisateurs à l'aide de diverses méthodes, y compris par e-mail/mot de passe, OIDC, etc. En général, chaque utilisateur authentifié par Firebase Auth reçoit un identifiant unique (uid) qui peut être utilisé pour associer l'utilisateur authentifié à d'autres données dans votre base de données Firestore.
Voici comment vous pouvez procéder:
- Modification de la classe User:
Dans le diagramme, ajoutez un champ authUid à la classe User:
Le champ authUid est utilisé pour stocker l'identifiant unique de l'utilisateur (uid) retourné par Firebase Auth lorsque l'utilisateur s'authentifie.
- Authentification de l'utilisateur:
Lorsqu'un utilisateur s'authentifie, Firebase Auth renvoie une promesse avec un UserCredential. Vous pouvez obtenir l'uid de l'utilisateur à partir de cette promesse:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
final FirebaseAuth _auth = FirebaseAuth.instance;
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
void signIn(String email, String password) async {
try {
UserCredential userCredential = await _auth.signInWithEmailAndPassword(email: email, password: password);
User user = userCredential.user;
if (user != null) {
_firestore.collection("users").doc(user.uid).set({
'name': user.displayName,
'email': user.email,
'authUid': user.uid, // Authenticated user's uid
'rate': 3
}).then((_) {
print("Document successfully written!");
}).catchError((error) {
print("Error writing document: $error");
});
}
} catch (error) {
print("Error signing in: $error");
}
}