tag:blogger.com,1999:blog-2360295419257510421.comments2012-06-27T19:01:47.842+02:00CoderNubAnonymoushttp://www.blogger.com/profile/15625546905018255907noreply@blogger.comBlogger15125tag:blogger.com,1999:blog-2360295419257510421.post-47037149537778237462012-06-27T19:01:47.842+02:002012-06-27T19:01:47.842+02:00Thanks for posting this, it was helpful.Thanks for posting this, it was helpful.Justin Collumhttps://www.blogger.com/profile/07190193185280912171noreply@blogger.comtag:blogger.com,1999:blog-2360295419257510421.post-65534409318680258242012-05-26T10:13:32.200+02:002012-05-26T10:13:32.200+02:00It's a good while since I last wrote this, but...It's a good while since I last wrote this, but I think you'll find that funny stuff happens when you try to account for strikes and spares in the 10th frame, where the rules are special, if you don't track which frame you're on. Typically, you'll get a result of greater than 300 for a perfect game, for example.<br /><br />As for names, I've always been a fan of tiny functions with clear names. Code and unit tests as documentation and all that. While it might not be as necessary for small programs like this, it's a habit. :) <br /><br />What is not well formed in the checking of frames? I'm an utter Haskell noob, so maybe you can elaborate there.<br /><br />For a perhaps more compact example with a similar structure, I did this exercise in F# as well a while back, that I think is more like your crufty mood example.<br /> <br />http://codernub.blogspot.com/2010/05/bowling-kata-in-f-yup-more-bowling.html<br /><br />If you do an example with a custom data structure, I'd love to see it. There's nothing in the definition of the problem that says you couldn't do that, and it sounds like a cool exercise. :)Anonymoushttps://www.blogger.com/profile/15625546905018255907noreply@blogger.comtag:blogger.com,1999:blog-2360295419257510421.post-71153551175721995902012-05-25T21:28:40.616+02:002012-05-25T21:28:40.616+02:00Also, what's with the many and long names? I&...Also, what's with the many and long names? I'd go with<br /><br />main = runTestTT $ TestList [<br /> TestCase $ assertEquals "gutterballs" 0 $ score $ replicate 20 0,<br /> ...]<br /><br />And perhaps, depending on how crufty a mood I was in, I might not have an inner function scorePerFrame but just have score evaluate to 0 on [] and (scoreOfThisFrame + score the_rest) otherwise. In any case, I'd call it something short and generic like loop, step, go, rec, recur or something like that.<br /><br />(For some less local helper routine I might do something different)Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-2360295419257510421.post-60694793258683884592012-05-25T21:18:12.402+02:002012-05-25T21:18:12.402+02:00My thoughts, as a mediocre intermediate Haskeller:...My thoughts, as a mediocre intermediate Haskeller:<br /><br />- I'd put scorePerFrame in a `where' clause below calculateScore.<br />- I'd try and get rid of the frame counting. Why not just stop when rolls is empty?<br /> (You're not doing full well-formedness checking of frames anyways)<br /><br />- An issue with the _problem_ rather than your solution: my fingers would itch to define some data structure that would _only_ be able to represent a well-formed series of frames. Hmm, perhaps something like this:<br /><br />data Hit = First | Second | Never<br />data Frame = Hits { pin1 :: Hit, pin2 :: Hit, {- and so on -} pin10 :: Hit }<br />data Series = Frame { frame1 :: Frame {- and more -} }<br /><br />It definitely doesn't make this kata any shorter or smoother, or perhaps improves it in an way, but in a real, serious, industry-grade bowling application, I'd want to ask the type system for _some_ kind of help.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-2360295419257510421.post-48911099287086812792011-11-18T12:40:09.112+01:002011-11-18T12:40:09.112+01:00Ooooo, very nice code. Pattern matching FTW!Ooooo, very nice code. Pattern matching FTW!Torbjørn Marøhttp://blog.kjempekjekt.comnoreply@blogger.comtag:blogger.com,1999:blog-2360295419257510421.post-26045508438928639132010-11-20T13:34:29.969+01:002010-11-20T13:34:29.969+01:00Muchas gracia por tu respuesta comenzare a intenta...Muchas gracia por tu respuesta comenzare a intentar armarlo si .Anonymoushttps://www.blogger.com/profile/03384441287384095219noreply@blogger.comtag:blogger.com,1999:blog-2360295419257510421.post-67495159400859613052010-11-19T15:00:58.981+01:002010-11-19T15:00:58.981+01:00Gustavo, I'm sorry, but I don't quite unde...Gustavo, I'm sorry, but I don't quite understand what you're asking. From what I can tell, you need help with a bowling application maybe? If so, what you have here is a good guide to how to do scoring, done step by step, with unit tests. If there's a concept that is unclear, I can try to explain that, but I don't have the time to do software development for others, in general.Anonymoushttps://www.blogger.com/profile/15625546905018255907noreply@blogger.comtag:blogger.com,1999:blog-2360295419257510421.post-74583930837709964742010-11-19T13:06:21.530+01:002010-11-19T13:06:21.530+01:00Hi I found very interesting your contribution to&#...Hi I found very interesting your contribution to'm bowling novice kata c # you can help me make my point application<br />Bowling have a program running on kata bowling or something to guide me to<br />implementing kata class bowling thank you very much.<br />Ferrioli@gmail.comAnonymoushttps://www.blogger.com/profile/03384441287384095219noreply@blogger.comtag:blogger.com,1999:blog-2360295419257510421.post-89428814599224616322010-04-30T21:32:37.490+02:002010-04-30T21:32:37.490+02:00Excellent post! I completely agree: SRP is key. An...Excellent post! I completely agree: SRP is key. And, while I like the new language constructs Microsoft is adding to C#, I appreciate your final thought: that sometimes the "old-fashioned" way is the right way. That implies one should not use language constructs because they are new/hip/trendy, but because they are the right tool for the job.Paul Nelsonhttp://salientblue.comnoreply@blogger.comtag:blogger.com,1999:blog-2360295419257510421.post-72734093157300474472010-03-15T13:10:38.854+01:002010-03-15T13:10:38.854+01:00Good stuff Christian!Good stuff Christian!Hans Martin Myhrehttps://www.blogger.com/profile/03883678482399473613noreply@blogger.comtag:blogger.com,1999:blog-2360295419257510421.post-75795838484792630682010-02-18T10:29:28.131+01:002010-02-18T10:29:28.131+01:00Well spoken. I am glad to have a passion for my wo...Well spoken. I am glad to have a passion for my work as well, but people is different.<br /><br />Some people is more passionate than others. I believe success, and happiness, does not require passion. Anyway it certainly helps.Hans Martin Myhrehttps://www.blogger.com/profile/03883678482399473613noreply@blogger.comtag:blogger.com,1999:blog-2360295419257510421.post-49297022318030763792010-01-09T08:40:23.464+01:002010-01-09T08:40:23.464+01:00Sorry, currentRoll wasn't a class member I thi...Sorry, currentRoll wasn't a class member I think. That line wasn't supposed to be there. I was just getting confused between different versions of the code. :)Anonymoushttps://www.blogger.com/profile/15625546905018255907noreply@blogger.comtag:blogger.com,1999:blog-2360295419257510421.post-62502749006230700402010-01-09T06:14:25.895+01:002010-01-09T06:14:25.895+01:00Thanks for the comment. currentRoll was already a ...Thanks for the comment. currentRoll was already a class member. As commented above, pasting in the unrefactored code was actually my mistake, which I didn't notice until I was away from the machine that had the code on it. I've edited with the refactored end result now.<br /><br />How would using an array solve the gutterballs failure? The error was happening from trying to access invalid indexes, which would be a problem with an array as well. Though you're right in that an array would suit just fine here as well. I do like the dynamicity of a list type though, since you're not bowling 21 balls every time. <br /><br />On the other hand, I guess a maximum of nine unused memory blocks isn't the worst of overhead out there, and I might lose more than that by using a full list object rather than a simple array. ;)Anonymoushttps://www.blogger.com/profile/15625546905018255907noreply@blogger.comtag:blogger.com,1999:blog-2360295419257510421.post-5959909941738028412010-01-09T05:49:45.894+01:002010-01-09T05:49:45.894+01:00Excellent work! This is much improved over your pr...Excellent work! This is much improved over your previous attempt (which was quite good as well).<br /><br />As far as the "superfluous" tests are concerned, I think they are fine. While there are tests that probably don't need to be there I feel more confident with them there. Keeping them does come at a cost, and it is good to consider the cost while making a decision.<br /><br />There are some excellent refactorings that could be done in the Scorer class, and when I teach TDD it includes a refactoring step: Test -> Code -> Refactor.<br /><br />Specifically, a few helper methods could vastly improve the expressiveness of the code. For instance:<br /><br />if (rolls[currentRoll] == 10)<br /><br />could be replaced by <br /><br />if (isAStrike(currentRoll)<br /><br />isAStrike would be a simple method, but there is no extra overhead and the conditional becomes very obvious.<br /><br />Likewise, scoring a strike or spare could be encapsulated in a helper method to improve expressiveness:<br /><br />score += (scoreASpare(currentRoll)<br /><br />Finally, your frames loop: why not make it a bit more expressive:<br /><br />for (var frame = 0; frame < 10; frame++)<br /><br />Oh, and next time you might try just using an int array (int[21] to be exact) for rolls and make currentRoll a class member: this solves the problem of forcing a complete game before we can score the game (the all gutterballs failure).<br /><br />Very well done! I'm enjoying your blog entries. Keep 'em coming! :)Paulhttp://salientblue.comnoreply@blogger.comtag:blogger.com,1999:blog-2360295419257510421.post-72244442135490324062009-11-12T03:10:29.090+01:002009-11-12T03:10:29.090+01:00Nice post, Christian! You're definitely gettin...Nice post, Christian! You're definitely getting the hang of TDD.<br /><br />Katas do make sense for software development, much the same way they do for martial arts. What you may find, as you retry the same kata, is that the way you drive to the solution will change.<br /><br />For instance, you make a pretty big jump in the code under test when moving from rolling all gutter balls to rolling all ones. The test progression is perfect, but you move to adding a collection too soon. All you need to get the "roll all ones" test to pass is to create a new class variable that is an integer, named "score." Then, every time the "Roll" method is called, add pins to score. Finally, the "Score" method contains only one line: return score;<br /><br />Part of the key to TDD is to do the simplest thing in the code to get the new test, and all previous tests to pass. Why? Because, if I can do something ugly like I mention above, it indicates that I don't have sufficient test coverage and need to add more test cases. So, then I ask "what is the next test I need to write to force my implementation closer to the 'real' implementation?"<br /><br />There are a couple other jumps, some in the tests, that are too big, but that's good for starters. :)<br /><br />Keep up the great work!Paulhttp://salientblue.comnoreply@blogger.com