Lite osäker om det här är en arkitekturfråga men den handlar om implementeringen av affärslogiken. Du behöver verkligen börja titta på OOP, objektorienterad programmering :) Jag gör i många fall som ni säger men föstår inte vad det har men huvudproblemet att göra.Långa funktioner
Affärslogiken i mina projekt består som alla andra av inläsning, behandling, utmatning. Ofta är det naturligtvis inte helt renodlat utan funktionerna går i varandra (t.ex. behandlingen resulterar i att man behöver mer data).
När jag implementerar logiken gör jag det ofta som en enda lång funktion där jag endast bryter ut delar som upprepas till (statiska) medlemmar. Personligen har jag inga problem med det men andra personer tycker ofta att jag borde dela upp det i flera funktioner så man får en övergripande funktion som ser ut så här:
main
func1()
func2()
func3()
...
Detta skulle ge bättre överblick över vad funktionen gör (om man namnger funktionerna på ett bra sätt förståss).
Jag köper det argumentet men problemet är hur man skall hantera data. När allt är i samma funktion lägger jag ju allt i lokala variabler och har tillgång till all data utan problem.
Om man skall skapa flera funktioner finns det några olika alternativ:
1. Skicka data som argument till från funktionerna
List x,y,z
func1(x,y)
func2(x,z)
func3(z,y)
2. stoppa in variablerna i nån klass/struktur och skicka runt den mellan funktionerna
class C {
List x,y,z;
Integer u,v,w
};
C vars;
func1(vars);
func2(vars);
...
3. Lägga variablerna som medlemmar i logikklassen.
Problemet jag har med alla ovanstående sätt är att man tappar kontrollen över livstiden/giltighetstiden på data. Om jag använder lokala variabler är det ju enkelt att styra med initiering och scoping. Har jag dessutom flera olika logikfunktioner så gäller det ju att hålla reda på vilka variabler som hör till vilken funktion.
Speciellt svårt har jag för metod 3 eftersom jag då får känslan av att jag programmerar i Fortran (massa globala variabler). Ändå verkar metod 3 vara den vanligaste när jag ser andra personers kod.Sv: Långa funktioner
Dina objekts scope är lätt att hantera och du får en logisk uppbyggnad av vad som ska vara i scope just nu.
Jag gissar att din affärslogik handlar om verkliga saker och inte bara "abstrakt data".
Typ Personer, Bilar, Fakturor....?
Då bör du skapa klasser för dessa företeelser i den verkliga världen: Klasserna instantierar du som objekt som du fyller med data och operationer. T.ex en bil:
public class Bil
{
public string BilMarke;
public string Modell;
public string Farg;
public float TankVolym;
public float TankInnehall;
public float Forbrukning;
public float TankaBilen(float antalLiter)
{
TankInnehall += antalLiter;
return TankInnehall;
}
}
// ANVÄNDNING
Bil MinBil = new Bil();
MinBil.Modell="911 Turbo";
MinBil.TankaBilen(56);
MessageBox.Show (MinBil.TankInnehall.ToString());
Jag brukar ha som tumregel att ta in max 4 params i en metod.
Är de fler gör jag en struct / class av det.Sv:Långa funktioner
Om jag skall läsa fakturainformation från en XML fil då kan jag ju göra det på två sätt:
1. Ha en metod i fakturaklassen som läser in data. Jag tycker att detta är fel väg eftersom jag då kopplar fakturaklassen till en specifik inläsningsmetod (XML) och klassen blir svår att återanvända om jag i en annan applikation läser från t.ex en textfil.
2. Ha en fristående funktion som fyller på en fakturaklass från en XML fil.
Det är här mitt problem uppstår:
Oavsett vilken metod jag använder så skriver jag en funktion/metod som endast används på ett enda ställe i applikationen. Funktionen behöver ju information om en massa saker som filnamn, eventuellt urval, defaultvärden mm.
Denna information har jag ju tillgänglig i huvudfunktionen och jag måste således skicka den till xmlläsningsfunktionen på något sätt (eller använda någon slags medlemsvariabler).
dvs koden blir något i stil med: (hoppas det inte gör något att jag använder c++)
int dobusiness(parametrar, filnamn, urval, default) {
xmlreader xml....
std::vector<tInvoice> invoices;
while (...) {
invoices.push_back(readInvoiceXML(xmlreader, parametrar, urval, default, blablabla));
}
something(parametrar, invoices, bla bla);
}
Varför är detta bättre än att lägga koden för readInvoiceXML direkt i whileloopen? Jag får ju då möjligheten att kanske göra andra saker samtidigt. Antag att jag vill veta hur många fakturor som inte uppfyllde urvalet. Då måste jag lägga till en parameter till i anropet och en lokal variabel. Ligger koden direkt i loopen behöver jag ju bara en lokal räknare.
Självklart kan man flytta hela inläsningen till en klass och där ha information om antalet fakturor som inte uppfyller urvalet men då blir det ännu fler funktioner som jag måste skicka runt parametrar och urval till.