Written by: Stefan Bradstreet
When it comes to creating software there are many choices you can make along the way in terms of what programming language do I use, what kind of data stores should I use, how will my applications talk to each other, and more. Then in addition to this there is an infinite number of ways to write the code to drive your software. However, even with all these options this article will describe the basic framework I’ve been using when creating new services or platforms that will help you put in some proactive thought into the all the parts of your application and have a successful launch and efficient software development life cycle.
Remember, It’s important to put in a high level of hard work and critical thought in the beginning because creating an application takes a lot of time and there is nothing worse in software development then spending 6 months building an application which bombs and having to spend an additional 6 months to redesign it causing stress and frustration. Compare this to putting in 2 months of detailed upfront design and having a 5 month coding time of high quality and maintainable software components.
This up front mental investment will save you tons of time and frustration towards the end of your project and post launch. Imagine you are on a plane going from one side of the world to the other, if your pilot is of course at the beginning by just a few degrees in the beginning; this will result in you and everyone else on the plane being thousands of miles from your destination after the same amount of time.
Nothing in the world is worth having or worth doing unless it means effort, pain, difficulty… I have never in my life envied a human being who led an easy life. I have envied a great many people who led difficult lives and led them well.Theodore Roosevelt
Identify your need and estimate the value it will provide
When creating software you may think it’s a cool idea to create a game where you have turtles in space that can time travel because these are all things you really like in a game. If you are just building this for yourself as a learning project then great, feel free to build “Moon Turtles Time Machine”. But I don’t believe a lot of people will download your game because it’s only providing a small amount of value for a small group of people, and if there is already a game like this on steam then the need for yet another turtle space game might not be very high either.
This also goes for websites, or automation projects. Typically if you or your company has some problem that is requiring a lot of manual effort to do that could be solved with software and you can quantify that the overall time saved would be more than the time to create said software then that is a worthwhile project to design and create.
Ensure this idea is actually solving the problem for your desired customers
As a simple example imagine your customers main problem is that they were given a box of nails and some pre-cut wood and they need to build a birdhouse. If this is your customers main need you likely wouldn’t design a screwdriver for them and a guide for making toy cars. You would need to make a hammer and a pamplet for a bird house. Sure, with some frustration a few of the customers may end up making something that looks like a birdhouse on wheels from the first product but which one would you rather have?
Also you should consider how many of your customers are you solving a problem for. If you are running a large carpentry class with 100 students and only 5 of your students have the birdhouse problem but the other 95 students are looking to build toy cars with screws; then we should prioritize creating screwdrivers now to provide the most value. In an ideal world we could solve all of the customers problem but with limited resources we need to evaluate the trade offs of the work we commit to.
Another example from my own experience is while working for an emerging technologies team; we designed a system that created a completely new user experience for customers interacting with an ATM. You would queue your transactions on the phone then go to the ATM and scan a QR card to enact the transaction and dispense your cash. The technology involved in this project was extremely fun to build and it demoed well at trade shows but several years later this product isn’t nationwide. One can only assume this is because a lot of people aren’t using cash as often and the ones that do are already too familiar with the current ATM experience. And the ATM works well enough that banks aren’t eager to buy completely new cash dispensing solutions.
Recognize who your customers are
When it comes to software there are a wide array of customers you could be creating applications for such as:
- your direct team
- internal team A and internal team B where each team has different needs
- small businesses
- the mass population
- niche groups (people with dogs, moms of twins, software developers)
Early in your design phase you should discuss with your customers to get more details of their experiences with the problem you are trying to solve. Getting as much input as you can early from the customer will help you design a software application that can provide more long term value and enable you to see use cases or feature ideas you likely didn’t think of yourself. These details can also help you as you go to the next phase where you figure out which building blocks you will need to cater to the main use cases of your application.
Scope out your features and components
Now that you are confident your software will solve a problem for your customers and have feedback from them in what else they would like from your application you can start thinking through the features you will need. For instance if you are creating a server based web application to let people share files with each other you will likely need to support the following feature requirements:
- A user should be able to log in and out to a webapp to have files controlled by them
- A user should be able to upload a file and share it to someones email address
- A user should know when a file is shared with them
- A developer should know if their system is suffering problems
To support these requirements we will need the following components:
- Server hosts
- Load balancer
- Webserver such as apache, nginx
- Deployable web application code
- Storage for user files
- User access system
- File permissions system
- Notification service to let people know when a file has been shared with them
- Something that tells you when your web application is not performing well
Of these components you can break this down into even smaller functional pieces by creating architecture diagrams of the system and class level designs for the central objects we will need such as User, FileUploader, FilePermissionManager, Notifier, MetricEmitter and potential data structures that will be used by these classes. Going through the exercise of breaking down your components into smaller and smaller parts will help you in laying out the project plan by having a better idea of what tasks will need to be done.
T Shirt Size your features
T shirt sizing is an exercise where you take a list of features or tasks and as a team you estimate the level of effort each will take to be done in terms of complexity from Extra Small to Extra Large.
Create a UI form for a user to enter their username and password would be an XS task.
Create an entire user access system would likely be XL as it includes creating all the code, setting up the user database, making all the web pages.
If you end up with too many XL features during your T Shirt sizing exercise that is a good sign that the team should go back and break down the features more into distinct functional tasks. Sizing down a feature into several smaller tasks will lead to more accurate estimates and better development cycles from having a more detailed map to follow.
Identify the minimum viable product that will provide value
When it comes to designing software, often times the developers and customers will come up with a long list of features they want this software to accomplish. Your initial estimates may drag months into the future to deliver your complete software application but carefully filtering through the tasks you T-Shirt sized can help you come up with a phase plan to deliver pieces of works in release cycles.
Separate out your nice to haves
According to the 80/20 rule, 20% of the features proposed during these brain storming sessions or feature gathering phase will provide 80% of the results. These should be the features you target for in your first release cycle. If you go back through your feature list and also TShirt size your return on investment for the feature you should start to see a picture form of how to lay out your results. Any S effort task that provides a L level of return on investment should greatly be considered in your first release.
It’s also worth pointing out if this is completely new software your first release cycle will take longer then follow up releases since you will need to setup all of your systems infrastructure and define your initial software patterns in this phase.
Each release should add more functionality to increase how effectively your software solves problems for the customers similar to the diagram below. Obviously design your releases to be like the bottom with a constantly increasing suite of features and simplification!
Create your project plan
Now that we have put proactive thought into our components and our releases we can create the project plan and the timelines. From our TShirt sizes we can estimate how many developers it would take to reach certain target release dates. If you are creating this software on your own then you can determine how long it will take with your current plans.
General during this phase you will have enough confidence in the level of effort that will be required and the value that will be gained to revisit if the ends justifies the means.
However, if your project plan is too long for the resources available but there is still a high return from this work; now would be the time to determine what trade offs can be made in your design. For instance instead of taking on an effort to create and manage your own servers could you sacrifice monthly costs for cloud based hosting which would be faster to provision and provide less maintenance? Does your skateboard in drawing 1 really need 4 wheels? Would you be okay skating along on three wheels for a while until you can pick up another wheel down the road?
A real life situation for this would be you know three months from now your company is going to be facing a significant problem that will require extra man-power that your software solve; but your desired first design would take five months for the first working release. In my experience I’ve found you can shorten schedules by getting creative with reusing existing infrastructure patterns, components, or code libraries. When doing this it’s important to consider the maintenance overhead that may come from sharing resources or introducing extra dependencies.
Drive your development cycles
After the plan is finished you can break up all your tasks and start working on them in a logical order, meaning you likely wouldn’t want to work on Restful APIs before you even have a web application to run the APIs or you wouldn’t want to create user manager service logic before defining your User base classes. Doing first things first will let you define reusable patterns and build up tests in a way to have extra confidence when adding functionality into existing classes.
If you are working on this software with a team you can also look into agile development management such as scrum, waterfall, or kanban to assign work, test, and improve your software quality. Following a development methodology will help you drive a productive software development life cycle from design phase to coding iterations and then to release and support.
How do you ensure your software is doing what it is supposed to do
Eventually you will get to a point where you can launch your software. It may be a web application with just a web page but after doing the hard work of setting up the hosts, determining what web application framework you want to use and making a hello world in nodeJs/Spring/Flask; you just want to see the fruits of your labor in action. After visiting your basic web page that looks like it was from the 1980s you go to work on configuring a theme. A few hours go by and you visit your page again and all you get is a big fat “500 internal server” error.
Your application is down, not a big deal right now, but imagine it was actually serving a purpose and 100 of your customers saw that error. Now what if this was an application that actually generated revenue for your business and now 10 of your customers are so mad at the outage they cancel and 20 other customer who were going to order something went to your competitors instead.
This is why it’s important to know as soon as possible that your application is broken. Cloud platforms like AWS allow you to set up different metrics to watch CPU, Memory, and uptime of your hosts and set up notifications to “alarm” you if something goes over a set threshold. If you’re not using AWS you should look into finding libraries within your tech stack then recreate this kind of spying for you.
Strive for great test coverage
While developing code most of you know writing unit tests is a best practice, but how many tests should you write. Early in your project you should aim for having a certain percentage of lines being covered by your tests. A good percentage is at least 80% and a great percentage to aim for would be 95%. Your testing library should be able to generate test reports that breaks down the lines covered by your test suite and shows what lines are missing coverage.
You should also insist on high quality tests from yourself and other developers working on your software. If your application has a main method that just so happens to call your applications 10 functions, writing a unit tests that just calls main() and reports 100% coverage is not a good testing strategy. Instead there should be 10 test that call each function that asserts the happy path calls and also tests edge inputs and garbage inputs to ensure it ‘breaks’ in a recoverable way. Also if you have one function that makes up a large portion of your application such that it is hard to test because of dependencies or data transforms then that function should probably be refactored into discrete testable parts. In that instance it would be good to consider inversion of control and pass in a challenging dependency into the function which the client is responsible for creating or mocking. Each data transform should also be its own function and test.
Another effective benefit of a good test coverage strategy is other developers can run the unit tests to learn how sections of code works.
Document your design and functionality
We have a hello world application, we know when it breaks, we have tests, but how in the hell does anyone else know what you have? Sure they can run the tests but how do they do that? Maybe they can pull the code, but where is the code?
Unless you want to answer a lot of the same questions down the road then remember to document your software. Not only does it give you a chance to think through your software more but it also saves you time down the road by being an important resource for people to learn about the software without needing a complete code walk-through from you. That person you’re helping might even be you when you write this software, you go work on something else for a few years, then you come back to add functionality into a library of your old code and you don’t remember all the places you need to edit. Spending an extra hour to make a clear class diagram may save future developers 10 hours of onboarding time in the years to come.
Informative User guides
Think of this as documentation for your customer who doesn’t care one bit about how well written your code is, so long as it works and it helps them do their work better. A well written user guide should walk a user through all aspects of your system in a simple and concise way with visuals. The communication style should also be aware of the audience, if the end user aren’t tech customers don’t use a lot of large techy words like your user password is salted and stored in the mysql backend. Just say “we store your password secured”.
This is another one of those things where the better you write the user guide and the more stable the system is, the less time you will need to support user questions and the more time you can iterate new helpful features.
The launch announcement
After getting to a point where the first major release is done and your application is in a state where the end user can get value from it you should communicate that to your users. This can be an email if the customers are internal, paid advertising, blasting your social media groups, or working with the product manager if you had one to determine how to let people know your software is available. As long as the people know your software is there, that it will provide value, and where the user guides are then you’ve finally made it but the software development life cycle doesn’t end here. The next step is in the hands of your customers to use all your hard-work and start providing feedback while you maintain the software.
Keep an eye on your application
Now the exciting part is just beginning. Since users are now using the application you should know be getting customer usage metrics. Here you can see how many people are using it and you can see if failures are occurring. If you know a certain database lookup was taking a second in your testing but your metrics are showing it takes 20 seconds for your users this would be a bad experience for your customers. It might not be so bad that they email you about it, but bad enough to deter them from using it. You should also have your alarms setup to let you know if your service is completely unavailable to all users. Imagine you know you have an average usage pattern but now your key heartbeat graphs are showing zero, this is where you should drop everything else you’re doing and figure out why you are experience an outage. Firstly sanity test your own production version of your application to see if it works and if it does if you can find your metric spike. Occasionally systems that watch systems break too.
Several weeks after launching your application you should reach out to trusted customers either in person or through a usage survey to get a feel for how they enjoy the user experience of the application. Customers will happily tell you what they like or dislike about your product as if it was a reddit user up-voting a post. Treat this feedback as good as gold because without the customers your software is just a bunch of ones and zeros sitting on a computer somewhere.
While working on the future releases of your software you should also find room to take the customer feedback and bring in work to address any concerns they may have had. If a lot of users are complaining that they don’t understand what to do after their create their user account, then building in more guidance and education into your application while simplifying layouts should take precedence over whatever the next feature is. If your feature is using a similar style of experience to the first user you should also consider this feedback to change the new feature to be more simple as well with more tool tips built in.
Going forward you should be able to use these steps to keep driving well thought out and proactive pieces of software. You know how to define your problem and determine its value. You can communicate this to customers to gather additional requirements for determine the features you will support. You can prioritize your features to break them up into released and a minimum viable product. During your develop you know the important of creating and watching metrics, testing, documentation, and user guides. And lastly you can announce the launch of your high quality software and gather customer feedback to improve your future releases. Thank you in advance for all the great software you will launch using this approach to your software development!
Additional critical design references
In order to pay the bills for this website I would greatly appreciate if you would check out these resources on Amazon for more detailed coding practices. Or just click on the link and then go buy something else you may need would work too. But if you don’t need anything now just remember to come back here first when you do, the developers that read future articles posted here will appreciate it too.
About Stefan Bradstreet
Stefan is a Senior Software Developer at Amazon with 8+ years of experience in tech. He is passionate about helping people become better coders and climbing the ranks in their careers, as well as his own, through continued learning of leadership techniques and software best practices.
Thank you for visiting!
Please remember if you found this content useful and would like to see more python and software development articles from us, help us conquer the google algorithm in any of the ways below:
- Comment your thoughts below
- Share this on your social media
- follow me on twitter
- subscribe to our Youtube channel
- Contact me on the service page for coaching
- Shop through our affiliate links: Python crash course book
If you didn’t find what you expected feel free to use the contact page and let us know ways we can improve or what would help you grow as a developer better! I am honored by every view and it takes a village to really make this great.
2 thoughts on “How to Develop High Quality Software From the Ground Up”
Hey! I’m at work surfing around your blog from my new iphone 4!
Just wanted to say I love reading through your blog and look forward to all your posts!
Keep up the superb work!