97 Things Every Software Architect Should Know – Notes

Notes from the book “97 Things Every Software Architect Should Know

General

    • The conclusions we draw from experiences may not be entirely correct in the overall context. It is only when we accept our flaws that we open the possibility of improving. 
    • To get the most of the experience we have to rationalize it (free from irrationalities). The best way of working through it is to attempt to explain it to another person. You do not really understand something until you cannot explain it easily.
    • If our ideas and believes do not stand the test of a debate, then it is better we find out now than build on it later. 
    • Everyone can recognize and reject a bad ideas. It is the good ones that slip through and cause trouble with scope, complexity. “Good ideas” waste efforts on incorporating into the application something that is not necessary to meet the business need.
    • You need to be open to new ideas, tools, and designs that progress the project.
    • When you are talking you can only hear something you already know. Do not ever start thinking you are so smart that no one else has something valuable to say. Find a way to establish a good relationship with the business and do not let your ego damage it.
    • Better is possible. It does not take genius, it takes diligence. Diligence is an exercise in perseverance and paying the right amount of attention to each task and each architectural goal of the system.
    • Effective architects often follow mundane daily and weekly checklists to remind them of that which they already know academically, but fail to practice by habit.
    • Stand up to double your effectiveness of communicating ideas.
    • Criticism of your creation is not criticism of you.
  • Communicate goals and ideas in clear and concise manner.

Architect

    • Architect should understand the business domain, business problem, business goals and industry trends to design an effective architecture. (E.g. business domain: insurance vs finance markets, industry trends: on demand insurance, business goal: acquisition vs heavy online presence)
    • Architect must act as a bridge between the business and technology communities.
    • Creating bridges is a major part of being architect (see forward and backward, past and future, merge reality with vision, business and management expectations with development constraints, carry two ideas/thoughts, goals/visions, satisfy different stakeholders)
    • You should be able to use the language business, testers and programers use.
    • Human factor is important in the job of architect.
    • Listen to the points of pain and try to improve them.
    • If you design it, you should be able to code it. You need to have a feel for the amount of effort necessary to implement each element of your design. If your architecture depends on design elements that you have not personally used, there can be a number of negative side effects (do not know the learning curve, do not know the pitfalls, unnecessary risk)
    • Your ego can be your worst enemy. You do not drive the architecture, requirements do. You need the team’s help as much as they need yours. The model is only your understanding how the architecture should work.
  • Common sense (knowledge of what is reasonable within a given context) is the key in building architectures. It is accumulated through experience and education.

Human Resources

    • You are searching for developers with problem-solving skills and passion. You need people who are good at attaching problem regardless of the technology involved.
    • Ask to explain her approach to diagnosing a performance problem. This will give insight into her methods of problem solving.
    • Ask what she would change given the chance to start her most recent project anew. This will tell you about ability to apply lessons learned.
  • The architect must be familiar with different characters (types of people in the team) and ensure that the architecture has roles for all of them. (Dwarves, elves, wizards)

Team and communication

    • Architect is also a leader. As a leader, you must gain respect to build an effective and healthy environment.
    • Make sure developers have tools they need (software, hardware, infrastructure) and the development environment is efficient.
    • Make sure developers have the skills they need (training, or at least free events)
    • Open communication in the team is more important than technical aspects.
    • It is important to share big picture and reasoning with developers.
    • The team should feel it is part of the solution/decision, but the architect should chair the discussion and identify the right solution.
    • Let developers make their own decisions where acceptable within constraints and standards.
  • Keep criticism constructive and do not require that every solution look like it came from you.

Project Management

    • Often, an issue is identified by someone in the team early on but the majority dismissed or ignored it.
    • Track risks in the same way you track bugs. Review and prioritize when new information arrives.
    • Architect (not PM) should be responsible for the quality of the project and the delivery to the business.
  • If keeping originally planned timeline is not possible, try to move non-critical functionality to future releases.

Knowledge sharing

  • The most beautiful architecture/pattern/framework will only be reused by people who know it is there, know how to use it, and are convinced that it is better than doing it themselves.

Stakeholders

    • Discussing cost-cutting related to technology choices you need to be negotiator in the first place.
    • Initial reaction to a new system are less of a concern than a sustained negative reaction. Be aware of and measure the threat of acceptance problems and work toward mitigating those threats. Be cognizant of them and consider the reasons for them.
    • Start early having discussions with your end users about the new system and its real and perceived benefits and disadvantages. Use design of the system to address the concerns. Do trainings, system demonstrations, knowledge sharing. Select users that represent the user groups or stakeholders and give them your assistance in every way you can.
  • Make strong business case for architecture. Establish the value proposition. Build metrics to quantify. Link back to traditional business measures. Know where to stop. Find the right timing.

Requirements

    • Ask for the intended value of a requested feature to address the real problem (not what the customer thinks is a viable solution).
    • Avoid vague adjectives (“fast”, “responsive”, “extensible”, “flexible”, “maintainable”). Quantify the requirements. How many? How often? How soon? Increasing or decreasing? At what rate?
    • The most valuable requirement should be the driving requirement.
    • Facts and assumptions are the pillars on which your software will be built. Make sure that the foundations are solid.
    • Architecting is about balancing the technical requirements with the business requirements of the stakeholders.
    • Requirements should cover security, usability, supportability, release management, deployment options.
    • If your customer’s customer wins, your customer wins.
    • Software architecture requires a continual refinement of thought, a repeated straining of ideas until we determined the essence of each requirement in the system. We clarify our concepts, to make the relations within the architecture verifiability true, internally consistent. Reduce and reduce. Test statement by asking “would you make the same statement if I append always and forever and in every circumstance”
    • Reducing project scope often results in a simpler architecture. Simple architecture improves the chances of success.
    • Architect must understand the limits of value of the software initiative to the business (ROI)
  • Use technologies and solutions appropriate to the requirements (not what you want to use).

KISS (Keep it simple, stupid)

    • Solve specific problem. Do not overdesign.
    • Build the simplest thing that could possibly work. (Understand the real need. Divide and conquer. Prioritize. Deliver the results as soon as possible.)
    • Simplicity vs context
    • Architects and developers learn to enter problem solving mode immediately. But sometimes no solution is the best solution. See if you can change the problem. Ask yourself, what the architecture would look like if I did not have the problem.
    • Clever software is expensive, hard to maintain and brittle. Do not be clever. Dumb solutions are easier to implement and maintain. Each component can do only one thing. They inherit optimization from the building blocks. Less time to create and change.
    • Do not give in to the temptation to make your design or your implementation perfect. Aim for “good enough” and then stop.
    • Over engineering at the architectural level causes many of the same issues as it does at the development level, but the negative effects tend to multiply.
  • Keep it simple and do not over complicate. You may not even remember why you did what you did.

Tradeoffs

    • You cannot have it all. Every architecture has its tradeoffs.
    • A software architecture is about choosing the right tradeoffs between various quality attributes, cost, time and other factors. Document rationale behind each decision that is made, especially when that decisions involves tradeoffs (a vs b).
    • Consistency, availability and partition tolerance are commonly desired properties of a distributed system. It is impossible to achieve all three at the same time. Instead of treating these properties as religious artifacts, we should think about the problem at hand. Why must these properties hold? What benefits is to be had by doing so? When are these properties desirable? How can we break the system to achieve better result?
    • If you can only think of one solution to a problem, you are in trouble. Architecture is about finding the best solution for a problem given any number of constraints. Generally, tradeoffs must be made by choosing the solution that best satisfies the requirements according to the most critical priorities.
  • A useful approach for finding out how pragmatic or appropriate every option is, is to consider architectural decisions as investments and take into account the associated rate of return (ROI).

Changes

    • Architect’s role is ensure that change is manageable. Architect must understand the impact of the change. Change can be in many forms: functional requirements change, scalability needs to evolve, system interfaces are modified, people in the team come and go.
    • Architecture represents the significant design decisions that shape a system (measured by cost of change). An effective architecture is one that generally reduces the significance of design decisions.
    • Both business and software are living, moving entities. Business requirements change rapidly. This makes it very difficult to approach software project in the same manner as a traditional engineering pursuit such as bridge construction.
    • It is simply not possible to future proof an architecture. No matter what architectural decisions you make now, that choice will become obsolete eventually. Choose the best solution that meets your needs today. Anything else will not only be wrong choice tomorrow, but the wrong choice today.
    • No matter how well thought-out your design, it will never come out looking the same as in your head. Design is a discovery process, as we implement we discover new information that is often impossible to know upfront.
    • As you look back, you will always be looking at designs that do not match your current expectations. Learn to embrace the old stuff and resist temptation to get back and fix it.
  • There is a hidden cost to making quick and dirty fixes. For technical debt, interest takes the form of instability of the system, increased maintenance costs due to the quick fixes, lack of proper design and documentation and tests. If needed make the change but do not stop there.

Decomposition

    • Consider decomposition of the system by non-functional parameters.
    • Architect should be able to separate problem into smaller chunks. Important is that these problem chunks are stable. The problem chunks should be cohesive i.e. conceptually unified, so all of the tasks, data and features are related. The problem chunks should be well separated from other chunks i.e. there is little or no overlap between them. Stable problem → stable design → high quality.
  • The hard part is to find natural places to locate boundaries and define the appropriate interfaces needed to build a working system. Minimize coupling, maximize cohesion. Do not slice through regions where high rates of information exchange is required

Designing

    • Look for limits in the design that will occur when system scales. Whether infrastructure accommodates increases. How workload will be scaled across additional hardware and the transition paths.
    • Diagrams are a very high view, code is a ground view. Create an intermediate view based on the aggregated metrics from the code.
    • As architect your main focus is to sit back and really look at how the whole system fits together.
    • Arrangement of interdependent programs and their relationships are called architecture. Have a clear and detailed understanding of the relationships.
    • Enterprise patterns, application patterns, integration patterns, design patterns.
    • The real world is not quite that binary. The request can be canceled. Users prefer shallow interfaces (instead of one dimensional process logical to developers). Loosely coupled, asynchronous, concurrent systems.
  • Programming is not about building software; it is about designing software.

Documentation

    • When creating your architecture, you should explicitly use documented principles instead of implicitly leveraging your experience, opinions, and tastes. Easier to communicate, invaluable for subsequent architect, consistency throughout implementation and across time.
    • With each decision and rationale, document factors that contributed to the final judgement. This will make assumptions visible and explicit. It is critical to validate assumptions.
    • An architectural decision has been made when it has been put in writing (because architectural decisions are rarely trivial), and it has been communicated to the people who execute it and the people who will be affected directly or indirectly.
  • Examine the results of your decisions against expectations.

Iterative Development

    • One useful strategy for implementing, verifying and evolving an application architecture is to start with walking skeleton (a minimal end-to-end implementation of the system that links together all the main architectural components). Start with walking skeleton, keep it running, and grow it incrementally.
    • Great software is not build it is grown. Have a grand vision, not a grand design. Design the smallest system you can, help deliver it, and let it evolve toward the grand vision.
    • Lean development: Delay decision to the last responsible moment. The later a decision is made, the more information is available. The architect does not have to make the decision, he should be looking for decisions that will have to be made soon, and ask developers to come up with a solution.
    • Early deployment of individual components provide both higher commercial value and better architectural qualities.
  • Plan to deploy one component at a time. The technical risk is spread over time. It also leads to better coherence and looser coupling. (Cohesion is a measure of how strongly-related and focused the various responsibilities of a software module are)

User Interface

    • During successful use, the tools vanishes, the tool becomes an extension of the user’s body and is not experienced in its own. It becomes invisible, unfelt, insignificant. (pen) Does the user interface fall naturally to hand, or do your system keep demanding attention, distracting users from their goals.
    • Always be mindful of the impact of your decisions have on your users.
    • The architect should enlist the services of specialists such as user experience designers and usability experts.
    • The response time is not the only factor. Just as important are intuitiveness of the interface and number of gestures needed to achieve a business goal.
  • The success of the system depends on the content. Spend a healthy part of the design process to assess the value of your content.

Performance

    • Pay careful attention to performance.
    • The application performance and scalability is mainly determined by the architecture (not software brand or infrastructure).
    • Performance testing should start as early as possible.
  • Hardware capacity planning is important.

Maintenance

    • Maintenance will, in the long run, consume more resources than initial development. Shortcuts taken during the initial development phase can result in a significant maintenance costs later. Whenever you encounter an architectural problem or design flaw, insist that it be rectified now, when it is cheapest to fix.
    • Since 80% of application’s lifecycle is spent in maintenance, you should pay a lot of attention to the problems of support and maintenance when you are designing.
  • In production, it is hard to reproduce an error, the pressure to fix bugs comes from customers and executives, there is no debugger, deployments need to be scheduled and coordinated, logging level is low, support team has different skill set.

Failure

  • Everything will fail. Design system’s reactions to specific failures.

Data

    • It is important to build a solid database data model from day one.
    • You need to be able to build the entire application, including the database, as one unit. Make data and schema management a seamless part of your automated build and testing process.
  • Functionality is what we see first, but it is data that forms the core of every system.

Code

    • The main goal of a design specification is a working code.
    • If you cannot name it, you cannot write it. Design is all about trying to fulfill intentions and names convey intentions.
    • Important properties of the code: clarity (obvious role of components and classes), testability (easy to verify), correctness (no nasty fixes), traceability (being able to find and fix an issue for a person who has limited experience with the code)
    • Metaphor provide tangible/physical for abstract, complex or moving targets. Do not fall in love with your system metaphor – only use it for exploratory communication purposes. Do not allow it to slip into your system design.
    • Continuous integration (automated building and testing) is a must.
    • Duplication is evil
    • Repetitive work slows down development.
  • Design patterns are excellent tools for mitigating necessary complexity, but like all tools they can be misused.

Abstraction

    • Use the uncertainty as a driver to determine where you can defer commitment to details and where you can partition and abstract to reduce the significance of design decisions.
  • Generalization allows to reduce a problem to something more essential. However be careful because often generalization becomes a work item in itself.

Frameworks

    • You must choose frameworks that do not overlap and that are humble, simple, and specialized.
    • As architects we need to stay abreast of industry trends, but we do not need to be the first to embrace fledgling technology. There is usually no huge advantage to being the first to adopt new technology, but there can be several drawbacks. Before you try to use a new technology, ask yourself how business will benefit from the decision. If the best outcome is that no one will notice, rethink your decision. Wait for the hype to die down and see if the technology settles into a space of usefulness.
    • Leverage the diversity. Combining specific, powerful tools may provide more possibilities.
  • Trying multiple approaches might be the least expensive option.