You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.html 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  1. <?xml version="1.0" encoding="iso-8859-1"?>
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  3. "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  4. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  5. <!-- This file represents the Exercises for the hands-on AspectJ
  6. tutorial. It is commonly checked into CVS with identifying
  7. information for the latest conference (such as presenters
  8. and publication information).
  9. When you use it for your own purposes, don't forget to
  10. modify at the very least anything that says
  11. id="copyright" or class="presenter". If you're in an A4
  12. country, don't forget to modify the paper size.
  13. The gif included at the end is somewhat fragile,
  14. so be careful with different paper sizes.
  15. TODO: There is currently something weird about PDF generation
  16. from this: If generated from a windows machine, it will
  17. generate mac-unfriendly PDF because of the requested windows
  18. font. If the PDF is only used for immediate printing,
  19. that's fine, but if it's used for distribution, bad.
  20. -->
  21. <head>
  22. <title>Hands-on Programming with AspectJ&reg; &mdash; Exercises</title>
  23. <style type="text/css">
  24. div.instruction { padding: 0.5em; border-width: 1px; border-style: solid }
  25. body { background-color: #FFF; margin: 2em }
  26. body { font-family: "Gill Sans MT", "Gill sans", "Trebuchet ms", Verdana, sans-serif; }
  27. .newpage { page-break-before: always }
  28. pre { margin-left: 1em; border-left-style: solid; border-width: 1px; padding-left: 1em;}
  29. h2 { margin-top: 4ex; }
  30. h3 { margin-top: 4ex; border-bottom-style: solid; border-width: 1px }
  31. .presenter { text-align: right }
  32. @page {
  33. size: 8.5in 11in;
  34. margin: 3in;
  35. marks: cross
  36. }
  37. @media print {
  38. body { font-size: 10pt }
  39. #copyright {
  40. font-family: "Times New Roman", "Times Roman", fixed;
  41. font-size: 8pt;
  42. display: normal;
  43. position: absolute;
  44. bottom: 1in;
  45. border-style: none
  46. }
  47. }
  48. @media screen {
  49. #copyright { display: none }
  50. }
  51. </style>
  52. </head>
  53. <body>
  54. <h1>Hands-on Programming with AspectJ<sup>&reg;</sup></h1>
  55. <div class="presenter">Erik Hilsdale</div>
  56. <div class="presenter">Mik Kersten</div>
  57. <div class="presenter">http://www.eclipse.com/aspectj</div>
  58. <h2>Overview</h2>
  59. <p> In this tutorial you will solve some canonical programming
  60. tasks using AspectJ. The tasks progress from writing
  61. non-functional, development-only aspects to writing aspects that
  62. augment a deployed program with crosscutting features. This
  63. follows the same progression most users see in their own adoption
  64. of AspectJ. </p>
  65. <p> Since this is a hands-on tutorial, you will be working with a
  66. live AspectJ distribution. The example code we will be working
  67. with is a simple figure editor, along with JUnit tests for each
  68. exercise. We will break up into groups of two to three people
  69. per computer to foster discussion within the group as well as
  70. with the presenters. </p>
  71. <p> If you have a laptop running a recent version of Windows,
  72. MacOS or Linux, feel free to bring it along. We will provide CDs
  73. and other installation media for a standalone AspectJ system,
  74. including the figure editor code these exercises are based on and
  75. unit tests for the exercises. If you don't have a laptop with
  76. you, don't worry about it. </p>
  77. <p> These notes consist of four sections of exercises, a quick
  78. reference to AspectJ syntax, and a UML diagram of a figure editor
  79. program. </p>
  80. <div class="instruction"> If you receive these tutorial notes
  81. early, feel free to have a quick look, especially at the UML
  82. diagram and quick reference. But you'll be cheating yourself if
  83. you try to do the exercises early; you'll learn a lot more by
  84. working through it in groups during the tutorial proper. </div>
  85. <!--
  86. This space is used for a copyright that appears on the
  87. bottom of the _printed_ page. It's suppressed when viewed on
  88. a computer screen by the stylesheet.
  89. <div id="copyright">
  90. Copyright is held by the author/owner(s). <br />
  91. OOPSLA’04, October 24-28, 2004, Vancouver, British Columbia, Canada <br />
  92. 2004 ACM 04/0010
  93. </div>
  94. -->
  95. <h3 class="newpage">Command-line usage</h3>
  96. <p> While the AspectJ system is well integrated with a number of
  97. IDEs, it can also be used as a command-line compiler. The
  98. standalone package we provide (containing the tests, the base
  99. code, JUnit, and a distribution of AspectJ) needs information
  100. about where Java lives (so set your JAVA_HOME environment
  101. variable). It assumes that you unzip it in c:\ (on Windows) or
  102. in your home directory (on Linux): If you put it somewhere else,
  103. edit <code>setpaths</code> or <code>setpaths.bat</code>, as
  104. appropriate.
  105. </p>
  106. <p> Each time you open a new shell window run
  107. <code>setpaths.bat</code> or <code>source setpaths</code> to
  108. export some other needed environment variables. </p>
  109. <p> In general, all the files in the program are listed in
  110. <code>base.lst</code>, including test cases and an empty answer
  111. aspect, <code>answers/Answer.java</code>. Therefore, if you
  112. write your answers there, all you need to do is compile
  113. <code>base.lst</code>, either in an IDE or with </p>
  114. <pre>
  115. $ ajc -argfile base.lst
  116. </pre>
  117. <p> Before you move onto another exercise, though, make sure to copy
  118. your answer into a different file so we can discuss the answers
  119. together:
  120. </p>
  121. <pre>
  122. &gt; copy answers/Answer.java answers/2a.java (Windows)
  123. $ cp answers/Answer.java answers/2a.java (Unix)
  124. </pre>
  125. <p> After building the system, you should invoke Java on the compiled
  126. test class. On the command-line, this this would be </p>
  127. <pre>
  128. $ java tests.Test2a
  129. </pre>
  130. <p> The default test, <code>tests.CoreTest</code>, performs some
  131. rudimentary tests on figure elements, and so is a useful test to run
  132. periodically. You should also look at the JUnit tests for each
  133. exercise as you do it. </p>
  134. <p> Again, we will be looking at solutions and having discussion,
  135. which is much more difficult without incremental solutions. So
  136. when you go from one exercise to the next, <strong>save your
  137. work</strong> in a file before going on to the next exercise
  138. even if you plan to duplicate some code. </p>
  139. <div class="instruction"> When we give examples of execution in
  140. these exercises we will show the command-line use, but of course
  141. you should use the appropriate compile and execute tools if you
  142. are using the AspectJ browser, Emacs, or Eclipse. </div>
  143. <!-- ============================== -->
  144. <h2 class="newpage">1. Static Invariants</h2>
  145. <p> The easiest way to get started with AspectJ is to use it to
  146. enforce static invariants.
  147. </p>
  148. <h3>1.a. Find old tracing</h3>
  149. <div class="instruction"> <strong>Sample Exercise</strong>: The
  150. main point of this exercise is to make sure your configuration
  151. works. Type in the answer below into your answer file, make sure
  152. you get the desired compile-time error, remove the offending
  153. line, and make sure you pass the JUnit test. </div>
  154. <p> <strong>Task:</strong> Signal an error for calls to
  155. <code>System.out.println</code>.
  156. </p>
  157. <p> The way that we are all taught to print "hello world" from Java is
  158. to use <code>System.out.println()</code>, so that is what we typically
  159. use for one-off debugging traces. It's a common mistake to leave
  160. these in your system far longer than is necessary. Type in the aspect
  161. below to signal an error at compile time if this mistake is made.
  162. </p>
  163. <p> <strong>Answer:</strong>
  164. </p>
  165. <pre>
  166. package answers;
  167. import figures.*;
  168. aspect Answer1a {
  169. declare error
  170. : get(java.io.PrintStream System.out) &amp;&amp; within(figures..*)
  171. : "illegal access to System.out";
  172. }
  173. </pre>
  174. <p> When you use this on the given system, you'll find one incorrect
  175. trace in <code>SlothfulPoint</code>.
  176. </p>
  177. <pre>
  178. $ ajc -argfile base.lst
  179. ./figures/SlothfulPoint.java:38 illegal access to System.out
  180. 1 error
  181. </pre>
  182. <p> Note that this answer does not say that the <em>call</em> to the
  183. <code>println()</code> method is incorrect, rather, that the field get
  184. of the <code>out</code> field is illegal. This will also catch those
  185. users who bind System.out to a static field to save typing. </p>
  186. <p> After you have successfully used this aspect, edit your
  187. program to remove the illegal tracing call. </p>
  188. <p> Make sure your program still passes the JUnit test
  189. <code>tests.CoreTest</code> (which it should also pass at the beginning of
  190. all exercises) before continuing. </p>
  191. <pre>
  192. $ java tests.CoreTest
  193. ....
  194. Time: 0.03
  195. OK (4 tests)
  196. </pre>
  197. <h3 class="newpage">1.b. Mandate setters</h3>
  198. <p> <strong>Task:</strong> Signal a warning for assignments outside
  199. of setter methods. </p>
  200. <p> <strong>Tools:</strong> <code>set</code>, <code>withincode</code>,
  201. the <code>void set*(..)</code> pattern
  202. </p>
  203. <p> One common coding convention is that no private field should
  204. be assigned to outside of setter methods. Write an aspect to
  205. signal a warning at compile time for these illegal assignment
  206. expressions. </p>
  207. <p> This is going to look like
  208. </p>
  209. <pre>
  210. aspect A {
  211. declare warning: <em>&lt;pointcut here&gt;</em> : "bad field set";
  212. }
  213. </pre>
  214. <p> where the pointcut picks out join points of private field sets
  215. outside of setter methods. "Outside", here, means that the code for
  216. the assignment is outside the <em>text</em> of the setter.
  217. <p> Make sure your program still passes the JUnit test
  218. <code>tests.CoreTest</code> before continuing. Make sure you get eleven
  219. warnings from this. Wait to fix them until the next exercise. </p>
  220. <h3>1.c. Refine setters mandate</h3>
  221. <p> <strong>Task:</strong> Allow assignmnents inside of constructors.
  222. </p>
  223. <p> <strong>Tools:</strong> the <code>new(..)</code> pattern</p>
  224. <p> Look at some of the warnings from the previous exercise. Notice
  225. that a lot of them are from within constructors. Actually, the common
  226. coding convention is that no private field should be assigned to outside of
  227. setter methods <em>or constructors</em>. Modify your answer to signal
  228. an actual error at compile time (rather than just a warning) when such
  229. an illegal assignment expression exists. </p>
  230. <p>You'll want to add another <code>withincode</code> primitive
  231. pointcut to deal with the constructors.
  232. </p>
  233. <p>After you specify your pointcut correctly, you'll still find that
  234. the convention is violated twice in the figures package. You should see
  235. the following two errors:</p>
  236. <pre>
  237. .\figures\Point.java:37 bad field set
  238. .\figures\Point.java:38 bad field set
  239. 2 errors
  240. </pre>
  241. <p>Rewrite these two occurrences so as not to violate
  242. the convention. Make sure your program still passes the JUnit test
  243. <code>tests.CoreTest</code> before continuing. </p>
  244. <div class="instruction"> Congratulations, you've taken your
  245. first steps. At this point, check the people to your left and
  246. right. If they're stuck somewhere, see if you can help them.
  247. Try to resist moving on to the next section until we discuss
  248. solutions as a group. </div>
  249. <!-- ============================== -->
  250. <h2 class="newpage">2. Dynamic invariants</h2>
  251. <p> The next step in AspectJ adoption is often to augment a test suite
  252. by including additional dynamic tests.
  253. </p>
  254. <div class="instruction"> Tutorial attendees typically progress
  255. at different speeds through these exercises. Throughout this
  256. tutorial, if you finish early, see what the people around you are
  257. doing and if they need help. Don't help them out of charity,
  258. help them out of naked self-interest&mdash;we promise you'll learn a
  259. lot about using AspectJ by explaining it. </div>
  260. <h3>2.a. Check a simple precondition</h3>
  261. <div class="instruction"> <strong>Sample Exercise</strong>: We've
  262. provided the answer to this exercise to get you started. Feel
  263. free to think a bit, but don't get stuck on this one. </div>
  264. <p> <strong>Task:</strong> Pass <code>tests.Test2a</code>.
  265. </p>
  266. <p> <strong>Tools:</strong> <code>args</code>, <code>before</code>
  267. </p>
  268. <p> Write an aspect to throw an <code>IllegalArgumentException</code>
  269. whenever an attempt is made to set one of <code>Point</code>'s
  270. <code>int</code> fields to a value that is less than zero. </p>
  271. <p> This should make the test case of <code>tests.Test2a</code> pass,
  272. which wouldn't without your aspect. So before compiling in the
  273. aspect,
  274. </p>
  275. <pre>
  276. $ java tests.Test2a
  277. .F..F....
  278. Time: 0.04
  279. There were 2 failures:
  280. 1) testTooSmall(tests.Test2a)junit.framework.AssertionFailedError: should have thrown IllegalArgumentException
  281. 2) testMove(tests.Test2a)junit.framework.AssertionFailedError: should have thrown IllegalArgumentException
  282. FAILURES!!!
  283. Tests run: 7, Failures: 2, Errors: 0
  284. </pre>
  285. <p> But after compiling in the aspect...
  286. </p>
  287. <pre>
  288. $ ajc -argfile base.lst answers/Answer.java
  289. $ java tests.Test2a
  290. .......
  291. Time: 0.04
  292. OK (7 tests)
  293. </pre>
  294. <p> <strong>Answer:</strong>
  295. </p>
  296. <pre>
  297. package answers;
  298. import figures.*;
  299. aspect Answer2a {
  300. before(int newValue): set(int Point.*) &amp;&amp; args(newValue) {
  301. if (newValue &lt; 0) {
  302. throw new IllegalArgumentException("too small");
  303. }
  304. }
  305. }
  306. </pre>
  307. <h3>2.b. Check another precondition</h3>
  308. <p> <strong>Task:</strong> Pass <code>tests.Test2b</code>. </p>
  309. <p> <strong>Tools: </strong> <code>call</code>.
  310. </p>
  311. <p> <code>Group</code> is a <code>FigureElement</code> class that
  312. encapsulates groups of other figure elements. As such, only actual
  313. figure element objects should be added to <code>Group</code> objects.
  314. Write an aspect to throw an <code>IllegalArgumentException</code>
  315. whenever <code>Group.add()</code> is called with a <code>null</code>
  316. value. </p>
  317. <p> Look at <code>tests/Test2b.java</code> to see exactly what we're
  318. testing for. </p>
  319. <h3>2.c. Check yet another precondition</h3>
  320. <p> <strong>Task:</strong> Pass <code>tests.Test2c</code>. </p>
  321. <p> <strong>Tools:</strong> <code>target</code>
  322. </p>
  323. <p> Another constraint on a well-formed group is that it should not
  324. contain itself as a member (though it may contain other groups). Write
  325. an aspect to throw an <code>IllegalArgumentException</code> whenever
  326. an attempt is made to call <code>Group.add()</code> on a
  327. <code>null</code> value, or on the group itself. </p>
  328. <p> You will want to use a <code>target</code> pointcut to expose the
  329. <code>Group</code> object that is the target of the <code>add</code>
  330. call.
  331. </p>
  332. <h3>2.d. Assure input</h3>
  333. <p> <strong>Task: </strong> Pass <code>tests.Test2d</code>.
  334. </p>
  335. <p> <strong>Tools: </strong> around advice
  336. </p>
  337. <p> Instead of throwing an exception when one of <code>Point</code>'s
  338. <code>int</code> fields is set to a negative value, write an aspect
  339. to trim the value to zero. You'll want to use <code>around</code>
  340. advice that exposes the new value of the field assignment with an
  341. <code>args</code> pointcut, and <code>proceed</code> with the trimmed
  342. value. </p>
  343. <p> This is going to look something like
  344. </p>
  345. <pre>
  346. aspect A {
  347. void around(int val): <var>&lt;Pointcut&gt;</var> {
  348. <var>&lt;Do something with val&gt;</var>
  349. proceed(val);
  350. }
  351. }
  352. </pre>
  353. <h3 class="newpage">2.e. Check a postcondition</h3>
  354. <p> <strong>Task: </strong> Pass <code>tests.Test2e</code>
  355. </p>
  356. <p> <strong>Tools: </strong> around advice
  357. </p>
  358. <p> A postcondition of a <code>Point</code>'s <code>move</code>
  359. operation is that the <code>Point</code>'s coordinates should change.
  360. If a call to move didn't actually move a point by the desired
  361. offset, then the point is in an illegal state and so an
  362. <code>IllegalStateException</code> should be thrown.
  363. </p>
  364. <p> Note that because we're dealing with how the coordinates change
  365. during move, we need some way of getting access to the coordinates
  366. both before <em>and</em> after the move, in one piece of advice. </p>
  367. <h3>2.f. Check another postcondition</h3>
  368. <p> <strong>Task: </strong> Pass <code>tests.Test2f</code>
  369. </p>
  370. <p> <strong>Tools:</strong> the <code> Rectangle(Rectangle)</code>
  371. constructor, the <code>Rectangle.translate(int, int)</code> method.
  372. </p>
  373. <p> <code>FigureElement</code> objects have a <code>getBounds()</code>
  374. method that returns a <code>java.awt.Rectangle</code> representing the
  375. bounds of the object. An important postcondition of the general
  376. <code>move</code> operation on a figure element is that the figure
  377. element's bounds rectangle should move by the same amount as the
  378. figure itself. Write an aspect to check for this postcondition --
  379. throw an <code>IllegalStateException</code> if it is violated. </p>
  380. <!-- ============================== -->
  381. <h2 class="newpage">3. Tracing</h2>
  382. <p> Tracing is one of the classic AspectJ applications, and is often
  383. the first where AspectJ is used on deployed code.
  384. </p>
  385. <h3>3.a. Simple tracing</h3>
  386. <p> <strong>Task:</strong> Pass <code>tests.Test3a</code>.</p>
  387. <p> <strong>Tools:</strong>
  388. <code>Log.write(String)</code>,
  389. <code>thisJoinPoint.toString()</code>,
  390. <code>execution</code>,
  391. <code>within</code>
  392. </p>
  393. <p> Write an aspect to log the execution of all public methods
  394. in the figures package. To do this, use the utility class
  395. <code>Log</code> (this is in the <code>support</code> package, so
  396. remember to import it into your answer aspect). Write a message
  397. into the log with the static <code>write(String)</code> method.</p>
  398. <h3>3.b. Exposing a value</h3>
  399. <p> <strong>Task:</strong> Pass <code>tests.Test3b</code>.</p>
  400. <p> <strong>Tools:</strong> <code>target</code>
  401. </p>
  402. <p> AspectJ can expose the target object at a join point for tracing.
  403. In this exercise, you will print not only the join point information,
  404. but also the target object, with the form
  405. </p>
  406. <pre>
  407. <em>thisJoinPointInfo</em> at <em>targetObject</em>
  408. </pre>
  409. <h3>3.c. More specialized logging</h3>
  410. <p> <strong>Task:</strong> Pass <code>tests.Test3c</code>.</p>
  411. <p> <strong>Tools:</strong> <code>args</code>.
  412. </p>
  413. <p> Write an aspect to log whenever a <code>Point</code> is added to a
  414. group. The <code>args</code> pointcut allows you to select join points
  415. based on the type of a parameter to a method call. </p>
  416. <p> Look at the test case to see the trace message we expect you
  417. to write in the log.
  418. </p>
  419. <h3 class="newpage">3.d. Logging extended to checking an invariant</h3>
  420. <p> <strong>Task:</strong> Pass <code>tests.Test3d</code>.</p>
  421. <p> <strong>Tools:</strong> <code>inter-type field declaration</code>
  422. </p>
  423. <p> Make sure that a <code>Point</code> is never added to more
  424. than one <code>Group</code>. To do so, associate a boolean flag
  425. with each <code>Point</code> using an inter-type declaration,
  426. such as </p>
  427. <pre>
  428. boolean Point.hasBeenAdded = false;
  429. </pre>
  430. <p> Check and set this flag with the same kind of advice from your
  431. answer to problem (c). Throw an <code>IllegalStateException</code> if
  432. the point has already been added.
  433. </p>
  434. <h3>3.e. Better error messages for 3.d.</h3>
  435. <p> <strong>Task:</strong> Pass <code>tests.Test3e</code>.</p>
  436. <p> Extend your solution to problem (d) by using the string
  437. representation of the Point's containing group as the <code>msg</code>
  438. part of the <code>IllegalStateException</code>. </p>
  439. <!-- ============================== -->
  440. <h2 class="newpage">4. Caching</h2>
  441. <p> Computation of the bounding box of <code>Group</code> objects
  442. needs to deal with all aggregate parts of the group, and this
  443. computation can be expensive. In this section, we will explore
  444. various ways of reducing this expense. </p>
  445. <div class="instruction"> <strong>Optional</strong>: In all of
  446. these exercises, you should only deal with points that are added
  447. directly to Groups, rather than those that are added "indirectly"
  448. through Lines and Boxes. You should handle those points
  449. contained in Lines and Boxes only if time permits. </div>
  450. <h3>4.a. Make a constant override</h3>
  451. <p> <strong>Task:</strong> Pass <code>tests.Test4a</code>.</p>
  452. <p> <strong>Tools:</strong> <code>around</code>,
  453. <code>FigureElement.MAX_BOUNDS</code>
  454. </p>
  455. <p> <code>Group</code>'s <code>getBounds()</code> method could be
  456. understood to be a conservative approximation of the bounding box of a
  457. group. If that is true, then it would be a legal (and much faster)
  458. implementation of <code>getBounds()</code> to simply always return a
  459. rectangle consisting of the entire canvas. The entire canvas is returned
  460. by the static method <code>FigureElement.MAX_BOUNDS</code>.
  461. </p>
  462. <p> Write an aspect to implement this change. You can override
  463. <code>Group</code>'s <code>getBounds()</code> method entirely with
  464. around advice intercepting the method.
  465. </p>
  466. <h3>4.b. Make a constant cache</h3>
  467. <p> <strong>Task:</strong> Pass <code>tests.Test4b</code>.
  468. </p>
  469. <p> <strong>Tools:</strong> inter-type field.
  470. </p>
  471. <p> Instead of making the (very) conservative approximation of
  472. <code>getBounds()</code> from part (a), write an aspect instead that
  473. remembers the return value from the first time
  474. <code>getBounds()</code> has been called on a <code>Group</code>, and
  475. returns that first <code>Rectangle</code> for every subsequent
  476. call. </p>
  477. <p> <em>Hint: You can use an inter-type declaration to keep some
  478. state for every <code>Group</code> object.</em> </p>
  479. <h3>4.c. Invalidate, part 1</h3>
  480. <p> <strong>Task:</strong> Pass <code>tests.Test4c</code>.
  481. </p>
  482. <p> <strong>Tools:</strong> <code>before</code>
  483. </p>
  484. <p> While caching in this way does save computation, it will lead to
  485. incorrect bounding boxes if a <code>Group</code> is ever moved.
  486. Change your aspect so that it invalidates the cache whenever the
  487. <code>move()</code> method of <code>Group</code> is called.
  488. </p>
  489. <h3 class="newpage">4.d. Invalidate, part 2</h3>
  490. <p> <strong>Task:</strong> Pass <code>tests.Test4d</code>.</p>
  491. <p> Of course, part (c) didn't really solve the problem. What if a
  492. <code>Point</code> that is part of a <code>Group</code> moves?
  493. Whenever either of a Point's fields are set it should invalidate the
  494. caches of all enclosing groups. Use your solution to problem 3c to
  495. modify your invalidation criteria in this way, but note that this is
  496. slightly different than the problem in 3c: Here you care about fields,
  497. where there you cared about method calls. </p>
  498. <h3>4.e. Invalidate, part 3</h3>
  499. <p> <strong>Task:</strong> Pass <code>tests.Test4e</code>.</p>
  500. <p> <strong>Tools:</strong> <em>You're on you're own</em></p>
  501. <p> Did you really do part (d) correctly? Run the JUnit test
  502. <code>tests.Test4e</code> to see. If you pass, congratulations, now
  503. go help other people. Otherwise, you have fallen prey to our cruel
  504. trap: Remember that whenever a point moves it should invalidate the
  505. caches of <em>all</em> enclosing groups. </p>
  506. <div class="instruction">
  507. <p> Congratulations! Not only have you learned about how to
  508. program in AspectJ, you have worked through exercises paralleling
  509. a common AspectJ adoption strategy. You should be able to
  510. pick up AspectJ and use it to improve your own software's
  511. crosscutting modularity. </p>
  512. <p> You can find the current binaries, source, documentation and
  513. an active user community for AspectJ at</p>
  514. <blockquote>
  515. http://www.eclipse.org/aspectj
  516. </blockquote>
  517. </div>
  518. <img style="newpage" src="figures_classes.gif" height="900" alt="" />
  519. </body> </html>