What has changed over time are the constraints. Nowadays if you want to store a number you can just do so. NSDictionary deals with mappings. You can just serialise data out and back again. You don't need to worry about memory until a crash says you are using too much, at which point Instruments points the finger. You are unlikely to encounter most boundary conditions in your code (I don't remember the last time malloc-equivalents returned no memory).
Back in the "olden" days, storing a number required thought. 8 bit processors could often deal with 16 bit values, but beyond that you were on your own. You had to be very careful designing your data structures so they used the least memory possible. Saving data was unreliable. There were often no debugging tools at all. Some lucky folks had ICE[1] but most of us had to guess why the system hung. All this meant you had to get low level because of the constraints.
But you know back in those olden days we didn't have to have a comprehensive help system. We could assume users were proficient. We didn't have to deal with security and attacks. No networking. Undo was rare, and if it existed was a single step. Your code only ran in one human language. So while we did have to care about the low level implementation details of the code, we didn't have to worry too much about the rest.
The low level constraints are pretty much gone now. The tools are great. And you do have to worry about a lot beyond the actual implementation like usability, smooth animations (games had to worry about that in the olden days but in a different way), multiple languages, coordinating with other systems over a hostile network, attacks and a whole bunch more. I'm glad for all this, because worrying about fitting data structures and a framebuffer in 16kb of memory didn't make for a better app.
Being familiar with the low level is still sometimes helpful, but not that often. It is also a heck of a lot more complicated - eg compiler produced code is not straightforward and logical. Multiple levels of cache, cache policies, speculative execution etc make reasoning about data more difficult. The majority of the time it doesn't matter.
Right now the majority of mobile apps behave rather poorly if you have more than one device. In the future that will be a given. UI is more likely to be goal driven with the system figuring best practises for meeting the goals, versus nudging things by pixels as is done today. (Heck a user will probably do some combination of pointing, speaking, thinking and just plain old looking.) I'd expect a more functional approach where immutable states are the unit of an app, and new states are produced via interaction and external updates with the states syncing across everywhere relevant instantly.
Back in the "olden" days, storing a number required thought. 8 bit processors could often deal with 16 bit values, but beyond that you were on your own. You had to be very careful designing your data structures so they used the least memory possible. Saving data was unreliable. There were often no debugging tools at all. Some lucky folks had ICE[1] but most of us had to guess why the system hung. All this meant you had to get low level because of the constraints.
But you know back in those olden days we didn't have to have a comprehensive help system. We could assume users were proficient. We didn't have to deal with security and attacks. No networking. Undo was rare, and if it existed was a single step. Your code only ran in one human language. So while we did have to care about the low level implementation details of the code, we didn't have to worry too much about the rest.
The low level constraints are pretty much gone now. The tools are great. And you do have to worry about a lot beyond the actual implementation like usability, smooth animations (games had to worry about that in the olden days but in a different way), multiple languages, coordinating with other systems over a hostile network, attacks and a whole bunch more. I'm glad for all this, because worrying about fitting data structures and a framebuffer in 16kb of memory didn't make for a better app.
Being familiar with the low level is still sometimes helpful, but not that often. It is also a heck of a lot more complicated - eg compiler produced code is not straightforward and logical. Multiple levels of cache, cache policies, speculative execution etc make reasoning about data more difficult. The majority of the time it doesn't matter.
Right now the majority of mobile apps behave rather poorly if you have more than one device. In the future that will be a given. UI is more likely to be goal driven with the system figuring best practises for meeting the goals, versus nudging things by pixels as is done today. (Heck a user will probably do some combination of pointing, speaking, thinking and just plain old looking.) I'd expect a more functional approach where immutable states are the unit of an app, and new states are produced via interaction and external updates with the states syncing across everywhere relevant instantly.
[1] http://en.wikipedia.org/wiki/In-circuit_emulator