It is my impression that the vast majority of new developers, tend to underestimate the importance of design and implementation details as they struggle to prove that they can deliver a solution very quickly and please their managers with very tight deadlines.
A developer eager to prove his abilities, is focusing on things that are more tangible and visible to users, shifting his effort to the front end development, usually neglecting the quality of the code base.
Although this “Quick and Dirty” approach might be applauded in the early stages of the lifespan of a project, it will eventually create a chaotic environment. The system will not be able to adapt to new requirements, eventually reaching the point when a complete rewrite will be required. Such a rewrite is a very expensive process and there are many technological companies that went down because of it, simply because their competitors provided a better solution that became the leader of the domain.
Among other factors, creating successful applications with long potential life span depends heavily on the talent, the experience and the skills of the developer which are the topics of this posting.
I believe that a valid categorization of the skills involved in mastering the craft of programming can be found in three fundamental dimensions:
- Design Patterns
- Language Mastery
Each dimension has its own characteristics but all of them need to be mastered by someone who wants to become a good programmer. Maintaining a balance across these three skills dimensions will allow a developer to become an expert in his craft. It will enable him to come up with good judgment calls in design decisions and suitable for the problem implementations, that will be reflected in the success of the resulting application and its longevity and adaptability to unanticipated needs. Deep knowledge of algorithms, design patterns and language internals, provide the confidence to make correct decisions when trying to optimize the relation of software quality, cost of development and delivery timing.
Algorithms represent the Achilles heel of most of the programmers I have met. Since modern programming languages tend to hide most of the basic algorithms, providing build in functions for things like sorting, mapping and message queues, the programmer needs to have a good understanding of them to successfully select the proper solution based on the special needs of the problem. Even more than this, there are many problems which require the development of a custom solution, usually a variant of one of a standard algorithm and, thus, the programmer should be able to detect the optimal approach.
The good thing about algorithms lies in the fact that they represent a very mature knowledge domain, which will remain pretty much unchanged for the whole lifespan of the developer. In contrary to many other aspects of computing, its very basic elements (and algorithms is one of them) do not present the extremely quick evolution that tends to make large chunks of knowledge outdated within a few years. Once you understand and master an algorithm, chances are that it will not be changed any time soon, so you will not have to spend any more time constantly studying its evolution, so it is definitely worth the effort.
A developer should self-evaluate his algorithmic skills and spend enough quality time improving them to the point of mastering at least the basic algorithms, like quick and merge sort, queues and stacks, hash tables, graphs, strings and dynamic programming. It is true that studying algorithms is a little boring and more than this their application to real world problems might not be apparent at first glance, but it is also true that their mastery is what separates men from the boys when it comes to software development, and thus they need to be mastered by anyone who wants to become a top level programmer.
From the very early days of computing, the need for good design became very obvious. A focal point in the evolution of program design, was the notorious book of the Gang of Four “Design Patterns”, which summarized and gave an “official” name to several of the common patterns that were in use among the expert programmers. Today, having a deep understanding of design is one of the most fundamental parts of a senior programmer’s arsenal and having the ability to apply the most suitable pattern can signify the difference between success and failure.
I do not think I am exaggerating when I say that the main reason of failure of any project, can be found in its poor design.
The programmer needs to be able to foresee the future needs of the application, by selecting the most suitable design to allow for extensibility, while simultaneously avoiding over engineering, providing a platform that will be easy to understand, maintain and extend as time goes by.
Avoiding pitfalls like coupling with external technologies, limiting the adaptability to newer concepts, simplifying unit testing and continuous integration represent extremely important concepts that can be answered by the developer only if he has a very deep understanding of the applicable patterns and design solutions.
When it comes to his core language(s), the programmer needs to know them to a full extend and be able to write idiomatic code using the special style of it. A programming language is similar to a human language in the sense that in both cases exist several levels of expression ability.
Exactly like we have baby speaking in English we have the same in any programming language. Similarly, it takes time and education to covert from baby speaking to University professor level.
Also, as developers are moving from one language to another, they tend to retain some kind of an “accent” dictated by their native one and as in natural languages it takes time and effort to get rid of it and perfect your expressibility using the new one.
On top of the language mastery, the programmer needs to have a comprehensive understanding of the related ecosystem including the standard library and the open source components that are in common use.
Becoming a master programmer and developer is a time consuming process that requires a lot of study and dedication. The main dimensions of the required knowledge are algorithms, design and language mastery and the developer needs to have a balanced mix of them in order to be able to produce successful applications that will stand the test of the time.