Two of the most impressive languages in my mind are Lisp and Smalltalk. They are both extremely limited: Lisp is structured around spaces and parentheses. That’s it.

Smalltalk has only 6 keywords: true, false, nil, self, super, and thisContext. Everything in Smalltalk, including conditionals, is handled by sending messages to objects. How many keywords does Swift have already? Why can’t I name my UISwitch “switch”? (I know why, and it’s vexing.)

Most languages don’t do this. Their users want more toys and more sugar in the language. The language maintainers add it, and you end up with a languages that are a complicated mess.

While most langauges aren’t designed with simplicity as a feature, I’ve found that with a little self-control, it’s possible to intentionally limit yourself to a subset of your favorite language, and have great results.

I’m writing Objective-C and Javascript on a day-to-day basis, so my examples will come from those languages. The idea, however, is universalizable.

First, app structure. When structuring an app, I limit myself to one structure. Inasmuch as I can control it, everything has one and only one owner, so that my object graph looks as much like a tree as possible. From the top, the app is run by coordinators, which boss around the view controllers. Those view controllers each have a view, which is a custom subclass of UIView designed specifically for each view controller. This lets me push subview configuration and layout out of the view controller and down into the view. Subview allocation is always handled via lazy loading. Layout itself is pushed even further into a layout object.

I’ll break these rules every once in a blue moon, but almost every time, I will write code like this. It helps increase consistency and removes any doubt about how to structure the simple stuff. When a new programmer comes on board, if they understand one section of the app, they’ll be able to easily navigate through the rest of it.

Second, communication patterns. Since everything is a tree, messages need to go down, from parents to children, and up, from children to their parents. Parents know about their children, so they can just send simple messages. But when children talk to parents, I almost always use the delegate pattern exclusively. I know about KVO, I know about NSNotificationCenter, and I know about the responder chain, but delegates have a simplicity to them that I value. Their relationships are one-to-one (each object generally has one delegate), their data is typed, and it’s easy to search for delegate conformance. There’s a small cost to the extra code of declaring the protocol, but I find that it pays off in the long run.

Delegates are great, but the key here is not the pattern itself, but limiting yourself to it. The artifical limitation simplifies decision-making while writing code. When you limit yourself intentionally, you don’t end with a tangled mess of code that fires an NSNotification from inside of block that calls another method via a delegate.

Finally, a Javascript example. The project I’ve been working on has a backend written in Express. Express assumes very little about your code’s structure. It gives you the standard Node.js Request and Response types, as well as a Router. That’s pretty much it. Routers let you register functions with routes. Now, I could try to build a roughly object-oriented model layer within Javascript, but I don’t really understand how Javascript constructors work, so that choice is out.

Instead of trying to make each route (represented by a function) talk to an object-oriented model layer, the User type holds onto all of the things that a user can do.

var loginAction = function(req, res, next) {  
	var creds = { email: req.body.email, password: req.body.password };  
	User.login(creds).then(function(session) {  
		res.sendJSON({ session: session });  
	}).catch(function(error) {  
		res.sendError(error, "There was an error logging in.");  
	});  
}  

Each of the things on the User type is a function, and calling it returns a new Promise. This, and the fact that data is represented by dumb objects that do nothing but hold the data, make the model layer is very functional in nature. Of course, it wouldn’t be interesting if it were only in one place, so every single route in the system works like this.

When I’m making a new route, it’s no longer necessary to think about how go from the functional “action” layer to the Promise-based model layer. It’s always the same. The sendJSON and sendError functions on Result are also almost always used, making it dead simple to add new endpoints. You get to the meat of writing your code even quicker. Limiting you and providing a One True Way to do stuff is how frameworks like Rails help you speed up development.

When you limit yourself to a small part of the language, you end up with code that’s simpler and requires less thought to implement. It removes a lot of the weight from working in your codebase and makes it easier for outsiders to understand how things work.