While there are several meanings for "software design," we'll focus on the process used to plan what we want to build ahead of actually coding up a software solution.
This process creates documentation and other helpful artifacts, such as diagrams, to be used when implementing software. While there are many ways to perform this process, the final result is usually the same: a design document outlining all essential information necessary to build the system in question.
A design document lays out a few critical pieces of information:
While most of this information can be fully explained with text, various types of diagrams and sketches can prove helpful as well. UML, universal modeling language, is commonly used to create diagrams for design documents. When designing systems with UI, sketches, or mockups of these UI components are highly preferred.
Software design and the process with which you build software are not entirely intertwined. Many will think this is all advocating for a Waterfall process, and while that is one way to make use of upfront software design, it's not the only way. It is entirely possible to do upfront design with an Agile methodology. While a Waterfall process may imply a more granular design document ahead of implementation, design-first agile can rely on a rougher document that gets iterated upon as the software is built. Essential requirements and initial tradeoffs are documented first. As prototypes are constructed to validate specific areas of concern, the results are recorded, and the design is further hardened, just like the software.
More granular, less granular, where to draw the line and call a design document "finished"? First off, software itself is iterative in nature, our designs must follow suit. That said, it should not be the goal of one's design process to account for every single potential outcome or plan every variable and function to code up. A balance needs to be struck where all major concerns are addressed in an upfront design, but not every detail.
The right balance varies wildly, too, based on the industry, company size, and type of system being built. A big company can afford to spend a little more time on design, ensuring the system will support the large scale the company already operates at. A startup should spend minimal -- but not zero -- time on this, getting an implementation out there to quickly get feedback and iterate. Only through continuous trial and error will you and your team find the right balance, which will continue to shift over time.
An essential piece of this process, which requires balancing the time taken, is peer reviews of designs. An implementation plan can be stress-tested early by multiple team members with varying backgrounds (as in, frontend, backend, security, etc.) vetting it. These reviews can be done synchronously in a meeting, or asynchronously, using comments on Google docs to further refine the design document, for example.
Bringing compassion to these discussions is critical, though, as ideas flow best when everyone in the room (or virtual room) is comfortable speaking their minds and collaborating on the problem. While this may seem like a significant investment in time and energy to make upfront, with the right balance of time given your team's circumstances, there are undeniable benefits.
It's actually faster to have design documents to work from! Peer reviews form consensus ahead of implementation, reducing the time and friction of reviewing code. The general architecture has already been agreed upon, so code reviewers can focus on smaller details knowing the overall picture has been figured out. Questions from partner teams (marketing, sales, etc.) about what is being built can be re-routed to design documents, freeing up even more engineering time. Furthermore, for large projects spanning many individuals, this documentation acts as the foundation upon which all pieces are built.
In addition to architecture being established ahead of code reviews, upfront designs reduce the number of edge case style bugs. During implementation, engineers can better focus on all the small details since the overall architecture has already been established. Lastly, costly architectural mistakes that can sometimes take years to unwind can be avoided, just because a reviewer of the design document caught a pattern that could cause pain once implemented, and steered the design away from that architectural anti-pattern.
Software design is a vast subject with no single right answer. Every organization does it their own way, and every successful organization has a process for designing their software. Whether it's a super formal process or a casual conversation, collaborating on software design is the key to unlocking its time-saving potential, combined with writing down these thoughts and ideas, to act as a reference when actually programming out these solutions.
Benjamin is a passionate software engineer with a strong technical background, with ambitions to deliver a delightful experience to as many users as possible. He previously interned at Google, Apple and LinkedIn. He built his first PC at 15, and has recently upgraded to iOS/crypto-currency experiments. Benjamin holds a bachelor's degree in computer science from UCLA and is completing a master’s degree in Software Engineering at Harvard University.