This post is not about software engineering principles or why good practices should be observed. I take those vital concepts for granted. It is about why some trade-offs should be considered where some objectives may compete against each other.
Time and space complexity are always to be considered while designing an algorithm or even writing a chunk of code; thus, both complexities may be embraced in one concrete objective: (1) to minimize or at least approach the best conceivable run-time and space.
Skilled developers tend to, hopefully, follow guidelines like completeness, expect unexpected input, be flexible with others while strict with yourself when implementing APIs, etcetera. Objective (2) can be defined as complying with well-grounded guidelines.
Each project has characteristics of its own. Some born as a minimal viable product and scale up fast either in team size and features to be developed. Other ones are subject to big staff and decision changes. Whatever the reason, projects are more like living than fixed things.
Under the weight of quotes like “swim or drown”, project managers usually add some objectives of their own, like (3) deliver fast, and (4) specify the features so they will cover the actual needs, but keep future expansions on sight to enhance benefits as the project evolves.
Like in tug war game, but with many teams playing at the same time and each one to their direction, one step closer to an objective may be detrimental to other objectives.
Distinct actions and attitudes may greatly impact the objectives summarized below. The following table cells are populated with 👍 and 👎 depending upon the effect being positive or negative. Empty cells mean that effects are not so deep, even when impacts may exist up to some extend.
Objective 1: keep complexity under control
Objective 2: follow guidelines
Objective 3: deliver fast
Objective 4: evolution
|Exemplifier actions and attitudes||Objective 1||Objective 2||Objective 3||Objective 4|
|Cut-off the nonessential||👍|
|Leave features specification open for further expansion||👎||👍||👎|
|Simplify features to speed up deployment||👎||👍|
|Keep an open mind about project goals||👎||👍||👎||👎|
|Perform stress tests||👍||👍||👎|
|Deploy to a beta tester user base||👍||👍|
Readers are more than welcome to disagree and, if you are one of them, please leave a comment or contact me.
How should a good trade-off look like?
Coding joined to management may be seen as a multi-objective problem. Algorithm and frameworks are designed to solve defined problems. Variations on the problem’s definition may affect the solution’s performance or turn a good solution into a future obstacle or limitation.
Designers and developers seek to find advantages in patterns and data characteristics to come up with an efficient and maintainable solution to complete a task. While open definitions and oversimplification look like a solution at managing level —precision takes more time and effort—, it can be the death sentence for optimizations.
A project with well-defined boundaries and features eases the developing of fine-tuned code tackling complexity and resources in its different aspects. Nevertheless, the optimal code does not suffice for itself for a project to be successful. It needs to be ready at the right time with the available means.
Trade-offs are not meant to fulfill everybody’s expectations. On the bargain, each side must clearly state their needs and numerically define basic and desired thresholds.
Remember that sides are not enemy armies, one person may stand on more than one side when performing more than one role. Thus, the negotiation should truly be in the benefits of the whole project, allowing it to be birth and to be maintained in the long run as well.