Are you really using JUnit during your development?

View: New views
20 Messages — Rating Filter:   Alert me  
< Prev | 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - 15 | Next >

Re: Re: Test-friendly, but not caller-friendly?

by Elliotte Harold :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Robert Martin wrote:

> Sorry, sometimes I forget about Java's dumb rules about where you can  
> have static methods and where you can't.  Anyway, this works in Java  
> and amounts to the same thing:
>
> interface Document extends Cloneable {
>    public static Document prototype = null;
>    ...
> }
>
> Document doc = Document.prototype.clone();
>
> Make sure "main" sets the Document.prototype variable to the  
> prototypical Document derivative.

You actually need

try {
   Document doc = (Document) Document.prototype.clone();
   // ...
}
catch (CloneNotSupportedException ex) {
   throw new RuntimeException(ex);
}


Adding that to the need to set the prototype variable somewhere else in
the code, I still think the simple constructor is significantly simpler
and thus preferable.

--
Elliotte Rusty Harold  elharo@...
Java I/O 2nd Edition Just Published!
http://www.cafeaulait.org/books/javaio2/
http://www.amazon.com/exec/obidos/ISBN=0596527500/ref=nosim/cafeaulaitA/


 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/junit/

<*> To unsubscribe from this group, send an email to:
    junit-unsubscribe@...

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/
 




Re: Re: Test-friendly, but not caller-friendly?

by Elliotte Harold :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Robert Martin wrote:

> So check for those preconditions and invariants if you must.  And  
> then write unit tests that make sure your code works as you expect,  
> including that it detects the faulty preconditions and invariants.

Absolutely. Much better than sticking my head in the sand and pretending
  the preconditions will never be violated, and it's not my fault what
happens if they are.

A side note: when you write code for checking preconditions, code
coverage tools like Cobertura will usually alert you if you've forgotten
to test one. (Yes, I know we should have written the test first, but
we're all imperfect and sometimes miss a case.) if there's no code to
test the precondition, there's also no warning that you've forgotten to
write the test for it.

--
Elliotte Rusty Harold  elharo@...
Java I/O 2nd Edition Just Published!
http://www.cafeaulait.org/books/javaio2/
http://www.amazon.com/exec/obidos/ISBN=0596527500/ref=nosim/cafeaulaitA/


 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/junit/

<*> To unsubscribe from this group, send an email to:
    junit-unsubscribe@...

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/
 




Parent Message unknown RE: Re: Test-friendly, but not caller-friendly?

by Antti Karanta :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


> > Document doc = Document.prototype.clone();
> >
> > Make sure "main" sets the Document.prototype variable to the  
> > prototypical Document derivative.
>
> You actually need
>
> try {
>    Document doc = (Document) Document.prototype.clone();
>    // ...
> }
> catch (CloneNotSupportedException ex) {
>    throw new RuntimeException(ex);
> }

  No, the original is correct (if we are talking Java5 or above):

  Java5 (finally) introduced covariant return types, so clone() in
sublclass of Object may return something more specific than Object, in
the case of clone() the class itself is used as the return type.

  The overriding method may declare to throw less exceptions than the
overridden method, thus the clone() method in subclass of Object does
not usually declare to throw CloneNotSupportedException.



     -Antti-




 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/junit/

<*> To unsubscribe from this group, send an email to:
    junit-unsubscribe@...

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/
 



Re: Re: Test-friendly, but not caller-friendly?

by Elliotte Harold :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Antti Karanta wrote:

>   No, the original is correct (if we are talking Java5 or above):
>
>   Java5 (finally) introduced covariant return types, so clone() in
> sublclass of Object may return something more specific than Object, in
> the case of clone() the class itself is used as the return type.
>
>   The overriding method may declare to throw less exceptions than the
> overridden method, thus the clone() method in subclass of Object does
> not usually declare to throw CloneNotSupportedException.

Interesting. I didn't know that. It seems a useful addition to the Java
language. However I'm still working in a world where Java 1.4 is a
necessity, so it's not immediately practical; but it does make me more
likely to consider Java 5 in the future, much more so than the more
hyped features like generics and autoboxing.

--
Elliotte Rusty Harold  elharo@...
Java I/O 2nd Edition Just Published!
http://www.cafeaulait.org/books/javaio2/
http://www.amazon.com/exec/obidos/ISBN=0596527500/ref=nosim/cafeaulaitA/


 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/junit/

<*> To unsubscribe from this group, send an email to:
    junit-unsubscribe@...

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/
 




Parent Message unknown Re: Test-friendly, but not caller-friendly?

by unclebob :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


> On 9/4/06, Robert Martin <UncleBob@...> wrote:
> >
> >
> > > That's not what I was saying. If you use the Interface Segregation
> > > Principle, you can't pass an IAccount2 to someone expecting an
> > > IAccount.
> > >
> > > Which makes this principle fairly useless in my opinion...
> >
> > You can, if the object you are passing derives from both IAccount  
> and
> > IAccount2...
>
> Sure, but the client code won't be able to do that since it was  
> written
> before IAccount2 was released.

If you want to call the new method that's in IAccount2 then you'll  
have to modify the client code anyway.  If you don't want to call the  
new method provided by IAccount2 then there is no need to change the  
client.


----
Robert C. Martin (Uncle Bob)  | email: unclebob@...
Object Mentor Inc.            | blog:  www.butunclebob.com
The Agile Transition Experts  | web:   www.objectmentor.com
800-338-6716                  |






[Non-text portions of this message have been removed]



 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/junit/

<*> To unsubscribe from this group, send an email to:
    junit-unsubscribe@...

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/
 




Parent Message unknown Re: Test-friendly, but not caller-friendly?

by unclebob :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


> You actually need
>
> try {
> Document doc = (Document) Document.prototype.clone();
> // ...
> }
> catch (CloneNotSupportedException ex) {
> throw new RuntimeException(ex);
> }

I'll leave it to you as an exercise to find a way to eliminate the  
need for the try/catch.  ;-)

>
> Adding that to the need to set the prototype variable somewhere  
> else in
> the code, I still think the simple constructor is significantly  
> simpler
> and thus preferable.

A simple constructor is the easiest.  However, as the system starts  
to get complicated those simple constructors sometimes become  
complications because of the need to have mocks for unit tests. Later  
they become even greater complications because of the need to break  
or invert dependencies between modules.

This does not mean that you should avoid all simple constructors.  
That would be silly and pointless.  What it does mean is that all  
programmers should be adept at the various techniques for quickly  
converting from simple constructors to simple polymorphic  
constructors.  It also means that all programmers should understand  
the issues of intermodule dependencies and how to manage them (which  
is what OO is really all about).


----
Robert C. Martin (Uncle Bob)  | email: unclebob@...
Object Mentor Inc.            | blog:  www.butunclebob.com
The Agile Transition Experts  | web:   www.objectmentor.com
800-338-6716                  |






[Non-text portions of this message have been removed]



 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/junit/

<*> To unsubscribe from this group, send an email to:
    junit-unsubscribe@...

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/
 




Parent Message unknown Re: Test-friendly, but not caller-friendly?

by unclebob :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


> Robert Martin wrote:
>
> > So check for those preconditions and invariants if you must. And
> > then write unit tests that make sure your code works as you expect,
> > including that it detects the faulty preconditions and invariants.
>
> Absolutely. Much better than sticking my head in the sand and  
> pretending
> the preconditions will never be violated, and it's not my fault what
> happens if they are.

Certainly.  Sticking your head in the sand is irresponsible.

So, to sum up.  If you are building a library for other people to  
call, then you should write unit tests for that library, complete  
with unit tests for all the exceptions that your library will throw  
because of violated preconditions.  These unit tests will provide  
part of the documentation that will help your callers avoid those  
exceptions.

>
> A side note: when you write code for checking preconditions, code
> coverage tools like Cobertura will usually alert you if you've  
> forgotten
> to test one. (Yes, I know we should have written the test first, but
> we're all imperfect and sometimes miss a case.) if there's no code to
> test the precondition, there's also no warning that you've  
> forgotten to
> write the test for it.

Agreed.  I use Clover myself, but Cobertura looks pretty good.  
Employing code coverage tools is an important part of any testing  
strategy because, as you say, even test-firsters can't think of every  
test case.  Ensuring your code is covered with tests is simply part  
of every professional programmer's daily job.


----
Robert C. Martin (Uncle Bob)  | email: unclebob@...
Object Mentor Inc.            | blog:  www.butunclebob.com
The Agile Transition Experts  | web:   www.objectmentor.com
800-338-6716                  |






[Non-text portions of this message have been removed]



 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/junit/

<*> To unsubscribe from this group, send an email to:
    junit-unsubscribe@...

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/
 




Re: Re: Test-friendly, but not caller-friendly?

by Elliotte Harold :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Robert Martin wrote:

> A simple constructor is the easiest.  However, as the system starts  
> to get complicated those simple constructors sometimes become  
> complications because of the need to have mocks for unit tests. Later  
> they become even greater complications because of the need to break  
> or invert dependencies between modules.

At such point as that becomes a real problem, I'm willing to refactor to
accomplish this. However in my experience most classes are not reused,
most do not need to be mocked, most do not need to be decoupled, and
very few classes need multiple implementations.

My objection is not to using these techniques in the rare cases where
it's actually necessary. My objection is to starting by assuming that
the simplest thing (concrete classes with constructors) can't possibly
work, and jumping straight into the deep end every time.

If you need it, fine; but more likely than not you don't. YAGNI isn't
just about features. It's also about programming techniques. Additional
layers of indirection are powerful problem solvers; but they are also
powerful obfuscators. They should not be introduced gratuitously just
because they might be useful to someone some day.

--
Elliotte Rusty Harold  elharo@...
Java I/O 2nd Edition Just Published!
http://www.cafeaulait.org/books/javaio2/
http://www.amazon.com/exec/obidos/ISBN=0596527500/ref=nosim/cafeaulaitA/


 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/junit/

<*> To unsubscribe from this group, send an email to:
    junit-unsubscribe@...

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/
 



Re: Re: Test-friendly, but not caller-friendly?

by Michael Feathers :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Elliotte Harold wrote:

>Michael Feathers wrote:
>  
>
>>The sneaky thing about DbC is that if you want to use its assertions
>>essentially as tests you have to exercise your code.  It's not just a
>>matter of writing the assertions.  When you test, the code that you
>>write is the exercising code, and you can test both clients and
>>providers.  Not saying that DbC is bad, just that I wouldn't want to
>>rely on its assertion mechanism rather than tests.  
>>    
>>
>
>One of the things I write unit tests for is the proper behavior of the
>methods in the face of a precondition violation. (Usually that's
>throwing an exception.)
>
>  
>
>>On the other hand, I
>>feel oddly comfortable writing code with lots of tests and no embedded
>>DbC constructs.
>>    
>>
>
>You're perhaps not worrying about other programmers using your code with
>no tests, or other programmers trying to break your security and do bad
>things with your code. I am quite uncomfortable thinking about such
>things. That's why I check my preconditions rigorously.
>  
>
Again, this comes down to the difference between API code and
application code.  At the API level, it often makes sense to do more
checking.  Internally, tests and clear code can be sufficient.

Michael Feathers
www.objectmentor.com



 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/junit/

<*> To unsubscribe from this group, send an email to:
    junit-unsubscribe@...

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/
 




Re: Re: Test-friendly, but not caller-friendly?

by Michael Feathers :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Robert Martin wrote:

>>On 9/4/06, Robert Martin <UncleBob@...> wrote:
>>    
>>
>>>      
>>>
>>>>That's not what I was saying. If you use the Interface Segregation
>>>>Principle, you can't pass an IAccount2 to someone expecting an
>>>>IAccount.
>>>>
>>>>Which makes this principle fairly useless in my opinion...
>>>>        
>>>>
>>>You can, if the object you are passing derives from both IAccount  
>>>      
>>>
>>and
>>    
>>
>>>IAccount2...
>>>      
>>>
>>Sure, but the client code won't be able to do that since it was  
>>written
>>before IAccount2 was released.
>>    
>>
>
>If you want to call the new method that's in IAccount2 then you'll  
>have to modify the client code anyway.  If you don't want to call the  
>new method provided by IAccount2 then there is no need to change the  
>client.
>  
>
Yes, it's a lot like the Extension Object Pattern that way.

Michael Feathers
www.objectmentor.com



 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/junit/

<*> To unsubscribe from this group, send an email to:
    junit-unsubscribe@...

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/
 




Re: Re: Test-friendly, but not caller-friendly?

by Cédric Beust ♔ :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On 9/5/06, Robert Martin <UncleBob@...> wrote:
>
> If you want to call the new method that's in IAccount2 then you'll
> have to modify the client code anyway.  If you don't want to call the
> new method provided by IAccount2 then there is no need to change the
> client.


It seems we're talking past each other...

I have a client that uses IAccount.  I release an extension of IAccount
called IAccount2, that has a few extra methods, but I want to be able to
pass these IAccount2 objects to clients that expect IAccount, and the only
way to do this is to have IAccount2 extend IAccount.

Which is why I was saying that since the Interface Segregation Principle
doesn't respect the is-a relationship, it's of little help for upgrade
problems, and the technique that I described in my initial message was the
only viable way to add methods to existing interfaces without breaking
clients.

--
Cédric
http://testng.org


[Non-text portions of this message have been removed]



 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/junit/

<*> To unsubscribe from this group, send an email to:
    junit-unsubscribe@...

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/
 



Re: Test-friendly, but not caller-friendly?

by J. B. Rainsberger :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Elliotte Harold wrote:

> J. B. Rainsberger wrote:
>
>  > JDBC consists of a generic API, mostly interfaces, and vendors implement
>  > those interfaces. The idea is that, at least in the broad strokes,
>  > different JDBC drivers implement the same basic concepts the same way
>  > (setting prepared statement parameters, getting connections, that kind
>  > of thing... differences in SQL are another story altogether).
>
> JDBC is one of the rare cases where interfaces do make sense because
> there really are multiple independent implementations, and the same code
> may even need to work against more than one of them over time.
> Supporting this flexibility doesn't come without severe costs, but in
> the case of JDBC I think those costs are worth paying. This is really
> the classic example to demonstrate why we need interfaces.
>
> However, far too commonly people extrapolate from JDBC and similar
> examples to use cases where interfaces simply don't make sense. The vast
> majority of code and classes never needs more than a single
> implementation. The division of code into separate modules for interface
> and implementation is needless abstraction most of the time. The costs
> are high, and very little if any benefit is achieved.
>
> Interfaces are a special purpose solution for a few uncommon but
> important use cases. They are not the first thing you should pull out of
> your toolbox. They should not be the default way you design a class
> absent an obvious need.

This is one of those interested cases where we /each/ can say the following:

"Your argument is sound, and the theory is plausible, but my experience
says the opposite is true."

In your case, you have experience with over-designing with interfaces,
so you tend to avoid them. In my case, I have experience with slow and
complicated testing without interface, so I tend to use them.

The only statement you make that I wouldn't make is "The costs are high,
and very little if any benefit is achieved". I achieve considerable
benefit from interfaces, as my tests become smaller, simpler and faster,
so I write more of them and run them more frequently. This gives me the
feedback I want to know my code works. That is the benefit I gain from
pushing the abstraction line further than it might strictly need to go.
--
J. B. (Joe) Rainsberger :: http://www.jbrains.ca
Your guide to software craftsmanship
JUnit Recipes: Practical Methods for Programmer Testing
2005 Gordon Pask Award for contribution Agile Software Practice


 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/junit/

<*> To unsubscribe from this group, send an email to:
    junit-unsubscribe@...

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/
 



Re: Test-friendly, but not caller-friendly?

by J. B. Rainsberger :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Elliotte Harold wrote:

> Michael Feathers wrote:
>
>  > Elliotte, what are the downsides of interfaces, in your opinion? I know
>  > you don't like to use them as much as many other people do, but I don't
>  > know why.
>
> 1. Excess complexity

/More/ complexity in the production code, with /less/ complexity in the
tests.

> 2. No precondition, postcondition, or class invariant validation

I use Contract Tests for that.

> 3. Cannot add new methods to an existing interface in a later version
> without breaking all existing code

This is true. Since this isn't a problem for me, I assume it's endemic
to a particular kind of work, such as publishing reusable interfaces. I
just don't get to do much of that.
--
J. B. (Joe) Rainsberger :: http://www.jbrains.ca
Your guide to software craftsmanship
JUnit Recipes: Practical Methods for Programmer Testing
2005 Gordon Pask Award for contribution Agile Software Practice


 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/junit/

<*> To unsubscribe from this group, send an email to:
    junit-unsubscribe@...

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/
 



Are interfaces unnecessarily complex? (Relates to design-for-testability)

by J. B. Rainsberger :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Elliotte Harold wrote:

> Robert Martin wrote:
>  >>> Elliotte, what are the downsides of interfaces, in your opinion?
>  >> 1. Excess complexity
>  >
>  > They make receiving a message more complex, it's true. They make
>  > sending a message much simpler. Or rather, they add more lines of
>  > code on the receiving side; but they eliminate dependencies on the
>  > sending side. The benefit of those eliminated dependencies is very
>  > powerful.
>
> I'm not sure I believe the second part. In practice, replacing a
> concrete-class based solution with an interface-based solution expands
> the complexity for the caller. What used to require a single class now
> typically requires three: a factory to create the factory, the factory
> itself, and the interface you're actually trying to create. I'm not sure
> you really need all that, but you need at least two pieces where you
> previously needed one, and in practice three is what we usually seem to
> end up with. (Think of DocumentBuilderFactory, DocumentBuilder, and
> Document in JAXP/DOM for example). And of course there are still
> concrete classes for each of these. We've turned what could have been
> one concrete class (Document) into six separate pieces! What could have
> been this:
>
> Document doc = new Document();
>
> is now this:
>
> DocumentBuilderFactory factory = DocumentBuilderFactory.getInstance();
> DocumentBuilder builder = factory.newDocumentBuilder();
> Document doc = builder.newDocument();

Be careful! The Builder pattern is by no means needed to create an
instance of an interface. JAXP/DOM combines, for whatever reason, the
Singleton, Abstract Factory and Builder pattern, when all you really
need is this:

     Document document = new WritableDocument();

I could see using the Builder pattern to simplify the interface for
constructing a document, separating creating a document from reading it,
but by no means does JAXP/DOM do what it does because of /interfaces/.

It's true that if you have a bunch of related interfaces (like in a GUI
toolkit), you might want an Abstract Factory, but neither Singleton nor
Builder enter the picture just because you have interfaces.

> I fail to see how that's simpler.

It's not, and interfaces didn't make it more complex: the Singleton,
Abstract Factory and Builder patterns did. If this is a representative
example of why you find interfaces unnecessarily complex, then I really
believe you're blaming the wrong part of the design.

Take care.
--
J. B. (Joe) Rainsberger :: http://www.jbrains.ca
Your guide to software craftsmanship
JUnit Recipes: Practical Methods for Programmer Testing
2005 Gordon Pask Award for contribution Agile Software Practice



 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/junit/

<*> To unsubscribe from this group, send an email to:
    junit-unsubscribe@...

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/
 



Re: Re: Test-friendly, but not caller-friendly?

by J. B. Rainsberger :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Elliotte Harold wrote:

> http://www.cafeconleche.org/XOM/designprinciples.xhtml#d0e161 
> <http://www.cafeconleche.org/XOM/designprinciples.xhtml#d0e161>

I tried, but there is plain text at the top of the file (before the
preamble), so neither of my browsers will render it.
--
J. B. (Joe) Rainsberger :: http://www.jbrains.ca
Your guide to software craftsmanship
JUnit Recipes: Practical Methods for Programmer Testing
2005 Gordon Pask Award for contribution Agile Software Practice



 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/junit/

<*> To unsubscribe from this group, send an email to:
    junit-unsubscribe@...

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/
 




Re: Re: Test-friendly, but not caller-friendly?

by J. B. Rainsberger :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Michael Feathers wrote:
> But back to your original point: "It might sometimes be a
> NullPointerException or something else instead, but advertising a
> precondition is not an excuse for misbehavior just because you receive
> bad data." Under DbC, it is. Fact is, if your precondition fails or you
> get a NullPointerException, there's a bug in the client. You can have
> checking enabled, or not, but checking is not error handling. The point
> of DbC is to build software robust enough so that you don't have to
> write error handling code at each level. Relevant section is 11.6
> "Assertions are not an input checking mechanism."

Indeed. If I violate your precondition, then I am writing defective
code. There are a few remedies:

1. Be nice and tolerate my indiscretion, say by substituting sensible
default values and continuing.

2. Telling me directly, "You shouldn't do that," by throwing a specific
exception that explains my mistake.

3. Telling me indirectly, by failing is some deterministic, by
non-obvious way.

4. Providing me examples of how not to violate your precondition.

5. Documenting the precondition and warning me that violating it leads
to "undefined behavior".

6. Providing Contract Tests that I can inherit to help me know that my
code won't violate your precondition.

There are others, I'm sure.

It looks as though you reject #5 out of hand, and I agree, but all the
others are viable choices. I would choose the one providing the best ROI
for the situation. In a language that checks preconditions for me, I
would get #2 for free. In Java, which doesn't, it depends on the cost of
violating the precondition. If it's anything like persistent data
corruption all the way up to loss of life, I would probably insist on
#2. If it's nothing worse than having to retry one of a batch of
transactions, I might go with #1. Still, I would probably insist on #4
and prefer #6.
--
J. B. (Joe) Rainsberger :: http://www.jbrains.ca
Your guide to software craftsmanship
JUnit Recipes: Practical Methods for Programmer Testing
2005 Gordon Pask Award for contribution Agile Software Practice




 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/junit/

<*> To unsubscribe from this group, send an email to:
    junit-unsubscribe@...

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/
 




Re: Test-friendly, but not caller-friendly?

by Dean Wampler :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I'm the author of Contract4J. Here's my perspective.

To be quite honest, I use TDD far more than DbC these days. They
overlap enough in terms of what they do and TDD has enough advantages
that I only use DbC when I'm in a situation where testing, and
implicitly defining the contract with automated tests, is hard. The
last time this really happened was a few years ago while working on an
EJB v2 application. Before TDD, I used DbC and was very successful
with it. One thing I particularly like about DbC is that it explicitly
states information that is more implicit, in unit tests, but which is
no less essetially to clients.

That EJB project was before I wrote Contract4J, so why did I bother?
Well, I know that many people still use DbC and AspectJ is a natural
and powerful tool to implement it. (I may extend the framework for
other "metaprogramming-like" purposes later....)

But, is the contract a "cross-cutting concern"? Doesn't it have to be
to use AspectJ?? DbC is an interesting "grey-area" example. The
contract is most definitely an integral part of a component; how can
you use the component without understanding the requirements on inputs
and expected outputs? However, you can argue (perhaps weakly ;^) that
how you *exploit* the contract is the crosscutting part. In the case
of C4J, it's an *enforcement* tool. You could also imagine other tools
that use the contract for other purposes, e.g., an IDE that enhances
code completion with contract information. Okay, maybe this argument
is splitting hairs, but I'm more interested in practicalities than
theory anyway. So sue me. ;)

Here's a funny thing about Cedric's comment about aspects only being
useful for reuse scenarios; the actual aspects in C4J are very
generic; all the unique contract stuff is in the user annotations.

Among its many limitations, most reflect limitations of Java itself.
(I prefer Ruby these days...) Cedric is correct about some of the
limitations; especially the fact that tests are written as strings and
aren't compiled until runtime interpretation. I made that choice so I
could use annotations and I chose annotations to (i) separate out the
contract code from the "business logic" and (ii) get the contract into
the method and class signatures that you would see in Javadoc output.

Believe me, it was a big design pain doing runtime interpretation and
the majority of the Contract4J unit tests (yes, it's tested with
junit) have something or other to do with testing the expression
evaluation.

The performance is also not great, as you might expect, but this is
not a serious issue most of the time, IMHO, as the contracts are
usually only enabled during the testing process.

Finally, if you really have a huge contract expression, I suspect you
need to refactor an overly-complicated class or method. If not, then
go ahead and write an "isValid()" method as regular Java and call it
in the contract.

dean
 

--- In junit@..., "Cédric Beust â™" " <cbeust@...> wrote:
>
> One more thought:  I don't think AOP is the right tool for this job.
>
> AOP helps you when the same concerns are crosscutting your code and
can be
> factored out.  In the case of pre/postconditions or invariants, each of
> these will be fairly unique to the method they apply to, so there is
little
> reuse going on, and therefore, little point in capturing them in aspects
> (which this tool doesn't seem to do, by the way, since they are
captured in

> a string).
>
> --
> Cedric
>
>
> On 9/4/06, Cédric Beust â™" <cbeust@...> wrote:
> >
> >
> >
> > On 9/4/06, Ray V <ttftestrayv@...> wrote:
> > >
> > > I wonder what you guys think of Contract4J:
> > >
http://www.contract4j.org/contract4j<http://www.google.com/url?sa=D&q=http%3A%2F%2Fwww.contract4j.org%2Fcontract4j>

> > >
> > > It combines an annotation based design by contract
> > > approach with the "fail fast" philosophy, and can be
> > > turned off (like assertions) when it's time to deploy.
> > >
> > >
> > > It seems very complimentary to unit testing, and would
> > > help in doing less defensive programming.  I've been
> > > curious about this tool for a while, but have yet to
> > > use it myself on a real project.
> >
> >
> > Based on the example on the Web site, it seems to me it's the
wrong way to
> > solve the problem.
> >
> > The example is basically moving asserts inside the method into a
string
> > inside an annotation.  By doing that, you lose type checking, you
lose IDE
> > assistance, you lose highlighting and you lose refactoring
capabilities.
> >
> > I also wonder how well it scales when your preconditions or
postconditions
> > need to span ten lines, or when you want to intersperse them
in-between
> > several lines inside your method.
> >
> > These reasons are exactly why I think Design by Contract simply
doesn't
> > work:  either your DBC tests are small enough to fit in one-line
assertions
> > (which can be optimized away by the compiler) or they are fairly
complex and
> > better captured in tests.
> >
> > --
> > Cédric
> >
http://testng.org<http://www.google.com/url?sa=D&q=http%3A%2F%2Ftestng.org>

> >
> >
>
>
> --
> Cédric
>
>
> [Non-text portions of this message have been removed]
>










 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/junit/

<*> To unsubscribe from this group, send an email to:
    junit-unsubscribe@...

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/
 



Re: Re: Test-friendly, but not caller-friendly?

by Michael Feathers :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

J. B. Rainsberger wrote:

>Michael Feathers wrote:
>  
>
>>But back to your original point: "It might sometimes be a
>>NullPointerException or something else instead, but advertising a
>>precondition is not an excuse for misbehavior just because you receive
>>bad data." Under DbC, it is. Fact is, if your precondition fails or you
>>get a NullPointerException, there's a bug in the client. You can have
>>checking enabled, or not, but checking is not error handling. The point
>>of DbC is to build software robust enough so that you don't have to
>>write error handling code at each level. Relevant section is 11.6
>>"Assertions are not an input checking mechanism."
>>    
>>
>
>Indeed. If I violate your precondition, then I am writing defective
>code. There are a few remedies:
>
>1. Be nice and tolerate my indiscretion, say by substituting sensible
>default values and continuing.
>
>2. Telling me directly, "You shouldn't do that," by throwing a specific
>exception that explains my mistake.
>
>3. Telling me indirectly, by failing is some deterministic, by
>non-obvious way.
>
>4. Providing me examples of how not to violate your precondition.
>
>5. Documenting the precondition and warning me that violating it leads
>to "undefined behavior".
>
>6. Providing Contract Tests that I can inherit to help me know that my
>code won't violate your precondition.
>
>There are others, I'm sure.
>
>It looks as though you reject #5 out of hand, and I agree, but all the
>others are viable choices. I would choose the one providing the best ROI
>for the situation. In a language that checks preconditions for me, I
>would get #2 for free. In Java, which doesn't, it depends on the cost of
>violating the precondition. If it's anything like persistent data
>corruption all the way up to loss of life, I would probably insist on
>#2. If it's nothing worse than having to retry one of a batch of
>transactions, I might go with #1. Still, I would probably insist on #4
>and prefer #6.
>  
>
Joe,

I'll answer this assuming that you're talking about API code, not
application code.  If that's not the case, let me know.

In some systems #1 is the best answer, but those situations are rare
and, as a strategy, it can lead to misunderstandings..  #2 and #4 are
great strategies and I like #6 as well.

I think it's interesting to talk about #5, though.    In nearly every
other area of life, we deal with warranties and license agreements in
which we explicitly assume responsibility for our use of products and
services.  In software we often try to protect clients from themselves
and don't consider notice a fair grant of responsibility.

The fact is, it isn't universally true.  Lots of luck having Win32 save
you from violations of its preconditions, for instance. :-)

Frankly, I wouldn't want to have only #5 at the API level, but I think
that this tendency we have to believe that we can not have an agreement
with users that is not enforced by code leads to a great deal of
trouble. Particularly in the area of visibility.. many developers assume
that no written agreement can be sufficient if something is made
public.  I think that the issue is that we are not used to thinking
about agreements beyond the code and we're not used to holding people to
them.

There are some exceptions.  One is the Eclipse API Rules of Engagement:
http://www.eclipse.org/articles/Article-API%20use/eclipse-api-usage-rules.html

It's a contract above the code and it has some great ideas.  I really
like the idea of "soft final" for instance.  It's like a license
agreement.. you can do this (subclass and override, etc) and we won't
prevent you, but if you break the rules we can't be responsible for you.

Michael Feathers
www.objectmentor.com






 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/junit/

<*> To unsubscribe from this group, send an email to:
    junit-unsubscribe@...

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/
 



Re: Test-friendly, but not caller-friendly?

by belugabrain :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

--- In junit@..., Michael Feathers <mfeathers@...> wrote:
>
> J. B. Rainsberger wrote:
>
> >Michael Feathers wrote:
> >  
> >
> >>But back to your original point: "It might sometimes be a
> >>NullPointerException or something else instead, but advertising a
> >>precondition is not an excuse for misbehavior just because you
receive
> >>bad data." Under DbC, it is. Fact is, if your precondition fails
or you
> >>get a NullPointerException, there's a bug in the client. You can
have
> >>checking enabled, or not, but checking is not error handling.
The point
> >>of DbC is to build software robust enough so that you don't have
to
> >>write error handling code at each level. Relevant section is 11.6
> >>"Assertions are not an input checking mechanism."
> >>    
> >>
> >
> >Indeed. If I violate your precondition, then I am writing
defective
> >code. There are a few remedies:
> >
> >1. Be nice and tolerate my indiscretion, say by substituting
sensible
> >default values and continuing.
> >
> >2. Telling me directly, "You shouldn't do that," by throwing a
specific
> >exception that explains my mistake.
> >
> >3. Telling me indirectly, by failing is some deterministic, by
> >non-obvious way.
> >
> >4. Providing me examples of how not to violate your precondition.
> >
> >5. Documenting the precondition and warning me that violating it
leads
> >to "undefined behavior".
> >
> >6. Providing Contract Tests that I can inherit to help me know
that my
> >code won't violate your precondition.
> >
> >There are others, I'm sure.
> >
> >It looks as though you reject #5 out of hand, and I agree, but
all the
> >others are viable choices. I would choose the one providing the
best ROI
> >for the situation. In a language that checks preconditions for
me, I
> >would get #2 for free. In Java, which doesn't, it depends on the
cost of
> >violating the precondition. If it's anything like persistent data
> >corruption all the way up to loss of life, I would probably
insist on
> >#2. If it's nothing worse than having to retry one of a batch of
> >transactions, I might go with #1. Still, I would probably insist
on #4
> >and prefer #6.
> >  
> >
> Joe,
>
> I'll answer this assuming that you're talking about API code, not
> application code.  If that's not the case, let me know.
>
> In some systems #1 is the best answer, but those situations are
rare
> and, as a strategy, it can lead to misunderstandings..  #2 and #4
are
> great strategies and I like #6 as well.
>
> I think it's interesting to talk about #5, though.    In nearly
every
> other area of life, we deal with warranties and license agreements
in
> which we explicitly assume responsibility for our use of products
and
> services.  In software we often try to protect clients from
themselves
> and don't consider notice a fair grant of responsibility.
>
> The fact is, it isn't universally true.  Lots of luck having Win32
save
> you from violations of its preconditions, for instance. :-)
>
> Frankly, I wouldn't want to have only #5 at the API level, but I
think
> that this tendency we have to believe that we can not have an
agreement
> with users that is not enforced by code leads to a great deal of
> trouble. Particularly in the area of visibility.. many developers
assume
> that no written agreement can be sufficient if something is made
> public.  I think that the issue is that we are not used to
thinking
> about agreements beyond the code and we're not used to holding
people to
> them.
>
> There are some exceptions.  One is the Eclipse API Rules of
Engagement:
> http://www.eclipse.org/articles/Article-API%20use/eclipse-api-
usage-rules.html
>
> It's a contract above the code and it has some great ideas.  I
really
> like the idea of "soft final" for instance.  It's like a license
> agreement.. you can do this (subclass and override, etc) and we
won't
> prevent you, but if you break the rules we can't be responsible
for you.
>
> Michael Feathers
> www.objectmentor.com
>

#1 doesn't help anybody, in the long-term.
It doesn't inform the client that they messed up, but merely lulls
them into a false sense of security that their code is fine.
There's not often a sensible default to use - and if there was, it
probably wouldn't be to the client's liking anyway.
The best example I can think of for how meeting criteria #1 can
backfire is the behaviour of Internet Explorer. Give it some HTML
with a missing </td> tag and it will silently provide one for you.
All this has done is to relieve thousands of web developers from the
responsibility of ensuring that they produce correct markup.
It really is a case of treating the symptoms whilst allowing the
disease to spread in an unchecked manner.
#5 covers a vast majority of cases - as Michael points our, we deal
with 'terms and conditions' in so many other parts of our life, why
not do so whlst carry out our chosen profession.

Bob

P.S. If we were to implement #1, surely it would be documented by #5?












 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/junit/

<*> To unsubscribe from this group, send an email to:
    junit-unsubscribe@...

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/
 




Re: Re: Test-friendly, but not caller-friendly?

by Elliotte Harold :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

J. B. Rainsberger wrote:
> Elliotte Harold wrote:
>
>> http://www.cafeconleche.org/XOM/designprinciples.xhtml#d0e161 
>> <http://www.cafeconleche.org/XOM/designprinciples.xhtml#d0e161>
>
> I tried, but there is plain text at the top of the file (before the
> preamble), so neither of my browsers will render it.

Damn, I see what happened. Ant's putting warnings in the same file it
where it places the output. I'll fix it. Try

http://www.xom.nu/designprinciples.xhtml#d0e161



--
Elliotte Rusty Harold  elharo@...
Java I/O 2nd Edition Just Published!
http://www.cafeaulait.org/books/javaio2/
http://www.amazon.com/exec/obidos/ISBN=0596527500/ref=nosim/cafeaulaitA/


 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/junit/

<*> To unsubscribe from this group, send an email to:
    junit-unsubscribe@...

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/
 


< Prev | 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - 15 | Next >