window.pipedriveLeadboosterConfig = { base: 'leadbooster-chat.pipedrive.com', companyId: 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version: 2, } ;(function () { var w = Fenster if (w.LeadBooster) { console.warn('LeadBooster existiert bereits') } else { w.LeadBooster = { q: [], on: function (n, h) { this.q.push({ t: 'o', n: n, h: h }) }, trigger: function (n) { this.q.push({ t: 't', n: n }) }, } } })() Objektorientierte Programmierung. Das ist nicht, wie Sie denken - The Codest
Der Codest
  • Über uns
  • Dienstleistungen
    • Software-Entwicklung
      • Frontend-Softwareentwicklung
      • Backend-Softwareentwicklung
    • Staff Augmentation
      • Frontend-Entwickler
      • Backend-Entwickler
      • Daten-Ingenieure
      • Cloud-Ingenieure
      • QS-Ingenieure
      • Andere
    • IT-Beratung
      • Prüfung und Beratung
  • Branchen
    • Fintech & Bankwesen
    • E-commerce
    • Adtech
    • Gesundheitstechnik
    • Herstellung
    • Logistik
    • Automobilindustrie
    • IOT
  • Wert für
    • CEO
    • CTO
    • Delivery Manager
  • Unser Team
  • Fallstudien
  • Gewusst wie
    • Blog
    • Begegnungen
    • Webinare
    • Ressourcen
Karriere Kontakt aufnehmen
  • Über uns
  • Dienstleistungen
    • Software-Entwicklung
      • Frontend-Softwareentwicklung
      • Backend-Softwareentwicklung
    • Staff Augmentation
      • Frontend-Entwickler
      • Backend-Entwickler
      • Daten-Ingenieure
      • Cloud-Ingenieure
      • QS-Ingenieure
      • Andere
    • IT-Beratung
      • Prüfung und Beratung
  • Wert für
    • CEO
    • CTO
    • Delivery Manager
  • Unser Team
  • Fallstudien
  • Gewusst wie
    • Blog
    • Begegnungen
    • Webinare
    • Ressourcen
Karriere Kontakt aufnehmen
Pfeil zurück ZURÜCK
2019-05-06
Software-Entwicklung

Objektorientierte Programmierung. So denken Sie nicht

Pawel Wal

Dank der vielen kostenlosen Ressourcen, Bücher und Online-Kurse kann heute jeder das Programmieren lernen. Dennoch gibt es immer noch eine Qualitätslücke zwischen Programmierung und Softwaretechnik. Muss es eine geben?

Mein erstes "Hello World" habe ich vor über zwanzig Jahren geschrieben - das ist die Antwort, die ich gebe, wenn mich jemand fragt, wie lange ich schon Programmierer bin. In den letzten zehn Jahren habe ich eine Karriere genossen, bei der ich mit Code fast jeden Tag - das ist die Antwort, die ich gebe, wenn ich gefragt werde, wie lange ich schon ein professioneller Programmierer bin.

Wie lange bin ich schon ein Software-Ingenieur? Ich würde sagen, etwa fünf Jahre. Moment mal, diese Zahlen scheinen nicht zusammenzupassen! Was hat sich also geändert? Wen würde ich als Software-Ingenieur bezeichnen, und wen "nur" als Programmierer?

Die Definition eines Software-Ingenieurs

Kodierung ist relativ einfach. Es geht nicht mehr nur um Assembler-Mnemonics auf lächerlich eingeschränkten Systemen. Und wenn Sie etwas so ausdrucksstarkes und leistungsfähiges wie Ruby verwenden, ist es sogar noch einfacher.

Sie nehmen einfach ein Ticket in die Hand, suchen die Stelle, an der Sie Ihren Code einfügen müssen, überlegen sich die Logik, die Sie dort einfügen müssen, und bumm - fertig. Wenn Sie etwas fortgeschrittener sind, sorgen Sie dafür, dass Ihr Code schön ist. Logisch in Methoden aufgeteilt ist. Anständige Spezifikationen hat, die nicht nur den glücklichen Weg testen. Das ist es, was ein guter Programmierer tut.

Ein Softwareentwickler denkt nicht mehr in Methoden und Klassen, zumindest nicht in erster Linie. Nach meiner Erfahrung denkt ein Software-Ingenieur in Flüssen. Sie sehen in erster Linie den tosenden, wütenden Fluss von Daten und Interaktionen, der durch das System braust. Sie denken darüber nach, was sie tun müssen, um diesen Fluss umzuleiten oder zu verändern. Der schöne Code, die logischen Methoden und die großartigen Spezifikationen kommen fast wie ein nachträglicher Einfall.

Schildkröten auf dem Weg nach unten

Im Allgemeinen denken die Menschen bei den meisten Interaktionen mit der Realität auf eine bestimmte Weise. Nennen wir es in Ermangelung eines besseren Begriffs die "Top-down"-Perspektive. Wenn mein Gehirn damit beschäftigt ist, mir eine Tasse Tee zu machen, wird es zuerst die allgemeinen Schritte herausfinden: in die Küche gehen, den Wasserkocher aufsetzen, die Tasse zubereiten, Wasser einschenken, an den Schreibtisch zurückkehren.

Er wird nicht zuerst herausfinden, welche Tasse er zuerst benutzen soll, wenn ich entspannt am Schreibtisch sitze; das wird später geschehen, wenn ich vor dem Schrank stehe. Er wird nicht daran denken, dass wir vielleicht keinen Tee mehr haben (oder zumindest nicht mehr den gut Zeug). Es ist breit angelegt, reaktiv und fehleranfällig. Alles in allem - sehr menschlich in der Natur.

Wenn der Software-Ingenieur über Änderungen an dem etwas verwirrenden Datenfluss nachdenkt, wird er dies natürlich auf ähnliche Weise tun. Betrachten wir dieses Beispiel einer User Story:

Ein Kunde bestellt ein Widget. Bei der Preisgestaltung für den Auftrag muss Folgendes berücksichtigt werden:

  • Grundpreis des Widgets in der Region des Nutzers
  • Widgetform (Preismodifikator)
  • ob es sich um einen Eilauftrag handelt (Preismodifikator)
  • ob die Lieferung der Bestellung an einem Feiertag im Land des Nutzers erfolgt (Preismodifikator)

Das alles mag konstruiert erscheinen (und ist es natürlich auch), aber es ist nicht weit entfernt von einigen tatsächlichen Anwenderberichten, die ich in letzter Zeit erleben durfte.

Lassen Sie uns nun den Gedankengang durchgehen, den ein Software-Ingenieur anwenden könnte, um dies zu bewältigen:

"Nun, wir müssen den Benutzer und seine Bestellung erfassen. Dann fangen wir an, die Summe zu berechnen. Wir beginnen bei Null. Dann wenden wir den Modifikator für die Widgetform an. Dann die Eilgebühr. Dann schauen wir, ob es ein Feiertag ist, und schon ist die Bestellung vor dem Mittagessen fertig!"

Ah, der Rausch, den eine einfache Benutzergeschichte auslösen kann. Aber der Software-Ingenieur ist nur ein Mensch und keine perfekte Multi-Thread-Maschine, und das obige Rezept ist nur ein grober Entwurf. Der Ingenieur denkt dann tiefer:

"Der Modifikator für die Form des Widgets ist... oh, das ist sehr abhängig vom Widget, nicht wahr. Und sie können je nach Gebietsschema unterschiedlich sein, wenn auch nicht jetzt, so doch in Zukunft. Sie denken, dass sie zuvor durch veränderte Geschäftsanforderungen verbrannt wurden, "und die Eilzuschläge könnten auch sein. Und Feiertage sind auch super ortsspezifisch, augh, und Zeitzonen werden beteiligt sein! Ich hatte hier einen Artikel über den Umgang mit Zeiten in verschiedenen Zeitzonen in Rails hier... ooh, ich frage mich, ob die Bestellzeit mit Zone in der Datenbank gespeichert ist! Ich überprüfe besser das Schema."

In Ordnung, Software-Ingenieur. Stopp. Du sollst dir eigentlich eine Tasse Tee machen, aber du sitzt vor dem Schrank und überlegst, ob die geblümte Tasse überhaupt für dein Teeproblem geeignet ist.

Das Widget für die perfekte Tasse

Aber das kann leicht passieren, wenn man versucht, etwas zu tun, das für das menschliche Gehirn so unnatürlich ist wie das Denken in mehreren Detailtiefen gleichzeitig.

Nach einem kurzen Stöbern in ihrem geräumigen Arsenal an Links zur Handhabung von Zeitzonen reißt sich unser Ingenieur zusammen und fängt an, dies in konkreten Code umzusetzen. Wenn sie den naiven Ansatz versuchen würden, könnte es ungefähr so aussehen:

 def preisberechnung(benutzer, auftrag)
   bestellung.preis = 0
   bestellung.preis = WidgetPreise.find_by(widget_type: bestellung.widget.typ).preis
   auftrag.preis = WidgetFormen.find_by(widget_form: auftrag.widget.form).modifier
   ...
 end

Und so ging es weiter und weiter, auf diese herrlich prozedurale Art und Weise, nur um dann bei der ersten Codeüberprüfung schwer zu scheitern. Denn wenn man darüber nachdenkt, ist es völlig normal, so zu denken: erst die groben Züge, und die Details viel später. Sie haben anfangs gar nicht gedacht, dass Sie aus dem guten Tee raus sind, oder?

Unser Techniker ist jedoch gut geschult und ihm ist das Serviceobjekt nicht fremd, so dass er stattdessen Folgendes tut:

class BaseOrderService
def self.call(benutzer, auftrag)
new(benutzer, auftrag).call
end

def initialize(benutzer, auftrag)
@Benutzer = Benutzer
@Auftrag = Auftrag
end

def aufruf
puts "[WARN] Implementiere Nicht-Standardaufruf für #{self.class.name}!"
benutzer, auftrag
end
end

class WidgetPriceService < BaseOrderService; end
Klasse ShapePriceModifier < BaseOrderService; end
Klasse RushPriceModifier < BaseOrderService; end
class HolidayDeliveryPriceModifier < BaseOrderService; end

class OrderPriceCalculator < BaseOrderService
def Aufruf
Benutzer, Bestellung = WidgetPriceService.call(Benutzer, Bestellung)
benutzer, auftrag = ShapePriceModifier.call(benutzer, auftrag)
benutzer, auftrag = RushPriceModifier.call(benutzer, auftrag)
benutzer, bestellung = HolidayDeliveryPriceModifier.call(benutzer, bestellung)
Benutzer, Bestellung
end
end
```

Gut! Jetzt können wir etwas gutes TDD anwenden, einen Testfall dafür schreiben und die Klassen ausbauen, bis alle Teile an ihrem Platz sind. Und schön wird es auch noch sein.

Und es ist auch völlig unmöglich, darüber nachzudenken.

Der Feind ist der Staat

Sicher, das sind alles gut getrennte Objekte mit einzelnen Verantwortlichkeiten. Aber hier ist das Problem: Es sind immer noch Objekte. Das Dienstobjektmuster mit seinem "zwangsweise vorgeben, dass dieses Objekt eine Funktion ist" ist wirklich eine Krücke. Es gibt nichts, was jemanden daran hindert, die Funktion HolidayDeliveryPriceModifier.new(user, order).something_else_entirely. Nichts hindert die Menschen daran, diesen Objekten einen internen Status hinzuzufügen.

Nicht zu vergessen Benutzer und Bestellung sind ebenfalls Objekte, und sie zu manipulieren ist so einfach, wie wenn jemand heimlich eine schnelle bestellen.speichern irgendwo in diesen ansonsten "reinen" funktionalen Objekten die zugrundeliegende Quelle des Zustands der Wahrheit, auch bekannt als Datenbank, verändern. In diesem konstruierten Beispiel ist das keine große Sache, aber es kann sich als nachteilig erweisen, wenn das System an Komplexität zunimmt und sich in zusätzliche, oft asynchrone Teile ausdehnt.

Der Ingenieur hatte die richtige Idee. Und er benutzte eine sehr natürliche Art, diese Idee auszudrücken. Aber zu wissen, wie diese Idee auszudrücken ist - auf eine schöne und leicht zu begründende Weise - wurde durch das zugrundeliegende OOP-Paradigma fast verhindert. Und wenn jemand, der noch nicht den Sprung geschafft hat, seine Gedanken als Ablenkungen des Datenflusses auszudrücken, versucht, den zugrundeliegenden Code weniger geschickt zu verändern, werden schlechte Dinge passieren.

Funktional rein werden

Wenn es doch nur ein Paradigma gäbe, in dem die Formulierung von Ideen in Form von Datenflüssen nicht nur einfach, sondern notwendig wäre. Wenn die Argumentation einfach wäre, ohne die Möglichkeit, unerwünschte Nebeneffekte einzuführen. Wenn Daten unveränderlich wären, so wie die Blumentasse, in der Sie Ihren Tee zubereiten.

Ja, ich scherze natürlich nur herum. Dieses Paradigma existiert, und es heißt funktionale Programmierung.

Schauen wir uns an, wie das obige Beispiel in einem persönlichen Favoriten, Elixir, aussehen könnte.

defmodule WidgetPreise do
def preisbestellung([benutzer, bestellung]) do
[Benutzer, Bestellung]
|> widgetprice
|> formPreisModifizierer
|> rushpricemodifier
|> Feiertagspreismodifikator
Ende

defp widgetprice([Benutzer, Bestellung]) do
%{widget: widget} = Bestellung
Preis = WidgetRepo.getbase_price(widget)
[benutzer, %{bestellung | preis: preis }]
end

defp shapepricemodifier([user, order]) do
%{widget: widget, Preis: currentprice} = Bestellung
modifier = WidgetRepo.getshapeprice(widget)
[Benutzer, %{Bestellung | Preis: aktuellerPreis * Modifikator} ]
end

defp rushpricemodifier([user, order]) do
%{Eile: Eile, Preis: aktuellerPreis} = Bestellung
if rush do
[Benutzer, %{Bestellung | Preis: aktuellerPreis * 1.75} ]
sonst
[Benutzer, %{Bestellung | Preis: aktueller_Preis} ]
end
end

defp urlaubspreismodifizierer([benutzer, bestellung]) do
%{Datum: Datum, Preis: aktuellerPreis} = Bestellung
modifier = HolidayRepo.getholidaymodifier(user, date)
[Benutzer, %{Bestellung | Preis: aktuellerPreis * Modifikator}]
end
end
```

Sie werden feststellen, dass es sich um ein vollständiges Beispiel dafür handelt, wie die User Story tatsächlich umgesetzt werden kann. Das liegt daran, dass es weniger langatmig ist als es in Ruby der Fall wäre. Wir verwenden einige Schlüsselfunktionen, die es nur in Elixir gibt (die aber allgemein in funktionalen Sprachen verfügbar sind):

Reine Funktionen. Wir ändern nicht wirklich die eingehenden Bestellung Wir erstellen lediglich neue Kopien - neue Iterationen des Ausgangszustands. Wir springen auch nicht zur Seite, um etwas zu ändern. Und selbst wenn wir das wollten, Bestellung nur eine "dumme" Karte ist, können wir nicht bestellen.speichern an irgendeiner Stelle, weil es einfach nicht weiß, was das ist.

Mustervergleich. Ähnlich wie bei der Destrukturierung in ES6 können wir damit die Preis und Widget und weiterzugeben, anstatt unsere Kumpels zu zwingen, die Bestellung WidgetRepo und UrlaubsRepo zu wissen, wie man mit einer vollen Bestellung.

Rohrleitungsbetreiber. Gesehen in preis_bestellungkönnen wir Daten in einer Art "Pipeline" durch Funktionen leiten - ein Konzept, das jedem, der schon einmal ps aux | grep postgres um zu überprüfen, ob das verdammte Ding noch läuft.

So denken Sie

Nebenwirkungen sind nicht wirklich Teil unseres Denkprozesses. Nachdem Sie Wasser in Ihre Tasse gegossen haben, machen Sie sich in der Regel keine Sorgen, dass ein Fehler im Wasserkocher dazu führen könnte, dass er überhitzt und explodiert - zumindest nicht so sehr, dass Sie in seinen Innereien herumstochern, um zu prüfen, ob nicht jemand versehentlich etwas vergessen hat explodieren_nach_dem_Ausgießen hochgeklappt.

Der Weg vom Programmierer zum Software-Ingenieur - der über die Beschäftigung mit Objekten und Zuständen hinausgeht und sich mit Datenflüssen befasst - kann in manchen Fällen Jahre dauern. Bei mir, der ich mit OOP aufgewachsen bin, hat es jedenfalls gedauert. Mit funktionalen Sprachen beginnt man, über Datenflüsse nachzudenken in Ihrer ersten Nacht.

Wir haben Softwaretechnik für uns selbst und für jeden einzelnen Neuling auf diesem Gebiet kompliziert. Programmieren muss nicht schwer und hirnzermürbend sein. Es kann einfach und natürlich sein.

Machen wir es nicht kompliziert und gehen wir gleich zur Sache. Denn so denken wir nun einmal.

Lesen Sie auch:

  • Warum beschleunigt die Technologie das Wachstum von E-Commerce, Marktplätzen und SaaS-Unternehmen?
  • Warum ist das Ruby on Rails eine gute Wahl für die Softwareentwicklung? Meine persönlichen Gedanken

Ähnliche Artikel

Software-Entwicklung

Zukunftssichere Web-Apps bauen: Einblicke vom The Codest-Expertenteam

Entdecken Sie, wie sich The Codest bei der Erstellung skalierbarer, interaktiver Webanwendungen mit Spitzentechnologien auszeichnet, die nahtlose Benutzererfahrungen auf allen Plattformen bieten. Erfahren Sie, wie unsere Expertise die digitale Transformation und...

DAS SCHÖNSTE
Software-Entwicklung

Top 10 Softwareentwicklungsunternehmen in Lettland

Erfahren Sie in unserem neuesten Artikel mehr über die besten Softwareentwicklungsunternehmen Lettlands und ihre innovativen Lösungen. Entdecken Sie, wie diese Technologieführer Ihr Unternehmen voranbringen können.

thecodest
Enterprise & Scaleups Lösungen

Grundlagen der Java-Softwareentwicklung: Ein Leitfaden für erfolgreiches Outsourcing

Entdecken Sie diesen wichtigen Leitfaden zum erfolgreichen Outsourcing der Java-Softwareentwicklung, um die Effizienz zu steigern, auf Fachwissen zuzugreifen und den Projekterfolg mit The Codest voranzutreiben.

thecodest
Software-Entwicklung

Der ultimative Leitfaden für Outsourcing in Polen

Der Anstieg des Outsourcings in Polen wird durch wirtschaftliche, bildungspolitische und technologische Fortschritte angetrieben, die das IT-Wachstum und ein unternehmensfreundliches Klima fördern.

TheCodest
Enterprise & Scaleups Lösungen

Der vollständige Leitfaden für IT-Audit-Tools und -Techniken

IT-Audits gewährleisten sichere, effiziente und gesetzeskonforme Systeme. Erfahren Sie mehr über ihre Bedeutung, indem Sie den vollständigen Artikel lesen.

Der Codest
Jakub Jakubowicz CTO & Mitbegründer

Abonnieren Sie unsere Wissensdatenbank und bleiben Sie auf dem Laufenden über das Fachwissen aus dem IT-Sektor.

    Über uns

    The Codest - Internationales Software-Unternehmen mit technischen Zentren in Polen.

    Vereinigtes Königreich - Hauptsitz

    • Büro 303B, 182-184 High Street North E6 2JA
      London, England

    Polen - Lokale Tech-Hubs

    • Fabryczna Office Park, Aleja
      Pokoju 18, 31-564 Kraków
    • Brain Embassy, Konstruktorska
      11, 02-673 Warszawa, Polen

      Der Codest

    • Startseite
    • Über uns
    • Dienstleistungen
    • Fallstudien
    • Gewusst wie
    • Karriere
    • Wörterbuch

      Dienstleistungen

    • IT-Beratung
    • Software-Entwicklung
    • Backend-Softwareentwicklung
    • Frontend-Softwareentwicklung
    • Staff Augmentation
    • Backend-Entwickler
    • Cloud-Ingenieure
    • Daten-Ingenieure
    • Andere
    • QS-Ingenieure

      Ressourcen

    • Fakten und Mythen über die Zusammenarbeit mit einem externen Softwareentwicklungspartner
    • Aus den USA nach Europa: Warum entscheiden sich amerikanische Start-ups für eine Verlagerung nach Europa?
    • Tech Offshore Development Hubs im Vergleich: Tech Offshore Europa (Polen), ASEAN (Philippinen), Eurasien (Türkei)
    • Was sind die größten Herausforderungen für CTOs und CIOs?
    • Der Codest
    • Der Codest
    • Der Codest
    • Privacy policy
    • Website terms of use

    Urheberrecht © 2025 von The Codest. Alle Rechte vorbehalten.

    de_DEGerman
    en_USEnglish sv_SESwedish da_DKDanish nb_NONorwegian fiFinnish fr_FRFrench pl_PLPolish arArabic it_ITItalian jaJapanese ko_KRKorean es_ESSpanish nl_NLDutch etEstonian elGreek de_DEGerman