window.pipedriveLeadboosterConfig = { bas: 'leadbooster-chat.pipedrive.com', företagId: 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version: 2, } ;(funktion () { var w = fönster if (w.LeadBooster) { console.warn('LeadBooster finns redan') } annars { w.LeadBooster = { q: [], on: funktion (n, h) { this.q.push({ t: "o", n: n, h: h }) }, trigger: funktion (n) { this.q.push({ t: 't', n: n }) }, } } })() Objektorienterad programmering. Det är inte så du tänker - The Codest
Codest
  • Om oss
  • Tjänster
    • Utveckling av programvara
      • Frontend-utveckling
      • Backend-utveckling
    • Staff Augmentation
      • Frontend-utvecklare
      • Backend-utvecklare
      • Dataingenjörer
      • Ingenjörer inom molntjänster
      • QA-ingenjörer
      • Övriga
    • Det rådgivande
      • Revision och rådgivning
  • Industrier
    • Fintech & bankverksamhet
    • E-commerce
    • Adtech
    • Hälsoteknik
    • Tillverkning
    • Logistik
    • Fordon
    • IOT
  • Värde för
    • VD OCH KONCERNCHEF
    • CTO
    • Leveranschef
  • Vårt team
  • Fallstudier
  • Vet hur
    • Blogg
    • Möten
    • Webbinarier
    • Resurser
Karriär Ta kontakt med oss
  • Om oss
  • Tjänster
    • Utveckling av programvara
      • Frontend-utveckling
      • Backend-utveckling
    • Staff Augmentation
      • Frontend-utvecklare
      • Backend-utvecklare
      • Dataingenjörer
      • Ingenjörer inom molntjänster
      • QA-ingenjörer
      • Övriga
    • Det rådgivande
      • Revision och rådgivning
  • Värde för
    • VD OCH KONCERNCHEF
    • CTO
    • Leveranschef
  • Vårt team
  • Fallstudier
  • Vet hur
    • Blogg
    • Möten
    • Webbinarier
    • Resurser
Karriär Ta kontakt med oss
Pil tillbaka GÅ TILLBAKA
2019-05-06
Utveckling av programvara

Objektorienterad programmering. Det är inte så man tänker

Pawel Wal

Med den mängd gratis resurser, böcker, onlinekurser och bootcamps för kodning som finns tillgängliga just nu kan alla lära sig att koda. Det finns dock fortfarande ett kvalitetsgap mellan kodning och programvaruteknik. Måste det finnas en?

Jag skrev mitt första "Hello world" för över tjugo år sedan - det är det svar jag ger om någon frågar mig hur länge jag har varit kodare. Under de senaste tio åren har jag haft en karriär som har gett mig möjlighet att röra vid kod nästan varje dag - det är det svar jag ger om jag får frågan hur länge jag har varit professionell kodare.

Hur länge har jag varit Programvaruingenjör? Jag skulle säga ungefär fem år. Vänta lite, de här siffrorna verkar inte stämma! Så vad är det som har förändrats? Vem skulle jag betrakta som en mjukvaruingenjör och vem "bara" som en kodare?

Definitionen av en mjukvaruingenjör

Kodning är relativt enkelt. Det handlar inte längre om mnemotekniker på löjligt begränsade system. Och om du använder något så uttrycksfullt och kraftfullt som Ruby är det ännu enklare.

Du plockar bara upp en biljett, hittar var du behöver infoga din kod, du räknar ut logiken du behöver lägga där, och boom - klart. Om du är lite mer avancerad ser du till att din kod är vacker. Logiskt uppdelad i metoder. Har anständiga specifikationer som inte bara testar den lyckliga vägen. Det är vad en bra kodare gör.

En mjukvaruutvecklare tänker inte längre i metoder och klasser, åtminstone inte i första hand. Enligt min erfarenhet tänker en mjukvaruingenjör i flöden. De ser först och främst den dånande, rasande floden av data och interaktion som brusar genom systemet. De funderar på vad de behöver göra för att avleda eller förändra detta flöde. Den snygga koden, de logiska metoderna och de bra specifikationerna kommer nästan som en eftertanke.

Det är sköldpaddor hela vägen ner

Människor tänker i allmänhet på ett visst sätt om de flesta interaktioner med verkligheten. I brist på en bättre term kan vi kalla det för "uppifrån och ner"-perspektivet. Om min hjärna arbetar med att göra mig en kopp te kommer den först att räkna ut de allmänna stegen: gå till köket, sätta på vattenkokaren, förbereda koppen, hälla upp vatten, återvända till skrivbordet.

Den kommer inte att räkna ut vilken kopp jag ska använda först, när jag står och zonerar vid mitt skrivbord; den zoneringen kommer senare, när jag står framför skåpet. Den kommer inte att tänka på att teet kan vara slut (eller i alla fall bra grejer). Den är bred, reaktiv och felbenägen. Sammantaget - mycket människa i naturen.

När programvaruingenjören överväger ändringar i det något häpnadsväckande dataflödet kommer de naturligtvis att göra det på ett liknande sätt. Låt oss titta på det här exemplet på en användarberättelse:

En kund beställer en widget. Vid prissättningen av ordern måste följande beaktas:

  • Widgets baspris på användarens ort
  • Widget-form (prismodifierare)
  • Om det är en brådskande order (prismodifierare)
  • Om orderleveransen sker på en helgdag i användarens land (prismodifierare)

Allt det här kan verka konstruerat (och det är det naturligtvis), men det är inte långt ifrån några faktiska användarberättelser som jag har haft nöjet att ta del av nyligen.

Låt oss nu gå igenom den tankeprocess som en programvaruutvecklare kan använda för att ta itu med detta:

"Vi måste få fram användaren och deras beställning. Sedan börjar vi beräkna totalsumman. Vi börjar på noll. Sedan applicerar vi widgetformsmodifieraren. Sedan rusningsavgiften. Sen ser vi om det är en helgdag, boom, klart före lunch!"

Åh, den kick som en enkel användarberättelse kan ge. Men programvaruingenjören är bara en människa, inte en perfekt flertrådad maskin, och receptet ovan är ett brett grepp. Ingenjören fortsätter att tänka djupare då:

"Widgetens formmodifierare är... det är väldigt beroende av widgeten, eller hur. Och de kan vara olika per lokal, även om det inte är nu så i framtiden," tror de, tidigare brända av förändrade affärskrav, "och rusningsavgiften kan också vara det. Och helgdagar är också superlokalspecifika, augh, och tidszoner kommer att vara inblandade! Jag hade en artikel här om att hantera tider i olika tidszoner i Rails här ... ooh, jag undrar om ordertiden lagras med zon i databasen! Bäst att kolla schemat."

Okej, mjukvaruingenjör. Sluta, sluta. Det är meningen att du ska göra en kopp te, men du sitter framför skåpet och funderar på om den blommiga koppen ens är tillämplig på ditt teproblem.

Bryggning av den perfekta koppen widget

Men det är vad som lätt kan hända när man försöker göra något så onaturligt för den mänskliga hjärnan som att tänka på flera detaljnivåer samtidigt.

Efter en kort genomgång av deras rymliga arsenal av länkar om tidszonshantering tar vår ingenjör sig samman och börjar bryta ner detta till faktisk kod. Om de försökte med den naiva metoden skulle det kunna se ut ungefär så här:

 def beräkna_pris(användare, order)
   order.pris = 0
   order.price = WidgetPrices.find_by(widget_type: order.widget.type).price
   order.price = WidgetShapes.find_by(widget_shape: order.widget.shape).modifier
   ...
 slut

Och så fortsatte de på det här härliga procedurmässiga sättet, bara för att bli rejält nedslagna vid den första kodgranskningen. För om man tänker efter är det helt normalt att tänka på det här sättet: stora drag först och detaljer mycket senare. Du trodde inte ens att du var ute ur det goda teet först, eller hur?

Vår ingenjör är dock välutbildad och inte främmande för Service Object, så här är vad som börjar hända istället:

klass BaseOrderService
def self.call(användare, order)
new(användare, order).call
slut

def initialize(användare, order)
@användare = användare
@order = order
slut

def anrop
puts "[WARN] Implementera icke-standardanrop för #{self.class.name}!"
användare, order
slut
slut

class WidgetPriceService < BaseOrderService; end
class ShapePriceModifier < BaseOrderService; end
klass RushPriceModifier < Basbeställningstjänst; end
klass HolidayDeliveryPriceModifier < Basbeställningstjänst; end

klass OrderPriceCalculator < Basbeställningstjänst
def anrop
användare, order = WidgetPriceService.call(användare, order)
användare, order = ShapePriceModifier.call(användare, order)
användare, order = RushPriceModifier.call(användare, order)
användare, order = HolidayDeliveryPriceModifier.call(användare, order)
användare, beställning
slut
slut
```

Bra! Nu kan vi använda lite bra TDD, skriva ett testfall för det och fylla på med klasser tills alla bitar faller på plats. Och det kommer att bli vackert också.

Samt helt omöjligt att resonera kring.

Fienden är staten

Visst, det här är alla väl separerade objekt med enskilda ansvarsområden. Men här är problemet: de är fortfarande objekt. Serviceobjektmönstret med dess "tvinga låtsas att det här objektet är en funktion" är verkligen en krycka. Det finns inget som hindrar någon från att ringa HolidayDeliveryPriceModifier.new(användare, order).something_else_entirely. Inget hindrar människor från att lägga till interna tillstånd till dessa objekt.

För att inte tala om användare och ordning är också objekt, och att mixtra med dem är lika enkelt som att smyga in en snabb order.spara någonstans i dessa annars "rena" funktionella objekt, ändra den underliggande källan till sanningens, alias en databas, tillstånd. I det här konstruerade exemplet är det ingen stor sak, men det kan verkligen komma tillbaka och bita dig om det här systemet växer i komplexitet och expanderar till ytterligare, ofta asynkrona, delar.

Ingenjören hade rätt idé. Och använde ett mycket naturligt sätt att uttrycka denna idé. Men att veta hur man skulle uttrycka denna idé - på ett vackert och lättbegripligt sätt - hindrades nästan helt av det underliggande OOP-paradigmet. Och om någon som ännu inte har tagit steget till att uttrycka sina tankar som avledningar av dataflödet försöker att mindre skickligt ändra den underliggande koden, kommer dåliga saker att hända.

Att bli funktionellt ren

Om det ändå fanns ett paradigm där det inte bara var enkelt, utan nödvändigt, att uttrycka sina idéer i termer av dataflöden. Om resonemang kunde göras enkla, utan möjlighet att införa oönskade bieffekter. Om data kunde vara oföränderliga, precis som den blommiga koppen du gör ditt te i.

Ja, jag skämtar naturligtvis. Det paradigmet finns, och det kallas funktionell programmering.

Låt oss titta på hur ovanstående exempel kan se ut i en personlig favorit, Elixir.

defmodul WidgetPriser do
def priceorder([användare, order]) do
[användare, order]
|> widgetpris
|> shapepricemodifier
|> rushprismodifierare
|> semesterprismodifierare
slut

defp widgetpris([användare, order]) do
%{widget: widget} = order
pris = WidgetRepo.getbase_price(widget)
[användare, %{order | pris: pris }]
slut

defp shapepricemodifier([användare, order]) do
%{widget: widget, pris: aktuellt pris} = order
modifier = WidgetRepo.getshapeprice(widget)
[användare, %{beställning | pris: aktuellt pris * modifierare} ]
slut

defp rushpricemodifier([användare, order]) do
%{rusning: rusning, pris: aktuellt pris} = order
if rush do
[användare, %{order | pris: aktuellt pris * 1,75} ]
annat
[användare, %{order | pris: aktuellt_pris} ]
slut
slut

defp holidaypricemodifier([user, order]) do
%{datum: datum, pris: aktuellt pris} = order
modifier = HolidayRepo.getholidaymodifier(användare, datum)
[användare, %{order | pris: aktuellt pris * modifier}]
slut
slut
```

Du kanske noterar att det är ett fullfjädrat exempel på hur användarberättelsen faktiskt kan uppnås. Det beror på att det är mindre av en munfull än det skulle vara i Ruby. Vi använder några nyckelfunktioner som är unika för Elixir (men som är allmänt tillgängliga i funktionella språk):

Rena funktioner. Vi ändrar faktiskt inte den inkommande ordning Vi skapar bara nya kopior - nya iterationer av det ursprungliga tillståndet. Vi hoppar inte heller åt sidan för att ändra något. Och även om vi skulle vilja det, ordning är bara en "dum" karta, vi kan inte kalla order.spara på någon punkt här eftersom den helt enkelt inte vet vad det är.

Mönstermatchning. På samma sätt som ES6:s destrukturering kan vi här plocka ut pris och widget av ordern och skicka den vidare, istället för att tvinga våra kompisar att WidgetRepo och SemesterRepo för att veta hur man hanterar en full ordning.

Röroperatör. Sett i pris_orderlåter den oss skicka data genom funktioner i en slags "pipeline" - ett koncept som är välbekant för alla som någonsin kört ps aux | grep postgres för att kontrollera om den fortfarande var igång.

Det är så här du tänker

Biverkningar är egentligen inte en grundläggande del av vår tankeprocess. När du har hällt upp vatten i din kopp oroar du dig i allmänhet inte för att ett fel i vattenkokaren kan leda till att den överhettas och exploderar - åtminstone inte tillräckligt för att du ska gå och peta i dess interna delar för att kontrollera om någon inte oavsiktligt har lämnat explodera_efter_hällning vänds högt.

Vägen från kodare till mjukvaruutvecklare - att gå från att oroa sig för objekt och tillstånd till att oroa sig för dataflöden - kan i vissa fall ta flera år. Det gjorde den verkligen för undertecknad som var OOP-skolad. Med funktionella språk börjar du tänka på flöden på din första natt.

Vi har gjort programvaruutveckling komplicerat för oss själva och för varenda nykomling på området. Programmering behöver inte vara svårt och hjärntvättande. Det kan vara enkelt och naturligt.

Låt oss inte göra det här komplicerat och gå funktionellt redan nu. För det är så vi tänker.

Läs också:

  • Varför påskyndar tekniken tillväxten för e-handel, marknadsplatser och SaaS-företag?
  • Varför Ruby on Rails är ett bra val för mjukvaruutveckling? Mina personliga tankar

Relaterade artiklar

Utveckling av programvara

Bygg framtidssäkrade webbappar: Insikter från The Codest:s expertteam

Upptäck hur The Codest utmärker sig genom att skapa skalbara, interaktiva webbapplikationer med banbrytande teknik som ger sömlösa användarupplevelser på alla plattformar. Läs om hur vår expertis driver digital omvandling och affärsutveckling...

DEKODEST
Utveckling av programvara

Topp 10 Lettlandsbaserade mjukvaruutvecklingsföretag

Läs mer om Lettlands främsta mjukvaruutvecklingsföretag och deras innovativa lösningar i vår senaste artikel. Upptäck hur dessa teknikledare kan hjälpa till att lyfta ditt företag.

thecodest
Lösningar för företag och uppskalningsföretag

Java Software Development Essentials: En guide till framgångsrik outsourcing

Utforska denna viktiga guide om framgångsrik outsourcing av Java-programvaruutveckling för att förbättra effektiviteten, få tillgång till expertis och driva projektframgång med The Codest.

thecodest
Utveckling av programvara

Den ultimata guiden till outsourcing i Polen

Den kraftiga ökningen av outsourcing i Polen drivs av ekonomiska, utbildningsmässiga och tekniska framsteg, vilket främjar IT-tillväxt och ett företagsvänligt klimat.

TheCodest
Lösningar för företag och uppskalningsföretag

Den kompletta guiden till verktyg och tekniker för IT-revision

IT-revisioner säkerställer säkra, effektiva och kompatibla system. Läs mer om hur viktiga de är genom att läsa hela artikeln.

Codest
Jakub Jakubowicz CTO och medgrundare

Prenumerera på vår kunskapsbas och håll dig uppdaterad om expertisen från IT-sektorn.

    Om oss

    The Codest - Internationellt mjukvaruutvecklingsföretag med teknikhubbar i Polen.

    Förenade kungariket - Huvudkontor

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

    Polen - Lokala tekniknav

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

      Codest

    • Hem
    • Om oss
    • Tjänster
    • Fallstudier
    • Vet hur
    • Karriär
    • Ordbok

      Tjänster

    • Det rådgivande
    • Utveckling av programvara
    • Backend-utveckling
    • Frontend-utveckling
    • Staff Augmentation
    • Backend-utvecklare
    • Ingenjörer inom molntjänster
    • Dataingenjörer
    • Övriga
    • QA-ingenjörer

      Resurser

    • Fakta och myter om att samarbeta med en extern partner för mjukvaruutveckling
    • Från USA till Europa: Varför väljer amerikanska startup-företag att flytta till Europa?
    • Jämförelse av Tech Offshore Development Hubs: Tech Offshore Europa (Polen), ASEAN (Filippinerna), Eurasien (Turkiet)
    • Vilka är de största utmaningarna för CTO:er och CIO:er?
    • Codest
    • Codest
    • Codest
    • Privacy policy
    • Användarvillkor för webbplatsen

    Copyright © 2025 av The Codest. Alla rättigheter reserverade.

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