Use mature, well established technologies to avoid pouring time into fixing things that aren't related to what you are building. Asses technologies as objectively as you can based on your requirements. Avoid packages that evolve too frequently.
On my journeys as a developer, I've come across teams that have consistently failed to deliver sprint targets, and products that failed to deliver many things of use to end users. Getting to the end of a two week sprint and proudly telling the product owner that the sprint was a success because the development team re-wrote the database access layer of the application with zero impact on the end user, is not going to be well received.
This was often because of poor technical decisions that resulted in the development team's focus moving away from actually delivering features, to fighting with frameworks and technologies that either did not fit in with the application or were simply not mature enough to be used yet.
Go for maturity over modernity
Developing for the web is a fast moving area of technology, and as a result, there are many competing technologies that essentially do the same thing. Take a for example, a server side web framework. There are lots of well established web frameworks out there, but for various reasons, we keep inventing new ones. This in isolation, is not a bad thing - it gives us an opportunity to consider new ways of doing things.
However, it becomes a problem when development teams adopt immature technologies, or technologies that are not suited to what they are doing, and attempt to deliver something that has to run in the wild. Take for example a standard problem that us web developers have to deal with - Cross-site request forgery. Any public facing website that takes user input must have measures in place to counter act the threat of Cross-site request forgery. In established frameworks like expressJs, this is trivial, and can be implemented in about an hour. In an immature server side framework, you'd likely have to spend days putting together your own solution to guard against the threat of CSRF. These are days that could be spent working on actual product features.
You don't have to follow the crowd
In software development, we regularly hear about new technologies and associated success stories. A good example would be NoSQL databases. In the last decade or so, we've seen a shift away from traditional Relational Databases, and a pivot towards document databases, like MongoDB.
MongoDB has it's detractors (here and here), as well as it's evangelists. When picking a technology to use, we ought to be making some suitability assessments. For example, if we were considering using a NoSQL database like MongoDb, we should be asking ourselves the following:
- Is my data really unstructured? Will all of the documents contain different fields?
- Are there really no relationships between documents?
- Was I hoping to use something like mongoose, which puts a schema on top of a schemaless database?
If your answers are no to any of the first two, or yes to the last one, then you should consider a well established relational database like PostgreSql, which will be easier to query structured data and even supports unstructured JSON data.
Forcing structured relational data into a schemaless database will result in technical debt in the form of clumsy to write and slow to execute database queries.
If you are worried about tooling, don't be! There are plenty of open source packages out there that can help you with migrations.
Avoid packages that go through big api changes regularly
As I mentioned earlier, web development (especially anything happening on the front end), is a fast moving area. This can lead to problems when package maintainers re-write APIs, or deprecate parts of an API in favour of some new API calls. If you are consuming a package like this, you will get pain when you need to make an adjustment, as you'll probably need to re-write all of your config files.
Take for example migrating webpack from version 3 to 4:
- More packages were added
- Some packages were removed
- Some packages were deprecated
- Some packages need upgrading in isolation
Or migrating babel from version 6 to 7, which is so complex that it needs a nearly 2,500 word guide.
Even if you aren't upgrading the package, you can get pain when you need to make an adjustment. This is because any research that you now do will throw up additional noise - the way of doing whatever you're trying to do in the old version of the package, and the way of doing it in the new version of the package.
Understand that cloud service before you use it
Any mistakes made when opting for proprietary cloud services can be costly from a billing point of view, can tie you into a platform, and can give your end users a bad experience. Looking specifically at databases, the cloud providers offer plenty of managed solutions. Some are slightly adjusted versions of standard database technologies (e.g. Azure Sql Database), and others are more heavily adapted versions of existing technologies (e.g. Amazon Redshift, which is not to be confused with Amazon RDS).
An example of a mistake here would be plugging Amazon Redshift directly into a web application. It's really not what the service is for - but you'd need to do your research to find this out.
Even if you get something working, it's better to realise your mistake early and to throw those mistakes away before they start hurting your users, and you become to wedded to the underlying technology. The cost of correcting a poor technical decision will get more expensive as time goes on, so the earlier the better.
Developer convenience is important, but the product and it's users are more important
A complaint I see often is that we as devs focus on our own development experiences instead of our user's experience. Here I'd say there needs to be a balance. The developers need to have a good, friction free (any of the previous mentioned points can be sources of friction) experience when they are developing so that they can deliver features. But the users also need to not be burdened with the mistakes of any poor technical decisions that have been made (such as using the wrong database technology, resulting in application slowness).
Strong technical leads are important
I would expect that a strong technical lead would be able to find the balance between developer happiness, and product owner and user happiness. A good technical lead will put a development team on a platform that keeps them productive, which in turn keeps the product owner and users happy as working, tangible features that they see will get delivered.
To summarise, a good technical lead will:
- Listen to and support the development team
- Listen to and support the product owner
- Asses technologies with the application goals in mind
- Deliver features