2023-01-05, 16:59
  #13
Medlem
Citat:
Ursprungligen postat av bithax
"Dot syntax" r ju nd en del av sprket. Men det ska man d inte anvnda.
Du missar pongen. Jag anvnder funktionell stil s ofta som mjligt. Det ger mig mer lttlst, och mindre kod med frre buggar. T.ex. anvnder jag mycket Linq, det r en form av funktionell programmering.

En challenge: skriv om fljande kod till klassisk, imperativ stil s jmfr vi sedan?

Kod:
List<Tuple<stringstring>> tuples //
var grouped tuples.GroupBy(=> t.First)
    .
OrderBy(grp => grp.Key)
    .
Select(grp => new { Key grp.KeyItems grp.OrderBy(=> t.Second) }); 

Den stora charmen med detta r att jag inte skapar en massa egna tillstnd i programmet med olika variabler. I stllet sger jag vad jag vill ha och d fr jag det. Det finns frre mjligheter att gra fel och jag ser mycket snabbare vad koden gr.
Citera
2023-01-07, 11:00
  #14
Medlem
bithaxs avatar
Citat:
Ursprungligen postat av Binary
Du missar pongen. Jag anvnder funktionell stil s ofta som mjligt. Det ger mig mer lttlst, och mindre kod med frre buggar. T.ex. anvnder jag mycket Linq, det r en form av funktionell programmering.

En challenge: skriv om fljande kod till klassisk, imperativ stil s jmfr vi sedan?

Kod:
List<Tuple<stringstring>> tuples //
var grouped tuples.GroupBy(=> t.First)
    .
OrderBy(grp => grp.Key)
    .
Select(grp => new { Key grp.KeyItems grp.OrderBy(=> t.Second) }); 

Den stora charmen med detta r att jag inte skapar en massa egna tillstnd i programmet med olika variabler. I stllet sger jag vad jag vill ha och d fr jag det. Det finns frre mjligheter att gra fel och jag ser mycket snabbare vad koden gr.

Nu kanske just detta r ett exempel dr linq passar vldigt bra, men i mnga fall s inser man att man kan optimera och ta bort minst en loop om man skriver koden utan linq.

Men vi kan testa. Jag skrev om ditt program s att det fungerar:

Kod:
List<Tuple<string, string>> tuples = new List<Tuple<string, string>>();
tuples.Add(Tuple.Create("1", "pelefant"));
tuples.Add(Tuple.Create("1", "apa"));
tuples.Add(Tuple.Create("2", "jagular"));
tuples.Add(Tuple.Create("2", "platypus"));
tuples.Add(Tuple.Create("3", "unicorn"));

var result = tuples.GroupBy(x => x.Item1)
    .OrderBy(grp => grp.Key)
    .Select(grp => new { Key = grp.Key, Items = grp.OrderBy(t => t.Item2) });

foreach(var r in result)
{
    foreach (var i in r.Items)
    {
        Console.WriteLine($"{i}");
    }
}

Och hr r samma kod i imperativt format villket blev 26 rader i stllet fr 19 rader.
Kod:
List<Tuple<string, string>> tuples = new List<Tuple<string, string>>();
tuples.Add(Tuple.Create("1", "pelefant"));
tuples.Add(Tuple.Create("1", "apa"));
tuples.Add(Tuple.Create("2", "jagular"));
tuples.Add(Tuple.Create("2", "platypus"));
tuples.Add(Tuple.Create("3", "unicorn"));

Dictionary<string, List<Tuple<string, string>>> groupedTuples = new Dictionary<string, List<Tuple<string, string>>>();

foreach (var tuple in tuples)
{
    if (!groupedTuples.ContainsKey(tuple.Item1))
    {
        groupedTuples[tuple.Item1] = new List<Tuple<string, string>>();
    }
    groupedTuples[tuple.Item1].Add(tuple);
}

foreach (var key in groupedTuples.Keys.OrderBy(k => k))
{
    var sortedTuples = groupedTuples[key].OrderBy(t => t.Item2);
    foreach (var tuple in sortedTuples)
    {
        Console.WriteLine($"{tuple}");
    }
}

Nu tycker jag egentligen inte att linq r det vrsta som C# har att erbjuda.
De kunde ha kallat select fr map i stllet och haft reduce, dvs samma som javascript.
Men s bra skulle det ju inte vara.

Det jag str mig p mest r folk som sitter och hittar p egena funktionella syntaxer
t.ex. genom att skapa en massa olika statiska metoder. Jo det r ju fint, men jag kan ju inte ditt
funtionella sprk du har hittat p. Linq r ju i alla fall en del av sprket och ngot man kan frvnta
sig att folk som stter sig in i ett nytt projekt kan grunderna i.
__________________
Senast redigerad av bithax 2023-01-07 kl. 11:32.
Citera
2023-01-07, 11:48
  #15
Medlem
Citat:
Ursprungligen postat av bithax

Det jag str mig p mest r folk som sitter och hittar p egena funktionella syntaxer
t.ex. genom att skapa en massa olika statiska metoder. Jo det r ju fint, men jag kan ju inte ditt
funtionella sprk du har hittat p. Linq r ju i alla fall en del av sprket och ngot man kan frvnta
sig att folk som stter sig in i ett nytt projekt kan grunderna i.

Det kallas fr domain specific language, domnspecifiktsprk. Och r ett mycket bra stt att ka lsbarheten i ett komplext system. Hr r ett exempel frn ett av mina system dr jag r systemarkitekt i.

Kod:
        private MatchOutcomeWithReason GetJobOutcome(MatchJob job)
        {
            if (job.LooseMatch) return MatchOutcome.Refund.Because(RefundReason.OcrMissing);
            if (job.Payments.Any() && job.Invoice.InvoiceState == InvoiceState.Paid) return MatchOutcome.Refund.Because(RefundReason.AlreadyPaid);
            if (!job.CanPay) return MatchOutcome.Refund.Because(RefundReason.WrongOrder);
            if (job.Invoice.InvoiceState == InvoiceState.Paid) return MatchOutcome.Noop;
            if (job.Diff != 0) return MatchOutcome.Deviation;

            return MatchOutcome.Paid;
        }
__________________
Senast redigerad av CyberVillain 2023-01-07 kl. 11:50.
Citera
2023-01-07, 12:53
  #16
Medlem
bithaxs avatar
Citat:
Ursprungligen postat av CyberVillain
Det kallas fr domain specific language, domnspecifiktsprk. Och r ett mycket bra stt att ka lsbarheten i ett komplext system. Hr r ett exempel frn ett av mina system dr jag r systemarkitekt i.

Kod:
        private MatchOutcomeWithReason GetJobOutcome(MatchJob job)
        {
            if (job.LooseMatch) return MatchOutcome.Refund.Because(RefundReason.OcrMissing);
            if (job.Payments.Any() && job.Invoice.InvoiceState == InvoiceState.Paid) return MatchOutcome.Refund.Because(RefundReason.AlreadyPaid);
            if (!job.CanPay) return MatchOutcome.Refund.Because(RefundReason.WrongOrder);
            if (job.Invoice.InvoiceState == InvoiceState.Paid) return MatchOutcome.Noop;
            if (job.Diff != 0) return MatchOutcome.Deviation;

            return MatchOutcome.Paid;
        }

Jo men bygg det dr och s g och sluta och skit i att dokumentera ntt. Nsta person som kommer in efter dig brjar om frn brjan och skriver ett nytt system frn grunden med en ny DSL som han tycker r mycket bttre. S hller det p sdr.

Vi har ocks haft en arkitekt som suttit och byggt dsl i sin kontomodell och ja, det r ju synd om dem som ska underhlla det dr. Jag kommer inte gra det. Sa upp mig nr han sa upp sig.

Problemet r att man inte vet vad som pgr under. Och steppar du in i det med en debugger, ja d r det mesta one-liners som kallar p andra one-liners. Tnkt d att man ska ndra ntt dr inne. Eller om man behver lgga till funktionalitet.

Hitintills har jag inte sett ngon hemmagjord DSL som fljer SOLID principerna. Det gr skert att bygga sdana men vore enklare med en vanlig domnmodell med objekt.
__________________
Senast redigerad av bithax 2023-01-07 kl. 13:19.
Citera
2023-01-07, 14:05
  #17
Medlem
Citat:
Ursprungligen postat av bithax
Jo men bygg det dr och s g och sluta och skit i att dokumentera ntt. Nsta person som kommer in efter dig brjar om frn brjan och skriver ett nytt system frn grunden med en ny DSL som han tycker r mycket bttre. S hller det p sdr.

Vi har ocks haft en arkitekt som suttit och byggt dsl i sin kontomodell och ja, det r ju synd om dem som ska underhlla det dr. Jag kommer inte gra det. Sa upp mig nr han sa upp sig.

Problemet r att man inte vet vad som pgr under. Och steppar du in i det med en debugger, ja d r det mesta one-liners som kallar p andra one-liners. Tnkt d att man ska ndra ntt dr inne. Eller om man behver lgga till funktionalitet.

Hitintills har jag inte sett ngon hemmagjord DSL som fljer SOLID principerna. Det gr skert att bygga sdana men vore enklare med en vanlig domnmodell med objekt.

Det r klart att just detta exempel fljer inte open/closed principen i SOLID d man mste ndra p metoden fr att infra fler matching outcomes. Sjlv tycker jag man ibland kan bryta mot open closed som i detta fallet. Man mste vara lite pragmatisk.

andra sidan tycker jag man ska implementera strategier s ofta man kan just fr att flja open / closed principen.

Har egentligen inget med DSL att gra. DSL gr koden mer lttlst och mer som att lsa en mening i klartext.
Citera
2023-01-07, 14:34
  #18
Medlem
bithaxs avatar
Citat:
Ursprungligen postat av CyberVillain
Det r klart att just detta exempel fljer inte open/closed principen i SOLID d man mste ndra p metoden fr att infra fler matching outcomes. Sjlv tycker jag man ibland kan bryta mot open closed som i detta fallet. Man mste vara lite pragmatisk.

andra sidan tycker jag man ska implementera strategier s ofta man kan just fr att flja open / closed principen.

Har egentligen inget med DSL att gra. DSL gr koden mer lttlst och mer som att lsa en mening i klartext.

Ja ta t.ex masstransit konfigurationen dr han tvingar en att konfigurera en AWS region innan du kan gra ntt annat. Det hade varit s mycket bttre att bara kunna skicka in en AWS konfiguration direkt, men nej, han ska ju skapa den t dig. nnu bttre hade varit att kunna skicka in en factory som skapar AWS klienten.

AWS klienten kan konfigureras med environmentvariabler, men det gr inte att anvnda nr DSLen skapar en config t dig och ramverket skapar en AWS klient t dig.

Detta r bara ett exempel, men jag har sett snthr minst 10 gnger att man hindrar injection fr man har nn DSL som ska gra det bttre.

Anvnd dependency injection istllet, eller ge tminstone ett alternativ att anvnda injection. Om man inte gr det s kommer inte dehr apierna verleva tidens tand. I alla fall inte utan ngon som hela tiden sitter och uppdaterar dem.
__________________
Senast redigerad av bithax 2023-01-07 kl. 14:40.
Citera
2023-01-07, 15:26
  #19
Medlem
Citat:
Ursprungligen postat av bithax
Ja ta t.ex masstransit konfigurationen dr han tvingar en att konfigurera en AWS region innan du kan gra ntt annat. Det hade varit s mycket bttre att bara kunna skicka in en AWS konfiguration direkt, men nej, han ska ju skapa den t dig. nnu bttre hade varit att kunna skicka in en factory som skapar AWS klienten.

AWS klienten kan konfigureras med environmentvariabler, men det gr inte att anvnda nr DSLen skapar en config t dig och ramverket skapar en AWS klient t dig.

Detta r bara ett exempel, men jag har sett snthr minst 10 gnger att man hindrar injection fr man har nn DSL som ska gra det bttre.

Anvnd dependency injection istllet, eller ge tminstone ett alternativ att anvnda injection. Om man inte gr det s kommer inte dehr apierna verleva tidens tand. I alla fall inte utan ngon som hela tiden sitter och uppdaterar dem.

Just masstransits ide r ju att man ska kra med de conventions som r uppsatta av masstransit nr det gller ker. Kr det p jobbet fr att management inte ville betala fr nServicebus som jag vill anvnda. Har inget att invnda mot just den biten. Men masstransit r rtt dligt implementerat ver lag. Saker silent fallerar utan errors osv.

Edit: masstransit anvnder IOC under utan dock och inget hindrar dig dig byta ut dessa
__________________
Senast redigerad av CyberVillain 2023-01-07 kl. 15:28.
Citera
2023-01-07, 16:24
  #20
Medlem
Citat:
Ursprungligen postat av bithax
Nu kanske just detta r ett exempel dr linq passar vldigt bra, men i mnga fall s inser man att man kan optimera och ta bort minst en loop om man skriver koden utan linq.

Men vi kan testa. Jag skrev om ditt program s att det fungerar:

Kod:
List<Tuple<string, string>> tuples = new List<Tuple<string, string>>();
tuples.Add(Tuple.Create("1", "pelefant"));
tuples.Add(Tuple.Create("1", "apa"));
tuples.Add(Tuple.Create("2", "jagular"));
tuples.Add(Tuple.Create("2", "platypus"));
tuples.Add(Tuple.Create("3", "unicorn"));

var result = tuples.GroupBy(x => x.Item1)
    .OrderBy(grp => grp.Key)
    .Select(grp => new { Key = grp.Key, Items = grp.OrderBy(t => t.Item2) });

foreach(var r in result)
{
    foreach (var i in r.Items)
    {
        Console.WriteLine($"{i}");
    }
}

Och hr r samma kod i imperativt format villket blev 26 rader i stllet fr 19 rader.
Kod:
List<Tuple<string, string>> tuples = new List<Tuple<string, string>>();
tuples.Add(Tuple.Create("1", "pelefant"));
tuples.Add(Tuple.Create("1", "apa"));
tuples.Add(Tuple.Create("2", "jagular"));
tuples.Add(Tuple.Create("2", "platypus"));
tuples.Add(Tuple.Create("3", "unicorn"));

Dictionary<string, List<Tuple<string, string>>> groupedTuples = new Dictionary<string, List<Tuple<string, string>>>();

foreach (var tuple in tuples)
{
    if (!groupedTuples.ContainsKey(tuple.Item1))
    {
        groupedTuples[tuple.Item1] = new List<Tuple<string, string>>();
    }
    groupedTuples[tuple.Item1].Add(tuple);
}

foreach (var key in groupedTuples.Keys.OrderBy(k => k))
{
    var sortedTuples = groupedTuples[key].OrderBy(t => t.Item2);
    foreach (var tuple in sortedTuples)
    {
        Console.WriteLine($"{tuple}");
    }
}

Nu tycker jag egentligen inte att linq r det vrsta som C# har att erbjuda.
De kunde ha kallat select fr map i stllet och haft reduce, dvs samma som javascript.
Men s bra skulle det ju inte vara.

Det jag str mig p mest r folk som sitter och hittar p egena funktionella syntaxer
t.ex. genom att skapa en massa olika statiska metoder. Jo det r ju fint, men jag kan ju inte ditt
funtionella sprk du har hittat p. Linq r ju i alla fall en del av sprket och ngot man kan frvnta
sig att folk som stter sig in i ett nytt projekt kan grunderna i.
Fast nu fuskade du lite och anvnda Linq-metoden OrderBy. Dvs, du anvnde faktiskt funktionell programmering i ditt exempel dr du frskte visa att imperativ stil r bttre. Map, Reduce r ocks funktionell programmering. S egentligen gillar du det, du r bara inte verens med hur det r designat eller namngivet i .net?

Om du ven hade skrivit en egen implementation fr sortering, eller sortering p flera flt d hade du tydligare sett frdelen med funktionell stil. Ju mer komplext det blir, desto bttre blir funktionell programmering. Folk som jobbar mycket med komplicerade berkningar anvnder ofta funktionella sprk.

Att skapa egna lager med funktionella anrop r ofta en bra id tycker jag.
Kodens syfte blir mycket enklare att frst om du fr in mer affrsregler och begrepp. T.ex
list.map(...) //innehller logik som rknar om priser till EUR
Vs:
shoppingcart.mapToCurrency(..., currencyInfo) //mycket bttre kod IMHO

Dremot godknner jag inte att gra sdant som globala extensions, d fr man God objects som vet allt, det r inte bra. Typ string.ParseCustomer()
Citera
2023-01-07, 16:35
  #21
Medlem
Citat:
Ursprungligen postat av CyberVillain
Det kallas fr domain specific language, domnspecifiktsprk. Och r ett mycket bra stt att ka lsbarheten i ett komplext system. Hr r ett exempel frn ett av mina system dr jag r systemarkitekt i.

Kod:
        private MatchOutcomeWithReason GetJobOutcome(MatchJob job)
        {
            if (job.LooseMatch) return MatchOutcome.Refund.Because(RefundReason.OcrMissing);
            if (job.Payments.Any() && job.Invoice.InvoiceState == InvoiceState.Paid) return MatchOutcome.Refund.Because(RefundReason.AlreadyPaid);
            if (!job.CanPay) return MatchOutcome.Refund.Because(RefundReason.WrongOrder);
            if (job.Invoice.InvoiceState == InvoiceState.Paid) return MatchOutcome.Noop;
            if (job.Diff != 0) return MatchOutcome.Deviation;

            return MatchOutcome.Paid;
        }
N, detta r ett frsk att gra DDD med method chaining, det r inte en DSL.
SQL r en DSL, det r ett begrnsat, inte generellt sprk fr att hantera data i databaser.
Citera
2023-01-07, 21:38
  #22
Medlem
Citat:
Ursprungligen postat av Binary
N, detta r ett frsk att gra DDD med method chaining, det r inte en DSL.
SQL r en DSL, det r ett begrnsat, inte generellt sprk fr att hantera data i databaser.

Det r en form av DSL absolut. Vldigt lokalt och begrnsat sjlvfallet. Men DSL. Fluent APIer som dessa r bra exempel p funktionell programmering nr den anvnds korrekt.
Citera
2023-01-07, 22:12
  #23
Medlem
Citat:
Ursprungligen postat av CyberVillain
Det r en form av DSL absolut. Vldigt lokalt och begrnsat sjlvfallet. Men DSL. Fluent APIer som dessa r bra exempel p funktionell programmering nr den anvnds korrekt.
Fortfarande nej. DSL = Domain Specific Language.
Det r om du uppfinner ett eget sprk fr din domn. Men om du i C# skriver t.ex.
MatchOutcome.Refund.Because(RefundReason.WrongOrde r)
D r detta sprket C# fortfarande, och inte ett eget konstruerat sprk.
Du har hr properties och metoder som r trevligt namgivna, troligt inspirerat av DDD, Domain Driven Design, men det r inte drfr ett eget sprk, en egen DSL.
Citera
2023-01-08, 00:25
  #24
Medlem
Citat:
Ursprungligen postat av Binary
Fortfarande nej. DSL = Domain Specific Language.
Det r om du uppfinner ett eget sprk fr din domn. Men om du i C# skriver t.ex.
MatchOutcome.Refund.Because(RefundReason.WrongOrde r)
D r detta sprket C# fortfarande, och inte ett eget konstruerat sprk.
Du har hr properties och metoder som r trevligt namgivna, troligt inspirerat av DDD, Domain Driven Design, men det r inte drfr ett eget sprk, en egen DSL.

Nej du har fel. Du kan bygga DSL i ett annat sprk. Det kallas fr intern DSL.


Citat:
External and Embedded Domain Specific Languages

DSLs implemented via an independent interpreter or compiler are known as External Domain Specific Languages. Well known examples include LaTeX or AWK. A separate category known as Embedded (or Internal) Domain Specific Languages are typically implemented within a host language as a library and tend to be limited to the syntax of the host language, though this depends on host language capabilities.


__________________
Senast redigerad av CyberVillain 2023-01-08 kl. 00:28.
Citera

Skapa ett konto eller logga in för att kommentera

Du måste vara medlem för att kunna kommentera

Skapa ett konto

Det är enkelt att registrera ett nytt konto

Bli medlem

Logga in

Har du redan ett konto? Logga in här

Logga in