Skip to content
Snippets Groups Projects
Commit b82e0473 authored by Colin DAMON's avatar Colin DAMON
Browse files

Features order explaination

parent a9f2f95d
No related branches found
No related tags found
1 merge request!95Resolve "Names"
Showing
with 426 additions and 0 deletions
...@@ -41,3 +41,4 @@ include: ...@@ -41,3 +41,4 @@ include:
- local: "/diamond-ts/.gitlab-ci.yml" - local: "/diamond-ts/.gitlab-ci.yml"
- local: "/java-memoizers/.gitlab-ci.yml" - local: "/java-memoizers/.gitlab-ci.yml"
- local: "/markov-chain/.gitlab-ci.yml" - local: "/markov-chain/.gitlab-ci.yml"
- local: "/names/.gitlab-ci.yml"
package-names:
variables:
PROJECT_FOLDER: "names"
extends: .java
only:
refs:
- master
- merge_requests
changes:
- ".gitlab-common-ci.yml"
- "names/**/*"
<?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>
# 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)
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();
}
}
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();
}
}
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());
}
}
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());
}
}
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);
}
}
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();
}
}
package fr.craft.kata.domain;
public interface UsersRepository {
Names managers();
}
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();
}
}
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")));
}
}
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");
}
}
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");
}
}
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());
}
}
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");
}
}
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());
}
}
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()));
}
}
...@@ -45,6 +45,7 @@ Un kata de code est un petit exercice pensé pour s'entrainer jusqu'à maitriser ...@@ -45,6 +45,7 @@ Un kata de code est un petit exercice pensé pour s'entrainer jusqu'à maitriser
- [Puzzles](java-puzzles) - [Puzzles](java-puzzles)
- [Diamond](java-diamond) - [Diamond](java-diamond)
- [Markov chain](markov-chain) - [Markov chain](markov-chain)
- [Names](names)
### Énervé ### Énervé
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment