Browse Source

revised section 4 (untested)

tags/V1_1_1
jhugunin 21 years ago
parent
commit
e81b7e76f0

+ 1
- 6
docs/teaching/exercises/answers/Answer4a.java View File

import java.awt.Rectangle; import java.awt.Rectangle;


aspect Answer4a { aspect Answer4a {
private Rectangle wholeCanvas =
new Rectangle(FigureElement.MIN_VALUE, FigureElement.MIN_VALUE,
FigureElement.MAX_VALUE - FigureElement.MIN_VALUE,
FigureElement.MAX_VALUE - FigureElement.MIN_VALUE);

Rectangle around(): execution(Rectangle Group.getBounds()) { Rectangle around(): execution(Rectangle Group.getBounds()) {
return wholeCanvas;
return FigureElement.MAX_BOUNDS;
} }
} }

+ 2
- 1
docs/teaching/exercises/answers/Answer4b.java View File

private Rectangle Group.cache = null; private Rectangle Group.cache = null;


Rectangle around(Group g): Rectangle around(Group g):
execution(Rectangle Group.getBounds()) && this(g) {
execution(Rectangle Group.getBounds()) && this(g)
{
if (g.cache == null) { if (g.cache == null) {
g.cache = proceed(g); g.cache = proceed(g);
} }

+ 2
- 1
docs/teaching/exercises/answers/Answer4c.java View File

private Rectangle Group.cache = null; private Rectangle Group.cache = null;


Rectangle around(Group g): Rectangle around(Group g):
execution(Rectangle Group.getBounds()) && this(g) {
execution(Rectangle Group.getBounds()) && this(g)
{
if (g.cache == null) { if (g.cache == null) {
g.cache = proceed(g); g.cache = proceed(g);
} }

+ 4
- 2
docs/teaching/exercises/answers/Answer4d.java View File

private Group Point.enclosingGroup = null; private Group Point.enclosingGroup = null;


before(Point p, Group g): before(Point p, Group g):
execution(void add(FigureElement)) && args(p) && target(g) {
execution(void add(FigureElement)) && args(p) && target(g)
{
p.enclosingGroup = g; p.enclosingGroup = g;
} }


Rectangle around(Group g): Rectangle around(Group g):
execution(Rectangle Group.getBounds()) && this(g) {
execution(Rectangle Group.getBounds()) && this(g)
{
if (g.cache == null) { if (g.cache == null) {
g.cache = proceed(g); g.cache = proceed(g);
} }

+ 4
- 2
docs/teaching/exercises/answers/Answer4e.java View File

private Group FigureElement.enclosingGroup = null; private Group FigureElement.enclosingGroup = null;


before(FigureElement p, Group g): before(FigureElement p, Group g):
execution(void add(FigureElement)) && args(p) && target(g) {
execution(void add(FigureElement)) && args(p) && target(g)
{
p.enclosingGroup = g; p.enclosingGroup = g;
} }


Rectangle around(Group g): Rectangle around(Group g):
execution(Rectangle Group.getBounds()) && this(g) {
execution(Rectangle Group.getBounds()) && this(g)
{
if (g.cache == null) { if (g.cache == null) {
g.cache = proceed(g); g.cache = proceed(g);
} }

+ 2
- 2
docs/teaching/exercises/figures/FigureElement.java View File

import java.awt.geom.*; import java.awt.geom.*;


public interface FigureElement { public interface FigureElement {
public static final int MIN_VALUE = 0;
public static final int MAX_VALUE = 500;
public static final Rectangle MAX_BOUNDS =
new Rectangle(0, 0, 500, 500);


public abstract void move(int dx, int dy); public abstract void move(int dx, int dy);



+ 26
- 42
docs/teaching/exercises/index.html View File



<h3>a. Make a constant override</h3> <h3>a. Make a constant override</h3>


<p> <strong>Problem:</strong> Pass <code>tests.Test4a</code>.</p>

<p> <strong>Tools:</strong> <code>around</code>,
<code>FigureElement.MAX_BOUNDS</code>
</p>

<p> <code>Group</code>'s <code>getBounds()</code> method could be <p> <code>Group</code>'s <code>getBounds()</code> method could be
understood to be a conservative approximation of the bounding box of a understood to be a conservative approximation of the bounding box of a
group. If that is true, then it would be a legal (and much faster) group. If that is true, then it would be a legal (and much faster)
implementation of <code>getBounds()</code> to simply always return a implementation of <code>getBounds()</code> to simply always return a
rectangle consisting of the entire canvas, that is
rectangle consisting of the entire canvas. The entire canvas is returned
by the static method <code>FigureElement.MAX_BOUNDS</code>.
</p> </p>


<blockquote><PRE>
new Rectangle(FigureElement.MIN_VALUE, FigureElement.MIN_VALUE,
FigureElement.MAX_VALUE - FigureElement.MIN_VALUE,
FigureElement.MAX_VALUE - FigureElement.MIN_VALUE)
</PRE></blockquote>

<p> Write an aspect to implement this change. You can override <p> Write an aspect to implement this change. You can override
<code>Group</code>'s <code>getBounds()</code> method entirely with <code>Group</code>'s <code>getBounds()</code> method entirely with
around advice intercepting the method. around advice intercepting the method.
</p> </p>


<p> Your code should pass the JUnit test case
<code>tests.Test4a</code> with this change.
</p>
<h3>b. Make a constant cache</h3>


<p> <strong>Answer: </strong>
<p> <strong>Problem:</strong> Pass <code>tests.Test4b</code>.
</p> </p>


<blockquote><PRE>
package answers;

import figures.*;
import java.awt.Rectangle;

aspect Answer4a {
private Rectangle wholeCanvas =
new Rectangle(FigureElement.MIN_VALUE, FigureElement.MIN_VALUE,
FigureElement.MAX_VALUE - FigureElement.MIN_VALUE,
FigureElement.MAX_VALUE - FigureElement.MIN_VALUE);

Rectangle around(): execution(Rectangle Group.getBounds()) {
return wholeCanvas;
}
}
</PRE></blockquote>

<h3>b. Make a constant cache</h3>
<p> <strong>Tools:</strong> <code>private Rectangle Group.mumble;</code>
</p>


<p> Instead of making the (very) conservative approximation of <p> Instead of making the (very) conservative approximation of
<code>getBounds()</code> from part (a), write an aspect instead that <code>getBounds()</code> from part (a), write an aspect instead that
<p> <em>Hint: You can use an inter-type declaration to keep some <p> <em>Hint: You can use an inter-type declaration to keep some
state for every <code>Group</code> object.</em> </p> state for every <code>Group</code> object.</em> </p>


<p> Your code should pass the JUnit test case
<code>tests.Test4b</code> with this change.
</p>



<h3>c. Invalidate, part 1</h3> <h3>c. Invalidate, part 1</h3>


<p> <strong>Problem:</strong> Pass <code>tests.Test4c</code>.
</p>

<p> <strong>Tools:</strong> <code>before</code>
</p>

<p> While caching in this way does save computation, it will lead to <p> While caching in this way does save computation, it will lead to
incorrect bounding boxes if a <code>Group</code> is ever moved. incorrect bounding boxes if a <code>Group</code> is ever moved.
Change your aspect so that it invalidates the cache whenever the Change your aspect so that it invalidates the cache whenever the
<code>move()</code> method of <code>Group</code> is called. <code>move()</code> method of <code>Group</code> is called.
</p> </p>


<p> Your code should pass the JUnit test case
<code>tests.Test4c</code> with this change.
</p>

<h3>d. Invalidate, part 2</h3> <h3>d. Invalidate, part 2</h3>


<p> <strong>Problem:</strong> Pass <code>tests.Test4d</code>.</p>

<p> <strong>Tools:</strong> <code>your solution to 3c</code></p>

<p> Of course, part (c) didn't really solve the problem. What if a <p> Of course, part (c) didn't really solve the problem. What if a
<code>Point</code> that is part of a <code>Group</code> moves? <code>Point</code> that is part of a <code>Group</code> moves?
Whenever either of a Point's fields are set it should invalidate the Whenever either of a Point's fields are set it should invalidate the
slightly different than the problem in 3c: Here you care about fields, slightly different than the problem in 3c: Here you care about fields,
where there you cared about method calls. </p> where there you cared about method calls. </p>


<p> Your code should pass the JUnit test case
<code>tests.Test4d</code> with this change.
</p>

<h3>e. Invalidate, part 3</h3> <h3>e. Invalidate, part 3</h3>


<p> <strong>Problem:</strong> Pass <code>tests.Test4e</code>.</p>

<p> <strong>Tools:</strong> <em>You're on you're own</em></p>

<p> Did you really do part (d) correctly? Run the JUnit test <p> Did you really do part (d) correctly? Run the JUnit test
<code>tests.Test4e</code> to see. If you pass, congratulations, now <code>tests.Test4e</code> to see. If you pass, congratulations, now
go help other people. Otherwise, you have fallen prey to our cruel go help other people. Otherwise, you have fallen prey to our cruel

+ 1
- 0
docs/teaching/exercises/tests/Test.java View File



public class Test extends TestCase { public class Test extends TestCase {
public Test(String name) { super(name); } public Test(String name) { super(name); }
public Test() {}


public static void main(String[] args) { public static void main(String[] args) {
junit.textui.TestRunner.run(Test.class); junit.textui.TestRunner.run(Test.class);

+ 1
- 11
docs/teaching/exercises/tests/Test4a.java View File

import junit.framework.*; import junit.framework.*;


public class Test4a extends Test { public class Test4a extends Test {
Rectangle wholeCanvas =
new Rectangle(FigureElement.MIN_VALUE, FigureElement.MIN_VALUE,
FigureElement.MAX_VALUE, FigureElement.MAX_VALUE);

public Test4a(String name) { super(name); }

public static void main(String[] args) { public static void main(String[] args) {
junit.textui.TestRunner.run(Test4a.class); junit.textui.TestRunner.run(Test4a.class);
} }


public void setUp() {
super.setUp();
}

public void testGroupBounds() { public void testGroupBounds() {
assertEquals(g.getBounds(), wholeCanvas);
assertEquals(g.getBounds(), FigureElement.MAX_BOUNDS);
} }
} }

+ 2
- 12
docs/teaching/exercises/tests/Test4b.java View File

import junit.framework.*; import junit.framework.*;


public class Test4b extends Test { public class Test4b extends Test {

public Test4b(String name) { super(name); }

public static void main(String[] args) { public static void main(String[] args) {
junit.textui.TestRunner.run(Test4b.class); junit.textui.TestRunner.run(Test4b.class);
} }


public void setUp() {
super.setUp();
}

public void testBasicEquality() { public void testBasicEquality() {
assertTrue(g.getBounds() == g.getBounds()); assertTrue(g.getBounds() == g.getBounds());
} }


public void testNotWholeCanvas() { public void testNotWholeCanvas() {
assertTrue("bounds for this group should not be the whole canvas", assertTrue("bounds for this group should not be the whole canvas",
g.getBounds().getWidth() <
(FigureElement.MAX_VALUE - FigureElement.MIN_VALUE));
g.getBounds().getWidth() < FigureElement.MAX_BOUNDS.getWidth());
assertTrue("bounds for this group should not be the whole canvas", assertTrue("bounds for this group should not be the whole canvas",
g.getBounds().getHeight() <
(FigureElement.MAX_VALUE - FigureElement.MIN_VALUE));

g.getBounds().getHeight() < FigureElement.MAX_BOUNDS.getHeight());
} }
} }



+ 0
- 7
docs/teaching/exercises/tests/Test4c.java View File

import junit.framework.*; import junit.framework.*;


public class Test4c extends Test { public class Test4c extends Test {

public Test4c(String name) { super(name); }

public static void main(String[] args) { public static void main(String[] args) {
junit.textui.TestRunner.run(Test4c.class); junit.textui.TestRunner.run(Test4c.class);
} }


public void setUp() {
super.setUp();
}

public void testBasicEquality() { public void testBasicEquality() {
assertTrue(g.getBounds() == g.getBounds()); assertTrue(g.getBounds() == g.getBounds());
} }

+ 0
- 4
docs/teaching/exercises/tests/Test4d.java View File

junit.textui.TestRunner.run(Test4d.class); junit.textui.TestRunner.run(Test4d.class);
} }


public void setUp() {
super.setUp();
}

public void testBasicEquality() { public void testBasicEquality() {
assertTrue(g.getBounds() == g.getBounds()); assertTrue(g.getBounds() == g.getBounds());
} }

+ 0
- 4
docs/teaching/exercises/tests/Test4e.java View File

junit.textui.TestRunner.run(Test4e.class); junit.textui.TestRunner.run(Test4e.class);
} }


public void setUp() {
super.setUp();
}

public void testBasicEquality() { public void testBasicEquality() {
assertTrue(g.getBounds() == g.getBounds()); assertTrue(g.getBounds() == g.getBounds());
} }

Loading…
Cancel
Save