Programim dhe zhvillim, javascript, python, php, html

Përfitimi i IoC mbi Factory Singleton tim

Duket se ka një stigmë mbi SO në lidhje me përdorimin e Singletons. Nuk e kam blerë kurrë personalisht, por për hir të mendjes së hapur po përpiqem të provoj konceptet e IoC si alternativë, sepse sinqerisht jam i mërzitur me punën time të përditshme dhe do të doja të provoja diçka ndryshe. Më falni nëse interpretimi im i koncepteve të IoC është i pasaktë ose i gabuar.

Këtu është situata: Unë po ndërtoj një server të thjeshtë ueb bazuar në HttpListener në një shërbim Windows që përdor një model shtesë për të përcaktuar se si duhet të trajtohet një kërkesë bazuar në URL-në e kërkuar (ashtu si çdokush tjetër që pyet për HttpListener). Qasja ime për të zbuluar shtojcat është të kërkoj një drejtori të konfiguruar për asambletë të zbukuruara me një HttpModuleAssemblyAttribute. Këto asamble mund të përmbajnë 0 ose më shumë IHttpModule fëmijë të cilët përveç kësaj janë zbukuruar me një HttpModuleAttribute që përdoret për të specifikuar emrin e modulit, versionin, përshkrimin e lexueshëm nga njeriu dhe informacione të tjera të ndryshme. Diçka si:

[HttpModule(/*Some property values that matter */)]
public class SimpleHttpModule : IHttpModule
{
    public void Execute(HttpListenerContext context)
    {
        /* Do Something Special */
    }
}

Kur zbulohet një HttpModule, unë zakonisht do ta shtoja atë në një objekt Dictionary<string, Type>, i cili qëllimi i vetëm është të mbajë gjurmët se për cilat module dimë. Ky fjalor zakonisht do të jetonte në varietetin tim të një Singleton që merr personalitetin e një Singleton ACE (një trashëgimi nga ditët e mia në C++ ku mësova për Singletons).

Tani ajo që unë po përpiqem të zbatoj është diçka e ngjashme duke përdorur (të kuptuarit tim) konceptet e përgjithshme të IoC. Në thelb ajo që kam është një koleksion AppService ku IAppService përkufizohet si:

public interface IAppService : IDisposable
{
    void Initialize();
}

Dhe shtojca ime AppService do të dukej diçka si kjo:

[AppService("Plugins")]
internal class PluginAppService : IAppService, IDictionary<string, Type>
{
    /* Common IDictionary Implementation consisting of something like: */
    internal Type Item(string modName)
    {
        Type modType;
        if (!this.TryGetValue(modName, out modType)
            return null;

        return modType;
    }

    internal void Initialize()
    {
        // Find internal and external plug-ins and add them to myself
    }

    // IDisposable clean up method that attempts to dispose all known plug-ins
}

Pastaj gjatë shërbimit OnStart unë instantoj një shembull të AppServices i cili është i njohur lokalisht, por i kalohet konstruktorit të të gjitha shtojcave të instancuara:

public class AppServices : IDisposable, IDictionary<string, IAppService>
{
    /* Simple implementation of IDictionary */

    public void Initialization()
    {
        // Find internal IAppService implementations, instantiate them (passing this as a constructor parameter), initialize them and add them to this.

        // Somewhere in there would be something like
        Add(appSvcName, appSvc);
    }
}

Zbatimi i metodës sonë dikur të vetme bëhet një zbatim abstrakt + një konstruktor për fëmijën:

[HttpModule(/*Some property values that matter */)]
public abstract class HttpModule : IHttpModule
{
    protected AppServices appServices = null;
    public HttpModule(AppServices services)
    {
        appServices = services;
    }            

    public abstract void Execute(HttpListenerContext context);
}

[HttpModule(/*Some property values that matter */)]
public class SimpleHttpModule : HttpModule
{
    public SimpleHttpModule(AppServices services) : base(services) { }
    public override void Execute(HttpListenerContext context)
    {
        /* Do Something Special */
    }
}

Dhe çdo akses në shërbimet e aplikacioneve të përdorura zakonisht bëhet:

var plugType = appServices["Plugins"][plugName];

më mirë se:

var plugType = PluginManager.Instance[plugName];

A më mungon ndonjë koncept bazë IoC këtu që do ta thjeshtonte të gjithë këtë apo ka vërtet një përfitim nga i gjithë ky kod shtesë? Në botën time, Singletonët janë krijesa të thjeshta që lejojnë kodin përgjatë një programi të aksesojë informacionin e nevojshëm (relativisht statik) (në këtë rast llojet).

Për të shtruar pyetjet më qartë:

  1. A është ky një zbatim i vlefshëm i një Factory Singleton të përkthyer në konceptet IoC/DI?
  2. Nëse është, ku është kthimi/përfitimi për kodin shtesë që kërkohet dhe vendosja e një API në dukje më të ngathët?

  • Ndoshta nuk po e merrni përgjigjen që po kërkoni sepse pyetja juaj është shumë e paqartë (pavarësisht se është kaq e gjatë). Ju duhet të kuptoni saktësisht se çfarë pyetjeje dëshironi t'i përgjigjeni dhe ta bëni atë. 31.01.2012
  • Unë mendoj se reagimi i përgjithshëm ndaj singletonëve është për shkak të faktit se ato janë një metodë e futjes së gjendjes globale në një aplikacion, e cila bie ndesh me dizajnin e orientuar nga objekti. Ato janë gjithashtu shpesh të vështira për t'u testuar në njësi. 09.03.2012
  • @DBM - Shteti global është në kundërshtim me OOP? Si keshtu? Në përgjithësi është një qasje e pranuar në C++ (e cila është gjithashtu OO). 09.03.2012

Përgjigjet:


1

IoC është një term i përgjithshëm. Injeksioni i varësisë është termi më i preferuar këto ditë.

Dependency Injection me të vërtetë shkëlqen në disa rrethana. Së pari, ai përcakton një arkitekturë më të testueshme sesa zgjidhjet që kanë instanca të koduara të varësisë. Singletonët janë të vështirë për t'u testuar në njësi sepse janë statike dhe të dhënat statike nuk mund të "shkarkohen".

Së dyti, Dependency Injection jo vetëm që instancon llojin që dëshironi, por të gjitha llojet e varura. Kështu, nëse klasa A ka nevojë për klasën B, dhe klasa B ka nevojë për klasën C dhe D, atëherë një kornizë e mirë DI do të krijojë automatikisht të gjitha varësitë dhe do të kontrollojë jetëgjatësinë e tyre (për shembull, duke i bërë ato të jetojnë për jetëgjatësinë e një kërkese të vetme ueb).

Kontejnerët DI mund të konsiderohen si fabrika gjenerike që mund të instantojnë çdo lloj objekti (për sa kohë që është i konfiguruar siç duhet dhe plotëson kërkesat e kornizës DI). Kështu që ju nuk keni nevojë të shkruani një fabrikë me porosi.

Ashtu si me çdo zgjidhje gjenerike, është krijuar për t'i dhënë 90% të rasteve të përdorimit atë që u nevojitet. Sigurisht, ju mund të krijoni një strukturë të të dhënave të listave të lidhura të krijuara me dorë sa herë që keni nevojë për një koleksion, por 90=% të rasteve një gjenerik funksionon mirë. E njëjta gjë është e vërtetë për DI dhe Fabrikat me porosi.

31.01.2012
  • E vlerësoj depërtimin, megjithëse jam i hutuar se si zbatohet për rrethanat e specifikuara në pyetje? Kam lexuar artikuj rreth Injeksionit të Varësisë dhe Përmbysjes së Kontrollit, por e kam përdorur këtë model në të gjitha gjuhët me përvoja pozitive të Testimit të Njësive. Pse ndërroni tani? 31.01.2012
  • E thënë ndryshe, çfarë në lidhje me skenarin tim të përshkruar e bën DI një zgjedhje më të mirë? A po më mungon koncepti? 31.01.2012
  • Duhet gjithashtu të theksohet se ka një ndryshim midis Inversion of Control (IoC) dhe Dependency Injection (DI), stackoverflow.com/questions/4596300/ 31.01.2012
  • @M.Babcock - Nuk thashë se ishte një zgjedhje më e mirë. Vetëm ju mund ta vendosni këtë. Unë adresoj pyetjen tuaj në lidhje me fabrikën IoC vs Singleton, dhe shpjegova pse Singletons janë të këqija për testim dhe se si DI është më gjenerike dhe bën më shumë sesa instantimin e një objekti të vetëm. 31.01.2012
  • Në disa mënyra shpresoja për një përgjigje më të qëndrueshme. E kuptoj se në fund varet nga unë se në cilën mënyrë ta hartoj aplikacionin tim. Duke pasur parasysh shtytjet mjaft të forta që kam parë drejt IoC/DI në SO, shpresoja që dikush të mund të merrte shembullin tim dhe të më tregonte pse në këtë situatë Singletonët janë të këqij. 31.01.2012
  • @M.Babcock - Duket se po lexoni më shumë në atë që thashë sesa atje. IoC është një term i përgjithshëm që zbatohet për shumë gjëra. Injeksioni i varësisë është termi i saktë për teknikën që po diskutojmë. IoC nuk është. 31.01.2012

  • 2

    IoC bëhet më interesante kur arrin të shkruash testet e njësive. Na vjen keq t'i përgjigjem një pyetjeje me më shumë pyetje, por... Si do të dukeshin testet e njësisë për të dy implementimet tuaja? A do të ishit në gjendje të bashkoni klasat e testimit që përdorën PluginManager pa kërkuar asamble nga disku?

    EDITO

    Vetëm për shkak se mund të arrini të njëjtin funksionalitet me beqarë nuk do të thotë se është aq i lehtë për t'u mirëmbajtur. Duke përdorur IoC (të paktën këtë stil me konstruktorët) ju po deklaroni në mënyrë eksplicite varësitë që ka një objekt. Duke përdorur singletons, ai informacion fshihet brenda klasës. Gjithashtu e bën më të vështirë zëvendësimin e atyre varësive me implementime alternative.

    Pra, me një singleton PluginManager do të ishte e vështirë të testosh serverin tënd HTTP me shtojca të rreme, në vend që t'i kërkosh ato nga një vendndodhje në disk. Me versionin IoC, ju mund të kaloni një version alternativ të IAppService që thjesht shikon shtojcat nga një Dictionary e parapopulluar.

    31.01.2012
  • Bazuar në natyrën e një kornize plug-in (edhe më konkretisht atë që kam përcaktuar këtu), talljet janë të lehta për t'u zbatuar sepse ato duhet vetëm të dekorohen me një HttpModuleAttribute me të njëjtin emër dhe të zbatojnë ndërfaqen. Kuadri është injorant përtej kësaj. Realisht të dy implementimet tregojnë varësitë sepse të dyja zbatojnë kërkesën që IHttpModule ose HttpModule të zbatohet. Ndoshta shembuj më konkretë të mangësive do të ndihmonin. 31.01.2012
  • Çfarë e përdor PluginManager megjithatë? Këtu do të shihni ndryshimin IMHO. 31.01.2012
  • Vetë korniza përdor PluginManager në varësi të URL-së së marrë. http://server.com/moduleName/someFile.txt do të ishte diçka e konsumuar nga korniza dhe moduleName do të ishte emri i modulit të regjistruar ose me PluginManager ose PluginAppService. Sido që të jetë, ndërveprimi i tij me të është i njëjtë. 31.01.2012

  • 3

    Ndonëse ende nuk jam vërtet i bindur se IoC/DI është më i mirë në këtë situatë, unë padyshim që kam parë përfitime ndërsa shtrirja e projektit zvarritet. Për gjëra të tilla si regjistrimi dhe konfigurimi, sigurisht që është qasja e duhur.

    Mezi pres të eksperimentoj më shumë me të në projektet e ardhshme.

    09.03.2012
    Materiale të reja

    Masterclass Coroutines: Kapitulli-3: Anulimi i korutinave dhe trajtimi i përjashtimeve.
    Mirë se vini në udhëzuesin gjithëpërfshirës mbi Kotlin Coroutines! Në këtë seri artikujsh, unë do t'ju çoj në një udhëtim magjepsës, duke filluar nga bazat dhe gradualisht duke u thelluar në..

    Faketojeni derisa ta arrini me të dhënat false
    A e gjeni ndonjëherë veten duke ndërtuar një aplikacion të ri dhe keni nevojë për të dhëna testimi që duken dhe duken më realiste ose një grup i madh të dhënash për performancën e ngarkesës...

    Si të përdorni kërkesën API në Python
    Kërkesë API në GitHub për të marrë depot e përdoruesve duke përdorur Python. Në këtë artikull, unë shpjegoj procesin hap pas hapi për të trajtuar një kërkesë API për të marrë të dhëna nga..

    Një udhëzues hap pas hapi për të zotëruar React
    Në këtë artikull, do të mësoni se si të krijoni aplikacionin React, do të mësoni se si funksionon React dhe konceptet thelbësore që duhet të dini për të ndërtuar aplikacione React. Learning..

    AI dhe Psikologjia — Pjesa 2
    Në pjesën 2 të serisë sonë të AI dhe Psikologji ne diskutojmë se si makineritë mbledhin dhe përpunojnë të dhëna për të mësuar emocione dhe ndjenja të ndryshme në mendjen e njeriut, duke ndihmuar..

    Esencialet e punës ditore të kodit tim VS
    Shtesat e mia të preferuara - Git Graph 💹 Kjo shtesë është vërtet e mahnitshme, e përdor përpara se të filloj të punoj për të kontrolluar dy herë ndryshimet dhe degët më të fundit, mund të..

    Pse Python? Zbulimi i fuqisë së gjithanshme të një gjiganti programues
    Në peizazhin gjithnjë në zhvillim të gjuhëve të programimit, Python është shfaqur si një forcë dominuese. Rritja e tij meteorike nuk është rastësi. Joshja e Python qëndron në thjeshtësinë,..