i started my logging journey with inline comments, then i moved to a more structured approach where i created one file for each task i was working on but that didn't scale as i often struggled to decide whether to write what i know in the log file or to continue with the investigations. switching contexts between the code and the logfile is quite expensive, you loose the momentum.
coming full circle, i now write logs with comments near to the code which they discribe. instead of writing plain comments, i start them with numbers and that way i leave markers for myself or someone else to build the mental model which i built during the investigation.
what the code does should be apparent from the function, variable and struct names. low level functionality should be separated out into functions so that when someone is reading a high level function, they have a choice of diving into details (i got that from clean code. there can be exceptions to this but generally i like this approach).
each function or logical block of code has a direction, it calls some
functions on objects, gets some data, operates on that data. there are
multiple ways of expressing this flow, not all being good. this commit
demonstrates it pretty well, instead of checking if (vUrls.empty())
and returning, we check for the favourible case and thus connect the
logical chain with the previous statement i.e. "get the urls" -> "if
not empty, open them all".
when written the bad way, it reads like "get the urls" -> "return if empty" -> "if not empty, open them all", there's redundent logic in this chain of thought.
software projects do not require the fancy bells and wistels during the prototyping stage but when they pick up some pace, it's a good practice to have a proper system for managing issues and testing new features. a nice readme and doxygen make it easy for others to read your code, understand it atleast from the high level and use it for their needs.
critiques are good, they help you improve, but not all critiques are good, and for those bad ones, one needs to stand for their opinions. these critiques don't provide any solid thing in their comments, just say "i don't like it", "i don't agree", "i am against it", or they use too many words which conveny almost nothing. good ones tell you "why they dislike the idea" and what they consider a better approach/solution.
the best solution for sleepiness is to yawn and have some water and continue doing what you were. you will notice that after some yawning you don't feel sleepy anymore. but this requires dedication for the work and an uncompromising attitude towards it and a "whatever" attitude towards sleep.
michael sthal told me this on the matrix channel when there were discussing about this new generation consuming stuff from videos and when i asked for alternatives he suggested that for languages and big tools like make and gdb, one should start with a 150-200 page book as that acts as a good tutorial to the language/tool. man pages aren't a good place to learn about how make works and how make macros work. so books and good articles can be the first place to gain the initial knowledge about the topic. once you are past that, you can experiment things yourself and look into the man pages and the info pages (specification) to learn more.
programming skills don't compound if you keep switching context on a daily/weekly/monthly basis. you have to do one thing for years to get good at it.
if you are able to sit for hours without any distractions then you have so much time and you get a lot of things done everyday. for minimising distractions, you can set separate times for checking chat/mail applications like before starting the work and after a long session of work.
this takes time and if you context switch after reading some part of code, you will miss out details which you would have noticed if you stayed for longer. externalization doesn't mean you can slack off more frequently, spend atleast a few hours continuously with the problem, or better not start if you can't spend a few hours without looking at the clock. when you are just there for the problem without any time constraints in your head and without any distractions, the problem reveals itself to you, be patient!
i used to think of objects in terms of parent-child relationships and that made it quite hard for me to understand what was going on. i found that thinking in terms of functionality helps as then you talk in terms of who has what functionality, the child has parent's functionality and the parent doesn't have child's functionality. this works also because code is always in terms of functionality and it's various subsets (parent/child) so you are thinking very close to what you want to write.
if the code footprint is large, it becomes hard to keep everything in the head. there are projects which last for weeks and months, so it's a good habbit to create a log file per project and add important observations, comments, change of plans, subtasks etc to it. one thing which i found useful was class hierarchies to depict parent-child relationships. this would help you retain what you already noted while exploring the rest.
just looking at the code is apparently not enough, or atleast not enough if you want to get things done in one lifetime. it's slow because the subconscious picks up small amount of data at a time and after a lot of iterations you all the sudden know what's going on. this is highly unreliable and often takes longer than any other approach out there.
instead one should speak out what they see verbally inside their head or literally if noone is around. this way one solidifies what they see in their head and within a few minutes or hours (if the problem is large) a mental model is built inside the head or on a logfile after which implementing stuff is not that hard as you already know the terrain.
small details like some comment in a bug report or an issue on github, or the message in the big stdout which tells what the error is. these are the most important details and these are often hidden away within large text walls, i see mike kaganski's point :). one needs to have an eye for such things, it's a quality developed with experience.
then there are small details in the code, things like one type being passed into other type, a type holding a reference to some other type. these things define the relation between various entities and thus should not be just seen and not noticed. this way you build the mental model of the code quickly and understand both the problem and the potential solutions.
proper planning is the most important part of any project, you keep track of the most important resource i.e. time. weekly milestones help with this, you know where you want to be at the end of this week and therefore you know how to spend the time you have. this way you are not shooting arrows in the dark and exactly know what the situation is.
another issue that pedro made me realize of (indirectly) was my habbit of jumping from one shiny object to the other. i should not context switch between chat and browser and code and should make a conscious effort to stay in one context for as long as possible. sticking with something for some time leads to compounding results, that "some time" in software is atleast 5 years.
this task required some css changes and i thought that it's a simple/easy fix and i was wrong! there is no easy or hard fix, some take less time and some take more. if one thinks of them in terms of easiness then there is a high possibility that one overlooks small important details like i did in this case, i added css rule for left border and didn't notice that it was overwritten just two lines below. small or large, tasks require equal seriousness and attention.
when pushing ui changes, it's very very important that we add the screenshots along with the change. that way it becomes very easy for the reviewers as they know what to look for while testing, often issues are directly visible in the screenshots, so the review-rework-push cycle moves quickly.