Varför är dessa Java projekt så avancerat skrivet?

Permalänk
Medlem
Skrivet av heretic16:

Jag skriver sällan bibliotek. Mest bara applikationer. Men det händer att jag skriver bibliotek och då gör jag det i MATLAB och C. Bara funktioner. Riktigt strukturerat och rent. Inget "Jaha...hur har han tänkt här???". Mest bara "Okej, funktionen anropar...".

Jag har full förståelse att OOP är riktigt bra om man skriver bibliotek. Men detta kan ju lösas med vanlig funktionsprogrammering också.

Jag förespråkar enbart interfaces, inte OOP. Inget fan av OOP alls personligen, utan skriver nästan exklusivt i (hybrid)funktionella språk som Haskell och Rust. I Haskell heter det "type class" och i Rust heter det "trait", men i praktiken fyller de ungefär samma funktion som "interface" i Java, fast bättre.

Exempel på några bra typklasser som låter dig lösa problem generellt och med mindre kod: Ord, Eq, Num, Functor, Monad, Monoid, Traversable; och några traits: Default, From, Clone, Deref.

Självklart kan du skriva program utan polymorfism i språk som C också, men jämför man med Rust är det ofta svårare och jobbigare att skriva högpresterande kod, främst av anledningen att du inte kan återanvända existerande datastrukturer för dina egna typer. Vill du ha ett B-träd där varje element är din egna strukt "Foo"? I Rust är det bara att implementera traitet "Ord" på "Foo". I C måste du omimplementera hela B-trädet just för din typ, annars tvingas du lägga datan bakom void-pekare vilket gör minneshanteringen mer komplex och kan skada prestandan rejält beroende på hur liten "Foo" är.

Visa signatur

Arbets- / Spelstation: Arch Linux - Ryzen 5 3600 - RX 7900 XT - 32G DDR4
Server: Arch Linux - Core i5-10400F - 16G DDR4

Permalänk
Skrivet av zaibuf:

Kan ta ett exempel. Halvvägs in i ett projekt blev vi tvungen att byta ut hela datalagret i en applikation från en ORM till en annan. Hade vi inte kodat hela datalagret abstrakt bakom interfaces så hade det varit ett rent helvete att byta ut, då applikationslagret arbetade mot datalagret. Men eftersom applikationslagret inte hade en aning om vad datalagret gjorde då ända kopplingen mellan dessa var ett interface med några metoder som kontrakt, så blev det att vi successivt kunde byta ut delar av det tills att allt var klart. Detta helt utan påverkan i affärs eller presentationslagret av applikationen.

Tänk även på att då du arbetar med skarpa projekt kan krav ändras rätt frekvent, kanske släpper en konkurrent på marknaden en ny feature som du behöver lägga till också. Då kan du inte ha massa tightly coupled kod som kräver att du skriver om 1000 rader kod för att byta ut en feature.

Handlar ju också om skalning. Kanske räcker det med att betala för mer memory för din cachingservice, istället för att behöva höja planen för hela applikationen? Det är mer lönsamt i längden att dela upp det i microservices. Sen är det också som jag sa tidigare, enklare att släppa kontinuerligt med features, gör man releases flera gånger i veckan så kan man inte sitta på en monolit.

Nu vet jag inte vad metoden har för syfte, men låter som du vill använda generics och då ha en implemenation där du sätter datatypen vid anropet. Sen kan du sätta upp repositoryt via constructor injection. Nu är detta i C#.

public abstract class LogBase { } public class DataLog : LogBase { } public class UserLog : LogBase { } public interface ILoggingProvider<in T> where T : LogBase { void AddSelect(); } public class LoggingProvider<T> : ILoggingProvider<T> where T : LogBase { private readonly IRepository<T> repository; public LoggingProvider(IRepository<T> repository) { this.repository = repository; } public void AddSelect() { IEnumerable<T> logs = repository.FindAll(); // Do something... } }

Så kan du i din dependency injection service sätta upp det som exempelvis:

// Abstraction / Implementation services.AddTransient(typeof(IRepository<,>), typeof(Repository<,>)); services.AddTransient(typeof(ILoggingProvider<,>), typeof(LoggingProvider<,>));

Jag vet vad ORM är, men kan ej associera till vad du försöker beskriva. Känner ej igen händerlserna.

Jag skulle använda OOP om jag utför spelutveckling då varje komponent är ett objekt.
Jag skulle övrigt försöka hålla mig till funktioner när det handlar om att utnyttja funktionaliteter så som hemsidor osv.

Permalänk
Medlem
Skrivet av heretic16:

Jag vet vad ORM är, men kan ej associera till vad du försöker beskriva. Känner ej igen händerlserna.

Jag skulle använda OOP om jag utför spelutveckling då varje komponent är ett objekt.
Jag skulle övrigt försöka hålla mig till funktioner när det handlar om att utnyttja funktionaliteter så som hemsidor osv.

Då låter det snarare som om du saknar erfarenhet av att arbeta i mer komplexa affärsapplikationer. Vilket då även gör det svårare att relatera till varför man gör på vissa sätt. Objekt används för att kapsla in relaterad logik i små komponenter och för att få starktypad data.

Inom webb använder du ju komponenter hela tiden. Du vill inte repetera kod och logik på flera ställen.

Finns ju en orsak till varför TS är att föredra framför JavaScript vid större projekt.

Permalänk
Skrivet av zaibuf:

Då låter det snarare som om du saknar erfarenhet av att arbeta i mer komplexa affärsapplikationer. Vilket då även gör det svårare att relatera till varför man gör på vissa sätt. Objekt används för att kapsla in relaterad logik i små komponenter och för att få starktypad data.

Inom webb använder du ju komponenter hela tiden. Du vill inte repetera kod och logik på flera ställen.

Finns ju en orsak till varför TS är att föredra framför JavaScript vid större projekt.

Som jag sade. Jag är bara hobbyprogrammrare som använder lite kodning på jobbet. Mest bara för att underlätta egna sysslor och automatisera. Det är riktiga saker och inga "små skript". Nu sitter jag och gör ett projekt som hanterar databaser + grafer och man ska kunna administrera dessa. Har inte använt mig av interface än. Kanske kommer, få se...

Jag har lyssnat rätt mycket på webbutvecklare och dom som har lång erfarenhet i mjukvaruutveckling och dom hävdar att när man programmerar så är det viktigare att skriva lite kod som är enkel, än avancerat och proffesionellt. Dels för att deras kunder betalar inte för proffisionell kod, utan för att lösa problemet.

Jag repeterar aldrig logik eller samma kod på flera ställen. Därför använder jag funktioner. Inbland har jag en klass som jag har min funktionssamling som jag sedan plockar ut vissa funktioner. Då använder jag interface.

Jag använder Java med Spring. Jag tycker Java är ett tråkigt språk. Men med tanke på att Java är grymt robust och alltid fungerar så kör jag på det. Speciellt Vaadin ramverket gillar jag verkligen. Då slipper man HTML, CSS, JavaScript, PHP osv.

Permalänk
Skrivet av heretic16:

Känner igen mig. Jag tycker att det är vanligt att många projekt använder sig av olika metoder för att skriva projekt. Man står mest bara som ett frågetecken och undrar hur man använder det.

Jag har hört talas som testning, men har aldrig riktigt förstått hur man använder det.

Hur skulle du avgöra Pi4J på GitHub? Är det rörigt projekt eller är det utmärkt strukturerat så vem som helst kan hoppa in och börja bygga?
Just nu så vet jag att det är mest bara 2 personer som har byggt på Pi4J. Robert Savage och Frank Deporte.

Hobbyprogrammerare, men jag brukar använda detta i jobbet också.

Vet inte vad testning är.

Exakt. Jag har svårt att förstå Pi4J. Dels för att jag har programmerat hårdvara förut i C och då är det bara funktioner som gäller. Funktioner och structs. Inge mer. Superekelt. Men Pi4J verkar tro att desto mer avancerat det blir, desto bättre blir det.

I hårdvara så har du X antal ingångar och Y antal utgångar. Behövs OOP här om alla ut- och ingångar är kända?
Jag talade med en duktig C programmerare och han sade att orsaken varför C används inom hårdvara har med att C++ är för överkurs och kostar mer. Han menade att det räker bara med funktioner för att få jobbet gjort.

Pi4J använder Java + JNI för att tala med C-kod som vidare talar med hårdvaran. Varför OOP här då?

Ingen ”behöver” OOP, det är bara ett annat sätt att strukturera koden. Vad som är mest lämpligt är en kombination av komplexitet, språk och vad utvecklare teamet är komfortabla i. Alla problem kan lösas med alla språk.

Men i verkligheten finns det ofta ett ganska givet svar. För kod som ligger nära hårdvara är det förmodligen mest lämpligt att använda C eftersom man väldigt korrekt kan modellera verkligheten. Hårdvaruportar att läsa/skriva ifrån representeras ex säkert bäst bara som en pekare (ok, nu gissar jag bara). Men ju ”högre” upp i stacken du kommer desto mindre viktigt blir denna direkthet mot hårdvaran och istället är det viktigare att koden är underhållsbar, lätt att testa, lätt att isolera mm och det är här ganska tydligt att objektorienterade språk har vunnit.

Jag har inte tittat på projekten du pekar ut men jag antar att de erbjuder Java-access till någonting annat? Det låter så spontant rimligt att det finns mer objekt involverade för målgruppen är också mer vana vid det. Jag skulle nog känna mig mer hemma i den kodbasen, än en som var strikt funktionell.

Fö, kopplat till OOP så är jag personligen inget jättefan av arv. Eller, min syn på det är:

Interface = det kontakt som ska gälla. Ligger logiskt nära en header-fil i C
Arv = en ren implementationsdetalj för att öka koddelning

De bästa kodbaserna är imo där jag endast kodar mot / länkar mot interface. Om sen makarna till koden velat göra det med 10 nivåer av arv (hej Spring!) så är väl det ok, men minimera hur mycket av det jag behöver se tack.

Testning, väldigt kort, handlar om att skriva kod som testar annan kod. Det kan låta onödigt eller larvigt som ensam utvecklare, men är i mitt tycke ett obligatoriskt inslag i modern utveckling. Små projekt kan en ensam utvecklare ha helt i huvudet och kan ändra hej vilt, men det är en premiss som är helt omöjlig att upprätthålla i stora projekt. Dessutom är man inte smart nog att faktiskt ha alla detaljer i huvudet. Men hur man skriver bra effektiv testning och hur man bakar in det till ett flöde med automatisk accepttestning, releaser mm är en helt annat diskussion.

Permalänk
Hedersmedlem

Hela den här diskussionen känns extremt diffus och ospecifik. Jag kan nog hålla med generellt om att OOP för OOP:s skull är något man gärna undviker så långt om möjligt, men jag tror att vi skulle kunna få en mer produktiv diskussion om vi istället tittade på någon specifik kodsnutt, eller någon specifik klass, och började prata lite om hur denna skulle se ut olika beroende på programmeringsparadigm.

Permalänk
Skrivet av pv2b:

Hela den här diskussionen känns extremt diffus och ospecifik. Jag kan nog hålla med generellt om att OOP för OOP:s skull är något man gärna undviker så långt om möjligt, men jag tror att vi skulle kunna få en mer produktiv diskussion om vi istället tittade på någon specifik kodsnutt, eller någon specifik klass, och började prata lite om hur denna skulle se ut olika beroende på programmeringsparadigm.

Jag hänvisar till OjAlgo och Pi4J.
Dom är bra bibliotek. Inge fel på dom. OjAlgo är det bästa Javabibliotek när det kommer till matematil. Tro mig, jag har testat alla dom bästa Javabiblioteken för matematik. OjAlgo är snabbast och erbjuder mest funktioner. jBlas, Apache Commons Math, EJML är inte ens i närheten.

Men jag förstår dom inte. Vart ska man börja i sådant projekt? Det är ju hundratals java-filer.
Finns absolut ingen "karta" över hur tänket är i projektet.

Permalänk
Medlem

Men för att dra något ur luften bara, säg att du ska göra en simpel bankapplikation där du har olika slags kundtyper, och kunderna har olika slags konton. Gör man det där i Java utan OOP så blir det riktigt äckligt skulle jag säga men jag blir gärna motbevisad.

Enligt OOP så hade man skapat nån abstrakt klass eller interface att modellera specifika kundtyper ifrån och olika kontotyper likaså. Annars måste man ju ha en miljon olika datastrukturer för att hålla alla olika variationer?

Blir gärna motbevisad i hur man skulle göra det här simpla exemplet i Java utan att det blev rikigt äckligt. Jag kanske är för djupt inne i OOP för att se något annat sätt.

Permalänk
Datavetare

Nu är det ganska många år sedan jag senaste knackade Java-kod professionellt och har skrivit minimalt med Java frivilligt, så min bild av "bra Java" kanske inte är helt aktuellt.

Kikade lite på Pi4J. Tror att från ett rent Java-perspektiv gör man saker ungefär som förväntat. Problemet är att huvudmålet med all kod är i slutändan att den ska lösa en uppgift och sättet Pi4J "löser" uppgiften är allt annat än optimal givet att vad man normalt vill få ut av den här typen av bibliotek.

Några axplock på problem

  • I botten använder man wiringPi, ett C bibliotek som primärt är tänkt för att ge folk från Arduino-världen något som ser ungefär lika ut på en RPi. Problemet här är: Arduino är tänkt för mikrokontrollers som sitter i en tight loop och gör något extremt specifikt, RPi snurrar på en multi-user OS där man inte vill köra busy-wait. Pi4J "löser" detta med att skapa trådpooler. Rätt sätt: låt Linux-kärnan polla HW m.h.a. interrupt (vilket med rätt val av GPIO-bibliotek är fullt möjligt då Linux-kärnan stödjer detta)

  • Man har så många abstraktionslager som jag har lite svårt att se vad de tillför just då man bygger allt på ett abstraktionslager (wiringPi) som hanterar de mesta av skillnaderna i HW. Enda som egentligen skiljer är smådetaljer i pinout (och även det lär skilja rätt lite då de flesta kort man stödjer är RPi kompatibla).

  • Ignorerar man ovan så är ändå en av huvudfunktionerna i ett GPIO bibliotek att ge effektiv och låglatens access till HW-pinnarna, att då blanda in flera OS-trådar i ett icke realtids-OS är en rejäl anti-pattern (och att ovanpå det köra en miljö med tracing-GC gör inte saken bättre, men det är ett litet problem i detta fall)

Sedan är vissa abstraktioner lite märkliga, ser inte riktigt vad GpioPinPwm tillför när man också har GpioPinPwmOutput. Inte så att PWM på något sätt är vettigt för input och även GpioPinPwmOutput är inte interface (man skiljer på HW PWM och software PWM, vilket är vettigt).

Interface GpioPinDigitalOutput har allt för mycket. Varför finns det blink() och pulse() metoder? De är väl ändå en service som kan utföras på en digital utgående pinne, inte en del av vad en digital pinne är?

Pi4J är mer ett ramverk än ett bibliotek, vilket för vad man försöker lösa känns rätt onödigt. Känns också som det mer är ett projekt för författaren av koden för att denne ska få testa på så många olika Java och RPi finesser som möjligt än ett vettig bibliotek för andra att använda... Exempel på en bra abstraktion av GPIO är t.ex. denna (långt mindre API jämfört med Pi4J även om tittar enbart på GPIO, ändå får det in långt fler användbara koncept som HW-interrupt utan trådar och läsa/skiva grupper av pinnar atomärt).

Angående OOP. Finns absolut användningsområden för OOP, men det är bara en teknik bland många och få saker inom programmering lär användas på fel ställe som OOP... Om man inte har nytta av tillstånd så är OOP fel val, så är extremt osannolikt att t.ex. affärslogik passar bra till OOP då själva logiken brukar vara helt tillståndslös. Samma sak gäller moderna "mikroservices" med REST APIer. Finns självklart undantag, det finns alltid.

OOP är ofta en väldigt dålig idé i multitrådade program. Detta då effektiv och korrekt synkronisering av data kräver att man explicit ser hur data representeras, vilket en av hörnsterna i OOP förhindrar (Rust är en av få språk som fått detta riktigt rätt, data och beteende är helt separerat där och språket garanterar att data endera är read-only eller bara kan nås från en enda tråd).

Ofta är det bara två av ovan man vill ha, polymorfism och abstraktion. Men dessa har i sig inget med OOP att göra, går hur bra som helst att använda båda de koncepten helt fristående från OOP.

Att allt måste finnas i kontext av en klass är en kraftig designmiss i Java. Hindrar inte att man använder icke-OOP teknik, men det ser lite yxigt ut ibland. Sedan finns ju andra språk som fungerar ihop med Java-plattformen, som Kotlin, vilket visar att problemet inte alls är fundamentalt i Java (i alla fall inte i plattformen Java).

Visa signatur

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

Permalänk
Skrivet av Xenofonus:

Men för att dra något ur luften bara, säg att du ska göra en simpel bankapplikation där du har olika slags kundtyper, och kunderna har olika slags konton. Gör man det där i Java utan OOP så blir det riktigt äckligt skulle jag säga men jag blir gärna motbevisad.

Enligt OOP så hade man skapat nån abstrakt klass eller interface att modellera specifika kundtyper ifrån och olika kontotyper likaså. Annars måste man ju ha en miljon olika datastrukturer för att hålla alla olika variationer?

Blir gärna motbevisad i hur man skulle göra det här simpla exemplet i Java utan att det blev rikigt äckligt. Jag kanske är för djupt inne i OOP för att se något annat sätt.

Jag skulle nog säga att Java + Spring Boot + JPA är riktigt bra om man vill göra databaser för varje kund Så jag hade kört på det. Det blir ju lite OOP, men inte mycket.

Vill du ha ett exempel på Crud i Java?
https://github.com/alejandro-du/crudui/tree/master/demo/src/m...

Snyggt, elegant, mimialt med kod och man behöver bara specifiera entity för att skapa databasen. Alltså en klass. Bara en!

Så här ser databashantering ut i Java med Spring JPA.

Databasen:

@Entity @Getter @Setter public class CalibrationLogg { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long CID; // Comment for these calibration @NotNull private String comment; // y = S*AI + B private float SAI0; private float BAI0; private float SAI1; private float BAI1; private float SAI2; private float BAI2; private float SAI3; private float BAI3; }

Hur vi kommer åt databasen. Här kan man alltså lägga till getters och setters för att hitta rätt rad i databasen.
Exempel på en metod. Måste heta findByX, där X är namnet på fältet i entity-klassen.

public interface CalibrationLoggRepository extends JpaRepository<CalibrationLogg, Long>{ CalibrationLogg findByComment(String myComment); // Exempel }

Eller så kan man anropa databasen igenom att skriva detta fält.

@Autowired private CalibrationLoggRepository calibrationLoggRepository;

och sedan anropar man objektet "calibrationLoggRepository" så här:

List<CalibrationLogg> helaDatabasen = calibrationLoggRepository.findAll(); List<CalibrationLogg> allaRaderSomHarRadernaHejIDatabasen = calibrationLoggRepository.findByComment("Hej");

Supersmidigt i Spring Boot. Älskar verkligen detta. Java må vara tråkigt och stort, men så fort man börjar använda Spring Boot så blir livet enklare. Nu kan vi komma åt databsen och skriva till den. Inge SQL eller något sånt där.

Permalänk
Skrivet av Yoshman:

Nu är det ganska många år sedan jag senaste knackade Java-kod professionellt och har skrivit minimalt med Java frivilligt, så min bild av "bra Java" kanske inte är helt aktuellt.

Kikade lite på Pi4J. Tror att från ett rent Java-perspektiv gör man saker ungefär som förväntat. Problemet är att huvudmålet med all kod är i slutändan att den ska lösa en uppgift och sättet Pi4J "löser" uppgiften är allt annat än optimal givet att vad man normalt vill få ut av den här typen av bibliotek.

Några axplock på problem

  • I botten använder man wiringPi, ett C bibliotek som primärt är tänkt för att ge folk från Arduino-världen något som ser ungefär lika ut på en RPi. Problemet här är: Arduino är tänkt för mikrokontrollers som sitter i en tight loop och gör något extremt specifikt, RPi snurrar på en multi-user OS där man inte vill köra busy-wait. Pi4J "löser" detta med att skapa trådpooler. Rätt sätt: låt Linux-kärnan polla HW m.h.a. interrupt (vilket med rätt val av GPIO-bibliotek är fullt möjligt då Linux-kärnan stödjer detta)

  • Man har så många abstraktionslager som jag har lite svårt att se vad de tillför just då man bygger allt på ett abstraktionslager (wiringPi) som hanterar de mesta av skillnaderna i HW. Enda som egentligen skiljer är smådetaljer i pinout (och även det lär skilja rätt lite då de flesta kort man stödjer är RPi kompatibla).

  • Ignorerar man ovan så är ändå en av huvudfunktionerna i ett GPIO bibliotek att ge effektiv och låglatens access till HW-pinnarna, att då blanda in flera OS-trådar i ett icke realtids-OS är en rejäl anti-pattern (och att ovanpå det köra en miljö med tracing-GC gör inte saken bättre, men det är ett litet problem i detta fall)

Sedan är vissa abstraktioner lite märkliga, ser inte riktigt vad GpioPinPwm tillför när man också har GpioPinPwmOutput. Inte så att PWM på något sätt är vettigt för input och även GpioPinPwmOutput är inte interface (man skiljer på HW PWM och software PWM, vilket är vettigt).

Interface GpioPinDigitalOutput har allt för mycket. Varför finns det blink() och pulse() metoder? De är väl ändå en service som kan utföras på en digital utgående pinne, inte en del av vad en digital pinne är?

Pi4J är mer ett ramverk än ett bibliotek, vilket för vad man försöker lösa känns rätt onödigt. Känns också som det mer är ett projekt för författaren av koden för att denne ska få testa på så många olika Java och RPi finesser som möjligt än ett vettig bibliotek för andra att använda... Exempel på en bra abstraktion av GPIO är t.ex. denna (långt mindre API jämfört med Pi4J även om tittar enbart på GPIO, ändå får det in långt fler användbara koncept som HW-interrupt utan trådar och läsa/skiva grupper av pinnar atomärt).

Angående OOP. Finns absolut användningsområden för OOP, men det är bara en teknik bland många och få saker inom programmering lär användas på fel ställe som OOP... Om man inte har nytta av tillstånd så är OOP fel val, så är extremt osannolikt att t.ex. affärslogik passar bra till OOP då själva logiken brukar vara helt tillståndslös. Samma sak gäller moderna "mikroservices" med REST APIer. Finns självklart undantag, det finns alltid.

OOP är ofta en väldigt dålig idé i multitrådade program. Detta då effektiv och korrekt synkronisering av data kräver att man explicit ser hur data representeras, vilket en av hörnsterna i OOP förhindrar (Rust är en av få språk som fått detta riktigt rätt, data och beteende är helt separerat där och språket garanterar att data endera är read-only eller bara kan nås från en enda tråd).
https://miro.medium.com/max/2114/1*8BSPw3u9qBdqJxrEfrN9JA.png
Ofta är det bara två av ovan man vill ha, polymorfism och abstraktion. Men dessa har i sig inget med OOP att göra, går hur bra som helst att använda båda de koncepten helt fristående från OOP.

Att allt måste finnas i kontext av en klass är en kraftig designmiss i Java. Hindrar inte att man använder icke-OOP teknik, men det ser lite yxigt ut ibland. Sedan finns ju andra språk som fungerar ihop med Java-plattformen, som Kotlin, vilket visar att problemet inte alls är fundamentalt i Java (i alla fall inte i plattformen Java).

Exakt. Jag har svårt att tro att OOP ska göra Pi4J mycket bättre. För jag vet att allt handlar om att göra så att Pi4J använder WiringPi (Nya Pi4J V2.0 kommer använda Pigpio då WiringPi utvecklas inte längre på grund utav utvecklarens hälsokäl) och WiringPi är rent C.

Jag anser att man kan lika gärna göra en "hög med funktioner" i Pi4J och ändå få det mer strukturerat.

Permalänk
Medlem
Skrivet av heretic16:

Exakt. Jag har svårt att tro att OOP ska göra Pi4J mycket bättre. För jag vet att allt handlar om att göra så att Pi4J använder WiringPi (Nya Pi4J V2.0 kommer använda Pigpio då WiringPi utvecklas inte längre på grund utav utvecklarens hälsokäl) och WiringPi är rent C.

Jag anser att man kan lika gärna göra en "hög med funktioner" i Pi4J och ändå få det mer strukturerat.

Du kan säkert skriva en egen java-wrapper av WiringPi om du vill som ser ut som du vill ha den. Jag tror man ska lägga mindre tid på att försöka förstå hur personen tänkte än hur koden ser ut om om den är användbar. Kanske personen som skrev koden hade något annat liknande redan färdigt som råkade vara från ett större projekt med massa oop? Jag försöker bara förklara att det finns lika många åsikter som det finns programmerare och dessutom har alla skrivit kod de är nöjda med som efter ett halvår känns som ren katastrof. Allting ändras hela tiden och åsikter skiftar, vissa älskar nog upplägget. För mig löser OOP bara vissa specifika problem, men att separera kod i moduler med tydliga ’interface’/funktionalitets-specifikationer är det bästa som finns, då går det enkelt att testa, fixa en sak i taget utan att behöva ändra allt etc.

Permalänk
Skrivet av medbor:

Du kan säkert skriva en egen java-wrapper av WiringPi om du vill som ser ut som du vill ha den. Jag tror man ska lägga mindre tid på att försöka förstå hur personen tänkte än hur koden ser ut om om den är användbar. Kanske personen som skrev koden hade något annat liknande redan färdigt som råkade vara från ett större projekt med massa oop? Jag försöker bara förklara att det finns lika många åsikter som det finns programmerare och dessutom har alla skrivit kod de är nöjda med som efter ett halvår känns som ren katastrof. Allting ändras hela tiden och åsikter skiftar, vissa älskar nog upplägget. För mig löser OOP bara vissa specifika problem, men att separera kod i moduler med tydliga ’interface’/funktionalitets-specifikationer är det bästa som finns, då går det enkelt att testa, fixa en sak i taget utan att behöva ändra allt etc.

Har du lust och tid att visa mig ett praktiskt exempel på hur det går till när man använder interfaces i syfte att jobba med projektform?
Jag vet hur man använder interfaces. Brukar kalla det för "filter" då man använder interfaces för att deklarera vissa funktioner och fält man vill ha från en klass.

Men har aldrig använd detta i syfte för att jobba med flera andra utvecklare.
Lått oss säga att jag gör klassen A och du gör klassen B. Jag behöver funktionalitet från din klass B. Men du är inte helt klar med din klass B och jag är 90% klar med min klass A. Vad ska jag göra nu?

Permalänk
Medlem
Skrivet av heretic16:

Har du lust och tid att visa mig ett praktiskt exempel på hur det går till när man använder interfaces i syfte att jobba med projektform?
Jag vet hur man använder interfaces. Brukar kalla det för "filter" då man använder interfaces för att deklarera vissa funktioner och fält man vill ha från en klass.

Men har aldrig använd detta i syfte för att jobba med flera andra utvecklare.
Lått oss säga att jag gör klassen A och du gör klassen B. Jag behöver funktionalitet från din klass B. Men du är inte helt klar med din klass B och jag är 90% klar med min klass A. Vad ska jag göra nu?

Skriva klart din klass A till 100% låter som en bra fortsättning. Finns ingen anledning att låta alla sista tio procenten vänta, du har ju ett "kontrakt" på vad B ska tillhandahålla.

Dina enhetstester bör ju ändå inte använda den konkreta implementationen av klass B, så det finns i regel mycket du kan göra för att skriva klart klass A och vara trygg med att den gör vad den ska.

Permalänk
Skrivet av fourbyfour:

Skriva klart din klass A till 100% låter som en bra fortsättning. Finns ingen anledning att låta alla sista tio procenten vänta, du har ju ett "kontrakt" på vad B ska tillhandahålla.

Dina enhetstester bör ju ändå inte använda den konkreta implementationen av klass B, så det finns i regel mycket du kan göra för att skriva klart klass A och vara trygg med att den gör vad den ska.

Du menar att man redan vet vad andra redan gör?
Jag har sett hur övriga utvecklar på github och jag förstår inte deras arbetsätt. Ibland verkar dom tala med sig själva.

Permalänk
Medlem
Skrivet av heretic16:

Du menar att man redan vet vad andra redan gör?
Jag har sett hur övriga utvecklar på github och jag förstår inte deras arbetsätt. Ibland verkar dom tala med sig själva.

Specifikationen på hur klass b ska fungera är ju interfacet. Det kommer man överrens om först, sen kan båda jobba ostört och oberoende av varandra

Edit: det är precis så man separerar moduler i större projekt, en modul för nätverk, en för lagring, en för ui/frontend, en annan för kryptografi... då kan man enkelt testa koden med automatiska tester eller byta ut delar utan att allt behöver börja om från grunden

Permalänk
Medlem
Skrivet av heretic16:

Har du lust och tid att visa mig ett praktiskt exempel på hur det går till när man använder interfaces i syfte att jobba med projektform?
Jag vet hur man använder interfaces. Brukar kalla det för "filter" då man använder interfaces för att deklarera vissa funktioner och fält man vill ha från en klass.

Men har aldrig använd detta i syfte för att jobba med flera andra utvecklare.
Lått oss säga att jag gör klassen A och du gör klassen B. Jag behöver funktionalitet från din klass B. Men du är inte helt klar med din klass B och jag är 90% klar med min klass A. Vad ska jag göra nu?

Skriva unit tests.
Inte bara rörmokare som behöver mocka för att slippa skit.

Permalänk
Datavetare
Skrivet av heretic16:

Har du lust och tid att visa mig ett praktiskt exempel på hur det går till när man använder interfaces i syfte att jobba med projektform?

Det räcker med detta enkla exempel för att belysa fördelarna med interface

Action getSome(Reader reader) { if (reader.read() == 42) { return Action.BUILD_EARTH; } return Action.TRY_AGAIN; }

Kan använda vilken typ som helst så länge den implementerar Reader. Fast det har inget med OOP att göra.

OOP kan vara vettigt att använda, men faktum är att det är ett verktyg för en väldigt smal nisch av problem (och antagligen krympande idag p.g.a. trend mot multi-core och tillståndslösa mikroservices).

Skulle vara väldigt förvånad om mindre än hälften av alla lägen där folk idag försöker använda OOP skulle må mycket bättre av att man lät bli. Så är mest det som är problemet, OOP var en sådan brutal buzz-word på 90-talet att det fortfarande hänger kvar långt mer än det rimligen förtjänar.

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

Men hur vet man struktren vid från början av ett projekt som är helt ny?

Jag använder typ aldrig extends eller implements eller interface i Java. Känner inget behov utav det.

Skrivet av heretic16:

Jag vet vad extends och interface är. Men jag sitter bara i enmansprojekt oftast.

Kan ju bero på det du nämner att du har svårt att sätta dig in i koden som folk skriver på github.
Att utöka en klass eller implementera ett interface är extremt vanligt och troligen lär du inte sitta med
särskilt avancerade projekt om du aldrig känner behovet av att göra detta. Och om du enbart sitter
i egna småprojekt så kanske du inte riktigt lärt dig att läsas andras kod heller, utan mer din egen bara.
Alla skriver kod på sitt sätt precis som man skriver texter / artiklar whatever, och man behöver lära sig att
förstå och läsa andras kod också.

Men om du tycker att att projekten är för avancerat skrivna, fråga dom som skrivit koden om det i så fall.
Lite konstigt att fråga det här, där ingen varit med och skrivit den kod du syftar på (antagligen).

Visa signatur

WS: Mac Studio M1 Max | 32 GB | 1TB | Mac OS
WS: Intel i5 12600K | 64 GB DDR4 @3600 Mhz | 2x1TB nvme 2x1TB SSD SATA | Windows 11 & Manjaro Linux
Bärbar: Macbook Pro 14" | M1 Pro | 16GB RAM | 512GB SSD | Mac OS
Servrar: Intel i7 10700K | 64 GB DDR4 @3600Mhz | 3 TB SSD + 22TB HDD | Unraid |
4x Raspberry pi 4b 8Gb | Dietpi |

Permalänk
Medlem
Skrivet av heretic16:

Jag har lyssnat rätt mycket på webbutvecklare och dom som har lång erfarenhet i mjukvaruutveckling och dom hävdar att när man programmerar så är det viktigare att skriva lite kod som är enkel, än avancerat och proffesionellt. Dels för att deras kunder betalar inte för proffisionell kod, utan för att lösa problemet.

Det där är lite halvkonstigt argumenterat. Om man inte skriver vettig kod, utan bara kod "som löser problemet" så kan du potentiellt skapa mycket teknisk skuld och mycket svårförvaltad programvara = blir i slutändan dyrare för kunden.
Skriv vettig kod, strukturera din kod, skriv och förvalta tester så blir det enklare att förvalta koden i framtiden, och säkerligen billigare också. Får man skräpkod i knät som någon skrivit och denne har struntat i tester så kommer det resultera i stora, troligen dyra, omskrivningar av koden. Det tycker nog uppdragsgivaren är mindre roligt.

Visa signatur

WS: Mac Studio M1 Max | 32 GB | 1TB | Mac OS
WS: Intel i5 12600K | 64 GB DDR4 @3600 Mhz | 2x1TB nvme 2x1TB SSD SATA | Windows 11 & Manjaro Linux
Bärbar: Macbook Pro 14" | M1 Pro | 16GB RAM | 512GB SSD | Mac OS
Servrar: Intel i7 10700K | 64 GB DDR4 @3600Mhz | 3 TB SSD + 22TB HDD | Unraid |
4x Raspberry pi 4b 8Gb | Dietpi |

Permalänk
Medlem
Skrivet av heretic16:

Har du lust och tid att visa mig ett praktiskt exempel på hur det går till när man använder interfaces i syfte att jobba med projektform?
Jag vet hur man använder interfaces. Brukar kalla det för "filter" då man använder interfaces för att deklarera vissa funktioner och fält man vill ha från en klass.

Men har aldrig använd detta i syfte för att jobba med flera andra utvecklare.
Lått oss säga att jag gör klassen A och du gör klassen B. Jag behöver funktionalitet från din klass B. Men du är inte helt klar med din klass B och jag är 90% klar med min klass A. Vad ska jag göra nu?

Ett interface är inte ett filter, det är ett kontrakt på hur två delar ska interagera.

En stickkontakt är ett bra exempel på ett interface. Så länge du har två strömledande pinnar som tar emot 220volt, spelar det ingen roll för vägguttaget om det är en lampa eller hårtork.

I din fråga - Klass A ska helst inte behöva Klass B. Men om du nu absolut vill göra så, hänvisar du bara till interfacet för klass B, så spelar det ingen roll om Klass B är färdig eller ej.

Men i övrigt handlar det om planering och samarbete. Du får väl jobba på Klass C medan du väntar, om man nu trots allt hamnar i en sådan situation.

Det är kul att du frågar. Jag tror fler poletter kommer ramla ner om du läser lite fler böcker i ämnet dock. Du är på god väg med intresset, nu måste du bara bilda dig lite mer så kommer det här bli helt kanon om några år

Permalänk

Så här programmerar jag. Jag börjar först med att jag skriver all kod i en enda klass. När jag har löst problemet så delar jag upp koden och gör en fin struktur av det så koden blir mer läsbar. Jag delar upp koden så varje funktion gör sin sak.

När jag har gjort likadant med många andra klasser så börjar jag se en struktur på projektet.
Jag har väldigt svårt att tillämpa OOP med applikationsprogrammering, t.ex. om jag ska koppla ihop en databas med UI på webben. Då brukar jag mest bara köra strukturerad programmering.

Men börjar jag göra websidor som ser likadana ut, så bygger jag självklart en klass av detta där jag ändrar objektets struktur. Då kommer OOP in. Men bara grundläggande t.ex. arv och interface. Men det är BARA om jag ser att jag börjar repetera min kod.

Jag försöker lösa så mycket som det bara går med just strukturerad programmering. Jag använder Vaadin + Spring Boot. Känns som allt är endast färdigt då.

Permalänk

Vad tycker ni om denna kod? Jag tycker att det verkar som OjAlgo använder OOP till 100%.

https://github.com/optimatika/ojAlgo/blob/develop/src/org/oja...

Permalänk
Skrivet av SanTeoX:

Det där är lite halvkonstigt argumenterat. Om man inte skriver vettig kod, utan bara kod "som löser problemet" så kan du potentiellt skapa mycket teknisk skuld och mycket svårförvaltad programvara = blir i slutändan dyrare för kunden.
Skriv vettig kod, strukturera din kod, skriv och förvalta tester så blir det enklare att förvalta koden i framtiden, och säkerligen billigare också. Får man skräpkod i knät som någon skrivit och denne har struntat i tester så kommer det resultera i stora, troligen dyra, omskrivningar av koden. Det tycker nog uppdragsgivaren är mindre roligt.

Jag menar inte dålig kod. Jag menar ren och enkel kod.

Titta på denna
https://www.youtube.com/watch?v=-AQfQFcXac8 (mycket kul)

Och även på denna man.
https://youtu.be/muSNl2AB46s?t=467

Och denna
https://youtu.be/W8ykZNSLDqE?t=401

Permalänk
Avstängd
Skrivet av heretic16:

Jag menar inte dålig kod. Jag menar ren och enkel kod.

Titta på denna
https://www.youtube.com/watch?v=-AQfQFcXac8 (mycket kul)

Och även på denna man.
https://youtu.be/muSNl2AB46s?t=467

Ren och enkel kod är professionell. Men om man bara "löser problemet" så snabbt och enkelt som möjligt så skapar man ju problem framöver, när nästa eller näst-näst-nästa problem ska lösas.

Permalänk
Medlem
Skrivet av heretic16:

Jag menar inte dålig kod. Jag menar ren och enkel kod.

Titta på denna
https://www.youtube.com/watch?v=-AQfQFcXac8 (mycket kul)

Och även på denna man.
https://youtu.be/muSNl2AB46s?t=467

Och denna
https://youtu.be/W8ykZNSLDqE?t=401

Lättförståelig är helt olika för alla utvecklare beroende på bakgrund och vilka projekt man är insatt i. Han man skrivit mycket OOP kan man kanske förstå mer varför något är som det är. Till exempel behöver man inte sätta sig in i hela koden för att implementera ett interface, eller så kanske koden använder standardiserade interface som används på många andra ställen? Jag säger inte att jag personligen tycker det exemplet är fantastiskt, men jag har sett många andra exempel i min karriär som är långt värre. De som utvecklade denna har säkert en bakgrund där dessa typer av hierarki redan fanns. Sen kan det finnas andra saker som skalbarhet och prestanda som kan skilja mellan olika typer av implementationer... eller kanske koden ska gå att återanvända i många olika scenarion och sånt

Permalänk
Skrivet av medbor:

Lättförståelig är helt olika för alla utvecklare beroende på bakgrund och vilka projekt man är insatt i. Han man skrivit mycket OOP kan man kanske förstå mer varför något är som det är. Till exempel behöver man inte sätta sig in i hela koden för att implementera ett interface, eller så kanske koden använder standardiserade interface som används på många andra ställen? Jag säger inte att jag personligen tycker det exemplet är fantastiskt, men jag har sett många andra exempel i min karriär som är långt värre. De som utvecklade denna har säkert en bakgrund där dessa typer av hierarki redan fanns. Sen kan det finnas andra saker som skalbarhet och prestanda som kan skilja mellan olika typer av implementationer... eller kanske koden ska gå att återanvända i många olika scenarion och sånt

Men alla dessa tre nämner gemensam sak. Att skriv enkel och ren kod. Börja inte göra koden mer avancerad och gör inte koden svår att läsa eller komplex.

Om katten din förstår din kod så har du skrivit världens bästa kod, som det sägs i första filmen.

Jag har full förståelse om man jobbar med objekt. Då är OOP passande.

Permalänk
Medlem
Skrivet av heretic16:

Men alla dessa tre nämner gemensam sak. Att skriv enkel och ren kod. Börja inte göra koden mer avancerad och gör inte koden svår att läsa eller komplex.

Om katten din förstår din kod så har du skrivit världens bästa kod, som det sägs i första filmen.

Jag har full förståelse om man jobbar med objekt. Då är OOP passande.

Det kan vara enklare eller svårare beroende på din bakgrund. Har du tidigare suttit i projekt som har samma/liknande interface och struktur kanske det är enklare att skriva det så här för att man förstår innebörden. Samma sak kan gälla för att det kan räcka med att implementera en liten liten del, resten är redan klart och fungerar utan att du behöver skriva det. Första gången man sätter sig in i ett sånt här ’avancerat’ projekt kan det vara avskräckande, men det kan innebära att den koden du behöver skriva (när du fattar vart den ska in) blir väldigt enkel och väldigt få rader för att de mesta andra redan görs av den befintliga koden.

Svaret är att ’katten’ aldrig kommer förstå vissa stora komplexa kodbaser oavsett hur varje metod är skriven

Permalänk
Medlem
Skrivet av heretic16:

Jag menar inte dålig kod. Jag menar ren och enkel kod.

Titta på denna
https://www.youtube.com/watch?v=-AQfQFcXac8 (mycket kul)

Och även på denna man.
https://youtu.be/muSNl2AB46s?t=467

Och denna
https://youtu.be/W8ykZNSLDqE?t=401

Bra råd, i min åsikt. Gjorde själv flera liknande förenklingar på mitt förra jobb. Koden jag tog över var full med OOP patterns som var där mer "för sakens skull" än för att de faktiskt löste några problem. Ett speciellt vanligt pattern var att alla klasser också hade ett associerat interface, och all kod som använde klassen använde inte klassen direkt, utan interfacet. Tror tanken var att programmet skulle vara "utökningsbart" ifall man någonsin lade till en variant av en klass, men som implementerade samma interface. I praktiken hade de dock alltid bara en enda implementerare av varenda interface, så det var bara onödig komplexitet. Jag tycker man ska skriva kod först och främst för problemen man faktiskt har idag, och inte för de man möjligen kommer ha imorgon. Refaktorering är alltid ett alternativ.

Iallafall, skrev om koden, och tog bort allt jag ansåg vara övergenerellt bloat. När jag var klar var programmet ca. 8k rader, istället för ca. 40k som det var innan... Det nya programmet var betydligt mer lättläst, och man kunde faktiskt ha hela grejen i huvudet, utan att trassla in sig på alla de tomma abstraktionerna.

EDIT:
Var dock medveten om att långt ifrån alla bruk av interfaces är bloat. Abstraktion är absolut inte något dåligt per automatik. Ofta gör det koden mycket simplare om man kan identifiera rimliga abstraktioner i koden. Problemet tror jag mest är att många nyexade OOP-programmerare inte ännu har känslan för när abstraktion är passande, så de angriper problemet mer systematiskt, och klämmer in abstraktioner på alla ställen som deras favoritbok om OOP patterns säger att det är möjligt.

Visa signatur

Arbets- / Spelstation: Arch Linux - Ryzen 5 3600 - RX 7900 XT - 32G DDR4
Server: Arch Linux - Core i5-10400F - 16G DDR4

Permalänk
Avstängd
Skrivet av Bryal:

Bra råd, i min åsikt. Gjorde själv flera liknande förenklingar på mitt förra jobb. Koden jag tog över var full med OOP patterns som var där mer "för sakens skull" än för att de faktiskt löste några problem. Ett speciellt vanligt pattern var att alla klasser också hade ett associerat interface, och all kod som använde klassen använde inte klassen direkt, utan interfacet. Tror tanken var att programmet skulle vara "utökningsbart" ifall man någonsin lade till en variant av en klass, men som implementerade samma interface. I praktiken hade de dock alltid bara en enda implementerare av varenda interface, så det var bara onödig komplexitet. Jag tycker man ska skriva kod först och främst för problemen man faktiskt har idag, och inte för de man möjligen kommer ha imorgon. Refaktorering är alltid ett alternativ.

Iallafall, skrev om koden, och tog bort allt jag ansåg vara övergenerellt bloat. När jag var klar var programmet ca. 8k rader, istället för ca. 40k som det var innan... Det nya programmet var betydligt mer lättläst, och man kunde faktiskt ha hela grejen i huvudet, utan att trassla in sig på alla de tomma abstraktionerna.

Det är ju rätt bra med interfaces för enhetstestning också. Beroende på hur man skriver sina tester förstås, men jag tycker det är rätt trevligt att kunna ha "dummy"-klasser som använder samma interface som de faktiska klasserna i applikationen. Mocking är ju också trevligt förstås men det blir mycket duplicering om applikationen inte är helt trivial.