_roll],&rolls[first_roll+rolls_to_score(first_roll)],0); } std::vector<unsigned> frame_starts() const { std::vector<unsigned> res; for(unsigned i=0;res.size()<frame_count;i+=rolls_in_frame(i)) { res.push_back(i); } return res; } std::vector<unsigned> frame_scores() const { return ::accumulate(frame_starts(),std::vector<unsigned>(),AddFrameScore(*this)); } };
And now the tests:
#include <algorithm> #include <iostream> #define ASSERT_EQUALS(lhs,rhs) \ { \ if(lhs!=rhs) { \ std::cerr<<__FILE__<<": "<<__LINE__ \ <<": Error: Assertion failed: " #lhs "==" #rhs ", lhs=" \ <<lhs<<", rhs="<<rhs<<std::endl; \ } \ } template<typename T> std::ostream& operator<<(std::ostream& os,std::vector<T> const& vec) { os<<"{"; for(typename std::vector<T>::const_iterator it=vec.begin(), end=vec.end(); it!=end; ++it) { os<<*it<<","; } return os<<"}"; } template<unsigned Size> std::ostream& operator<<(std::ostream& os,unsigned const (& vec)[Size]) { os<<"{"; for(unsigned i=0;i<Size;++i) { os<<vec[i]<<","; } return os<<"}"; } template<typename LhsRange,unsigned RhsRangeSize> bool operator!=(LhsRange const& lhs,unsigned const(& rhs)[RhsRangeSize]) { return (std::distance(lhs.begin(),lhs.end())!= RhsRangeSize) ||!std::equal(lhs.begin(),lhs.end(),rhs); } int main() { unsigned const full_game_rolls=20; unsigned const all_zeros[full_game_rolls]={0}; ASSERT_EQUALS(Game(all_zeros).score(),0); unsigned const all_open[]={1,2,2,6,3,2,4,1,5,4,6,0,7,2,8,0,9,0,0,2}; ASSERT_EQUALS(Game(all_open).score(),64); unsigned const all_open_frame_starts[]={0,2,4,6,8,10,12,14,16,18}; ASSERT_EQUALS(Game(all_open).frame_starts(),all_open_frame_starts); for(unsigned i=0;i<full_game_rolls;i+=2) { ASSERT_EQUALS(Game(all_open).rolls_to_score(i),2); } unsigned const spare[full_game_rolls]={6,4,6,2}; ASSERT_EQUALS(Game(spare).rolls_to_score(0),3); ASSERT_EQUALS(Game(spare).rolls_to_score(2),2); unsigned const all_open_frame_scores[Game::frame_count]={3,8,5,5,9,6,9,8,9,2}; ASSERT_EQUALS(Game(all_open).frame_scores(),all_open_frame_scores); unsigned const spare_frame_scores[Game::frame_count]={16,8}; ASSERT_EQUALS(Game(spare).frame_scores(),spare_frame_scores); ASSERT_EQUALS(Game(spare).score(),24); unsigned const strike[full_game_rolls-1]={10,6,2}; ASSERT_EQUALS(Game(strike).rolls_to_score(0),3); ASSERT_EQUALS(Game(strike).rolls_to_score(1),2); unsigned const strike_frame_starts[]={0,1,3,5,7,9,11,13,15,17}; ASSERT_EQUALS(Game(strike).frame_starts(),strike_frame_starts); unsigned const alternating[]={10,1,9,10,1,9,10,1,9,10,1,9,10,1,9,10}; ASSERT_EQUALS(Game(alternating).score(),200); unsigned const all_strikes[]={10,10,10,10,10,10,10,10,10,10,10,10}; ASSERT_EQUALS(Game(all_strikes).score(),300); }
Posted by Anthony Williams
[/ cplusplus /] permanent link
Digg This | Save to del.icio.us | Stumble It! | Submit to Reddit | Submit to DZone
Message Handling Without Dependencies
Wednesday, 19 April 2006
My article, Message Handling Without Dependencies has been published in the May 2006 issue of Dr Dobb's Journal.
In the article, I describe a technique using templates and virtual functions to reduce dependencies when passing messages in C++. I have used this technique to great effect in production code.
Posted by Anthony Williams
[/ news /] permanent link
Digg This | Save to del.icio.us | Stumble It! | Submit to Reddit | Submit to DZone
Review of Refactoring to Patterns by Joshua Kerievsky
Wednesday, 12 April 2006 which makes up the bulk of the book.
The catalogue is divided into chapters based on the type of change required — is this a refactoring to simplify code, generalize code, or increase encapsulation and protection? Each chapter has an introduction which gives an overview of the refactorings contained within that chapter, followed by the refactorings themselves. These introductions clearly illustrate the principles and choices which by this book. If you are serious about software development, buy this book, inwardly digest it, and keep it by your side.
Highly Recommended.
Buy this book
Refactoring to Patterns
Joshua Kerievsky
Published by Addison-Wesley
ISBN 0-321-21335-1
Buy from Amazon.co.uk
Buy from Amazon.com
Posted by Anthony Williams
[/ reviews /] permanent link
Digg This | Save to del.icio.us | Stumble It! | Submit to Reddit | Submit to DZone
Review of Working Effectively With Legacy Code by Michael C. Feathers
Wednesday, 12 April 2006
A lot of the book is spent covering different techniques for getting nasty convoluted code under test. These techniques often focus on breaking dependencies, so you can instantiate an object in a test harness, or call a function without it sending an email or talking to the database. In many cases, these are sensible recommendations for improvements to the codebase, but in some cases, Michael recommends techniques you wouldn't expect to see in production code, such as defining preprocessor macros with the same name as functions to avoid calling them, or writing dummy implementations of API functions. This is not to say that the book recommends such techniques wholesale — Michael is keen to point out that these techniques should only be used to get the code under test, so that it can be refactored safely.
Chapters are helpfully named, with titles like "This class is too big, and I don't want it to get any bigger", and the book gives good advice on how to deal with the nastiest codebases. The key recommendation underlying it all is "get the code under test, so you can refactor safely", and this is borne in mind with those techniques that require changing the production code in order to get it under test — these techniques provide step by step instructions to help you make the required changes without breaking anything.
The content of this book is excellent, and the writing clear, so it is unfortunate that it is marred by numerous minor errors, such as spelling mistakes, or using the wrong identifier when referring to a code example. However, this minor niggle is not enough to stop me recommending it — every software developer should have a copy.
Highly Recommended. This book is a must-have for anyone who has to maintain code — which is pretty much every software developer on the planet.
Buy this book
Working Effectively With Legacy Code
Michael C. Feathers
Published by Prentice Hall PTR
ISBN 0-13-117705-2
Buy from Amazon.co.uk
Buy from Amazon.com
Posted by Anthony Williams
[/ reviews /] permanent link
Digg This | Save to del.icio.us | Stumble It! | Submit to Reddit | Submit to DZone
Review of Extreme Programming Adventures in C# by Ron Jeffries
Tuesday, 14 February 2006
The project is not just one big success story; Ron shares his mistakes with us so that we may learn from them. The book is interspersed with "lessons", where Ron reflects on the preceding section and tries to identify important points, either things that he felt worked well, or things the mistakes he made, and what he thinks could be done to try and avoid similar mistakes. Also throughout the book are sentences marked "sb", for "sound bite". These are short phrases which summarise a