1. 12
  1. 6

    I’ve worked on designing, building and deploying a couple of large systems at Uber/Skype/Microsoft and reviewed the design of several more of them. None of them follow the documentation advice or approaches given in this post, not even close.

    However when we need to explain to someone else (new developer, product owner, investor, …) how the application works, we need something more… we need documentation. But what documentation options do we have that can express the whole application building blocks and how it works?!

    This post then goes through formats like UML, 4+1 Architectural view model, ADS, C4, dependency diagrams and application map. I’ve heard of some of them (e.g. UML taught extensively at universities), but haven’t used them and find it unlikely I’ll reach for these tools. Here’s why.

    What I’ve found to work best when documenting architecture is this: Simplicity.

    1. Whiteboard should be your top choice. If you can’t explain the architecture of your system/app on a whiteboard to another person or a team starting at the high-level and digging into the components, you have a problem. You either cannot step back to being high level enough to start with a simple state. Or you don’t understand how key parts of the system interact. Go back and practice until you get there.
    2. Simple documentation with simple diagrams based on what you would draw on a whiteboard. If you can explain how it works on a whiteboard, write it down into a document. Write it using clear and easy to follow language.
    3. Architecture is about tradeoffs. Be clear on what tradeoffs you choose. My beef with much of the “let’s find the best way to document software architecture” is how these discussions seem to sideline the fact that architecture is just a tool to choose certain tradeoffs for certain short- or long-term benefits. A good architecture reasoning should explain what tradeoffs it’s chosen and what goals it’s optimizing for. This detail is a lot more important in implementing it correctly, than having perfect documentation.

    This is the approach I’ve seen people and teams use when building systems at places like Uber, Facebook, Microsoft, Google, Amazon. Amazon has the famous 6-pager narrative, which teams I’ve heard follow more or less for new systems as well. At Uber, we write down and share system design proposals via an RFC-like format (I’ve written more about that here).

    I’ve seen heavyweight, formal architecture documentation indicate a slow-moving company/team. When we rebuilt the payments system at Uber, we used the lightweight design documentation I mentioned above, completed the planning&protoyping in 2 months, built and rolled it out in 6 months. I talked with a peer who was redesigning the payments system at a major bank. They were using formal methodologies (UML et al) and were 2 years into the planning, not even starting development. A key difference between how the two places work is that this bank had architects who only did paper architecting, not being involved in coding it. While at most major tech companies, the team who comes up with the design also codes/ships this, keeping focus, engagement and accountability higher.

    Use the KISS principle to architecture planning and prefer iteration over perfection. Keep it stupid simple. This worked really well for me and it continues to work well for most of the major tech companies.

    1. 3

      I think however that none of the two approaches (Uber vs bank) is better or worse. It just works for both companies respectively. (I do not want to create the impression that you said anything negative about the bank situation; you did not. “slow-moving company/team” and “2 years into the planning” itself does not mean anything negative at all, it’s only natural that banks with massive legacy systems that have to run and be maintained are extremely slow; I just think that many people here on lobste.rs probably think that “slow-moving” == bad).

      Uber on the one hand is a small and young tech company, thus for them it works that a few engineers design a new system in a short amount of time.

      A bank has a massive amount of legacy systems, a lot of legal requirements to follow etc. and to get a grasp of all these requirements and compare them to the newly planned system a lot of communication and planning ahead is needed. The result still will be less than optimal, but from recent experience I just think that is how it goes when communication spans several departments (and developers get re-scheduled from and to other projects).

      I mainly work on quite small systems in automotive, but even I recognize how much communication overhead you start to get as soon as multiple department start to get involved and you have to combine all of their input into a new solution.

      I also do not do any of the methods from research (e.g 4+1 diagram) from the article above. I currently try to do a one page overview for each new project I start and in these usually include 1 or 2 charts of the existing situation and the planned architecture.

      1. 2


        Generally I just say cover: what and why.

        What, from a high-level down to whatever level detail you need.

        Why, why did you make the decisions you made? again, start from a high-level and go down in detail as needed.

        Which is basically what you said, just put differently.

        1. 2

          I also believe that documenting the decisions RFC-like is one of the most valuable points. We call these “design decision documents”. Documenting context, tradeoffs, and assumptions is the most important part there. While the chosen solution is apparent later because it got implemented but the “why” is easily lost. Especially in large long-running projects where many people come and go.

          What I like about these templates is that they provide a checklist of things to consider. Even if you keep things simple and fitting on a whiteboard it makes sense to do a stakeholder analysis and define your quality goals. Maybe half an hour is already enough in your project but it can result in some surprising insights.

          I work in automotive. Due to a customer-supplier relationship (requirements engineering) and safety regulations we are more process-heavy. Once that level is requirement there is on additional aspect I can recommend: Model your architecture! I have heard many interpretations what that could mean. The relevant point is that multiple diagrams are kept consistent by a common data structure (the model). Generate code from that data structure to keep the code base consistent with the architecture model.

          1. 1

            The relevant point is that multiple diagrams are kept consistent by a common data structure (the model).

            Can you elaborate a bit more on this point or do you have some links / papers I should read? I am currently learning for a university exam in “Software Architecture” and one of the many questions they deal with in the material for this lecture (but do not present a final solution) is: How can you make sure that multiple diagrams are always consistent?

            (If I remember the lecture correctly they actually ask this question about a thing they call “architectural structures” and then show “architectural views” as a solution, which are the views also used in the 4+1 diagram; but then again you can ask the question how to ensure that the 4+1 diagrams are always consistent)

            1. 2

              The good way is have some tool for that. Enterprise Architect and similar stuff can do it. I’m not sure if a tool supports 4+1 but lets assume there is one. The paper of Kruchten linked in the article clearly considers an embedded system. If you develop cloud software there usually not much of a physical layer. Maybe you pick an AWS region?

              Well, lets pick an example which should apply everywhere. The logical view is essentially class diagrams. The development view is essentially the repository/file structure. The consistency question is: How can we ensure that all classes we draw in UML also exist in the code and vice versa?

              1. I’d say the usual industry approach for consistency is to do it manually. Of course that never really works in all details but it is good enough for legal requirements.
              2. Generate code from UML.
              3. Generate UML from the code.
              4. Have tool support to update UML from code changes and vice versa. Allegedly IBM Rational can do that but I have never heard someone praising it.

              There are nuances and variants in these approaches. If you use C++, then you could generate only header files from UML.

              I guess the reason why your lecture does not provide a final solution is because there are many possibilities and it depends on the circumstances which one is best.

              Thinking of UML, we can be more specific and many tools have support there. For example, a tool could ensure that a sequence diagram only uses classes and methods which are modeled in a class diagram. The UI might only provide a drop-down menu with the modeled classes. This is what I actually had in mind by having a single model behind multiple views. The “data structure” here is an XMI file or a server database.