Writing code is easy. Instantiating objects, calling methods, memorising functions (or using the documentation instead); these are all trivial tasks that we have all taken time to study and practise. But engineering software is so much more than coding. As a software engineer you take on several roles throughout the software development life cycle. Let us take a look at some key roles that developers play during the software development life cycle, some problems you can run into, and how to solve them.
The secret to planning any successful project is good estimates or no deadlines. Since the latter never happens, you need to take on the former and become a planner. This is the most challenging step of software development and the most critical. A lot of software engineers would like to think that planning is not useful to a project. The concept of 'the software will be done when I finish it is very appealing, allowing you to continue developing with no outside interference. However in practice that is not feasible for most businesses. In order to run a project, a business needs to have a plan of what will be done, including a timeline which relates to the budget, and feel confident that in the end they will have a working deliverable. This means you must bite the bullet and make a plan before you begin to code.
A common claim is that planning doesn't work because its impossible to predict the future, however this is only true to an extent. It is entirely possible to plan how to write a particular piece of software and how long it will take. It is also perfectly feasible to stick to this plan and deliver on time. The problems arise when an unknown is encountered during the course of the project, throwing you off schedule. This is totally normal but you cannot prevent, predict or stop this from happening. The only thing you can do is change your reaction to it. Flag the event as soon as it appears and tell the client about it. Be prepared to tell them the solution to the problem at the same time and the new delivery date if it will change.
Making accurate estimates is entirely possible if you take your time and really think about what you need to do. Break the project up into smaller pieces of work, called features or stories. Do not simply accept your gut instinct of how long it will take to do something. Think about each step you will need to take in building each piece of the software. There could well be a step you didn't consider in your initial estimate. This hidden work will cost you a lot of time over the course of the project. Once you've estimated how long it will take to write the code, you should add to your estimate the time it will take to complete all the other work including architecture, testing and documentation. The easiest way to do this is to figure out a scale which you can calculate against. For example, if you spend 7 hours coding something, it will take you 1 hour to document it. This scale will vary depending on your project or team.
Architecting software is actually part of the planning process. It is a very lengthy part involving a lot of research, thought and work; thus it becomes our second role in developing software. In order to build software, you need to have a plan. And in order to have a plan, you need to know what you will build. If you do not give a developer some general guidelines on how to write their code, they will improvise and do it in their own way. If you begin to code up front without taking time to design the system, you'll find yourself re-doing a lot of the work in refactoring later on. This is not good for the stability of the product and can cause problems or bottlenecks during the development process. You may end up repeating the same work over and over again if you have not taken a good look beforehand to determine what to do.
All too often when building a system we overlook the importance of the system infrastructure. This is traditionally a systems administration task, but as a team lead or member of the planning team, you are responsible for determining what is needed and getting it implemented so your software can be used. You need to allow time to determine the system infrastructure and implement at least a development environment before starting the project. If this infrastructure is not in place beforehand, you'll have a lot of time wasted by developers trying to set up and maintain their own environments.
Its not possible to create software with only a production environment, so you'll need that environment mirrored for development and staging environments. Also, throughout the project, you may have several changes made to the environment as requirements change. Using virtual machines is a great way to solve both these problems. They can be used by anyone on any platform, are completely portable and can be version controlled. Set up the virtual machine to match your production environment exactly and this will save you tonnes of time during testing and release cycles.
Architecting code is all about setting standards, so set standards for as many things as you can. The development team should not have to worry about where to put a specific file or whether this functionality should go in the service layer or in a model. These types of decisions should be set out in the architecting process. If you can, use already created, well established coding standards; someone else has always solved the problem before you. If you have a service layer, consider using REST web services as the layout is very simple and straight forward to use and the developer will have lots of resources to refer to when creating it. If you are using a framework, always adhere to their coding standard. In the end the standard doesn't matter as long as all the layouts and formatting are consistent throughout the project.
Implementation is the hard part. No wait, its supposed to be the easy part! Implementation is hard because you have to stick to what you planned. So what happens when something has changed along the way, or something is harder and more time consuming to complete than you thought? This brings us to our third major role in we perform in software development, coding.
The easy solution to challenges that come up during implementation is to improvise instead of doing what you planned. This is not a solution but causes more problems. As soon as there's a problem with implementation, it should be flagged to the team management immediately so you can discuss the problem and determine a solution. Developers are natural problem solvers, so going to other people when a problem arises goes against everything you know. Resist the natural compulsion to sort it out yourself and keep the team aware of everything that comes up along the way because its probably also affecting others. Raising problems early results in finding solutions early and keeps you on schedule.
There are many different ways to keep in contact with your team during implementation. If you are practising Agile project management methodologies through SCRUM, your daily stand up will provide a great base for communication of progress and blockers. Your version control system holds a complete record of everything that is going on in the project and you should take a look at the commits each day to get an overview of what's been going on. Whether or not your team is remote, you should have a team chat of some sort. This can be through any chat system which supports group chats or a message board system. There will always be times when your team can't chat in person because they are away from their desk or are just working quietly. A chat system keeps the communication lines open at all times and provides a great reference log. During implementation your team should plan on keeping an up to date knowledge base of everything they know about the project. This is essential for team members to reference parts of the project they are unfamiliar with and especially for new team members joining during a project.
Great! Your feature is done and it is awesome! Time to refactor it because you can do so much better!
OK, this does not happen 100% of the time, but quite often at the end of finishing a feature, there are parts of it that turned out less well. This is usually because you understand the problem fully once its completely solved. Afterwards you can see lots of other, potentially better, ways of solving the problem, and taking the time to polish the code will cause fewer problems in the future. If the code does not comply to your coding standards or does not perform well, this will negatively impact the overall maintainability of the software. Its a good idea to take a little bit of time and have one final look at it, or have a colleague do a quick review.
There is the refactorer role in all of us, we just have to find it. Having regularly scheduled code review meetings are a great way to be proactive about ensuring code quality and also for mentoring developers. A code review can happen either weekly or monthly depending on how much time you have, and should include at least the team leader and one developer. Choose a piece of code that is an important part of what has been worked on since the last code review. Its not necessary to find a piece of code that is bad. A code review that looks at code which is well written and not in need of any changes is just as effective and the positive feedback is great for the team.
Our fourth role of the tester is just as important as any of the other roles mentioned, but is most often omitted. When you are crunched for time, writing tests for quality assurance is often the first thing to drop to lowest priority on your list of things to do. It is quite hard to prove that testing is absolutely necessary to do in order for the software to be complete. The tests are not actually part of the software, and are not required to make the software work. However, tests are required to make sure the software is stable. If your software is complete, but is not tested, you can not be sure that it is ready for production. The larger the software is, the more important testing becomes. A medium size development team, as few as 5 people, will be able to commit massive amounts of code each day. This code is intended to interact with each other in one way or another but its not possible or feasible for every developer to keep tabs on what another developer is doing all day. Therefore its not possible to ensure that what you are building today is not breaking what someone else built yesterday unless you test it.
Testing is in general not a fun thing to do. You do not create anything new and it can be quite time consuming figuring out all the test cases you should write. Try to make testing as easy as possible in your project. At the start of the project, have all the infrastructure you need to support testing in place so its as little hassle as possible for the developers to actually do it. There are several tools you can use to set up this infrastructure.
Do you understand the software that you're writing? I mean really truly understand not only what it is doing, but why? When you have completed a feature the final step is to ensure it does what it is supposed to do through a process called user acceptance testing. During this process, the client who requested the software will manually test the software by using it in the same way the end user is expected to. As a PHP developer, usually the last thing we think about is actually using the software. There are so many other things going on from a technical perspective in creating the software that there can be very little scope for making sure the software is doing what the client wants it to. The fact of the matter is that everything you build on the back end means nothing if it is not what the client wants. You might be on a roll with writing all the code for this feature and lose sight of what the feature is actually doing so try to continually refer back to the technical specification or acceptance criteria. Even though you will not be doing the 'official' user acceptance testing, take a bit of time when you finish a feature and actually use it. Very often you can find problems. It can be a bit of a fun break to use the application instead of just code it. It also gives you a chance to look back at what you have worked on, see what you actually made, and be proud of it!
Every developer hates writing documentation. This is because we all know that code is self documenting; its says exactly what it does. Writing documentation is hard in the same way that writing tests is hard; in the end its hard to justify how it affects the bottom line of getting the software finished. Also it is much less interesting than writing code. The best way to ensure that documentation gets written is to set up infrastructure and processes for it at the beginning of the project. If the process exists, there are fewer excuses a developer can use for not documenting. There are several tools available which can be used to scan the code and look for specific API documentation and flag files which are missing this documentation. Another great motivator for getting developers to write documentation is actually compiling the documentation so it can be used. If the team is using the documentation on a regular basis and benefiting from it, they are much more likely to want to contribute to it.
Each of the six roles described here are vital to any software development project. Ideally in a project each of these roles is required of one individual. However we all know this almost never happens. This means each of us have to perform most, if not all, of these roles. This can be very challenging to keep on top of everything, although the challenges of the individual roles are not impossible. Hopefully these tips can help you better plan out your next project and to overcome challenges more easily.