My comparison to waterfall was a reductionistic take on the specifications up-front before coding starts aspect. If comparing it to the full waterfall process then it is definitely a fresh take!
I miss the passive nature of the web. A page got loaded and then it was idle. Now I can stare at a page of text with my cpu spinning at 100% in the background, it adds nothing extra to my experience except for a quiet hum from the CPU fans
The TDD advocates I have been exposed to are mostly cargo culting consultants and this alone makes me very sceptical. It has some good core ideas but I find that in practice it leads to unit tests that are highly coupled to implementation details. Quick to execute but almost worthless from a test perspective. Its best to throw them out after the inital implementation is done since the usually just become a burden to maintain. Black box at system boundaries are the only tests that bring value long term in my experience. I would really like to hear more details about projects that use TDD and how they use it a few years down the line. All I can find are toy examples..
I don't like people saying just hello and expecting me to answer before they get to the point. If I see the message and immediately respond hello back then I have to sit and wait and watch the 'person is writing' indication until I get the the real reason they contact me. This time is just active waiting and can't be used for anything. In the situation where I see the hello at some later time and reply back the other person might not even be there. Should I actively wait or start something else and keep an eye on the chat, prepared to be interrupted? A lose-lose situation for me..
Yes definitely. But only reading the code and looking at the history can sometimes be enough to build the picture when the same names repeatedly show up in troublesome code
If you are working on an old code base for a reasonable time I recommend to get to know the old developers. Check out the commit history, who wrote what, talk with them a bit if they are still around to get a feel for them. After a while you will probably see patterns, guy A usually wrote solid code, guy B a bit more sloppy. If you are investigating a bug in a specific area of the code use git blame and start investigating any additions by guy B first
A variant of no 3 is used for some large scale telecom equipment supporting multi millions of attached users with serious uptime requirements. State is distributed and handled locally and replicated to a sibling node for fallback protection in case a node goes down. The replication is dynamic so new sibling relationships are established when nodes come and go. There is also some more persistent state (like billing information) that is used to recover in case of total node failure but a lot of the transient state can be rebuilt when users are forced to reattach
Agree with this. I obviously comment on bugs and also convoluted code that I know will be hard to understand later. If it is just small details it is easier to just change them myself when I inevitably have to revisit the code later on rather than nitpicking and arguing during the review. If I don't have to revisit the code for any change then just let it be. Out of sight, out of mind
Seems like a common theme with the explosion of new programming related projects. Everyone wants to be innovative, why check first when it's more fun to reinvent the wheel (now done in Rust :P)
One Chinese I talked to said there are two reasons that can play into this pressure. First reason is that the grandparents probably had the same situation themselves, they were raised by their grandparents, so now they have a urge to take the parent role themselves since they never were that close when their own children grew up. Second is the age aspect, they want to do this before they get to old and tired.
I notice that it's not uncommon for American recipes to be tied to a specific brand of sauce or similar. I don't see this as often in "European" recepies, here usually the recipe is broken down further or listing a generic ingredients, this makes the recipe more useful in contexts where it is hard to get "Trademark brand sauce", but of course you lose some precision in the flavor..
I love the C2 wiki! Such a nice collection of discussions and ideas. When I encounter some predicament or some ideas pop into my mind about a particular subject I always check C2 to see what they have on it.
Reading about reading code takes me back to when I came from the university as a young naive programmer to my first job at a multinational software company. The code base we were working in was huge and had been worked on by hundreds and hundreds of programmers.
I was only used to my own smallish programs, the sanitized examples code examples presented in assignments or tutorials or at worst a code base hacked together by a handful of students over a few weeks.
After the grace period at my new work I was given the assignment to add some new logic to an old piece of code. The code in question was a couple of modules adding up to a few thousand lines of code. The logic was heavy and tightly interconnected. I remember that it used exceptions as part of the control flow, I knew enough to know this was bad practice and scuffed a bit at it but in the same time I could see it was just not abuse out of ignorance, the control flow was kind of ingenious in its own twisted way. I tried to come to grips with it for a few days but it wouldn’t really fit in my head the whole thing. I was lucky to have a mentor of great quality, something as rare as and well accomplished academic turned to a pragmatic industrial programmer. I came to him and asked what I should do with this code. He said the code is mostly untouched since it was first developed some years ago, it has worked well and had only needed small touchups to fix some corner cases. He admitted himself had never fully took the effort to understand the code and he acknowledged that this assignment was given to me as a challenge of my abilities. He told me I should go and talk with the original author and so I did.
The originator of the code was an old programmer and he light up when I told him I was investigating his code. I could tell he was a bit sentimental about the work he had put in. He told me this piece of code did not come easily, it was something he had been spending months on to get right. The problem was a complicated and the code had the right to show some complexity too. We talked a bit about the high level problem and then I asked him if he could give me an overview of the code but to my surprise he said no. The reason for this apart from the time passed was that it was written in a state of flow when he had been engulfed in the problem. He needed the right context to bring it back and the context was not there anymore. I can respect this. It is one of the best programming experiences, when you in the flow and are programming at a complexity level that are just at the limit of your ability. When you finally get it all in place the details drain away quickly and there is a satisfying emptiness when the complicity dislodges itself from your brain.
He couldn’t give me any clarity in the problem at hand but he told me an anecdote about how hot code swapping in Erlang was a nice feature but he remembers how they used to do that in assembler way before Erlang was around. The way he talked about this cemented my view of him as a very clever programmer. I can always respect cleverness but it is not always what you want when you are handed down some arcane piece of code...
I went back to my mentor and explained that I was not much wiser about the code. He sighed a bit and told me “just stare at the code until it makes sense”. At the time I was not so happy about this answer. I interpreted it as a kind of brush off response to my predicament. Later I realized that this advice embodied a kind of zen like wisdom.
I went back to the code and did as I was told. For a couple of weeks I spent all my time with the code. I kind of blankly accepted the complexity. I scrolled the code up and down, jumping back and forth trying to puzzle the logic in my head. Advances was made in small increments as the logic slowly structured itself in my mind. Eventually I got in the flow and I made leaps of progress. I could see the point of the clever tricks my predecessor had left for me. I could tell he had enjoyed writing this code and it gave me satisfaction to unravel his thinking. This kind of programmer type is something I encounter infrequently; they should be admired for the accomplishments they can achieve when they are in the right state but also a bit resented for their masturbatory cleverness. Anyway, finally it clicked, I was on the bus or in the shower, I had finally accumulated all the information in my head and my background thought process had been churning away on it long enough. The code had become lucid. I did the code change and left some comments to try to help future challengers. [1]
Since that experience I have deciphered a vast amount of legacy code. There is always the satisfaction when you get the ‘click’ and reach full understanding. Unfortunately, I have never had a repeat of the exact same fulfilling experience as above. Sadly, most code is not an expedition into a ingenuous madman’s legacy, it is more like shifting through a heap of old accumulated cruft and accidental complexity. Complexity not in any way tied to the complexity of the problem domain, rather built up from a horde of opportunistic coding by generic programmers trying to solve their bug report before the go to lunch, no passion, no pride for the craft, no regard for the next programmer that comes along and trying to untangle the mess they build upon. No hard feeling, they do not do it to spite you, they have no sadistic inclinations, they just want to get their work done and move on. They do not see the bigger picture of technical debt and they do not share your ideals of sound programming practices. To give them a passionate speech about these topics will just leave you looking at a blank stare.
I have two pieces of advice when it comes to reading code. They seem a bit contradictory but they have been proven useful.
The first advice is that when you approach an unfamiliar codebase do so without judgment. It is easy to get offended by bad code left around. It is like seeing someone left a mess in a public space, the lack of decency and respect annoy you, you might try to picture the degenerate who did this in your mind and you get riled up. Instead see just see it as it is. The code might be convoluted because it is working around a problem that is not existing anymore. The abstraction might have made perfect sense until some ignorant programmer came along years later and did a quick hack that left the original abstraction looking half-assed. Or what is usually the case: a small fix upon a small fix upon a small fix. Each one making sense from an opportunistic perspective but together they make up monstrous complexity. Just focus on the logic and accept that superfluous complexity is unavoidable in a legacy system.
My second advice is that if you are coming back repeatedly to the same legacy code base then get to know the people who wrote it. If you see similar horrendous patterns or you find nuggets of slick quality code take some time and do some archaeologic investigation in your version control system to find out who the original author was. Later when you encounter more legacy code you can find the author and give the code a baseline of trust depending on what you have seen from them so far. This can help with the tricky code, if it was written by someone that warrants respect try to approach it again and understand why the trick is there, if a more clouded mind wrote it you can in most cases just assume the “trick” is ignorance and save you some time by just assuming you know the problem better than they do since that is most likely the case.
My advice when it comes to writing code is no surprise. Simplicity is king. Simplicity of implementation trumps all until proven the other is needed beyond doubt. Yes, simplicity of implementation trumps performance. Simplicity trumps abstraction and reuse. The thing is true simplicity comes from fully understanding the problem at hand and usually does not appear until after a few iterations of possible solutions. Cleverness is masturbation, simplicity is the hard part.
Push complexity away from the core. The Berkley approach is the way to go [2]. If you solve the complexity of your corner cases in the core of your program it might make the outer layers look slick but it is a false sense of simplicity. With a complicated core the complexity will seep out through all the outer layers even if they do or do not take advantage of all the features of the core. Yes, simplicity even trumps readability in this sense.
[1] I like to think I did leave some comments at least… comments are not easy to write when the problem is lucid in mind. If you have the discipline, write down the questions you encounter during your investigation, when you reach enlightenment go back and answer them and add this as comments in the code.