// demokratismus while (!vysledekHlasovani) { vysledekHlasovani = demokratickyParlament->hlasuj(zakon); } demokratickyParlament->uvedVPlatnost(zakon);Jako programátor ihned vidím optimalizaci, kterou můžeme ve výše uvedeném kódu provést (kód bude přehlednější a výsledek stejný, a navíc rychleji):
// skutečná, ničím nemaskovaná totalita totalitniParlament->uvedVPlatnost(zakon);PS: Kontext.
Zvykl jsem si v PHP aplikacích používat knihovnu mPDF. Umí vytvářet PDF soubory z HTML šablon, takže člověk nemusí ručně kreslit každou čáru, řešit zalamování textu apod.
Tato velká výhoda je pochopitelně doprovázena i růnými nevýhodami: mPDF je docela moloch a navíc náročný na RAM. Některé části knihovny se sice dají vyházet, ne všechny problémy to však řeší.
Nyní jsem řešil problém v aplikaci, kdy zákazník potřebuje tisknout několikastránkové tabulkové přehledy v PDF. Server měl limit RAM použité na PHP skript (memory_limit) původně 32 MB, posléze 64 MB a i to už v některých případech nestačilo. S řešením požádat hosting o další navýšení jsem se nechtěl spokojit, proto jsem začal hledat možnosti optimalizace. Upgradoval jsem mPDF ze staré verze 4.něco na nejnovější 5.2. Z hlediska RAM to však nepomohlo, spíš naopak. Generovaná PDF se však zmenšila na zhruba třetinu původní velikosti, což je fajn.
Dle dostupných rad, jsem měl zapnuté nastavení mPDF->packTableData. Generování desetistránkové tabulky s okraji kolem elementů <td> zabralo 128 MB RAM. Okraje patrně žerou paměti fakt hodně, jejich vypnutí v CSS mělo za následek pokles potřebné RAM na 44 MB (!).
Experimentoval jsem dál – vypnutí nastavení mPDF->packTableData paradoxně spotřebu RAM snížilo na 21 MB (ač by dle dokumentace mělo způsobit opak – dalo by se tedy říci, že s tímto nastavením je mPDF sice pomalejší, ale zato zabere víc paměti).
Samozřejmě netvrdím, že vypnutí mPDF->packTableData vždy pomůže (u okrajů si tím skoro jist jsem) – pro konkrétní situaci tedy doporučuji zjistit velikost využité RAM pomocí Xdebug a Function Traces.
Logika dostává v našem světě na frak snad každý den, ale pořád mě to nepřestává udivovat. Připadá tohle naprosto neuvěřitelné jen mně?
Microsoft musí z vůle EU nabízet uživatelům instalaci alternativních internetových prohlížečů. EU patrně opět považuje uživatele za naprosté idioty, kteří si neumí sami najít a stáhnout produkt, který by jim vyhovoval. A idioty je potřeba co? No podporovat…
Ale proč jen prohlížeče? Proč si obdobná nařízení nevymohli i tvůrci alternativních kalkulaček, malovátek, přehrávačů, nebo třeba souborových systémů a vrstvy abstrakce HW? Jsem zvědavý, kdy přijdu do Tesca a to mi bude muset nabídnout, jestli nechci zavézt do koloniálu Františka Vopičky na nákup.
A vůbec, proč by MS neměl mít právo dát do svého produktu, co uzná za vhodné? O jakém zneužívání monopolního postavení může být řeč? Monopol by to byl, pokud byste chtěli používat počítač a neobešli se bez produktů Microsoftu. Tak to ale vůbec není (ostatně, skutečné monopoly existují jen na základě státních regulací).
Microsoft maximálně tak využívá postavení, které si za ta léta sám vybudoval. Jakýkoliv konkurent měl možnost vyvinout produkt svůj a být s ním úspěšnější.
Chápu ale, že pro autory prohlížečů (obzvlášť těch, které dosud v podstatě nikdo neznal) musí být reklama zdarma v cizím produktu (který si dokázal najít miliony a miliony uživatelů) naprosto úžasná. Ale ještě se dokážou pohádat, na jakém místě by jejich prohlížeč měl být zobrazen.
Jenže jak k tomu přijdou ti vývojáři kalkulaček? Těm zadarmo nikdo nic nedá (a je to tak správně).
Nedávno jsem adaptoval instalátor jedné aplikace, aby běžel bez problémů i na 64bitových Windows a zde se podělím o pár poznatků.
Nejprve jsem potřeboval zjistit, zda je moje aplikace zrovna spuštěna na systému 32bitovém nebo 64bitovém. Nápady s kontrolou velikosti číselných datových typů je třeba zavrhnout, ta by se totiž určila natvrdo již během kompilace a ne až při spuštění aplikace.
Architektura procesoru je uložená v proměnné prostředí Windows s názvem PROCESSOR_ARCHITECTURE, kde najdete buď „x86″ nebo něco jako „AMD64″ (i na Intel procesorech). Má to ale jeden háček – funkce GetEnvironmentVariable() v klidu vrátí „x86″ i na 64bitovém systému, voláte-li ji z 32bitové aplikace. Tudy cesta také nevede.
Informaci je potřeba vyčíst z registru, to funguje spolehlivě:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment\PROCESSOR_ARCHITECTUREDalší zajímavá vlastnost 64bitových Windows je oddělený přístup do části registrů. 32bitová aplikace pracuje s jinými registry, než 64bitová (týká se větve Software\ jak v HKEY_LOCAL_MACHINE, tak v HKEY_CURRENT_USER). Větve pro 32bitové aplikace jsou umístěny pod uzlem Wow6432Node, přistupuje se k nim však zcela transparentně.
Co však v případě, pokud potřebujeme přistupovat v 32bitové aplikaci do 64bitové části registru nebo naopak? Řešení je poměrně jednoduché, existují speciální příznaky pro samDesired parametr funkcí RegCreateKeyEx(), RegDeleteKeyEx() a RegOpenKeyEx(): KEY_WOW64_64KEY a KEY_WOW64_32KEY.
Z 32bitové aplikace tak můžeme otevřít klíč v 64bitové části registru třeba takto:
RegOpenKeyEx(HKEY_LOCAL_MACHINE, regPath, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);Toť zatím vše, příště možná něco třeba o podepisování ovladačů a utilitě DpInst.exe :)
V dnešní době mají běžné počítače dostatečně velký výkon na to, aby zvládaly provádět více věcí naráz než kdy jindy. Na co jste dříve potřebovali síť o několika strojích, dnes hravě zvládne jeden jediný.
Na jednom fyzickém počítači tak může naráz běžet několik počítačů virtuálních, z nichž každý může poskytovat určité služby, mít nainstalovaný jiný operační systém apod. Výhodou je, že tyto počítače běží zcela izolovaně a nemohou se ovlivnit navzájem. Mohou být ale propojeny do virtuální sítě a využívat všech možností, které síťování nabízí.
Používám síťový režim bridged, každý virtuální stroj pak může mít vlastní IP adresu a být tak pohodlně používaný jako server.
Virtualizujte, ulehčí vám to práci :-)
Total Commander je fajn aplikace, ale občas v něčem trochu opožděná. Ještě před pár lety třeba vypadala jako v dobách největší slávy Windows 3.1.
Ale časy se mění a nové verze už dokonce zvládají mít pro každého uživatele vlastní nastavení. To se samozřejmě hodí a odpadá i nutnost být administrátorem, aby se vaše konfigurace ukládala (což bylo nezbytné, když býval wincmd.ini soubor přímo v adresáři windows). Instaloval jsem tedy verzi 7.04a a během instalace zvolil, že uživatelská konfigurace má být v profilu každého uživatele (Profil/Application Data).
Pro uživatele Administrator, kde jsem prováděl instalaci, to i fungovalo. U ostatních běžných uživatelů ovšem ne, Total Commander se vytrvale pokoušel načíst a uložit konfiguraci do starého dobrého adresáře windows.
Řešení je poměrně jednoduché, pro každého uživatele je potřeba zapsat do registru tyto údaje:
[HKEY_CURRENT_USER\Software\Ghisler\Total Commander]
"IniFileName"="%APPDATA%\\GHISLER\\wincmd.ini"
"FtpIniName"="%APPDATA%\\GHISLER\\wcx_ftp.ini"a do adresáře %APPDATA%\GHISLER\ případně nakopírovat vaši oblíbenou konfiguraci.
Obecně se má za to, že software pro správu verzí se vyplatí používat na větších projektech, neboť právě ohlídání kolizí ve změnách prováděných více programátory současně je jeho hlavní úkol.
Nicméně, verzovací systémy nabízejí i další funkce, které využijete i na projektech vyvíjených klidně jedním člověkem.
V takovém případě oddělíte před započetím vývoje těchto novinek tzv. branch od hlavní verze a vývoj provadíte na této nové branchi. V případě potřeby se samozřejmě do hlavní verze můžete kdykoliv přepnout. Po odladění nové verze přenesete změny i do verze hlavní, nebo-li provedete merge.
Jsem přesvědčen, že jednoduchý systém pro správu verzí (jakým je třeba SVN), najde své opodstatnění pro nasazení na libovolném softwarovém projektu, který vám trvá víc než jedno odpoledne, nebo u kterého je pravděpodobnost, že se k němu někdy budete chtít vracet.
V okamžiku, kdy začnete vyvíjet aspoň trochu seriozní webové aplikace, pak má jistě smysl uvažovat o nějakém testování, nejlépe automatizovaném.
/** * Pokusná třída, jednoduchá kalkulačka, která umí sčítat a dělit čísla. */ class Kalkulacka { /** * Prázdný konstruktor. */ function Kalkulacka() { } /** * Metoda pro sčítání. * * @param a 1. sčítanec * @param b 2. sčítanec * @return součet a + b */ function Secti($a, $b) { return $a + $b; } /** * Metoda pro dělení. * * @param a dělenec * @param b dělitel * @return a děleno b (nebo false, pokud by mělo dojít k dělení nulou) */ function Vydel($a, $b) { if ($b != 0) { return $a / $b; } else { return false; } } }
// načíst knihovnu SimpleTest require_once 'simpletest/unit_tester.php'; require_once 'simpletest/reporter.php'; // načíst naší testovanou třídu require_once 'Kalkulacka.php'; /** * Třída pro testování kalkulačky. */ class KalkulackaTests extends UnitTestCase { /** * Konstruktor. */ function KalkulackaTests() { UnitTestCase::UnitTestCase(); } /** * Test sčítání. * (název metody by měl začínat na test...) */ function testSecti() { // vytvořit instanci třídy kalkulačka $instance = &new Kalkulacka(); // otestovat, zda byla instance v pořádku vytvořena $this->assertNotNull($instance); // otestovat, zda volání Secti(1, 1) vrací správně 2 $this->assertEqual(2, $instance->Secti(1, 1)); // otestovat, zda volání Secti(0, 15) vrací správně 15 $this->assertEqual(15, $instance->Secti(0, 15)); // ... a mohli bychom pokračovat dle libosti } /** * Test dělení. * (název metody by měl začínat na test...) */ function testVydel() { // vytvořit instanci třídy kalkulačka $instance = &new Kalkulacka(); // otestovat, zda byla instance v pořádku vytvořena $this->assertNotNull($instance); // otestovat, zda volání Vydel(1, 1) vrací správně 1 $this->assertEqual(1, $instance->Vydel(1, 1)); // otestovat, zda volání Vydel(0, 1) vrací správně 0 $this->assertEqual(0, $instance->Vydel(0, 1)); // otestovat, zda volání Vydel(15, 0) vrací false (pokus o dělení nulou) // a nesmí to spadnout $this->assertFalse($instance->Vydel(15, 0)); // ... a mohli bychom pokračovat dle libosti } } // založíme nový test suite, tedy kolekci testovacích tříd $test = &new TestSuite('Test pokusné třídy Kalkulacka:'); // přidáme naši testovací třídu (= test case) do tohoto test suitu $test->addTestCase(new KalkulackaTests()); // spustíme test suite, jako výstup se použije obyčejný textový report // vrácená hodnota je předána PHP skriptu pro možné pozdější využití // (0 = OK, jinak se stala chyba) exit ($test->run(new TextReporter()) ? 0 : 1);
Test pokusné třídy Kalkulacka: OK Test cases run: 1/1, Passes: 7, Failures: 0, Exceptions: 0SimpleTest nám sděluje, že testy proběhly a v pořádku bylo 7 kontrol, u žádné nebyla zjištěna chyba a neobjevila se ani jedna PHP výjimka.
return $a - $b;Spuštění testů by ukázalo toto, tedy dvě chyby s označením testů a čísel řádků, kde k nim došlo:
Test pokusné třídy Kalkulacka: 1) Equal expectation fails because [Integer: 2] differs from [Integer: 0] by 2 at [KalkulackaTests.php line 34] in testSecti in KalkulackaTests 2) Equal expectation fails because [Integer: 15] differs from [Integer: -15] by 30 at [KalkulackaTests.php line 37] in testSecti in KalkulackaTests FAILURES!!! Test cases run: 1/1, Passes: 5, Failures: 2, Exceptions: 0Dokumentaci k dalším použitelným kontrolám (asserts) lze najít zde. A příště se budu věnovat tzv. mockům :-)
Při tvorbě webu je stále potřeba přizpůsobovat vzhled různým obskurním prohlížečům, třeba takovému IE verze 6 (například na Trainweb chodí z IE6 18,3 % všech lidí).
Naposledy jsem se nad tím vztekal včera, kdy jsem potřeboval mít div element vysoký přesně 6 pixelů. Stylopis hovořil jasně:
.divider { height: 6px; }Nicméně IE tvrdojíšně kreslil daný rámeček vysoký dobrých 15 pixelů. Někde jsem se dočetl, že je potřeba nastavit ještě line-height na nulu. To taky nepomohlo.
Nakonec se ukázalo, že starostlivý Internet Explorer se obával, že by se mi do tohoto elementu nevešlo písmo o velikosti 10pt (zděděno z elementu body) a tak výšku raději přizpůsoboval. Text jsem dovnitř samozřejmě dávat nehodlal. Řešení je tedy prosaické:
.divider { height: 6px; font-size: 1pt; }Můžete si tak v případě potřeby ušetřit zhruba 20 minut googlování :)
Už přes rok kontinuálně vyvíjím jistou webovou aplikaci a již od začátku jsem si dával záležet na tom, abych ke každé třídě a metodě psal tzv. doxygen-style komentáře, popisující co která třída a metoda dělá, u metod navíc třeba dokumentaci parametrů a návratových hodnot.
/** * Ukázka doxygen-style komentáře. * * @class UkazkovaTrida * @author Hans * * @date 2008-05-29 */ class UkazkovaTrida { /** * Ukázka doxygen-style komentáře. * Funkce vracející nulu. * * @author Hans * * @date 2008-05-29 * * @param zbytecny zbytečný parametr * @return vždy 0 */ function Nula($zbytecny) { return 0; } }
Na ten jsem následně spustil doxygen.exe z příkazové řádky a rázem mám čtyřmegový balík provázané dokumentace v HTML včetně grafického znázornění závislosti tříd a podobných vymožeností.
To se mi líbí, v podstatě se jedná o jediný smysluplný (a zároveň snadný a nepříliš otravující) způsob dokumentování kódu. Kdysi jsem svůj kód zkoušel prohnat tuším PhpDocumentorem, ale ten se mi nepodařilo nakonfigurovat a rozchodit během jednoho odpoledne, toto šlo oproti tomu zcela samo.