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.
FfredriknMedlem sedan okt. 200850 inlägg
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.
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?
SSPiNMedlem sedan mars 20007 896 inlägg 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(). :)
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
Hmm, nä, blir inge bra ändå! :(
Då settern är tom kan inte nhibernate fylla listan från databasen.
SSPiNMedlem sedan mars 20007 896 inlägg 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);
}
}
SSPiNMedlem sedan mars 20007 896 inlägg 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?
SPiN skrev:
En chansning?
Som inte gick hem! ;) Däremot ser loopningen ovanför ut att kunna fungera! :)
SSPiNMedlem sedan mars 20007 896 inlägg 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
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 :)
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;
}
EerkaMedlem sedan dec. 19996 522 inlägg 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>
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?
EerkaMedlem sedan dec. 19996 522 inlägg GGladhMedlem sedan maj 20012 812 inlägg 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
spangoMedlem sedan juni 20008 205 inläggIList (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;
}
}