window.pipedriveLeadboosterConfig = { base: 'leadbooster-chat.pipedrive.com', companyId: 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version: 2, } ;(function () { var w = finestra if (w.LeadBooster) { console.warn('LeadBooster esiste già') } 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 }) }, } } })() Programmazione orientata agli oggetti. Non è così che si pensa - The Codest
The Codest
  • Chi siamo
  • Servizi
    • Sviluppo di software
      • Sviluppo Frontend
      • Sviluppo backend
    • Staff Augmentation
      • Sviluppatori Frontend
      • Sviluppatori backend
      • Ingegneri dei dati
      • Ingegneri del cloud
      • Ingegneri QA
      • Altro
    • Consulenza
      • Audit e consulenza
  • Industrie
    • Fintech e banche
    • E-commerce
    • Adtech
    • Tecnologia della salute
    • Produzione
    • Logistica
    • Automotive
    • IOT
  • Valore per
    • CEO
    • CTO
    • Responsabile della consegna
  • Il nostro team
  • Case Studies
  • Sapere come
    • Blog
    • Incontri
    • Webinar
    • Risorse
Carriera Contattate
  • Chi siamo
  • Servizi
    • Sviluppo di software
      • Sviluppo Frontend
      • Sviluppo backend
    • Staff Augmentation
      • Sviluppatori Frontend
      • Sviluppatori backend
      • Ingegneri dei dati
      • Ingegneri del cloud
      • Ingegneri QA
      • Altro
    • Consulenza
      • Audit e consulenza
  • Valore per
    • CEO
    • CTO
    • Responsabile della consegna
  • Il nostro team
  • Case Studies
  • Sapere come
    • Blog
    • Incontri
    • Webinar
    • Risorse
Carriera Contattate
Freccia indietro TORNA INDIETRO
2019-05-06
Sviluppo di software

Programmazione orientata agli oggetti. Non è così che si pensa

Pawel Wal

Con la quantità di risorse gratuite, libri, corsi online e bootcamp di codifica disponibili in questo momento, tutti possono imparare a codificare. Tuttavia, c'è ancora un divario di qualità tra il coding e l'ingegneria del software. Deve esistere?

Ho scritto il mio primo "Hello world" più di vent'anni fa: questa è la risposta che do se qualcuno mi chiede da quanto tempo sono un coder. Negli ultimi dieci anni, mi sono goduto una carriera che mi ha permesso di toccare codice quasi ogni giorno - è la risposta che do quando mi chiedono da quanto tempo sono un codificatore professionista.

Da quanto tempo sono un ingegnere del software? Direi circa cinque anni. Aspettate, questi numeri non sembrano coincidere! Allora cosa è cambiato? Chi dovrei considerare un ingegnere del software e chi "semplicemente" un codificatore?

La definizione di ingegnere del software

La codifica è relativamente facile. Non si tratta più di mnemotecniche di assemblaggio su sistemi ridicolmente vincolati. E se si usa qualcosa di espressivo e potente come Ruby, è ancora più facile.

Basta prendere un biglietto, trovare il punto in cui inserire il codice, capire la logica da inserire e bum, il gioco è fatto. Se siete un po' più avanzati, vi assicurate che il vostro codice sia bello. Sia logicamente suddiviso in metodi. abbia specifiche decenti che non testino solo il percorso felice. Questo è ciò che fa un buon codificatore.

Un ingegnere del software non pensa più a metodi e classi, almeno non principalmente. Secondo la mia esperienza, un ingegnere del software pensa per flussi. Vede innanzitutto il fiume impetuoso e fragoroso di dati e interazioni che scorre nel sistema. Pensano a ciò che devono fare in termini di deviazione o alterazione di questo flusso. Il bel codice, i metodi logici e le ottime specifiche sono quasi un ripensamento.

Le tartarughe sono tutte in basso

In genere le persone pensano in un certo modo alla maggior parte delle interazioni con la realtà. In mancanza di un termine migliore, chiamiamola prospettiva "dall'alto verso il basso". Se il mio cervello sta lavorando per prepararmi una tazza di tè, capirà innanzitutto i passaggi generali: andare in cucina, accendere il bollitore, preparare la tazza, versare l'acqua, tornare alla scrivania.

Non si accorgerà di quale tazza usare per prima, mentre sono assopito alla scrivania; l'assopimento avverrà in un secondo momento, quando mi troverò di fronte alla credenza. Non prende in considerazione il fatto che potrebbe essere finito il tè (o perlomeno, il tè è finito). buono cose). È ampio, reattivo e soggetto a errori. Tutto sommato - molto umano in natura.

Quando l'ingegnere del software prende in considerazione le modifiche al flusso di dati un po' strabiliante, lo farà naturalmente in modo simile. Consideriamo questo esempio di storia utente:

Un cliente ordina un widget. Nella determinazione del prezzo dell'ordine, si deve tenere conto di quanto segue:

  • Prezzo base del widget nella località dell'utente
  • Forma del widget (modificatore di prezzo)
  • Se si tratta di un ordine urgente (modificatore di prezzo)
  • Se la consegna dell'ordine avviene in un giorno festivo nella località dell'utente (modificatore di prezzo)

Tutto questo può sembrare artificioso (e ovviamente lo è), ma non si discosta molto da alcune storie di utenti reali che ho avuto il piacere di analizzare di recente.

Esaminiamo ora il processo di pensiero che un ingegnere del software potrebbe impiegare per affrontare questo problema:

"Dobbiamo ottenere l'utente e il suo ordine. Poi iniziamo a calcolare il totale. Inizieremo da zero. Poi applicheremo il modificatore di forma del widget. Poi il costo della fretta. Poi vediamo se è un giorno festivo, e boom, fatto prima di pranzo!".

Ah, l'emozione che può dare una semplice storia utente. Ma l'ingegnere informatico è solo un essere umano, non una perfetta macchina multi-thread, e la ricetta di cui sopra è un'idea di massima. L'ingegnere continua a pensare in modo più approfondito:

"Il modificatore di forma del widget è... oh, dipende molto dal widget, vero? E potrebbero essere diversi per ogni locale, anche se non ora, ma in futuro". pensano, bruciati in precedenza dall'evoluzione dei requisiti aziendali, "e anche il costo della fretta potrebbe esserlo. E anche le festività sono super specifiche del luogo, e i fusi orari saranno coinvolti! Ho pubblicato qui un articolo su come gestire gli orari in fusi orari diversi in Rails... oh, mi chiedo se l'orario dell'ordine sia memorizzato con il fuso orario nel database! Meglio controllare lo schema".

Va bene, ingegnere del software. Fermatevi. Dovresti preparare una tazza di tè, ma sei assopito davanti alla credenza a pensare se la tazza fiorita sia applicabile al tuo problema del tè.

Widget per la preparazione della tazza perfetta

Ma questo è facilmente ciò che può accadere quando si cerca di fare qualcosa di innaturale per il cervello umano come pensare a diversi livelli di dettaglio. contemporaneamente.

Dopo una breve ricerca nell'ampio arsenale di link sulla gestione dei fusi orari, il nostro ingegnere si ricompone e inizia a scomporre il tutto in codice. Se avessero tentato un approccio ingenuo, il codice sarebbe stato più o meno così:

 def calculate_price(user, order)
   ordine.prezzo = 0
   order.price = WidgetPrices.find_by(widget_type: order.widget.type).price
   order.price = WidgetShapes.find_by(widget_shape: order.widget.shape).modifier
   ...
 fine

E continuavano ad andare avanti, in questo modo deliziosamente procedurale, per poi essere pesantemente bloccati alla prima revisione del codice. Perché se ci pensate, è perfettamente normale pensare in questo modo: prima le grandi linee, poi i dettagli. All'inizio non pensavate nemmeno di essere fuori dal tè buono, vero?

Il nostro ingegnere, tuttavia, è ben addestrato e non è estraneo all'oggetto Service, quindi ecco cosa succede:

classe BaseOrderService
def self.call(utente, ordine)
nuovo(utente, ordine).call
fine

def initialize(utente, ordine)
@utente = utente
@ordine = ordine
fine

def call
mette "[WARN] Implementare una chiamata non predefinita per #{self.class.name}!".
utente, ordine
fine
fine

classe WidgetPriceService < BaseOrderService; fine
classe ShapePriceModifier < BaseOrderService; fine
classe RushPriceModifier < BaseOrderService; fine
classe HolidayDeliveryPriceModifier < BaseOrderService; fine

classe OrderPriceCalculator < BaseOrderService
def chiamata
utente, ordine = WidgetPriceService.call(utente, ordine)
utente, ordine = ShapePriceModifier.call(utente, ordine)
utente, ordine = RushPriceModifier.call(utente, ordine)
utente, ordine = HolidayDeliveryPriceModifier.call(utente, ordine)
utente, ordine
fine
fine
```

Bene! Ora possiamo impiegare un buon TDD, scrivere un caso di test e completare le classi finché tutti i pezzi non vanno al loro posto. E sarà anche bello.

Oltre che completamente impossibile da ragionare.

Il nemico è lo Stato

Certo, si tratta di oggetti ben separati con singole responsabilità. Ma il problema è che si tratta pur sempre di oggetti. Lo schema degli oggetti di servizio, con il suo "fingere forzatamente che questo oggetto sia una funzione", è davvero una stampella. Non c'è nulla che impedisca a qualcuno di chiamare HolidayDeliveryPriceModifier.new(utente, ordine).something_else_entirely. Nulla impedisce di aggiungere uno stato interno a questi oggetti.

Per non parlare utente e ordine sono anch'essi oggetti, e manipolarli è facile come se qualcuno si intrufolasse in un rapido ordine.salvare da qualche parte in questi oggetti funzionali altrimenti "puri", modificando la fonte sottostante della verità, ovvero un database, lo stato. In questo esempio artificioso non è un grosso problema, ma di sicuro può ritorcersi contro di voi se questo sistema cresce in complessità e si espande in parti aggiuntive, spesso asincrone.

L'ingegnere ha avuto l'idea giusta. E ha usato un modo molto naturale di esprimere questa idea. Ma sapere come esprimere questa idea - in un modo bello e facile da ragionare - era quasi impedito dal paradigma OOP sottostante. E se qualcuno che non ha ancora fatto il salto di qualità nell'esprimere i propri pensieri come deviazioni del flusso di dati cerca di alterare meno abilmente il codice sottostante, accadranno brutte cose.

Diventare funzionalmente puri

Se solo esistesse un paradigma in cui esprimere le proprie idee in termini di flussi di dati fosse non solo facile, ma necessario. Se il ragionamento potesse essere semplice, senza la possibilità di introdurre effetti collaterali indesiderati. Se i dati potessero essere immutabili, proprio come la tazza fiorita in cui si prepara il tè.

Sì, sto scherzando, naturalmente. Quel paradigma esiste e si chiama programmazione funzionale.

Consideriamo come l'esempio precedente potrebbe apparire in uno dei nostri preferiti, Elixir.

defmodulo WidgetPrices do
def priceorder([utente, ordine]) do
[utente, ordine]
|> widgetprice
|> modificatore del prezzo di forma
|> modificatore di prezzi urgenti
|> modificatore prezzo vacanze
fine

defp widgetprice([utente, ordine]) do
%{widget: widget} = ordine
prezzo = WidgetRepo.getbase_price(widget)
[utente, %{ordine | prezzo: prezzo }]
fine

defp shapepricemodifier([utente, ordine]) do
%{widget: widget, prezzo: prezzo corrente} = ordine
modificatore = WidgetRepo.getshapeprice(widget)
[utente, %{ordine | prezzo: prezzo corrente * modificatore} ]
fine

defp rushpricemodifier([user, order]) do
%{sfogo: sfogo, prezzo: prezzo corrente} = ordine
se fretta, fare
[utente, %{ordine | prezzo: prezzo corrente * 1,75} ]
altrimenti
[utente, %{ordine | prezzo: prezzo_corrente} ]
fine
fine

defp holidaypricemodifier([utente, ordine]) do
%{data: data, prezzo: prezzo corrente} = ordine
modificatore = HolidayRepo.getholidaymodifier(utente, data)
[utente, %{ordine | prezzo: prezzo corrente * modificatore}]
fine
fine
```

Si può notare che si tratta di un esempio completo di come la storia utente può essere effettivamente realizzata. Questo perché è meno complicato di quanto sarebbe in Ruby. Utilizziamo alcune caratteristiche chiave esclusive di Elixir (ma generalmente disponibili nei linguaggi funzionali):

Funzioni pure. In realtà non cambiamo l'ingresso ordine Stiamo solo creando nuove copie, nuove iterazioni dello stato iniziale. Non saltiamo a lato per cambiare qualcosa. E anche se volessimo, ordine è solo una mappa "stupida", non si può chiamare ordine.salvare in qualsiasi momento, perché semplicemente non sa cosa sia.

Corrispondenza dei modelli. In modo piuttosto simile alla destrutturazione di ES6, questo ci permette di prelevare prezzo e widget dall'ordine e passarlo, invece di costringere i nostri compagni WidgetRepo e VacanzeRepo di sapere come gestire un'intera ordine.

Operatore del tubo. Visto in ordine_prezzopermette di passare i dati attraverso le funzioni in una sorta di "pipeline" - un concetto immediatamente familiare a chiunque abbia mai eseguito ps aux | grep postgres per verificare se l'aggeggio fosse ancora in funzione.

Questo è il modo in cui si pensa

Gli effetti collaterali non sono una parte fondamentale del nostro processo di pensiero. Dopo aver versato l'acqua nella tazza, in genere non ci si preoccupa che un errore nel bollitore possa causarne il surriscaldamento e l'esplosione, almeno non tanto da andare a frugare nei suoi interni per verificare se qualcuno non abbia inavvertitamente lasciato esplodere_dopo_la_versione ribaltato in alto.

Il percorso da coder a ingegnere del software - che va oltre la preoccupazione per gli oggetti e gli stati, per arrivare a preoccuparsi dei flussi di dati - in alcuni casi può richiedere anni. Per il sottoscritto, cresciuto con l'OOP, è stato sicuramente così. Con i linguaggi funzionali, si inizia a pensare ai flussi di dati. la prima notte.

Abbiamo fatto ingegneria del software complicato per noi stessi e per ogni nuovo arrivato nel settore. La programmazione non deve essere per forza difficile e cervellotica. Può essere facile e naturale.

Non complichiamo le cose e diventiamo già funzionali. Perché è così che pensiamo.

Leggi anche:

  • Perché la tecnologia accelera la crescita di e-commerce, marketplace e aziende SaaS?
  • Perché l'Ruby on Rails è una buona scelta per lo sviluppo di software? Il mio pensiero personale

Articoli correlati

Sviluppo di software

Costruire applicazioni web a prova di futuro: le intuizioni del team di esperti di The Codest

Scoprite come The Codest eccelle nella creazione di applicazioni web scalabili e interattive con tecnologie all'avanguardia, offrendo esperienze utente senza soluzione di continuità su tutte le piattaforme. Scoprite come la nostra esperienza favorisce la trasformazione digitale e il business...

IL CANCRO
Sviluppo di software

Le 10 principali aziende di sviluppo software con sede in Lettonia

Scoprite le migliori aziende di sviluppo software della Lettonia e le loro soluzioni innovative nel nostro ultimo articolo. Scoprite come questi leader tecnologici possono aiutarvi a migliorare la vostra attività.

thecodest
Soluzioni per aziende e scaleup

Essenziali di sviluppo software Java: Guida all'outsourcing di successo

Esplorate questa guida essenziale sullo sviluppo di software Java con successo outsourcing per migliorare l'efficienza, accedere alle competenze e guidare il successo del progetto con The Codest.

thecodest
Sviluppo di software

La guida definitiva all'outsourcing in Polonia

L'aumento di outsourcing in Polonia è guidato dai progressi economici, educativi e tecnologici, che favoriscono la crescita dell'IT e un clima favorevole alle imprese.

IlCodesto
Soluzioni per aziende e scaleup

Guida completa agli strumenti e alle tecniche di audit IT

Gli audit IT garantiscono sistemi sicuri, efficienti e conformi. Per saperne di più sulla loro importanza, leggete l'articolo completo.

The Codest
Jakub Jakubowicz CTO e cofondatore

Iscrivetevi alla nostra knowledge base e rimanete aggiornati sulle competenze del settore IT.

    Chi siamo

    The Codest - Società internazionale di sviluppo software con centri tecnologici in Polonia.

    Regno Unito - Sede centrale

    • Ufficio 303B, 182-184 High Street North E6 2JA
      Londra, Inghilterra

    Polonia - Poli tecnologici locali

    • Parco uffici Fabryczna, Aleja
      Pokoju 18, 31-564 Cracovia
    • Ambasciata del cervello, Konstruktorska
      11, 02-673 Varsavia, Polonia

      The Codest

    • Casa
    • Chi siamo
    • Servizi
    • Case Studies
    • Sapere come
    • Carriera
    • Dizionario

      Servizi

    • Consulenza
    • Sviluppo di software
    • Sviluppo backend
    • Sviluppo Frontend
    • Staff Augmentation
    • Sviluppatori backend
    • Ingegneri del cloud
    • Ingegneri dei dati
    • Altro
    • Ingegneri QA

      Risorse

    • Fatti e miti sulla collaborazione con un partner esterno per lo sviluppo di software
    • Dagli Stati Uniti all'Europa: Perché le startup americane decidono di trasferirsi in Europa
    • Confronto tra gli hub di sviluppo Tech Offshore: Tech Offshore Europa (Polonia), ASEAN (Filippine), Eurasia (Turchia)
    • Quali sono le principali sfide di CTO e CIO?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Condizioni di utilizzo del sito web

    Copyright © 2025 di The Codest. Tutti i diritti riservati.

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