Skip to content
Programmeren in Python, leer de nieuwste technieken
Programmeren in PythonProgrammeren in Python
  • Home
  • Blog
  • Documentatie
  • Cursussen
Programmeren in PythonProgrammeren in Python
  • Home
  • Blog
  • Documentatie
  • Cursussen

Introductie

4
  • 1.1 Wat is Python?
  • 1.2 Python installatie
  • 1.2.1 Python installeren voor MacOS
  • 1.3 PyCharm Installatie

Basisprogrammering

6
  • 2.1 Python Basis: Variabelen, Datatypes en Operatoren
  • 2.2 Python if else (en elif)
  • 2.3 Python list (Array, Lijsten)
  • 2.4 Python Lussen: for loop, while loop, break, continue
  • 2.5 Python Functies: Definities, Parameters en Terugkeerwaarden
  • 2.6 Foutafhandeling: try, except, else, finally

Datatypes

13
  • 3.1 Introductie tot Geavanceerde Datatypes
  • 3.2 Python Tuple
  • 3.3 Python Set
  • 3.4 Python Dictionary
  • 3.5 Werken met Strings en String-methoden
  • 3.6 Collections Module: Krachtige Tools in Python
  • 3.7 Iterators en Generators
  • 3.8 List Comprehensions
  • 3.9 Geavanceerde Sortering
  • 3.10 Werken met Multi-dimensionale Data
  • 3.11 Typing en Datatypes
  • 3.12 Itertools voor Geavanceerde Iteraties
  • 3.13 Data Conversies

Modules

8
  • 4.1 Wat zijn Modules en Waarom zijn ze Belangrijk?
  • 4.2 Werken met Ingebouwde Modules
  • 4.3 Installeren en Gebruiken van Externe Pakketten
  • 4.4 Eigen Modules Maken
  • 4.5 Introductie tot Pakketten
  • 4.6 Importeren en Namespaces Begrijpen
  • 4.7 Geavanceerd: Relatief Importeren
  • 4.8 Organiseren van Grotere Projecten

Data Analyse

3
  • 5.1 Python Dataframe en Data Opschonen met Pandas
  • 5.2 Python Pandas Basisstatistieken en Data-analyse
  • 5.3 Python Numpy (NpArray): De Kracht van Numerieke Berekeningen

Webontwikkeling

5
  • 7.1 Inleiding tot Webontwikkeling
  • 7.2 HTTP-Verzoeken met requests: Communiceren met het Web
  • 7.3 Webscraping met BeautifulSoup: Data van het Web Halen als er geen APIs zijn
  • 7.4 Python Flask, een webserver & API tutorial
  • 7.5 WSGI & WebOb

Deploy

1
  • Deploy met Supervisor op Ubuntu

Object Georiënteerd Programmeren

8
  • Wat is Objectgeoriënteerd Programmeren (OOP) in Python?
  • Python class & object maken
  • self en __init__ uitgelegd (met voorbeelden)
  • Attributen afschermen: @property (getters/setters)
  • Overerving in Python + super() (en wanneer je het beter níet doet)
  • Dunder methods: __str__, __repr__, vergelijken (en waarom dit je OOP-code “Pythonic” maakt)
  • @dataclass: snelle nette classes (minder boilerplate, meer duidelijkheid)
  • OOP in de praktijk: design & structuur
View Categories
  • Home
  • Documentatie
  • Object Georiënteerd Programmeren
  • OOP in de praktijk: design & structuur

OOP in de praktijk: design & structuur

3 minuten leestijd

Na dit hoofdstuk kun je:

  • bepalen welke classes je überhaupt nodig hebt,
  • verantwoordelijkheid goed verdelen (zodat je geen “mega class” krijgt),
  • kiezen tussen overerving en compositie met heldere redenen,
  • en je begrijpt een paar “best practices” die je code onderhoudbaar maken.

1. Hoe bedenk je classes? Begin bij “dingen” en “regels” #

Een handige manier om classes te vinden:

  1. Schrijf in gewone taal op wat je systeem doet.
  2. Onderstreep de zelfstandige naamwoorden → kandidaten voor classes (“dingen”).
  3. Onderstreep de werkwoorden → kandidaten voor methodes (gedrag).
  4. Onderstreep regels → invarianten/validatie die bij een object horen.

Voorbeeldzin:
“Een order bevat orderregels en kan betaald worden.”

  • dingen: Order, OrderLine, Payment
  • gedrag: add_line(), pay()
  • regels: “Je kunt niet betalen als er geen regels zijn”, “betaald = kan niet opnieuw”

Dit voorkomt dat je meteen in code schiet zonder structuur.

2) “Een class moet één reden hebben om te veranderen” (SRP, maar simpel uitgelegd) #

Je hoeft SOLID niet te memoriseren. Deze ene zin is vaak genoeg:

Als je class meerdere soorten problemen oplost, wordt hij rommelig.

Voorbeeld van een te brede class #

User die:

  • wachtwoorden hasht,
  • emails verstuurt,
  • database opslaat,
  • én permissions checkt.

Dat zorgt voor:

  • moeilijk testen,
  • veel afhankelijkheden,
  • elke kleine wijziging breekt iets anders.
Beter: verantwoordelijkheid splitsen #
  • User → alleen user data + regels (state/gedrag)
  • PasswordHasher → hashing logic
  • EmailSender → mail
  • UserRepository → opslag

Praktische test:
Kun je de class in één zin beschrijven zonder “en”?
Als je “en” nodig hebt, is het vaak te veel.

3. Encapsulation: hou state consistent door methodes #

Een veelgemaakte beginnersfout is “van buiten” aan state trekken en duwen:

order.total -= 10
order.status = "paid"
Python

Dat lijkt makkelijk, maar:

  • regels worden omzeild,
  • state kan inconsistent worden.

Beter: geef intentie-methodes

order.apply_discount(10)
order.mark_paid()
Python

Waarom dit beter is:

  • alle checks zitten op één plek,
  • je object blijft altijd “geldig”.

Dit is de kern van OOP: objecten bewaken hun eigen regels.

4. Composition over inheritance (maar met echte uitleg) #

Overerving is verleidelijk, maar vaak te rigide.
Compositie is vaak flexibeler:

  • Overerving: “ik bén dit”
  • Compositie: “ik héb dit / ik gebruik dit”
Waarom compositie vaak wint #

Omdat je gedrag kunt “pluggen” zonder inheritance-explosies.

Voorbeeld: je wil betaalmethodes kunnen wisselen.
Niet:

  • OrderWithPaypal
  • OrderWithCard
  • OrderWithIdeal

Maar:

class Order:
    def __init__(self, payment_provider):
        self.payment_provider = payment_provider

    def pay(self, amount):
        return self.payment_provider.pay(amount)
Python

Dan kan payment_provider Paypal/Card/iDEAL zijn, zonder subclasses van Order.

Vuistregel:

  • Overerving voor echte “is-a” relaties.
  • Compositie voor variatie in gedrag (“strategy”), integraties, features.

5. Maak afhankelijkheden expliciet (Dependency Injection “light”) #

Veel code wordt “moeilijk” omdat classes dingen intern aanmaken:

class InvoiceService:
    def __init__(self):
        self.client = SomeApiClient()  # hard-coded
Python

Probleem:

  • lastig te testen (je zit vast aan echte API),
  • lastig te vervangen.

Beter: geef dependencies mee:

class InvoiceService:
    def __init__(self, client):
        self.client = client
Python

Nu kun je:

  • in productie een echte client geven,
  • in tests een fake/mock client.

Dit is een hele praktische OOP-skill.

6. Kies je “public API” bewust: wat mogen anderen gebruiken? #

Een class is makkelijker te gebruiken als hij een klein, duidelijk setje methodes/attributen heeft.

  • Public: wat je “belooft” stabiel te houden
  • Intern: wat je later nog wil kunnen aanpassen

Python-conventie:

  • self._x → intern
  • self.x / methodes zonder underscore → publiek

Tip: maak je publieke API klein:

  • liever 3 duidelijke methodes dan 12 half-overlappende.

7. Houd objecten klein en testbaar (praktisch) #

Een testbare class is meestal:

  • klein,
  • doet één ding,
  • heeft weinig externe afhankelijkheden,
  • heeft methodes die deterministisch zijn.

Als je merkt:

  • je moet 10 dingen “mocken” om één methode te testen,
    dan is je class vaak te druk.

8. Veelvoorkomende “code smells” in OOP (herkennen = voorkomen) #

8.1 God object / Mega class #

Eén class die “alles” weet en doet.

Symptomen:

  • 500+ regels
  • veel verschillende verantwoordelijkheden
  • veel private helper methods

Fix: splits op in kleinere classes/services.

8.2 Te diepe inheritance tree #

A -> B -> C -> D -> E
Je bent constant aan het raden waar gedrag vandaan komt.

Fix: compositie / mixins beperken / flatten.

8.3 “Anemic domain model” #

Classes met alleen data, en alle logica zit in losse functies/services.

Fix: zet domeinregels terug in objecten die de data bezitten (encapsulation).

8.4 Te vroeg abstraheren #

Interfaces, base classes, patterns… terwijl je nog maar 1 variant hebt.

Fix: start simpel. Abstracteer pas als je 2–3 echte varianten hebt.

9. Praktische checklist (kort, maar bruikbaar) #

Als je een class maakt, check:

  • Wat is de verantwoordelijkheid (in één zin)?
  • Welke regels moet deze class bewaken?
  • Welke state hoort echt bij dit object?
  • Welke afhankelijkheden kan ik injecteren i.p.v. intern aanmaken?
  • Is dit “is-a” (overerving) of “has-a” (compositie)?
  • Kan iemand dit object verkeerd gebruiken? (zo ja: extra methods/properties)

Updated on januari 4, 2026

What are your Feelings

@dataclass: snelle nette classes (minder boilerplate, meer duidelijkheid)
Inhoudsopgave
  • 1. Hoe bedenk je classes? Begin bij “dingen” en “regels”
  • 2) “Een class moet één reden hebben om te veranderen” (SRP, maar simpel uitgelegd)
    • Voorbeeld van een te brede class
    • Beter: verantwoordelijkheid splitsen
  • 3. Encapsulation: hou state consistent door methodes
  • 4. Composition over inheritance (maar met echte uitleg)
    • Waarom compositie vaak wint
  • 5. Maak afhankelijkheden expliciet (Dependency Injection “light”)
  • 6. Kies je “public API” bewust: wat mogen anderen gebruiken?
  • 7. Houd objecten klein en testbaar (praktisch)
  • 8. Veelvoorkomende “code smells” in OOP (herkennen = voorkomen)
    • 8.1 God object / Mega class
    • 8.2 Te diepe inheritance tree
    • 8.3 “Anemic domain model”
    • 8.4 Te vroeg abstraheren
  • 9. Praktische checklist (kort, maar bruikbaar)
Programmeren in Python

Leer python op je eigen tempo met mooie interactieve hedendaagse voorbeelden.

© Copyright 2026 Programmeren in Python.
Sign inSign up

Sign in

Don’t have an account? Sign up
Lost your password?

Sign up

Already have an account? Sign in