---
title: "Software design principles"
manual: "TYPO3 Explained"
version: "main"
permalink: "https://docs.typo3.org/permalink/t3coreapi:extension-software-design-principles@main"
source: "ExtensionArchitecture/BestPractises/SoftwareDesignPrinciples.rst"
modified: "2026-09-14T11:10:56+00:00"
---

# Software design principles

The following principles are considered best practices and are good to know when you develop
extensions for TYPO3.

-   [Object-Oriented Programming (OOP)](https://phptherightway.com/#programming_paradigms)
    organizes software design around data, or objects, rather than the functions and logic of procedural programming.
-   [Domain-Driven Design (DDD)](https://leanpub.com/ddd-in-php) is a
    collection of principles and patterns that help developers design elegant
    code around clearly defined conceptual models.
-   [Model-View-Controller (MVC)](https://code.tutsplus.com/tutorials/mvc-for-noobs--net-10488)
    is a programming paradigm that leads to clear isolation of data,
    presentation layer, and business logic.
-   [Test-Driven Development (TDD)](https://phptherightway.com/#test_driven_development)
    is a basic technique for generating code that is stable,
    resilient to errors, and legible — and therefore maintainable.
-   [Dependency Injection](https://phptherightway.com/#dependency_injection)
    is a software design pattern that adds flexibility by removing the need
    for hard-coded dependencies.
-   [Separation of Concerns](https://en.wikipedia.org/wiki/Separation_of_concerns)
    and [Single-responsibility principle (SRP)](https://en.wikipedia.org/wiki/Single-responsibility_principle)
    are computer programming principles that help developers create modular,
    coherent, and maintainable software.

We also recommend to study common [software design
patterns](https://designpatternsphp.readthedocs.io/en/latest/).

## Data transfer objects (DTO) as a software design concept

A very common pattern in Extbase extensions is a DTO.

A DTO is an instance of a basic class that usually only has a constructor,
getters and setters. It is not meant to be an extension of an Extbase `AbstractEntity`.

This DTO serves as pure data storage. You can use it to receive and retrieve
data in a `<f:form>` Fluid
[CRUD](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete)
("Create Read Update Delete") setup.

Later on, the DTO can be accessed and converted into a "proper" Extbase domain model
entity: The DTO getters retrieve the data, and the Extbase domain model entity's setters
receive that data:

**Example of DTO and AbstractEntity used in an Extbase controller**

```php
<?php

declare(strict_types=1);

use TYPO3\CMS\Core\Utility\GeneralUtility;

// The actual "plain" DTO, just setters and getters
class PersonDTO
{
  protected string $first_name;
  protected string $last_name;

  public function getFirstName(): string
  {
    return $this->first_name;
  }

  public function setFirstName(string $first_name): void
  {
    $this->first_name = $first_name;
  }

  public function getLastName(): string
  {
    return $this->last_name;
  }

  public function setLastName(string $last_name): void
  {
    $this->last_name = $last_name;
  }
}

// The Extbase domain model entity.
// Note that the getters and setters can easily be mapped
// to the DTO due to their same names!
class Person extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
{
  protected string $first_name;
  protected string $last_name;

  public function getFirstName(): string
  {
    return $this->first_name;
  }

  public function setFirstName(string $first_name): void
  {
    $this->first_name = $first_name;
  }

  public function getLastName(): string
  {
    return $this->last_name;
  }

  public function setLastName(string $last_name): void
  {
    $this->last_name = $last_name;
  }
}

// An Extbase controller utilizing DTO-to-entity transfer
class DtoController extends TYPO3\CMS\Extbase\Mvc\Controller\ActionController
{
  public function __construct(protected MyVendor\MyExtension\Domain\Repository\PersonRepository $personRepository) {}

  public function createAction(): Psr\Http\Message\ResponseInterface
  {
    // Set up a DTO to be filled with input data.
    // The Fluid template would use <f:form> and its helpers.
    $this->view->assign('personDTO', new PersonDTO());
  }

  public function saveAction(PersonDTO $personDTO): Psr\Http\Message\ResponseInterface
  {
    // Transfer all data to a proper Extbase entity.
    // Create an empty entity first:
    $person = GeneralUtility::makeInstance(Person::class);

    // Use setters/getters for propagation
    $person->setFirstName($personDTO->getFirstName());
    $person->setLastName($personDTO->getLastName());

    // Persist the extbase entity
    $this->personRepository->add($person);

    // The "old" DTO needs to further processing.
  }
}

```

DTOs are helpful because:

-   They allow to decouple pure data from processed/validated data in entities.
-   They allow to structure data into distinct data models.
-   They allow to use good type hinting and using setters/getters instead of using
    untyped and unstructured PHP arrays for data storage.
-   They can be used to hide implementation details of your actual entities by transferring
    data like filter settings that internally gets applied to actual data models.

> [!NOTE]
> **See also**
>
> -   [Extbase reference: Data transfer objects (DTO) in Extbase](https://usetypo3.com/dtos-in-extbase/)
> -   [usetypo3.com: Data Transfer Objects in Extbase](https://usetypo3.com/dtos-in-extbase/)
