Svi postovi sa bloga: ViewSource

Problem

Recimo da neko naruči od vas da napravite neku aplikaciju. Vi sve odradite i pošaljete korisniku, a on ne zna šta da radi s tim jer ne može da pokrene vaš program. Posle niza neuspešnih pokušaja da preko telefona navedete korisnika da kaže u čemu je zapravo problem (Jesi li instalirao? Da li uopšte možeš da pokreneš nešto? Da li otvaraš pravu stvar?), odlazite do korisnika i shvatate da on nema potreban softver za pokretanje vašeg koda (odgovarajući .Net Framework, JRE ili nešto treće). Zvuči poznato? )
Rešenje je naravno da mu kažete “sa te i te adrese skini to i to i instaliraj”, ali postaje problem ako ćete svakom korisniku slati program i spisak potrebnog softvera koji treba da download-uje kako bi sve radilo.

Rešenje: Install Wizard

Install Wizard (Demo verziju) možete besplatno skinuti sa http://www.wininstaller.com/. Ukoliko želite, možete kupiti Full verziju po ceni od 90 do 400 dolara, ali za neke osnovne stvari, Demo verzija “završava posao”.
Kada pokrenete Install Wizard i idete na New Project, možete videti da je već integrisano dosta stvari koje su vam potrebne. Čak je moguće definisati da li nešto treba instalirati u Program Files, Windows, MyPictures ili nekom četvrtom folderu.

Osnovne funkcionalnosti

Uz Install Wizard ide jako dobar Help i mislim da svako može da se snađe, ali ipak ću objasniti neke osnovne funkcionalnosti.

  • U delu General Information, možete podesiti neke informacije kao npr ime programa koji se instalira, verzija, instalacioni folder, neke osnovne podatke o proizvođaču softvera itd.

  • U delu Files se dodaju fajlovi koji će biti instalirani, u Setup Types se može definisati šta obuhvata tipična (Typical) instalacija, šta minimalna, a moguće je napraviti i Custom instalaciju.
  • U okviru Splash Screen možete dodati neku sliku u format .bmp, .jpg ili .gif kao SplashScreen.
  • Dialog Boxes je sekcija koja nudi izbor između nekoliko prozora koji će se pojavljivati u toku instalacije, njihov redosled i sadržaj.
  • Background Window omogućava dva različita izgleda pozadine tokom instalacije. Moguće je isključiti pozadinu, ovo znači da će instalacija biti kao prozor na desktopu. Druga opcija (često viđena prilikom instalacije PC igara) je da se postavi neka pozadina, to može biti naka slika vezana za softver koji se instalira ili bilo šta drugo.

  • Moguće je još mnogo toga definisati, to ostavljam vama. Dodaću još samo Requirements u kome možete zadati koji operativni sistem je podržan, koji procesor je potreban, koliko RAM-a, rezolucija, itd.
Zaključak

Na kraju, reći ću samo da je u Demo verziji moguće samo napraviti Single Image Build Setup, koji možete naći u folderu My Setups (verovatno na C:\My Setups) nakon što build-ujete instalaciju. Takođe, Install Wizard je alat pomoću koga možete napraviti i Update, ne samo inicijelnu instalaciju. To se postiže korišćenjem Template-a i vezuje se za prethodno kreiran projekat (instalaciju).

Kratak osvrt na prethodni deo

Ćao ljudi! Prošlo je tačno dve nedelje od kako smo objavili drugi deo serijala o kreiranju WordPress teme. Pre nego što nastavimo dalje, hajde na brzaka da se podsetimo šta smo sve radili u prethodnom delu:

  • sređivali smo header, odnosno pomoću bloginfo() funkcije smo ubacivali linkove do CSS i JavaScript fajlova.
  • izdvojili smo delove našeg sajta koji su identični na svim stranama (header i footer) i od tih celina kreirali posebne template fajlove koje smo smestili u root direktorijum naše Aurelius teme i sve to uz pomoć funkcija get_header() i get_footer().
  • kreirali smo 4 strane iz WP-Admin panela i njih prikazali u navigaciji pomoću wp_list_pages() funkcije, ali i nekoliko parametara koje ta funkcija prima (title_li, sort_column, sort_order), kako bismo prikazali stavke u navigaciji onako kako je dizajner osmislio.
  • završili smo page template koji je odgovoran za prikaz stranica koje smo definisali (i koje ćemo u buduće definisati) u Admin panelu.
  • Na posletku, pomenuli smo WordPress loop i objasnili kako možemo uz minimalan trud da izvučemo neke podatke iz baze.

Okej, ovo je bio kratki rezime prethodnog dela sa naglašenim funkcijama koje bi trebalo da ostanu svim čitaocima u glavi – ukoliko je nešto nepoznato, bilo bi poželjno da se vratite na prethodni (ili čak prvi članak) kako biste bez ikakvih problema mogli da ispratite nove zanimljivosti koje slede.

1. Dodatno sređivanje navigacije

Primetio sam da smo u prethodnom delu zaboravili na dve stvari kada je u pitanju navigacija: trenutno, ukoliko kliknete na link Home, nećete otići na početnu stranicu kao što očekujete, već ostajete na trenutnoj i drugo – ne postoji strelica iznad stavke u navigaciji koja služi kao indikator posetiocu da se nalazi na određenoj stranici.

Ispis linka ka početnoj strani

Prvu stavku ćemo lako rešiti – ukoliko pogledamo fajl header.php, videćemo da nismo ispisali vrednost koju je get_home_url() funkcija vratila. Dakle, umesto linije:


1
<li><a href="<?php get_home_url(); ?>">Home</a></li>

potrebno je ubaciti:


1
<li><a href="<?php echo get_home_url(); ?>">Home</a></li>
Prikaz tanke crne linije na vrhu stranice

Ovde postoje dva problema: ukoliko pogledate ponovo HTML/CSS temu koju smo skinuli sa NetTuts-a, videćete da pored pomenute strelice nedostaje i crna tanka linija na samom vrhu stranice. Razlog zbog kojeg se ona ne prikazuje ćete najlakše otkriti tako što odradite inspect elemenata koji bi mogli da imaju tu crnu liniju (to su body ili div#wrapper). Ja za ovakve koristim Firebug i preko njega sam detektovao da body kao svoju pozadinu ima sličicu url(“../images/bg.png”) repeat-x scroll 0 0 #FFFFFF, ali Firebug prikazuje “Failed to load the given URL”. Kada dobijete takvu grešku, odmah znate da u CSS fajlu putanja do sličice nije dobra. Naša tema ima sledeću strukturu (ovo smo već videli, ali hajde da ponovimo samo za one foldere i fajlove koji su nam trenutno bitni):

-aurelius

– images (folder)

–style.css

Dakle, bitna stvar da uočite ovde je da su style.css i images folder na istom nivou. Ukoliko otvorite CSS fajl teme, videćete na liniji 63 sledeću liniju:


1
2
3
4
5
6
body {
  background:url(../images/bg.png) repeat-x #FFFFFF;
  font-size:12px;
  font-family:'Lucida Grande', 'Lucida Sans Unicode', Tahoma, Arial, san-serif;
  color:#000000;
}

To zapravo znači da će WordPress ići jedan folder unazad u odnosu na onaj u kome se nalazi style css i tu tražiti folder images. Upravo je to razlog zašto je Firebug izbacio grešku da browser nije uspeo da učita sličicu na definisanoj lokaciji. Potrebno je da obrišemo te dve tačkice, pa će browser onda direktno ići u images folder kako bi pronašao bg.png sličicu. Dakle, umesto linije iznad ubacite:


1
2
3
4
5
6
body {
    background:url(images/bg.png) repeat-x #FFFFFF;
    font-size:12px;
    font-family:'Lucida Grande', 'Lucida Sans Unicode', Tahoma, Arial, san-serif;
    color:#000000;
}

Pošto u temi ima sigurno još sličica koje vode ka pogrešnim putanjama, bilo bi idealno kada bismo još sada to ispravili. Možete ići ručno, liniju po liniju i tako ispraviti putanje, ali ja se držim stare dobre find-replace tehnike: u omiljenom editoru za u find polje unesite: ../images, a u replace: images.

Prikazivanje strelice iznad aktivne stranice

Sledeća stvar je po meni zanimljivija, mada se svodi na isto – imamo greščicu u koracima negde u CSS-u, samo je potrebno da provalimo gde. Ovde savetujem sledeće: pogledajte kako je dizajner napravio da radi strelica – indikator aktivne stranice i istu stvar primenite i vi. Dakle, inspect-ovanjem navigacije na HTML/CSS temi (recimo kada nam je u browseru otvorena About us tema) možemo primetiti sledeće:


1
2
3
4
5
6
7
<ul id="navigation" class="grid_8">
    <li><a href="contact.html"><span class="meta">Get in touch</span><br />Contact Us</a></li>
    <li><a href="blog.html"><span class="meta">Latest news</span><br />Blog</a></li>
    <li><a href="portfolio.html"><span class="meta">Our latest work</span><br />Portfolio</a></li>
    <li><a href="about.html" class="current"><span class="meta">Who are we?</span><br />About</a></li>
    <li><a href="index.html"><span class="meta">Homepage</span><br />Home</a></li>
</ul>

Dakle, link na about us stranici ima klasu current. Hajde da gvirnemo u CSS kako bismo saznali šta radi ta klasa (mada je i više nego očigledno). Na liniji 161. ćete pronaći upravo ono što želimo da vidimo:


1
2
3
ul#navigation li a.current {
    background:url(images/triangle.gif) no-repeat center top;
}

Pošto smo utvrdili da se strelica prikazuje u onoj stavki navigacije čiji link ima klasu current, potrebno je da istražimo kako WordPress utvrđuje koja stranica je trenutno aktivna. Mi smo za našu navigaciju koristili funkciju wp_list_pages(), a dobra stvar je da ona, pored toga što ispisuje sve stranice koje imamo u bazi, vrši evidenciju i o tome koja stranica je trenutno aktivna. Da bih vam približio ovo, ponovo ću vas uputiti na Firebug, samo što ćete ovog puta otvoriti blog i neka ponovo bude otvorena About Us stranica. Videćete sledeći kod:


1
2
3
4
5
6
7
8
<!-- Navigation Menu -->
<ul id="navigation" class="grid_8">
    <li class="page_item page-item-11"><a href="http://localhost/wordpress/contact/">Contact</a></li>
    <li class="page_item page-item-9"><a href="http://localhost/wordpress/blog/">Blog</a></li>
    <li class="page_item page-item-7"><a href="http://localhost/wordpress/portfolio/">Portfolio</a></li>
    <li class="page_item page-item-5 current_page_item"><a href="http://localhost/wordpress/about/">About</a></li>
    <li><a href="http://localhost/wordpress" class="current">Home</a></li>
</ul>

Dve stvari su nam bitne ovde. Prva, WordPress ne koristi klasu current, već current_page_item. Druga je to da WordPress tu klasu ne stavlja na link (a tag) već na njegovog roditelja (li tag). Sve što je potrebno da uradimo je da izmenimo CSS kako bismo ideju dizajnera prilagodili načinu na koji radi WordPress. Dakle, u style.css fajlu, umesto 161. linije ubacite:


1
2
3
ul#navigation li.current_page_item a {
    background:url(images/triangle.gif) no-repeat center top;
}
Strelica na početnoj strani? Funkcija is_home()

Ukoliko vam je ovo palo na pamet dok ste čitali – čestitam. Šta je ovde problem? Sećate se da smo pomoću funkcije wp_list_pages() izlistali sledeće stranice: About Us, Portfolio, Blog i Contact. Home strana je dodata ručno, što znači da WordPress nikako ne može da sam po sebi stavi strelicu iznad Home linka u situaciji kada je posetilac na početnoj stranici. Ipak, mi to možemo veoma jednostavno rešiti tako što ćemo sami ispitati da li je trenutna stranica home.php i ukoliko jeste, dodaćemo klasu current_page_item prvom li tagu u navigaciji. U ovakvim slučajevima koristimo funkciju is_home() koja vraća true kada je posetilac na početnoj stranici, odnosno false u suprotnom. Dakle, modifikujte ručno dopisanu liniju (header.php fajl) za prikaz Home linka u navigaciji i to na sledeći način:


1
<li <?php if(is_home()) { echo 'class="current_page_item"'; } ?>><a href="<?php echo get_home_url(); ?>">Home</a></li>
2. Priprema terena za Blog stranicu

Došli smo do dela koji zapravo predstavlja glavni zalogaj za ovaj deo serijala – izgradnja blog stranice na kojoj će se izlistavati svi postovi koje budemo imali u bazi. Na WordPress sajtovima se obično postovi izlistavaju na početnoj stranici (pogledajte recimo ViewSource blog), međutim s obzirom da mi ne pravimo klasičan blog, već sajt koji u svom sklopu ima i blog, moraćemo da preduzmemo nekoliko stvari kako bismo omogućili da se postovi izlistavaju na stranici Blog.

Ukoliko u ovom trenutku kliknemo na Blog stranicu, dobićemo tekst koji smo definisali u Admin panelu, kao sadržaj za tu stranicu i to zato što sve stranice u WordPress-u po defaultu koriste page.php template, koji smo razvili u prethodnom delu. U ovom konkretnom slučaju, nama ne odgovara da blog stranica koristi taj template, već neki drugi u kome postoji logika za izlistavanje svih postova. Loša vest je da WordPress sam po sebi nema tako nešto out-of-the-box, ali veoma ohrabrujuća vest je da je to vrlo jednostavno za pravljenje. Moraćemo, dakle, da uradimo dve stvari:

  • da kreiramo poseban template za izlistavanje svih postova (nazvaćemo ga blog.php)
  • da iz WP-Admin panela stranici Blog dodelimo taj template.
  • Template name: Blog

    Ukoliko se sećate, još u prvom delu ovog serijala smo kreirali fajl blog.php i u njega ubacili sve što se nalazilo na stranici blog.html, koji smo dobili u sklopu HTML/CSS teme. U drugom delu smo izvršili njegovo sređivanje, pa smo delove koji su isti na svim stranama (header i footer) ubacili pomoću funkcija get_header() i get_footer(). U ovom nastavku ćemo ga dodatno srediti. Za početak, napravićemo od njega template koji će WordPress prepoznati i koji će moći da se dodeli Blog strani iz admin panela. Sve što treba da uradimo je da na samom početku blog.php fajla imamo sledeći kod:

    
    1
    2
    3
    <?php
    /* Template name: Blog */
     get_header(); ?>

    Ukoliko se pitate, Template name treba da bude pod komentarima i na taj način vi bukvalno kažete WordPress-u da je taj fajl ustvari još jedan template i da ćete ga koristiti umesto standarnog page.php template-a na nekoj od stranica. Naravno, iako ste ga na ovaj način registrovali novi template u sistemu, ne morate nikad da ga iskoristite – WordPress se neće buniti zbog toga, ali će vam ubuduće prilikom kreiranja nove stranice iz Admin panela uvek ponuditi kao opciju da njoj dodelite taj template. Ta opcija se nalazi desno od sadržaja stranice (Page attributes->Template->Blog).

    // SLIČICA (nedostaje): page_template.png

    Naravno, mi ćemo izabrati da Blog strana koristi upravo taj novi template. Ukoliko sada refreshujemo naš blog i posetimo Blog stranicu, videćemo da se njen sadržaj promenio – više ne stoji ono što piše u Admin panelu na toj stranici, već je prikazan sadržaj iz fajla blog.php. Ukoliko je i kod vas tako, sjajno, na dobrom ste putu, ali ukoliko nije – pažljivo proverite da li ste dobro ispratili prethodne korake.

    Kreiranje nekoliko kategorija

    Pre nego što se detaljnije pozabavimo Blog stranicom iz programerskog ugla, moramo da imamo podatke sa kojima ćemo da radimo. Tu pre svega mislim na kategorije i postove. Sećate se da smo još u uvodnom delu objasnili da su svi blog postovi u WordPress-u raspoređeni po kategorijama, pa ćemo zbog toga prvo kreirati nekoliko kategorija, a onda i nekoliko postova.

    Da biste kreirali kategorije, idite na WP-Admin ->Posts -> Categories i napravite sledeće kategorije (spisak sam preuzeo iz sidebar-a na blog stranici):

    • So who are we?
    • Philosophy
    • History
    • Jobs
    • Staff

    Čisto da naglasim za one koji prvi put kreiraju kategorije u WordPress-u: potrebno je samo da popunite polje Name, dok polja Slug, Parent i Description slobodno preskočite.

    Kreiranje nekoliko postova

    Sledeća stvar kojom ćemo se pozabaviti je kreiranje nekoliko blogpostova, kako bismo imali šta da prikažemo na Blog stranici. Kao i prethodna stvar sa kategorijama, sve se završava u Admin panelu (Posts->Add new post). Ako pogledamo kako izgleda blog template, videćemo da moramo da za svaki post definišemo sledeće podatke:

    • naslov
    • sadržaj
    • kategoriju u kojoj pripada
    • sličica koja će da se prikazuje uz sam post

    Prve tri stavke su veoma jednostavne i ne zahtevaju nikakvo dodatno pojašnjavanje. Sličicu koja će ići uz post možete definisati na nekoliko načina od kojih ću ja pomenuti dva: kao featured image i kao meta field.

    Featured image je po defaultu nedostupan i moraćete prvo morate da omogućite, tako što ćete kreirati novi fajl, functions.php u root direktorijumu teme i onda unutra paste-ovati sledeći kod:

    
    1
    2
    3
    <?php
    add_theme_support( 'post-thumbnails' );
    ?>

    Nakon toga, refreshujte stranicu u Admin panelu u kojoj ste krenuli da pišete blog post i videćete da vam se sa desne strane pojavila opcija Featured image. Sve je veoma jednostavno, možete kliknuti na Set featured image i uploadovati željenu sličicu.

    Meta field je, kao što mu samo ime kaže, neka dodatna informacija o postu. Konrektno, mi želimo da uz svaki post imamo zakačenu sličicu (koju ćemo nazivati na dalje thumb). Ispod sadržaja posta, videćete novi set opcija po imenu Custom fields. Da biste stvorili input polje za upload postavljanje sličice (thumb-a), potrebno je da kliknete na Enter new i pod Name unesete thumb, a pod Value link do sličice koju želite da zakačite za post. Ukoliko još uvek niste uploadovali sličicu na blog i nemate njen link, ispratite sledeće korake:

    Idite na WP-Admin->Media -> Add new kako biste uploadovali sliku. Kada to završite, vaša slika će biti dostupna u Media -> Library. Pre nego što zatvorite prozor kojim ste uploadovali sliku, obavezno kopirajte link do nje (File URL) i to prekopirajte u Value polje koje smo malopre pomenuli. Naravno, sada možete kliknuti na Update (sa desne strane) kako biste sačuvali sve promene. Jedna lepa stvar ovde je da WordPress pamti sva vaša meta polja, tako da kada ubuduće pišete novi post i dođete do dela za upload sličice preko Meta field-a, nećete više morati da idete na Add new, već da iz select box-a izaberete thumb. Naravno, kao Value ćete uvek morati da upisujete link do sličice koju želite da zakačite uz post.

    Pre nego što pređemo na poslednji deo za danas, želim da vam skrenem pažnju na dve stvari:

    1. napomena: Ukoliko ne vidite Featured image/Custom Fields, odmah ispod crne trake skroz na vrhu ekrana, ispod Vašeg imena stoji Screen Options. Čekirajte opciju Feautred/Custom fields.

    2. napomena: potpuno je svejedno da li ćete zakačiti sličicu uz post na prvi ili drugi navedeni način, ali nemojte na oba. U nastavku ću vam pokazati kako da to prikažete na Blog strani.

    3. Razvoj Blog stranice

    Pošto smo pripremili sve što nam je potrebno (nadam se da ste dodali nekoliko blog postova), sad treba da prikažemo te podatke na stranici. Srećom, nije potrebno da dizajniramo ništa, jer je to dizajner uradio za nas. Pogledajmo blog.php kako bismo videli sa čime raspolažemo. Odmah se uočava da postoji div sa klasom post koji ustvari reprezentuje jedan blog zapis. On se ponavlja tri puta (dizajner je u HTML-u definisao tri blog posta), ali ćemo mi zadržati samo jedan, a preostala dva izbrisati. Sećate se priče o template-ima iz prvog dela – potreban nam je šablon za jedan post, koji ćemo staviti u WordPress loop (while petlja) i ostatak je u potpunosti na WordPress-u – on će izlistati onoliko post divova, ali i sve njihove informacije, koliko ima i postova za prikaz.

    Manje-više, ovo će biti samo obnavljanje gradiva koje smo naučili u drugom delu kada smo razvijali page.php template. Postoje dve stvari po kojima se blog.php razlikuje:

  • za razliku od page.php koji prikazuje samo jedan zapis (sadržaj te stranice), na Blogu će se prikazivati onoliko zapisa koliko ih bude bilo u bazi. Šta ukoliko ih ima 1000? Moramo da vodimo računa o paginaciji. Na našu sreću, WordPress može sam da vodi računa o tome, samo je potrebno da ga nateramo.
  • naš blog se izlistava na template-u koji je WordPress-u stran – kao što rekoh još na samom početku, WordPress je napravljen da postove izlistava na template-ima kao štu su index.php, category.php, ili archive.php. Iz tog razloga, onaj klasičan loop: while(have_posts()) : the_post() neće raditi, nego ćemo ga za nijansu izmeniti i definisati poseban upit za izlistavanje postova.
  • Dakle, mnoge stvari će vam biti poznate, a za ono malo što je izmenjeno čitajte komentare:

    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    <div class="grid_8">
        <?php

            // moramo da utvrdimo na kojoj strani se nalazimo
            // ukoliko smo otvorili stranicu http://localhost/wordpress/blog, $paged = 1
            // na stranici http://localhost/wordpress/blog/page/2, $paged = 2 itd...
            $paged = (get_query_var('paged')) ? get_query_var('paged') : 1;

            $args=array(
               'post_type'=>'post', // biramo samo postove, ne stranice                    
               'posts_per_page' => 2, // ogranicavamo broj postova po strani na 2
               'paged'=>$paged // sluzi kao offset WP-u
            ); 

            // kreiramo novi upit i prosledjujemo mu gornje parametre  
            $wp_query = new WP_Query($args);
               
                // odavde je sve poznato.
            while($wp_query->have_posts()) : $wp_query->the_post();
        ?>
             
            <!-- Blog Post -->
            <div class="post">
                <!-- Post Title -->
                <h3 class="title"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h3>
                <!-- Post Data -->
                <p class="sub"><a href="#"><?php the_category(', '); ?></a> &bull; <?php the_date('Y-m-d'); ?> &bull;
                    <a href="#"><?php comments_number( 'Nema odgovora', '1 odgovor', '% odgovora' ); ?></a></p>
                <div class="hr dotted clearfix">&nbsp;</div>

                <!-- Post Image -->

                <!--
                    Ukoliko ste sličicu uploadovali preko featured image,
                    prikažite je ovako:
                -->
                <?php
                    $thumbnail_url = wp_get_attachment_url( get_post_thumbnail_id($post->ID) );
                    if($thumbnail_url != false) { ?>
                        <img class="thumb" alt="" src="<?php echo $thumbnail_url; ?>" alt="<?php the_title(); ?>" />
                <?php } ?>

                <!--
                    Ukoliko ste sličicu uploadovali preko Custom field-a,
                    prikažite je ovako
                -->
                <?php $img = get_post_meta($post->ID, 'thumb', true);
                if(!empty($img) ) { ?>
                    <img class="thumb" alt="" src="<?php echo $img; ?>" alt="<?php the_title(); ?>" />
                <?php } ?>

               
                <!-- Post Content -->
                <?php the_content(); ?>
                <!-- Read More Button -->

                <p class="clearfix"><a href="<?php the_permalink(); ?>" class="button right"> Read More...</a></p>
            </div>
       
        <?php endwhile; ?>
        <div class="hr clearfix">&nbsp;</div>

        <!-- Blog Navigation -->

        <p class="clearfix">
            <?php previous_posts_link('<< Previous Posts', '') ?>
            <?php next_posts_link('Newer Posts >>', '') ?>
        </p>
    </div>
    Kraj trećeg dela

    S obzirom da mi već stižu mailovi zašto nema trećeg dela, odlučio sam da objavim ne baš kompletnu verziju ovog posta, ali vas molim da navratite u toku nedelje na blog ponovo kako biste pročitali malo više detalja u poslednjoj fazi gde smo kodirali blog template. Takođe, biće postavljeni i materijali iz ove lekcije za download. Ostaje standarna rečenica – ukoliko nešto ne razumete, otvoreni su komentari i dobićete vrlo brzo odgovor.

    Uvod

    Palo mi je pre nekoliko dana na pamet da vidim šta je to što nam je donela Java 7, pa eto posle malo guglanja naišao sam simbolično baš na 7 stvari.

    1. Binarni literali

    Celobrojni tipovi (byte, short, int, long) mogu biti izraženi korišćenjem binarnog sistema. Prilikom zadavanja binarnog literala piše se prefiks 0b ili 0B.

    1
    2
    3
    4
    5
    6
    byte ab = (byte)0b00100001;
    short as = (short)0b1010000101000101;
    int ai = 0b10100001010001011010000101000101;
    int ai2 = 0B101;
    long al = 0b10100001010001011010000101000101101000010010000101000101L;
    // primetiti sufiks L

    Korišćenje binarnih literala može učiniti neke veze u podacima očiglednijim nego kada se isti podaci predstave u oktalnoj ili heksadekadnoj reprezentaciji. Npr. ako se uzastopni elementi niza dobijaju rotiranjem ulevo za po jedan bit:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public static final int[] phases = {
        0b00110001,
        0b01100010,
        0b11000100,
        0b10001001,
        0b00010011,
        0b00100110,
        0b01001100,
        0b10011000
    }

    isti niz, zapisan korišćenjem heksadekadnih literala, izgleda ovako:

    1
    2
    3
    public static final int[] phases = {
        0×31, 0×62, 0xC4, 0×89, 0×13, 0×26, 0x4C, 0×98
    }

    Korišćenjem binarnih literala bitmapa postaje čitljivija. Takođe, korišćenje binarnih literala kao operanada bitskih operacija pomaže razumevanju logike i strukture programa.

    2. Podvlake u numeričkim literalima

    Bilo gde između cifara numeričkog literala može se naći proizvoljan broj podvlaka (_), čime se pospešuje čitljivost koda. Npr. ako literal sadrži veliki broj cifara, podvlakama se cifre mogu razdvojiti u grupe od po tri.

    1
    2
    3
    4
    5
    6
    7
    8
    long creditCardNumber = 1234_5678_9012_3456L;
    long socialSecurityNumber = 999_99_9999L;
    float pi = 3.14_15F;
    long hexBytes = 0xFF_EC_DE_5E;
    long hexWords = 0xCAFE_BABE;
    long maxLong = 0x7fff_ffff_ffff_ffffL;
    byte nybbles = (byte)0b0010_0101;
    long bytes = 0b11010010_01101001_10010100_10010010;

    Podvlake se mogu naći samo između cifara, ne i na sledećim mestima:
    - na početku ili kraju broja
    - pored decimalne tačke u broju sa pokretnim zarezom
    - ispred sufiksa F ili L

    3. Stringovi u switch 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    public static String podelaJezika(String jezik) {
        String paradigma;
        switch (jezik) {
            case "Java":
            case "C#":
                paradigma = "Objektno-orijentisana";
                break;
            case "C":
                paradigma = "Proceduralna";
                break;
            case "Python":
            case "PHP":
            case "Javascript":
                paradigma = "Skriptna";
                break;
            case "Haskell":
                paradigma = "Funkcionalna";
                break;
            default:
                throw new IllegalArgumentException("Ne pripada ni jednoj paradigmi: " + jezik);
        }
        return paradigma;
    }

    Naredba switch poredi string u svom izrazu sa izrazima pridruženim svakom case koristeći metod equals() klase String. Prema tome, poređenje je case sensitive. Java kompajler generiše efikasniji byte code od naredbi switch koje koriste stringove nego od ekvivalentnih else-if naredbi.

    4. Automatsko određivanje tipova prilikom kreiranja generičkih instanci

    Možete zameniti argumente tipa potrebne da se pozove konstruktor generičke klase sa praznim skupom parametara tipa (<>) takozvani dijamant, a kompajler će sam iz konteksta zaključiti tip. Npr. umesto

    
    1
      Map<String, List<String>> myMap = new HashMap<String, List<String>>();

    može se pisati:

    
    1
    2
      Map<String, List<String>> myMap = new HashMap<>();
    // primetiti da je neophodno pisati "”

    Zaključivanje tipova prilikom kreiranja instanci generičkog tipa je ograničeno i moguće je samo kada su tipovi očigledni iz konteksta, nešto slično kao var u C#-u.

    5. try-with-resources

    U pitanju je naredba try koja deklariše jedan ili veći broj resursa. Resurs je objekat koji se mora zatvoriti kada program završi rad sa njim. Naredba try-with-resources garantuje da je, na njenom kraju, svaki resurs zatvoren. Kao resurs se može koristiti svaki objekat klase koja implementira java.lang.AutoCloseable, što uključuje objekte klasa koje implementiraju java.io.Closeable.

    Sledeći primer čita prvu liniju iz fajla koristeći objekat klase BufferedReader. Ovaj objekat je resurs koji mora biti zatvoren nakon što program završi sa njegovim korišćenjem.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    static String citaPrvuLinijuFajla(String putanja) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader(putanja));
        try {
            return br.readLine();
        } finally {
            if (br != null)
            br.close();
        }
    }

    U gornjem kodu korišćen je finally blok kako bi se resurs zatvorio bez obzira da li je try blok završen normalno ili je prekinut izuzetkom. U Javi 7, korišćenjem try-with-resources, ista stvar se može uraditi na sledeći način:

    1
    2
    3
    4
    5
    static String citaPrvuLinijuFajla(String putanja) throws IOException {
        try (BufferedReader br = new BufferedReader(new FileReader(putanja))) {
            return br.readLine();
        }
    }

    U ovom primeru, kao resurs je deklarisan objekat klase BufferedReader. Deklaracije resursa se navode unutar para oblih zagrada koje neposredno slede ključnu reč try. Pošto je ovaj objekat deklarisan u try-with-resources, biće zatvoren bez obzira na to da li je try završen normalno ili je prekinut izuzetkom tipa IOException koji može izbaciti metod readLine().
    Međutim, u prvom primeru, ako i readLine() i close() izbace izuzetak, metod citaPrvuLinijuFajla () izbacuje izuzetak izbačen u finally bloku. Nasuprot tome, u drugom primeru, ako se izuzeci izbace i iz try bloka i iz try-with-resources, metod citaPrvuLinijuFajla() izbacuje izuzetak izbačen u try bloku.

    Unutar try-with-resources moguće je deklarisati i veći broj resursa. Npr.

    1
    2
    3
    4
    5
    6
    try ( java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFileName);
                java.io.BufferedWriter writer =
                java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
            ) {
                …
            }

    Deklaracije se razdvajaju tačka-zapetom. Po završetku koda koji neposredno sledi, bilo normalno bilo zbog izuzetka, automatski se pozivaju metodi close() za objekte BufferedWriter i ZipFile, tim redom, tj. redosledom obrnutim od redosleda kojim su kreirani.

    try-with-resources može imati catch i finally blokove, kao i običan try. Za try-with-resources, catch i finally blokovi se izvršavaju nakon zatvaranja deklarisanih resursa.

    6. Rukovanje većim brojem tipova izuzetaka

    Jedan catch blok može rukovati većim brojem tipova izuzetaka. Ovim se može smanjiti ponavljanje koda.
    U narednom fragmentu, ponavlja se kod u svakom od catch blokova:

    1
    2
    3
    4
    5
    6
    7
    catch (IOException ex) {
        logger.log(ex);
        throw ex;
        catch (SQLException ex) {
        logger.log(ex);
        throw ex;
    }

    U Javi 7, ponavljanje tog koda je moguće eliminisati na sledeći način:

    1
    2
    3
    4
    catch (IOException|SQLException ex) {
        logger.log(ex);
        throw ex;
    }

    Tipovi izuzetaka kojima catch blok može rukovati razdvajaju se vertikalnim crtama (|). Ukoliko catch blok rukuje većim brojem tipova izuzetaka, njegov parametar je implicitno final. U gornjem primeru, to znači da je parametar ex final, te mu nije moguće pridružiti nikakvu vrednost unutar catch bloka.
    Byte code generisan kompajliranjem catch bloka koji rukuje većim brojem tipova izuzetaka biće manji, a time i superiorniji negoli onaj nastao kompajliranjem većeg broja catch blokova koji rukuju po jednim tipom izuzetaka.

    7. Reizbacivanje izuzetaka sa opsežnijom proverom tipova

    Omogućuje preciznije zadavanje tipova izuzetaka koji mogu biti izbačeni u throws klauzi deklaracije metoda.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    static class FirstException extends Exception { }
    static class SecondException extends Exception { }

    public void rethrowException(String exceptionName) throws Exception {
      try {
        if (exceptionName.equals("First")) {
          throw new FirstException();
        }
        else {
            throw new SecondException();
        }
      } catch (Exception e) {
            throw e;
        }
    }

    try blok može izbaciti jedino izuzetke tipova FirstException i SecondException. Pretpostavimo da želimo da zadamo te tipove u throws klauzi deklaracije metoda. U ranijim verzijama Jave to nismo mogli, jer je parametar e catch klauze tipa Exception, a catch blok reizbacuje njega, pa je u throws klauzi moguće zadati samo tip Exception. Međutim, u Javi 7, mogu se zadati FirstException i SecondException u throws klauzi jer je kompajler u stanju da utvrdi da izbačeni izuzetak e mora poticati iz try bloka, a jedini izuzeci koje try blok može izbaciti su tipa FirstException ili SecondException. Iako je parametar e catch klauze tipa Exception, kompajler može utvrditi da je on instanca FirstException ili SecondException.

    1
    2
    3
    4
    5
    6
    7
    8
    public void rethrowException(String exceptionName) throws FirstException, SecondException {
      try {
          // ...
      }
      catch (Exception e) {
          throw e;
      }
    }

    Ova analiza se onemogućuje ako se unutar catch bloka parametru e pridruži neka druga vrednost. U tom slučaju mora se zadati tip Exception u throws klauzi deklaracije metoda.
    Preciznije, u Javi 7, kada se u catch klauzi deklariše jedan ili veći broj tipova i reizbaci izuzetak kojim catch blok rukuje, kompajler proverava da li tip reizbačenog izuzetka zadovoljava sledeće uslove:
    - try blok može da izbaci izuzetak tog tipa
    - nema prethodećih catch blokova koji mogu rukovati njime
    - u pitanju je potklasa ili natklasa jednog od tipova deklarisanih u catch klauzi.

    U gornjem primeru, kompajler dopušta da se tipovi FirstException i SecondException zadaju u throws klauzi, jer možemo da reizbacimo izuzetak koji je tipa natklase bilo kog od tipova deklarisanih u throws.

    U prethodnim verzijama Jave, nije moguće izbaciti izuzetak koji je tipa natklase tipa deklarisanog u nekoj od catch klauza. Takav pokušaj dovodi do greške „unreported exception Exception; must be caught or declared to be thrown“ u naredbi throw e. Kompajler proverava da li je moguće tip izbačenog izuzetka dodeliti nekom od tipova deklarisanih u throws klauzi, a kako je tip parametra e Exception natklasa, a ne potklasa od FirstException andSecondException, to nije moguće.

    Dobrodošli u treći tutorijal

    U ovom nastavku obrađujemo osnovne tipove podaka u C++-u: primitivne tipove, nizove, pokazivače i reference. Pa, idemo redom. Ako vam se učini da vam je dosta čitanja, stanite pa nastavite kasnije. )

    Primitivni tipovi (int, float, double…)

    Po pitanju primitivnih tipova, Java i C# se prilično razlikuju. U Javi su oni to što jesu primitivni, možete im dodeliti vrednost, koristiti u izrazima, prosleđivati metodama. U C# nisu baš toliko primitivni, tamo možete nad njima pozivati metode.

    C++ je po pitanju primitivnih tipova kao Java, sada ćemo da ih pobrojimo.

    NazivVeličinaOpis

    int 4 bajta ceo broj, od -2^31 do +2^31-1 short 2 bajta manji ceo broj, od -32767 do +32768 long 4 ili 8 bajtova long long 8 bajtova mnogo veliki ceo broj, od -2^63 do +2^63-1 char 1 bajt od -128 do +127 unsigned int 4 bajta nenegativan ceo broj, od 0 do +2^32-1 unsigned short 2 bajta nenegativan, od 0 do 65535 unsigned long 4 ili 8 bajtova unsigned long long     8 bajtova nenegativan, od 0 do +2^64-1 unsigned char 1 bajt od 0 do 255 float 4 bajta decimalan broj double 8 bajtova decimalan broj sa većom preciznošću

     

    U Javi i C# nazivi tipova nenegativnih celih brojeva se od naziva običnih razlikuju za početno slovo “u”, dok se u C++-u cela reč unsigned dodaje ispred imena tipa, i odvojena je od imena tipa.

    A sada ću pomenuti prvu zaćkoljicu u C++-u (biće ih još u narednim člancima). Verovatno se pitate zašto u tabeli za long stoji “4 ili 8 bajtova”. Kratak odgovor je da je long 64 bita i to je to. Ako hoćete duži odgovor pročitajte sledeći odeljak. (C++ je jezik sa raznim začkoljicama, koje ću predstavljati na ovaj način u ovim člancima)

    Začkoljica 1:
    Verovatno znate iz Jave i/ili C# koje su veličine primitivnih tipova. Te veličine za byte, short, int, long su propisane standardom za Javu, odnosno C#, i nema razloga da se posumlja u to. Kod C-a i C++-a stvari su malo zamršene. U C-u, po standardu, veličina celobrojnih tipova zavisi od pojedinačne implementacije C jezika (to se zove “implementation defined”), pa je na nekim starim računarima pre PC-a, veličina int-a bila 2 bajta, itd… U suštini i C i C++ su dovoljno stari jezici da su u vreme njihovog nastanka ovakve stvari bile oubičaene. Ali praktično su veličine de facto standardizovane, pa možete očekivati da je na PC-u u C++-u kompajliranim GCC kompajlerom veličina long-a 64 bita. Ali opet nije loše znati, ko zna kad može zatrebati, da veličine celobrojnih tipova nisu standardizovane.

    1
    2
    3
    4
    5
    6
    7
    #include <QTextStream>
    int main()
    {
    QTextStream out(stdout);
    out << "Velicina long-a je:" << sizeof(long) << endl;
    return 0;
    }

    Ovo će ispisati koliko bajtova je veliki broj long tipa. Inače sizeof() je ugrađena funkcija u C++-u koja se evaluira tokom kompajliranja (ako napišete sizeof(int) kompajler će to zameniti brojem 4) i ona daje veličinu bilo kog tipa.

    Ono što bi trebalo naglasiti u kontektstu primitivnih tipova (da bi bolje zapamtili) je da je veličina char tipa 8 bita (1 bajt), za razliku od Jave i C#-a gde je 2 bajta. Šta više u C++-u char je zapravo celobrojni tip, koji ima pozitivno-negativnu, kao i nenegativnu (unsigned) varjantu. Odnosno char se koristi kao celobrojni tip veličine 1 bajt. Takođe se koristi i u kontekstu stringova, ali moramo još da pređemo da bi došli do stringova.

    Nizovi

    U Javi i C#-u nizovi su objekti, pri kreiranju se daje dužina koja se može pročitati iz niza u svakom trenutku. Možete slobodno da zaboravite na to. Prvo ćemo videti kako se u C++-u deklariše niz, pa ću objasniti.

    1
    2
    3
    4
    5
    6
    7
    8
    void nekaFunkcija()
    {
    int niz1[10]; //deklaracija niza na stacku
    int niz2[5] = {1, 2, 3, 4, 5}; //deklaracija i skraćena inicijalizacija

    int broj = niz1[6];
    niz2[3] = broj;
    }

    Sintaksa deklaracije izgleda čudno, ali zapravo oponaša sintaksu korišćenja nizova. Kada se u C++-u niz deklariše na ovaj način, onda će on biti ceo kreiran na stack-u. Broj elemenata niza mora da se da kao konstanta (morate da otkucate neki broj). Niz u C++-u nije objekat, nema metode, ne možete čitati njegovu veličinu, možete samo pristupiti elementima preko indeksa. Mislite o C++ nizu kao o mogućnosti da skraćeno deklarišete više istorodnih promenljivih (u gornjem primeru, smo deklarisali 10 int-ova). Sledeća dva primera su ekvivalentna u smislu onoga što se dešava u memoriji. U oba primera će na stack-u biti 5 int-ova sa dole navedenim vrednostima.

    1
    2
    3
    4
    5
    6
    int num0 = 12;
    int num1 = 23;
    int num2 = 6;
    int num3 = 76;
    int num4 = 42;
    out << num2; 1
    2
    int num[5] = {12, 23, 6, 76, 42};
    out << num[2];

    Naravno moguće je deklarisati ovakve nizove od bilo kog tipa u C++-u.

    Ali, uopšte se ne proverava da li je kod pristupa elementima indeks validan, možete čak staviti negativne brojeve kao indeks. Ako se pristupi indeksom izvan veličine, ne zna se šta će se desiti (undefined behaviour), najverovatnije ćete pristupiti sadržaju memorije udaljenom za taj indeks od početka niza (što može biti memorija neke druge promenljive na stack-u, ili stack memorija neke druge funkcije, a ako to izmenite ko zna šta će se desiti sa programom).

    Začkoljica 2: Validnost indeksa kod pristupanja nizovima se ne proverava, odnosno nije definisano šta će se desiti ako indeks prekoračuje veličinu niza. Možda ništa, a možda program crash-uje.

    Vidite i sami da ovakvi nizovi nisu nešto korisni. Nalaze se na stacku, moraju da se deklarišu konstantom. Uskoro ćemo saznati bolju varjantu, a do nje će nas dovesti

    Pokazivači (pointer-i)

    Ovo je tip podatka koji ne postoji u Javi (postoji u C#-u, ali se jako retko koristi). Pokazivači u C++-u omogućavaju da se objekti kreiraju na heap-u, a da na stack-u postoje samo promenljive koje sadrže njihove adrese (i pokazuju na objekte koje su na nekom drugom mestu u memoriji). U Javi i C#-u reference su zapravo pokazivači, ali jako ograničeni. Dok u Javi možete samo menjati na koji objekat ona pokazuje i dodeliti null vrednost, u C++-u se sa pokazivačima može mnogo više. Krećemo sa sintaksom i prostim programom.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    #include <QTextStream>

    int main()
    {
    QTextStream out(stdout);

    int broj = 32;
    int* pokazivac = &broj;

    out << "Broj je: " << broj << endl;

    *pokazivac = 64;

    out << "Broj je: " << broj << endl;

    return 0;
    }

    Prvo deklarišemo promenljivu broj čiji je tip int i dodeljujemo joj vrednost 32. Zatim deklarišemo promenljivu pokazivac čiji je tip “pokazivač na int” i dodeljujemo joj adresu promenljive broj. Ovde vidimo da zvezdica osim kao znak za množenje u C++-u ima i drugu svrhu (zapravo još dve svrhe) i da & osim kao operator za AND nad bitovima brojeva ima drugu svrhu.

    Dakle da bi deklarisali pokazivač na int pišemo int*, da bi deklarisali pokazivač na double pišemo double*, i tako za bilo koji tip u C++-u. Pošto je pokazivač u suštini primitivni tip, moramo da mu damo neku početnu vrednost da bi bio od koristi. Vrednosti koje dodeljujete pokazivačima su memorijske adrese. Da bi uzeli adresu neke promenljive koristimo address of operator (&). Dakle, sledeći izraz

    1
    &broj

    daje adresu promenljive broj. I onda našem pokazivaču dodeljujemo tu adresu. Tako da pokazivač sada “pokazuje” na promenljivu broj.

    Ali za šta mi možemo da koristimo pokazivač na neku drugu promeljivu, pa da operišemo sa vrednošću te druge promenljive, ili čak i da menjamo tu vrednost. Da bi dobili vrednost promenljive na koju pokazivač pokazuje koristimo operator dereferenciranja, odnosno zvezdicu * . Dakle sledeći izraz

    1
    *pokazivac

    daje vrednosti promenljive na koju pokazivač pokazuje, u našem slučaje dobijamo vrednost promenljive broj. A preko pokazivača možemo i da menjamo vrednosti promenljive čiju adresu sadrži pokazivač. Samo treba prethodni izraz da stavimo s leve strane operatora dodele (=).

    Ilustrovaćemo jednu od primena pokazivača sledećim primerom, kojim ćete verovatno bolje i shvatiti.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void povecajZaDeset(int* pBroj)
    {
    *pBroj += 10;
    }

    int main()
    {
    int broj = 123;
    povecajZaDeset(&broj);
    //broj sada ima vrednost 133;
    return 0;
    }

    Jedna od glavnih primena je da jedna funkcija dopusti drugoj funkciji da menja neke od njenih promenljivih, tako što će drugoj funkciji da prosledi adresu svoje promenljive, a onda ta druga funkcija može da je menja “preko pokazivača” (ovako se kaže ) ).

    Već sam rekao da se u C++-u pokazivači, između ostalog, koriste za upravljanje podacima na heap-u. Tokom izvršavanja programa, na stack-u bi trebalo da postoje veze ka svim podacima na heap-u. U Javi i C#-u su to reference ka objektima koji se kreiraju ključnom reči new i pozivom konstruktora. Vratimo se na C++.

    Da bi mogli da upravljamo instancama tipova na heap-u preko pokazivača, moramo nekom pokazivaču da dodelimo adresu nekog objekta ili primitivne promenljive koja je na heap-u. A ona se dobija pri kreiranju nečega na heap-u. Kako se kreiraju podaci na heap-u? I u C++-u se koristi ključna reč new. I evo ga primer.

    1
    2
    3
    4
    5
    6
    7
    8
    int main()
    {
    int* naHeapu = new int(156);
    int naStacku = *naHeapu;
    //naStacku sada ima vrednost 156

    return 0;
    }

    U prvoj liniji smo deklarisali promenljivu tipa “pokazivač na int” i dodelili joj adresu int-a koji je kreiran na heap-u. Izraz “new int(156)” odvaja prostor na heap-u za jedan int, daje mu vrednost 156 i vraća adresu tog odvojenog memorijskog prostora. Zatim promenljivoj na stacku dodeljujemo vrednost int-a koji se nalazi na heap-u.

    Samo što nam i nije nešto korisno da kreiramo na heap-u obične primitivne promenljive (čak je i loše sa strane performansi), heap služi za nešto veće, za objekte i nizove. Kako se kreira niz na heap-u u C++-u? Zapravo je isto kao u Javi i C#. Primer.

    1
    2
    3
    4
    5
    6
    7
    int main()
    {
    int* niz = new int[14];

    niz[6] = 25;
    return 0;
    }

    Izraz “new int[14]“ će odvojiti memoriju za 14 int-ova i vratiti adresu te memorije. Tu adresu smeštamo u pokazivač ka int-u. Iako smo promenljvu niz deklarisali kao pokazivač ka int, mi znamo da se na toj adresi nalazi niz od više uzastopnih int-ova. Ali u C++-u ne postoji način da se to iskaže u deklaraciji pokazivača.

    Zapravo uvek kada deklarišemo pokazivač, mi u stvari deklarišemo pokazivač ka nizu, a granični slučaj je da taj niz ima samo jedan element.

    Imajte na umu da smo mi dobili samo običan pokazivač na neki deo memorije. U njemu je samo sadržana adresa u memoriji gde se niz nalazi. Znači da ne možemo u svakom trenutku samo iz tog pokazivača saznati dužinu niza na toj adresi. Dužinu moramo sami da prenosimo zajedno sa niz-om. I iz ovoga je očigledno da se ni ovde ne proverava validnost indeksa kod pristupa. Ako je indeks izvan granica niza, ne znamo šta bi moglo da se desi, možda samo pristupimo memoriji nekog drugog objekata ili niza, ili možda ubodemo memoriju koja nam još nije dodeljena, pa program crash-uje.

    U C++-u, stoga možete indeksirati bilo koji pokazivač, bez obzira da li je ka jednoj instanci ili nizu. Ali šta se u stvari dešava kad se napiše

    1
    2
    int* niz = new int[50];
    int broj = niz[36];

    Taj kod je zapravo ekvivalentan sledećem

    1
    2
    int* niz = new int[50];
    int broj = *(niz+36);

    Dakle indeksiranje pokazivača je isto što i dodavanje indeksa na adresu koju pokazivač ima i dereferenciranje dobijene adrese. Ovde će broj dobiti vrednost int-a koji se nalazi na adresi niza uvećanoj za 36 veličina int-a. Ali, možda se pitate kako to da su ova dva primera ekvivalentna, kada u drugom primeru samo doajemo 36 na adresu niza, a int je 4 bajta veliki, pa onda dobijamo 9. int (36/4=9). E pa nije. Jer kad se u C++-u pokazivač sabira sa nekim drugim brojem stupa na snagu “pointer aritmetika”.

    Šta to znači? To znači da ako na int* dodamo 36, zapravo dodajemo 36*sizeof(int) (odnosno 36*4 = 144). Tako da stvarno dobijamo adresu 36. int-a u nizu, a ne 9.

    Ja sam ovde svuda koristio samo tip int, ali umesto njega može i da stoji bilo koji drugi tip. Recimo da imamo definisanu klasu SuperCoolObjekat.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int main()
    {
    SuperCoolObjekat objekatNaStacku;

    SuperCoolObjekat* pokazivac = &objekatnaStacku;

    SuperCoolObjeakt* objeaktNaHeapu = new SuperCoolObjekat();

    SuperCoolObjekat* niz = new SuperCoolObjekat[42];
    return 0;
    }

    S tim što moram da naglasim jednu nevidljivu, bitnu razliku u odnosu na Javu i C#. Kada tamo kreirate niz objekata, zapravo kreirate niz referenci koje sve dobijaju početnu vrednost null.

    Kada u C++-u kreirate niz objekata, u nizu će se nalaziti pravi objekti, i svi će biti konstruisani praznim konstruktorom, ako ta klasa ima prazan konstruktor. Ako nema, kompajler će prijaviti grešku.

    Ali, ako želite ponašanje isto kao i u Javi/C#-u, onda napravite niz pokaivača na objekte. Tada morate promenljivu da deklarišete kao “pokazivač na pokazivač na <tip>, odnosno dupli pokazivač (tako se nekad kaže).

    1
    2
    3
    4
    5
    6
    SuperCoolObjekat** niz = new SuperCoolObjekat*[21];
    //pa možemo u petlji da dodeljujemo objekte pokazivačima
    for (int i= 0; i < 21; i++)
    {
    niz[i] = new SuperCoolObjekat();
    }

    Sve je ovo lepo, ali šta se dešava sa tim objektima i nizovima koje smo napravili na heap-u, kada nam više ne trebaju. Zapamtite C++-u nema automatsko upravljanje memorijom. Znači moraćemo sami da ih obrišemo iz memorije. Kako se to radi? Koristi se ključna reč delete.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    int main()
    {
    MojObjekat* obj = new MojObjekat();

    double* niz = new double[20];

    //radimo nešto sa ovim objektom i nizom

    delete obj;
    delete[] niz;
    return 0;
    }

    Zapamtite da uvek kada brišete niz sa heap-a morate da koristite delete[] (sa pravougaonim zagradama). To je specijalna naredba za brisanje niza. Razlog za to je u tome što se u C++-u osim samog brisanja objekta moraju obaviti još neke radnje (objekti moraju da “počiste za sobom”, a o tome u nekom budućem članku). I to se mora uraditi za svaki objekat u nizu, a pošto se naredbi za brisanje daje običan pokazivač, vi morate da kažete kompajleru da li je to pokazivač ka jednom objektu ili nizu objekata. U zavisnosti od toga da li imate niz instanci primitivnih tipova, objekata koji ne moraju da čiste za sobom ili objekata koji to moraju, korišćenje delete umesto delete[] može ili ne mora da dovede do ozbiljnih problema u izvršavanju programa. Pa zapamtite da uvek koristite delete[] za brisanje niza.

    Elem, sada moramo da popričano teorijski o nečemu jako važnom, a to su šeme upravljanja memorijom. Zar nismo rekli da ako ćemo da koristimo neki objekat ili niz samo u okviru jedne funkcije, treba da ih deklarišemo na stacku. Jesmo, pa se zato obično objekti i nizovi kreirani na heap-u prosleđuju drugim funkcijama ili se vraćaju kao povratna vrednost. Ali onda se nameće pitanje kako neka funkcija može da zna da li sme da obriše neki objekat, možda neki drugi objekat ima isti pokazivač. Ako vi imate pristup kod-u svih klasa i funkcija koje će koristiti neki objekat, onda možete znati kad neče više biti potreban i obrisati ga na tom mestu, ali šta ako nemate pristup svom kod-u (što je najčešći slučaj) ili jednostavno ne želite da pretražujete ceo kod ručno tražeči pravo mesto za brisanje nekog objekta (što je još češći slučaj D )? Na ovo pitanje postoji mnogo različitih odgovora. To su sve različite šeme upravljanja meorijom koje se sastoje od pravila koja bi trebalo poštovati kako bi izbegli analiziranje celog programa. Qt biblioteka ima više od jedne šeme. O tome kad dođe vreme, ali ipak imajte na umu da u C++-u brisanje memorije nije automatsko i da morate da mislite o tome.

    Pošto smo završili sa pokazvačima, moram da se vratim na nizove sa vrha članka, Zato što oni imaju veze sa pokazivačima. U C++-u niz može da degradira u pokazivač(tako se kaže). Šta ovo zapravo znači? To znači da ako neka funkcija prima argument tipa “pokazivač na nešto” vi joj možete proslediti i niz tog nečega. U tom slučaju se niz pretvara u pokazivač sa adresom u stack memoriji gde se niz nalazi.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void doSomething(float* arr, int length)
    {
    //radi nešto sa ovim nizom
    }

    int main()
    {
    float niz[60];

    doSomething(niz, 60);
    return 0;
    }

    Upozorenje: Pošto je ovo niz na stacku, on će nestati kada funkcija u kojoj je deklarisan završi sa izvršavanjem. Tako da ne bi smeli da prosleđujete pokazivač ka ovom nizu funkcijama koje će ga sačuvati negde za kasnije. Prosleđujte ga samo onim funkcijama za koje znate da, kad urade to što treba da urade, neće sačuvati taj pokazivač negde (recimo u neku globalnu ili statičku promenljivu, ili u promenljivu objekta ako je u pitanju metod).

    Reference

    Do sada sam reference pominjao samo kao nešto što imaju Java i C#, i da su to ograničeni pokazivači. A koja su to ograničenja. Sad može da ih pobrojimo. U C++-u pokazivačima možemo da dodajemo ili oduzimamo brojeve, u stvari možemo da im dodelimo bilo koju celobrojnu vrednost, a da li je to validna memorijska adresa na kojoj postoji instanca tipa na koji se pokazuje, o tome samo programer vodi računa.

    Ali ako hoćete ograničenja (ne trebaju vam mogućnosti pokazivača), C++ ima i reference. Ali tu je ironija. Reference u C++-u su još ograničenije od referenci iz Jave i C#-a. U C++-u jedna referenca može biti ka samo jednoj instanci. Ali u C++ reference nisu samo ka objektima, već se reference mogu deklarisati ka instanci čak i primitivnog tipa. Kako se deklarišu reference? Slično kao pokazivači, samo što se umesto * stavlja &.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    int main()
    {
    int a = 25;
    int b = 30;
    int& r = a;
    //deklarišemo referencu na int i vezujemo je sa promenljivom a

    r = 48;
    //sada je vrednost a 48
    r = b;
    //sada je vrednost a 30
    return 0;
    }

    Referenca se ponaša kao da je drugo ime za pravu instancu sa kojom je vezana. Ako referenci dodelimo neku vrednost, originalna promenljiva će dobiti tu vrednost. Nemoguće je promeniti objekat ili promenljivu sa kojom je referenca vezana. Poslednji red u gornjem primeru uzima vrednost iz b i dodeljuje je promenljivoj za koju je referenca vezana (a). Ne može se nikako raskinuti veza između r i a.

    Iz ovoga proizilazi jedina realna primena referenci. Prenošenje argumenata funkcijama po referenci. Ako vam termin nije poznat, to je dozvoljavanje nekoj funkciji da menja promenljive neke druge funkcije, tako što jedna drugoj prosledi adresu svoje promenljive. Ovako je išlo sa pokazivačima. Sledi primer sa referencama.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void smanjiZaPetnaest(int& num)
    {
    num -= 15;
    }

    int main()
    {
    int a = 35;
    smanjiZaPetnaest(a);
    //a je sada 20
    return 0;
    }

    Primetićete da smo u primeru sa pokazivačima ranije u tekstu morali da dereferenciramo pokazivač. Ovde ne mora, jer se referenca implicitno dereferencira u svim operacijama. Takođe nismo morali da uzimamo adresu od a (address of operatorom), jer se kod vezivanja reference za promenljivu taj operator ne koristi.

    Treba istaći da mnogi ljudi (uključujući i mene) smatraju da je čitljivije ako se u ovakvim situacijama promenljive prenose preko pokazivača, a ne preko reference, jer se pri pozivu metode onda mora staviti address of operator, a tako neko ko čita kod može lakše da vidi šta se stvarno dešava. Ovako sa referencama izgleda kao da se vrednost promenljive prosleđuje funkciji, a ne njena adresa.

    No, imaju reference primena osim ovakvih u primerima, do kojih ćemo doći kasnije.

    Rezime

    Iz materiajla izloženog u ovom članku možete primetiti da je C++ jezik primetno nižeg nivoa od Jave i C#-a. U tim jezicima je sve automatsko i uređeno. Primitivne promenljive su na stacku, objekti se kreiraju na heap-u, automatski sistem briše objekte sa heap-a koji nisu više potrebni. S druge strane u C++-u vi morate sve eksplicitno da kažete. Morate da kažete da li hoćete primitivnu promenljivu ili objekat na stacku ili na heap-u, da li niz hoćete na stack-u ili na heap-u, da li u nizu hoćete cele objekte ili samo pokazivače ka objektima. Morate sami da odlučite kada objekti više nisu potrebni i na tom mestu ih obrišete. Ovo zviči kao dosta stvari o kojima teba voditi računa. Ali ako se u pisanju programa poštuju određena pravila (koja se koriste kao konvencija) i koriste određene stvari koje Qt biblioteka obezbeđuje, može se znatno umanjiti teret upravljanja memorijom koji pada na programera.

    Do sledećeg čitanja.

    Intervju sa organizatorima

    Udruženje studenata informatike FONIS organizuje konferenciju i takmičenje pod nazivom “Start Conference“, sa ciljem promocije novih tehnologija i njihovom približavanju stručnoj i široj javnosti u Srbiji.

    Povodom ovog interesantnog projekta, pričali smo sa Vladimirom Stoiljkovićem, PR-om organizacije.

    START je novi projekat studentske organizacije FONIS. Možeš li nam reći nešto o START-u?

    U pitanju je projekat koji se po prvi put organizuje na Fakultetu organizacionih nauka, podržanog od strane fakulteta, Microsoft-a i drugih sponzora, a koji se finansira iz sredstava Digitalne agende. Projekat će se održati 8. i 9. decembra, a sastoji se iz konferencijskog i takmičarskog dela. Kroz konferencijski deo, nastojićemo da studentima u Srbiji približimo tehnologije koje su trenutno aktuelne u svetu, ali i da kroz uspešne primere predavača pokažemo da i kod nas postoji mogućnost za razvoj poslovanja korišćenjem tih tehnologija. U takmičarskom delu, nadmetaće se ukupno 8 ekipa od tri programera u razvoju društveno-korisnih Windows 8 aplikacija. Za kreiranje aplikacija, timovi će na raspolaganju imati 24 sata, slično formatu hakatona. Pobednički tim očekuju vredne nagrade od strane organizatora i sponzora projekta.

    Šta je to što čini START drugačijim od ostalih projekata, pre svega FONIS-a, ali i projekata drugih studentskih organizacija?

    Ono što je najinteresantnije na ovom projektu jeste samo takmičenje, u kojem će učesnici po prvi put u Srbiji razvijati aplikacije za Windows 8, najnoviji operativni sistem Microsoft-a. Koncept takmičenja je sličan hakatonu, gde je cilj da programeri ponude zanimljivo rešenje na zadatu temu upotrebom modernih tehnologija. Uz prijatnu atmosferu, prisustvo mentora iz Microsoft-a i raspoloživosti svih potrebnih resursa za rad, verujemo da će takmičari ponuditi dobra i zanimljiva rešenja i da će žiri biti na slatkim mukama prilikom izbora najbolje aplikacije. Obzirom da je Microsoft nedavno omogućio programerima iz Srbije plasiranje svojih aplikacija u Windows Store prodavnici aplikacija, nakon takmičenja, sve aplikacije će biti objavljene u toj prodavnici, što predstavlja pravi način za promociju domaćih programera. Paralelno sa takmičenjem, održaće se konferencija, na kojoj će predavači zainteresovanim studentima podeliti dragocena iskustva kroz svoje uspešne projekte. Na taj način, želimo da pokažemo da se u Srbiji, uprkos usporenom stepenu razvoja i korišćenja novih tehnologija, može ostvariti uspeh u realizaciji različitih projekata.

    Da li postoje neka ograničenja za učešće na takmičenju? Koliko košta kotizacija za konferenciju?

    Konferencija, zajedno sa takmičenjem, je potpuno besplatna. Konferencija je otvorena za sve, dok je takmičenje namenjeno studentima ili osobama do 27 godina starosti.

    Da li je potrebna prijava za učešće na takmičenju ili prisustvovanje konferenciji?

    Da, prijava je potrebna, kako za takmičenje, tako i za prisustvo konferenciji. Prijava za takmičenje je trenutno otvorena do 1. decembra i nju možete popuniti na sajtu projekta, dok će prijave za konferenciju biti uskoro objavljene.

    Kako planirate da približite ideju START-a i Windows 8 aplikacija potencijalnim učesnicima takmičenja?

    U sklopu projekta, organizujemo edukativne radionice na različitim fakultetima širom Srbije. Kroz niz praktičnih radionica, svi studenti će imati priliku da se upoznaju sa načinom razvoja aplikacija i mogućnostima koje donosi Windows 8 operativni sistem. Nedavno smo posetili Elektronski fakultet u Nišu, a najavljene su radionice u Zrenjaninu, Novom Sadu i Beogradu. Analogno takmičenju i konferenciji, prisustvo radionicama je potpuno besplatno.

    Zašto po tvom mišljenju neko treba da se prijavi za učešće na ovom projektu?

    Sinergija druženja, učenja, velike količine energije i kreativnosti prilikom razvoja aplikacija su dovoljni motivatori da pojedinac bude istrajan u pokušaju realizovanja svoje ideje koja bi u budućnosti mogla biti prepoznata. Na konferenciji garantujemo veliki broj zanimljivih i poučnih informacija, pa ovim putem pozivam sve zainteresovane osobe da se prijave!

    Više informacija o konferenciji i takmičenju, uz mogućnost prijave za učešće, se mogu dobiti na zvaničnom sajtu projekta “Start Conference”.

    Dobro došli u drugi deo serijala

    U prvom delu smo izneli zahteve koje naša tema mora da podrži, zatim smo uspešno instalirali WordPress na localhost-u, ukratko objasnili njegovu strukturu, definisali fajlove koji se obično nalaze u standarnoj WordPress temi. Onda smo temu aktivirali kroz admin panel, nakon čega je nastala prava katastrofa – ona ne izgleda ni blizu dizajnu HTML teme koju smo preuzeli. U nastavku ću vam pokazati kako to možete da rešite.

    1. Sređivanje linkova do CSS/JavaScript fajlova i slika

    Postavlja se pitanje zašto se ovo dešava kad smo identično iskopirali fajlove koje smo dobili u temi. Pogledaćemo source kod koji smo dobili od servera kako bismo došli do odgovora. Otvorite tab u kome se nalazi blog (dakle, http://localhost/wordpress tab) i kliknite bilo gde na strani desnim klikom i izaberite View page source.

    Iz priložene slike se sve razjašnjava – linkovi do CSS fajla, kao i JavaScript fajlova nisu ispravni. Pre svega, mi čak i nemamo fajlove koji se zovu reset.css i styles.css – sećate se da smo ta dva fajla spojili u jedan koji se zove style.css, koji se nalazi na sledećoj putanji: /wp-content/themes/aurelius/style.css. Međutim, to i dalje neće raditi zato što moramo ispred svega da dodamo naziv domena na kome se nalazi WordPress sajt. S obzirom da smo mi na localhost-u, tačna putanja je: http://localhost/wordpress/wp-content/themes/aurelius/style.css. Prekopirajte ovu liniju u browseru i videćete CSS fajl. Ukoliko u fajlu home.php između head tagova svuda gde treba dopišemo prave putanje, ovako:

    
    1
    2
    3
    4
    5
    6
    7
        <!-- Stylesheets -->
        <link rel="stylesheet" href="http://localhost/wordpress/wp-content/themes/aurelius/style.css" />   
       
        <!-- Scripts -->
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
        <script type="text/javascript" src="http://localhost/wordpress/wp-content/themes/aurelius/js/jquery.roundabout-1.0.min.js"></script>
        <script type="text/javascript" src="http://localhost/wordpress/wp-content/themes/aurelius/js/jquery.easing.1.3.js"></script>

    i refresh-ujemo stranu, dobićemo nešto što već liči na temu koju pravimo.

    Zašto ovaj pristup nije dobar?

    Bez obzira što radi, ovo nije najbolje rešenje iz jednog prostog razloga – zamislite da selite blog sa localhost-a na neki pravi domen (recimo http://www.viewsource.rs). U tom slučaju, vaš kod neće raditi, jer će on tražiti CSS i JS fajlove na localhost domenu. Drugim rečima, vi ste hardcode-ovali ove podatke i striktno vezali blog da radi isključivo na localhost-u. Sada verovatno mislite – u redu, šta je tu problem, otići ću ponovo u home.php i prepraviti neispravne putanje. Da, to jeste rešenje, ali nije najbolje. Idealna situacija bi bila kada bi postojao neki mehanizam da,nezavisno od domena na kome se sajt nalazi, putanja bude uvek dobra. Da bismo to napravili, pozvaćemo u pomoć WordPress-ovu funkciju – bloginfo().

    bloginfo() funkcija

    Bloginfo funkcija (zadatak: pogledati njenu zvaničnu dokumentaciju) generalno ispisuje informacije o blogu koji su upisani u Admin panelu unutar Settings menija, kartica General. Tačnije, u zavisnosti od toga šta joj prosledite, takav ćete ispis dobiti. Pogledajmo par primera:

    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // ispisuje: http://localhost/wp-content/themes/aurelius
    bloginfo('template_directory');

    // ispisuje: http://localhost/wp-content/themes/aurelius
    bloginfo('stylesheet_directory');

    // ispisuje: Aurelius (hint: wp-admin/settings/general)
    bloginfo('name');

    // ispisuje: This is just another WordPress blog (hint: wp-admin/settings/general)
    bloginfo('description');

    Dakle, sve što treba da uradimo je da svuda gde primetimo relativne putanje, ubacimo bloginfo(‘template_directory’). Trebalo bi da dobijete uradite to ovako:

    
    1
    2
    3
    4
    5
    6
    7
        <!-- Stylesheets -->
        <link rel="stylesheet" href="<?php bloginfo('template_directory'); ?>/style.css" />
       
        <!-- Scripts -->
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
        <script type="text/javascript" src="<?php bloginfo('template_directory'); ?>js/jquery.roundabout-1.0.min.js"></script>
        <script type="text/javascript" src="<?php bloginfo('template_directory'); ?>js/jquery.easing.1.3.js"></script>

    Ne zaboravite da istu proceduru primenite i na ostatku home.php stranice (tu posebno mislim na 5 featured sličica i 4 sličica ispod).

    2. Izdvajanje delova koji su isti na svim stranicama

    Nakon ove faze, početna stranica izgleda stilizovano. Međutim, pogledajte šta se dešava kad kliknete na sledeći link: http://localhost/wordpress/?p=1 (ovo je link default blogpost-a koji postoji kada instalirate WordPress). Ovo vam je sad poznat problem sa prepoznatljivom dijagnozom: linkovi do CSS-a i JavaScript-a, kao i svih ostalih sličica nisu dobri. Da li pokušavam da kažem da ćete morati na svakoj stranici da ručno upisujete bloginfo(‘template_directory’)? Ne, to bi bilo suludo. Umesto toga, postoji drugi, bolji i praktičniji način – identifikovaćemo delove sajta koji su identični na svim stranicama i izdvojiti u poseban fajl, koji ćemo onda uključiti u svaki mogući template.

    header.php

    Ako se vratimo na HTML/CSS temu koju smo preuzeli sa NetTuts-a i pogledamo njene stranice (savetujem da pogledate i vi dok pratite ovaj tutorijal), doći ćemo do zaključka da je gornji deo sajta identičan na svim mogućim stranicama. Jedino po čemu se one razlikuju je strelica iznad stavke u navigacionom meniju koja sugeriše posetiocu na kojoj stranici se on trenutno nalazi. U WordPress-u je omogućeno postići taj efekat sa strelicom na veoma jednostavan način (uskoro ćete videti kako).

    Na slici je prikazan vizuelno deo koji se ponavlja od strane do strane. Kod koji čini taj deo (unutar home.php fajla) je:

    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>Aurelius | A premium Business and Portfolio theme</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
       
        <!-- Stylesheets -->
        <link rel="stylesheet" href="<?php bloginfo('template_directory'); ?>/style.css" />
        <!-- Scripts -->
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
        <script type="text/javascript" src="<?php bloginfo('template_directory'); ?>js/jquery.roundabout-1.0.min.js"></script>
        <script type="text/javascript" src="<?php bloginfo('template_directory'); ?>js/jquery.easing.1.3.js"></script>
        <script type="text/javascript">    
            $(document).ready(function() { //Start up our Featured Project Carosuel
                $('#featured ul').roundabout({
                    easing: 'easeOutInCirc',
                    duration: 600
                });
            });
        </script>  

    </head>
    <body>
        <div id="wrapper" class="container_12 clearfix">

            <!-- Text Logo -->
            <h1 id="logo" class="grid_4">Aurelius</h1>
           
            <!-- Navigation Menu -->
            <ul id="navigation" class="grid_8">
                <li><a href="contact.html"><span class="meta">Get in touch</span><br />Contact Us</a></li>
                <li><a href="blog.html"><span class="meta">Latest news</span><br />Blog</a></li>
                <li><a href="portfolio.html"><span class="meta">Our latest work</span><br />Portfolio</a></li>
                   
                <li><a href="about.html"><span class="meta">Who are we?</span><br />About</a></li>
                <li><a href="index.html" class="current"><span class="meta">Homepage</span><br />Home</a></li>
            </ul>
           
            <div class="hr grid_12">&nbsp;</div>
            <div class="clear"></div>

    Sve što treba da uradimo je da taj deo koda izbacimo iz fajla home.php i ubacimo ga u fajl header.php, koji smo već kreirali u prvom delu.

    footer.php

    Pre nego što nekako ubacimo (include-ujemo) header.php fajl u home.php (ali i u ostale template koje smo definisali), prepoznaćemo još jedan deo sajta koji se izdvaja kao zajednički na svim stranicama. To je footer, koji je čak potpuno identičan i nema nikakvu karakteristiku na nekoj stranici (za razliku od header-a, koji ima strelicu). Vizuelno, deo koji smo uočili da se ponavlja je:

    a kod koji čini taj deo je:

    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <div class="hr grid_12 clearfix">&nbsp;</div>
            <!-- Footer -->
            <p class="grid_12 footer clearfix">
                <span class="float"><b>&copy; Copyright</b> <a href="">QwibbleDesigns</a> - remove upon purchase.</span>
                <a class="float right" href="#">top</a>
            </p>
           
        </div><!--end wrapper-->
    </body>
    </html>

    Na potpuno isti način, to parče koda ćemo iseći iz home.php fajla i ubaciti u fajl footer.php.

    Funkcije get_header() i get_footer()

    Kada biste u ovom trenutku refresh-ovali početnu stranicu, dobili biste novi raspad sistema, što je i logično s obzirom da smo iz home.php fajla izbacili veoma bitan deo gde uključujemo CSS i JavaScript funkcije. Taj kod se, kao što smo malopre rekli, nalazi u header.php fajlu. Potrebno ga je sad ubaciti nazad u home.php, ali i u sve ostale fajlove koji postoje. Da biste ubacili header.php fajl u neki template (recimo home.php), potrebno je da pozovete WordPress-ovu funkciju get_header() na samom početku tog fajla (home.php) i to će njemu biti sasvim dovoljno da zna šta zapravo želite da uradite.

    Ista stvar važi i za footer.php, s tim što ćete, intuitivno, na kraju home.php fajla pozvati funkciju get_footer(). Ako sada refresh-ujete početnu stranicu, videćete da se sve ponovo vratilo u normalu. Međutim, ukoliko ponovo odete na link od malopre http://localhost/wordpress/?p=1, videćete da tu stvari i dalje ne funkcionišu. Da biste to ispravili, potrebno je da istu proceduru koju ste primenili na home.php, primenite i na ostalim template-ima:

    • category.php
    • page.php
    • blog.php
    • single.php
    • portfolio.php
    • portfolio-single.php

    U svim ovim fajlovima ćete videti na samom početku i samom dnu blokove koda koje smo izdvojili u fajlovima header.php i footer.php, te je potrebno da ih obrišete i da pozovete get_header() i get_footer() funkcije.

    Zašto je dobar ovaj pristup?

    Možda se pitate, zašto ovo radimo? Glavni i jedini razlog je da bismo imali manji posao prilikom izmena (nadogradnje) sajta. Zamislite da u jednom trenutku želite da dodate novu JavaScript biblioteku unutar head tagova. Sa ovakvom organizacijom fajlova, potrebno je da tu JavaScript biblioteku ubacite u samo jedan fajl i promena će se reflektovati na svim ostalim stranicama. U suprotnom, morali bismo da menjamo svaki template koji imamo u našoj temi kako bismo bili sigurni da se promena reflektovala na svakoj strani sajta.

    3. Kreiranje navigacionog menija

    Da bismo uopšte otpočeli sa sređivanjem navigacije, moramo prvo imati sa čime da radimo, odnosno moramo kreirati strane koje će biti u toj navigaciji. Ulogujte se u svoj admin panel na localhost/wordpress/wp-admin i kliknite na Pages sa leve strane. Čisto jedna blaga napomena – ovde treba napraviti razliku između dve vrste zapisa u WordPress-u: postova i stranica.

    Postovi su vezani za određene kategorije i to je ono što ćemo da izlistavamo na strani blog.php. Stranice, sa druge strane, predstavljaju neki statični sadržaj, koji nije vezan ni za koju kategoriju, niti se prikazuje datum kada je ona objavljena. Jednostavno, njen zadatak je da pruži određene informacije (About, Portfolio, Contact i slično). Ono što ćemo mi imati u navigaciji su stranice. S obzirom da jasno na slici imamo koje stranice su potrebne, sledeće što ćemo uraditi je da ih kreiramo.

    S obzirom da ste ispratili prvi pasus u podnaslovu 3, trebalo bi da se nalazite u delu admin panela za uređivanje stranica. Tamo se nalazi default WordPress stranica koju treba da obrišete. S obzirom da je sve isuviše jednostavno, zamoliću vas da kreirate sledeće stranice (obratite pažnju, pored naslova i proizvoljnog sadržaja, unesite i vrednost u Order polju, koje se nalazi sa desne strane) :

    • About (order 0)
    • Portfolio (order 1)
    • Blog (order 2)
    • Contact (order 3)

    Vrednost order koju smo uneli na svim stranicama će nam pomoći da u navigaciji strane idu redosledom kojim mi želimo. Kao što vidite, izostavili smo Home, videćete veoma brzo zašto.

    Funkcija wp_list_pages()

    Umesto hardcode-ovane navigacije (nalazi se u header.php fajlu), ubacićemo novu WordPress funkciju koja će nam izlistati sve strane koje smo upravo kreirali. Ta funkcija je wp_list_pages() koja prima razne argumente (tip: pogledati sve mogućnosti koje pruža ova funkcija na zvaničnoj dokumentaciji). Napomena, sve češća praksa je da se navigacioni meni kreiraju u admin panelu, a onda ispisuju pomoću wp_nav_menu() funkcije i to je sjajan istraživački zadatak za one koji žele da saznaju više.

    Dakle, otvorite header.php fajl i izbrišite sve stavke iz navigacije (oko linije 30) osim poslednje (Homepage). Umesto svega toga, unećemo wp_list_pages() koja će nam ispisati sve stranice koje smo mi malopre kreirali. Treba da imate sledeći kod:

    
    1
    2
    3
    4
    <ul id="navigation" class="grid_8">
        <?php wp_list_pages( 'title_li=&sort_column=menu_order&sort_order=DESC' ); ?>
        <li><a href="<?php get_home_url(); ?>" class="current">Home</a></li>
    </ul>

    Ukoliko refresh-ujete stranicu, dobićete navigaciju koja je u potpunosti prikazana iz baze. Obratite pažnju na parametre koje smo prosledili wp_list_pages() funkciji:

    • title_li= ostaje prazno, zato što ne želimo da imamo nikakav naslov iznad naše liste.
    • sort_column=menu_order, ovim smo stavili do znanja da želimo da se stranice sortiraju po vrednosti iz polja Order
    • sort_order=DESC, sortiranje u opadajućem redosledu.

    Kada prosleđujete više parametra jednoj funkciji, morate ih spajati & karakterom.

    Početna stranica i home.php vs page.php template

    Jedina stvar koju nismo izvukli iz baze je Home stranica, zato što ona ustvari nije klasična stranica (ne koristi page.php template), već je to home stranica (koristi home.php template). Mogli smo je napraviti kao klasičnu stranicu, a onda u njenim podešavanjima reći da ta stranica koristi home.php kao svoj template, ali u tom slučaju ta stranica se ne bi automatski otvarala kada korisnik poseti adresu (http://localhost/wordpress), već bi se otvorila index.php stranica. Naravno, moguće je i to ispraviti (WordPress je previše fleksibilan sistem, videćete već) tako što bismo otišli na Settings->Reading->Front page displays i izabrati Home page. Ništa od ovoga nije komplikovano, ali se meni lično dopada više pristup da početnu stranicu odvojimo od ostalih strana na sajtu, a to oko dodeljivanja posebnog template-a određenoj stranici ćemo uraditi kod portfolio i blog stranica, pa ćete tu tačno videti o čemu je reč.

    4. Izgradnja page.php template-a

    Sledeća stvar kojom ćemo se pozabaviti je ispis sadržaja na svakoj od stranica iz gornje navigacije. Trenutno, kada korisnik klikne na bilo koju od stavki (About, Portfolio, Contact), dobiće hardcode-ovan sadržaj koji se nalazi unutar page.php. Ono što je naš cilj ovde je da konačno uvedemo neku dinamiku – sećate se priče o template-ima iz prvog dela i forme koja je definisana samo jednom, a njen sadržaj se dinamički popunjava pomoću PHP-a iz baze podataka? Ukoliko da, upravo je to ono čime se u nastavku bavimo.

    WordPress loop

    WordPress loop je način na koji vi ustvari ispisujete podatke iz baze na stranu na kojoj se trenutno nalazite. To je stvar na koju ćete se vraćati svaki put kada radite sa WordPress-om i zato je veoma poželjno da upamtite kako on funkcioniše. Zapravo, postoji šablon koji uopšte nije težak za pamćenje. Otvorite fajl page.php koji smo malopre definisali i unesite sledeći kod:

    
    1
    2
    3
    4
    5
    6
    <?php if(have_posts()) : while(have_posts()) : the_post(); ?>
    <div class="grid_8">
        <h4 class="page_title"><?php the_title(); ?></h4>
        <div class="hr dotted clearfix">&nbsp;</div>
        <?php the_content(); ?>
    </div>

    Šta se ovde dešava? Prvo, ova petlja proverava da li uopšte postoji neki post za prikaz (if klauzula). Ukoliko je uslov ispunjen, počinje while petlja, koja se izvršava onoliko puta koliko ima postova za prikaz. S obzirom da ispisujemo sadržaj jedne stranice, petlja će se izvršiti samo jednom. Unutar te petlje se pozivaju neke funkcije koje su dostupne samo unutar ovog while bloka (uskoro o njima). Sačuvajte page.php fajl i refresh-ujte blog. Kliknite na neku od strana iz navigacije i videćete njen naslov i sadržaj, koji ste vi sami uneli kada ste kreirali ove stranice.

    Ono što je u celoj priči prelepo je to da vi uopšte ne morate da vodite računa ni o čemu: na primer, nije potrebno da razvijete neku logiku za utvrđivanje stranice na kojoj se korisnik trenutno nalazi, te u zavisnosti od toga da kreirate ručno (i sami) SQL upit kojim biste zahtevali podatke iz baze o toj stranici. Čak i kada biste to uradili, potrebno bi bilo da podatke dobijene od servera (spakovane u niz) nekako raspakujete i prikažete korisniku. Međutim, WordPress je to već uradio za vas (postoje funkcije the_title() i the_content()). Dakle, WordPress je kompletnu logiku razvio za sebe, vi samo to treba da znate da koristite.

    Pregled funkcija koje su dostupne u WordPress loop-u

    Kao što smo malopre videli, WordPress je definisao neke funkcije kojima imamo pristup samo unutar loop-a, jer one uglavnom vraćaju ili ispisuju nešto što je povezano sa postom koji je trenutno u petlji. To su:

    the_title() – ispisuje naslov posta/strane

    the_excerpt() – ispisuje skraćenu verziju sadržaja

    the_content() – ispisuje kompletan sadržaj

    the_ID() – ispisuje ID posta/strane

    the_permalink() – ispisuje link do posta/strane

    the_author() – ispisuje ime autora koji je objavio post/stranu

    the_category() – ispisuje kategoriju posta pod kojom je zaveden (ili više njih)

    5. Sidebar na stranicama about i contact

    Ovaj deo ćemo završiti dodavanjem sidebar-a na stranicama sa kojima smo upravo radili. Već znamo da je template koji generiše njihov sadržaj page.php, te će sigurno biti potrebno da izvršimo modifikaciju u njemu. Ukoliko otvorimo taj template u nekom editoru, videćemo po HTML komentarima tačno mesto gde sidebar treba da se nalazi (Column 2 / Sidebar). Potrebno je da čitav kod koji se nalazi u divu ispod (ima klasu grid_4) isečemo i smestimo u novi fajl, recimo about-sidebar.php. Potpuno istu stvar ćemo uraditi i za stranicu contact. S obzirom da u našoj temi nemamo kod koji treba da se nalazi na toj stranici (sećate se da smo od stranice about napravili template page.php koji će opsluživati stranice about i contact, ali i sve ostale strane u budućnosti koje imaju istu strukturu), moraćemo da se vratimo na HTML/CSS template i pogledamo kako izgleda kod za sidebar na contact stranici.

    Dakle, otvorite stranicu contact.html iz HTML/CSS teme koju smo skinuli i pronađite blok koji se odnosi na sidebar (između 94. i 130. linije koda). Sačuvajte taj deo u novi fajl unutar naše teme, recimo contact-sidebar.php i onda možete da zatvorite contact.html iz HTML teme.

    get_template_part() funkcija

    Nakon što smo pripremili fajlove koje ćemo ubaciti u naš template, potrebno je da to zapravo i uradimo. Ukoliko se sećate, kada smo uključivali header.php i footer.php u sve ostale template, mi smo koristili funkcije get_header() i get_footer(). Međutim, kada uključujemo delove koji nisu neki od ta dva fajla, moramo da koristimo funkciju get_template_part() koja kao svoj parametar prima naziv fajla koji želimo da uključimo, ali bez njegove ekstenzije. Dakle, za sidebar na about strani će biti get_template_part( ‘about-sidebar’ ), a za sidebar na contact strani get_template_part( ‘contact-sidebar’ ).

    is_page() funkcija

    Bilo bi idealno ukoliko ste se sad zbunili! Najbolje pitanje koje sebi u ovom trenutku možete postaviti je: zar stranice about i contact ne koriste jedan zajednički template, page.php? Kako da pozovem dva puta ovu funkciju – dobiću dva sidebar-a? Ukoliko vam je ovo prošlo kroz glavu, čestitam vam, zato što ste pažljiv čitalac. Ukoliko nije, razmislite još jednom – ako u template page.php pozovemo dva puta funkciju get_template_part() sa različitim ulaznim parametrima, kada refreshujemo neku od te dve stranice, dobićemo dva sidebar-a, jedan ispod drugog. Potrebno je postaviti uslov – ukoliko je posetilac na stranici about, prikaži mu about-sidebar. Sa druge strane, ukoliko je na contact, prikaži mu contact-sidebar.

    Upravo za ove stvari se koristi is_page funkcija, koja kao parametar može primiti ID stranice (vidite u linku), ili čak naziv stranice. Sledeći blok koda je veoma jednostavan, pa ga neću dodatno komentarisati (potrebno ga je ubaciti na mesto sidebar-a u page.php).

    
    1
    2
    3
    4
    <?php
        if( is_page(5) ) { get_template_part( 'about-sidebar' ); }
        if( is_page(11) ) { get_template_part( 'contact-sidebar'); }   
    ?>
    Download fajlova iz ovog dela

    Sve što je do sada urađeno možete preuzeti odavde.

    Kraj drugog dela

    Došli smo i do kraja drugog dela. Uradili smo dosta, ali isto tako – veliki posao je pred nama. U sledećem delu, koji izlazi u subotu, napravićemo blog i single template, ali i omogućiti komentarisanje na blogu. Ukoliko se ne snađete sa bilo čim iz ova dva dela, ostavite komentar kako bih mogao da pomognem.

    Izgradnja Aurelius WordPress teme

    Na ovogodišnjem serijalu predavanja Studenti studentima u okviru FONIS-a držim WordPress development kurs sa primarnim fokusom na kreiranje teme od nule. Ta tema već postoji i možete je preuzeti sa NetTuts-a. Naš posao, dakle, nije HTML/CSS kodiranje, već isključivo izgradnja jedne WordPress teme od nule. Ukoliko ste i vi u potrazi za jednim takvim tutorijalom – na pravom ste mestu, jer ono što sledi su beleške sa tih radionica.

    Stvari koje će biti obuhvaćene ovim serijalom
  • Analiza zahteva koje moramo ispuniti
  • Instalacija WordPress-a
  • Upoznavanje sa strukturom foldera i fajlova WordPress-a
  • Kreiranje WordPress teme
  • Nadogradnja teme naprednijim funkcionalnostima
  • 1. Analiza zahteva koje moramo ispuniti

    Zamislite da ste uz ovaj dizajn dobili i zahteve kako Aurelius tema mora da radi. Tu pre svega mislim na to šta od sadržaja na sajtu može biti statičko (hardcode-ovano), a šta mora biti dinamično, odnosno izmenljivo kroz WordPress admin panel. Krenućemo redom. Otvorite folder Aurelius HTML/CSS teme, koji ste maločas skinuli sa NetTuts-a.

    Navigacija

    Ovaj deo sajta je skoro u potpunosti identičan na svim stranicama na sajtu, osim što postoji strelica koja signalizira posetiocu sajta na kojoj se strani trenutno nalazi. Potrebno je omogućiti da se stavke (odnosno linkovi ka stranicama) iz ove navigacije prikazuju iz baze, naravno uz prikazivanje strelice iznad stranice na kojoj je posetilac trenutno. To zapravo znači da će svaka nova stranica koja bude kreirana u okviru Admin panela biti prikazana u navigaciji, ali i da će svaka stranica nestati iz navigacije ukoliko je administrator obriše iz admin panela.

    index.html

    Na ovoj stranici je potrebno obezbediti da jQuery slajder bude dinamičan. Administrator će iz admin panela birati koje sličice će biti u tom slajderu, ali će isto tako imati mogućnost da upiše link (takođe u admin panelu) na koji će korisnik biti redirektovan kada klikne na sliku. Ostatak početne početne stranice može biti statičan: tagline i četiri kvadratića (linkova) neće biti izmenljivi kroz ACP.

    Stranice: about.html, contact.html

    Iako se u navigaciji nalaze još i portfolio.html i blog.html, njih ćemo razmatrati u sledećem pasusu iz razloga što se suviše razlikuju u odnosnu na ove dve koje su navedene. I about.html i contact.html imaju svoj tagline, koji mora biti izmenljiv unutar admin panela, zatim centralni deo u kome se nalazi sadržaj te stranice (mora biti izmenljiv iz admin panela), kao i sidebar sa desne strane koji ima neki svoj sadržaj (biće statički, pa korisnik ne može da ga menja).

    Stranice: portfolio.html i portfolio_single.html

    Takođe ima tagline koji mora biti izmenljiv iz ACP. Na ovoj stranici su prikazani radovi vlasnika sajta, s tim što su oni grupisani u tri celine (umesto WebDesign-a koji se ponavlja tri puta, mi ćemo imati sledeće kategorije: WordPress, Joomla, Drupal). Kada posetilac klikne na bilo koji od izloženih radova, odlazi na novu stranicu portfolio_single.html na kojoj se nalaze detalji (naziv projekta, opis, screenshot i eksterni link) o tom pojedinačnom projektu. Ovo je veoma karakteristična struktura koja ne postoji u WordPress-u po defaultu. Drugim rečima, ne postoji skup polja u admin panelu gde bismo mi mogli da pored naziva, opisa i slike unesemo i eksterni link do tog projekta. Zato ćemo na neki način morati da proširimo WordPress i omogućimo administratoru input za eksterni link.

    Stranice: blog.html i single.html

    Ove dve stranice predstavljaju srž WordPress-a kao platforme zato što omogućavaju ono za šta je on u osnovi i namenjen – hronološkom prikazu blog postova, njihovoj kategorizaciji, ostavljanju komentara i slično. Klasični WordPress blogovi imaju takav prikaz postova na naslovnoj stranici, ali to kod nas nije slučaj. Iz tog razloga ćemo prvo morati da kreiramo poseban template koji će blog stranica da koristi, a onda ćemo ga njoj i dodeliti unutar admin panela (videćete kasnije o čemu je tačno reč). Takođe, primećujete da se i na blog.html i single.html nalazi sidebar sa desne strane na kome je prikazan spisak postojećih kategorija, blog arhiva, kao i spisak najnovijih zapisa (na stranici single.html).

    2. Instalacija WordPress-a na localhost-u

    Da biste instalirali WordPress, neophodno je da proverite da li imate sledeće stvari:

  • WordPress instalaciju, koju možete preuzeti sa zvaničnog sajta
  • WAMP, program koji će vam instalirati Apache web server, PHP i MySQL (neophodni da bi WordPress radio). Dowload link.
  • Naravno, možete instalirati WordPress ukoliko radite i na Linux-u ili MacOS-u, s tim što ćete u tom slučaju umesto WAMP-a instalirati LAMP na Linux-u, odnosno MAMP za MacOS.

    Ukoliko posedujete sve što smo naveli, pokrenite WAMP (indikator da radi je zelena W ikonica u System tray-u, kod sata) i onda otvorite WWW folder (tačna lokacija je: C:\wamp\www). Ovde imate dve opcije: da raspakujete sve WordPress foldere i fajlove direktno u www direktorijum (takozvani root direktorijum) ili da unutar root direktorijuma kreirate poseban folder, recimo wordpress i da onda tu ubacite sve WordPress-ove stvari. Ja ću uraditi na drugi način, zato što sam na taj način omogućio da, pored WordPress-a, na mom serveru postoji još drugih sajtova (mogu čak imati i više WordPress instalacija na jednom serveru, recimo C:\wamp\www\wordpress, C:\wamp\www\wordpress1, C:\wamp\www\wordpress2 itd).

    Pogledajte screenshot kako izgleda kod mene direktorijum sa WordPress fajlovima i proverite da li ste i vi tako uradili. Možete proveriti da li vam je sve dobro tako što ćete iz vašeg omiljenog browser-a posetiti stranicu http://localhost/naziv-wordpress-foldera (kod mene je http://localhost/wordpress). Ukoliko je sve kako treba, pojaviće vam se WordPress installer, kroz koji ćemo proći nakon što kreiramo bazu.

    Kreiranje baze

    Nakon što smo uspešno raspakovali WordPress fajlove, sledeća stvar koju treba da uradimo je da kreiramo bazu za WordPress. Iz vašeg omiljenog browser-a posetite stranicu http://localhost/phpmyadmin (ukoliko WAMP nije uključen, neophodno ga je uključiti). Iz navigacionog menija izaberite Databases (prva stavka na vrhu), a onda će vam se pojaviti polje za kreiranje nove baze. U prvo input polje upišite aurelius i kliknite na Create. To je sve u ovoj fazi.

    WordPress installer

    Sada imamo sve što je potrebno te možemo pristupiti WordPress instalaciji. Posetite adresu http://localhost/naziv-wordpress-foldera (kod mene će to biti http://localhost/wordpress). Nakon dobrodošlice, pojaviće vam se stranica na kojoj treba da ukucate parametre za pristup bazi koju ste maločas kreirali. U polje Database Name upišite aurelius, Database user: root, Database password: ostavite prazno. Ostale stvari koje tu stoje ostavite tako kako je već upisano. Napomena: Ovde su uneti parametri koje smo koristili pri kreiranju baze u prethodnoj fazi. Ukoliko ste vi dali drugačije ime bazi, unesite to polje u Database name. Isto važi i za database user-a i database password (koji ne postoji po defaultu, ali ukoliko ste vi naknadno dodali, potrebno je da upišete tu vrednost).

    Poslednja stvar koju treba da uradite je da nekako nazovete vaš blog (recimo Aurelius), ali i da date sebi neki username/password preko kojih ćete se logovati na sistem (ja ću postaviti admin/admin).

    I za kraj ovog dela, još jednom:

    • pristup front delu sajta (http://localhost/wordpress)
    • pristup admin delu sajta (http://localhost/wordpress/wp-admin)
    3. Upoznavanje sa strukturom foldera i fajlova WordPress-a

    Pre nego što krenemo na razvoj teme, želim da na kratko obratimo pažnju na samu strukturu jednog WordPress sajta. Unutar njegovog root foldera se nalaze tri foldera i desetak običnih fajlova, od kojih bih izdvojio samo wp-config.php kao fajl sa kojim ćete imati posla. U njemu se nalaze parametri za konektovanje sa bazom, u njemu se definiše prefix svih tabela u toj bazi, kao i jezik koji je aktivan na sajtu (linija 72). To je fajl koji WordPress popunjava prilikom instalacije, odmah čim kliknete na next ispod forme u koju ste  unosili parametre za bazu podataka. Ukoliko nekad rešite da preselite sajt koji ste razvijali na localhostu na neki web hosting, wp-config.php je fajl u kome ćete ručno ubaciti parametre nove baze umesto postojećih parametra.

    • /wp-admin je folder u kome se nalazi sve što vidite unutar administratorskog dela sajta. Uglavnom vas neće interesovati sadržaj ovog foldera, osim u situacijama kad želite da modifikujete Admin panel.
    • /wp-content je folder kojim ćete se najčešće baviti tokom vaše WordPress karijere. U njemu se nalaze folderi /themes gde su smeštene sve instalirane teme bloga (među njima i naša, koju uskoro krećemo da razvijamo), zatim /plugins gde će biti smešteni svi dodaci koje imate na blogu i izdvojio bih /uploads folder u kome se čuvaju sve sličice koje uploadujete u vašim blog postovima/stranama.
    • /wp-includes je folder u kom se nalaze sve biblioteke i klase koje pokreću WordPress sajt. Žargonski rečeno, to vam je glavno jezgro, motor sajta (engl. WordPress core). Slično kao i sa /wp-admin folderom, veoma retko ćete zalaziti u ovaj deo.
    4. Kreiranje WordPress teme

    Došlo je vreme za glavnu stvar na ovom kursu – kreiranje teme od nule. Tačnije, ne baš skroz od nule, s obzirom da imamo iskodiran sajt, ali bez obzira – ako uzmemo u obzir šta je naš cilj, definitivno trenutno nemamo ništa. Postoji više različitih načina za kreiranje WordPress teme, ali ćemo na ovom kursu pokušati da ispoštujemo standarde kojih se drže mnogi, tj. držaćemo se najbolje prakse. S obzirom da smo još u prvom delu detaljno “stavili na papir” spisak zahteva koje naša tema mora da ispuni, na to se više nećemo vraćati (ukoliko vam je potreban podsetnik, vratite se na sam početak ovog teksta). Sledeće logično pitanje koje se postavlja je: šta uopšte čini jednu WordPress temu, tj. koje su njene komponente.

    Osnovne komponente jedne WordPress teme

    Pre svega, WordPress tema je skup .php, .css i .js fajlova koji se čuvaju u jednom folderu unutar /themes foldera koji smo spomenuli malopre. Dakle, kada kreirate temu, ona treba da se nalazi na sledećoj putanji: wordpress_root/wp-content/themes/naziv_vaše_teme. U našem slučaju, folder teme će se zvati aurelius, pa će njegova putanja biti wordpress_root/wp-content/themes/aurelius. Unutar nje će se nalaziti sledeća skoro identična struktura kao i folderu teme koji smo mi skinuli:

    • /js – folder gde će biti smešteni svi naši JavaScript fajlovi
    • style.css – fajl u kome će se nalaziti čitav CSS naše teme.
    • index.php – osnovni template bez koga tema ne može da postoji.
    • home.php – template za naslovnu stranicu
    • page.php – template koji će opsluživati sve naše stranice
    • blog.php – template koji će hronološki prikazivati sve naše postove
    • category.php – template koji će prikazivati sve postove unutar neke određene kategorije
    • single.php – template koji će prikazati čitav sadržaj jednog blogpost-a
    • comments.php – poseban template koji će izlistavati komentare na postovima, ali i sadržati formu za slanje novog komentara
    • 404.php – za prikaz error 404 stranice ukoliko posetilac pokušava da otvori stranu koja ne postoji
    Kratki uvod u template sistem. Zašto je on važan?

    Pre nego što nastavimo dalje, moram da skrenem pažnju na par stvari. Pre svega, u spisku fajlova iznad, termin template se veoma često javlja. Šta bi tačno bio template? Možete zamisliti template kao šablon ili obrazac koji će uvek imati istu formu, samo drugačije podatke. S obzirom da su čitaoci ovog bloga uglavnom studenti, zamislite formular za potvrdu o položenim ispitima. Fakultet je  definisao formu koju računar, zahvaljujući bazi podataka, popunjava za konkretnog studenta koji je podneo zahtev: ime i prezime, godina i smer, status studiranja, položene ispite i slično. Dakle, forma je definisana samo jednom, ali se podaci koji se nalaze na njoj razlikuju kod svakog studenta. Potpuno ista stvar je i sa template-om u WordPress-u: Postoji forma definisana HTML-om, ali je WordPress pomoću PHP koda i baze podataka popunjava različito svaki put, u zavisnosti od toga šta se traži.

    S obzirom na to da je dizajner HTML teme koju prebacujemo u WordPress temu definisao nekoliko različitih formi (stranice about.html, contact.html imaju jedan izgled, blog.html drugi izgled, portfolio.html treći izgled itd), mi moramo za svaku od njih da definišemo šablon, odnosno template. Šta ćemo time ustvari postići? Za stranice about.html i contact.html (ali i sve ostale koje imaju tu strukturu) ćemo definisati samo jedan template i onda dinamički (PHP-om) upisati adekvatne podatke, u zavisnosti od toga da li se posetilac nalazi na About, Contact ili nekoj trećoj strani sa istom strukturom. Dalje, pogledajmo među fajlovima teme koje smo skinuli fajl single.html. To je šablon kako treba da izgleda jedan blog post. Koliko blog postova ima na jednom blogu? Deset, dvadeset, 100…1000? Potpuno je nebitno, mi ćemo definisati šablon single.php koji će važiti za sve moguće blogpost-ove.

    Dva fajla bez kojih tema ne funkcioniše: index.php i style.css

    Primećujete da su fajlovi style.css i index.php plavi? To je druga napomena koju želim da naglasim: ukoliko ova dva fajla ne postoje, tema neće raditi i za to postoji dobar razlog.

    style.css se mora zvati style.css. Ne sme biti u nekom folderu (recimo CSS), već mora biti u root direktorijumu vaše WordPress teme. Ovaj fajl je neizostavni deo teme zato što se u njemu nalaze osnovne informacije o vašoj temi. Ukoliko otvorite style.css bilo koje teme, videćete da se na samom početku nalazi blok koji izgleda ovako (prikazujem vam skraćenu i neophodnu verziju ovog bloka, za punu pogledajte ovde):

    
    1
    2
    3
    4
    5
    6
    /*
    Theme Name: Aurelius
    Description: Tema koju pravimo na S2S kursu.
    Author: Milan Stojanov
    Version: 1.0
    */

    Dakle, vrlo jednostavno – ukoliko izostavite ovaj blok, WordPress neće imati nikakve informacije o temi koju pokušavate da napravite i samim tim će izbaciti grešku da tema nije validna.

    index.php je template na koji može sve da se svali. Šta to znači? Ukoliko izostavite neki od template-a iznad, WordPress će pozvati index.php i izvršiti kod koji se nalazi u njemu. Pogledajte sledeću šemu:

    —HOME: home.php > index.php —PAGE: page.php > index.php —CATEGORY: category.php > archive.php> index.php —SINGLE: single.php > index.php —ARCHIVE: archive.php > index.php —404: 404.php > index.php

    Kako se ovo tumači? Ukoliko posetilac ode na link http://localhost/wordpress (želi da otvori početnu stranicu sajta), WordPress će prvo potražiti fajl home.php i ukoliko ga pronađe, izvršiće njega. Ukoliko ne, pozvaće fajl index.php koji sigurno postoji jer drugačije ne bismo mogli da aktiviramo temu. Dalje, sećate se da su sve stavke iz naše gornje navigacije ustvari stranice koje ćemo tek napraviti? Kada bi korisnik kliknuo recimo na About iz navigacije, WordPress će prepoznati da se zahteva stranica i prvo će pokušati da prikaže page.php template, ali ukoliko ga ne pronađe, otvoriće index.php. Isti princip važi i za ostale strane (blog postove, kategorije, 404 str i slično).

    Kraj prvog dela

    Ovim završavamo prvi deo ovog serijala. Novi izlazi već sutra, gde ćemo primeniti ono što smo danas naučili i kreirati sve fajlove koji će činiti našu temu, ali ono što je još bitnije – otpočeti njeno kodiranje. Nadam se da sa nestrpljenjem očekujete nastavak sutra. Pozdrav

    U ovom članku ćemo se upoznati sa osnovama rada u Qt Creator-u, krenuti sa pisanjem prvog C++ koda: podsetićemo se šta se dešava u memoriji dok program radi, naučićemo neke specifičnosti objekata u C++-u, te kako se u program uvode klase definisane negde drugde.

    Prvi koraci

    Qt Creator - Welcome - Develop

    Prvo što vidimo kad se pokrene Qt Creator je početni, pozdravni ekran. Na levoj strani prozora je vertikalna traka na kojoj se nalaze “tabovi”:

    • Welcome – U kviru njega na vrhu imamo tri podtaba, najviše ćete koristiti Develop ekran, tu komande za otvaranjei kreiranje projekata, kao i lista skoro otvaranih projekata
    • Edit – Ovo je mod za kucanje koda. Tu je lista trenutno otvorenih projekata, njihovih fajlova i naravno editor koda (koji podržava semantičko bojenje koda (naziva tipova, promenljivih u okviru objekata…) i autocomplete svega)
    • Design – Ovaj mod se koristi za pravljenje grafičkog interfejsa
    • Debug – ovo je ekran za debug-ovanje (traženje grešaka u programu)
    • Projects – Ovde su sva podešavanja otvorenih projekata (kompajliranje, pokretanje itd…)
    • Analyze – Ovo je mod za analizu performansi, nećemo ga koristi
    • Help – Ovde se nalazi sva ona dokumentacija koju ste štiklirali pri instalaciji Qt-a, dakle dokumentacija cele Qt biblioteke i pratećeg softver-a

    Na dnu trake su komande za kompajliranje (čekić) i pokretanje (play dugme) programa koje pišete.

    Kreiraćemo novi projekat klikom na dugme “Create Project…” ili iz menia File->New File or Project… Za tip projekta ćemo izabrati Other Project -> Qt Console Application. Kada date ime projektu i lokaciju gde će bit njegov folder, preskočite sledeću fazu, i dobićete ekran sa početnim podešavanja koja ću objasniti.

    Treba da bude štiklirano Desktop (gole levo), iz liste “Create Build Configuration” izabraćemo drugu stavku. Shadow Building će bit razbeleženo. Iz liste Qt Version izaberite prvu stavku (novija verzija Qt-a), a štiklirajte obe opcije koje su na dnu (debug i release). Sa ovim podešavanjima svi proizvodi kompajliranja će ići u isti folder sa C++ fajlovima. Ovo je u redu za sitne programe, ali za veće projekte treba bolja organizacija, o tome u nekom idućem članku, za sada je ovako OK.

    Po kliku na Done otvoriće se Edit mod sa otvorenim fajlom main.cpp. Na levoj strani ćete videti spisak fajlova u vašem projektu. Prvi na listi je takozvani PRO fajl. U njemu se nalze informacije potrebne da bi se projekat kompajlirao, za sada nas on ne zanima, o PRO fajlu će biti reču u nekom od kasnijih članaka. Qt Creator sve fajlove projekta deli po tipu, main.cpp je C++ source fajl pa se nalazi u grupi Sources. Ovo nije folder u fajl sistemu, već je samo u pitanu grupisanje koje pravi Qt Creator dok je projekat otvoren.

    Obnavljanje znanja

    Da bi mogli da razumete C++ moramo da obnovimo znanje o tome šta se dešava u RAM memoriji računara tokom izvršavanje programa. Tokom izvršavanja u memoriji postoje dva segmenta: stack i heap. Sve promenljve primitivnog tipa (int, long, float, char…) koje deklarišete unutar neke funkcije se nalaze na stack-u i životni vek im je onoliki koliko traje izvršenje te funkcije (jer ne postoji način da im se pristupi kad se funkcija završi). Životni vek podataka na heap-u je neodređen. Da bi moglo da se pristupa nekim podacima na heap-u, mora na stack-u da postoji neka promenljiva u kojoj se nalazi meorijska adresa tih podataka na heap-u.

    U Javi i C#-u postoji pojam klase, i klase su takozvani referentni tipovi. To znači da kada se deklariše neki objekat kao promenljiva, u stvari je deklarisana promeljiva na stacku koja sadrži adresu stvarnog objekta koji se nalazi na heap-u. To je zapravo referenca. Njoj je potrebno dodeliti objekat na koji će da pokazuje (povratna vrednost neke metode, neki postojeći objekat, ili novokreirani objekat (ključnom reči new)).

    U C++-u, osim na heap-u, objekti mogu postojati i na stack-u i oni će nestati po završetku funkcije u kojoj su deklarisani. O tome kako se radi sa objektima koji su na stack-u, a kako sa oniama koji su na heap-u će biti reči kasnije. Sada počinjemo sa pravim C++ kodom.

    Prvi C++ kod

    Sada slobodno obrišite sadržaj main.cpp fajla koji je Qt Creator sam generisao i iskucajte sledeći kod:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #include <QTextStream>

    int main(int argc, char* argv[])
    {
        QTextStream out(stdout);

        out << "Ovo treba da se vidi na konzoli.\n";
        return 0;
    }

    (Savetujem vam da kodove ne kopirate nego da ih prekucavate ručno, tako ćete naučiti ) )

    Kompajlirajte i pokrenite. Ako ste sve dobro prekucali, neće biti grešaka, i tekst će biti prikazan na konzoli.

    Ali šta se u ovom programu zapravo događa, šta znači koja linija koda? Objasnićemo deo po deo ovog programa.

    1
    int main(int argc, char* argv[])

    Ovako se u C++-u definiše main funkcija, za sada treba da znate da u C++-u main funkcija mora da vraća int. Trebalo bi da se sećate da u Javi i C#-u main funkcija kao ulaz ima niz stringova (koji predstavljau argumente sa konzole). I ovde je isti slučaj, samo što je ovde u pitanju drugačiji format, za sada ćemo zanemariti, vratićemo se u nekom sledećem članku.

    1
    QTextStream out(stdout);

    Ovom komandom smo deklarisali promenljivu koja se zove out, a njen tip je klasa QTextStream. Zagrade posle imena promenljive su za argumente konstruktoru. Svaki put kada se pravi novi objekat, bilo na stacku ili na heap-u mora se pozvati konstruktor. Ovo je u C++-u sintaksa za pozivanje kostruktora za objekte koji su na stack-u. Ovde konstruišemo objekat nekim konstruktorom koji prima jedan argumenat, i dajemo stdout (stdout je promenljiva definisana negde drugde, a sada nas ne zanima kog je tipa; stdout znači standardni izlaz, i podaci koje prosledimo ovom text stream-u će biti ispisani na konzoli).

    Ako se setimo Jave i C#-a, tamo se svi objekti kreiraju na heap-u, a briše ih automatski sistem za upravljanje memorijom, garbage collector. Sada ću vam reći lošu vest, a to je da u C++-u ne postoji automatsko upravljanje memorijom, objekti se moraju ručno brisati. Međutim, dobra vest je da je C++ takav jezik da se upravljenje memorijom može učiniti poluautomatskim. Jedna od dobrih stvari je i ova mogućnost da se objekti kreiraju na stacku, a obrišu automatski po završetku funkcije.

    1
    out << "Ovo treba da se vidi na konzoli.\n";

    Ova linija će ljudima koji znaju samo Javu izgledati čudno. Poznato je da je << operator za pomeranje bitova koji radi sa celim brojevima. U C++-u se operatori mogu redefinisati (kao i u C#-u, ali bez ograničenja koja postoje u C#-u). Ovde imamo da je redefinisan operator << za objekte klase QTextStream, a koji kao drugi argument prima niz karaktera (da, ovo nije string, u C++-u je ovo prost niz karaktera, znatno prostiji nego nizovi u Javi ili C#-u, a o tome, naravno, kasnije).

    1
    #include <QTextStream>

    Ako ste upoznati sa Javom ili C#-om možda pretpostavljate šta ova komanda znači. E pa nije to što mislite. U C-u i C++-u postoji nešto što se zove preprocesor. To je faza kompajliranja, koja zapravo ne spadau kompajliranje, nego se dešava pre njega. Šta preprocesor u stvari radi. On čita direktive koje se nalze u C++ fajlovima (one počinju sa tarabom) i vrši izmene u samom tekstu programa u skladu sa direktivama. Ovde imamo directivu #include. Ona kao argument prima ime nekog tekstualnog fajla. Preprocesor će kada naiđe na ovu direktivu jednostavno obrisati tu direktivu i na njeno mesto staviti ceo sadržaj tog drugog fajla. Ovde mi include-ujemo fajl koji se zove “QTextStream”. U tom fajlu je definisana klasa QTextStream (to što se fajl zove isto kao i klasa koju koristimo je samo dobra praksa, i nije obavezno). Tu je definisano koja polja i metode klasa ima.

    Ako se setimo Jave i C#-a, tamo ste samo morali da napišete using ili import i navedete namespace ili paket koji hoćete da koristite, i da u projektu naznačite biblioteke koje sadrže te namespace-ove, odnosno pakete. Sve što je bilo potrebno je .dll ili .jar fajl bibloteke. U C++-u nije tako. Uz bibloteke osim samog fajla dolaze i tekstualni fajlovi u kojima je navedeno šta se sve u toj biblioteci nalazi. Ovo mora zato što C++ kompajler ne može iz samog fajla biblioteke izvući šta sve u njoj ima (ne pitajte zašto je tako, prosto je tako), već su potrebne deklaracije sadržaja u tekstualnom obliku.

    Naš jedini fajl sa kodom se zove main.cpp, ovo je ekstnezija za C++ fajlove sa implementacijama, odnosno u ovim fajlovima pišete metode i funkcije. Postoji i druga vrsta fajlova (pomenuti u prethodnom pasusu), to su fajlovi sa deklaracijama. Mogu imati ekstenziju .h (jer se oni zovu header fajlovi), a nekad su i bez ekstenzije, kao u slučaju fajla QTextStream.

    Dakle, mi ovde #include direktivom uključujemo fajl sa deklaracijom klase QTextStream da bi mogli da je koristimo u našem kodu. Takođe promenljiva stdout (koju smo dali kao argument konstruktoru) je deklarisana u nekom fajlu koji mi posredno uključujemo (njega uključuje fajl koji smo mi uključujli).

    U C++-u postoje i using direktive, koje imaju sličnu svrhu kao u Javi i C#-u, ali se u radu sa Qt-om ne koriste, jer se u Qt biblioteci sve klase nalaze van namespace-ova. (da, i to može)

    Rezime

    U ovom članku smo prošli osnovno kreiranje projekta u Qt Creator-u, napisali program koji ispisuje tekst na konzoli, i upoznali se sa nakim od glavnih odlika C++-a. Kako budu prolazili članci, tako ćete bolje i shvatati, a verovatno ću i ja neke od ovih stvari ponoviti tu i tamo.

    Do sledećeg čitanja.

    Uvod

    Builder pattern spada u grupu creational paterna što znači da se koristi pri kreiranju novih objekata. U ovu grupu paterna spadaju i abstract factory pattern, factory method pattern itd. tako da se postavlja pitanje u kojim slučajevima i zašto koristiti builder patern a ne neki od drugih creational paterna? Takodje postavlja se pitanje kada i zašto uopšte koristiti builder pattern? Odgovor nije jednostavan, najjednostavniji odgovor bio bi da koristimo builder pattern u slučajevima kada kreiramo objekte koji imaju dosta opcionih parametara (neki granična vrednost je 4-5).

    Međutim postoji jedan problem sa builder paternom a to je da vrlo loše radi u sprezi sa nasleđivanjem (bar ova verzija koja ću predstaviti u daljem teksu). Tako da pamet u glavu, treba dobro razmisliti pre upotrebe ove verzije ovog paterna.

    Primeri koje ću upotrebiti u daljem tekstu značajno se oslanjaju na primere iz knjige Effective Java Joshua Bloch i topla preporuka svima da pročitaju tu knjigu uz duboko razumevanje.

    Kada koristimo builder pattern i koje druge mogućnosti imamo na raspolaganju?

    Kao što sam rekao u uvodu builder pattern koristimo kada imamo klasu koja će se instancirati prosleđujući joj veliki broj opcionih parametara. Posto su većina primera vezana za buider pattern na internetu primeri nekih jela, jer u jela jelte ide dosta opcionih sastojaka, mi ćemo u našem slučaju uzeti za primer klasu koja će predstavljati sarmu ) To bi izgledalo nekako ovako:

    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class Sarma{
        //konstruktori su namerno izostavljeni jer tu dolazi do problema
        private final boolean meso;
        private final boolean beliLuk;
        private final boolean jaje;
        private final boolean susenoMeso;
        private final boolean pirinac;
        private final boolean kupus;
        private final boolean biber;
        private final boolean paprika;
        //metode ove klase nisu bitne za dalje razmatranje
    }

    Modelovali smo sarmu tako da imamo osam parameta. Za ovih osam parametara možemo reći da jedino meso, pirinač i kupus obevezno idu u sarmu, dok su ostalih pet parametara opcioni. Ako bi ovakvu klasu želeli da instanciramo pomoću konstruktora morali bi da obezbedimo značajan broj konstruktora, naravno u slučaju da želimo da omogućimo bili kakvu kombinaciju opcionih parametara. Takođe klasa bi bila nemoguća za održavanje jer prilikom dodavanja jednog novog atributa u klasu bilo bi potrebno dodati pregršt novih konstruktora. A zamislite i korsnika naše klase koji treba da unese pet opcionih parametara ili više ,pri instanciranju objekta, često gledajuću u dokumentaciju podsećajući se u kom redosledu su parametri navedeni u konstruktorima.

    Postoje dva rešenja za ovaj problem koja Joshua Bloch pominje u svojoj knjizi kao nepodesna. To su telescoping constructor pattern i praksa da se klasa instancira pomocu praznog konstruktora pa da se atributi inicijalizuju pomoću setAtribut() metoda. Nećemo se baviti problemima ovih paterna, ukoliko zelite da saznate više o tome pročitajte knjigu )

     

    Kada koristiti buider pattern a kada abstract factory pattern?

    Možemo reći da builder pattern koristimo kada želimo da kreiramo objekat korak po korak. Za razliku od abstract factory patterna koji će u zavisnosti od ulaznih parametara vratiti objekat neke subklase koja implementira zahtevani interfejs, builder pattern ćemo koristiti u slučajevima kada zelimo da dobijemo objekat koji će biti zahtevanog tipa ali sa finijim podešavanjima.

    Implementacija

    Implementiraćemo builder pattern za iznad navedenu klasu Sarma

    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    public class Sarma{

        private final boolean meso;
        private final boolean beliLuk;
        private final boolean jaje;
        private final boolean susenoMeso;
        private final boolean pirinac;
        private final boolean kupus;
        private final boolean biber;
        private final boolean paprika;

        public static class Builder {
            //zahtevani parametri su nam meso, kupus i pirinac
            private final boolean meso = true;
            private final boolean pirinac = true;
            private final boolean kupus = true;

            //opcione parametre cemo podesiti na false jer je to njihova podrazumevana zato sto nisu obavezni
            private boolean beliLuk = false;
            private boolean jaje = false;
            private boolean susenoMeso = false;
            private boolean biber = false;
            private boolean paprika = false;

            //default onstructor
            public Builder(){
            }

        public Builder dodajBeliLuk(){
          this.beliLuk = true;
          return this;
        }

        public Builder dodajJaje(){
          this.jaje = true;
          return this;
        }

        public Builder dodajSusenoMeso(){
          this.susenoMeso = true;
          return this;
        }

            //iste ovakve metode treba napraviti za sve opcione parametre

        public Sarma napravi(){
          return new Sarma(this);
        }
        }
        private Sarma (Builder builder){
            meso = builder.meso;
            kupus = builder.kupus;
            pirinac = builder.pirinac;
            jaje = builder.jaje;
            paprika = builder.paprika;
            biber = builder.biber;
            susenoMeso = builder.susenoMeso;
            beliLuk = builder.beliLuk;

        }
    }

    U našem slučaju nije bilo potrebno postaviti default konstruktor, u klasi Builder jer bi ga kompajler sam dodao za nas. Međutim eksplicitno sam ga naveo da bih naglasio jednu stvar. U našem primeru atributi meso, kupus i pirina; su obavezni i uvek imaju vednost true. Međutim obavezni atributi mogu biti i drugih tipova npr. integer pa bi ovaj konstruktor služio da prihvati parametre koji bi predstavljali njihove vrednosti i da ih inicijalizuje pri kreiranju Builder objekta.

    Kako sve ovo radi?

    Napravićemo test klasu koja će u sebi sadržati main metodu i koja će nam poslužiti da pokažemo kako radi a usput i da testiramo naš kod.

    
    1
    2
    3
    4
    5
    6
    public class BuilderExample {
        public static void main(String[] args) {
            Sarma s = new Sarma.Builder().dodajBeliLuk().dodajJaje().dodajSusenoMeso().napravi();
            System.out.printline(s);
        }
    }

    Takođe ćemo redefinisati toString metodu klase Sarma da bi dobili neki smisleni ispis na ekranu

    
    1
    2
    3
    public String toString(){
        return "Sastojci sarme su: meso:" + meso + " ,pirinac:" + pirinac + " ,kupus:" + kupus + " ,susenoMeso:" + susenoMesto + " ,beliLuk:" + beli luk + " ,paprika:" + paprika + " ,biber:" + biber + " ,jaje:" + jaje;
    }

    Zaključak

    Najveća mana builder paterna je sto kada zelimo kreiramo novi objekat prvo se inicijalizuju atributi builder objekta pa se posle toga njihove vrednosti dodeljuju atributima sarma objekta. Tako da dolazi do bespotrebnog kopiranja vrednosti atributa. Ipak kada su u pitanju klase slične ovoj na kojoj smo radili primer, builder pattern je najbolje rešenje. Može se primetiti da je vrlo jednostavan za održavanje, u slučaju dodavanja novih atributa dovoljno je napraviti par jednostavnih izmena. Takodje builder patter obezbedjuje konzistentnost objekta što je njegova najveća prednost u odnosu na Java Beans pristup.

    O manama ove verzije builder paterna vezanim za nasleđivanje u nekom drugom tekstu. Ako imate nekih pitanja, ispravki ili komentara biće mi zadovoljstvo da odgovorim.

    Uvod

    Ako već nemate instaliranu neku Linux distribuciju predlažem vam da da pogledate sajt Distrowatch gde imate najbolji pregled trenutnih distribucija i podhitno instalirate neku ) .
    E ako biste nakon toga želeli da programirate nešto, nadam se da će ovo biti dobar vodič. Naravno i u Linuxu, poput Windowsa postoje IDE-i za različite programske jezike, al’ nekako u duhu Linuxa je da se koriste editor, kompajler(interpreter) i naravno konzola. Kao editor ja koristim Kate koji dolazi uz KDE grafičko okruženje, ali se može i naknadno instalirati na ostala okruženja. U poznate editore koji su više hakerski spadaju Emacs i Vim, pa ako vam se oni više sviđaju slobodno koristite njih.

    Kate

    Jedna od glavnih prednosti ovog editora je što se može uključiti konzola unutar njega, što znatno ubrzava rad.

    Još jedna pogodnost ovog editora je dopunjavanje reči. Naime, kada jednom ukucate neku reč, bilo ona promenljiva, string ili bilo šta drugo, Kate je pamti i sledeći put kad otkucate prva 2 slova te reči, Kate vam nudi da pritiskom na enter dopuni do kraja.

    Osnovne konzolne komande

    Dosta ljudi ima strah upravo od ove stvari, ali jednom kad naučite, verujem da ćete ih uglavnom koristiti jer je mnogo brže raditi sa komandama. Kao i na windowsu strelica gore-dole lista prethodne komande, a tab dopunjuje. Kad želimo administratorska prava dovoljno je kucati sudo -s, zatim ukucati šifru i možemo raditi dalje kao admin. Ako nešto ne znamo kako da uradimo tu su man stranice koje treba koristiti što češće. Npr. man ls će nam izlistati opis komande ls, koji su njeni argumenti i slično. Za traženje u man stranicama koristi se man -k ‘niska’ i izlistaće nam sve man stranice koje sadrže datu nisku. A da, za izlaz iz man stranice koristi se taster q. Za prekidanje programa koristi se kombinacija ctrl+c, a za suspendovanje
    ctrl+z. Vrlo često postoji potreba da se program pokrene u pozadini (konzola ostaje oslobođena i može se dalje nešto raditi), e za to se koristi & nakon naredbe, npr. kate& otvoriće kate u pozadini, a vama ostaviti konzolu slobodnu. Ako već imate previše slova u konzoli, naredbom clear čisti se konzola. To su bile neke male tajne, ajmo sad konkretno na komande.

    Naredbe za kretanje, kreiranje, listanje, brisanje

    Linux komande se sastoje iz tri dela (poslednja dva su opciona):
    1. ime komande
    2. opcije komande (slova ili reči kojima prethodi ­)
    3. argumenti (nazivi datoteka, direktorijuma, proizvoljni tekst)
    Npr.

    1
     ls -l /tmp 

    izlistaće sve fajlove u -tmp u specifičnom formatu kog smo definisali sa -l. Isto kao ls radi i dir
    Za kretanje kroz foldere koristi se naredba cd pa naziv foldera u koji hocemo da udjemo. Za povratak nazad ide cd .. a ako recimo hoćemo da se vratimo u home direktorijum idemo cd ~.
    Za kopiranje foldera koristimo cp ‘fajl’ ‘nova lokacija’, a za pomeranje služe mv ‘fajl’ ‘nova lokacija’.
    Kad hoćemo da kreiramo novi folder koristimo mkdir ‘naziv’ , a ako hoćemo da ga obrišemo rm ‘fajl’. Za brisanje praznog foldera služi rmdir ‘fajl’, a ako unutar njega postoji još neki folder pozivom rm -R ‘fajl’, rekurzivno brišemo sve unutar njega. Ali obratite pažnju da kada ovako brišete ne prenosi se u recycle bin, tako da se trajno briše. Komanda pwd  štampa tekući direktorijum. U slucaju da imate neki sitan tekstualni fajl vrlo zgodna je opcija cat koja će ispisati direktno u konzoli sadržaj tog fajla.

    Za pretraživanje unutar fajlova ukuliko poznajete regularne izraze koristi se naredba grep ‘regex’ ‘putanja do fajla’. Regularan izraz može da sadrži:

    • ^ – početak linije
    • $ – kraj linije
    • . – bilo koji karakter
    • [lista_karaktera] – bilo koji karakter iz skupa u zagradama, npr [1­2abc9­D]
    • [^lista_karaktera] – tačno jedan karakter koji nije među navedenim
    • izraz{n} – izraz se pojavljuje n puta
    • izraz* – izraz se pojavljuje 0, 1 ili više puta
    • izraz+ – izraz se pojavljuje bar jednom
    • izraz? – izraz se pojavljuje 0 ili jednom
    GCC kompajler i Makefile

    Pošto ću u narednim tekstovima pisati neke programe u C-u red je da se objasni kako se oni prevode, a i nije zgoreg da znate šta se dešava kada kliknete na dugme run ili kako već u nekom IDE-u ) .
    Dakle najprostija naredba kojom se prevode c-fajlovi, u ovom slučaju hello.c fajl je:

    1
     gcc -o hello hello.c

    Ukoliko ne bismo naveli kako želimo da nam se zove prevedeni program (hello), gcc bi ga nazvao univerzalnim imenom a.out. Pozivom -o naglasili smo da želimo da se obavi i prevođenje i linkovanje prevedenih fajlova, u našem slučaju samo jednog fajla. Često bi trebali samo da prevedemo fajl do objektnog fajla (hello.o), a tek kasnije ga linkujemo sa ostalima. E to se radi naredbom -c u pozivu gcc-a, a kasnije se poziva i linker. U slučaju da želimo da dobijemo i warninge, a ne samo greške pri kompajliranju dodaćemo -Wall.

    I tu već priča postaje poprilično zamorna, kad šta pokrenuti, šta ide posle čega i kako se poziva. Kako bi se taj proces automatizovao smišljen je alat koji se zove Make. Naime, potrebno je napraviti fajl koji se zove Makefile i u njemu napisati skup pravila kad se šta i kako poziva. Evo jednog jednostavnog Makefile-a:

    
    1
    2
    3
    4
    5
    6
    program: hello.o zdravo.o
        gcc -Wall -o program hello.o zdravo.o
    hello: hello.c
        gcc -Wall -c hello.c
    zdravo: zdravo.c
        gcc -Wall -c zdravo.c

    I sada nakon neke izmene je dovoljno otkucati samo make, a on tačno zna šta dalje treba činiti. Valja napomenuti da ako neki fajl nije menjan, neće se ponovo izvršiti njegova kompilacija, nego će se samo povezati sa izmenjenim fajlovima.

    Na kraju..

    Nadam se da sam uspeo da vam objasnim neke osnove komandne linije i rada u Linuxu. Vi naravno možete raditi i kako ste navikli u specijalizovanim okruženjima, ovo je samo jedan način rada. U narednim postovima radićemo neke konkretne programe iz različitih oblasti i koristiti različite programske jezike, ali ovo su neke osnove koje se svuda manje ili više koriste.

    blogodak blog

    Blogodak?

    Blogodak je vaš pogled na domaću blogosferu. Prijavite se i napravite sopstvenu listu blogova koje pratite.

    O projektu

    Podrška

    MyCity.rs

    DevProTalk

    Duhovi iz Palmotićeve 37