In a project involving the creation of a new software library, the architect’s role is somehow similar to that of a product manager. The product is the library, and the architect may be in charge of maintaining the vision associated with this product. Reflecting on personal experience, this article exposes what an architect may expect while collaborating within a moderately sized team. I have found that, should one or more of these elements be missing, waste may occur, and product integrity may be compromised. Here’s the list.
1. Trust and Respect
The architect is in charge of the product’s vision – the API or library is the product. Other team members should trust and respect the architect’s work, assuming the following to be true:
- (a) The architect has sufficient expertise in the target domain to formulate reasonable propositions.
- (b) The architect has much more time than the rest of the team to consider, and direct the team towards, short to long term API development strategies.
- (c) The architect is defining functionality that will be at least attractive, and usually valid, from the API user’s point of view(1).
If a team member feels that (a) or (c) can be disproven, then they should raise the matter with their team lead or technical director.
If a team member finds that (b) is untrue, they should try to support the architect better, so they find time to do their job (see support)
2. Understanding good design
Good design doesn’t require locally perfect APIs, nor even striving towards a hypothetical, holistically perfect API.
Good design means creating an API with the following qualities:
- Fitness for purpose - If the API can be successfully used to do the job it is intended to, local flaws matter little.
- Consistency - It is often better to strive for consistency than to strive for local perfection.
- Timely delivery - While this may not always be critical, there are often operational goals associated with the development of an API.
Maybe the most essential point about good design is that there are always several, roughly equivalent ways to design a fit for purpose API. Further, few APIs partaking a fit for purpose library, if any, will be ‘locally perfect’.
Consistency requires giving up a little perfection here and there. Timely delivery occasionally requires taking shortcuts, deferring a re-factoring, or even endorsing what will ultimately prove to be a design of significantly lesser quality. Neither needs be a concern as long as fitness for purpose is not affected.
If team members understand good design and trust the architect – or at least, respect their expertise – they are ready to support API development. What does this mean?
To support API development means to participate in a team effort promoting good design, versus promoting personal twists and quirks. Here are a few things that a good team member will do:
- Review the design either with trust and respect, or with a degree of domain expertise matching that of the architect. If a team member isn’t interested in the overall design or doesn’t understand the product vision, they do not qualify as a peer (2), and therefore should defer to the architect’s design decisions.
- Situate implementation related concerns within a wider scope. A team member should discuss implementation related problems only insofar as such problems may invalidate the proposed API, e.g. by making realizing the desired functionality impossible (logical flaw) or intractable (lack of time), or by significantly limiting the performance of the resulting API (or that of a product dependent on such API).
A team member should not expose or discuss all implementation details to/with their architect. The architect won’t be able to do a good job if they spend their time learning and analyzing such or such detail versus designing the API and maintaining the development strategy.
- Respect the API coding style and semantics. Stylistic matters… …don’t matter. Consistency in naming APIs, whether using explicit or implicit policies, is, however, essential. Discuss stylistic matters at the beginning of the project if you can’t help it. Learn policies, either by reading them or looking at the specs, if you’re joining an existing project.
- Propose improvements, not cancellations – APIS are means to ends. Suggesting that an API isn’t useful may be OK if a team member genuinely understands the product vision and the library’s design goals. Otherwise, the architect should legitimately feel disappointed that they get no support from their team member.
- Attempt not to overload APIs – an API is built atop other APIs. The target product isn’t the sum of all its components. It is intended as a domain specific, enabling technology. If the API omits to set such or such parameter, it is quite possible that the implementation is expected to take care of this on a best effort basis – just forwarding additional, unrequited parameters risks exposing details better hidden from the API user.
- Know when is the time to discuss APIs – Whenever work pressure allows it, the architect will discuss both details and general orientations with other staff, within and without the team. The architect may be trying to assert feasibility, be concerned about timely delivery or just looking for advice; conversely, team members may feel that they have concerns about the API at any thinkable level. So when is the time to discuss APIs?
- Discuss once and only once. Moving forward requires ‘moving in the same direction for a while’ . Discussing things over and over reduces the chances that the library will be delivered on time.
- Re-discuss when and as new information is being uncovered. Agile API design is incremental. New information is likely to be discovered during this process. If a team member encounters new information that significantly questions previous choices, they must expose relevant evidence.
Ways to discover new information may include writing proofs of concept, deep thinking, testing APIs with code that uses them and other methods.
- Endorse and implement design decisions. Ultimately, individual team members may or may not feel happy about design decisions. So if a team member perceives a decision to be flawed against the architect’s or the rest of the team’s opinion, what should they do (see below for more options)? They should go ahead, endorse and implement either the requested design, or at least a proof of concept. libraries are code. Prove or disprove a design using running code rather than re-discussing issues over and over. Everybody makes mistakes; everybody is sometimes right against everybody else. The burden of proof is on running code.
- Commonsense. Unless an architect is extremely methodic and has a lot of time on their hands, they are likely to miss out details while drafting APIs. The API designer’s goal is to communicate enough about the APIs that they can be implemented by a supportive team endowed with commonsense. The architect will expect an implementer to fill in the details, not stare at the holes.
- Awareness. A team member should strive to keep pace with the developing API, not just look at things from their own, narrow end. Awareness allows a team member to support design by refining their understanding of the emerging product. Without awareness, a team member will neither acquire, nor retain peer status, therefore may no longer contribute to design discussions, and may misunderstand the intent behind APIs pushed to them.
Even if a team member does not wish to involve in the design process, they should keep a reasonable degree of awareness. In this case, consider awareness a natural extension of commonsense.
Within an API development team, collaboration means at least two separate things:
- Help each other work faster by learning each other’s code and promoting code reuse.
Share code; share advice; share knowledge. When an API becomes large enough, opportunities for sharing and reusing code naturally multiply. While the architect may anticipate such opportunities, modeling dependencies internal to an API implementation is not the primary role of the API designer. Team players quickly detect opportunities for reuse, for example by reviewing each other’s code.
- Non-competition. The team must strive to build the library together. There are various ways in which team members can drift away from this goal.
Team members may develop frustration over time because the wider goals of the API and library development process stifle their individual creativity.
Such or such team member may favor a utility library over the team’s choice…
Team members may develop an alternative vision while developing awareness…
Non competition means that, before asking oneself ‘Can I do this better than what the spec/implementation design says?‘, a team member should ask themselves: ‘Will my choice promote our success‘. A team member may feel that deviating from the team’s choices and re-writing existing libraries signals excellence. Unfortunately, the better is usually the enemy of the good in this case. Even moderately large libraries require canvassing and compromises.
5. Knowing how to say NO
Finally, what should a team member do when they disagree with the team and/or the architect?
- Disagree, once and only once – Team members should explain why they disagree. This may often help shift or correct the team’s decision. Once and only once also means that, once a general direction has been agreed, it is not OK to re-discuss this orientation while dealing with every instance of the general case.
- Apply deference and trust. This is a simple rule that may be more difficult to apply from a team lead’s point of view. If the team lead and the architect are not the same person, then the team lead should normally defer to the architect, unless they combine peer status with authority.
Whenever the team lead overrides or denigrates the architect’s decisions (beyond seeking consensus), they are practically undermining the architect’s role. This can be OK from time to time if the team lead is actually right. Otherwise – or simply if it’s impossible to figure what’s right or wrong – this will likely lead to the architect being forced to step down. Why? Not only because this makes it hard for the architect to do their job, but also because, from the architect’s point of view, continued disagreements with the team lead can lead to managerial action against the architect.
- Get help from above - Get help from somebody who cumulates peer status and, roughly speaking, experience above or at the same level as, the architect’s. Getting help from above is only meaningful if a team member feels that they are addressing a critical / major issue that will compromise ‘good design’ as described in (2). Not everybody senior and experienced considers clearing misunderstandings and nit-picking as a valuable use of their time.
The architect is not mandated to validate all of their decisions with a senior, more experienced staff. First of all there might not be such a person around. Should there be, the architect won’t be doing their job if they have to routinely rely on external advice. Regularly asking your architect if they have discussed this and that with such and such senior staff evaluates to questioning their competence.
- Avoid sarcasm, irony and bad omens. Agreeing to something while promising it will lead to disaster or waste is not just promoting bad mood in the team, it is also irresponsible. If a team member has serious issues with the team or the architect’s decisions, they should appeal to a senior (e.g., technical director) and, ultimately, defer to their advice.
Right – I don’t think this stuff is too original, and I suspect a lot of it applies to team work in general, not just API design or the architect’s role. If you’re having trouble understanding what’s going on in your team and suspect there are little grains of sand between the cogs and wheels, I hope this helps.
(1) Depending on the library’s target audience, different constraints may define what is an attractive or valid API. Writing an API for a casual PHP developer does not generate the same constraints as writing an API for financial banking. What is essential to financial banking programmers may be unthinkable for casual script writers.
(2) Several points in this article depend on understanding so called ‘peer status’. Peer status (in short, having expertise relevant to the design problems underlying API design) is not a global property of a team member. Peer status is more like a variable – Whether a team member is competent to address a design problem should often be considered on a case basis.