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

Permalänk
Medlem
Skrivet av klk:

Det är ingen brist utan språket är så kraftfullt att du kan göra det mesta bättre själv

Menar du att det är riskfritt att använda annans kod?
Skall du göra ett system som skall ha en livslängd på +20 år, då begränsar det ordentligt vad du kan plocka in. Du måste tänka annorlunda jämfört med om livslängden är kanske 3 år innan det behöver börja refaktoreras.
Externa bibliotek är att bygga in sig.

Med det menar jag inte att man aldrig lägger med externa bibliotek i C++. Det gör jag också men inte alls på samma sätt som när man gör det i andra språk. Personligen så handlar det nästan uteslutande om extern funktionalitet där källkoden är med och kompileras upp. Är det inte källkoden som är med skall det väldigt mycket till för att ta med det.

Mitt första program jag skrev som utvecklare, jobbade 7 månader på ett bolag och skrev då ihop en. mitten på 1990 talet. Det säljs fortfarande och omsätter runt 50 miljoner varje år. Det skrev för Windows 3.11 och Microsoft MFC användes som ramverk.

Att C++ lösningar kan leva så länge är för många mycket viktigare än att slänga ihop något som endast fungerar för vad just det företaget har behov av.

Det finns ju system som en gång i tiden skrevs i Cobol eller Fortran eller C och som byggdes för att användas i många år, och som fortfarande används med framgång.
Vad kan C++ bidra med, enligt dig, som inte de språken kan göra minst lika bra?

Permalänk
Medlem
Skrivet av Erik_T:

Det finns ju system som en gång i tiden skrevs i Cobol eller Fortran eller C och som byggdes för att användas i många år, och som fortfarande används med framgång.
Vad kan C++ bidra med, enligt dig, som inte de språken kan göra minst lika bra?

C++ bidrar till de andra språken. Mycket i .NET, kanske det mesta är skrivet i C++.

Ofta skrivs logiken i C/C++ och sedan wrappas det för att smidigt kunna tas med i andra språk. Många kända C++ bibliotek används på detta vis. Ta bara Sqlite, världens mest använda databas skriven i C.

Och om jag spekulerar så något jag tror kommer hända och det har med AI att göra. Fler C++ programmerare kommer bygga generella lösningar som har bättre funktionalitet och är vältestade. Dessa kommer användas i andra språk.

Min tolkning av hur AI påverkar duktiga utvecklare så för dem handlar det inte så mycket om att hitta nya lösningar, där kan inte AI hjälpa speciellt mycket. Men AI är mycket stor hjälp för att plocka bort allt tråkigt och upprepande jobb.
För egen del så är jag dyslektiker, att skriva dokumentation är inte en styrka om man säger så. AI har här varit otroligt bra. AI är grymt för att skriva testkod som kan testa igenom och bättre hitta missar. AI är också smidigt för att söka hjälp.

Exempel (kompleterar tidigare inlägg om JSON):
Låt säga att en utvecklare behöver XPATH men i JSON. Det finns gott om JSON bibliotek men de saknar selektering. Då skulle en utvecklare kunna skriva en selekterings logik (parsa text och göra om till kommandon). Bygga kopplingar till kända JSON bibliotek i C++ (kommando från parsad selektering kod översätts till kommandon för respektive JSON bibliotek) och så har de här fått möjlighet att söka värden.
Det som normalt tar mest tid i något sådant handlar om att hitta ett bra format och försöka följa standarder. XPATH är en standard och kan man följa den och göra något slags JSONPATH är det bättre än att hitta på helt eget. Men för utvecklaren är det tidsödande och läsa på och lära sig allt som finns specificerat för XPATH.
Här är AI jättebra och mycket tidsbesparande.

Annat som AI är väldigt bra på är att tolka C++ fel från kompilatorn och det tror jag många är välkommet för det är inte lätt. Man behöver förstå termer och annat, tyda koden. Här finns det gott om träningsdata och det går att klistra in information i AI och den lyckas nästan alltid hitta vad som behöver göras.

Permalänk
Datavetare
Skrivet av klk:

Det är möjligt men i det du beskriver just nu så verkar jag ha förstått rätt, att min kritik stämmer. Och att det snarare handlar om att du missuppfattar C++.

Kan absolut inte allt i C++, men har trots allt en hyfsat gedigen kunskap i att använda språket (har gjort allt från custom-game-engine, Unreal Engine m.a.p. spel, en rad backend-system, test-ramverk, ett par applikationer och implementerat standardbiblioteket för C++11/14). Är uppenbarligen inte med på vad jag helt missuppfattar här.

Skrivet av klk:

Som jag skrivit tidigare i varianter. C++ är inte gjort för att vara lätt, det är inte gjort för att använda sig av ett paket med funktionalitet som följer med språket. C++ är ett verktyg för att möjliggöra bästa möjliga lösning (utan att börja hacka assembler).

Det bokstavligen skapades för att vara ett "bättre C". Med tiden har C och C++ divergerat en hel del, men C++ är fortfarande primärt ett systemspråk.

Skrivet av klk:

Att andra språk är "enklare" vet jag också. Men vad som är enkelt i ett språk är inte samma sak som att det skulle vara enkelt att skriva kompletta applikationer som skall installeras hos kunder eller köras av väldigt många användare.

Historiskt kanske C++, ihop med C, var någorlunda unikt om man ville skapa extremt högpresterande lösningar. Flera av de "nya" (nya här är rätt mycket "lanserade efter millenneskiftet") som fungerar minst lika bra, framförallt finns det bättre lösningar för att effektivt hantera multicore system.

Skrivet av klk:

C# och C++ är två totalt olika språk, samma med java. De är varandras motpoler.
java skeppar också en herrans massa funktionalitet.

För någon som varken kan C# eller Java kanske det kan te sig så. Får själv säga att jag också hade missuppfattningen att Java och C# är väldigt nära. Har erfarenhet av C++ och Java sedan länge, började använda C# professionellt så sent som 2022.

Microsoft hävdar att C# mer är ett modernt C++ än vad det är en Java-klon. Efter att nu jobbat en hel del i C# får jag ge Microsoft att den beskrivningen är mer rätt än man kan tro!

Skrivet av klk:

Exakt, det är verkligen ingen översättning. Det är en helt annan lösning för du plockar där in ett bibliotek som någon annan skrivit åt dig. Och det är självklart bra för utvecklare då de slipper skriva koden själv men det visar brister i språket. Istället för att lära sig programmera behöver du lära dig bibliotek.

Då har du nog totalt misslyckas att läsa Clojure-koden. Försökte hålla den så nära C++ sett till hur den använder bibliotek och standardbilbliotek. Enda som inte tillhör standardbiblioteket är "ar", där används något som (så långt jag kan bedöma) har samma API som den "archive" klass din C++-lösning använder.

Samma gäller Go-exemplet.

Visa signatur

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

Permalänk
Datavetare
Skrivet av klk:

C++ bidrar till de andra språken. Mycket i .NET, kanske det mesta är skrivet i C++.

Det finns delar av .NET-runtime som är skrivna i C++, men det mesta är faktiskt C# inklusive hela tool-chain:en. Tool-chain var initialt skriven i C++, men sedan lanseringen av "Roslyn" 2015 är den C#.

Edit: det skrivet, C# och dess runtime är explicit designad för att ha zero-overhead i att använda bibliotek skrivna i C och/eller C++ (och exporterade via COM). Java har likt de flesta runtimes en viss overhead, Go har p.g.a. av sina unika runtime rätt hög overhead att anropa C (men logiskt är det superenkelt då C-interop är integrerat i språket/toolchain).

Att det är ju C# som blivit alternativet till C++ för spel är en direkt konsekvents av detta. Rent allmänt är detta något Microsoft gjort för att C# ska kunna ersätta C++ för applikationer och vissa systemtjänster i Windows (fast på senare tid verkar Microsoft gå allt mer mot Rust som ersättare för C++ i just Windows-systemtjänster).

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 Yoshman:

Microsoft hävdar att C# mer är ett modernt C++ än vad det är en Java-klon. Efter att nu jobbat en hel del i C# får jag ge Microsoft att den beskrivningen är mer rätt än man kan tro!

Ursäkta om jag inte svarar på allt (nu), lite ont om tid.

Men jag tolkar dig som att du anser att C# är likt C++, eller hur kan jag översätta "modernt C++"? Vad är det i C# som är likt C++ (om jag fattat rätt) ?

Själv tror jag att C# minskar betydligt på grund av AI. Den kod som jag sett som ofta skrivs i C# kan ofta automatgenereras med AI. Det finns också massor av träningsdata och koden är mycket lik vanlig text. C# (även java), där skrivs ofta kod med namn efter domänen, inte smarta lösningar. Så fort något liknar vanlig text går man in på LLMs hemmaplan. Här kan inte människor konkurrera.

FRÅGA
Passar också på och fråga om någon känner till bra kod för att spara filer i en enda fil. Ungefär som att zippa ihop filer men utan att zippa?
Att jag skrev ihop archive klassen i fredags har och göra med att behöver en lösning för att samla filer i en enda fil. Inte en jättesvår lösning att göra men om det finns något där så tar jag gärna emot tips.
Lösningen är till för att agera som en slags cache, snabba SSD diskar cachar stora mängder data istället för att mellanlagra i databaser.

Permalänk
Medlem
Skrivet av Yoshman:

Att det är ju C# som blivit alternativet till C++ för spel är en direkt konsekvents av detta. Rent allmänt är detta något Microsoft gjort för att C# ska kunna ersätta C++ för applikationer och vissa systemtjänster i Windows (fast på senare tid verkar Microsoft gå allt mer mot Rust som ersättare för C++ i just Windows-systemtjänster).

Microsoft måste gå över till Rust (eller liknande) för att vara konkurrenskraftiga men de byter inte ut C++ utan jag tror de byter ut annat. De behöver så många utvecklare och vill inte betala astronomiska löner, de vill också ha en hel del "enklare" kod där de kan ersätta utvecklare.
Rust enligt mig är ett av de språken som kommer plocka andelar från java och C#. Och det skulle inte förvåna om inte Microsoft själva snart kommer ut med något liknande.

Den här transformeringen måste Microsoft göra och det beror på AI. Jättarnas monopol är hotat på grund av AI

Finns också en del designproblem i C# och tror att kostnaden för att underhålla hela C#s ekosystem kommer bli dyrt om antalet utvecklare minskar och det blir fler plattformar.

Permalänk
Datavetare
Skrivet av klk:

Ursäkta om jag inte svarar på allt (nu), lite ont om tid.

Men jag tolkar dig som att du anser att C# är likt C++, eller hur kan jag översätta "modernt C++"? Vad är det i C# som är likt C++ (om jag fattat rätt) ?

Själv tror jag att C# minskar betydligt på grund av AI. Den kod som jag sett som ofta skrivs i C# kan ofta automatgenereras med AI. Det finns också massor av träningsdata och koden är mycket lik vanlig text. C# (även java), där skrivs ofta kod med namn efter domänen, inte smarta lösningar. Så fort något liknar vanlig text går man in på LLMs hemmaplan. Här kan inte människor konkurrera.

FRÅGA
Passar också på och fråga om någon känner till bra kod för att spara filer i en enda fil. Ungefär som att zippa ihop filer men utan att zippa?
Att jag skrev ihop archive klassen i fredags har och göra med att behöver en lösning för att samla filer i en enda fil. Inte en jättesvår lösning att göra men om det finns något där så tar jag gärna emot tips.
Lösningen är till för att agera som en slags cache, snabba SSD diskar cachar stora mängder data istället för att mellanlagra i databaser.

C# är ett i raden av "C-style languages", så ur den aspekten har det likheter med C++. Ställer man C# mot Java har det förra mer likheter med C++.

Men var inte det jag menade (och rätt säker att det inte heller är vad Microsoft menar). Utan "modernt C++" handlar mer om att applikationer/funktioner man historiskt utvecklat i C++ går i de flesta fall precis lika bra att utveckla i C#. Och även om C# tyvärr är ett rätt komplext språk sett till dess specifikation är det ändå betydligt lättare än C++.

Just att C# blivit populärt i spel är lite unikt, även om det finns spel skrivet i de flesta språk är det rätt mycket bara C++ och C# som är rejält utbredda. Desktop-applikationer verkar vara en allt mer utdöende genre, men i den mån det fortfarande sker är C# ett fullt rimligt alternativ till C++ i de flesta fall, men å andra sidan är ju JS/TS en "snabbt stigande stjärna" inom detta område tack vare Electron. Vilket också är fullt rimligt givet att Windows inte längre har några >90 % av marknaden, idag ligger Windows på ca 70-75 % om man enbart tittar på desktop, långt mindre om man tar med plattor/telefoner.

Electron eller annan webbteknik är väl rätt mycket det som "suck-less" av de alternativ man har om man vill tänka in de populära plattformarna (Windows, MacOS, ChromeOS och Linux).

Tyvärr tycker jag ändå C# har förvånadsvärt mycket vårtor och "foot-guns". Färre en C++, men märks ändå att C# (och även Java) utvecklades innan man riktigt fick grepp om multicore-programmering och framförallt innan man hittade lika bra sätt att hantera beroenden och bygg-logik som vi idag har hos Rust (Cargo är rent tekniskt ett 3:e-parts ramverk, inte en del av språket men i praktiken är det en de-facto standard) och framförallt Go (i raden av "killer-features" är dess tool-chain ännu en sådan, rätt lite som är bra handlar egentligen om språket utan man nailade så mycket kritiskt runt omkring).

Vad det gäller det sista: ingen aning i C++ (har gjort exakt det som del i custom-game-engine i C++, borde ju finnas färdiga bibliotek).

package main import ( "archive/zip" "io" "log" "os" ) func main() { outFile, err := os.Create("output.zip") if err != nil { log.Fatal(err) } defer outFile.Close() zipWriter := zip.NewWriter(outFile) defer zipWriter.Close() files := []struct { Name, Path string }{ {"file1.txt", "data/file1.txt"}, {"file2.txt", "data/file2.txt"}, } for _, file := range files { f, err := os.Open(file.Path) if err != nil { log.Fatal(err) } defer f.Close() w, err := zipWriter.Create(file.Name) if err != nil { log.Fatal(err) } if _, err := io.Copy(w, f); err != nil { log.Fatal(err) } } log.Println("Archive created: output.zip") }

Go kan göra det via standardbiblioteket

using System.IO; using System.IO.Compression; class Program { static void Main() { string zipPath = "output.zip"; string[] files = { "data/file1.txt", "data/file2.txt" }; using (var zipStream = new FileStream(zipPath, FileMode.Create)) using (var archive = new ZipArchive(zipStream, ZipArchiveMode.Create)) { foreach (var filePath in files) { string entryName = Path.GetFileName(filePath); var entry = archive.CreateEntry(entryName); using (var input = File.OpenRead(filePath)) using (var output = entry.Open()) { input.CopyTo(output); } } } System.Console.WriteLine("Archive created: output.zip"); } }

Även C# kan göra detta via standardbiblioteket

Att kunna göra det via standardbiblioteket är en rejäl styrka, framförallt när man bygger programvara som hamnar i drift under decennium. Förutom att vara just en del av standarden tenderar standardbiblioteken ha väldigt hög kvalité och stabilitet.

Visa signatur

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

Permalänk
Datavetare
Skrivet av klk:

Microsoft måste gå över till Rust (eller liknande) för att vara konkurrenskraftiga men de byter inte ut C++ utan jag tror de byter ut annat. De behöver så många utvecklare och vill inte betala astronomiska löner, de vill också ha en hel del "enklare" kod där de kan ersätta utvecklare.
Rust enligt mig är ett av de språken som kommer plocka andelar från java och C#. Och det skulle inte förvåna om inte Microsoft själva snart kommer ut med något liknande.

Den här transformeringen måste Microsoft göra och det beror på AI. Jättarnas monopol är hotat på grund av AI

Finns också en del designproblem i C# och tror att kostnaden för att underhålla hela C#s ekosystem kommer bli dyrt om antalet utvecklare minskar och det blir fler plattformar.

Nej det är explicit väldigt "core-features" som tidigare var utvecklade primärt i C++ som man ersätter med Rust. Ett väldigt noterbart exempel är GDI (Graphics Device Interface).

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 Yoshman:

Vad det gäller det sista: ingen aning i C++ (har gjort exakt det som del i custom-game-engine i C++, borde ju finnas färdiga bibliotek).

Tack.
Håller med och sökte en del på det igår men hittade inget. zip lösnignar finns men de är alldeles för sega för det här.
Molnlösningar som producerar mycket filer är heller inte roliga att jobba med om saker skall flyttas runt.

Permalänk
Datavetare

Och för att faktiskt skriva något som är on-topic: kom ut ett nytt avsnitt av CppCast för ett par dagar sedan
https://cppcast.com/news_and_catch-up/

Där nämns bl.a. att Bjarnes "lösning" på C++-säkerhetsproblem, Profiles, kommer tyvärr inte att komma med i C++26. Så om det är vägen C++ ska ta finns en standardiserad lösning tidigast i C++29.

Däremot kommer en första version av "contracts" i C++26. Timur Doumler, som tillsammans med Phil Nash, driver CppCast för tillfället, är ordförande för SG21, "contracts study group" inom ISO C++ standard kommittén.

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 Yoshman:

Nej det är explicit väldigt "core-features" som tidigare var utvecklade primärt i C++ som man ersätter med Rust. Ett väldigt noterbart exempel är GDI (Graphics Device Interface).

Ok, jag vill nog se mer bevis för det där. Vad de faktiskt tänker göra.
Jag tror inte Microsoft skulle ta in något som gjorde något centralt utan att kunna kompilera upp koden med egna verktyg, inte än i alla fall. Eller så har de skrivit egen kompilator för Rust.

Tänk på att Microsoft är ett aktiebolag och de är hemskt brutala för att tjäna pengar och behålla monopol. Vad de säger utåt behöver inte alls vara samma sak som vad de faktiskt gör.

Permalänk
Medlem
Skrivet av Yoshman:

Däremot kommer en första version av "contracts" i C++26. Timur Doumler, som tillsammans med Phil Nash, driver CppCast för tillfället, är ordförande för SG21, "contracts study group" inom ISO C++ standard kommittén.

Japp, det är ett mycket bra tillägg för vad de gör är att standardisera "assert" med en del extra och vad jag vet är det många C/C++ nördar som efterfrågat det.

Passar på att lägga upp Lex Friedman om assert

Ibland tror jag det här kallas för "defensive programming" (osäker). Och som John Carmack att utvecklare som inte använder debugger är ett galet uttalande.
Fördelen med att tränat upp sig i sådan här defensive programmering är kvalitet, utvecklare slipper leta buggar.
Rusts väg och applikationer med GC har helt plockat bort möjligheten med minne men fortfarande är allt annat kvar, felaktiga värden. Där finns inte säkerhetsproblem men det är fortfarande buggar.

Permalänk
Datavetare
Skrivet av klk:

Ofta skrivs logiken i C/C++ och sedan wrappas det för att smidigt kunna tas med i andra språk. Många kända C++ bibliotek används på detta vis. Ta bara Sqlite, världens mest använda databas skriven i C.

Som redan nämnts i tråden, finns en rewrite av Sqlite i Rust som presterar bättre än originalet...

Skrivet av klk:

Ok, jag vill nog se mer bevis för det där. Vad de faktiskt tänker göra.
Jag tror inte Microsoft skulle ta in något som gjorde något centralt utan att kunna kompilera upp koden med egna verktyg, inte än i alla fall. Eller så har de skrivit egen kompilator för Rust.

Tänk på att Microsoft är ett aktiebolag och de är hemskt brutala för att tjäna pengar och behålla monopol. Vad de säger utåt behöver inte alls vara samma sak som vad de faktiskt gör.

Varför skulle kompilatorn vara ett problem givet att den är LLVM-baserad? Även Microsoft har ju en diskussion kring om de ska släppa MSVC++ och, likt vad Intel gjorde för ett par år sedan, fokusera på LLVM/Clang .

Och just nu heter ju Microsoft CTO Mark "Windows Internals" Russinovish. Han ser sig själv sedan länge som en "Rustancian"

Långt innan han gjorde sin tweet om att "alla nya projekt som inte kan använda GC ska i första hand nu skrivas i Rust" sa detta flera år tidigare

"One of the things that I did even before that tweet was say no more systems code in C++ in Azure and I did that probably two or three years before that tweet because I was already like enough is enough with this rust is ready let's just start"

I denna video går Mark Russinovish igenom hur Microsoft använder Rust, bl.a. i Windows, Office och Azure.

Och åter igen, om "in-house kompilator" skulle vara kritiskt vore det ju helt otänkbart för Microsoft att välja Go som språk/tool-chain till deras nya TypeScript kompilator. Det har varit / är en hel del diskussion kring varför man inte valde .NET/C#, Rust eller till och med C++. Att man inte valde .NET/C# är extra noterbart givet att det var Anders Hejlsberg (skaparen av C#) som gjorde valet, det efter man testat en rad språk, C# inkluderat.

Att använda MSVC++ (propretär och stängd källkod) är väl egentligen en större risk än att använda LLVM/Clang i nuläget? Nog för att C#-kompilatorn numera är öppen källkod ("Roslyn" som primärt supportas av Microsoft), de har ju samma säkerhet med Go då även den är öppen källkod (finns idag både en GCC-variant och den "traditionella" som Google supportar en hel del).

Rust har också en LLVM-baserad kompilatorn (den ursprungliga) och numera finns även en GCC-baserad.

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

Där är inget slut på ditt yrande.

Skrivet av klk:

Ibland tror jag det här kallas för "defensive programming" (osäker). Och som John Carmack att utvecklare som inte använder debugger är ett galet uttalande.

Somliga klarar att lösa uppgiften utan vart enda verktyg i verktygslådan dvs debuggern är inte nödvändig i många fall ...

Skrivet av klk:

Fördelen med att tränat upp sig i sådan här defensive programmering är kvalitet, utvecklare slipper leta buggar.
Rusts väg och applikationer med GC har helt plockat bort möjligheten med minne men fortfarande är allt annat kvar, felaktiga värden. Där finns inte säkerhetsproblem men det är fortfarande buggar.

Rust har redan en del sådan features som att du måste hantera errors, Rust varnar för icke-hanterade returvärden. Om du använder motsvarigheten till switch-case för enums eller tagged unions så måste du hantera alla members eller aktivt välja en catch-all.

Sedan kan ju kompilatorn inte läsa dina tankar(åtminstone inte tills alla sitter med neurolink ) så det finns inget skydd mot logiska fel.

Permalänk
Medlem
Skrivet av Yoshman:

Som redan nämnts i tråden, finns en rewrite av Sqlite i Rust som presterar bättre än originalet...

Är den klar än? https://github.com/tursodatabase/limbo

Vad är "bättre"? sqlite har en specifik uppgift och är begränsad av det eftersom det är så många system som är beroende av sqlite.

Tror annars att det kommer skapas mycket mer nytt i och med AI för äntligen kan personer med ideer skapa saker där efterlevnaden är enklare. Är något bara beroende av en enda person eller några få så kan de göra hur bra saker som helst, det kommer ändå inte bli använt eftersom det är knutet till kunskap de har i själva.

Med väldokumenterad och välskriven C++ kod (liksom annan kod) kan AI hjälpa till och tolka koden.

Permalänk
Medlem
Skrivet av orp:

Rust har redan en del sådan features som att du måste hantera errors, Rust varnar för icke-hanterade returvärden. Om du använder motsvarigheten till switch-case för enums eller tagged unions så måste du hantera alla members eller aktivt välja en catch-all.

Och det tror jag få C++ utvecklare skulle acceptera.

Labbar jag med något kanske jag skriver om två eller tre gånger innan jag är nöjd. Då vill man inte ha massa bråk med en kompilator

Permalänk
Medlem
Skrivet av klk:

Och det tror jag få C++ utvecklare skulle acceptera.

Labbar jag med något kanske jag skriver om två eller tre gånger innan jag är nöjd. Då vill man inte ha massa bråk med en kompilator

Jag skriver också om 2-3 gånger. Jag introducerade LSP i min editor först när jag började koda Rust för att lättare hantera dom delarna, som att hantera alla enum-members. Det finns dock lata sätt att kringgå detta om man nu vill prototypa.

Permalänk
Medlem
Skrivet av Yoshman:

Finns en brilliant presentation av Rich Hickey just kring det temat (för det är tyvärr rätt vanligt att tänka exakt så)
https://www.infoq.com/presentations/Simple-Made-Easy/

I.e. folk blandar ihop "easy/hard" (lätt/svårt) med "simple/complex" (enkelt/komplicerat). Det man tror är att man gör saker som är enkla, inte komplexa. Men många gånger gör man onödigt komplexa saker bara för att de råkar vara lätt(are) för just dig din tidigare erfarenhet gör att du vet hur problemet ska lösas med en viss teknik.

Har lyssnat, det han tar upp är ett enormt område och olika saker passar för olika lösningar. Hörde inte att han beskrev det, hur omfattande det han pratar om faktiskt är.

Exempel:
- Att isolera funktionalitet är viktigt, mycket viktigt. Men vad är "en" funktionalitet. Där är första problemet, inte alla vet vad som är EN funktionalitet när man programmerar.
- Han pratade en del om att plocka bibliotek som om det var enklare. Tycker inte han förklarade riskerna att bygga in sig och hur svårt det blir när saker inte fungerar längre. Har nämnt att det sitter ett team i närheten som helt trasslat in sig i mängder av komponenter. Det är python utvecklare som är vana att skriva skript åt sig själva. Nu dräller det av komponenter i en ganska enkel lösning. Förstår inte hur man lyckas använda så mycket för något så enkelt som de gör.
- Saknade att han bättre skulle förklara hur viktigt det är att investera tid i kommunikation mellan funktionalitet. "decuple" är värt att lägga tid på och det är ok att den koden är avancerad internt, svårt att få till bra kommunikation med "lätt" kod.
- Det är en genomgång man måste lyssna igenom flera gångar för det är så mycket han tar upp och man hinner inte processa det medan han pratar. Lätt att missförstå även om det är bra tips.

Permalänk
Medlem
Skrivet av orp:

Jag skriver också om 2-3 gånger. Jag introducerade LSP i min editor först när jag började koda Rust för att lättare hantera dom delarna, som att hantera alla enum-members. Det finns dock lata sätt att kringgå detta om man nu vill prototypa.

Det tolkar jag som att även du tycker det är störande med en nitisk kompilator?

Använder exempelvis inte ens "private" för medlemsvariabler just av denna orsak. Vill man testa eller har buggar där man måste skriva om lite kod för att se och förstå hur bäst buggen löses så är det jobbigt med dessa hinder. Har flera gånger svurit över extern kod där de satt saker som private men som man skulle använda sig av.

Utvecklare får bara lära sig att inte accessa medlemsvariabler i färdig kod.

Har några gånger haft diskussioner med andra där de frågat "varför använder du inte private" på medlemsvariabler. Brukar då fråga varför jag skulle göra det. Tror aldrig jag fått något bra svar

Onödiga hinder gynnar inte koden

Permalänk
Medlem
Skrivet av klk:

Inte en jättesvår lösning att göra men om det finns något där så tar jag gärna emot tips.

Äh, det fixar du själv, du har ju flertalet gånger berättat hur överlägsen du är alla oss andra.

Permalänk
Skrivet av klk:

Tack.
Håller med och sökte en del på det igår men hittade inget. zip lösnignar finns men de är alldeles för sega för det här.
Molnlösningar som producerar mycket filer är heller inte roliga att jobba med om saker skall flyttas runt.

Jag funderade ut pseudokod och bad sedan Gemini Flash 2.0. Thinking att ge något som i princip concatenate filer men först med metadata för att sedan också kunna splitta ut dessa. För att inte tugga igenom varje fil bara för att få veta dess längd så bad jag den att nyttja OS:et filsystem för det borde ju redan sitta på den informationen såsom längd i bytes, filnamn och filändelse.

Den hopsatta filen - om C++-koden kompilerar (vilket den troligen aldrig kan göra från LLM:er!) - ska då innehålla metadata om filnamn, bytes-längd vilket då kan användas som avskiljare när den skriver ut de separata filerna igen. Först tänkte jag på att föra in extra bytes som avskiljare mellan filerna men då finns risken att samma bytes redan används i någon fil som då skulle avskilja vid fel ställe och därmed skapa korrupta filer. Så metadata i början av den stora filen bör lösa det problemet.

Den använder en Struct som innehåller filnamn och bytes-längd och sedan nyttjas en vektor för att lagra metadata av den typen av Struct. Programmet ska köras med att skicka minst 3 argument till den kompilerade "konsolfilen.exe" via char* argv.

Kika gärna och se om det skapar inspiration. Förhoppningsvis ligger prestandan på O(n) där n är antalet filer som ska slås ihop (jag kan ej yttra mig om huruvida den kan innehålla minnesläckor eller ej):

// WARNING: This was written Gemini Flash 2.0 Thinking after prompt from a Junior Web Developer // This means the code is probably worse than code written by someone who has never seen a line of code before! #include <iostream> #include <fstream> #include <vector> #include <string> #include <filesystem> // Requires C++17 #ifdef _WIN32 #include <windows.h> #else #include <sys/stat.h> #endif namespace fs = std::filesystem; // Structure to hold file metadata struct FileInfo { std::string name; uint64_t size; }; // Function to get the size of a file uint64_t getFileSize(const std::string& filename) { #ifdef _WIN32 WIN32_FILE_ATTRIBUTE_DATA fileData; if (GetFileAttributesEx(filename.c_str(), GetFileExInfoStandard, &fileData)) { return (static_cast<uint64_t>(fileData.nFileSizeHigh) << 32) | fileData.nFileSizeLow; } return 0; // Error case #else struct stat stat_buf; int rc = stat(filename.c_str(), &stat_buf); return rc == 0 ? stat_buf.st_size : 0; // Error case #endif } int main(int argc, char* argv) { if (argc < 3) { std::cerr << "Usage: " << argv[0] << " <output_file> <input_file1> [input_file2 ...]" << std::endl; return 1; } std::string outputFilename = argv[1]; std::vector<std::string> inputFilenames; for (int i = 2; i < argc; ++i) { inputFilenames.push_back(argv[i]); } std::ofstream outputFile(outputFilename, std::ios::binary); if (!outputFile.is_open()) { std::cerr << "Error opening output file: " << outputFilename << std::endl; return 1; } // 1. Write the number of files uint32_t numFiles = static_cast<uint32_t>(inputFilenames.size()); outputFile.write(reinterpret_cast<const char*>(&numFiles), sizeof(numFiles)); // 2. Extract and write metadata std::vector<FileInfo> fileInfos; for (const std::string& inputFilename : inputFilenames) { uint64_t fileSize = getFileSize(inputFilename); fileInfos.push_back({fs::path(inputFilename).filename().string(), fileSize}); // Write filename (size + content) uint32_t nameLength = static_cast<uint32_t>(fileInfos.back().name.length()); outputFile.write(reinterpret_cast<const char*>(&nameLength), sizeof(nameLength)); outputFile.write(fileInfos.back().name.c_str(), nameLength); // Write file size outputFile.write(reinterpret_cast<const char*>(&fileInfos.back().size), sizeof(fileInfos.back().size)); } // 3. Concatenate file contents for (const std::string& inputFilename : inputFilenames) { std::ifstream inputFile(inputFilename, std::ios::binary); if (!inputFile.is_open()) { std::cerr << "Error opening input file: " << inputFilename << std::endl; outputFile.close(); return 1; } char buffer[4096]; // Using a buffer for efficiency while (inputFile.read(buffer, sizeof(buffer))) { outputFile.write(buffer, inputFile.gcount()); } inputFile.close(); std::cout << "Concatenated: " << inputFilename << std::endl; } outputFile.close(); std::cout << "Successfully concatenated files into: " << outputFilename << std::endl; return 0; }

Dold text

Du får gärna berätta vad möjligen även är segt med denna LLM-lösning kontra kompressionsmjukvarors sätt att slå samman filer. I det sistnämnda tänker jag att de vill tugga igenom varje fil för att kunna komprimera vid behov vilket kanske är en delorsak till varför de är segare än om vi redan vet längden på varje fil och inte vill komprimera dem?

Mvh,
WKF.

Visa signatur

(V)ulnerabilities
(I)n
(B)asically
(E)verything
Programming

Permalänk
Medlem
Skrivet av WebbkodsFrilansaren:

Jag funderade ut pseudokod och bad sedan Gemini Flash 2.0. Thinking att ge något som i princip concatenate filer men först med metadata för att sedan också kunna splitta ut dessa. För att inte tugga igenom varje fil bara för att få veta dess längd så bad jag den att nyttja OS:et filsystem för det borde ju redan sitta på den informationen såsom längd i bytes, filnamn och filändelse.

Den hopsatta filen - om C++-koden kompilerar (vilket den troligen aldrig kan göra från LLM:er!) - ska då innehålla metadata om filnamn, bytes-längd vilket då kan användas som avskiljare när den skriver ut de separata filerna igen. Först tänkte jag på att föra in extra bytes som avskiljare mellan filerna men då finns risken att samma bytes redan används i någon fil som då skulle avskilja vid fel ställe och därmed skapa korrupta filer. Så metadata i början av den stora filen bör lösa det problemet.

Den använder en Struct som innehåller filnamn och bytes-längd och sedan nyttjas en vektor för att lagra metadata av den typen av Struct. Programmet ska köras med att skicka minst 3 argument till den kompilerade "konsolfilen.exe" via char* argv.

Kika gärna och se om det skapar inspiration. Förhoppningsvis ligger prestandan på O(n) där n är antalet filer som ska slås ihop (jag kan ej yttra mig om huruvida den kan innehålla minnesläckor eller ej):

// WARNING: This was written Gemini Flash 2.0 Thinking after prompt from a Junior Web Developer // This means the code is probably worse than code written by someone who has never seen a line of code before! #include <iostream> #include <fstream> #include <vector> #include <string> #include <filesystem> // Requires C++17 #ifdef _WIN32 #include <windows.h> #else #include <sys/stat.h> #endif namespace fs = std::filesystem; // Structure to hold file metadata struct FileInfo { std::string name; uint64_t size; }; // Function to get the size of a file uint64_t getFileSize(const std::string& filename) { #ifdef _WIN32 WIN32_FILE_ATTRIBUTE_DATA fileData; if (GetFileAttributesEx(filename.c_str(), GetFileExInfoStandard, &fileData)) { return (static_cast<uint64_t>(fileData.nFileSizeHigh) << 32) | fileData.nFileSizeLow; } return 0; // Error case #else struct stat stat_buf; int rc = stat(filename.c_str(), &stat_buf); return rc == 0 ? stat_buf.st_size : 0; // Error case #endif } int main(int argc, char* argv) { if (argc < 3) { std::cerr << "Usage: " << argv[0] << " <output_file> <input_file1> [input_file2 ...]" << std::endl; return 1; } std::string outputFilename = argv[1]; std::vector<std::string> inputFilenames; for (int i = 2; i < argc; ++i) { inputFilenames.push_back(argv[i]); } std::ofstream outputFile(outputFilename, std::ios::binary); if (!outputFile.is_open()) { std::cerr << "Error opening output file: " << outputFilename << std::endl; return 1; } // 1. Write the number of files uint32_t numFiles = static_cast<uint32_t>(inputFilenames.size()); outputFile.write(reinterpret_cast<const char*>(&numFiles), sizeof(numFiles)); // 2. Extract and write metadata std::vector<FileInfo> fileInfos; for (const std::string& inputFilename : inputFilenames) { uint64_t fileSize = getFileSize(inputFilename); fileInfos.push_back({fs::path(inputFilename).filename().string(), fileSize}); // Write filename (size + content) uint32_t nameLength = static_cast<uint32_t>(fileInfos.back().name.length()); outputFile.write(reinterpret_cast<const char*>(&nameLength), sizeof(nameLength)); outputFile.write(fileInfos.back().name.c_str(), nameLength); // Write file size outputFile.write(reinterpret_cast<const char*>(&fileInfos.back().size), sizeof(fileInfos.back().size)); } // 3. Concatenate file contents for (const std::string& inputFilename : inputFilenames) { std::ifstream inputFile(inputFilename, std::ios::binary); if (!inputFile.is_open()) { std::cerr << "Error opening input file: " << inputFilename << std::endl; outputFile.close(); return 1; } char buffer[4096]; // Using a buffer for efficiency while (inputFile.read(buffer, sizeof(buffer))) { outputFile.write(buffer, inputFile.gcount()); } inputFile.close(); std::cout << "Concatenated: " << inputFilename << std::endl; } outputFile.close(); std::cout << "Successfully concatenated files into: " << outputFilename << std::endl; return 0; }

Dold text

Du får gärna berätta vad möjligen även är segt med denna LLM-lösning kontra kompressionsmjukvarors sätt att slå samman filer. I det sistnämnda tänker jag att de vill tugga igenom varje fil för att kunna komprimera vid behov vilket kanske är en delorsak till varför de är segare än om vi redan vet längden på varje fil och inte vill komprimera dem?

Mvh,
WKF.

Skulle inte säga att det är värt att koda det själv av två skäl. Dels för att resultatet blir ett eget filformat som inget annat program kan hantera och dels för att en bugg skulle kunna göra filerna oläsbara och att det kanske upptäcks långt senare.

C# löser detta snyggt i ramverket med System.IO.Compression där man även kan lägga till filer i existerande arkiv. Där är fördelen att funktionaliteten redan finns och är vältestad. Dock klassas det nog som konsultkod för @klk

Visa signatur

Ryzen 7 7800X3D | ASUS TUF Gaming B650-Plus WIFI | Kingston 32GB (2x16GB) DDR5 6GT/s CL30 FURY Beast | Kingston Fury Renegade M.2 NVMe SSD Gen 4 2TB | MSI RTX 4060 8GB | Fractal Design Define S | MSI MPG A850G 850W | Thermalright Phantom Spirit 120 SE | Windows 11 Pro | AOC 27" AGON AG276QZD2 OLED QHD 240 Hz

Permalänk
Medlem
Skrivet av klk:

Det tolkar jag som att även du tycker det är störande med en nitisk kompilator?

Nja, nitisk kompilator är väl bra, om man skriver rätt så klagar den ju inte.
Det var aningen överväldigande inledningsvis om något.

Skrivet av klk:

Använder exempelvis inte ens "private" för medlemsvariabler just av denna orsak.

Jag använder private-scoping i lib:ar för att koden blir självförklarande utan dokumentation för användaren och jag använder det i binärer för att exempelvis lättare kunna "scanna"( ) och ignorera metoder som jag enbart använder inom objekten.

Permalänk
Medlem
Skrivet av Xeonist:

Äh, det fixar du själv, du har ju flertalet gånger berättat hur överlägsen du är alla oss andra.

Tror inte jag sagt att jag är överlägsen, däremot har jag nämnt att C++ öppnar möjligheter
Med det sagt så
Har faktiskt börjat på en lösning. Vart förvånad hur lite som fanns om något sådant här. Sökte mer igår men hittade inget så har börjat.
Det är inte svårt på annat sätt att man behöver ha logik för att plocka bort filer internt och då är det troligen lättast att kopiera filer från en fil med många filer till en ny fil och endast välja de som inte skall plockas bort. När alla skrivits över raderas den gamla och den nya får samma namn.
Filen behöver en del i sig också som är som en slags beskrivning över vilka filer den innehåller och var (offset positioner)

Kan nog posta upp koden när den är klar

Permalänk
Medlem
Skrivet av Joppis:

Skulle inte säga att det är värt att koda det själv av två skäl. Dels för att resultatet blir ett eget filformat som inget annat program kan hantera och dels för att en bugg skulle kunna göra filerna oläsbara och att det kanske upptäcks långt senare.

C# löser detta snyggt i ramverket med System.IO.Compression där man även kan lägga till filer i existerande arkiv. Där är fördelen att funktionaliteten redan finns och är vältestad. Dock klassas det nog som konsultkod för @klk

Ett problem är att jag inte har tillgång till C#, det hela körs på noder i molnet och det är framförallt snabbhet som är mycket viktigt.

Kör man hårddiskar som är långsammare vid läs och skrivning kan säkert kompression göra en lösning snabbare men gissningsvis är det bättre att inte komprimera om ssd'er används. Kompression är jag också lite orolig för att man behöver läsa in hela filen i minnet eller om det är något sådant hinder. En del filer kan bli så stora att de inte får plats i minnet.

Permalänk
Medlem
Skrivet av WebbkodsFrilansaren:

Jag funderade ut pseudokod och bad sedan Gemini Flash 2.0.

Kort kommentar om olika LLMer (osäker på vad man kallar det när det gäller olika system). Har du testat grok? Uppfattar själv grok som bäst hittills, i alla fall när det kommer till udda lösningar.
En enkel funktionalitet jag önskar de snart lagt till är att man slipper skriva in vilken stil de skall skriva ut kod med, att jag skulle kunna konfigurera så den minns.
Nu får jag för varje gång man vill ha exempel kod skriv att jag vill ha "allman" style och vilka prefix på variablerna som önskas. Det blir självklart en del pill ändå men bättre än när den får göra som den vill

Permalänk
Medlem
Skrivet av klk:

Använder exempelvis inte ens "private" för medlemsvariabler just av denna orsak. Vill man testa eller har buggar där man måste skriva om lite kod för att se och förstå hur bäst buggen löses så är det jobbigt med dessa hinder. Har flera gånger svurit över extern kod där de satt saker som private men som man skulle använda sig av.

OK, inkapsling är för n00bs och försvårar bara debugging.

Även arkitektur försvårar debugging och är ett onödigt hinder. Låt oss skriva kod där alla lager interagerar med varandra direkt. Finns inget motargument egentligen.

Men sånt fattar bara den som är tillräckligt erfaaaarnaaaaa..... *luktar på min egen fis*

Permalänk
Skrivet av klk:

Använder exempelvis inte ens "private" för medlemsvariabler just av denna orsak. Vill man testa eller har buggar där man måste skriva om lite kod för att se och förstå hur bäst buggen löses så är det jobbigt med dessa hinder. Har flera gånger svurit över extern kod där de satt saker som private men som man skulle använda sig av.

Utvecklare får bara lära sig att inte accessa medlemsvariabler i färdig kod.

Det kanske funkar när du skriver all kod själv, men om du exponerar din privates kommer folk att använda dem. Lite som Hyrum's law (With a sufficient number of users of an API, it does not matter what you promise in the contract: all observable behaviors of your system will be depended on by somebody.) Detta kommer göra det omöjligt för dig att faktorisera om koden utan att göra "breaking changes" i koden som ärver från dina klasser. Det ingår väl ändå i god kodhygien att inte medvetet göra saker som kommer ställa till det senare?

Permalänk
Medlem
Skrivet av Ingetledigtnamn:

Det kanske funkar när du skriver all kod själv, men om du exponerar din privates kommer folk att använda dem. Lite som Hyrum's law (With a sufficient number of users of an API, it does not matter what you promise in the contract: all observable behaviors of your system will be depended on by somebody.) Detta kommer göra det omöjligt för dig att faktorisera om koden utan att göra "breaking changes" i koden som ärver från dina klasser. Det ingår väl ändå i god kodhygien att inte medvetet göra saker som kommer ställa till det senare?

Riktigt att det inte går att släppa in nybörjare i kod som kräver en del förkunskap men det finns andra sätt och lösa problemet än att blockera.

Man kan exempelvis dela in kod i nivåer, och på så sätt förhindra programmerare att röra i delar som man behöver mer kunskap i. Vet i alla fall ett gigantiskt företag som gör så. Varit med och införa den tekniken på platser jag jobbat.

Syftet med det är att programmerare i olika nivåer skall kunna jobba ihop och att nya utvecklare så snabbt som möjligt skall ha möjlighet att lära sig. De måste få möjlighet att leka och testa samt skriva mycket kod.

Man kan då exempelvis ha 4 nivåer, en som är djup (kalla den för generell kod eller för att köra engelska "general, core"). Kod där har regler. Där jag jobbar får den koden endast ha beroende till vad som är standard i C++.
Nivån över det kan vara kod som är generell för företaget. Kod som skall kunna användas i alla applikationer som produceras i företaget.
Nästa nivå är kod för respektive targets (target kommer från CMake), det är kod som är specifik för just den applikationen de ligger i.
Sista nivån skulle kunna heta play. Här kan man leka och göra lite vad man vill

Nya utvecklare kan då gå direkt in i play och leka bäst de vill för att börja känna på koden.

Olika kodstilar kan användas för att det lätt skall gå och identifiera vad det är för typ av kod

Permalänk
Medlem
Skrivet av Perkoff:

OK, inkapsling är för n00bs och försvårar bara debugging.

Sant

Men principen används även om tekniken för att använda är olika. Förr kallade en del detta för extreme programmering.

Vad det handlar om är att programmerare inte vet vad de skall göra på första försöket, när de börjar koda så lär de sig hur de borde ha gjort. Applikationer är så komplexa så ingen kan sitta och fundera ut den perfekta koden.

Om man vet om detta kan man preparera för det, exempelvis veta innan att det första som görs skall slängas bort. Endast till för att lära sig och testa olika lösningar inför att göra den verkliga lösningen. Då är det "jobbigt" att skriva perfekt kod. Det blir någon form av prototyp

Eller så skrivs kod så att den går att ändra och man har andra tekniker för att förhindra att kod skrivs sönder.

Att kräva att nya utvecklare eller kanske till och med utvecklare med en del års erfarenhet skall klara att skriva kvalitetskod är mycket begärt, och idag med alla konstiga regler för att förhindra att göra fel så lär de sig aldrig.