OK, so you already know how to program some software that kind of works. When you are ready to take your software development to the next level, we recommend to implement these tactics:
- Project Management
- Issue Tracking
- Version Control
- Unit Tests
- Test Coverage
- Code Quality
- Performance Optimization
1. Project Management
Before you can set out to improve your software you need an effective way to plan and organize your development work and keep it on track. Methodologies provide a way to break down tasks, prioritize them, and get them assigned to the right team members so they can get done on time. Popular methods to manage software development projects include agile methodologies including scrum, kanban, and a combination of scrum and kanban called scrumban. There is much evidence that using these well known frameworks the right way can help save much time and money on software development projects.
2. Issue Tracking
It's hard to efficiently resolve bugs and feature requests in the software if you can't keep track of them. Integrated issue tracking systems (sometimes called bug trackers) provide a way for users, developers, and testers to communicate efficiently about issues and stay on the same page. Such systems provide a central database where bugs and feature requests can be entered for a software project. Useful information can be attached to each issue, such as how to contact the person who reported it, date and time, error messages, screenshots, and priority. Status can be tracked for when bugs are open, in progress, and resolved in a certain version. Open source issue tracking systems include Bugzilla, MantisBT, and Redmine. Some tools integrate project management and issue tracking.
3. Version Control
Unless you are a miraculously perfect developer, you have probably used the undo feature to restore a previous "revision" when you have made a mistake in code. With many lines of code in multiple files, it became desirable to keep full backups of the code often. That way, a developer could change whatever he wanted without fearing that it would be too hard to get back to a working version if he made a mistake. Version control (also called source code control) systems make this process really simple and easy.
When use correctly, these system keep a complete record of who changed what when, and why. No longer does code need cluttered with comments like "# On the next line Isaac changed x from 1 to 2 on August 4th to add an example". Now code can be added to version control then kept clean from such comments. It is like a super undo command because it allows you to rewind any part of the code right back to the state it was at any point of time in history. Additionally, including Issue IDs in version control comments can enable amazing integration between version control and issue tracking and project management.
It is worth investing some time to master version control concepts such as branches, merging, and resolving conflicts. Some version control systems include Subversion, Git, and Mercurial.
4. Unit Tests
Once you have project management and issue tracking in place to know what to do when, and once you have version control in place to manage changes so you can almost code fearlessly, it is high time to look at unit tests.
Since you started developing software, you probably tested it even without thinking about it. When you wrote a program then ran it to see whether it printed "Hello World!", you were testing it. You had a certain expected result for a certain condition, and you exercised the code to verify that it worked as expected. As programs got more complicated, you may have memorized a sequence of every feature you went in and exercised to test the program. If you had somebody else test it for you, you may have written the sequence out as a test script.
Automated testing makes our lives much easier by letting us specify the expected results for various conditions in code. Like a manual test script, each automated test could be collected together into a test suite. After each change, the whole suite could be run to test many different parts of the program in case a change in one part unexpectedly affected another.
The difference between unit tests and other automated tests, is that each unit test only exercises a specific isolated piece of code known as a unit. One advantage of this is that when something breaks, you can tell which piece of code had the issue quickly by which unit test fails. Unit tests use mocks and stubs (sometimes called fakes) to model assumptions about dependencies external to the unit. Tools for Java include, for example, JUnit, JMockit for mocking, and Hamcrest matchers for verification.
5. Test Coverage
Once you start adding unit tests, you can use code coverage tools to track how much of your code is exercised by your unit test suites. The idea is to have much of the code covered by the testing. Some master developers like to use TDD (Test Driven Development), where they basically always write the unit tests before the actual code. But even if you add unit tests later, it is very useful to have a comprehensive unit test suite where tests are true unit tests (isolated using mocks and/or stubs) and a high level of coverage. This allows you to fearlessly refactor and change code without worrying about it breaking something else in another place. One code coverage tool for the Java programming language and Eclipse platform is EclEmma.
6. Code Quality
We need to realize that there is a big difference between code that kind of works and good code. It doesn't take long for a master developer to identify quality issues in low quality code. Some quality issues include inconsistent formatting, dead code, redundancy, and over complication. These issues can all be resolved by refactoring.
We talked about many other concepts first, because if you go trying to refactor quality issues and fix bugs without the previous concepts, you risk a change in one place causing more issues in other places. Once you have effective project management, issue tracking, version control, unit tests, and test coverage, you should be able to refactor and resolve issues fearlessly. Also, the process of developing comprehensive unit test suites is a great way to discover code quality issues that need resolved.
Some modern IDEs (Integrated Development Environments) such as the Eclipse platform include automated refactoring features, which can save time and cut down on mistakes. It is also helpful to use a static code analysis tool to detect and catalog code quality issues so that you can fix them. One such tool for Java is FindBugs.
7. Performance Optimization
One useful tactic for optimizing software performance is using a profiling tool. A good profiler can tell which parts of the code take the longest to run each time, which are run the most times, and which take up the most total time. Then optimization efforts can be focused on first optimizing the code that has the biggest performance issues.
It is often found that the same code with performance problems also has other problems, such as those addressed above. Some tactics for optimizing a piece of problem code may include:
- Consider whether it is possible to skip the inefficient code entirely at least sometimes
- Familiarize yourself with the best tools for certain jobs (such as data structures and algorithms)
- Implementing some type of caching - more advanced and could have other implications
It is also a good idea to optimize the performance of the unit test suites, so that the whole suite can be run and verified often, preferably so any failures can be fixed before each time of checking in changes to version control.