Having recently taken over a project with a LOT of legacy and bad practices in it, I'd like to lay out some general guidelines of using code as a means of communication and how to respect your craft and fellow craftsmen that have to work with and/or take over from you.
Why are software developers needed? Is it to write and maintain code?
I'd argue no.
Coding is a means to an end. Not the end in itself. It's merely the tool that we use in order to accomplish specific business cases. Without those business cases, there would be no need for developers.
If we had a medium that we could express ourselves better in, we would probably use that instead of code.
Our job is to bring order out of chaos.
To model the world in a way that is logical and unambiguous so that both computers and other people can understand what we are doing. If we miss those goals, we have failed as professionals.
Note that other people are a factor here. You are not just using the code to instruct computers but also as a means of communication between yourself and others.
The key to good communication is simplicity.
Neither the business nor your users care about how elegant your implementation of some fancy framework is, nor how many amazing design patterns you've used.
Your job is to deliver, to get things done.
Anything that prevents or prohibits that from happening is your enemy.
I'm not saying not to use a new, shiny framework or design pattern. I'm just saying that there should be a viable use case for it.
Your code will be read far more than you will write it so when in doubt, keep it simple.
Modelling the real world introduces it's own complexities and there's really no need to make things harder than they should be.
As such, here are some things I would've liked to instill into the people whose code I am now stuck with and often attempting to decipher.
At some point you will have to start defining data structures and have them reference and communicate with each other.
Have clear rules as to what is and isn't valid with regards to this.
Have the code flow logically and clearly.
There are many schools of thought here, but what I've learned that works quite well for me is to divide your system up into layers and modules that go from generic to specific. A module can communicate with another module on the same layer or a more generic one, but never a more specific layer. This helps you to clearly see what depends on what and if the business has more needs, you can easily build on top of your more generic layers.
Code is not your friend, despite how you may feel about it.
You might be super proud having written it, but it comes with a cost. Someone else (including your future-self) has to read it and understand it. It often creates dependencies on other pieces of code that now make the project that much harder to change.
If no longer needed, delete it. That's it. Don't be sentimental.
This is what source control is for. You can always go back and get it if a particular time comes that it's needed again, but chances are, it will need major refactoring anyway. Keeping it in your existing code base means that you have to keep maintaining pieces of code that aren't providing any value to you or the business. It will also increase the learning curve of anyone new joining the team.
Define specific patterns for doing things and stick to them.
"Oh, you need a particular setting for an instance of the website? It's here, you use this tool to insert it into the database and then call this service to get it into your code."
That's a nice experience right?
Now contrast this to what I'm dealing with now which is:
"Sometimes it's in this table, but other time's it's in this other table but it can also be in these particular files because some guy in the past wanted to create a domain specific language. Someone got annoyed with that however so it's also inserted into a config file and if it's not in any of those places then it's probably in this XML file that lives with the code now."
I have no issue with any one of these methods (I prefer the database whenever possible) as long as it's consistent. I have no issue with changing these things, but you then need to take the plunge and change it everywhere.
Use standards so that everyone is on the same page and it's clear what is happening throughout the system.
Introducing new design patterns / frameworks, basically multiple ways of achieving the same thing, adds to the complexity of the system and therefore the maintenance and learning curve.
I've often seen developers who learn something new and lo and behold, what a coincidence! The very next thing they get tasked with doing is the PERFECT place to try out their new toy.
Please, take a step back and properly understand what is needed instead of introducing something new for the sake of it.
Not everyone is the same as you. They might not be as clever, they might not be that interested in learning every single feature of the framework you have put into place. I find that the 80/20 rule works quite well in the frameworks and libraries I've used in that 80% of what I need to do can be accomplished with 20% of the capabilities of the tool in question.
I've met and worked with some amazingly clever and driven people. I've also worked with MANY people who I would describe differently. That's OK and it will happen.
I'm always reminded of the analogy of a mine. You have a few, highly intelligent engineers that plan how to do things and what should be done next and then you have a force of people that actually do the digging. They are both important. They both fulfill their roles and it might not be ideal, but sometimes you are going to work with people that actually don't care.
The unfortunate thing is, your company might hire people like this. Yes, they can get things done but it's not going to be all that pretty and well thought of. Using every clever design pattern and framework feature you can find will completely cripple them. Junior developers as well. It also increases the risk that they may not fully understand what all the implications are when changing something and potentially cause a really big problem later.
I've heard people argue against these things.
"Code should be self documenting" and "Documentation means you now have two places to update the same thing".
I agree with those statements, but they are guidelines rather than rules.
Commenting every line of code, stating what the code does is pointless and if this is necessary, then there is something seriously wrong with your code base.
However, commenting why a specific thing has been done in a certain way can save a lot of time, effort and pain for someone later when they cannot understand why you've done something a certain way. I'm not saying this has to go everywhere, and it's always a trick to know when someone else might need this but I think as a rule of thumb, take a step back and try see your code as someone who is reading it for the first time and ask "why?".
Documentation doesn't mean taking all the functions you are writing and drawing flow diagrams for each of them.
Concentrate on high-level views with important pieces of detail.
Integrating with a 3rd party? Great, document the URL's with the headers/schema's that are being passed back and forth in an event sequence diagram.
These types of things become unlikely to change over time and are not always clear as to who calls who, when and with what information.
By no means is this a complete list of everything you should do but these are the principles that have been on my mind the most lately due to my day-to-day dealings with this system.
Let me know what you think and what I've missed!
Happy coding :)