Marcel Weiher writes about programming language design, Objective-C and Swift, software architecture, and performance, drawing on long experience with Apple platforms.
HN commenters point to his work on storage combinators and critiques of Swift syntax and compiler direction, and some argue with his architecture views.
The very nature of what we do is so different. We have so many more interactions with so many different libraries & technologies than we used to have.
I'm missing some of the other good recent discussions, but there's a core idea I love & think is true: that modern software dev is much more about "glue" code, about combining existing libraries, services, systems. Some recent pieces: https://www.oreilly.com/radar/thinking-about-glue/ https://blog.metaobject.com/2021/06/glue-dark-matter-of-software.html
By comparison, software dev used to be a purer act of raw artifice: I remember we had our db.perl & db.php at the little webshack I started at. We authored/maintained/grew it, and it was just our little library of helpers, totally independent of the rest of the world. Imported across the dozens of properties we webmastered. That's how software was! Independently developed, owned, & operated. Now, there is much assumed context, countless tools & technologies in play in every situation. Rather than big levers, we adjust large systems, or graft on new sub-machines.
Perl, in my mind, was the real starting place, the pivot where open source let us start to consume each other's code rapidly: CPAN was a great early way to start finding & using code, rather than writing it yourself. Since then, online package repos have only increased.
And some years after that, hosted services started growing in popularity. Cloud platforms started emerging. Rather than being a master-crafter…
My remark was just an old Java joke I repurposed for Ant!
"Java is a DSL for taking large XML files and converting them to stack traces." -Andrew Back
https://www.reddit.com/r/programming/comments/eaqgk/java_is_a_dsl_for_taking_large_xml_files_and/
But in all seriousness:
OpenLaszlo used XML with embedded JavaScript in a way that let you extend XML by defining your own tags in XML+JavaScript. I've done a lot of work with it, and once you make your peace with XML (which seemed like a prudent thing to do at the time), it's a really productive enjoyable way to program! But that's more thanks to the design of OpenLaszlo itself, rather than XML.
https://en.wikipedia.org/wiki/OpenLaszlo
OpenLaszlo (which was released in 2001) inspired Adobe Flex (which was released in 2004), but Flex missed the point of several of the most important aspects of OpenLaszlo (first and foremost being cross platform and not locking you into Flash, which was the entire point of Flex, but also the declarative constraints and "Instance First Development" and the "Instance Substitution Principal", as defined by Oliver Steele).
https://en.wikipedia.org/wiki/Apache_Flex
https://blog.osteele.com/2004/03/classes-and-prototypes/
The mantle of constraint based programming (but not Instance First Development) has been recently taken up by "Reactive Programming" craze (which is great, but would be better with a more homoiconic language that supported Instance First Development and the Instance…
Indeed, one of the articles cited by the article that this discussion is about (https://blog.metaobject.com/2020/11/m1-memory-and-performance.html) links to a paper saying that GC needs 4x the memory to match manual memory management and then makes a huge wacky leap to say that ARC could achieve that with less. It can't. ARC will always be slower than manual memory management because it behaves the same way as naive manual memory management with some overhead on top.
On the other hand, that same paper shows that for every single one of their tested workloads, the generational GC outperforms manual memory management. Now obviously, you could do better with manual memory management if you took the time to understand the memory usage of your application to reduce fragmentation and to free entire arenas at a time, but for applications that don't have the developer resources to apply to that (the vast majority), the GC will win.
I'm not saying that better memory management is the reason Android wins these launch to interactivity benchmarks because the difference is so stark relative to the hardware performance that memory management isn't nearly enough to explain it, but it does contribute to it. (My own guess is that most of the performance difference comes from smarter process initialization from usage data. Apple is notoriously bad at using data for optimization.)
AOT native results in slower runtimes for applications with one simple
exception: startup time. In every other case a modern JIT compiler like the
JVM will win due to gathering information and layered compilation.
That's not necessarily true. JIT compilation is severely constrained in the amount of analysis that it can do for the simple reason that JIT has to be fast. Fast enough to not noticeably slow down the app. Meanwhile, an AOT compiler can take all the sweet time it needs, and roam all over the program in order to discover optimizations.
JIT compilers work very well on untyped languages like Smalltalk because the compiler can discover the type information at runtime, and then pre-compile the types that it sees most often. But that's not really that useful on the JVM, because Java is typed, as are most other JVM languages, with the exception of Clojure.
Most funnily Microsoft was heavily advertising AOT with .net framework 1.0
but in general switched to dynamic profiling and optimization in later
versions of .net. (System assemblies that everybody uses during startup are
AOT compiled using ngen, however)
Actually, with .Net Native, Microsoft is back to advertising AOT.
http://blog.metaobject.com/2015/10/jitterdammerung.html
Apple uses and maintains https://sproutcore.com, not Cappuccino. The latter was made by ex-applers a long time ago. Though Apple also isn't monolithic and has many teams independently evaluating Angular, React and others.
Not too coincidentally, the author of Objective-Smalltalk, who said above that he wants to leverage Cappuccino, has also written up his criticism of React here: https://blog.metaobject.com/2018/12/uis-are-not-pure-functions-of-model.html
Related: I've talked to a Cappuccino founder recently too, and my casual observation (which he agreed with) was that had they done Cappuccino all over again, they should have probably dropped Objective-J. Imo it's just a bit too much of a language bikeshedding and I don't think it would have changed framework _that_ much (proof: Swift works well with UIKit and AppKit). Though my opinion was just based on practicality of adoption; if Objective-smalltalk wants to take its time exploring around more than anything else, then I'd say it + cappuccino seems like a nice fit.
I'm really looking forward to Cappuccino staying alive for another ten years (and I wish all the luck to Objective-smalltalk's author) =). Though the recent Cappuccino conf doesn't feature many younger programmers.
I would like to hear more discussion on this subject, since there seems to be a confusion in the community regarding MVC (myself included.) see also author's previous article http://blog.metaobject.com/2015/04/model-widget-controller-mwc-aka-apple.html
I'm a React developer, have little experience with native development myself. With that in mind, here is a small implementation of how I would envision how developing a native app with React's always rendering in mind: https://github.com/ustun/mvc-vs-react/blob/master/singleviewtest2/ViewController.m
Notice every UI action results in a call to a model method, immediately follows by render. The whole model-view syncronization is centralized in a render method, so it is not allowed to modify view manually in UIAction methods, you just set model methods and then render.
What React does is to make this seamless, that is you call setState which in turn triggers render automatically. This way, the data flows from your model to your view.
Of course this doesn't take into account how this flow goes when child views are involved, normally you would want to call render in each childview as well, and that's where virtual DOM comes into play with React.