A summary of all Swift by Sundell content published during May 2020.
This week’s article is about library development, and contains a few techniques and principles that can be good to keep in mind when designing and building reusable Swift libraries.
This week, let’s take a look at a few techniques that can help us make our code easier to read, test and maintain, by reducing the amount of indentation within it.
Swift’s many protocols can, in general, be split up into four main categories. Let’s go through them, and how keeping them in mind can help us write well-formed protocols that are consistent with those found in the standard library.
Swift enums are really powerful, but they can often be made even more capable when mixed with other kinds of Swift types — such as protocols and structs. This week, let’s take a look at a few examples of doing just that.
Let’s take a look at how even the smallest utility functions can have quite a big impact on the way we write code on a day-to-day basis, by making common tasks easier and preferred patterns simpler.
This week, let’s explore the topic of UI modularization in the context of SwiftUI, by taking a look at a few different techniques that can be useful in order to avoid trading Massive View Controllers for Massive Views.
This week, let’s take a look at a few tips and techniques that can help us make our types more well-defined, by splitting them up once their responsibilities have started to grow beyond the ideal scope of a single type.
The phrase “Swifty code” is often used to describe code that follows the conventions that are currently the most popular within the Swift community. But what exactly does that entail? Let’s take a look.
This week, let’s take a look at a few different ways of configuring views when using SwiftUI, and the sort of pros and cons that each of those approaches gives us in terms of code structure and flexibility.
Let’s take a look at one of the core aspects of object-oriented programming — initialization. What characteristics should an initializer ideally have, and what sort of techniques could be useful in order to keep our initializers simple and predictable?
This week, let’s take a look at a few core language features that enable us to design really lightweight APIs in Swift, and how we can use them to make a feature or system much more capable through the power of composition.
This week, let’s take a look at a few different ways to deploy unit testing in a more pragmatic manner — to use testing to solve immediate problems, and to enable our code to be tested without having to fundamentally change it.
When designing APIs, using default arguments can often let us strike a nice balance between flexibility and ease of use — as they let us add solid, intuitive defaults to many of the configuration options that we’ll end up providing. Let’s take a look at a few examples of how they may be used.
Let’s take a look at a few different techniques that can let us achieve a nice balance between code reuse and configurability, by building lightweight abstractions that enable us to encapsulate our configuration code.
Protocols are, without a doubt, a major part of Swift’s overall design. However, they also come with their own set of downsides and trade-offs. This week, let’s take a look at some of those characteristics, and explore a few alternative ways of abstracting code in Swift — to see how they compare to using protocols.
This week, let’s take a look at a technique that can let us leverage Swift’s type system to perform data validation at compile time — removing potential sources of ambiguity, and helping us preserve type safety throughout our code base — by using phantom types.
Very often we can make a big impact on the quality of our code base by improving some of its more minor details. This week, let’s take a look at one technique for doing such local improvements, by refactoring large functions into dedicated, rule-based systems.
One really interesting aspect of Swift’s overall design is how centered it is around the concept of value types. This week, let’s take a look at a few different ways in which we can make use of the semantics of value types — and how doing so could significantly improve the flexibility of our value-based code.
Deciding whether or not to generalize a piece of code to fit more than one use case can sometimes be quite tricky. This week, let’s take a look at a few key factors that can help us strike a nice balance between being able to reuse as much of our code as possible, while also avoiding making things too complicated or ambiguous in the process.
iOS developer and YouTuber Mayuko Inoue joins John to discuss team work and how a solid code structure can make teams more productive. Other topics include goal setting, how to grow as an engineer, and contributing to open source.
Establishing a solid structure within a code base is often essential in order to make it easier to work with. This week, let’s take a look at a few different techniques for structuring the data that makes up our core models, and how improving that structure can have a big positive impact on the rest of our code base.
One way to make a code base easier to navigate, while still maintaining a solid overall structure, is to inline functionality whenever two pieces of code are heavily related. This week, let’s take a look at how that can be done using inline types and functions, and how — when tactically deployed in the right situations — it can make our code a bit easier to follow.
A race condition is what happens when the expected completion order of a sequence of operations becomes unpredictable, causing our program logic to end up in an undefined state. This week, let's take a look at a common scenario that can cause race conditions, possible ways to avoid them - and how we can make our code more robust and predictable in the process.
Rahul Malik of Pinterest joins John to talk about working on a large-scale iOS app, using third party build systems, client/server networking architectures and much more.
A DSL, short for Domain Specific Language, can be explained as a special kind of API that focuses on providing a simple syntax that's tailored to working within a specific domain. Swift's type inference and overloading capabilities also make it a really great language to build DSLs in - and this week, let's do just that.
This week, let's take a look at how we can be inspired by the functional programming world to improve the structure and robustness of our Swift code - this time focusing on using functions that return objects and values as early as possible.
With each new release, Swift keeps getting better and better at creating compiler-generated implementations of common boilerplate. One such new feature in Swift 4.2 is the new CaseIterable protocol - that enables us to tell the compiler to automatically synthesize an allCases collection for any RawRepresentable enum. This week, let's take a look at some examples of scenarios in which this new feature can come very much in handy.
Adding new features to an app or framework often involves adding new arguments to existing functions. While most such changes may seem trivial at first, if we're not careful, we could - over time - end up with functions that are a bit unclear and cumbersome to use. This week, let's take a look at how to deal with such functions, and how they often can be simplified by reducing the number of arguments they accept.
One thing that almost all apps and frameworks have in common is that they tend to grow in both size and complexity as time passes. As a project grows it becomes more and more important to maintain a solid and consistent structure, but at the same time it also becomes increasingly difficult to do so.
Adding new features to existing code can be really challenging - especially if that code is heavily used throughout one or many projects. Backward compatibility can in many ways help us make such changes in a much smoother fashion, so this week, let's take a look at a few different techniques that can help us make changes to our code base fully backward compatible.
Peter Steinberger, creator and CEO of PSPDFKit, joins John to talk about building and maintaining a large framework project, how PSPDFKit came to be, how his team works with Radar, and all the challenges and excitement that comes with running a business based on a closed source SDK.
Being able to use unit testing in a productive way often requires the various parts of an app to be written with testability in mind, which isn't always the case. This week, let's take a look at a few different refactoring techniques that can help us make non-testable code much easier to test.
When and how to write documentation and code comments tends to be something that causes a lot of debate among developers. This week, let's take a look at a few simple tips and tricks that can let us write code that is more self-documenting - code that makes the underlying intent and details more clear, simply by the way it's structured and how it's written.
One really interesting feature of Swift is the ability to create lightweight value containers using tuples. The concept is quite simple - tuples let us easily group together any number of objects or values without having to create a new type. But even though it's a simple concept, it opens up some really interesting opportunities, both in terms of API design and when structuring code.
Composition is a super useful technique that lets us share code between multiple types in a more decoupled fashion. It's often posed as an alternative to subclassing, with phrases like "Composition over inheritance" - which is the idea of composing functionality from multiple individual pieces, rather than relying on an inheritance tree. This week, let's take a look at a few situations in which composition can be used with structs, classes and enums in Swift.
While Swift does not yet feature a dedicated namespace keyword, it does support nesting types within others. Let’s take a look at how using such nested types can help us improve the structure of our code.