00:00:17.080
all right afternoon everybody my name is uh Greg Mech I work for a company called strobe and uh they sent me here so I
00:00:24.000
wanted to just Express a bit of uh gratefulness to that and also tell you that uh if you got guys are building any
00:00:31.359
JavaScript application that is talking to a backend um just basically as an API I would
00:00:38.239
encourage you to check out strobe it basically allows you to deploy the application to the web Android and iOS
00:00:45.000
just with a simple uh strobe deploy command so check that out if you want
00:00:51.039
and uh this afternoon I guess it's still morning I'm going to be talking about why you don't get mock
00:00:58.399
objects so first first uh matter of introduction a little bit about
00:01:04.159
me first thing you need to know is that I am not a primary teacher now you might
00:01:09.560
wonder what the heck is that but I am a secondary teacher let me explain what I
00:01:16.360
mean by that there's a quote from uh Mortimer Adler in his book how to read a
00:01:21.439
book where he says this the secondary teacher should regard himself as learning from the Masters along with his
00:01:27.840
students he should not act as if he were a primary teacher using a great book as if it were just another textbook of the
00:01:34.600
sort one of his colleagues might write he should not mascarade as one who knows and can teach by virtue of his own
00:01:40.960
original discoveries the primary sources of his own knowledge should be the primary sources of learning for his
00:01:46.560
students and such a teacher functions honestly only if he does not aize himself by coming between the great
00:01:52.960
books and their readers he should not come between as a nonconductor but he should come between as a mediator as one
00:02:00.039
who helps the less competent make more effective cont contacts with the best
00:02:05.119
Minds so when I say I am not a primary teacher but rather a secondary teacher I mean this I am not an expert on mock
00:02:12.480
objects in the sense that I develop them or come up with anything new basically in this talk basically everything I'm
00:02:18.720
going to say is something that somebody has said before probably better than me the only difference is that they
00:02:24.800
probably said it in relation to Java
00:02:30.319
this is uh the book that I think is probably the best book on mock objects and if you haven't read it you really
00:02:36.879
should go and get it it's called growing object-oriented software Guided by tests by Steve Freeman and Nat price these
00:02:43.560
guys are the primary teachers I'm just going to try to bridge the context today into
00:02:49.720
Ruby secondly let's talk a little bit about mock objects now the Ruby Community plus mock
00:02:56.599
objects equals what love
00:03:02.720
uh no not really mock objects have been called the
00:03:08.040
following inside of the Ruby Community wastes of time if you are using mock
00:03:13.560
objects you are wasting your time they have been called scams it's like somebody's trying to
00:03:19.239
pull the wool over your eyes and my personal favorite testing
00:03:26.120
heresies if you are are using mock objects you are a heretic and you deserve to be burned at the stake okay
00:03:32.200
maybe not quite that strong but still that seems to be the general reception
00:03:37.959
within the Ruby Community now why is that generally people give two reasons
00:03:44.560
as to why they don't like mock objects the first being that they duplicate implementation so here is an rspec
00:03:51.799
example from a talk that was given at Ruby comp in 2008 and you have uh describing a show
00:03:58.680
controller and it says when a TV show has no public videos it should not
00:04:03.720
display any shows and in order to do that it uses should receive all on the
00:04:10.439
show object with select ID name video count condition shows. video count
00:04:16.840
equals z and return an empty array and then it does the rest of the test and
00:04:22.240
then you come to the implementation and oh look show all
00:04:27.639
select ID name video count count conditions shows video count greater than zero you see that part right
00:04:35.880
there is exactly duplicated in the
00:04:41.039
implementation and they say well this is stupid if I want to change anything about this I'm going to have to change
00:04:46.680
both the tests and the implementation I'm just duplicating the system under test seems pretty bad
00:04:54.320
huh second I've heard it argued that it leads to brittle tests that do a poor job
00:05:00.840
so for example uh this is from the arpec book written by David chelimsky uh and
00:05:06.520
it's describing a codebreaker game and it says when the game starts it sends
00:05:12.320
the welcome message and in order to be able to do that it provides a mock object doubles as the output it says the
00:05:19.280
output should receive puts with welcome to codebreaker and then it says game.
00:05:25.960
start and then you come into the actual implementation and and you've got the same sort of thing output puts welcome
00:05:32.560
to code breaker but imagine we were to refactor this instead of using
00:05:38.880
puts we use wrs that would be the same from the end user perspective and yet guess what
00:05:46.080
happens if you change that the tests fail oh wow that's stupid I mean the end
00:05:52.960
behavior is the same why would I ever use these the output doesn't change QED right right end of story mock
00:06:04.600
suck well maybe or maybe you just don't understand
00:06:11.840
them in fact actually uh there was a talk that I was G going to give on a
00:06:17.199
clean arpec at the LA Ruby uh Meetup and I was going to slam on mock objects
00:06:23.440
pretty bad because I thought that they did exactly these sorts of things and then I stopped and I said
00:06:31.039
this is this seems so obvious if this is how mock objects are supposed to be used why would anybody
00:06:38.520
ever have invented these pieces of junk and I said okay well maybe I just
00:06:44.240
don't understand them so I'm not going to slam on them until I understand them
00:06:50.400
which by the way just a piece of practical advice is usually a pretty good idea
00:06:59.800
when smart people invent something and then you think hey man this is so
00:07:05.960
stupid don't say that to anybody until you actually understand it
00:07:12.840
then if you want to declare it stupid that's fine but make sure you understand it before you start talking or you're going
00:07:20.199
to end up looking like a fool okay so why then would we use mock objects let's talk about that a little
00:07:27.840
bit the first thing I want want to say is that mock objects plus procedural programming is a bad
00:07:34.199
idea almost always first thing related to that mocks are not
00:07:40.319
stubs now I hear a lot of people talk about well I'm just going to mock out that object because mock objects are the
00:07:46.599
way that people generally have done that but there is a subtle distinction between what is a mock object and what
00:07:51.720
is a stub mocks assert on messages that go between objects whereas stubs return a value
00:08:01.159
so a stub is going to say when you call this method give this value back so that I can assert on some state within the
00:08:07.800
object a mock is actually designed to get in between the two objects and allow
00:08:13.319
you to assert on the message going between the two so for example here in this show
00:08:19.120
controller this part right here is really a stub now there is an
00:08:24.280
expectation on it because it has a should receive but the point is that
00:08:29.840
when I call this method I want it to return an empty array so that I don't have to talk to the database or whatever
00:08:36.039
and you can tell that this is actually a stub and not a mock because you're actually asserting
00:08:41.360
on the body it's asserting on state when you're asserting on state you're stubbing when
00:08:48.160
you're asserting on messages between objects you're mocking so mocking plus procedural
00:08:55.600
programming is a bad idea but mocking plus oop is a good
00:09:01.120
idea so the key idea in object-oriented programming is objects tell objects to
00:09:07.640
do things now I know we don't write our code this way a lot inside of the Rails
00:09:12.920
community at least but I think we're moving in that direction a little bit there's been a lot of chatter on the
00:09:18.200
blogosphere and on like the Ruby Rogues podcast lately about moving towards objectoriented programming more of a
00:09:24.720
tell don't ask sort of style and uh this is uh what Allan K had to say about
00:09:31.120
object oriented program how many of you know who Alan K is okay that's encouraging for those of
00:09:37.600
you who don't he's the inventor of small talk and kind of the guy who coined the idea of object-oriented programming to
00:09:44.120
begin with and he says this the big idea of object-oriented programming is
00:09:49.720
messaging that is what the kernel of small talk or squeak is all about the
00:09:54.839
key in making great and growable systems is much more to design how it's mod modules communicate rather than what
00:10:01.839
their internal Behavior should be so for example this might be uh
00:10:07.680
internally what your system would look like the circles represent objects and
00:10:13.440
the arrows in between are the messages that they send hey do this hey do this hey do this and what Alan K is saying is
00:10:20.800
that the key important thing in growing objectoriented systems is not to worry
00:10:26.320
about what is contained inside of the objects but but to worry about the messages that go between them that it is
00:10:33.760
inside of the messages of an object-oriented program that the meaning or the uh domain logic of the
00:10:41.720
application is truly found so for example to change the
00:10:47.079
behavior of a system we compose objects instead of modifying methods so let's
00:10:54.000
look at a contrived example see if we can see what what I have in mind here imagine that you have have a ticket
00:11:00.120
machine interface maybe it's like an ATM you've got a bunch of buttons and you're going to type in the number of tickets
00:11:05.680
that you want to use then you're going to push submit okay and you've got this ticket
00:11:10.720
machine object and you've got a ticket reserving system you're going to say hey
00:11:17.000
I pushed you know this number and then this number then I pushed submit and it should Reserve those uh tickets for me
00:11:26.800
imagine if you wanted to save the request before sending them okay you have this
00:11:32.000
object it manages the interface you want to save the request maybe to a database or something before you send the
00:11:39.320
request in procedural programming how would you do that well you'd go to the method that does it and you would add
00:11:45.800
code to that method you would insert okay before you do this you're going to
00:11:51.480
add this code and then you can do what you were doing before whereas object-oriented programming says once an
00:11:56.600
object is complete and it does what you want it to do in order to modify Its Behavior you shouldn't have to change
00:12:02.480
the object itself you just change the object composition so for instance you
00:12:08.600
have the ticket machine interface and it still is reserving tickets but you put another object in
00:12:16.399
between the two objects to persist the ticket requests and then it calls the
00:12:21.920
same API on the ticket Reserve System and this enables you to not have to
00:12:27.040
change the code that you already know is working you just change the composition of the
00:12:33.160
objects so what would code for this interface look like maybe something like
00:12:39.639
this you have the ticket machine interface on initialization you have a request Handler and you store the
00:12:45.839
current display when a number is pressed you add that number to the current display when delete is pressed you drop
00:12:52.959
off the last number that went on and when you submit the request you tell the request Handler to reserve a current
00:12:59.800
display to I to those of you who are are not used to working in more of an O style this might be a little weird but
00:13:05.560
this is basically how tell don't ask well-encapsulated code
00:13:11.680
works and there are two things that you want to notice about this first it follows the tell don't ask
00:13:19.040
principle notice everything is being the object is being told things hey this
00:13:25.440
number was pressed delete was pressed submit this request so it's following
00:13:33.160
tell don't ask it's not asking for information out of the objects in order to make decisions based off of that
00:13:38.839
information that it gets back it's telling the object certain things have happened or to do certain
00:13:44.560
things second notice that it hides its internal State what is the internal State
00:13:51.519
here it's that current display whatever is currently being displayed is what
00:13:56.560
this object is encapsulating and hiding data for and notice that there are no
00:14:01.880
Getters on this object there's no way really to get at this current display
00:14:08.120
except in Ruby this actually does return the thing right but it's supposed to be a command not a
00:14:14.680
query and so now all of a sudden we've got this internal state that is
00:14:20.000
completely hidden and we have no ability to access it which leads to a question
00:14:26.399
how could you write a unit test for this code
00:14:31.839
usually when we do tdd we think of it in terms of I call an API it's going to change the state on the object and then
00:14:37.399
I'm going to assert that this state is now this that it did what I expected but if I'm hiding all of the internal
00:14:43.959
implementation of my code how would I test this can you assert on the state no
00:14:50.320
you don't have access to the internal State and by the way that's a good thing if you don't think it is you should read
00:14:56.040
up on information hiding it allows you to build complex apis that you don't have to know the implementation of all
00:15:02.079
you have to know is its API in order to be able to use it it basically becomes a black box an
00:15:08.160
abstraction all of us expect that of our libraries can you imagine a library that you had to know the internal details in
00:15:14.759
order to be able to use it but we don't generally expect that of our own code base but when we start moving in that
00:15:21.959
direction hiding the internal implementation of the object we no longer can see its internal State we can
00:15:27.480
only see what it does and so how would we unit test this well one method that's
00:15:33.120
been proposed is just add Getters for the tests I don't really think that's a good
00:15:38.360
idea because when you start modifying and adding special paths into your code
00:15:43.759
just in order to be able to test it you're not actually operating on the
00:15:48.880
path that your code is going to run in production it seems bad to me so then how would you do the
00:15:55.000
test well remember this is kind of our picture we have this ticket machine interface and these objects are telling
00:16:00.839
each other to do things so what if instead of actually using a real ticket Reserve System I replaced that ticket
00:16:08.079
Reserve System oh I guess I don't have the ability to get
00:16:14.199
into the test but I can assert on the message going between the tests kind of
00:16:19.839
like Alan K said the key thing is the messages going between and so I can assert on the message that the ticket
00:16:25.920
machine is telling the ticket Reserve System so how would I do that well
00:16:31.519
instead of re re using a real ticket Reserve System I'm going to replace it
00:16:36.880
pass it into the Constructor with a fake object and this fake object is what we
00:16:42.399
call a mock object and so my test would look something like this my request
00:16:49.600
Handler should receive Reserve with 55 and you see I'm passing that that
00:16:56.319
request Handler in in the place of that ticket Reserve
00:17:02.720
System you see I'm replacing it with a mock object a fake and the the the
00:17:08.720
responsibility of this mock object is to record every message that is sent to the object so that I can then assert on
00:17:15.959
those messages that were sent and so I I say hey mock object this
00:17:21.880
is my assertion you should receive the message Reserve with these parameters
00:17:28.240
passed to it and that's the assertion on the message
00:17:34.559
going between the two objects and then I call the public API I
00:17:40.400
pressed five and then I pressed five again and then I pressed the submit
00:17:45.440
button and that should send the message Reserve with the number
00:17:52.480
55 here's the key idea o in oop behavior is found in the messages
00:17:59.880
and so we don't want to assert on the state of an object we want to assert on the messages going between the objects
00:18:06.960
and in order to be able to do that we replace real objects with fake objects or mock objects in order to be able to
00:18:13.600
assert on those messages okay so having said that then
00:18:20.520
it takes a little bit of a change of mindset in the way you do programming honestly if you just are doing a rails
00:18:27.120
application that you are doing things procedurally odds are mock objects are not for
00:18:32.960
you it's kind of like this okay if you wanted to bang a nail into a piece of
00:18:40.200
wood you want to use a hammer a screwdriver might
00:18:45.280
work but a screwdriver is not designed to bang in the nail you want to use a
00:18:50.720
hammer which is generally assertions on state when you're doing a more procedural flow when you are hiding your
00:18:56.320
information encapsulating it and telling other objects to do something then you pull out the tool called the mock object
00:19:03.320
because that's what they're designed to be used for so let's talk a little bit then
00:19:09.240
knowing that about some key mocking rules and I'm taking all of these from
00:19:14.320
Steve Freeman and Nat price over the years so again I am completely not
00:19:19.400
unique or interesting the only difference is is that I'm using Ruby whereas they are using
00:19:24.880
Java so the first rule is mock roles not objects what do I mean well here's the
00:19:32.360
paper that they wrote for oopsa in 2004 if you want to look it up that's actually entitled mock roles not
00:19:39.840
objects and the basic gist is wanting to mock concrete objects is a design
00:19:47.880
smell that is it's telling you the implementation of your actual code has a
00:19:55.480
problem why because well-designed objects don't know explicitly who they
00:20:00.520
are talking to why because who they are talking to
00:20:06.480
can change they should only know the role that their collaborator is
00:20:12.840
playing not the concrete object which they are talking to so for example in
00:20:17.919
our ticket machine interface this role on the right side
00:20:22.960
that the ticket Reserve System is playing is may be called the ticket machine request Handler it handles
00:20:29.200
requests from the ticket machine the ticket machine doesn't need to know that it is particularly talking to a real
00:20:35.919
ticket Reserve System and in fact if you know that you're talking to a real ticket Reserve System you can't do
00:20:41.760
something like this you see now I've changed the composition of the objects and now
00:20:49.120
instead of the ticket Reserve System playing the role of the ticket machine request Handler my persist ticket
00:20:57.400
requests object is playing the role of my Reserve or my ticket machine request
00:21:03.440
Handler and from the perspective of the ticket machine I need to not care what the actual object is doing
00:21:10.679
when I send it the message all I need to know is what are the roles that the potential collaborators are playing so
00:21:17.360
that I can tell them to do something and then let them carry out their things and so when mocking rolls tdd
00:21:25.600
becomes a design process not merely about asserting that the behavior is
00:21:31.600
correct although it does that too it becomes a question of what are the roles
00:21:37.679
that my collaborating object should be playing that is what doesn't belong internal to my object so for example if
00:21:45.600
I start with just a ticket machine interface and presumably I have you know come to this interface through some form
00:21:52.799
of tdd so I already know what role it's playing because I know that there's
00:21:57.919
going to be an object sending messages to it so I start with this I know it's going to have number pressed delete
00:22:03.760
pressed and submit request what do I do well I'm going to come up with a
00:22:10.799
scenario that is going to demonstrate the domain logic of this Behavior it reserves the correct number of tickets
00:22:17.360
when a number is pressed two times before submitting and I would say okay here's a scenario kind of like what Jim
00:22:22.440
was talking about earlier given a ticket machine interface when I press five
00:22:29.440
twice which is machine number pressed five times and then I submit the request
00:22:35.159
what would be the proper behavior and then I ask myself okay does
00:22:40.520
this behavior that it's supposed to do is it supposed is is this really behavior that belongs inside of my
00:22:46.559
ticket machine interface if it's following the single responsibility principle an object
00:22:52.080
should have one and only one reason to change I don't want to actually put the logic for handling the request
00:22:59.279
in the same place that I'm going to put the logic for handling the interface
00:23:05.039
those belong to two separate things and so I okay I say okay what is the role
00:23:10.240
that the collaborating object here needs to play well I need whatever object I'm
00:23:16.799
going to tell to handle a request when I am ready to send one and so I create a
00:23:23.640
mock object not an actual object that is going to be implemented but a role that
00:23:30.840
that object is going to play particularly here it's the request Handler and I'm going to say okay what
00:23:36.919
Behavior should I tell this object to do I should tell it that it needs to
00:23:43.640
reserve 55 tickets because I pushed 55 twice and then I told it to submit the
00:23:51.440
request and then I come back and I say okay I have this role so I need to pass
00:23:56.960
it into my Constructor I add it to the Constructor and I know I'm going to submit my request I'm going to do re
00:24:03.600
request Handler reserve and I'm going to need to send it whatever the current display is now this should start to feel
00:24:09.440
like tdd to you hey wait a second okay I'm sending the current display but I'm
00:24:15.120
not doing anything with the current display yet so if I want to get it to actually send the right message I have
00:24:21.880
to implement the number pressed API so that it is storing whatever the current display is as it goes along and so I add
00:24:28.919
an internal State current display and I say number pressed when that happens add
00:24:34.480
that to the current display and when I send it I want it to be an integer by the way you'll notice this is
00:24:40.720
not complete code because if I were to just immediately push submit request what's it going to send an empty string
00:24:47.120
to I guess I need more test cases right but you see this is the same sort of
00:24:52.200
thing in the way that you do tdd normally the only difference is you are asserting on a message instead of
00:24:59.399
asserting on the state of the object and what you end up doing is you
00:25:04.840
end up getting a more decoupled system because now you're talking to a role and you're following this it helps
00:25:12.080
you to follow the sing Single inter or the single responsibility Principle as well as a bunch of the
00:25:18.399
other solid design techniques so the first thing is mock
00:25:24.559
roles not objects the second rule is only mock types that you own now in
00:25:32.080
Ruby we don't really have types but the idea I think still holds here's uh two references I put
00:25:39.200
these in primarily so that if you want to look at the slides afterwards you can look them up and here's the basic rule
00:25:45.159
if you don't own the API there is no design feedback that you were going to get by writing a test for
00:25:53.640
it instead of mocking a role what you are really mocking is an
00:25:59.000
implementation because you don't own the API and you can't form it into whatever the role is going to be
00:26:05.760
played and so what you end up doing is you end up duplicating your production code in your test which is a test smell
00:26:16.080
that doesn't mean you should never do it right it just means when you smell it you should go H do I really need to do
00:26:24.120
this and so this means don't mock boundary objects what do I mean by that
00:26:29.520
here's the example that we talked about earlier in relation to the Codebreaker game from the rspec book and by the way
00:26:36.320
when uh this came up on a Blog Dave chelimsky actually said that this is the
00:26:42.320
way you should do it so I'm I'm not necessarily critiquing David um but here
00:26:47.720
is the example right and inside of the code breaker
00:26:53.000
game what you're doing is you are sending a message to
00:26:58.919
puts right there and we're sending the message output to
00:27:05.360
puts what's the problem with that well we're coupling that to the actual
00:27:10.640
standard output we're saying the responsibility of this game is to talk to a command line
00:27:17.320
interface so it's specifying more than it needs to it's handling the starting of the game as well as specifying what
00:27:24.720
the object it is talking to is instead of specifying a role so what would we do
00:27:30.880
instead we would mock the RO in the domain object so for example instead of calling
00:27:37.360
it output we might call it displayer and we would pass in that
00:27:42.760
displayer and we would say the displayer should receive display with welcome to
00:27:48.559
code breaker and we would do the same thing in the actual
00:27:54.399
code we would implement the display object using then puts whatever the role
00:28:00.159
that we're playing would then use puts you might be thinking how is this any
00:28:05.840
better isn't this just changing words I mean you playing semantic games with me
00:28:12.320
no I think it actually is better because say for example you want to move from
00:28:17.679
using a command line interface to using a rich guey should you have to change your game
00:28:25.080
object in order to change from a command line interface to a rich goey no because
00:28:33.559
that object is really just a role it's the the role that it's playing is displaying the information the fact that
00:28:40.760
it's using puts is an implementation detail specific to how you display the
00:28:46.360
object or display the state as opposed to the actual game itself so we should
00:28:52.080
separate concerns that way we could switch the object if we wanted to to to move to a
00:28:59.320
guy instead of using the command line puts we would implement it doing something else and the game object
00:29:05.720
wouldn't have to know the difference so what about testing the display
00:29:11.120
object it's like am I just getting into a problem that this is going all the way down well the Steve Freeman Nat price
00:29:18.960
the guys who are are heavy into the London School of tdd actually say no in
00:29:24.279
those cases you should not write unit tests you you should not isolate that object instead you should write what
00:29:31.120
they call integration tests integrating with an outside system or if it's simple
00:29:36.399
enough like it probably is in this case you can leave it to your acceptance
00:29:41.519
tests right you could write an end to end acceptance test using something like AR Ruba to test the command line
00:29:48.519
interface and it's going to verify that that code on the edges of your system is actually doing the right thing and the
00:29:55.840
reason why they say that is because if if you are mocking an object that you don't own you don't get any design
00:30:01.360
feedback it's not representing a role inside of your system and so necessarily
00:30:06.440
you will have to couple that object or couple that message that you're sending
00:30:12.159
to the implementation of how you are currently using it instead we want to keep that implementation outside of our
00:30:18.120
domain objects and test those borders independently in integration test if you
00:30:24.120
need to or just let your acceptance tests handle it okay last
00:30:29.519
principle uh mock peers and not internals this is another thing that
00:30:35.159
gets people into a lot of trouble it's something that actually has only begun to be articulated a little more recently
00:30:40.960
mock objects have been around I think since the 90s uh I think that this distinction only came about in the
00:30:46.039
growing object-oriented systems Guided by testbook that I talked about and those are two references and the basic
00:30:52.720
idea is this you need to decide what is inside and what is outside of your
00:30:58.440
object when tdd becomes a design process you have to ask yourself does this
00:31:05.799
implementation that I am talking about belong internal to my object or as a
00:31:11.919
collaborator of my object and the key thing to notice here is that not everything belongs to a you
00:31:19.919
can't just infinitely delegate things out there has to actually be some domain logic contained inside of your domain
00:31:26.760
objects and and not everything inside of there if you use objects has to be
00:31:32.240
mocked out the key question you want to ask yourself when you're thinking about do I
00:31:39.039
push this outside of my object or do I stay inside of my object is is this implementation that I'm doing is this
00:31:46.720
the role that I am supposed to play as object XYZ if it is my role then I'm going to
00:31:54.720
make that internal to my object even if I use other objects and I am not going to mock that because
00:32:01.880
that is going to be an implementation detail of how I play the role that I am going to play so for
00:32:08.840
example um this is I'm actually taking out of the growing objectoriented systems Guided by testbook they actually
00:32:14.720
build a a whole uh auction bidder uh for you and this is one of the beginning
00:32:22.360
parts of the uh system they have an auction server that sends messages in
00:32:27.960
into the system and it's sending it in you know some form of a string coming down over a socket I believe and it
00:32:34.000
calls process message on this auction message translator object and the role
00:32:39.480
of this auction message translator is to translate the message that comes in from
00:32:44.679
this string into the language of the domain that is different types of
00:32:51.399
messages come in and the translator translates them into domain terms into
00:32:56.919
the way that it talks to the apis internal to the system and so this would look something like this describe
00:33:04.120
auction message translator it notifies bid details when a current price message is received and it has a role of an
00:33:12.039
event listener and it says The Listener should receive current price with 192
00:33:17.919
and seven that 192 is coming from the current price and the Seven is coming
00:33:24.679
from the increment how much it changed by the basic idea is this is coming down from the server in a string but when
00:33:31.440
you're working internal to your objects you don't want to have to know about that string all you care about is
00:33:36.760
whatever the current price is and whatever the increment is and so the way
00:33:42.120
that they do this is they say the message translator when it receives a message with so version 1.1 event price
00:33:50.000
current price 192 increment 7 bitter someone else should send a message into
00:33:55.600
the system saying the current price is now 192 and changed by
00:34:03.799
seven make sense and then the way that they do this
00:34:09.480
is they have an auction message translator that processes the message by
00:34:14.919
saying unpack event from this message if the event type is closed you're going to
00:34:20.440
send the message auction closed if the event type is not closed send the
00:34:26.440
current price with event current price and event. increment that's pretty
00:34:31.720
semantic I think inside of in inside of the process message but the key thing to notice how do they do that well unpack
00:34:39.720
event creates a new object called the auction
00:34:45.560
message event and passes in the string and then they create a nice API that
00:34:50.639
they're going to work with so that they can just say event. type instead of having to extract that out of the string
00:34:58.400
and they can say event. current price event. increment this is essentially
00:35:03.599
creating an immutable value object from the string that came in from the
00:35:10.160
server but you'll notice if we go back and look at the tests there is no
00:35:15.560
mention of this object this auction message event they're not stubbing it
00:35:22.320
they're not mocking it why because it's an in internal object
00:35:29.359
it's an implementation detail about how they are doing what they are doing instead of what they are doing and so
00:35:36.960
not every object needs to be mocked not every object needs to be stubbed don't mock this don't stub it why because it's
00:35:44.359
an implementation detail as that string changes the thing might change and you
00:35:50.760
end up getting very brittle tests when you start stubbing these things it's
00:35:55.839
better to just execute the code as a black box and when it changes or when uh
00:36:03.040
when you know the requirements change you add more tests you change the inside but the tests don't need to know about
00:36:08.520
it the tests respect the encapsulation of your code and test it from the outside of the system not
00:36:16.400
inside okay so further resources I'm going to tell you there is one that I
00:36:22.400
would recommend anybody who is interested in this pick up and it's growing object-oriented software Guided
00:36:28.079
by Tess yes it is in Java but you know Java in many ways is
00:36:34.359
the lingual lingua franka of a lot of object-oriented design and a lot of uh
00:36:42.079
tdd a lot of this was developed inside of java and if we're going to be Craftsmen if we're going to be
00:36:47.280
professionals we need to learn to read Java even if we don't write
00:36:53.920
Java so I would recommend highly that if you're interested in this pick up this book uh I learned a huge amount of
00:37:00.560
things by reading it through and I think that uh that's about
00:37:06.200
it there any questions how would you recommend tell
00:37:12.800
me if thiss into Des we have aent who an API we not have
00:37:20.520
to it but we need to know U we don't want to have to actually hit the API for
00:37:26.160
real you that would be a good case to use a to say when we give them this
00:37:31.280
message we expect this response for them so I think the key thing to to notice um
00:37:39.119
is you're not really doing a command there uh you said uh when we send it
00:37:44.520
this message it gives us this back so that isn't really a mock that's a
00:37:50.280
stub um and so we want to be careful with where we use stubs because we are coupling it to an implementation but I
00:37:56.680
think that one legitimate use case to use stubs is so that you don't hit a real server um I do find it helpful to
00:38:03.400
at least have some tests that run against the real thing though so that I know if they broke it uh generally those
00:38:08.839
I would consider like integration tests
00:38:35.960
so you can definitely feel the notion of a role inside of an interface um Steve
00:38:42.040
Freeman though has a lot of his original background is in small talk which is uh
00:38:48.520
where a lot of the design philosophies originated um the way I tend to think
00:38:53.960
about it is my mock objects are actually defining that
00:38:59.880
interface um and so even though the language construct does not exist I
00:39:05.760
don't view that necessarily as a bad thing because I think it actually is a little cleaner inside of java you have
00:39:12.280
to specify that interface both in your production code and in your tests and so
00:39:18.079
you end up having to refactor both your uh production code and your tests when you want to change the the role uh or
00:39:25.319
the message maybe for design reasons or for whatever I find that to be actually a little easier and clearer to do in a
00:39:30.640
dynamic language because then I only have one place where it actually is specifying that role which is inside of
00:39:38.000
my tests are
00:39:44.800
youself now am I yeah so uh my design style has become
00:39:54.400
very mock driven um I I think I would subscribe to what
00:39:59.960
Michael feathers calls the London School of tdd uh because I found that it produces a better design system it
00:40:06.520
doesn't mean I mock everywhere uh there are some places where it makes sense to do assertions on state as opposed to
00:40:13.040
doing assertions on uh instead of doing assertions on the
00:40:19.000
messaging between the objects on behavior um so like maybe if if that uh
00:40:26.599
if that underl object which is an internal peer uh the logic became very complex and I wasn't satisfied with just
00:40:34.560
treating it like a blackbox I might write unit tests for that object um that
00:40:40.440
just tested the responses coming out of it and I would use state for that but generally I tend to to think
00:40:48.200
much more in a tell don't ask style uh can you talk a little bit about
00:40:55.599
how you do this when reflector when you have a class that's overload with responsibilities extract that
00:41:03.319
out sure um so one of the things that is is
00:41:09.040
difficult is when you come into I guess I should repeat the question the question is how
00:41:15.920
would you refactor something from using heavily state-based uh tests to a more
00:41:22.520
mock based uh test um and I think think
00:41:28.000
it can be challenging uh because you're not just changing the way you test you are
00:41:34.520
changing the way that um you're changing the internal entire internal
00:41:40.599
implementation of your code it's kind of like you're going from a procedural oriented um place where you're getting
00:41:47.760
information and then making decisions based off of that information to a telling um the thing that I find to be
00:41:53.000
the most helpful is actually having an end to end test Suite something like cucumber or some acceptance tests that I
00:41:59.560
can turn off the unit tests and try the refactor like rewriting it
00:42:05.960
um the other the other resource that I might point you to is uh Michael feathers book um dealing with Legacy
00:42:12.880
code doesn't address that topic directly um but he talks about how would you
00:42:18.440
inject an interface um in his purpose it's it's kind of sprouting an object for
00:42:24.599
uh for cleaning up Legacy code being actually able to test but I find some of
00:42:29.640
the same techniques apply um you just have to be careful breaking the
00:42:36.880
dependencies any other questions in your example you
00:42:44.520
use display object that you made instead of put inside your class when would you just straight up go with puts inside
00:42:51.280
your class or should you always create a object sure so the question is uh in my
00:42:56.440
example I uh created an object to do the display instead of uh just using puts
00:43:03.400
inside of the object when would I make an object versus just using puts inside
00:43:09.240
of the object um I think the answer to that question for me generally is
00:43:14.559
whenever I would write tests for it um something that is simple enough and small enough of a program that I don't
00:43:22.640
have I'm not worried about maintaining it it's just a script I would put those things inside of an object
00:43:27.839
uh I probably wouldn't write unit tests for it I might write an end to-end acceptance test and just kind of treat
00:43:33.200
the whole system as a black box uh but when I personally get into the situation
00:43:38.640
where I know I'm going to incrementally build this system over time and I'm going to have to maintain this I'm going
00:43:45.240
to want to have a strong separation of concerns and stuff like that that's when I would do the the sort of mock create
00:43:52.359
an object all right well if you have any
00:43:57.559
other questions feel free to come and talk to me thank you very much for coming