Time Driven Development

Katerina Trajchevska

Designing software for easy maintenance and knowing when to prioritize time efficiency.

Transcript

00:00:00 hi everyone excited to be here so I will be talking about time driven development which is a bit different software development process a little bit of background before we start so this is me I'm a proud 1x engineer also part of my tech speakers since recently that's an amazing community that promotes likes sharing knowledge about open source stuff so I really recommend that you check it out I'm also the co-founder of diva which is an exclusive developers network we work fully remotely and we partner with companies to help them

00:00:36 scale their engineering teams so as part of this organization I've had the opportunity to work with a variety of companies in different stages from startups to Fortune 500 and that's when I realized that no matter the size they all have the same approach to evaluating new projects and that was always oriented around developing time so that's when I started digging more into software architecture and trying to optimize the software development processes to achieve this like saving time on on the larger scale on team

00:01:08 level not only for you at the moment when you develop something so what are we going to talk about today the first thing is how to design software that will make it easy for you to maintain it extend it and modify it on the long run and the second thing is how to know when to stop and make better use of your time so to go through this I will use examples from my personal experience with a diva the first one is developing a module for managing your user profiles on our platform so basically when we started we were a

00:01:42 small local team it was very easy for us to manage everything we had all the data for our employees their previous employment history and everything so it was pretty easy pretty simple once we started expanding and working remotely this started to become a bit of a hassle for us so it's when we decided that we need to have some more structured place somewhere where we keep all that information for our community members and then be able to access it very easily but we still didn't want to spend a lot

00:02:14 time upfront to build something from scratch we wanted to take a lean approach and learn as we go and then develop things only when we absolutely needed them so we decided to sign up for a third-party CRM system where we would store all of our data and then create this simple interface for our users to be able to just log into the platform and update manage their profile details so this was basically how the front-end looked like and on the back end we just depended on this single class which was

00:02:48 Soho that's the name of the CRM we used it was just our interface towards their API all of the crud methods that we needed to get the details for the candidate their previous their employment and their education history and let's see how the controller looked like so this is basically it it's pretty simple at this stage two things we need to notice here the first one is this we depend directly on the CRM class and we use its methods to pull all the data we need for the candidates the second one

00:03:23 is that we directly depend depend on their naming conventions so basically this is not standard at all when we need to when we move things to our local database we would probably have to go ahead and delete all of this and change it with our new naming conventions so this is the first red flag we directly depend on the CRM storage and on their implementation of things and this is on the view side so again we have this where it's the same problem with the names but also we are using arrays to access this data and if we look a bit

00:03:59 further when we change to a local database we would probably need to change this as well we would have to depend on collections instead of arrays and all of our views will need to change accordingly this is what happens on the update so pretty much the same scenario we depend on the class itself we need to adapt everything to work with their variable names so we're using this array to update things on on the CRM side and then we call their update method to do so the experiences and education x' have

00:04:34 the same logic behind it's just cut out for simplicity so what are the red flags with this implementation the first one is the controller knows way too much and it's open for modification what does this mean it means that if we want to change something if you want to change the logic and implement local database instead of using a third-party CRM software we will need to go ahead in our controller and change everything we did so it gets changed very often and that makes it vulnerable and it won't get

00:05:08 stable over time it won't get tested enough so it's stable to use the second red flag is that methods depend directly on the CRM store storage and then also their naming conventions this is the problem we had both in the views and the controllers and the third part is the way we access the data inside the views is different between the CRM storage and data base we will use afterwards so let's see what would happen if we try to change the implementation and use a local database instead now I there's not

00:05:49 enough time to do the changes together but I I did implement this earlier so basically I have this project repository where everything is implemented the way it was described on the slides and I have a separate branch which I call the local where we have all these changes that we need to do to implement our local database so first let's see what are the files that we'll need to get changed this three over here are basically the new files that we added those are the models that we created to access and work with our local database

00:06:29 the user one is also technically added but since this is like a fresh literal installation it comes with it that's why it's shown as modified the three that we want to check over here the controller and the views and all of the changes that happen there so basically all we try to do is see what changes we need to make in our files to re-implement things accordingly so let's do this so as you can see the first one the Edit function is completely changed everything is deleted and everything is reimplemented again we are now depending

00:07:08 on the eloquent classicist instead of over here instead of using the previous CRM API that we used and accordingly we are passing the data to the view and using it afterwards the update method is pretty similar so one other thing that is very important here is that we need to change all of these names to the new ones over here I made a little change in the structure as well so the main skills and the basic overview of the candidate is now stored in a separate table with a separate model and that's where we use

00:07:44 the eloquent relations to do so so basically the logic is a bit changed to work with the tables and also the classes we depend on our change to work with eloquent I'm just going to go through this real quickly so basically you can see all of the lines are red and green meaning that everything got changed as we worked on it and quickly with the view as well so again we have all of these changes that go from the naming over here until the access to the Virata so instead of using arrays we are now using objects and the literal

00:08:31 collections to access everything so basically what this meant is to switch to the storage from using a third-party CRM to using our local database we needed to add the elephant models to use with my sequel which is fine because that's what we always do when we want to implement SQL storage after that we had to change all of the controller dependencies from the CRM class to our elephant classes and used those eloquent classes instead of the CRM to pull the data that we sent to review or the data that we used to

00:09:10 update the database we had to switch all the variables to a new naming convention both in the controller and in the views and we had to change the way we access the data in the views from arrays to objects so basically these are all the changes that we had to do into single into files and it was a lot it was deleting everything we had and re-implementing again so we didn't reuse anything of what we had earlier and if you scale this to all of the other features that we implemented on the admin side as we went forward it meant

00:09:45 basically re-implementing everything that we used with the CRM so it also includes all the changes on the admin features unit tests and everything that was done to work accordingly so the question is how can we save time by improving the design of the code the first thing we can do is not to depend on concrete implementations so over here we depend it very tightly on the CRM implementation we knew how things were handled on their end and how the variables were accessed and we use that inside our controller to basically

00:10:22 create the logic around updating and displaying the profile information so what this means in terms of code we have this interface over here basically creating a repository interface that will define all of the methods that we need to use to update and pull the candidate detail we have again all the crud operations over here and for this purpose we can also create separate interfaces to handle the education history and the experience history but for simplicity I avoided that because we will always pull them together with the

00:10:58 candidate details so it's basically enough to have this one repository get to handle everything for us now in the Edit method in the controller and we'll see the updates afterwards we depend on this interface instead of depending on the concrete CRM implementation this means that now we can delegate everything that's done in the controller to this repository because we know what methods it provides us with and we know that it can handle everything on on its end without us having to do anything about it a great

00:11:33 example from real life do they like to connect with this it's this is the dependency inversion principle which is part of the solid design principles and there's a great example that compares this with using electricity to plug in your computer or to charge your phone it's basically saying that you don't need to go ahead do a hole in the wall and try to wire things together because you don't care about how things are implemented in the background you just know that you have an interface which is

00:12:01 the socket and you can use it to charge whatever you need to charge and then go on with your life this is basically the representation of it in code we don't know how it's handled in the background we don't care how it's handled in the background we just know that we can count on it to do it for us this is again the update method so it's basically doing the same thing depending on this interface instead of depending on the concrete implementation of of the CRM API so we're basically abstracting all of

00:12:34 our dependencies and again delegating the update part to the the proper repository the second thing we should do and this is again part of the solid depend solely design principles which is the risk of one so basically we need to be mindful about what our program expects and if we if we think a few steps ahead and if we know that we would need to implement MySQL storage and we would need to use deliquent classes we would know that for example in the views we will need to access collections instead of arrays or use different

00:13:13 naming etc so basically with this step we want to think about that to know what we want to achieve and use that to set up the initial architecture so it can be easier for us to do the changes as we go forward so this is what I did there basically I try to mock the the elephant classes with a candidate class over here we have up there there the the properties that we use inside the class this methods over here are representing the relations with the with the other tables so basically I'm using this inside the candidate repository to

00:13:55 be able to access all of the relationships that it has and update everything over there and now in the views you will see that we are able to use the relation between the elephant models over here when we loop through all of the experience history and then use objects instead of arrays to access this and this is great because after that when we need to change with a database we won't need to change anything inside these views everything will be defined upfront and usable so the part where the risk of substitution

00:14:31 principle comes in is basically that we are able to substitute this with a new implementation without this view knowing that something changed in the background it will be able to keep working as is because the architecture is made in a way that supports this and finally to be able to implement this as is I mean as it is its described in the steps defined previously we need to bind the abstractions with a concrete implementation so the way to do that is to add this binding inside the app service provider where we state that

00:15:07 this specific CRM repository is the one that will handle everything that's going to this candidate repository interface and we're good now everything that we do depends on this abstracted repository so let's see after we did all these changes how it would affect the the adjustments we'll need to do in the storage so basically I named is the good and the bad I'm going to go to the new repository now which is the new implementation and we'll see the diff again so we have all these classes which are added which is ok again it's

00:15:50 the eloquent models that we have to use with the I mean we we will use with the database implementation the user model is again modified because of that and you will notice that the one thing that's added is this database candidate repository so this is a good approach to extend something is by adding new code instead of going ahead and modifying things inside that and this is another one of the solid design principle principles which says that your code should be open for extension but closed for modification what this means is

00:16:27 essentially that you need to be able to extend the features the functionality of your system without changing implementation but by adding new classes and new entities to it the way this helps improve is that your code will get tested over time and be very stable and very resistant to bugs so that you can just test the new models that you're writing and be good to go now let's see the single change that we need to make is this one and it's a single line so basically if we go ahead with this implementation we have everything the

00:17:07 whole architecture designed properly we are able to do all this to skip all of the changes we had to do in all of the files previously and just add a single file which is the new repository and do this single line change it basically saves us tons of time and it also it's much more means that the system would be much more stable because we don't change a lot of it so again to recap what did it take to switch the storage this time from the CRM API to the local database the first one as previously is adding the elephant models

00:17:48 the second step was creating the database candidate repository that implemented the repository interface we previously defined so basically this helps us know that we have something that handles everything in the background for us the third step is to change the binding for this interface inside the app service provider so that saves us a lot of time it made our lives easier just because we thought things through upfront and we knew how we are going to use them and implement it in the future so knowing this we decided to

00:18:31 apply it in another project that we had internally that was developing a module for integrating github it was basically once we started getting a lot of candidate applications we wanted to find a way to optimize the screening process and automate part of it so we wanted to pull data from github repositories your user profiles and do some assessment based on that knowing what we discussed now we decided that it's not a good idea to have everything rely on the controller so basically the controller

00:19:08 shouldn't be the one that handles the logic and decides which how things are implemented thinking that in the future we might need to add bitbucket or github account we decided to create a factory that will do the instantiation for us initialize the proper class and then based on that we can use all of the methods that we want to use so this is basically what it does based on the type of the account it gets from the user it initializes the appropriate class to be able to work with this we now have to

00:19:48 have an abstract interface again which will define all of the methods that we will need to use with this github class so this class will implement this interface what a new class for new get account that we will add in the future will also have to implement this to be able to work as this so with this part we are again abstracting things and depending on on abstractions instead of instead of concrete implementation this is what happens to get github class basically implementing that interface and 100

00:20:24 thing that you will notice here is this adapter so basically to avoid that problem with the risk of substitution principle with having different naming conventions between the classes we decided to create this adapter which will prepare the input we get from the API for the one we will need to use with our application so that's why it's added it's another level of complexity to the system because we need to implement this new class again and use it so this is how our controller looks like this is

00:20:57 the method that basically pulls the data shows it to the user it's basically using the version control factory to get the type of the account that the user has and then based on that use that initialize class to get the proper details for the users and this seems like a perfect design because it allows us to be able to extend it in the future add new new options for the get accounts like bid bucket get lab whatever we want to implement in the future we just add new code instead of modifying the

00:21:31 existing one and we are good to go the problem is one year after this the code is still the same we never needed to add with buckets we never needed to add get love we never needed to change anything inside this because we're not even using this feature at the moment so basically the whole time we spent preparing this designing it the proper way investing a lot to implement it this way just it wasn't useful remember this now this was me back then so sometimes you just want to create something perfect

00:22:10 you just want to invest a lot of time into creating something that will be useful and it will be extendable but you don't spend enough time thinking whether you would like to extend it or you would need to change it basically so it just means that you waste time upfront without knowing what's going to happen in the future and that's where this principle comes in so the agni principle which says that you aren't going to need it you don't need to spend time on it it's basically a world where both solid and yagna and

00:22:43 kiss and everything can co-exist it all depends on the context and it all depends on what you need to to do and how you need to use your code to know what kind of architecture you need to build if you go back to the first example redeveloping it redesigning it in a way that will allow us to extend everything was very helpful and saved us a lot of trouble going forward because we knew what we needed to do but if you're not certain about it if that's something you probably won't need to do in the future then spending that time up

00:23:15 front would really mean wasting time that you could devote to providing value to your customers or to your company so is there a better way to do this apparently using the github package to pull this data what we did previously could be done in just two lines so I spent 10 minutes to set this up and it pulled the same data that the previous complex architecture pulled so the moral of the story is basically to understand whether we need to invest that time or we are better off if we do something

00:23:53 faster and then refactor and in the future we spent ten times more time to set up the thing previously and now if we can do it for ten minutes it makes much more sense to go back to this once we need to extend it refactor the code and then move forward so that's where the time driven development comes that concept comes in it's it's not really something that exists it just sounded good in my head but basically it's weird though because it makes sense at least to me basically what I thought with it is not that we need to develop

00:24:32 in a way that will save us most time at the moment where we do it when we do it it's thinking about what will make most sense as we go forward for the company for our team for whatever whoever developer comes after us and here is our project because doing things the proper way would mean that we save time on a larger level and with that we are able to bring much more value to our users and our customers so that's basically keeping the context in mind and developing with common sense and choosing the proper architecture when

00:25:06 doing so so this is a recap all software development practices comes come with trade-offs most of them need you to spend much more time writing code at the beginning so invest a lot into preparing the architectures so that you can spend much less time reading it afterwards and that makes sense for complex systems it makes sense because your code is much more readable much easier to maintain but it also it can be an overkill and over-engineering for simpler systems when you just need to develop something

00:25:40 more simple for that github example when I go back to it now it just over complicated things for me so it's not even simpler to navigate through it because it would be much easier to do it if it's just a single two lines of code basically so know your trade-offs and use them when you're deciding on your software architecture the second part is software design principles should simplify your life not complicated so if you're using something if you're following some principle and you see that it's complicating things it's it

00:26:13 needs you to do something more than you would if you didn't use them and it's probably not the right right way to to use them and finally thinking about the bigger picture will help you create much more than just simple software it will help you create value because if you understand what you need to do and why you're doing it you will know what would be the best way to dedicate your time and how to do what to do to basically do more for your company and more for your customers so it all boils down to this

00:26:45 basically software design principles are your tools they're not your goals so you're not you shouldn't try to achieve them you should not try to achieve solid or whatever else you're doing you should just use them to achieve a better better development experience and simplify your life so how to start practicing this the first step is to talk to your product team try to understand the business values why you're doing things what you need to implement when you propose architecture for it because based on

00:27:19 that you will know what would be the best use of your time the second one is always have the context in mind when designing software because this is most important when designer when deciding on the code design and finally don't blame others don't shame them on Twitter for not using the best development practices because they are not best development practices what's best development practice depends on the context of the project and what what's best for you doesn't mean it would be best for everyone else so that would be all

00:27:49 thanks a lot you you


Highlights

00:00-01:22 ⏱️ Katerina introduces herself as a video script expert and talks about her background and experience in software development.
01:23-03:25 ⏱️ She discusses the concept of Time Driven Development and its importance in optimizing software development processes.
04:20-06:00 ⏱️ Katerina explains the issues with a previous implementation and the red flags that indicate the need for redesigning the code.
06:01-08:55 ⏱️ She demonstrates how to implement a more efficient design using abstractions and the SOLID design principles.
08:56-12:45 ⏱️ Katerina emphasizes the importance of considering the context and trade-offs when choosing software design principles.
12:46-15:00 ⏱️ She provides practical tips for practicing Time Driven Development, such as understanding business values and keeping the context in mind.

Key Insights

💡 Time Driven Development focuses on optimizing software development processes to save time on a larger scale, rather than just focusing on individual development tasks.
💡 Red flags in software development, such as direct dependencies on external systems and inconsistent naming conventions, indicate the need for code redesign to improve maintainability and scalability.
💡 Using abstractions and following SOLID design principles can help create more flexible and maintainable code, reducing the need for frequent modifications and increasing stability over time.
💡 However, it is important to consider the context and trade-offs when choosing software design principles, as over-engineering can lead to unnecessary complexity and wasted time.
💡 Time Driven Development requires understanding the business values and priorities of the project to determine the best use of time and resources.
💡 Keeping the context in mind when designing software, considering factors such as future scalability and potential changes, can help create more efficient and adaptable systems.
💡 Blaming others or shaming them for not following specific development practices is not productive, as the best practices depend on the specific context and goals of the project.