 This time, this is really bad. All right, so... I would appreciate if people can see that I'm not close to the client, because I have kind of a batch code for my client. And the batch code is... So, that's where I'll talk a lot and not see a lot of questions. So, before we start, for those who are kind of regular clients, we have obviously a lot of clients. I think... So... Can you see me? Huh? We have a... Are you getting this prepared? No, I'm not. Yeah. I'm old enough to give out power. Wait, you said you can give out marriage if you want to try to speak? No, I'm bad at it. Okay. Anyway. So, I'm... Hi everybody, I am Stanley. And I grew up here. Here in Singapore. I'm living here all the time. So, what I'm doing now, I have a small company called HotE. We do software development coaching and co-practices on companies. Companies who wants to improve their development practices, who wants to learn how to better solve problems, experimentation. That's what I do. And that's the gis of it. So, I have two personalities. One of me is HotE of me, which is I have a job, 200 jobs. And the other part of me is like Michael. I'm a volunteer in a community. What community? Agile community. And this Agile community has been running for about six years since 2010. It started much earlier, but anyway. We started the regular meet-up since 2010. And for the past six years, we hold three conferences. Last year was the one of three. One of the most unnotable conferences. We had 2013 conference, 14. And then 2016 conference. The purpose of the conference is to... I know many people have been reading about Agile development on books, but what if you can hear from the people who actually started it? So, with that in mind, we bring people who are originators of Agile development to Singapore to close up the knowledge gap. And we are very lucky that we are able to get money following last year. And there are many stories to how we get... It's not easy to get the funds. There are many stories to share. That would be another topic. So, from... I work in Audi for about six years already. Six, seven years. Before that, I'm mostly a Java.net developer. And I'm surprised to meet some of my ex-colleagues. My ex-companies are colleagues over here. And... What else? So, I've been mostly a full-time developer and then I decided to join a company that do co-training, public training, and on the people's side. I'm very interested in that aspect because the more involved I am in finding out how to develop software effects, I try to introduce to people and then I get why that doesn't work. No, no, we have all ways of working here. But that doesn't work with us. So, as a kind of a problem solver, I'm very curious to find out why. Why people seem to be resisting. And the more I find out, the more interesting it becomes. It goes into a system dynamics, into a system organization. And then I have an opportunity to join up in where I get to learn a lot from mentors to learn even deeper into organization. And here I am doing this. When I'm busy now, I'm helping a company creating a technical training program so I can take care of their developers to level up their technical skills. Code smells and refactoring is one small part of it and it's also a very core part of it. So... I've been in software development for 10 years now. And one of the challenges in software development that we trust me a lot and deeply is the challenge of software maintenance. What is that? After you develop software from a new green field project, you go very fast. Very fast, yes, you can do a lot. And as you do more and more, you find that it goes slower. There are more and more effects coming down. You spend more time on the effects, you have less time on writing code. So I've been to many companies and I've seen again and again developers spend more time on reading code trying to understand their writing code. If you are a customer, would you like to pay their reading code? Probably not. So to get a quick poll, how many of you spend more than 50% of the time or trying to understand a code before you can make a change? Yes, imagine you can use stats to lower that. I don't think you can prevent that from happening. But since 1990s, hands-back multipollers, here I've been introducing techniques and skills that can help to tackle that problem. And I'm very interested in that problem because in 2004, I bought a book, Michael Fedders. He wrote Working Effectively with Legacy Code. That book compared to, at that time it was Java 2. Java 2 or 1.5, I forgot. A spring framework book, version 2.0 at that time probably. After 10 years, that book by Michael Fedders, Working Effectively with Legacy Code, is still very useful. The book on technologies, it gets outdated. So I'm very interested in such practices, technical skills. I try to... So I try to find such technical courses in the past when I was still a developer, a full-time developer. I try to find such a course that I can learn a lot from. I couldn't find any. But very fortunately, I meet a lot of good people and then I learn from them to tackle this problem. I coach companies, I join teams, I experience how developers work. Often they have something to change. They make one step, and then make a change, and then suddenly they step on the mind. They run away. But instead of the mind, they took two steps back. And then they want to make a few more steps forward, and then another mind came. Someone steps back. It's hard to get to the destination when we are... I felt the atmosphere in that the team is like... they are working on a mind field. It's hard to do forward. And of course, from a business perspective, it is hard to understand as well. Usually they don't see that... that... It is harder for them to go deep into that part. How serious that could be. And... So... This is a big problem. I'm going to introduce just very briefly looking at system dynamics. And... there's something, a figure, a diagram I'm going to share is called Causional Diagram. It's a system thinking to see how things go. So this is a very quick introduction. You have two variables. One is your bank balance. And the other one is your earned interest. So these arrows are links. Links are... How do we read this? With a bank balance, the more bank balance you have, you increase interest, increase interest, you have more bank balance. This is a reinforcement. If you map it to a graph, the two variables go up. Can you imagine that? This is a reinforcing loop. There's a circle. So another scenario in a company where a feature velocity means at the speed of developing features, you go faster, you create more attacks. That's the... for certain companies. This is a simplified model of one of the companies that I have known. When they are pressured to go fast, they create more defects. Create more defects. Spare more time on defects. That will reduce the time. It will reduce the velocity. So this is called a balancing loop. If you draw out on a graph, it goes something like this. One goes up, the other goes down. Okay? This is just an introduction. I'm going to show very quickly the kind of... the kind of... the nature of software development we are in. And then what can you do to get out of that kind of vicious cycle? So a variable amount of backcode we have will increase the number of bugs. Agreed? More backcodes increase the number of bugs. The more bugs increase, you spend more time trying to fix the bugs. And then panic. Panic, what happens? You increase the packs. You open up your developer secret tool box. And then you do all the... quick hacks. Quick hacks introduce more backcode. So this is a reinforcement look. It will increase. And not only that, it could also affect the motivation of developers. It could reduce the motivation of developers. Reduce motivation of developers increased the amount of backcode. So you can spend all day to expand this even wider. To why developers are leave company sometimes. Because they are not motivated by the backcode and they don't know how to deal with it. So... Sorry, so motivation of developers will the last motivation they have will increase the amount of backcode. So what can we do? I'm going to introduce this term called code smells. Amount of code smells indicates backcode. It's a way to to sense. It's a signal that how bad is the code. Or how smell is the code. If we have that sense, that sensory it can help us to opens up the opportunity for refactoring. Refactoring means that we improve the design of the codes without affecting the behavior so that it is easy to change. So if we refactoring we can reduce the amount of backcode. So if the circle means there's an opposite direction we reduce the amount of backcode. So this is the nature of software development. James Greening two years ago came to Singapore and gave a talk at now he's given a talk. He used to be new. He gave a talk about why is he still a developer. In one of the topics he said that's no in software development you change something a customer asks you to change something. You change it and you bring to them and then you say thank you and they will ask you for more change. That's common. And he says that if you can't deal with change, you can't improve on how to change easily then you're probably in the wrong business. So in software development this is the nature. The question the big part of how to solve is how do we make it easy to change? So this builds up the motivation of why so why we want to increase software maintenance. What is code smell? Code smell is that's what it says although in fact this term is coined by back in 1990s and the story goes that at that time he just had the first child and then his grandma said that if your child smells it may not necessarily be a problem it indicates there's a problem. So then he was trying to he and my father has been talking about refactoring for quite some time and then they realized that hey how did they get to know those refactoring weights and how to improve the code they realized when they track back they realized there is something that triggers them to do those refactoring something is the signal it's the indicators and he coined it as code smell so it's a surface indication it does not mean it's that code but it may indicate a different problem there's a list of code smells there's a list of even more code smells which you probably may use this later and then when it's refactoring it is improving the design of the existing code without actually changing external behavior there are many refactoring methods like those that you see here and if you haven't know the book Martin follows I think it's 2001 sure it came out with a refactoring book it's all written in Java it is actually applicable for many languages and in the cover of it it actually indicates if you meet certain code smells what kind of refactoring can you do so it's actually quite systematic and what is it when do you refactor when there is a smell that's the most important part which many people doesn't know so then there's a lot of time if I don't stop at 8.45 please tell me because sometimes when I start to quote I may get possessed we are going to everyone comes from a different company I don't have I wish that I can come up with a quote where it is related to your work but if you do that together this is what I do when I'm in company I specifically smell the code and then pick up examples and do it but we look at that luxury so I kind of like inspired and created that exercise myself with lots of smells here for these we have to take a dating app a dating app okay let's see if they open source that okay so this quote here let me go through a quote here anyone seen this quote before has seen an email in a message that Michael sent okay that's a feedback that's a that is why I try to fit the quote within a screen so that you can understand it is very simple I have this diagram here we have an orders writer a class that accepts a domain object called order this order itself has many products what it's essentially trying to do is that this order writer is trying to convert this order with a JSON product into a JSON JSON string okay what you see here if that's in the back you can't see please move yourself forward you have the JSON object and you have the properties of the JSON you are already taking out the domain object orders data and product data and then put it I'm I can't stop being curious on that anyone have been through such quote before in your book this is much better than that before it already has string but they don't have string combination that's about it yeah I'm trying to optimize alright so this is right common what I see when I go to companies as well so we are going to our task until 8.45 is to remove as many smells as possible how to remove it by refactoring when we refactor we remove some smells we keep doing this again and again so this is where it requires some of your I will be your operator kind of like Siri and then I'll ask you what smells there are you tell me and then I will actually so although there is a contents it goes beyond that at the bottom is quite straight forward just try to close up the take away the common try to close up the curly braces you also have some methods like get size 4 and get color 4 these methods are already used in the get contents for JSON models so this class has three lines we are going to focus on the get contents because it has what smell long method so every time that you identify some smells I will unlock that so you remove those long methods ok what other smells can use in this code primitive obsession primitive obsession where are you going to give me your size size which line at the bottom at the bottom let's focus on this contents first on this screen first 11 to 9 what smells can you comment comments where no comment seriously this function seems not need for but also product I am going to go through very specific here because code smells are very very specific and it is quite close to being objective so let me go through comments comments is a smell when if there is a comment let me create a comment smell this is create a of order JSON string this comment is why because it tells you what the function does not why it is there so comments that describe what the code is doing is a smell because we can factor that out to express the intention of the code we will check that in that case that doesn't mean comments are bad what are good comments give me some examples the decisions you made why you want to use a certain construct and the description what is close both outcomes exactly I will get in the day excellent so comments that describes how this class is working with the other classes sometimes using this API that requires a number 3 the API doesn't have any documentation and then you can go through some comments that say that so to remove comments smell remove of course you may stop that you should do more refactoring the other comments what other smells can you use the magic number I think it is not magic there why is there a magic number line number 47 line number what line number 47 line number 55 why the subtraction of 2 so 2 doesn't really help the attention that's magic number great so I look at that I am going to run through a few smells first before I start refactoring what other smells there is another one very clear duplicate the code where same same number 47 can you tell me the words of the characters we don't have a pen yes exactly we have this you can highlight that and it tells you great what is another smell very prominent some things that we should use you said on the stream static twitter we should use I make products we should have we can use what which is that over here 3 2g 2g very variable better use the smell are very specific so someone said primitive What is primitive obsession? Where is primitive obsession? Currency. Currency suspensions. Currency suspensions. Currency can be one. What is another one? Very, very... Sorry? Size. Size. That's another one, which is very prominent. Long method. Yes, that's a nice smell. What about primitive obsession? The biggest one. It's right in front of you. Yes. One look second. This class is orders writer. In orders writer, there is a method called get contents. And this get contents tells how to... What is a data structure? It's used to accumulate the string. String user. String user is primitive obsession. It's a low level primitive data or structure that is used at a higher level abstraction method. So this is a smell. One of the most prominent smell. We will spend some time trying to remove that. Let's go. I need to make sure I don't get carried away. So I also do... We'll spend some time to remove some of the key, the very, very interesting smell. So let's tackle duplicated codes and primitive obsession in hand in hand. So what I mean by that? So let's try to tackle duplicated code and let's try to tackle duplicated code. Let's reduce the amount of duplicated code for now. So from right here, I can see that there are certain patterns in this code. Did you see that? I tried to make some space to it. There are certain patterns. What does this represent in JSON? Key and property. So the code doesn't say that. This is a JSON property. It says it has to be a pen, blah, blah, blah, blah. So I'm going to try to reduce the duplication and also to focus on a reduced duplication. One of the ways I'll do is... Because this thing, this is the value and this is kind of like a key. It's embedded inside an SPMN. What if I try to take that apart? Take that apart. Take that apart so that as be a pen, the way how it tries to a pen between this section and this section are exactly the same. When it's exactly the same, then we have removed some of the duplicated code. How do I do that? I'm going to introduce some data structure. I'm going to introduce a map. Very simple. Not trying to think too far. What is the smallest thing I can do that I can remove the duplicated code? So what I can think of is perhaps data and then call it hash map. Data I want to do a code, a key, a key call code and then a value, a value called product.getCode. So I have one property. And now, before that, please run a test. Before you do that in every factory. Test pass at the corner there. It's a bit small. I can bring this up. So before we have, just to prove to you we have a series of tests. The coverage is high. We can kind of like assure that functionally it doesn't break or if it breaks it tells us. Now we introduce this. We kind of duplicate even more code here because we duplicated a key here. So I'm going to attempt to kind of create the logic for this. I'm going to do a look to look through the dictionary. The map spent too much time on C shop. So a map and every job I apply about map for each. Is that a simple way? Map for each. Is it ready? So the data for each. Data for each. There you go. So this is a function inside. Is that right? You have to be a little bit careful. Hash map doesn't guarantee you the sequence and for each doesn't guarantee you the sequence either. So it might come out in a different sequence if that's a field break and voyages. But the for each look has the same problem. That is a kind of linked hash map. Okay. So great. So this will be my first time to try out this. Let's see what happens. So how come there is an embellishment error? So it's not expected. Two. Key value. Key. Key value. Yup. I think key is key. Put the pranks. Alright. So key common value. Like this. Oh yeah. Interesting. Okay. Yeah, I learned something new. Thank you. You're welcome. So for each we are going to do this a pen. One way I can think of is doing a format. And then we have this kind of a quote. This one quote. Maybe I use like this. And then we have, because it is extreme, so we need another quote. Okay. I'm trying to be very, very careful here. It is common space. Common space, yes, that's right. Let me put it below. Okay. So common and space. Wow, this looks long. Cool. Let's run the tests. Okay, good. Test pass, this becomes a big quote. Let's remove that. Alright. So then follow on next week. No, we haven't really removed duplicated quote. We just did one of the instance. Let's try to put a color. Put color. Right. And then command this out to run the tests. Still pass. Let's try size. Will size be the same? I'm going to duplicate this. There's a command shield up to move the lines. And then data.coot. We have size, comma. We have size for product. Command this out, run the tests. Still pass. Remove the quotes. Now we get price. Price is a bit special. Why? It's actually a double. So double doesn't have any double quotes. How can we do this in small steps without breaking the code for too long? No, I can actually do this. Data.coot. And then what is the price? Product get price. And of course it will complain. Maybe I'll do it. To string but it doesn't do to string. Let me just hack a bit. Because we're not going to really use that. So it will not work. So the code currently, the code currently in this form does not allow double. It's not specific to double yet. What can we do? Command this out. So this should be the one. Run the tests. We are still green. So one of the ways is that before you do this, make your quote a little bit more general. A little bit more general. How do you do that? We can do a simple one. We can do this. An instance of if it's a double. Then our pen. How come? In order not to change too much. So I should actually change this to object first. I changed this object. This is excellent. Much better than before. So value dot is instance of double. Then I do... So if it's double, I would not use the double code. Run the tests. Still pass. Uncomment. Run the tests. Fail. Why? You didn't comment. You didn't comment. 45. Oh, okay. Thank you. This is the reason why more than one pair of eyes is good. All right. So the last bit. Currency. Data dot puts. Currency. Common product dots. Yeah. Currency. I have one question. When you changed. So first the price in JSON was represented as numbers. No developers. So you moved it into the back. And then you ran the test. And the tests were not finished. But then you changed it and it else and removed the worker. So it means that you introduced the change. That you knew that's what you did in the first place was wrong. But the test was still passing. And here in return to me, what I will do is also maybe write a new test. Or I can read the other way around, which is to really fill the test. And then write this new statement to pass it. Good catch. Now we fail. Why? Because the comma is correct. Because of the comma. So before it is this, going back to the green, this is tricky. So let me try to split it away this. So that it is... Let's see. It's tricky. It wants to... So now I undo. It will still fail. It will still fail. Why? Because it still depends on the comma. So one way... There are many ways of doing it. I will do one of the ways to kind of introduce a bit more magic. If there are better ways, you can do that. So take a look at the code now. We have to remove a bunch of... We have to remove a bunch of ones. A bunch of SBNN. And we have the logic over here. We split this consensus. We separate the concepts of data away from the building of JSON. The logic of JSON. So we split them apart. We're not really splitting up the parts yet because this one, that basis is still out there. So I like to localize it. Shift command down. So that everything about JSON is over here. This is a technical recording software. Bring close to where it has been used. I like to pause here for a while and see what we have done. What smells we have unlocked? What other smells we have unlocked? You can do that. Now we talk about that. We are trying to get away. So it's still there. And the number is still there. Let us take code. What else? Change the code. It's gone. It's gone. It's dead. What are we trying to do? We try to replace something with that. We're going to continue. So we split away the two of the consents. And now this concept seems to be pretty generic to build a JSON object. This part seems to be something about properties. What if we do a small step by data4h? We're trying to do this for properties. In IntelliJ, you can use a control T and then a struct method. What if we call it JSONPROP? I don't really like to pass in string buffer and let it accumulate and pass by reference like this. I like it to be immutable. So how can I do that? Let me run the task first. Let's do not append. I append the JSON properties. I remove away the parameter. This will make JSON properties unhappy. So I'm going to make it even more unhappy. And then I'm going inside. Now compiler tells me where to change. So from here it became clear. I'm going to do kind of a small step first. String buffer. So this is the quickest way to make the compiler happy. And then I return sd. to string. This will make that unhappy and then I pass in change to return parameter. So this way run the task. It produces JSON properties. And of course I'm pretty sure some of you would have known a better algorithm to represent this. What is that? Use Jackson? Oh, okay. Thanks for reminding me. For this exercise, assume that you can't use any of the party I use. Otherwise, no more fun. I know you can use that. Thanks for reminding me that. So other than Jackson, what else? I think it still stinks. The right end needs to know exactly what properties are there. So I rather would delegate the, like I say, give me a list of your properties to the respective object and then just give me a map back if you want to use a map. And then let you write out. And then I add a description property to my product and my code close or doesn't return a proper result. And then I need to have two places in my application, one in the writer, one in the data object that I need to update. So the data object should know what it needs to hand over to the writer. Okay. How do we get that in small steps? That is what we're talking about. Making small steps. So I just, as you were saying, lambda. So I know another way. Kind of like to make this a bit more simpler for now. So if you have some other better ways, you could try it on the site. So using map to... What is this? Map? There it is. And then there we go. So that's key. There we go. Okay. I do a map. Okay. This is good. This is good. This is good. Okay. Do a map and then I can do a collect. Joining to... Thank you. Let's see if this works. Okay. That's pass. Okay. This code still smells white. JSON properties, as you mentioned. It doesn't really make sense to be inside order writer. Order's writer. Is that one you could believe? As long as the map you pass in comes from the object. So you have the part where you say the part where you say data put, data put. That phase from line 30 to 36 should be a call to the product object. Product get JSON map. So data able to... Let's try that and see how that goes. So this is trying to produce a data. Get properties. So let's extract methods. Command option M. Let's call it product JSON model. So why do I call it this specifically? JSON model is because it is not... It is something related to JSON. I want to name it so that it can help me to sense to smell it and where it wants to go. If you keep going straight to the product page... Product get properties. Because the map itself has nothing to do with JSON yet. And that's okay because the product object doesn't mean to know where you want to do XML. You want to do JSON. You want to do edifact. So you would go product dot get properties. And then it returns you a map to an object. And then in your writer you decide that you are going to do JSON or XML. Correct. So are you listening to move this to product? Yeah. So here you can do that. I'll probably not go that far for now. It is possible. It depends on what is your domain object. How much do you want your domain object to know about JSON? Well when you're saying you make it get properties like get business properties or something. Map string object doesn't know anything about JSON. So we renamed the function name to product property map. But it's not as straight JSON. Okay. That's true. Let's try that. So... Rename. Rename. Let's move it first and then let's rename and then see how product goes. So this method will follow this private quantity. Where is the gets? Colour. And size. Correct. To belong to products. So what happens is that get size and colour fall is still used in others products. We try to move them to the products as well. Because at the end of the day they are product properties. So once we move it we can then have a second function that creates XML, not just eschages and stuff. Okay. Thanks for the suggestion. I suggest let me try another alternative map and let's see how product goes. We can have a discussion with you. Thank you. I want you to... Thank you. So let's see if we can... You want me to do 8.5. Yes. Time stop. Time stop. Okay. Let's see what we can do with the last two minutes. So this represents a JSON object. Is that right? Let's abstract that. Okay. And again I don't want it to... I don't want it to use the string builder from there. Do the same. Return string.format. Okay. Then return... Make it return the JSON object. Let's run the test. Test field. What happened? You missed the comma. Comma? Oh. The comma. Yeah. It looks like one comma came off. So I'm not going to... Okay. I'm going to pass the test first. And then I'm going to start a pen. The comma. Take away that comma. Right? So now we have... Let me move this up. One of the methods is to write out a JSON object with the curly braces and the JSON properties. I might do a decision like something like this. Let's do a refactoring of putting it abstracting to a separate class. And in a simpler way I can think of is probably to make it static as a static method first. Because it doesn't have any instance variable. And then use delegates. This is abstract class refactoring. Maybe we call it JSON. We move it over there. When we move it over there, now the name says JSON JSON object. Kind of like repeating itself. I'm going to rename that take away the JSON. Maybe call object. Or if I want to sugar coat it, I can call objectify. So... 846. Okay. Well, next time I'll try to improve further. So I'm fully aware that we're not going to complete the removal of the smells. But let's take a review back into what refactoring should have done. What have we... What refactoring should have used? Extract. Extract. Extract. What else? Single response. Great. Single. No other refactoring. Sorry? Yes, we need this refactoring. What else? Extract class. Extract class. What else? Change signature. Anything else? Sorting? Try to bring the use, the declaration closer to the use. What else refactoring? I think we did a two line variable. It was very short one. Two line variable. So in the class I learned why others might want to introduce K-Song class. There are two methods. What is it? Object. And how to do this? Others might want to use this class. So that is all I have. I have to get very quick some of your voices. Why have you become more aware of this kind of thing? Sorry? What is more mechanical? What is more mechanical? Then we need what is happening. A bit more illegal. One more? So there was a story that back in the days of I think 1990s where people were arguing about what is good design. They were showing quotes and saying my design is better than yours. Yours is better than mine. So they couldn't get to agreement at all. And then later on they realized that hey, although we can't agree on what is good design, but we can pretty easily say what is that quote. Smelling quotes. And someone said that what if we remove smells from quotes. If we remove the quote smells, that quote would be actually better. Would it be actually a quote? Probably yes. So since then, that is kind of like my philosophy in trying to create mechanical software and also trying to make it more objective in identifying smells and reflecting. And I hope you like this session. And we have just kind of like a participative removing smells to get better quote. Thank you.