different projects for codurance
authorGustavo Martin Morcuende <gu.martinm@gmail.com>
Sun, 27 Nov 2016 15:52:24 +0000 (16:52 +0100)
committerGustavo Martin Morcuende <gu.martinm@gmail.com>
Sun, 27 Nov 2016 15:52:24 +0000 (16:52 +0100)
35 files changed:
TDD/sandromancuso/README.md [deleted file]
TDD/sandromancuso/pom.xml [deleted file]
TDD/sandromancuso/romannumbers/pom.xml [new file with mode: 0644]
TDD/sandromancuso/romannumbers/src/main/resources/log4j2.xml [new file with mode: 0644]
TDD/sandromancuso/romannumbers/src/main/resources/logback.xml [new file with mode: 0644]
TDD/sandromancuso/src/main/java/org/craftedsw/tripservicekata/TripService_Original.java [deleted file]
TDD/sandromancuso/src/main/java/org/craftedsw/tripservicekata/UserBuilder.java [deleted file]
TDD/sandromancuso/src/main/java/org/craftedsw/tripservicekata/exception/CollaboratorCallException.java [deleted file]
TDD/sandromancuso/src/main/java/org/craftedsw/tripservicekata/exception/UserNotLoggedInException.java [deleted file]
TDD/sandromancuso/src/main/java/org/craftedsw/tripservicekata/trip/Trip.java [deleted file]
TDD/sandromancuso/src/main/java/org/craftedsw/tripservicekata/trip/TripDAO.java [deleted file]
TDD/sandromancuso/src/main/java/org/craftedsw/tripservicekata/trip/TripService.java [deleted file]
TDD/sandromancuso/src/main/java/org/craftedsw/tripservicekata/user/User.java [deleted file]
TDD/sandromancuso/src/main/java/org/craftedsw/tripservicekata/user/UserSession.java [deleted file]
TDD/sandromancuso/src/main/resources/log4j2.xml [deleted file]
TDD/sandromancuso/src/main/resources/logback.xml [deleted file]
TDD/sandromancuso/src/test/java/org/craftedsw/tripservicekata/trip/TripDAOShould.java [deleted file]
TDD/sandromancuso/src/test/java/org/craftedsw/tripservicekata/trip/TripServiceShould.java [deleted file]
TDD/sandromancuso/src/test/java/org/craftedsw/tripservicekata/user/UserShould.java [deleted file]
TDD/sandromancuso/tripservice/README.md [new file with mode: 0644]
TDD/sandromancuso/tripservice/pom.xml [new file with mode: 0644]
TDD/sandromancuso/tripservice/src/main/java/org/craftedsw/tripservicekata/TripService_Original.java [new file with mode: 0644]
TDD/sandromancuso/tripservice/src/main/java/org/craftedsw/tripservicekata/UserBuilder.java [new file with mode: 0644]
TDD/sandromancuso/tripservice/src/main/java/org/craftedsw/tripservicekata/exception/CollaboratorCallException.java [new file with mode: 0644]
TDD/sandromancuso/tripservice/src/main/java/org/craftedsw/tripservicekata/exception/UserNotLoggedInException.java [new file with mode: 0644]
TDD/sandromancuso/tripservice/src/main/java/org/craftedsw/tripservicekata/trip/Trip.java [new file with mode: 0644]
TDD/sandromancuso/tripservice/src/main/java/org/craftedsw/tripservicekata/trip/TripDAO.java [new file with mode: 0644]
TDD/sandromancuso/tripservice/src/main/java/org/craftedsw/tripservicekata/trip/TripService.java [new file with mode: 0644]
TDD/sandromancuso/tripservice/src/main/java/org/craftedsw/tripservicekata/user/User.java [new file with mode: 0644]
TDD/sandromancuso/tripservice/src/main/java/org/craftedsw/tripservicekata/user/UserSession.java [new file with mode: 0644]
TDD/sandromancuso/tripservice/src/main/resources/log4j2.xml [new file with mode: 0644]
TDD/sandromancuso/tripservice/src/main/resources/logback.xml [new file with mode: 0644]
TDD/sandromancuso/tripservice/src/test/java/org/craftedsw/tripservicekata/trip/TripDAOShould.java [new file with mode: 0644]
TDD/sandromancuso/tripservice/src/test/java/org/craftedsw/tripservicekata/trip/TripServiceShould.java [new file with mode: 0644]
TDD/sandromancuso/tripservice/src/test/java/org/craftedsw/tripservicekata/user/UserShould.java [new file with mode: 0644]

diff --git a/TDD/sandromancuso/README.md b/TDD/sandromancuso/README.md
deleted file mode 100644 (file)
index 12e4c51..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-Sandro Mancuso: testing a refactoring legacy code
-
-Rules for refactoring legacy code.
-
-1. You may not change production code if not covered by tests. Before refactoring some legacy code we must write a Unit Test for it.
-
-   But some times for writing the test we must make modifications in the legacy code. If such modifications are required: just automated refactoring (via IDES) are allowed, if needed to write the test.
-
-
-Steps:
-
-1. Start testing the legacy code following the shortest branch.
-
-2. In Unit Test we should not invoke other classes but the one being under test (the other classes should be stub, mocke, etc, etc)
-
-3. When the legacy code is covered by a unit test we may refactor it (never before) We have to refactor our legacy code from the deepest to the shortest branch.
-
diff --git a/TDD/sandromancuso/pom.xml b/TDD/sandromancuso/pom.xml
deleted file mode 100644 (file)
index 91ce619..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-<?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>
-    <groupId>org.craftedsw</groupId>
-    <artifactId>sandromancuso</artifactId>
-    <packaging>jar</packaging>
-    <version>1.0-SNAPSHOT</version>
-    <name>tdd-by-example</name>
-    <url>http://gumartinm.name</url>
-    <description>TDD by example</description>
-    <organization>
-        <name>Gustavo Martin Morcuende</name>
-        <url>http://www.gumartinm.name</url>
-    </organization>
-    <scm>
-        <developerConnection>scm:git:http://git.gumartinm.name/TDDbyExample</developerConnection>
-        <url>http://git.gumartinm.name/TDDbyExample</url>
-    </scm>
-    <properties>
-        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    </properties>
-    <dependencies>
-        <!--
-        **************************************************************************************************************************
-            1. LOGBACK: SLF4J NATIVE IMPLEMENTATION. See: http://logback.qos.ch/
-        **************************************************************************************************************************
-        -->
-        <!--
-            1/1 Required dependency for native implementation (nothing else is required)
-
-            Native implementation. There are also SLF4J bindings external to the SLF4J project, e.g. logback which implements
-            SLF4Jnatively. Logback's ch.qos.logback.classic.Logger class is a direct implementation of SLF4J's org.slf4j.Logger
-            interface. Thus, using SLF4J in conjunction with logback involves strictly zero memory and computational overhead.
-            see: http://www.slf4j.org/manual.html
-        -->
-        <dependency>
-            <groupId>ch.qos.logback</groupId>
-            <artifactId>logback-classic</artifactId>
-            <version>1.1.2</version>
-        </dependency>
-        <!--
-        **************************************************************************************************************************
-            2. SLF4J AND LOG4J 2. See: http://logging.apache.org/log4j/2.x/
-        **************************************************************************************************************************
-        -->
-
-        <!--
-            1/2 Required dependency for log4j 2 with slf4j: binding
-        <dependency>
-            <groupId>org.apache.logging.log4j</groupId>
-            <artifactId>log4j-slf4j-impl</artifactId>
-            <version>2.0-rc1</version>
-        </dependency>
-        -->
-        <!--
-            2/2 Required dependency for log4j 2 with slf4j: log4j 2 maven plugin
-        <dependency>
-            <groupId>org.apache.logging.log4j</groupId>
-            <artifactId>log4j-core</artifactId>
-            <version>2.0-rc1</version>
-        </dependency>
-        -->
-        <dependency>
-               <groupId>javax.inject</groupId>
-               <artifactId>javax.inject</artifactId>
-               <version>1</version>
-               </dependency>
-
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <version>4.12-beta-1</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-               <groupId>org.mockito</groupId>
-               <artifactId>mockito-core</artifactId>
-               <version>2.0.31-beta</version>
-               <scope>test</scope>
-               </dependency>
-    </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <version>3.1</version>
-                <configuration>
-                    <source>1.8</source>
-                    <target>1.8</target>
-                                       <!--
-                                       <source>1.6</source>
-                    <target>1.6</target>
-                    -->
-                    <encoding>${project.build.sourceEncoding}</encoding>
-                    <compilerArgument>-Xlint:deprecation</compilerArgument>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-resources-plugin</artifactId>
-                <version>2.6</version>
-                <configuration>
-                    <encoding>${project.build.sourceEncoding}</encoding>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-surefire-plugin</artifactId>
-                <version>2.17</version>
-                <!--
-                Trying autodetection, see: http://maven.apache.org/surefire/maven-surefire-plugin/examples/junit.html
-                <dependencies>
-                    <dependency>
-                        <groupId>org.apache.maven.surefire</groupId>
-                        <artifactId>surefire-junit47</artifactId>
-                        <version>2.17</version>
-                    </dependency>
-                </dependencies>
-                -->
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-jar-plugin</artifactId>
-                <version>2.3.1</version>
-                <configuration>
-                    <archive>
-                        <manifestEntries>
-                            <Specification-Title>${project.description}</Specification-Title>
-                            <Specification-Version>${project.version}</Specification-Version>
-                            <Specification-Vendor>${project.organization.name}</Specification-Vendor>
-                            <Implementation-Title>${project.description}</Implementation-Title>
-                            <Implementation-Version>${project.version}</Implementation-Version>
-                            <Implementation-Vendor>${project.organization.name}</Implementation-Vendor>
-                        </manifestEntries>
-                    </archive>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-       <reporting>
-        <plugins>
-            <plugin>
-                               <!--
-                               <groupId>org.jacoco</groupId>
-                       <artifactId>jacoco</artifactId>
-                       <version>0.7.2.201409121644</version>
-                               -->
-                       <groupId>org.codehaus.mojo</groupId>
-                       <artifactId>cobertura-maven-plugin</artifactId>
-                       <version>2.6</version>
-                       </plugin>
-               </plugins>
-       </reporting>
-</project>
diff --git a/TDD/sandromancuso/romannumbers/pom.xml b/TDD/sandromancuso/romannumbers/pom.xml
new file mode 100644 (file)
index 0000000..da85916
--- /dev/null
@@ -0,0 +1,158 @@
+<?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>
+    <groupId>org.craftedsw</groupId>
+    <artifactId>romannumbers</artifactId>
+    <packaging>jar</packaging>
+    <version>1.0-SNAPSHOT</version>
+    <name>romannumbers</name>
+    <url>http://gumartinm.name</url>
+    <description>TDD codurance</description>
+    <organization>
+        <name>Gustavo Martin Morcuende</name>
+        <url>http://www.gumartinm.name</url>
+    </organization>
+    <scm>
+        <developerConnection>scm:git:http://git.gumartinm.name/TDDbyExample</developerConnection>
+        <url>http://git.gumartinm.name/TDDbyExample</url>
+    </scm>
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+    <dependencies>
+        <!--
+        **************************************************************************************************************************
+            1. LOGBACK: SLF4J NATIVE IMPLEMENTATION. See: http://logback.qos.ch/
+        **************************************************************************************************************************
+        -->
+        <!--
+            1/1 Required dependency for native implementation (nothing else is required)
+
+            Native implementation. There are also SLF4J bindings external to the SLF4J project, e.g. logback which implements
+            SLF4Jnatively. Logback's ch.qos.logback.classic.Logger class is a direct implementation of SLF4J's org.slf4j.Logger
+            interface. Thus, using SLF4J in conjunction with logback involves strictly zero memory and computational overhead.
+            see: http://www.slf4j.org/manual.html
+        -->
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <version>1.1.2</version>
+        </dependency>
+        <!--
+        **************************************************************************************************************************
+            2. SLF4J AND LOG4J 2. See: http://logging.apache.org/log4j/2.x/
+        **************************************************************************************************************************
+        -->
+
+        <!--
+            1/2 Required dependency for log4j 2 with slf4j: binding
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-slf4j-impl</artifactId>
+            <version>2.0-rc1</version>
+        </dependency>
+        -->
+        <!--
+            2/2 Required dependency for log4j 2 with slf4j: log4j 2 maven plugin
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-core</artifactId>
+            <version>2.0-rc1</version>
+        </dependency>
+        -->
+        <dependency>
+               <groupId>javax.inject</groupId>
+               <artifactId>javax.inject</artifactId>
+               <version>1</version>
+               </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.12-beta-1</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+               <groupId>org.mockito</groupId>
+               <artifactId>mockito-core</artifactId>
+               <version>2.0.31-beta</version>
+               <scope>test</scope>
+               </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.1</version>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                                       <!--
+                                       <source>1.6</source>
+                    <target>1.6</target>
+                    -->
+                    <encoding>${project.build.sourceEncoding}</encoding>
+                    <compilerArgument>-Xlint:deprecation</compilerArgument>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-resources-plugin</artifactId>
+                <version>2.6</version>
+                <configuration>
+                    <encoding>${project.build.sourceEncoding}</encoding>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>2.17</version>
+                <!--
+                Trying autodetection, see: http://maven.apache.org/surefire/maven-surefire-plugin/examples/junit.html
+                <dependencies>
+                    <dependency>
+                        <groupId>org.apache.maven.surefire</groupId>
+                        <artifactId>surefire-junit47</artifactId>
+                        <version>2.17</version>
+                    </dependency>
+                </dependencies>
+                -->
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>2.3.1</version>
+                <configuration>
+                    <archive>
+                        <manifestEntries>
+                            <Specification-Title>${project.description}</Specification-Title>
+                            <Specification-Version>${project.version}</Specification-Version>
+                            <Specification-Vendor>${project.organization.name}</Specification-Vendor>
+                            <Implementation-Title>${project.description}</Implementation-Title>
+                            <Implementation-Version>${project.version}</Implementation-Version>
+                            <Implementation-Vendor>${project.organization.name}</Implementation-Vendor>
+                        </manifestEntries>
+                    </archive>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+       <reporting>
+        <plugins>
+            <plugin>
+                               <!--
+                               <groupId>org.jacoco</groupId>
+                       <artifactId>jacoco</artifactId>
+                       <version>0.7.2.201409121644</version>
+                               -->
+                       <groupId>org.codehaus.mojo</groupId>
+                       <artifactId>cobertura-maven-plugin</artifactId>
+                       <version>2.6</version>
+                       </plugin>
+               </plugins>
+       </reporting>
+</project>
diff --git a/TDD/sandromancuso/romannumbers/src/main/resources/log4j2.xml b/TDD/sandromancuso/romannumbers/src/main/resources/log4j2.xml
new file mode 100644 (file)
index 0000000..2de3fd2
--- /dev/null
@@ -0,0 +1,197 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    * name: The name of the configuration.
+    * dest: Either "err", which will send output to stderr, or a file path or URL.
+    * status: The level of internal Log4j events that should be logged to the console. Valid values for this attribute are "trace",
+      "debug", "info", "warn", "error" and "fatal". Log4j will log details about initialization, rollover and other internal
+      actions to the status logger.
+    * strict: Enables the use of the strict XML format. Not supported in JSON configurations.
+    * monitorInterval: If the monitorInterval attribute is specified on the configuration element and is set to a non-zero value
+      then the file will be checked the next time a log event is evaluated and/or logged and the monitorInterval has elapsed
+      since the last check.
+    * packages: A comma separated list of package names to search for plugins. Plugins are only loaded once per classloader so
+      changing this value may not have any effect upon reconfiguration.
+-->
+<Configuration name="XMLConfigTest" dest="err" status="trace" strict="true" monitorInterval="30" packages="org.apache.logging.log4j.test">
+    <!--
+        Log4j 2 supports the ability to specify tokens in the configuration as references to properties defined elsewhere. Some of
+        these properties will be resolved when the configuration file is interpreted while others may be passed to components
+        where they will be evaluated at runtime.
+    -->
+    <Properties>
+        <Property name="filename">target/fileappender.log</Property>
+        <Property name="filerandomname">target/filerandomappender.log</Property>
+    </Properties>
+
+    <!--
+         Filters may be configured in one of four locations:
+
+        Context-wide Filters are configured directly in the configuration. Events that are rejected by these filters
+        will not be passed to loggers for further processing. Once an event has been accepted by a Context-wide filter it will not be evaluated by any other Context-wide Filters nor will the Logger's Level be used to filter the event. The event will be evaluated by Logger and Appender Filters however.
+    Logger Filters are configured on a specified Logger. These are evaluated after the Context-wide Filters and the Log Level for the Logger. Events that are rejected by these filters will be discarded and the event will not be passed to a parent Logger regardless of the additivity setting.
+    Appender Filters are used to determine if a specific Appender should handle the formatting and publication of the event.
+    Appender Reference Filters are used to determine if a Logger should route the event to an appender.
+
+    <Filter type="ThresholdFilter" level="debug"/>
+    -->
+    
+    <Appenders>
+        <Appender type="Console" name="STDOUT">
+            <!--
+            <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
+            -->
+            <Filter type="ThresholdFilter" level="trace"/>
+            <!--
+            <Layout type="PatternLayout" pattern="%d{ABSOLUTE} %5p %c{1}:%L %m%n"/>
+            -->
+            <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx - %X{id} %X{name} %X{surname}%n"/>
+            <!--  
+            <Filters>
+                See: FlowTracingExample class in this project.
+                <Filter type="MarkerFilter" marker="FLOW" onMatch="ENTER" onMismatch="NEUTRAL"/>
+                <Filter type="MarkerFilter" marker="EXCEPTION" onMatch="CATCHING" onMismatch="ACCEPT"/>
+                
+                See: MarkersExample class in this project.
+                ¿Cómo usar esto cuando hago logger.debug(QUERY_MARKER, "SELECT * FROM {}", table);?
+                ¿Sería marker="DEBUG"?
+                <Filter type="MarkerFilter" marker="FLOW" onMatch="SQL_UPDATE" onMismatch="NEUTRAL"/>
+                <Filter type="MarkerFilter" marker="EXCEPTION" onMatch="SQL_QUERY" onMismatch="ACCEPT"/>
+            </Filters>
+            -->
+        </Appender>
+        <Appender type="Console" name="FLOW">
+            <Layout type="PatternLayout" pattern="%C{1}.%M %m %ex%n"/><!-- class and line number -->
+            <Filters>
+                <Filter type="MarkerFilter" marker="FLOW" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
+                <Filter type="MarkerFilter" marker="EXCEPTION" onMatch="ACCEPT" onMismatch="DENY"/>
+            </Filters>
+        </Appender>
+        <!--
+            ¿Puedo mezclar bufferedIO=true con immediateFlush=true?
+            LOG4J 1.2: bufferedIO="false" immediateFlush="true" (es como se ejecuta actualmente la N2A)
+            JUGAR CON ESOS 2 VALORES A VER QUE TAL... :/
+        -->
+        <Appender type="File" name="FileAppender" fileName="${filename}" bufferedIO="false" immediateFlush="true" append="true">
+            <Layout type="PatternLayout">
+                <!--
+                <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
+                -->
+                <Pattern>"%d{yyyyMMddHHmmssSSS} - %-5p - [%t] - %m%n"</Pattern>
+                <Charset>UTF-8</Charset> 
+            </Layout>
+        </Appender>
+         <!--
+           * Asynchronous Loggers are a new addition to Log4j 2. Their aim is to return from the call to Logger.log to the application
+             as soon as possible. You can choose between making all Loggers asynchronous or using a mixture of synchronous and asynchronous
+             Loggers. Making all Loggers asynchronous will give the best performance, while mixing gives you more flexibility.
+           * LMAX Disruptor technology. Asynchronous Loggers internally use the Disruptor, a lock-free inter-thread communication library,
+             instead of queues, resulting in higher throughput and lower latency.
+           * Asynchronous Appenders already existed in Log4j 1.x, but have been enhanced to flush to disk at the end of a batch
+             (when the queue is empty). This produces the same result as configuring "immediateFlush=true", that is, all received log events
+             are always available on disk, but is more efficient because it does not need to touch the disk on each and every log event.
+             (Async Appenders use ArrayBlockingQueue internally and do not need the disruptor jar on the classpath.)
+           * (For synchronous and asynchronous use) Random Access File Appenders are an alternative to Buffered File Appenders. Under the hood,
+             these new appenders use a ByteBuffer + RandomAccessFile instead of a BufferedOutputStream. In our testing this was about 20-200%
+             faster. These appenders can also be used with synchronous loggers and will give the same performance benefits. Random Access
+             File Appenders do not need the disruptor jar on the classpath.
+        -->
+        <!-- El random access file siempre es con buffer!!!
+             When set to true - the default, each write will be followed by a flush. This will guarantee the data is written
+             to disk but could impact performance.
+
+             Flushing after every write is only useful when using this appender with synchronous loggers. Asynchronous loggers
+             and appenders will automatically flush at the end of a batch of events, even if immediateFlush is set to false.
+             This also guarantees the data is written to disk but is more efficient. 
+        -->
+        <Appender type="RandomAccessFile" name="RandomAccessFileAppender" fileName="${filerandomname}" immediateFlush="true" append="true">
+            <Layout type="PatternLayout">
+                <Pattern>"%d{yyyyMMddHHmmssSSS} - %-5p - [%t] - %m%n"</Pattern>
+                <Charset>UTF-8</Charset> 
+            </Layout>
+        </Appender>
+        <!--
+            El AsyncAppender siempre es bufferado y hace siempre un immediateFlush ¿independientemente del appender ref? SÍ, mira:
+
+            Mejor usar includeLocation=false proque el AsyncAppender siempre debe hacer la localización del log (nombre de clase, método y línea)
+            independientemente de si luego se va a loguear o no (porque haya filtros por ejemplo) Esto es así porque el asyncappender
+            debe generar toda la info necesaria antes de pasar esta info a la cola. Una vez en la cola asíncrona esa info ya no puede
+            ser generada. Por tanto, aunque ese log finalmente no se use, siempre se pone en la cola asíncrona con todos sus datos.
+
+            Extracting location is an expensive operation (it can make logging 5 - 20 times slower). To improve performance, location
+            is not included by default when adding a log event to the queue. You can change this by setting includeLocation="true".
+            Para extraer la localización al parecer hay que recorrer el stacktrace por eso es una operacion pesada.
+        -->
+        <Appender type="Async" name="AsyncAppender" blocking="true" bufferSize="128" errorRef="FileAppender" ignoreExceptions="false" includeLocation="false">
+                <!--
+                Probar las dos configuraciones
+                <AppenderRef ref="RandomAccessFileAppender"/>
+                -->
+                <AppenderRef ref="FileAppender"/>
+        </Appender>
+
+    </Appenders>
+     
+    <Loggers>
+        <!--
+        <Logger name="de.loggers.test" level="debug" additivity="false">
+            <Filter type="ThreadContextMapFilter">
+                <KeyValuePair key="test" value="123"/>
+            </Filter>
+            <AppenderRef ref="STDOUT"/>
+        </Logger>
+        -->
+    
+        <!-- 
+        <Logger name="de.loggers.test" level="debug" additivity="false">
+            <AppenderRef ref="File"/>
+        </Logger>
+        -->
+
+        <Logger name="de.loggers.test.simple" level="TRACE">
+            <!--
+              * Because THIS logger has additivity="true" by default THIS logger will use the same appender as its parent's logger,
+                which in this case is the logger Root.
+              * Because THIS logger has additivity="true" by default if we use this AppenderRef we will see for
+                classes in de.loggers.test.simple the same messages twice. One from this logger and one from its parent's logger,
+                which in this case is the logger Root.
+            <AppenderRef ref="STDOUT"/>
+            -->
+        </Logger>
+        <Logger name="de.loggers.test.formatter" level="TRACE" additivity="false">
+            <!--
+              * Because THIS logger has additivity="false" THIS logger will not use the same appender as its parent's logger.
+            -->
+            <AppenderRef ref="STDOUT"/>
+        </Logger>
+        <!--
+            By default, location is not passed to the I/O thread by asynchronous loggers. If one of your layouts or custom
+            filters needs location information, you need to set "includeLocation=true" in the configuration of all relevant loggers,
+            including the root logger.
+        -->
+
+
+
+        <!--
+           * Asynchronous Loggers are a new addition to Log4j 2. Their aim is to return from the call to Logger.log to the application
+             as soon as possible. You can choose between making all Loggers asynchronous or using a mixture of synchronous and asynchronous
+             Loggers. Making all Loggers asynchronous will give the best performance, while mixing gives you more flexibility.
+           * LMAX Disruptor technology. Asynchronous Loggers internally use the Disruptor, a lock-free inter-thread communication library,
+             instead of queues, resulting in higher throughput and lower latency.
+           * Asynchronous Appenders already existed in Log4j 1.x, but have been enhanced to flush to disk at the end of a batch
+             (when the queue is empty). This produces the same result as configuring "immediateFlush=true", that is, all received log events
+             are always available on disk, but is more efficient because it does not need to touch the disk on each and every log event.
+             (Async Appenders use ArrayBlockingQueue internally and do not need the disruptor jar on the classpath.)
+           * (For synchronous and asynchronous use) Random Access File Appenders are an alternative to Buffered File Appenders. Under the hood,
+             these new appenders use a ByteBuffer + RandomAccessFile instead of a BufferedOutputStream. In our testing this was about 20-200%
+             faster. These appenders can also be used with synchronous loggers and will give the same performance benefits. Random Access
+             File Appenders do not need the disruptor jar on the classpath.
+        -->
+        <AsyncLogger name="de.loggers.test.loggernames" level="TRACE" includeLocation="false">
+            <AppenderRef ref="RandomAccessFileAppender"/>
+        </AsyncLogger>
+        <Root level="TRACE">
+            <AppenderRef ref="STDOUT"/>
+        </Root>
+    </Loggers>
+     
+</Configuration>
diff --git a/TDD/sandromancuso/romannumbers/src/main/resources/logback.xml b/TDD/sandromancuso/romannumbers/src/main/resources/logback.xml
new file mode 100644 (file)
index 0000000..685c34c
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- For assistance related to logback-translator or configuration  -->
+<!-- files in general, please contact the logback user mailing list -->
+<!-- at http://www.qos.ch/mailman/listinfo/logback-user             -->
+<!--                                                                -->
+<!-- For professional support please see                            -->
+<!--    http://www.qos.ch/shop/products/professionalSupport         -->
+<!--                                                                -->
+<configuration>
+  <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+      <pattern>%d{yyyyMMddHHmmssSSS} - %-5p - [%t] - [%C] - %m%n</pattern>
+    </encoder>
+  </appender>
+  <root level="INFO">
+    <appender-ref ref="stdout"/>
+  </root>
+</configuration>
diff --git a/TDD/sandromancuso/src/main/java/org/craftedsw/tripservicekata/TripService_Original.java b/TDD/sandromancuso/src/main/java/org/craftedsw/tripservicekata/TripService_Original.java
deleted file mode 100644 (file)
index a2ba5ee..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-package org.craftedsw.tripservicekata;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.craftedsw.tripservicekata.exception.UserNotLoggedInException;
-import org.craftedsw.tripservicekata.trip.Trip;
-import org.craftedsw.tripservicekata.trip.TripDAO;
-import org.craftedsw.tripservicekata.user.User;
-import org.craftedsw.tripservicekata.user.UserSession;
-
-public class TripService_Original {
-
-       public List<Trip> getTripsByUser(User user) throws UserNotLoggedInException {
-               List<Trip> tripList = new ArrayList<Trip>();
-               User loggedUser = UserSession.getInstance().getLoggedUser();
-               boolean isFriend = false;
-               if (loggedUser != null) {
-                       for (User friend : user.getFriends()) {
-                               if (friend.equals(loggedUser)) {
-                                       isFriend = true;
-                                       break;
-                               }
-                       }
-                       if (isFriend) {
-                               tripList = TripDAO.findTripsByUser(user);
-                       }
-                       return tripList;
-               } else {
-                       throw new UserNotLoggedInException();
-               }
-       }
-       
-}
diff --git a/TDD/sandromancuso/src/main/java/org/craftedsw/tripservicekata/UserBuilder.java b/TDD/sandromancuso/src/main/java/org/craftedsw/tripservicekata/UserBuilder.java
deleted file mode 100644 (file)
index 8f95bc9..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.craftedsw.tripservicekata;
-
-import org.craftedsw.tripservicekata.trip.Trip;
-import org.craftedsw.tripservicekata.user.User;
-
-public class UserBuilder {
-       private User[] friends = new User[]{};
-       private Trip[] trips = new Trip[]{};
-       
-       public static UserBuilder aUser() {
-               return new UserBuilder();
-       }
-
-       public UserBuilder withTrips(Trip...trips) {
-               this.trips  = trips;
-               return this;
-       }
-
-       public UserBuilder friendsWith(User...friends) {
-               this.friends = friends;
-               return this;
-       }
-       
-       public User build() {
-               User user = new User();
-               addTripsTo(user);
-               addFriendsTo(user);
-               return user;
-       }
-
-       private void addFriendsTo(User user) {
-               for (User friend : friends) {
-                       user.addFriend(friend);
-               }               
-       }
-
-       private void addTripsTo(User user) {
-               for (Trip trip : trips) {
-                       user.addTrip(trip);
-               }
-       }
-}
diff --git a/TDD/sandromancuso/src/main/java/org/craftedsw/tripservicekata/exception/CollaboratorCallException.java b/TDD/sandromancuso/src/main/java/org/craftedsw/tripservicekata/exception/CollaboratorCallException.java
deleted file mode 100644 (file)
index 828353e..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.craftedsw.tripservicekata.exception;
-
-public class CollaboratorCallException extends RuntimeException {
-
-       private static final long serialVersionUID = -4584041339906109902L;
-
-       public CollaboratorCallException() {
-               super();
-       }
-
-       public CollaboratorCallException(String message,
-                       Throwable cause) {
-               super(message, cause);
-       }
-
-       public CollaboratorCallException(String message) {
-               super(message);
-       }
-
-       public CollaboratorCallException(Throwable cause) {
-               super(cause);
-       }
-
-       
-}
diff --git a/TDD/sandromancuso/src/main/java/org/craftedsw/tripservicekata/exception/UserNotLoggedInException.java b/TDD/sandromancuso/src/main/java/org/craftedsw/tripservicekata/exception/UserNotLoggedInException.java
deleted file mode 100644 (file)
index 880bf20..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.craftedsw.tripservicekata.exception;
-
-public class UserNotLoggedInException extends RuntimeException {
-
-       private static final long serialVersionUID = 8959479918185637340L;
-
-}
diff --git a/TDD/sandromancuso/src/main/java/org/craftedsw/tripservicekata/trip/Trip.java b/TDD/sandromancuso/src/main/java/org/craftedsw/tripservicekata/trip/Trip.java
deleted file mode 100644 (file)
index f12ff3c..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-package org.craftedsw.tripservicekata.trip;
-
-public class Trip {
-
-}
diff --git a/TDD/sandromancuso/src/main/java/org/craftedsw/tripservicekata/trip/TripDAO.java b/TDD/sandromancuso/src/main/java/org/craftedsw/tripservicekata/trip/TripDAO.java
deleted file mode 100644 (file)
index ab859ed..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.craftedsw.tripservicekata.trip;
-
-import java.util.List;
-
-import org.craftedsw.tripservicekata.exception.CollaboratorCallException;
-import org.craftedsw.tripservicekata.user.User;
-
-public class TripDAO {
-
-       public static List<Trip> findTripsByUser(User user) {
-               throw new CollaboratorCallException(
-                               "TripDAO should not be invoked on an unit test.");
-       }
-
-       // At the end and by means of many code refactoring our app
-       // will end up using the instance method. In the meanwhile we
-       // will not be able to remove the static method but at least
-       // we are offering something that can be tested.
-       // Be careful when refactoring this code because in real life
-       // findTripsByUser for sure will be used in many places but again
-       // in the meanwhile with this code we can write unit tests (we
-       // always need to write a test of our legacy code before refactoring it)
-       public List<Trip> tripsBy(User user) {
-               return TripDAO.findTripsByUser(user);
-       }
-       
-}
\ No newline at end of file
diff --git a/TDD/sandromancuso/src/main/java/org/craftedsw/tripservicekata/trip/TripService.java b/TDD/sandromancuso/src/main/java/org/craftedsw/tripservicekata/trip/TripService.java
deleted file mode 100644 (file)
index 276710f..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.craftedsw.tripservicekata.trip;\r
-\r
-import java.util.ArrayList;\r
-import java.util.List;\r
-\r
-import javax.inject.Inject;\r
-\r
-import org.craftedsw.tripservicekata.exception.UserNotLoggedInException;\r
-import org.craftedsw.tripservicekata.user.User;\r
-\r
-public class TripService {\r
-       \r
-       private final TripDAO tripDAO;\r
-\r
-       @Inject\r
-       public TripService(TripDAO tripDAO) {\r
-               this.tripDAO = tripDAO;\r
-       }\r
-\r
-       public List<Trip> getTripsByUser(User user, User loggedInUser) throws UserNotLoggedInException {\r
-               validate(loggedInUser);\r
-               \r
-               return user.isFriendsWith(loggedInUser)\r
-                               ? tripsBy(user)\r
-                           : noTrips();\r
-       }\r
-\r
-       private void validate(User loggedInUser) {\r
-               if (loggedInUser == null) {\r
-                       throw new UserNotLoggedInException();\r
-               }\r
-       }\r
-\r
-       private ArrayList<Trip> noTrips() {\r
-               return new ArrayList<>();\r
-       }\r
-\r
-       private List<Trip> tripsBy(User user) {\r
-               return tripDAO.tripsBy(user);\r
-       }\r
-}\r
diff --git a/TDD/sandromancuso/src/main/java/org/craftedsw/tripservicekata/user/User.java b/TDD/sandromancuso/src/main/java/org/craftedsw/tripservicekata/user/User.java
deleted file mode 100644 (file)
index d038fe8..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-package org.craftedsw.tripservicekata.user;\r
-\r
-import java.util.ArrayList;\r
-import java.util.List;\r
-\r
-import org.craftedsw.tripservicekata.trip.Trip;\r
-\r
-public class User {\r
-\r
-       private List<Trip> trips = new ArrayList<Trip>();\r
-       private List<User> friends = new ArrayList<User>();\r
-       \r
-       public List<User> getFriends() {\r
-               return friends;\r
-       }\r
-       \r
-       public void addFriend(User user) {\r
-               friends.add(user);\r
-       }\r
-\r
-       public void addTrip(Trip trip) {\r
-               trips.add(trip);\r
-       }\r
-       \r
-       public List<Trip> trips() {\r
-               return trips;\r
-       }\r
-\r
-       public boolean isFriendsWith(User anotherUser) {\r
-               return friends.contains(anotherUser);\r
-       }\r
-\r
-}\r
diff --git a/TDD/sandromancuso/src/main/java/org/craftedsw/tripservicekata/user/UserSession.java b/TDD/sandromancuso/src/main/java/org/craftedsw/tripservicekata/user/UserSession.java
deleted file mode 100644 (file)
index 6b91c0d..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.craftedsw.tripservicekata.user;
-
-import org.craftedsw.tripservicekata.exception.CollaboratorCallException;
-
-public class UserSession {
-
-       private static final UserSession userSession = new UserSession();
-       
-       private UserSession() {
-       }
-       
-       public static UserSession getInstance() {
-               return userSession;
-       }
-
-       public User getLoggedUser() {
-               throw new CollaboratorCallException(
-                               "UserSession.getLoggedUser() should not be called in an unit test");
-       }
-
-}
diff --git a/TDD/sandromancuso/src/main/resources/log4j2.xml b/TDD/sandromancuso/src/main/resources/log4j2.xml
deleted file mode 100644 (file)
index 2de3fd2..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    * name: The name of the configuration.
-    * dest: Either "err", which will send output to stderr, or a file path or URL.
-    * status: The level of internal Log4j events that should be logged to the console. Valid values for this attribute are "trace",
-      "debug", "info", "warn", "error" and "fatal". Log4j will log details about initialization, rollover and other internal
-      actions to the status logger.
-    * strict: Enables the use of the strict XML format. Not supported in JSON configurations.
-    * monitorInterval: If the monitorInterval attribute is specified on the configuration element and is set to a non-zero value
-      then the file will be checked the next time a log event is evaluated and/or logged and the monitorInterval has elapsed
-      since the last check.
-    * packages: A comma separated list of package names to search for plugins. Plugins are only loaded once per classloader so
-      changing this value may not have any effect upon reconfiguration.
--->
-<Configuration name="XMLConfigTest" dest="err" status="trace" strict="true" monitorInterval="30" packages="org.apache.logging.log4j.test">
-    <!--
-        Log4j 2 supports the ability to specify tokens in the configuration as references to properties defined elsewhere. Some of
-        these properties will be resolved when the configuration file is interpreted while others may be passed to components
-        where they will be evaluated at runtime.
-    -->
-    <Properties>
-        <Property name="filename">target/fileappender.log</Property>
-        <Property name="filerandomname">target/filerandomappender.log</Property>
-    </Properties>
-
-    <!--
-         Filters may be configured in one of four locations:
-
-        Context-wide Filters are configured directly in the configuration. Events that are rejected by these filters
-        will not be passed to loggers for further processing. Once an event has been accepted by a Context-wide filter it will not be evaluated by any other Context-wide Filters nor will the Logger's Level be used to filter the event. The event will be evaluated by Logger and Appender Filters however.
-    Logger Filters are configured on a specified Logger. These are evaluated after the Context-wide Filters and the Log Level for the Logger. Events that are rejected by these filters will be discarded and the event will not be passed to a parent Logger regardless of the additivity setting.
-    Appender Filters are used to determine if a specific Appender should handle the formatting and publication of the event.
-    Appender Reference Filters are used to determine if a Logger should route the event to an appender.
-
-    <Filter type="ThresholdFilter" level="debug"/>
-    -->
-    
-    <Appenders>
-        <Appender type="Console" name="STDOUT">
-            <!--
-            <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
-            -->
-            <Filter type="ThresholdFilter" level="trace"/>
-            <!--
-            <Layout type="PatternLayout" pattern="%d{ABSOLUTE} %5p %c{1}:%L %m%n"/>
-            -->
-            <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx - %X{id} %X{name} %X{surname}%n"/>
-            <!--  
-            <Filters>
-                See: FlowTracingExample class in this project.
-                <Filter type="MarkerFilter" marker="FLOW" onMatch="ENTER" onMismatch="NEUTRAL"/>
-                <Filter type="MarkerFilter" marker="EXCEPTION" onMatch="CATCHING" onMismatch="ACCEPT"/>
-                
-                See: MarkersExample class in this project.
-                ¿Cómo usar esto cuando hago logger.debug(QUERY_MARKER, "SELECT * FROM {}", table);?
-                ¿Sería marker="DEBUG"?
-                <Filter type="MarkerFilter" marker="FLOW" onMatch="SQL_UPDATE" onMismatch="NEUTRAL"/>
-                <Filter type="MarkerFilter" marker="EXCEPTION" onMatch="SQL_QUERY" onMismatch="ACCEPT"/>
-            </Filters>
-            -->
-        </Appender>
-        <Appender type="Console" name="FLOW">
-            <Layout type="PatternLayout" pattern="%C{1}.%M %m %ex%n"/><!-- class and line number -->
-            <Filters>
-                <Filter type="MarkerFilter" marker="FLOW" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
-                <Filter type="MarkerFilter" marker="EXCEPTION" onMatch="ACCEPT" onMismatch="DENY"/>
-            </Filters>
-        </Appender>
-        <!--
-            ¿Puedo mezclar bufferedIO=true con immediateFlush=true?
-            LOG4J 1.2: bufferedIO="false" immediateFlush="true" (es como se ejecuta actualmente la N2A)
-            JUGAR CON ESOS 2 VALORES A VER QUE TAL... :/
-        -->
-        <Appender type="File" name="FileAppender" fileName="${filename}" bufferedIO="false" immediateFlush="true" append="true">
-            <Layout type="PatternLayout">
-                <!--
-                <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
-                -->
-                <Pattern>"%d{yyyyMMddHHmmssSSS} - %-5p - [%t] - %m%n"</Pattern>
-                <Charset>UTF-8</Charset> 
-            </Layout>
-        </Appender>
-         <!--
-           * Asynchronous Loggers are a new addition to Log4j 2. Their aim is to return from the call to Logger.log to the application
-             as soon as possible. You can choose between making all Loggers asynchronous or using a mixture of synchronous and asynchronous
-             Loggers. Making all Loggers asynchronous will give the best performance, while mixing gives you more flexibility.
-           * LMAX Disruptor technology. Asynchronous Loggers internally use the Disruptor, a lock-free inter-thread communication library,
-             instead of queues, resulting in higher throughput and lower latency.
-           * Asynchronous Appenders already existed in Log4j 1.x, but have been enhanced to flush to disk at the end of a batch
-             (when the queue is empty). This produces the same result as configuring "immediateFlush=true", that is, all received log events
-             are always available on disk, but is more efficient because it does not need to touch the disk on each and every log event.
-             (Async Appenders use ArrayBlockingQueue internally and do not need the disruptor jar on the classpath.)
-           * (For synchronous and asynchronous use) Random Access File Appenders are an alternative to Buffered File Appenders. Under the hood,
-             these new appenders use a ByteBuffer + RandomAccessFile instead of a BufferedOutputStream. In our testing this was about 20-200%
-             faster. These appenders can also be used with synchronous loggers and will give the same performance benefits. Random Access
-             File Appenders do not need the disruptor jar on the classpath.
-        -->
-        <!-- El random access file siempre es con buffer!!!
-             When set to true - the default, each write will be followed by a flush. This will guarantee the data is written
-             to disk but could impact performance.
-
-             Flushing after every write is only useful when using this appender with synchronous loggers. Asynchronous loggers
-             and appenders will automatically flush at the end of a batch of events, even if immediateFlush is set to false.
-             This also guarantees the data is written to disk but is more efficient. 
-        -->
-        <Appender type="RandomAccessFile" name="RandomAccessFileAppender" fileName="${filerandomname}" immediateFlush="true" append="true">
-            <Layout type="PatternLayout">
-                <Pattern>"%d{yyyyMMddHHmmssSSS} - %-5p - [%t] - %m%n"</Pattern>
-                <Charset>UTF-8</Charset> 
-            </Layout>
-        </Appender>
-        <!--
-            El AsyncAppender siempre es bufferado y hace siempre un immediateFlush ¿independientemente del appender ref? SÍ, mira:
-
-            Mejor usar includeLocation=false proque el AsyncAppender siempre debe hacer la localización del log (nombre de clase, método y línea)
-            independientemente de si luego se va a loguear o no (porque haya filtros por ejemplo) Esto es así porque el asyncappender
-            debe generar toda la info necesaria antes de pasar esta info a la cola. Una vez en la cola asíncrona esa info ya no puede
-            ser generada. Por tanto, aunque ese log finalmente no se use, siempre se pone en la cola asíncrona con todos sus datos.
-
-            Extracting location is an expensive operation (it can make logging 5 - 20 times slower). To improve performance, location
-            is not included by default when adding a log event to the queue. You can change this by setting includeLocation="true".
-            Para extraer la localización al parecer hay que recorrer el stacktrace por eso es una operacion pesada.
-        -->
-        <Appender type="Async" name="AsyncAppender" blocking="true" bufferSize="128" errorRef="FileAppender" ignoreExceptions="false" includeLocation="false">
-                <!--
-                Probar las dos configuraciones
-                <AppenderRef ref="RandomAccessFileAppender"/>
-                -->
-                <AppenderRef ref="FileAppender"/>
-        </Appender>
-
-    </Appenders>
-     
-    <Loggers>
-        <!--
-        <Logger name="de.loggers.test" level="debug" additivity="false">
-            <Filter type="ThreadContextMapFilter">
-                <KeyValuePair key="test" value="123"/>
-            </Filter>
-            <AppenderRef ref="STDOUT"/>
-        </Logger>
-        -->
-    
-        <!-- 
-        <Logger name="de.loggers.test" level="debug" additivity="false">
-            <AppenderRef ref="File"/>
-        </Logger>
-        -->
-
-        <Logger name="de.loggers.test.simple" level="TRACE">
-            <!--
-              * Because THIS logger has additivity="true" by default THIS logger will use the same appender as its parent's logger,
-                which in this case is the logger Root.
-              * Because THIS logger has additivity="true" by default if we use this AppenderRef we will see for
-                classes in de.loggers.test.simple the same messages twice. One from this logger and one from its parent's logger,
-                which in this case is the logger Root.
-            <AppenderRef ref="STDOUT"/>
-            -->
-        </Logger>
-        <Logger name="de.loggers.test.formatter" level="TRACE" additivity="false">
-            <!--
-              * Because THIS logger has additivity="false" THIS logger will not use the same appender as its parent's logger.
-            -->
-            <AppenderRef ref="STDOUT"/>
-        </Logger>
-        <!--
-            By default, location is not passed to the I/O thread by asynchronous loggers. If one of your layouts or custom
-            filters needs location information, you need to set "includeLocation=true" in the configuration of all relevant loggers,
-            including the root logger.
-        -->
-
-
-
-        <!--
-           * Asynchronous Loggers are a new addition to Log4j 2. Their aim is to return from the call to Logger.log to the application
-             as soon as possible. You can choose between making all Loggers asynchronous or using a mixture of synchronous and asynchronous
-             Loggers. Making all Loggers asynchronous will give the best performance, while mixing gives you more flexibility.
-           * LMAX Disruptor technology. Asynchronous Loggers internally use the Disruptor, a lock-free inter-thread communication library,
-             instead of queues, resulting in higher throughput and lower latency.
-           * Asynchronous Appenders already existed in Log4j 1.x, but have been enhanced to flush to disk at the end of a batch
-             (when the queue is empty). This produces the same result as configuring "immediateFlush=true", that is, all received log events
-             are always available on disk, but is more efficient because it does not need to touch the disk on each and every log event.
-             (Async Appenders use ArrayBlockingQueue internally and do not need the disruptor jar on the classpath.)
-           * (For synchronous and asynchronous use) Random Access File Appenders are an alternative to Buffered File Appenders. Under the hood,
-             these new appenders use a ByteBuffer + RandomAccessFile instead of a BufferedOutputStream. In our testing this was about 20-200%
-             faster. These appenders can also be used with synchronous loggers and will give the same performance benefits. Random Access
-             File Appenders do not need the disruptor jar on the classpath.
-        -->
-        <AsyncLogger name="de.loggers.test.loggernames" level="TRACE" includeLocation="false">
-            <AppenderRef ref="RandomAccessFileAppender"/>
-        </AsyncLogger>
-        <Root level="TRACE">
-            <AppenderRef ref="STDOUT"/>
-        </Root>
-    </Loggers>
-     
-</Configuration>
diff --git a/TDD/sandromancuso/src/main/resources/logback.xml b/TDD/sandromancuso/src/main/resources/logback.xml
deleted file mode 100644 (file)
index 685c34c..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!-- For assistance related to logback-translator or configuration  -->
-<!-- files in general, please contact the logback user mailing list -->
-<!-- at http://www.qos.ch/mailman/listinfo/logback-user             -->
-<!--                                                                -->
-<!-- For professional support please see                            -->
-<!--    http://www.qos.ch/shop/products/professionalSupport         -->
-<!--                                                                -->
-<configuration>
-  <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
-    <encoder>
-      <pattern>%d{yyyyMMddHHmmssSSS} - %-5p - [%t] - [%C] - %m%n</pattern>
-    </encoder>
-  </appender>
-  <root level="INFO">
-    <appender-ref ref="stdout"/>
-  </root>
-</configuration>
diff --git a/TDD/sandromancuso/src/test/java/org/craftedsw/tripservicekata/trip/TripDAOShould.java b/TDD/sandromancuso/src/test/java/org/craftedsw/tripservicekata/trip/TripDAOShould.java
deleted file mode 100644 (file)
index 34f6cc5..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.craftedsw.tripservicekata.trip;
-
-import org.craftedsw.tripservicekata.exception.CollaboratorCallException;
-import org.craftedsw.tripservicekata.user.User;
-import org.junit.Test;
-
-public class TripDAOShould {
-
-       @Test(expected = CollaboratorCallException.class) public void
-       throw_exception_when_retrieving_user_trips() {
-               new TripDAO().tripsBy(new User());
-       }
-}
diff --git a/TDD/sandromancuso/src/test/java/org/craftedsw/tripservicekata/trip/TripServiceShould.java b/TDD/sandromancuso/src/test/java/org/craftedsw/tripservicekata/trip/TripServiceShould.java
deleted file mode 100644 (file)
index 1111b54..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-package org.craftedsw.tripservicekata.trip;\r
-\r
-import static org.hamcrest.core.Is.is;\r
-import static org.junit.Assert.assertThat;\r
-import static org.mockito.BDDMockito.given;\r
-\r
-import java.util.List;\r
-\r
-import org.craftedsw.tripservicekata.UserBuilder;\r
-import org.craftedsw.tripservicekata.exception.UserNotLoggedInException;\r
-import org.craftedsw.tripservicekata.user.User;\r
-import org.junit.Before;\r
-import org.junit.Test;\r
-import org.junit.runner.RunWith;\r
-import org.mockito.InjectMocks;\r
-import org.mockito.Mock;\r
-import org.mockito.Spy;\r
-import org.mockito.runners.MockitoJUnitRunner;\r
-\r
-@RunWith(MockitoJUnitRunner.class)\r
-public class TripServiceShould {\r
-       \r
-       private static final User GUEST = null;\r
-       private static final User UNUSED_USER = null;\r
-       private static final User REGISTERED_USER = new User();\r
-       private static final User ANOTHER_USER = new User();\r
-       private static final Trip TO_BRAZIL = new Trip();\r
-       private static final Trip TO_BERLIN = new Trip();\r
-       \r
-       @Mock TripDAO tripDAO;\r
-       @InjectMocks @Spy private TripService tripService;\r
-       \r
-       @Before\r
-       public void setUp() {\r
-               tripService = new TripService(tripDAO);\r
-       }\r
-\r
-       @Test(expected=UserNotLoggedInException.class) public void\r
-       throw_an_exception_when_user_is_not_logged_in() {               \r
-               tripService.getTripsByUser(UNUSED_USER, GUEST);\r
-       }\r
-       \r
-       @Test public void\r
-       not_return_any_trips_when_users_are_not_friends() {     \r
-               User friend = UserBuilder.aUser()\r
-                                               .friendsWith(ANOTHER_USER)\r
-                                               .withTrips(TO_BRAZIL)\r
-                                               .build();\r
-               \r
-               List<Trip> friendTrips = tripService.getTripsByUser(friend, REGISTERED_USER); \r
-               // You must always begin writing the assert.\r
-               // Remember: the assert must match the unit test method's name!!\r
-               // In this case, no trips must be returned.\r
-               assertThat(friendTrips.size(), is(0));\r
-       }\r
-       \r
-       @Test public void\r
-       return_friend_trips_when_users_are_friends() {\r
-               User friend = UserBuilder.aUser()\r
-                                               .friendsWith(ANOTHER_USER, REGISTERED_USER)\r
-                                               .withTrips(TO_BRAZIL, TO_BERLIN)\r
-                                               .build();\r
-               given(tripDAO.tripsBy(friend)).willReturn(friend.trips());\r
-               \r
-               List<Trip> friendTrips = tripService.getTripsByUser(friend, REGISTERED_USER); \r
-               // You must always begin writing the assert.\r
-               // Remember: the assert must match the unit test method's name!!\r
-               // In this case, no trips must be returned.\r
-               assertThat(friendTrips.size(), is(2));\r
-       }\r
-}\r
diff --git a/TDD/sandromancuso/src/test/java/org/craftedsw/tripservicekata/user/UserShould.java b/TDD/sandromancuso/src/test/java/org/craftedsw/tripservicekata/user/UserShould.java
deleted file mode 100644 (file)
index dfe2aee..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-package org.craftedsw.tripservicekata.user;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-
-import org.craftedsw.tripservicekata.UserBuilder;
-import org.junit.Test;
-
-public class UserShould {
-
-       private static final User JOHN = new User();
-       private static final User PAUL = new User();
-
-       @Test public void
-       inform_when_users_are_not_friends() {
-               User user = UserBuilder.aUser()
-                                               .friendsWith(JOHN)
-                                               .build();
-               
-               assertThat(user.isFriendsWith(PAUL), is(false));
-       }
-       
-       @Test public void
-       inform_when_users_are_friends() {
-               User user = UserBuilder.aUser()
-                               .friendsWith(JOHN, PAUL)
-                               .build();
-               
-               assertThat(user.isFriendsWith(PAUL), is(true));
-       }
-}
diff --git a/TDD/sandromancuso/tripservice/README.md b/TDD/sandromancuso/tripservice/README.md
new file mode 100644 (file)
index 0000000..12e4c51
--- /dev/null
@@ -0,0 +1,17 @@
+Sandro Mancuso: testing a refactoring legacy code
+
+Rules for refactoring legacy code.
+
+1. You may not change production code if not covered by tests. Before refactoring some legacy code we must write a Unit Test for it.
+
+   But some times for writing the test we must make modifications in the legacy code. If such modifications are required: just automated refactoring (via IDES) are allowed, if needed to write the test.
+
+
+Steps:
+
+1. Start testing the legacy code following the shortest branch.
+
+2. In Unit Test we should not invoke other classes but the one being under test (the other classes should be stub, mocke, etc, etc)
+
+3. When the legacy code is covered by a unit test we may refactor it (never before) We have to refactor our legacy code from the deepest to the shortest branch.
+
diff --git a/TDD/sandromancuso/tripservice/pom.xml b/TDD/sandromancuso/tripservice/pom.xml
new file mode 100644 (file)
index 0000000..9aac466
--- /dev/null
@@ -0,0 +1,158 @@
+<?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>
+    <groupId>org.craftedsw</groupId>
+    <artifactId>tripservce</artifactId>
+    <packaging>jar</packaging>
+    <version>1.0-SNAPSHOT</version>
+    <name>tripservice</name>
+    <url>http://gumartinm.name</url>
+    <description>TDD codurance</description>
+    <organization>
+        <name>Gustavo Martin Morcuende</name>
+        <url>http://www.gumartinm.name</url>
+    </organization>
+    <scm>
+        <developerConnection>scm:git:http://git.gumartinm.name/TDDbyExample</developerConnection>
+        <url>http://git.gumartinm.name/TDDbyExample</url>
+    </scm>
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+    <dependencies>
+        <!--
+        **************************************************************************************************************************
+            1. LOGBACK: SLF4J NATIVE IMPLEMENTATION. See: http://logback.qos.ch/
+        **************************************************************************************************************************
+        -->
+        <!--
+            1/1 Required dependency for native implementation (nothing else is required)
+
+            Native implementation. There are also SLF4J bindings external to the SLF4J project, e.g. logback which implements
+            SLF4Jnatively. Logback's ch.qos.logback.classic.Logger class is a direct implementation of SLF4J's org.slf4j.Logger
+            interface. Thus, using SLF4J in conjunction with logback involves strictly zero memory and computational overhead.
+            see: http://www.slf4j.org/manual.html
+        -->
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <version>1.1.2</version>
+        </dependency>
+        <!--
+        **************************************************************************************************************************
+            2. SLF4J AND LOG4J 2. See: http://logging.apache.org/log4j/2.x/
+        **************************************************************************************************************************
+        -->
+
+        <!--
+            1/2 Required dependency for log4j 2 with slf4j: binding
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-slf4j-impl</artifactId>
+            <version>2.0-rc1</version>
+        </dependency>
+        -->
+        <!--
+            2/2 Required dependency for log4j 2 with slf4j: log4j 2 maven plugin
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-core</artifactId>
+            <version>2.0-rc1</version>
+        </dependency>
+        -->
+        <dependency>
+               <groupId>javax.inject</groupId>
+               <artifactId>javax.inject</artifactId>
+               <version>1</version>
+               </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.12-beta-1</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+               <groupId>org.mockito</groupId>
+               <artifactId>mockito-core</artifactId>
+               <version>2.0.31-beta</version>
+               <scope>test</scope>
+               </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.1</version>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                                       <!--
+                                       <source>1.6</source>
+                    <target>1.6</target>
+                    -->
+                    <encoding>${project.build.sourceEncoding}</encoding>
+                    <compilerArgument>-Xlint:deprecation</compilerArgument>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-resources-plugin</artifactId>
+                <version>2.6</version>
+                <configuration>
+                    <encoding>${project.build.sourceEncoding}</encoding>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>2.17</version>
+                <!--
+                Trying autodetection, see: http://maven.apache.org/surefire/maven-surefire-plugin/examples/junit.html
+                <dependencies>
+                    <dependency>
+                        <groupId>org.apache.maven.surefire</groupId>
+                        <artifactId>surefire-junit47</artifactId>
+                        <version>2.17</version>
+                    </dependency>
+                </dependencies>
+                -->
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>2.3.1</version>
+                <configuration>
+                    <archive>
+                        <manifestEntries>
+                            <Specification-Title>${project.description}</Specification-Title>
+                            <Specification-Version>${project.version}</Specification-Version>
+                            <Specification-Vendor>${project.organization.name}</Specification-Vendor>
+                            <Implementation-Title>${project.description}</Implementation-Title>
+                            <Implementation-Version>${project.version}</Implementation-Version>
+                            <Implementation-Vendor>${project.organization.name}</Implementation-Vendor>
+                        </manifestEntries>
+                    </archive>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+       <reporting>
+        <plugins>
+            <plugin>
+                               <!--
+                               <groupId>org.jacoco</groupId>
+                       <artifactId>jacoco</artifactId>
+                       <version>0.7.2.201409121644</version>
+                               -->
+                       <groupId>org.codehaus.mojo</groupId>
+                       <artifactId>cobertura-maven-plugin</artifactId>
+                       <version>2.6</version>
+                       </plugin>
+               </plugins>
+       </reporting>
+</project>
diff --git a/TDD/sandromancuso/tripservice/src/main/java/org/craftedsw/tripservicekata/TripService_Original.java b/TDD/sandromancuso/tripservice/src/main/java/org/craftedsw/tripservicekata/TripService_Original.java
new file mode 100644 (file)
index 0000000..a2ba5ee
--- /dev/null
@@ -0,0 +1,34 @@
+package org.craftedsw.tripservicekata;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.craftedsw.tripservicekata.exception.UserNotLoggedInException;
+import org.craftedsw.tripservicekata.trip.Trip;
+import org.craftedsw.tripservicekata.trip.TripDAO;
+import org.craftedsw.tripservicekata.user.User;
+import org.craftedsw.tripservicekata.user.UserSession;
+
+public class TripService_Original {
+
+       public List<Trip> getTripsByUser(User user) throws UserNotLoggedInException {
+               List<Trip> tripList = new ArrayList<Trip>();
+               User loggedUser = UserSession.getInstance().getLoggedUser();
+               boolean isFriend = false;
+               if (loggedUser != null) {
+                       for (User friend : user.getFriends()) {
+                               if (friend.equals(loggedUser)) {
+                                       isFriend = true;
+                                       break;
+                               }
+                       }
+                       if (isFriend) {
+                               tripList = TripDAO.findTripsByUser(user);
+                       }
+                       return tripList;
+               } else {
+                       throw new UserNotLoggedInException();
+               }
+       }
+       
+}
diff --git a/TDD/sandromancuso/tripservice/src/main/java/org/craftedsw/tripservicekata/UserBuilder.java b/TDD/sandromancuso/tripservice/src/main/java/org/craftedsw/tripservicekata/UserBuilder.java
new file mode 100644 (file)
index 0000000..8f95bc9
--- /dev/null
@@ -0,0 +1,42 @@
+package org.craftedsw.tripservicekata;
+
+import org.craftedsw.tripservicekata.trip.Trip;
+import org.craftedsw.tripservicekata.user.User;
+
+public class UserBuilder {
+       private User[] friends = new User[]{};
+       private Trip[] trips = new Trip[]{};
+       
+       public static UserBuilder aUser() {
+               return new UserBuilder();
+       }
+
+       public UserBuilder withTrips(Trip...trips) {
+               this.trips  = trips;
+               return this;
+       }
+
+       public UserBuilder friendsWith(User...friends) {
+               this.friends = friends;
+               return this;
+       }
+       
+       public User build() {
+               User user = new User();
+               addTripsTo(user);
+               addFriendsTo(user);
+               return user;
+       }
+
+       private void addFriendsTo(User user) {
+               for (User friend : friends) {
+                       user.addFriend(friend);
+               }               
+       }
+
+       private void addTripsTo(User user) {
+               for (Trip trip : trips) {
+                       user.addTrip(trip);
+               }
+       }
+}
diff --git a/TDD/sandromancuso/tripservice/src/main/java/org/craftedsw/tripservicekata/exception/CollaboratorCallException.java b/TDD/sandromancuso/tripservice/src/main/java/org/craftedsw/tripservicekata/exception/CollaboratorCallException.java
new file mode 100644 (file)
index 0000000..828353e
--- /dev/null
@@ -0,0 +1,25 @@
+package org.craftedsw.tripservicekata.exception;
+
+public class CollaboratorCallException extends RuntimeException {
+
+       private static final long serialVersionUID = -4584041339906109902L;
+
+       public CollaboratorCallException() {
+               super();
+       }
+
+       public CollaboratorCallException(String message,
+                       Throwable cause) {
+               super(message, cause);
+       }
+
+       public CollaboratorCallException(String message) {
+               super(message);
+       }
+
+       public CollaboratorCallException(Throwable cause) {
+               super(cause);
+       }
+
+       
+}
diff --git a/TDD/sandromancuso/tripservice/src/main/java/org/craftedsw/tripservicekata/exception/UserNotLoggedInException.java b/TDD/sandromancuso/tripservice/src/main/java/org/craftedsw/tripservicekata/exception/UserNotLoggedInException.java
new file mode 100644 (file)
index 0000000..880bf20
--- /dev/null
@@ -0,0 +1,7 @@
+package org.craftedsw.tripservicekata.exception;
+
+public class UserNotLoggedInException extends RuntimeException {
+
+       private static final long serialVersionUID = 8959479918185637340L;
+
+}
diff --git a/TDD/sandromancuso/tripservice/src/main/java/org/craftedsw/tripservicekata/trip/Trip.java b/TDD/sandromancuso/tripservice/src/main/java/org/craftedsw/tripservicekata/trip/Trip.java
new file mode 100644 (file)
index 0000000..f12ff3c
--- /dev/null
@@ -0,0 +1,5 @@
+package org.craftedsw.tripservicekata.trip;
+
+public class Trip {
+
+}
diff --git a/TDD/sandromancuso/tripservice/src/main/java/org/craftedsw/tripservicekata/trip/TripDAO.java b/TDD/sandromancuso/tripservice/src/main/java/org/craftedsw/tripservicekata/trip/TripDAO.java
new file mode 100644 (file)
index 0000000..ab859ed
--- /dev/null
@@ -0,0 +1,27 @@
+package org.craftedsw.tripservicekata.trip;
+
+import java.util.List;
+
+import org.craftedsw.tripservicekata.exception.CollaboratorCallException;
+import org.craftedsw.tripservicekata.user.User;
+
+public class TripDAO {
+
+       public static List<Trip> findTripsByUser(User user) {
+               throw new CollaboratorCallException(
+                               "TripDAO should not be invoked on an unit test.");
+       }
+
+       // At the end and by means of many code refactoring our app
+       // will end up using the instance method. In the meanwhile we
+       // will not be able to remove the static method but at least
+       // we are offering something that can be tested.
+       // Be careful when refactoring this code because in real life
+       // findTripsByUser for sure will be used in many places but again
+       // in the meanwhile with this code we can write unit tests (we
+       // always need to write a test of our legacy code before refactoring it)
+       public List<Trip> tripsBy(User user) {
+               return TripDAO.findTripsByUser(user);
+       }
+       
+}
\ No newline at end of file
diff --git a/TDD/sandromancuso/tripservice/src/main/java/org/craftedsw/tripservicekata/trip/TripService.java b/TDD/sandromancuso/tripservice/src/main/java/org/craftedsw/tripservicekata/trip/TripService.java
new file mode 100644 (file)
index 0000000..276710f
--- /dev/null
@@ -0,0 +1,41 @@
+package org.craftedsw.tripservicekata.trip;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import javax.inject.Inject;\r
+\r
+import org.craftedsw.tripservicekata.exception.UserNotLoggedInException;\r
+import org.craftedsw.tripservicekata.user.User;\r
+\r
+public class TripService {\r
+       \r
+       private final TripDAO tripDAO;\r
+\r
+       @Inject\r
+       public TripService(TripDAO tripDAO) {\r
+               this.tripDAO = tripDAO;\r
+       }\r
+\r
+       public List<Trip> getTripsByUser(User user, User loggedInUser) throws UserNotLoggedInException {\r
+               validate(loggedInUser);\r
+               \r
+               return user.isFriendsWith(loggedInUser)\r
+                               ? tripsBy(user)\r
+                           : noTrips();\r
+       }\r
+\r
+       private void validate(User loggedInUser) {\r
+               if (loggedInUser == null) {\r
+                       throw new UserNotLoggedInException();\r
+               }\r
+       }\r
+\r
+       private ArrayList<Trip> noTrips() {\r
+               return new ArrayList<>();\r
+       }\r
+\r
+       private List<Trip> tripsBy(User user) {\r
+               return tripDAO.tripsBy(user);\r
+       }\r
+}\r
diff --git a/TDD/sandromancuso/tripservice/src/main/java/org/craftedsw/tripservicekata/user/User.java b/TDD/sandromancuso/tripservice/src/main/java/org/craftedsw/tripservicekata/user/User.java
new file mode 100644 (file)
index 0000000..d038fe8
--- /dev/null
@@ -0,0 +1,33 @@
+package org.craftedsw.tripservicekata.user;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.craftedsw.tripservicekata.trip.Trip;\r
+\r
+public class User {\r
+\r
+       private List<Trip> trips = new ArrayList<Trip>();\r
+       private List<User> friends = new ArrayList<User>();\r
+       \r
+       public List<User> getFriends() {\r
+               return friends;\r
+       }\r
+       \r
+       public void addFriend(User user) {\r
+               friends.add(user);\r
+       }\r
+\r
+       public void addTrip(Trip trip) {\r
+               trips.add(trip);\r
+       }\r
+       \r
+       public List<Trip> trips() {\r
+               return trips;\r
+       }\r
+\r
+       public boolean isFriendsWith(User anotherUser) {\r
+               return friends.contains(anotherUser);\r
+       }\r
+\r
+}\r
diff --git a/TDD/sandromancuso/tripservice/src/main/java/org/craftedsw/tripservicekata/user/UserSession.java b/TDD/sandromancuso/tripservice/src/main/java/org/craftedsw/tripservicekata/user/UserSession.java
new file mode 100644 (file)
index 0000000..6b91c0d
--- /dev/null
@@ -0,0 +1,21 @@
+package org.craftedsw.tripservicekata.user;
+
+import org.craftedsw.tripservicekata.exception.CollaboratorCallException;
+
+public class UserSession {
+
+       private static final UserSession userSession = new UserSession();
+       
+       private UserSession() {
+       }
+       
+       public static UserSession getInstance() {
+               return userSession;
+       }
+
+       public User getLoggedUser() {
+               throw new CollaboratorCallException(
+                               "UserSession.getLoggedUser() should not be called in an unit test");
+       }
+
+}
diff --git a/TDD/sandromancuso/tripservice/src/main/resources/log4j2.xml b/TDD/sandromancuso/tripservice/src/main/resources/log4j2.xml
new file mode 100644 (file)
index 0000000..2de3fd2
--- /dev/null
@@ -0,0 +1,197 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    * name: The name of the configuration.
+    * dest: Either "err", which will send output to stderr, or a file path or URL.
+    * status: The level of internal Log4j events that should be logged to the console. Valid values for this attribute are "trace",
+      "debug", "info", "warn", "error" and "fatal". Log4j will log details about initialization, rollover and other internal
+      actions to the status logger.
+    * strict: Enables the use of the strict XML format. Not supported in JSON configurations.
+    * monitorInterval: If the monitorInterval attribute is specified on the configuration element and is set to a non-zero value
+      then the file will be checked the next time a log event is evaluated and/or logged and the monitorInterval has elapsed
+      since the last check.
+    * packages: A comma separated list of package names to search for plugins. Plugins are only loaded once per classloader so
+      changing this value may not have any effect upon reconfiguration.
+-->
+<Configuration name="XMLConfigTest" dest="err" status="trace" strict="true" monitorInterval="30" packages="org.apache.logging.log4j.test">
+    <!--
+        Log4j 2 supports the ability to specify tokens in the configuration as references to properties defined elsewhere. Some of
+        these properties will be resolved when the configuration file is interpreted while others may be passed to components
+        where they will be evaluated at runtime.
+    -->
+    <Properties>
+        <Property name="filename">target/fileappender.log</Property>
+        <Property name="filerandomname">target/filerandomappender.log</Property>
+    </Properties>
+
+    <!--
+         Filters may be configured in one of four locations:
+
+        Context-wide Filters are configured directly in the configuration. Events that are rejected by these filters
+        will not be passed to loggers for further processing. Once an event has been accepted by a Context-wide filter it will not be evaluated by any other Context-wide Filters nor will the Logger's Level be used to filter the event. The event will be evaluated by Logger and Appender Filters however.
+    Logger Filters are configured on a specified Logger. These are evaluated after the Context-wide Filters and the Log Level for the Logger. Events that are rejected by these filters will be discarded and the event will not be passed to a parent Logger regardless of the additivity setting.
+    Appender Filters are used to determine if a specific Appender should handle the formatting and publication of the event.
+    Appender Reference Filters are used to determine if a Logger should route the event to an appender.
+
+    <Filter type="ThresholdFilter" level="debug"/>
+    -->
+    
+    <Appenders>
+        <Appender type="Console" name="STDOUT">
+            <!--
+            <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
+            -->
+            <Filter type="ThresholdFilter" level="trace"/>
+            <!--
+            <Layout type="PatternLayout" pattern="%d{ABSOLUTE} %5p %c{1}:%L %m%n"/>
+            -->
+            <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx - %X{id} %X{name} %X{surname}%n"/>
+            <!--  
+            <Filters>
+                See: FlowTracingExample class in this project.
+                <Filter type="MarkerFilter" marker="FLOW" onMatch="ENTER" onMismatch="NEUTRAL"/>
+                <Filter type="MarkerFilter" marker="EXCEPTION" onMatch="CATCHING" onMismatch="ACCEPT"/>
+                
+                See: MarkersExample class in this project.
+                ¿Cómo usar esto cuando hago logger.debug(QUERY_MARKER, "SELECT * FROM {}", table);?
+                ¿Sería marker="DEBUG"?
+                <Filter type="MarkerFilter" marker="FLOW" onMatch="SQL_UPDATE" onMismatch="NEUTRAL"/>
+                <Filter type="MarkerFilter" marker="EXCEPTION" onMatch="SQL_QUERY" onMismatch="ACCEPT"/>
+            </Filters>
+            -->
+        </Appender>
+        <Appender type="Console" name="FLOW">
+            <Layout type="PatternLayout" pattern="%C{1}.%M %m %ex%n"/><!-- class and line number -->
+            <Filters>
+                <Filter type="MarkerFilter" marker="FLOW" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
+                <Filter type="MarkerFilter" marker="EXCEPTION" onMatch="ACCEPT" onMismatch="DENY"/>
+            </Filters>
+        </Appender>
+        <!--
+            ¿Puedo mezclar bufferedIO=true con immediateFlush=true?
+            LOG4J 1.2: bufferedIO="false" immediateFlush="true" (es como se ejecuta actualmente la N2A)
+            JUGAR CON ESOS 2 VALORES A VER QUE TAL... :/
+        -->
+        <Appender type="File" name="FileAppender" fileName="${filename}" bufferedIO="false" immediateFlush="true" append="true">
+            <Layout type="PatternLayout">
+                <!--
+                <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
+                -->
+                <Pattern>"%d{yyyyMMddHHmmssSSS} - %-5p - [%t] - %m%n"</Pattern>
+                <Charset>UTF-8</Charset> 
+            </Layout>
+        </Appender>
+         <!--
+           * Asynchronous Loggers are a new addition to Log4j 2. Their aim is to return from the call to Logger.log to the application
+             as soon as possible. You can choose between making all Loggers asynchronous or using a mixture of synchronous and asynchronous
+             Loggers. Making all Loggers asynchronous will give the best performance, while mixing gives you more flexibility.
+           * LMAX Disruptor technology. Asynchronous Loggers internally use the Disruptor, a lock-free inter-thread communication library,
+             instead of queues, resulting in higher throughput and lower latency.
+           * Asynchronous Appenders already existed in Log4j 1.x, but have been enhanced to flush to disk at the end of a batch
+             (when the queue is empty). This produces the same result as configuring "immediateFlush=true", that is, all received log events
+             are always available on disk, but is more efficient because it does not need to touch the disk on each and every log event.
+             (Async Appenders use ArrayBlockingQueue internally and do not need the disruptor jar on the classpath.)
+           * (For synchronous and asynchronous use) Random Access File Appenders are an alternative to Buffered File Appenders. Under the hood,
+             these new appenders use a ByteBuffer + RandomAccessFile instead of a BufferedOutputStream. In our testing this was about 20-200%
+             faster. These appenders can also be used with synchronous loggers and will give the same performance benefits. Random Access
+             File Appenders do not need the disruptor jar on the classpath.
+        -->
+        <!-- El random access file siempre es con buffer!!!
+             When set to true - the default, each write will be followed by a flush. This will guarantee the data is written
+             to disk but could impact performance.
+
+             Flushing after every write is only useful when using this appender with synchronous loggers. Asynchronous loggers
+             and appenders will automatically flush at the end of a batch of events, even if immediateFlush is set to false.
+             This also guarantees the data is written to disk but is more efficient. 
+        -->
+        <Appender type="RandomAccessFile" name="RandomAccessFileAppender" fileName="${filerandomname}" immediateFlush="true" append="true">
+            <Layout type="PatternLayout">
+                <Pattern>"%d{yyyyMMddHHmmssSSS} - %-5p - [%t] - %m%n"</Pattern>
+                <Charset>UTF-8</Charset> 
+            </Layout>
+        </Appender>
+        <!--
+            El AsyncAppender siempre es bufferado y hace siempre un immediateFlush ¿independientemente del appender ref? SÍ, mira:
+
+            Mejor usar includeLocation=false proque el AsyncAppender siempre debe hacer la localización del log (nombre de clase, método y línea)
+            independientemente de si luego se va a loguear o no (porque haya filtros por ejemplo) Esto es así porque el asyncappender
+            debe generar toda la info necesaria antes de pasar esta info a la cola. Una vez en la cola asíncrona esa info ya no puede
+            ser generada. Por tanto, aunque ese log finalmente no se use, siempre se pone en la cola asíncrona con todos sus datos.
+
+            Extracting location is an expensive operation (it can make logging 5 - 20 times slower). To improve performance, location
+            is not included by default when adding a log event to the queue. You can change this by setting includeLocation="true".
+            Para extraer la localización al parecer hay que recorrer el stacktrace por eso es una operacion pesada.
+        -->
+        <Appender type="Async" name="AsyncAppender" blocking="true" bufferSize="128" errorRef="FileAppender" ignoreExceptions="false" includeLocation="false">
+                <!--
+                Probar las dos configuraciones
+                <AppenderRef ref="RandomAccessFileAppender"/>
+                -->
+                <AppenderRef ref="FileAppender"/>
+        </Appender>
+
+    </Appenders>
+     
+    <Loggers>
+        <!--
+        <Logger name="de.loggers.test" level="debug" additivity="false">
+            <Filter type="ThreadContextMapFilter">
+                <KeyValuePair key="test" value="123"/>
+            </Filter>
+            <AppenderRef ref="STDOUT"/>
+        </Logger>
+        -->
+    
+        <!-- 
+        <Logger name="de.loggers.test" level="debug" additivity="false">
+            <AppenderRef ref="File"/>
+        </Logger>
+        -->
+
+        <Logger name="de.loggers.test.simple" level="TRACE">
+            <!--
+              * Because THIS logger has additivity="true" by default THIS logger will use the same appender as its parent's logger,
+                which in this case is the logger Root.
+              * Because THIS logger has additivity="true" by default if we use this AppenderRef we will see for
+                classes in de.loggers.test.simple the same messages twice. One from this logger and one from its parent's logger,
+                which in this case is the logger Root.
+            <AppenderRef ref="STDOUT"/>
+            -->
+        </Logger>
+        <Logger name="de.loggers.test.formatter" level="TRACE" additivity="false">
+            <!--
+              * Because THIS logger has additivity="false" THIS logger will not use the same appender as its parent's logger.
+            -->
+            <AppenderRef ref="STDOUT"/>
+        </Logger>
+        <!--
+            By default, location is not passed to the I/O thread by asynchronous loggers. If one of your layouts or custom
+            filters needs location information, you need to set "includeLocation=true" in the configuration of all relevant loggers,
+            including the root logger.
+        -->
+
+
+
+        <!--
+           * Asynchronous Loggers are a new addition to Log4j 2. Their aim is to return from the call to Logger.log to the application
+             as soon as possible. You can choose between making all Loggers asynchronous or using a mixture of synchronous and asynchronous
+             Loggers. Making all Loggers asynchronous will give the best performance, while mixing gives you more flexibility.
+           * LMAX Disruptor technology. Asynchronous Loggers internally use the Disruptor, a lock-free inter-thread communication library,
+             instead of queues, resulting in higher throughput and lower latency.
+           * Asynchronous Appenders already existed in Log4j 1.x, but have been enhanced to flush to disk at the end of a batch
+             (when the queue is empty). This produces the same result as configuring "immediateFlush=true", that is, all received log events
+             are always available on disk, but is more efficient because it does not need to touch the disk on each and every log event.
+             (Async Appenders use ArrayBlockingQueue internally and do not need the disruptor jar on the classpath.)
+           * (For synchronous and asynchronous use) Random Access File Appenders are an alternative to Buffered File Appenders. Under the hood,
+             these new appenders use a ByteBuffer + RandomAccessFile instead of a BufferedOutputStream. In our testing this was about 20-200%
+             faster. These appenders can also be used with synchronous loggers and will give the same performance benefits. Random Access
+             File Appenders do not need the disruptor jar on the classpath.
+        -->
+        <AsyncLogger name="de.loggers.test.loggernames" level="TRACE" includeLocation="false">
+            <AppenderRef ref="RandomAccessFileAppender"/>
+        </AsyncLogger>
+        <Root level="TRACE">
+            <AppenderRef ref="STDOUT"/>
+        </Root>
+    </Loggers>
+     
+</Configuration>
diff --git a/TDD/sandromancuso/tripservice/src/main/resources/logback.xml b/TDD/sandromancuso/tripservice/src/main/resources/logback.xml
new file mode 100644 (file)
index 0000000..685c34c
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- For assistance related to logback-translator or configuration  -->
+<!-- files in general, please contact the logback user mailing list -->
+<!-- at http://www.qos.ch/mailman/listinfo/logback-user             -->
+<!--                                                                -->
+<!-- For professional support please see                            -->
+<!--    http://www.qos.ch/shop/products/professionalSupport         -->
+<!--                                                                -->
+<configuration>
+  <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+      <pattern>%d{yyyyMMddHHmmssSSS} - %-5p - [%t] - [%C] - %m%n</pattern>
+    </encoder>
+  </appender>
+  <root level="INFO">
+    <appender-ref ref="stdout"/>
+  </root>
+</configuration>
diff --git a/TDD/sandromancuso/tripservice/src/test/java/org/craftedsw/tripservicekata/trip/TripDAOShould.java b/TDD/sandromancuso/tripservice/src/test/java/org/craftedsw/tripservicekata/trip/TripDAOShould.java
new file mode 100644 (file)
index 0000000..34f6cc5
--- /dev/null
@@ -0,0 +1,13 @@
+package org.craftedsw.tripservicekata.trip;
+
+import org.craftedsw.tripservicekata.exception.CollaboratorCallException;
+import org.craftedsw.tripservicekata.user.User;
+import org.junit.Test;
+
+public class TripDAOShould {
+
+       @Test(expected = CollaboratorCallException.class) public void
+       throw_exception_when_retrieving_user_trips() {
+               new TripDAO().tripsBy(new User());
+       }
+}
diff --git a/TDD/sandromancuso/tripservice/src/test/java/org/craftedsw/tripservicekata/trip/TripServiceShould.java b/TDD/sandromancuso/tripservice/src/test/java/org/craftedsw/tripservicekata/trip/TripServiceShould.java
new file mode 100644 (file)
index 0000000..1111b54
--- /dev/null
@@ -0,0 +1,71 @@
+package org.craftedsw.tripservicekata.trip;\r
+\r
+import static org.hamcrest.core.Is.is;\r
+import static org.junit.Assert.assertThat;\r
+import static org.mockito.BDDMockito.given;\r
+\r
+import java.util.List;\r
+\r
+import org.craftedsw.tripservicekata.UserBuilder;\r
+import org.craftedsw.tripservicekata.exception.UserNotLoggedInException;\r
+import org.craftedsw.tripservicekata.user.User;\r
+import org.junit.Before;\r
+import org.junit.Test;\r
+import org.junit.runner.RunWith;\r
+import org.mockito.InjectMocks;\r
+import org.mockito.Mock;\r
+import org.mockito.Spy;\r
+import org.mockito.runners.MockitoJUnitRunner;\r
+\r
+@RunWith(MockitoJUnitRunner.class)\r
+public class TripServiceShould {\r
+       \r
+       private static final User GUEST = null;\r
+       private static final User UNUSED_USER = null;\r
+       private static final User REGISTERED_USER = new User();\r
+       private static final User ANOTHER_USER = new User();\r
+       private static final Trip TO_BRAZIL = new Trip();\r
+       private static final Trip TO_BERLIN = new Trip();\r
+       \r
+       @Mock TripDAO tripDAO;\r
+       @InjectMocks @Spy private TripService tripService;\r
+       \r
+       @Before\r
+       public void setUp() {\r
+               tripService = new TripService(tripDAO);\r
+       }\r
+\r
+       @Test(expected=UserNotLoggedInException.class) public void\r
+       throw_an_exception_when_user_is_not_logged_in() {               \r
+               tripService.getTripsByUser(UNUSED_USER, GUEST);\r
+       }\r
+       \r
+       @Test public void\r
+       not_return_any_trips_when_users_are_not_friends() {     \r
+               User friend = UserBuilder.aUser()\r
+                                               .friendsWith(ANOTHER_USER)\r
+                                               .withTrips(TO_BRAZIL)\r
+                                               .build();\r
+               \r
+               List<Trip> friendTrips = tripService.getTripsByUser(friend, REGISTERED_USER); \r
+               // You must always begin writing the assert.\r
+               // Remember: the assert must match the unit test method's name!!\r
+               // In this case, no trips must be returned.\r
+               assertThat(friendTrips.size(), is(0));\r
+       }\r
+       \r
+       @Test public void\r
+       return_friend_trips_when_users_are_friends() {\r
+               User friend = UserBuilder.aUser()\r
+                                               .friendsWith(ANOTHER_USER, REGISTERED_USER)\r
+                                               .withTrips(TO_BRAZIL, TO_BERLIN)\r
+                                               .build();\r
+               given(tripDAO.tripsBy(friend)).willReturn(friend.trips());\r
+               \r
+               List<Trip> friendTrips = tripService.getTripsByUser(friend, REGISTERED_USER); \r
+               // You must always begin writing the assert.\r
+               // Remember: the assert must match the unit test method's name!!\r
+               // In this case, no trips must be returned.\r
+               assertThat(friendTrips.size(), is(2));\r
+       }\r
+}\r
diff --git a/TDD/sandromancuso/tripservice/src/test/java/org/craftedsw/tripservicekata/user/UserShould.java b/TDD/sandromancuso/tripservice/src/test/java/org/craftedsw/tripservicekata/user/UserShould.java
new file mode 100644 (file)
index 0000000..dfe2aee
--- /dev/null
@@ -0,0 +1,31 @@
+package org.craftedsw.tripservicekata.user;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+
+import org.craftedsw.tripservicekata.UserBuilder;
+import org.junit.Test;
+
+public class UserShould {
+
+       private static final User JOHN = new User();
+       private static final User PAUL = new User();
+
+       @Test public void
+       inform_when_users_are_not_friends() {
+               User user = UserBuilder.aUser()
+                                               .friendsWith(JOHN)
+                                               .build();
+               
+               assertThat(user.isFriendsWith(PAUL), is(false));
+       }
+       
+       @Test public void
+       inform_when_users_are_friends() {
+               User user = UserBuilder.aUser()
+                               .friendsWith(JOHN, PAUL)
+                               .build();
+               
+               assertThat(user.isFriendsWith(PAUL), is(true));
+       }
+}