1. This Week I Learned #3

    Here are some of the things I learned this week, in the order I’ve noted them down.

    • The words ”esoteric” and ”niche” do not have the same connotations. I used the two interchangeably in the past, and that resulted in some really awkward sentences. Thanks anonymous reader for the tip!

    # Programming

    • How the layout algorithm works in SwiftUI stack views. Huge props to Adrian Zubarev for making that task easier for me. I will be sharing more about these findings, and the context that motivated them, in the near future.
    • Database normalization and normal forms, through various articles and resources, including this one. I’ve intentionally tried to stay as far as possible from databases for the past 10 years, but now I feel like I am missing out on a fundamental aspect of building server-side software.
    • After all these years, CSS is still fun.
  2. I’m genuinely excited to see Chris Krycho adopt the format I’ve been recently experimenting with on this microblog. I’ve learnt a lot from reading Chris’ essays and journal entries1, and I am looking forward to reading more of these.


    1. That’s also where I got the assumed audience idea from.

  3. This Week I Learned #2

    Here are some of the things I learned this week, in the order I’ve noted them down. This week I created a separate section for programming to keep things tidy.

    • Contact tracing. A joint initiative by Apple and Google to help health organizations throughout the world slow down the spread of COVID-19. This excellent entry on NSHipster is a good place to start if you’re interested in the nitty-gritty details. The official documentation itself can be found here.
    • Last week I mentioned free access to the ACM Digital Library during COVID-19. This week I stumbled upon this list of similar offers compiled by Michael Tsai.

    # Programming

    • The relationship between size, stride, and alignment in the memory layout of Swift types, thanks to this excellent article by Greg Heo.
    • In Swift Combine, you can filter out nil values using .compactMap { $0 } (reference). I was using filter(_:) before but that still requires force-unwrapping the value in subsequent operations.
  4. This Week I Learned #1

    Here are some of the things I learned this week, in the order I’ve noted them down:

    • Calm technology. A term coined by PARC researcher Mark Weiser in 1995, referring to technology that does not seek to become the center of attention when we use it. It’s there when we need it, and out of sight when we don’t. More on the topic here.
    • Eggcorn. A phrase or expression that resulted from intentionally or accidentally substituting one or more words from an expression with similar-sounding words (Wikipedia). For example:

      • Praying mantis -> preying mantis.
      • Cut to the chase -> cut to the cheese.
      • Acorn -> eggcorn (duh).
    • The entire ACM Digital Library is free to access until June 30th. There’s more to COVID-19 quarantine than Netflix 😉.
  5. Dear GitHub,

    Where is my official dark mode support at? My eyes would profusely thank you for it. And they will be joined by many, many others in doing that.

    Sincerely,

  6. GIF Hunt?

    Product Hunt

    While browsing Product Hunt yesterday, I couldn’t help but get a strong mid-90s, GeoCities-esque, vibe as I scrolled past the animated GIF thumbnails.

    I get it. This is how the attention economy works, and the Internet loves them GIFs. But when everything is screaming for your attention at the same time, the whole thing becomes a kitschy, obnoxious mess.

  7. More on Metasyntactic Variables

    My good friend Mikael Muszynski sent me this nugget about metasyntactic variables:

    I was reminded of the fact that companies which speak primarily in Swedish have their own metasyntactic variables!

    The code will generally be written in English, but instead of foo and bar, they have a clever system:

    “Apa” is the word for monkey [in Swedish], and not only is it a somewhat amusing word, it also happens to start with the letter “a”!

    So the pattern goes apa, bepa, cepa, depa

    Clever indeed.

  8. Margin Considered Harmful

    Max Stoiber on using margins in UI components:

    Margin breaks component encapsulation. A well-built component should not affect anything outside itself.

    It’s very hard to disagree with this statement if you’ve been involved in any capacity with creating reusable UI components. Baked-in margins can and will hinder component reuse across different adaptive layouts.

    A few years back, margins were the only way to create float-based grid layouts in CSS. Today, margin gymnastics are no longer necessary.

    Instead of margin I have started using spacer components, which move the responsibility of managing space to the parent-level.

    Implementation details aside, delegating the spacing between adjacent items to the wrapping component is the right approach. For instance, SwiftUI uses a similar API to the one suggested in the blog post:

    VStack(spacing: 8) {
      Text(Item 1)
      Text(Item 2)
      Text(Item 3)
    }
  9. Full-Page Screenshots in MacOS Safari without Extensions

    Here’s a new trick I picked up this morning: you can take full-page screenshots of any Web page in Safari for macOS without using third-party extensions.

    Before trying this at home, make sure you have the Develop menu enabled. In case it’s not visible in the menu bar, head to Safari ▶ Preferences ▶ Advanced ▶ Show Develop menu in menu bar.

    Once that’s taken care of, follow these steps:

    1. Head to Develop ▶ Show Web Inspector or use the Option + Command + I shortcut.
    2. In the first Elements tab, look for the html tag in the source tree.
    3. Right-click the html tag and choose Capture Screenshot.
    4. Choose a destination and save the file. Append the .png extension to the name if you want preview to properly recognize it as an image.

    Bonus: You can capture any HTML tag in the source tree, not just the root element.

  10. Metasyntactic Variables

    You know those placeholder words used when writing tests or documentation for software programs? They are called metasyntactic variables, and today I picked up some brand new ones beside the usual foo, bar, baz, and qux: corge, grault, garply, waldo, fred, plugh, xyzzy, and thud (source). The last one is definitely a keeper.

    struct Thud: Thuddable { ... }

    I remember the first time I was introduced to toto—the most used metasyntatcic variable in French programming literature—and made fun of how silly and immature it sounded; a shortsighted take in retrospect.

  11. Going Indie

    Today was officially my first day as an indie. Even though the timing might be less than ideal, I can’t help but feel excited about it—especially whenever I take a gander at my meeting-free calendar.

    I have drafted some plans leading to this, but I didn’t have a global pandemic in any of them. Silly me.

    Then again, a quarantine is exactly what I need to start chiseling away at one or two behemoth projects that have been staring me down for the better part of last year.

    Wish me luck. And f☆ck COVID-19.

  12. I am slowly starting to appreciate the versatility of the CSS Grid layout module. For instance, in this commit I replaced a flex grid that required finicky media queries and margin gymnastics with essentially three lines of code using grid. Here is a variable-free version of what I ended up with:

    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
    grid-gap: 1rem;

    The result can be seen here. Not only this achieves the exact same result as my previous flex solution, but it is cleaner and doesn’t use any media queries. Sign me up!

  13. Using Key Paths for Deduplicating Swift Arrays

    Today I needed to remove redundant elements from a Swift array based on the value of a specific property. After some foraging, I came across this post where Antoine extends Sequence to handle the more generic case of deduplicating elements that conform to Hashable.

    public extension Sequence where Iterator.Element: Hashable {
      func deduplicated() -> [Iterator.Element] {
        var seen = Set<Iterator.Element>()
        return filter { seen.insert($0).inserted }
      }
    }

    For my use case, I needed a bit more control over how the elements get deduplicated. Since I am only interested in comparing a single property, I resorted to key paths since they lend themselves quite well to this usage.

    public extension Sequence {
      func deduplicated<T>(
        by keyPath: KeyPath<Iterator.Element, T>
      ) -> [Iterator.Element] where T: Hashable {
        var seen = [T: Iterator.Element]()
    
        return filter { element in
          let key = element[keyPath: keyPath]
    
          if seen[key] == nil {
            seen[key] = element
            return true
          } else {
            return false
          }
        }
      }
    }

    And here is an excerpt from the code where I am using this extension.

    struct Game: Codable, Hashable {
      var name: String
      var releaseDates: [Date]
      /* ... */
    }
    
    /*
      The API reponse returns a list of non-unique games separated.
      by release date, but for this view we only want a single instance.
      of each game.
    */
    
    let games: [Game] = /* ... */
    let deduplicatedGames = games.deduplicated(by: \.name)

    For the name, I chose to not go with unique because it describes the elements of the sequence rather than the sequence itself. I instead took some hints from Rust’s similar-but-not-quite Vec::dedup.

  14. There is a new trend emerging in the design Dribbble community. And some creative souls decided to call it neumorphism.

    I have absolutely no qualms with visual experimentation, depth in user interfaces, or the specific effects used in this new trend. But I can’t help but feel put off by this incessant, collective infatuation with fads in UI design circles. It’s not healthy for anyone caught up in it, especially newcomers who have yet to find their creative footing.

    If you are just starting out as a UI designer, learn to ignore design trends. You can thank me later.

  15. Ten Years

    The beginning of a new year is often considered a good time to develop new habits or quit bad ones. The beginning of a decade, however, offers the less frequent opportunity to look back at a more substantial chunk of our lives and reflect on where to go next.

    Ten years ago, I had just landed a full-time contract as a junior product designer at a large telco company in Paris, France. My tasks straddled mobile product design, project planning, and community management. Even though the organizational unit where I worked was intended to function like an independent startup, the hierarchy, bureaucracy, and waterfall processes made it everything but.

    At the time, I had no clear career path in mind. All I knew was that I wanted to build mobile applications for a living. My “programming” experience prior to that was limited to Wordpress and Flash, and the labyrinth of memory management has consistently stood between me and learning Objective-C.

    After a year and a half in Paris, I moved to the US where I joined a local startup in the DC area, then thoughtbot in 2012. Working at the latter for a little over 4 years has drastically changed how I see software, both as a user, and as a maker. I eventually managed to overcome Objective-C, move to Stockholm, and change jobs twice since.

    During my job interview in 2010, I was asked where I’d see myself in ten years. I don’t remember the exact answer I concocted, but I remember it was utter nonsense. Ten years is a long enough time to make any attempt to predict the course of one’s life an exercise in futility.

    Where do I see myself ten years from now? Not the slightest clue. I might still be making software for a living. Maybe running a successful company of one, or two. Or perhaps I’ll find solace in cultivating the land.

    Only time will tell.

  16. IBM 💔 Server-Side Swift

    IBM has unofficially announced that they are abandoning Swift and their work within the SSWG starting 2020. Sad news, given that their stewardship of Kitura and clout in the enterprise market gave a much-needed credence boost to Swift in the server-side space.

    Four years since Apple open-sourced Swift and made it run on Linux, the ecosystem still has ways to go to stand on its own as a battle-tested stack that attracts developers from other established communities. With that being said, this process has been accelerated since SSWG started a little over a year ago; they since have been doing a remarkable job with reconciling different projects and focusing on key modular components that benefit the community at large.

    While this news is a bit of a setback, I firmly believe that server-side Swift’s best days are still ahead of it.

  17. Alexey Naumov in Performance Battle: AnyView vs Group:

    I cannot say there is a clear leader among AnyView and ConditionalView, but the myth about negative AnyView performance implication is BUSTED.

    I take most of what I see on Twitter with a grain of salt, especially when it’s technical advice that’s not backed by examples or reproducible benchmarks. In the case of SwiftUI, there is no shortage of guesswork and hearsay given how under-documented the framework is. And while I appreciate the openness, the occasional tweet from members of the core team is not enough to fill the knowledge gap.

    Luckily, there is always an industrious soul in the community that rises up to the task of winnowing the chaff from the grains.

  18. PeerTube 2.0

    The nice folks over at Framasoft have been doing a tremendous job with PeerTube in general, and this release in particular.

    For those unfamiliar, PeerTube is the Mastodon of video—a federated video platform that uses the ActivityPub protocol to connect multiple independent instances. Any individual or organization can run their own instance and have total control over their content and communities.

    I am very excited to see this platform evolve and get more traction the world over. Hating on YouTube is cliché these days, but the service deserves every bit of it. And then some.

    Now, I understand that people making a living out of content creation can’t move to other platforms willy nilly, but that’s exactly the reason why it’s important to get behind projects like these.

  19. Inset Grouped Lists in SwiftUI

    When SwiftUI shipped earlier this fall, it didn’t provide any APIs to use the newly introduced inset style for grouped lists and table views. The latest release seems to have addressed that, albeit silently and not in the way that I had expected.

    As of iOS 13.2, grouped lists will use the inset style when the horizontal size class environment value is .regular, such is the case with fullscreen scenes on iPad.

    Grouped Lists

    If you want to forcibly enable or disable this style, you have to manually set the size class environment variable, preferably directly on your list to avoid any unintended side effects:

    List {
      Text("Item 1")
      Text("Item 2")
      Text("Item 3")
    }.listStyle(GroupedListStyle())
    // To enable the inset style
    .environment(\.horizontalSizeClass, .regular)
    // To disable the inset style
    .environment(\.horizontalSizeClass, .compact)

    While I am not aware of any issues caused by this approach, I’d have preferred if Apple introduced a dedicated InsetGroupedListStyle or, even better, exposed the underlying ListStyle protocol instead.

  20. Embrace the Darkness

    Dark mode support for this website, fresh out of the oven.

    I have a soft spot for dark interfaces. So much so that the several instances I had to switch back to light mode while working on this made me feel inexplicably uncomfortable.

    Since I had already done the legwork of using CSS variable for the colors used throughout the site, it was relatively easy to implement this new dark theme. Here is the commit for those of you interested in the nitty-gritties.

    Currently the site takes the same appearance as the OS, but I am entertaining the idea of adding a manual toggle sometime down the road.