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)
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ší).
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í
Komponenta koncipovaná jako MBean je často vytvářena takto:
Co odlišuje skriptování od "ostatních" pg. jazyků?
Rychlý vývoj, přímočarý životní cyklus SW: napiš - spusť (- potom odlaď)
Obvyklé dynamicky (až za běhu) typovaný jazyk, nevyžaduje deklarace proměnných, definice tříd...
Jazyk je často kombinovatelný s běžnými pg. jazyky - lze volat jejich metody, používat knihovny...
Prostá, obvykle intuitivní, syntaxe
Mnohdy jde de-facto o syntaktický klon "plného" jazyka - mj. aby se snáze učilo
Obvykle malé nároky na udržovatelnost, dokumentovatelnost, rozšiřitelnost vzniklých SW výtvorů
Jednoduché věci jdou napsat jednoduše, složité složitě, nepěkně nebo pořádně vůbec...
Proč je potřeba skriptovat silná právě dnes, když je tolik dokonalých programovacích jazyků s rychlými překladači?
Bean Scripting Framework (BSF) je projektem jakarta.apache.org, původně však vytvořený v IBM T.J.Watson Laboratories (jako produkt "alphaWorks").
BSF (software i další info) lze získat na http://jakarta.apache.org/bsf.
Vynikající články o BSF jsou k dispozici přímo na http://jakarta.apache.org/bsf/resources.html.
http://www.javaworld.com/javaworld/jw-03-2000/jw-03-beans.html
Definice mapy (asociativního pole) a přístup k prvku:
map = ["name":"Gromit", "likes":"cheese", "id":1234]
assert map['name'] == "Gromit"
Řízení toku pomocí switch s velmi bohatými možnostmi:
x = 1.23
result = ""
switch (x) {
case "foo":
result = "found foo"
// lets fall through
case "bar":
result += "bar"
case [4, 5, 6, 'inList']:
result = "list"
break
case 12..30:
result = "range"
break
case Integer:
result = "integer"
break
case Number:
result = "number"
break default:
result = "default"
}
assert result == "number"
Existuje několik "standardních" protokolovacích API:
od Java 1.4: balík java.util.logging
již dříve nezávislé open-source řešení
log4j
Obě řešení jsou srovnatelná, log4j je o něco elegantnější a propracovanější. Nejlépe (pokud to stačí) je použít zastřešujícího API:
Existuje několik "standardních" protokolovacích API:
od Java 1.4: balík java.util.logging
již dříve nezávislé open-source řešení
log4j
Obě řešení jsou srovnatelná, log4j je o něco elegantnější a propracovanější. Nejlépe (pokud to stačí) je použít zastřešujícího API: