int foo(int a){
int returnValue = 1;
if(1 == a){
returnValue = 0;
//do stuff
}
return(returnValue);
}
Funktionen kan bli så faslig att underhålla annars.
Man råka på problem om man enligt samma tankesätt utelämnar en return som inte är villkorlig, dvs i vissa fall returnerar funktionen inget alls! Man får aldrig glömma att C är lömskt
Nja, jag anser nog att "return" tidigt i funktioner är en fördel.
Annars får man hela tiden ta hänsyn till tidigare kriterier.
Ju tidigare man kan konstatera att en funktion t.ex. inte kan fortsätta p.g.a. någon kriterie, ju lättare är det att göra en snygg, logisk och funktionsfull funktion.
Att ta med ett returvärde genom hela funktionen låter väldigt rörigt...
Sen finns det ju anledning till att man kan avsluta funktionen tidigare: det är mindre kod som ska löpas igenom vilket ger snabbare program.
Om man har problem att underhålla sina rutiner har man definierad dom dåligt till att börja med.
När jag gör program börjar jag alltid med att definiera vilka rutiner jag behöver och vad de förväntar som input och vad de ger i output. Kan jag inte göra den definition vet jag att det kommer att bli problem.
Jag definierar även värden som är gemensamma för mer än 1 rutin och/eller som kan komma att ändras under projektets gång, det kan vara array-storleker, min/max värden osv.
På mitt projekt med Janfires pelletsbrännare har jag en hel fil enbart med "konstant" definitioner, en annan fil med alla texter och i huvudfilen är det 14 olika parametra som väljer om det är labb-program eller produktionsprogram.
Skulle jag göra mina rutiner så att de "släpade" med ett returvärde kommer det ju inte att fungera, vara sig i logik som i hastighet.
Vad jag däremot ofta använder är #define, om man har ett värde som ska vara tydligt men består av en hårdvara-hänvisning kan det vara mycket lättare att läsa med define. Ett exempel från ett MikroC-program:
PORTA.F1 = true; // Turn on green LED
PORTA.F2 = false; // Turn off red LED
Utan kommentarer är det skit att läsa, alltså MÅSTE man kommentera varenda gång man fibblar med dessa LED. Gör man däremot såhär:
#define LED_GREEN PORTA.F1
#define LED_RED PORTA.F2
kommer
LED_GREEN = true;
LED_RED = false;
nära nog att kommentera sig själv fastän att det efter preprocessorn kommer att vara identisk för kompilern.
Om jag gör en funktion som ska returnera ett värde är det första jag lägger in i den rutin en return(); med ett default värde eller ett värde jag enkelt kan leta upp till var det kommer ifrån, ska det svaras med 0-100 t.ex. kommer default värdet att vara -1.
Nu handlar det ju förvisso om embedded-produkter och har man en rutin som ofta anropas kanske man tom ska skriva den i ASM, men generellt spelar nog inte en breq, cpse eller dylikt extra så stor roll?
Kod som är villkorlig är villkorlig
Visst är det viktigt att abstrahera och så fort man är klar med det översätter man det i headerfiler, implementera funktioner är nog det sista som händer... men jag tycker (jovisst det är min helt personliga åsikt) nog fortfarande att det kan vara bra att undvika fantomreturer och andra pitfalls då det är så jobbigt att debugga i dessa fall. För det är ju inte i abstraktionen som det slår slint i sådana här fall utan i implementationen, när man försöker optimera/utveckla sin funktion (eller nån annans för den delen).
För mig handlar det ju inte om att skriva en funktion som fungerar som man tänkt sig, det handlar om att skriva en funktion som fungerar även om det inte går som man tänkt sig...
Nu har jag aldrig upplevd "fantomreturer" vad det nu är och jag brukar lägga krutet på att rutinen fungerar i alla lägen, om man uppnår "även om det inte går som man tänkt sig..." och har gjort kod som fallera av den anledning bör man tänka om sitt programmeringssätt...
"även om det inte går som man tänkt sig" handlar självfallet om yttre omständigheter, t.ex. att temp-sensorn går sönder i pelletsbrännaren och ger en rökgastemperatur på -1 grader C. Fantomretur skulle då tex kunna vara:
Angående multipla return from en funktion, så brukar jag personligen,
när det gäller assembler, anse att man enbart ska ha en RETURN i varje
subrutin. Det blir betydligt snyggare, och det är mindre risk att man av
misstag lägger dit något nytt som skall utföras direkt före den sista
RETURN'en, och missar den högre upp i koden. "Priset" är en extra GOTO
ner till den avslutande RETURN...
Jag är är inte helt inne på samma linje, jag anser att man kan trycka in en 'return' om det är befogad, jag delar i stället upp med kommentarer för att säkerställa att man inte gör klantigheter. Dock är det ofta sådan att jag läggar in returerna under optimeringsfasen, under FSAF-fasen ("Få-Skiten-Att-Fungera") håller jag oftast ihop rutinerna så mycket som möjligt.
Jag tycker att, om man ligger så "on the edge" så att man måste skriva kod som
riskerar att bli svår att underhålla i framtiden, så har man större problem...