Great article, and I found the comments just as interesting. If you have a certain level of pride and dedication in what you do, you will understand and respect Jiro for the level of mastery he has in his craft. If you don’t, that kind of commitment to improvement and excellence is a completely alien thing.
I don’t know if I agree with Zed that indirection and abstraction are constantly mixed up. I think that often indirection creates useful abstractions. For example, in scala, if you want to create an iterable, you only have to implement two things—be able to make an iterator, and say how to make something of the original type you described. After that, you get every item in this list for free, because they rely upon the abstraction of an iterable—as long as we know you can iterate over it, we know that we can do all of these other things, and we don’t really care how else it works.
In that way, I think that an abstract class is supposed to define most of the methods based on a few items which the user is supposed to define, knowing that if the user follows the contract, the rest of the methods will work too. The fundamental way that a class should be able to work has been abstracted (or in zed shaw’s words, simplified) to just a few methods, instead of many, many methods.
I think that Zed Shaw is right that there are many poor interface designers, but I don’t think his reasons for why they aren’t good are right. APIs are very hard to write, and once an API starts to be used, it is very painful to change it. Everyone espouses, measure twice, cut once, but in general, it’s not that big a deal, and you can just change it later if it sucks. People will curse your name if you change your API, so bad APIs, where the author assumed he/she could measure once, cut an arbitrary number of times, ended up very bad.
However, I think that clarifying what indirection and abstraction are, and what they should be used for is good—I just don’t think the vitriol is appropriately placed, and I suspect that better advice for bad API designers would be to think longer before releasing a crappy API.
As Shigeru Miyamoto said, “A delayed game is eventually good; a bad game is bad forever.”
By Zed’s definition, an iterable is not an abstraction, it is an indirection to hook into a rich collection API.
It’s not like Iterable is a bad thing, it is a very powerful construct that can save you a lot of time, so the degree that you end up making your datastructure more complex is more then offset by the benefits.
The rant kind of reminded me of Rich Hickey’s simple made easy talk http://www.infoq.com/presentations/Simple-Made-Easy where he defines the terms simple and complex, then goes to show how many common constructs in programming languages make things easy at the cost of making them more complex.
It seems to me like it simplifies as well as indirects, but maybe I’m conflating easy and simple. The talk looks interesting, but it’s very long, so I probably won’t get to it soon.
I think that often indirection creates useful abstractions.
By Zed’s definiton, that’d be an abstraction, not an indirection. Note that an abstraction says nothing about how it’s implemented.
I’m not certain which part of my comment you’re referring to, so I’ll try to cover all of my bases.
If you’re referring to only the part that you quoted, I don’t think that Zed claims that the two are mutual exclusive, and I think that by “reducing coupling or dependence”, you can often “reduce complexity”. Refactoring code to use dependency injection often does this. Dependency injection lets you just inject the version of something that you’re using, you don’t have to have different code to handle each version of something. If you can indirect a “datastore” away from a “postgres store” and a “mongodb store” away to a storage object with a common interface, you can drastically reduce complexity.
If you’re referring to the part about iterables, it seemed to me like he criticized the idea of abstract classes because in truth they were indirect classes. The specific part of his post that I am referring to is this:
Even more proof comes from the fact that Java uses the keyword “abstract” to create objects which actually support indirection. Think about it, the “abstract” keyword doesn’t reduce, summarize, or generalize a more concrete implementation, but rather creates an indirect path to the real implementation of that function. If this “abstract” class were to follow the previous definitions it would simply reduce the number of functions needed to use the actual concrete implementation. But, when you implement an “abstract” Java class you must implement the same number of functions including the abstract functions just to get it work. Ladies and gentlemen, this is indirection at its finest and abstraction left the building years ago.
My main argument is that it is certainly indirection, but because the two are not mutual exclusive, it can also be abstraction. It in fact does “reduce, summarize, or simplify” a concrete implementation, by making the concrete implementations only have to implement the parts that make them special, and avoid most of the logic. It means that if I want to reason about why my iterable isn’t behaving the way I expect it to, assuming I can trust the library writers, my bug can only be in one of two places—where I say how to build an instance of my class, or where I say how to iterate over it.
Ah. Zed is bad at making this point, and it is a shame because it’s the entire point: abstractions reduce by virtue of composing (indirect) interfaces.
If you can take an implementation and remove all of its dependencies and create the most efficient function you possibly could, then the interface to this function would not be an abstraction. An abstraction does not have any defined performance behavior. It is simply the composition of smaller, well-defined behaviors. You may be able to replace an abstraction with a well-defined interface and implementation that is well-defined to the composed behavior, but the two terms are mutually exclusive: you’d destroy the abstraction when you destroy the composition.
The reason to split interfaces and abstractions into two separate things (and to understand the difference) is that you don’t care about abstraction performance and you refactor interface implementations to gain performance improvements. The abstractions are domain-specific languages that allow you to access the implementations. It’s not indirection because you don’t change the mapping to the implementations of that interface, the interface alone provides the indirection since we can change/improve the implementations. This indirectly benefits code that uses the abstraction, however, which I admit blurs the line, but the indirection occurs after the line drawn at the interface, not at the abstraction, which doesn’t change at all.
As someone who doesn’t agree with almost any of Crockfords opinions on js style, I am glad to see not being dogmatic about such things as “leaving adolescence”
With all due respect, ruby is extremely inconsistent (eg. spat operator), wildly complex (eg. eigenclass, argument binding), and is an extremely immature platform (debugging/profiling/performance). If you spend the time to gain expertise, you can look past these things
This feels like 7 languages in 7 weeks, where you spend enough time to have an idea what the language is about, but nowhere near enough time to really absorb the strengths/weaknesses, community, and ideas. For example, if you are not a lisp guy, and are doing this part time, you need at least a year on clojure to begin to get these things from it.
With all due respect, could you elaborate on “eg. spat operator”? How is the eigenclass wildly complex? I find the Ruby object model and hierarchy pretty straightforward.
I moved to Ruby after working qite a bit with perl and PHP. I was also doing Web development in Java (using an in-house framework that was very fast and very slick, so it was fun).
I picked up Ruby quite quickly, and found that most of the time if I guessed at how to do something I was right. The language has assorted inconsistencies, but it never occur to me to call it extremely inconsistent or wildly complex; if that were the case I doubt I would have stuck with it.
Over the years I’ve worked with Ruby I’ve determined that many things about the language are so poorly taught in books and articles that it’s wonder people learn anything advanced. Things are often made out to be more complicated than they really are.
I was being a bit facetious. What I am saying is that there are things that dont make sense in ruby (much more then a lot of the language the speaker covered), but at the end of the day after a few months with the language it doesn’t matter. A lot of the speakers complaints with other languages will pretty much disappear once you gain a level of expertise with them. You are only a beginner for a little while, and the problems of a beginner aren’t the problems of an expert.
Anyways, splat to gather params and splat to apply a list of args to a method are only related concepts on paper. When you are actually learning/teaching the language, it tends to be a pain point. And an invisible class in the lookup chain, plus multiple inheritance with modules makes “why something vs something else is called” much more complex then it is in pretty much any other language. On top of that, binding methods to the eigenclass of your class (which is an instance of Class) as the only way to have class level methods, is an extremely complex set of concepts that is in your face very early on. Ditto with method binding, making parens optional leads to some very non obvious corner cases that can actually lead to hard to see bugs.
Anecdotally , what I’ve found with languages is that those that are rigorous in their core principles become hard to use in the course of common programming tasks. If special or exceptional behavior is added to make common scenarios easier they usually come at the expense of language simplicity. This certainly seems to be the case with Ruby. Syntax and behavior were added to fit the Principle of Least (to matz') Surprise, at the cost of making other (possibly less common) things harder to do or harder to understand. I find it, overall, a big win, but I can see that if someone comes at the language with different experience or expectations it might seem a mess.
OTOH, languages like Ruby make it easy to jump in and start doing things without having to know jack shit about, say, eigenclasses.
Whether Ruby is any worse than any other language, I can’t say, because as you’ve mentioned by the time I’ve used a language long enough to run into things that break my mental model of the language I’ve already become accustomed to a lot and tend to forget how weird some things may have been at first.
This may be hard to judge objectively because that look simple (or not) on paper or abstractly may not play out that way for real people using to build real things. This is one reason I’m skeptical of any “7 languages in 7 weeks” deal because just knowing the syntax, without a good amount of practical experience, isn’t going to allow you to really assess a language. You have to live with it for a while to know what aspects are important and how well they work.
This might have once been true, but I don’t think it is currently true. I think JetBrains and Eclipse have evolved in ways that the original author never imagined in ‘04. If you learn the tooling for a single language in JetBrains or Eclipse, there will often be a plugin for other languages that has very similar keybindings. My hunch is that emacs is similar, although I have only ever used emacs as a text editor with syntax highlighting, or occasionally as a REPL (usually for python—I never used SLIME, and haven’t had good experiences with ENSIME, mostly because scala compiles so slowly).
Because tools work across many languages, learning tools is a force multiplier. Being an avid vim-scripter, or emacs lisper, or an eclipse junkie, will not only make you more effective in the language you learn it for, but also across all other languages. Yes, knowing the shortcut to compile a program will not be useful for an interpreted language, but it might be useful if you can remap that keybinding to use a linter. F3 goes to method definition will always be useful. Command+shift+t, search for the initials of a class to find where it’s defined in code is far better than using a regex egrep/ack.
Of course, there will always be some tricks which end up only working where the tooling is the greatest. One of my old mentors showed me a trick where he got around the problem where Java didn’t have smart type inference, and so you would always have to type your parameter twice, something that could get messy with a lot of nested generics, by using eclipse’s smart type inference. Instead of typing:
TYPE<TYPETY, TYPE, TYPE> x = new TYPE<TYPETY, TYPE, TYPE>()
he would instead type
x = new TYPE<TYPETY, TYPE, TYPE>
And then ask eclipse to fix his errors. The error was that he had omitted the type, so when it fixed it, it added the proper type for him. Three keystrokes (ctrl+1, enter) instead of many.
I think that this article is good in that it doesn’t necessarily pass judgment on tool-mavens vs. language-maven, but I think that it doesn’t promote being a tool-maven and language-maven sufficiently. I don’t think becoming a low-grade tool-maven is that expensive, especially if you’re not writing your own tools, and because of its force multiplying effects, I think it is very useful. Learning new languages is also important, not only because not every language is good for every job, but also because they make you think in new ways, which is in its own way its own force multiplier.
The one shitty thing for me about using powerful tools is that they are slow on my puny macbook air. My old dev box had 8 gigs of ram and 4 cores, so it chewed up eclipse like it was nothing, but my macbook air sometimes chokes on “organize imports,” which is frankly an embarrassment. When I just want to read-only a file, or know exactly the change I want to make, I usually use vim instead of tools I know better, just because of its short start-up time (unless I already have an emacs instance running, in which case I just fg it).
depends on what you consider as a new language. Scala is pretty popular and has a lot of traction compared to, say io. io is an amazing language, and learning it can really change how you think about OOP, but if you have trouble using a language not supported by JetBrains, you are SOL.
The other thing is that editors have their own form of productivity — they FAR outstripe IDEs in the act of actually manipulating text. An IDE will make that back with stuff like automated refactoring and smart auto-complete, but using vim with minimal language support vs heavy language support isn’t as wide a gap as jetbrains with minimal support vs heavy support.
The truth is, it doesn’t really matter what your first language is if your aspiration is to become a good programmer.
Learning to program well is something that transcends languages and platforms. Usually a community will focus on a specific aspect of solving the problems you typically solve with the language, and pretty much all of them have something to teach you. Even if they don’t, the language will.
But your first language probably shouldn’t be INTERCAL.
Nerd humor – awesome!
So assuming you are looking for a language that scales codebase size easier, why would you choose TypeScript over Dart? Dart has been baking longer, has a more holistic view of the problem, and solves a bunch of other WTFs in the language. I don’t think the subset of people doing JS that want this are big enough to support fracturing, and Dart is so obviously a better solution then this, it is very hard to see it getting anywhere
TypeScript supports more editors, and key editors at that. http://blogs.msdn.com/b/interoperability/archive/2012/10/01/sublime-text-vi-emacs-typescript-enabled.aspx
Dart supports the Dart editor and the jetbrains editors.
Both languages are fully open source. Typescript uses Git. Dart uses Subversion.
I haven’t used either, but I personally am more inclined to try TypeScript due to the editor support and because I’m assuming it will have a smaller learning curve than Dart.
From what I understand, both are optionally typed (meaning you don’t have to use type annotations, but if you do they will be checked at compile time and ignored at runtime)
The reason typescript has more editor support is because it doesn’t go as far, which is basically what I was trying to say — If you are going to make the jump to a pre-processor, that why not use the thing that is more fleshed out? If all you want is type annotations, why not use the google closure compiler which gives you that without having to go to a pre-processor?
I had never used the google closure compiler so i played with it a little after reading your comment. The compression is great but I found it to be pretty opinionated. It also requires annotations for type checking which TypeScript does automatically.
It’d be interesting to see a side by side comparison of the various options. I’m going to put that on my list of “good ideas for a blog post” (which is already filled with lots of out-dated never completed ideas.)
honestly, acme is the only editor listed in the same league as emacs or vi, and TextMate/Sublime were pretty glaring ommissions
Agreed, Acme, ed, teco are epochal text editors whereas some of the others listed were mostly intended to be “autobiographical” and to spark discussion. IMHO there aren’t really that many big paradigm shifts in text editors aside from modal/non-modal and maybe terminal/gui.
Hey guys, I’m the author behind Shortcat. Feel free to ask me about the app!
The screencast odin posted is pretty old; I’ll be doing an updated one this weekend.
As a HUGE fan of things like ace jump mode in emacs, this just made my month. Thank you so much for building it!
Glad you like it! The other benefit I haven’t listed on the site yet is hopefully as it gets more popular, more app developers will make their apps more accessible, which would benefit people who actually use the Accessibility API for screen readers etc
I can’t type anything in the cat window after pressing cmd+shift+space. Is this a bug?
Are you on Lion? I’ve heard reports of this bug happening more often on Lion. Restarting Shortcat should fix it
Mountain Lion. It works after restarting the app.
Happened again. App is unusable if I have to restart it every time.
It seems to be a bug with OS X itself… I’ve already tried a few workarounds but I haven’t been able to reliably reproduce the problem which makes it rather difficult to fix. Currently looking for someone who can help me reliably reproduce it, but I might add a shortcut to restart the app as a temporary hack.
I’d like to see the usage dialog again, how can I access it? If I double-click on Shortcat.app again, it doesn’t show the dialog.
You can access it via the cat icon in the menu bar and clicking on “Help”, otherwise you can go to http://shortcatapp.com/readme.html
just wait for the huge flood of issues related to js globals sticking around between page loads, js memory leak issues which don’t manifest until you take reloads out of the equation. Not saying pjax is not a good idea, but it isn’t magic fairy dust you sprinkle and things get faster. There are a certain class of issues that you didn’t need to be aware of before which you now do.
there are already a bunch of people trying and fixing this, there were a bunch of issues, PR and mostly fixes just today.
Certainly not production ready, true, but for pet projects, why not? :)
I like what he is saying here, but I’d like to actually see the talk. I hope they have a video come up.
Seems that Gary is pointing out that our industry has pointed its self in a certain direction and is charging full steam a head. Building on abstractions we don’t really fully understand, and then building on top of those. I think he’s arguing that while yes we can do so much more with our machines and code, we really haven’t taken the time to revaluate where we are going and if its really working.
I think its a valuable discussion that our young industry needs to have.
isn’t the whole point of abstractions to be able to build on them without having to understand the full implementation?
Yes it is, but how many of those abstractions are bad? It’s like building on a swamp and hoping it doesn’t eventually sink.
His argument is that just because someone abstracted this is away once doesn’t mean we should all stop finding better ways.
I really wish we had a ‘-1, terrible, terrible troll’ voting button.
I found the rhetoric in this article incredibly annoying. I understand the point that was trying to be made, but seriously, I could barely get through it. The twisting of words to come up with some sort of inflammatory statement really grinds my gears.
I came away thinking the same. There’s really no reason to inject such vitriol into an article about programming. It’s a good example of what makes parts of programmer culture unpalatable to many, to the detriment of all.
This is an argument that is older (and about as useful) as vim vs emacs, where the people who engage the most aggressively typically understand that actual pros and cons of the other side very poorly.
I guess anymore I just read past the troll comments in articles, and was more hoping to raise up interesting conversation. My bad.
It happens! I myself had a submission here voted to -1. We’re all figuring out what the hell this place is, still. :)
Bluster aside, I think the point about typed vs classified is worth some thought. It’s obvious to anyone who’s written a ruby or python C extension that every object is represented as a single type, the PyObj or ruby_thing or whatever it’s called.
Of course, the author is an ML junkie who thinks type inference is the solution to all the “I don’t want to type so much” objections to static typing. I found it frustrating because until you learn to pattern your program into something the type inferencer expects, it will just keep beating you with the “can’t do that” stick.
For the record, I feel static typing is much safer and leads to better programs, but still prefer Lua just because it’s easy. Like vegetables, I know it’s good for me, but I’m not going to eat it unless I have to.
This is especially true if you subscribe to the ridiculous Church of 80-character Lines.
If I am getting anywhere close to 80 chars in ruby, generally I am being ridicules, and almost always leads to an extract variable.
It’s not a hard and fast rule for me, often string literals will cause a line to wrap. but it is a great guideline (at least if you are not using a super verbose language), and leads to readable code.
really nice complement to traditional automated acceptance testing. Never seen anything like this, but it would be an amazing tool to catch regressions for larger applications
Mostly I’m curious: aside from VimScript (which, at this point, I think is honestly a straw man in these conversations) what is it about Vim that its users don’t like? I’ve been using Vim for about 18 months; I’ve put together a vimrc that works for me and a small set of plugins that add functionality that I find useful.
What is it that drives people who really grok Vim to explore other editors—and then do their best to make them like Vim?
VimScript is more than just a straw man, IMO. VimScript is the entire gateway to extensibility of Vim and it’s abilities and flaws directly affect the experience in the editor. The main thing other than VimScript is how atrociously it handles external processes — especially if you want to interface with that process via a buffer (e.g. a terminal, REPL, whatever). Vim’s extensibility model is also complex and finicky.
Don’t get me wrong… I put a lot of love into my .vimrc to get it right. But, when I have to use another editor, the things that are truly integral to the essence of Vim and the powerful abilities it brings are actually a pretty small part of Vim.
I explored Emacs mostly because I was doing more Lisp and, being partially written in a lisp, Emacs' lisp support (esp with things like Paredit) is phenomenal.
I had a pretty elaborate vim setup https://github.com/mbriggs/dotvim, and now I am using emacs with evil. I’ll go through the reasons why, with a giant caveat being I actually don’t care what editor anyone who reads this uses, so long as they learn it and it works for them. As someone who has used both, vim shines for people who aren’t in to heavy customization. You can heavily customize vim, but it is so easy to make it dog slow, and even with a ton of work you won’t hit what you can accomplish in emacs. Here are some examples, and also essentially why I am no longer using vim, YMMV
If I want to run a command and have it pipe to another buffer AND not completely lock up the editor, I can do that with a few lines and compilation-mode. This is next to impossible in vim. I can split my editor window and have a shell running on the other side, that i can use all the keys and tools on that I use to edit code, again, not possible in vim. I can have a repl connected to my editor that the editor uses for auto-complete targets, and to pass code to to evaluate it. You can fake some of this in vim with a bunch of hackery, but it is nowhere near as nice.
There is also a pretty wide range of modes that are possible to do in vim, but for whatever reason just aren’t there. Some I use constantly all day:
smex lets me fuzzy narrow a list of all commands in the editor to find what I want (kind of like sublimes command pallet)
auto-complete will put up a light grey outline of text as you type if it finds things you can complete, if you want to select it you hit tab, if you ignore it it won’t intrude on your life.
magit is sort of like fugitive, just way more full featured, and the UI is quite a bit nicer. I have tried a bunch of git gui tools, and even those costing ~80$ really don’t hold a candle to magit (once you learn how to use it)
flymake tells me about syntax errors as I type
js3 mode has some of the best js indentation I have seen, and does full AST parsing, which means it can tell you things that are wrong with the code as you type. Linting on save works as well, but this is nicer.
org-mode is an amazing tool for many things. I use it for notes, team brainstorming sessions, todo lists. Lets say I am testing a csv output, if I paste it into an org mode buffer, I can c-c |, and it becomes a tablle that I can navigate, modify, sort, etc. Haven’t used any general purpose structured text tool that even comes close. If you pair it with deft, and store your org files on dropbox, you can have an amazing searching interface to a directory of your notes/todos/etc that auto-backups/replicates.
This is just scratching the surface. calc-mode is the most advanced calculator app i know of on my computer. regex-builder i use regularly. IDO mode is so sweet it is really painful to watch vim people use :Explore
Finally, the last piece is elisp vs vimscript. I got to the point with my vim usage that I needed to learn vimscript to do what I wanted to do, and I hated it. elisp has its own quirks and baggage, but it is so far ahead of vimscript in every way that you can barely compare the two. vimscript is a giant hack tacked on to a massive existing set of commands, compared to emacs which is an elisp platform that happens to have implemented editor functionality.
The formatting of your comment got messed up – it’s all one big paragraph. Here’s a version I made that corrects that, making the comment easier to read.
Use two consecutive newlines for a paragraph break, not just one newline. See my version’s Markdown source for an example. You can check your formatting with “Preview Comment” before posting.
I wish I had read your comment before reading the entire über-paragraph.
I think I actually hit some sort of bug. It was nicely formatted, but I edited, which created a new comment. Then I copy pasted the edit into this one, and made mega-paragraph. Now I cant edit :(
Makes me jealous. I would love to build tooling like this, never worked for an employer that valued these things enough to let me do it.
If it’s worth it, find the time. You may just inspire the ones making the decisions of what is ‘value’.
There is always a balance to made between investing in infrastructure and banging out the minimal set of things to take you where you need to be next. It’s also very difficult to know what is the best move to make at any given time. In my experience some organizations more heavily favor infrastructure investment (e.g. github) while others do not. If you’re in an organization that is biased against infra development then you’re going to need to work hard to sell your ideas…
Infrastructure at my company isn’t the highest on the list of things to do. It’s sad to say we’ve had to almost fight to get time to maintain infrastructure. Maybe it’s because I’m young and dumb but I’m working on tooling exactly like this post funnily enough. It needs to be done but it’s not exactly “my task for the week”. If anything I’ll write it off as a cost of making my future tasks easier to solve.
I’m not exactly “selling” the idea, it seems I’m doing it for free.
This is why most oldschool newsgroups and irc channels used to tell people that they aren’t going to get answers there that show up on the first page of search results when you enter your question into google. I remember getting booted from #java on dalnet many years ago for answering a super basic question on exceptions, when I asked why the response was that they didn’t want it turning into what you describe here. I know nowadays everything is super newbie friendly, but by supporting those kinds of people you aren’t doing them any favours (in the long run), and the time you sink into them can be spent exploring more interesting problems.