The Big Picture
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Title of Series | ||
Number of Parts | 50 | |
Author | ||
License | CC Attribution - ShareAlike 3.0 Unported: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this | |
Identifiers | 10.5446/37496 (DOI) | |
Publisher | ||
Release Date | ||
Language | ||
Producer | ||
Production Place | Miami Beach, Florida |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
Ruby Conference 201349 / 50
2
3
7
13
15
17
18
19
28
29
35
39
44
48
49
50
00:00
LaptopStandard deviationLie groupWordFormal languageMultiplication signLevel (video gaming)BitHypermediaField (computer science)Right angle
01:56
Formal languageBitDistanceNP-hardMultiplication signComputer animation
03:14
Interactive televisionDigital photographyType theoryWater vaporBitRight angleComputer-assisted translationAcoustic shadowLecture/ConferenceComputer animation
04:48
Product (business)AuthorizationDemosceneOffice suiteField (computer science)
06:03
Object-oriented programmingGroup actionComputer clusterEmailJava appletSoftware developerLibrary (computing)NumberPlanningLevel (video gaming)CodeDiagramFormal languageProcess (computing)BuildingBitSource code
07:30
Formal languageTunisPattern languageInheritance (object-oriented programming)CodeRight angleSolid geometryMathematical optimizationDifferent (Kate Ryan album)Social classCuboidCommunications protocolObject (grammar)ExpressionPoint (geometry)Computer clusterDiagramLevel (video gaming)Attribute grammarComputer programmingTriangleModule (mathematics)Direction (geometry)Arrow of timeLie groupInterface (computing)AnglePoisson-KlammerHand fanExistenceProgramming languageSoftwareFormal languageProduct (business)Degree (graph theory)Real numberBitSoftware developerCartesian coordinate systemSource codeImplementationCASE <Informatik>Category of beingEndliche ModelltheorieEmailWordStandard deviationSoftware testingForcing (mathematics)ArmSpeech synthesisView (database)Boss CorporationProcess (computing)Disk read-and-write headLine (geometry)
15:42
Group actionField (computer science)Revision controlType theoryCommunications protocolSoftware frameworkMereologySoftware testingSocial classLogicCartesian coordinate systemHexagonCuboidGame controllerObject (grammar)CalculationArrow of timePattern languageSet (mathematics)Computer architectureRight anglePlastikkarteStrategy gameImplementationMultiplication signPhysical systemStandard deviationTap (transformer)Cellular automatonWordHecke operatorOffice suiteDivisorRow (database)
18:55
Game controllerMessage passingLevel (video gaming)Communications protocolRow (database)LogicDatabaseSoftware testingTemplate (C++)Repository (publishing)Computer programmingObject (grammar)System callContext awarenessUniform resource locatorVolumenvisualisierungType theoryComputer animation
20:56
Software testingDisintegrationProxy serverObject (grammar)Level (video gaming)CodeSoftware testingDiagramRight angleGame controllerCuboidINTEGRALDivision (mathematics)Wage labourLogicDatabaseNumberCartesian coordinate systemDirection (geometry)Row (database)Computer architectureBitInformationWeb 2.0Connected spaceArrow of timeField (computer science)Latent heatUnit testingGoodness of fitMereologyValidity (statistics)User interfaceModule (mathematics)NamespaceExecution unitTask (computing)Parameter (computer programming)Data structureEndliche ModelltheorieCommunications protocolSoftware development kitLabour Party (Malta)
23:58
Social classTime domainRule of inferenceSpacetimeData structureTask (computing)Inheritance (object-oriented programming)Data structureCartesian coordinate systemCasting (performing arts)Task (computing)Computer fileBit rateData managementEndliche ModelltheorieDiagramNamespaceArithmetic meanSource codeGame theoryControl flowMereologyBitRepresentation (politics)WeightSocial classOptical disc driveRule of inferenceUniform resource locatorObject (grammar)Electronic mailing listReading (process)Point (geometry)SpacetimePhysical systemGroup actionInheritance (object-oriented programming)MathematicsBusiness objectDomain nameMappingModule (mathematics)Computer animation
26:53
Object (grammar)Computer fileTask (computing)Data managementData structureCodeRight angleDirection (geometry)Communications protocolNamespaceRevision controlRewritingRule of inferenceNetwork topologyLink (knot theory)Control flowElectronic mailing listCodeMessage passingBit rateEmailCartesian coordinate systemCasting (performing arts)Engineering drawing
28:28
Social classEmailObject (grammar)DiagramMultiplication signException handlingPoint (geometry)Natural numberDifferent (Kate Ryan album)Bit rateMathematical singularityEngineering drawing
29:55
DiagramLevel (video gaming)Object (grammar)Software testingNamespaceData structureComputer programmingMultiplication signExecution unitTask (computing)Data managementSpacetimeProgram flowchart
30:33
Execution unitObject (grammar)RoboticsOffice suiteLaptop
31:14
Computer programmingLibrary (computing)Process (computing)Right angleDiagram2 (number)Dependent and independent variablesComputer architectureObject (grammar)Cartesian coordinate systemComputer animation
32:02
DiagramCommunications protocolDependent and independent variablesArithmetic progressionNavigationStreaming mediaMessage passingMoment (mathematics)Object (grammar)Cartesian coordinate systemTape driveGame controllerDivision (mathematics)Social classData streamClass diagramModemLevel (video gaming)Right angleWeightEngineering drawing
33:58
Social classDependent and independent variablesGame controllerObject (grammar)Communications protocolDiagramVideo gameTask (computing)Particle systemBitCodeNavigationProgram flowchart
34:47
Object (grammar)Network socketGame controllerImplementationInjektivitätObject (grammar)Default (computer science)Reading (process)Task (computing)Stylus (computing)Game controllerLine (geometry)DiagramDependent and independent variablesCodeTape driveRight angleException handlingComputer animationEngineering drawingProgram flowchart
36:08
Port scannerInformationDigitizingState of matterCircleMedical imagingDiagramMoment (mathematics)Group actionSystem callDifferent (Kate Ryan album)Social classImplementationObject (grammar)Streaming mediaError messageIntegerState diagramFinite-state machineTape driveComputer animation
37:46
Tape driveNavigationObject (grammar)Network socketState of matterMultiplication signRow (database)Mechanism designAlgorithmMathematics2 (number)WeightRight angleState diagramStreaming mediaInteractive televisionSoftware testingLibrary (computing)Computer animation
39:37
Set (mathematics)Right angleExpected valueFigurate numberRow (database)Object (grammar)Interactive televisionDiagramCodeLibrary (computing)Sequence diagramWordProgram flowchart
40:13
Social classObject (grammar)Data structureDiagramWhiteboardLine (geometry)PixelPresentation of a groupStandard deviationElectronic program guideModeling languageDiagramGreatest elementInteractive televisionObject (grammar)Theory of relativitySocial classSequence diagramSystem callMultiplication signResultantProcess (computing)Hash functionExpected valueCASE <Informatik>Line (geometry)Row (database)Source codeBookmark (World Wide Web)PixelParameter (computer programming)Goodness of fitSign (mathematics)WhiteboardMessage passingSoftware bugElectric generatorPoint (geometry)Programmer (hardware)Motion captureProper mapField (computer science)CodeDirectory serviceData structureSatelliteLattice (order)Matching (graph theory)Level (video gaming)Office suiteAutomationEmailGame controllerCartesian coordinate systemFreewareArmCoefficient of determinationState of matterPresentation of a groupFluxSequelMathematics2 (number)Doubling the cubeComputer animationEngineering drawing
46:59
Office suiteWhiteboardDiagramCartesian coordinate systemProcess (computing)Presentation of a groupAxiom of choiceJava appletComputer animation
47:55
SoftwareVideoconferencingEvent horizonDiagramCodeComputer animation
Transcript: English(auto-generated)
00:02
It means it's about time to start. Are you guys enjoying Miami? Awesome!
00:26
So why are you in here and not down at the beach? Oh, thank you, thank you, yes, okay. How many people recognize this picture right here? Yeah, can you name it? Nighthawks, yeah, by Edward Hopper.
00:42
It was painted in 1942. If you recognize it, it might be because it's one of the standard Mac backgrounds that you can select on your desktop, and I had this on my desktop for a long time. And I really, really enjoy this picture. This is a really cool picture. Just a little bit of details about it.
01:00
It was painted in 1942, I believe. It was sold to the Chicago Art Institute for about $3,000 just a few months after it was painted. It's hanging up in the institute since that time. My daughter, who goes to art school, said she took a field trip to Chicago and actually saw the actual painting up there, so when I was describing it to her,
01:23
she immediately recognized, oh yeah, that's the Hopper picture. But this is fascinating to look at. Because it was on my background, I would open my laptop up and I would see this and I would think about maybe the story behind this. I mean, look at this.
01:41
It's a diner. It's in New York somewhere. It's got a cigar ad at the top. It's hard to see in the washed out lighting here for five cent cigars. It's dark outside, but the inside of the diner is bright light. And there's a couple characters in there. Now look at this couple. Look at their body language. What is their body language telling you about them?
02:06
They're sitting together. There's some kind of couple, but notice how closed off they are. Their hands are almost touching, but not touching. Look at her face, how serious she looks. The dark eyes. Maybe she's been crying. Maybe she's sad.
02:22
I can't quite tell what she's holding in her hand, but it looks like it might be a wad of money of some type. Maybe a little bit of money. Maybe these two people are a couple that are having problems. Maybe it's money related problems. That's why she's looking at the money so hard. Look at the guy's face. He is not a happy camper.
02:43
Someone wrote a poem about this picture, and she says, and the poem says, I bet she wrote him a letter, and he is no longer the guy that reads her letters twice. Wow. Wow. Nighthawks, probably so named because the hawk beak of the nose for this guy, actually.
03:03
That's an interesting little tidbit. So, there's something going on there. Couple problems, money problems, maybe some other kinds of problems, but definitely tension in that couple. Now from a distance, I looked at this guy, and I thought, oh wow, he looks like he's really happy to have these customers late at night in his diner,
03:21
but when I zoomed in and looked closer, that's not a smile he has on his face. That's a grimace. And he's looking at that couple. So what is going on with the couple that is making the waiter unhappy? You know, did they just get done with the fight, and they're sitting there sullenly, and he's like, okay, what's going to happen next?
03:42
You know, there's some interaction going on there as well. And then this guy, what's he doing there? He's sitting alone. He's all by himself. He's got a newspaper under his left elbow there. I believe that's a newspaper. You can see it just a little bit in the photo. It looks like he's holding a glass of water. He's got a cup of coffee right by him.
04:03
Now I don't actually see any food in front of him, but it looks like he's drinking something. He's sitting there all alone, kind of in the shadows, his hat's kind of down over his eyes, so you can't see what's going on. Is he watching the other couple? Is he tailing them? Is this a gangster type thing, where maybe they're involved in some kind of gangster thing,
04:20
and that's the money problem, and he's an enforcer, and he's fine. I don't know. I mean, the possibilities of this are wild. Notice his pocket, his coat pocket right down there is open. He's got something in it. Is that his gun that he's got in his coat pocket? I don't know. There's all kinds of possibilities with this picture.
04:40
That's why I love this picture. I don't know what it's about exactly, but the possibilities of the stories behind this is really interesting. Now this painting has been referenced in literature. There's been stories about it. Charles Spiegel published five short stories based upon what authors thought might be going on in this picture,
05:04
so five different stories, at least one of which ended in a massacre. It's used in movies, I think. Pennies from Heaven reproduced this scene. Oh, the guy's name escapes me.
05:21
Who did Blade Runner? The director. Ridley Scott. Ridley Scott, thank you. When Ridley Scott did Blade Runner, he would take a reproduction of this film and shove it under the noses of his production team, and say, this is the feel that I want for my movie,
05:41
this kind of dark, noir feel. And that's kind of what pushed Blade Runner, the feel of Blade Runner was inspired very much by the feel of this picture as well. Art says a lot. Pictures speak a lot. Now, they don't say exactly what's going on, but they open up so many other questions,
06:00
and I find it fascinating to look at pictures. So I'm Jim Weirich, I'm chief scientist for NEO, and I'm here to talk to you about the big picture. People have been asking me this week, Jim, what are you going to talk about at RubyConf? What's your talk about? And I say, I'm going to talk about UML at a Ruby conference.
06:23
Yeah, yeah, I get two reactions from that. Oops. Yeah, like, huh, what's UML? I do not know of this UML which you speak. The other reaction is, this is probably the Java developer
06:44
who has been immersed in UML for so long, he is sick and tired of it and never wants to see it again. Truthfully, as I work with other Rubyists, I discovered that they have not used diagramming to any great degree, and they're not aware of what UML can do for you.
07:01
So I'm here to give you some very basics in UML. What I'm going to do is I'm going to give you a vocabulary, a vocabulary in pictures that you can use to build diagrams. And then I'm going to talk about three or maybe four of my own libraries and the diagrams that I drew of those libraries, and then what I learned from those diagrams
07:23
that I did not see by just looking at the code. So it's kind of my plan for this talk. If that's our roadmap, that's where we're going to go. So let's go talk and just mention UML just a little bit. There are basically three ways people use UML. One is a sketch language to capture quick ideas
07:41
and to get them down on paper so they can communicate with each other. UML as sketch omits details. UML as a sketch will lie about the software because the lie is better than what the reality is there. If you want to convey an idea, the idea is what's important, not necessarily the details.
08:01
So UML as sketch. You can use it in both ways. You can sketch up an idea before you implement it, just to kind of get an idea of the roadmap you want to go to. You can take an existing piece of code and draw the diagrams afterwards to kind of get a better understanding of what the software is doing. That's what I've done on the examples that follow.
08:22
UML as a blueprint is probably what gives the most Java developers the eh feeling. It's when you use UML down to such a detailed degree that an architect can take the UML diagram and hand it off to a coder and the coder just implements it.
08:41
I don't believe that works very well at all and I'm not a fan of UML as a blueprint. Even worse than UML as a blueprint is UML as a programming language. I used to work for a company called Compuware. We had a product called Optimal J and the salesman for Compuware, they said, Jim, you've got to push Optimal J for us.
09:01
You know, it's so great. You just draw the pictures and then you push a button and you get an application out of it. Yeah, that's exactly what I did. I said, uh-huh, yeah, laugh. Jim, it really works. It's got to work. We use patterns. I said, you guys really don't know what patterns are, do you?
09:21
No, but we know they're good. So, I was never a big believer in Optimal J. It turns out that when you dig deeper for every diagram you draw, you have to accompany it with something called this expression language to kind of tie it down how to map it into a programming language.
09:40
And I told my sales guys, this kind of looks like programming right here. Oh, no, no, no, it's not. Don't worry, it's nothing like programming. Okay. So, UML as a programming language, no, I'm not a big believer in that. But UML as Sketch, I am still a big fan of. So, let's go ahead and start. Let's start with the first example. And this is talking about dependencies in my software.
10:01
I think this is one of the strongest features of UML is to get a broad overview of what your code depends on. Before we do that, I've got to build up the vocabulary of the diagram so you know what I'm talking about. First of all, if you have a class in Ruby, such as a Car class,
10:22
you can represent it as a diagram. It's just a simple box with the name of the class right in here. This represents this bit of code right here. If you wish to get more detailed and you wish to include the methods in it, you can add a second box, divide your box in two, the name goes on the top, and the methods go down here into this second box.
10:41
So, you talk about particular methods on that particular class. And like I say, UML as Sketch means that you include the methods that you wish to talk about right now. You don't include every single method. You just include what's important to the idea that you wish to convey in that particular diagram. If you want to get even more detailed,
11:01
and I rarely do this, is that if there are internal attributes, you can list them in a third box that goes below the name and above the actual methods. Like I say, I rarely go to the attribute level. If one class uses another class, and you can always tell it uses it
11:21
because it will reference the class by name here, if so, then you can create a dependency between this class and that class. The direction of the arrow goes in the direction of the dependency, and this is always, always, always true in UML. Whenever you draw an arrow, it means it's a dependency,
11:40
and it goes in the direction of the thing that's doing the depending towards the thing that it is being depended on. This means that if I use an engine object, I can use it independently. But if ever I use a car object, I also need to drag in an engine object along with it. And we can see that because man, we're referencing engine right here
12:00
in the code base. That's a dependency, and UML is great for capturing these dependencies. Here's a dependency where a car is also using wheel, and you can say on your dependency line, you can say one car has many wheels. In this case, four wheels. You could put a four here for the star, or you could just say star says eh, one to many.
12:22
So it's kind of a one to many relationship right there. Again, dependency goes from car to wheel. If you inherit, the inheritance relationship is also an arrow. This arrow is an open triangle pointing from the subclass to the superclass. So again, I can use car by itself,
12:40
but if I want to use a sports car class, I get car automatically because it's dragged in by that dependency. Ruby has modules, and this is how I designate modules in a UML diagram when I'm talking about Ruby. It's essentially the same as a class,
13:00
but I put this, it's called a stereotype. I say it's a module in this, I use angle brackets but what they really should be are French quotes, which I cannot pronounce the real name for, but that's a stereotype right there, and that says it's kind of like a class but it has these special properties,
13:21
and it's a module. And if you're doing Ruby programming, you know what a module is, and that's all it's telling you, that drivable is a module. I use the same arrow to indicate include as inheritance here because essentially it's the same relationship. The difference between inheritance and including a module in Ruby is very subtle,
13:41
and I don't really call out the difference in a UML diagram because of that. Okay. So, there's one more thing I want to show you, and this is really important. Here, car is being passed an engine object,
14:02
and so there is no longer a direct reference to the engine class inside my car class anymore. So, car no longer depends upon the engine class, but it does depend upon some kind of object that behaves like an engine does. In other words, it's duct typed
14:21
to an engine. I captured this in Java. If you're doing this in Java, this would be an interface, and you'd have to actually write code that had the start and stop method on it and say this is an interface, and that the engine implements the interface. In Ruby, the stuff for this thing right here doesn't exist.
14:41
There is no source code for this box right here, but it's an important concept that you need to capture and be able to talk about. Car does not depend upon engine, but it does depend upon an object that obeys this protocol, the start and stop method on it. Engine implements
15:01
that protocol. It's kind of like the inheritance line, but dotted instead of solid. I'm saying engine implements this, car uses it, car does not depend upon engine. That means if I want to test a car, I can just drop anything in that acts sufficiently like a car, sufficiently like an engine for my testing,
15:21
and I can test car without having an engine available at all. And this is an important concept in drawing these dependency diagrams, is to recognize that, hey, that dependency no longer is all the way to engine, but it's just using a protocol at that point. Alright. So now we've got some basic vocabulary to talk about dependencies in our programs.
15:43
So this is a pretty standard Rails application right here. This is actually an implementation of the pay employee problem that is common in literature. You probably run into it. You have three kinds of employees. Hourly, salaried, and commissioned.
16:00
Hourly employees are paid according to the time cards they turn in. Salaried employees are paid a yearly salary, paid once a month, so they get one-twelfth of their annual salary once a month. Commissioned employees get a salary, plus a commission based upon the sales receipts that they turn in. So there's three different ways of calculating their paycheck.
16:20
Here, what's important to notice is that in this Rails version of this solution, we have an employee controller. It inherits from application controller, which inherits from action controller base. The red classes are Rails classes. They are part of Rails. The pink classes are our application
16:42
classes that depend upon Rails. So, if I want to test my employee controller, I've got to bring in Rails to do it. If I want to test my employee object, I've got to bring in ActiveRecord to do that testing. So they are dependent upon the framework. However, the way I chose to implement the salary calculation was as a
17:02
set of strategies that the employee picks the strategy based upon what type of employee he is, and then just calls the strategy. HourlyPaycheck, SalaryPaycheck, CommissionPaycheck would all implement the protocol that includes calculatePayAmount and gets passed in an employee object. There is nothing
17:21
in these guys that directly reference the employee class. They just depend upon something that acts like an employee. That means these guys can be tested very simply by, like, if I want to test SalaryPaycheck, I just need to pass in an object that has an annual salary field on it, and I can test that without loading
17:41
Rails at all. That's why they are green. These tests on the green things can be run very quickly and very safe. And we can tell that by examining the arrows. Notice that in this dotted box here, all the arrows are pointing inwards. There is nothing pointing outwards from this box. That means I do not depend
18:01
upon the framework, and that tells me I can test those very efficiently and very quickly. However, if I want to test the employee object directly, I've got to load Rails. If I want to test controller directly, I want to load Rails again. I'm teaching a class with Bob Koss right now on testing in Rails and refactoring and patterns
18:21
and things like this, and we use this example in our class. One of the things we do is to push this system to see how much we can get decoupled from the Rails framework. So we can test as much logic as we possibly can without invoking Rails. One of the techniques
18:41
we use is some of the techniques from the hexagonal architecture talks that Matt Wynn does, and Kevin Rutherford has done. And if you look at that, they basically take this approach. And this concentrates on the controller now. They take the employee controller, and they say
19:02
some of the logic in the controller is Rails-dependent. Things that says redirect to this URL. Render this template. Here is the params hash. Those are our Rails things. However, some of the logic is really business logic. Even in a standard dumb Rails controller,
19:22
there's still business logic in there. How do I create an employee object? How do I save an employee object? How do I validate and how do I how do I detect whether it's saved or not? Validated or not? It's all really kind of business logic. So they very carefully pick
19:40
that controller apart into two pieces. One piece remains here in the controller. The other piece they pull out, and I'm calling it a runner, because they tend to give it the method called run. And into the run, they pass in a couple things. They pass in a protocol that is essentially the context object, which is the controller.
20:02
They pass, and I have also pulled out a repository object here, so all the database related stuff is done through a repository. It's a little tedious, but it's really not hard at all. You can almost automate that piece very easily. So the runner now depends upon something that
20:20
has save and find employee type methods on it. It depends upon some callbacks and context provides, but there is no direct reference to Rails anywhere in the runner anymore. That means I can test the business logic in here very carefully, and now I've got a whole bunch more logic that is totally free
20:40
from Rails, and that I can easily test. There's one more stage I like to do, and I'd like to get most of the business logic in here freed from Rails as well. There's many ways to do this. Here's one. Let's treat employee, the active record employee object,
21:00
as a dumb data holder. I let three things go in there. Number one, I let database fields be in that object. I let relationships be in that object, because Rails is really good at defining relationships. It doesn't make sense to pull those out. Likewise, validations are in that object. You could make
21:20
an argument. You could pull validations out. Yeah, okay, you could do that too. I tend to leave them in. So it tends to be dumb without any business logic in it. Then, I create a business employee object. I usually just namespace that, put it in a module called biz or whatever, and then he proxies to
21:42
the employee object, and all he needs to do is assume that he has an object that supports the dumb data portions of employee. That means he knows about the employee name. He knows about the annual salary. There's no business logic in here, or represented by this protocol at all.
22:02
Now, my whole application can use this business employee as if it were the active record object. But he himself doesn't actually depend upon active record. He just depends upon the protocol for dumb data. It's pretty easy, actually. Now, with that,
22:21
the whole thing here, actually my entire application is now inside the red box. I can test stories here at this level. The create employee story is actually implemented by this code here. The employee specific business is in here,
22:41
and all I have to do... So I can test all this very easily. I can actually run unit tests at this level. If I want to, I can go ahead and include the active record part of this and do story level testing all the way to the database without going through the web interface because I'm hitting this guy right here.
23:01
The only thing outside the box now is just a little bit of wiring that happens in the controller. I can easily test that at an integration level test by hitting the web UI. My web UI testing is lightweight and small, and just enough to make sure the connections are made. My story level testing hits here and can go all the way to the database, and then my unit tests
23:22
are at this level here, and they can be fast and very fine-grained and have a lot of them to really exercise the logic. I think that's a good division of labor between your tests, and I really like the architecture that I've been experimenting here with this idea. But notice how the diagram tells you all that information. I can look at this diagram, and I can tell
23:41
here are the arrows, and this is the direction they are pointing, and this green stuff has no arrows leaving it going out to any of my active record stuff. So, the diagram really helps convey that information without me going through and showing you a lot of code, code, code. Okay. Next example, let's talk about
24:01
structure. This is a diagram I drew based on Rake. I was actually rather surprised when I got done with this diagram. This has very little mapping in how my mind thinks about Rake.
24:21
So, the diagram to me was very interesting. First of all, the first thing that kind of came out to me is that Rake has a lot of large classes with lots of methods on it. So, a few classes, but the classes have lots of methods, and you don't see all the methods here because this is Sketch, and I omitted the methods I was interested in
24:41
showing, but as I was going through the diagram I saw, oh, this task manager's got a bazillion methods on it. Application has a lot of methods on it. Task has a bazillion and a half methods on it. They're just not being shown here. So, that was kind of odd. I was kind of
25:01
surprised by that. Another thing I noticed is there's lots of things in here, domain knowledge about Rake that is not represented anywhere by a class. This bothers me just a little bit. Rake has a concept of rules. There is no rules class in Rake at all. It's kind of odd. Rake also
25:21
locations where a task is defined, so you can find it easily in your source code. There's no domain object representing locations in Rake, and this is kind of bothersome to me as well. And this one's really odd. So, what is happening? Your task manager is the guy who contains the tasks. And the way Rake is designed,
25:41
task manager is a module that is included into your application, so your application is the thing that holds the tasks. It tracks the current scope. There are namespaces in Rake, and that's represented by the scope. And I really like this part of it. This has worked really well here. But, it's a little bit odd in that as you read a Rake file,
26:01
the scope is constantly changing. I'm defining a task in this namespace, I pop out of the namespace, and as you're doing it, the current scope keeps changing. And as you define a task, he grabs whatever current scope the task manager has at that point. And that works fairly well, but what I end up with is a flat list of all the tasks in the system, and there's
26:21
nothing that captures the structure of the namespaces at all. I was kind of surprised by that. When I went back and actually looked at how I implemented it, this seemed a little bit weird. The other weird thing is that file tasks essentially ignore scope, because they're defining files, and files have no idea of what the namespaces are,
26:40
so they kind of ignore scope when they're being defined. So why does file task inherit from a task which has a scope? That struck me in reading this diagram as something a little bit odd. So maybe I should rewrite Rake version 20, yeah.
27:01
And here's an idea, here's one way I might approach it. So this is now UML as a sketch, kind of exploring an idea that we could go in. So here's your application, but rather than inheriting from task manager, make task manager an object in and of itself.
27:22
And task manager is now responsible for managing all the tasks in that scope, but no other scope. The scope object kind of goes away, and rather a linked list, task manager now becomes a tree of namespaces. Now I can represent the namespace structure of your Rake file explicitly in my code base.
27:42
It seems to me that would be a good thing. Tasks still have, this is mislabeled, this should say scope right here, that's another problem with UML, it doesn't always accurately reflect your code base. This would actually be scope, not task, but they would have, one task would
28:02
point to a particular scope, task manager would have many tasks, and then task and rule and file tasks would all implement some kind of task protocol that's there. And I think that might be an interesting way to go. It might be worth exploring to it. The problem is, of course, Rake is a well-defined application, and if I change the internal structure too
28:22
much, I might break somebody's code, so I've got to treat this with care. But here's an idea of a direction to go. So how am I representing scopes now in here? So I've got to give you some new vocabulary. So now, let's talk about objects. Rather than classes, we talk about
28:40
objects. So here is a car object, myCar, and we can represent that in UML as myCar colon car, and we underline the whole thing, and it looks a lot like a class box, except it's got an underlined thing in it, and that means it's an object, not a class. If we don't care what the thing is called, we can leave off the name. If we don't care what
29:00
class it is, and we just want to talk about this object with this name, we can leave off the colon and the class name. So either way works. Any three of these are valid. So here is a car with an engine and four wheels. So this object diagram, so a class captures the static nature
29:22
of the class relationships. An object diagram captures a snapshot in time of an object and what it has. At this point in time, this car has an engine and a wheel. If I leave it out on the street, and someone steals the wheels off
29:40
of it, and all of a sudden it's got less wheels, so that would be a different snapshot in time, or someone takes out the engine and replaces the engine, well that would be a different snapshot. So an object diagram captures this is how your objects look right now at this point in time. So this is how Rake might look at a point in time. Here we
30:00
have a top level task manager namespace, and we have a test namespace here, and he has a task called units, so test colon units would be the name of this task, db test prepare would be the name of this task, db migrate would be the name of this task. So now I'm representing
30:20
the scopes and the namespaces of Rake in a data structure inside of Rake as well. So object diagram can capture that kind of snapshot idea of your program. I really like that. Okay. Let's talk about creation of objects. I have a goal
30:43
this year to talk about flying robots in every single talk I give. Thank you, thank you. I think I've only missed one talk so far, and I slipped it kind of into the comments then at the end. But here, so let's talk about the flying robot
31:02
that we're playing with back in the office. This is a Parrot AR drone. It's a quadcopter, it has two cameras on it, it runs Linux on the copter itself, and it talks to your laptop via wifi. I have written a library called Argus that you can use to control an AR drone, and here's a simple
31:22
program where we create a drone, we tell it to start all its subprocesses up, we tell the drone to take off, tell it to turn right, turn left, hover, and then land, and then shut down. So let's see if that program works. Okay, take off,
31:41
turn right, I think I actually turned right for five seconds instead of two. Turn left, hover, and then land. Okay, so cool. So that's all controlled by Ruby. A good way to talk
32:02
about the Argus library is to use an object diagram. I can show you this diagram and I can talk about the pieces of this architecture and how, what the responsibilities for each piece is. The drone object is the drone that the application plays with. It is the front-facing object that you send all your commands to.
32:21
You don't have to worry about anything behind the drone. The controller is responsible for for translating these high-level commands like go up, go down, turn left, turn right, into lower-level drone commands. And then taking those commands and then calling the right commands on the AT commander. AT because
32:42
every command on the drone begins with the letters AT. It's like the guy who wrote this protocol was really hung up on the Haze modem protocol. It's AT star, the name of the command, and then strings after that. So the high-level commands here like turn left
33:01
get turned into a progress command, a P command here with a particular amount of data. This class is responsible for generating the stream of text messages that get sent to the drone. And then the UDP sender class is responsible for actually sending those packets over the wire. So it's a very clear division of responsibility. I really like
33:21
this design. On this side we have a nav monitor which monitors the navigation coming back from the drone. So it watches for commands like saying, okay, I am now this high, my battery is running out, somebody do something, you know, little messages like that come back over the navigation data stream. And then the nav streamer
33:41
is responsible for handing timeout issues on that navigation stream. We'll get more on the nav streamer here in a moment. This is an object diagram, so I thought it would be interesting to look at the class diagram for this. It looks like this. We can still see the seven objects
34:01
listed here, but now we're showing them at a protocol level, protocols they implement. So the drone assumes something with this protocol. The controller implements the protocol. The drone also then uses a T commander protocol, which the controller also uses.
34:22
The nav monitor uses this protocol, and so on and so forth. And so this is really nice. It seems I can test each of these concrete classes very easily just by providing something that responds to the protocol, and they can all be tested independently. It's a little weird, though, looking at this diagram because they've got these objects hanging out here that nothing connects to.
34:41
And so this diagram lies just a little bit. What's really going on is that I have code that looks like this in the drone. It says, okay, create these concrete objects here unless you override it with something. So I can override any of the concrete implementations very easily. So it's a really cheap
35:01
kind of dependency injection technique that you can use in Ruby. So that makes it easy to test, but makes it so that if I just use it by default the right things get built up and used. So let's go ahead and draw these relationships in, and let's mark it with a style that says create, and I'm going to do these lines in red so
35:21
we can see them. So the drone will create the Mav monitor, create a controller, it'll create the UDP sender, now everything is attached by lines. Notice anything really unusual in this diagram. The drone does almost all the creation, but almost all the creation, except for this guy
35:41
right down here. And for some reason the Mav monitor thought it was his responsibility to create the Mav streamer down here. I'm not sure why. And it wasn't apparent to me looking at the code that did not stand out to me looking at the code until I kind of drew the diagram and saw this create line prop up here
36:01
that was different from all the others. So again, the diagram helped me see things that I did not see in the code itself. I think I want to talk about that Mav streamer thing that handles timeouts, but to do that we need to be able to talk about dynamic behavior.
36:23
So here is a UML diagram that's different than what we've seen before. This is a state diagram. And essentially this class here, this toggle class, has two states, on and off. And when okay, so you start in the off state, so the black dot indicates where you start.
36:42
The errors are transitions from state to state, and the transition happens when you hit a trigger. The trigger here is called button push, and we implement triggers as methods on objects. When you're in the off state and you hit a button, then the action you want to take is called turn on. So, the trigger happens
37:02
button, you look at your state, you say oh we're off, then we want to turn ourselves on, then we switch the state to being on as well. So that's the next state there. So, you can look at this, and this is a pretty simple state implementation here, but looking at the diagram here gives you a lot more information.
37:26
Here's another one I just wanted to show. This is a recognizer for an integer. You start here on the empty state, if you get a digit then you're good, and you move to the integer state, as long as you keep getting digits, you get that. You get a non-digit, you say, yep,
37:40
we're done, we got our integer. So it's just a little recognizer here. The dot with a circle is a stop state. So, let's talk about the nav streamer now. The nav streamer is responsible for handling timeouts. This is how it works. When we start up, we go into the wait state. In the wait state,
38:01
the thing we expect to get is a start command. The start will issue a reconnect. The reconnect will essentially go out and create a UDP socket, and it will start listening on it right away. It also requests the nav data as well. We go into a wait state,
38:21
and as soon as we receive data, we go into a run state. This is the expected place to be in. If we timeout during the run state, with a short timeout, we ignore it. We receive data in the run state, we stay in the run state. But if we get a long timeout, long timeout is I think a second or so.
38:41
Short timeouts are like 50 milliseconds, the longer timeouts are like a second. If we get a long timeout, then I need to reconnect. I need to clobber my UDP socket object, recreate it, re-request the nav data, and go back to the wait until I receive data again. In the wait state, if I get a short timeout, I've got to keep requesting the nav data
39:01
because it's UDP, it might have missed it, I've got to resend it. This very succinctly tells me exactly the algorithm used by the timeout mechanism in nav streamer. So, I like state diagrams. I think we should use more of them. Let's see,
39:20
what are we doing on time here? You know what? I'm in trouble because I didn't hit the start button on my timer up here. So, we've got 10 minutes? Thank you. Alright. Interactions. We'll go through this really quick. Here's FlexMock. A library I wrote for mocking.
39:41
It contains a mock container. Mock containers are responsible for managing mocks within a test. This is the mock object right here. So a mock container contains many mock objects. The mock object records by method name a set of expectations here and particular detail expectations here.
40:01
Describing this whole thing right here and how these interact is very hard to do in words. It's even harder to look at the code and figure out what's going on. So we need a new vocabulary to talk about these. And these are sequence diagrams. They're essentially objects here. So it's kind of like an object diagram with lifetimes on it. So here
40:21
in this class we call drive. Drive calls go faster. Go faster calls accelerate on engine. Drive is, so this is the method called drive. This is how long it's alive. Drive calls go faster. So this is go faster right here. Inside of go faster we call accelerate. Accelerate returns a result. Returns here. Go faster returns
40:41
drive. And then drive returns at the bottom here. It's just a sequence of calls and kind of timing related. So here's the interaction in FlexMock. Let's walk through this. A mock gets a message called foo.
41:03
That triggers a message missing which goes into here. So this is message missing right here. Message missing immediately creates a call record to record the fact that that foo has been called. That's so we can query it later to see what messages have been called.
41:20
It then goes and locates the proper expectation director. It's based upon the name foo. So that's just a hash lookup. I didn't record the hash lookup in my sequence diagram because of the detail I don't want to talk about right now. So then we call call on the hash expectation director and give in the arguments to foo and the call
41:41
record. So then expectation director immediately calls find expectation on itself passing in the arguments. And then it goes to each of the expectations that it is managing. And it says oh, expectation number one, do you match the arguments that just got passed in? And expectation number one says nope, false return.
42:02
The director says okay, let's go to expectation number two. And do we match the arguments for this? And this expectation says yes, I expect to be called with no arguments. And that's exactly how we're calling foo. So yes, I match and I return true. And then the director says oh, so you match the arguments. Now are you eligible to be called?
42:21
We ask eligible because some expectations expect to be called once or twice or three times. And so have we run out of times we're allowed to call this expectation or not? Are we eligible? And it says yeah, yeah, you can still call me. So eligible returns true. Find expectation returns expectation number two here.
42:41
That's the return value to here to our call thing. Call then sets the expectation field in the call record to indicate which expectation we called. And then it calls verify call and it asks the expectation to calculate the return value for this mocked call. And then it returns
43:03
here to call, call returns from message missing, and foo returns from there. So that's how we find the expectations in FluxMock. That's a lot of details there, but when I walk you through this, and kind of walk you through it, it's a very easy way to describe it. I
43:20
like and dislike sequence diagrams. They are the most fragile diagram to write because they break all the time. As soon as I change anything, this diagram will be critically wrong in some manner. They're also a pain to draw. There's lots of details in here in getting everything
43:40
to match up right, and that's a pain. This took me probably the longest diagram of anything to call, and to draw it I have to walk through the code myself to understand it. However, the process of walking through the code to draw this diagram is worth everything. This is the one case where I feel the diagram, eh, I have ambivalent feelings
44:00
about it. But the process of writing this diagram means I've got to really understand what's going on underneath the covers, and that to me is the big win of this kind of thing. So UML, I find, I draw diagrams not so much for the diagrams benefit, but a lot for the learning that happens when I draw the diagram. So let's kind of summarize here just really quickly.
44:22
UML, it's great for detecting dependencies, and that's my favorite thing about UML altogether. Yeah, let's knock down the sign. My favorite thing about UML is doing the dependency looks there. Looking at structure, looking for anomalies in structure when I draw
44:40
the diagram, it's good for that. It's good for denoting dynamic behavior in a way that the code kind of obscures sometimes. And then object interaction is another feature of UML that is probably a less used feature of UML that I personally use, but well worth knowing about. Some tips. If you want to start drawing diagrams, here's some ideas.
45:02
Decide what idea you want to communicate with this particular diagram, and draw it with that in mind. Don't worry about capturing all the details. Capture only enough details so the diagram makes sense to the audience that you're addressing so they can understand the idea that you wish to convey.
45:22
Explore ideas. Like I did with that rake redesign thing. Maybe we could redo it like this. Now that diagram is probably wrong. I probably missed some detail somewhere. But it was worth exploring. Give me an idea of where I might want to go in the future. I recommend you draw the diagram. Don't depend upon automated
45:42
drawing tools that examine your source code and put up diagrams. They put way too many details in the diagram. They don't convey an idea. They convey exactly what the source code conveys. You might as well just look at the source code at that point. It's the editing process that makes the diagram useful.
46:00
And keep them ephemeral. Don't try to generate lots and lots and lots and lots of diagrams for your application, thinking, oh, it's going to help so many programmers in the future. A few well-designed high-level UML diagrams placed in the document directory. Excellent. Lots of detailed diagrams placed in the document directory. They'll get out of date
46:21
before you know it, and just not worth it. So keep them ephemeral, and I love whiteboards for drawing UML. Presentation tips. If you're going to do a talk, and you're putting UML diagrams up, make the lines two pixels. Who knew they looked so much better like that? They looked like, mmm, they mean something.
46:41
Ah, this is wimpy. A good book on UML is UML Distilled. It's a thin book, unlike the thick books you can buy in UML that go into all the very details. UML still talks about just the essentials of UML and gets you going and getting your diagrams up and running. It's still pretty good. Some tools. Whiteboards. We have an office that has three walls
47:02
of whiteboards. Mmm, I love it. If you want to do it programmatically, on the cheap, I recommend UMLlet. It is a Java application. It's really lightweight. It's got a really unusual editing feature, but you can get good looking
47:20
diagrams up and running fairly quickly with UMLlet. All the diagrams I did for this talk were done in OmniGraffle, which does really pretty diagrams. Umm, pretty is important. I think sometimes making them pretty makes you feel like you need to keep them around longer than you need to.
47:41
So, I'm not actually recommending UML for your day-to-day UML diagrams. Whiteboards is my first choice. UMLlet is my second choice. If you're doing a presentation and you want it to look pretty, OmniGraffle then is a good choice for that. Okay, so you're all going to go and start drawing diagrams now instead of writing Ruby code.