There are quite a few rules/principles that get thrown around in the software world. Some that come to mind are , , , etc. I totally stand by all of them and believe our world would be a much better place if these principles are followed more. SOLID principles Design Patterns Do one thing and do it well The problem, however, is that those principles are quite abstract and at a very high level. During my code reviews, engineering discussions and writing of code, its tough to apply them directly. You wouldn’t know when you’re violating any/some of them. I thought of compiling a list of principles that are easier to apply. They are derivatives of the above mentioned ones. Let’s begin! 1. Do not build for the future I have found myself falling into this trap more times than I’m willing to admit. Let’s create a ParentClass (that will be extended by only 1 ChildClass), let’s store the history of user status changes (even though we need only the latest one now), etc. Don’t! After burning my fingers a couple of times, I found out I’m not the only one. There’s a principle called YAGNI: YAGNI- You Aren’t Going to Need It Martin Fowler has ; the gist of it is: a great piece on it We end up with three classes of presumptive features, and four kinds of costs that occur when you neglect yagni for them. Now, when engineers or project managers argue we need it in the future, I tell them YAGNI (and share the above link). might We needed to show the job application status of a job. We thought, let’s store the history of the statuses, Needless to say, we didn’t. Moreover, we started seeing duplicate jobs in some cases. Due to a programming bug, the SQL query was giving duplicates on production data. When I realized the root cause, I’m like An example: we might need it in the future. INNER JOIN I violated YAGNI 🤦♂️. 2. Do not copy-paste code Every time you copy and paste code (even if it’s just one line), you’re making a mistake. Do not copy-paste code. Create a private function and put the common code there. Create a common base class, or extract the common functionality into a module. In software, DRY is preferred over WET DRY- Don’t Repeat Yourself WET- We Enjoy Typing. “ on’t epeat ourself” — How many times do you see that there are similar codes in different parts of a system? The DRY principle, formulated by Andrew Hunt and David Thomas in their book that “ In other words, you must try to maintain the behavior of a functionality of the system in a single piece of code. D R Y The Pragmatic Programmer, states every piece of knowledge must have a single, unambiguous, authoritative representation within a system.” On the other hand, when the DRY principle is not followed, this is known as WET solutions, which stands for either or Write Everything Twice We Enjoy Typing. — Oscar Salas Another way to look at this principle is to have a I have another piece on the lengths I went to have a single source of truth. Totally worth the effort. Single Source of Truth. I used metaprogramming in production. Recently, instead of copy-pasting a lot of raw SQL in my ORM, I created a small framework that takes in the params, and creates SQL queries based on that. That took longer than expected; because, you know, SQL. While writing the queries and fixing the SQL errors, I was regretting my decision. Nonetheless, I powered through. Weeks later, I had to add a simple clause in 7–8 SQL queries. Fastest change I have ever made. When the code worked in the first attempt, made me smile at the computer. WHERE complex 3. Code readability, not performance Optimize for code readability rather than for performance. As a software engineer, fresh in college, I took great pride in optimizing code (use fewer CPU cycles). I wish I had gotten this advice then: Programs must be written for people to read, and only incidentally for machines to execute. — Abelson & Sussman, Structure and Interpretation of Computer Programs the (premature) optimzations I have ever done have never ever solved (or partly helped) even one of the performance issues I have faced. Now, I solve for performance, when the profiler running in production tells me to, or when my apps are crashing with OutOfMemoryExceptions; not a moment before. All actually Make it correct, make it clear, make it concise, make it fast. In that order. — Wes Dyer Don’t write instead of . All modern compilers will generate the exact same output anyway. x << 1 x * 2 4. Delete unused code This is a corollary to both YAGNI and code readability. Delete unused code because you aren’t going to need it, and, nothing is much more readable than anything else! I always delete classes/functions/variables that aren’t being used. In Java (using the IDE) this is very easy to spot. In python (and other interpreted languages) I have to be more deliberate about code deletion. This means: always Don’t commit commented code. Delete commented code whenever you see it. Deleting directly unused code is easy. I take it a step further and delete old (unused) API endpoints and other functionality. Because that means I can delete the corresponding view, controller and serializer(s)! It’s not always easy to figure which endpoints are not being used anymore but it is always worth the effort. My Favourite Code refactor so far! By far my favourite story is : Engineers secretly hatched a plan to effectively deprecate IE 6, and secretly push this change without the necessary approvals from the management. A Conspiracy To Kill IE6 This banner caused IE 6 usage to suddenly drop drastically! These “Old YouTubers” This story isn’t all about deleting old code. It just illustrates my point very well. Go to the extra mile to delete code. first made the old code unused, then deleted the unused code! The best way you can contribute to an open source project is to remove lines of code from it. We should endeavour to write code that a novice programmer can easily understand without explanation or that a maintainer can understand without significant time investment. 5. Be deliberate with your naming Name your classes, methods, class variables and even local variables very semantically. Whenever you’re introducing a new name, stop and think for a few seconds. Name the symbol as per its behaviour. I follow a consistent naming pattern: Models should be singular. class User Objects of collections (Arrays, Sets) should be plural. List<User> users There is a world of difference between the methods and . Name your method as it behaves! get_user get_or_create_user This actually prevents me from violating the Single Responsibility Principle. If I need to name my class something of the form of I know I’m making a mistake. class DoesXAndY In my early open source days, I spent a lot of time renaming my variables achieving the desired functionality. I used to think . Now, when I read others’ code, I realize its importance. I don’t feel bad about being pedantic in code reviews: after “What a waste of time. The code is working” change num_users to number_of_users or user_count 6. Change one thing at a time I have done this mistake many times. I take the task of refactoring a part of the codebase. While refactoring, I realize these other things that are broken (as they always are). I fix them as well. Soon, I end up having a thousand line long PR! I needed to refactor the project’s Job model. It had a lot of related models. I guess the intent was to have a de-normalized schema. Instead, it was a tangled messed of bad data modelling. I knew how it should it look ideally. Naively, I created that schema and started writing migrations. So many dependant things broke. It was stressful for me and the entire team. Instead of 3 days and 1 engineer, it took 7 days and 2 engineers. Not to mention the un-needed stress and loss of faith. It was like opening a can of worms. In hindsight, I should have removed one dependant model at a time, rather than all at one go. Remove one model, migrate it, test it. Then, repeat this process a couple of times. “Change One Thing at a Time” extends to the entire engineering process, not just to the coding phase. It’s very common for companies to break up their monolith into smaller services as they grow and handle more scale. This process takes months and years. Not only does the code needs to be refactored, the teams need to be re-organized. Project structure, deployment process, everything needs to change. All this cannot be done in one huge change. If you every wonder how to do a change that seems like moving a mountain, now you know how to do it. Break the task down into smaller bite-sized chunks, and finish them one by one. At Apna, we do feature sprints rather than the usual fixed-days (1 week or 2 week) sprint. We build one feature, test it internally, and then release it in production. There is no point in clubbing 2–3 unrelated features in a release. Our sprints range from 3 to 4working days long. This gives us the much needed speed as a startup, and reduces the amount of stress during a release. 7. Write Dumb Code This is one of the most counter-intuitive thing I’ve learnt (rather, am learning). The following excerpt explains it perfectly: If, like me, you were once a Junior Dev, you may remember your first experience looking at a Senior Dev’s code and thinking, “I can write that. Why aren’t I a senior?” Yet I tried to write code like that for a long time, and I couldn’t. What was so mystifying about “Senior Dev” code was that I didn’t understand it, but that I could understand it immediately, it was fundamentally dumb, and it seemed like there had to be more to it. “Where’s the rest?” I remember thinking. “How does this do all of that?” not Since then I’ve learned all the names of all the principles and qualities of code that make it dumb: YAGNI, Single Responsibility Principle, DRY, Single Level of Abstraction Principle, low coupling, etc. And I’ve become a “Senior Dev” as well. The greatest lessons I’ve learned are that writing dumb code is actually hard, and that it pays exponential dividends to do so. — Why Senior Devs Write Dumb Code Kent Beck said it more provocatively: Any fool can write code that a computer can understand. Good programmers write code that humans can understand. — Kent Beck I have made the mistake myself of writing cool code like meta programming, but the real achievement would have been to get the same functionality without the “cool” code. In my defence, I did write a lot of comments. Phew, that’s a long list! Still, there are many more that I didn’t write down. I too forget to follow them sometimes. I do cut corners under time pressure. So, I wrote them down to remind myself. I have regretted violating any of the principles a few weeks/months later. These are rules of - you don’t follow them, but you’re always better off following them. always thumb have to The principles mentioned above are not necessarily applicable to all of software engineering. It is more inclined towards high level software projects- python/java, web/mobile apps. The stuff that I work on. Probably most of it wouldn’t be applicable in, say, LINUX kernel development, the GNU C/C++ compiler, etc. I want this post to be a perpetual work in progress- add, re-arrange and remove ideas from time to time. Reply to this post or for any suggestions/corrections. hit me up on twitter