tag:blogger.com,1999:blog-2208890564265615027.post2816647721951124038..comments2024-03-08T19:47:41.485+11:00Comments on Ascii Dreams: Asserting a Coding StyleAndrew Doullhttp://www.blogger.com/profile/11099404183952971291noreply@blogger.comBlogger16125tag:blogger.com,1999:blog-2208890564265615027.post-31109990162158007742008-12-23T21:17:00.000+11:002008-12-23T21:17:00.000+11:00The thing about the paranoia code is that it is on...The thing about the paranoia code is that it is only put there in the first place because the programmer suspects that something may be wrong. I found a years-old bug in O/FAangband recently which was <B>caused</B> by a piece of code introduced as a make-sure-this-definitely-works measure, and had been causing significant player grief ever since.<BR/><BR/>Whenever I try to state a general strategy for this sort of thing it always comes back to some sort of motherhood statement like "Do your best", and then I just end up deciding that lots of playtesting is the answer. So I guess I'm just saying do whatever the hell you like. In fact, (*warms to subject*) if roguelike programming isn't done for fun, then nothing is. Stop worrying, damn you! Have fun!<BR/><BR/>Over and out.Nickhttps://www.blogger.com/profile/07923262851958039182noreply@blogger.comtag:blogger.com,1999:blog-2208890564265615027.post-84804753988943304032008-12-23T07:23:00.000+11:002008-12-23T07:23:00.000+11:00Philosophically, the fail-fast approach is what le...Philosophically, the fail-fast approach is what lets the <A HREF="http://erlang.org" REL="nofollow">Erlang</A> programming language reach <A HREF="http://ll2.ai.mit.edu/talks/armstrong.pdf" REL="nofollow">ninenines of reliability</A> - 99.9999999% - in a certain telecom switch application. That's 31ms of downtime per year!<BR/><BR/>Then once you start getting into the junction of concurrency and fail-fast, you see this little flash of light behind your eyes, and you want to start programming everything in Erlang.<BR/><BR/>Best of luck on your respective trips to programming Nirvana (:Joe Osbornhttps://www.blogger.com/profile/13745963819679671079noreply@blogger.comtag:blogger.com,1999:blog-2208890564265615027.post-44663198264810283032008-12-22T11:25:00.000+11:002008-12-22T11:25:00.000+11:00I feel like I'm taking the first steps on the path...I feel like I'm taking the first steps on the path to programming enlightenment...Andrew Doullhttps://www.blogger.com/profile/11099404183952971291noreply@blogger.comtag:blogger.com,1999:blog-2208890564265615027.post-10444685177679035382008-12-22T11:10:00.000+11:002008-12-22T11:10:00.000+11:00I was a bit carried away with the "refactorin...I was a bit carried away with the "refactoring is cheap" line. It depends on the refactoring. Some kinds touch contracts just as much as they touch the code. Others just tweak the implementations (e.g. switching to a different library), so the contract stays the same.<BR/><BR/>> should I be refactoring this out? <BR/><BR/>No, you shouldn't, for exactly the reason, that the contract often stays the same, while the code changes. So, the old code becomes the contract for the new (possibly more complex) code. Which is not ideal, but still much better than no contract or an absurdly long one written using e.g. only conditional expressions and inequalities. Moreover, you can sometimes test with the old code in place of the new one and compare the results.<BR/><BR/>But for imperative programming languages this is all probably moot, because you usually _can't_ write contracts using them. For functional programming languages, OTOH, it's customary to give full power of the language and then some to the contract writer.Mikolajhttps://www.blogger.com/profile/01280729045107273819noreply@blogger.comtag:blogger.com,1999:blog-2208890564265615027.post-34310415205313453662008-12-22T11:02:00.000+11:002008-12-22T11:02:00.000+11:00> Am I not then effectively> duplicating the...> Am I not then effectively<BR/>> duplicating the code in the contract?<BR/><BR/>Yes, you are. So what? If the language for writing contracts is much poorer than the programming language, you may even end with a contract longer than code. So what? The purpose of contracts is not to shorten the source files. <BR/><BR/>The longer answer is that it depends on the code. If the function's code is deep, with a mathematical model, lots of logic in it and simple, high-level types of the function's input and output, then the contract will be much simpler than the code, even if the implementation is very naive (and much more so if the implementation is optimized and tricky --- moreover, the contract stays the same, so refactoring is cheap!!!).<BR/><BR/>If, however, the function's code is shallow and/or with low-level (or none at all) function's input and output, as is common for e.g. UI code, the contract won't magically shorten the boring list of random things to do in random order. Perhaps you don't want to write contracts for such code.<BR/><BR/>Of course, in codebases with good separation of boring (UI, ports, parsers and pretty-printers) and interesting code (game rules, content generation, AI), the decisions are easier. You can decide to write contracts only for the interesting code and don't end up with a half-done chaotic mess.Mikolajhttps://www.blogger.com/profile/01280729045107273819noreply@blogger.comtag:blogger.com,1999:blog-2208890564265615027.post-42186745794620839442008-12-22T07:23:00.000+11:002008-12-22T07:23:00.000+11:00Mikolaj:> > end up with a contract> > ...Mikolaj:<BR/><BR/>> > end up with a contract<BR/>> > as complex as the code<BR/><BR/>> Happens in all (semi-)formal methods.<BR/><BR/>Hang on. Am I not then effectively duplicating the code in the contract? In which case, should I be refactoring this out? :)<BR/><BR/>It seems to me more and more that I might just be better off ensuring that the code, just, you know, works, than trying to specify complex contracts...Andrew Doullhttps://www.blogger.com/profile/11099404183952971291noreply@blogger.comtag:blogger.com,1999:blog-2208890564265615027.post-46141308736353607272008-12-22T05:16:00.000+11:002008-12-22T05:16:00.000+11:00I have been trying to work out ways of unit-testin...I have been trying to work out ways of unit-testing Angband, but the code requires extensive refactoring before that can happen. My plan was always to have assert()s which failed when running to unit-test, but which didn't do anything when not unit-testing.Andihttps://www.blogger.com/profile/17836168735308708661noreply@blogger.comtag:blogger.com,1999:blog-2208890564265615027.post-84046448006285762702008-12-22T01:08:00.000+11:002008-12-22T01:08:00.000+11:00> end up with a contract > as complex as the...> end up with a contract <BR/>> as complex as the code<BR/><BR/>Happens in all (semi-)formal methods. There are two popular answers:<BR/><BR/>1. Hang on to it and next time, when you reimplement the function in a very tricky and stunningly efficient way, the contract will at last prove simpler. You may even keep the old simple implementation on the side for comparative testing.<BR/><BR/>2. Screw it and write a much simplified "contract" formally plus a bit of hand-waving or pointing to code in comments. I the limit case, the contract is empty, there are no comments and all the hand-waving is in the name of the function and the readability of the code. Improve from there.Mikolajhttps://www.blogger.com/profile/01280729045107273819noreply@blogger.comtag:blogger.com,1999:blog-2208890564265615027.post-78659868846241497202008-12-21T17:05:00.000+11:002008-12-21T17:05:00.000+11:00Mikolaj: Completely agree - I don't know if this w...Mikolaj: Completely agree - I don't know if this will be useful, but its something to keep in mind, and let me sleep at night :)<BR/><BR/>One reservation I have with design by contract is that you made end up with a contract as complex as the code you're intending to implement. In which case, you're not helping at all. It's mostly intended to formalise the 'paranoia' code that occasionally gets injected into a function.Andrew Doullhttps://www.blogger.com/profile/11099404183952971291noreply@blogger.comtag:blogger.com,1999:blog-2208890564265615027.post-57972291569804588802008-12-21T15:36:00.000+11:002008-12-21T15:36:00.000+11:00Design by Contract is OK, indeed, especially if it...Design by Contract is OK, indeed, especially if it's not mandatory. Good luck with it.<BR/><BR/>I've tried to use asserts in UnAngband as often as I did in my other projects, including those in C, but it somehow didn't work. I think one reason is the functions in Angband are often too long, so in the middle of the function body you lose track of soundness conditions. The other reason may be the overall hackish smartness of the code, when the same code path is used for different purposes. Another reason is poor separation of UI and logic, e.g., you can expect any piece of code to happily print things on the screen directly, so it's hard to write assertions about the state of the screen (see the easy-more nightmare). One more reason is low-level stuff, e.g., a lot of logical properties can only be expressed as conditions on bit-flags --- which then fail miserably after addition of one too many flag that spills to another word, etc.Mikolajhttps://www.blogger.com/profile/01280729045107273819noreply@blogger.comtag:blogger.com,1999:blog-2208890564265615027.post-90155250810666586802008-12-21T09:07:00.000+11:002008-12-21T09:07:00.000+11:00Humpolec: You mean there's an assert.h? :)VRBones:...Humpolec: You mean there's an assert.h? :)<BR/><BR/>VRBones: It reminded me of a <A HREF="http://pcg.wikidot.com/pcg-algorithm:rapidly-exploring-random-tree" REL="nofollow">rapidly exploring random tree</A> for the same reason.<BR/><BR/>Stu: The implementation picks a random cell, do something based on the nearest neighbours - yes, it is undoubtedly a cellular automata. Its optimised, of course, to ensure that it picks only cells that it can do work with.<BR/><BR/>I'm trying as a side project to come up with a generic cellular automata class in Javascript for the PCG Wiki if anyone wants to help out. Have a look at <A HREF="http://pcg.wikidot.com/pcg-algorithm:cellular-automata" REL="nofollow">the simple first pass attempt</A> if you want. It's intended as a teaching tool to help people understand how flexible CA are.<BR/><BR/>Jotaf: Since DBC is intended for a class based environment, I'm sure someone will have done something similar for C++. Let us know if you find anything.Andrew Doullhttps://www.blogger.com/profile/11099404183952971291noreply@blogger.comtag:blogger.com,1999:blog-2208890564265615027.post-62317719903265073542008-12-21T03:10:00.000+11:002008-12-21T03:10:00.000+11:00Stu, that's very neat indeed! Any chance it works ...Stu, that's very neat indeed! Any chance it works for C++ (or there is an alternative that does)? (Judging from the article I guess not.) The custom script puts me off a bit, I dunno how easy it would be to integrate something like this in my VS2005 environment... I'll start digging for DBC alternatives now :)Jotafhttps://www.blogger.com/profile/11804130701206652599noreply@blogger.comtag:blogger.com,1999:blog-2208890564265615027.post-23308639897982634592008-12-21T01:32:00.000+11:002008-12-21T01:32:00.000+11:00Looks like ye standard cellular automata (based on...Looks like ye standard cellular automata (based on looking only at the two pictures) to me thats already in the rogue dev wiki...<BR/><BR/>as for the require macro.. Sometimes I use DBC for C, its written in ruby and its pretty cool doing pre/post/invariant rules in your C code if you specify them in comments before the routine itself.. <BR/><BR/>pretty neat.<BR/>http://www.onlamp.com/pub/a/onlamp/2004/10/28/design_by_contract_in_c.htmlStuhttps://www.blogger.com/profile/03746769788742751281noreply@blogger.comtag:blogger.com,1999:blog-2208890564265615027.post-68726074313620741482008-12-20T23:23:00.000+11:002008-12-20T23:23:00.000+11:00new algorithm output immediately reminded me of ri...new algorithm output immediately reminded me of river basins ...VRBoneshttps://www.blogger.com/profile/10654192372497663948noreply@blogger.comtag:blogger.com,1999:blog-2208890564265615027.post-92176843040840866322008-12-20T21:49:00.000+11:002008-12-20T21:49:00.000+11:00Ad 2. I would just do what standard "assert.h...Ad 2. I would just do what standard "assert.h" does - make a macro dependent on some 'DEBUG_LEVEL' symbol, that would either compile to nothing, a code that returns, or a call to some helper function.<BR/>As for the return value, make it an argument in your macro. Then you can just write <BR/>REQUIRE(x > 0,);<BR/>if you want the function to fail with "return;" or<BR/>REQUIRE(x > 0, 42);<BR/>if you want it to "return 42;".<BR/><BR/>Ad 3. Does "execinfo.h" in GNU libc do what you want? I'm not sure if it works in Windows version.humpolechttps://www.blogger.com/profile/05268630131048166288noreply@blogger.comtag:blogger.com,1999:blog-2208890564265615027.post-39016884130912823392008-12-20T14:13:00.000+11:002008-12-20T14:13:00.000+11:00The link to the source doesn't work here. Probably...The link to the source doesn't work here. Probably something strange on my end. :/<BR/><BR/>I agree with you on the 'fail hard and fast' school of code writing. I'm afrwaid I can't really be more help than that. Setting the stuff at compile time is easily achieved with a macro, runtime you would have to use a function, but the compile out completely setting would have to be compile time I would think.Unknownhttps://www.blogger.com/profile/07961415849799133913noreply@blogger.com