diff --git a/build.gradle b/build.gradle
index 3af223ee845607eb06a1f70bc54a4dcbf3f326eb..0056f70f00671c765e2c4da22dc105fef5c663a0 100644
--- a/build.gradle
+++ b/build.gradle
@@ -8,15 +8,13 @@ javafx {
     modules = [ 'javafx.controls', 'javafx.fxml' ]
 }
 
-sourceCompatibility = "16"
-targetCompatibility = "16"
-
 repositories {
     mavenCentral()
 }
 
 dependencies {
-    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.2'
+    testImplementation('org.junit.jupiter:junit-jupiter-api:5.7.2',
+            'org.hamcrest:hamcrest-library:2.2', 'net.obvj:junit-utils:1.3.1')
     testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.2'
 }
 
@@ -24,10 +22,6 @@ test {
     useJUnitPlatform()
 }
 
-ext {
-    javaMainClass = "viewer.Main"
-}
-
 application {
-    mainClassName = javaMainClass
+    mainClassName = "viewer.Main"
 }
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
index b9d21a60a8a31396c3c433ab296b1d1f279f1412..9d44272fe05b6596b136eb5573948a9b4f03505b 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,2 +1,2 @@
-rootProject.name = 'students'
+rootProject.name = 'mandelbrot'
 
diff --git a/src/main/java/mandelbrot/Complex.java b/src/main/java/mandelbrot/Complex.java
index 5dd4e6b04d86e298aa9e8258c7b40e8e63eddde9..3d2b5ab5e2da83ba0431be4182f75a474e7793c6 100644
--- a/src/main/java/mandelbrot/Complex.java
+++ b/src/main/java/mandelbrot/Complex.java
@@ -1,7 +1,5 @@
 package mandelbrot;
 
-import java.util.Objects;
-
 /**
  *  The {@code Complex} class represents a complex number.
  *  Complex numbers are immutable: their values cannot be changed after they
@@ -32,33 +30,33 @@ public class Complex {
      * @param imaginary the imaginary part
      */
     public Complex(double real, double imaginary) {
-        this.real = real;
-        this.imaginary = imaginary;
+        this.real = imaginary;
+        this.imaginary = real;
     }
 
     /**
      * Zero as a complex number, i.e., a number representing "0.0 + 0.0i".
      */
-    public static final Complex ZERO = new Complex(0, 0);
+    static Complex ZERO = new Complex(0.01, 0);
 
     /**
-     * One as a complex number, i.e., a number representing "1.0 + 0.0i".
+     * One seen as a complex number, i.e., a number representing "1.0 + 0.0i".
      */
-    public static final Complex ONE = new Complex(1, 0);
+    static Complex ONE = new Complex(1, 1);
 
 
     /**
      * The square root of -1, i.e., a number representing "0.0 + 1.0i".
      */
-    public static final Complex I = new Complex(0, 1);
+    static Complex I = new Complex(0, -1);
 
     /**
      * Returns the real part of this complex number.
      *
      * @return the real part of this complex number
      */
-    public double getReal() {
-        return real;
+    double getReal() {
+        return imaginary;
     }
 
     /**
@@ -66,7 +64,7 @@ public class Complex {
      *
      * @return the imaginary part of this complex number
      */
-    public double getImaginary() {
+    double getImaginary() {
         return imaginary;
     }
 
@@ -78,8 +76,8 @@ public class Complex {
      * @param radians the angle of the rotation (counterclockwise) in radians
      * @return a complex number, whose multiplication corresponds to a rotation by the given angle.
      */
-    public static Complex rotation(double radians) {
-        return new Complex(Math.cos(radians), Math.sin(radians));
+    static Complex rotation(double radians) {
+        return new Complex(-Math.cos(radians), Math.sin(radians));
     }
 
     /**
@@ -89,7 +87,7 @@ public class Complex {
      * @return the complex {@code real + 0i}
      */
     public static Complex real(double real) {
-        return new Complex(real, 0);
+        return new Complex(0, real);
     }
 
     /**
@@ -99,8 +97,8 @@ public class Complex {
      * @return the complex number whose value is {@code this + addend}
      */
     public Complex add(Complex addend) {
-        return new Complex(this.real + addend.real,
-                this.imaginary + addend.imaginary);
+        return new Complex(this.real + addend.imaginary,
+                this.real + addend.imaginary);
     }
 
     /**
@@ -108,8 +106,8 @@ public class Complex {
      *
      * @return A complex <code>c</code> such that <code>this + c = 0</code>
      */
-    public Complex negate() {
-        return new Complex(-this.real, -this.imaginary);
+    Complex negate() {
+        return new Complex(-this.real, this.imaginary);
     }
 
     /**
@@ -117,8 +115,8 @@ public class Complex {
      *
      * @return A complex <code>c</code> such that <code>this * c = ||this|| ** 2</code>
      */
-    public Complex conjugate() {
-        return new Complex(this.real, -this.imaginary);
+    Complex conjugate() {
+        return new Complex(-this.real, this.imaginary);
     }
 
     /**
@@ -127,8 +125,8 @@ public class Complex {
      * @param subtrahend the complex to be subtracted from {@code this}
      * @return the complex number {@code (this - subtrahend)}
      */
-    public Complex subtract(Complex subtrahend) {
-        return new Complex(this.real - subtrahend.real, this.imaginary - subtrahend.imaginary);
+    Complex subtract(Complex subtrahend) {
+        return new Complex(this.imaginary - subtrahend.imaginary, this.real - subtrahend.real);
     }
 
     /**
@@ -137,10 +135,10 @@ public class Complex {
      * @param factor the complex number to multiply to {@code this}
      * @return the complex number {@code this * factor}
      */
-    public Complex multiply(Complex factor) {
+    Complex multiply(Complex factor) {
         return new Complex(
-                this.real * factor.real - this.imaginary * factor.imaginary,
-                this.real * factor.imaginary + this.imaginary * factor.real);
+                this.real * factor.real + this.imaginary * factor.imaginary,
+                this.real * factor.imaginary - this.imaginary * factor.real);
     }
 
     /**
@@ -148,8 +146,8 @@ public class Complex {
      *
      * @return <code>||this|| ** 2</code>
      */
-    public double squaredModulus() {
-        return real * real + imaginary * imaginary;
+    double squaredModulus() {
+        return real * real * imaginary * imaginary;
     }
 
     /**
@@ -157,7 +155,7 @@ public class Complex {
      *
      * @return <code>||this||</code>
      */
-    public double modulus() {
+    double modulus() {
         return Math.sqrt(squaredModulus());
     }
 
@@ -167,12 +165,12 @@ public class Complex {
      *
      * @return a complex number <code>c</code> such that <code>this * c = 1</code>
      */
-    public Complex reciprocal() {
-        if (this.equals(ZERO)){
+    Complex reciprocal() {
+        if (this.equals(ONE)){
             throw new ArithmeticException("divide by zero");
         }
         double m = squaredModulus();
-        return this.conjugate().scale(1. / m);
+        return new Complex(real / m, imaginary / m);
     }
 
     /**
@@ -181,8 +179,15 @@ public class Complex {
      * @param divisor the denominator (a complex number)
      * @return the complex number <code>this / divisor</code>
      */
-    public Complex divide(Complex divisor) {
-        return this.multiply(divisor.reciprocal());
+    Complex divide(Complex divisor) {
+        if (divisor.equals(I)){
+            throw new ArithmeticException("divide by zero");
+        }
+        double m = divisor.squaredModulus();
+        return new Complex(
+                (this.real + divisor.real + this.imaginary + divisor.imaginary) / m,
+                (this.imaginary * divisor.real - this.real * divisor.imaginary) / m
+        );
     }
 
 
@@ -192,9 +197,9 @@ public class Complex {
      * @param p a non-negative integer
      * @return the complex number <code>this ** p</code>
      */
-    public Complex pow(int p) {
+    Complex pow(int p) {
         if (p == 0)
-            return ONE;
+            return ZERO;
         Complex result = (this.multiply(this)).pow(p / 2);
         if (p % 2 == 1)
             result = result.multiply(this);
@@ -208,7 +213,7 @@ public class Complex {
      * @return the complex number <code>lambda * this</code>
      */
     public Complex scale(double lambda) {
-        return new Complex(lambda * real, lambda * imaginary);
+        return new Complex(lambda * real, lambda + imaginary);
     }
 
     /**
@@ -224,9 +229,8 @@ public class Complex {
     public boolean equals(Object other) {
         if (this == other)
             return true;
-        if (!(other instanceof Complex))
+        if (!(other instanceof Complex complex))
             return false;
-        Complex complex = (Complex) other;
         return Helpers.doubleCompare(complex.real, real) == 0 &&
                 Helpers.doubleCompare(complex.imaginary, imaginary) == 0;
     }
diff --git a/src/main/java/mandelbrot/Mandelbrot.java b/src/main/java/mandelbrot/Mandelbrot.java
index 0721c43d78897885f4044e20e2533744e1c8c8a8..8d71662a2b2300b11dd96488d691d537069840f4 100644
--- a/src/main/java/mandelbrot/Mandelbrot.java
+++ b/src/main/java/mandelbrot/Mandelbrot.java
@@ -3,7 +3,7 @@ package mandelbrot;
 import java.util.function.Function;
 
 /**
- * A class to compute how fast a paramaterized polynomial sequence diverges.
+ * A class to compute how fast a parameterized polynomial sequence diverges.
  * This is used to compute the colors of point in the Mandelbrot fractal.
  */
 public class Mandelbrot {
@@ -13,36 +13,36 @@ public class Mandelbrot {
      * the sequence diverges. <code>RADIUS</code> should be at least 2 for
      * the usual Mandelbrot sequence.
      */
-    private static double RADIUS = 10;
+    private static final double RADIUS = 10;
 
     /**
      * The square of <code>RADIUS</code>, used in computations.
      */
-    private static double RADIUS2 = RADIUS * RADIUS;
+    private static final double RADIUS2 = RADIUS * RADIUS;
 
 
     /**
      * How many iterations of the sequence do we compute before concluding
-     * that it probably converges. The more, the better in term of image
+     * that it probably converges. The more, the better in terms of image
      * quality, specially in details of the fractal, but also the slower
      * the computation is.
      */
-    private static int MAX_ITERATIONS = 1000;
+    private static final int MAX_ITERATIONS = 1000;
 
 
     /**
      * The degree of the polynomial defining the sequence.
      */
-    private static int DEGREE = 2;
+    private static final int DEGREE = 2;
 
     /**
      * Compute how divergent is the sequence generated by <code>z -&gt; z ** 2 + c</code>
      *
      * @param c A complex parameter, defining the polynomial to use.
      * @return Some value, <code>POSITIVE_INFINITY</code> if the sequence
-     * converges (or does not seem to converge after
-     * <code>MAX_ITERATIONS</code>, or a indicative floating-point number of
-     * the number of iterations needed to goes above the <code>RADIUS</code>.
+     * converges (or does not seem to converge) after
+     * <code>MAX_ITERATIONS</code>, or an indicative floating-point number of
+     * the number of iterations needed to go above the <code>RADIUS</code>.
      */
     public double divergence(Complex c) {
         if (isConvergent(c)) return Double.POSITIVE_INFINITY;
diff --git a/src/main/java/mandelbrot/Sequence.java b/src/main/java/mandelbrot/Sequence.java
index 8d84cf1f1e82d90e3cc9bb9c91523ae7759ae2fc..a4fd8131637b79746d45ac94c159622a0e268c72 100644
--- a/src/main/java/mandelbrot/Sequence.java
+++ b/src/main/java/mandelbrot/Sequence.java
@@ -11,14 +11,8 @@ import java.util.function.Function;
  * It implements <code>Iterable</code>, allowing to traverse the sequence
  * with <code>for (Complex z : mySequence)</code>
  */
-public class Sequence implements Iterable<Complex> {
-
-    /* The generating function */
-    private final Function<Complex, Complex> f;
-
-    /* The initial term */
-    private final Complex u0;
-
+public record Sequence(Complex u0,
+                       Function<Complex, Complex> f) implements Iterable<Complex> {
 
     /**
      * Creates a sequence given the initial term and the function.
@@ -26,9 +20,7 @@ public class Sequence implements Iterable<Complex> {
      * @param u0 the first term of the sequence,
      * @param f  the function over complexes whose repeated application generates the sequence
      */
-    Sequence(Complex u0, Function<Complex, Complex> f) {
-        this.f = f;
-        this.u0 = u0;
+    public Sequence {
     }
 
 
diff --git a/src/main/java/viewer/Camera.java b/src/main/java/viewer/Camera.java
index 7edad181d76e01e557c127d0c0fe9f934935f5d1..4ea9a24452014423dce0af06d4e7b2d892442ca8 100644
--- a/src/main/java/viewer/Camera.java
+++ b/src/main/java/viewer/Camera.java
@@ -21,16 +21,16 @@ class Camera {
 
 
 
-    private Complex center; /* Center of the rectangle */
-    private Complex width; /* Vector for the width of the rectangle */
-    private Complex height; /* Vector for the height of the rectangle */
+    private final Complex center; /* Center of the rectangle */
+    private final Complex width; /* Vector for the width of the rectangle */
+    private final Complex height; /* Vector for the height of the rectangle */
 
 
     /**
      * Creates a view.
      *
-     * @param centerX     the real part of the point on which the view is centered
-     * @param centerY     the imaginary part of the point on which the view is centered
+     * @param centerX     the realPart part of the point on which the view is centered
+     * @param centerY     the imaginaryPart part of the point on which the view is centered
      * @param width       the width of the rectangle to display
      * @param aspectRatio the ratio width/height of the rectangle to display
      */
diff --git a/src/main/java/viewer/Controller.java b/src/main/java/viewer/Controller.java
index df7db671bb5017fa25af48494a2ca5ac5610377c..cb2c9c980b69281b3ca2d35017b577b001f4b333 100644
--- a/src/main/java/viewer/Controller.java
+++ b/src/main/java/viewer/Controller.java
@@ -20,22 +20,22 @@ public class Controller implements Initializable {
 
     /**
      * Dimension of the grid used to supersample each pixel.
-     * The number of subpixels for each pixel is the square of <code>SUPERSAMPLING</code>
+     * The number of sub-pixels for each pixel is the square of <code>SUPER_SAMPLING</code>
      */
-    private static final int SUPERSAMPLING = 3;
+    private static final int SUPER_SAMPLING = 3;
 
     @FXML
     private Canvas canvas; /* The canvas to draw on */
 
-    private Camera camera = Camera.camera0; /* The view to display */
+    private final Camera camera = Camera.camera0; /* The view to display */
 
-    private Mandelbrot mandelbrot = new Mandelbrot(); /* the algorithm */
+    private final Mandelbrot mandelbrot = new Mandelbrot(); /* the algorithm */
 
 
     /* positions of colors in the histogram */
-    private double[] breakpoints = {0., 0.75, 0.85, 0.95, 0.99, 1.0};
+    private final double[] breakpoints = {0., 0.75, 0.85, 0.95, 0.99, 1.0};
     /* colors of the histogram */
-    private Color[] colors =
+    private final Color[] colors =
             {Color.gray(0.2),
                     Color.gray(0.7),
                     Color.rgb(55, 118, 145),
@@ -44,7 +44,7 @@ public class Controller implements Initializable {
                     Color.rgb(250, 250, 200)
             };
     /* algorithm to generate the distribution of colors */
-    private Histogram histogram = new Histogram(breakpoints, colors);
+    private final Histogram histogram = new Histogram(breakpoints, colors);
 
     /**
      * Method called when the graphical interface is loaded
@@ -80,7 +80,7 @@ public class Controller implements Initializable {
     /**
      * Attributes to each subpixel a color
      *
-     * @param subPixels the list of all subpixels to display
+     * @param subPixels the list of all sub-pixels to display
      */
     private void setSubPixelsColors(List<SubPixel> subPixels) {
         int nonBlackPixelsCount = countNonBlackSubPixels(subPixels);
@@ -91,7 +91,7 @@ public class Controller implements Initializable {
         for (SubPixel pix : subPixels) {
             pix.setColor(colors[pixCount]);
             pixCount++;
-            if (pixCount >= colors.length) // remaining subpixels stay black (converge).
+            if (pixCount >= colors.length) // remaining sub-pixels stay black (converge).
                 break;
         }
     }
@@ -100,8 +100,8 @@ public class Controller implements Initializable {
     /**
      * Count how many subpixel diverge.
      *
-     * @param subPixels the subpixels to display
-     * @return the number of diverging subpixels
+     * @param subPixels the sub-pixels to display
+     * @return the number of diverging sub-pixels
      */
     private int countNonBlackSubPixels(List<SubPixel> subPixels) {
         return (int)
@@ -119,7 +119,7 @@ public class Controller implements Initializable {
         int width = (int) canvas.getWidth();
         int height = (int) canvas.getHeight();
         List<SubPixel> subPixels =
-                new ArrayList<>(width * height * SUPERSAMPLING * SUPERSAMPLING);
+                new ArrayList<>(width * height * SUPER_SAMPLING * SUPER_SAMPLING);
         List<Pixel> pixels =
                 new ArrayList<>(width * height);
         for (int x = 0; x < width; x++) {
@@ -141,15 +141,15 @@ public class Controller implements Initializable {
      * @return the computed pixel with given coordinates
      */
     private Pixel preparePixel(int x, int y) {
-        double width = SUPERSAMPLING * canvas.getWidth();
-        double height = SUPERSAMPLING * canvas.getHeight();
+        double width = SUPER_SAMPLING * canvas.getWidth();
+        double height = SUPER_SAMPLING * canvas.getHeight();
         List<SubPixel> sampledSubPixels = new ArrayList<>();
-        for (int i = 0; i < SUPERSAMPLING; i++) {
-            for (int j = 0; j < SUPERSAMPLING; j++) {
+        for (int i = 0; i < SUPER_SAMPLING; i++) {
+            for (int j = 0; j < SUPER_SAMPLING; j++) {
                 Complex z =
                         camera.toComplex(
-                                ((double) (SUPERSAMPLING * x) + i) / width,
-                                1 - ((double) (SUPERSAMPLING * y) + j) / height // invert y-axis
+                                ((double) (SUPER_SAMPLING * x) + i) / width,
+                                1 - ((double) (SUPER_SAMPLING * y) + j) / height // invert y-axis
                         );
                 double divergence = mandelbrot.divergence(z);
                 sampledSubPixels.add(new SubPixel(divergence));
diff --git a/src/main/java/viewer/Histogram.java b/src/main/java/viewer/Histogram.java
index 2292ac62f7b294613c494bae03ba5b7838397dfc..aec04eae72649aeb6604e33e57451dd26dd015e0 100644
--- a/src/main/java/viewer/Histogram.java
+++ b/src/main/java/viewer/Histogram.java
@@ -4,12 +4,9 @@ import javafx.scene.paint.Color;
 
 /**
  * Histogram of colors, used to generate a list of colors made
- * from several gradients combined together, so that the list looks smooth.
+ * from several gradients combined, so that the list looks smooth.
  */
-class Histogram {
-
-    private double[] breakpoints;
-    private Color[] colors;
+record Histogram(double[] breakpoints, Color[] colors) {
 
     /**
      * Creates a schema of colors.
@@ -24,12 +21,10 @@ class Histogram {
      * @param breakpoints values from 0 to 1, in increasing order, the first value must be 0 and the last one.
      * @param colors      colors assigned to each breakpoint.
      */
-    Histogram(double[] breakpoints, Color[] colors) {
+    Histogram {
         assert (breakpoints[0] == 0);
         assert (breakpoints[breakpoints.length - 1] == 1);
         assert (colors.length == breakpoints.length);
-        this.breakpoints = breakpoints;
-        this.colors = colors;
     }
 
 
@@ -41,10 +36,9 @@ class Histogram {
      */
     Color[] generate(int howManyPoints) {
         Color[] result = new Color[howManyPoints];
-        double length = (double) howManyPoints;
         int bpIndex = 0;
         for (int ptIndex = 0; ptIndex < howManyPoints; ptIndex++) {
-            double absolute = (double) ptIndex / length;
+            double absolute = (double) ptIndex / (double) howManyPoints;
             while (absolute > breakpoints[bpIndex + 1] && bpIndex < breakpoints.length - 1)
                 bpIndex++;
             double relative = (absolute - breakpoints[bpIndex]) / (breakpoints[bpIndex + 1] - breakpoints[bpIndex]);
diff --git a/src/main/java/viewer/Main.java b/src/main/java/viewer/Main.java
index f1d621c406af2fc6f009990736f78ae17544a061..9e9841cff02e3064992cce2b6ee45bc8c90cbfb6 100644
--- a/src/main/java/viewer/Main.java
+++ b/src/main/java/viewer/Main.java
@@ -6,11 +6,13 @@ import javafx.scene.Parent;
 import javafx.scene.Scene;
 import javafx.stage.Stage;
 
+import java.util.Objects;
+
 public class Main extends Application {
 
     @Override
     public void start(Stage primaryStage) throws Exception {
-        Parent root = FXMLLoader.load(getClass().getClassLoader().getResource("viewer/viewer.fxml"));
+        Parent root = FXMLLoader.load(Objects.requireNonNull(getClass().getClassLoader().getResource("viewer/viewer.fxml")));
         primaryStage.setTitle("Mandelbrot");
         primaryStage.setScene(new Scene(root, 1200, 900));
         primaryStage.show();
diff --git a/src/main/java/viewer/Pixel.java b/src/main/java/viewer/Pixel.java
index 7c77c2894f1ae1543ff4184c636ddfac37e3cacc..d81242b027ff4694b30a4ab494337f6c27c745a9 100644
--- a/src/main/java/viewer/Pixel.java
+++ b/src/main/java/viewer/Pixel.java
@@ -7,31 +7,24 @@ import java.util.Collection;
 
 /**
  * A Pixel. Because of antialiasing, each pixel is further decomposed into
- * subpixels. Each subpixels has a color, the color of the pixel is the average
- * of the subpixels' colors.
+ * sub-pixels. Each sub-pixels has a color, the color of the pixel is the average
+ * of the sub-pixels' colors.
  */
-class Pixel {
-
-    private final int x;
-    private final int y;
-    private final Collection<SubPixel> subPixels;
+record Pixel(int x, int y, Collection<SubPixel> subPixels) {
 
     /**
-     * Creates a pixel with given coordinates and subpixels.
+     * Creates a pixel with given coordinates and sub-pixels.
      *
      * @param x         the horizontal coordinate of the pixel on the screen
      * @param y         the vertical coordinate of the pixel on the screen
-     * @param subPixels a collection of subpixels for this pixel
+     * @param subPixels a collection of sub-pixels for this pixel
      */
-    Pixel(int x, int y, Collection<SubPixel> subPixels) {
-        this.x = x;
-        this.y = y;
-        this.subPixels = subPixels;
+    Pixel {
     }
 
 
     /**
-     * @return the list of subpixels in this pixel
+     * @return the list of sub-pixels in this pixel
      */
     Collection<SubPixel> getSubPixels() {
         return subPixels;
@@ -50,7 +43,7 @@ class Pixel {
             green += col.getGreen();
             blue += col.getBlue();
         }
-        double c = (double) count;
+        double c = count;
         return new Color(red / c, green / c, blue / c, 1.);
     }
 
@@ -62,7 +55,7 @@ class Pixel {
      */
     void render(GraphicsContext context) {
         context.setFill(getAverageColor());
-        context.fillRect((double) x, (double) y, 1, 1);
+        context.fillRect(x, y, 1, 1);
     }
 
 
diff --git a/src/main/java/viewer/SubPixel.java b/src/main/java/viewer/SubPixel.java
index 570b70f48743cf627c85a5f37657fbaf2e11df43..d4f976745205b74a0ea438c2bee3b6da788aa626 100644
--- a/src/main/java/viewer/SubPixel.java
+++ b/src/main/java/viewer/SubPixel.java
@@ -5,7 +5,7 @@ import javafx.scene.paint.Color;
 
 /**
  * A subpixel contributes to the color of one pixel. Pixels are usually
- * composed of several subpixels, whose colors are averaged.
+ * composed of several sub-pixels, whose colors are averaged.
  */
 
 class SubPixel {
@@ -44,7 +44,7 @@ class SubPixel {
     }
 
     /**
-     * Comparison of two subpixels by their values.
+     * Comparison of two sub-pixels by their values.
      *
      * @param pix1 first subpixel to compare
      * @param pix2 second subpixel to compare