Design Types

Read about the dimensions.

Introduction

In order to distinguish how developers think when making design decisions, one can distinguish four dimensions:

  • simple-vs-powerful
  • abstract-vs-concrete
  • pragmatic-vs-idealistic
  • technologic-vs-robust

These dimensions are described here:

Simple vs. Powerful

Simple

Developers with this attitude prefer simple solutions which are easy to write and to maintain.

The main idea is avoiding complexity. To prefer simple solutions means to implement only necessary and requested things without any frills. Simple code is easier to read, better to maintain, and cointains fewer bugs. Typical followers know about the power of simplicity. The key to handling complexity is not to master it but rather to avoid it. They prefer small and clear modules with few dependencies. They use libraries and frameworks if this makes the code easier to read and write and they don't use them if this only means that the reader of the code needs to know how all these libraries work. Explicit solutions are preferred to indirect, declaratrive ones. This means that simple solutions are not overly generic but they communicate the intent well.

On the other hand simple design tends to be less foresighted. This makes frequent changes and refactorings necessary. While this is not a problem for a single class, it may become one when interfaces to other teams are affected. Simple and explicit solutions often tend to be tightly coupled to requirements, used libraries and external dependencies. Decoupling introduces complexity (additional abstraction layers, indirect calls, etc.) but it also provides flexibility. This flexibility is sometimes underused by simple developers.

Simple developers typically follow the following principles: KISS, MIMC, YAGNI, RoE, and PLS

Rather disregarded principles for these developers are: GP and LC

Powerful

Developers with this attitude prefer powerful, flexible, and foresighted solutions.

The main idea is to create flexible and foresightes solutions. Generalized solutions can be applied for several use cases by just customizing or configuring them. Followers typically include flexibility and extensibility naturally into software design. Powerful developers like runtime configurability, powerful frameworks, decoupling, and the use of many design patterns. They think ahead and include thoughts on extensibility, performance, and portability into their design process. This keeps structures and interfaces stable and helps reducing effort imposed by changing requirements inthe future.

On the other hand powerful solutions take much time especially for their initial creation. Some of the flexibility might never be used so one could argure that introducing it was unnecessary effort. Powerful developers may tend also to get lost in providing flexibility instead of fulfilling requirements. Powerful code is flexible and foresighted but it is also hard to read and to understand. Furthermore complex and powerful solutions are more error-prone than simple ones.

Powerful developers typically follow the following principles: GP, ECV, IH/E, DIP, and LC

Rather disregarded principles for these developers are: KISS, MIMC, YAGNI, and RoE

Abstract vs. Concrete

Abstract

Developers with this attitude think in terms of abstractions and concepts.

Abstract developers always have the big picture in mind. They think in terms of abstraction layers, patterns, package dependencies, architectural constraints, etc. Structure is very important and abstract developery keep the structure clean and clearly arranged. Single lines of code are not impotent. You shouldn't look at a software system with a magnifying glass. It has to work as a whole and it can be understood as a whole. Abstract solutions follow clear concepts that are easy to understand and fundamental to the whole system. Followers have a very good overview over the whole system. Furthermore they are also able to give advice on consequences of particular changes. Often abstract developers also like having natural, requirements-based object-designs where the software structure mimics the real-world concepts. This can make understanding the code even easier and may lead to fewer code changes when requirements change.

On the other hand abstract developers typically don't like working with legacy code that has bad structure. They feel the need to understand the system as a whole and will try to refactor the code such that there is a clear structure. If there is time for that and the system will be maintained further, this is a good thing. In the other cases an abstract developer will feel lost and will be unhappy with making changes to that code which he doesn't quite understand.

Abstract developers typically follow the following principles: LC, TdA/IE, PSU, IH/E, SLA, MP, and UP

Rather disregarded principles for these developers are: RoE, ECV, and YAGNI

Concrete

Developers with this attitude directly think in terms of code.

Concrete developers directly transfer requirements into code. They are also good at working with and refactoring legacy code that they do not understand completely. They don't have to understand the whole system in all its details and they know that this attitude wouldn't scale either. As soon as a system has a certain level of complexity, one mind cannot understand it fully. Nevertheless a concrete developer can work quite well with such a system. When they refactor they heavyly rely on the boyscout rule. They improve code bottom-up rather than planning it top-down.

On the other hand concrete developers may overoptimize unnecessary details and tend to lose sight of the big picture. They may violate achitectural constraints and weaken the overall structure because thinking in terms of packages, layers and dependencies is not in their focus.

Concrete developers typically follow the following principles: DRY, HC, SRP, ECV, and OCP

Rather disregarded principles for these developers are: MP, TdA/IE, PSU, and LSP

Pragmatic vs. Idealistic

Pragmatic

Developers with this attitude focus on time to market.

The main motivation of such developers is to fulfill the requested requirements as soon as possible. It's the result that counts so tasks are only done if there is a valuable benefit. This approach prevents complexity and overengineering. Furthermore they can use the saved time to implement even more features and deliver benefit to the customer even faster. Followers do not like to reinvent the wheel and use templates, code snippets, etc. to avoid implementing everything by their own. This normally leads to faster solutions and success. Freed from technical or structural sensitivities followers of this dimension adapt very fast to any new environment, rules or specifications for example to a new team. They are also able to bring others down to earth and redirect them to the primary goal.

On the other hand pragmatic developers tend to neglect code quality. So while pragamtic developers are really fast at the beginning, they may be slower in the long run as maintainability decreases, bugs show up more often and the code gets less readable.

Pragmatic developers typically follow the following principles: YAGNI, RoE, KISS, and MIMC

Rather disregarded principles for these developers are: UP, GP, MP, LSP, IH/E, DIP, LC, HC, TdA/IE, EUHM, and IAP

Idealistic

Developers with this attitude prefer clean solutions.

The main motivation of these developers is the observation that while bad quality can be ignored for a short period of time, it is a serious threat in the long run. So idealistic developers like doing things either right or not at all. Idealistic developers care for the software they write and fight for it with all their expertise and professionalism. It is their job to fight this fight against the odds of deadlines, management, and project schedules. It is not enough to finish a project on-time. If the software dies shortly after the "successful" completion of the project, it is still a failure. Idealistic developers know that and will produce high-quality software that works even after the project managers have left for another project.

On the other hand idealsitic developers sometimes lose focus on the real requirements and on economical aspects. Software needs to be maintainable but in most cases it doesn't need to be perfect. Idealistic developers sometimes spend too much time on perfection. Furthermore discussions with idealistic developers sometimes can be exhausting and are not always productive. Idealsitic developers work well with others who think similarly but working with other developers who are also idealistic but rather different in in the other dimensions can become quite difficult.

A unique property of idealictic developers is that their idealism increases the advantages and disadvantages of the other attributes. So a simple idealistic developer will strive for perfection in simplicity and a powerful idealistic developer will create even more powerful software, etc.

Idealistic developers typically follow the following principles: UP, PSU, DRY, IH/E, furthermore being idealistic adds even more weight on the principles you favor because of the other dimensions

Rather disregarded principles for these developers are: YAGNI, and RoE although this heavyly depends on the other dimensions

Robust vs. Technologic

Robust

Developers with this attitude prefer stabe solutions which stood the test of time.

Software needs to be stable, maintainable, and robust. It's the responsibility of the software developer to ensure that the software has this qualities. Technologies come and go. Most of them are just hypes, just another magic cure for an illness which almost nobody really has, or just a variation of an old idea. Some of them are valuable and some of them aren't. When they arise it is very difficult to tell that apart. But sooner or later time will show what will survive, what can be safely adapted and what isn't even worth a try. New technology may be fancy and fun but often ist's not wise to adapt them too early. Even if they prove to be a good idea, in the beginning they will be volatile, badly documented and not well understood. Robust developers know about that, they are patient and only adapt those technologies which are worthwhile. This saves them time as they don't have to relearn everything every now and then and as the experiments are done by other people. This free time can be used to harden the software, to implement decent logging, monitoring, and exception handling. Robust developers program defensively, document wisely, and strive for homogeneous, standardized solutions.

On the other hand robust developers easily get left behind. They fear the future and rather stick to old and outdated technology. Thus they don't profit from what others already have achieved and do their own thing just as they've always done it. They don't like changing their ways of thinking and it takes considerable time for them to adapt to new working environments. Furthermore always thinking about what could go wrong, all the defensive programming, parameter checking, and exception handling take their time to implement and impose a considerable amount of complexity. To others they seem like the ones who don't evolve and slow down everything.

Robust developers typically follow the following principles: ML, EUHM, UP, RoE, and IH/E

Rather disregarded principles for these developers are: KISS and LC

Technologic

Developers with this attitude prefer technically advanced solutions.

Technologic developers embrace the fact that lifelong learning is an essential part of their job. Technology evolves faster and faster, new technologies arise, new methodologies become popular, and bad habits slowly die out. New technology can make you more productive and enable you to do things that weren't possible before. They can be your key advantage over your competitor. Technologic developers are open-minded for technological improvement and new ideas. Likewise they continuously try to improve themselves just like they try to improve their code.

On the other hand technologic developers risk riding the wrong horse. Sometimes they experiment too much, invest too much time in learning the wrong technologies and risk the stability and maintainability of their code. Although they are very creative, this ceativity may lead to unnecessarily complex solutions and especially to ones which are hardly understandable by those who don't know all the technologies used. Technologic developers need to play around and feel uncomfortable when they don't get enough freedom. They don't play it safe, they take risks. Sometimes they win and sometimes they lose.

Technologic developers typically follow the following principles: GP, LC, ML, and DRY

Rather disregarded principles for these developers are: RoE, UP, and MIMC