Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > it.comp.www.php > #22357 > unrolled thread
| Started by | alex <1j9448a02@lnx159sneakemail.com.invalid> |
|---|---|
| First post | 2018-11-23 08:51 +0100 |
| Last post | 2018-11-27 08:25 +0100 |
| Articles | 15 — 4 participants |
Back to article view | Back to it.comp.www.php
parent::__contruct() prima o dopo alex <1j9448a02@lnx159sneakemail.com.invalid> - 2018-11-23 08:51 +0100
Re: parent::__contruct() prima o dopo Alessandro Pellizzari <shuriken@amiran.it> - 2018-11-24 09:07 +0000
Re: parent::__contruct() prima o dopo alex <1j9448a02@lnx159sneakemail.com.invalid> - 2018-11-24 14:39 +0100
Re: parent::__contruct() prima o dopo Alessandro Pellizzari <shuriken@amiran.it> - 2018-11-24 13:51 +0000
Re: parent::__contruct() prima o dopo alex <1j9448a02@lnx159sneakemail.com.invalid> - 2018-11-24 16:04 +0100
Re: parent::__contruct() prima o dopo Alessandro Pellizzari <shuriken@amiran.it> - 2018-11-25 11:12 +0000
Re: parent::__contruct() prima o dopo alex <1j9448a02@lnx159sneakemail.com.invalid> - 2018-11-26 11:26 +0100
Re: parent::__contruct() prima o dopo Alessandro Pellizzari <shuriken@amiran.it> - 2018-11-26 10:31 +0000
Re: parent::__contruct() prima o dopo alex <1j9448a02@lnx159sneakemail.com.invalid> - 2018-11-26 12:26 +0100
Re: parent::__contruct() prima o dopo Alessandro Pellizzari <shuriken@amiran.it> - 2018-11-26 11:45 +0000
Re: parent::__contruct() prima o dopo alex <1j9448a02@lnx159sneakemail.com.invalid> - 2018-11-26 13:02 +0100
Re: parent::__contruct() prima o dopo Alessandro Pellizzari <shuriken@amiran.it> - 2018-11-26 15:18 +0000
Re: parent::__contruct() prima o dopo Flavix <imeil@a.a> - 2018-11-26 17:03 +0100
Re: parent::__contruct() prima o dopo Alessandro Pellizzari <shuriken@amiran.it> - 2018-11-26 16:20 +0000
Re: parent::__contruct() prima o dopo off line <mail@inva.it> - 2018-11-27 08:25 +0100
| From | alex <1j9448a02@lnx159sneakemail.com.invalid> |
|---|---|
| Date | 2018-11-23 08:51 +0100 |
| Subject | parent::__contruct() prima o dopo |
| Message-ID | <pt8bik$jv7$1@gioia.aioe.org> |
class A extends B {
private $_saveAs;
function __construct1($saveAs, $wrapped) {
$this->_saveAs = $saveAs;
parent::__construct( $wrapped );
}
function __construct2($saveAs, $wrapped) {
parent::__construct( $wrapped );
$this->_saveAs = $saveAs;
}
}
Quale dei due costruttori scegliere?
[toc] | [next] | [standalone]
| From | Alessandro Pellizzari <shuriken@amiran.it> |
|---|---|
| Date | 2018-11-24 09:07 +0000 |
| Message-ID | <g5sin5Flg5vU2@mid.individual.net> |
| In reply to | #22357 |
On 23/11/2018 07:51, alex wrote:
> class A extends B {
> private $_saveAs;
>
> function __construct1($saveAs, $wrapped) {
> $this->_saveAs = $saveAs;
> parent::__construct( $wrapped );
> }
>
> function __construct2($saveAs, $wrapped) {
> parent::__construct( $wrapped );
> $this->_saveAs = $saveAs;
> }
> }
>
> Quale dei due costruttori scegliere?
Evita l'ereditarietà, se puoi.
E poi scegli quello giusto per il caso d'uso. In Java sei obbligato a
chiamare parent() come prima cosa. In PHP hai flessibilità di farlo
dopo, quindi se settare _saveAs a un valore diverso può essere utile al
costruttore del genitore, usa la prima, altrimenti la seconda.
È comunque un code smell non indifferente. Probabilmente se lo stai
facendo c'è un modo migliore per fare la stessa cosa con codice più pulito.
Bye.
[toc] | [prev] | [next] | [standalone]
| From | alex <1j9448a02@lnx159sneakemail.com.invalid> |
|---|---|
| Date | 2018-11-24 14:39 +0100 |
| Message-ID | <ptbka8$1uvd$1@gioia.aioe.org> |
| In reply to | #22360 |
Il 24/11/18 10:07, Alessandro Pellizzari ha scritto:
> Evita l'ereditarietà, se puoi.
>
> E poi scegli quello giusto per il caso d'uso. In Java sei obbligato a
> chiamare parent() come prima cosa. In PHP hai flessibilità di farlo
> dopo, quindi se settare _saveAs a un valore diverso può essere utile al
> costruttore del genitore, usa la prima, altrimenti la seconda.
>
> È comunque un code smell non indifferente. Probabilmente se lo stai
> facendo c'è un modo migliore per fare la stessa cosa con codice più pulito.
interface Sender {
/**
* Invia un'email.
*/
function send();
}
class SimpleSender implements Sender {
function send() {
//...
}
}
abstract class AdvancedSender implements Sender {
protected $_wrapped;
public function __construct( Sender $wrapped ) {
$this->_wrapped = $wrapped;
}
}
class VerboseSender extends AdvancedSender {
private $_verboseStream;
public function __construct( $verboseStream, $wrapped ) {
$this->_verboseStream = $verboseStream;
parent::__construct( $wrapped );
}
function send() {
$this->_verboseStream->write('Sto inviando un email...');
$this->_wrapped->send();
}
}
Tu come faresti?
[toc] | [prev] | [next] | [standalone]
| From | Alessandro Pellizzari <shuriken@amiran.it> |
|---|---|
| Date | 2018-11-24 13:51 +0000 |
| Message-ID | <g5t3b2Fp484U1@mid.individual.net> |
| In reply to | #22362 |
On 24/11/2018 13:39, alex wrote:
> interface Sender {
> function send();
> }
>
> class SimpleSender implements Sender {
> function send() {
> abstract class AdvancedSender implements Sender {
> protected $_wrapped;
>
> public function __construct( Sender $wrapped ) {
> $this->_wrapped = $wrapped;
> }
> }
>
> class VerboseSender extends AdvancedSender {
> private $_verboseStream;
>
> public function __construct( $verboseStream, $wrapped ) {
> $this->_verboseStream = $verboseStream;
> parent::__construct( $wrapped );
> }
>
> function send() {
> $this->_verboseStream->write('Sto inviando un email...');
> $this->_wrapped->send();
> }
> }
>
> Tu come faresti?
Perché AdvancedSender è abstract?
in VerboseSender inietti già un Sender ($wrapped) e lo decori. Non ti
serve estendere AdvancedSender. Puoi avere tre classi (SimpleSender,
AdvancedSender e VerboseSender) che implementano la stessa interfaccia
Sender ed eviti ereditarietà.
Bye.
[toc] | [prev] | [next] | [standalone]
| From | alex <1j9448a02@lnx159sneakemail.com.invalid> |
|---|---|
| Date | 2018-11-24 16:04 +0100 |
| Message-ID | <ptbpir$all$1@gioia.aioe.org> |
| In reply to | #22363 |
Il 24/11/2018 14:51, Alessandro Pellizzari ha scritto:
> in VerboseSender inietti già un Sender ($wrapped) e lo decori. Non ti
> serve estendere AdvancedSender. Puoi avere tre classi (SimpleSender,
> AdvancedSender e VerboseSender) che implementano la stessa interfaccia
> Sender ed eviti ereditarietà.
A questo punto elimino del tutto la classe AdvancedSender, però in ogni
decoratore mi tocca incollare questa cosa:
private $_wrapped;
function __construct( Sender $wrapped ) {
$this->_wrapped = $wrapped;
//...
}
Volevo evitarlo.
[toc] | [prev] | [next] | [standalone]
| From | Alessandro Pellizzari <shuriken@amiran.it> |
|---|---|
| Date | 2018-11-25 11:12 +0000 |
| Message-ID | <g5vecfFac48U2@mid.individual.net> |
| In reply to | #22364 |
On 24/11/2018 15:04, alex wrote:
> in ogni
> decoratore mi tocca incollare questa cosa:
>
> private $_wrapped;
>
> function __construct( Sender $wrapped ) {
> $this->_wrapped = $wrapped;
> //...
> }
Un decoratore decora. Devi dirgli cosa decora... :)
PHP non ha una sintassi apposta per i decoratori. Il modo corretto è
proprio quello.
Tra l'altro quella è dependency injection, che va un casino negli ultimi
anni. :D
Bye.
[toc] | [prev] | [next] | [standalone]
| From | alex <1j9448a02@lnx159sneakemail.com.invalid> |
|---|---|
| Date | 2018-11-26 11:26 +0100 |
| Message-ID | <ptghpd$1lg7$1@gioia.aioe.org> |
| In reply to | #22365 |
Il 25/11/18 12:12, Alessandro Pellizzari ha scritto: > Un decoratore decora. Devi dirgli cosa decora...:) > PHP non ha una sintassi apposta per i decoratori. Il modo corretto è > proprio quello. E' quindi usare un decoratore astratto va bene?
[toc] | [prev] | [next] | [standalone]
| From | Alessandro Pellizzari <shuriken@amiran.it> |
|---|---|
| Date | 2018-11-26 10:31 +0000 |
| Message-ID | <g620cvFrnu5U1@mid.individual.net> |
| In reply to | #22366 |
On 26/11/2018 10:26, alex wrote: > Il 25/11/18 12:12, Alessandro Pellizzari ha scritto: >> Un decoratore decora. Devi dirgli cosa decora...:) >> PHP non ha una sintassi apposta per i decoratori. Il modo corretto è >> proprio quello. > > E' quindi usare un decoratore astratto va bene? Non capisco che utilità potrebbe avere, visto che poi devi istanziarlo, e non si può istanziare una classe astratta. Bye.
[toc] | [prev] | [next] | [standalone]
| From | alex <1j9448a02@lnx159sneakemail.com.invalid> |
|---|---|
| Date | 2018-11-26 12:26 +0100 |
| Message-ID | <ptgla2$1sd8$1@gioia.aioe.org> |
| In reply to | #22367 |
Il 26/11/18 11:31, Alessandro Pellizzari ha scritto: > On 26/11/2018 10:26, alex wrote: > >> Il 25/11/18 12:12, Alessandro Pellizzari ha scritto: >>> Un decoratore decora. Devi dirgli cosa decora...:) >>> PHP non ha una sintassi apposta per i decoratori. Il modo corretto è >>> proprio quello. >> >> E' quindi usare un decoratore astratto va bene? > > Non capisco che utilità potrebbe avere, visto che poi devi istanziarlo, > e non si può istanziare una classe astratta. > > Bye. Eh????????? Comunque ecco due link https://code.tutsplus.com/tutorials/design-patterns-the-decorator-pattern--cms-22641 https://csharpcorner-mindcrackerinc.netdna-ssl.com/UploadFile/damubetha/decorator-pattern-in-csharp/Images/decorator.png
[toc] | [prev] | [next] | [standalone]
| From | Alessandro Pellizzari <shuriken@amiran.it> |
|---|---|
| Date | 2018-11-26 11:45 +0000 |
| Message-ID | <g624nhFsmd0U1@mid.individual.net> |
| In reply to | #22368 |
On 26/11/2018 11:26, alex wrote: > Il 26/11/18 11:31, Alessandro Pellizzari ha scritto: >> Non capisco che utilità potrebbe avere, visto che poi devi >> istanziarlo, e non si può istanziare una classe astratta. > Eh????????? > > Comunque ecco due link > https://code.tutsplus.com/tutorials/design-patterns-the-decorator-pattern--cms-22641 Che conferma quello che ho detto: non puoi istanziare la classe astratta. Puoi avere una classe astratta per semplificare il wrapping nel caso base, ma è molto limitante. Cosa succede se devi passare altra roba al decoratore, invece che solo la classe decorata? Il tuo codice richiede sia la classe wrappata che il $verboseStream, per esempio. Per quello dico che non ha senso definire una classe astratta per il decoratore. L'articolo è del 2015, tra l'altro. Usa pesantemente l'ereditarietà anche quando non serve. Molto Java-inspired. :D > https://csharpcorner-mindcrackerinc.netdna-ssl.com/UploadFile/damubetha/decorator-pattern-in-csharp/Images/decorator.png Questo a me pare abbastanza insulso, onestamente. C'è già un'interfaccia che il decoratore deve implementare. A cosa serve avere anche una classe astratta? Forse dipende da limitazioni di C# o di Java, ma in PHP non ha proprio senso. Serve solo a rendere meno flessibile e più lento il codice. Bye.
[toc] | [prev] | [next] | [standalone]
| From | alex <1j9448a02@lnx159sneakemail.com.invalid> |
|---|---|
| Date | 2018-11-26 13:02 +0100 |
| Message-ID | <ptgndd$mh$1@gioia.aioe.org> |
| In reply to | #22369 |
Il 26/11/18 12:45, Alessandro Pellizzari ha scritto:
> On 26/11/2018 11:26, alex wrote:
>
>> Il 26/11/18 11:31, Alessandro Pellizzari ha scritto:
>
>>> Non capisco che utilità potrebbe avere, visto che poi devi
>>> istanziarlo, e non si può istanziare una classe astratta.
>
>> Eh?????????
>>
>> Comunque ecco due link
>> https://code.tutsplus.com/tutorials/design-patterns-the-decorator-pattern--cms-22641
>
>
> Che conferma quello che ho detto: non puoi istanziare la classe astratta.
Ma penso che si possa istanziare una delle classi derivate, mi pare
*super ovvio*.
> Puoi avere una classe astratta per semplificare il wrapping nel caso
> base, ma è molto limitante. Cosa succede se devi passare altra roba al
> decoratore, invece che solo la classe decorata?
Cioè?
Cmq un decoratore dovrebbe solo richiedere il $wrapper e nient'altro, o
sbaglio?
> Il tuo codice richiede sia la classe wrappata che il $verboseStream, per
> esempio.
>
> Per quello dico che non ha senso definire una classe astratta per il
> decoratore. L'articolo è del 2015, tra l'altro. Usa pesantemente
> l'ereditarietà anche quando non serve. Molto Java-inspired. :D
>
>> https://csharpcorner-mindcrackerinc.netdna-ssl.com/UploadFile/damubetha/decorator-pattern-in-csharp/Images/decorator.png
>
>
> Questo a me pare abbastanza insulso, onestamente. C'è già un'interfaccia
> che il decoratore deve implementare. A cosa serve avere anche una classe
> astratta?
Ad evitare di ripetere questa cosa:
private $wrapped;
function __construct( Sender $wrapped ) {
$this->wrapped = $wrapped;
}
Mi sembra che l'avevo già scritto.
> Forse dipende da limitazioni di C# o di Java, ma in PHP non ha proprio
> senso. Serve solo a rendere meno flessibile e più lento il codice.
Un esempio?
[toc] | [prev] | [next] | [standalone]
| From | Alessandro Pellizzari <shuriken@amiran.it> |
|---|---|
| Date | 2018-11-26 15:18 +0000 |
| Message-ID | <g62h5bFssoU1@mid.individual.net> |
| In reply to | #22370 |
On 26/11/2018 12:02, alex wrote:
> Cmq un decoratore dovrebbe solo richiedere il $wrapper e nient'altro, o
> sbaglio?
Mi pare che abbiamo già avuto questa conversazione qualche mese fa...
Questo è il codice che hai scritto tu:
class VerboseSender extends AdvancedSender {
private $_verboseStream;
public function __construct( $verboseStream, $wrapped ) {
$this->_verboseStream = $verboseStream;
parent::__construct( $wrapped );
}
function send() {
$this->_verboseStream->write('Sto inviando un email...');
$this->_wrapped->send();
}
}
Che, tra parentesi, trasformi in decoratore cambiando solo la prima riga
class VerboseSender implements Sender {
...
}
Questo è un decoratore, e prende $verboseStream, oltre a $wrapped.
>> A cosa serve avere
>> anche una classe astratta?
>
> Ad evitare di ripetere questa cosa:
>
> private $wrapped;
>
> function __construct( Sender $wrapped ) {
> $this->wrapped = $wrapped;
> }
> Mi sembra che l'avevo già scritto.
Sì, e io ripeto che mi sembra un motivo insulso.
Ci sono ben pochi decoratori che non hanno bsogno di altre informazioni
oltre all'oggetto wrappato. Tipicamente fanno cose abbastanza basilari,
tipo `toUpper`.
Ma se wrappi un oggetto tipicamente vuoi fare qualcosa di più, tipo,
appunto, scrivere info aggiuntive in uno stream (e ti serve lo stream),
personalizzare il comportamento in base a dati esterni (e ti serve una
connessione al DB o un oggetto coi i dati da aggiungere), ecc.
In programmazione funzionale puoi fare currying del decoratore (in
pratica generare dinamicamente un decoratore prima di applicarlo
all'oggetto/funziona wrappata), ma in OOP devi passare roba al
costruttore (o avere un DecoratorFactory... more Java! :P)
>> Forse dipende da limitazioni di C# o di Java, ma in PHP non ha proprio
>> senso. Serve solo a rendere meno flessibile e più lento il codice.
>
> Un esempio?
Vedi sopra.
Bye.
[toc] | [prev] | [next] | [standalone]
| From | Flavix <imeil@a.a> |
|---|---|
| Date | 2018-11-26 17:03 +0100 |
| Message-ID | <pth5q3$ro7$1@gioia.aioe.org> |
| In reply to | #22371 |
Il 26/11/2018 16:18, Alessandro Pellizzari ha scritto:
> Che, tra parentesi, trasformi in decoratore cambiando solo la prima riga
>
> class VerboseSender implements Sender {
> ...
> }
Scusate se mi intrometto, ma allora quello di alex cos'era?x
> Sì, e io ripeto che mi sembra un motivo insulso.
> Ci sono ben pochi decoratori che non hanno bsogno di altre informazioni
> oltre all'oggetto wrappato. Tipicamente fanno cose abbastanza basilari,
> tipo `toUpper`.
>
> Ma se wrappi un oggetto tipicamente vuoi fare qualcosa di più, tipo,
> appunto, scrivere info aggiuntive in uno stream (e ti serve lo stream),
> personalizzare il comportamento in base a dati esterni (e ti serve una
> connessione al DB o un oggetto coi i dati da aggiungere), ecc.
>
> In programmazione funzionale puoi fare currying del decoratore (in
> pratica generare dinamicamente un decoratore prima di applicarlo
> all'oggetto/funziona wrappata), ma in OOP devi passare roba al
> costruttore (o avere un DecoratorFactory... more Java! :P)
E qual'è il problema?
[toc] | [prev] | [next] | [standalone]
| From | Alessandro Pellizzari <shuriken@amiran.it> |
|---|---|
| Date | 2018-11-26 16:20 +0000 |
| Message-ID | <g62kr8F1mpcU1@mid.individual.net> |
| In reply to | #22372 |
On 26/11/2018 16:03, Flavix wrote:
> Il 26/11/2018 16:18, Alessandro Pellizzari ha scritto:
>> Che, tra parentesi, trasformi in decoratore cambiando solo la prima riga
>>
>> class VerboseSender implements Sender {
>> ...
>> }
>
> Scusate se mi intrometto, ma allora quello di alex cos'era?x
Vedi la discussione di qualche mese fa riguardo decoratori, wrapper,
proxy, ecc. ecc.
Diversi nomi con minime differenze, ma il succo è lo stesso: wrappare un
oggetto per fargli fare altre cose non previste senza dover modificare
il codice originale.
Tecnicamente entrambi sono decoratori (mantengono la stessa interfaccia
pubblica). Avere una classe astratta in mezzo non serve a niente.
>> In programmazione funzionale puoi fare currying del decoratore (in
>> pratica generare dinamicamente un decoratore prima di applicarlo
>> all'oggetto/funziona wrappata), ma in OOP devi passare roba al
>> costruttore (o avere un DecoratorFactory... more Java! :P)
>
> E qual'è il problema?
Sovraingegnerizzazione, che in questo caso, oltre a essere inutile, è
anche dannosa (per le prestazioni e la flessibilità, oltre che per la
pulizia del codice)
In Java viene parzialmente attenuato il problema, perché c'è una fase di
compilazione, in cui l'optimizer potrebbe anche accorgersi che non usi
mai alcuni percorsi della Factory, o che la classe astratta è
piccolissima, e potrebbe decidere di mettere il codice inline,
cancellando di fattola factory o l'abstract.
In PHP non c'è questa fase (anche perché PHP compila in millisecondi,
mentre Java a volte impiega minuti), quindi ti becchi il problema a runtime.
Bye.
[toc] | [prev] | [next] | [standalone]
| From | off line <mail@inva.it> |
|---|---|
| Date | 2018-11-27 08:25 +0100 |
| Message-ID | <ptirgi$1flv$1@gioia.aioe.org> |
| In reply to | #22373 |
Il 26/11/18 17:20, Alessandro Pellizzari ha scritto: >> >> Scusate se mi intrometto, ma allora quello di alex cos'era?x > > Vedi la discussione di qualche mese fa riguardo decoratori, wrapper, > proxy, ecc. ecc. interesserebbe anche a me ma non la trovo
[toc] | [prev] | [standalone]
Back to top | Article view | it.comp.www.php
csiph-web