How to Become a Better PHP Developer?

So I will be talking about the solid design principles and how we can use them to write better code in PHP and essentially become better developers so a little bit of background my name is Katrina I am software engineer and co-founder of ativan I devised a marketplace for remote working and we’re focused on helping companies scale their teams with remote developers so working in an environment like this I’ve had a chance to work with a variety of companies and projects and be part from both the startup environment and also the enterprise and they’re both very different but they are similar in the way of you know working with spaghetti code and trying to find your way through messy lines in in the codebase apart from that I advocate for remote work because I’ve been doing it since the beginning so it’s really great and I recommend it to everyone and I’m volunteering for the local tech communities also joining initiatives for inclusion equality so you can you can talk to me about it later if you’re interested in that too now I’d like to start with that for PHP humor I’m not sure about you but I hate this so this is part of a larger comic it was published by by toga a while back and it’s what it does it explains how you can rescue the princess by using a different programming language so every programming language has its traits it’s you know downsides and all of those were incorporated in this comic but when it got to PHP it was like okay this night is giving up he is unable to save the princess and he would rather not try so instead he he gives up and he dies and this is something that you know it was an irritating ending for me because I’ve been working with PHP for 6 years I’ve been working on software that’s really high scale with teams from all around the world and you can really scale PHP and Demyan also demonstrated how you can do it yesterday so it’s it’s not it’s impossible to save a princess so when you think about this it’s more of the approach we have towards programming and not so much the language itself so while I was preparing for this presentation and ran onto this research made by hacker ranked and these survey developers on various topics one of those was what they hate most when programming or what they hate most in their daily work and what they answered was spaghetti code so I’m sure we can all relate to this right it’s it’s something that we dread and whenever we join a legacy system or whenever we join a team we’re you know we’re new and we need to get up and running with everything it’s getting hard because we don’t understand what the code does and we spend much more time reading it and trying to understand it then we do actually developing new features or fixing bugs so that’s what I will try to cover with this talk I wanted to go through a specific example of something I currently work on and there will be some code even though it’s early in the morning so I hope you’ve had your coffees this is a screenshot of the platform for for a diva so basically it’s the login page after the the developer signs up they’re accepted to our community so this is where they can access all of the opportunities that they have and update their profiles so basically what it does it’s a couple of links on the side and then a forum where they can edit their profile details at their experience and at their education so when we first started working on this we were still pretty small and we could manage everything on on slack so all of the developer communication and all the opportunities were managed directly but after a while since we started growing we decided we needed to place where everyone could log in and manage everything on their own so but we didn’t want to spend a lot of time and invest a lot of resources at the beginning in building a large platform we wanted to do it step by self and that’s how we how we decided to start so we were using After party system for managing all of our applicants it’s called zoko recruits and it’s kind of like a crm for candidates so you can manage all of their details attach CDs and edit their experience their education history and all of that and it was fine our administrators would log in there and manage everything and here we wanted to just create a simple form and connect it through the third party API so that we can save all of the details there so how this looks in the back we started this was the only page that we needed so we decided okay we’ll just create one class and put everything inside that this is a candidate class that handles it’s like an adapter on our end that handles all of the API calls so basically it has the the methods for updating candidate details their education their experience and also several more that are not listed here but we added them afterwards like adding notes for the candidate and sending email scheduling interviews so stuff that were more important on on the admin side then this is the part where we actually display this form it’s pretty simple just makes a connection to that API and then calls of all of the the needed functions to return the data we need and this is how it’s displayed in the view so why this is important is to notice that we are actually manipulating arrays so everything we get is used as an array afterwards now this is a bit more complex and it’s the actual update function so it’s how things work once we click the the Update button and over here we have a bit more messy code so it has this part which handles the candidate details update basically gets all of the basic details like name email and sends them to to the system to the third-party system after that we have some logic for going through all of the experiences so we probably noticed that there was a button to add multiple experiences and it’s also an option to delete ones that you’re not interested in having in your in your profile anymore so what this does is it goes through all of the experiences that reddit checks if they exists in the system already and then if they do it updates them otherwise it adds a new record and at the end is the solid part where it deletes everything that’s not used anymore and we have a similar logic for the education as well it’s just we changed the calls and we changed the variable names but it’s basically the same so after completing this we realized it was a good approach it worked for us we had the system on the back end in the background that we were using for storing everything related to the developers and we had a nice interface for them to log in and edit all of the details and once we started moving forward we decided okay we’ll add one feature at a time for the admin side as well so we started with manipulating managing candidates adding new candidates deleting existing ones qualifying and qualifying them and everything that’s needed that needed to be done on the at my side finishing with generating their profiles sending client proposals so everything that was related to the developer side to the developers data and we needed for the admin side was slowly getting developed and over time it became became massive not that massive but for this use case it was it was really large code base and very messy code because we kept on adding and adding new and not well structure code so after completing all of this this third party system wasn’t flexible enough for us anymore so we decided that we needed to switch to a local database we wanted to have the flexibility of working with everything on our end and then adding new features as we needed so let’s see what it took for us to move to a local database with this code structure now looking again at this larger updates method the first thing is to switch from using the Zoho api for updating the candidate details to using our Nelkin model so this is a largely rural card code but it’s pretty similar no matter what you use so basically we changed the approach and instead of using this class for calling all of the API methods we’re now using eloquent models and just using the methods they have for updating things in the database the second part was to update the experiences and over here again we use the same approach but instead of using separate model for the experience we decided to rely on the relation between the candidate and the experience so that that part of the eloquent models and the education is pretty much the same so it replaces with a similar code like this one now if you look at this a little bit closer we can see all of the changes that we had to make make so this is pretty simple piece of code but it has several changes that needed to be made the first one is here where we use a different approach to check if the experience exists so that’s the one change that we need to make here we need to use a different approach to update it and then we need to use again a different approach to create one and delete the existing experiences so it’s three different changes and changes of logic not on which changes of certain references in a simple code snippet which is several lines long and if we scale this to the whole system even if you scale this to the to the method we have three more changes like this for the education part we have two more changes for the candidate details that we saw on the previous slide and it makes eight changes of code in a single method so scaling this to the whole system scaling this to the admin side would really take a lot of changes to get from the third-party systems using a local database and use the flexibility that this local database would offer so this is where the solid design principle principles come so I’d like to go through this example again but by using the solid design principles and seeing how they can help us simplify this code and make it much easier to change at a later point but first just as a little overview again of what the solid design principles are so the first one is the single responsibility principle which basically states that every class should have only one responsibility you shouldn’t mix everything in one class like we did with our candidates API you should separate all of the specific responsibilities and specific smaller classes that are responsible for for each thing so you might think about it’s like instead of having on one large class with one generic name you would have several smaller classes with more specific names and have those names really define what that class is responsible about the second one is the open closed principle this one can be confusing but it’s really very important and can help a lot in extending systems so what it stands for is having a system that’s open for extension but closed for modification and this means that you should be designing your code in a way that allows you to add new features and extend or change existing functionality by adding new code to it instead of modifying what you’ve already wrote because if we keep on modifying what we have we would never get to a point where our system is tested enough so that it can become stable we constantly change something and we constantly need to retest it right so it’s it’s never at a point where it’s resistant to bugs a good example about using the open closed principle is with open source libraries so whenever you use you install a package with with Composer you hopefully don’t go in the vendor folder and edit everything there and then use it like that you just add another piece of code on top of it that modifies what you used what you get from from that package and it adapts it to your specific needs and specific use case and that’s why the open-source libraries are so stable because they get tested all the time and that they rarely get modified so this this is in particularly important for the core of your system not not for every part of it of course but the core of your system has to be resistant to bugs and you should change it less so that you can get to a point where it’s more stable and the third one is the Liskov substitution principle and this states that you should always be careful about what a class does before you replace it with another one and this is not only about the interface that it implements or what methods it has it’s also about what those methods do and what they return or whether they throw an exception or not when you have a class that returns something and then replace it with another class that returns something else even though it uses the same method then your code will eventually break the fourth one is the interface segregation principle and this goes closely with the single responsibility one it’s essentially for separating your code in smaller pieces smaller interfaces that you will depend on instead of depending on a large class and why this is helpful about is you would use smaller classes or smaller interfaces to handle something in your code if you depend on a large class if we always depend on this candidate class we would depend on the ability to create notes or send emails when we actually just need two unqualified a candidate so your code is very coupled together and one change in one area can cause a lot of problems in another area and that’s why you it’s very important to set to separate those interfaces and depend on only things that you need and things that want to use and finally the last one is the dependency inversion principle this one states that it should always depend on abstractions instead of depending on concrete implementations and one good example over here is comes from the real world so when you want to charge your computer at your office or your home you usually plug it and use a socket to do that you don’t go behind the wall and wire things up so that you can get electricity you don’t care how things are done behind that socket that’s that’s done for you it happens in the background and you just want to use it and you use this socket as an interface to get electricity and this is how your code should behave it should it should use what you have in the background and know that it’s somewhere but it doesn’t have to know what happens in the background it doesn’t have to wire things up in the background it just needs to rely on an interface that essentially enables them enables it to to complete a functionality so if we go back to our code now let’s see how many places we violate this principle these principles the five of them first we always still have too many responsibilities here the first one is the candidate update part so this thing again updates all of the candidate details sends them to to the third party API and it’s a separate responsibility that should be moved away from this controller the second one is updating the experience so this is this part is again responsible for the experiences of the developer so it should be probably somewhere else where it would be specific specifically handling the experiences the third part is manipulating the education similar to the experience part it has a separate logic and it’s probably better off in another place and finally the fourth responsibility which is what our controller should actually be responsible for is returning what we have to the client so controllers are responsible for handling the flow of the application they they should get the details from from the client they should pass everything to separate entities who who handle things for it and then they should return the proper response to the client that you don’t care about how everything is handled in the background so all of this responsibility is apart from the part where we get the request and that’s that so pests as a as a parameter to the to dysfunction so the request is handled separately and it’s validated separately so it doesn’t mess up this code additionally but still we have three responsibilities that needs to be moved away from here and then we can only handle the the flow of the application so it’s an obvious valuation of single responsibility principle now what about extending this code with additional functionality so right now we have education we have experience but at one point we needed to add projects as well and further developers the project snippet would be similar it would need to go through all of the projects update them or delete or add creates new ones so it’s essentially a similar code snippet that said it right before we returned the details to our view and this is modifying this function it makes it much Messier it makes it much larger and it also has to modify the class a candidate class that we were relying on because we had everything handled back there this violates the open closed principle because if we keep on changing this this method whenever we need to add something new to to this profile we would really get to a point where we would never get to a point where everything is stable we constantly need to retest everything and six bucks when we’re we don’t expect them in this part over here so we depend on the candidate class directly so we depend on a full class that has all of the methods which violates the interface segregation principle because again we shouldn’t rely we shouldn’t depend on something that we don’t want to use but it also violates the dependency inversion principle because we are depending on something concrete we’re trying our controller is trying to wire things up so it can update the candidate details it doesn’t rely on on the implementation that we have in the background and this makes it much more difficult to change in the future and to replace it with the local database and how we would handle it now this edit part it was pretty simple and short but it still has some slight issues with it so again we depend on this concrete class for the candidate that has everything coupled together but if we need to change it it’s it’s just a short change instead of depending on the third party API we are again using our eloquent model and we can do everything in two lines after that we also need to change our view so instead of using separate variable we are now relying on the relation provided to us by the by the model and this should work right it’s fairly simple three lines of code it shouldn’t break anywhere but it does and it breaks at a point where we forgot that we were using a race and we’re now trying to pass it an object of candidate experience so it violates the risk of substitution principle because we weren’t really aware of what we’re using and how we need to access the data that we have we just replaced one class with another and we hoped it would work properly so what did it took to move to a local database first we needed to create the models for all of our database tables which is fine we would obviously have to do it at some point then we need we needed to change all the controller dependencies so instead of depending on the third party API we’re now depending on these eloquent models and we have to go everywhere in the code and replace them manually apart from that we also need to change the control controller logic because it needs to rely on the functionality provided by these new models instead of relying on the third party API and this includes all parts of the system it includes the developer side where developers can log in and edit their profiles or register it also involves the admin side where we have management’s of all of the candidates and then sending proposals adding profiles or everything else that was coming afterwards we had to change all the views because we were using an array previously and now we want to use objects and collections of course we need to adapt our unit test because we changed everything we obviously need to change them too and we need to retest all of it as a whole because we introduced so many changes in the system that it will probably break somewhere and what we estimated for this was actually 30 days less it’s probably an older version of the presentation with the wrong estimation but still it’s something too long to to take to move from one one version to another so it’s not something that we wanted to do because still we wanted to go lean and then add things as we as we moved forward so we can do better than this how can we incorporate all of these principles into our code and make it work better and make it easier to extend and change in the future first when to separate the responsibilities in specific classes so instead of relying on one large candidate class we would now separate everything into candidate experience candidate education candid project candidate basic details so separate all of them in smaller smaller specific classes that have names which define what the class is responsible about the second step would be to design the code in a way that allows us to extend it by adding new code instead of changing the existing one third to be aware of the return type so when we expect an array we should never send an object so we should think about this upfront and use object since the beginning we shouldn’t depend on concrete implementations this would make it much easier for us to change to the new implementation afterwards and we shouldn’t depend on unnecessary methods so we shouldn’t depend on things we don’t use because those things it can break code where it’s not expected to break now this is a first step what we do here is actually creating an interface interfaces for all of the the separate features that we have we have candidate experience interface which handle which has all of the methods we need to to execute the update process all of the process is related to the experience and then we also have candidate education and candidate interfaces which are collapsed just for the simplicity but they basically do the the same thing and this is where we segregate the interfaces so this is where we comply to the interface segregation principle because instead of depending on one huge class we are now depending on separate interfaces the second step is to create repositories so each of these repositories would be the concrete implementation of our interfaces this is how things will work in the background this would be the wiring and our interfaces will be sockets so this class is implement the interface that we interfaces that we defined and they comply with the single responsibility principle because they are small and your specific third step would be to create several separate classes that would mimic model classes which we would be using later so over here we would just have a simple class that has methods for returning relationships like education and experience in order to not have to create use separate variables and then change them with their relationships so this is where we think about the substitutions and we think about what our classes do and what their methods actually return so that we can know how to replace them at a later point and this is how our update function looks like so we got from over 50 lines of code to a code of four lines where everything is delegated to separate separate methods to separate classes and you will notice that this code is much more readable it’s much easier to understand if you need to see how you manage the experiences you would probably find the implementation of the candidate experience and see what’s done over there if you don’t need it then you don’t need to read through unnecessary code in order to get to the point where you need to change something so you will notice here that we depend on the interface instead of the actual repositories and this is where we did dependency inversion so we depend on abstractions and with this we would be able to just change the implementation in the background by adding new repositories and everything would work we would not need to go through all of our code and all of our controllers to to replace the dependencies we would just need to add new add new files new classes and everything would work and that’s the open closed principle we extend by adding new code instead of modifying the existing one at that point our code would get tested well enough and it would get much more stable than it would if we were just going back and changing everything all the time there’s one change that we need to do and that’s where we bind the actual implementations to the to the interfaces and it’s just a three lines change so instead of depending on our third party API we’re now depending on the new repositories and that’s it that’s all we need to change in our code to make it work with the local database so let’s see how this worked out again we may have to create a local model store the new database tables we had to create repositories now that work with the local database because our new structure requires repositories to handle everything we had to write unit tests for the new classes but only for them because everything else works out of the box and we need to bind the repository so that change that we need to make just make sure that when we rely on the interface it uses the repositories the repository that we need and that’s it and with this we estimated five days and you might think it’s too big of a difference and it’s too unrealistic but essentially we are relying on ten methods or twelve methods from the third party API we don’t have too many methods that we rely on the problem is that we are using those same methods over and over again in our code and then what we need to change something we need to go inside our code and change change it everywhere if we if we were using this approach where we rely on the solid design principles we would just need to go in our repository write 12 new methods in all of our specific classes and that would be it so it’s been a long overview but to sum it all up what does it take to become better developers the first thing to do is to incorporate thoughtful programming so you should always care about what you’re working on you should always think about what’s the best solution for your problem instead of what’s the easiest solution to it you need to think about the bigger picture talk to other people try to understand what your task requires it’s not just a story that’s on JIRA or whatever you’re using for managing the project it’s something more and it’s something that’s related to the business logic code of the application that you’re building and if you understand what you’re working on you would be able to understand how to implement it better you would be able to write code it would be extendable and easy to maintain on the long run the second one is to think about the UX of your code and this is developer experience in our case so the users of our code or other developers or we are the users of our code and you should be thinking about writing code that another developer would like to continue working on you should write code that other team members would like to hop on and continue working on it with you or you would be able to go back to something that you’ve been working on a year ago and know what you actually did there because your code is well structured and it’s readable and understandable so always think about even if you’re not using the solid design principle principles always think about writing code that’s easy to read and easy to understand we talked about this a while so using the solid design principles you can write code that’s easy to maintain easy to extend and easy to change on the long run but it’s not the rule so it always depends on your use case and it always depends on what you need to do how complex your code is and whether or not it should be extended or changed in the future so think about it use common sense think about your trade-offs whether you should spend more time structuring your code and writing better architecture upfront or that’s unnecessary because solid takes a bit more time writing code at the beginning so it can get easier in on the long run to change it and to to extend it so it’s your tool it’s not your goal so you should never try to achieve solve it as a goal you should use it as other principles to achieve code that’s easier to work with and that would make your lives easier and finally please don’t laugh on PHP jokes let’s show everyone that we’re a really nice community and we can be built a lot of cool stuff with PHP thank you