Chainable Programming: Principles and a Simple Implementation
Introduction I have been using Masonry for a while and became quite interested in its chainable programming style, so I took some time to look at how it is implemented. In my view, Masonry's main advantage is: <font color="red">the ability to group a view's constraint code together, making it easier to read and modify.</font Chainable programming links multiple operations (multiple lines of code) together with dot notation () into a single expression, improving code readability. The core idea is: a method's return value is a block; the block must have a return value (which is , the object itself); and the block's parameter is the value to operate on. Using Masonry Let's start with a typical Masonry usage: Pretty simple to use. The question is: how does calling multiple properties in a chain work? Let's look at the method: You can see that primarily sets layout constraints on the view and saves all of them into the constraint maker: - Creates a constraint maker; - Calls , saving all of the view's constraints into the constraint maker; - iterates over all constraints in the constraint maker and applies them to the view. In practice, it first iterates and uninstalls any existing constraints, then installs the new ones, and finally returns the list of constraints. The key is the chain call . saves both the width and height constraints into through . Note: Xcode occasionally glitches and treats as properties of , but they are actually methods that return a . A restart of Xcode fixes this. Now look at the source for : What exactly is this?! To allow passing arguments via parentheses, a block is defined inside the called method, returns that block, and the caller can then invoke the block. The key is: the return value must be a Block. Let's summarize the thinking: - Chainable programming concept: wrap the work to be done inside a block and provide a method that returns that block to the outside. - Characteristic of chainable programming methods: the method's return value must be a block. Block parameter: the value to operate on. Block return value: the method's caller (the object itself). A Simple Chainable Programming Implementation Below is a calculator implemented in both the traditional style and the chainable style for comparison: All those nested square brackets look quite ugly. Here's the same calculator implemented following Masonry's approach: The entire calculation is returned as a block. The block's parameter is the number to add, and its return value is , enabling continued chaining. Of course, to achieve a Masonry-like call style, you need to use a category. For example, adding a category to : This method creates a calculator maker when called, invokes the passed-in block, and returns the result. Code All code from this article can be found on my GitHub .