[{"data":1,"prerenderedAt":40},["ShallowReactive",2],{"site-settings-batix":3,"batix-blog-ein-schichtenmodell-das-mitwaechst-controller-service-repository-dto":22,"page-seo-\u002Fblog\u002Fein-schichtenmodell-das-mitwaechst-controller-service-repository-dto":12},{"id":4,"user_created":5,"date_created":6,"user_updated":7,"date_updated":8,"site_name":9,"site_url":10,"tagline":11,"default_og_image":12,"favicon":12,"organization_legal_name":13,"organization_email":14,"organization_phone":15,"organization_address_street":16,"organization_address_zip":17,"organization_address_city":18,"organization_address_country":19,"social_linkedin":20,"social_xing":21,"social_youtube":21,"social_instagram":21,"google_site_verification":12},"368daec2-c06c-4d64-bba7-feb859b94322","4686f9ba-fccc-4a50-9410-b80ae06ef0eb","2026-05-07T15:29:22.000Z","7d85c00d-d619-4d10-86a2-a469f8283bfc","2026-08-12T12:11:25.000Z","Batix","https:\u002F\u002Fbatix.swiss","Ihr Partner für IT-Beratung, Lösungen und massgeschneiderte Softwareentwicklung in der Schweiz.",null,"Batix Schweiz AG","info@batix.ch","+41 44 545 32 70","Grindlenstrasse 3","8954","Geroldswil","Schweiz","https:\u002F\u002Fwww.linkedin.com\u002Fcompany\u002Fbatix\u002F","",{"id":23,"title":24,"slug":25,"subtitle":26,"category":27,"cover_image":28,"lead_text":29,"definition":30,"content":31,"graphic":32,"graphic_caption":33,"faqs":12,"cta_text":34,"cta_label":35,"cta_url":36,"author":37,"published_at":38,"date_updated":39},"1ee93900-351b-40ae-b852-b08acf597695","Ein Schichtenmodell, das mitwächst: Controller, Service, Repository, DTO","ein-schichtenmodell-das-mitwaechst-controller-service-repository-dto","Wie eine klare Trennung zwischen Controller, Service und Repository aus schwer wartbarem Code eine wiederverwendbare Basis macht und wo sie an ihre Grenzen stösst.","Development","be03a899-157a-4c5b-90e7-9613574fc4af","Viele Softwareprojekte starten schlank. Ein Controller nimmt Anfragen entgegen, eine Klasse spricht direkt mit der Datenbank, fertig. Nach ein paar Jahren und etlichen neuen Features sieht das anders aus: Datenbankzugriffe, Geschäftslogik und Schnittstellencode liegen in denselben Klassen, jede Änderung zieht unvorhergesehene Nebenwirkungen nach sich, und Reviews dauern länger, weil niemand mit Sicherheit sagt, was eine Anpassung sonst noch betrifft.\nBei Batix stand die Softwareentwicklung genau vor diesem Problem, als das Team die Architektur für BX:EDUCATION plante. Die Lösung war ein Schichtenmodell mit klar getrennten Verantwortlichkeiten – Controller, Service, Repository, dazwischen DTOs und Models. Eingeführt wurde das Muster zuerst dort, inzwischen ist es in mehreren weiteren Batix-Projekten im Einsatz und wird von Projekt zu Projekt weiter verfeinert.\n","Eine Schichtenarchitektur trennt eine Anwendung in klar abgegrenzte Ebenen, etwa Controller, Service und Repository, die ausschliesslich über definierte Schnittstellen wie DTOs und Models miteinander kommunizieren.","\u003Cp>\u003Cstrong>\u003Cspan style=\"color: #2e5b7f;\">Warum gewachsener Code irgendwann bremst\u003C\u002Fspan>\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom: 8.0pt;\">Ohne klare Trennung landen Datenbankzugriff, Validierung und Gesch&auml;ftslogik oft in derselben Klasse. Das funktioniert an Tag eins. Mit jedem neuen Feature w&auml;chst aber die Zahl der Stellen, die bei einer &Auml;nderung mitbedacht werden m&uuml;ssen. Ein Feld in der Datenbank umzubenennen heisst dann, Controller, Validierung und Anzeige-Logik gleichzeitig anzupassen &ndash; und zu hoffen, keine der Stellen &uuml;bersehen zu haben. Ein typisches Symptom: Ein Pull Request f&uuml;r eine kleine fachliche &Auml;nderung w&auml;chst schnell auf mehrere hundert Zeilen an, weil dieselbe Logik an drei oder vier Stellen im Code nachgezogen werden muss.\u003C\u002Fp>\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom: 8.0pt;\">Bei Batix war genau das der Ausgangspunkt f&uuml;r BX:EDUCATION: Der bestehende Code liess sich kaum noch warten oder erweitern, ohne an anderer Stelle etwas zu brechen. Der Aufwand f&uuml;r ein Refactoring, das diese Kopplung aufl&ouml;st, wirkt zu Beginn hoch. Er zahlt sich aber genau dann aus, wenn ein Projekt &uuml;ber Jahre w&auml;chst statt nach einem Release zu enden.\u003C\u002Fp>\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom: 8.0pt;\">\u003Cstrong>\u003Cspan style=\"color: #2e5b7f;\">Die Aufteilung: Controller, DTO, Service, Model, Repository\u003C\u002Fspan>\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom: 8.0pt;\">Der Controller nimmt Anfragen entgegen und gibt sie als DTO an den Service weiter. Ein DTO transportiert nur das, was die Schnittstelle nach aussen braucht, unabh&auml;ngig davon, wie die Daten intern gespeichert sind. Der Service enth&auml;lt die Gesch&auml;ftslogik und spricht mit dem Repository &uuml;ber ein Model. Models bilden die Datenbank-Entit&auml;ten eins zu eins ab. Ein Beispiel: Eine interne Spalte wie ein Bearbeitungs-Flag oder ein technischer Zeitstempel geh&ouml;rt ins Model, weil sie Teil der Datenbank-Entit&auml;t ist. &Uuml;ber die API muss sie deshalb noch lange nicht sichtbar sein, das entscheidet allein das DTO.\u003C\u002Fp>\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom: 8.0pt;\">Diese Trennung hat einen konkreten Vorteil: &Auml;ndert sich die Datenbankstruktur, betrifft das nur Model und Repository. &Auml;ndert sich die externe Schnittstelle, betrifft das nur das DTO. Beides l&auml;sst sich unabh&auml;ngig voneinander anpassen und testen. Ein weiterer Effekt zeigt sich beim Testen selbst: Der Service l&auml;sst sich mit einem gemockten Repository pr&uuml;fen, ohne dass ein Test gegen eine echte Datenbank laufen muss.\u003C\u002Fp>\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom: 8.0pt;\">\u003Cstrong>\u003Cspan style=\"color: #2e5b7f;\">Wiederverwendbare Queries dank AbstractRepository\u003C\u002Fspan>\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom: 8.0pt;\">Weil jedes Model eins zu eins einer Datenbank-Entit&auml;t entspricht, liess sich ein grosser Teil der Datenbankabfragen nicht mehr pro Repository einzeln schreiben, sondern einmal in einem gemeinsamen AbstractRepository. Suchen, Filtern und Paginieren stehen damit f&uuml;r jede neue Entit&auml;t sofort zur Verf&uuml;gung, ohne dass jemand dieselbe Query ein weiteres Mal implementiert. Je mehr Entit&auml;ten im Laufe der Zeit dazukamen, desto deutlicher zeigte sich der Effekt: Ein neues Repository musste oft nur noch die fachlichen Ausnahmen erg&auml;nzen, der gr&ouml;ssere Teil kam bereits aus der gemeinsamen Basis.\u003C\u002Fp>\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom: 8.0pt;\">\u003Cem>Sascha, der die Architektur bei Batix mitentwickelt hat:\u003C\u002Fem>\u003C\u002Fp>\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom: 8.0pt;\">\u003Cem>&laquo;Weil unsere Models die Datenbank-Entit&auml;ten eins zu eins abbilden, liessen sich sehr viele Queries in einem AbstractRepository einmal bauen und dann in allen Plugins wiederverwenden. Der alte Code liess sich davor kaum noch warten oder erweitern.&raquo;\u003C\u002Fem>\u003C\u002Fp>\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom: 8.0pt;\">\u003Cstrong>\u003Cspan style=\"color: #2e5b7f;\">Die Grenze: Plugin-Architektur und geteilte Datenzugriffs-Logik\u003C\u002Fspan>\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom: 8.0pt;\">Der Ansatz st&ouml;sst an eine Grenze, sobald mehrere Plugins auf dieselbe Datenbank zugreifen m&uuml;ssen. Bei BX:EDUCATION lag der datenbanknahe Code, Models und Repositories, zuerst nur in einem einzelnen Plugin. Andere Plugins brauchten diesen Code aber ebenfalls und hatten keinen sauberen Zugriff darauf.\u003C\u002Fp>\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom: 8.0pt;\">Sascha:\u003C\u002Fp>\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom: 8.0pt;\">\u003Cem>&laquo;Wir hatten die Datenbank-Seite mit Models und Repositories zuerst nur in einem Plugin. Andere Plugins brauchten diesen Code aber auch. Am Ende mussten wir das in eine eigene Library auslagern &ndash; und die nachtr&auml;glich in jedes Plugin zu integrieren, war aufw&auml;ndig und m&uuml;hsam.&raquo;\u003C\u002Fem>\u003C\u002Fp>\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom: 8.0pt;\">Die L&ouml;sung war eine eigenst&auml;ndige, gemeinsam genutzte Library f&uuml;r den datenbanknahen Teil. Nachtr&auml;glich aufgebaut, liess sie sich nur mit Mehraufwand in die bereits bestehenden Plugins integrieren, jedes Plugin musste einzeln umgestellt werden. Im R&uuml;ckblick h&auml;tte sich dieser Umbau vermeiden lassen, wenn die Datenzugriffsschicht von Beginn an als eigene, plugin-unabh&auml;ngige Library geplant worden w&auml;re.\u003C\u002Fp>\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom: 8.0pt;\">\u003Cstrong>\u003Cspan style=\"color: #2e5b7f;\">Fazit\u003C\u002Fspan>\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom: 8.0pt;\">Wer eine Plugin- oder Modul-Architektur plant, sollte die Datenzugriffsschicht deshalb von Anfang an als eigenst&auml;ndige, gemeinsam nutzbare Komponente denken, nicht als Teil des ersten Plugins, das sie zuf&auml;llig gebraucht hat. Bei Batix ist das Schichtenmodell seit BX:EDUCATION fester Bestandteil neuer Projekte und wird von Fall zu Fall weiter angepasst.\u003C\u002Fp>\n\u003Cp>&nbsp;\u003C\u002Fp>\n\u003Cp>\u003Cstrong>\u003Cspan style=\"font-size: 11.0pt; font-family: 'Arial',sans-serif; mso-fareast-font-family: Arial; color: #2e5b7f; mso-ansi-language: DE-CH; mso-fareast-language: DE-CH; mso-bidi-language: AR-SA;\">H&auml;ufig gestellte Fragen\u003C\u002Fspan>\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom: 2.0pt;\">\u003Cstrong>\u003Cspan style=\"color: #2e5b7f;\">Was ist der Unterschied zwischen einem Model und einem DTO?\u003C\u002Fspan>\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom: 8.0pt;\">Ein Model bildet die Datenbank-Entit&auml;t eins zu eins ab und wird zwischen Service und Repository verwendet. Ein DTO transportiert nur das, was die externe Schnittstelle braucht, und wird zwischen Controller und Service eingesetzt. So bleiben Datenbankstruktur und Programmierschnittstelle unabh&auml;ngig voneinander ver&auml;nderbar, auch wenn sich eine der beiden Seiten &auml;ndert.\u003C\u002Fp>\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom: 8.0pt;\">\u003Cstrong>\u003Cspan style=\"color: #2e5b7f;\">Lohnt sich eine Schichtenarchitektur auch f&uuml;r kleine Projekte?\u003C\u002Fspan>\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom: 8.0pt;\">Bei sehr kleinem Umfang steht der Mehraufwand an zus&auml;tzlichen Files und Mapping-Code oft in keinem guten Verh&auml;ltnis zum Nutzen. Sobald Wartung und Erweiterung &uuml;ber einen l&auml;ngeren Zeitraum absehbar sind, zahlt sich die Trennung aus. Ein guter Anhaltspunkt ist, ob das Projekt voraussichtlich mehrere Jahre und mehrere Personen im Team &uuml;berdauert.\u003C\u002Fp>\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom: 8.0pt;\">\u003Cstrong>\u003Cspan style=\"color: #2e5b7f;\">Was macht ein AbstractRepository?\u003C\u002Fspan>\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom: 8.0pt;\">Es b&uuml;ndelt wiederkehrende Datenbankabfragen wie Suchen, Filtern oder Paginieren an einer Stelle. Einzelne Repositories erben diese Funktionen, statt sie jeweils neu zu implementieren. Neuer, entit&auml;tsspezifischer Code kommt nur noch f&uuml;r die tats&auml;chlichen Ausnahmen dazu.\u003C\u002Fp>\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom: 8.0pt;\">\u003Cstrong>\u003Cspan style=\"color: #2e5b7f;\">Was ist bei einer Plugin-Architektur zus&auml;tzlich zu beachten?\u003C\u002Fspan>\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom: 8.0pt;\">\u003Cstrong>\u003Cspan style=\"color: #2e5b7f;\">&nbsp;\u003C\u002Fspan>\u003C\u002Fstrong>Datenbanknahe Komponenten wie Models und Repositories sollten von Beginn an als eigenst&auml;ndige, gemeinsam nutzbare Library aufgebaut werden. Liegen sie zuerst nur in einem einzelnen Plugin, l&auml;sst sich das sp&auml;ter nur mit Mehraufwand korrigieren, wie die Erfahrung bei BX:EDUCATION zeigt.\u003C\u002Fp>\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom: 8.0pt;\">\u003Cstrong>\u003Cspan style=\"color: #2e5b7f;\">Wo setzt Batix diese Architekturmuster ein?\u003C\u002Fspan>\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom: 8.0pt;\">Eingef&uuml;hrt wurde es bei der Entwicklung von BX:EDUCATION. Seither wird es projektspezifisch verfeinert und kommt in weiteren Batix-Projekten zum Einsatz.\u003C\u002Fp>\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom: 8.0pt;\">&nbsp;\u003C\u002Fp>\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom: 8.0pt;\">&nbsp;\u003C\u002Fp>","10af1bfa-7425-49ca-944c-3b26b4a6c4db","Der Datenfluss von der Anfrage bis zur Datenbank: Controller, DTO, Service, Model, Repository.","Wer eine bestehende Software modernisieren oder ein neues System von Grund auf wartbar aufbauen will, findet in der individuellen Softwareentwicklung der Batix den passenden Ansprechpartner.","Kontakt aufnehmen","\u002Fcontact","Sascha Wechsler","2026-09-28T08:14:00.000Z","2026-09-28T08:14:05.000Z",1790596487371]