Статьи

Некоторые из моих наиболее часто используемых мантр развития (1/2)

Утверждение: я предполагаю, что это работает так!
Мантра: предположение — мать всех придурков

Давайте начнем с этого короткого фрагмента из Under Siege2:
http://www.youtube.com/watch?v=wg4trPZFUwc

В этом случае его предположение имело довольно смертельный исход, который вы, вероятно, могли бы вспомнить, если бы смотрели фильм. Но, хорошо, будучи наемником, его ситуация может отличаться от ежедневного разработчика. Продолжая этот пример, вы, возможно, помните, что в поезде был компьютерный гудок, выполняющий такие вещи, как управление спутником. А теперь представьте, что вы тот парень и вас попросили запустить спутниковую связь. Вы быстро пишете некоторый код и при этом пишете следующую строку: 
i = i++;

Обычно мы пишем что-то как ‘i ++’, оставляя назначение.
Тем не менее, назначение кажется избыточным в большинстве. Мы предполагаем, что у него нет других побочных эффектов, и запускаем нашу программу. Но вдруг … БУМ! Сбой связи, Кейси Рэйбэк пинают его задницу (на самом деле, я бы хотел увидеть это), запустить ядерное оружие, и мир во всем мире далек. Наше предположение оказало довольно негативное влияние.

Хорошо, давайте посмотрим, о чем идет речь, и проведем небольшой тест.
Что вы ожидаете, что это печатает, у вас есть какие-либо идеи, почему это так?
int i = 0;
i = i++;
System.out.println("i:"+ i);

Пока вы думаете об этом, позвольте мне объяснить, что происходит. Как видно, у нас есть выражение, существующее из унарного оператора и присваивания. Как обсуждалось ранее, назначение является избыточным. Но помимо того, что он избыточен, он также вызывает неприятный побочный эффект. Это заставляет этот код вести себя иначе, чем можно было бы ожидать. Если мы отбросим присваивание (просто оставив ‘i ++;’), код точно сделает то, что, как вы думаете, он сделает.
What happens is that when using an assignment, the JVM will put the value of the operands on the so called operand stack before doing something with them. When the expression is evaluated, the value for making the assignment to the left hand variable is popped from the operand stack. That sneaky unary operator follows different rules. It uses the ‘iinc’ instruction. The iinc instruction takes as parameter a position in the local variable array of the current frame to put it’s value.
So, what happens is that «0» is pushed on the local operand stack. Next the variable «i» is incremented by 1 because of the iinc instruction. At this time the local variable ‘i’ would actually have the value ‘1’. We can’t show this in a normal way, since the assignment/expression is evaluated in a single step. When the assignment is made, it will pop the latest value from the operand stack assigning it to the variable ‘i’. This means that ‘i’ will be overwritten with the value from the operand stack, changing it’s value from 1 back to 0.
Note: when you write  ‘i = ++i;’ thinks will work as expected and the assignment is just redundant without side effects. In that case the iinc instruction is executed before pushing the local variable value to the operand stack. The rational is actually no different as when incrementing a variable in a method call; someMethod(++i) or someMethod(i++) . However, with an assignment it seems less clear that a pre or post unary makes any difference, because we tend to relate it to i++ or ++i on a single line where it absolutely makes no difference if the ++ is pre or post.
In nearly every line of code (depending on experience and knowledge) we take assumptions. This works out most of the time because some of the assumptions will be correct.  Incorrect assumptions do not necessarily lead to bugs as they might get balanced out by other assumptions. Or, maybe the side effects are never detected because of the boundaries in which our software operates.
A good way to track down incorrect assumptions in code is to write tests. But that alone is not enough. It is also  important to accept this rule. No matter how brilliant you are, there is always (a lot) of internals you don’t know or fully understand. One needs to remain skeptical, don’t be lazy. Always try lookup things as much as possible. Even in the case when there is only a little bit of doubt: look it up and/or make small test case. It does cost time and energy, but the ROI (being able to write working and high quality code) will be well worth it.
Statement: don’t worry, it’s only temporary!
Mantra: there is no such thing as temporary code

Agreed, a lot of things in life are temporary. The

 stock of Westvleteren 12 in my fridge is just one example. But in software projects, «temporary» tends to start a life on its own inflicting poorly designed or written code along its way.

This makes sense if you think about it; I don’t think anyone works with the same amount of energy or dedication if something is considered temporary. The problem is however that temporary code will become permanent before you even realize it.
An example I can share on this topic is a user management system which we designed for a previous project. The system was going to be a «temporary» user management system because the «permanent» system was delayed for some reason. I won’t go into detail, but the name of the software needed to reflect that it was temporary. So it was named TUM (Temporary User Management system). And you guessed it; in the end the system existed for years to come and over time became the one and only UAM. After a while it even became hard to convince new colleagues that the «T» actually stood for «temporary».
I’m going to put this a bit harsh, but «temporary» helps no one and gives developers a wild card to justify bad decisions, laziness or incompetence. In such situations chances are high that the design will not be what could have been and the resulting code will be suffering quality issues. So the rule is simple: always design or write code in the assumption it will stick around for quite a while. It will be beneficial in the long run as nearly all code will, in one form or another.
But make no mistake friends, no matter how dedicated or how good you are, the dark side is always waiting around the corner. If you are being tempted, simply ask the question how you would feel if your car mechanic decided to fix your brakes «temporary» because he didn’t have any idea at the time on how to fix them properly? Enough said I think.
Like most rules, there are exceptions. It would be naive to think that there are no real temporary software projects in general. Of course there are, and fundamentally it is no big issue if that would be the case. The important part is to keep this decision on project management level. Doing so one avoids infecting the team with it.
Don’t forget that in the end you’re never sure how temporary a project is going to be. And even if the project is really temporary, it’s code might still find it’s way to other modules or projects in the future.