From 6a1dcf2e9e9f077b6adb733654c4d3b727a1d1de Mon Sep 17 00:00:00 2001
From: ehilsdal
Date: Mon, 23 Aug 2004 23:08:20 +0000
Subject: [PATCH] tutorial exercises updated for OOPSLA. The printout looks
much nicer and is a bit more streamlined.
---
docs/teaching/exercises/figures_classes.gif | Bin 14202 -> 18540 bytes
docs/teaching/exercises/index.html | 427 ++++++++++++--------
2 files changed, 248 insertions(+), 179 deletions(-)
diff --git a/docs/teaching/exercises/figures_classes.gif b/docs/teaching/exercises/figures_classes.gif
index a5952fb9ebb974df7b5f26bb2c6c6cb93c9190a4..3440bbff828ee63f3f7caa88271e51f9f6b0bdac 100644
GIT binary patch
literal 18540
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
rIZt}l)1LRlXAH)=E2SsQ?6}nIh6aWA_Z>YE$
literal 14202
zcmV-=H-*SYNk%w1VcP?b0`UL<@9*yb00960|AdBwA^8LW00000EC2ui0NVqP0ssR3
zgpaAq?GK}zwAzca-n{z{hT=$;=82~2%C_zc$MQ_q_KoNI&iDQg3<`(DqVb4KDwoWr
z^9hYgr_`$Tip^@b+-@}h4vWX+viXcotJmzdTkVa@=k&V$9uEli{J#GW7$`VMSZH{N
zm^c_PfamxK87VnQ>7l2HnW?$S+3Ckv87ewTT59@q>8ZNP+Ik3j8Y??XTWi~q>Z-fT
zy9s*>94tIc44K=DoUGjUTkQM{9W70Cylj2V+C06@-R=GTQH?!LuBZ);p02*WEnd#&
z?#}$add_~2pRXS(pL~27k5IowpWfNqhcKbSgG@p7$JHb
zcaWjTkt9p*7^v%CL5dbzvU~|}WlWeW;el*qGN;a+JX4@dnQNoVnHgznoC&X@#*f%S
z_IwI8s#F9&cd0Z=ROZmFFKx~%=X9#rv1Aigy_U5j#$Zc7H}5B$
zcKiDMTkNdf!Mx-GK8!f=Bf*3lXXC3lvgFBg7(2eq$uQ;3oI4+}j5)M9$ev4^J`Du4
z=+%WZqkauLwh7g&YXfpEJGbuL6=>W3ZILwZ;lztS@D1EHZsW|GpGKaX^>XLbt4D?&
zUG#M8+`HGs{z@tGF)p*A74AK~dcWWewJ-10ytVD?>)R*!USLh}L;fYkkG~OlNhKvw
zeuB_JIE{z5?H3?Y;!Q~4jU_IHBacch8I6yKAeEgeDl$oBm3TP$
zB$l;JX=RsQa-n6EVCDE_nP%1zrkFRK$!42$q^ah4Zq7+(7H`~%XP$cQ$)_1))(L2!
zpT$Y&UVar*1qd%Oy2^_(zsg*DNl@C)m!Yo
z{mfe(-J$K&D
z)ou6EdjG8;-+eEFH{gcrCiviS6@GZ*uT>RM&`CS~*jif$iaj6Wj&JT6!DRxz__-5sJV|{@C>9KOUm&DvNBPzWG+HmGHXjVqkAey4
zlLtQt!VsQ;gFaE5bR=lF#Mv!@BvhdZnSnyUxe#qE{BQ_0*qf+Ain7Be6>J5sMa-#nIs7OO8<_(L5vf}x;*h4MOjfh}8kQhnW
z!O}_WN$#-BgO2f{
z`SQ2Ag|V(gL&~1(W*5lsKq5aU$ICc!dhBbR&4{0R0(GWaUO-=39R4W=)Tnx2pK^@vvS5ws#7Lt(2)2JJX#mq$vG?in0<88Y7
zvaf0fu8-^lKcNZ7sgBqv{a%S;l`uX~hh
zXu>K($bwTu>ar!yP+6ggB@=ld3m97^MpupQ;W=bZcJS2TS&S3_t`?r!0kwMuNVjlAXN@8IYS=
zdg8ON{dryT##z`(x=*`?-6w0=`!n~1SE8B?=y9i6+$_cx7udP0l;#7}ksh$1q9aj$
z!os^hFzUT!-!!H3}D49
zZn2AB4C5Hfc*ZoYv5OgD;~eXF$1M)PUjb{n6i>p(LLhQ>JB;Kc_vynzJ_$vF5QgCb
zIde^x#I~Re1}RT@gH>J(JbvKgFlTqmLGJP$A_8Vps=0+^=CYaX@Q)r4dCqKZGo_gP
z<{5;H2XtO@L+!l&J3QwZ28un&0gP;9odTLugRabha**gq|9R1*YP1~k1!<~idV;47
z&x4%1A5SmSbK{YTpe?Ne(cK`?e&!>m58T?|2GVnQoi(e1gX%7*+6Jud^{d0@SaS7N
zvPg1X&_114V!P#&pY>#U35@GpYoQG_V0Eiqt-uLOSfSBv-gTY5ZHQHOv!s+Zegq8d
zfDSLZ>t3I4BP+aS+xAD{hOoKOgzj$J7qkHMwyfc;?b=?h-lx8IB&_}Fj#RVQnFQs`
zA{Sq`gv{aTmiTCy`DyVK+~6ocIG=xvA#>bXua)LFn1vCT4@b%*riZ*Ugta3Nb9t5jg}XCznubculC%9
zUA^zA+g^@UwzD}~aR*j??-%Gh4IB^B&35{d;Xb=`o#}SQI|1@C;QZ;f4e{gF8`PIK
zS4kIturW|Y^@nCXA6;)s*pp%PVxWDLTVH$J-~RQv=l$+u-+SQCUiVohexzlO{NNAY
z_r+)a@s*$a-#b)0f+6@;BiIcScsLf;NC=36OrU~dHEU)?Irn9L
zy5fTLmx2Cwe`Cc~Cu4(1BY!#AF$36n4mf_S^Kd5iJ$L0@0M$}N=q52(7F3ui1z36B
zRS^D_R>eeBQrIR|I2K}<0c4nf5ppEyMo?VHTh8-^5%?S$xGc^jKJ&wdgG4)Th=Fm)
zgBvI_Oc+VyWj%*Cc;zBuQ8Irom;`1hHxo8;EGUAC_zaAAM=O_qc!G#vD2dci{(>fG
zD4Pfkl(;sK$W?G?8luQ|73hfqp^0aLiaqg)5)g~7xQdjuIkTt}xOg0@Sc@07ho>lq
z)7OivXo{twiwxFk6~zx
zw-EyyNhJ&Rem`}RY{HWJ5Dy;NgO}I_=6H*p^Jp(HlS{IUdJ&WJNOp1lVM92Hl$V&1
zMA>;N$w52@l~E~`Q%RLn$&|Lxkyoje&k>PZd6hp2b<9A3UYTNG8I~3?mSnkKX2~FE
znU-oPSZvvrU@4by8CMc$mUU^DypfcB>6dyL4u2__gIQC1S%uTsfl&~YfHjncX$**&
zHev^vbLE&~v6z>&l(;gPn9-P(c_o|qB$;_=pvhC7DHWH=nWD)@q}hU|85O8mnsCRO
zM5UUpxdpJy?JR3rZQ|NAD||3V5gWp
z^pZhTo6LCy{iR4DDTr#PaA@dWBm!}`b6(^Vna9~gw^2{=hG72LshtfWCDsR8I71}$
zloj@QpZQrY3h8v}nNs#dZeO*W@d+lkc0lS>K()m)?WRdFLmrO!pVe7J+;)*VX`uLl
zEZHYWtHqD|#%;fahu@Z-6k4IrbfFlTp(fE^_Q_cPb1dqmh7qbi>*J!!c7T%ELk$FY
zf7p*JS`wP#N61;5xS5SV3Zx7K626d}IH;pr_F4s+q*h?0r3j$Ad3sYS5>?8ZSBj-$
zqNNPMr9xSxUz&ID8Kz4>m}{D3Margc3a2=grW|ReC+MYh8d!5mlX&`xCd#L4qNjWM
zr_tu8gGyzAdX|GKrD6s$*FGU
zsp^oaibtuV8fc};4yT%>cN(3U;gZkEjSDI^w)$TY@u;i{W}sT8UAT=D_C9AvjzK7$
z&oYh;1`xZ-tKev;p*orjCu{?>_z$&1KhinBkON*pG48yF=
z>SWLQs~)P56bY_r7*6$xki<56)HI;vRxjzQu8`)dPdcq5I%16#dJLCrqi22inT_>E
zoD0{W&;_mi3T6KapjxJE3?x408*pDa*IU>9>Ddj(>Ed?+1j?d7acKxNS(H{S<#`2b|kj
zYW3=D9N{AJ^w90Q5`)=hlZuZ-_j@!MUS8I@aq1igR1^K>fl%jNN
zz_k!F?O3zhr9M1kUewjVy!5i4g`RyowFCRR@aV3-i?ad(Ul23A^gBDttEnM83$yA9
z(4t1U`MAb^I}8ckZj-CM-6>a-Zz#HRqbnY*`xdx2RT3tOD0RP4o}
z3&vXfwJ=!5Nq5GjAjXG!#A^&UZH&fx8^?0YyL2oHZ)~Yqi^qhk$9tT{YWl~39LSZx
z$5rdcg$%=oJY=LxoWa>f_q+ZjN*k=^fD)9vyB)>Ejx1Ge1zeVUUka>;cTBp)O1-H|
zW}WQG;V@aqi-$7$ogs?5-|4VY9Jmz>g~p417B^xexk&>wN!yB>tlY|4)w(7_pP^NU
z0Jb2TgBO1j=#~*B{jhz*wG%{8-ZB5&OF3X*tSiP$ZV|A
za5l(FFw+ZJ(~gkStNz->jO>d$ZPRv4#y~yCLOs-qYRN_&nn<10e_GN^{l!k*oJ1YN
zQr*;4?PylL$XJcPT3yvj9n)SN)L^Y^J_ymLY_RN!%TWx+MZKZNT2_ghtoU`ha&4t%
zeb%;i((iR(*jLwT&1gS;%Em(1sO+3jrPq7ia3)Ny;@MC93(Pa~5!}^|E{s6!y32gE
zJ?T`C<{8heclAk*UP~S98Bh`ZzK)3
zdacglM!w~BhdL~8IqXlkJk`@&+utnQ8Y|Eq+rR-m(3qLp2YRu5CEFC$Jq%6Fk!!{h
z-E9}gpU~~y{?fhMcD7z}$*zkR$8O_o(?Z@Kdj!o#<8=OuV
zH@~0Mb^yJyNcG!h4ZZ*t&neN@cMI2@`@|rf&*0VG(?+ch1UAZTa}!SCl)|_ep5a)~
z(}QiwWL<70PNg@!h${ZoEH0m7P1s(Y(iwi@RO8
zed^;iKABOS82$*O$Rcg(`>hu&N0xgko*&J3PN
zOmcW_-$*U6wK;`eCrc^Gj@KYS@^O6O}-RI6q-#~
z6b;Y8t?b?-+mT%0<*VM=tmnm!)4QIJ+Oq7fo>-)FuhVVmS52$_{Gs>-uNho-!Oq*>
z?l<7B#?qRwg9y!;4!Mf7!Z<87PI$Z$cdj~HrqCXE$o|2X*
z58S@%*aC#$iUpDp=Y;G@*=zmQQ+tSm7oL~xh5x=?<0IdI2KWqa?(eSdBjfDed$C-s
z_w&8o#T~xu-Da5&*48etCNlB0UF+BU>!L5-ug~iiF7A}3`dS_D+urEa9Q(lz!nH4O
z2y42%Ztsk_;H&@M3ir)8d)bTsoc6l#pP{B5_nca4`(P{adUbo-zc|BzP_Wz0E_EP!)4G$491P2)#9UmbhC9et-
zEiD%(4=OJ^J;yRNMMp_XO;5KtKUd8{HC0(-WlK&_ZEtaNb$1P5XMc-aCw+m7frWXK
zm6w^DeTXN50;Z*-t)r(kh_gGWwT+P@p#`M9gB7>UJ;pECjVZ#N{^jTC>*vR-6|coO
zee=JswF6h{6uyA&^jY|qf!`S+2;arCH<4mRi;(znBUesBpL`49HN+NjO-Y65;DuD#
zNur~S8L@RtIdWgj3g)PpoVgR`N}Sx(ZTzS4oi>6OktS8TRL;km-wArrlg
zn|FEh=ar$xWP3aZ)q2$bdFy6=dqvOD=hwgg5pz%C?K=ZMQT#guK>03%>plJ$Y|z0U
z5)AN|0bh~OLgyaLP{R$ai10$pC>-X)5#d`Ch6m`KPs^#!O1AO?2@7>vn*rF
zIlv6FMJv5bQ%#G?G&71Zn{rc5qt>j`&ZP_rtdgKm8X>q1)LQNw?c782tB11cW*t5W
zeJs%804iaiJ1MQy9vI((v@eJd5^1O>@G^KDJEH@pp3;DI{~mNKWx
zZLTka`-N86eNmman^#xc?lW{5gY4dOUz5yUfEvd4U?eFf*yNKbnHOQuP8BZXe;e}`
zmUlZYR9@F`UP#)0IL4V}b9-+1=laM980DjphJjh37RwepbQRJmGPMl0DW|2aHO)Bi
zCcb&=>N1|XCU2holenQR`^oHUw>=v?vHlfi!|0^xuKNL^*YVehR<#DW)io0FW#6VF`pUM!cza4rJxJR;0DFWv5|QBPg<)md-d
z_19sKUG~|pCcTc(MK9)a(|P}PfZu@+UijgOFW&g$ktg1S={PS1&e*O9BzZ)L+;dfL1`uXo)@%y{<
zzWlMocK$Qq0TJMl06IiZ=IRJvFdLeYRpfV9Zq
z2~p^PJ#nyC(~=IZf)hcSs0~=m{-Kt}veqtX`Kl`gOyLiEr;7GHXQA!NP#&*P+fzX9M1Dkd}C>Wtdaf)R$pg*AWvcI5hRX9|m&Y+dU
ztc>wLJ~ZPUk%mSh_6lx{+1Ar26E#QCaD=?NS_?g-GM}l;BN5Y?)npJfheS$g`puf%6c{#zq|I%@
zftlVkXNJJ}%f4x28;KhJrxd7pPI-1Foi<94B?I$LAeD2T{X|baYh*~K5i5~EOQNy#
z83=y*lcBo-D2@usmC|fVZwWm@JR6!(q&zf51l3k{DhNV+TGWIZHR&&7c^o-LG$HXJ
zsX|X0Qyj(eJBJ(&awux6mo@>TGW97lIC@M{iF2pq`RP#`6x0(%2%$x-5>lbcAEk1L
zc2%|NRk4~?t!`Cz3ytbmfx0H>jg_orHS1Z?n%1;}m90f;>s#T9y{X2Pu632wT4%>ef8_N@cLK54t7I4TEc88(WvimbSH3l5KID+t=!rx4l)uYJD4A;VN#p
z#Wk)5kDFZO-fg+fb#5=78{OmrSGv{BEOo7$UCClsyWLGJcfA{4!Gc%3<<%>B&70o1
zqF24`1uJ{q8{ebCSHAT
z9N{uTSi%)fA%!iR;R|9|!yWD)hdmtP^?_K#B?cdfO`Kxhp;*N&&K!$f9OI*LmBux;
z@r`kuV;%39$36D(kAWOyArG0zMKZvHZ-Lj+vrDX`cjL|w54Ok>2FFp(v$Ww
zsVn{HQx`hbrY3W#VI68uH&)bUto1!+&DdK{ao5i1wX9kFX;r_v)v<=vuaAvtVY_Vd)wF+v$enLZ9XTN+~u~hlFXfMb+0?ew_x|X;mtZ!
zaGM@Pb*g}FcW-?gHMINoo>#M%M}MP_4)z{6iFNgCG1@p%pm8>zHqd?=<1#n|Q<>
z{yyW2H&WsoPiVz+uyBuqTn!KRcqt2h@{a>N3nJe*$?;-xm6xdFGnXdJ)nM~(vAjbv
z*Eua=S|(Bp^W4*ypmcd$
zeQ(`EI@!SyQm0lu>Bl%?PSyS?BuuCvJ|9sGv*n|+TU1-s(kI(vfOfA>#%kQUSa)71
zczA&Qw{~w)PF;GTy??xqPvkq}!>+rXEwL4~BP(QxWT@`fj!>{`-@cq6s5pVTtwKwCJ8|G1Pe)priAoFhpe&jz*
z_`}EkMccpq`tN+o59$IC6!35S2C!fXaG%6)0jcNzdLaMS?f}6r0jod)DGmZ7zyWi|
z0#}3s_l5$E&I5mI{Y;SEG>`#Ka0OX#-BNITS}+EWOaz6F1R(?jdFln300#?42XO!c
zGjIWb@br8zPIxdFif|K-@ByV~3AKaIXu%r?|{+@5})DGh=
zVhAs<0k@C{weSqPW(U0|4BhGLJVOnUzzY9I4woqn?T{g$kQJ=2SrGmye(2B($Z+M%
zFb^d!5ZlfW*RTtZ!Smo{_BKipZ6@U;kwv6Xg(?wH_Aq{e=3hXMO)^mr3o#UL;}SQJ
z6x(4FyP^~Q0uslt6)0$MkO=F9=nWl+7Q0T27HVvtc5H^v!-F!%(?EzZvr6>b@0u~C>&g!-g`<}Om0
zu~YVe4kM_8fUzAJ2aM3sG~7{yMv5FSsZmTt8lKVh%&{DkQ5}o1>0Cx11ECkILKRg`
z94)Ro8b?_ql5B3pZ6wlS@-93YLR0$ip#G?5_GM?d4E|6d{
zVfLXUe?@OV5^a3LB0Vzkh@&Mrk|*&li7v-$HWF+Is_>37CD%zMy+fc{(S{Q5Q-YF@
zRBDifGW`%RAhkeOZjUQlaXSifEo4%N95MFbNP>88goct5y&
za$~+yCiD`DM9N}>4==B1E$c6i`cmsygD`uNjozp%E2AU%#V+eIA+fRowX)?M*w^Ee#x{^Wr32l=r%XVV}3l3vC#7kl#<
zuhBFG(+I=zI*SN9-6)G3Q#QX+F4Yq?ZnHZ@voMuY>*muWn{YSFvpj|IFF%j?9Md-q
zvo_UoGDom7v!?_;%JgXR3_jCkK#GS*(}U8|I6yLxBvdhb4>cF1Sc((+maiRfh4AJQ
zGZlj_Yp5%6(?N+PKWFkOV{-fObB4k*^bnLo6%=b2^doVTI4=|&r4mI+Ge)6rMtea9
zjkI>+Q17&{>~POR~N$ri4xRDZL
zBygg1Z_4CM2a`*AY6^Cd4Qo(LFAxaZ#fXQGW|k9~Dw{$5Qz~Qz=#F`ZVVhRZlfFQh^Us!Sv-gbqYt7
z7fY27R}~XcwHpOB5?d8bUv*MW^;Q{COr$Y1UsD;)GaG3$REv&R#WPnoRZ=sNQV~*8
z=Fy$<(L;>nBVv^Y^5hGB5*LYeO^=RLLFQ2~l3TBFNw?5g>+m0oMM}ZY-w3oQwJ#}k
zGBwBbB|T+Xe$*UGt<^&D9MjkXG9=
zH{H@48B;8)Qa4W`GNtlb$B~bma*h62>QA7OCB5~j&@@o2W@BTfG(M6i8x~|~)mLcp
zVZw4j2ku>cayVJj8sU{N`emZ(lV9W0K5aE$_~b0naz6Lbawbn{VUndlbn`5h6de|d
zaP~137X6@5NWD@&@$xxImNt*pXvr37U$OH>20-0~W4ktgqBb-2^JN2;Y@ZejvzBf1
zm1v9h;69a|Y?L>3mR%8#ZB+$q6P7SDMr}cHJ?DdIzmqSA4mDZS9{pBmDYsc^b_Xxl
zY>zYY^eu30&j_OLA3K*iMRrBGcBSIRYLl{ZJ5F3Fv}#wX>0mb_IhQCk6OpiGAUkj3
zNVjym)KBJgZSz(nYn4p0@BT`a^`cVOPvaJ3IBSh&J!xs*Bl~B)Dc(M0b;n!8$cSo4D60J8(0TvYx_I^3;eH}G^AufFr
zv3}VXfXV1h5x7?iw12S{Tou@Y1bAj^mQiiBfs=KD#jxMj*MTv3Z8bOz%GZDAH(f{g
z3e{Ca@3vis>4eo6SxK0KVKsjxaerlFU<=kv3>X?2M`X6OX}fis{?{tkCLM^8Sa0}*
z4Fc~BS7M8bXPL5zsP-oH2Zj&0js9~zgLQ{lPlDa{Wc>k(U3iIY7&fQ3g#niWlXGhU
zGSLe8ab6Ar(m-Uy4
zuhZ{T`I6oBl)bc+F0H4KbtTccXQAgFTx5JXnTRID{WJg`xDM1DJu~nNBN}q^sF}VH%x5IuAv<
zfU&p>ry)^i`k8YYrD^norT2k%VTkHUpJ%zFi~9X`+75eKp?_Kk;}5B4II4GUs^w6m
z#o40G)2Z<-J%rkV6PT-ku7XYYf&+F!jn|o%S_Rrvn)h>^%GGT9k&M3;r#qB~KJ*L6
z+NB9(g(Gx`<&m$Qu4W5aFC=#=A#|~Mful&MjH}eHwHQkQ(XSg>oA20*IogJ|m|FW;
ziRC&_MVXWTmX%d2C$f5=TJm14Z_a+LdZaLtaJJ5*oXaFr#SpIu{RB#LXp7H#Wui-ym)pLvq~d1fq`i%XhD
zrDnIiyJNsxmV0oKkr|swIgQOXNr#r}5+*b+cb(l^aKamZGr5+t50=3&z|9!Br@JaM
z_wc>}!B1O-!+D;8w{dycL_|-%$%VapkGr$ezjO1wsTmPyxx2m2mpd~#BUpNBd$a}g
zDFGb5BfJg`y0qh41v6a3S=eJ9w2$=~Mo;v^Wwe5N7FarXt8Mlo*`~+o8ALI3sQWFP
zucfn}oN9R-x~GR{9hwkdybT?#i8|5u
zIi+1%&qoK+3j!b7N7JJlr!74Py;=>c8gP$Pc335%sT!(BodFj;v>ScqOn}onok3BU
z(oOo+4Y1VD@YI31NOPg73LVt5+|_xV)MGupS31yz9Tx~am5jXukv-W>m(MfZuupdz
z%Mk+?LF{hDt&h9XtsS1Q{m`4efwn!fnRHpZytPk}ELHQOhjHGeui6Q`g#!B*&ymq(
zI${JGvAdo8*!UuCR*M+dUx&Lzxu*Euee_=3zFSvX&-}*8oqGB8lMnle{+WFg+UY#|
zys`!G0M|RBaQnMse8e|fg+?#A_rg1JyJejlW3eOVd;5xK7r1G=V;3Hf`&E!{TERWa
zv44}ftz+hOs^O`fVi(-<8eAoTsh1gAOpFNVqek!4?h+T-Q7`yBJ@K}|iI
zA!&aR^}d_kme)Za`I$Z@yi7g0I{U
zeg5dx3+PZ=I)wtc)ydWl9=vVfh6F?4Yu?3)A~|AYSY;leg9vAx(`SmLhKU;~?z2Zm
zWu_RzGQ8tyGF3q&I9EE;NzmuR3*cTz#Nmk_L#QS@hKf4XLC2W_n+jz{^eYIC{KS4N
z8x>_cvNW%j+zJxqR+>`fjr9ogq+PR4y@FMgF=R=YAoI!;=~ge@!aGAU_UQPmT)07V
z4DCzfFWkY9N5&($_-(Jw+&=4_TNv+D$@lpBMgE=k=Uu8twHhX@mi64W8u#(c
z*gx|M_Pz8pa)-TtA7{RIcNpW+gHzP#54ZE4v;}3AUVE|)-OyVvw;s1RI_$yAcpOW=>)HGLKV*QD>-ci8Gx0Y}<8E70}jlm}jfL{@K-e0HP
zRh56!>GvLg7jgyOJ{1P&gNW^Ah~9+Dv6r86`(gFqdu}|1)?0Gjx7cQ;!4{ipcZhdl
zH8iGJBU;0)wP1%x&S)fpG=^v5N=J65BZe{7nB9jqDskwrlX<6P8fIiOYU
zc{$^ebY!E$k}-+d4Vh&^B9>h*b|#@l{s*44;deJ{Y+;03aWf2oOF~~%~TXHxeXWRtJpLBc%$t~OavV}5pa?g8IQKnitD+88wQJnFU=4P3YPW%QDS9u>w>f_A%{EYOgS(JYN)DvK-FT-^
z?X2qH7+OQrhBA4vjh78~<&btlx8Z`zpn2LY%Br{w>zqEJ!WJRgr-q;k%4=zov8p0)
ziH@}6tr=lMy3;SA4pF7UhOUmE&;TApPmtr6?C^<;t_|>k!^fgci(oIaMPPF2;hMv#
z$>DZzde6Ayhjf}KX|TTvW37fGW~q$HEDr>qzRLrG+FhS*TKWcZi5@F;zuwdMEkIChgX{-d7>mk4_c0kMMT#TQ{%SV
z`Oa0z!^`@XbQ@5?O;(IjM;J4v!!0fHipLXVrN;P0Fa{`29yB8zBjvw3<}i|OG!+~l
zCnYOsk#*>?BpwNe2dBvGa9w~Qz1Ekb*QtsZ0*ufehj=?L{b_-dq~y5vw;vp}34m|n
zr7e>gK_!VQR{p;kdUEWYkvIi6+v(0w>g$1@3mDGah|g#7Q*R6Xr$9gU
z&`~thq4xabMDgO{k};L(
zOFeqi*5y>BJMBbCY1-2hrF3gG)x}QWpex3jHMB}fs&wrp9K$Nst~HOH#M9o3ZXs8&
z2v2{k{)@$1>xfmUx?^>%2xtW(cUK)`^;pO=Y*QeME4_~4M$=r>1n0*`Y=YL76vUMu
z23xbsZqJo~Ehj=No43B6(?PG@(qxmCSID(Cd&I*nPg6C_Q!Z$Yn>FEoLYW0w_VIFK
z5iKDhsmlr)^Ifv_%K`-%TEh+sn>$I&fsDynim7&U+U#zq9thneN*1-gbl<)BDo0Yn
z@34PtW4e@EHWsqgky$!tf9(id`(0O*wY)F*08GRv=Jp!}UaklO{Hi8uZ@~z*Z$E|W
zANpeIZ5&Rne*1<-W)2rZ5G*V*O*~!-F?PPltuKmS++YWvb;Q{$@raEp;O^QuzNz~D
zERO;C!w%O;n=U%!*d9!jMzV#z?6uX0!82I?zL>}hiSmp=x!WdTa*kQNa+Sq2(^WQU
zo*)jf7%`ipAaCTo;LYW9Rm@!^D`U!mdG7v>eB#gR
z*a1;U!`CUV4sM_|TWPGg8k$eVsFJIMs9_Vk*v39KvXiasWiz|k&VDwtqZxn{%=*vQ
zNHz1It?g}dyW8IWcDI9iKx|WE0Ome7y3?)hb+fzO?tVAC<1O!b)4SgGR(JkB6j5z!
zXHL2I{x`q_F7Sa9eBi$}DVh_ma7Bh;-~6s~uoo`zu(g!j6Tdh?5!JJYD=*?0|2WKI
zYH^U0Jb}~RIL8TG@|E}S)`Imo%VQoqho>ACBbPbOeOPgr=e*}8uX)FPE_9SSkF9S=
zY;9A^^Pw~SU@ix`-I^|Su<|yrmA)VOt0QTOI0ESo+;B9w!N3*vhHf9)9P}in<5B@gbJA5H@R;
z^x`@0nt3wiscTTQn%(he9^~c!$m2HenYE*mv%tdQ`PD1;Ei8>9;r_j+uZdiE?ZK^#AR^m6~Xx26Q5_QfxOO1Kc55VxUD+|RE9nc_~O@C(9hKM6G{jK7vT$>xVY{zvwblgsk@3obOCt;*Wj
zn0UEg{vF`!$sL*T8Y>A2xIG{QMxX>vAO%*S1zw=CVS^Rb--jSemf;=(k{+APGj`
z0Nh^)rr?t8pC~Ed{Aok4{TT?VAiWfv4c;IQ=3p+MAPx3ltZ@g|m7ov~ArTfK3BI2X
zCZXf-pb|Er`lMF~=%5r%Ar)4k6<%SwIiVJ&;P7ps7sAX(f_$MEjv*O-UKf@j8al%n
zrXd@)p&M4x8or?%&LJJvp&hcs9p<4P?jaxcp&$MsAO@l!4k95Iq9Gn4A||3DE+Qi~
zq9Z;cBu1hnP9h~%q9tA;CT5~0ZXzdkq9=YLD2Adajv^_RqA8vtDyE_;t|BY8qAR{4
QEXJZN&LS
-
-AspectJ Exercises
+
+
+
+
+
+
+
+
+
+
+
+
+ Hands-on Programming with AspectJ — Exercises
+
-
-Hands-on Aspect-Oriented Programming with AspectJ
+
+
+Hands-on Programming with AspectJ
+
+Erik Hilsdale
+Mik Kersten
+http://www.eclipse.com/aspectj
+
+Overview
-Organization
+ In this tutorial you will solve some canonical programming
+tasks using AspectJ. The tasks progress from writing
+non-functional, development-only aspects to writing aspects that
+augment a deployed program with crosscutting features. This
+follows the same progression most users see in their own adoption
+of AspectJ.
- This tutorial consists of the attendees solving AspectJ
-programming tasks (with unit tests) in pairs or triples and discussing
-the answers with the group and with the tutorial presenters. The
-exercises work with a figure editor together with JUnit test cases.
-They progress, as most users do in their adoption of AspectJ, from
-non-functional, development-only aspects to aspects which augment a
-deployed program with crosscutting features.
+ Since this is a hands-on tutorial, you will be working with a
+live AspectJ distribution. The example code we will be working
+with is a simple figure editor, along with JUnit tests for each
+exercise. We will break up into groups of two to three people
+per computer to foster discussion within the group as well as
+with the presenters.
+
+ If you have a laptop running a recent version of Windows,
+MacOS or Linux, feel free to bring it along. We will provide CDs
+and other installation media for a standalone AspectJ system,
+including the figure editor code these exercises are based on and
+unit tests for the exercises. If you don't have a laptop with
+you, don't worry about it.
These notes consist of four sections of exercises, a quick
reference to AspectJ syntax, and a UML diagram of a figure editor
-program. While you should feel free to have a quick look through
-these notes before the tutorial, please do not try to seriously read
-or do the exercises; you'll learn a lot more by working through it in
-groups.
-
-Command-line usage
-
- At the beginning of the tutorial we will make available a binary
-package that includes the tests, the base code, JUnit, and a
-distribution of AspectJ. All it needs is information about where Java
-lives (so set your JAVA_HOME environment variable). It assumes that
-you unzip it in c:\ (on Windows) or in your home directory (on Linux):
-If you put it somewhere else, edit setpaths or setpaths.bat, as
-appropriate. Once all this is done, run setpaths.bat
or
-source setpaths
to export some other needed environment
-variables.
-
- All the files in the program are listed in base.lst, including
-test cases and an empty answer aspect,
-answers/Answer.java
. Therefore, if you write your
-answers there, all you need to do is compile base.lst, either in an
-IDE or with
-
-
+program.
+
+ If you receive these tutorial notes
+early, feel free to have a quick look, especially at the UML
+diagram and quick reference. But you'll be cheating yourself if
+you try to do the exercises early; you'll learn a lot more by
+working through it in groups during the tutorial proper.
+
+
+Copyright is held by the author/owner(s).
+OOPSLA04, October 24-28, 2004, Vancouver, British Columbia, Canada
+2004 ACM 04/0010
+
+
+Command-line usage
+
+ While the AspectJ system is well integrated with a number of
+IDEs, it can also be used as a command-line compiler. The
+standalone package we provide (containing the tests, the base
+code, JUnit, and a distribution of AspectJ) needs information
+about where Java lives (so set your JAVA_HOME environment
+variable). It assumes that you unzip it in c:\ (on Windows) or
+in your home directory (on Linux): If you put it somewhere else,
+edit setpaths
or setpaths.bat
, as
+appropriate.
+
+
+ Each time you open a new shell window run
+setpaths.bat
or source setpaths
to
+export some other needed environment variables.
+
+ In general, all the files in the program are listed in
+base.lst
, including test cases and an empty answer
+aspect, answers/Answer.java
. Therefore, if you
+write your answers there, all you need to do is compile
+base.lst
, either in an IDE or with
+
+
$ ajc -argfile base.lst
-
+
Before you move onto another exercise, though, make sure to copy
your answer into a different file so we can discuss the answers
together:
-
+
> copy answers/Answer.java answers/2a.java (Windows)
$ cp answers/Answer.java answers/2a.java (Unix)
-
+
After building the system, you should invoke Java on the compiled
test class. On the command-line, this this would be
-
+
$ java tests.Test2a
-
-
- (For these exercises, when we give examples of execution we will
-show the command-line use, but of course if you are using JBuilder,
-Forte/NetBeans, Emacs, or Eclipse, use the appropriate compile and
-execute tools.)
+
The default test, tests.Test
, performs some
rudimentary tests on figure elements, and so is a useful test to run
-periodically. Looking at the JUnit tests for each exercise may also
-be helpful.
-
- Again, we will be looking at some solutions and having discussion,
-which is much more difficult without incremental solutions. So when
-you go from one exercise to the next, make sure to save your work in a
-file and go on to work in a different file, even if you plan to
-duplicate some code.
-
-Environment
-
- You may use whatever editor or environment you choose to work
-through these exercises. We provide a simple code-browser that can
-work well as an editor for these short exercises, in addition to
-providing better visualization of how aspects affect the system:
-
-
-$ ajbrowser base.lst
-
-
- With the browser you can edit code (including the
-answers/Answer.java
file), and after saving hit the build
-button to start an ajc compile. We recommend you start up another
-shell, though, to run the JUnit tests (and don't forget to run the
-setpaths
script when you open the new shell): You could
-set up the run button to run a test through the Options menu, but
-we've found this is fairly cumbersome.
+periodically. You should also look at the JUnit tests for each
+exercise as you do it.
+
+ Again, we will be looking at solutions and having discussion,
+which is much more difficult without incremental solutions. So
+when you go from one exercise to the next, save your
+work in a file before going on to the next exercise
+even if you plan to duplicate some code.
+
+ When we give examples of execution in
+these exercises we will show the command-line use, but of course
+you should use the appropriate compile and execute tools if you
+are using the AspectJ browser, Emacs, or Eclipse.
-
-1. Static Invariants
+1. Static Invariants
The easiest way to get started with AspectJ is to use it to
enforce static invariants.
-a. Catch old tracing
+1.a. Find old tracing
- Sample Exercise: The main point of this exercise
-is to make sure your configuration works. Type in the answer below
-into your answer file, make sure you get the desired compile-time
-error, remove the offending line, and make sure you pass the JUnit
-test.
+ Sample Exercise: The
+main point of this exercise is to make sure your configuration
+works. Type in the answer below into your answer file, make sure
+you get the desired compile-time error, remove the offending
+line, and make sure you pass the JUnit test.
Task: Signal an error for calls to
System.out.println
.
@@ -121,70 +179,69 @@ test.
The way that we are all taught to print "hello world" from Java is
to use System.out.println()
, so that is what we typically
use for one-off debugging traces. It's a common mistake to leave
-these in your system longer than is necessary. Type in the aspect
-below to force an error at compile time if this mistake is made.
+these in your system far longer than is necessary. Type in the aspect
+below to signal an error at compile time if this mistake is made.
+ Answer:
+
+
+
+package answers;
+
+import figures.*;
+
+aspect Answer1a {
+ declare error
+ : get(java.io.PrintStream System.out) && within(figures..*)
+ : "illegal access to System.out";
+}
+
+
When you use this on the given system, you'll find one incorrect
trace in SlothfulPoint
.
-
+
$ ajc -argfile base.lst
./figures/SlothfulPoint.java:38 illegal access to System.out
1 error
-
+
- Remove the illegal tracing call.
-
+ Note that this answer does not say that the call to the
+println()
method is incorrect, rather, that the field get
+of the out
field is illegal. This will also catch those
+users who bind System.out to a static field to save typing.
+
+ After you have successfully used this aspect, edit your
+program to remove the illegal tracing call.
Make sure your program still passes the JUnit test
tests.Test
(which it should also pass at the beginning of
all exercises) before continuing.
-
+
$ java tests.Test
....
Time: 0.03
OK (4 tests)
-
-
- Answer:
-
-
-
-package answers;
-
-import figures.*;
-
-aspect Answer1a {
- declare error
- : get(java.io.PrintStream System.out) && within(figures..*)
- : "illegal access to System.out";
-}
-
-
- Note that this answer does not say that the call to the
-println()
method is incorrect, rather, that the field get
-of the out
field is illegal. This will also catch those
-users who bind System.out to a static field to save typing.
-
-
+
-b. Mandate setters
+1.b. Mandate setters
Task: Signal a warning for assignments outside
of setter methods.
Tools: set
, withincode
,
-signature void set*(..)
+the void set*(..)
pattern
- One common coding convention is that no private field should be
-set outside of setter methods. Write an aspect to warn at compile
-time when such an illegal assignment expression exists.
+ One common coding convention is that no private field should
+be assigned to outside of setter methods. Write an aspect to
+signal a warning at compile time for these illegal assignment
+expressions.
This is going to look like
@@ -200,19 +257,19 @@ outside of setter methods. "Outside", here, means that the code for
the assignment is outside the text of the setter.
Make sure your program still passes the JUnit test
-tests.Test
before continuing. Make sure you get 11
+tests.Test
before continuing. Make sure you get eleven
warnings from this. Wait to fix them until the next exercise.
-c. Refine setters mandate
+1.c. Refine setters mandate
Task: Allow assignmnents inside of constructors.
- Tools: signature new(..)
+ Tools: the new(..)
pattern
Look at some of the warnings from the previous exercise. Notice
that a lot of them are from within constructors. Actually, the common
-coding convention is that no private field should be set outside of
+coding convention is that no private field should be assigned to outside of
setter methods or constructors. Modify your answer to signal
an actual error at compile time (rather than just a warning) when such
an illegal assignment expression exists.
@@ -225,42 +282,43 @@ pointcut to deal with the constructors.
the convention is violated twice in the figures package. You should see
the following two errors:
-
+
.\figures\Point.java:37 bad field set
.\figures\Point.java:38 bad field set
2 errors
-
+
Rewrite these two occurrences so as not to violate
the convention. Make sure your program still passes the JUnit test
tests.Test
before continuing.
-d. Congratulations
-
- You've taken your first steps. At this point, check the people to
-your left and right. If they're stuck somewhere, see if you can help
-them.
+ Congratulations, you've taken your
+first steps. At this point, check the people to your left and
+right. If they're stuck somewhere, see if you can help them.
+Try to resist moving on to the next section until we discuss
+solutions as a group.
-
-2. Dynamic invariants
+2. Dynamic invariants
The next step in AspectJ adoption is often to augment a test suite
by including additional dynamic tests.
- Tutorial attendees typically progress at different speeds through
-these questions. Throughout this tutorial, if you finish early, see
-what the people around you are doing and if they need help. Feel free
-to help them out of naked self-interest; we promise you'll learn a lot
-about AspectJ by explaining it.
+ Tutorial attendees typically progress
+at different speeds through these exercises. Throughout this
+tutorial, if you finish early, see what the people around you are
+doing and if they need help. Don't help them out of charity,
+help them out of naked self-interest—we promise you'll learn a
+lot about using AspectJ by explaining it.
-a. Check a simple precondition
+2.a. Check a simple precondition
- Sample Exercise: We've provided the answer to
-this exercise below to get you started.
+ Sample Exercise: We've
+provided the answer to this exercise to get you started. Feel
+free to think a bit, but don't get stuck on this one.
Task: Pass tests.Test2a
.
@@ -277,7 +335,7 @@ which wouldn't without your aspect. So before compiling in the
aspect,
-
+
$ java tests.Test2a
.F..F....
Time: 0.04
@@ -287,12 +345,12 @@ There were 2 failures:
FAILURES!!!
Tests run: 7, Failures: 2, Errors: 0
-
+
But after compiling in the aspect...
-
+
$ ajc -argfile base.lst answers/Answer.java
$ java tests.Test2a
@@ -300,12 +358,12 @@ $ java tests.Test2a
Time: 0.04
OK (7 tests)
-
+
Answer:
-
+
package answers;
import figures.*;
@@ -317,9 +375,9 @@ aspect Answer2a {
}
}
}
-
+
-b. Check another precondition
+2.b. Check another precondition
Task: Pass tests.Test2b
.
@@ -336,7 +394,7 @@ value.
Look at tests/Test2b.java
to see exactly what we're
testing for.
-c. Check yet another precondition
+2.c. Check yet another precondition
Task: Pass tests.Test2c
.
@@ -354,7 +412,7 @@ an attempt is made to call Group.add()
on a
call.
-d. Assure input
+2.d. Assure input
Task: Pass tests.Test2d
.
@@ -381,8 +439,7 @@ aspect A {
}
-
-e. Check a postcondition
+2.e. Check a postcondition
Task: Pass tests.Test2e
@@ -401,7 +458,7 @@ offset, then the point is in an illegal state and so an
during move, we need some way of getting access to the coordinates
both before and after the move, in one piece of advice.
-f. Check another postcondition
+2.f. Check another postcondition
Task: Pass tests.Test2f
@@ -420,14 +477,13 @@ throw an IllegalStateException
if it is violated.
-
-3. Tracing
+3. Tracing
Tracing is one of the classic AspectJ applications, and is often
the first where AspectJ is used on deployed code.
-a. Simple logging
+3.a. Simple logging
Task: Pass tests.Test3a
.
@@ -441,7 +497,7 @@ in the figures package. To do this, use the utility class
Log
(with an import from support.Log
)
and call Log.log(String)
-b. Exposing a value
+3.b. Exposing a value
Task: Pass tests.Test3b
.
@@ -453,12 +509,12 @@ In this exercise, you will print not only the join point information,
but also the target object, with the form
-
+
thisJoinPointInfo at targetObject
-
+
-c. More specialized logging
+3.c. More specialized logging
Task: Pass tests.Test3c
.
@@ -469,10 +525,10 @@ but also the target object, with the form
group. The args
pointcut allows you to select join points
based on the type of a parameter to a method call.
- Look at the test case for details about the tested log message.
+
Look at the test case for details about the required log message.
-d. Logging extended to checking an invariant
+3.d. Logging extended to checking an invariant
Task: Pass tests.Test3d
.
@@ -483,43 +539,39 @@ based on the type of a parameter to a method call.
To do so, associate a boolean flag with each Point using an inter-type
declaration, such as
-
+
boolean Point.hasBeenAdded = false;
-
+
Check and set this flag with the same kind of advice from your
answer to problem (c). Throw an IllegalStateException
if
the point has already been added.
-e. Better error messages for 3d
+3.e. Better error messages for 3.d.
Task: Pass tests.Test3e
.
- Tools:
-
-
Extend your solution to problem (d) by using the string
representation of the Point's containing group as the msg
part of the IllegalStateException
.
-
-4. Caching
+4. Caching
Computation of the bounding box of Group
objects
needs to deal with all aggregate parts of the group, and this
computation can be expensive. In this section, we will explore
various ways of reducing this expense.
- Optional: In all of these exercises, you should
-only deal with points that are added directly to Groups, rather than
-those that are added "indirectly" through Lines and Boxes. You should
-handle those points contained in Lines and Boxes only if time permits.
-
+ Optional: In all of
+these exercises, you should only deal with points that are added
+directly to Groups, rather than those that are added "indirectly"
+through Lines and Boxes. You should handle those points
+contained in Lines and Boxes only if time permits.
-a. Make a constant override
+4.a. Make a constant override
Task: Pass tests.Test4a
.
@@ -540,7 +592,7 @@ by the static method FigureElement.MAX_BOUNDS
.
around advice intercepting the method.
-b. Make a constant cache
+4.b. Make a constant cache
Task: Pass tests.Test4b
.
@@ -559,7 +611,7 @@ call.
state for every Group
object.
-c. Invalidate, part 1
+4.c. Invalidate, part 1
Task: Pass tests.Test4c
.
@@ -573,8 +625,7 @@ Change your aspect so that it invalidates the cache whenever the
move()
method of Group
is called.
-
-d. Invalidate, part 2
+4.d. Invalidate, part 2
Task: Pass tests.Test4d
.
@@ -586,7 +637,7 @@ modify your invalidation criteria in this way, but note that this is
slightly different than the problem in 3c: Here you care about fields,
where there you cared about method calls.
-e. Invalidate, part 3
+4.e. Invalidate, part 3
Task: Pass tests.Test4e
.
@@ -598,5 +649,23 @@ go help other people. Otherwise, you have fallen prey to our cruel
trap: Remember that whenever a point moves it should invalidate the
caches of all enclosing groups.
-
+
+
+
Congratulations! Not only have you learned about how to
+program in AspectJ, you have worked through exercises paralleling
+a common AspectJ adoption strategy. You should be able to
+pick up AspectJ and use it to improve your own software's
+crosscutting modularity.
+
+
You can find the current binaries, source, documentation and
+an active user community for AspectJ at
+
+
+ http://www.eclipse.org/aspectj
+
+
+
+
+
+
--
2.39.5