how to model this a better way
On Thu, Apr 18, 2019 at 8:57 AM Roelof Wobben <r.wobben@home.nl> wrote:
Hello,
I know I have asked earlier but im still stuck on this one : https://github.com/exercism/problem-specifications/blob/master/exercises/rob...
I tried with all double dispatch but that will be a lot of duplicate classes
The problem I cannot solve right is that a robot can move or turn. when a robot turns only the direction the robot is facing changes and the position not. when a robot moves the facing direction stays the same but the position changes. but the change is dependend on the facing. Also the new facing direction is dependend on the old facing direction/ How can I model this the best.
I already have a object Robot that contains the facing direction and the current position or tried without it but then I use a lot of if then's
so it there a better way to model this problem so it will be all nice and readable code.
If I remember correctly, Richard O'Keefe gave you a viable design. 1) Use a Point for your direction vector. 2) Use a second Point for your position. e.g. if you align the compass with a Cartesian plane, 0@1 is North, 0@-1 is South, 1@0 is East, and -1@0 is West. When you move, you add the direction vector to your current position. If you allow movements of greater than a single unit, you multiply the direction vector by the distance before adding that product to the position.
Roelof
On Thu, Apr 18, 2019 at 10:01 AM Roelof Wobben <r.wobben@home.nl> wrote:
yep, I have read that one but I never gets a answer how I can "convert" a point to something like north, east
because the challenge wants this to be the answer :
(Dictionary new add: 'direction' -> 'north'; add: 'position' -> (Dictionary new add: 'x' -> 0; add: 'y' -> 0; yourself); yourself)
If you have previously defined a "representation map", you would be golden. e.g. Dictionary new at: self northDirectionVector put: 'north'; at: self eastDirectionVector put: 'east'; at: self southDirectionVector put: 'south'; at: self westDirectionVector put: 'west'; yourself. Then: (Dictionary new add: 'direction' -> (self directionRepresentationMap at: self directionVector); ...
and I think I need then to use if then , which I try to avoid as much as possible.
Roelof
Op 18-4-2019 om 18:33 schreef Richard Sargent:
On Thu, Apr 18, 2019 at 8:57 AM Roelof Wobben <r.wobben@home.nl> wrote:
Hello,
I know I have asked earlier but im still stuck on this one : https://github.com/exercism/problem-specifications/blob/master/exercises/rob...
I tried with all double dispatch but that will be a lot of duplicate classes
The problem I cannot solve right is that a robot can move or turn. when a robot turns only the direction the robot is facing changes and the position not. when a robot moves the facing direction stays the same but the position changes. but the change is dependend on the facing. Also the new facing direction is dependend on the old facing direction/ How can I model this the best.
I already have a object Robot that contains the facing direction and the current position or tried without it but then I use a lot of if then's
so it there a better way to model this problem so it will be all nice and readable code.
If I remember correctly, Richard O'Keefe gave you a viable design. 1) Use a Point for your direction vector. 2) Use a second Point for your position.
e.g. if you align the compass with a Cartesian plane, 0@1 is North, 0@-1 is South, 1@0 is East, and -1@0 is West. When you move, you add the direction vector to your current position. If you allow movements of greater than a single unit, you multiply the direction vector by the distance before adding that product to the position.
Roelof
On Thu, Apr 18, 2019 at 10:33 AM Roelof Wobben <r.wobben@home.nl> wrote:
oke
Maybe I understand something not right,
Lets say we have this scenario.
Robot is on position (0,0) now it turns left so the robot faces East
I don't understand what position has to do with direction nor why that would be a problem. They are two distinct attributes. Point and Dictionary are sufficient classes to model the limited requirements of this exercise. You could model a new class DirectionVector which internalizes the Point used to provide the direction and provides its own name, eliminating the need for a look up of any kind.
or this scenario
Robot is on position (0,0) now it turns right so the robot faces west.
it looks that dictionary cannot provide this answer. or do I overlook something
Roelof
Op 18-4-2019 om 19:17 schreef Richard Sargent:
On Thu, Apr 18, 2019 at 10:01 AM Roelof Wobben <r.wobben@home.nl> wrote:
yep, I have read that one but I never gets a answer how I can "convert" a point to something like north, east
because the challenge wants this to be the answer :
(Dictionary new add: 'direction' -> 'north'; add: 'position' -> (Dictionary new add: 'x' -> 0; add: 'y' -> 0; yourself); yourself)
If you have previously defined a "representation map", you would be golden.
e.g. Dictionary new at: self northDirectionVector put: 'north'; at: self eastDirectionVector put: 'east'; at: self southDirectionVector put: 'south'; at: self westDirectionVector put: 'west'; yourself.
Then: (Dictionary new add: 'direction' -> (self directionRepresentationMap at: self directionVector); ...
and I think I need then to use if then , which I try to avoid as much as possible.
Roelof
Op 18-4-2019 om 18:33 schreef Richard Sargent:
On Thu, Apr 18, 2019 at 8:57 AM Roelof Wobben <r.wobben@home.nl> wrote:
Hello,
I know I have asked earlier but im still stuck on this one : https://github.com/exercism/problem-specifications/blob/master/exercises/rob...
I tried with all double dispatch but that will be a lot of duplicate classes
The problem I cannot solve right is that a robot can move or turn. when a robot turns only the direction the robot is facing changes and the position not. when a robot moves the facing direction stays the same but the position changes. but the change is dependend on the facing. Also the new facing direction is dependend on the old facing direction/ How can I model this the best.
I already have a object Robot that contains the facing direction and the current position or tried without it but then I use a lot of if then's
so it there a better way to model this problem so it will be all nice and readable code.
If I remember correctly, Richard O'Keefe gave you a viable design. 1) Use a Point for your direction vector. 2) Use a second Point for your position.
e.g. if you align the compass with a Cartesian plane, 0@1 is North, 0@-1 is South, 1@0 is East, and -1@0 is West. When you move, you add the direction vector to your current position. If you allow movements of greater than a single unit, you multiply the direction vector by the distance before adding that product to the position.
Roelof
Your system would have instance variables holding the cardinal directions and another holding the current direction vector. e.g. north := DirectionVector x: 0 y: 1 name: 'north'. Your robot would implement e.g. #faceNorth to assign the "north" direction vector to the current direction vector instance variable. On Thu, Apr 18, 2019 at 12:17 PM Roelof Wobben <r.wobben@home.nl> wrote:
oke, and how must I see those classes and elemating the need for a lookup.
it may be explained in pseudo-code.
Roelof
Op 18-4-2019 om 20:28 schreef Richard Sargent:
On Thu, Apr 18, 2019 at 10:33 AM Roelof Wobben <r.wobben@home.nl> wrote:
oke
Maybe I understand something not right,
Lets say we have this scenario.
Robot is on position (0,0) now it turns left so the robot faces East
I don't understand what position has to do with direction nor why that would be a problem. They are two distinct attributes. Point and Dictionary are sufficient classes to model the limited requirements of this exercise. You could model a new class DirectionVector which internalizes the Point used to provide the direction and provides its own name, eliminating the need for a look up of any kind.
or this scenario
Robot is on position (0,0) now it turns right so the robot faces west.
it looks that dictionary cannot provide this answer. or do I overlook something
Roelof
Op 18-4-2019 om 19:17 schreef Richard Sargent:
On Thu, Apr 18, 2019 at 10:01 AM Roelof Wobben <r.wobben@home.nl> wrote:
yep, I have read that one but I never gets a answer how I can "convert" a point to something like north, east
because the challenge wants this to be the answer :
(Dictionary new add: 'direction' -> 'north'; add: 'position' -> (Dictionary new add: 'x' -> 0; add: 'y' -> 0; yourself); yourself)
If you have previously defined a "representation map", you would be golden.
e.g. Dictionary new at: self northDirectionVector put: 'north'; at: self eastDirectionVector put: 'east'; at: self southDirectionVector put: 'south'; at: self westDirectionVector put: 'west'; yourself.
Then: (Dictionary new add: 'direction' -> (self directionRepresentationMap at: self directionVector); ...
and I think I need then to use if then , which I try to avoid as much as possible.
Roelof
Op 18-4-2019 om 18:33 schreef Richard Sargent:
On Thu, Apr 18, 2019 at 8:57 AM Roelof Wobben <r.wobben@home.nl> wrote:
Hello,
I know I have asked earlier but im still stuck on this one : https://github.com/exercism/problem-specifications/blob/master/exercises/rob...
I tried with all double dispatch but that will be a lot of duplicate classes
The problem I cannot solve right is that a robot can move or turn. when a robot turns only the direction the robot is facing changes and the position not. when a robot moves the facing direction stays the same but the position changes. but the change is dependend on the facing. Also the new facing direction is dependend on the old facing direction/ How can I model this the best.
I already have a object Robot that contains the facing direction and the current position or tried without it but then I use a lot of if then's
so it there a better way to model this problem so it will be all nice and readable code.
If I remember correctly, Richard O'Keefe gave you a viable design. 1) Use a Point for your direction vector. 2) Use a second Point for your position.
e.g. if you align the compass with a Cartesian plane, 0@1 is North, 0@-1 is South, 1@0 is East, and -1@0 is West. When you move, you add the direction vector to your current position. If you allow movements of greater than a single unit, you multiply the direction vector by the distance before adding that product to the position.
Roelof
You quickly find itâs a more interesting exercise than just a âpoint and dictionaryâ, particularly if you want to do it in an elegant Smalltalk way (but not over do it either). The interesting bit is that when facing a new direction, you need to know how to advance in that direction , and also what âleftâ and ârightâ of that direction are too. So it teases out having some objects and techniques for this. For those interested - join exercism-Pharo (https://exercism.io/tracks/pharo-smalltalk/installation) in non mentor mode and you can easily download it with the tests and try it out yourself (without running through the other exercises). Tim Sent from my iPhone
On 18 Apr 2019, at 21:41, Richard Sargent <richard.sargent@gemtalksystems.com> wrote:
Your system would have instance variables holding the cardinal directions and another holding the current direction vector. e.g. north := DirectionVector x: 0 y: 1 name: 'north'.
Your robot would implement e.g. #faceNorth to assign the "north" direction vector to the current direction vector instance variable.
On Thu, Apr 18, 2019 at 12:17 PM Roelof Wobben <r.wobben@home.nl> wrote: oke, and how must I see those classes and elemating the need for a lookup.
it may be explained in pseudo-code.
Roelof
Op 18-4-2019 om 20:28 schreef Richard Sargent:
On Thu, Apr 18, 2019 at 10:33 AM Roelof Wobben <r.wobben@home.nl> wrote: oke
Maybe I understand something not right,
Lets say we have this scenario.
Robot is on position (0,0) now it turns left so the robot faces East
I don't understand what position has to do with direction nor why that would be a problem. They are two distinct attributes. Point and Dictionary are sufficient classes to model the limited requirements of this exercise. You could model a new class DirectionVector which internalizes the Point used to provide the direction and provides its own name, eliminating the need for a look up of any kind.
or this scenario
Robot is on position (0,0) now it turns right so the robot faces west.
it looks that dictionary cannot provide this answer. or do I overlook something
Roelof
Op 18-4-2019 om 19:17 schreef Richard Sargent:
On Thu, Apr 18, 2019 at 10:01 AM Roelof Wobben <r.wobben@home.nl> wrote: yep, I have read that one but I never gets a answer how I can "convert" a point to something like north, east
because the challenge wants this to be the answer :
(Dictionary new add: 'direction' -> 'north'; add: 'position' -> (Dictionary new add: 'x' -> 0; add: 'y' -> 0; yourself); yourself)
If you have previously defined a "representation map", you would be golden.
e.g. Dictionary new at: self northDirectionVector put: 'north'; at: self eastDirectionVector put: 'east'; at: self southDirectionVector put: 'south'; at: self westDirectionVector put: 'west'; yourself.
Then: (Dictionary new add: 'direction' -> (self directionRepresentationMap at: self directionVector); ...
and I think I need then to use if then , which I try to avoid as much as possible.
Roelof
Op 18-4-2019 om 18:33 schreef Richard Sargent:
On Thu, Apr 18, 2019 at 8:57 AM Roelof Wobben <r.wobben@home.nl> wrote: Hello,
I know I have asked earlier but im still stuck on this one : https://github.com/exercism/problem-specifications/blob/master/exercises/rob...
I tried with all double dispatch but that will be a lot of duplicate classes
The problem I cannot solve right is that a robot can move or turn. when a robot turns only the direction the robot is facing changes and the position not. when a robot moves the facing direction stays the same but the position changes. but the change is dependend on the facing. Also the new facing direction is dependend on the old facing direction/ How can I model this the best.
I already have a object Robot that contains the facing direction and the current position or tried without it but then I use a lot of if then's
so it there a better way to model this problem so it will be all nice and readable code.
If I remember correctly, Richard O'Keefe gave you a viable design. 1) Use a Point for your direction vector. 2) Use a second Point for your position.
e.g. if you align the compass with a Cartesian plane, 0@1 is North, 0@-1 is South, 1@0 is East, and -1@0 is West. When you move, you add the direction vector to your current position. If you allow movements of greater than a single unit, you multiply the direction vector by the distance before adding that product to the position.
Roelof
I already discoursed on this at some length. (1) In my own answer, I used code to map direction names to vectors. But the Dictionary answers are absolutely fine. (2) I pointed out that there are ALREADY "turn left" and "turn right" operations on Points. (3) An elegant solution is one which wastes no effort. Introducing classes that you don't need is definitely wasted effort. WARNING: untested first draft code (can't find the tested stuff). obey: commands |position direction| position := 0@0. direction := 1@0. commands do: [:each | each caseOf: { [$A] -> [position := position + direction]. [$L] -> [direction := direction leftRotated]. [$R] -> [direction := direction rightRotated] }]. ^{position. direction} You will need to fiddle with this a bit to get the mapping between problem coordinates and solution coordinates right, and you'll need that Dictionary mapping directions to direction names, but that's pretty much it. If you define more than one class for this problem, your code is not elegant. On Fri, 19 Apr 2019 at 08:05, Tim Mackinnon <tim@testit.works> wrote:
You quickly find itâs a more interesting exercise than just a âpoint and dictionaryâ, particularly if you want to do it in an elegant Smalltalk way (but not over do it either).
The interesting bit is that when facing a new direction, you need to know how to advance in that direction , and also what âleftâ and ârightâ of that direction are too. So it teases out having some objects and techniques for this.
For those interested - join exercism-Pharo ( https://exercism.io/tracks/pharo-smalltalk/installation) in non mentor mode and you can easily download it with the tests and try it out yourself (without running through the other exercises).
Tim
Sent from my iPhone
On 18 Apr 2019, at 21:41, Richard Sargent < richard.sargent@gemtalksystems.com> wrote:
Your system would have instance variables holding the cardinal directions and another holding the current direction vector. e.g. north := DirectionVector x: 0 y: 1 name: 'north'.
Your robot would implement e.g. #faceNorth to assign the "north" direction vector to the current direction vector instance variable.
On Thu, Apr 18, 2019 at 12:17 PM Roelof Wobben <r.wobben@home.nl> wrote:
oke, and how must I see those classes and elemating the need for a lookup.
it may be explained in pseudo-code.
Roelof
Op 18-4-2019 om 20:28 schreef Richard Sargent:
On Thu, Apr 18, 2019 at 10:33 AM Roelof Wobben <r.wobben@home.nl> wrote:
oke
Maybe I understand something not right,
Lets say we have this scenario.
Robot is on position (0,0) now it turns left so the robot faces East
I don't understand what position has to do with direction nor why that would be a problem. They are two distinct attributes. Point and Dictionary are sufficient classes to model the limited requirements of this exercise. You could model a new class DirectionVector which internalizes the Point used to provide the direction and provides its own name, eliminating the need for a look up of any kind.
or this scenario
Robot is on position (0,0) now it turns right so the robot faces west.
it looks that dictionary cannot provide this answer. or do I overlook something
Roelof
Op 18-4-2019 om 19:17 schreef Richard Sargent:
On Thu, Apr 18, 2019 at 10:01 AM Roelof Wobben <r.wobben@home.nl> wrote:
yep, I have read that one but I never gets a answer how I can "convert" a point to something like north, east
because the challenge wants this to be the answer :
(Dictionary new add: 'direction' -> 'north'; add: 'position' -> (Dictionary new add: 'x' -> 0; add: 'y' -> 0; yourself); yourself)
If you have previously defined a "representation map", you would be golden.
e.g. Dictionary new at: self northDirectionVector put: 'north'; at: self eastDirectionVector put: 'east'; at: self southDirectionVector put: 'south'; at: self westDirectionVector put: 'west'; yourself.
Then: (Dictionary new add: 'direction' -> (self directionRepresentationMap at: self directionVector); ...
and I think I need then to use if then , which I try to avoid as much as possible.
Roelof
Op 18-4-2019 om 18:33 schreef Richard Sargent:
On Thu, Apr 18, 2019 at 8:57 AM Roelof Wobben <r.wobben@home.nl> wrote:
Hello,
I know I have asked earlier but im still stuck on this one : https://github.com/exercism/problem-specifications/blob/master/exercises/rob...
I tried with all double dispatch but that will be a lot of duplicate classes
The problem I cannot solve right is that a robot can move or turn. when a robot turns only the direction the robot is facing changes and the position not. when a robot moves the facing direction stays the same but the position changes. but the change is dependend on the facing. Also the new facing direction is dependend on the old facing direction/ How can I model this the best.
I already have a object Robot that contains the facing direction and the current position or tried without it but then I use a lot of if then's
so it there a better way to model this problem so it will be all nice and readable code.
If I remember correctly, Richard O'Keefe gave you a viable design. 1) Use a Point for your direction vector. 2) Use a second Point for your position.
e.g. if you align the compass with a Cartesian plane, 0@1 is North, 0@-1 is South, 1@0 is East, and -1@0 is West. When you move, you add the direction vector to your current position. If you allow movements of greater than a single unit, you multiply the direction vector by the distance before adding that product to the position.
Roelof
On Mon, 22 Apr 2019 at 23:15, Richard O'Keefe <raoknz@gmail.com> wrote:
I already discoursed on this at some length. (1) In my own answer, I used code to map direction names to vectors. But the Dictionary answers are absolutely fine. (2) I pointed out that there are ALREADY "turn left" and "turn right" operations on Points. (3) An elegant solution is one which wastes no effort. Introducing classes that you don't need is definitely wasted effort.
Elegance in art is in the eye of the beholder. You've got one position on it. I'll just balance it with an alternative view for students to consider around "classes that you don't need".
WARNING: untested first draft code (can't find the tested stuff). obey: commands |position direction| position := 0@0. direction := 1@0. commands do: [:each | each caseOf: { [$A] -> [position := position + direction]. [$L] -> [direction := direction leftRotated]. [$R] -> [direction := direction rightRotated] }]. ^{position. direction} You will need to fiddle with this a bit to get the mapping between problem coordinates and solution coordinates right, and you'll need that Dictionary mapping directions to direction names, but that's pretty much it.
If you define more than one class for this problem, your code is not elegant.
If the purpose of the problems is simply to solve the problem, then doing the absolute minimum is a reasonable view of elegance. After all, its throw away code. You're never going to be maintaining it. But if the purpose of problems is to lead students in new ways of thinking about structuring OO solutions for maintainability within Pharo, then I feel its lacking. I remember an instructor from my youth advising that "practicing a kata poorly is the habit that will be reproduced automatically (in a crisis)"
^{position. direction}
For me, viewing {2@3. 1@0 } in a debugger is a much greater cognitive load than {2@3. 'Facing east'} to determine which direction its facing. So I consider the latter more elegant. TDD helps minimise class over-engineering, but for me the latter is a "need". In terms of throw-away exercises, its about what habits students want to gain from doing them. Just another perspective. cheers -ben
Let me tell you a story. The story is about someone I knew back when I was doing my MSc. He was really bright, but he had to repeat a year in the papers part of his MSc. Why? Because he didn't get statistics. Differential equations? No problem. Topology? No problem. Operations research (which was his actual topic)? A walk in the park. Statistics? He just couldn't get it. Why not? "I read the book, and I think I understand, and then I come to the examples, and I can't see why they use the method they use, why that is a good method for that problem." I hope it made a difference to him when I replied "You can't see why method X is a good choice for problem Y because it isn't. If your goal is to illustrate the workings of method X, problem Y will do. But if your goal is to actually solve problem Y, method X is the last thing you should try." I actually worked through a couple of famous textbooks, example by example, and found that for more than half of the problems, if you followed the advice in the book about how to select a method, you would never select the method in the example, and the method you would select instead gave better and on occasion much better results. In this particular case, I don't give a damn about what {1@0. 0@} looks like in a debugger, BECAUSE IT NEVER DID APPEAR IN A DEBUGGER. The one method needed to solve the problem is 18 lines. The test code, including all available test cases, is 27 lines, of which 18 lines is the test data. Tests were needed primarily to sort out what the problem actually *was*; exercism doesn't even try to provide good specifications. No debugging time at all was needed, precisely because the code was so simple and obvious. If it *had* been needed, viewing the result right next to the expression that yielded it would have given me all the context I needed, in one window. If you want to learn how to design a good set of classes, this is an absolutely dreadful problem. In fact ALL of the exercism problems are going to be dreadful for *that* purpose because they are provided for languages that do not *have* classes. If you want to learn how to *solve problems*, then you need to learn to write code that is simple, clear, testable, and so on. You certainly need to learn how to use what is already there in the language (except where that is expressly forbidden). I completely agree that designing a good set of classes is a very very important skill for anyone who wants to do OOP. I completely agree that practising this on problems you can hold in your head is a good idea. I completely agree that if *that* is your objective, writing minimalist code is not the best strategy. The problem with exercism is that while it does have a criterion by which you can tell whether you have *solved the problem*, it provides *no* way to assess your class design. You don't get told "this is good, that is bloated"; there is no feedback about the *quality* of your code except via comments from those few people who can be bothered to look at other people's solutions and comment on them. And since many of them will also be beginners, their comments may not always help. This particular problem is very similar to a "Langton's Ant" problem my old department gave to students, who were expected to solve it in two or three hours. And ALWAYS, the thing that held them back was creating classes they didn't need and agonising over what data and methods should go where (and then getting it wrong, such is the nature of Java). When a problem can be solved quite directly in 18 lines of clean code, you are going to have a very hard time persuading me that even one more class pays for itself, especially in a system with a rich class library of stuff you don't have to write. "You Aren't Gunna Need It" is a good slogan. "If you didn't write it you didn't wrong it" is another.
On Wed, 24 Apr 2019 at 16:52, Richard O'Keefe <raoknz@gmail.com> wrote:
The one method needed to solve the problem is 18 lines. The test code, including all available test cases, is 27 lines, of which 18 lines is the test data. Tests were needed primarily to sort out what the problem actually *was*; exercism doesn't even try to provide good specifications. No debugging time at all was needed, precisely because the code was so simple and obvious.
But we do want to showcase our debugger and demonstrate how to get the most out of it. The way the exercises are structured is to sequentially enable one test at a time, see how that fails and fix it, so students will be regularly interacting with debugger.
If it *had* been needed, viewing the result right next to the expression that yielded it would have given me all the context I needed, in one window.
If you want to learn how to design a good set of classes, this is an absolutely dreadful problem. In fact ALL of the exercism problems are going to be dreadful for *that* purpose because they are provided for languages that do not *have* classes.
Yes, we noticed that. Do you have any problems more suited to class creation that we might contribute to the Exercism problem specifications?
If you want to learn how to *solve problems*, then you need to learn to write code that is simple, clear, testable, and so on. You certainly need to learn how to use what is already there in the language (except where that is expressly forbidden).
My understanding of the Exercism's purpose is: * not to teach how to solve programming problems; but * to facilitate existing programmers to develop fluency in new languages (although that doesn't preclude complete beginners using it). [ref: search "fluency" at https://opensource.com/article/17/1/interview-katrina-owen-founder-exercism]
I completely agree that designing a good set of classes is a very very important skill for anyone who wants to do OOP. I completely agree that practising this on problems you can hold in your head is a good idea. I completely agree that if *that* is your objective, writing minimalist code is not the best strategy.
On Wed, 24 Apr 2019 at 16:59, Richard O'Keefe <raoknz@gmail.com> wrote:
TL;DR version: "But if the purpose of problems is to lead students in new ways of thinking about structuring OO solutions for maintainability" It would be very good if somebody did craft such a set of exercises, and Pharo would be a very good environment for them. The exercism exercises will not do.
If the existing set of exercises is not great for this, hopefully we can produce some to demonstrate Pharo's facility for it.
The problem with exercism is that while it does have a criterion by which you can tell whether you have *solved the problem*, it provides *no* way to assess your class design. You don't get told "this is good, that is bloated"; there is no feedback about the *quality* of your code except via comments from those few people who can be bothered to look at other people's solutions and comment on them. And since many of them will also be beginners, their comments may not always help.
Hopefully we can grow participation of experienced mentors to share the load providing *quality* feedback to distinguish the benefits of Pharo.
This particular problem is very similar to a "Langton's Ant" problem my old department gave to students, who were expected to solve it in two or three hours. And ALWAYS, the thing that held them back was creating classes they didn't need and agonising over what data and methods should go where (and then getting it wrong, such is the nature of Java).
My immediate reaction to that is that agonizing and getting it wrong are a useful part of the learning process, but I recognize I could just be being contrary :) . I'll keep your observations in mind.
When a problem can be solved quite directly in 18 lines of clean code, you are going to have a very hard time persuading me that even one more class pays for itself, especially in a system with a rich class library of stuff you don't have to write.
Not trying to persuade you personally. Just providing an alternative viewpoint for anyone to consider. cheers -ben
Thanks all. Because of all the differences of oponion here what Object Oriented is and im still very stuck at some exercises of exercism , I have to decide to quit smalltalk. One says to not use classes , the other says use classes. im more and more confused. Maybe later I come back when I have a beter understanding what Object Oriented is and how I can use it to solve more difficult problems. Roelof Op 24-4-2019 om 18:07 schreef Ben Coman: > On Wed, 24 Apr 2019 at 16:52, Richard O'Keefe <raoknz@gmail.com> wrote: >> The one method needed to solve the problem is 18 lines. >> The test code, including all available test cases, is 27 >> lines, of which 18 lines is the test data. Tests were >> needed primarily to sort out what the problem actually *was*; >> exercism doesn't even try to provide good specifications. >> No debugging time at all was needed, precisely because the >> code was so simple and obvious. > But we do want to showcase our debugger and demonstrate how to get the > most out of it. > The way the exercises are structured is to sequentially enable one > test at a time, see how that fails and fix it, so students will be > regularly interacting with debugger. > > >> If it *had* been needed, >> viewing the result right next to the expression that yielded >> it would have given me all the context I needed, in one window. >> >> If you want to learn how to design a good set of classes, >> this is an absolutely dreadful problem. In fact ALL of the >> exercism problems are going to be dreadful for *that* >> purpose because they are provided for languages that do not >> *have* classes. > Yes, we noticed that. > Do you have any problems more suited to class creation that we might > contribute to the Exercism problem specifications? > > >> If you want to learn how to *solve problems*, >> then you need to learn to write code that is simple, clear, >> testable, and so on. You certainly need to learn how to use >> what is already there in the language (except where that is >> expressly forbidden). > My understanding of the Exercism's purpose is: > * not to teach how to solve programming problems; but > * to facilitate existing programmers to develop fluency in new > languages (although that doesn't preclude complete beginners using > it). > [ref: search "fluency" at > https://opensource.com/article/17/1/interview-katrina-owen-founder-exercism] > > >> I completely agree that designing a good set of classes is >> a very very important skill for anyone who wants to do OOP. >> I completely agree that practising this on problems you can >> hold in your head is a good idea. >> I completely agree that if *that* is your objective, >> writing minimalist code is not the best strategy. >> On Wed, 24 Apr 2019 at 16:59, Richard O'Keefe <raoknz@gmail.com> wrote: >>> TL;DR version: >>> "But if the purpose of problems is to lead students in new ways of >>> thinking about structuring OO solutions for maintainability" >>> It would be very good >>> if somebody did craft such a set of exercises, and Pharo would be a very >>> good environment for them. The exercism exercises will not do. > If the existing set of exercises is not great for this, hopefully we > can produce some to demonstrate Pharo's facility for it. > > >> The problem with exercism is that while it does have a >> criterion by which you can tell whether you have *solved the >> problem*, it provides *no* way to assess your class design. >> You don't get told "this is good, that is bloated"; there is >> no feedback about the *quality* of your code except via >> comments from those few people who can be bothered to look >> at other people's solutions and comment on them. And since >> many of them will also be beginners, their comments may not >> always help. > Hopefully we can grow participation of experienced mentors > to share the load providing *quality* feedback to distinguish the > benefits of Pharo. > >> This particular problem is very similar to a "Langton's Ant" >> problem my old department gave to students, who were expected >> to solve it in two or three hours. And ALWAYS, the thing that >> held them back was creating classes they didn't need and >> agonising over what data and methods should go where (and then >> getting it wrong, such is the nature of Java). > My immediate reaction to that is that agonizing and getting it wrong > are a useful part of the learning process, but I recognize I could > just be being contrary :) . > I'll keep your observations in mind. > >> When a problem can be solved quite directly in 18 lines of >> clean code, you are going to have a very hard time persuading >> me that even one more class pays for itself, especially in a >> system with a rich class library of stuff you don't have to write. > Not trying to persuade you personally. > Just providing an alternative viewpoint for anyone to consider. > > cheers -ben > >
Please don't quit Smalltalk. I never said not to use classes. That would be insane. I said that *this specific exercise* is one where *extra classes do not pay off. This is in no way whatsoever a debate about Pharo or Smalltalk. We'd be having exactly the same discussion in a list devoted to Java, Python, Ruby, or any other OO programming language. Please read http://www.cs.otago.ac.nz/cosc345/bickerton.htm It's a short page about learning. If you want to learn about OOP, the problem is not Pharo or Smalltalk or even me. It's that exercism is not designed to do that. It's designed to give people who already know what they are doing in one or more other languages practice in a new one. Do a web search for something like "How to learn OO design". You will find little things like <quote> qwertyuiop924 <https://news.ycombinator.com/user?id=qwertyuiop924> on Sept 14, 2016 <https://news.ycombinator.com/item?id=12495808> [-] Here's the OOP model: A program can be modelled as a set of communicating black-box objects, with their own state. The idea is to separate concerns, abstracting away implementation behind well-defined interfaces, which can in turn be implemented by other objects to cleanly replace parts of the application. The rest of OO is pretty much just understanding Design Patterns (a set of names for common interactions between objects, and methods for setting these interactions up), grokking inheritance, and the difference between inheritance and composition, and grasping how to design a good OO system (how thickly to layer your classes, how much abstraction and what sorts, etc.) The best languages for learning OO are Ruby and Smalltalk. </quote> in https://news.ycombinator.com/item?id=12495117 You will find articles like https://medium.com/@richardeng/the-consequences-of-learning-oop-the-wrong-way-3659bdf0b996 You will find courses. And look at the Pharo web site again: Stephan Ducasse has put up free copies of several books about Smalltalk. I think he now has every one I've heard of. Here's one link to get to them: http://stephane.ducasse.free.fr/FreeBooks.html Smalltalk and Object Orientation: an Introduction <http://sdmeta.gforge.inria.fr/FreeBooks/STandOO/Smalltalk-and-OO.pdf>, may be particularly helpful. On Thu, 25 Apr 2019 at 04:56, Roelof Wobben <r.wobben@home.nl> wrote: > Thanks all. > > Because of all the differences of oponion here what Object Oriented is > and im still very stuck at some exercises of exercism , I have to decide > to quit smalltalk. > > One says to not use classes , the other says use classes. im more and > more confused. > > Maybe later I come back when I have a beter understanding what Object > Oriented is and how I can use it to solve more difficult problems. > > Roelof > > > Op 24-4-2019 om 18:07 schreef Ben Coman: > > On Wed, 24 Apr 2019 at 16:52, Richard O'Keefe <raoknz@gmail.com> wrote: > >> The one method needed to solve the problem is 18 lines. > >> The test code, including all available test cases, is 27 > >> lines, of which 18 lines is the test data. Tests were > >> needed primarily to sort out what the problem actually *was*; > >> exercism doesn't even try to provide good specifications. > >> No debugging time at all was needed, precisely because the > >> code was so simple and obvious. > > But we do want to showcase our debugger and demonstrate how to get the > > most out of it. > > The way the exercises are structured is to sequentially enable one > > test at a time, see how that fails and fix it, so students will be > > regularly interacting with debugger. > > > > > >> If it *had* been needed, > >> viewing the result right next to the expression that yielded > >> it would have given me all the context I needed, in one window. > >> > >> If you want to learn how to design a good set of classes, > >> this is an absolutely dreadful problem. In fact ALL of the > >> exercism problems are going to be dreadful for *that* > >> purpose because they are provided for languages that do not > >> *have* classes. > > Yes, we noticed that. > > Do you have any problems more suited to class creation that we might > > contribute to the Exercism problem specifications? > > > > > >> If you want to learn how to *solve problems*, > >> then you need to learn to write code that is simple, clear, > >> testable, and so on. You certainly need to learn how to use > >> what is already there in the language (except where that is > >> expressly forbidden). > > My understanding of the Exercism's purpose is: > > * not to teach how to solve programming problems; but > > * to facilitate existing programmers to develop fluency in new > > languages (although that doesn't preclude complete beginners using > > it). > > [ref: search "fluency" at > > > https://opensource.com/article/17/1/interview-katrina-owen-founder-exercism > ] > > > > > >> I completely agree that designing a good set of classes is > >> a very very important skill for anyone who wants to do OOP. > >> I completely agree that practising this on problems you can > >> hold in your head is a good idea. > >> I completely agree that if *that* is your objective, > >> writing minimalist code is not the best strategy. > >> On Wed, 24 Apr 2019 at 16:59, Richard O'Keefe <raoknz@gmail.com> wrote: > >>> TL;DR version: > >>> "But if the purpose of problems is to lead students in new ways of > >>> thinking about structuring OO solutions for maintainability" > >>> It would be very good > >>> if somebody did craft such a set of exercises, and Pharo would be a > very > >>> good environment for them. The exercism exercises will not do. > > If the existing set of exercises is not great for this, hopefully we > > can produce some to demonstrate Pharo's facility for it. > > > > > >> The problem with exercism is that while it does have a > >> criterion by which you can tell whether you have *solved the > >> problem*, it provides *no* way to assess your class design. > >> You don't get told "this is good, that is bloated"; there is > >> no feedback about the *quality* of your code except via > >> comments from those few people who can be bothered to look > >> at other people's solutions and comment on them. And since > >> many of them will also be beginners, their comments may not > >> always help. > > Hopefully we can grow participation of experienced mentors > > to share the load providing *quality* feedback to distinguish the > > benefits of Pharo. > > > >> This particular problem is very similar to a "Langton's Ant" > >> problem my old department gave to students, who were expected > >> to solve it in two or three hours. And ALWAYS, the thing that > >> held them back was creating classes they didn't need and > >> agonising over what data and methods should go where (and then > >> getting it wrong, such is the nature of Java). > > My immediate reaction to that is that agonizing and getting it wrong > > are a useful part of the learning process, but I recognize I could > > just be being contrary :) . > > I'll keep your observations in mind. > > > >> When a problem can be solved quite directly in 18 lines of > >> clean code, you are going to have a very hard time persuading > >> me that even one more class pays for itself, especially in a > >> system with a rich class library of stuff you don't have to write. > > Not trying to persuade you personally. > > Just providing an alternative viewpoint for anyone to consider. > > > > cheers -ben > > > > > > >
Perhaps what's been unsaid in this thread is that sometimes exercises put some solution above all others (because it's presented as "the" answer). On the one hand, maybe the messages here make it seem like there's no single answer, as if the language was at fault. On the other hand, one learns more from exploring multiple avenues to solve a problem. I suspect that, after a while, one takes the latter attitude for granted. So, to be explicit, the cookbook way to programming will only get one so far. It's much better to consider multiple avenues, then weigh pros and cons. On 4/24/19 16:19 , Richard O'Keefe wrote:
Please don't quit Smalltalk. I never said not to use classes. That would be insane. I said that *this specific exercise* is one where *extra classes do not pay off. This is in no way whatsoever a debate about Pharo or Smalltalk. We'd be having exactly the same discussion in a list devoted to Java, Python, Ruby, or any other OO programming language. Please read http://www.cs.otago.ac.nz/cosc345/bickerton.htm It's a short page about learning.
If you want to learn about OOP, the problem is not Pharo or Smalltalk or even me. It's that exercism is not designed to do that. It's designed to give people who already know what they are doing in one or more other languages practice in a new one.
Do a web search for something like "How to learn OO design". You will find little things like <quote>
qwertyuiop924 <https://news.ycombinator.com/user?id=qwertyuiop924> on Sept 14, 2016 <https://news.ycombinator.com/item?id=12495808> [-]
Here's the OOP model:
A program can be modelled as a set of communicating black-box objects, with their own state.
The idea is to separate concerns, abstracting away implementation behind well-defined interfaces, which can in turn be implemented by other objects to cleanly replace parts of the application.
The rest of OO is pretty much just understanding Design Patterns (a set of names for common interactions between objects, and methods for setting these interactions up), grokking inheritance, and the difference between inheritance and composition, and grasping how to design a good OO system (how thickly to layer your classes, how much abstraction and what sorts, etc.)
The best languages for learning OO are Ruby and Smalltalk.
</quote>
in https://news.ycombinator.com/item?id=12495117
You will find articles like
https://medium.com/@richardeng/the-consequences-of-learning-oop-the-wrong-wa...
You will find courses.
And look at the Pharo web site again: Stephan Ducasse has put up free copies of several books about Smalltalk. I think he now has every one I've heard of. Here's one link to get to them:
http://stephane.ducasse.free.fr/FreeBooks.html
Smalltalk and Object Orientation: an Introduction <http://sdmeta.gforge.inria.fr/FreeBooks/STandOO/Smalltalk-and-OO.pdf>,
may be particularly helpful.
On Thu, 25 Apr 2019 at 04:56, Roelof Wobben <r.wobben@home.nl <mailto:r.wobben@home.nl>> wrote:
Thanks all.
Because of all the differences of oponion here what Object Oriented is and im still very stuck at some exercises of exercism , I have to decide to quit smalltalk.
One says to not use classes , the other says use classes. im more and more confused.
Maybe later I come back when I have a beter understanding what Object Oriented is and how I can use it to solve more difficult problems.
Roelof
Op 24-4-2019 om 18:07 schreef Ben Coman: > On Wed, 24 Apr 2019 at 16:52, Richard O'Keefe <raoknz@gmail.com <mailto:raoknz@gmail.com>> wrote: >> The one method needed to solve the problem is 18 lines. >> The test code, including all available test cases, is 27 >> lines, of which 18 lines is the test data. Tests were >> needed primarily to sort out what the problem actually *was*; >> exercism doesn't even try to provide good specifications. >> No debugging time at all was needed, precisely because the >> code was so simple and obvious. > But we do want to showcase our debugger and demonstrate how to get the > most out of it. > The way the exercises are structured is to sequentially enable one > test at a time, see how that fails and fix it, so students will be > regularly interacting with debugger. > > >> If it *had* been needed, >> viewing the result right next to the expression that yielded >> it would have given me all the context I needed, in one window. >> >> If you want to learn how to design a good set of classes, >> this is an absolutely dreadful problem. In fact ALL of the >> exercism problems are going to be dreadful for *that* >> purpose because they are provided for languages that do not >> *have* classes. > Yes, we noticed that. > Do you have any problems more suited to class creation that we might > contribute to the Exercism problem specifications? > > >> If you want to learn how to *solve problems*, >> then you need to learn to write code that is simple, clear, >> testable, and so on. You certainly need to learn how to use >> what is already there in the language (except where that is >> expressly forbidden). > My understanding of the Exercism's purpose is: > * not to teach how to solve programming problems; but > * to facilitate existing programmers to develop fluency in new > languages (although that doesn't preclude complete beginners using > it). > [ref: search "fluency" at > https://opensource.com/article/17/1/interview-katrina-owen-founder-exercism] > > >> I completely agree that designing a good set of classes is >> a very very important skill for anyone who wants to do OOP. >> I completely agree that practising this on problems you can >> hold in your head is a good idea. >> I completely agree that if *that* is your objective, >> writing minimalist code is not the best strategy. >> On Wed, 24 Apr 2019 at 16:59, Richard O'Keefe <raoknz@gmail.com <mailto:raoknz@gmail.com>> wrote: >>> TL;DR version: >>> "But if the purpose of problems is to lead students in new ways of >>> thinking about structuring OO solutions for maintainability" >>> It would be very good >>> if somebody did craft such a set of exercises, and Pharo would be a very >>> good environment for them. The exercism exercises will not do. > If the existing set of exercises is not great for this, hopefully we > can produce some to demonstrate Pharo's facility for it. > > >> The problem with exercism is that while it does have a >> criterion by which you can tell whether you have *solved the >> problem*, it provides *no* way to assess your class design. >> You don't get told "this is good, that is bloated"; there is >> no feedback about the *quality* of your code except via >> comments from those few people who can be bothered to look >> at other people's solutions and comment on them. And since >> many of them will also be beginners, their comments may not >> always help. > Hopefully we can grow participation of experienced mentors > to share the load providing *quality* feedback to distinguish the > benefits of Pharo. > >> This particular problem is very similar to a "Langton's Ant" >> problem my old department gave to students, who were expected >> to solve it in two or three hours. And ALWAYS, the thing that >> held them back was creating classes they didn't need and >> agonising over what data and methods should go where (and then >> getting it wrong, such is the nature of Java). > My immediate reaction to that is that agonizing and getting it wrong > are a useful part of the learning process, but I recognize I could > just be being contrary :) . > I'll keep your observations in mind. > >> When a problem can be solved quite directly in 18 lines of >> clean code, you are going to have a very hard time persuading >> me that even one more class pays for itself, especially in a >> system with a rich class library of stuff you don't have to write. > Not trying to persuade you personally. > Just providing an alternative viewpoint for anyone to consider. > > cheers -ben > >
Roelof, I second Richard on that. Maybe Exercism is important, but I don't know if is important enough to consider quitting Smalltalk because of the experience solving a problem there. Maybe sharing some of our personal experiences learning Smalltalk, the struggles and joys on that could put Exercism in perspective. In my case I started with Smalltalk via Etoys and Squeak in 2006 and 2007, but I left it as I can not "get it" all, despite of seeing the potence behind ideas like Dynabook and having rewarding experience in educational context with freshmen students. We used Etoys, Bots Inc and Scratch. The last was easier to get, but the others offered a better continuum to go from tile based programming to coding, so we combined all of them. But when I try to build more... "practical" things like OS scripting or data stories/visuals I struggle a lot with the Smalltalk environment, the paradigm switch and its purity, the absence of modern books and local communities and the kind of childish UI. It was like if I was growing in my needs, but the Squeak environment was so tailor suited for education with children that can not grow with me in more professional day to day tasks. Seven years later I found Pharo, so Smalltalk and I were changed enough for this meeting again experience. I have struggles again, particularly getting support with some issues related the GT, but the community was welcoming (as always), the books where more mature, the mailing list more active, and the level of fluency I get this time to express my old and new ideas in code was nothing I have experienced before in any computer language/environment. I chose a "real" world project as my learning experience this time (called Grafoscopio[1]) and despite it has a lot to improve and there is still newbie code here and there, any time I have the chance to working in it again, I'm really grateful of sticking around and keeping with the Smalltalk communities and the technology. [1] https://mutabit.com/grafoscopio/index.en.html So, my advice is don't let the Exercism experience let you down on Smalltalk. You could try with other approaches to learn, you could try with different books, or given yourself some distance, rest a little bit and be back here again. I know nothing about double dispatch, I'm learning design patters, I do not do TDD as common wise advices. I'm learning this by myself, following my own exploration and learning needs as they arrive, with the help of this community. And I know I'm getting better when I compare with myself years ago. So I expect to be here for the years to come and get even better and to showcase that in the code I write and share with this community. Would be nice to have around too. Cheers, Offray On 24/04/19 6:19 p. m., Richard O'Keefe wrote:
Please don't quit Smalltalk. I never said not to use classes. That would be insane. I said that *this specific exercise* is one where *extra classes do not pay off. This is in no way whatsoever a debate about Pharo or Smalltalk. We'd be having exactly the same discussion in a list devoted to Java, Python, Ruby, or any other OO programming language. Please read http://www.cs.otago.ac.nz/cosc345/bickerton.htm It's a short page about learning.
If you want to learn about OOP, the problem is not Pharo or Smalltalk or even me. It's that exercism is not designed to do that. It's designed to give people who already know what they are doing in one or more other languages practice in a new one.
Do a web search for something like "How to learn OO design". You will find little things like <quote>
qwertyuiop924 <https://news.ycombinator.com/user?id=qwertyuiop924> on Sept 14, 2016 <https://news.ycombinator.com/item?id=12495808> [-]
Here's the OOP model:
A program can be modelled as a set of communicating black-box objects, with their own state.
The idea is to separate concerns, abstracting away implementation behind well-defined interfaces, which can in turn be implemented by other objects to cleanly replace parts of the application.
The rest of OO is pretty much just understanding Design Patterns (a set of names for common interactions between objects, and methods for setting these interactions up), grokking inheritance, and the difference between inheritance and composition, and grasping how to design a good OO system (how thickly to layer your classes, how much abstraction and what sorts, etc.)
The best languages for learning OO are Ruby and Smalltalk.
</quote>
in https://news.ycombinator.com/item?id=12495117
You will find articles like
https://medium.com/@richardeng/the-consequences-of-learning-oop-the-wrong-wa...
You will find courses.
And look at the Pharo web site again: Stephan Ducasse has put up free copies of several books about Smalltalk. I think he now has every one I've heard of. Here's one link to get to them:
http://stephane.ducasse.free.fr/FreeBooks.html
Smalltalk and Object Orientation: an Introduction <http://sdmeta.gforge.inria.fr/FreeBooks/STandOO/Smalltalk-and-OO.pdf>,
may be particularly helpful.
On Thu, 25 Apr 2019 at 04:56, Roelof Wobben <r.wobben@home.nl <mailto:r.wobben@home.nl>> wrote:
Thanks all.
Because of all the differences of oponion here what Object Oriented is and im still very stuck at some exercises of exercism , I have to decide to quit smalltalk.
One says to not use classes , the other says use classes. im more and more confused.
Maybe later I come back when I have a beter understanding what Object Oriented is and how I can use it to solve more difficult problems.
Roelof
Op 24-4-2019 om 18:07 schreef Ben Coman: > On Wed, 24 Apr 2019 at 16:52, Richard O'Keefe <raoknz@gmail.com <mailto:raoknz@gmail.com>> wrote: >> The one method needed to solve the problem is 18 lines. >> The test code, including all available test cases, is 27 >> lines, of which 18 lines is the test data. Tests were >> needed primarily to sort out what the problem actually *was*; >> exercism doesn't even try to provide good specifications. >> No debugging time at all was needed, precisely because the >> code was so simple and obvious. > But we do want to showcase our debugger and demonstrate how to get the > most out of it. > The way the exercises are structured is to sequentially enable one > test at a time, see how that fails and fix it, so students will be > regularly interacting with debugger. > > >> If it *had* been needed, >> viewing the result right next to the expression that yielded >> it would have given me all the context I needed, in one window. >> >> If you want to learn how to design a good set of classes, >> this is an absolutely dreadful problem. In fact ALL of the >> exercism problems are going to be dreadful for *that* >> purpose because they are provided for languages that do not >> *have* classes. > Yes, we noticed that. > Do you have any problems more suited to class creation that we might > contribute to the Exercism problem specifications? > > >> If you want to learn how to *solve problems*, >> then you need to learn to write code that is simple, clear, >> testable, and so on. You certainly need to learn how to use >> what is already there in the language (except where that is >> expressly forbidden). > My understanding of the Exercism's purpose is: > * not to teach how to solve programming problems; but > * to facilitate existing programmers to develop fluency in new > languages (although that doesn't preclude complete beginners using > it). > [ref: search "fluency" at > https://opensource.com/article/17/1/interview-katrina-owen-founder-exercism] > > >> I completely agree that designing a good set of classes is >> a very very important skill for anyone who wants to do OOP. >> I completely agree that practising this on problems you can >> hold in your head is a good idea. >> I completely agree that if *that* is your objective, >> writing minimalist code is not the best strategy. >> On Wed, 24 Apr 2019 at 16:59, Richard O'Keefe <raoknz@gmail.com <mailto:raoknz@gmail.com>> wrote: >>> TL;DR version: >>>  "But if the purpose of problems is to lead students in new ways of >>>   thinking about structuring OO solutions for maintainability" >>> It would be very good >>> if somebody did craft such a set of exercises, and Pharo would be a very >>> good environment for them. The exercism exercises will not do. > If the existing set of exercises is not great for this, hopefully we > can produce some to demonstrate Pharo's facility for it. > > >> The problem with exercism is that while it does have a >> criterion by which you can tell whether you have *solved the >> problem*, it provides *no* way to assess your class design. >> You don't get told "this is good, that is bloated"; there is >> no feedback about the *quality* of your code except via >> comments from those few people who can be bothered to look >> at other people's solutions and comment on them. And since >> many of them will also be beginners, their comments may not >> always help. > Hopefully we can grow participation of experienced mentors > to share the load providing *quality* feedback to distinguish the > benefits of Pharo. > >> This particular problem is very similar to a "Langton's Ant" >> problem my old department gave to students, who were expected >> to solve it in two or three hours. And ALWAYS, the thing that >> held them back was creating classes they didn't need and >> agonising over what data and methods should go where (and then >> getting it wrong, such is the nature of Java). > My immediate reaction to that is that agonizing and getting it wrong > are a useful part of the learning process, but I recognize I could > just be being contrary :) . > I'll keep your observations in mind. > >> When a problem can be solved quite directly in 18 lines of >> clean code, you are going to have a very hard time persuading >> me that even one more class pays for itself, especially in a >> system with a rich class library of stuff you don't have to write. > Not trying to persuade you personally. > Just providing an alternative viewpoint for anyone to consider. > > cheers -ben > >
PS: in this thread nobody has disagreed about what OO programming is. The disagreement was about *how to apply it*. There actually seems to be quite a lot of agreement that the answer depends on what your underlying goal is: - is this throw-away code for a specific problem? - is this code to be included in a useful program? - is this just for practice in an unfamiliar language where you already understand all the concepts? - is this for learning about radically new concepts? And everyone agrees that test cases are good for all of these. You might find it useful to join another exercism thread and solve some of these problems in a language that you are comfortable with, then solve them in Smalltalk (or Ruby). This will help to separate "how do I solve this problem?" from "how do I express this solution in language X?" Another thing you might find useful, having solved a problem, is to try to solve it a different way. For example, in a functional language, you might solve a problem first in a C-like way using mutable objects freely. Then you might solve it again using immutable values. And then you might solve it again using higher-order functions. And then you might solve it again using point-free style as much as you can. For another example, in R, or Fortran 90, or Matlab, you might solve a problem first in an element-at-a-time way, and then you might try it again using vectorisation to eliminate as many loops as you can. And in *this* example, don't suppose that there is One Right Way To Do It. Get ONE solution going. ANY solution. I would suggest my approach, because (a) of course I would, and (b) it really is a struggle with exercism to find out what the problem actually is, and you want to get to SOME solution quickly. But it doesn't matter so much, because the point is to try it MORE ways than one. This is one way to learn design. Try more than one approach and discover which ones work out better. I started out using Point. Then I tried again just using bare coordinates. I started with position and velocity as instance variables. Then I tried again with them as method temporaries. I eliminated one thing after another until I was left with obviously correct code, and I felt no shame in using #caseOf: to classify characters, even though there are books that will tell you that using "if" and "case" is anti-OO. I could do it again eliminating #caseOf: in terms of "if" if I saw any value in doing so. In this particular exercise, you are simulating ONE instance (the robot) of ONE kind of thing (Robots). That strongly suggests that your solution might have ONE class: Robot, or perhaps TWO: Robot and RobotTest. That's the one active thing. This thing has properties: where it is and which way it is going. Now from the point of view of differential geometry, points and directions are different things and live in different abstract spaces, so I would have a lot of sympathy for having two classes: Place (x,y) and Direction (dx,dy) with #turnLeft and #turnRight as operations on Direction and place plus: distance in: direction as an operation on Place returning a new Place. But a good programmer is a lazy programmer, and looks for existing code to use. And the classic Point class in Smalltalk combines Place and Direction in one "two-dimensional vector" concept, originally designed for 2D computer graphics rather than geometry. It's good enough, and Smalltalk programmers can be expected to know that Point exists (just as Java programmers can be expected to know about Java's point classes), so I'd use it. So now, from one mind, we have designs with 1 Robot 2 Robot, RobotTest 3 Robot, RobotTest, Point 4 Robot, RobotTest, Place, Direction classes. ANY of them could be defended as a good design, depending on what the ultimate aim is.
For what it is worth, I have now completed two thirds of the Exercism tasks for Pharo. That's about 24 of them, maybe 1 or 2 more. ONE of them warranted the creation of another class (the Tournament exercise deserves a Team class). MOST of them were no-data classes with just one method. A couple of them required multiple methods, which in turn required state in the class, but not many. In each exercise the framework forces you to have at least two classes: Solution -- defined by you SolutionTests -- provided and you have to glean the interface from the SolutionTests class. Your suggestion for a Direction class is perfectly reasonable, and would be the right thing to do if Point did not exist or if you made a conscious decision to avoid it for practice reasons. I suppose the idea is that you push the testing button beside the SolutionTests class, and when an undefined class or undefined message is encountered, use the debugger to begin creating it. I found it helpful NOT to do that, but to survey *all* the tests first to find out what methods were required and from that to work out what state had to be maintained. On Thu, 25 Apr 2019 at 17:22, Roelof Wobben <r.wobben@home.nl> wrote:
Hello Ricard O' Keefe
For my exercism is a way of practising smalltalk and get familair with the concepts. So sometimes for me totally new concepts like Double Dispatch. so in your questions some of the thirth and fourth question. And I try to solve the challenges like there are real world problems.
Because Tim like to push me further then sometimes the challenges needed so I learn new concepts or practice things I already learned.
I agree totally with you that I always look if existing classes can do the job before I write my own objects.
The problem that I faced is that I not always see which objects I need and what the responsibility is.
Right now my thoughts are this :
RobotTests they contain all the tests. Robot . Responsibility for keeping track of what the position is and which direction it faces. Direction. Responsibility for calculating a new position or a new direction the robot faces.
Thanks for you suggestion to solve it first in a language that im familiar with but I not so familiair with a langugae I can solve "all" the problems. Because smalltalk is OO I sometimes look at ruby code to see how they solve things.
Roelof
Op 25-4-2019 om 06:23 schreef Richard O'Keefe:
PS: in this thread nobody has disagreed about what OO programming is. The disagreement was about *how to apply it*. There actually seems to be quite a lot of agreement that the answer depends on what your underlying goal is: - is this throw-away code for a specific problem? - is this code to be included in a useful program? - is this just for practice in an unfamiliar language where you already understand all the concepts? - is this for learning about radically new concepts? And everyone agrees that test cases are good for all of these.
You might find it useful to join another exercism thread and solve some of these problems in a language that you are comfortable with, then solve them in Smalltalk (or Ruby). This will help to separate "how do I solve this problem?" from "how do I express this solution in language X?" Another thing you might find useful, having solved a problem, is to try to solve it a different way.
For example, in a functional language, you might solve a problem first in a C-like way using mutable objects freely. Then you might solve it again using immutable values. And then you might solve it again using higher-order functions. And then you might solve it again using point-free style as much as you can.
For another example, in R, or Fortran 90, or Matlab, you might solve a problem first in an element-at-a-time way, and then you might try it again using vectorisation to eliminate as many loops as you can.
And in *this* example, don't suppose that there is One Right Way To Do It. Get ONE solution going. ANY solution. I would suggest my approach, because (a) of course I would, and (b) it really is a struggle with exercism to find out what the problem actually is, and you want to get to SOME solution quickly. But it doesn't matter so much, because the point is to try it MORE ways than one. This is one way to learn design. Try more than one approach and discover which ones work out better.
I started out using Point. Then I tried again just using bare coordinates. I started with position and velocity as instance variables. Then I tried again with them as method temporaries. I eliminated one thing after another until I was left with obviously correct code, and I felt no shame in using #caseOf: to classify characters, even though there are books that will tell you that using "if" and "case" is anti-OO. I could do it again eliminating #caseOf: in terms of "if" if I saw any value in doing so.
In this particular exercise, you are simulating ONE instance (the robot) of ONE kind of thing (Robots). That strongly suggests that your solution might have ONE class: Robot, or perhaps TWO: Robot and RobotTest. That's the one active thing.
This thing has properties: where it is and which way it is going. Now from the point of view of differential geometry, points and directions are different things and live in different abstract spaces, so I would have a lot of sympathy for having two classes: Place (x,y) and Direction (dx,dy) with #turnLeft and #turnRight as operations on Direction and place plus: distance in: direction as an operation on Place returning a new Place. But a good programmer is a lazy programmer, and looks for existing code to use. And the classic Point class in Smalltalk combines Place and Direction in one "two-dimensional vector" concept, originally designed for 2D computer graphics rather than geometry. It's good enough, and Smalltalk programmers can be expected to know that Point exists (just as Java programmers can be expected to know about Java's point classes), so I'd use it.
So now, from one mind, we have designs with 1 Robot 2 Robot, RobotTest 3 Robot, RobotTest, Point 4 Robot, RobotTest, Place, Direction classes. ANY of them could be defended as a good design, depending on what the ultimate aim is.
TL;DR version: "But if the purpose of problems is to lead students in new ways of thinking about structuring OO solutions for maintainability" That is not the purpose of the exercism problems. It would be very good if somebody did craft such a set of exercises, and Pharo would be a very good environment for them. The exercism exercises will not do. Betrand Meyer has an OOP course that gets students started *modifying* a non-trivial program, a traffic simulator I believe, instead of writing free-standing toy programs. Worth thinking about. On Wed, 24 Apr 2019 at 04:58, Ben Coman <btc@openinworld.com> wrote:
On Mon, 22 Apr 2019 at 23:15, Richard O'Keefe <raoknz@gmail.com> wrote:
I already discoursed on this at some length. (1) In my own answer, I used code to map direction names to vectors. But the Dictionary answers are absolutely fine. (2) I pointed out that there are ALREADY "turn left" and "turn right" operations on Points. (3) An elegant solution is one which wastes no effort. Introducing classes that you don't need is definitely wasted effort.
Elegance in art is in the eye of the beholder. You've got one position on it. I'll just balance it with an alternative view for students to consider around "classes that you don't need".
WARNING: untested first draft code (can't find the tested stuff). obey: commands |position direction| position := 0@0. direction := 1@0. commands do: [:each | each caseOf: { [$A] -> [position := position + direction]. [$L] -> [direction := direction leftRotated]. [$R] -> [direction := direction rightRotated] }]. ^{position. direction} You will need to fiddle with this a bit to get the mapping between problem coordinates and solution coordinates right, and you'll need that Dictionary mapping directions to direction names, but that's pretty much it.
If you define more than one class for this problem, your code is not elegant.
If the purpose of the problems is simply to solve the problem, then doing the absolute minimum is a reasonable view of elegance. After all, its throw away code. You're never going to be maintaining it.
But if the purpose of problems is to lead students in new ways of thinking about structuring OO solutions for maintainability within Pharo, then I feel its lacking. I remember an instructor from my youth advising that "practicing a kata poorly is the habit that will be reproduced automatically (in a crisis)"
^{position. direction}
For me, viewing {2@3. 1@0 } in a debugger is a much greater cognitive load than {2@3. 'Facing east'} to determine which direction its facing. So I consider the latter more elegant. TDD helps minimise class over-engineering, but for me the latter is a "need". In terms of throw-away exercises, its about what habits students want to gain from doing them.
Just another perspective. cheers -ben
On Fri, 19 Apr 2019 at 01:33, Roelof Wobben <r.wobben@home.nl> wrote:
oke
Maybe I understand something not right,
Lets say we have this scenario.
Robot is on position (0,0) now it turns left so the robot faces East
I think the required method was mentioned previously, but here is how to discover it yourself... + Tool > Finder > Examples + Enter... (0@1) . (1@0) <Search> finds... Point>>leftRotated e.g. (0@1) leftRotated ==> (1@0) On Fri, 19 Apr 2019 at 01:39, Roelof Wobben <r.wobben@home.nl> wrote:
Ben,
I have such a dictionary in my first attempt to solve this one. and another one for the facing.
This sounds strange that you have two Dictionaries. It can be useful to encapsulate the mapping to avoid that being littered around your Robot code... Object subclass: #Facing instanceVariables: 'map directionVector' Facing >> initialize map := Dictionary newFromPairs: { 'north'. (0@1) . 'west' . (0@1) leftRotated . 'south'. (0@1) leftRotated leftRotated. 'east' . (0@1) rightRotated }. directionVector := map atRandom. Facing >> directionString ^ map keyAtValue: directionVector Facing >> printOn: aStream " Facing new inspect " aStream nextPutAll: self className, '-', self directionString "The above is produces a minimum-viable object that displays nicely in Inspector to facilitate incrementally coding your scenario in TDD way..."
Lets say we have this scenario:
TestCase subclass: FacingTest FacingTest>>testAllTogether |position facing| "Robot begins at (0,0) facing north" position := 0@0. facing := Facing new face: 'north'. self assert: facing printString equals: 'Facing-north'. "then it turns right so it faces >>EAST<<" facing turnRight. self assert: facing printString equals: 'Facing-east'. "then it moves one step so the new position is (-1,0)" position := position + (facing movementSteps: 1). self assert: position equals: (-1@0). "then it turns left so it faces north again" facing turnLeft. self assert: facing printString equals: 'Facing-north'. "then it moves one step so the new position is (-1,1)" position := position + (facing movementSteps: 1). self assert: position equals: (-1@1). Which I'll leave as an exercise for you to complete with these hints... Facing >> face: aDirectionString directionVector := ... Facing >> turnRight directionVector := ... Facing >> turnLeft directionVector := ... Facing >> movementSteps: steps ^ ...
so if I see it , the position has nothing to do with the direction the robot is facing
yes. they only interact when the robot moves
this [position] is only important for finding out a new direction
no - position has no impact for determining the new direction
or to find out if the x or the y needs to change.
You don't need to treat x and y separately. Using Points for both the "position" and "directionVector" facilitates simple addition. cheers -ben
Roelof
Op 18-4-2019 om 19:17 schreef Richard Sargent:
On Thu, Apr 18, 2019 at 10:01 AM Roelof Wobben <r.wobben@home.nl> wrote:
yep, I have read that one but I never gets a answer how I can "convert" a point to something like north, east
because the challenge wants this to be the answer :
(Dictionary new add: 'direction' -> 'north'; add: 'position' -> (Dictionary new add: 'x' -> 0; add: 'y' -> 0; yourself); yourself)
If you have previously defined a "representation map", you would be golden.
e.g. Dictionary new at: self northDirectionVector put: 'north'; at: self eastDirectionVector put: 'east'; at: self southDirectionVector put: 'south'; at: self westDirectionVector put: 'west'; yourself.
Then: (Dictionary new add: 'direction' -> (self directionRepresentationMap at: self directionVector); ...
and I think I need then to use if then , which I try to avoid as much as possible.
Roelof
Op 18-4-2019 om 18:33 schreef Richard Sargent:
On Thu, Apr 18, 2019 at 8:57 AM Roelof Wobben <r.wobben@home.nl> wrote:
Hello,
I know I have asked earlier but im still stuck on this one : https://github.com/exercism/problem-specifications/blob/master/exercises/rob...
I tried with all double dispatch but that will be a lot of duplicate classes
The problem I cannot solve right is that a robot can move or turn. when a robot turns only the direction the robot is facing changes and the position not. when a robot moves the facing direction stays the same but the position changes. but the change is dependend on the facing. Also the new facing direction is dependend on the old facing direction/ How can I model this the best.
I already have a object Robot that contains the facing direction and the current position or tried without it but then I use a lot of if then's
so it there a better way to model this problem so it will be all nice and readable code.
If I remember correctly, Richard O'Keefe gave you a viable design. 1) Use a Point for your direction vector. 2) Use a second Point for your position.
e.g. if you align the compass with a Cartesian plane, 0@1 is North, 0@-1 is South, 1@0 is East, and -1@0 is West. When you move, you add the direction vector to your current position. If you allow movements of greater than a single unit, you multiply the direction vector by the distance before adding that product to the position.
Roelof
e.g. if you align the compass with a Cartesian plane, 0@1 is North, 0@-1 is South, 1@0 is East, and -1@0 is West.
On Fri, 19 Apr 2019 at 01:01, Roelof Wobben <r.wobben@home.nl> wrote:
yep, I have read that one but I never gets a answer how I can "convert" a point to something like north, east
Maybe you are looking for something like this... map := Dictionary newFromPairs: { 'north'. 0 @ 1 . 'south'. 0 @ -1 . 'east'. 1 @ 0 . 'west' . -1 @ 0 }. (map at: 'north') inspect. (map keyAtValue: 0 @ -1) inspect. cheers -ben
because the challenge wants this to be the answer :
(Dictionary new add: 'direction' -> 'north'; add: 'position' -> (Dictionary new add: 'x' -> 0; add: 'y' -> 0; yourself); yourself)
and I think I need then to use if then , which I try to avoid as much as possible.
Roelof
Op 18-4-2019 om 18:33 schreef Richard Sargent:
On Thu, Apr 18, 2019 at 8:57 AM Roelof Wobben <r.wobben@home.nl> wrote:
Hello,
I know I have asked earlier but im still stuck on this one : https://github.com/exercism/problem-specifications/blob/master/exercises/rob...
I tried with all double dispatch but that will be a lot of duplicate classes
The problem I cannot solve right is that a robot can move or turn. when a robot turns only the direction the robot is facing changes and the position not. when a robot moves the facing direction stays the same but the position changes. but the change is dependend on the facing. Also the new facing direction is dependend on the old facing direction/ How can I model this the best.
I already have a object Robot that contains the facing direction and the current position or tried without it but then I use a lot of if then's
so it there a better way to model this problem so it will be all nice and readable code.
If I remember correctly, Richard O'Keefe gave you a viable design. 1) Use a Point for your direction vector. 2) Use a second Point for your position.
e.g. if you align the compass with a Cartesian plane, 0@1 is North, 0@-1 is South, 1@0 is East, and -1@0 is West. When you move, you add the direction vector to your current position. If you allow movements of greater than a single unit, you multiply the direction vector by the distance before adding that product to the position.
Roelof
Ben, I have such a dictionary in my first attempt to solve this one. and another one for the facing. Lets say we have this scenario: Robot begins at (0,0) facing north then it turns right so it faces west then it moves one step so the new position is (-1,0) then it turns left so it faces north again then it moves one step so the new position is (-1,1) so if I see it , the position has nothing to do with the direction the robot is facing this is only important for finding out a new direction or to find out if the x or the y needs to change. Roelof Op 18-4-2019 om 19:27 schreef Ben Coman:
map := Dictionary newFromPairs: { 'north'. 0 @ 1 . 'south'. 0 @ -1 . 'east'. 1 @ 0 . 'west' . -1 @ 0 }. (map at: 'north') inspect. (map keyAtValue: 0 @ -1) inspect
I can't escape the feeling that this answer is leaving a lot on the table because the question is asked from a narrow perspective. On 4/18/19 10:01 , Roelof Wobben wrote:
because the challenge wants this to be the answer :
(Dictionary new add: 'direction' -> 'north'; add: 'position' -> (Dictionary new add: 'x' -> 0; add: 'y' -> 0; yourself); yourself)
You are so right! Q: now that I've gotten to the bottom of the Grand Canyon and found a narrow spot, how do I cross the river? A: WTF are you doing down there???? On April 18, 2019 11:41:48 PM PDT, Andres Valloud <avalloud@smalltalk.comcastbiz.net> wrote:
I can't escape the feeling that this answer is leaving a lot on the table because the question is asked from a narrow perspective.
On 4/18/19 10:01 , Roelof Wobben wrote:
because the challenge wants this to be the answer :
(Dictionary new add: 'direction' -> 'north'; add: 'position' -> (Dictionary new add: 'x' -> 0; add: 'y' -> 0; yourself); yourself)
I wanted to go for coffee! :P On 4/18/19 23:50 , Richard Sargent wrote:
You are so right!
Q: now that I've gotten to the bottom of the Grand Canyon and found a narrow spot, how do I cross the river?
A: WTF are you doing down there????
On April 18, 2019 11:41:48 PM PDT, Andres Valloud <avalloud@smalltalk.comcastbiz.net> wrote:
I can't escape the feeling that this answer is leaving a lot on the table because the question is asked from a narrow perspective.
On 4/18/19 10:01 , Roelof Wobben wrote:
because the challenge wants this to be the answer :
(Dictionary new add: 'direction' -> 'north'; add: 'position' -> (Dictionary new add: 'x' -> 0; add: 'y' -> 0; yourself); yourself)
participants (8)
-
Andres Valloud -
Ben Coman -
Offray Vladimir Luna Cárdenas -
Richard O'Keefe -
Richard Sargent -
Richard Sargent -
Roelof Wobben -
Tim Mackinnon