diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 0b825bb3b47deef45fcf9c58ef2b9435eb3582dc..dd6653532182e805771d3ac942dc2b4172b18dc8 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -41,3 +41,4 @@ include:
   - local: "/diamond-ts/.gitlab-ci.yml"
   - local: "/java-memoizers/.gitlab-ci.yml"
   - local: "/markov-chain/.gitlab-ci.yml"
+  - local: "/names/.gitlab-ci.yml"
diff --git a/names/.gitlab-ci.yml b/names/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..8344009cb66ec0cd5d4f0fe1f2bb181af7c04aa5
--- /dev/null
+++ b/names/.gitlab-ci.yml
@@ -0,0 +1,11 @@
+package-names:
+  variables:
+    PROJECT_FOLDER: "names"
+  extends: .java
+  only:
+    refs:
+      - master
+      - merge_requests
+    changes:
+      - ".gitlab-common-ci.yml"
+      - "names/**/*"
diff --git a/names/pom.xml b/names/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8ef958b707b1b6a68d189fb854c07c6b2568ee7a
--- /dev/null
+++ b/names/pom.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <version>1.0.0</version>
+    <groupId>fr.ippon.kata</groupId>
+    <artifactId>java-parent</artifactId>
+    <relativePath>../java-parent</relativePath>
+  </parent>
+
+  <version>1.0.0-SNAPSHOT</version>
+  <artifactId>names</artifactId>
+
+  <name>Names</name>
+
+  <developers>
+    <developer>
+      <email>cdamon@ippon.fr</email>
+      <name>Colin DAMON</name>
+    </developer>
+  </developers>
+</project>
diff --git a/names/readme.md b/names/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..e446c7dfb86fb2d80155df6f78a7e879a0891600
--- /dev/null
+++ b/names/readme.md
@@ -0,0 +1,9 @@
+# Dans quel ordre faire les features
+
+Explications de l'ordre des features dans un projet
+
+-   **Auteurs** : Colin DAMON
+-   **Date** : 15/09/2021
+-   **Langage** : Java
+-   **Niveau** : Moyen
+-   **Replay** : [Twitch](https://www.twitch.tv/videos/1149536227)
diff --git a/names/src/main/java/fr/craft/kata/Application.java b/names/src/main/java/fr/craft/kata/Application.java
new file mode 100644
index 0000000000000000000000000000000000000000..702dae653c168aaabc52697d89f25fad328789a6
--- /dev/null
+++ b/names/src/main/java/fr/craft/kata/Application.java
@@ -0,0 +1,23 @@
+package fr.craft.kata;
+
+import fr.craft.kata.application.UsersApplicationService;
+import fr.craft.kata.domain.Names;
+import fr.craft.kata.infrastructure.primary.JavaUsers;
+import fr.craft.kata.infrastructure.secondary.InMemoryUsersRepository;
+
+public class Application {
+
+  private JavaUsers users;
+
+  public void start() {
+    UsersApplicationService applicationService = new UsersApplicationService(
+        new InMemoryUsersRepository());
+
+    users = new JavaUsers(applicationService);
+  }
+
+  public Names getManagers() {
+    return users.managers();
+  }
+
+}
diff --git a/names/src/main/java/fr/craft/kata/application/UsersApplicationService.java b/names/src/main/java/fr/craft/kata/application/UsersApplicationService.java
new file mode 100644
index 0000000000000000000000000000000000000000..e60bb716d89be0668fdfe501dabc7b78e892765e
--- /dev/null
+++ b/names/src/main/java/fr/craft/kata/application/UsersApplicationService.java
@@ -0,0 +1,18 @@
+package fr.craft.kata.application;
+
+import fr.craft.kata.domain.Names;
+import fr.craft.kata.domain.UsersRepository;
+
+public class UsersApplicationService {
+
+  private final UsersRepository users;
+
+  public UsersApplicationService(UsersRepository users) {
+    this.users = users;
+  }
+
+  public Names managers() {
+    return users.managers();
+  }
+
+}
diff --git a/names/src/main/java/fr/craft/kata/domain/Firstname.java b/names/src/main/java/fr/craft/kata/domain/Firstname.java
new file mode 100644
index 0000000000000000000000000000000000000000..2d2eff9b383efaae2a464833b3200a35200c589a
--- /dev/null
+++ b/names/src/main/java/fr/craft/kata/domain/Firstname.java
@@ -0,0 +1,51 @@
+package fr.craft.kata.domain;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public record Firstname(String firstname)
+    implements Comparable<Firstname> {
+  private static final Pattern FIRSTNAME_ELEMENT = Pattern
+      .compile("([a-zA-Z]+)([^a-zA-Z]*)");
+
+  public Firstname(String firstname) {
+    assertFirstname(firstname);
+
+    this.firstname = buildFirstname(firstname);
+  }
+
+  private String buildFirstname(String firstname) {
+    Matcher matcher = FIRSTNAME_ELEMENT.matcher(firstname);
+
+    StringBuilder result = new StringBuilder();
+    while (matcher.find()) {
+      String name = matcher.group(1);
+
+      result.append(name.substring(0, 1)
+          .toUpperCase());
+
+      result.append(name.substring(1, name.length())
+          .toLowerCase());
+
+      result.append(matcher.group(2));
+    }
+
+    return result.toString();
+  }
+
+  private void assertFirstname(String firstname) {
+    if (firstname == null || firstname.isBlank()) {
+      throw new IllegalArgumentException(
+          "You must set a firstname");
+    }
+  }
+
+  public String get() {
+    return firstname();
+  }
+
+  @Override
+  public int compareTo(Firstname other) {
+    return firstname().compareTo(other.firstname());
+  }
+}
diff --git a/names/src/main/java/fr/craft/kata/domain/Lastname.java b/names/src/main/java/fr/craft/kata/domain/Lastname.java
new file mode 100644
index 0000000000000000000000000000000000000000..d004e3b1106c38e2132ac9c6d9b3b1e17580b5f6
--- /dev/null
+++ b/names/src/main/java/fr/craft/kata/domain/Lastname.java
@@ -0,0 +1,26 @@
+package fr.craft.kata.domain;
+
+public record Lastname(String lastname)
+    implements Comparable<Lastname> {
+  public Lastname(String lastname) {
+    assertLastname(lastname);
+
+    this.lastname = lastname.toUpperCase();
+  }
+
+  private void assertLastname(String lastname) {
+    if (lastname == null || lastname.isBlank()) {
+      throw new IllegalArgumentException(
+          "You can't have a null lastname");
+    }
+  }
+
+  public String get() {
+    return lastname();
+  }
+
+  @Override
+  public int compareTo(Lastname other) {
+    return lastname().compareTo(other.lastname());
+  }
+}
diff --git a/names/src/main/java/fr/craft/kata/domain/Name.java b/names/src/main/java/fr/craft/kata/domain/Name.java
new file mode 100644
index 0000000000000000000000000000000000000000..3d08e560527eb7cb4f6ae94a275d7f32aca45eec
--- /dev/null
+++ b/names/src/main/java/fr/craft/kata/domain/Name.java
@@ -0,0 +1,25 @@
+package fr.craft.kata.domain;
+
+import java.util.Comparator;
+
+public record Name(Firstname firstname, Lastname lastname)
+    implements Comparable<Name> {
+
+  private static final Comparator<Name> COMPARATOR = Comparator
+      .comparing(Name::firstname)
+      .thenComparing(Name::lastname);
+
+  public Name(String firstname, String lastname) {
+    this(new Firstname(firstname), new Lastname(lastname));
+  }
+
+  public String get() {
+    return firstname.get() + " " + lastname.get();
+  }
+
+  @Override
+  public int compareTo(Name other) {
+    return COMPARATOR.compare(this, other);
+  }
+
+}
diff --git a/names/src/main/java/fr/craft/kata/domain/Names.java b/names/src/main/java/fr/craft/kata/domain/Names.java
new file mode 100644
index 0000000000000000000000000000000000000000..df7146787b16b20b3e0491e0bcbdbbe4216d59d7
--- /dev/null
+++ b/names/src/main/java/fr/craft/kata/domain/Names.java
@@ -0,0 +1,27 @@
+package fr.craft.kata.domain;
+
+import java.util.List;
+
+public record Names(List<Name> names) {
+
+  public Names(Name... names) {
+    this(buildNames(names));
+  }
+
+  private static List<Name> buildNames(Name... names) {
+    if (names == null || names.length == 0) {
+      throw new IllegalArgumentException(
+          "Can't build without names");
+    }
+
+    return List.of(names)
+        .stream()
+        .sorted()
+        .toList();
+  }
+
+  public List<Name> get() {
+    return names();
+  }
+
+}
diff --git a/names/src/main/java/fr/craft/kata/domain/UsersRepository.java b/names/src/main/java/fr/craft/kata/domain/UsersRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..a78f74f268601d740f1bce13b0643cffaf6b8d05
--- /dev/null
+++ b/names/src/main/java/fr/craft/kata/domain/UsersRepository.java
@@ -0,0 +1,7 @@
+package fr.craft.kata.domain;
+
+public interface UsersRepository {
+
+  Names managers();
+
+}
diff --git a/names/src/main/java/fr/craft/kata/infrastructure/primary/JavaUsers.java b/names/src/main/java/fr/craft/kata/infrastructure/primary/JavaUsers.java
new file mode 100644
index 0000000000000000000000000000000000000000..8f83b7b0024f648af432aec5e6e311a4e18ae64f
--- /dev/null
+++ b/names/src/main/java/fr/craft/kata/infrastructure/primary/JavaUsers.java
@@ -0,0 +1,18 @@
+package fr.craft.kata.infrastructure.primary;
+
+import fr.craft.kata.application.UsersApplicationService;
+import fr.craft.kata.domain.Names;
+
+public class JavaUsers {
+
+  private final UsersApplicationService users;
+
+  public JavaUsers(UsersApplicationService users) {
+    this.users = users;
+  }
+
+  public Names managers() {
+    return users.managers();
+  }
+
+}
diff --git a/names/src/main/java/fr/craft/kata/infrastructure/secondary/InMemoryUsersRepository.java b/names/src/main/java/fr/craft/kata/infrastructure/secondary/InMemoryUsersRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..476a8e3cec32ae3614e983e2321ca492a05cbddb
--- /dev/null
+++ b/names/src/main/java/fr/craft/kata/infrastructure/secondary/InMemoryUsersRepository.java
@@ -0,0 +1,18 @@
+package fr.craft.kata.infrastructure.secondary;
+
+import java.util.List;
+
+import fr.craft.kata.domain.Name;
+import fr.craft.kata.domain.Names;
+import fr.craft.kata.domain.UsersRepository;
+
+public class InMemoryUsersRepository
+    implements UsersRepository {
+
+  @Override
+  public Names managers() {
+    return new Names(
+        List.of(new Name("jean-paul", "dupond")));
+  }
+
+}
diff --git a/names/src/test/java/fr/craft/kata/domain/FirstnameUnitTest.java b/names/src/test/java/fr/craft/kata/domain/FirstnameUnitTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9441b7c31fbed1fe34a646d4c7c3d37ac48ac424
--- /dev/null
+++ b/names/src/test/java/fr/craft/kata/domain/FirstnameUnitTest.java
@@ -0,0 +1,35 @@
+package fr.craft.kata.domain;
+
+import static org.assertj.core.api.Assertions.*;
+
+import org.junit.jupiter.api.Test;
+
+class FirstnameUnitTest {
+
+  @Test
+  void shouldNotBuildWihtoutFirstname() {
+    assertThatThrownBy(() -> new Firstname(null))
+        .isExactlyInstanceOf(IllegalArgumentException.class)
+        .hasMessageContaining("firstname");
+  }
+
+  @Test
+  void shouldNotBuildWihtBlankFirstname() {
+    assertThatThrownBy(() -> new Firstname(" "))
+        .isExactlyInstanceOf(IllegalArgumentException.class)
+        .hasMessageContaining("firstname");
+  }
+
+  @Test
+  void shouldCapitalizeSimpleFirstname() {
+    assertThat(new Firstname("jean").get())
+    .isEqualTo("Jean");
+  }
+
+  @Test
+  void shouldCapitalizeComposeFirstname() {
+    assertThat(new Firstname("jean PAUL-jacque").get())
+        .isEqualTo("Jean Paul-Jacque");
+  }
+
+}
diff --git a/names/src/test/java/fr/craft/kata/domain/LastnameUnitTest.java b/names/src/test/java/fr/craft/kata/domain/LastnameUnitTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..4b13c79743bb68175b7866d906e05a935fa8ab22
--- /dev/null
+++ b/names/src/test/java/fr/craft/kata/domain/LastnameUnitTest.java
@@ -0,0 +1,29 @@
+package fr.craft.kata.domain;
+
+import static org.assertj.core.api.Assertions.*;
+
+import org.junit.jupiter.api.Test;
+
+class LastnameUnitTest {
+
+  @Test
+  void shouldNotBuildWithoutLastname() {
+    assertThatThrownBy(() -> new Lastname(null))
+        .isExactlyInstanceOf(IllegalArgumentException.class)
+        .hasMessageContaining("lastname");
+  }
+
+  @Test
+  void shouldNotBuildWithBlankLastname() {
+    assertThatThrownBy(() -> new Lastname(" "))
+        .isExactlyInstanceOf(IllegalArgumentException.class)
+        .hasMessageContaining("lastname");
+  }
+
+  @Test
+  void shouldGetUpperCaseLastname() {
+    assertThat(new Lastname("Dupond").get())
+        .isEqualTo("DUPOND");
+  }
+
+}
diff --git a/names/src/test/java/fr/craft/kata/domain/NameUnitTest.java b/names/src/test/java/fr/craft/kata/domain/NameUnitTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..be854ea387fb99ff9d157d83386bb47b5117769e
--- /dev/null
+++ b/names/src/test/java/fr/craft/kata/domain/NameUnitTest.java
@@ -0,0 +1,30 @@
+package fr.craft.kata.domain;
+
+import static fr.craft.kata.domain.NamesFixture.*;
+import static org.assertj.core.api.Assertions.*;
+
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+class NameUnitTest {
+
+  @Test
+  void shouldGetFullName() {
+    Name name = jeanPaul();
+
+    assertThat(name.get()).isEqualTo("Jean-Paul DUPOND");
+  }
+
+  @Test
+  void shouldSortNames() {
+    Name colin = colin();
+    List<Name> names = List.of(jeanPaul(), colin)
+        .stream()
+        .sorted()
+        .toList();
+
+    assertThat(names).containsExactly(colin, jeanPaul());
+  }
+
+}
diff --git a/names/src/test/java/fr/craft/kata/domain/NamesFixture.java b/names/src/test/java/fr/craft/kata/domain/NamesFixture.java
new file mode 100644
index 0000000000000000000000000000000000000000..334515f80da0a99cbed47d603c18c0306b920aaa
--- /dev/null
+++ b/names/src/test/java/fr/craft/kata/domain/NamesFixture.java
@@ -0,0 +1,15 @@
+package fr.craft.kata.domain;
+
+public final class NamesFixture {
+  private NamesFixture() {
+  }
+
+  public static Name jeanPaul() {
+    return new Name("Jean-paul", "Dupond");
+  }
+
+  public static Name colin() {
+    return new Name("colin", "damon");
+  }
+
+}
diff --git a/names/src/test/java/fr/craft/kata/domain/NamesUnitTest.java b/names/src/test/java/fr/craft/kata/domain/NamesUnitTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9640a2f194befe0425ed986c6a9ce16331b8b0cf
--- /dev/null
+++ b/names/src/test/java/fr/craft/kata/domain/NamesUnitTest.java
@@ -0,0 +1,30 @@
+package fr.craft.kata.domain;
+
+import static fr.craft.kata.domain.NamesFixture.*;
+import static org.assertj.core.api.Assertions.*;
+
+import org.junit.jupiter.api.Test;
+
+class NamesUnitTest {
+
+  @Test
+  void shouldNotBuildWithNullName() {
+    assertThatThrownBy(() -> new Names((Name[]) null))
+        .isExactlyInstanceOf(IllegalArgumentException.class)
+        .hasMessageContaining("names");
+  }
+
+  @Test
+  void shouldNotBuildWithoutName() {
+    assertThatThrownBy(() -> new Names())
+        .isExactlyInstanceOf(IllegalArgumentException.class)
+        .hasMessageContaining("names");
+  }
+
+  @Test
+  void shouldGetSortedNames() {
+    assertThat(new Names(jeanPaul(), colin()).get())
+        .containsExactly(colin(), jeanPaul());
+  }
+
+}
diff --git a/names/src/test/java/fr/craft/kata/infrastructure/primary/PersonsComponentTest.java b/names/src/test/java/fr/craft/kata/infrastructure/primary/PersonsComponentTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..325f447a723c2758b156e1f8b8315b9642580078
--- /dev/null
+++ b/names/src/test/java/fr/craft/kata/infrastructure/primary/PersonsComponentTest.java
@@ -0,0 +1,27 @@
+package fr.craft.kata.infrastructure.primary;
+
+import static fr.craft.kata.domain.NamesFixture.*;
+import static org.assertj.core.api.Assertions.*;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import fr.craft.kata.Application;
+import fr.craft.kata.domain.Names;
+
+public class PersonsComponentTest {
+
+  private static final Application application = new Application();
+
+  @BeforeAll
+  static void startApplication() {
+    application.start();
+  }
+
+  @Test
+  void shouldGetUsers() {
+    assertThat(application.getManagers())
+        .isEqualTo(new Names(jeanPaul()));
+  }
+
+}
diff --git a/readme.md b/readme.md
index 26510f9806ec1c9bf6927e150a0c9051ba9b2962..fbf8314451f27fde268d227593d1ec7b45a6e4df 100644
--- a/readme.md
+++ b/readme.md
@@ -45,6 +45,7 @@ Un kata de code est un petit exercice pensé pour s'entrainer jusqu'à maitriser
 -   [Puzzles](java-puzzles)
 -   [Diamond](java-diamond)
 -   [Markov chain](markov-chain)
+-   [Names](names)
 
 ### Énervé