webForumDet fria alternativet

Exponera Listor

.NET

36 svar · 1 836 visningar · startad av johannormen · sida 2 av 2

Frågan, av johannormen

Tänkte kolla med er om ni brukar exponera typ IList, List o sånt från era publika proppar eller metoder? haft en liten diskussion ang detta. Där vi alla var eniga om att man inte skall göra det av olika skäl bla det stora skälet att en IList har en hel del metoder och då menar jag rätt många metoder som enligt en ren OOP inte bör finnas där i sin applikations yttre. Om man skall använda IList m.m

Läs frågan i sin helhet →
Medlem sedan aug. 20003 575 inlägg
#21

johannormen skrev:

Problemet som uppstår här är Singe Responsability Principle/Rule.
Helt plötsligt blir din lista som egentligen mer eller mindre är en datacontainer beroende av så mkt mer än just containa... Ett annat problem är att OrderListan har inte reglerna som order kan kräva för viss kund etc. dessa regler äger Ordern. Vilket gör att det bör vara ordern som kör businesslogiken o kollar att man verkligen kan lägga till mer saker till ordern m.m.

Argumentet att alla är vana är sant. Problemet är bara att de är vara för de oftast inte har så stor kunskap om koddesign. Man härmar av exempel som ex microsoft har, man härmar av andra som härmat av andra etc... Det är för många idag som tyvärr inte baserar sin .Net kod efter OO samt OOP. Utan det är någon blandning av OO och gamla scriptvärldens tid, funktionsorienteringen etc som gör att man är van. Men vi ser ju felen oxå allt för ofta men ökad risk för spagettikod,. för komplexkod. för många sätt att ändra koden på etc...

Så jag tycker det är dags att göra det mer vant att nyttja OO...

Collectionen kan ha reglerna via olika lösningar eller fråga ordern om det är okej att lägga till det nya OrderItem. Men som vi kommit fram till så säger OO böckerna att man inte ska exponera listor.

En annan intressant sak är varför dom förespråkar att man skall göra på detta sättet? Att man inte skall exponera för mycket funktionalitet är en sak som jag köper men vad finns det fler för saker man tjänar på. Orsaken till att jag frågar detta är inte att jag är emot att man inte skall exponera listor jag tycker diskussionen är bra. Jag har bara inte riktigt bestämt mig på vilken sida jag skall landa :).

Nackdelen jag kan se med inwrappning av funktionaliteten är i ett projekt med 5 utvecklare där en person förespråkar OO-sättet och de andra 4 är vana vid Order.OrderItems.Add istället för Order.AddOrderItem() vad är mest korrekt i sådanafall. Men finns det flera konkreta fördelar med det andra så är det väl rätt att köra på. Som sagt regler går ju alltid att ha i din OrderItemCollection.

Medlem sedan okt. 200850 inlägg
#22

Nickemannen skrev:

Nackdelen jag kan se med inwrappning av funktionaliteten är i ett projekt med 5 utvecklare där en person förespråkar OO-sättet och de andra 4 är vana vid Order.OrderItems.Add istället för Order.AddOrderItem() vad är mest korrekt i sådanafall. Men finns det flera konkreta fördelar med det andra så är det väl rätt att köra på. Som sagt regler går ju alltid att ha i din OrderItemCollection.

Mitt svar är: Det beror på domän modellen.

Medlem sedan juni 20003 076 inlägg
#23

Hmm, får inte ihop det riktigt!
Har denna kod:

private IList<BusinessRegisterGroup> _groups = new List<BusinessRegisterGroup>();
public virtual IEnumerable<BusinessRegisterGroup> Groups
{
      get { return _groups; }
      private set { _groups = [b]value[/b]; }
}

public virtual void AddGroup(BusinessRegisterGroup group)
{
      if(!_groups.Contains(group))
           _groups.Add(group);
}

Det är settern den bråkar på: Cannot implicitly convert ...

Först kommenaterade jag bort settern helt men då bråkar NHibernate om att den måste finnas, så hur ska det se ut?

Medlem sedan mars 20007 896 inlägg
#24

Du behöver ju inte ha någon setter alls, då du lägger till element till listan med metoden AddGroup().

Hur som helst beror felet på att IList ärver från (implements) IEnumerable, inte tvärtom. Det betyder att du kan få en IList att bete sig som en IEnumerable, men du kan inte få en IEnumerable att bete sig som en IList då den kan komma att sakna implementationsmetoder som interfacet IList definierar.

Så lämna settern tom, och lägg till element via IList.Add(). :)

Medlem sedan juni 20003 076 inlägg
#25

SPiN skrev:

Så lämna settern tom, och lägg till element via IList.Add()

Ahh, tänkte aldrig på att settern kan vara helt tom! Tack! :bire

Medlem sedan juni 20003 076 inlägg
#26

Hmm, nä, blir inge bra ändå! :(
Då settern är tom kan inte nhibernate fylla listan från databasen.

Medlem sedan mars 20007 896 inlägg
#27

Förlåt, jag missade helt att du använde NHibernate. Då blir det såklart krångligare, för som jag förstår det vill du kunna sätta en IList i propertyn men hämta den som IEnumerable? Jag skulle tyvärr gissa på att du får, vid settern, tömma din lista och fylla den med datan från IEnumerable och spara till privata listan... Men så är jag ju ingen .NET-programmerare heller, så det kanske finns bättre sätt. ;)

public IEnumerable<BusinessRegisterGroup> Groups {
    get {
        return _groups;
    }
    set {
        _groups.Clear();
        foreach(BusinessRegisterGroup brg in value)
            _groups.Add(brg);
    }
}
Medlem sedan mars 20007 896 inlägg
#28

Felmeddelandet sa i och för sig att en implicit kastning inte kunde göras - kan du kanske explicit kasta om till en IEnumerable? Logiskt sett så borde det inte gå - men vi pratar ju faktiskt om MS-programvara här. ;)

set {
    _groups = (IEnumerable) value;
}

En chansning?

Medlem sedan juni 20003 076 inlägg
#29

SPiN skrev:

En chansning?

Som inte gick hem! ;) Däremot ser loopningen ovanför ut att kunna fungera! :)

Medlem sedan mars 20007 896 inlägg
#30

Som jag gissade då. I och med att IList definierar fler metoder än vad IEnumerable gör, bör det (och det var det!) omöjligt att kasta om den till en förälder-klass/-interface. Loopning borde fungera, ja - det tråkiga är att du måste iterera igenom för att få tag på värdena. :l

Medlem sedan aug. 20003 575 inlägg
#31

doggelito skrev:

Hmm, nä, blir inge bra ändå! :(
Då settern är tom kan inte nhibernate fylla listan från databasen.

Pröva private set, eller sätt fältet så slipper du problemet :)

Medlem sedan maj 200010 687 inlägg
#32

Jag trivs bättre med att använda Collection/KeyedCollection/ReadOnlyCollection för properties och return-typ på metoder. Tycker det är ganska trevligt att ge användaren en Count property.
Går lätt att extenda för egna typer där man vill kontrollera mer...

Sen är IEnumerable bra för parametrar till metoder där man inte behöver mer än att loopa igenom listan. ReSharper är bra på att ge förslag om sånt.
Sen så kan man ju också använda IEnumerable för att returnerade uträknade värden som en lista, men man vet inte hur många användarna kommer loopa igenom och returnerar dem då när användarna vill ha dem med yield return. Inget man vanligtvis gör dock...

Att loopa i settern känns inte som ett bra sätt. Dålig trådsäkerhet bl.a.
Går ju att skriva:

set {
    _groups = new List(value);
}

...men då blir det ju också en helt ny lista.

SPiN försökte ju casta, men gjorde det åt fel håll.
Detta hade fungerat om källan faktiskt är en List. Men det kan man ju inte kräva att den ska vara...

set {
    _groups = (List) value;
}
Medlem sedan dec. 19996 522 inlägg
#33

Med Nhibernate borde du kunna göra följande

public class MyClass
{
private readonly IList<MyObject> _myObjects;

public IEnumerable<MyObject> MyObjects
        {
            get{return _myObjects;}
}
public MyClass()
{
_myObjects = new List<MyObject>();
}

public void AddObject(MyObject myObject)
{
            if (myObject== null) throw new ArgumentNullException("myObject");
            _myObjects.Add(myObject);
}

}

och din mappning


<bag name="_myObjects" access="field" generic="true" inverse="true" cascade="none"  table="MyClassMyObjects" >
  <key column="MyClassId" />
  <many-to-many class="MyObject,MyAssembly"
                column="MyObjectId" />
</bag>
Medlem sedan maj 20011 312 inlägg
#34

Hur vore det att skapa en egen generell generisk CustomList som har count-metoden m.m. fast inte metoder som add, remove m.m? Jag misstänker att detta skapar problem eftersom ni inte tagit upp det men vilka är problem om man skulle skapa en sådan lista?

Medlem sedan dec. 19996 522 inlägg
Medlem sedan maj 20012 812 inlägg
#36

Om jag inte har helt fel för mig så har man i .NET 3.5 lagt till .Count() som en extension-metod på IList. Och om man inte har det, så är det bara att göra själv.

- M

Medlem sedan juni 20008 205 inlägg
#37

IList (och ICollection) har alltid haft en Count-property, det är IEnumerable<T> som har fått en extensionmetod Count() som funkar ungefär så här:

public int Count<T>(this IEnumerable<T> e)
{
    var c = e as ICollection<T>;
    if (c != null) return c.Count;
    else 
    {
        int n = 0;
        foreach (var o in e) ++n;
        return n;
    }
}
268 ms totalt · 4 externa anrop · v20260731065814-full.a51de22e
126 ms — deklarationer (db)
0 ms — hämta statistik (cache)
139 ms — hämta tråd, inlägg och bilagor (db)
119 ms — ändringar (db)