 Okay, good morning So today we'll be learning all the rules you need to know for making your code a very measurable testable and perfect I'll teach you everything you need to know you need to like memorize it obviously Right because if you don't memorize it, how can you know if it's good or bad when you see some code? Some people think that goes over aesthetics, but I I disagree strongly it should just be correct according to certain measurements I'm actually kidding and I was planning to start this This workshop asking you guys to please present with each other to the people at your at yourself And I will actually do it just in case but I see that you're already socializing I was going to ask you to please present Present yourself to the person at your right or left or whatever Tell their name and ask them if they are new to programming and how long have they been working with roby? So please go ahead. You have two minutes Okay starting Good morning everyone. Thanks. Thanks for coming. It's amazing that you're all here I'm so happy to see you We learned here how to transform this type of code you can see that it has some weird coding standards It has like dollar signs everywhere arrows for for object orientation Well, I'm actually kidding. It's just php But you can put here You can put here any any code you have in your applications that you feel is just painful to work with that you feel It's more complex and it should be Any code that it should just be clear or easier to maintain like you have an application for to-do lists And you can't implement a new feature. There's something wrong So my goal is that after this workshop you learn the specific Steps required to actually improve that code base while you are working on it without losing productivity And without obviously rewriting the entire application So check it out because we'll learn how to transform this code into this one. Oh, sorry into this one So while you can see that i'm cheating here, but the before and after like i'm cheating here It's just a one liner hiding all the complexity somewhere But the before and after code after you implement some of the patterns we'll see today can be as impressive as this I can assure you so that's amazing and that way i'm very passionate about refactoring I think every one of us should be constantly at least be aware of that these things exist And then use them or not freely like really there's no silver bullet. I agree with david in that But at least we should be aware of what things are we not doing right and we could just to to not Not get get stopped. It gets stalled in our in our development When we get code like this and we can't change it without breaking the application So before we start I need to know a little bit about you How many Couldn't get the repository yet my repository with the exercises one two three four Okay, who has a usb stick? Okay, please pass it around and i'll be asking that question every two minutes or three Anyway, as jeff said if you are having trouble and if you don't have ruby or the repository just please pair with the Thankfully, it's not a hard drive just Obviously like just pair with the person at your side and continue working um Okay, uh, we'll see today refactoring patterns. I didn't want to put those enterprisey words in the name of my talk But that's what we'll see today anybody's Familiar with these concepts refactoring and patterns Anybody want to describe like the idea of what what does it mean? That's okay. If it's a very general. I want uh, yeah, please I see refactoring is editing your draft I know that sounds corny after what we just saw but it is like you write something down and you say How can I make this simpler? How am I making my point clearer? Perfect. Yeah Indeed and by pattern by applying a pattern to refactoring What we make sure is that there are specific steps to to apply that will lead us to better code And there are scopes also so we want to end up rewriting entire chunks of code in a single in a single hour So what we'll learn today is a algorithms for improving our draft. Thank you Now a little bit about myself I'll tell you what I've been doing in the previous years and why am I so passionate about refactoring in general And why do I think that people should think about this constantly? But first thing first my name is not to actually my first name is eugenio But I had a problem with that name because there's a very famous Italian with that very same name and so when people in the open source community wanted to google me They would see this ship, but I'm not a ship. I can assure you I'm myself So this a costa grocery It was actually named after my name eugenio costa And it's and it's crazy because my grandparents actually traveled in that ship And they saw like all the merchants lives with my name and they freaked out And they brought home like big teddy bears small teddy bears bat mat So my house is all now embroidered with my name. It's crazy But this was not useful for open source because I want to relate with the community I want to be able to learn and teach from the community. So I just chose my nickname to te Which is hard to pronounce. I think I am coming from Buenos Aires, Argentina. This is In between Uruguay at the east chile at the west in the north. We have bolivia paraguay brazil Anyone here from latin america or spanish-speaking countries? Wow so many Okay, bienvenido Beautiful, let's talk after And even though i'm from argentina, I don't play soccer, but I do have an asado every four or five days a week Um Coming from argentina sometimes I say very clearly what I want to say in english, but people somehow don't understand So I was once at work and I said, hey, there's a bug in the software And they were like what and i'm like, dude, there's a bug in the software. You mean a bar? Oh, well, if you're gonna get technically I mean a bar So please if you find something weird and you want to interrupt me, please do and I'll just repeat it in different different terms So in 2011 I worked in a small startup called chef surfing. I didn't follow any best practice I was a dream of david actually. I was learning by my own experience I was doing whatever felt right, but I wasn't I didn't know so much about architecture patterns and stuff So I committed many mistakes there and this team was small. I was my own lead So we wrote a lot of code and every two months the complexity Would bite us and so somebody would say there's a bug in production So please fix it and I'm like, well if I fix that I have to I don't know break something else or just stop for days And refactor and it was annoying. It was like weird. We have to stop for a week after two months Test and refactor. It was not predictable. Not sustainable. It was just stressful It felt very much like this. You are very carefully working with something and some Suddenly it just breaks down and it's like I don't want to there has to be a better world So next year I went to general assembly. They had a real application in quite about jpe But it was tested. So refactoring wasn't so risky and thankfully they told me please refactor all the things and so I did And the amazing thing in this story that I actually could do it while I was While my team was still feature shipping. They were still deploying to production probably many times a day While I was refactoring not only the code but the database as well and stuff So I I felt that was a happy story that I want to repeat everywhere. I can and actually improve it as well And that way I'm very passionate about it like in general assembly. It improved so much the code It made it simpler. It made it smaller. It made it easier to work with it. It made it like nearer Um, I'm sorry. I left for the usb stick. Who has it? Who has my usb stick? Okay, who needs it You are using it. Okay after you uh over there, they will be needing it So, um And the team was so happy to receive the refactoring this refactoring into the code They said because suddenly we could stop the talk the same language as as developers as the project managers as the business owners Because when they said like something like a classroom full of students the code spoke about the same concepts So it gained productivity week after week and it's still I believe ripping benefits so Oh before who who here is like in a similar situation as I was with chef surfing Here where you can where you sometimes have to stop the word and refactor anybody like feeling they should improve their code big time Okay, not so many happily. Wow. What an audience. Hopefully you'll learn anyway Um before precondition you have tests never refactor without tests you are you run the risk of Introducing errors that weren't there and everybody loses you lose your client loses the users of the application lose If you try to refactor without test you end up like like this like I was in chef surfing like oh, no I thought I fixed something. I actually broke it. I would have stayed at home doing nothing and it was more productive So these are the four patterns we'll see today These are the magical spells that you need to memorize so the code will be correct Anyone familiar with these ones? I'd like you guys to describe whatever you You know about them. For example for intention revealing method Anyone would like to describe it? Nobody familiar with it. Okay, please You didn't look at the code and it essentially tells you what it's going to reveal that's in that code Yeah, I did Um Indeed it turns comments are necessary because suddenly the code itself is is saying what it's doing at the same time Uh, the second one we'll see today special case object who would like to introduce the idea Nobody special case object. It's a variant of null object. Uh, null object pattern that I also it's a case I'll present Okay, so special case object A voice type checks a voice conditionals in your code So if in your view you have code similar to if there's a current user here Then display this welcome message and if there's not displayed this other one All of those conditionals will will like suddenly not be needed in your views in your models in your controllers everywhere So that's the idea of this one refactoring pattern replace method with method object, uh, which seems very Very weird to speak about anyone familiar with it that would like to describe it Okay, so I guess I'll do it myself, but I'll wait another minute though use the stick replace method with method object is useful for Extracting big methods from big classes without Needing to rewrite the whole thing So the rigs there is that there's many instance variables and there's too much context And if you start to refactor to refactor that right away You will see that you break too many tests to be like contained in a single hour of work And suddenly you run the risk of of rewriting So the interesting thing of this pattern is that it scopes scopes your work of refactoring that big chunk of code And service object is useful for extracting Responsibilities from big good objects. So typically the user in a real application Knows how to speak out descriptions about the product advice and so on and it's like a 500 line of code if you're lucky So with service object refactoring pattern And You are able to extract these different concerns in an organized way So I'll start now showing code at last so intention reading method is It's a variant of extract a variable or extract method in which you give a proper name To a to a chunk of code So that it describes itself and you won't need any longer this comment So this line of code was totally cryptic That that's my own code actually and when I came to it a year after I had to add a comment to myself because I didn't understand What was going on there? Uh applying intention reading method, which is a simi is really really easy There's a really easy way in four steps that I'll show you right right away I could change it to this this uh, there's the before and after code Which the code itself says says what's going on putting commenting code is a bad practice Because at first like if you can call without comments It means that you're already writing code in a clear way in a readable way Such that you don't need to comment in in natural language And more than that a comment is a lie waiting to happen Because you may in the future change the behavior or something and the tests run and everything goes well and you commit it But you may forget to change the comments and so they are actually misleading So, um, I find very interesting this idea of trying to call without comments That's that's another rule that you can bend whenever it's better to bend But it's a nice rule for myself like that's this code need to comment and so how can I improve it? So I don't need any longer The algorithm I have to apply in this pattern is you have a chunk of code. It doesn't describe itself I'll comment if it needs it if it has a comment great Then transform that comment syntactically remove the pound sign at the beginning Change the space by underscore and suddenly you get a method run the tests If you run the test at that level the method will don't exist And so you go ahead and write that method Remove the comments and the code write reads itself I'll show it to you this idea here calling in the browser That you are am I here? So what I just said is Remove this comment. Look what I do. This is just syntactical syntactical transformations. Remove the pound sign Transform this into a method Change it by the line of code we want to extract And suddenly no need of comment here. I can Define that new method Well, whatever it's hard not to look at your keyword And suddenly the code is better So that's all we need to just remove the comment and transform them into code So we start now with the exercise we get a 15 minutes a per each exercise. Let's start Do you have the Do you have the? The repo all of you So there is a read me there explaining how it works. I'll tell you right now before we start Uh, there's four folders for the four exercises We'll see they have the number at the left like the number one intentional link method Is the one that will work to win right now There's an app. There are v file, which is the one with which will work And there's tests then to run the tests you just run the app the app The app file So while you are coding you can constantly be running the test and see if you are breaking something or not And the goal is that the code that's there instead of being a long method, which is quite wide as well reads itself So the implementation details go down in the class You don't care about the implementation details and the main method reads like English So I'll be going around a few for 15 minutes and Work work together Please start and ask me any question if you have one and please help each other as well The first step guys is pleased to run the app. There are v file so that you actually see the tests run and they are green You will need mini test if it doesn't work for you Please pair with the person next to you and I encourage you to work in pairs It will be better because it is a very subjective matter And it's more just collaborative and more fun anyway So instead of having each one in some computer. I encourage you to actually work on a single one run the app there are v and I'll be going around to to explain what's the next step after that happens Just make the code read itself better removing the comment. I'll open them up here Removing the comment and making them code A comment. I forgot to make this requires many tests and I apologize I didn't include a gem file I thought it was with ruby. That's my mistake. So if you have many versions of ruby Choose the one that has many tests installed so you can actually run the tests Pair with a guy at your side or the woman at your side so you can actually work if it doesn't work And well, that's it. Like if you get a constantly missing mini test, that's that's yeah, that's my mistake Don't worry. I'm sorry and use my version of ruby or pair up with someone else Time is up for this exercise Thank you guys Sorry that we don't have enough time so I'll interrupt you right now This will happen in every exercise and I'm very passionate about this So if you want to like talk with me in the hallways or later or through twitter or github Please do because I love doing this work. But now I have to present more content. And so here we go Some people discovered while thinking about this particular case or while refactoring That there's some funkiness with the conditional and is the user is there or not and which lines of Of code get executed according to the conditions That that's right. There's something funky in that code and it's amazing that you found it That's that's another like nice benefit of refactoring You think twice about the same code and you ask is this a bug or a feature and in this case it was actually a bug So not only did you improve the architecture of the code and you maybe simplified it with one less conditional But also yeah, you discovered something that was going on your application and you weren't aware before of it So that's another benefit and thank you for pointing it out. That's that's totally Totally correct. So I'll move on to oh, sorry. I won't move on yet There's one rule speaking about rules very tough. It seems from this woman who is amazing at Speaking about design and the software development. She's called sandy meds and she said your methods shouldn't be Actually, she's here. Right. She's here right now sandy meds. I would love to see her and I see her And I want to thank her for her great book She said your methods shouldn't be longer than five lines And that's crazy because if you have a switch statement or an if with an lcf You're already in seven lines. So it's like are you are you trolling here? What's going on? But if you apply this pattern a certain amount of times it's actually easy to get to that size Because you start like a moving implementation details like the switch statement like the if router at last Into into private helpers in the same class and suddenly your code at the top is just speaking english It's just saying if user is a old in a like I don't know older than a week ago And you can write that in ruby in english Suddenly it's easy to follow this rule, which is amazing. It lives to better code in general And sometimes you should bend it for sure, but if we should have someone that authorizes you so she says um This is arguably the easiest pattern because it's just uh, sorry Oh, thank you. Wow I did This arguably the easiest pattern because it's just syntax transformations. Wow. Sorry. Sometimes I do I need the microphone at all Can you hear me like this? Oh a little okay, so I stick with the microphone But it's also the hardest one because it implies naming and naming is hard It's true that it's hard and not only naming it also implies that you know Which are the levels of obstructions of your code which is which counts as a business rule And which counts as just an implementation detail And well, you will see what feels better if you make a change on your code and the before and after looks worse Did what you did at least you gain the perspective over your code and your problem And if it's better go on with it So while it does seem simple Don't do it and just commit it because it may actually lead to something less readable or more confusing Hiding what's actually a business At something that's core rule to your application and that should be there on the top In the slides I put resources always at last of each pattern So I'll share them in twitter and speaker deck. So you will have them all Moving on to special case objects This avoids conditional in your code base. So suddenly you don't need to put an if The thing that it avoids especially the one that I'm going to show is the nil problem So you have seen as Ruby programmers probably this Hard to trace the error and define method email over nil class You never know where did it come from because it could be coming from a hash with a key that doesn't exist Or with a hash that has that key but actually have nil as a value inside Can come from a Conditional that didn't run like didn't have one of the bodies and it returns that one as an empty method So nil can come from many places. It's hard to trace So returning a symbol rather than nil is already an improvement Because at least you can you can get instead of an defined method Email over nil you will get a defined method email over a symbol over guest user Abdi Grimm suggested this pattern and it already helps to debug because then you you find in project that symbol And you know, where is it coming from? and even better than that sorry before that Here we have this conditional it has to be there all the time Whether you have a symbol whether you have nil you will need conditionals everywhere There's not an object that you were expecting in this case a current user. So you can say welcome user dot email And if you forget about it you will get exceptions in production everywhere And you will forget because the applications get big you have to put these conditionals in views in background jobs in models everywhere so better than Symbol the idea is to introduce a new object that responds to the same methods than the object we are Replacing so in this case in the top we have a new model called nil user Which is not active record. It's not baked in the database or anything. It just have a absent methods Then we have somewhere in the controller the current user helper Which either finds the one which is logged in and if it can't find it it will return a new instance of the new user Suddenly the view has no conditional Because whether there's a user backed in active record who is real who has a real email or there is this new nil user It will display the correct welcome message And suddenly not only that conditional was fixed But all the other ones in the your whole code base And suddenly you don't need to remember to put these conditionals everywhere you use a user And so it avoids a future problems And suddenly a code reads better also because you have like less imperative instructions in your code base So that's the idea of a special case object And let's move on to the second exercise. I'll put there again my beam Window I've seen many having trouble with mini test gem Please if you don't have somebody working like beside of you because two of you have that problem Move a move around and find somebody who can't do it Please pair because of all of this is so eager of is so subjective and so interesting to discuss about It's much more reach to be discussing one problem together rather than being in parallel trying to solve it by by yourself This is not hard technically, but it's hard like Like Which decisions to take which code to write how to name that method why to extract it. So please pair please be noisy Let's see So folder two I'll show it to you here I'll explain to you this problem. This extracted from an application. I worked with actually And there's a user who has a subscription the last one is the active one And you can cancel the description you can show it in the in the report job which is a background cron job that sends emails to their business owners and It may be nil because sometimes the description may not be there because the user signed up, but actually didn't subscribe So the goal is to introduce a new object that we return here So that when subscriptions that last is nil we we return something else And start simplifying all the code after that's running after you get a new class with a new object and you return it there You can get rid of the conditional line four and all the conditionals that are below line 25 So that's the goal today I'll hear some syntax and you please move on and I'll be going around and ask me questions and stop me Go on So sometimes the mini test problem is because of ruby versions Two one and two and one nine three run different My tests are inheriting from mini tests. I don't know what and he knows how to fix it There's There's a syntax change that if you make starts working. So please ask me if you think that's your case or change ruby versions Timeout is over How did this one go guys? Was it better than the previous exercise? Two was better than one Yeah, so I think I'm happy to hear that but if you have any trouble, please poke me and we're yeah He will be helping as well. Thank you and uh, yeah, you please stand up We three are helping you guys So whenever you're stuck with any step any syntax problem or any interesting discussion to have call us three What are your names guys? Jeff Roland and today obviously well obviously sorry Um Okay, I'm happy at this one better now. We'll move on to replace method with method object Which is for when you have code like this, which is so ugly this is uh, the first intention ruling method that was like Removing duplicate from the code. I took it from this piece of code that I wrote myself when I was six years old So you can see it's super long and ugly and there's like two chunks of Of uh of behavior. There's some initial. It's like a class in itself. It's like a class in itself this method Um and more problematically this method was instead of a class which was itself big So whenever I tried to change the behavior I would have to change the instance variables and so the other methods that were using those instance variables and everything And it was a big rewrite that I couldn't afford because I didn't have tests But thankfully previous year I saw the talk through the internet from katrina owens In cascadia roby where she implements this this pattern in a code, which was as bad as this one Uh, and it's a great talk that I encourage you to see she speaks for one hour on how did she solve it And how did she develop tests for for chunks of code that were completely untested very interesting Um, so I'll show you again an algorithm that you just apply and suddenly boom. It works. It's better Uh, the first step is to look carefully at it and get scared I'm just kidding the first step is to create a new class every every time we have a problem in object oriented software Typically an answer is to extract a new class a new object encoding this behavior or data Uh, in this case, I know that this code because I studied and a year after writing it Was trying to format a csv with one shape a file with data Into another shape shape. Let's call it format a to b And the first step is to create a class with the same arguments in the initializer as the method itself There's gonna be four steps You don't need to memorize or take note of them because they are written as a comment in the exercise in the file in the code But I'll now go through them The second step is to copy and paste the methods body into this new class With no arguments because now we'll be using The instance variable that we set in the initializer The third step is to replace the original method in the big class We call to this new class. So suddenly The the method which was problematic in a class that was big and complex Is a one-liner suddenly that class got smaller and a big chunk of behavior got its own object with its own name The fourth step applying tension ring pattern Intentional revealing method to the new class and this is safer now because you are now Constraint into this new object and whatever you do there in this new object is isolated from the big class And hopefully the application itself. So now you can do this in a more Constraint environment in a more safe one and whenever you want you can commit and if the tests are green then it's gonna be fine Um If you do it before you run the risk of having to change too much code at once and that's always dangerous So the whole idea of this is to apply intentional link method in a way that that you Don't touch too much of the application. So I'll open up that code now It's the three number three Uh Here is a big method. So the very first here the fourth step that we need to do I'll do the first one You define sorry, let me remove the comments You define a new class there Let's call it format a to b but you can call it whatever it makes sense to you And you define the initializer and so you go that's my suggestion as first steps Uh, and then apply one or two iterations of intentional revealing method and continue running tests all the time and call me whenever you need help Well time is up I'll go on to the fourth pattern service objects But this one I want to exercise it because it will move a After the hour we have which is until 12 30 So I'll just explain it to you and you always have the exercises in your machines And you can poke me and we look at it together later if you want to and if you don't want to whatever Here are the resources one of the links I put here. It's actually the video from cascadia ruby from a from I forgot the name Katrina oh and thank you Which is a great great explanation of how this should be factored something like this um So the fourth one is service objects The problem that it solves is when you have a god object And uh, you want to add new behavior in the case of my application? I was working with we have a user which was big. It wasn't so big It was a greenfield But anyway, we need to add the subscriptions and subscriptions wouldn't belong to the user. Although it was so easy to implement it there Uh, the problem was that if we put it in the user We would be coupling a new dependency losing cohesion for the user Testing it harder and slower suddenly a user can have so many relations and so on and following the single responsibility principle which we all love especially Especially david You can't describe any longer your class with and without and so now the user is this thing that knows how to persist itself knows about How to send a welcome email knows about authentication and also knows about descriptions uh That's not a problem if you have a rather small object But if it's a if it's a class that's already about 300 lines it can start it can get painful and The name service comes from domain driven design Which is a great book about how to architect your software in a manner that makes sense also for non-technical people Um, it's a service as opposed of a value or an entity This is a little bit technical But the idea is that the service has a only behavior and no state It's not persisted in the database. So in the case for a subscription It was a service because it was just uh connecting to a payment gateway checking if there was any error Either validating the credit card or a connection error and all that logic had no no state Uh, I'll show you some code quickly. We want to exercise this one Let's see And I'll I'll move on Oh, and before I will also Tell you that I have a branch in this repository called to the dash solutions to the dash solutions So if you check out that branch you will have four new files in each one of the I mean one new file in each folder Which is app dash solutions to the solutions or something there are b And you can see my take on this refactoring patterns. They are arguable We can discuss about it, but they are for sure better than the code before refactoring Uh, I'll do it now to explain this before and after for a service object So I'll open the before Here so we have this user a typical rails class with validations callbacks authentication Notifications and suddenly we added subscribe Which was which had this funky method try api to handle errors Uh and subscribe which is the the opposite and this crazy logic Which was only concerned about subscriptions, but was living instead of the user objects So when we extracted extracted it out I came into this code Where the user let me go down Where the user only calls that service it initializes it here as a private helper It sends the the user it sends self to it and it calls on it subscribe and subscribe And the user doesn't care what does that mean if it's through an api If it's through a phone call or through fax or whatever the user just doesn't care All the logic lives on this new object subscription service which receives a user And performs all these these these things which in this case is connecting to the api That's the idea of a service object as I said we want to exercise this now But I'm very happy to discuss it with you guys if you're interested later through twitter whatever Uh going back now to the top Again the branch for my solutions in the repository to the dash solutions plural solutions If you want to check them out compare and so on Let's see Uh next steps if you want to continue learning about um About a refactoring patterns a code design like in general just send pull requests to it have it's a gold mine I I learned a ton there the community is amazing There's these two projects that are uh are actually needing quite a bit of refactoring if you are interested in specific ones But you can choose whichever you want and just contribute The smaller ones are easier to get it to get to get in because the community is smaller And they need just more time and you will get more feedback people in my experience. Anyway in smaller projects I I received more constant feedback and that was very useful for learning go to it have if you'd like to Continue working if you don't want to break your own applications Send pull requests and see and see the code improve That's another next step. Uh, I encourage you to follow Follow the rules all the time follow the rules. I'm kidding But the four rules from sandy mets are amazing. They lead to they lead to green pastures and they are easy to grasp Uh classes should now be longer than 100 lines of code Methods should not be longer than five lines of code if you can Think about these problems and try to shape your code in that manner You will be following a lot of patterns a lot of The design like ideas you only following best practices without needing to study them all and become an erudite of Like all these things without becoming a pure scientist I love these rules because they are so easy to to grasp And they improve so much code basis And if you then want to actually study why they they lead to good code or not and so one is your choice uh But I strongly encourage you to to know about these ones and try try to to apply them to your own code Then the the other two ones are a method should not accept more than four parameters And a controller shouldn't just instantiate only one object, which I never wrapped my head around it yet So if you want to teach me actually, please do Uh while refactoring in my opinion, it's not only about aesthetics or although it's a consequence But it's about the shared understanding of how your project works in your team and with your business owners in my opinion refactoring is uh Bring so much productivity because suddenly discussing the things we need to implement with the business owners with the project managers And fixing the problems that arise become easier if you have a smaller code base They will sell something amazing the best the best key to improve codes a code is delete key I strongly believe that if you don't need to solve the problem Don't solve it if you can delete code delete it and you will have a more understanding and less errors in production And it may also be about performance today. Adrian suggested to me that if you're in If you're using null objects You should also make them singleton because they are always returning values And so you don't have 1000 objects saying all the time the same It's also about performance and of course about also finding and discovered yet bugs um Another idea that I like to think about while refactoring is that we work with the tools with which we work We are kind of meta professionals because we like so much the meta as developers We are the users and the creators of our own tools. This would be like we are carpenters and we can shape the Precise hammer that we want the precise tool that we want rather easily Like you take the hammer of another person and Suddenly shape it to your own hand to your own strength and that's crazy power for us. Suddenly we can shape the computer However, it's better to us That's an idea that I that I always find interesting And the last one if I'm going to chase a bias between over and under engineering I will always choose over because under engineering is risky expensive and overcrowded So that's all. Thank you very much. I hope you enjoyed and see you around