Software Engineering Isn't Just Coding
Arjun Aravind • 2 January 2021 • 10 min read Last year was definitely one of the more forgettable years out there.I think I can safely say that I feel like I lost one year of my life without being able to do a lot of things that I had extensively planned for after graduating from college. By that, I mean things like travelling, going out to meet friends, visiting restaurants, etc.
However, the dark cloud that was 2020 had its silver linings for me personally. I joined my first company, Ajira, and while I was not able to meet my colleagues, I definitely did learn a lot about software engineering from them and what it really means.
And if there's anything I learnt, it's that software engineering is much, much more than just coding.When starting to work on a project, it's not possible to just immediately sit down and code the entire thing. You need to first gather all the requirements (functional and non-functional), then you need to come up with an architecture and basic structure for your project and only then can you start developing it.
In fact, coding the solution is probably the final step in the entire process.
On that note, I've tried to briefly list some useful tips for topics that I believe constitute the 'science' of software engineering in this blogpost.
The reason I'm writing this article is because I thought it might be helpful to share what I learnt in the last year with others. To paraphrase one of my colleagues at Ajira, Tamizhvendan, it is our responsibility to pass on to others, knowledge, that has been passed on to us.
Just a few things to note before that.
- Topics will be really random but I've tried to separate them into sections.
- This article is only intended as a 'compass' for readers and some topics might require further exploration.
- And, finally, a VERY BIG SHOUTOUT to all my colleagues at Ajira who've helped me out, in the last year, by exposing me to new concepts and improving my technique!
I'd like to especially point out Tamizhvendan Sembiyan, Lordson Jacob, Arun Madhavan Govindarajan, Harish Bharadwaj and Sat, our CEO.
Let's start!
Define Your Requirements
This one is pretty simple. Without knowing what your application needs to achieve and the conditions it needs to satisfy, how can you program it?
The Hydra, a monster from Greek mythology.
Gathering requirements isn't also as simple as you think. Ever heard of the Hydra, the monster from Greek mythology which would grow two extra heads everytime one head was cut off?
Asking questions regarding the project requirements is a little bit like that. For every question you ask, two more questions will pop up!
Trust me. I've worked as a freelancer and clients do not know what they want. It's your job to ensure that you understand what they want and to define the project requirements.
So what can you do?
- Notes: Take meticulous notes of every single functionality. Don't try to memorise it, never works.
- Use Case Scenarios: Try to think of a project in terms of use-cases or scenarios, wherever possible.
So, for example, in Facebook, instead of visualising the 'profile page' as a single functionality, try to divide into scenarios such as "how will the page look and behave when the owner of the page is logged in?" compared to "how will it look and behave when a user, who isn't logged in, is viewing it?.
Ask questions with this in mind. Then, go through every single scenario as much as possible and note down the questions or doubts you have. Ask them.
This makes your job much easier, even while developing and testing, because you don't have to develop with a million scenarios in mind.
Architecture
Needs no explanation. #BadArchitecture
Having an architecture in mind is the key to being able to visualise how different sections of code will interact inside the application. This will help you separate your code better, i.e, write better functions and classes.
- Architecture Patterns: Read up about different architecture patterns for different types of applications. Get yourself acquainted with the various pros and (most importantly) cons of each architecture.
- Decision-Making: Choose the architecture based on how well it solves your requirements!
Architecture patterns can be your best friend if you use them properly. If you don't, they can become your 'arch'-enemy.....sorry, couldn't help the pun.
Tech Stack: Choose Wisely
If you have a say in choosing the project tech stack, then give it some thought before choosing.
This is one of the biggest lessons I've learnt after joining Ajira. Don't choose a language, technology or platform because you like it personally, or because it's trending at the time or even because it's well-established.
At the risk of quoting my colleague, Tamizhvendan, one more time, "always be pragmatic".Choose the tech stack based on how much it suits the application requirements. If you're application needs to be really readable and have a maintainable codebase, you could go for Python or Java. If the application needs to be super-fast and is also compute-intensive, then it's maybe better to go with a C or C++. You get the drift.
There are also lots of frameworks and libraries which solve most common use-cases and also implement common architectures. You could give these a look to see if you can simplify your work by using these!
Research your tech stack well. Make sure it's as well-suited to your application as possible.
Development Environment: Perfect It
Imagine starting to work on a project and your team leader hands you a list of all the software that need to be installed, along with their versions and the order in which they must be setup. You also get handed a list of environment and path variables that need to be setup. And did he/she mention that all this works only on Linux?
It's hell. You can end up taking weeks to do this and wasting a whole lot of man-hours. When done wrong, the setup might be difficult, tedious and clash with other projects' environments on the same machine. So, how can we improve this?
- SDK Installations: When installing any SDK such as the Java SDK, Python Tools or anything else, install it using a version manager, if available. Version managers will let you quickly let you switch between SDK versions with a single command. Examples are SDKman for JVM-based languages (Java, Kotlin, etc) and NVM for Node.
- Applications and the PATH variable: Make sure you add the location of an application's executable file to your path. If you're working with the command line a lot, this might let you launch apps or open files with a single command. For example, instead of navigating to an HTML file and opening it with Firefox, you can just type
firefox filename.html
in the command line.
- Containerisation: If there's a lot of servers or programs that need to be running for you to develop, think about using a tool like Docker to containerise them. This way, you can run all of them in just a single command. This approach might also make it easy to deploy the project.
- Virtual Environments: You might definitely have projects on the same machine which need different versions of the same dependency. Use a virtual environment, wherever possible, to make sure you switch to the correct dependency versions when you switch to a project. An example is PyEnv for Python.
Readability and Code-Separation
Code-separation? 😅
Alright, we're at the last and most fun part, coding!
A colleague of mine at a former internship once told me, "your code must read like a story". That's how well-written it needs to be.- Readability: Make sure every single variable, function and class is given a good, understandable name that describes exactly what it does.
For example, consider naming your functions as
switchToDarkModeIfLoggedIn()
instead of switchmode()
. That variable i
that you use for loop iterations can be called loopIterator
instead too.
- Code Seperation: As a rule, every single function should have just one objective to complete. Similarly, the objectives being achieved by a class must be singular, if possible.
For example, separate a function which logs in a user and also checks if they are over 18 or not. These must be two separate functions.
In the same way, an object or class which describes a 'person', in the context of a school management system, must not contain methods relating to the amount of kilometres they travel by bus everyday to get to school.
- Best Practises: Read about the best practises, concerning naming and application structure, for the framework or programming language that you are using.
Not only will it make the code neater, it might also increase performance as the language compiler or interpreter will contain in-built optimisations for these.
---------------
So, that brings us to the end of this article! I really hope it helped.
As usual, if there's something I've missed it out on or if I've made a mistake, please feel free to contact me by e-mail! Cheers!