C++ och dess framtid att programmera minnessäkert - Hur går utvecklingen?

Permalänk
Skrivet av klk:

Pekare (kontroll av minne) är viktigt för att skriva smidig återanvändbar kod.

Varför kan man inte skriva smidig återanvändbar kod om man använder smart pointers? Om man använder smart pointers för att man vill slippa alla problem med manuell minneshantering, slutar kod att vara återanvändbar då? Nu får du allt förklara varför! Eller blir den bara osmidig att återanvända? Det förstår jag inte heller.

Om du plockar ut pekaren ur din smart pointer, har du inte våldfört dig på hela idén då? Man missar hela finessen med smart pointers. Jag ser det som osannolikt att ditt exempel skulle vara ett vanligt mönster för hur smart pointers används.

Permalänk
Medlem
Skrivet av Ingetledigtnamn:

Varför kan man inte skriva smidig återanvändbar kod om man använder smart pointers? Om man använder smart pointers för att man vill slippa alla problem med manuell minneshantering, slutar kod att vara återanvändbar då?

Vad tror du koden gör och hur skulle du löst det?

Permalänk
Datavetare
Skrivet av klk:

Separera systemdomän från användardomän är viktigt. (använder de namn som Casey Maratori beskrev så bra).

Det är viktigt, men detta är nog något som p.g.a. av ökad mognadsgrad ett allt mindre problem.

Moderna/popular språk som t.ex. Python har rätt mycket "batterier inkluderade" till den grad att systemdomänen i praktiken är "klar". Finns ingen anledning att fokusera på något annat än användardomänen i de flesta projekt.

Detta är bra och visar på ökad mognad i denna sektor.

Skrivet av klk:

Det finns en bok som heter "clean code" skriven av Robert C Martin. Sämsta bok som skrivits och förstört massor eftersom den beskriver att bra kod är att skriva kod för användardomän. Att kod är som att läsa en bok.
Att den blev så populär tror jag beror på att många kunde äntligen göra något programmeringsmässigt. Så de trodde "nu är jag programmerare". Försöker då en "riktig" programmerare förklara att man inte gör som de lärt sig så förstår de inte alls.

Clean Code har fått en hel del kritik, men nog mer för att den framställer saker som egentligen är "best practices" mer som lagar. Den har också fått kritik för att fokusera allt för mycket på detaljer och lite får det att låta som "fixar man detaljerna är man hemma". Även perfekta delar kan bli en dålig helhet om ingen tänkt på hur man ska sätta ihop det hela...

Personligen gillar jag inte trenden, som Clean Code trycker hårt på, att inte använda sig av kommentarer. Kommentarer kan vara otroligt värdefulla när de berättar varför något är gjort på ett visst sätt, hur något är gjort står ju i koden!

Men den trycker också på en lång rad saker som känns som självklara saker. Som att varje funktion ska ha exakt en uppgift, ge saker namn som förklara avsikten.

En av mina käpphästar, som jag nog pushar lika hårt som du pushar HN, är att så långt som möjligt skriva saker så konsekvent som möjligt. Vilken kodstandard och hur många white-space man råkar ha vid indentering kvittar, men alla ska använda samma så långt som realistiskt möjligt!!

Go nailar det sista på ett för mig fullt acceptabelt sätt: standard-tooling inkluderar en language-server (som definitivt kan hantera väldigt stora projekt) där de flesta av dessa val redan är gjorda. Det håller inte bara en fin nivå inom projekten, det gör att även andra projekt har en mycket snarlik outline.

Har jobbat på ett ställe som hade väldigt bra ordning på sin kodbas, men där det ändå blev rätt drygt p.g.a. att den kodstandard man körde inom företaget var så ovanligt att all 3:e-partskod alltid såg "off" out. När IDE/textredigerar blev allt bättre att formatera automatiskt blev det ännu värre då typ ingen hade stöd för den variant som användes internt...

Det är också ett stor "därför suger HN", "ingen annan" använder det idag!

Skrivet av klk:

Hur jag vet att exempelvis rust eller andra "förlåtande" språk inte kommer användas till större svårare projekt
Vet man om ovanstående så är det ganska lätt och se hur långt ett projekt kommer. Det beror en del på vilken typ av domän koden hanterar. Är det domäner kända för utvecklare kommer de längre, är det ovanliga så kommer de inte speciellt långt.
Att utveckla en editor, spelmotor eller annat kan komma ganska långt även om det är tekniskt men det beror på att användardomänen också är känd för utvecklare.
Är det annat som vetenskapliga domäner eller liknande, då bli det genast mer problem.

Eftersom jag granskat en del rust projekt så, i princip samtliga rust projekt jag kollat uppträder för mycket "skitkod" och det är enligt mig orsaken till att de inte kommer så långt. Ett allvarligt designfel de har i rust är att språket saknar överlagring och det gör att att de har mycket svårare att skriva kod i mönster. Nästan alla "kända" rust projekt har en eldsjäl och de kan nå närmare 100 000 rader och då är det vad jag sett nästan alltid domäner välkända för utvecklare. Har inte sett rustprojekt med något mer udda domän som är större men tar gärna emot tips på sådant. Att det saknas projekt i domäner okända för utvecklare tror inte jag är en slump.

Ovan är direkt svammel. Rust används redan inom områden där en typisk programmerare knappast har någon djupare domänkunskap. Exempel är industri-tillämpningar, automotive, robotics, B2C och B2B.

Sen behöver du inte kolla längre än till Rust-kompilatorn + standardbibliotek för att hitta något som redan nått sjusiffrigt antal kodrader. Finns rätt många Rust-baserade open-source projekt som är en handfull hundratusentals rader.

Antar att du även räknar in Java, C# och Go i "förlåtande språk". Där finns det massor med väldigt stora projekt idag.

Skrivet av klk:

Vet du någon annan kodstil för att hantera kod
För ändringen är "skriv kod som du själv vill". Vad jag vet är det endast hungarian notation som finns och vars syfte är att hantera svår kod. Det kan vara mycket kod, avancerad kod, svår domän eller liknande. Hjärnan behöver inte arbeta lika mycket och kan därför lägga energi på annat.

Se ovan, ändringen är absolut INTE "skriv kod som du vill". Tycker personligen det är en kritisk del att så långt som realistiskt möjligt hålla en konsekvent stil i kodbasen.

Däremot ser jag ingen poäng med HN. Det har en poäng i svagt typade språk som t.ex. C och ännu mer i svagt typade språk som också är dynamiskt typade som många script-språk som t.ex. TCL, Perl, etc. Det har ingen poäng i statiskt och starkt typade språk som C++, Rust, Go, C#, m.fl. (det är extra meningslöst i språk med generics vilket i.o.f.s är alla nämnda).

Som @Ingetledigtnamn nämner ovan var du väldigt emot smarta pekare och likande. Vad tycker du då om det som sägs i videon du länkar ovan där jättar som Microsoft och Apple säger att de redan hittat tusentals buggar när de slog på "standard library hardening" som bl.a. lägger in bounds-check för operator[].

Har tror jag man fick en smärtsam "vi har inte längre CPUer designade på 70/80-talet där man kan cykelräkna", CPU-design har på flera sätt rejält sprungit ifrån det som historiskt gjorde C och C++ unikt men som idag ibland är rena sänken (att inte ha GC kan rätt bli ett sänke om man ger sig in i multi-thread programmering).

Att slå på de extra check:arna i "standard library hardening" verkar ju på moderna CPU-designer fått en prestanda-dipp på <1%. Ingen bryr sig om <1% givet hur mycket mer minnessäkert det ändring gör språken!!!

Samtidigt kan man också fatta varför det var en dålig idé innan vi fick de breda out-of-order CPUerna vi har idag. Det är rätt mycket instruktioner som läggs till om man gör något som detta

int foo(const vector<int> &v, int i) { return v[i]; }

men det är i praktiken helt irrelevant när CPUer kan köra 8-12 instruktioner per cykel, men de är väldigt ofta begränsade av RAM-access och liknande så det mer är 1-4 instruktioner per cykel som faktiskt körs. Att checka ovan orsakar inga sådan problem då den data som behövs redan ligger i register/L1$.

Skrivet av klk:

Det nya är deklarativ programmering, istället för att skriva kod som programmerare gör så skriv en bok. Inget som ersätter utan det är något helt annat eftersom imperativ kod jämfört med deklarativ kod ofta är varandras motsatser.

???

Det här är deklarativt

SELECT name FROM employees WHERE salary > 50000;

det här är imperativt

result = [] for emp in employees: if emp.salary > 50000: result.append(emp.name)

I min bok ser Python mer ut som #2...

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk
Medlem

Är vi tillbaka i deklarativ vs imperativ träsket? Hur hamnade vi här igen?

Permalänk
Datavetare
Skrivet av pine-orange:

Är vi tillbaka i deklarativ vs imperativ träsket? Hur hamnade vi här igen?

Visst är det Python?

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk
Medlem
Skrivet av pine-orange:

Är vi tillbaka i deklarativ vs imperativ träsket? Hur hamnade vi här igen?

Rekursion. Eller möjligen en vanlig loop. Knappast goto.

Permalänk
Medlem
Skrivet av Yoshman:

Se ovan, ändringen är absolut INTE "skriv kod som du vill". Tycker personligen det är en kritisk del att så långt som realistiskt möjligt hålla en konsekvent stil i kodbasen.

Och hur är de reglerna? Kan du förklara

Skrivet av Yoshman:

Däremot ser jag ingen poäng med HN. Det har en poäng i svagt typade språk som t.ex. C och ännu mer i svagt typade språk som också är dynamiskt typade som många script-språk som t.ex.

Har inte med typen att göra, du slipper läsa kod med HN och kan processa stora mängder kod. Skulle inte förvåna mig om en tränad HN "läsare" kan läsa (läs: skanna) kod 10 gånger snabbare än programmera som måste läsa koden. Jobbigt att behöva läsa kod

Skrivet av Yoshman:

Som @Ingetledigtnamn nämner ovan var du väldigt emot smarta pekare och likande. Vad tycker du då om det som sägs i videon du länkar ovan där jättar som Microsoft och Apple säger att de redan hittat tusentals buggar när de slog på "standard library hardening" som bl.a. lägger in bounds-check för operator[].

Att sätta ointresserade programmerare i C++ är inte smart. C++ är absolut inte för alla. C++ är för A-laget
Och i rätt händer slår det allt

Skrivet av Yoshman:

Antar att du även räknar in Java, C# och Go i "förlåtande språk". Där finns det massor med väldigt stora projekt idag.

Räknar inte CRUD applikationer som stora system och de kommer troligen att nära nog helt ersättas av AI genererad kod.
Tar man bort CRUD systemen kanske det finns 10% kvar och visst, det går men det är också mycket jobb

Skrivet av Yoshman:

Som @Ingetledigtnamn nämner ovan var du väldigt emot smarta pekare och likande.

Stämmer men ibland är det ok. Speciellt i skitkod. Och har också nämnt att det går att skriva säkrare kod trots att man sköter minnet. Framförallt på grund av att det går att göra så mycket smartare lösningar, smarta lösningar = återanvändbara lösningar = vältestad kod

Kan fråga dig med för jag tror du är med på vad som bli möjligt med följande kod
Den här table klassen är orsaken till varför mitt lilla hobbyprojekt kommer dra ifrån de andra sökverktygen såvida de inte gör något liknande.

auto ptableLineList = std::make_unique<gd::table::dto::table>(gd::table::dto::table(uTableStyle, { {"uint64", 0, "key"}, {"uint64", 0, "file-key"}, {"rstring", 0, "filename"}, {"rstring", 0, "line"}, {"uint64", 0, "row"}, {"uint64", 0, "column"}, {"string", 32, "pattern"}, {"string", 10, "segment"} }, gd::table::tag_prepare{}) ... detail::columns* pcolumnsThread = new detail::columns{}; ptableLineList->to_columns( *pcolumnsThread ); ... std::unique_ptr<table> ptableLineListLocal = std::make_unique<table>(pcolumnsThread, 10, ptableLineList->get_flags(), 10); // Create local table with 10 rows pre-allocated ... std::lock_guard<std::mutex> lockLineList(mutexLineList); ptableLineList->append(ptableLineListLocal.get()); // Append the results from the local table to the main table

C++ skriver ofta sina egna smarta objekt och där behövs pekare för att göra jobbet smidigare.
Hur skulle detta lösas i andra språk (om man inte skriver egna likartade objekt)

Permalänk
Medlem
Skrivet av pine-orange:

Är vi tillbaka i deklarativ vs imperativ träsket? Hur hamnade vi här igen?

Eftersom Python inte är riktig programmering enl. @klk, hur man nu hoppar från åsikter om Python till ett missförstånd om paradigm.

Skrivet av Yoshman:

Visst är det Python?

Japp

Skrivet av Erik_T:

Rekursion. Eller möjligen en vanlig loop. Knappast goto.

Tror snarare att någon klantat till något med sin manuella minneshantering.

Permalänk
Medlem
Skrivet av klk:

Har inte med typen att göra, du slipper läsa kod med HN och kan processa stora mängder kod. Skulle inte förvåna mig om en tränad HN "läsare" kan läsa (läs: skanna) kod 10 gånger snabbare än programmera som måste läsa koden. Jobbigt att behöva läsa kod

Nedan är ett exempel från min editor

struct Baz {} let foo: i32 = 123; let bar: bool = true; let baz: Baz = Baz{};

": Typ" är inte en sak som finns i koden utan är renderat av min editor så jag kan snabbt se typen utan HN. Om du menar att snabbt hoppa till vart saker används så kan jag kolla referenser till exempelvis en struct och hoppa dit. Jag tror aldrig att jag har behövt att list alla uint32 för att hitta vart jag ska.

Skrivet av klk:

Att sätta ointresserade programmerare i C++ är inte smart. C++ är absolut inte för alla. C++ är för A-laget

Du menar dom som sitter på en bänk med en elefantöl och skriker åt duvorna på torget?

Riktiga män kodar C och lämnar stödhjulen(C++) åt A-laget så att dom kan cykla hem när ölen är slut.

Skrivet av klk:

Räknar inte CRUD applikationer som stora system och de kommer troligen att nära nog helt ersättas av AI genererad kod.

Nu är vi tillbaka på CRUD...

Permalänk
Medlem
Skrivet av orp:

Nedan är ett exempel från min editor

struct Baz {} let foo: i32 = 123; let bar: bool = true; let baz: Baz = Baz{};

": Typ" är inte en sak som finns i koden utan är renderat av min editor så jag kan snabbt se typen utan HN. Om du menar att snabbt hoppa till vart saker används så kan jag kolla referenser till exempelvis en struct och hoppa dit. Jag tror aldrig att jag har behövt att list alla uint32 för att hitta vart jag ska.

Om jag tar mitt tidigare exempel på en metod med 32 lokala variabler och du skall förstå vad som pågår i den, hur gör du?
Och du vet säkert att som utvecklare måste man veta exakt vad som pågår

Permalänk
Medlem
Skrivet av klk:

Om jag tar mitt tidigare exempel på en metod med 32 lokala variabler och du skall förstå vad som pågår i den, hur gör du?
Och du vet säkert att som utvecklare måste man veta exakt vad som pågår

Variabler i sig åstadkommer inget så man måste ju läsa logiken för att förstå och min LSP renderar variabel typer för:
- parametrar till funktionsanrop
- variabel typerna i for/while loop (när man använder iterator i Rust)
- varje ospecad deklarering;
osv

Du kan ju ha hur många lokala variabler du vill det handlar ju om vad du gör med dessa. Deras namn som beskriver deras funktion i sammanhanget är viktigare än deras typ (som ändå visas av min editor).

Permalänk
Skrivet av klk:

Vad tror du koden gör och hur skulle du löst det?

Gissningsvis läggs innehållet i ptableLineListLocal till ptableLineList. Det är lite svårt att avgöra då vi inte fick hela implementationen, så koden skulle precis lika gärna kunna lägga in den råa pekaren i en tabell.

Men vad har det med min fråga att göra? Min ursprungliga fråga handlade om smart pointers mot råa pekare så när du skriver "Pekare (kontroll av minne) är viktigt för att skriva smidig återanvändbar kod." implicerar väl det att råa pekare är bättre än smart pointers när man skall skriva smart återanvändbar kod? Så jag frågar igen: På vilket sätt blir koden mindre återanvändbar om den använder smarta pekare?

PS. Skall inte typen vara sist i variabelnamnet? ptableLineListLocal har typen mitt i. DS.

Permalänk
Medlem
Skrivet av Ingetledigtnamn:

Gissningsvis läggs innehållet i ptableLineListLocal till ptableLineList. Det är lite svårt att avgöra då vi inte fick hela implementationen, så koden skulle precis lika gärna kunna lägga in den råa pekaren i en tabell.

Men vad har det med min fråga att göra? Min ursprungliga fråga handlade om smart pointers mot råa pekare så när du skriver "Pekare (kontroll av minne) är viktigt för att skriva smidig återanvändbar kod." implicerar väl det att råa pekare är bättre än smart pointers när man skall skriva smart återanvändbar kod? Så jag frågar igen: På vilket sätt blir koden mindre återanvändbar om den använder smarta pekare?

PS. Skall inte typen vara sist i variabelnamnet? ptableLineListLocal har typen mitt i. DS.

Första raden i exemplet är den viktiga för där visas att det är en tabell där kolumnerna går att konfigurera upp i runtime. Det gör tabellen flexibel (inte hårdkodad). Baserat på den informationen går det att förstå att möjligheterna är mycket större och koden är återanvändbar om det inte är en nötskalle som skrivit resten.

Har kollat ripgrep och tänkte kolla någon till men de har inget generellt som lagrar resultatet från deras sökningar, allt hänger samman vilket visserligen gör det den skall göra. Söka i kod men den kommer inte klara av att göra något mer utan att i skriva om en hel del av koden.
ripgrep är liksom ett flöde från början till slut istället för att kunna mellanlagra och då i ett format som går att bearbeta. Applikationen är hårdkodad för en sak

Permalänk
Datavetare
Skrivet av klk:

Och hur är de reglerna? Kan du förklara

Här är ett exempel: https://google.github.io/styleguide/go/guide

Nästan allt som har specifikt med hur kod ska formateras kan garanteras via tooling. Regeln att publika funktioner/variabler måste ha stor begynnelsebokstav är garanterad då man utelämnade "public/private", att ha stor begynnelsebokstav kommer med implicit "public".

Skrivet av klk:

Har inte med typen att göra, du slipper läsa kod med HN och kan processa stora mängder kod. Skulle inte förvåna mig om en tränad HN "läsare" kan läsa (läs: skanna) kod 10 gånger snabbare än programmera som måste läsa koden. Jobbigt att behöva läsa kod

Det viktigaste egenskaperna på kod för att den ska vara lätt att läsa är saker som

  • meningsfulla namn

  • en uppdelning i tillräckligt enkla bitar så varje bit är uppenbart korrekt, det i kontrast med att göra det så komplext att man inte hittar några uppenbara fel

  • varje modul håller sig till "sin" domän

HN hjälper inte med något av ovan, tvärtom minskar det signal-to-noise genom att blanda in massa redundant information i namnen. För namn måste också vara hyfsat korta, har man fler än 3-4 versaler i sitt camel-case namn har man nog ett problem...

Skrivet av klk:

Att sätta ointresserade programmerare i C++ är inte smart. C++ är absolut inte för alla. C++ är för A-laget
Och i rätt händer slår det allt

Knappast. C++ programmerare har varit B-laget från start, de som inte fixade "cut:en" till eliten där C och assembler hackarna svassar runt!

Mer seriöst så börjar faktiskt de språk som togs fram på 70, 80 och delvis även de från 90-talet börja visa en del ålderskrämpor nu när till och med rätt enkla datorer har rätt många CPU-kärnor. C och C++ är allt annat än optimala för hantera den typen av kod, man måste ha en enorm detaljkunskap för att nå prestanda/skalbarhet som personer med relativt basala kunskaper kan nå med Rust Rayon/Crossbeam (compute bound) eller Go (I/O-bound).

C++ och än mer C kommer finnas kvar under överskådlig tid. Men det är mest för "laggards" och av nödvändighet för det inte är realistiskt att skriva om allt.

Skrivet av klk:

Räknar inte CRUD applikationer som stora system och de kommer troligen att nära nog helt ersättas av AI genererad kod.
Tar man bort CRUD systemen kanske det finns 10% kvar och visst, det går men det är också mycket jobb
Stämmer men ibland är det ok. Speciellt i skitkod. Och har också nämnt att det går att skriva säkrare kod trots att man sköter minnet. Framförallt på grund av att det går att göra så mycket smartare lösningar, smarta lösningar = återanvändbara lösningar = vältestad kod

Det skrivs långt mer än CRUD applikationer även i Java. C# är ju väldigt populärt för att skriva "vanliga" applikationer, inklusive spel. I Go:s fall har det egenskaper som gjort det för "molnet" vad C är för OS-kärnor och systembibliotek, d.v.s. standardvalet. Så Go är knappast något som används primärt för CRUD.

Skrivet av klk:

C++ skriver ofta sina egna smarta objekt och där behövs pekare för att göra jobbet smidigare.
Hur skulle detta lösas i andra språk (om man inte skriver egna likartade objekt)

Och det kan man gör med precis _alla_ moderna språk, så vad är poängen?

Skrivet av klk:

Om jag tar mitt tidigare exempel på en metod med 32 lokala variabler och du skall förstå vad som pågår i den, hur gör du?
Och du vet säkert att som utvecklare måste man veta exakt vad som pågår

Har man 32 lokala variabler borde man tycka att nivån på "code-smell" börjar närma sig odören kring toaletterna på en rockfestival sista dagen...

Skrivet av klk:

Första raden i exemplet är den viktiga för där visas att det är en tabell där kolumnerna går att konfigurera upp i runtime. Det gör tabellen flexibel (inte hårdkodad). Baserat på den informationen går det att förstå att möjligheterna är mycket större och koden är återanvändbar om det inte är en nötskalle som skrivit resten.

Har kollat ripgrep och tänkte kolla någon till men de har inget generellt som lagrar resultatet från deras sökningar, allt hänger samman vilket visserligen gör det den skall göra. Söka i kod men den kommer inte klara av att göra något mer utan att i skriva om en hel del av koden.
ripgrep är liksom ett flöde från början till slut istället för att kunna mellanlagra och då i ett format som går att bearbeta. Applikationen är hårdkodad för en sak

?????????

ripgrep har en vettig separation mellan systemdomän och användardomän, var någon som nämnde att det är en viktig separation...

Du har en rätt amatörmässig hemmasnickrad implementation av work-stealing, ripgrep fokuserar på användardomän och använder crossbeam (systemdomän "work-stealing") för att hantera den biten där folk som är experter på det området skrivit koden.

Hur mycket snabbare än din "smarta tabell" (WTF, vilket standardbibliotek har inte en effektiv tabell som är dynamisk?) och ditt program i att söka igenom t.ex. Linux-koden jämfört med ripgrep?

Rätt nöjd med ripgrep prestanda på MacOS i alla fall, en komplett sökning av hela Linux-koden med ett par regex tar faktiskt bara ca 1,5 sekund på min laptop (och den verkar utnyttja de "stora" kärnorna rätt väl).

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk
Medlem
Skrivet av klk:

Har kollat ripgrep och tänkte kolla någon till men de har inget generellt som lagrar resultatet från deras sökningar, allt hänger samman vilket visserligen gör det den skall göra. Söka i kod men den kommer inte klara av att göra något mer utan att i skriva om en hel del av koden.

Jag använder ripgrep för sökning i min kod (integrerad i editorn), däremot så har jag inte nytta av att ha en lista med statiska regex som den ska leta efter varje gång.

Skrivet av klk:

ripgrep är liksom ett flöde från början till slut istället för att kunna mellanlagra och då i ett format som går att bearbeta. Applikationen är hårdkodad för en sak

ripgrep är ju designad som ett alternativ till grep och måste kunna hantera stdin och har inga krav på cache:ning.

Det är lite konstigt att du hängt upp dig på ripgrep och beklagar dig över att ripgrep inte löser ditt problem när den löser det den är designad för. Du kanske försöker använda fel verktyg för ditt problem?

Permalänk
Skrivet av klk:

Första raden i exemplet är den viktiga för där visas att det är en tabell där kolumnerna går att konfigurera upp i runtime. Det gör tabellen flexibel (inte hårdkodad). Baserat på den informationen går det att förstå att möjligheterna är mycket större och koden är återanvändbar om det inte är en nötskalle som skrivit resten.

Jag försöker inte argumentera emot dina påståenden om att din kod är återanvändbar. Jag frågar varför råa pekare skulle göra koden mer återanvändbar än om man använder smarta pekare. Var det inte det budskapet du ville föra fram med "Pekare (kontroll av minne) är viktigt för att skriva smidig återanvändbar kod."?

Här ångar du på i samma stil och tillskriver råa pekare en godtycklig egenskap, "en tabell där kolumnerna går att konfigurera upp i runtime", och framhåller att det gör att "möjligheterna är mycket större" utan att motivera varför de skulle vara större eller varför det skulle vara omöjligt att implementera samma tabell med hjälp av smart pointers. Denna typ av argumentation rasar som ett korthus om du inte hittar ett fall där man inte kan göra samma sak med smarta pekare. I mina nötskalleögon framstår det som att smarta pekare gör koden mer återanvändbar och säkrare då ägandeskap helt plötsligt blir en ickefråga. Allokerade block deallokeras automatiskt då den sista referensen går ur scope.

Du kan som ett litet experiment köra ditt sökverktyg på libcxx-sourcen och söka på shared_ptr. Koden i standardbiblioteket använder smart pointers under huven! Gör detta att den inte är återanvändbar?

Jag noterar med glädje att du i din exempelkod faktiskt använder (stödhjulet) unique_ptr. Har du sett fördelen med att slippa slösa hjärncykler på var man skall deallokera minnet? Sedan gör du en "optimering" och plockar ut den råa pekaren för att slippa skicka ett objekt till append. Har du mätt på det här? Hur mycket extra skulle det kosta att gå all in på smart pointers och köra en shared_ptr? Att du i samband med detta skall ta ett lås och kopiera en tabell borde göra att extrakostnaden för en shared_ptr är helt försumbar. Speciellt när append blir inline:ad och kompilatorn kan optimera över funktionsanropsgränsen. Jag skulle bli förvånad om du över huvud taget ser en mätbar skillnad på exekveringstiden.

Permalänk
Medlem
Skrivet av klk:

Om jag tar mitt tidigare exempel på en metod med 32 lokala variabler och du skall förstå vad som pågår i den, hur gör du?
Och du vet säkert att som utvecklare måste man veta exakt vad som pågår

Om jag har en metod med 32 lokala variabler, då är det hög tid att skriva om metoden.
Så många lokala variabler är en stark indikation på att metoden är dåligt skriven.

Permalänk
Medlem
Skrivet av Yoshman:

Det där är formatering/syntax, inte namngivning. Jag menar hur du benämner saker för namn är mycket viktigare än syntax

Skrivet av Yoshman:

Det viktigaste egenskaperna på kod för att den ska vara lätt att läsa är saker som

meningsfulla namn

Och då är min fråga, vad är "meningsfulla namn"?
Låt säga att det är 10 utvecklare som skriver kod i ett team, hur gör de för att förstå varandras namn?

Skrivet av Yoshman:

Det skrivs långt mer än CRUD applikationer även i Java. C# är ju väldigt populärt för att skriva "vanliga" applikationer, inklusive spel. I Go:s fall har det egenskaper som gjort det för "molnet" vad C är för OS-kärnor och systembibliotek, d.v.s. standardvalet. Så Go är knappast något som används primärt för CRUD.

Vet du något? jag hittar dem inte

Lätt att fråga någon AI och även de har svårt att få fram något och är det inte CRUD så är det nästan CRUD, en hög med endpoints där varje endpoint som små egna program. Den typen av applikationer har inte samma svårighet att skala som stora monoliter där mycket hänger samman

Of course. This is an excellent question because while the vast majority of enterprise Java applications are CRUD-based, there are some very large, famous, and complex open-source Java applications that solve entirely different problems.

Dold text
Permalänk
Medlem
Skrivet av klk:

Det där är formatering/syntax, inte namngivning. Jag menar hur du benämner saker för namn är mycket viktigare än syntax

Och då är min fråga, vad är "meningsfulla namn"?
Låt säga att det är 10 utvecklare som skriver kod i ett team, hur gör de för att förstå varandras namn?

Koncist och beskrivande i sin kontext.

Samma gäller oavsett om man använder HN, så känns som du svävar ut och försöker hitta en gotcha istället för att hålla dig till ämnet som vanligt.

Skrivet av klk:

Vet du något? jag hittar dem inte

neo4j världsledande grafdatabas (Java).
ghidra, NSAs reverse engineering verktyg (Java).
docker, container-motor (Go).
kubernetes, klusterlösning (Go).
coredns, namnserver (Go).
caddy, webbserver (Go).
grafana, datavisualisering (Go).
prometheus, tidseriedatabas (Go).
discord, meddelande- och VoIP-tjänst (Elixir+Rust).

Det känns som du är vilsen även i detta resonemanget. Vi diskuterade språks effektivitet att bygga respekterade applikation i avseende av kodkvalitet och skalbarhet, vad som gör dom enl. dig till "riktiga språk"(jäkla trams om jag ska vara ärlig). Om en applikation uppfyller kraven och råkar vara CRUD så diskvalificerar det ju inte applikationen i argumentet om man kan bygga respekterade applikation i särskilda språk eftersom AI kanske kommer kunna automatisera detta framöver ...

Permalänk
Medlem
Skrivet av orp:

Koncist och beskrivande i sin kontext.

Och det är "gör som du känner för/gör som du vill". Det tvingar andra att läsa och memorera för contexten är subjektivt. Lägg därtill att väldigt många utvecklare är ganska duktiga på att förkorta variabler. Man måste lusläsa koden om och om igen om det är svårare saker.

Skrivet av orp:

Samma gäller oavsett om man använder HN, så känns som du svävar ut och försöker hitta en gotcha istället för att hålla dig till ämnet som vanligt.

Det är ingen gotcha för det är bara HN som finns för att reglera namngivning. Har du ett team av utvecklare kommer du ha svårt att se vem som skrivit viss kod i teamet för all kod ser nära nog identisk ut.
Koden bli också lätt att söka i eftersom fokus ligger på data.

Förr i tiden när utvecklare skrev nästan all kod själva (fanns inte bibliotek) och alla dessa verktyg som man har idag för att hjälpa till, de saknades. Då fanns det inte så mycket tid att skriva om kod.
Det kunde exempelvis bli gigantiska metoder. Idag säger utvecklare "det där är bara dålig kod", men de vet inte hur det är att sitta med kod och hårdvara där en omkompilering kan ta över 10 minuter, ingen lsp och små skärmar.
Med HN går det att förstå "dålig" kod i form av väldigt stora metoder. Du kan hoppa in var som helst och se vad det är, man behöver inte läsa hela metoden eller kanske mer ändå.

Permalänk
Medlem
Skrivet av orp:

Det känns som du är vilsen även i detta resonemanget.

Till skillnad mot dig har jag laddat ner och tittat på många av dem, de är inte så stora. Det är ju bl.a. det jag gjort mitt sökverktyg för, för det är lätt att se. Och de har ofta enorma mängder testkod, ta bort den så bli de inte mycket kvar

Permalänk
Medlem
Skrivet av klk:

Och det är "gör som du känner för/gör som du vill". Det tvingar andra att läsa och memorera för contexten är subjektivt. Lägg därtill att väldigt många utvecklare är ganska duktiga på att förkorta variabler. Man måste lusläsa koden om och om igen om det är svårare saker.

Samma sak gäller ju för HN den specar ju inte vad variablen ska heta efter sitt typ-prefix. Om det står:

if (is_ready) { work(); }

eller

if (bIsReady) { work(); }

leder ju enbart till att det ser kladdigare ut utan att egentligen tillföra något. Det som vi behöver veta för att läsa koden är att whatever som satt is_ready eller bIsReady är sant så anropas work(). Det är ju enbart om work() inte anropas som förväntat som vi börjar nysta i varför och där stegar vi oss förhoppningsvis igenom med debuggern och inte dubbelkollar all variabeltyper.

Skrivet av klk:

Har du ett team av utvecklare kommer du ha svårt att se vem som skrivit viss kod i teamet för all kod ser nära nog identisk ut.

Varför är detta ett problem? När du läser koden så är det antingen förstå sammanhanget med målet att ändra kod eller förstå hur koden ska bete sig, inte för att urskilja vem som skrivit den. Det är ju helt oviktigt och om det blir viktigt så använd git blame.

Skrivet av klk:

Förr i tiden när utvecklare skrev nästan all kod själva (fanns inte bibliotek) och alla dessa verktyg som man har idag för att hjälpa till, de saknades. Då fanns det inte så mycket tid att skriva om kod.
Det kunde exempelvis bli gigantiska metoder. Idag säger utvecklare "det där är bara dålig kod", men de vet inte hur det är att sitta med kod och hårdvara där en omkompilering kan ta över 10 minuter, ingen lsp och små skärmar.
Med HN går det att förstå "dålig" kod i form av väldigt stora metoder. Du kan hoppa in var som helst och se vad det är, man behöver inte läsa hela metoden eller kanske mer ändå.

Du är verkligen fast i det förflutna... Förr i tiden så fanns varken C++ eller HN, varför är du fast i just eran när HN och C++ var en sak? Om det nu finns bättre metoder och verktyg för jobbet varför har du aktivt valt att stagnera i din personliga utveckling?

Du har än en gång fastnat på gigantiska metoder, varför inte skriva om din dåliga kod så att du inte har gigantiska metoder och måste använda HN för att förstå dessa?

Permalänk
Medlem
Skrivet av klk:

Till skillnad mot dig har jag laddat ner och tittat på många av dem, de är inte så stora. Det är ju bl.a. det jag gjort mitt sökverktyg för, för det är lätt att se. Och de har ofta enorma mängder testkod, ta bort den så bli de inte mycket kvar

Ok, min kodkatalog på min dator har 884647 unika filer med totalt 217993034 rader kod. Om det är för att testa ditt sökverktyg så klona bara dom största projekten på Github. Jag har inte strävat efter att uppnå kodmängd utan bara grävt rundor i random projekt så du lär nog också uppnå en stor kodmängd snabbt.

Om det istället handlar om din konstiga syn om prestige och att fler kodrader är mer prestigefyllt så kan du ju se det som att detta är marknadsledande projekt som åstadkommer funktionaliteten med färre rader än om det skulle varit implementerat C++ samt att dom har fler rader än ditt projekt.

Permalänk
Skrivet av klk:

Och det är "gör som du känner för/gör som du vill". Det tvingar andra att läsa och memorera för contexten är subjektivt. Lägg därtill att väldigt många utvecklare är ganska duktiga på att förkorta variabler. Man måste lusläsa koden om och om igen om det är svårare saker.

Har du ett team av utvecklare kommer du ha svårt att se vem som skrivit viss kod i teamet för all kod ser nära nog identisk ut.

HN har väl inga regler för "namn"-delen av namnet? Dvs, det är "gör som du känner för/gör som du vill" + suffix (eller prefix om man kör Simonyi style). Att koden ser likadan ut oavsett vilken utvecklare som har skrivit den beror på att ni har en vedertagen terminologi och alla sansade utvecklare anpassar sig till den etablerade stilen i existerande kod.

Om någon väljer dåliga/missvisande namn är du väl inte jättehjälpt av variablen har ett typsuffix (som inte kontrolleras av kompilatorn utan kan vara felaktigt)?

Permalänk
Medlem
Skrivet av Ingetledigtnamn:

HN har väl inga regler för "namn"-delen av namnet? Dvs, det är "gör som du känner för/gör som du vill" + suffix (eller prefix om man kör Simonyi style).

Tänk på att nästan alla läst fel om HN, de flesta har läst wikipedia och den beskrivningen är inte korrekt.
HN är en teknik, en princip. ingen specifik stil. Det är mycket mer att förstå syftet med att skriva kod på det viset och när man förstår syftet jämkas utvecklarna samman.

Till exempel tror de flesta att HN har fasta förkortningar, har de exempelvis läst någon HN kod och set att int variabler börjar med "i" så tror det att det är HN. Så är det INTE. För varje team väljs de förkortningar som passar teamet och målet skall vara att att man inte skall behöva memorera något. En förkortning måste vara naturlig. Att utvecklare instinktivt fattar vad det är utan att behöva läsa på. Och när man förstår hur viktig den principen är då klickar det lite överallt. Utvecklare fattar och ofta släpper det när de märker att kod som de tidigare slitit med för att förstå plötsligt blir hanterbar.

Du kan köra HN helt utan förkortningar.

En annan viktig princip med HN är att förstå att man inte skriver kod för att läsas. Har hört Simony säga flera gånger att ingen utvecklare skriver kod för den skall gå och läsa. Tror han nämnde i någon podd att "om man skall prata om sin kod så sätter man sig inte ner och läser koden för andra". Kod är kod, inte text

När utvecklare förstår att kod skrivs för att kunna hanteras, inte läsas. Då har de tagit ett stort kliv frammåt

Här finns fyra punkter: https://learn.microsoft.com/en-us/previous-versions/visualstu...

  1. Mnemonic value—so that the programmer can remember the name.

  2. Suggestive value—so that others can read the code.

  3. "Consistency"—this is often viewed as an aesthetic idea, yet it also has to do with the information efficiency of the program text. Roughly speaking, we want similar names for similar quantities.

  4. Speed of the decision—we cannot spend too much time pondering the name of a single quantity, nor is there time for typing and editing extremely long variable names.

När du läser om andra stilar så ser du ofta en hel lista (så här skriver vi). Handlar mycket mer om formatering och syntax.
Det är alltså inte tanken bakom HN

Notera punkt 1 och 2
1: so that the programmer can remember the name.
2: so that others can read the code.

Observera "others"

Och det är vad som tränas upp när man skriver HN och det är också därför att HN kodare kan läsa enorma mängder kod på kort tid. De läser inte koden utan skannar bara typerna och det går så snabbt att de nästan kan hinna med medan free wheel på en mus spinner iväg.

Permalänk
Medlem
Skrivet av klk:

Tänk på att nästan alla läst fel om HN. ...

Tänk att du skrev ett stycke som helt saknade substans.

Det är strunt samma vad typ-(pre|suf)fixen är eller vem som bestämt vad dom heter. Du började yra om namngivning av variabler och vi säger att HN ställer samma krav på namngivning i allmänhet och du adresserar inget av det och fortsätter att yra om typ-delen av variabelnamnet...

Jag förstår verkligen inte hur du kan arbeta med kodning du klar knappt att hålla kontext i 5 minuter :S

Skrivet av klk:

En förkortning måste vara naturlig

Vad är detta för jäkla kumbaya-kodning? Hur kommer du ihåg typerna C++ utan en egen namnkonvention?

Så om vi tar mitt exempel ovan är där något fel med is_ready som variabelnamn, vilken punkt bryter detta isf mot?

Hur klarar de största projekten på Github sig utan HN?
Har du någonsin funderat över att HN fungerar för dig men inte andra?

Permalänk
Medlem
Skrivet av orp:

int is_ready; eller double is_ready; eller class_name is_ready; ... if (is_ready) { work(); } if (bIsReady) { work(); }

Nu då?

Permalänk
Medlem
Skrivet av klk:

Jag vet inte vad std::string(jag har inte sådana högnivå saker i min C-kod) är men förklara för mig varför det är viktigt för mig att veta om is_ready är en double eller int när jag läser någons kod?

Du ändrade till class_name is_ready, du tyckte att det var ett bättre icke-högnivåkoncept som fungerar i min C-kod?

Permalänk
Medlem
Skrivet av orp:

Jag vet inte vad std::string(jag har inte sådana högnivå saker i min C-kod) är men förklara för mig varför det är viktigt för mig att veta om is_ready är en double eller int när jag läser någons kod?

Du ändrade till class_name is_ready, du tyckte att det var ett lågnivå koncept som fungerar i min C-kod?

Ja skrev snabbt och normalt för "is_ready" logik är att det är en hel del annat så poängen var att ha en klass/objekt. För den exempelkod du använder för att visa på ditt är inte normal kod och det är nära nog det enklaste du behöver ta till för att visa att HN inte spelar någon roll.

Man väljer inte hur kod skriv för enklaste möjliga exempel, man väljer hur kod skrivs för det mest avancerade. Det enklaste kan skrivas hur som helst, man fattar ändå

Det var så här de tryckte igenom OOP när det kom och hur java marknadsförde sig. De använde exempel som inte är realistisk kod för och visa hur bra OOP var. Och givetvis förstod de flesta C/C++ programmerare men inte andra. Java kunde locka de som inte visste vad programmering handlade om. Olika exempel med klasshierarkier där bilar, djur, symboler användes för att visa hur bra arv är.

Annars så det viktigaste med de här två olika exemplen och typisk HN kodare är att det undre exemplet är något som inte läses alls. Har jag en if(bXxxxXxxx == false eller if(bXxxxXxxx == true så hoppar jag över det automatiskt
Är det ett objekt så stannar jag upp för HN är väldigt bra för att veta vad man inte behöver titta på

if(is_ready){ work(); } eller if(bIsReady) { work(); }

Permalänk
Medlem
Skrivet av klk:

Ja skrev snabbt och normalt för "is_ready" logik är att det är en hel del annat så poängen var att ha en klass/objekt. För den exempelkod du använder för att visa på ditt är inte normal kod och det är nära nog det enklaste du behöver ta till för att visa att HN inte spelar någon roll.

Man väljer inte hur kod skriv för enklaste möjliga exempel, man väljer hur kod skrivs för det mest avancerade. Det enklaste kan skrivas hur som helst, man fattar ändå

if (is_ready) { work(); }

Du undviker som vanligt frågan och svarar på något helt annat... VARFÖR MÅSTE JAG VETA OM is_ready ÄR EN DOUBLE ELLER INT?

Här är ett exempel från mitt kodprojekt(Rust denna gången), vad är det som inte är normalt?

if schedule.is_ready(task) { ... }

Vad returnerar metoden is_ready(), är det relevant för dig som läsare? Den mellanlagras in ens i en variabel, hur skulle du någonsin förstå den koden?