 Who wants to play a game? Great Yeah, we won't be having any insults. So Yeah, I need a volunteer Okay Come on. We won't be Playing with swords But we'll be playing with tic-tac-toe. So what's your name? Bert, great. You'll be Alice from now on Okay Yeah, so here you can start the game you can join the game that I start and Yeah, that's basically it so you can start the game maybe So here we can see That Alice started the game and There is a Bob in the the other browser. Let me find the cursor so I can join the game now Okay, let's see What what Bob is doing or what Alice is doing? Okay, so it's your turn so we can Play it take great Okay, yeah, we can we can start another one. Maybe somebody wins Okay, I started the one from for you, so I think you need to go back to games and go to the This game. Okay, now do your best. Yeah I'm the rubber you're the glue go on go on Nice, okay, great job Okay, so Let me set up the Wi-Fi and Continue with the presentation Just a second. Okay, it should work Nice Okay So there are two facts about multiplayer games Players expect a snappy interface and The other one is that players usually cheat and What does it mean is that the game logic in this in this example at tic-tac-toe? So there are a couple of rules to win a game to make a next move so the game logic needs to be implemented on each client on in the multiplayer game and Also because players cheat the game logic needs to be implemented on the server So it used to mean a lot of redundancy because then We have a rail server then we have a JavaScript application and then we have an iOS application and so on so on But now now We have the technology with opal or air be We can create Ruby applications in the browser So has anyone here used opal before? Great free people maybe okay, so opal or be is a Ruby to JavaScript compiler It's quite fast. It's actively developed. It's not that stable yet, but it works and It has some drawbacks, but it allows us to Create actual Ruby applications in JavaScript, which is quite a good thing Then There is Ruby motion. How many of you use Ruby motion? Nice half of you So Ruby motion is a Ruby to objective C compiler and from Like two weeks ago There is also an Android toolkit for for Ruby motion It doesn't work that great yet, but let's say in a year. It will work as good as objective C one It has close to the native performance because it's compiled to objective C runtime and to Yeah basically Java compiled classes For Android it's actively developed and it's quite widely used in production So there are also there are there are already working applications made in Ruby motion like 37 signals base camp for example There is also mruby and how many of you use mruby or use that? None, okay, so this one is pretty interesting It's basically supports ISO Ruby standard and it can be embedded into any C application or any C library So it means you can put it in into any kind of application that can be linked with C so With mruby you can potentially create applications that run on any platform on Windows on Android on Yeah iOS Linux whatever whatever Works so it works even on Arduino do a because it requires Quite a lot of RAM like 96 kilobytes So it wants to run on the plain old Arduino But it works on Raspberry Pi Arduino do and a couple of other embedded devices And yeah, so it's basically promising for Windows desktop applications but Are any of those? Ruby like things really a Ruby Well kind of there are some differences for example In Ruby motion, we don't have require at runtime. So everything is statically compiled and Apple doesn't allow us to Generate code at runtime So basically we get a warning when we require something There is no evil at runtime. We can still use metaprogramming, but not The one that involve parsing Ruby At runtime, but we can still use Defined method using block or and things like that So There is this difference with Ruby MRI that threads are actually working So if you port things from MRI to to Ruby motion and use threads before then you might find Some bugs that you haven't find found before and It doesn't have garbage collection. So it uses automatic reference counting in Objective-C so Memory leaks are actually possible. They're not that common right now, but if you use blocks and Events then it's possible to have one then there is Opal-Rb and This basically works in a browser and it compiles to JavaScript. So Requiring files also don't make any sense So every required statement is translated into sprockets directive if you use it in Rails Strings are like in JavaScript are immutable Symbols are strings unfortunately because the focus was on the performance of the language and There was no better way to implement symbols in JavaScript There are differences in couple of things like regular expressions are Implemented as JavaScript regular expressions, which are different from Ruby obviously and All numbers are floats JavaScript Yeah, but there is for loop already so when I gave the talk half a year ago for loop wasn't implemented, but it's They work on the language like they work on the compiler all the time. So For loop is already there. So that's a good thing With mruby Still no required runtime If you want to include gems they work in a different way So you need to actually compile a compile them into mruby library up front so The focus of mruby is on the size of the program the Maths won't want it to be Small as possible so There are a lot of things in ruby that are not in In mruby for example regular expressions are not there by default you can include a MR gem it's the version of gem for mruby to include the missing functionality But you cannot do it on during runtime you could Probably implement some system on top of that, but that's up to you And it's optimized for size and This is interesting because because of that it's often faster than MRI But that's a side effect. So the main question is that are all of those really a ruby They ruby enough so if we Don't think about the differences and get rid of them and see what's What is the common subset of those languages we'll have cross-platform ruby and the idea of making the Applications in cross-platform ruby is to Have the some core logic into in this subset of common code written in the cross-platform ruby and have different platforms use that so these do Any one of you recognize the shapes here or something like that? Does it ring a bell? Like the hexagon in the middle Okay, so it's basically similar concept to hexagonal architecture that uncle Bob is talking about He's basically talking about Extracting the core logic of the application and have Adapters for for example database so we can switch databases easily you can have adapters for GUI If you need to present everything in a different way So the idea is to have the application work in a command line the application work in in rails and just switch adapters if you want to use different ones but When it comes to whole platforms, it's actually not feasible to abstract all of that So how would you imagine to abstract the whole iOS? That's yeah, that's just silly so It actually looks like that The idea is to have like the small subset of functionalities for example Let's say we want to save something and we we need to save it in iOS We need to save our models in in androids or in the browser Then we can extract the saving functionality to some pattern like repository or something like that Implement it in plain Ruby other interfaces to that on different platforms and use it so The most interesting thing about that Are the interactions between all of those systems? The first and easiest one are the internal interactions So how do we implement communication between the cross-platform Ruby components? So there are different ideas Clean architecture hexagonal DCI DDD cowboy coding. Why not? This is your dreamland you can do whatever you want This is plain Ruby no database no GUI no apps no different well No internet Connection just plain Ruby classes you can do whatever you want there. It's It's a great place to be test our fasts in the in this domain and Yeah, it works great then We have different kind of interactions. So When we want to access the cross-platform Ruby components from the outside So we have the iOS application. We have the rails application and we have some small component that's Does something for us so sorry for example, let's say we have We have translator module that will provide translations for labels or something like that. So we basically Create the interface on the cross-platform site and then access it from iOS We access it from rails and we do it in the same way. So basically here. Yeah, it's the really simple simple idea so We just want to get a text for the label that is the same on iOS and in the rails application The other The other thing we could do for example in this way let's say we want to Know what users do with our application. So we implement something like kiss metrics or Something like that and we want to encapsulate that Into some kind of interface and use it on iOS and use it on rails. So we have different events. We have different user behavior, but the core Interface for Saving the events is the same so we can actually encapsulate that and use the same thing on both platforms the next thing is when we Drive our application from inside. So the code that matters is in the cross-platform Ruby site and we want to Access the code on the outside. For example, let's say We have iOS we have the browser and we have some kind of wizard that's have some panels and We want to animate them and if we encapsulate the different ways of Of implementing that on a specific platform in a common interface We can actually encapsulate the logic of Let's say this wizard Into cross-platform Ruby and then drive it in the same way from one place and the last type of interactions are asynchronous ones so let's say we have a to-do item and We have the method market as done and We want to save it afterwards on each platform. So the saving on the on the different platforms might mean the different thing for example saving in Ruby in Rails, it might be just Saving it using active record to the database, but saving it in the web browser might be actually Creating a post request to the Rails application And let's say we want to have the same interface for that so if we want a common interface with with interactive Applications Let's say let's say we have a mobile application We press to do and we wanted to have it in the background and be have the The user interface updated automatically so we need to have some kind of mechanism to Have asynchronous interface So we can implement that in three different ways So we can use the abstract in for interface. So the same thing as in the previous Previous slide when when we drive the applications from inside We can use some kind of notifications like events or key value observers or We can use abstracts aspect oriented programming So with abstract interface We need to modify our class that is in the cross-platform Component so let's say we We inject some kind of saver object that will that will do the right thing on each platform and Then after market has done we just do saver save method and On different platforms we could for example save it to database we could save it via post request or something like that and And This has a pretty This is a pretty good idea because like it's it has well defined interactions and it's useful when Use cases on each platform are similar. So if we want to save the to-do item on different platforms then Creating the same interface For saving them is a good idea, but then the core our cross-platform Ruby component needs to know about saving and saving might be the concept that it's pretty alien to To the domain that we have like we have a to-do application We have to do we we just want to mark them as done. We don't care about them being saved maybe So it depends We could have like a bit more freedom with notifications. So let's say we have a to-do we include some kind of eventable module that will provide us Basically triggering events on some listeners so So let's say we we just need to add a trigger for an for an event after well Let's say after mark has done we do the the thing and then trigger the The actual event so in this case We just need to on different on different platforms. We just need to provide the event handlers so Let's we can save it to database we can post it to API but this is a Bit better thing if we really want to core to not care about the The actual use case so we just Push an event and we don't care what happens next So we don't need the same interface on different platforms. They can do whatever they want after To do is marked as done Yeah, it is But it is hard to compose interactions, so yeah, if you have nested ones like Yeah, one event is calling the other and so on This leads to pretty complicated code. So yeah, that's that's the con and Yeah, this is the place when we need to be aware of member leaks in the Ruby motion because mmm The blocks are handlets handled in a different way in objective C and Ruby and if you if we are not Careful about using weak references and strong references there then we can introduce member leaks But it's not that bad If we want to real freedom We can use aspect oriented programming and in this case our to do class that is the implementation of the core domain logic Can be blissfully unaware of the surroundings? So we don't need to change it at all. So it's just mark has done but then We use some kind of aspect oriented library and We can Add callbacks from the outside so for example In the rails application, we would have this database to do server and We we would add a callback after marking to do as done with When the domain class does that and then we can save it to database and Similarly We can do that from the From the browser. So then we post to the service after adding the callback from the outside so this is pretty good thing if you wanted the core to well to not change at all and only Add some code from the external platforms, but then The external Pratt platforms need to know about specifics of the The cross-platform Ruby code So Whenever like the to do mark has done changes then we probably need to change everything on each platform So it's well, it's not not that good in many cases But it's useful when use cases are totally different on on every platform So when we don't need to save the to-do we just don't add a callback at all and it's and it's great so Where to keep this logic? We can simply create cross product cross-platform gems and how to do that It requires a lot of work a bit of work. Let's say because It's not really possible to take a random gem and expect it to work on Opal and in Ruby motion because of basically require and couple of other stuff, but require is pretty important so For opal We need to somehow tell sprockets where to look for files and then require everything as usual for Ruby motion We are not really allowed to use a require in any any file that is included in runtime so we move all requires to the gem entry point and We need to add all those files to To configuration of Ruby motion application so they can be compiled and included in the application And the good thing about that it actually takes 20 lines of code So if you're interested in that I made a blog post about that It's really simple to to modify a gem to be to work on Opal or be and Ruby motion and rails and Yeah, but it needs to be written in the common subset of Ruby. That's that's the thing Let me show you some code So the game that you that you seen at the beginning of the talk of the tic-tac-toe one. It's actually created in the cross-platform Ruby, so it runs in the browser the same code runs in browser the same code runs in rails and also on iOS so This is how the application is structured. So we have the One common directory that has different implementation for each platform So this is basically the iOS application This is rails application and This is the common gem that includes the functionality for rails for Opal Ruby and for Ruby motion So This is not actually the Only a tic-tac-toe game. Basically, it's it's a platform for any turn-based multiplayer game and There is some abstracts there are some abstract classes like game Board the move there is like a move maker move outcomes player and there is also Implementation of tic-tac-toe Game so this thing is written in plain ruby There is no database no GUI no such thing so we can test it pretty quickly. It's it works on every platform and that is good and Yeah, so and there are also Things that I call the interactors. So this is the thing that has All the actions that player does in the application Do you see it or Yeah So basically are there are different actions. So when you start a game We create the class We we create an object for game Depending of game type it could be tic-tac-toe or something else Then we start a game like this and Inside of the domain logic and then we use some kind of adapter to To handle the event for starting the game so because like starting the game could be handled differently on on iOS or in the browser or in Basically raise application. So the same thing with joining joining a game What else finding a list of games Finding specific game making actual move so This is actually like Taking taking the mover presentation putting it inside of the game logic the game logic validates the move it will like rise an exception if something is wrong and Then it will publish some kind of event to the adapter Well, actually call a method on the adapter to make This move Yeah, and that's basically it. So let's see for a second how it's implemented in different applications So in iOS We have this controller, let's say so we have like a games view controller. So this is the No, I can show you what's so this is basically Something that represents so Unable to connect the internet. Okay, obviously so this is basically controller representing the list of games and There is there are a couple of actions here to start a game to join a game and fetching all those games so We just take this interactor We put the rest adapter that will be responsible for handling different things in our game and then We just add some code on Events that interactor will will post so When the games are found we just scheduled the next refresh. So yeah, basically it's long polling for for the games When the game is joined then we we do some stuff like Yeah, we basically do Like platform specific stuff. That's that is driven from inside of the interactor. So this this cross-platform Ruby part of the application and So and the same thing happens in the In the opal application So let me just show you quickly So we have games view. Where is this adapter? Oh, yeah so we have the interactor here and The same as before we just need to call the interactor and then respond to an event that will and that it posts so from From this point of view, it's like the basically the same implementation on each platform. We don't need to think about What we need to do in the game logic when we start a game some things happen like Probably a board needs to be generated then some things need to be saved in the database or sent to send via internet But we don't care about that we just We just implement things that we need to Do on each platform so after game is joined we we want to go to another view like the view of the game and show the game to the user If the game is started we also change the view and Yeah, if the on this event where games are found we just refresh the list of games with with the new one And that's that's basically it. So the only thing that changes is this This rest adapter and this thing is is just a simple class that Needs to conform to the common interface so it needs to have a method like start game join game find games and so on and it basically makes a post request and On success it triggers an event like the game Started after after request was successful and so on so on So the same thing is implemented in iOS We have also the rest adapter. It looks a bit different because we have different libraries Some platform specific stuff, but we also do post requests here as well But the interesting thing is that we can reuse that stuff In a rails application so Okay Here we have database adapter which conforms to the same interface, but instead of like making a post request it just Takes an active record object creates it from database and Yeah, basically does The thing required for all validations and stuff so And after it's it's done. It also triggers the event so the idea is to have like the the same interface in the Interactor and use it in In the mobile application and in the rails as well So this looks a bit different than what we are used to Because we have the games controller and this is basically a create application So usually we would like take active records. We would like take params put like created in a database validated and so on but This is a bit different. So here we use only Interactors We use it in the same way so We start the game we put params that were sent from the mobile application Then the game Interactor does this thing like validates all the game logic and all that stuff then it calls the database adapter and data that base adapter saves everything that it needs to save prepares Database objects and then it publishes event that the game actually started So it's the same thing with game joint when we have the list of games and When we make actual move so It feels a bit different It definitely requires some Like everybody to come if you if you decide to go this way you need to like conform to the Different way of doing stuff so conform to use only the The domain logic and respond to events which is which looks weird on in rails controllers, but It allows us to use basically the same code on each platform and it's kind of good idea so The idea is if it's if it works Well, yes, it is. This is the proof so you can create applications like that. Is it feasible? Not sure depends on your on your application so It definitely adds a lot of coupling between between different platforms so whenever you change the logic of Of The core of the application you would need to change something In each platform probably but on the other hand if you have use case like that when you have Some logic that is really Duplicated between different applications like mobile clients or web browser application or rails Then it might be a way to go So Some people said that Ruby is dead. I don't believe that I Think Ruby is alive and It's taking over the world one platform at a time. Thanks