diff --git a/src/Configuration.php b/src/Configuration.php
new file mode 100644
index 0000000..35d7199
--- /dev/null
+++ b/src/Configuration.php
@@ -0,0 +1,107 @@
+<?php
+
+/*
+ * This file is part of the Webmozarts Console Parallelization package.
+ *
+ * (c) Webmozarts GmbH <office@webmozarts.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace Webmozarts\Console\Parallelization;
+
+use Symfony\Component\Console\Command\Command;
+use Webmozart\Assert\Assert;
+use function ceil;
+use function sprintf;
+
+final class Configuration
+{
+    private $segmentSize;
+    private $rounds;
+    private $batchSize;
+    private $batches;
+
+    public function __construct(
+        bool $numberOfProcessesDefined,
+        int $numberOfProcesses,
+        int $numberOfItems,
+        int $segmentSize,
+        int $batchSize
+    ) {
+        Assert::greaterThan(
+            $numberOfProcesses,
+            0,
+            sprintf(
+                'Expected the number of processes to be 1 or greater. Got "%s"',
+                $numberOfProcesses
+            )
+        );
+        Assert::natural(
+            $numberOfItems,
+            sprintf(
+                'Expected the number of items to be 0 or greater. Got "%s"',
+                $numberOfItems
+            )
+        );
+        Assert::greaterThan(
+            $segmentSize,
+            0,
+            sprintf(
+                'Expected the segment size to be 1 or greater. Got "%s"',
+                $segmentSize
+            )
+        );
+        Assert::greaterThan(
+            $batchSize,
+            0,
+            sprintf(
+                'Expected the batch size to be 1 or greater. Got "%s"',
+                $batchSize
+            )
+        );
+
+        // We always check those (and not the calculated ones) since they come from the command
+        // configuration so an issue there hints on a misconfiguration which should be fixed.
+        Assert::greaterThanEq(
+            $segmentSize,
+            $batchSize,
+            sprintf(
+                'Expected the segment size ("%s") to be greater or equal to the batch size ("%s")',
+                $segmentSize,
+                $batchSize
+            )
+        );
+
+        $this->segmentSize = 1 === $numberOfProcesses && !$numberOfProcessesDefined
+            ? $numberOfItems
+            : $segmentSize
+        ;
+        $this->rounds = (int) (1 === $numberOfProcesses ? 1 : ceil($numberOfItems / $segmentSize));
+        $this->batchSize = $batchSize;
+        $this->batches = (int) (ceil($segmentSize / $batchSize) * $this->rounds);
+    }
+
+    public function getSegmentSize(): int
+    {
+        return $this->segmentSize;
+    }
+
+    public function getRounds(): int
+    {
+        return $this->rounds;
+    }
+
+    public function getBatchSize(): int
+    {
+        return $this->batchSize;
+    }
+
+    public function getBatches(): int
+    {
+        return $this->batches;
+    }
+}
diff --git a/src/Parallelization.php b/src/Parallelization.php
index a24cf9c..d197225 100644
--- a/src/Parallelization.php
+++ b/src/Parallelization.php
@@ -19,7 +19,6 @@
 use function array_filter;
 use function array_merge;
 use function array_slice;
-use function ceil;
 use function count;
 use function getcwd;
 use function implode;
@@ -294,40 +293,25 @@ protected function executeMasterProcess(
         $numberOfProcesses = $parallelizationInput->getNumberOfProcesses();
         $hasItem = null !== $parallelizationInput->getItem();
         $items = $hasItem ? [$parallelizationInput->getItem()] : $this->fetchItems($input);
-        $count = count($items);
-        $segmentSize = 1 === $numberOfProcesses && !$isNumberOfProcessesDefined ? $count : $this->getSegmentSize();
-        $batchSize = $this->getBatchSize();
-        $rounds = 1 === $numberOfProcesses ? 1 : ceil($count * 1.0 / $segmentSize);
-        $batches = ceil($segmentSize * 1.0 / $batchSize) * $rounds;
+        $numberOfItems = count($items);
 
-        Assert::greaterThan(
+        $config = new Configuration(
+            $isNumberOfProcessesDefined,
             $numberOfProcesses,
-            0,
-            sprintf(
-                'Requires at least one process. Got "%s"',
-                $input->getOption('processes')
-            )
+            $numberOfItems,
+            $this->getSegmentSize(),
+            $this->getBatchSize()
         );
 
-        if (!$hasItem && 1 !== $numberOfProcesses) {
-            // Shouldn't check this when only one item has been specified or
-            // when no child processes is used
-            Assert::greaterThanEq(
-                $segmentSize,
-                $batchSize,
-                sprintf(
-                    'The segment size should always be greater or equal to '
-                    .'the batch size. Got respectively "%d" and "%d"',
-                    $segmentSize,
-                    $batchSize
-                )
-            );
-        }
+        $segmentSize = $config->getSegmentSize();
+        $rounds = $config->getRounds();
+        $batches = $config->getBatches();
+        $batchSize = $config->getBatchSize();
 
         $output->writeln(sprintf(
             'Processing %d %s in segments of %d, batches of %d, %d %s, %d %s in %d %s',
-            $count,
-            $this->getItemName($count),
+            $numberOfItems,
+            $this->getItemName($numberOfItems),
             $segmentSize,
             $batchSize,
             $rounds,
@@ -339,16 +323,18 @@ protected function executeMasterProcess(
         ));
         $output->writeln('');
 
-        $progressBar = new ProgressBar($output, $count);
+        $progressBar = new ProgressBar($output, $numberOfItems);
         $progressBar->setFormat('debug');
         $progressBar->start();
 
-        if ($count <= $segmentSize || (1 === $numberOfProcesses && !$isNumberOfProcessesDefined)) {
+        if ($numberOfItems <= $segmentSize
+            || (1 === $numberOfProcesses && !$parallelizationInput->isNumberOfProcessesDefined())
+        ) {
             // Run in the master process
 
             $itemsChunks = array_chunk(
                 $items,
-                $this->getBatchSize(),
+                $batchSize,
                 false
             );
 
@@ -407,8 +393,8 @@ function (string $type, string $buffer) use ($progressBar, $output, $terminalWid
         $output->writeln('');
         $output->writeln(sprintf(
             'Processed %d %s.',
-            $count,
-            $this->getItemName($count)
+            $numberOfItems,
+            $this->getItemName($numberOfItems)
         ));
 
         $this->runAfterLastCommand($input, $output);
diff --git a/tests/ConfigurationTest.php b/tests/ConfigurationTest.php
new file mode 100644
index 0000000..d9511a3
--- /dev/null
+++ b/tests/ConfigurationTest.php
@@ -0,0 +1,347 @@
+<?php
+
+/*
+ * This file is part of the Webmozarts Console Parallelization package.
+ *
+ * (c) Webmozarts GmbH <office@webmozarts.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace Webmozarts\Console\Parallelization;
+
+use InvalidArgumentException;
+use PHPUnit\Framework\TestCase;
+use function func_get_args;
+
+/**
+ * @covers \Webmozarts\Console\Parallelization\Configuration
+ */
+final class ConfigurationTest extends TestCase
+{
+    /**
+     * @dataProvider valuesProvider
+     */
+    public function test_it_can_be_instantiated(
+        bool $numberOfProcessesDefined,
+        int $numberOfProcesses,
+        int $numberOfItems,
+        int $segmentSize,
+        int $batchSize,
+        int $expectedSegmentSize,
+        int $expectedBatchSize,
+        int $expectedRounds,
+        int $expectedBatches
+    ): void {
+        $config = new Configuration(
+            $numberOfProcessesDefined,
+            $numberOfProcesses,
+            $numberOfItems,
+            $segmentSize,
+            $batchSize
+        );
+
+        $this->assertSame($expectedSegmentSize, $config->getSegmentSize());
+        $this->assertSame($expectedBatchSize, $config->getBatchSize());
+        $this->assertSame($expectedRounds, $config->getRounds());
+        $this->assertSame($expectedBatches, $config->getBatches());
+    }
+
+    /**
+     * @dataProvider invalidValuesProvider
+     */
+    public function test_it_cannot_be_instantiated_with_invalid_values(
+        int $numberOfProcesses,
+        int $numberOfItems,
+        int $segmentSize,
+        int $batchSize,
+        string $expectedErrorMessage
+    ): void {
+        $this->expectException(InvalidArgumentException::class);
+        $this->expectExceptionMessage($expectedErrorMessage);
+
+        new Configuration(
+            true,
+            $numberOfProcesses,
+            $numberOfItems,
+            $segmentSize,
+            $batchSize
+        );
+    }
+
+    public static function valuesProvider(): iterable
+    {
+        yield 'empty' => self::createInputArgs(
+            false,
+            1,
+            0,
+            1,
+            1,
+            0,
+            1,
+            1,
+            1
+        );
+
+        yield 'only one default process: the segment size is the number of items' => self::createInputArgs(
+            false,
+            1,
+            50,
+            1,
+            1,
+            50,
+            1,
+            1,
+            1
+        );
+
+        yield 'an arbitrary number of processes given: the segment size is the segment size given' => self::createInputArgs(
+            true,
+            7,
+            50,
+            3,
+            1,
+            3,
+            1,
+            17,
+            51
+        );
+
+        yield 'one process given: the segment size is the segment size given' => self::createInputArgs(
+            true,
+            1,
+            50,
+            3,
+            1,
+            3,
+            1,
+            1,
+            3
+        );
+
+        // Invalid domain case but we add this test to capture this behaviour nonetheless
+        yield 'multiple default processes: the segment size is the segment size given' => self::createInputArgs(
+            true,
+            7,
+            50,
+            3,
+            1,
+            3,
+            1,
+            17,
+            51
+        );
+
+        yield 'there is no rounds if there is no items' => self::createInputArgs(
+            false,
+            1,
+            0,
+            1,
+            1,
+            0,
+            1,
+            1,
+            1
+        );
+
+        yield 'there is only one round if only one process (default)' => self::createInputArgs(
+            false,
+            1,
+            50,
+            1,
+            1,
+            50,
+            1,
+            1,
+            1
+        );
+
+        yield 'there is only one round if only one process (arbitrary)' => self::createInputArgs(
+            true,
+            1,
+            50,
+            1,
+            1,
+            1,
+            1,
+            1,
+            1
+        );
+
+        yield 'there is enough rounds to reach the number of items with the given segment size (half)' => self::createInputArgs(
+            true,
+            2,
+            50,
+            25,
+            1,
+            25,
+            1,
+            2,
+            50
+        );
+
+        yield 'there is enough rounds to reach the number of items with the given segment size (upper)' => self::createInputArgs(
+            true,
+            2,
+            50,
+            15,
+            1,
+            15,
+            1,
+            4,
+            60
+        );
+
+        yield 'there is enough rounds to reach the number of items with the given segment size (lower)' => self::createInputArgs(
+            true,
+            2,
+            50,
+            40,
+            1,
+            40,
+            1,
+            2,
+            80
+        );
+
+        yield 'the batch size used is the batch size given' => self::createInputArgs(
+            false,
+            1,
+            0,
+            10,
+            7,
+            0,
+            7,
+            1,
+            2
+        );
+
+        yield 'there is enough batches to process all the items of a given segment (half)' => self::createInputArgs(
+            true,
+            2,
+            50,
+            30,
+            15,
+            30,
+            15,
+            2,
+            4
+        );
+
+        yield 'there is enough batches to process all the items of a given segment (upper)' => self::createInputArgs(
+            true,
+            2,
+            50,
+            30,
+            10,
+            30,
+            10,
+            2,
+            6
+        );
+
+        yield 'there is enough batches to process all the items of a given segment (lower)' => self::createInputArgs(
+            true,
+            2,
+            50,
+            30,
+            25,
+            30,
+            25,
+            2,
+            4
+        );
+    }
+
+    public static function invalidValuesProvider(): iterable
+    {
+        yield 'invalid number of processes (limit)' => [
+            0,
+            0,
+            1,
+            1,
+            'Expected the number of processes to be 1 or greater. Got "0"',
+        ];
+
+        yield 'invalid number of processes' => [
+            -1,
+            0,
+            1,
+            1,
+            'Expected the number of processes to be 1 or greater. Got "-1"',
+        ];
+
+        yield 'invalid number of items (limit)' => [
+            1,
+            -1,
+            1,
+            1,
+            'Expected the number of items to be 0 or greater. Got "-1"',
+        ];
+
+        yield 'invalid number of items' => [
+            1,
+            -10,
+            1,
+            1,
+            'Expected the number of items to be 0 or greater. Got "-10"',
+        ];
+
+        yield 'invalid segment size (limit)' => [
+            1,
+            0,
+            0,
+            1,
+            'Expected the segment size to be 1 or greater. Got "0"',
+        ];
+
+        yield 'invalid segment size' => [
+            1,
+            0,
+            -1,
+            1,
+            'Expected the segment size to be 1 or greater. Got "-1"',
+        ];
+
+        yield 'invalid batch size (limit)' => [
+            1,
+            0,
+            1,
+            0,
+            'Expected the batch size to be 1 or greater. Got "0"',
+        ];
+
+        yield 'invalid batch size' => [
+            1,
+            0,
+            1,
+            -1,
+            'Expected the batch size to be 1 or greater. Got "-1"',
+        ];
+
+        yield 'segment size lower than batch size' => [
+            1,
+            0,
+            1,
+            10,
+            'Expected the segment size ("1") to be greater or equal to the batch size ("10")',
+        ];
+    }
+
+    private static function createInputArgs(
+        bool $numberOfProcessesDefined,
+        int $numberOfProcesses,
+        int $numberOfItems,
+        int $segmentSize,
+        int $batchSize,
+        int $expectedSegmentSize,
+        int $expectedBatchSize,
+        int $expectedRounds,
+        int $expectedBatches
+    ): array {
+        return func_get_args();
+    }
+}
diff --git a/tests/ParallelizationIntegrationTest.php b/tests/ParallelizationIntegrationTest.php
index 62bea7f..6f72e33 100644
--- a/tests/ParallelizationIntegrationTest.php
+++ b/tests/ParallelizationIntegrationTest.php
@@ -78,7 +78,7 @@ public function test_it_can_run_the_command_without_sub_processes(): void
         if ($this->isSymfony3()) {
             $this->assertSame(
                 <<<'EOF'
-Processing 2 movies in segments of 2, batches of 50, 1 round, 1 batches in 1 process
+Processing 2 movies in segments of 2, batches of 50, 1 round, 1 batch in 1 process
 
  0/2 [>---------------------------]   0% < 1 sec/< 1 sec 10.0 MiB
  1/2 [==============>-------------]  50% < 1 sec/< 1 sec 10.0 MiB
@@ -94,7 +94,7 @@ public function test_it_can_run_the_command_without_sub_processes(): void
         } else {
             $this->assertSame(
                 <<<'EOF'
-Processing 2 movies in segments of 2, batches of 50, 1 round, 1 batches in 1 process
+Processing 2 movies in segments of 2, batches of 50, 1 round, 1 batch in 1 process
 
  0/2 [>---------------------------]   0% < 1 sec/< 1 sec 10.0 MiB
  2/2 [============================] 100% < 1 sec/< 1 sec 10.0 MiB
@@ -124,7 +124,7 @@ public function test_it_can_run_the_command_with_a_single_sub_processes(): void
         if ($this->isSymfony3()) {
             $this->assertSame(
                 <<<'EOF'
-Processing 2 movies in segments of 50, batches of 50, 1 round, 1 batches in 1 process
+Processing 2 movies in segments of 50, batches of 50, 1 round, 1 batch in 1 process
 
  0/2 [>---------------------------]   0% < 1 sec/< 1 sec 10.0 MiB
  1/2 [==============>-------------]  50% < 1 sec/< 1 sec 10.0 MiB
@@ -140,7 +140,7 @@ public function test_it_can_run_the_command_with_a_single_sub_processes(): void
         } else {
             $this->assertSame(
                 <<<'EOF'
-Processing 2 movies in segments of 50, batches of 50, 1 round, 1 batches in 1 process
+Processing 2 movies in segments of 50, batches of 50, 1 round, 1 batch in 1 process
 
  0/2 [>---------------------------]   0% < 1 sec/< 1 sec 10.0 MiB
  2/2 [============================] 100% < 1 sec/< 1 sec 10.0 MiB
@@ -170,7 +170,7 @@ public function test_it_can_run_the_command_with_multiple_processes(): void
         if ($this->isSymfony3()) {
             $this->assertSame(
                 <<<'EOF'
-Processing 2 movies in segments of 50, batches of 50, 1 rounds, 1 batches in 2 processes
+Processing 2 movies in segments of 50, batches of 50, 1 round, 1 batch in 2 processes
 
  0/2 [>---------------------------]   0% < 1 sec/< 1 sec 10.0 MiB
  1/2 [==============>-------------]  50% < 1 sec/< 1 sec 10.0 MiB
@@ -186,7 +186,7 @@ public function test_it_can_run_the_command_with_multiple_processes(): void
         } else {
             $this->assertSame(
                 <<<'EOF'
-Processing 2 movies in segments of 50, batches of 50, 1 rounds, 1 batches in 2 processes
+Processing 2 movies in segments of 50, batches of 50, 1 round, 1 batch in 2 processes
 
  0/2 [>---------------------------]   0% < 1 sec/< 1 sec 10.0 MiB
  2/2 [============================] 100% < 1 sec/< 1 sec 10.0 MiB
@@ -216,7 +216,7 @@ public function test_it_can_run_the_command_with_one_process_as_child_process():
         if ($this->isSymfony3()) {
             $this->assertSame(
                 <<<'EOF'
-Processing 2 movies in segments of 50, batches of 50, 1 round, 1 batches in 1 process
+Processing 2 movies in segments of 50, batches of 50, 1 round, 1 batch in 1 process
 
  0/2 [>---------------------------]   0% < 1 sec/< 1 sec 10.0 MiB
  1/2 [==============>-------------]  50% < 1 sec/< 1 sec 10.0 MiB
@@ -232,7 +232,7 @@ public function test_it_can_run_the_command_with_one_process_as_child_process():
         } else {
             $this->assertSame(
                 <<<'EOF'
-Processing 2 movies in segments of 50, batches of 50, 1 round, 1 batches in 1 process
+Processing 2 movies in segments of 50, batches of 50, 1 round, 1 batch in 1 process
 
  0/2 [>---------------------------]   0% < 1 sec/< 1 sec 10.0 MiB
  2/2 [============================] 100% < 1 sec/< 1 sec 10.0 MiB