 to talk to me about programming and minimalism. Real quick, I'm a co-founder of a startup called ZenCoder. We do video coding as API service, we're basically API to a high-performance video and coding platform. So what I really want to talk to me about today is this question. What is good programming? To answer that question, we have to ask another question first, which is what is programming to begin with? A real simple answer to this might be programming is typing characters and everything to get executed by a machine. That's not a very deep answer to that question. That's kind of like saying programming is, or that's kind of like saying map is the thing where you write numbers down on a piece of paper with a multiplication sign. That's not really map, that's just sort of a shadow answer. I think when you look deeper at programming, programming is ultimately about the process. The technical term for this is doing shit. More specifically, programming is about defining complex processes in a really precise way. This is true whether your program are an operating system or a website or some sort of crazy, drummy video game. You're often looking for the rules that define what you want to happen and you have to describe those rules in a very precise way. So in an interesting sense, programming is not really about computers at all. In the 21st century, the 20th century computers are where our programs live. You cannot just imagine a world in a feature where what we do in defining complex processes doesn't even touch a computer. So let's go a little bit deeper. What is programming like? What is this practice of defining complex processes like? Anyone have any thoughts about what programming is like? Was it a good metaphor? Writing a novel, okay? What else? Sketching. Sketching, okay? Music. Music? What else? So I think that gives a lot of good answers for this question. I'm going to look at three of them briefly today. One is engineering. Programming is kind of like engineering. Engineering is the discipline where you apply rigorous math, science, et cetera to the design of things, into the building of things. So civil engineer applies math and physics to the design of a bridge. And chemical engineer applies rigorous thought to the conversion of chemical materials, let's say. So there's some similarities here. We're both applying rigorous thought to the process of building things. But there's some differences too. For one thing, engineers tend to build phase, whereas we build processes. You can think of it as engineers build now as immemorial verbs. Another difference is that engineering is typically a first stage in a two-step process. The engineer designs something, but they don't actually do the work of manufacturing or construction. So the civil engineer who designs a bridge is unlikely to be the person who actually builds that bridge. So it's a two-phase process. We actually have two phases in program, a team, we call the second phase compiler. And it's effectively free and effective in the instance. It'd be like if the aerospace engineer could tweak the design of a plane and instantly be up in the air flying that plane. That's the luxury we have as programmers. So the second metaphor I want to look at is craft. Programming is, in a lot of ways, like craftsmanship. You've seen this metaphor before. I'm sure if you've been in the ruby community or the agile community. So we're an engineer who focuses on the upfront sort of design problem solving behind something. The craftsperson actually focuses on building. This involves a focus, let's say, on tools, on having the right tools and knowing how to use the right tools for a job. This is a focus on skill. So to an engineer, the process of building something is basically a commodity. You build a bridge and either it works or it doesn't work. It's sort of a minor government. So to an engineer, building is a commodity. It works or it doesn't. To a craftsperson, it's not. Grades of skill come into play in what gets produced. Small teams, crafts people tend to work, say like the guild system is a model here. We have small teams working together closely to do things. The same thing happens in programming. Even in large companies, teams get broken down. It's hard for 80 people to work on the same bit of code. Finally, crafts people focus on habits and practices that enable them to be successful. They focus on internally, what do I do in order to guarantee or to create good outcomes? Or what do I do as a team? What are good practices for a team to create good outcomes? Engineering doesn't focus on those. Engineering focuses on the problem solving. Craftsperson focuses on creating conditions in which problems can be solved. So test-driven development is a practice that doesn't actually help you directly solve a problem, but it creates the conditions in which you can solve problems. So the third metaphor I want to look at is writing. Before I do, and I'll just spend most of the talk on this, quick question. Which of these three models is the right model? Engineering, craft, or writing? Craft. Craft. So I would say they're all the right model. They all get at programming from a different standpoint. They all get at something in programming. And actually, so most of us probably tend towards one extreme or another. Maybe we're a great engineer, but we don't have the best practices. And the best program is actually people who are able to do all of these things. The second thing I want to look at before we get into writing is how do these, each of these roles, do the hard work of solving complex processes? We're dealing with huge amounts of complexity in programming. Way more complexity than we can naturally handle on our own. And each of these models has a different approach to complexity. So the engineer looks at complexity as a problem to be solved. You, through experimentation, through trial and error, through smart design, you directly solve a problem. A craftsperson looks at complexity and looks for the right conditions under which complexity can be managed, the right practices and the right habits that allow this. The writer looks at complexity and tries to simplify it by thinking clearly about it. And we'll see that as we go forward. So let's look at if programming is writing. Programming is a form of writing. This becomes clear, I think, when you think about it a little bit. Programming is the practice of taking abstract ideas and thought and transcribing them into language. The same is true of poetry. The same is true of prose, even music composition. So an essayist has an idea that they want to communicate. So they write and they rewrite and they rewrite, maybe starting with an outline, until they get to the end result that they want to produce. Similarly, a programmer starts with an idea, something they want to accomplish, maybe creates an outline, an architecture, and then we code and recode and refactor until we've effectively done what we want to do. It's a similar process. Writing comes in many forms, of course, though. And I think music composition is a fairly interesting parallel to programming. In particular, a composer and a programmer both write in a medium that's totally unlike the end result they're trying to create. So a composer writes these dots on a page, but that's not the end result. The composer's not trying to produce dots on the page. They're trying to produce music and sound in the experience of hearing that music. Similarly, a programmer writes characters in an editor, but this is not our goal. We're not trying to produce a bunch of characters in an editor. We're trying to produce a running application. So here's the interesting thing about writing. How many ways are there to express an idea in writing? There was a philosopher actually in the early 20th century named Ludwig Wittgenstein who believed that philosophical problems were primarily due to language problems. So ambiguity in language and imprecision in language is what caused confusion. It's what caused us to have these philosophical problems. In other words, if there was only one way to communicate an idea, we wouldn't have philosophical confusion. The interesting thing here is that Wittgenstein's theory was refuted about 20 years later by another philosopher named Ludwig Wittgenstein. The way Wittgenstein realized, and I think rightly, that the problem is not imprecision in language. It's forgetting how language is used in its actual context. So we put too much weight on words. We try to put too much meaning directly in words and in structures instead of looking at how things are used. So what does this mean? Wittgenstein would say this means absolutely nothing because you have no idea how it's being used. It could mean very different things in very different situations. There's no inherent meaning in that word. So getting back to programming, the point is that there's never just one way to express an idea in programming. If there was, we wouldn't really be writers. We'd just be implementers. We'd take our ideas and there'd be a one-to-one correlation between an idea and code. But the fact is there's any number of ways of expressing our ideas and that's why no matter what, we have to write with style. We always have a style. So if we're asking what is good programming, the real question for us as writers is what is good programming style? And to answer that question, we're gonna look at style in music and then we're gonna look at style in writing. So starting with music. Artistic traditions tend to move in cycles that look something like this. Someone starts with something that's simple and interesting and then someone builds on it. Someone builds on it and builds on it and builds on it and builds on it. Until you end up with something that's enormous and stale and boring. Incidentally, some software is actually written following this pattern. So what's the next move in the cycle? Start over. Someone throws away 80% of the tradition and keeps the most interesting 20% and starts over, starts the cycle again. We're gonna look at this a few times in the history of music. First, looking at classical music. Early 18th century, a composer named Johann Sebastian Bach wrote in a style that's called Baroque. Baroque, of course, means complex and ornamented. And his music is complex. There's a lot going on in box music. So box music is complex. There's a lot of voices kind of playing into each other. It's interesting, but it's complex. Next come Haydn and Mozart who start what's known as the classical tradition. This is a move towards simplicity. They've simplified this Baroque tradition and put it in a simple structure. Classical music follows these simple rules, simple forms, and it pretty much all conforms to this. So I think you can hear it. Here we go. So see how that's a much more sort of simple, structured, predictable music. So after Mozart, Beethoven builds on this classical tradition. Makes it larger, makes it more complex. They build on this classical tradition. So Brahms builds on it, Mahler builds on it. By the time he gets to Mahler in the beginning of the 20th century, the classical orchestra has grown by 150%. So Mozart wrote for 42 musicians, Brahms wrote for 108. And while Haydn wrote 10 minute symphonies, Mahler wrote a symphony that's 90 minutes long. And it's a lot more complex. Simplicity and complexity. It turns out that this tension is at the core of art. It's at the core of the development of music and history and it's really at the core of a lot of art. More specifically, it's the interplay between these two that makes things interesting. Something that's too simple is not very interesting. Something that's too complex is not very comprehensible. And great artists are the people who are able to balance these to navigate the tension between simplicity and complexity. So coming back to the 20th century in music, by the time you get to the 50s and the 60s and the 70s, music has gotten hugely more complex even than in Mahler's day. It's almost become an academic exercise where composers write based on theory. And they almost don't like music to be listened to. They write music for the ideas behind the music. And they've kind of lost the connection with music as being something that people enjoy listening to. So along come composers like Steve Wright, our repair and Philip Glass, who start writing in a new style that comes to be known as minimalism. They've stripped down this classical tradition to what they see as the core, what they see as the interesting bits. And they've produced things that are simple and really beautiful. In the 60s, the Beatles came along and started writing the simple catchy pot music. The Beatles along come the later Beatles who write music that's a bit more complex. Here's the double guitar, which builds on this tradition. I'll put you that here. But they do write very complex music. They write 20 minute rock operas based on Anne Rahn's philosophy, which is a departure really from sort of the core of rock music. So what's the next step in this progression? Yep, so the clash and the sex pistols stripped rock music back down to what they see as the essence. And they write music that's simple and very expressive. Minimalism is not just less. It's not just taking things away. It actually adds something that you don't have in more complex forms of expression. So let's move now from music to writing. To do this, we're gonna look at George Orwell. Orwell's best known for his novels about totalitarianism, 1984 Animal Farm. But he's also an excellent essayist. And he wrote what I think is one of the best essays on the topic of writing. It's called politics in the English language. Has anyone read this essay? This is essay on some great examples of bad writing and some guidelines for writing with good style. But what's especially interesting about this essay is that he connects bad writing to sloppy thinking. And he connects that to propaganda and totalitarianism. His basic premise is that clear writing and clear language allows for clear thought. Whereas bad writing does not. Bad writing creates bad thinking. So let's look at an example, contemporary example in the realm of politics. USA Patriot Act. What was this act about? Patriotism, that's what the title would lead you to believe. Ultimately, it was an act about surveillance. If this had been called the expanded surveillance act, we could have had rational discussion about it. We could have weighed the pros and cons of something like this. But given a name like USA Patriot Act, obscures discussion and prevents rational thought. So this set of language and bad writing in general let us avoid really thinking about things for ourselves. People can package up thoughts for us and put them in our heads. We can actually speak about them without them really entering maybe even the realm of rational thought. We operate kind of at a lower level. Another way to express this is that vague language and bad writing are a key tool of propaganda. So Ola gives an example. Imagine this bit of text written by a Soviet sympathizing academic in Britain in the late 1940s. It says, well, freely conceiving that the Soviet regime exerts certain features which the humanitarian may be inclined to deplore, we must, I think, agree that a certain curtailment of the right to political opposition is an unavoidable concomitant of transitional periods and that the values which the Russian people have been called upon to undergo have been amply justified in the sphere of concrete achievement. What is this actually saying? You gotta break a few eggs and make an omelet. Yeah, and taking a step further, it's saying that tens of millions dead in Stalin's purges is justified. But no one would ever come out and actually say that. You express that thought like this. You hide behind vague language so that people don't really understand the implications of what you're saying. Here's another example, a much less sinister example. This actually comes from an English professor in Orwell's Day. I'm not indeed sure whether it is not true to say that the Milton who once seemed not unlike a 17th century Shelley had not become, out of an experience ever more bitter in each year, more alien to the founder of that Jesuit sect which nothing could induce him to tolerate. Besides being utterly incomprehensible, this sentence actually has mistakes in it. If you want to make any sense out of this, the fourth negative probably shouldn't be there. And what alien probably should be akin. So not only is bad writing impossible to understand, it's also buggy. So Orwell gives some guidelines for writing with good style that I think are interesting. It says first, never use a metaphor, simile, or other figure of speech which you are used to seeing in print. Second, never use a long word where a short one will do you. Third, if it is possible to cut a word out, always cut it out. Fourth, never use the passive where you can use the active. Fifth, never use a foreign phrase, a scientific word, or a jargon word if you can think of an everyday English equivalent. And sixth, break any of these rules sooner than say anything outright barbarous. This is an important rule too. If you slavishly follow guidelines like these, you'll probably end up making mistakes. Guidelines like these should be combined with good judgment in how to apply them. So my takeaway from Orwell is that clear writing enables clear thinking. The bad writing leads to bad thinking which enables totalitarianism. So coming back to programming, how do we apply these things to programming into your question of what is good programming? I think good programming as a writer is good programming style and good programming style is ultimately minimalism. So you might be wondering why minimalism? If beauty is found in the interplay of simplicity and complexity, why am I focusing on minimalism here? Well, I think the simplest answer to that is that our job as programmers is to define complex processes. So we have complexity baked right into the core of what we're doing. If you define complex processes in very, very complex ways, there's no balance, there's no tension there, it's just complexity. Whereas if you're able to define really, really hard, complex things in simple, elegant ways, that can be beautiful. So minimalist style coupled with clear direct writing, and clear direct writing is what allows us to think well about what we're doing. So let's look at some specific guidelines for maybe programming with this kind of style. First, always take the simplest approach to a problem. If you look at a problem and there's a simple approach and it's not too ugly, it's a simple, elegant approach or there's maybe the right approach which is to build a whole big system around something, you're probably better off taking the simple approach. Second, clever code is bad code. Here's a little bit of code from an application I worked on back in like 2006. It's basically a view helper that prints out a bit of text only if that text belongs to the currently logged in user. The problem is this code is clever and that is not intended as a compliment. It firstly uses the returning method. Who's used returning before? I think returning was actually pulled out of, that's actually more than I expected, that's interesting. Returning I think has actually been pulled out of active support, it was an active support specific thing. It's a K combinator, it returns a value from a block. It's totally the wrong method to use here. Besides being non-standard and probably tripping up people who are not familiar with it, it's intended to return a value. It's intended to return a modified value that's passed through a block, but we don't need to return anything here, we just need to yield or not yield. And there's all sorts of other rude things here. So the user argument is optional. It optionally will infer it from an instance variable, which is kind of weird, et cetera. This code could have been written like this. Yield if user is current user. That's pretty simple. Third, any code that isn't doing something is harming your project. So features that you've taken out that are still on your app, features that users don't need, code that's half finished, isn't neutral. It actually decreases the value of your code. Fourth, accept constraints. So if your framework or your language gives you a simple way to solve a problem and maybe you can get a slightly better approach by taking a very complex way, you're probably better off living within the constraints that are given to you. Fifth, if it isn't a local business logic, it should be a library. This allows you to, you've probably seen this progression here. Move logic from views to controllers and you don't want them controllers, so move logic onto the views. But there's another progression that's important too. You shouldn't stop here. You should move logic from models to libraries and if possible from libraries to shared libraries. The way I like to think about this is anything that's proprietary and specific to your application probably should be in a lib or maybe in a model. But anything that's generic functionality, ultimately you're better off if it's in vendor, if it's a shared library that you share with the community. It takes a maintenance load off your plate. It takes away the amount of work that you're actually doing in your application. That one was a consultant that used to actually structure agreements like this. Anything that was proprietary and specific to the business problem at hand, the client owned. Anything that was generic, I owned. And licensed back to the client, of course. That let me reuse code across projects. That let me open source things. And I never got client pushback from this. They always understood it. Sixth, break hard problems down. This is one of the most important powerful tools we have as programmers. So let's say you have to write an airline booking system. That's hard. I can't tell you how to do that. But if you break it down, maybe you can get somewhere. So here's what you wanna do. You wanna book a flight for a customer. Well, we can take that method and break it down into simpler things. To book a flight for a customer, we have to reserve a flight. We have to charge the customer and maybe we have to notify the customer. It's a little bit easier. Charging and notifying, that's simple. I've done that before. So how do we reserve a flight for a customer? Maybe something like this. If the flight is available, mark it as reserved. And we can keep going. We can look at how do we find out if a flight's available? How do we flag it as reserved? We can dig into how to charge and how to notify. So we've taken something that I have no idea how to do and broken it down into things that I can start to wrap my head around. The flip side of that is not to over abstract. I love this kind of thing in Ruby. Simple one liners that are fairly easy to understand. This just maps a list of names of the user's groups and makes it into a nice sentence. I could make that a method. I could have a group list method on my user model. But to me, that looks more complex than a nice simple one liner. It's more code I have to maintain. The flip side is one liners can get too big. Anyone know what this does? If you can't understand a one liner in like four seconds maybe, you probably should be abstracting a little bit. Eighth, you don't need metaprogramming. Seriously, you don't. Unless you do, and sometimes you do, and metaprogramming can be really, really effective and really beautiful. But don't use it lightly. If you can solve a problem without metaprogramming, you probably should. Nine, always actively clean up your code. Code that is not being worked on, that is not being cleaned up is going downhill. It doesn't stand still. How many of you could step into a Rails 1.2 project today and be productive? I get lost on things like hasn't belongs to many. I haven't used that in years. The form tag thing. I wouldn't know where to start. So one way we do this on some of our projects is to actually flag code debt in our issue tracker. And then every week try to get rid of a little bit of code debt. So we kind of mark the things that maybe need cleaning up and constantly make progress against them. Ten, apply these rules wisely. Slavishly following guidelines like this will probably get you into trouble. You don't have a list of rules that you need to follow. What you need is judgment that knows how to apply guidelines like this. Finally, simple code is beautiful. And writing code that looks good and is beautiful actually is better code. So if programming is the process of defining complex processes, we've seen the engineer solves complex problems by designing around them, by modeling the right solutions to problems. The class person creates the right conditions, the right habits, the right environment where hard problems can be solved. And the writer solves hard problems by making them simple and thinking clearly about them. So how do you become a good writer? I think there's three things you have to do. First, you have to consume good writing. Read good code. I think a great way to do this is to pair with people who are good programmers or maybe better than you. And you can see instantly in real time how they style solutions to problems. I wouldn't stop at code too. I think being a consumer of other forms of good writing, fiction, poetry, even music, overlaps the aesthetics of those things, overlap with the aesthetics of writing software. Second, you have to study. So all are written essay on how to write with good style. And in the programming world, we have any number of books, good books on how to write clean code, how to write properly. People talk about this all the time. And then third, you have to produce. You have to be a producer of code to learn how to write with style. You don't become a good poet the first time you write a poem. You write 1,000 poems that suck and you throw them away. And then maybe you start writing something that's reasonable. And the same is true of software. So remember, you have a programming style. You have to. So make it better. I believe good programming style is minimal. It's simple and expressive, just like Ruby. And not only is it effective and efficient and a good way to be productive, it can also be beautiful. So write beautiful code. Thanks.