Domanda

Sto lavorando a un progetto in C #. Il programmatore precedente non conosceva la programmazione orientata agli oggetti, quindi la maggior parte del codice è in enormi file (stiamo parlando di 4-5000 righe) distribuiti su decine e talvolta centinaia di metodi, ma solo una classe. Rifattorizzare un progetto del genere è un'impresa enorme, quindi per ora ho semi-imparato a conviverci.

Ogni volta che viene utilizzato un metodo in uno dei file di codice, la classe viene istanziata e quindi il metodo viene chiamato sull'istanza dell'oggetto.

Mi chiedo se ci siano delle penalità di prestazione evidenti nel farlo in questo modo? Devo rendere statici tutti i metodi "per ora" e, soprattutto, l'applicazione ne trarrà vantaggio in alcun modo?

È stato utile?

Soluzione

Da qui , una chiamata statica è da 4 a 5 volte più veloce che costruire un'istanza ogni volta che chiami un metodo di istanza. Tuttavia, stiamo ancora parlando di decine di nanosecondi per chiamata, quindi è improbabile che notiate alcun vantaggio a meno che non abbiate cicli molto stretti che chiamano un metodo milioni di volte e potreste ottenere lo stesso vantaggio costruendo una singola istanza all'esterno quel loop e riutilizzarlo.

Dato che dovresti cambiare ogni sito di chiamata per utilizzare il nuovo metodo statico, probabilmente è meglio dedicare il tuo tempo al refactoring graduale.

Altri suggerimenti

Ho affrontato un problema simile in cui lavoro. Il programmatore prima di me ha creato 1 classe di controller in cui sono state scaricate tutte le funzioni BLL.

Stiamo ridisegnando il sistema ora e abbiamo creato molte classi di controller a seconda di ciò che dovrebbero controllare ad esempio

UserController, GeographyController, ShoppingController ...

All'interno di ogni classe di controller hanno metodi statici che effettuano chiamate alla cache o al DAL usando il modello singleton.

Questo ci ha dato 2 vantaggi principali. È leggermente più veloce (circa 2-3 volte più veloce ma qui parlavano nanosecondi; P). L'altro è che il codice è molto più pulito

cioè

ShoppingController.ListPaymentMethods()

anziché

new ShoppingController().ListPaymentMethods()

Penso che abbia senso usare metodi o classi statici se la classe non mantiene alcuno stato.

Dipende da cos'altro contiene quell'oggetto - se l'oggetto " oggetto " è solo un mucchio di funzioni, quindi probabilmente non è la fine del mondo. Ma se l'oggetto contiene un mucchio di altri oggetti, quindi un'istanza chiamerà tutti i loro costruttori (e distruttori, quando viene eliminato) e potresti ottenere la frammentazione della memoria e così via.

Detto questo, non sembra che le prestazioni siano il tuo problema più grande in questo momento.

Devi determinare gli obiettivi della riscrittura. Se vuoi avere un buon testabile, estensibile & amp; codice OO gestibile, quindi è possibile provare a utilizzare gli oggetti e i relativi metodi di istanza. Dopotutto si tratta di programmazione orientata agli oggetti di cui stiamo parlando qui, non di programmazione orientata alla classe.

È molto semplice falsificare e / o simulare oggetti quando si definiscono classi che implementano interfacce ed eseguono metodi di istanza. Ciò rende i test di unità completi rapidi ed efficaci.

Inoltre, se devi seguire buoni principi OO (vedi SOLID su http: //it.wikipedia.org/wiki/SOLID_%28object-oriented_design%29 ) e / o utilizzare modelli di progettazione che farai sicuramente uno sviluppo basato su istanze, basato su interfacce e non usando molti metodi statici.

Come per questo suggerimento:

  
    

Mi sembra sciocco creare un oggetto SOLO in modo da poter chiamare un metodo che     apparentemente non ha effetti collaterali sull'oggetto (dalla tua descrizione presumo questo).

  

Lo vedo molto nei negozi di dot net e per me questo viola l'incapsulamento, un concetto chiave di OO. Non dovrei essere in grado di dire se un metodo ha effetti collaterali se il metodo è statico o meno. Oltre a rompere l'incapsulamento, questo significa che dovrai cambiare i metodi da statico a istanza se / quando li modifichi per avere effetti collaterali. Ti suggerisco di leggere il principio Open / Closed per questo e vedere come l'approccio suggerito, citato sopra, funziona tenendo a mente quello.

Ricorda che la vecchia castagna, "l'ottimizzazione prematura è la radice di tutti i mali". Penso che in questo caso ciò significhi non saltare attraverso i cerchi usando tecniche inadeguate (ad es. Programmazione orientata alla classe) fino a quando non sai di avere un problema di prestazioni. Anche allora esegui il debug del problema e cerca il più appropriato.

I metodi statici sono molto più veloci e utilizzano molta meno memoria. C'è questo malinteso che è solo un po 'più veloce. È un po 'più veloce finché non lo metti su anelli. A proposito, alcuni loop sembrano piccoli ma in realtà non lo sono perché la chiamata del metodo contenente il loop è anche un altro loop. Puoi distinguere il codice che esegue le funzioni di rendering. Molto meno memoria è purtroppo vera in molti casi. Un'istanza consente una facile condivisione delle informazioni con metodi gemelli. Un metodo statico richiederà le informazioni quando ne ha bisogno.

Ma come nella guida di automobili, la velocità comporta responsabilità. I metodi statici di solito hanno più parametri rispetto alla loro controparte dell'istanza. Poiché un'istanza si occuperebbe della memorizzazione nella cache delle variabili condivise, i metodi dell'istanza appariranno più belli.

ShapeUtils.DrawCircle(stroke, pen, origin, radius);

ShapeUtils.DrawSquare(stroke, pen, x, y, width, length);

VS

ShapeUtils utils = new ShapeUtils(stroke,pen);

util.DrawCircle(origin,radius);

util.DrawSquare(x,y,width,length);

In questo caso, ogni volta che le variabili di istanza vengono utilizzate da tutti i metodi la maggior parte delle volte, i metodi di istanza ne valgono la pena. Le istanze NON SONO DI STATO, si tratta di CONDIVISIONE sebbene lo STATO COMUNE sia una forma naturale di CONDIVISIONE, NON SONO LO STESSO. La regola generale è questa: se il metodo è strettamente associato ad altri metodi --- si amano così tanto che quando vengono chiamati uno, anche l'altro deve essere chiamato e probabilmente condividono la stessa tazza d'acqua-- -, dovrebbe essere fatto istanza. Tradurre metodi statici in metodi di istanza non è poi così difficile. Devi solo prendere i parametri condivisi e metterli come variabili di istanza. Il contrario è più difficile.

Oppure puoi creare una classe proxy che collegherà i metodi statici. Mentre in teoria può sembrare più inefficiente, la pratica racconta una storia diversa. Questo perché ogni volta che devi chiamare DrawSquare una volta (o in un ciclo), vai direttamente al metodo statico. Ma ogni volta che lo userete più volte insieme a DrawCircle, userete il proxy dell'istanza. Un esempio sono le classi SystemInIO FileInfo (istanza) vs File (statico).

I metodi statici sono testabili. In effetti, ancora più testabile dell'istanza una volta. Il metodo GetSum (x, y) sarebbe molto testabile non solo per test unitari, ma per test di carico, test integrato e test di utilizzo. I metodi di istanza sono buoni per i test delle unità, ma orribili per tutti gli altri test (che contano più dei test delle unità BTW) per questo motivo riceviamo così tanti bug in questi giorni. La cosa che rende NON testabili TUTTI i metodi sono parametri che non hanno senso come (Sender, EventArgs e) o stato globale come DateTime.Now. In effetti, i metodi statici sono così bravi nella testabilità che vedi meno bug nel codice C di una nuova distribuzione Linux rispetto al tuo programmatore OO medio (è pieno di s *** lo so).

Penso che tu abbia parzialmente risposto a questa domanda nel modo in cui l'hai posta: ci sono evidenti penali di prestazione nel codice che hai?

Se le penalità non sono evidenti, non devi necessariamente fare nulla. (Anche se è ovvio che la base di codice trarrebbe grandi benefici da un graduale refactoring in un rispettabile modello OO).

Suppongo sia quello che sto dicendo, un problema di prestazioni è solo un problema quando noti che è un problema.

Mi sembra sciocco creare un oggetto SOLO in modo da poter chiamare un metodo che apparentemente non ha effetti collaterali sull'oggetto (dalla tua descrizione presumo questo). Mi sembra che un compromesso migliore sarebbe avere diversi oggetti globali e semplicemente usarli. In questo modo puoi inserire le variabili che normalmente sarebbero globali nelle classi appropriate in modo che abbiano un ambito leggermente più piccolo.

Da lì puoi spostare lentamente l'ambito di questi oggetti in modo da renderli sempre più piccoli fino a quando non avrai un design OOP decente.

Quindi, l'approccio che I probabilmente userebbe è diverso;).

Personalmente, probabilmente mi concentrerei sulle strutture e sulle funzioni che operano su di esse e proverei a convertirle in classi con membri a poco a poco.

Per quanto riguarda l'aspetto prestazionale della domanda, i metodi statici dovrebbero essere leggermente più veloci (ma non molto) poiché non implicano la costruzione, il passaggio e la decostruzione di un oggetto.

Non è valido in PHP,
Il metodo Object è più veloce:
http://www.vanylla.it/tests/static-method-vs -object.php

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top