diff --git a/pystencils/assignment.py b/pystencils/assignment.py
index 9d570727fbd0d92b7fbb7f81472628ff21641e85..c3ae4b4367da32764224736ea55cbc2bd6acb219 100644
--- a/pystencils/assignment.py
+++ b/pystencils/assignment.py
@@ -20,6 +20,7 @@ def assignment_str(assignment):
 _old_new = sp.codegen.ast.Assignment.__new__
 
 
+# TODO Typing Part2 add default type, defult_float_type, default_int_type and use sane defaults
 def _Assignment__new__(cls, lhs, rhs, *args, **kwargs):
     if isinstance(lhs, (list, tuple, sp.Matrix)) and isinstance(rhs, (list, tuple, sp.Matrix)):
         assert len(lhs) == len(rhs), f'{lhs} and {rhs} must have same length when performing vector assignment!'
diff --git a/pystencils/astnodes.py b/pystencils/astnodes.py
index d2826fa850a6dbf06db192bf45509147633bfc93..ef0bcc6d758fdb67fc42b708038882360a9eee65 100644
--- a/pystencils/astnodes.py
+++ b/pystencils/astnodes.py
@@ -564,7 +564,6 @@ class LoopOverCoordinate(Node):
 
 class SympyAssignment(Node):
     def __init__(self, lhs_symbol, rhs_expr, is_const=True, use_auto=False):
-        # TODO add default type, float_type, int_type use sane defaults
         super(SympyAssignment, self).__init__(parent=None)
         self._lhs_symbol = sp.sympify(lhs_symbol)
         self.rhs = sp.sympify(rhs_expr)
diff --git a/pystencils/backends/cbackend.py b/pystencils/backends/cbackend.py
index 42503a8ef4100549a32bcc41fb36f94bb351b765..ddcfb02dc737551d8ce4c716b351889b22d2d034 100644
--- a/pystencils/backends/cbackend.py
+++ b/pystencils/backends/cbackend.py
@@ -64,6 +64,7 @@ def generate_c(ast_node: Node,
         printer = custom_backend
     elif dialect == Backend.C:
         try:
+            # TODO Vectorization Revamp: instruction_set should not be just slapped on ast
             instruction_set = ast_node.instruction_set
         except Exception:
             instruction_set = None
@@ -126,7 +127,7 @@ def get_headers(ast_node: Node) -> Set[str]:
 
 # --------------------------------------- Backend Specific Nodes -------------------------------------------------------
 
-# TODO CustomCodeNode should not be backend specific
+# TODO future CustomCodeNode should not be backend specific move it elsewhere
 class CustomCodeNode(Node):
     def __init__(self, code, symbols_read, symbols_defined, parent=None):
         super(CustomCodeNode, self).__init__(parent=parent)
@@ -301,9 +302,10 @@ class CBackend:
                         elif self._vector_instruction_set['float'] == '__m128':
                             printed_mask = f"_mm_castps_si128({printed_mask})"
 
-                rhs_type = get_type_of_expression(node.rhs)  # TOOD: vector only???
+                rhs_type = get_type_of_expression(node.rhs)
                 if type(rhs_type) is not VectorType:
-                    rhs = CastFunc(node.rhs, VectorType(rhs_type))
+                    raise ValueError(f'Cannot vectorize inside of the pretty printer! This should have happen earlier!')
+                    # rhs = CastFunc(node.rhs, VectorType(rhs_type)) # Unknown width
                 else:
                     rhs = node.rhs
 
@@ -417,7 +419,7 @@ class CBackend:
             return self._print_Block(node.true_block)
         elif type(node.condition_expr) is BooleanFalse:
             return self._print_Block(node.false_block)
-        cond_type = get_type_of_expression(node.condition_expr)  # TODO: Could be vector or bool?
+        cond_type = get_type_of_expression(node.condition_expr)
         if isinstance(cond_type, VectorType):
             raise ValueError("Problem with Conditional inside vectorized loop - use vec_any or vec_all")
         condition_expr = self.sympy_printer.doprint(node.condition_expr)
@@ -468,7 +470,7 @@ class CustomSympyPrinter(CCodePrinter):
             return f'fabs({self._print(expr.args[0])})'
 
     def _print_AbstractType(self, node):
-        return str(node)
+        raise ValueError(f'Cannot print AbstractType: {node}')
 
     def _print_Function(self, expr):
         infix_functions = {
@@ -600,7 +602,7 @@ class VectorizedCustomSympyPrinter(CustomSympyPrinter):
         instruction = 'makeVecConst'
         if basic_data_type.is_bool():
             instruction = 'makeVecConstBool'
-        # TODO is int, or sint, or uint?
+        # TODO Vectorization Revamp: is int, or sint, or uint (my guess is sint)
         elif basic_data_type.is_int():
             instruction = 'makeVecConstInt'
         return self.instruction_set[instruction].format(number, **self._kwargs)
@@ -616,7 +618,7 @@ class VectorizedCustomSympyPrinter(CustomSympyPrinter):
         instruction = 'makeVecConst'
         if basic_data_type.is_bool():
             instruction = 'makeVecConstBool'
-        # TODO is int, or sint, or uint?
+        # TODO Vectorization Revamp: is int, or sint, or uint (my guess is sint)
         elif basic_data_type.is_int():
             instruction = 'makeVecConstInt'
         return self.instruction_set[instruction].format(symbol, **self._kwargs)
@@ -625,7 +627,7 @@ class VectorizedCustomSympyPrinter(CustomSympyPrinter):
         arg, data_type = expr.args
         if type(data_type) is VectorType:
             # vector_memory_access is a cast_func itself so it should't be directly inside a cast_func
-            assert not isinstance(arg, VectorMemoryAccess)  # TODO Is this true for our new type system?
+            assert not isinstance(arg, VectorMemoryAccess)
             if isinstance(arg, sp.Tuple):
                 is_boolean = get_type_of_expression(arg[0]) == create_type("bool")
                 is_integer = get_type_of_expression(arg[0]) == create_type("int")
diff --git a/pystencils/backends/cuda_backend.py b/pystencils/backends/cuda_backend.py
index ebcda56af81ceb11156172078300de817c3c22d9..f8fdb16dac8911811915d6d69e5af7af8f149f4f 100644
--- a/pystencils/backends/cuda_backend.py
+++ b/pystencils/backends/cuda_backend.py
@@ -37,26 +37,13 @@ class CudaBackend(CBackend):
         return code
 
     @staticmethod
-    def _print_ThreadBlockSynchronization(node):
-        code = "__synchtreads();"
-        return code
+    def _print_ThreadBlockSynchronization(_):
+        return "__synchtreads();"
 
     def _print_TextureDeclaration(self, node):
-
-        # TODO: use fStrings here
-        if node.texture.field.dtype.numpy_dtype.itemsize > 4:
-            code = "texture<fp_tex_%s, cudaTextureType%iD, cudaReadModeElementType> %s;" % (
-                str(node.texture.field.dtype),
-                node.texture.field.spatial_dimensions,
-                node.texture
-            )
-        else:
-            code = "texture<%s, cudaTextureType%iD, cudaReadModeElementType> %s;" % (
-                str(node.texture.field.dtype),
-                node.texture.field.spatial_dimensions,
-                node.texture
-            )
-        return code
+        cond = node.texture.field.dtype.numpy_dtype.itemsize > 4
+        return f'texture<{"fp_tex_" if cond else ""}{str(node.texture.field.dtype)}, ' \
+               f'cudaTextureType{node.texture.field.spacial_dimensions}D, cudaReadModeElementType> {node.texture};'
 
     def _print_SkipIteration(self, _):
         return "return;"
diff --git a/pystencils/bit_masks.py b/pystencils/bit_masks.py
index ad4e967f0131dde5347c20de467afbab4892e149..f8b6b7ef0361cf3555ce67375a34328ef2e1157c 100644
--- a/pystencils/bit_masks.py
+++ b/pystencils/bit_masks.py
@@ -22,7 +22,7 @@ class flag_cond(sp.Function):
 
     def __new__(cls, flag_bit, mask_expression, *expressions):
 
-        # TODO reintroduce checking
+        # TODO Jan reintroduce checking
         # flag_dtype = get_type_of_expression(flag_bit)
         # if not flag_dtype.is_int():
         #     raise ValueError('Argument flag_bit must be of integer type.')
diff --git a/pystencils/cache.py b/pystencils/cache.py
index 15274ccb84e7609f7b80e44270993955d2e59db4..119e5ea6c6959c397e6c41351cfd077fd4c973c3 100644
--- a/pystencils/cache.py
+++ b/pystencils/cache.py
@@ -1,13 +1,8 @@
 import os
 from collections.abc import Hashable
-from functools import partial
+from functools import partial, lru_cache
 from itertools import chain
 
-try:
-    from functools import lru_cache as memorycache
-except ImportError:  # TODO what python version is this???
-    from backports.functools_lru_cache import lru_cache as memorycache
-
 from joblib import Memory
 from appdirs import user_cache_dir
 
@@ -28,7 +23,7 @@ def _wrapper(wrapped_func, cached_func, *args, **kwargs):
 
 def memorycache_if_hashable(maxsize=128, typed=False):
     def wrapper(func):
-        return partial(_wrapper, func, memorycache(maxsize, typed)(func))
+        return partial(_wrapper, func, lru_cache(maxsize, typed)(func))
 
     return wrapper
 
diff --git a/pystencils/config.py b/pystencils/config.py
index 3fea3f37fd5b9a72f906456afc6ae0bbf63dabd3..e5f22392575de3d459967ed8ff3f535da42f0084 100644
--- a/pystencils/config.py
+++ b/pystencils/config.py
@@ -11,7 +11,8 @@ from pystencils.typing.typed_sympy import BasicType
 import numpy as np
 
 
-# TODO: think of more classes better usage, factory whatever ...
+# TODO: CreateKernelConfig is bloated think of more classes better usage, factory whatever ...
+# Proposition: CreateKernelConfigs Classes for different targets?
 @dataclass
 class CreateKernelConfig:
     """
@@ -29,9 +30,8 @@ class CreateKernelConfig:
     """
     Name of the generated function - only important if generated code is written out
     """
-    # TODO: config should check that the datatype is a Numpy type
-    # TODO: check for the python types and issue warnings
-    # TODO: QoL default_number_float and default_number_int should be data_type if they are not specified by the user
+    # TODO Sane defaults: config should check that the datatype is a Numpy type
+    # TODO Sane defaults: QoL default_number_float and default_number_int should be data_type if they are not specified
     data_type: Union[str, Dict[str, BasicType]] = 'float64'
     """
     Data type used for all untyped symbols (i.e. non-fields), can also be a dict from symbol name to type
@@ -82,7 +82,7 @@ class CreateKernelConfig:
     Dict with indexing parameters (constructor parameters of indexing class)
     e.g. for 'block' one can specify '{'block_size': (20, 20, 10) }'.
     """
-    # TODO rework this docstring
+    # TODO Markus rework this docstring
     default_assignment_simplifications: bool = False
     """
     If `True` default simplifications are first performed on the Assignments. If problems occur during the
@@ -127,7 +127,7 @@ class CreateKernelConfig:
 
     def __post_init__(self):
         # ----  Legacy parameters
-        # TODO adapt here the types for example "float", python float, everything ambiguous should not be allowed
+        # TODO Sane defaults: Check for abmigous types like "float", python float, which are dangerous for users
         if isinstance(self.target, str):
             new_target = Target[self.target.upper()]
             warnings.warn(f'Target "{self.target}" as str is deprecated. Use {new_target} instead',
diff --git a/pystencils/cpu/kernelcreation.py b/pystencils/cpu/kernelcreation.py
index 7e4216568c169cf0be1eb46a52c25df765952da6..4514c628c1e030bc7f5385991f9baf71475fd6bc 100644
--- a/pystencils/cpu/kernelcreation.py
+++ b/pystencils/cpu/kernelcreation.py
@@ -45,7 +45,7 @@ def create_kernel(assignments: Union[AssignmentCollection, NodeCollection],
         split_groups = assignments.simplification_hints['split_groups']
     assignments = assignments.all_assignments
 
-    # TODO: try to delete
+    # TODO Jan: try to delete
     def type_symbol(term):
         if isinstance(term, Field.Access) or isinstance(term, TypedSymbol):
             return term
@@ -57,7 +57,7 @@ def create_kernel(assignments: Union[AssignmentCollection, NodeCollection],
         else:
             raise ValueError("Term has to be field access or symbol")
 
-    # TODO move add_types to create_domain_kernel or create_kernel
+    # TODO Jan Cleanup: move add_types to create_domain_kernel or create_kernel?
 
     assignments = add_types(assignments, config)
 
@@ -90,7 +90,6 @@ def create_kernel(assignments: Union[AssignmentCollection, NodeCollection],
 
     if any(FieldType.is_buffer(f) for f in all_fields):
         resolve_buffer_accesses(ast_node, get_base_buffer_index(ast_node), read_only_fields)
-    # TODO think about typing
     resolve_field_accesses(ast_node, read_only_fields, field_to_base_pointer_info=base_pointer_info)
     move_constants_before_loop(ast_node)
     return ast_node
diff --git a/pystencils/cpu/vectorization.py b/pystencils/cpu/vectorization.py
index 9f8e381c3f3f16627cdfecd6caa4e46e648f7efc..0b4a9a0b2a04f7cdff7114b3c89c6cbf47aaa4f4 100644
--- a/pystencils/cpu/vectorization.py
+++ b/pystencils/cpu/vectorization.py
@@ -77,8 +77,8 @@ class CachelineSize(ast.Node):
 def vectorize(kernel_ast: ast.KernelFunction, instruction_set: str = 'best',
               assume_aligned: bool = False, nontemporal: Union[bool, Container[Union[str, Field]]] = False,
               assume_inner_stride_one: bool = False, assume_sufficient_line_padding: bool = True):
-    # TODO we first introduce the remainder loop and then check if we can even vectorise. Maybe first copy the ast
-    # and return the copied version on failure
+    # TODO Vectorization Revamp we first introduce the remainder loop and then check if we can even vectorise.
+    #  Maybe first copy the ast and return the copied version on failure
     """Explicit vectorization using SIMD vectorization via intrinsics.
 
     Args:
@@ -124,7 +124,6 @@ def vectorize(kernel_ast: ast.KernelFunction, instruction_set: str = 'best',
                                   "to differently typed floating point fields")
     float_size = field_float_dtypes.pop().numpy_dtype.itemsize
     assert float_size in (8, 4)
-    # TODO: future work allow mixed precision fields
     default_float_type = 'double' if float_size == 8 else 'float'
     vector_is = get_vector_instruction_set(default_float_type, instruction_set=instruction_set)
     kernel_ast.instruction_set = vector_is
@@ -164,7 +163,7 @@ def vectorize_inner_loops_and_adapt_load_stores(ast_node, assume_aligned, nontem
             if len(loop_nodes) == 0:
                 continue
             loop_node = loop_nodes[0]
-            # TODO loop_node is the vectorized one
+            # loop_node is the vectorized one
 
         # Find all array accesses (indexed) that depend on the loop counter as offset
         loop_counter_symbol = ast.LoopOverCoordinate.get_loop_counter_symbol(loop_node.coordinate_to_loop_over)
@@ -258,7 +257,7 @@ def insert_vector_casts(ast_node, instruction_set, default_float_type='double'):
     handled_functions = (sp.Add, sp.Mul, fast_division, fast_sqrt, fast_inv_sqrt, vec_any, vec_all, DivFunc,
                          sp.UnevaluatedExpr, sp.Abs)
 
-    def visit_expr(expr, default_type='double'):  # TODO get rid of default_type
+    def visit_expr(expr, default_type='double'):  # TODO Vectorization Revamp: get rid of default_type
         if isinstance(expr, VectorMemoryAccess):
             return VectorMemoryAccess(*expr.args[0:4], visit_expr(expr.args[4], default_type), *expr.args[5:])
         elif isinstance(expr, CastFunc):
@@ -325,14 +324,13 @@ def insert_vector_casts(ast_node, instruction_set, default_float_type='double'):
         elif isinstance(expr, (sp.Number, TypedSymbol, BooleanAtom)):
             return expr
         else:
-            # TODO better error string
-            raise NotImplementedError(f'Should I raise or should I return now? {type(expr)} {expr}')
+            raise NotImplementedError(f'Due to defensive programming we handle only specific expressions.\n'
+                                      f'The expression {expr} of type {type(expr)} is not known yet.')
 
     def visit_node(node, substitution_dict, default_type='double'):
         substitution_dict = substitution_dict.copy()
         for arg in node.args:
             if isinstance(arg, ast.SympyAssignment):
-                # TODO only if not remainder loop (? if no VectorAccess then remainder loop)
                 assignment = arg
                 # If there is a remainder loop we do not vectorise it, thus lhs will indicate this
                 # if isinstance(assignment.lhs, ast.ResolvedFieldAccess):
diff --git a/pystencils/fast_approximation.py b/pystencils/fast_approximation.py
index 65f85a71a25e2da0082a61a5418ce4c4eb656af0..ab0dc59740e9ec7fcd3e59eb826979cd5350aa3f 100644
--- a/pystencils/fast_approximation.py
+++ b/pystencils/fast_approximation.py
@@ -9,17 +9,25 @@ from pystencils.assignment import Assignment
 
 # noinspection PyPep8Naming
 class fast_division(sp.Function):
-    # TODO how is this fast? The printer prints a normal division???
+    """
+    Produces special float instructions for CUDA kernels
+    """
     nargs = (2,)
 
 
 # noinspection PyPep8Naming
 class fast_sqrt(sp.Function):
+    """
+    Produces special float instructions for CUDA kernels
+    """
     nargs = (1, )
 
 
 # noinspection PyPep8Naming
 class fast_inv_sqrt(sp.Function):
+    """
+    Produces special float instructions for CUDA kernels
+    """
     nargs = (1, )
 
 
diff --git a/pystencils/field.py b/pystencils/field.py
index ceaeb82acc1a5eebfa6880fe5b8004ed832ee415..e92cac4046400061b19d851755af63db76dea110 100644
--- a/pystencils/field.py
+++ b/pystencils/field.py
@@ -319,7 +319,7 @@ class Field:
         assert isinstance(field_type, FieldType)
         assert len(shape) == len(strides)
         self.field_type = field_type
-        self._dtype = create_type(dtype)  # TODO do we have AoS???
+        self._dtype = create_type(dtype)
         self._layout = normalize_layout(layout)
         self.shape = shape
         self.strides = strides
diff --git a/pystencils/functions.py b/pystencils/functions.py
index c499d04ed6fcb1274639eb9791955db69c9619bf..722c2c5d410dd81968cc593871c6714bbbba1645 100644
--- a/pystencils/functions.py
+++ b/pystencils/functions.py
@@ -3,7 +3,9 @@ from pystencils.typing import PointerType
 
 
 class DivFunc(sp.Function):
-    # TODO: documentation
+    """
+    DivFunc represents a division operation, since sympy represents divisions with ^-1
+    """
     is_Atom = True
     is_real = True
 
@@ -27,8 +29,9 @@ class DivFunc(sp.Function):
 
 
 class AddressOf(sp.Function):
-    # TODO: docstring
-    # this is '&' in C
+    """
+    AddressOf is the '&' operation in C. It gets the address of a lvalue.
+    """
     is_Atom = True
 
     def __new__(cls, arg):
diff --git a/pystencils/integer_functions.py b/pystencils/integer_functions.py
index 1975a877e36787466d1d2ffb7f4aec8a5791d341..cd0e6f231edc754bcf4c5d7e991e6048c623a45c 100644
--- a/pystencils/integer_functions.py
+++ b/pystencils/integer_functions.py
@@ -1,4 +1,4 @@
-# TODO move to a module functions
+# TODO #47 move to a module functions
 import numpy as np
 import sympy as sp
 
diff --git a/pystencils/kernel_contrains_check.py b/pystencils/kernel_contrains_check.py
index 7f7756d6f0318930c9e4d85656ce6314146da666..f79677656874dbe14c7bf7658e6b9534a6be18c1 100644
--- a/pystencils/kernel_contrains_check.py
+++ b/pystencils/kernel_contrains_check.py
@@ -13,8 +13,8 @@ from pystencils.transformations import NestedScopes
 
 accepted_functions = [
     sp.Pow,
-    sp.sqrt,  # TODO why not a class??
-    # TODO trigonometric functions
+    sp.sqrt,
+    # TODO trigonometric functions (and whatever tests will fail)
 ]
 
 
@@ -76,7 +76,7 @@ class KernelConstraintsCheck:
         self.process_lhs(assignment.lhs)
 
     def process_expression(self, rhs):
-        # TODO constraint for accepted functions
+        # TODO constraint for accepted functions, see TODO above
         self.update_accesses_rhs(rhs)
         if isinstance(rhs, Field.Access):
             self.fields_read.add(rhs.field)
diff --git a/pystencils/kernelcreation.py b/pystencils/kernelcreation.py
index bfb2c09a37323ff30943f19396e0f3d5ef65a519..cd744a0d9ad318792c7f6318bee3fbd41aa4746a 100644
--- a/pystencils/kernelcreation.py
+++ b/pystencils/kernelcreation.py
@@ -65,7 +65,7 @@ def create_kernel(assignments: Union[Assignment, List[Assignment], AssignmentCol
     if isinstance(assignments, list):
         assignments = NodeCollection(assignments)
     elif isinstance(assignments, AssignmentCollection):
-        # TODO check and doku
+        # TODO Markus check and doku
         # --- applying first default simplifications
         try:
             if config.default_assignment_simplifications:
@@ -135,7 +135,6 @@ def create_domain_kernel(assignments: NodeCollection, *, config: CreateKernelCon
     if config.target == Target.CPU:
         if config.backend == Backend.C:
             from pystencils.cpu import add_openmp, create_kernel
-            # TODO: data type keyword should be unified to data_type
             ast = create_kernel(assignments, config=config)
             for optimization in config.cpu_prepend_optimizations:
                 optimization(ast)
diff --git a/pystencils/simp/simplifications.py b/pystencils/simp/simplifications.py
index 086ff984115d5fcf03ed49dac45850cb17bd8c62..5ed8c4ea9ee62fca33933eead71be6fff5571704 100644
--- a/pystencils/simp/simplifications.py
+++ b/pystencils/simp/simplifications.py
@@ -225,9 +225,10 @@ def apply_on_all_subexpressions(operation: Callable[[sp.Expr], sp.Expr]):
     return f
 
 # TODO Markus
-# TODO: make this really work for Assignmentcollections
-# TODO: this function should ONLY evaluate
-# TODO: do the optims_c99 elsewhere optionally
+# make this really work for Assignmentcollections
+# this function should ONLY evaluate
+# do the optims_c99 elsewhere optionally
+
 # def apply_sympy_optimisations(ac: AssignmentCollection):
 #     """ Evaluates constant expressions (e.g. :math:`\\sqrt{3}` will be replaced by its floating point representation)
 #         and applies the default sympy optimisations. See sympy.codegen.rewriting
diff --git a/pystencils_tests/test_types.py b/pystencils_tests/test_types.py
index 8ac96f84e732debd8e1ff50426c483b6b5523868..16466df5238dde45ae711e124db451c688182e17 100644
--- a/pystencils_tests/test_types.py
+++ b/pystencils_tests/test_types.py
@@ -84,7 +84,6 @@ def test_mixed_add(dtype1, dtype2):
     assert test_f[0] == constant+constant
 
 
-# TODO vector
 def test_collation():
     double_type = BasicType('float64')
     float_type = BasicType('float32')
@@ -159,7 +158,6 @@ def test_sqrt_of_integer(dtype):
     assignments = [ps.Assignment(tmp, sp.sqrt(3)),
                    ps.Assignment(f[0], tmp)]
     arr = np.array([1], dtype=dtype)
-    # TODO Jupyter add auto lhs float/double problem
     config = pystencils.config.CreateKernelConfig(data_type=dtype, default_number_float=dtype)
 
     ast = ps.create_kernel(assignments, config=config)