|
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?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?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/ |
|
|
|
|
|
Re: Re: Test-friendly, but not caller-friendly?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/ |
|
|
|
|
|
|
|
|
|
|
|
Re: Re: Test-friendly, but not caller-friendly?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?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. > > 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?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. > > 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?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?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?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)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?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?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?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: > > > > > > > > > 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 > > 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?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. > > 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?--- 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?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 > |
| Free embeddable forum powered by Nabble | Forum Help |