Hopefully everybody is already familiar with what the terms strategy, tactics & logistics really mean. If you you're not 100% sure then read Strategy, Tactics & Logistics (in fact best skim through it even if you do think you already know).
Before I start there are two things I want to point out right from the off:
So, before we go any further there is one other thing we should do, which is to broad-brush what these terms mean¹ [1Just in case you ignored the guide with the detailed meanings.]:
You may reasonably be wondering why this matters. If you're already thinking about these things then why can't you just go off and read something else? This is a mistake.
When you're thinking through an problem the more ways you have of framing your thoughts and decisions the more likely you are to get a good solution. If you can only frame your thoughts in one way then the chances of you avoiding all the pitfalls isn't is high as if you can frame your thoughts in many different ways and on many different levels.
What's the difference between
p++? If you know what you're doing you'll already be using the first when incrementing loop variables (at least of iterators in C++). This is an example of logistics at work. At heart logistics are those things that always work to make programs better, smaller and faster.
The scope of these decisions is generally a few lines of code or the choice of a data type for a single attribute. Normally logistical questions have a single answer that is optimal. When you hear somebody say “That's an implementation detail”, what they really mean is that, for them at least, they consider it a logistical item and there should be a single optimal answer.
The nice thing about the logistical part of the problem is that this is the part that computers are good at. Every year that goes by more and more logistical matters are dealt with entirely by the compiler or language.
The fact that there should be an optimal answer doesn't mean that the answer is always easy to find. Sometimes you can get away with a good enough answer and not worry too much about it. That depends on the context though and that leads us on to tactics.
This I think is the area where things are most interesting. For example, whether you should implement accessors directly, or abstract them into helper classes is a tactical consideration.
There are thousands of these techniques that every master programmer knows and just as importantly they know when to apply them and when not to. Do you solve a problem recursively or do you convert the algorithm to a loop?
Tactics are by their nature situational. If you apply them in the wrong situation you get errors at worst and poor software at best. Apply them in the right situation though and you can build elegant software that does what it is meant to do with a minimum of problems.
The journey to being a master craftsman in software development is to learn as many of these tactical plays as you can and then to master the situations you should use them in. This means trying them all, not just repeating the one that worked last time.
Many of the rules that we come across in software development fall at this level. This is why we need to understand the rules in order to write better software. Merely following them will probably be OK, but if we actually understand what is behind the rule we can see the situations that the tactic doesn't work in.
These are questions to do with structure of the program. They are your plan for the approach you will take.
Here you enter the realm of strategy. In many ways strategy is woolly. But if there's something that you're thinking of before you start to code then it's probably strategic.
If you know a lot about databases, but nothing about web services then a framework that takes the tactical and logistical issues of HTTP out of your hands and can build HTML forms is your best strategy. If on the other hand you know nothing about databases but everything about AJAX then use a framework that makes the tactical and logistical issues about database communication, transactions and SQL statements for you.
Neither of these will make the best tactical or even logistical choices for you, but they will both give you better results than anything you'll be able to come up with no matter how agile your development process.
There is a deep point here and that is that the ability of you and your team matters and is an important input into what problems you can tackle, and how you should tackle them. If the problem looks intractable to you then it probably is, but that doesn't mean it can't be solved by somebody else. If you've never tackled a problem of a certain nature before then diving in is a good learning strategy, but a poor strategy to use when the system has to work.
There is also a correlation here with Frederick Brooks' notions of accidental and essential difficulties² [2No Silver Bullet: Essence and Accidents of Software Engineering]. His essential difficulties revolve around formulating the strategy for the development process, whereas the accidental difficulties are the logistical problems. This leaves the tactics out of course. They're the bits that we hope will become logistical with the aid of better tools, but no matter how hard we try there are always going to be strategic issues that need intelligent input.
Better frameworks, better languages and better understanding will help to move problems from strategy meetings, to tactical worries and on to logistical answers. The supply of strategic problems is of course infinite and no matter how good our tools and understanding gets there will always be something new that will require us to develop new strategies, work out how to make it tactical and then throw it into a new language or framework so it's logistical. This gives you time to start thinking about strategy for the Next Big Thing™.
Remember that if you know what the input data is going to look like then you can move things into the logistical arena that somebody writing more general software would have to leave at the tactical level. This is true for all levels. The better we understand the problem domain, the system inputs and how it will be used the more we can push from strategy to tactics and from tactics to logistics. Each problem must still be weighed and judged on its own merits.
I've been wondering whether, for software development at least, it isn't possible to formalise these three levels somewhat.
I'm not saying that these levels will be immune from considerations about the specific problem domain. If you know what the input is going to be before the software runs then you can move tactical issues to logistics that a developer without that understanding can't. I don't see that this affects the formalism at all.