"Many years ago, I taught training classes for experienced developers who were learning new technologies (like Java). The disparity between the productivity of the students always struck me: some were orders of magnitude more effective. And I don’t mean in the tool they were using: I mean in their general interaction with the computer. I used to make a joke to a few of my colleagues that some of the people in the class weren’t running their computers, they were walking them. Following a logical conclusion, that made me question my own productivity. Am I getting the most efficient use out of the computer I’m running (or walking)?"
[0] https://www.amazon.com/Productive-Programmer-Theory-Practice...
That said I agree that "Typing Practice for Programmers" on "SpeedCoder.net" is a little silly. Just learn to use a keyboard (and learn to spell, that helps too).
Typing speed is never the bottleneck. You could double most developers' typing speed when they code and it'd probably have a negligible impact on their overall productivity.
There are benefits, but do they really outweigh the benefits of those same hours spent studying a data structure or design pattern or trying new tech?
Personally I choose vim for the exact reason you choose not to: that is I want the ability to edit files in any language on any system I touch with maximum efficiency. This accelerates my ability to try new languages because I don't need to rely on language-specific tooling. Also, vim has more longevity than many design patterns which are susceptible to obsolescence by new language features, and new languages themselves which have a half-life proportional to their age.
My typing speed and accuracy are both pretty low, when and if I correct that, I hope to have a similar efficiency gain as I did when I adopted clang-format since I won't be falling out of flow for mundane things like typos. Not every moment spent programming is equal, and in my humble opinion it really helps to invest in making your "special moments" more productive.
I've also been playing around a bit with Atom lately.
I recently got a new mechanical keyboard, which had special "layers" for punctuation. "Common" punctuation like periods and commas are still there, but other punctuation like curly braces, brackets, etc. require new key combos. [1]
I agree with you that a lot of the time programming requires modifying rather than composing, but not all the time. In particular, I blog in Markdown, which requires a certain amount of extra symbols that I wouldn't normally be typing. (Goes hand in hand with the previous point).
[1] You might be wondering, "Why get a new keyboard, if you're typing slower with it?" The new one is easier on my hands, wrists, and fingers, as well as being an actual pleasure to use.
Though I'm not a musician I assume it is similar to playing two different instruments.
I shrug and say I don't type enough to mind.
Cognitive overload. Shell commands with their args ... core syntaxes for half a dozen languages ... a couple base class libraries and 0-2 frameworks for each ... plus all your own abstraction/automation stuff on top? Admittedly this all used to be quite a bit simpler back in a sole "Win32-app world": VisualStudio+MSDN=done, no shell to speak of, no web layer / stack, One GUI Way, etc. But 15-20-years-ago ain't coming back for at least another decade.
_Use_decl_annotations_
PVOID
TraceStoreAllocateRecordsWithTimestamp(
PTRACE_CONTEXT TraceContext,
PTRACE_STORE TraceStore,
ULONG_PTR NumberOfRecords,
ULONG_PTR RecordSize,
PLARGE_INTEGER TimestampPointer
)
/*++
Routine Description:
This routine allocates records from a trace store. It can be considered
the TraceStore-equivalent of a calloc()-type interface, in that the record
size and number of records are specified rather than the total size.
The memory to satisfy the total size is sourced from the trace store's
active memory map. If sufficient space is available, allocation is simply
a matter of adjusting the relevant pointers and returning.
If the required size can't be satisfied by the remaining memory in the
map, this routine consumes the "next" memory map that has been prepared
asynchronously in a threadpool if one is available. If the prepared map
is not yet available, the allocation fails and NULL is returned.
N.B. This routine should be called indirectly through the TraceStore's
AllocationRoutine function pointer.
The total size that can be allocated is limited to the maximum size of the
memory map. The allocator is geared more toward lots of small allocations
versus larger ones.
Arguments:
TraceContext - Supplies a pointer to a TRACE_CONTEXT structure.
TraceStore - Supplies a pointer to a TRACE_STORE structure that the memory
is to be allocated from.
NumberOfRecords - Supplies the number of records to allocate. The total
size is derived by multiplying RecordSize with NumberOfRecords.
RecordSize - Supplies the size of the record to allocate.
TimestampPointer - Optionally supplies a pointer to a timestamp value to
associate with the allocation. When non-NULL, the 64-bit integer
pointed to by the variable will be written to the allocation timestamp
metadata store. This should be NULL if the trace store is a metadata
store, or if the trace store's traits indicates that it is a linked
store (implying that allocation timestamp information will be provided
elsewhere).
Return Value:
A pointer to the base memory address satisfying the total requested size
if the memory could be obtained successfully, NULL otherwise.
--*/ typedef
_Check_return_
_Success_(return != 0)
PVOID
(ALLOCATE_RECORDS_WITH_TIMESTAMP)(
_In_ PTRACE_CONTEXT TraceContext,
_In_ PTRACE_STORE TraceStore,
_In_ ULONG_PTR NumberOfRecords,
_In_ ULONG_PTR RecordSize,
_In_opt_ PLARGE_INTEGER TimestampPointer
);
typedef ALLOCATE_RECORDS_WITH_TIMESTAMP *PALLOCATE_RECORDS_WITH_TIMESTAMP;
typedef PALLOCATE_RECORDS_WITH_TIMESTAMP \
volatile VPALLOCATE_RECORDS_WITH_TIMESTAMP;
That allows me to include it in a public struct via: typedef struct _TRACE_STORE {
...
VPALLOCATE_RECORDS_WITH_TIMESTAMP AllocateRecordsWithTimestamp;
...
} TRACE_STORE, *PTRACE_STORE;
Basically I've resigned to living with the ugliest possible function typedefs, complete with SAL annotations and whatnot, at the benefit of much cleaner interaction elsewhere in the code, e.g. to call it I'd just do: Foo = (PFOO)TraceStore->AllocateRecordsWithTimestamp(
TraceContext,
TraceStore,
4,
sizeof(*Foo),
&Timestamp
);
_Use_decl_annotations is a life saver.Back when I was in Windows, the system was so robust that if the static analyzer reported on your code, it was your code that had the problem, not the analyzer. It did bounds checking, nullability analysis, and tons of useful stuff. It's fantastic.
The thing about NT-style pointer typedefs is that they discourage const-correctness: it's enough of a pain to make a PFOO. You want a PCFOO too? That said, I'd be more than happy to live with poiner typedefs if I got SAL back.
BTW, I also used a hacked-up cc-mode that understood all the SAL annotations and fontified them using font-lock-keyword-face. It worked great.
I've been contemplating doing a little project that scans all the SDK/DDK headers for SAL annotations in use and making a big cross-reference where you can, like, click on the #defines in <sal.h> and see all the places where there are real examples of it being used.
Some of the complex uses are really hard to grok just from MSDN documentation alone; I've found looking around at the WDK/DDK headers much more useful.
Unrelated question: why'd you leave Microsoft? Were you doing NT kernel development there? Is that what you've done in the past?
If you find yourself bottlenecked on typing while programming, it's a signal that you should stop what you're doing and write some automation or abstraction. Sometimes you can just structure a program so that it requires less typing --- almost always a good thing.
In the rare cases where you need to be verbose in source code, you can use build-time source code generation, or failing that, an editor snippet library. I like yasnippet for that purpose.
Back at Microsoft, NT kernel style requires a big doc-comment before each major function. (These comments are extremely helpful --- but that's beside the point.) The doc comment's style is a bit more complex than Javadoc; there are multiple sections (e.g., description, arguments) and specific indentation requirements within each section.
I found it very annoying to write and format these comments. Instead of just cursing doc comment writing all day, I took a week and solved the problem. I taught Emacs to highlight and indent these comments. I taught M-q to reformat paragraphs exactly as needed. I added code to automatically generate a skeleton description from the function prototype. And after all that, I was never bothered by the doc comment stuff again.
(Incidentally, in a big monolithic IDE, I think the barrier to this kind of extension would have too high to bother with, and I'd have been left cursing this code.)