diff --git a/calculator/Operators.py b/calculator/Operators.py
deleted file mode 100644
index fdd2090d31600b428cabcbd97622e1dc6e1d7cb1..0000000000000000000000000000000000000000
--- a/calculator/Operators.py
+++ /dev/null
@@ -1,46 +0,0 @@
-class Operator:
-    def __init__(self, symbol, precedence):
-        self.symbol = symbol
-        self.precedence = precedence
-
-    def __repr__(self):
-        return self.symbol
-
-    def __call__(self):
-        raise NotImplemented
-
-class Adder(Operator):
-    def __init__(self):
-        super().__init__('+', 1)
-
-    def __call__(self, a, b):
-        return a + b
-
-class Subtracter(Operator):
-    def __init__(self):
-        super().__init__('-', 1)
-
-    def __call__(self, a, b):
-        return a - b
-
-class Multiplyer(Operator):
-    def __init__(self):
-        super().__init__('*', 2)
-
-    def __call__(self, a, b):
-        return a * b
-
-class Divider(Operator):
-    def __init__(self):
-        super().__init__('/', 2)
-
-    def __call__(self, a, b):
-        return a / b
-
-
-STANDARD_OPERATORS = {
-    '+': Adder(),
-    '-': Subtracter(),
-    '*': Multiplyer(),
-    '/': Divider(),
-}
diff --git a/calculator/__init__.py b/calculator/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/calculator/Calculator.py b/calculator/calculator.py
similarity index 57%
rename from calculator/Calculator.py
rename to calculator/calculator.py
index f69d7238f0f2b3a48b51b380f256ffede8fb70dc..ef0da93e221160bb9ecee49d1d917dc1bca739b2 100644
--- a/calculator/Calculator.py
+++ b/calculator/calculator.py
@@ -1,18 +1,24 @@
 """
-This Calculator module is a simple calculator that can parse and evaluate expressions of the form:
-expression ::= term | expression operator expression
-operator ::= + | - | * | /
-with the usual precedence rules.
+This Calculator holds the logic for the calculator.
 """
 
-from Operators import Operator, STANDARD_OPERATORS
-from Expression import Token, Term, Expression, TermExpression, OperatorExpression
+from calculator.operators import Operator, STANDARD_OPERATORS
+from calculator.expression import Token, Term, Expression, TermExpression, OperatorExpression
+
 
 class Calculator:
-    def __init__(self, operators = STANDARD_OPERATORS):
+    """
+    Calculator class is a simple calculator that can parse and evaluate expressions of the form:
+    expression ::= term | expression operator expression
+    operator ::= + | - | * | /
+    with the usual precedence rules.
+    """
+    def __init__(self, operators=None):
+        if operators is None:
+            operators = STANDARD_OPERATORS
         self.operators = operators
 
-    def _tokenize(self, line: str) -> list[Token]:
+    def tokenize(self, line: str) -> list[Token]:
         """
         Tokenize an expression into a list of tokens.
         """
@@ -24,11 +30,14 @@ class Calculator:
                 try:
                     term = float(token)
                     tokens.append(term)
-                except ValueError:
-                    raise ValueError(f"Unknown token: {token}")
+                except ValueError as exc:
+                    raise ValueError(f"Invalid token {token}") from exc
         return tokens
 
-    def _parse(self, tokens: list[Token]) -> Expression:
+    def parse(self, tokens: list[Token]) -> Expression:
+        """
+        Parse a list of tokens into an ordered expression.
+        """
         if not tokens:
             raise ValueError("Empty expression")
         if len(tokens) == 1:
@@ -51,7 +60,7 @@ class Calculator:
         right = tokens[operator_index + 1:]
 
         # Parse the left and right parts recursively
-        return OperatorExpression(operator, self._parse(left), self._parse(right))
+        return OperatorExpression(operator, self.parse(left), self.parse(right))
 
     def __call__(self, expression: str) -> Term:
-        return self._parse(self._tokenize(expression))()
+        return self.parse(self.tokenize(expression))()
diff --git a/calculator/Expression.py b/calculator/expression.py
similarity index 69%
rename from calculator/Expression.py
rename to calculator/expression.py
index d19ea88ffd75c185ae706239408735ac488f9f79..c461c95f688b652fe5fe2d3fe357c10ac1ab2350 100644
--- a/calculator/Expression.py
+++ b/calculator/expression.py
@@ -1,11 +1,17 @@
+"""
+Expression module defines the structure of an expression.
+"""
 from typing import Union
-from Operators import Operator
+from calculator.operators import Operator
 
 Term: type = float
 Token: type = Union[Operator, Term]
 
 
 class OperatorExpression:
+    """
+    OperatorExpression class is an expression that contains an operator and two sub-expressions.
+    """
     def __init__(self, operator: Operator, left, right):
         self.operator = operator
         self.left = left
@@ -19,6 +25,9 @@ class OperatorExpression:
 
 
 class TermExpression:
+    """
+    TermExpression class is an expression that contains a single term.
+    """
     def __init__(self, value: Term):
         self.value = value
 
diff --git a/calculator/operators.py b/calculator/operators.py
new file mode 100644
index 0000000000000000000000000000000000000000..a353a0108b7235105d0287dfec68c5d8d7c37910
--- /dev/null
+++ b/calculator/operators.py
@@ -0,0 +1,24 @@
+"""
+Operator module contains the Operator class and a list of standard operators.
+"""
+class Operator:
+    """
+    Operator class is a binary operator with a symbol, a precedence and an evaluation function.
+    """
+    def __init__(self, symbol, precedence, evaluate_function):
+        self.symbol = symbol
+        self.precedence = precedence
+        self.evaluate_function = evaluate_function
+
+    def __repr__(self):
+        return self.symbol
+
+    def __call__(self, left, right):
+        return self.evaluate_function(left, right)
+
+STANDARD_OPERATORS = {
+    '+': Operator('+', 1, lambda a, b: a + b),
+    '-': Operator('-', 1, lambda a, b: a - b),
+    '*': Operator('×', 2, lambda a, b: a * b),
+    '/': Operator('/', 2, lambda a, b: a / b),
+}
diff --git a/calculator/requirements.txt b/calculator/requirements.txt
index 9c7788af16fa05ef099b6c72c09d5702edf5712c..21bed0c340d06b80af1992f45528a1d5b5163fe4 100644
--- a/calculator/requirements.txt
+++ b/calculator/requirements.txt
@@ -1,2 +1,4 @@
 fastapi[all]
 uvicorn[standard]
+pylint
+pytest
diff --git a/calculator/server.py b/calculator/server.py
index 8f5fed6b46f404572e5e3dfdad0b628f8add9db8..7f34df5b5e367ce1bb52be74cc2fac7c881ef3b7 100644
--- a/calculator/server.py
+++ b/calculator/server.py
@@ -1,19 +1,25 @@
+"""
+Server module for the web calculator.
+"""
 from fastapi import FastAPI
 from fastapi.requests import Request
 from fastapi.templating import Jinja2Templates
-from Calculator import Calculator
+from calculator.calculator import Calculator
 
 app = FastAPI()
 templates = Jinja2Templates(directory="templates")
 calc = Calculator()
 
-@app.get("/icon")
-
 @app.get("/")
 async def root(request: Request):
+    """
+    Default and only route of the web calculator.
+    Expects either no query parameters or a single query parameter named "expression".
+    """
     expression = request.query_params.get("expression", "")
-    context = { "request": request }
+    context = {"request": request}
     if expression:
         result = calc(expression)
-        context = { "request": request, "expression": expression, "result": result}
+        context = {"request": request,
+                   "expression": expression, "result": result}
     return templates.TemplateResponse("index.html", context)