For all people out there who are keen to become a programmer or advance their career in the field of IT, I will present to you in this blog post what you need to learn/know to make this happen.
It might seem like an awful lot at first sight, but depending on your aimed part of the industry you probably only need to know some basic concepts of some, and deeper knowledge of some other topics.
Although this is just a mere view on some topics, as this industry is evolving quite fast, you cannot truly master anything really, and one of the most important skill then becomes the one of learning and adapting quickly.
Because of this I will shed some light on the technical and personal skills I deem necessary to become a good software engineer. Although this is only my perspective and I am open to discussion and other peoples opinions.
With that said, I present the items on this list like some mandatory set of skills but this is just for the sake of the presentation.
Remember also that this is not an extensive list, I appended an additional list with theoretical concepts at the end of the required technical skills, which could of course also be of high interest for (aspiring) software developers. I simply perceive the other ones as having a slightly higher priority.
Let’s start with the technical skills I think are required to become a skilled software engineer. This is deducted by my personal experience and on what I read on blogs and books:
- Multiple programming languages
- Automated Tests
- Contionous Integration and Deployment
- Source Control Management
- CLI and Scripting
Technical skills required to become a software engineer
With technical skills I mean that you at least understand the semantics but in most cases also know how to use the syntax as well as the tools that make your day to day work so much easier.
Multiple programming languages. This one seems like a no-brainer, as a programmer you need to know at least one programming language.
But you might ask, what does the knowledge of different languages give you? IMHO it opens up perspectives on how to handle things and shows different ideas and different think patterns.
With this I obviously mean not only knowing the syntax but being comfortable with actual programming in those languages. Which means using frameworks to solve given problems at hand.
When you start out this will of course not be the case right off the bat, but when you feel confident in one language, feel free to move to another language and you will see what good it does to you working with different concepts.
Besides different languages it might make sense to work with different paradigms. Which include object orientation, functional, procedural style and asynchronous programming. The last one is particularly important in the multi core environment we live in these days (see my blog posts on TPL for this).
If you are using .Net you get all of these styles free to go even with C# alone. (think of LINQ and such).
The next obvious choice is databases. This includes SQL but for the modern day also NoSql databases.
Databases are a huge topic and you can make a whole career out of it by only working with different databases and administering them. Still basic knowledge of setting up, operating and querying is absolutely essential for developers. There will probably no application without a data store. Maybe if you are working in frontend of an SPA you will not have the need to operate a database, still those concepts can be of high value to you. Think of indexing, joining data and other data optimization techniques.
We will first look at SQL databases. If you do not know any SQL I recommend one of the following books for a start:
To be comfortable around a SQL database you need to have in at least a rudimentary understanding of the following concepts (again this depends on your field of software engineering)
- Administrating a given database. This includes setting it up, creating dumps/backups and restores as well as advanced concepts like sharding and clustering
- Of course you will need to know the SQL syntax and semantics of the commands/queries
- You will need to know what ACID means and how it blends in with transactions
- Also you should know about the different NormalForms of SQL data design
- Furthermore you need to have heard of the object relational impedance mismatch (for starters, the relationship in a database is inverted to the ones of object oriented languages
- ORMs like EF/core and how they help to boost your productivity, but also what caveats they have
- Types of columns
- … and much others
The most important NoSql databases can be put in different categories: aggregate oriented, graph database, key value store.
An excellent book as an introduction on this topic is : NoSql Distilled.
Aggregate oriented are most useful in a clustered scenario. This includes MongoDB, RavenDB and others. Key values stores are good for associating keys with values of column families. You can look at Redis and Cassandra as industry standard key value stores here.
Last but not least is the notion of graph databases which excel at depicting relations between data.
An example for this is Neo4j.
Testing – Unit, Integration and Acceptance tests
I am an advocate of TDD (test driven development) and try to develop all the code I write in this fashion. I know that this is a style that not everyone is comfortable with, but on the other hand I never heard a good reason against it besides a masquerade of “I do not want to change my style”.(see my rant post here)
Besides that, automated testing gives you much more confidence in your code and makes the following topic of Contionous Integration and Deployment feasible. On how to write proper unit tests see the book The Art of unit testing.
Besides Unit testing (testing a function/method or a class in general) you also have integration tests, which isolate parts of the system and checks if they are working properly when run with spec similar to production. This includes orchestration of some components and different aspects. Yet this not necessarily includes the testing of complete workflows.
The next step then is acceptance test also called end to end tests which runs in a production ready environment and checks whole use case workflows and scenarios.
The names are not important here, some people would call integration tests what I call acceptance test. The main point I want to deliver is, that you need to know how you write automated tests for different scopes and interactions of your application.
Last but not least there are also load tests, which can be part of acceptance tests or be run in an isolated fashion. Here we simply create artificial calls to our application with different ranges to test how it behaves under load and if we need to improve the performance in different ways.
When you know all the things about the different testing techniques you are fit to proceed with the notion of Contionous Integration and Contionous Deployment.
Contionous Integration and Deployment
Continous Integration also includes the next topic of source code management systems so these two have the same priority for me on this list.
Continous Integration describes the topic of bringing everyone working on the same code base to the exact same state of the applications source code as fast as possible after changes occurred.
This is done by automatically applying different actions to the committed code. Those actions are called stages and build on top of each other. For example the first stage could be build, the next one then uses the build artifacts to create the application and run some tests on it.
All those stages need to be done with emphasis on automation. To evaluate if you are doing contionous integration you should ask yourself the following questions:
- Do you check in to mainline once per day?
- Do you have a suite of tests to validate your changes?
- When the build is broken, is it the #1 priority of the team to fix it?
This whole process is called a contionous integration pipeline and should be highly customized to the needs of your company/team and your application. If you go as far as deploying each change to production if the pipeline does not fail you, this is then called continuous deployment.
The benefit of this is not only shorter release cycles and the way your code is owned by the team but also improved quality and the confidence with which you can deploy your code because of the smaller steps, and smaller change sets in general.
For this to work you obviously need to know about integration tools like jenkins, build city and others. Also you will probably should be able to handle docker images and containers, config files as well as deployments to a given cloud platform. This again can also be handled by designated devOps engineers or the operations team in general, but rudimentary understanding of this principles should still be in the skillset of each modern software engineer. This is because you will need to understand how your version control flow and change management/feature management is organized.
Source control management
A modern software development project without a version control system is not feasible. This is the reason you need to know at least the most basic commands for the version control system your team is utilizing to operate. In most cases you will use git as a version control system.
Besides the syntax you again need to understand the semantics of it.
There is a lot to know about git itself and some of it is very abstract and from time to time it is very inconsistent (the CLI for example) and abstruse.
Yet it can be a considered something of an industry standard (if something like this exists in our industry) so you need to know at least the basic stuff like pushing to a repository, working offline, branching (probably the most important concept) and how different workflows are operated in your team (like gitflow).
I think this is a topic that everybody needs to know to a certain extent and this should not be underestimated for developer productivity. The best thing it is easy to learn (yet hard to master) and free to learn with git pre-installed on most OS these days.
CLI and scripting
Last but not least for technical skills you should be able to operate your OS and most other applications like github, cloud infrastructure and other things from the command line. Not only because this is way more flexible and faster to use than a GUI but also because it gives you much more insights in how things are working under the hood.
Also lots of things only can be done by using the CLI for some tools. This might also include the utilization of a unix OS like Linux or macOS. Even though you can emulate most commands on a windows OS. This is because most of the servers in operation and in cloud infrastructures are still unix OS and will be for the foreseeable future.
Besides using CLI tools, you should be able to use scripting for automation purposes with bash/powershell or a language like Python/Ruby/Perl. This works well with the idea of learning different programming languages.
There is so much about our industry one should know about, that I simply appended a list of other concepts which might come in handy quite often.
- networking/network stack:
protocols like TCP/UDP/HTTP
- How the web works
Http request/reply, headers, body messages
SOAP / REST
- Software design and architecture
Design patterns (Structural, Creational, Behavioral)
architectural patterns (tiered architecture, SOA, microservices)
- How to in technical documentation
reading and writing
- Big-O notation and time complexity
- Basic algorithms and data structures
sorting, trees and others
lists, linked lists, dictionaries, sets, etc.
Besides those technical skills that might seem overwhelming at first glance (especially for beginners) you can lack most of them at the start if you have the following personal skillset and find some mentors that are willing to teach you all of the stuff above with the right amount of patience. Still in the end you have to do it yourself and learn by doing it!
Personal skills useful for every developer
My selection of personal skills every developer should have to become successful:
Curiosity and an open mind to new ideas, opinions and concepts. With this two skills you are set to learn anything in any profession.
For software engineering this is especially important because our craft is somewhere between engineering and art. It has technical properties but on the other hand it has so much subtle difficulties which cannot be foreseen before implementing the actual system and seeing it work together.
Another aspect of this is accepting that there are people that may know more on a given topic than you do.
Enjoyment in puzzle solving. This is so important because puzzle solving can be frustrating at times, because neither do you know where to start nor where exactly it will lead you in the end.
This frustration is guaranteed to be part of your experience and you have to embrace it to become a very good developer because those are the days you grow as a developer and as a person.
Structured way to work. Software systems are complex entities and without a structured way to work you will introduce much more complexity than needed (accidental complexity). The easy way to do this is thinking before doing.
It also means to write down what you want to do and then reconsidering it when you have more information on how to solve an issue.
Learning fast and adapting quickly. This cannot be stretched enough. The software development industry is a young one and it is developing rapidly in terms of technologies to be used and concepts be applied.
Fast learning is an essential skill to keep up with the things you need to work on. I have never encountered a project where I did not have to learn at least some technologies (or go into much more depth than before). And from my personal view I hope this never changes because it is a lot more fun this way.
If you do not know already how you can learn things fast, take a look at my blog post on this topic.
Fun with collaboration is also extremely important and helpful.
There still is the association of the developer sitting in some compartment without any light and lots of junk food and coffee. This is obviously far from the truth. No really sophisticated systems where ever built without collaboration.
Being a team player brings you always far in life but especially in programming. Not only is it more fun if you tackle the problems at hand together, but also you built better systems, enjoy your work more and have a higher income in the long run ;-).
Fast typing is probably not the most important skill on this list (this is why it comes last) but still something worth being on this list IMHO. In the end typing is what you do most of the day to implement the code. It is your most important tool, and with faster typing comes faster implementation. This is no substitute for thinking but typing still can help you get a long way. There is a saying in germany: “Was man nicht im Kopf hat, muss man in den Beinen haben”
Which translates to:
The things you cannot be mindful about, you need to do with more physical effort.
Or: Things you do not have in your mind you need to have in your legs (fingers in this context).
Which means if you do not think before you act you need to walk twice (again: type in this context).
In this post we looked at different technical and personal skills I think programmers need to have to become successful engineers in this profession.
We started off with the following technical skills:
You ought to know different programming languages and paradigms to develop different insights for the way programming works and you solve problems in this way of thinking.
Also you must know databases and have rudimentary understanding of the syntax (SQL in most cases) and the semantics of how to operate on data and how to organize it.
Next up you will have to have some understanding of testing. This means you should be able to apply tests to different scopes of the application like unit tests, integration tests and acceptance tests. (pic of testing pyramid)
Continous integration/continous deployment and source code management systems are other big topics you ought to be comfortable around as a programmer.
Last but not least you need to be comfortable around the command line and especially with UNIX like OS.
As other topics we did not look at in detail but still are considered worth looking into, I assembled a small list with the following items:
– networking stack
– time complexity
– design and architecture of systems
– technical documentation
– algorithms and data structures.
Besides those technical skills one should have the following personal traits and skills at least to some degree to become a successful software engineer:
This includes curiosity and an open mind to different ideas topics and opinions. Software can be a very subjective thing in terms of quality (even though a lot of people will tell you their opinion is the only one that counts…)
One should find at least some enjoyment in puzzle solving, because this is what one often does with new code or even with debugging old code.
Also you need to have a structured way of working with problems to tackle and solve them efficiently and effectively
Because our industry develops as fast as the light moves, you must be a fast learner to keep up with the ever changing industry.
Sophisticated software systems are always developed with collaboration. This demands good team players.
One of the not so obvious things is fast typing, because this is your way to apply your craft (besides thinking clearly and in a structured manner).