< Return to Video

rmod-pharo-mooc.lille.inria.fr/.../C019-Videos-Redo-DSL-HD_720p_4Mbs.m4v

  • 0:02 - 0:04
    This video is a Redo for the MOOC.
  • 0:05 - 0:07
    Redo means do it yourself,
  • 0:08 - 0:10
    watch the video and do what is
    shown step by step.
  • 0:10 - 0:13
    It is also an invitation to
    look at how we program.
  • 0:14 - 0:18
    I won't follow a precise script,
  • 0:18 - 0:20
    I will try to do it,
    but if I encounter bugs or
  • 0:20 - 0:23
    things like that, I'm gonna
    handle them as I go along.
  • 0:25 - 0:29
    In this video, the idea
    is to program a little
  • 0:29 - 0:32
    language that you can find
    in role-playing games like
  • 0:32 - 0:36
    "Dungeons and Dragons".
    For example,
  • 0:36 - 0:39
    for the ones who have this
    expression, what
  • 0:39 - 0:40
    does this expression mean?
  • 0:40 - 0:45
    It means: you must throw 2
    20-sided dice and 1 4-sided.
  • 0:46 - 0:47
    You'll see it can be a Pharo
    expression.
  • 0:48 - 0:52
    So in this video we're going
  • 0:53 - 0:55
    to implement a class representing
    a die and a class
  • 0:55 - 0:57
    representing a handful of dice.
  • 0:59 - 1:00
    So let's begin.
  • 1:01 - 1:04
    We begin with defining a package.
  • 1:06 - 1:07
    We call this package "Dice".
  • 1:07 - 1:12
    I don't really want to see
  • 1:12 - 1:17
    other things. So in this
  • 1:17 - 1:19
    video I won't code in the
  • 1:20 - 1:22
    debugger, you've seen it in another
    video, I will
  • 1:22 - 1:24
    do it on a case-by-case
    basis, in an opportunistic way.
  • 1:25 - 1:30
    Here I define the "Die" class
    which
  • 1:30 - 1:31
    has a certain number of "faces".
  • 1:32 - 1:36
    I compile. I add a class comment.
  • 1:43 - 1:46
    For the moment, not much thing
    because it is very very simple.
  • 1:48 - 1:52
    We are starting to enable our
  • 1:53 - 1:54
    object to be initialized.
  • 2:00 - 2:02
    I will do it like this.
  • 2:10 - 2:14
    I call for an initialization of
    the super-class,
  • 2:14 - 2:18
    by default I assign 6 faces
    to my die because it is
  • 2:18 - 2:19
    the most common die.
  • 2:20 - 2:23
    Now I'm starting to
    develop a
  • 2:23 - 2:26
    tests class, to be sure that what
    we do
  • 2:26 - 2:27
    doesn't break what has already
    been done.
  • 2:27 - 2:30
    Tests classes are sub-classes of the
    TestCase class.
  • 2:31 - 2:34
    We call it "DieTest".
  • 2:34 - 2:38
    I have my tests class.
  • 2:38 - 2:40
    One of the first tests to do,
    you
  • 2:40 - 2:42
    don't have always to do it
    like this, but
  • 2:43 - 2:47
    in any case I want to begin with
    a test that works well.
  • 2:48 - 2:52
    As for the moment we don't have many
    things, I say that initialization is ok.
  • 2:54 - 2:56
    This is also a way to show you
  • 2:56 - 3:00
    how you can test that you can
    catch exceptions
  • 3:00 - 3:01
    or that exceptions mustn't
    occur.
  • 3:02 - 3:05
    Here I am saying:
  • 3:05 - 3:06
    "Die new should not raise error".
  • 3:18 - 3:19
    What does it mean?
  • 3:19 - 3:23
    It means that when I execute this
    bit of code "Die
  • 3:23 - 3:26
    new", no error must occur.
  • 3:28 - 3:33
    I'm gonna classify my test
    and execute it.
  • 3:33 - 3:36
    It's green. All right.
  • 3:36 - 3:40
    So now, I'd like to define the
  • 3:40 - 3:45
    method that makes a die roll.
  • 3:45 - 3:49
    I know that in Pharo there must
    be a method
  • 3:49 - 3:50
    called "at Random".
  • 3:50 - 3:54
    At Random, what does it do?
  • 3:54 - 3:58
    It enables to have... Ok...
  • 3:58 - 4:01
    So now I look at the implementation
    to be sure
  • 4:01 - 4:04
    it's ok. AtRandom, what does it
    do?
  • 4:05 - 4:09
    It returns an integer at random
    from 1 to self, so it's perfect.
  • 4:11 - 4:14
    So I'm gonna define a new
  • 4:15 - 4:19
    method in Operations.
  • 4:21 - 4:22
    What will it do?
  • 4:22 - 4:27
    Roll. I say: "you return faces
  • 4:28 - 4:28
    atRandom".
  • 4:36 - 4:37
    So I write a test for this.
  • 4:40 - 4:44
    TestRolling. What do we do now?
  • 4:44 - 4:49
    We create a die.
    d:= die
  • 4:49 - 4:50
    new
  • 4:51 - 4:53
    And now I write
    "1000 timesRepeat".
  • 4:54 - 4:58
    What? "d roll".
  • 5:04 - 5:08
    And I want this to be
    between 1 and 6.
  • 5:08 - 5:13
    "Between: and:", it's
  • 5:13 - 5:16
    ok. "Between 1 and 6".
  • 5:16 - 5:19
    It is not very good
    because here we created
  • 5:19 - 5:22
    a test only for 6-sided dice,
    we could have said
  • 5:23 - 5:25
    it works depending on the
    number of sides of the die.
  • 5:26 - 5:27
    We will do it later.
  • 5:27 - 5:27
    So I compile.
  • 5:33 - 5:36
    I get an error. Here it is...
  • 5:38 - 5:39
    It is ok, I have my test.
  • 5:39 - 5:41
    Now it's time to save.
    Here I have my "Dice"
  • 5:42 - 5:45
    package, I save it locally,
    "Save".
  • 5:45 - 5:49
    I had created others before
    to train a little so I
  • 5:49 - 5:52
    create a new one
    "New version with
  • 5:57 - 6:01
    rolling and test". All right.
  • 6:01 - 6:02
    Ok, it is saved.
  • 6:11 - 6:15
    Now I'd like to change
  • 6:15 - 6:19
    the creation interface.
    First we rearrange
  • 6:20 - 6:22
    categories. If we want to change
    a little the creation
  • 6:22 - 6:26
    interface. We say:
    "to create a die
  • 6:27 - 6:28
    use die faces".
  • 6:39 - 6:43
    On this expression you must see
  • 6:43 - 6:46
    that faces is a message sent to
    the die class and not
  • 6:46 - 6:49
    to an instance of die class,
    as it is the case
  • 6:49 - 6:52
    in the roll method or in others
    methods coded until now.
  • 6:52 - 6:55
    I will do this for you to understand
    when you
  • 6:55 - 6:59
    have to use and go to the class
    level or not.
  • 6:59 - 7:01
    Let's begin by writing a test.
  • 7:03 - 7:06
    "betterInterface".
  • 7:09 - 7:10
    If I go on with the same logic,
  • 7:12 - 7:18
    "TestbetterCreationInterface",
  • 7:18 - 7:21
    Here I'd like to do something like
    this for instance,
  • 7:23 - 7:24
    and this to be faces.
  • 7:31 - 7:32
    I will do it slowly.
  • 7:33 - 7:37
    I go there and I type
    "instance creation", faces: , anInteger.
  • 7:47 - 7:49
    I could write it in a short way
    but here
  • 7:49 - 7:51
    I do it in a calm way.
  • 7:51 - 7:53
    I create a die.
  • 7:54 - 7:58
    I write "self new", as
    self here is the die class itself.
  • 7:58 - 8:00
    I tell: "create an instance".
  • 8:01 - 8:04
    And now with this instance I
    use
  • 8:04 - 8:08
    an accessor to assign it the value
    passed as an argument.
  • 8:09 - 8:12
    Obviously, I return the die
    that has just been created.
  • 8:14 - 8:17
    When the code will be executed,
    it won't work because
  • 8:17 - 8:20
    faces doesn't exist, so don't
    worry.
  • 8:20 - 8:23
    You see that the test isn't ok,
    but
  • 8:23 - 8:28
    it's normal, if I
    execute this
  • 8:28 - 8:30
    for example, if I do debug to see...
  • 8:34 - 8:38
    And I click on Over, here it
    says: "I don't know
  • 8:39 - 8:41
    the faces message."
  • 8:42 - 8:46
    Here we will do it calmly, I won't
    do it in the debugger.
  • 8:47 - 8:50
    I say: "that's true, I have
    to add an accessor
  • 8:53 - 8:57
    here. So I write
    faces: anInteger.
  • 8:58 - 9:02
    And there I write : faces := anInteger.
  • 9:05 - 9:08
    And while I'm at it, I create
    the read accessor.
  • 9:09 - 9:12
    I return this one.
  • 9:13 - 9:14
    And here my test is green.
  • 9:15 - 9:19
    So we save, "save"
  • 9:19 - 9:22
    "better die creation
    method with tests".
  • 9:22 - 9:23
    All right.
  • 9:32 - 9:34
    Now we can start to
  • 9:34 - 9:38
    define what we want for
  • 9:39 - 9:42
    diceHandle. Basically if we
    look, diceHandle,
  • 9:42 - 9:44
    how would we like to write it?
  • 9:44 - 9:45
    We would like to write
    diceHandle new addDie.
  • 9:49 - 9:53
    So now we are going to create
    a new die, "die faces 6, addDie".
  • 9:55 - 10:00
    "Die faces 10".
  • 10:07 - 10:12
    We start to write a
  • 10:12 - 10:14
    test class, this time.
  • 10:15 - 10:20
    So a new class which
    inherits from TestCase.
  • 10:20 - 10:22
    All right. I have my new
    tests class.
  • 10:24 - 10:27
    And I define a test.
  • 10:30 - 10:33
    The idea is to create a
    handful and to
  • 10:33 - 10:35
    check there are the right dice
    in it.
  • 10:35 - 10:39
    I write "testAdding",
    I want to reuse my
  • 10:40 - 10:44
    code, there is no reason otherwise.
  • 10:46 - 10:48
    So I have my
  • 10:54 - 10:59
    handle; yourself , because I
    want to
  • 10:59 - 11:02
    get the message receiver,
    it is to say the handle
  • 11:02 - 11:04
    and not the argument that is here.
  • 11:04 - 11:08
    Now what should I do?
  • 11:08 - 11:13
    I write "self
    assert h diceNumber
  • 11:14 - 11:15
    equals 2".
  • 11:21 - 11:23
    I compile. Obviously the system
    says: "I don't
  • 11:24 - 11:26
    know the DiceHandle variable. Do
    you want it
  • 11:26 - 11:27
    to be a class?"
  • 11:27 - 11:28
    Yes. It must be a class.
  • 11:29 - 11:30
    Here it will define it.
  • 11:30 - 11:31
    As I know that I have
    to stop the dice anyway
  • 11:32 - 11:36
    I take this opportunity to
  • 11:37 - 11:40
    put an instance variable.
  • 11:40 - 11:41
    I compile all this.
  • 11:42 - 11:46
    Now it's red because "Add die"
    hasn't been defined.
  • 11:48 - 11:49
    So we will do it.
  • 11:49 - 11:52
    Before doing this, it will
    be nice to initialise
  • 11:54 - 11:57
    the handle, so we do it like this,
    it will prevent
  • 11:57 - 11:58
    to have a bug later.
  • 12:03 - 12:05
    dice : = OrderedCollection new.
  • 12:05 - 12:05
    Recategorize.
  • 12:22 - 12:25
    And now, I must be able to
    run my
  • 12:25 - 12:28
    test, which will crash.
    Ok, very well.
  • 12:28 - 12:30
    I create Add die.
  • 12:31 - 12:31
    Adding.
  • 12:35 - 12:38
    It says: "You should implement
    this method."
  • 12:38 - 12:39
    Yes, it makes sense.
  • 12:39 - 12:42
    I write "Dice add aDie".
  • 12:44 - 12:46
    Ok, very good.
    My test won't still
  • 12:46 - 12:48
    work because I still don't
    have defined the diceNumber
  • 12:48 - 12:52
    method, let's do it.
    Yes, diceNumber,
  • 12:52 - 12:57
    we will create it, in
    accessing this time.
  • 12:57 - 12:59
    And diceNumber,
    what will it do?
  • 12:59 - 13:00
    It must return
  • 13:06 - 13:08
    dice size. I compile again,
    proceed.
  • 13:10 - 13:13
    And my test should be green
    so, the tests
  • 13:13 - 13:15
    are green and I save.
  • 13:17 - 13:19
    "With addDie and test".
  • 13:25 - 13:28
    We could improve the test because
    here
  • 13:28 - 13:32
    it checks that we add 2 numbers,
    I'd like
  • 13:32 - 13:35
    to check that when
  • 13:35 - 13:38
    we add twice the same die
    we don't lose it.
  • 13:38 - 13:39
    I write
    "TestAddingTwiceTheSame DieisOK".
  • 13:49 - 13:50
    Here what do I do?
  • 13:50 - 13:55
    I add 6 and 6 and I want to
    get 2
  • 13:57 - 14:00
    I do this I run my test,
    it's green, super.
  • 14:01 - 14:05
    Now, it will be nice to be able
  • 14:06 - 14:09
    to define what it is to do
  • 14:11 - 14:15
    add 2 dice. But before this,
    let's do something.
  • 14:15 - 14:17
    If you look, what I don't like,
  • 14:17 - 14:19
    when I inspect this for example,
  • 14:24 - 14:29
    if I do "Inspect"
    here, I don't see
  • 14:29 - 14:32
    the dice values and it's not
    practical to debug.
  • 14:32 - 14:33
    In the debugger, we don't see this.
  • 14:33 - 14:36
    So before going on, I want
    to improve
  • 14:36 - 14:38
    this. I'm going to add
    a method
  • 14:39 - 14:42
    in the Printing protocol.
    The "PrintOn" method
  • 14:44 - 14:47
    is defined on all the objects of
    the system and
  • 14:47 - 14:50
    it will convert an object to a
  • 14:51 - 14:53
    textual representation and
  • 14:55 - 14:59
    pass a stream. We will only precise
  • 14:59 - 15:00
    the representation we want
    inside it.
  • 15:02 - 15:04
    If I do this, I've done nothing
    in fact.
  • 15:04 - 15:08
    If I do super PrintOn, in fact I've
    done nothing.
  • 15:08 - 15:09
    Now I will do
  • 15:09 - 15:13
    "aStreamnextPut", so I will
    put characters in the
  • 15:13 - 15:15
    stream, but what will I
    put first?
  • 15:16 - 15:18
    I will write a parenthesis with a
    space, maybe it
  • 15:18 - 15:20
    will be nicer, a parenthesis.
  • 15:20 - 15:24
    Then I will consider faces
    and convert them
  • 15:24 - 15:28
    in numbers, in strings, and
    concatenate all this
  • 15:28 - 15:31
    with a closing parenthesis.
  • 15:31 - 15:35
    If I do this... I closed the debugger,
    so I open it again.
  • 15:36 - 15:39
    I have the debugger. Now
    I have a 6-sided die
  • 15:39 - 15:40
    and a 10-sided die. So it is
    much
  • 15:41 - 15:44
    nicer, you will see, if we
    encounter bugs, it will help.
  • 15:45 - 15:48
    So here I didn't do anything special,
    my tests are running.
  • 15:49 - 15:53
    I save again, it doesn't cost
    much, "With printing".
  • 15:55 - 15:56
    We write "with die printOn".
  • 16:03 - 16:08
    All right. Now we create the
    test, we won't
  • 16:08 - 16:10
    do it, we will go
    directly there.
  • 16:10 - 16:12
    We select "add
    protocol", "roll", "operations".
  • 16:14 - 16:18
    So,
  • 16:18 - 16:23
    there are several ways to define
    this.
  • 16:23 - 16:25
    I propose you one, this is not
    the nicest but
  • 16:25 - 16:27
    at least it is probably the
    clearest for you.
  • 16:28 - 16:29
    There is a compact way, I could
  • 16:29 - 16:31
    do it in one line, but using
    iterators
  • 16:32 - 16:33
    like "Injected to", here I'm
    gonna use a loop.
  • 16:34 - 16:34
    So what do I do?
  • 16:34 - 16:37
    I take a value that I
    initialize to zero.
  • 16:37 - 16:42
    Then I do a loop on all the dice,
    and
  • 16:42 - 16:47
    for each loop step I get
    a die, and what am
  • 16:47 - 16:48
    I going to do with this die?
  • 16:48 - 16:52
    I ask it to get a die roll
    and to add the result to
  • 16:52 - 16:53
    my variable.
  • 16:56 - 17:00
    Nothing very special but at least
    it is very very explicit.
  • 17:02 - 17:05
    Now if I do "Inspect" and there
  • 17:06 - 17:11
    "Roll", 5, it doesn't prove
    it is working.
  • 17:11 - 17:12
    Let's try once more.
  • 17:12 - 17:13
    11. Ok, it's working.
  • 17:14 - 17:16
    We are gonna try to write
    a test, there is
  • 17:16 - 17:20
    no reason, so we do
    "Test", I want to see this one
  • 17:22 - 17:23
    and I call it rolling.
  • 17:27 - 17:31
    So how do we have to do to test
    this?
  • 17:31 - 17:36
    It has to be between one and
    the maximum of the number of dice.
  • 17:38 - 17:42
    So we will do this.
  • 17:42 - 17:43
    We
  • 17:48 - 17:50
    could define a method
    doing this.
  • 17:50 - 17:53
    Let's create a method
    defining the maximum.
  • 17:57 - 18:00
    "Operation maxValue".
  • 18:02 - 18:03
    What is maxValue ?
  • 18:03 - 18:05
    It is very close to this.
  • 18:06 - 18:10
    Here instead of doing roll,
  • 18:11 - 18:12
    I will ask for the faces.
  • 18:17 - 18:20
    Let's check. If I do
    "Inspect", there
  • 18:22 - 18:25
    I do "maxValue", "16".
  • 18:28 - 18:30
    Yes, it's right 10 and 6.
  • 18:31 - 18:33
    So we write a test for
  • 18:37 - 18:42
    "maxValue". So I have this,
    I do "maxValue equal
  • 18:42 - 18:42
    16".
  • 18:45 - 18:48
    So here you see, I could have
    coded something
  • 18:48 - 18:51
    very dirty in my test, but
    finally, it is better
  • 18:51 - 18:54
    to create a method in the class
    and to use it.
  • 18:54 - 18:58
    So now, we can test the
    roll method
  • 18:59 - 19:02
    works well. Let's do
    "roll",
  • 19:06 - 19:09
    and say it must be comprised
  • 19:09 - 19:11
    between... "Roll between 1 and
  • 19:14 - 19:16
    h maxValue.
  • 19:24 - 19:26
    If I do this, ok it works.
  • 19:28 - 19:31
    This is not very statistical,
    so here we could do
  • 19:31 - 19:36
    something like
    1 000 timesRepeat.
  • 19:36 - 19:39
    Ok. And there,
  • 19:42 - 19:47
    we have our 1000 tests.
  • 19:48 - 19:49
    Now we save. All right.
  • 19:49 - 19:52
    We save once more.
    "save" added maxValue
  • 19:55 - 19:56
    and roll with tests.
  • 20:04 - 20:08
    We've almost finished,
  • 20:09 - 20:11
    what we want to express now,
    is
  • 20:11 - 20:14
    instead of having "die faces 6",
  • 20:16 - 20:18
    I'd like to have "1 D6".
  • 20:18 - 20:18
    And
  • 20:26 - 20:28
    what you see at the end is that
    it means "send
  • 20:28 - 20:31
    the message 6 to a small integer".
  • 20:32 - 20:35
    So we go and look at the
    integer class.
  • 20:35 - 20:40
    What we are going to do is
  • 20:40 - 20:44
    to define a class extension.
  • 20:44 - 20:45
    What is a class extension?
  • 20:46 - 20:50
    I'm gonna package my methods
    with the same name as my package.
  • 20:51 - 20:53
    So you will see, what do I do?
    I add a
  • 20:54 - 20:57
    protocol, I put *, it must
    start with *dice which is
  • 20:58 - 21:01
    my package's name, automatically
    this is put in grey, and
  • 21:01 - 21:03
    it means the method will be
    packaged
  • 21:03 - 21:04
    at the same time as this package.
    So let's do it.
  • 21:05 - 21:09
    Let's imagine we do...
    What is D6?
  • 21:10 - 21:14
    A D6... I have to think
    a little about it...
  • 21:21 - 21:24
    We first create a handle because
    it could
  • 21:24 - 21:26
    be 2 D6 finally.
  • 21:27 - 21:32
    So "handle", we do
    "diceHandle
  • 21:32 - 21:33
    new",
  • 21:37 - 21:38
    ok, so I have created my thing.
  • 21:39 - 21:42
    Now for each receiver,
    I will do
  • 21:42 - 21:45
    "self", this is my integer,
    "timesRepeat".
  • 21:46 - 21:50
    We will have really used a lot
    the timesRepeat, it's rare.
  • 21:52 - 21:54
    "TimesRepeat handle addDie", of what?
  • 21:57 - 22:01
    Of "die faces". And there,
  • 22:02 - 22:04
    we know it's 6.
  • 22:06 - 22:10
    And indeed, it would maybe be
    good to return the handle.
  • 22:11 - 22:12
    So does it work?
  • 22:12 - 22:15
    We're going to test like this and
    we write a test.
  • 22:15 - 22:20
    But if I do 2 D6, Inspect,
    look,
  • 22:21 - 22:22
    I do have 2 D6. So that's cool.
  • 22:23 - 22:24
    Let's write the test.
  • 22:26 - 22:27
    We will categorize those tests
    after all.
  • 22:28 - 22:29
    We write "testNewSyntax".
  • 22:34 - 22:36
    Here for the moment we only have
    D6, we will generalize later.
  • 22:38 - 22:40
    We want to do exactly the
    same thing
  • 22:40 - 22:44
    than this, so we will have
    an handle, let's say 2 D6.
  • 22:47 - 22:50
    And there, we do
    "selfAssert".
  • 22:53 - 22:54
    What could we test?
  • 22:55 - 22:56
    That diceNumber equals 2
  • 23:03 - 23:05
    for instance. So you've noticed
    sometimes I use
  • 23:06 - 23:09
    diceHandle, I could have also
    used = 2 here.
  • 23:10 - 23:12
    In general, it is nicer to use
    assert equal
  • 23:13 - 23:14
    because like this, when there is
    an error, the system
  • 23:14 - 23:18
    says: "I've received this and
    got this value instead of..."
  • 23:19 - 23:23
    If I write =, it will say:
    "I've got a wrong expression."
  • 23:24 - 23:26
    Here for the final user, who is
    yourself,
  • 23:27 - 23:29
    as a developer, it is better
    to use
  • 23:31 - 23:33
    assert equals because it will
    say: "I've received 3 whereas
  • 23:34 - 23:35
    I was expecting 2", for instance.
  • 23:36 - 23:37
    So here, I do this.
  • 23:38 - 23:39
    Ok, it works.
  • 23:39 - 23:42
    Could we have a smarter
  • 23:42 - 23:43
    version of this test?
  • 23:43 - 23:44
    For the moment, it suits us.
  • 23:45 - 23:47
    You see that now in
  • 23:47 - 23:50
    the package, I have an extension
    called D6.
  • 23:51 - 23:55
    We will generalize this
    with
  • 23:56 - 23:58
    "aNumberOfFaces"
  • 24:01 - 24:04
    So "aNumberOfFaces",
    we put it there.
  • 24:05 - 24:08
    And we rewrite D6 because it would
    be better.
  • 24:08 - 24:13
    We write D6 like this. We do
  • 24:13 - 24:17
    returns self D6.
  • 24:19 - 24:21
    We do all the other ones.
  • 24:21 - 24:24
    We do 4,
  • 24:26 - 24:31
    2. It's more a coin than a die,
    but 2,
  • 24:31 - 24:36
    10 and 20.
  • 24:36 - 24:38
    You've understood the principle.
  • 24:42 - 24:46
    So let's run the tests, as we've
    changed the implementation.
  • 24:47 - 24:49
    2 D6... it means it works.
  • 24:50 - 24:51
    So let's save.
  • 25:00 - 25:03
    What is there still to do?
  • 25:04 - 25:08
    In fact, we have still to be able
    to add the handles.
  • 25:09 - 25:12
    What tests do I want?
  • 25:12 - 25:15
    For instance, I want to be sure
    if I do
  • 25:19 - 25:23
    "addingHandles",
  • 25:23 - 25:26
    (I can use the new syntax,
  • 25:26 - 25:26
    so it's nice)
  • 25:27 - 25:29
    I want to test that if
  • 25:29 - 25:34
    I write 2 D20 + 3 D5
  • 25:34 - 25:39
    or 3 D6 instead (don't start to complicate
  • 25:39 - 25:42
    things). How much should I get ?
  • 25:43 - 25:47
    diceNumber should be equal to 5.
  • 25:48 - 25:52
    So here you see that we have to define
    the + operator.
  • 25:53 - 25:56
    In Pharo + isn't an operator,
    it's just a message.
  • 25:56 - 25:59
    So we define a message on the
    DiceHandle class.
  • 26:01 - 26:03
    We write +.
  • 26:05 - 26:06
    So "aDiceHandle".
  • 26:08 - 26:09
    Now we can wonder if
  • 26:10 - 26:12
    we modify the receiver or
    either if we use
  • 26:12 - 26:13
    a functional approach.
  • 26:13 - 26:15
    I prefer to use a functional approach
  • 26:15 - 26:17
    in which we create
    a new handle.
  • 26:20 - 26:24
    So I'm gonna create a
    new handle, I write
  • 26:26 - 26:28
    "handle self class new".
  • 26:30 - 26:34
    Here I avoided to write
    diceHandle and later there
  • 26:34 - 26:36
    will be a lesson explaining why.
  • 26:37 - 26:38
    I prefer, it's closer.
  • 26:38 - 26:40
    In general you don't hard-code
    the classes' name.
  • 26:40 - 26:43
    You will see it in week 7 or
    something like this,
  • 26:43 - 26:44
    there is a complete explanation.
  • 26:45 - 26:50
    If I do "self
    dice do", I
  • 26:50 - 26:53
    iterate on my dice
    and I add them in handle.
  • 26:54 - 26:56
    So I do
    "handle addDie each",
  • 27:00 - 27:04
    and I do the same...
    Here I don't
  • 27:04 - 27:06
    need self and in fact I don't
    know
  • 27:06 - 27:07
    the message, that's what it was
    telling me, and
  • 27:08 - 27:09
    it makes me notice that, indeed,
    I haven't defined it
  • 27:10 - 27:13
    and it hasn't worked for
    "diceHandle", but
  • 27:16 - 27:20
    no matter, let's compile first
    and we'll fix it later.
  • 27:21 - 27:22
    So here, what does it mean?
  • 27:23 - 27:25
    It means it lacks an accessor,
    dice.
  • 27:25 - 27:29
    So we add dice here,
    dice returns
  • 27:29 - 27:32
    the collection of my dice.
  • 27:32 - 27:35
    Now I'm gonna test, see if
    my test is ok.
  • 27:36 - 27:39
    My test is ok, it's super, it
    means I have
  • 27:39 - 27:44
    almost finished, I save,
    "with handles
  • 27:45 - 27:47
    additions". Ok, all right.
  • 27:50 - 27:54
    It means now we can write
  • 27:57 - 28:02
    2 D4 and we
  • 28:02 - 28:06
    can do "Roll", and it returns
    a number.
  • 28:08 - 28:10
    Now you are ready to play
    "Dungeons and Dragons".
  • 28:11 - 28:16
    What you have to know:
    we defined
  • 28:18 - 28:19
    our methods, we defined
    our tests, we run
  • 28:20 - 28:23
    them, we extended a system
    class,
  • 28:23 - 28:27
    the integer class, with extensions
    linked to our
  • 28:27 - 28:31
    package, which will only be visible
    when our package will be loaded.
  • 28:32 - 28:35
    We also overloaded operators,
    but
  • 28:35 - 28:39
    in fact we only defined a new
    + message, because
  • 28:39 - 28:44
    in Pharo the addition is
    just another message,
  • 28:44 - 28:48
    this enabled us to
    express quite easily a nice DSL.
  • 28:50 - 28:51
    So now it's your turn to code!
Title:
rmod-pharo-mooc.lille.inria.fr/.../C019-Videos-Redo-DSL-HD_720p_4Mbs.m4v
Video Language:
French
Duration:
28:53

English subtitles

Revisions