Diskuze: C# aplikace na výpočet provizí

C# .NET .NET (C# a Visual Basic) C# aplikace na výpočet provizí American English version English version

Avatar
Mára
Člen
Avatar
Mára:

Ahoj, komunito. Jsem sedmnáctiletý student gymnázia a baví mě programovat.
Již dlouho se trápím s jedním problémém a nevěděl jsem, kam jinam se obrátit jelikož jediné mé zdroje informací ohledně programování jsou itnetwork.cz a google.
Můj problém spočívá v tom, že nevím, jak objektově zapsat algoritmus počítání provizí a jak říká jeden článek tady na itnetwork - pokud neprogramuju objektově tak z toho vznikne spaghetti code. Popíšu vám svůj algoritmus.

Od uživatele dostanu n počet TextBoxů, ve kterých jsou uložena čísla, ze kterých se počítá provize. Každé číslo se nejprve vynásobí procentovou hodnotou - ta se mění podle toho, jak moc je to číslo velké. A nebo - a tady začíná zádrhel - podle jiných kritérií. K pochopení budu muset trošku přiblížit situaci. Od uživatele získám například číslo, které je větší než 320 000, takže ho násobím číslem 0.32 - 32%. Jenže musím zároveň ošetřit případ, kdy uživatel předem pevně stanoví v druhém TextBoxu, kolik to je procent. To se musí dít s každým dalším číslem. Poté se už počítá provize.
Ta se získá tak, že sečtu všechny neupravené originální TextBoxy, vynásobím je podle stejného klíče jako každý samotný originální TextBox a odečtu od něj ty upravené TextBoxy.

Omlouvám se, pokud tomu nejde rozumět a také se předem omlouvám tomu, kdo se mnou bude mít to strpení a podívá se na můj kód.
Děkuji všem, kteří jsou ochotni mi dát nějaký tip a nebo radu do budoucna.
Marek. Kód

 
Odpovědět 8. listopadu 17:09
Avatar
Odpovídá na Mára
Michal Štěpánek:
  1. chtělo by to psát komentáře, aby se i ostatní v tom kódu vyznali.
  2. asi by bylo lepší používat konstrukci podmínek "if -> else if -> else" místo prostého "if", pak by se daly podmínky výrazně zjednodušit

třeba

if (s < 20000)
     odecet = odecet + s * 0.04;
else if (s < 40000)
     odecet = odecet + s * 0.08;
else if (s < 60000)
     odecet = odecet + s * 0.12;
else if...
...
...
...
else
{
co se stane, když nevyhovuje žádná podmínka
}
  1. ty podmínky se mi zdají trochu zběsilé, např. co se bude dít, když třeba "s < 10000", nebo s > 360000 a přitom procenty[i].Text = "35%"?
  2. těžko fundovaně radit, když nevím, co která proměnná v kódu znamená, kde se bere a proč?
Editováno 8. listopadu 21:24
Nahoru Odpovědět 8. listopadu 21:22
Nikdy neříkej nahlas, že to nejde. Vždycky se totiž najde blbec, který to neví a udělá to...
Avatar
Mára
Člen
Avatar
Odpovídá na Michal Štěpánek
Mára:

Děkuji mockrát za reakci i přes to, že jsem kód nepopsal!
procenty jsou instance TextBoxů, ve kterých jsou uložené přesně dané procenta - tzn. když si uživatel přesně zadá, kolik procent potřebuje

protected List<int> hodnoty = new List<int>() ; // uložené Parsované int hodnoty
protected List<TextBox> textboxy = new List<TextBox>(); // objekty TextBox - parsuji do protected Listu hodnoty
protected List<Label> labely = new List<Label>(); // text - nijak nezpracovávám
protected List<TextBox> procenty = new List<TextBox>(); // čtu a používám při výpočtech

tyhle Listy mám v

public partial class MainWindow : Window

To, čeho se snažím dosáhnout v kódu, který se nachází pod

if (bodovy_soucet >= 360000)
          {
              procenta = 0.32;
          }

je to, že pokud má uživatel ve své síti 35 a nebo 32, tak mu podle toho vypočítá provizi
to, že má uživatel 35, nebo 32 se zjistí pomocí Listů, ve kterých jsou uloženy při

if (s >= 360000 && (procenty[i].Text != "35%") && (procenty[i].Text != "37%") && (procenty[i].Text != "39%") && (procenty[i].Text != "40%"))
                {
                    odecet = odecet + s * 0.32;
                    seznamtricetdvojek.Add(s);
                }
                if (procenty[i].Text == "35%")
                {
                    odecet = odecet + s * 0.35;
                    seznamtricetpetek.Add(s);
                }

Pokud má jednu 32(a zároveň když odečteme od bodovy_soucet tuhle 32, musí vyjít číslo větší než 300 000), jeho procenta jsou 35

Pokud má dvě 32(stejná podmínka), jeho procenta jsou 37 - zároveň se snažím ošetřit to, že kdyby měl méně než 300 000, tak se zkusí podívat, jestli aspoň ta jedna má dostatek, a pak by jeho procenta byli 35

Pokud má tři 32(stejná podmínka), procenta = 39 - zároveň se snaží ošetřit dvě, když to nestačí tak jednu 32

Pokud má alespoň tři 35 - procenta jsou 40, zároveň zkouší další možnosti, když je míň než 300 000 (tzn. měl by odebrat největší prvek ze seznamu(Listu hodnoty), atd. pokud už je 35 méně než tři, tak zkusí všechny možnosti 32)

Přikládám ještě celý kód, okomentovaný a snad lépe viditelný.
Děkuji, pokud bys mi byl ochoten zase odpovědět:)
kód

 
Nahoru Odpovědět 8. listopadu 22:28
Avatar
Marian Benčat
Redaktor
Avatar
Marian Benčat:

Obávám se, že přesně takovýto kód je neobjektový kód. Nebudu ti to přepisovat, ale dám ti jednoduchý příklad na kterém to třeba pochopíš.

1)

class pocitani : textove_prvky // textove_prvky dědí MainWindows - takže jsou v ní ty protected Listy v MainWindow
    {

Už todle je hodně špatně.. Ty máš Model, tedy věc čisté logiky.. ten tvuj class Pocitani nic jineho ani neni.. a ty abys dostal hodnoty textboxu, tak si podedis od Main_WINDOW????

Pokud vim, tak ty potrebujes dostat jen ty jejich hodnoty,.. spravny pristup (je jich spoustu) je poslat si do vypocitej ty hodnoty tech textboxu.

  1. Mas tam asi tak 100 podminek, ktere ti kontroluji urcite meze a na zaklade toho nejak modifikuji odecet, procenta atp,

Todle je naprosto ideální čas na to udělat si nějaký třeba List "mezí a modifikací". Dám ti jednoduchý příklad v pseudokodu.

class Procenta {
  int horniMez;
  intDolniMez;
  int procenta;
  getProcenta() {
    return procenta;
  }
  bool  vyhovuje(int value) {
      return value>=dolniMez && <hornimez;
   }
}

List<Procenta> procentaList = new...;
 procentaList.Add(new Procenta(10000, 20000, 0.04);
 procentaList.Add(new Procenta(20000, 40000, 0.08);

a použití místo těch 10 000 podmínek:

procenta = procentaList.First(x=>x.vyhovuje(bodovy_soucet)).getProcenta();

Samozřejmě by si mohl ten LINQ nahradit vlastní třídou atp. Toto řešení má spoustu i dalších výhod.. například... pokud se ti změní ty hodnoty a meze pro procenta.. změníš jen to přidávání do listu.. nebo to můžeš číst z configu atp.

Toto je objektový přístup.Cela ta metoda vypocitej, by se dala pomoci ruznych navrhovych vzoru (State, Behavior) a nastroju OOP (polymorfismus) smrsknout tak na 1/10 a hlavne by to bylo zcela pochopitelne co to dela.. Takhle je to jen dlouhy nic nerikajici kod.

Píši ti to protože tě očividně zajímá OOP... Správné OOP se ale nikde úplně neučí a tak ti povím, co ti může dobře napovědět, že nějaký kód nen napsaný jako spávné OOP, ale jen imperativní kod s classama...

  1. Obsahuje tam prave podobný decision tree pomocí 20ti ifu, co tam ty máš - tomudle se říká branching a v OOP se řeší často pomocí nějakého vnitřního stateu (tam se používá návrhový vzor state, předek- potomek a polymorfismus.)
  2. Objekty mají public settery.
Akceptované řešení
+20 Zkušeností
+1 bodů
Řešení problému
 
Nahoru Odpovědět 8. listopadu 23:48
Avatar
Mára
Člen
Avatar
Odpovídá na Marian Benčat
Mára:

Moc děkuji za tvoji reakci, hodně jsem si z toho vzal a jsem rád za rady. Ale je pro mě stále záhadou, jak pomocí OOP tam dostat ty podmínky týkající se tohohle kódu.

if (seznamtricetdvojek.Count() == 1)
            {
                int pomocna_promenna = 0;
                foreach (int s in seznamtricetdvojek)
                {
                    pomocna_promenna = pomocna_promenna + s;
                }
                if (bodovy_soucet - pomocna_promenna >= 300000)
                {
                    procenta = 0.35;
                }
                else
                    procenta = 0.32;
            }
 
Nahoru Odpovědět 9. listopadu 8:50
Avatar
Marian Benčat
Redaktor
Avatar
Marian Benčat:

Ja jsem z toho kodu silne ponekud nesvuj , mozna kdyby si to popsal matematickou funkcí, poznas ze to jde pomoci matematickyh pravidel pretransformovat na neco rozumnejsiho. Takhle to vypada jako nejaka matematicka posloupnost, z toho co jsem pochopil.

Ten kod co si daval nahore moc nedava smysl sam o sobe..

  1. Kouknes se jestli nejaky "SEZNAMTRICET­DVOJEK" ma jeden prvek a pokud ano, tak to projizdis foreachem? :-/
  2. Neomezuj se v C# zadnyma programovacíma paradigmatama. C# zvládá velmi dobře libovolnou kombinace OOP, imperativního a funkcionalniho programovani.

Opět příklad:

if (seznamtricetdvojek.Count() == 1)
            {
                int pomocna_promenna = 0;
                foreach (int s in seznamtricetdvojek)
                {
                    pomocna_promenna = pomocna_promenna + s;
                }
                if (bodovy_soucet - pomocna_promenna >= 300000)
                {
                    procenta = 0.35;
                }
                else
                    procenta = 0.32;
            }

Lze převézt na třeba:

procenta = (bodovy_soucet  - seznamtricetdvoje.Sum()) >= 30000 ? 0.35 : 0.32;

a stále je to velmi čitelné = stačí pohled na to a hned je každému jasné, co to dělá.. Je mu totiž hned jasné, že v tom není žádná složitá logika.

kdežto pokud tam dáě těch 25řádek kódu, tak bude každý luštit, co to vlastně dělá.

Přesto, že jsem mluvil o tom, že tvůj kód není OOP, tak nesdílím názor Čápky (autora těch článků), že OOP je samospásné a neOOP kód je spaghetti. Využij jedné z největších výhod C# a sice to, že jde o tzv. multi-paradigmatický jazyk.

Zatímco pro řízení programu můžeš dobře použít OOP, na matematické výpočty (jako jsou tvoje procenta) se hodí třeba zase jeho funkcionální číst, případně kombinace funkcionální+OOP.

NO.. a pak je tam ještě další level. A sice reactive extensions.. ale tim te nebudu zatezovat ;-)

 
Nahoru Odpovědět  +2 9. listopadu 17:36
Avatar
Mára
Člen
Avatar
Mára:

Moc děkuji za podnětné rady, už to zkouším celé překopat a udělat nějak logicky, přehledně a lépe.

 
Nahoru Odpovědět  +1 9. listopadu 19:47
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 7 zpráv z 7.