sobota 15. září 2007

O architektech...

Občas přemýšlím o tom, co děla rozdíl mezi architekty a co by měl takový architekt umět a jaké by měl mít vlastnosti. Je dobrou praktikou rozdělovat architekty do rodin, minimálně do dvouch zásadních: funkční architekt a technický architekt. Občas to sice bývá spojené, ale na tom z pohledu tohoto článku nezáleží. Protože mi je bližší práce technického architekta, tak budu dále v textu mluvit v kontextu jeho práce.

Za svou praxi jsem spolupracoval s třemi architekty, které mojí práci ovlivnili a nebo ovlivňují zásadním způsobem. Dva z nich nebudu jmenovat, protože s nimi stále spolupracuji a oni určitě vědí o koho se jedná. Tím třetím do party je můj exkolega Jirka Kotal, který mě hodně ovlivnil a jsem mu věčný za spoustu věcí. Ještě jednou díky.

Jestli tyto architekty něco spojovalo, pak to byly následující vlastnosti, které já osobně považuji za nejdůležitější pro práci architekta.

  • pragmatismus
  • vizionářství
  • analytické myšlení
  • zkušenosti
  • obecný rozhled

Pragmatik vs Vizionář

Je to tak trochu zvláštní, že jsem vedle sebe vypíchnul pragmatismus a vizionářství. Ten důvod je takový, že architekt musí být dostatečný vizionář, ale zároveň musí být dostatečně pragmatický smýšlející, aby ty vize byly vůbec realizovatelné. Výrazná převaha jedné či druhé vlastnosti je spíše na škodu. Prostě a jednoduše musí to být vyvážený mix.

Analytické myšlení

Propracované analýzy, smysl pro detail, schopnost nahlížet na problém z několika úhlů pohledu. Málokdy jsem v analýzách těchto lidí našel bílé místo. Pokud architekt nedokáže problém zanalyzovat, pak je celkem k ničemu. Z hlediska analýz bych ještě vypíchnul fakt, že architekt musí být schopen závěry analýzy obhájit před developmentem. Pokud to nedokáže, tak se mu může prostě stát, že si to vývojáři udělají po svém.

Zkušenosti

Nejhorší je technický architekt, který sice zná "všechno" teoreticky, ale prakticky nic nevyzkoušel a nebo nepoužil. Pokud jsem se nedávno obouval do certifikací, tak to je přesně ten případ, kdy je člověk certifikovaný architekt, ale v praxi nejsou jeho názory podpořený praktickou zkušeností a nebo s ní nekorespondují. Do jisté míry to také souvisí s výše zmiňovaným pragmatismem. Na druhou stranu zkušenosti nejsou všechno a je to opět jenom jedna z ingrediencí.

Obecný rozhled

Architekt musí mít obecný rozhled a povědomí i o technologiích, které zrovna nepoužívá. To platí i o oblastech, které s jeho prací souvisí jak přímo tak nepřímo. Obrazně řečeno architekt musí umět vidět za roh, to tak trochu souvisí se zmiňovaným vizionářstvím. Ono se to nezdá, ale ve výsledku to dává docela solidní škálu informaci, které musí absorbovat.

Nikde v článku nezmiňuji technologie, protože to je podružný detail. To že někdo zná například J2EE, z něj nedělá automatický kandidáta na pozici architekta. Znalost konkrétních technologií je dobrá, ale ve výsledku to nemusí vůbec nic znamenat. Protože právě v oblasti technologií se začnou projevovat výše uvedené vlastnosti: Pragmatismus, Vizionářství, Ananlytické myšlení, Zkušenosti a Obecný rozhled.

středa 12. září 2007

Spring 2.5 - podpora anotací, testovací framework a další

Nedávno uvolněný 4 milestone verze 2.1 Spring framewroku mě přinutil k migraci na tento release. Na začátek bych ovšem rád vysvětlil jak to bude s verzováním dalších releasu Springu, prototože je to trochu zmatečné. Takže číslo 2.1 se používá pro označení milestonů, číslo označující nadcházející verzi Springu je 2.5 (stále ompatibilní s J2SE 1.4) a finálně by měla být k dispozici v říjnu. Dalším zásadní verzí bude 3.0, pro kterou se očekává jako cílové prostředí J2SE 5.0.

Pokud s ptáte co bude na 2.5 tak zásadního, pak odpovím oficiální podpora anotací. Ano je to tak, řídící metadata pro IoC kontejner je možné vyjádřit pomocí anotací viz dokumentace 3.10. Annotation-based configuration. S tím souvisí i automatické vyhledávání anotovaných tříd na classpath.

    
@Component
public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Autowired
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }
}    
    
    

Další zásadní novinkou je integrace s novými verzemi testovacích frameworků JUnit a TestNG. Předchozí API využívané k psaní integračních testů záviselo na trojkové verzi JUnit, která nepodporovala anotace. Pokud jste tedy chtěli použít původní podporu a JUnit 4.x bylo potřeba využít workaround.

Do podpory testování bylo vloženo dost úsilí, které nechalo vzniknout Spring TestContext Frameworku. Psaní testů, ve kterých lze využít transakce, dependency injection je teď mnohem snašší. První rozdíl je v tom, že není potřeba dědit od konkrétní třídy.

    
@RunWith(SpringJUnit4ClassRunner.class)
// specifies the Spring configuration to load for this test fixture
@ContextConfiguration(locations={"daos.xml"})
public final class HibernateTitleDaoTests {

    // this instance will be dependency injected by type
    @Autowired    
    private HibernateTitleDao titleDao;

    public void testLoadTitle() throws Exception {
        Title title = this.titleDao.loadTitle(new Long(10));
        assertNotNull(title);
    }
}    
    
    

Druhý rozdíl je v koncepci, kdy se veškerá přidaná funkčnost řeší pomocí TestExecutionListeneru. Spring má tyto listenery předimplementované pro řízení transakcí a nebo dependency injection. Vy si samozřejmě můžete naimplementovat vlastní listener, kterým dodáte potřebnou funkčnost. Pokud jste četli výborný článek Honzi Novotného Jak na rychlé integrační testy ve Springu, tak pomocí listeneru a řízení transakcí anotacemi by to šlo naimplementovat elegantněji. Právě něco podobného implementuji ještě navíc s využitím DbUnit, takže se můžete v budoucnu těšit na obsáhlejší článek.

Samozřejmě 2.5 je i o dalších velice užitečných vlastnostech. Oficiálně certifikovaná podpora WebSphere 6, možnost deploynutí kontextu pomocí resource adapterů (lepší management zdrojů - vlákna) a další. Kompletní soupis pocházející z oficiálního postu Jurgena Hoellera následuje.

  • full Java 6 and Java EE 5 support (JDBC 4.0, JTA 1.1, JavaMail 1.4, JAX-WS 2.0, etc)
  • full-featured annotation-driven dependency injection (including support for 'qualifier' annotations)
  • support for component scanning in the classpath (autodetecting annotated classes)
  • "beanName" pointcut element in AspectJ pointcut expressions
  • built-in support for for AspectJ load-time weaving (based on Spring's LoadTimeWeaver abstraction)
  • further XML configuration namespaces ("context", "jms") for maximum convenience
  • extended SimpleJdbcTemplate functionality (support for named parameters etc)
  • officially certified WebSphere support (support for the WebSphere 6 UOWManager facility etc)
  • Spring ApplicationContext can be deployed as RAR file (for headless application modules)
  • JCA 1.5 message endpoint management (for Spring-managed JMS and CCI message listeners)
  • completely revised framework for integration tests (with support for JUnit 4 and TestNG)

úterý 11. září 2007

Deset rad jak psát kód efektivně

NkD má tezi o tom, že dneska již neprogramujeme, ale spojujeme dohromady pouze části frameworků, které napsal někdo jiný. Do jisté míry s tím lze souhlasit a já osobně na tom nevidím nic divného, každopádně v poslední době jsem strávil nezvykle množství času vlastním kódováním. Při té příležitosti mě napadlo se s vámi podělit o oblíbené rady a postupy, které se mi osvědčily. Nechci úplně papouškovat Joshe Blocha a jeho Effective Java, takže pokud se vám tato kniha nedostala do ruky, pak ji vřele doporučuji.

1.) Null object

Null object též řečený Active nothing je návrhový vzor, který částečně oprošťuje kód od ošetření null referencí.

2.) Inversion of Control a Dependency injection

Mám pocit, že Inversion of Control a Dependency injection (popis) jsou vnímány vývojáři hodně kontroverzně. To je částečně dáno dřívější nutností vyjadřovat závislosti v XML, ovšem moderní IoC kontejnery umožňují i další způsoby např. anotace. Každopádně pokud přijmete tento přístup při tvorbě API za vlastní neradi jej opouštíte.

3.) Neměnitelné třídy

Neměnitelné alias immutable třídy nedovoluji na instanci změnit její stav, který je nastaven během inicializace. Pěkně se o nich rozepsal Lukáš Křečan ve spotu Neměnitelné třídy. Ne všechny třídy lze pojmout jako neměnitelné, ale je dobré se nad tím minimálně zamyslet.

4.) Programování rozhraním

Další prubířský kámen mezi vývojáři. Je zvláštní jak každý ve svém API vystavuje java.util.List či java.util.Map namísto jeho implementace, ale pokud má stejný přístup aplikovat i pro své třídy, pak se začíná cukat. Já osobně raději programuji rozhraním protože je to trochu více konzistentní z hlediska budoucnosti a párkrát se mi to už vyplatilo. Z mého pohledu je rozhraní více striktnější z hlediska designu API, protože člověk nesklouzává k implementačním detailům.

5.) Open/Closed princip

Kombinaci protected metod a final public metod jsem okoukal ze Spring frameworku. Třídy, které mohou být potenciálně rozšiřitelné definují chování pomocí veřejných neměnitelných metod, potomek může překrýt protected metody a rozšířit (nikoliv změnit) chování předka. Přesně v duchu myšlenky Open/Closed principu - software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.

6.) Runtime výjimky

Zkoušeli jste zjistit kolik výjimek ve vašem API musí být kontrolovaných? Ve většině API to nebylo více jak 20%, 80% připadal na výjimky běhové. Při tvorbě API zakládám skoro jako první věc hierarchii výjimek, tím se vyhýbám zbytečným změnám, když výjimky přetečou mimo kontrolu. Celkem dobrým přístupem pro určitý typ běhových výjimek je Deklarovaná runtime výjimka. No a samozřejmě nesmím zapomenout fault barieru.

7.) Kontrolujte argumenty metod

Bolí to, ale funguje to. Pokud si nechcete vytvářet vlastní sadu programových kontrol, použijte například třídu Validate z balíku Jakarta Commons Lang či Springovskou org.springframework.util.Assert, pokud nevadí závislost na Spring API.

8.) Neopakujte se

Tomáš Záluský mi kromě jiných mouder předal jedno, které se mi vždycky aktivuje jaksi automaticky. Pokud se někde v kódu objevuje na vice místech jeden a ten samý kus kódu, něco není v pořádku a programátorovi by se měla v hlavě rozsvítit červená kontrolka. Jeden ze způsobů jak neopakovat kód je popsán v článku Návrhový vzor Template method a jeho aplikace v prostředí JDBC.

9.) Dokumentujte poctivě

Pokud vám někdo tvrdí, že dobře napsaný kód se dokumentuje sám, pak si o něm můžete myslet tři věci.

  • dělá si z vás srandu a zkouší vaší reakci
  • v životě nenapsal API, které by používal někdo jiný
  • pravděpodobně je to diletant a nebo chorobný optimista

Pište javadoc, pište interni komentáře uvnitř kódu, uveďte nějaký příklad použití daného API, případně nalinkujte UML schéma. To všechno jsou informace, které jsou velice cenné pokud pracujete nejen v týmu.

10.) Nebojte se refaktoru

Refaktoring je úžasný přístup k tomu, aby váš kód nezahnil špatnými rozhodnutimi a hacky. Bohužel to do jisté míry stojí na faktu, že máte k dispozici testy. Ale možná právě proto je to o důvod více proč psát testy. Takže kromě brutálních refaktoru půlky code base se uchylujte i k menším akcím jako extract method, extract local variable. Kód bude lépe čitelný a pochopitelný.