diff options
author | ehilsdal <ehilsdal> | 2004-08-23 23:08:20 +0000 |
---|---|---|
committer | ehilsdal <ehilsdal> | 2004-08-23 23:08:20 +0000 |
commit | 6a1dcf2e9e9f077b6adb733654c4d3b727a1d1de (patch) | |
tree | 88e7ce71e91ab9fa156d1753673fe85e2d9d06a1 /docs/teaching | |
parent | 5856b320e6c55a82d737df725ea1373dc2a25d94 (diff) | |
download | aspectj-6a1dcf2e9e9f077b6adb733654c4d3b727a1d1de.tar.gz aspectj-6a1dcf2e9e9f077b6adb733654c4d3b727a1d1de.zip |
tutorial exercises updated for OOPSLA. The printout
looks much nicer and is a bit more streamlined.
Diffstat (limited to 'docs/teaching')
-rw-r--r-- | docs/teaching/exercises/figures_classes.gif | bin | 14202 -> 18540 bytes | |||
-rw-r--r-- | 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 Binary files differindex a5952fb9e..3440bbff8 100644 --- a/docs/teaching/exercises/figures_classes.gif +++ b/docs/teaching/exercises/figures_classes.gif diff --git a/docs/teaching/exercises/index.html b/docs/teaching/exercises/index.html index b6130821f..84b11cd20 100644 --- a/docs/teaching/exercises/index.html +++ b/docs/teaching/exercises/index.html @@ -1,118 +1,176 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> -<html> <head> -<title>AspectJ Exercises</title> +<?xml version="1.0" encoding="iso-8859-1"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> + +<!-- This file represents the Exercises for the hands-on AspectJ + tutorial. It is commonly checked into CVS with identifying + information for the latest conference (such as presenters + and publication information). --> + +<!-- When you use it for your own purposes, don't forget to + modify at the very least anything that says + id="copyright" or class="presenter" --> + +<!-- Also, the gif included at the end is somewhat fragile, + so be careful with different paper sizes. --> + + +<head> + <title>Hands-on Programming with AspectJ — Exercises</title> + <style type="text/css"> +div.instruction { padding: 0.5em; border-width: 1px; border-style: solid } +body { background-color: #FFF; margin: 2em } +body { font-family: "Gill Sans MT", "Gill sans", "Trebuchet ms", Verdana, sans-serif; } +.newpage { page-break-before: always } +pre { margin-left: 1em; border-left-style: solid; border-width: 1px; padding-left: 1em;} +h2 { margin-top: 4ex; } +h3 { margin-top: 4ex; border-bottom-style: solid; border-width: 1px } +.presenter { text-align: right } +@page { + size: 8.5in 11in; + margin: 3in; + marks: cross +} +@media print { + body { font-size: 10pt } + #copyright { + font-family: "Times New Roman", "Times Roman", fixed; + font-size: 8pt; + display: normal; + position: absolute; + bottom: 1in; + border-style: none + } +} +@media screen { + #copyright { display: none } +} + </style> </head> -<body bgcolor="white"> -<h2>Hands-on Aspect-Oriented Programming with AspectJ</h2> +<body> + +<h1>Hands-on Programming with AspectJ</h1> + +<div class="presenter">Erik Hilsdale</div> +<div class="presenter">Mik Kersten</div> +<div class="presenter">http://www.eclipse.com/aspectj</div> + +<h2>Overview</h2> -<h3>Organization</h3> +<p> 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. </p> -<p> 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. </p> +<p> 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. </p> + +<p> 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. </p> <p> 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. </p> - -<h3>Command-line usage</h3> - -<p> 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 <code>setpaths.bat</code> or -<code>source setpaths</code> to export some other needed environment -variables. </p> - -<p> All the files in the program are listed in base.lst, including -test cases and an empty answer aspect, -<code>answers/Answer.java</code>. Therefore, if you write your -answers there, all you need to do is compile base.lst, either in an -IDE or with </p> - -<blockquote><PRE> +program. </p> + +<div class="instruction"> 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. </div> + +<div id="copyright"> +Copyright is held by the author/owner(s). <br /> +OOPSLA’04, October 24-28, 2004, Vancouver, British Columbia, Canada <br /> +2004 ACM 04/0010 +</div> + +<h3 class="newpage">Command-line usage</h3> + +<p> 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 <code>setpaths</code> or <code>setpaths.bat</code>, as +appropriate. +</p> + +<p> Each time you open a new shell window run +<code>setpaths.bat</code> or <code>source setpaths</code> to +export some other needed environment variables. </p> + +<p> In general, all the files in the program are listed in +<code>base.lst</code>, including test cases and an empty answer +aspect, <code>answers/Answer.java</code>. Therefore, if you +write your answers there, all you need to do is compile +<code>base.lst</code>, either in an IDE or with </p> + +<pre> $ ajc -argfile base.lst -</PRE></blockquote> +</pre> <p> Before you move onto another exercise, though, make sure to copy your answer into a different file so we can discuss the answers together: </p> -<blockquote><PRE> +<pre> > copy answers/Answer.java answers/2a.java (Windows) $ cp answers/Answer.java answers/2a.java (Unix) -</PRE></blockquote> +</pre> <p> After building the system, you should invoke Java on the compiled test class. On the command-line, this this would be </p> -<blockquote><PRE> +<pre> $ java tests.Test2a -</PRE> </blockquote> - -<p> (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.) </p> +</pre> <p> The default test, <code>tests.Test</code>, 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. </p> - -<p> 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. </p> - -<h3>Environment</h3> - -<p> 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: </p> - -<blockquote><PRE> -$ ajbrowser base.lst -</PRE></blockquote> - -<p> With the browser you can edit code (including the -<code>answers/Answer.java</code> 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 -<code>setpaths</code> 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. </p> +periodically. You should also look at the JUnit tests for each +exercise as you do it. </p> + +<p> 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, <strong>save your +work</strong> in a file before going on to the next exercise +even if you plan to duplicate some code. </p> + +<div class="instruction"> 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. </div> <!-- ============================== --> -<br style="page-break-after: always" /> -<h2>1. Static Invariants</h2> +<h2 class="newpage">1. Static Invariants</h2> <p> The easiest way to get started with AspectJ is to use it to enforce static invariants. </p> -<h3>a. Catch old tracing</h3> +<h3>1.a. Find old tracing</h3> -<p> <strong>Sample Exercise</strong>: 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. </p> +<div class="instruction"> <strong>Sample Exercise</strong>: 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. </div> <p> <strong>Task:</strong> Signal an error for calls to <code>System.out.println</code>. @@ -121,70 +179,69 @@ test. </p> <p> The way that we are all taught to print "hello world" from Java is to use <code>System.out.println()</code>, 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. </p> +<p> <strong>Answer:</strong> +</p> + +<pre> +package answers; + +import figures.*; + +aspect Answer1a { + declare error + : get(java.io.PrintStream System.out) && within(figures..*) + : "illegal access to System.out"; +} +</pre> + <p> When you use this on the given system, you'll find one incorrect trace in <code>SlothfulPoint</code>. </p> -<blockquote><PRE> +<pre> $ ajc -argfile base.lst ./figures/SlothfulPoint.java:38 illegal access to System.out 1 error -</PRE></blockquote> +</pre> -<p> Remove the illegal tracing call. -</p> +<p> Note that this answer does not say that the <em>call</em> to the +<code>println()</code> method is incorrect, rather, that the field get +of the <code>out</code> field is illegal. This will also catch those +users who bind System.out to a static field to save typing. </p> + +<p> After you have successfully used this aspect, edit your +program to remove the illegal tracing call. </p> <p> Make sure your program still passes the JUnit test <code>tests.Test</code> (which it should also pass at the beginning of all exercises) before continuing. </p> -<blockquote><PRE> +<pre> $ java tests.Test .... Time: 0.03 OK (4 tests) -</PRE></blockquote> - -<p> <strong>Answer:</strong> -</p> - -<blockquote><PRE> -package answers; - -import figures.*; - -aspect Answer1a { - declare error - : get(java.io.PrintStream System.out) && within(figures..*) - : "illegal access to System.out"; -} -</PRE></blockquote> - -<p> Note that this answer does not say that the <em>call</em> to the -<code>println()</code> method is incorrect, rather, that the field get -of the <code>out</code> field is illegal. This will also catch those -users who bind System.out to a static field to save typing. </p> - -<br style="page-break-after: always" /> +</pre> -<h3>b. Mandate setters</h3> +<h3 class="newpage">1.b. Mandate setters</h3> <p> <strong>Task:</strong> Signal a warning for assignments outside of setter methods. </p> <p> <strong>Tools:</strong> <code>set</code>, <code>withincode</code>, -signature <code>void set*(..)</code> +the <code>void set*(..)</code> pattern </p> -<p> 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. </p> +<p> 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. </p> <p> This is going to look like </p> @@ -200,19 +257,19 @@ outside of setter methods. "Outside", here, means that the code for the assignment is outside the <em>text</em> of the setter. <p> Make sure your program still passes the JUnit test -<code>tests.Test</code> before continuing. Make sure you get 11 +<code>tests.Test</code> before continuing. Make sure you get eleven warnings from this. Wait to fix them until the next exercise. </p> -<h3>c. Refine setters mandate</h3> +<h3>1.c. Refine setters mandate</h3> <p> <strong>Task:</strong> Allow assignmnents inside of constructors. </p> -<p> <strong>Tools:</strong> signature <code>new(..)</code> </p> +<p> <strong>Tools:</strong> the <code>new(..)</code> pattern</p> <p> 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 <em>or constructors</em>. Modify your answer to signal an actual error at compile time (rather than just a warning) when such an illegal assignment expression exists. </p> @@ -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:</p> -<PRE> +<pre> .\figures\Point.java:37 bad field set .\figures\Point.java:38 bad field set 2 errors -</PRE> +</pre> <p>Rewrite these two occurrences so as not to violate the convention. Make sure your program still passes the JUnit test <code>tests.Test</code> before continuing. </p> -<h3>d. Congratulations</h3> - -<p> 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. </p> +<div class="instruction"> 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. </div> <!-- ============================== --> -<br style="page-break-after: always" /> -<h2>2. Dynamic invariants</h2> +<h2 class="newpage">2. Dynamic invariants</h2> <p> The next step in AspectJ adoption is often to augment a test suite by including additional dynamic tests. </p> -<p> 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. </p> +<div class="instruction"> 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. </div> -<h3>a. Check a simple precondition</h3> +<h3>2.a. Check a simple precondition</h3> -<p> <strong>Sample Exercise</strong>: We've provided the answer to -this exercise below to get you started. </p> +<div class="instruction"> <strong>Sample Exercise</strong>: 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. </div> <p> <strong>Task:</strong> Pass <code>tests.Test2a</code>. </p> @@ -277,7 +335,7 @@ which wouldn't without your aspect. So before compiling in the aspect, </p> -<blockquote><PRE> +<pre> $ java tests.Test2a .F..F.... Time: 0.04 @@ -287,12 +345,12 @@ There were 2 failures: FAILURES!!! Tests run: 7, Failures: 2, Errors: 0 -</PRE></blockquote> +</pre> <p> But after compiling in the aspect... </p> -<blockquote><PRE> +<pre> $ ajc -argfile base.lst answers/Answer.java $ java tests.Test2a @@ -300,12 +358,12 @@ $ java tests.Test2a Time: 0.04 OK (7 tests) -</PRE></blockquote> +</pre> <p> <strong>Answer:</strong> </p> -<blockquote><PRE> +<pre> package answers; import figures.*; @@ -317,9 +375,9 @@ aspect Answer2a { } } } -</PRE></blockquote> +</pre> -<h3>b. Check another precondition</h3> +<h3>2.b. Check another precondition</h3> <p> <strong>Task:</strong> Pass <code>tests.Test2b</code>. </p> @@ -336,7 +394,7 @@ value. </p> <p> Look at <code>tests/Test2b.java</code> to see exactly what we're testing for. </p> -<h3>c. Check yet another precondition</h3> +<h3>2.c. Check yet another precondition</h3> <p> <strong>Task:</strong> Pass <code>tests.Test2c</code>. </p> @@ -354,7 +412,7 @@ an attempt is made to call <code>Group.add()</code> on a call. </p> -<h3>d. Assure input</h3> +<h3>2.d. Assure input</h3> <p> <strong>Task: </strong> Pass <code>tests.Test2d</code>. </p> @@ -381,8 +439,7 @@ aspect A { } </pre> -<br style="page-break-after: always" /> -<h3>e. Check a postcondition</h3> +<h3 class="newpage">2.e. Check a postcondition</h3> <p> <strong>Task: </strong> Pass <code>tests.Test2e</code> </p> @@ -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 <em>and</em> after the move, in one piece of advice. </p> -<h3>f. Check another postcondition</h3> +<h3>2.f. Check another postcondition</h3> <p> <strong>Task: </strong> Pass <code>tests.Test2f</code> </p> @@ -420,14 +477,13 @@ throw an <code>IllegalStateException</code> if it is violated. </p> <!-- ============================== --> -<br style="page-break-after: always" /> -<h2>3. Tracing</h2> +<h2 class="newpage">3. Tracing</h2> <p> Tracing is one of the classic AspectJ applications, and is often the first where AspectJ is used on deployed code. </p> -<h3>a. Simple logging</h3> +<h3>3.a. Simple logging</h3> <p> <strong>Task:</strong> Pass <code>tests.Test3a</code>.</p> @@ -441,7 +497,7 @@ in the figures package. To do this, use the utility class <code>Log</code> (with an import from <code>support.Log</code>) and call <code>Log.log(String)</code></p> -<h3>b. Exposing a value</h3> +<h3>3.b. Exposing a value</h3> <p> <strong>Task:</strong> Pass <code>tests.Test3b</code>.</p> @@ -453,12 +509,12 @@ In this exercise, you will print not only the join point information, but also the target object, with the form </p> -<blockquote><pre> +<pre> <em>thisJoinPointInfo</em> at <em>targetObject</em> -</pre></blockquote> +</pre> -<h3>c. More specialized logging</h3> +<h3>3.c. More specialized logging</h3> <p> <strong>Task:</strong> Pass <code>tests.Test3c</code>.</p> @@ -469,10 +525,10 @@ but also the target object, with the form group. The <code>args</code> pointcut allows you to select join points based on the type of a parameter to a method call. </p> -<p> Look at the test case for details about the tested log message. +<p> Look at the test case for details about the required log message. </p> -<h3>d. Logging extended to checking an invariant</h3> +<h3 class="newpage">3.d. Logging extended to checking an invariant</h3> <p> <strong>Task:</strong> Pass <code>tests.Test3d</code>.</p> @@ -483,43 +539,39 @@ based on the type of a parameter to a method call. </p> To do so, associate a boolean flag with each Point using an inter-type declaration, such as </p> -<blockquote><pre> +<pre> boolean Point.hasBeenAdded = false; -</pre></blockquote> +</pre> <p> Check and set this flag with the same kind of advice from your answer to problem (c). Throw an <code>IllegalStateException</code> if the point has already been added. </p> -<h3>e. Better error messages for 3d</h3> +<h3>3.e. Better error messages for 3.d.</h3> <p> <strong>Task:</strong> Pass <code>tests.Test3e</code>.</p> -<p> <strong>Tools:</strong> -</p> - <p> Extend your solution to problem (d) by using the string representation of the Point's containing group as the <code>msg</code> part of the <code>IllegalStateException</code>. </p> <!-- ============================== --> -<br style="page-break-after: always" /> -<h2>4. Caching</h2> +<h2 class="newpage">4. Caching</h2> <p> Computation of the bounding box of <code>Group</code> 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. </p> -<p> <strong>Optional</strong>: 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. -</p> +<div class="instruction"> <strong>Optional</strong>: 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. </div> -<h3>a. Make a constant override</h3> +<h3>4.a. Make a constant override</h3> <p> <strong>Task:</strong> Pass <code>tests.Test4a</code>.</p> @@ -540,7 +592,7 @@ by the static method <code>FigureElement.MAX_BOUNDS</code>. around advice intercepting the method. </p> -<h3>b. Make a constant cache</h3> +<h3>4.b. Make a constant cache</h3> <p> <strong>Task:</strong> Pass <code>tests.Test4b</code>. </p> @@ -559,7 +611,7 @@ call. </p> state for every <code>Group</code> object.</em> </p> -<h3>c. Invalidate, part 1</h3> +<h3>4.c. Invalidate, part 1</h3> <p> <strong>Task:</strong> Pass <code>tests.Test4c</code>. </p> @@ -573,8 +625,7 @@ Change your aspect so that it invalidates the cache whenever the <code>move()</code> method of <code>Group</code> is called. </p> -<br style="page-break-after: always" /> -<h3>d. Invalidate, part 2</h3> +<h3 class="newpage">4.d. Invalidate, part 2</h3> <p> <strong>Task:</strong> Pass <code>tests.Test4d</code>.</p> @@ -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. </p> -<h3>e. Invalidate, part 3</h3> +<h3>4.e. Invalidate, part 3</h3> <p> <strong>Task:</strong> Pass <code>tests.Test4e</code>.</p> @@ -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 <em>all</em> enclosing groups. </p> -<hr> +<div class="instruction"> + +<p> 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. </p> + +<p> You can find the current binaries, source, documentation and +an active user community for AspectJ at</p> + + <blockquote> + http://www.eclipse.org/aspectj + </blockquote> + +</div> + +<img style="newpage" src="figures_classes.gif" height="900" alt="" /> + </body> </html> |