# Pourquoi et comment on a testé les UUIDs ... à la place des ids dits "techniques" / "de base de données" --- ## C'est quoi un UUID ? C'est une chaîne de caractère générée aléatoirement ###### avec une possibilité infime qu'une même chaîne soit générée deux fois --- ## Pourquoi ? --- ``` PeakDays ( id <- provider_calendar_id type begin_date end_date creation_date ) PeakDaysProgrammingStatus ( id_device peak_day_id -> status ) ``` --- Use case basique : je veux récupérer tous les PeakDaysProgrammingStatus qui correspondent à un jour de pointe donné. --- Je peux faire deux requêtes... ``` PeakDay=( SELECT * FROM PeakDays WHERE type = "TEMPO_RED" AND date = "2024-01-25 06:00:00" ) PeakDaysProgrammingStatus=( SELECT * FROM PeakDaysProgrammingStatus WHERE peak_days_id = $PeakDay.id ) ``` --- ... ou faire une jointure. ``` SELECT PeakDaysProgrammingStatus.* FROM PeakDaysProgrammingStatus LEFT JOIN PeakDays ON (PeakDays.type = "TEMPO_RED" AND PeakDays.date = "2024-01-25 06:00:00") ``` --- Ou faire un WHERE très stupide. ``` SELECT * FROM PeakDaysProgrammingStatus WHERE peak_days_id = 1 ``` --- Vous préférez quoi ? --- ## Keep it simple and stupid ###### (la simplicité est un principe fondateur de Smartside) On peut rendre les IDs visibles du Domaine, ce qui permet de façon plus simple de récupérer les status de programmation d'un jour de pointe, à partir du peak_day_id. --- ## J'ai besoin d'identifer le PeakDay le LU envoie un rapport de programmation d'un PeakDay au SEC. Il faut identifier ce jour de pointe. Comment ? --- Par son type (EJP, TEMPO_RED, TEMPO_WHITE) et son jour. --- Par son ID --- ## Comment peuvent être générés les PeakDays id ? Par le BDD sous forme de séquence ? --- ## Problème On a un objet métier qui représente un PeakDay ; chaque PeakDay possède nécessairement un id, sauf un PeakDay qui n'a pas été généré en BDD --- ``` data class PeakDay( val id: PeakDayId, val calendarId: CalendarId, val type: PeakDayType, val creationDate: SmartDate, val beginDate: SmartDate, val endDate: SmartDate, ) { companion object { fun create( calendarId: CalendarId, type: PeakDayType, creationDate: SmartDate ) = when (type) { TEMPO_WHITE, TEMPO_RED -> tempoPeakDay(calendarId, type, creationDate) EJP -> ejpPeakDay(calendarId, creationDate) } private fun tempoPeakDay( calendarId: CalendarId, type: PeakDayType, creationDate: SmartDate ): PeakDay { return PeakDay(?, calendarId, type, creationDate, beginDate, endDate) } private fun ejpPeakDay( calendarId: CalendarId, creationDate: SmartDate ): PeakDay { //[...] return PeakDay(?, calendarId, EJP, creationDate, beginDate, endDate) } } } ``` --- ## Keep it simple and stupid ! Pour une raison de simplicité (et de charge mentale), je ne souhaite pas que mon objet PeakDay possède un état inderminé (id potentiellement null) --- Et si je pouvais m'éviter tout ce boilerplate dans les scripts de BDD pour utiliser une séquence... ``` CREATE SEQUENCE provider_calendar_peak_days_id_seq START WITH 1 INCREMENT BY 1 MINVALUE 1 NO MAXVALUE CACHE 1; ALTER TABLE public.provider_calendar_peak_days_id_seq OWNER TO smartuser; ALTER SEQUENCE provider_calendar_peak_days_id_seq OWNED BY provider_calendar_peak_days.id; ALTER TABLE provider_calendar_peak_days ALTER COLUMN id SET DEFAULT nextval('provider_calendar_peak_days_id_seq'::regclass); UPDATE provider_calendar_peak_days SET id = nextval('provider_calendar_peak_days_id_seq'::regclass); ``` --- On peut faire plus simple. --- ## Solution proposée Le métier génére lui-même l'id. On utilise des UUID Java natif. ``` data class PeakDay( val id: PeakDayId, val calendarId: CalendarId, val type: PeakDayType, val creationDate: SmartDate, val beginDate: SmartDate, val endDate: SmartDate, ) { companion object { fun create( calendarId: CalendarId, type: PeakDayType, creationDate: SmartDate ) = when (type) { TEMPO_WHITE, TEMPO_RED -> tempoPeakDay(calendarId, type, creationDate) EJP -> ejpPeakDay(calendarId, creationDate) } private fun tempoPeakDay( calendarId: CalendarId, type: PeakDayType, creationDate: SmartDate ): PeakDay { return PeakDay(PeakDayId(UUID.randomUUID()), calendarId, type, creationDate, beginDate, endDate) } private fun ejpPeakDay( calendarId: CalendarId, creationDate: SmartDate ): PeakDay { //[...] return PeakDay(PeakDayId(UUID.randomUUID()), calendarId, EJP, creationDate, beginDate, endDate) } } } ``` --- On Simplifie les scripts de création de la BDD ``` CREATE TABLE provider_calendar_peak_days ( id uuid PRIMARY KEY, ... ); ``` --- ## Et dans Exposed ? ``` object ProviderCalendarPeakDays : IdTable<UUID>("provider_calendar_peak_days") { override val id = uuid("id").entityId() val calendarId = reference("provider_calendar_id", MeterProviderCalendar) val type = customEnumeration("type", "peak_day_type", { value -> PeakDayType.valueOf(value as String) }, { PGEnum("peak_day_type", it) }) val beginDate = datetime("begin_date") val endDate = datetime("end_date") val creationDate = datetime("creation_date") } ``` --- ## En conclusion Les IDs générés par le métier... Ca révolutionne rien, mais c'est un petit pas vers la simplicité --- Merci !
{"title":"UUIDs","slideOptions":"{\"transition\":\"slide\"}","contributors":"[{\"id\":\"72e4fb31-4c08-4ab8-a2fe-bd95579765bf\",\"add\":8826,\"del\":2894}]","description":"… à la place des ids dits “techniques”"}
    81 views