Obsah
K dosažení tohoto ideálního stavu vede budto čistě formální cesta:
Dále zmiňované nástroje však toto nedokážou; omezují se na běhovou kontrolu platnosti předpsaných podmínek
jass je preprocesor javového zdrojového textu. Umožňuje ve zdrojovém textu programu vyznačit podmínky, jejichž splnění je za běhu kontrolováno.
stažení a instalace balíku z http://csd.informatik.uni-oldenburg.de/~jass/
vytvoření zdrojového textu s příponou .jass, javovou syntaxí s použitím speciálních komentářových značek
takový zdrojový text je přeložitelný i normálním překladačem javac, ale v takovém případě ztrácíme možnosti jass
proto nejprve .jass souboru převedeme preprocesorem jass na javový (.java) soubor
ten již přeložíme javac a spustíme java, tedy jako každý jiný zdrojový soubor v Javě
z .jass zdrojů je možné vytvořit také dokumentaci API obsahující jass značky, tj. informace, co kde musí platit za podmínky atd. - vynikající možnost!
úvodní materiálek k použití junit (v němčině, jako PDF)
Programový kód rozsáhlejších soudobých systémů je složitý, nepřehledný, nesnadno udržovatelný.
U systémů jsou často implementovány mimofunkční požadavky: protokolování, zabezpečení, optimalizace.
Pokrytí těchto požadavků jde napříč s požadavky funkčními - současné splnění vede nezřídka ke kombinatorické explozi a (téměř) exponenciálnímu nárůstu velikosti kódu.
Kód je nečitelný a ještě obtížněji udržovatelný.
I rozšiřování nelze většinou provést lokálně, nezřídka je jím zasaženo více částí kódu.
Příklad převzatý z weblogu Jablok Pavla Kolesnikova (typický kód aplikační logiky):
public class KusAplikacniLogiky extends ObecnejsiKus {
// data tridy;
// jina pomocna data;
// pretizeni rodicovskych metod
public void provedNecoPodstatneho () {
// autentizace
// autorizace
// dalsi nezajimavy kod
// logovani zacatku operace
// vlastni aplikacni logika — konecne!
// logovani ukonceni operace
// treba jeste neco
}
}
Překlad článku Graham O'Regana Introduction to Aspect-Oriented Programming na onjava.com nastiňuje hlavní principy:
AOP umožňuje přidat do statického OO modelu programu (třídy) dynamické aspekty - např. ovlivňovat (vstupovat do) volání metod.
Např. servlet očekává vstup z webového formuláře, naváže data z formuláře do vytvořeného datového objektu, ten zpracuje aplikační logikou a výsledek prezentuje.
Kromě toho ale musí řešit:
ošetření výjimek
zabezpečení přístupu
protokolování
Uvádíme pragmaticky jen to, co je potřeba zde (pro potřeby IoC), nechápat jako komplexní terminologii.
objekt poskytující navenek ucelenou funkcionalitu (část aplikační nebo pomocné logiky)
komponenta je obvykle chápána jako "velký objekt" nebo graf více objektů s vnějším rozhraním ("fasádou")
komponenta je sice do jisté míry samostatná, ale většinou nežije nezávisle; za běhu potřebuje návaznosti na další komponenty nebo hostující rámec (kontejner)
objekt, v němž jsou za běhu aplikace uloženy a spravovány komponenty (objekty)
kontejner dokáže většinou komponenty i vytvářet a poskytovat odkazy na ně (vyhledávat je)
V komponentních systémech bývá tradičním problémem zajistit správnou inicializaci a provoz komponent závislých na ostatních.
Co je třeba udělat při nasazení jedné nové komponenty
Postup vypadá přímočaře, ale je bohužel rekurentní... v bodě 1 (připravit komponenty...) se opakuje rekurentně celý postup
V Inversion of Control obracíme tento (pro komponentního programátora) nepraktický, obtížný postup.
O řešení závislostí se postará rámec (kontejner), komponenta pouze deklaruje na čem závisí.
Historicky se postupně vyvinuly tři přístupy k "injektáži" potřebných závislostí; tedy k IoC:
Blíže viz popis k IoC v systému (rámci) vraptor a následující slidy.
Komponenta MUSÍ IMPLEMENTOVAT určité, rámcem/kontejnerem dané rozhraní (příklad z článku Intro. to AOP):
import org.apache.avalon.framework.*;
public class JDBCDataManger implements Serviceable {
DataSource dataSource;
public void service (ServiceManager sm)
throws ServiceException {
dataSource = (DataSource)sm.lookup("dataSource");
}
public void getData() {
//use dataSource for something
}
}
Nevýhoda: musí implementovat dané rozhraní, nelze vyvíjet zcela nezávisle.
Komponenta je jako objekt JavaBean, má setXXX metody:
public class JDBCDataManger {
private DataSource dataSource;
public void setDataManager(DataSource dataSource {
this.dataSource = dataSource;
}
public void getData() {
//use dataSource for something
}
}
Rámec (kontejner), např. Spring musí vědět, jak komponentu vytvořit a na čem závisí:
<bean id="myDataSource"
class="org.apache.commons.dbcp.BasicDataSource" >
<property name="driverClassName">
<value>com.mydb.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mydb://server:port/mydb</value>
</property>
<property name="username">
<value>root</value>
</property>
</bean>
<bean id="dataManager"
class="example.JDBCDataManger">
<property name="dataSource">
<ref bean="myDataSource"/>
</property>
</bean>
Oproti Interface Injection: netřeba implementovat rozhraní
Je ale nezřetelné, které setXXX metody jsou pro účely nastavení závislostí přes Setter Injection a které ne.
public class JDBCDataManger {
private DataSource dataSource;
public JDBCDataManger(DataSource dataSource) {
this.dataSource = dataSource;
}
public void getData() {
//use dataSource for something
}
}
Existují jednoduché (lightweight) kontejnery pro nasazení a provoz komponent s využitím IoC.
Tyto kontejnery mnohdy neumí nic navíc, jde jen o základní správu komponent.
Příkladem je PicoContainer a Spring, který je však komplexnější (a složitější).