Java týden Java týden
Pouze tento týden sleva až 80 % na celý Java e-learning!
Brno? Vypsali jsme pro vás nové termíny školení OOP v Brně!

Rekurze

Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem.
Vydávání, hosting a aktualizace umožňují jeho sponzoři.

Co je to rekurze?

Metoda, která volá sama na sebe se nazývá rekurzivní. Takže, když metoda volá sama na sebe, tomu se říká rekurze. Klíčovou složkou rekurzivní metody je příkaz, který provádí volání na sebe sama.

K čemu je rekurze dobrá?

Rekurze se dá jednoduše použít při počítání faktoriálu. Pokud nevíte co je to faktoriál, tak si to teď vysvětlíme. Faktoriál z čísla N je součin všech celých čísel mezi 1čkou a N. Faktoriál z čísla 5 je 1 * 2 * 3 * 4 * 5 = 120. Takže faktoriál z čísla 5 je 120.

Bez rekurze by jste následující příklad řešili asi cyklem. No podívejme se na to jak bych to bez rekurze řešil já a samozřejmě mnozí z vás.

hlavní třída Program.java

public class Program {
    public static void main(String args[]){
        // vytvořím nový objekt třídy Faktorial
        Faktorial f = new Faktorial();
        // vypíšu faktoriál z čísla 5
        System.out.println(f.faktorial(5));
    }
}

Třída Faktorial.java

public class Faktorial {
    // Vytvořím veřejnou metodu, která vrací Integer.
    public int faktorial(int n){
        // N je číslo, z kterého chceme dostat faktoriál.
        int i, vysledek = 1;
        // součin všech čísel mezi 1 a N
        for(i = 1; i <= n;i++)
            vysledek = vysledek * i;
        // vrátím faktoriál z čísla N
        return vysledek;
    }
}

Jak jste si asi všimli, veřejná metoda faktoriál ve třídě Faktorial nám vrátil součin všech čísel od 1 do 5 (tedy N). Teď se podíváme na stejný příklad akorát s rekurzí.

Hlavní třída Program.java, je stejná jako ta předchozí.

public class Program {

    public static void main(String args[]){
        Faktorial f = new Faktorial();
        System.out.println(f.faktorial(5));
    }
}

Třída Faktorial.java, v které už je použita rekurze.

public class Faktorial {

    public int faktorial(int n){
        int vysledek;
        if(n == 1)
            return 1;
        vysledek = faktorial(n-1) * n;
        return vysledek;
    }
}

Jak vidíme, metoda volá sama na sebe "vysledek = faktorial(n-1) * n;", tudíž můžeme s klidem říct, že je rekurzivní. Je o dost jednodušší, než kdyby jsme použili cyklus. Při zavolání metody faktorial s argumentem 1 vrátí metoda 1čku. V opačném případě vrátí součin faktorial(n-1) - n. Pro vyhodnocení tohoto výrazu, se zavolá metoda faktorial() s hodnotou n-1. Tento proces se opakuje, dokud se n nerovná 1 a volání metody se nezačnou vracet. Například při volání výpočtu faktoriálu z čísla 2 způsobí první volání metody faktorial() provedení druhého volání s argumentem 1. Toto volání vrátí hodnotu 1, která se následně vynásobí číslem 2. Odpověď je tedy 2.

Další ukázkoví příklad rekurze je Fibonacciho posloupnost. Pokud nevíte co to je -> http://cs.wikipedia.org/…_posloupnost .

Nicméně ukázka Fibonacciho posloupnosti. O(2n)

public class Program {

    public static void main(String args[]){
        Fibonacci fib = new Fibonacci();
        System.out.println(fib.fibonaci(5));
    }
}

Fibonacci.java

public class Fibonacci {

    public int fibonaci(int n)
    {
        if (n == 1) return 1;
        else return fibonaci(n-1) + fibonaci(n-2);
    }
}

Hodně z vás by mi teď řeklo "bože to je pomalý to je hrůza", tak bohužel ano. Je to opravdu pomalé. :D Každopádně má to jedno super řešení jak to O(2n) zoptimalozivat na O(n). Trochu už zabíhám do algoritmů já vím. Nemůžu si pomoct.

public class Fibonacci {
    private List<Integer> list = new ArrayList<Integer>();
    public int fibonaci(int n)
    {   list.add(n);
        if (n == 1) return 1;
        if(!list.contains(n-1)) return fibonaci(n - 1);
        if(!list.contains(n-2)) return fibonaci(n - 2);
        return 0;
    }
}

O mnoho lepší, že? Stačilo si vytvořit list a sypat do něj hodnoty co přijdou, aby se neopakovali a ověřovat jestli tam ještě nejsou. Tím se to pěkně zrychlí a z O(n2) máme hnedle O(n).


 

Stáhnout

Staženo 393x (31.31 kB)
Aplikace je včetně zdrojových kódů v jazyce java

 

 

Článek pro vás napsal Зайчик
Avatar
Jak se ti líbí článek?
7 hlasů
Коммунизм для нашего будущего!
Všechny články v sekci
Zdrojákoviště Java - Základní konstrukce
Aktivity (2)

 

 

Komentáře

Avatar
Kit
Redaktor
Avatar
Kit:10.4.2013 16:42

Rekurze je skvělá například pro procházení adresářovým stromem nebo obecným stromem, který není příliš hluboký. Dá se elegantně použít např. na DOM.

Odpovědět 10.4.2013 16:42
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Lukáš Hruda (Luckin):10.4.2013 17:19

Nechci rejpat, ale nějak moc nechápu, co má dělat ta první metoda pro fibonacciho posloupnost, jelikož vrací číslo, ale fibonacciho posloupnost je řada čísel, tudíž by měla vracet pole nebo nějakou kolekci. Takhle akorát vyhodí stack overflow, pokud dosadíš cokoliv kromě 1, protože logicky n - 2 pro sudé n nebude nikdy 1. Tu druhou taky moc nechápu, ta jenom vždy vrátí 1.
Jenom pro zajímavost, ten faktoriál by se dal hodně zjednodušit:

public int faktorial(int n)
{
  return n == 1 ? 1 : faktorial(n - 1) * n;
}

Ale v tutoriálu by tohle samozřejmě bylo asi dost matoucí.

 
Odpovědět 10.4.2013 17:19
Avatar
Зайчик
Člen
Avatar
Odpovídá na Lukáš Hruda (Luckin)
Зайчик:10.4.2013 17:24

Já tu Fibonacciho posloupnost nevysvětluju. Ten kdo jí umí / chápe rozhodně bude vědět, že tam má přidat řádek navíc, aby to nevrátilo jednu hodnotu ale celou posloupnost. To je jen příklad jak se rekurze dá použít.

public int faktorial(int n)
{
  return n == 1 ? 1 : faktorial(n - 1) * n;
}

Hmm a nevím proč by to mělo být matoucí. '?' by se měl znát každopádně to mě nenapadlo. :[

Odpovědět 10.4.2013 17:24
Коммунизм для нашего будущего!
Avatar
Kit
Redaktor
Avatar
Odpovídá na Lukáš Hruda (Luckin)
Kit:10.4.2013 17:28

Kolik tedy vyjde faktorial(0)?

Odpovědět 10.4.2013 17:28
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Odpovídá na Зайчик
Lukáš Hruda (Luckin):10.4.2013 17:32

Protože je to tutoriál, a v něm by se měli věci vysvětlovat na příkladech na kterých je daný problém jasně vidět. Vysvětlovat rekurzi na kódu na jeden řádek by asi nebylo úplně ideální. Proto jsem napsal: "jenom pro zajímavost".

 
Odpovědět 10.4.2013 17:32
Avatar
Odpovídá na Kit
Lukáš Hruda (Luckin):10.4.2013 17:37

0! je 1... je tam chyba, v té podmínce by měla být 0 zahrnuta. Já jenom zjednodušil co je zde napsáno :) Stejně tak by měl být teoreticky ošetřen vstup na záporná čísla.

 
Odpovědět 10.4.2013 17:37
Avatar
Kit
Redaktor
Avatar
Odpovídá na Lukáš Hruda (Luckin)
Kit:10.4.2013 17:58

Dávám podmínku n <= 1. Sice vyjde 1 i pro záporná čísla, ale obvykle to nevadí.

Odpovědět 10.4.2013 17:58
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Odpovídá na Kit
Lukáš Hruda (Luckin):10.4.2013 18:01

A hlavně když je ta metoda rekurzivní, byla by asi hloupost aby pokaždé ošetřovala, zda číslo není záporné. V tomhle případě by to mělo být asi ošetřeno ještě před předáním metodě.

 
Odpovědět 10.4.2013 18:01
Avatar
Kit
Redaktor
Avatar
Odpovídá na Lukáš Hruda (Luckin)
Kit:10.4.2013 18:09

Hlavně je hloupost dělat faktoriál rekurzí.

Je jedno, jestli děláš test na rovnost jedné nebo na menší než jedna.

Odpovědět 10.4.2013 18:09
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Luboš Běhounek Satik
Autoredaktor
Avatar
Odpovídá na Kit
Luboš Běhounek Satik:10.4.2013 18:16

To je jen ukázka na rekurzi.
Jakákoliv rekurze se dá přepsat na nerekurzivní verzi.

Odpovědět 10.4.2013 18:16
https://www.facebook.com/peasantsandcastles/
Avatar
Kit
Redaktor
Avatar
Odpovídá na Luboš Běhounek Satik
Kit:11.4.2013 9:11

To je pravda, akorát nerekurzívní průchod adresářovým stromem je trochu opruz a určitě je lepší ho dělat rekurzívně.

Odpovědět 11.4.2013 9:11
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Luboš Běhounek Satik
Autoredaktor
Avatar
Odpovídá na Kit
Luboš Běhounek Satik:11.4.2013 11:15

Rekurze se obchází přes zásobník, i ten průchod adresářovým stromem je tak lepší, nemůže se pak stát, že by program spadl kvůli StackOverflow na příliš velkém/rozsáhlém adresáři a i režie (volání funkce má nějakou režii) je o něco málo menší.

Odpovědět 11.4.2013 11:15
https://www.facebook.com/peasantsandcastles/
Avatar
Kit
Redaktor
Avatar
Odpovídá na Luboš Běhounek Satik
Kit:11.4.2013 11:25

"Premature optimization is the root of all evil"

Filesystém má určitá omezení. Dřív narazíš na tato omezení, než na StackOverflow.

O režii rekurze v případě procházení filesystémem nemá smysl diskutovat. Je zcela zanedbatelná.

Editováno 11.4.2013 11:25
Odpovědět  +1 11.4.2013 11:25
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Luboš Běhounek Satik
Autoredaktor
Avatar
Odpovídá na Kit
Luboš Běhounek Satik:11.4.2013 11:26

Takhle nějak by vypadalo procházení adresářů ve složce bez rekurze, přes zásobník:

private List<String> VratVsechnySlozky(String slozka)
{
  Stack<String> zasobnik = new Stack<string>();
  List<String> tmp = new List<String>();

  zasobnik.Push(slozka);

  while (stack.IsNotEmpty)
  {
    String adresar = stack.Pop();
    foreach (String dir in Directory.GetDirectories(adresar))
    {
      stack.Push(dir);
      tmp.Add(dir);
    }
  }

  return tmp;
}
Odpovědět 11.4.2013 11:26
https://www.facebook.com/peasantsandcastles/
Avatar
Kit
Redaktor
Avatar
Odpovídá na Luboš Běhounek Satik
Kit:11.4.2013 11:40

Jenže máš výstup v jiném pořadí, než bys ho získal rekurzí. Záleží na tom, které pořadí v aplikaci potřebuješ.

Odpovědět 11.4.2013 11:40
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Luboš Běhounek Satik
Autoredaktor
Avatar
Odpovídá na Kit
Luboš Běhounek Satik:11.4.2013 12:04

Rekurzi bys ty slozky ziskal ve stejnem poradi, zalezi jen na tom, jak je napsana ta rekurze :)

Odpovědět 11.4.2013 12:04
https://www.facebook.com/peasantsandcastles/
Avatar
Luboš Běhounek Satik
Autoredaktor
Avatar
Odpovídá na Kit
Luboš Běhounek Satik:11.4.2013 12:07

Samotná rekurze je vnitřně taky řešena přes zásobník.

Odpovědět 11.4.2013 12:07
https://www.facebook.com/peasantsandcastles/
Avatar
Kit
Redaktor
Avatar
Odpovídá na Luboš Běhounek Satik
Kit:11.4.2013 12:19

Představ si, že v adresáři mám podadresáře pojmenované jmény autorů. V těchto podadresářích mám jako soubory jejich články. Chci převést tuto strukturu do jednoho souboru XML tak, abych měl uvnitř elementu autor elementy s jejich články. To je typický průchod stromem, tzv. traverzování. Ten tvůj algoritmus to neudělá.

Rekurze je vnitřně řešena přes zásobník. Nevidím tedy důvod, proč bych měl rekurzi přes zásobník obcházet.

Editováno 11.4.2013 12:21
Odpovědět 11.4.2013 12:19
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Kit
Redaktor
Avatar
Odpovídá na Luboš Běhounek Satik
Kit:11.4.2013 12:29

V jazycích jako je např. XSLT, bys byl bez rekurze úplně v loji, protože tam nejdou měnit hodnoty proměnných. Všechny jsou totiž final.

Odpovědět 11.4.2013 12:29
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Luboš Běhounek Satik
Autoredaktor
Avatar
Odpovídá na Kit
Luboš Běhounek Satik:11.4.2013 12:46

"Představ si, že v adresáři mám podadresáře pojmenované jmény autorů. V těchto podadresářích mám jako soubory jejich články. Chci převést tuto strukturu do jednoho souboru XML tak, abych měl uvnitř elementu autor elementy s jejich články"
Jak chceš tohle řešit rekurzivně? Tady nic k řešení rekurzivně není, když máš ve složce podsložky s jmény autorů a v nich soubory s jejich články, tak je tady rekurze úplně zbytečná, stačí ti dva vnořené cykly.

Nemůžeš srovnávat deklarativní (XSLT) jazyky s imperativními (java, C, psacal, atd.), tam se všechno řeší jinak...

Odpovědět 11.4.2013 12:46
https://www.facebook.com/peasantsandcastles/
Avatar
Kit
Redaktor
Avatar
Odpovídá na Luboš Běhounek Satik
Kit:11.4.2013 13:06

Proč mě chytáš za slovo? To byl jen příklad na to, že výpis podadresáře potřebuji tam, kde mám jméno adresáře. Prostě mám strom typu DOM a chci z něho udělat XML. Ten tvů algoritmus to neudělá.

Rekurzívní (na rozdíl od tvé verze funkční) podoba tvého příkladu:

import java.io.File;

public class ReadDir {
    public static void main(String[] args) {
        listFiles(new File("."));
    }

    public static void listFiles(File file) {
        if (file.isDirectory()) {
            System.out.println("Directory: " + file);
            for (File item : file.listFiles()) {
                listFiles(item);
            }
        } else {
            System.out.println(file);
        }
    }
}
Odpovědět 11.4.2013 13:06
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Kit
Redaktor
Avatar
Odpovídá na Luboš Běhounek Satik
Kit:11.4.2013 13:07

Java není imperativní jazyk. Asi sis ji s něčím spletl.

Odpovědět 11.4.2013 13:07
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Kit
David Čápka:11.4.2013 13:34

Pokud vím, imperativní jazyk je jazyk, kde popisujeme postup vedoucí k řešení zadání. To se v Javě děje.

Odpovědět  +1 11.4.2013 13:34
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
Luboš Běhounek Satik
Autoredaktor
Avatar
Odpovídá na Kit
Luboš Běhounek Satik:11.4.2013 13:36

Ty mě také pořád chytáš za slovo, tak jsem začal také.
Můj předchozí příklad jsem psal z hlavy a moc ho nekontroloval, ale základní myšlenku myslím vystihoval.

Citace: "Prostě mám strom typu DOM a chci z něho udělat XML. Ten tvů algoritmus to neudělá."

  • Proč by to neudělal? Stačí ho jen lehce upravit, tady máš obdobu tvé rekurzivní verze přes zásobník, tentokrát jsem ji i zkoušel spustit, aby jsi neměl výtky...
private static void listFiles(String slozka)
        {
            Stack<String> zasobnik = new Stack<string>();
            zasobnik.Push(slozka);

            while (zasobnik.Count > 0)
            {
                foreach (String dir in Directory.GetDirectories(zasobnik.Pop()))
                {
                    zasobnik.Push(dir);
                    Console.WriteLine("Directory: " + dir);
                    foreach (String file in Directory.GetFiles(dir))
                        Console.WriteLine(file);
                }
            }
        }

Java není imperativní jazyk? Odkdy? :D

Odpovědět 11.4.2013 13:36
https://www.facebook.com/peasantsandcastles/
Avatar
Luboš Běhounek Satik
Autoredaktor
Avatar
Odpovídá na David Čápka
Luboš Běhounek Satik:11.4.2013 13:41

V imperativním jazyce říkáš, jak přesně problém řešit, jakými příkazy.

V deklarativním jen definuješ, jaký chceš výsledek, už nedefinuješ, jak ho dosáhnout, sem patří tuším SQL a asi by se sem dal zařadit třeba Prolog.

Odpovědět 11.4.2013 13:41
https://www.facebook.com/peasantsandcastles/
Avatar
Homo
Člen
Avatar
Odpovídá na Kit
Homo:11.4.2013 13:47

Jen pro zajimavost, vypsani slozek v adresari pomoci NIO2 z Javy 7

Path pathToIterate = FileSystems.getDefault().getPath("C:");

DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>(){
    @Override
    public boolean accept(Path entry) throws IOException {
        return Files.isDirectory(entry);
    }
};

try(DirectoryStream ds = Files.newDirectoryStream(pathToIterate, filter)){
    for(Object p : ds){
        System.out.println(p.toString());
    }
} catch (IOException e) {
    e.printStackTrace();
}
Odpovědět  +1 11.4.2013 13:47
1010011 1000101 1011000
Avatar
Kit
Redaktor
Avatar
Odpovídá na David Čápka
Kit:11.4.2013 14:01

... ale nemá dít. Java je objektový jazyk, nemělo by záležet na pořadí provádění příkazů.

Odpovědět 11.4.2013 14:01
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Odpovídá na Kit
Lukáš Hruda (Luckin):11.4.2013 14:17

Na pořadí provádění příkazů záleží přeci vždycky, program přece nemůže skončit dřív než začal, nemůžeš zapisovat do souboru dřív než ho otevřeš, nemůžeš pracovat s daty ze vstupu dřív než je načteš... Nebo jsi to myslel jinak?

 
Odpovědět  +1 11.4.2013 14:17
Avatar
Kit
Redaktor
Avatar
Odpovídá na Homo
Kit:11.4.2013 14:21

To vypadá zajímavě. Rekurze je zde úplně skryta.

Odpovědět 11.4.2013 14:21
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Kit
Redaktor
Avatar
Odpovídá na Lukáš Hruda (Luckin)
Kit:11.4.2013 14:31

V objektovém jazyku nezáleží na pořadí deklarace tříd, metod ani proměnných. Podstatné je zapouzdření, co je čeho součástí. Na pořadí záleží obvykle až ve chvíli, kdy do bloku napíšu víc příkazů za sebe. Nemusí to však platit vždy, ty příkazy často bývají na sobě nezávislé.

Zpravidla je přece jedno, v jakém pořadí například volám settery jednoho objektu.

Odpovědět 11.4.2013 14:31
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Kit
Redaktor
Avatar
Odpovídá na Luboš Běhounek Satik
Kit:11.4.2013 14:37

V Javě se přece dá programovat deklarativně.

Odpovědět 11.4.2013 14:37
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Luboš Běhounek Satik
Autoredaktor
Avatar
Odpovídá na Kit
Luboš Běhounek Satik:11.4.2013 14:59

"V objektovém jazyku nezáleží na pořadí deklarace tříd, metod ani proměnných. Podstatné je zapouzdření, co je čeho součástí. Na pořadí záleží obvykle až ve chvíli, kdy do bloku napíšu víc příkazů za sebe. Nemusí to však platit vždy, ty příkazy často bývají na sobě nezávislé.

Zpravidla je přece jedno, v jakém pořadí například volám settery jednoho objektu."

Na pořadí deklarací tříd, metod ani proměnných nezáleží, ale záleží na pořadí příkazů uvnitř těch metod.
Na pořadí příkazů nezávisí právě v deklarativním programování, tam popíšeš problém a pak se hledá řešení, ale deklarativní/im­perativní a objektový/neob­jektový přístup jsou na sobě nezávislé, klidně můžeš programovat objektově imperativně, tam pak na pořadí provádění příkazů záleží.

"V Javě se přece dá programovat deklarativně."
To je možné (předpokládám, že je to nějaká obdoba LINQ z C# ?), ale to z ní nedělá (ani LINQ nedělá z C#) deklarativní jazyk, i když už můžeš některé části programu napsat deklarativně, stále je to primárně imperativní jazyk.

Odpovědět  +1 11.4.2013 14:59
https://www.facebook.com/peasantsandcastles/
Avatar
Odpovídá na Luboš Běhounek Satik
Lukáš Hruda (Luckin):11.4.2013 15:05

Pokud vím, tak všechny C-like jazyky jsou imperativní a mělo by se v nich asi podle toho také programovat. OOP je podtyp imperativního programování, ne jiný typ.

 
Odpovědět  +1 11.4.2013 15:05
Avatar
Kit
Redaktor
Avatar
Odpovídá na Luboš Běhounek Satik
Kit:11.4.2013 15:19

Zkusil jsem přepsat příklad od Homo tak, aby nezáleželo na pořadí příkazů. Jednotlivé bloky je možné libovolně přeházet, ale zapouzdření se musí dodržet. Vlastně jsem to ani moc upravovat nemusel. Není to ovšem praktické, protože tam nemám DI.

class PrintDir {
    public static void main(String[] args) {
        new PrintDir();
    }

    public PrintDir() {
        try {
            for(Object p : ds){
                System.out.println(p.toString());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    DirectoryStream ds = Files.newDirectoryStream(pathToIterate, filter);

    Path pathToIterate = FileSystems.getDefault().getPath("C:");

    DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>(){
        @Override
            public boolean accept(Path entry) throws IOException {
                return Files.isDirectory(entry);
            }
    };
}
Odpovědět 11.4.2013 15:19
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Luboš Běhounek Satik
Autoredaktor
Avatar
Odpovídá na Kit
Luboš Běhounek Satik:11.4.2013 15:28
DirectoryStream ds = Files.newDirectoryStream(pathToIterate, filter);
Path pathToIterate = FileSystems.getDefault().getPath("C:");

Tohle v Javě funguje? Že nejdřív použiješ nějakou proměnnou a pak ji teprve nadeklaruješ?

Odpovědět 11.4.2013 15:28
https://www.facebook.com/peasantsandcastles/
Avatar
Kit
Redaktor
Avatar
Odpovídá na Luboš Běhounek Satik
Kit:11.4.2013 15:33

Úplně v pohodě. Java s tím nemá problém.

Odpovědět 11.4.2013 15:33
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Luboš Běhounek Satik
Autoredaktor
Avatar
Odpovídá na Kit
Luboš Běhounek Satik:11.4.2013 15:44

To je zajímavé, zajímalo by mě, jak to na pozadí funguje o_O

Odpovědět 11.4.2013 15:44
https://www.facebook.com/peasantsandcastles/
Avatar
Odpovídá na Luboš Běhounek Satik
Lukáš Hruda (Luckin):11.4.2013 15:53

Řekl bych že program nejdříve vytvoří data a teprve potom je inicializuje. Třeba tohle...

public int a = b;
public int b = 1000;

...nefunguje.
Každopádně já bych to nedělal. I v objektovém jazyce by kód měl mít přeci nějakou logickou strukturu a neměl by používat věci které logicky ještě nebyly vytvořeny.

 
Odpovědět  +2 11.4.2013 15:53
Avatar
Kit
Redaktor
Avatar
Odpovídá na Luboš Běhounek Satik
Kit:11.4.2013 16:00

Jednoduše. U všeho, co je mimo metody, nezáleží na pořadí. Proto také do třídy píšu nejprve testovací třídu, pak metodu main(), pak konstruktor, pak veřejné metody a nakonec privátní metody. Proměnné objektu obvykle dávám před konstruktory, ale mohou být kdekoli. Totéž s objekty anonymních tříd.

Odpovědět 11.4.2013 16:00
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Luboš Běhounek Satik
Autoredaktor
Avatar
Odpovídá na Lukáš Hruda (Luckin)
Luboš Běhounek Satik:11.4.2013 16:03

Souhlasím, musí to působit hodně zmatečně, když vidím třeba ve funkci použitou nějakou proměnnou, která se tam ani nepředává parametrem a ani nebyla vytvořena do té doby, tak bych ji hledal mezi vlastnostmi třídy a asi bych byl hodně zmatený, až bych ji ani tam nenašel, ještě že C# tuhle šílenost nedovoluje :)

Odpovědět 11.4.2013 16:03
https://www.facebook.com/peasantsandcastles/
Avatar
Luboš Běhounek Satik
Autoredaktor
Avatar
Odpovídá na Kit
Luboš Běhounek Satik:11.4.2013 16:05

Ano to vím, že cokoliv mimo metody může být ve třídě uspořádáno libovolně, ale imperativní programování se týká samotného výkonného kódu, tedy u většiny jazyků těch příkazů uvnitř funkcí.

Editováno 11.4.2013 16:06
Odpovědět 11.4.2013 16:05
https://www.facebook.com/peasantsandcastles/
Avatar
Kit
Redaktor
Avatar
Odpovídá na Lukáš Hruda (Luckin)
Kit:11.4.2013 16:16

Zajímavé. Asi je dobře, že to takhle nefunguje. Program by měl mít nějakou logiku uspořádání, aby se v tom dalo vyznat. Na tohle jsem nenarazil zřejmě proto, že této vlastnosti nezneužívám a snažím se psát programy přehledně.

Odpovědět 11.4.2013 16:16
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Odpovídá na Kit
Michal Žůrek - misaz:11.4.2013 16:31

Tak to já sem přesný opak, nepřehledný kód mi nevadí.

 
Odpovědět 11.4.2013 16:31
Avatar
Kit
Redaktor
Avatar
Odpovídá na Michal Žůrek - misaz
Kit:11.4.2013 16:36

Já musím... Když si zvykneš psát kód úhledně, tak je to fajn. Navíc mám kvalitní editor, který mi v tom značně pomáhá.

Odpovědět  +1 11.4.2013 16:36
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Odpovídá na Michal Žůrek - misaz
Michael Olšavský:11.4.2013 16:38

To jsme viděli v Machru na particles system :D . Ale i přesto se k výsledku dopracuješ

 
Odpovědět 11.4.2013 16:38
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Michal Žůrek - misaz
David Čápka:11.4.2013 17:13

To proto, že jsi ještě nedělal na projektu velkého rozsahu, jinak by ti rychle vadit začal :)

Odpovědět  +1 11.4.2013 17:13
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
Odpovídá na David Čápka
Michal Žůrek - misaz:11.4.2013 17:32

Vzhledem k mému věku, bude trvat ještě pár let než se dostanu k velkým projektům.

 
Odpovědět 11.4.2013 17:32
Avatar
Kit
Redaktor
Avatar
Odpovídá na Michal Žůrek - misaz
Kit:11.4.2013 17:42

Na věku nezáleží. Už od zhruba 500 řádek mi nepřehledný kód začíná vadit, i když je to třeba jen malý zkušební program pro vlastní potřebu. Proto se tomu snažím předcházet. Později se taková špageta špatně refaktoruje.

Odpovědět 11.4.2013 17:42
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Petr Nymsa
Redaktor
Avatar
Odpovídá na Michal Žůrek - misaz
Petr Nymsa:11.4.2013 17:43

Sice i u mě to nejsou nijak extra velké projekty. Ale když budeš mít štěstí a dostaneš se na nějakou dobrou střední, tak děláme různě v týmech a není nic horšího když ti někdo pošle kus zdrojáku, to že nemá komenty se ještě dá snést, ale nejhorší je, když ti někdo zobrazí kód kde máš proměnné ve stylu

a,b,c pk,zb,pom

, autor se vyzná, má systém zkratek, ale nikdo jiný :) Takže i já se snažím už psát kódy přehledně, používám komentáře, nejen pro sebe (zapomínám :D ) ale i jakoby pro jiný, sice ty kódy nikdy asi nikdo nepoužije, ne asi, ale určitě, ale beru to jako přípravu :)

Odpovědět  +1 11.4.2013 17:43
Pokrok nezastavíš, neusni a jdi s ním vpřed
Avatar
Kit
Redaktor
Avatar
Odpovídá na Petr Nymsa
Kit:11.4.2013 18:05

Hodně záleží na dekompozici projektu. Třída by neměla být delší než 60 řádek, metoda delší než 15 řádek a řádek delší než 80 znaků. Je to hodně omezující, ale když si na to programátor zvykne, tak to vůbec není špatné.

Odpovědět 11.4.2013 18:05
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Odpovídá na Petr Nymsa
Michal Žůrek - misaz:11.4.2013 18:19

já rád nazývám proměnné:

neco
neco1
test
test1
:D

je možné že něco z toho dokonce zůstalo v tom machrovi.

Editováno 11.4.2013 18:20
 
Odpovědět 11.4.2013 18:19
Avatar
Honza Bittner
Šupák
Avatar
Odpovídá na Michal Žůrek - misaz
Honza Bittner:11.4.2013 18:26

jak užitečné a přehledné ... :D

Odpovědět 11.4.2013 18:26
Milovník Dartu. Student FIT ČVUT. Sleduj mě na https://twitter.com/tenhobi a ptej se na cokoli na https://github.com/...
Avatar
Odpovídá na Kit
Michal Žůrek - misaz:11.4.2013 18:33

kde se toto píše?

 
Odpovědět 11.4.2013 18:33
Avatar
Petr Nymsa
Redaktor
Avatar
Odpovídá na Michal Žůrek - misaz
Petr Nymsa:11.4.2013 18:47

Tak za tyto proměnné bych tě asi praštil notebookem :P :D .. ne, není dobré takto proměnné nazývat :) Schválně za půl roku, jestli budeš vědet o co se jedná. Co za půl roku, možná tak za měsíc :).. u mě občas i dřív :D

Odpovědět 11.4.2013 18:47
Pokrok nezastavíš, neusni a jdi s ním vpřed
Avatar
Hartrik
Redaktor
Avatar
Hartrik:11.4.2013 19:05

Nedávno jsem si stáhnul jeden open-source projekt a našel jsem tam třídu, která měla 3500 řádků, z toho 90 řádků importů a konstruktor s 18 argumenty :D

 
Odpovědět 11.4.2013 19:05
Avatar
Odpovídá na Hartrik
Michal Žůrek - misaz:11.4.2013 19:43

že, takový kraťoulinký zdrojový kód... :D

 
Odpovědět 11.4.2013 19:43
Avatar
Drahomír Hanák
Tým ITnetwork
Avatar
Odpovídá na Michal Žůrek - misaz
Drahomír Hanák:11.4.2013 20:33

To se nikde nepíše. Je to doporučení, kterého by ses měl držet. Prostě jedna z mnoha věcí, která by měla, při dobrém návrhu, vést k lepší čitelnosti a zčásti taky k lepšímu návrhu kódu. Není to žádné dogma, ale doporučuji se o to alespoň snažit.

Hartrik Třída, která má 18 argumentů v konstruktoru, je očividně špatně navržená ;)

Editováno 11.4.2013 20:34
 
Odpovědět  +1 11.4.2013 20:33
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Kit
David Čápka:11.4.2013 20:50

Třída mi připadá zbytečně krátká, to máš 3 metody na třídu. Když se mi v aplikaci množí třídy, obvykle se v ní vyznám hůře, než v méně delších třídách. Ale to asi záleží na člověku. S 15ti řádky souhlasím, 80ti na délku také.

Odpovědět  +2 11.4.2013 20:50
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
Luboš Běhounek Satik
Autoredaktor
Avatar
Odpovídá na Kit
Luboš Běhounek Satik:11.4.2013 21:47

80 řádků na třídu je požadavek tak pro studentský projektíky, nevím, jak bys to chtěl udržet třeba na projektu, kde největší tabulka měla 170 sloupců a tabulek tam bylo celkem přes 100 (jsou to cca reálná čísla z jednoho projektu z mého předchozího zaměstnání)...

Jinak samozřejmě také jsem proti špagetovému kódu, ale ne vždy to jde a jsou to jen doporučená čísla použitelná pro menší projekty.

Editováno 11.4.2013 21:49
Odpovědět  +1 11.4.2013 21:47
https://www.facebook.com/peasantsandcastles/
Avatar
Odpovídá na David Čápka
Lukáš Hruda (Luckin):11.4.2013 22:00

Asi záleží dost na jazyce, ale v C++ si nějak nedokážu představit ani těch 15 řádků na funkci. To abych každou funkci rozděloval do několika menších a dělal si v kódu spoustu zbytečných funkcí navíc a třídu abych měl plnou privátních metod. Běžně mívám funkce 30 - 40 řádků, a rozdělovat to do několika menších mi přijde ve výsledku méně přehledné a ještě je s tím víc práce.

 
Odpovědět  +2 11.4.2013 22:00
Avatar
Kit
Redaktor
Avatar
Odpovídá na Michal Žůrek - misaz
Kit:12.4.2013 10:02

Už hodněkrát jsem to četl jako požadavek různých vedoucích projektů. Je to doporučení, není to dogma. Pokud však tato pravidla systematicky porušuješ, něco je špatně. Pokud některé porušíš např. v každé páté třídě, je to OK.

Když si na to zvykneš, je to docela fajn. Za den takových tříd naprogramuješ víc :)

Odpovědět 12.4.2013 10:02
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Kit
Redaktor
Avatar
Odpovídá na David Čápka
Kit:12.4.2013 10:09

Většina metod se obvykle vejde na 5-10 řádek, takže těch metod může být ve třídě docela dost. Pokud nepíšeš getter/setter na každou vnitřní proměnnou, tak to ani není moc omezující.

Odpovědět 12.4.2013 10:09
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Kit
Redaktor
Avatar
Odpovídá na Luboš Běhounek Satik
Kit:12.4.2013 10:11

Tabulka, která má 170 sloupců, je chybně navržena. Asi je dobře, že jsi z takového zaměstnání odešel.

Odpovědět 12.4.2013 10:11
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Luboš Běhounek Satik
Autoredaktor
Avatar
Odpovídá na Kit
Luboš Běhounek Satik:12.4.2013 10:19

"Většina metod se obvykle vejde na 5-10 řádek, takže těch metod může být ve třídě docela dost."

Ano, ve školním projektě nebo jednoduchých webovkách možná.

Odpovědět 12.4.2013 10:19
https://www.facebook.com/peasantsandcastles/
Avatar
Kit
Redaktor
Avatar
Odpovídá na Hartrik
Kit:12.4.2013 10:19

Jeden oblíbený redakční systém má hlavní modul na 15000 řádcích. Dovedeš si jistě představit, jak jsem asi nadával, když jsem v něm opravoval název nefungující řídící proměnné cyklu, která byla nastavena jako globální pro celý projekt čítající asi 130000 řádek.

Evidentně se těmito pravidly každý vývojář neřídí.

Odpovědět 12.4.2013 10:19
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Kit
Redaktor
Avatar
Odpovídá na Luboš Běhounek Satik
Kit:12.4.2013 10:22

Přiznám se, že výstupní šablonu mívám delší.

Odpovědět 12.4.2013 10:22
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Зайчик
Člen
Avatar
Odpovídá na Kit
Зайчик:12.4.2013 10:27

Mě se metody většinou vejdou do těch 15-20 řádků ale třídy mám o hodně delší než říkáš. To z toho důvodu abych neměl 500 tříd v tom se pak moc nevyznam a ještě aby se v tom vyznal někdo kdo dělá projekt třeba semnou.

Odpovědět 12.4.2013 10:27
Коммунизм для нашего будущего!
Avatar
Luboš Běhounek Satik
Autoredaktor
Avatar
Odpovídá na Kit
Luboš Běhounek Satik:12.4.2013 10:33

Protože ty pravidla občas může být i lehce kontraproduktivní.

Osobně ve větším projektu raději uvidím pěkně na jednom místě jednu funkci na 100 řádků, než místo toho 10 menších funkcí, každá na 10 řádků.

Mluvím tu teď o projektech, kde má třída třeba 10 000 řádků, je rozdíl mít funkcí 100 nebo 1000.

Btw opakuji otázku, která už ti byla pokládána, na jakém nejsložitějším projektu jsi někdy pracoval?

Odpovědět 12.4.2013 10:33
https://www.facebook.com/peasantsandcastles/
Avatar
Kit
Redaktor
Avatar
Odpovídá na Зайчик
Kit:12.4.2013 10:39

Když používáš členění do balíků, tak tisíce tříd nevadí.

Odpovědět 12.4.2013 10:39
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Luboš Běhounek Satik
Autoredaktor
Avatar
Odpovídá na Kit
Luboš Běhounek Satik:12.4.2013 10:44

Nevím jak ty, ale čím víc tříd v projektu (pokud jich je opravdu hodně), tím více se začínám ztrácet a hůře si to dokážu celé představit.

Odpovědět 12.4.2013 10:44
https://www.facebook.com/peasantsandcastles/
Avatar
Kit
Redaktor
Avatar
Odpovídá na Luboš Běhounek Satik
Kit:12.4.2013 12:55

Proto jsou v Javě balíky. Slouží k tomu, aby sis aplikaci logicky rozdělil. Plošná struktura se dá použít jen na menší projekty.

Odpovědět 12.4.2013 12:55
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Hartrik
Redaktor
Avatar
Odpovídá na Kit
Hartrik:12.4.2013 20:13

Docela by mě zajímalo, jak se něco takového může stát u tak velkého projektu, na kterém určitě pracoval celý tým programátorů.

 
Odpovědět  +1 12.4.2013 20:13
Avatar
Kit
Redaktor
Avatar
Odpovídá na Hartrik
Kit:13.4.2013 9:53

To netuším. Přepisovat jim to nebudu, ale určitě bych ten kód zkrátil asi na třetinu. Je na tom patrné, jak se neustále nabalují nové vlastnosti bez revize těch stávajících.

Odpovědět 13.4.2013 9:53
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Hartrik
David Čápka:13.4.2013 9:58

Jednoduše, vznikl v době, kdy PHP nebylo objektové. Teď se to nikomu přepisovat nechce.

Odpovědět  +3 13.4.2013 9:58
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
Luboš Běhounek Satik
Autoredaktor
Avatar
Odpovídá na Kit
Luboš Běhounek Satik:13.4.2013 10:19

Téměř každý větší projekt vzniká nabalováním jako sněhová koule. A na revize nejsou téměř nikde finance ani čas.

Odpovědět 13.4.2013 10:19
https://www.facebook.com/peasantsandcastles/
Avatar
Kit
Redaktor
Avatar
Odpovídá na Luboš Běhounek Satik
Kit:13.4.2013 10:24

Pokud je dobrý návrh základu, tak k tomu ani nemusí dojít. Dobrou prevencí je TDD, refaktorovat pak můžeš kdykoli.

Odpovědět 13.4.2013 10:24
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Luboš Běhounek Satik
Autoredaktor
Avatar
Odpovídá na Kit
Luboš Běhounek Satik:13.4.2013 10:39

S tím návrhem je trochu potíž, protože téměř každý větší projekt se vyvíjí postupně a nikdy nevíš, co za požadavky ti přijde.

Odpovědět 13.4.2013 10:39
https://www.facebook.com/peasantsandcastles/
Avatar
Kit
Redaktor
Avatar
Odpovídá na Luboš Běhounek Satik
Kit:13.4.2013 10:43

Právě proto je dobré používat TDD, i když na začátku to připadá zdržující.

Odpovědět 13.4.2013 10:43
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Frunta
Redaktor
Avatar
Frunta:16.4.2013 19:46

Myslím si, že by bylo dobré se v článku zmínit i o dalších využitích rekurze. Mě bylo učeno například vyplňování určité části mapy (mapou mám na mysli int ahoj[50][50]).

Editováno 16.4.2013 19:47
 
Odpovědět 16.4.2013 19:46
Avatar
Odpovídá na Kit
Peter Gasparik:1.3.2017 19:16

A čo je to TDD ?

Odpovědět 1.3.2017 19:16
while (noSuccess) { tryAgain(); if (Dead) break;
Avatar
patrik.valkovic
Šéfredaktor
Avatar
Odpovídá na Peter Gasparik
patrik.valkovic:1.3.2017 19:18

Test Driven Development - první píšeš testy a teprve potom samotnou funkcionalitu.

Odpovědět 1.3.2017 19:18
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
Peter Gasparik:1.3.2017 19:30

Aha, ďakujem, značím si to do denníčka :).

Odpovědět 1.3.2017 19:30
while (noSuccess) { tryAgain(); if (Dead) break;
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 82 zpráv z 82.