Estendere una struttura. Usare classi di aiuto piuttosto che composizione

1

Ho una struttura a cui voglio aggiungere metodi statici. Sì, hai indovinato, sto parlando di Datetime .

È un requisito piuttosto tipico aggiungere MyCustomParse. Capita di restituire Datetime? , quindi non è un costruttore, ma è in quell'area, un metodo statico che restituisce un'istanza. Il contenuto di questo metodo è già stato scritto e attualmente vive felice come metodo di istanza di una classe che lo utilizza. Voglio portarlo fuori da quella classe così posso usarlo altrove.

Tradizionalmente lo inserisco in una classe helper (che è ciò che ho fatto qui), ma a quanto pare sono cattivi .

Quello che voglio veramente fare è legare Datetime.MyCustomParse(mystring) . Ma l'unico modo che vedo è creare una nuova struttura che compone Datetime . Poi aggiungo il mio metodo, scrivo le conversioni implicite e poi inserisco tutti gli altri metodi Datetime , ecc. Questo sarebbe un problema da codificare (Essere verboso causa anche problemi con i documenti xml e il codice ingenuo metriche di copertura, se ciò conta per qualsiasi cosa).

Ho preso in considerazione i metodi di estensione , ma non penso che i metodi abbiano senso sulle istanze.

Qual è la rigida posizione OO? Ricevo un metodo per scrivere metodi che dovrebbero appartenere alle classi in classi helper separate quando voglio estendere le strutture in questo modo?

Qual è la posizione pragmatica (non sto dicendo che OO non è pragmatico), è questo codice che vorresti scrivere o ho perso un trucco?

internal static class DateTimeHelper
{

    public static DateTime? MyCustomParse(string utcDateTimeText, string[] formats)
    {
        DateTime utcDateTime;
        if (DateTime.TryParseExact(utcDateTimeText, formats, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out utcDateTime))
        {
            return utcDateTime;
        }

        return null;
    }
}

PS So che ci sono visualizzazioni più sfumate sulle classi helper , ma mi sento ancora ho bisogno di giustificare il mio uso qui.

    
posta Nathan Cooper 07.08.2014 - 15:01
fonte

3 risposte

3

What is the strict OO position?

"strict" non è definito nello spazio OO?

What is the pragmatic position? I want to bring it out of that class so I can use it elsewhere. The content of this method has already been written and currently happy lives as a instance method of a class that uses it.

Razionalizzazione OO

Bene, un approccio potrebbe essere quello di pensare ai schemi di progettazione creazionali . Lo vedo come contrappunto all'idea di "classe helper". Vedo l'helper come una sorta di smorgasbord - incoerente in termini di design di oggetti di dominio.

Ma una Fabbrica, un Costruttore, ecc. compongono il comportamento all'interno di un oggetto, una cosa coerente al dominio. In che modo è diverso da una classe di aiuto? Intento.

OO Il pragmatismo incontra l'intenzione

Refactor per trasformare il metodo in un delegato. È possibile dichiarare il delegato a livello di spazio dei nomi, se necessario.

Scrivi un elemento di istanza qualcosa che registri / associa / qualunque sia il metodo delegato. Prevedo che l'implementazione del metodo sarà all'interno di questo qualcosa .

Lo scopo di

Somthing nella vita è quello di istanziare oggetti completamente realizzati della classe / struttura. Qualcosa non contiene quei metodi casuali "casuali" specifici (ma non di proprietà dell'istanza).

E a causa dell'intento non vogliamo l'approccio pragmatico di un metodo statico di classe, che hai già ignorato.

    
risposta data 07.08.2014 - 21:14
fonte
2

Perché non utilizzare un metodo di estensione?

public static class DateTimeExtensions
{
   public static DateTime? AsDateTime(this string value, string[] formats)
   {
       DateTime utcDateTime;

       if (DateTime.TryParseExact(utcDateTimeText, formats,CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out utcDateTime))
       {
            return utcDateTime;
       }

       return null;
   }
 }

Questo estenderà il tipo di stringa aggiungendo il metodo AsDateTime.

string[] formats= {"M/d/yyyy h:mm:ss tt", "MM/dd/yyyy h:mm:ss tt" }; 
string unParsedDateTime = "05/01/2009 6:32:05 PM";

DateTime parsed = unParsedDateTime.AsDateTime(formats);
// or  
parsed = "05/01/2009 6:32:05 PM".AsDateTime(formats);
    
risposta data 07.08.2014 - 23:05
fonte
1

Le classi helper possono essere un anti-pattern organizzativo quando si dispone di un file generico Helpers in cui si riversano tutte le singole funzioni statiche miscellanee che tutti i progetti hanno mai utilizzato. Non farlo. Indipendentemente da ciò, non sono male . Un metodo statico è il posto giusto dove mettere alcuni calcoli usati di frequente che non hanno bisogno di guardare lo stato privato di qualsiasi oggetto. Funzioni come MyCustomParse in realtà non appartengono a nessuna classe: possono portare a termine il lavoro senza guardare i dettagli di implementazione di nessuno, quindi non fanno parte di alcuna astrazione. È solo uno dei tanti modi in cui puoi scegliere di convertire tra due rappresentazioni di date.

Creare classi wrapper solo perché "sente" di più OOP se la funzione è collegata a un'istanza di qualcosa causerà solo mal di testa a voi e ai futuri manutentori del codice. Oltre a dover convertire avanti e indietro tra i tipi wrapper e wrapper, dovrai modificare il wrapper o crearne di nuovi ogni volta che ti serve un nuovo metodo di supporto, e in quest'ultimo caso avrai ancora più conversioni. Non scala.

I metodi di estensione consentono di utilizzare le funzioni di aiuto con la sintassi delle chiamate ai metodi, che può essere utile per Intellisense o quando una chiamata di funzione appare migliore in forma infissa. Questo è puro zucchero sintattico; semanticamente non c'è molta differenza tra i metodi di estensione e i metodi statici regolari.

    
risposta data 07.08.2014 - 23:24
fonte

Leggi altre domande sui tag