" but at some point I decided that the widget was no longer needed, so I commented out the widget's markup"
SOURCE CONTROL, DO YOU SPEAK IT?
In all seriousness, this is a major peeve of mine - the time that you're most confident that code can be deleted is when you're removing the pieces that depend on it. If the deletion really turns out to be wrong, you should be able to restore the code from source control. If you can't, stop using broken source control.
Leaving leftover dreck in your source files "just in case" is like stashing your leftover sandwich crumbs in your pocket at lunch. Clean up your mess!
The mental effort required to find and pull the old code is far greater than that required to toggle a code comment, or just the line using that code. The author rightly points out bad behavior by Ember: Unused code should not affect program behavior.
Yes code should be deleted and then later recovered from source control.
In the event it is needed to be glanced at or restored, but you're exaggerating how problematic commenting a method out of code is. If I'm scrolling through code and see a commented out method my brain says "well that's not in use" and I move forward.
If a commented method stays in code for a few months I would complain or simply remove it myself, but it isn't hurting anything (unless in the case of Ember).
Commented-out code is a "FIXME" to-do item that has no explanation of intent. If I comment out code, I always annotate it with a @todo marker and an explanation of why it is commented out. Otherwise, just delete it - commit message becomes the documentation.
I generally don't like seeing commented-out code in source control because you don't have any idea why it was commented out. Is it something that you added to debug while in the middle of a bug fix, and thus now useless? Is it a half-done refactoring that you ran out of time for or ended up not needing? Is it an attempt at a speedup or new feature that didn't work out? Did it have some tricky bug and get replaced by code that fixed it?
I can't think of any reason to do it that isn't a half-assed attempt at something a good source control system does much better. If you have lightweight branches, blame, and logs you can search and check by date, along with good changeset comments, then you already have everything your commented-out code can do, and all in the same place and system, instead of spread out into several different systems.
The scary part for me is uncommenting it, because the code has been removed from normal QA and testing (automatic or manual) and you don't know what evils you are unleashing upon the world.
That's because you're not using Haskell. :) Herein lies the crux of my point. Haskell's purity and strong static types allow you to make lots of very strong assertions about what kind of evils you might be unleashing.
True, but I find commented out code really distracting while I read a file. It's really easy to use the comment method to excess and end up with a file full of old trash code.
As far as Ember's issue, we didn't see the actual code. There's almost certainly a misplaced pointer somewhere. The author made of not being a JS regular, my guess: missing `var` somewhere.
If there is so much commented code that you can not read, delete it. If I'm not sure whether I will be putting the code back soon, no way I'm willing to dig repository history.
However, commented out code is by definition free to be deleted by anybody else if it happen to be forgotten later on.
In this day and age, why isn't there an automated way to keep file history? (like Dropbox does, but locally and with a decent interface) I am looking for something like that for Linux and my (admittedly short) research didn't turn up much.
I always use local lightweight tag objects in git for this - if there's a commit that I'm not sure about somewhere along the line I'll tag it REVERTME or something like that.
I can't even fathom this mindset. Deleting the code and relying on source control removes the issue from top of mind. Also, it will require more work to bring back later. Both of these are very good reasons to temporarily keep commented code around.
> Deleting the code and relying on source control removes the issue from top of mind.
That's the goal. Your top of mind is very limited; use tools like version control to help you conserve it.
> Also, it will require more work to bring back later.
Then you need better version control. You can either grab the reverse diff from the commit removing it and apply that (possibly with conflict resolution against more recent changes), or just grab the original file and copy the block of code out of it.
> Your top of mind is very limited; use tools like version control to help you conserve it.
Seeing a commented block scroll by doesn't waste top of mind. And if you really don't want to see it editors have something called code folding.
> Then you need better version control.
Have you ever tried searching a version history with thousands of commits to find a piece of code that you think you might have written awhile back, but you can't remember enough details about to come up with a good search term? No matter how good your version control is that's going to be a tough proposition.
> Have you ever tried searching a version history with thousands of commits to find a piece of code that you think you might have written awhile back, but you can't remember enough details about to come up with a good search term?
I find that a `author(..) and file(..)` (hg) query gets you at least 90% of the way there if you have things split into a reasonable number of files. From there, running through a few guesses about search terms or even scanning the commit messages is pretty feasible. Date ranging can help, too.
There's so much data in source control - don't navigate by just commit messages.
Tag commits which delete things you suspect you may want to restore later with a descriptive name and message. Occasionally go back and prune those tags when you have nothing better to do.
This assumes that you knew that the code was once there, and where it was. Working on a team with partially implemented features with planned future hooks, it's just easier to keep the intent in the live code (hopefully with some good comments/docs)
Your half-implemented feature will never, ever make it into live code.
Ever.
Just delete it, you commented out code leaving scum. We all hate you. And you smell.
But seriously. Never commit commented out code. It's a cardinal sin and massive code smell. Never leave YAGNI, but maybe one day, hooks in code. Just delete it. It will never make it live and when someone actually comes to do that feature they'll usually half finish the feature before they even find your code, and then won't be 100% sure your code is supposed to do exactly the same feature and so they won't delete your cruft as they don't really know what on earth it's supposed to do.
And on top of that your code won't work because it hasn't been refactored along with all the live code, so all the property names are wrong, it references methods with signatures that have changed and probably even the names of the classes have changed.
Seriously, though, we do it all the time. Successfully. We even write skeleton code, and have other people finish it off, or take the half-baked idea and implement it properly. Sometimes in this sprint, sometimes in the next. We tend not to let these things stagnate though, so if the spec changes, the ideas are usually ripped out along with them. A lot of the cruft eventually comes out during code reviews...
It's definitely an anti-pattern, using one's code base to communicate....but the right team with the right processes, can work for the short-term. (short-term vs long-term is probably the key here)
This wasn't a half-implemented feature. It was a fully implemented and debugged feature. I was experimentally removing it in favor of a different approach and didn't want to have to go dredging through source control or reinvent and debug it later if I decided we needed it.
"dredging"? It sounds like you aren't very familiar with your tools. Commit, delete the code, commit. Now you're a rollback/backout away from getting it back.
I agree that keeping commented-out source around is bad, but commented-out source should really not affect program behavior. The typical way of testing the removal of something is to comment it out, see the results, and if you like them you delete it and then commit.
I hear this sentiment a lot, and I at least understand the sort of purity of deleting code instead of commenting it out, but that's the only value it seems to bring whenever I try it.
Scrubbing back into history (or remembering that there's even something to scrub back to) doesn't seem to ever be as convenient for me as it is for people that are peeved by commented out code.
I'm not that great at Git, but I'm also not trawling through history very frequently and there still seems to be a mental overhead associated with it compared to seeing some commented code a few lines away.
The article goes on to say:
> I wasn't sure whether we would ultimately keep the
> widget or not, so I opted to keep the above
> javascript code for the controller and view around
> for awhile so it would be easily available if I
> later decided to re-enable that UI element.
That seems reasonable to me.
In a file I was just working on before I decided to habitually check HN, I have two past versions of a function commented out above the final revision of the function. Next to each older revision, I've annotated some reasons why they were revised. When I continue to work on this function a week from now, I'm reminded of my efforts so far.
Someone would probably say that those annotations should be moved into commit messages and the git log should tell the story about this function.
But all that really seems to do is disperse my notes about this function across intermittent entries into this file's commit history. And once those past revisions are deleted from the current view of the file, I certainly won't remember that those notes exist for me to scrub back to in the first place.
- How do you manage this kind of stuff?
- What's your workflow for looking for and fetching deleted code?
At work, our approach is to simply not allow commented out code to get through code review. It allows individual developers to comment out blocks, and even commit those comments if they so desire, but they never make it into master.
While you're not wrong, this doesn't speak at all to the issue that the OP is expressing. While you might think his/her style is messy, it should still be valid. Commented-out code should behave the same way as deleted code.
> Commented-out code should behave the same way as deleted code.
But it did, that's not the problem the author encountered.
The issue wasn't that commented code caused a behavior change, it's that uncommented-but-assumed-unused code caused a behavior change. The only thing that got commented out was the markup that originally invoked said code.
OTOH, finding removed code in your history is still a pain in the ass, unless commit messages are well and clearly crafted (which they usually aren't, and even then the keywords you search for may not be those you committed under).
VCS may need to grow a "full history" blame, which displays all hunks removed from the file.
I compleletly agree. But I will add that another solution is to keep the code alive, but wrapped in a conditional with a feature flag. This is not always a good alternative to just deleting code, but it can be a good alternative to commenting-out a block of code or using compiler directives.
I'm an experienced web developer (Backbone is my preferred framework) whose team is migrating to Ember. It has its high points, but on the whole, it's been driving me nuts.
Ember, like most modern frameworks, represents itself as MVC. But it's more like MVCLCTMRA (model-view-controller-layout-component-template-mixin-router-application, if you're following along at home). There are just so many moving pieces, and there's a lot of overlap between them. Should I be using a layout, a view or a component here? They're ALMOST the same, and they don't always vary in the places you'd expect them to. Also, the "model" portion, ember-data, is fairly immature and doesn't seem to be anywhere near production-ready.
There are also some design decisions that just leave me baffled. If templates are supposed to be the ideal place to declare stuff, why does a view's root element have to be declared in a bunch of JavaScript properties instead? Why do some of their camel-case names (e.g. RESTAdapter) violate the (fairly strict) naming conventions they enforce in user land?
I don't hate Ember, and I'm sure it perfectly fits the mental schema of at least one person on the planet, but it doesn't click all that well for me. And it's abstract enough that I don't think working through problems in it is making me better at anything except Ember.
It's also probably worth mentioning that about 80% of the documentation online seems to be in the form of StackExchange posts, and about 80% of those are obsolete, as Ember has gone through a lot of radical changes in the not-too-distant past.
If you're experienced with Backbone but want something that competes with Angular/Ember in terms of features, you should really try CanJS[1]. It has a small API surface area so it's very easy to learn but still manages to bring advanced features like Web Components to the table.
From reading those, it should be pretty clear how layouts differ. I admit that it may be a bit less clear how views and components differ. Components are actually a more isolated type of view. Views have been around for longer, but in the future, we're going to discourage people creating custom view classes in favor of using components primarily. If you're not sure whether to use a view or a component, go with a component first.
2) Ember Data
Ember Data isn't a part of Ember Core, and for a good reason. While Ember Data is certainly a useable product (myself and many other do use it in production), it's not yet as mature as Ember Core (hence still being in beta). If Ember Data isn't good for you yet, you don't need to use it. Discourse is an example of a large Ember app that completely forgoes Ember Data.
3) Templates and Views
The template is rendered inside of the view's element which explains this. Alternatively, specify `tagName` as a property when using `{{view}}` or a component helper.
4) Documentation
The guides have a ton of information so you should definitely look there first. Also, if your company is really investing in Ember there are some good paid trainings available, including online courses. Tilde, my employer, has an online training (http://www.tilde.io/events/introduction-to-ember-online/) as does CodeSchool (who I do not work for) (https://www.codeschool.com/courses/warming-up-with-emberjs), among others. Since Ember has reached 1.0 a number of months ago, the API has stabilized and documentation will be valid for much longer.
I've worked on large javascript applications written in Ember, Angular, JavsacriptMVC (now can.js), and jQuery and the conclusion I've come to is that things have not settled down in the world of front-end development enough to justify a framework as opinionated as Ember. For example, Ember relies very much on routing being handled a certain way. In fact, much of the magic in Ember comes from the fact that it's making a lot of assumptions about how routes are handled, constructed, and organized. This is great if you can assume that an app's routes will be written in a very traditional way, aka one route per page. It breaks down however when you want to tie different routes to two or more components on the same page (i.e. two different tabbed sections). One concern per route makes perfect sense on the server when serving a traditional stateful web application but it often doesn't make sense for rich desktop-style applications (which is probably why Photoshop doesn't have urls).
Data persistence on the client is another area I feel hasn't been nailed down in general and thus can't support a lot of opinionated assumptions. Should data be persisted at all? Ember caches data from all requests to the server in a "store", but it's not clear how you keep that cache up-to-date. Perhaps you could use websockets to keep resources current but at the time I was using Ember there wasn't a clear, well supported way to do that. I think the jury is still out on whether we should be duplicating our schema on the front-end at all but Ember-Data has gone all-in on mimicking ActiveRecord. Again, the dust has not settled in a lot of areas of the front-end development world as far as I'm concerned so I don't feel comfortable with these decisions being made for me.
I tend to lean toward convention over configuration. On the server I'm a big Rails fan but I feel like it's solving problems that aren't moving targets. On the front end I prefer Angular because it solves the main headaches (two-way binding, testability, modularity) of front-end development without being too opinionated about the stuff we haven't reached consensus on.
I've found this true in general - front end, back end, you name it.
Every time I've used multiple decoupled libraries instead of one large framework, things have gone fine. If a particular library isn't working out, I just swap it out for an alternative (or roll my own, if worst comes to worst) and continue building.
Every time I've used a large framework, I've ended up with major buyer's remorse. There's always at least one particular piece (like routing in your case) that's a bad fit, but everything is so tightly coupled, I can't just swap out the offending component without causing problems elsewhere...so I often end up accepting a bad fit.
For me, the productivity gains of big frameworks have always been outweighed by drawbacks as soon as I hit nonstandard use cases. I always find myself wishing I'd used multiple smaller, decoupled libraries instead.
I'm confused. Are you proposing that web apps don't use URLs? If so, this seems pretty antithetical to the very nature of the web. One of the things that often aggravates people about web apps is that the back (and refresh) button is often broken because of a disregard for URLs. You can see Tom Dale give a defense of URLs here http://2013.jsconf.eu/speakers/tom-dale-stop-breaking-the-we....
As far as Ember Data goes, this is something that it's clear that a lot of people do indeed want. That said, you can use Ember perfectly well without Ember Data (see Discourse for example).
It's funny that you point to Rails as an example of consensus, because when you look at the server-side development community as a whole, there is certainly not consensus that the Rails way is correct. I wouldn't expect complete consensus on the client side any more than I would expect complete consensus on the server side. Rails (and others) have shown that you can have multiple healthy ecosystems each with their own points of consensus.
I'm not proposing web apps don't us URLs. What I am saying is that the lines are being blurred as to when a web app should use urls and when they shouldn't. When I click a tab on a nested component in a larger page, should the url route there? Should the url route change when a modal pops up? If an accordion control slides open should the url change? Not sure? Neither am I. Routing on the web is not as simple as you're implying it is.
You're right about ember-data being optional but I mentioned it because it's what we were using on the project I was on.
I guess what I meant when mentioning rails was that there's a lot less change happening on the server-side than on the client-side these days so it's easier to confidently build an opinionated framework there. It's hard to favor convention over configuration when the very platforms you're targeting don't have established, agreed upon conventions.
I attempted to use Ember in side projects for quite a while, really dove in. Sadly, I never got productive with it. My conclusion was that Ember works for super smart people with a background in traditional MVC UI architecture (different than MVC server architecture), but that mortals like myself probably aren't up to the task.
I moved from Ember to React, and it has been a joy. It does what I actually want: makes interfaces easier to develop, lets you build your interface by composing parts together, lets you write view functions that are as smart as you are (no crippled templates like Ember/Ng). It is basically a simple low level building block that makes a lot of other stuff easier.
Anyway, as a non-genius developer who nonetheless has written a lot of javascript, React is my strong preference. Their approach is beautiful and simple.
It might not be so much a genius vs non-genius thing so much as your particular app not needing the heavyweight app-state management that Ember provides.
It's worth pointing out that the Ember core team has been approached by the React core team with the intent of unifying React's view layer with Ember's application state management, which is a major component of what Ember offers relative to other frameworks. If you haven't had to solve major problems with navigation, routing, complex nested async logic, etc., for the particular app you're trying to build, then it sounds like React would get you most of the way there, but even the React team themselves realize that for medium-large scale apps, React's only going to take you so far.
Ember's approach to watching for changes is pretty different. Also, the Ember view layer refactor codenamed HTMLbars has yielded some extremely promising (though admittedly early/premature) performance improvements that often outperform the React equivalent. So we're open to the idea and we have much we can learn from each other but we're not going to merge in React if we can do a better job :)
For me, and I think most people who get excited about it, performance isn't what attracts me to React. It is the semantics (is that even the right word?). The nice way it lets me think about things.
It looks to me like htmlbars is handlebars emitting DOM rather than string. In that case, I think it will be missing the benefits of React. Again, though, I obviously don't understand Ember well.
I haven't handled routing yet, a lot of people seem to use https://github.com/flatiron/director, which I would probably do. This is the one area where I missed something from Ember.
For models, I've just rolled my own so far. I've experimented in one small project with having a global state object that cotnains all application state data, and then just having domain fns that operate on that data. Inspired by the react people's descriptions of "flux" architecture. It felt really nice.
When using Ember, I got really confused by Ember's Ember Data vs. Ember Model vs. whatever conversation. Again, I just didn't really know what to do here, and I attribute it to my own shortcomings.
Yeah, it kicks your ass when you're just getting started and helps you move somewhat quicker once you have experience. But I have observed what you point out many times. I'm not sure it's worth it, in the end. You learn how to Google error messages, that's for sure.
It depends on the return value, yes. I usually try to keep modules small and use some kind of threading (needle + thread analogy, not os threads/web workers) strategy when building functions -- pulling out common patterns into globally visible utility functions that work with common types (e.g. jQuery events/objects).
It's not ideal, but in the absence of a true type system, it's all about mitigating potential problem areas.
He points back to static typing, but honestly I think UI code is harder to keep organized than service code (which I presume is what the Haskell backend does). Usually it's the UI that has to swallow the biggest chunk of the mismatch between the programming model and the user model – and as you move to smarter clients like you would with Ember.js, you end up pushing nearly all of that to the client. And you have to start interfacing with substantial complicated pieces of code, like the browser, code that every UI has to not just use, but negotiate with. All this complexity can be a way of coping with this system – not just coping with the system of a dynamically typed language, but all the many conflicting constraints in a browser environment implementing a UI for real people.
That said, there are differing opinions on which part you should "simplify" through a framework. Some of them are going to feel more magical than others. And when you come in with preconceptions about what makes a good environment, you're going to think about how the framework and environment lives up to your ideal. Some things you fix, some you leave as they are – and choosing the right battles is incredibly important. But service code and UI code are different sorts of warfare against complexity, I'd be skeptical of intuitions across the two domains. (None of which means Ember.js gets it right either – but if they don't, then I doubt the why is they just need a statically typed language.)
I've actually wondered some of this myself. I think the answer is that it's some combination of both inherent complexity in UI code AND problems that you get with weak and/or dynamic languages. In any case, we're probably going to switch all of our front-end code to Haskell, so I should be able to make a comparison at some point in the future.
Zombie Code Apocalypse: I would love to help you identify what it is that caused that problem. I don't suspect that it is an issue with Ember itself, though note that the Ember resolver will load code when you store it in `App.Foo(Controller|View|Route|...)` if that code is "needed" (say, by visiting the Foo route). So, unless you commented out the entire declaration it is entirely possible for that code to execute.
Spontaneously Changing Values: What was the key that you were trying to set? On what type of object (Route, View, Controller, etc.)? There are indeed some special values and it might be something that Ember can warn you of in the console as well as be documented. I'll be glad to make some documentation changes that make this issue easier to catch if you can provide me reproduction.
Godlike Refactoring: I work on a team with a widely distributed level of skills. One of my favorite features of Ember (which both has and will continue to save me hundreds of hours) is the fact that even if you make a mess of something you can generally come back and clean it up one piece at a time. My metaphorical description of this is that "all of the crap is in nice neat little piles instead of spread on the walls."
JavaScript.next: In the next/current version of JS both of these warts should be possible to resolve using Modules and Object.defineProperties(). I firmly believe that your complaints are not centered around Ember (which I honestly believe is insulating you from the worst of it) but instead from flaws in a language that was literally designed and built in an incredibly short time (my recollection is "a week" but I can't find a source).
Just a nit for accuracy, but the implication that "the Ember resolver will load code when you store it in App.Foo(Controller|View|Route|...)`" eagerly is not true. I believe the author use an HTML comment to comment out his usage and not a handlebars comment, so the code was still being run (just hidden behind html comments).
But regardless, Ember will not load everything in the App. namespace blindly- it will wait until that item is required, then try to load it.
This is your helpful Ember #protip for the day. :-p
I've edited it for clarity based upon my original comment. :) I actually rely on this behavior every day because the app I've built uses require.js to load values into the `App.` namespace dynamically.
That being said, now that you mention it, it seems far more likely that the issue was HTML vs HBS commenting. As an aside, what is the default behavior going to be for HTML comments inside of HTMLBars templates? That seems like a really weird edge case to decide how to handle (for developers).
Oh my man, you really need to dig into the resolver! You can avoid the App. namespace entirely if you already use modules. This is what Ember-App-Kit and Ember-App-Kit-Rails already do with ES6 modules, just transpiled to AMD internally.
And yeah, I'm unsure of that the behavior will be in HTMLBars. I really hope it doesn't touch logic inside HTML comments- that would be quite nice.
We started on this project using Ember 0.9.6 (though we've managed to keep up with HEAD) and much of our architecture is predicated on the toolchain choices we've made. Our first big task on our list after reaching feature-complete is to migrate to EAK, don't you worry. (We knew it was coming and adopted require to make it easier to migrate.)
Scala dev here who sometimes needs to do some JS (though haven't worked with ember). I feel your pain! Static typing and functional programming certainly make ones life easier once a project becomes bigger.
Anyway, for future reference, you may want to learn how to use the JS debugger (both Chrome and Firefox are quite good). You could have set a break/watchpoint on the variable 'foo'. Once it has changed, you can inspect the stack and would have found that the set('bar', ...) method was involved. Should be much quicker than printf-debugging...
I use the debugger all the time. One problem is that when you're using Ember a lot of the call stack is cluttered with Ember internal calls, which obscures things. But even after I isolated the problem down to that line, the debugger still didn't help me fix the problem.
I seem to remember reading that chrome added the ability to "black box" libraries to remove them from the debugging call stack to help with situations just like this.
I think this is the culture shock of not working with a compiled language.
I mostly work in compiled, statically typed languages, and it can be a bit of a surprise in Javascript when you don't find out about a syntax error until execution just stops, half way through your application loading, because of some code in a function you didn't think was called.
It's a surprise. But that doesn't mean it's wrong. We just aren't using the right tools - unit tests, JSLint, etc.
Question to regular JS users - what do you do 'in place' of static checking?
Yep, compilers turn out to be a pretty cool idea :).
I don't think anyone's doing anything 'in place' of static type checking exactly. Oftentimes I'll check if a method exists on an object before calling it. Usually when I'm "type checking" I really just want to know if an object has a certain attribute. That gives a fair amount of flexibility because polymorphism is built in.
I think by and large the errors that would be compile-time errors in a statically typed language are caught with unit tests (I use mocha). For front-end work, end-to-end testing has also gotten quite good and easy. Take a look at karma if you're interested in a good front-end testing workflow.
JSHint is helpful, especially (I think) for people who don't write a ton of JS. Unit tests are obviously important. I've been using Istanbul lately to check my test coverage, and that's made a big difference. It's awesome to be able to see, quickly, that "Oh. I'm not even testing half of this function."
Sticking to some kind of style guide also helps. Idiomatic.js is a good starting point.
Also, doing some basic checking on your own is often a good idea. Look at your arguments, make sure they're what you expect, and if now, throw an error. That'll make it a bit easier to see where your problems are, since you won't have to dig around stack traces as much.
Generally speaking, in dynamically typed languages, unit tests are the replacement for compile-time type checking. Type safety should not be a goal, duck typing is embraced and the correct behaviour is verified.
jshint is static checking. It would have caught your syntax errors. Even catches when you do something stupid like define a new function inside of a for loop. As far as type checking, typically it's not needed and can be confined in functions that care about types, you just defensively cast to the type you need. Closure's also an option if you really make heavy use of types of your application.
OK, so that's a very link baity way of saying. I don't know JavaScript or how to use source control and when I come across unexpected behaviour in my code I don't take the time to understand the cause.
JavaScript is hard, it's a very loose language and it's implementation in browsers sets you up for all sorts of falls. If you're going to code using it you either need to be disciplined or understand it intimately, preferably both. The problems in the article were not caused by Ember.js
> The root of the problem is the system we were operating in: an impure programming language with weak dynamic typing.
Is it really fair to blame this on dynamic typing? Having setters with side effects seems like a design decision to me, and not one that is easily supported. I would be interested in hearing an explanation of why this behavior is javascript's fault.
I'm not blaming it definitively on dynamic typing. I'm blaming it on the overall system of incentives that I have observed seem to come up a lot more frequently with impurity and dynamic and/or weak typing.
In a pure programming language with strong static typing this effect would simply be impossible to produce in a way that wouldn't make the problem obvious.
The things that are frustrating about writing an Ember app are the things that are frustrating about Javascript in general.
Those "set" and "get" calls are a great example: they're an unfortunately necessary workaround for Javascript's lack of real dynamic message dispatching (like Ruby's method_missing). We all look forward to ES6 fixing this.
The run loop is another example. It's a gross hack that wouldn't be necessary in a nicer language that managed its own runloop internally. Javascript developers who are ignorant of other paradigms often make the false claim that all the callback-driven asynchronicity is worth it because of performance, but they fail to realize that you can have exactly the same asynchronous architecture while writing code that reads synchronously.
I don't see how this relates to the problems posted in the article. How does the lack of Proxy make the behaviour less confusing? Where does the author mention asynchronous behaviour and JavaScript's run loop?
I was just commiserating and sharing my own experience.
The problems posted in the article are really hard to judge because the author doesn't actually explain what happened.
In the first example, he doesn't try. Fair enough, it's a judgement call on whether to spend time understanding what happened. Personally, I would consider it high priority, because otherwise you have no assurance that the same problem isn't biting you elsewhere.
In the second, he says something that doesn't actually make sense: "Ember's set function has special behavior for values in the content field". I know Ember's source about as a well as anybody not in the core team, and that statement isn't even false. If I had to guess, I'd assume he's really saying something about how ObjectControllers behave as proxies for models.
I don't mean to write off whatever problems he encoutered -- they are clearly real problems, either bugs in Ember or failures of developer ergonomics. If he could point to the specific actual problems I would personally work on a patch to address them. But I don't have enough to go on.
I don't mind those explicit set calls as much. I prefer when `obj.foo = 10` is a side-effect-free operation that only affects `obj` instead of something that triggers bunch of layout updates and got knows what other changes as well.
I do agree on the callback thing though and I find it kind of sad that not many people use CPS compilers for JS even though things like Cofeescript and SASS are pretty common.
I seriously considered going through a CPS transforming compiler for my major production Javascript application, but it's a risky step to take, relative to using a less invasive transformation like coffeescript.
It comes down to lack of mature tooling and debugability: coffeescript is easy to debug, because it's a very light level of syntactic sugar and dropping into the Javascript is easy. A more aggressive compilation step would require me to put a lot more trust in the maturity of the compiler and associated tools.
It can, occasionally, be frustrating (for example run loop craziness), but in my opinion it's no more frustrating than working with any other stateful front end framework (WPF, backbone etc...).
I've done quite a bit of Ember as well, and lately I'm kind of liking React's approach much better. It composes well with many routing/model solutions, and keeps the 'run loop' isolated in the view layer.
But the whole leap to needing "strong static type system like Haskell" leap seems really random.
It seems more like a need to spend more time with JS (which can be weird and a pain, but eventually makes sense) than blame Ember, which is pretty complex on top of the various aspects of JS that are a bit unintuitive to start with.
I understand the frustration of the author, but it's hard to tell exactly what the source of his issues is. Not enough information is provided in his descriptions to actually understand what is going on. I suspect that either he has run into a bug (which of course should be fixed) or that he's misunderstanding the behavior. It's very possible that he was given some bad explanations for the behavior which has further confused him. I've reached out to him to see if I can get some more insight into the details of the issues.
Most of the author's issues could have been replicated in any static typing language, apparently the author is just angry and wants to blame something other then the developers of the framework that confused him in the first place.
Also the whole static typing reasoning is BS, because the author could have simply used either Google Closure Compiler Linter that can enforce typehints, TypeScript or Dart.
Can anyone who is more experienced with ember help explain what was going on in those two weird examples in the OP? (Commenting a widget affecting another one and setting the "bar" field also changing the value of "foo" field)
The docs for ObjectController (and ObjectProxy, which ObjectController extends) both mention the specific behavior about 'content' (not model, the fact that model and content mean the same thing when you're talking about proxying controllers is something you learn as you go along):
Sorry to hear about the pain points so far. I felt like this many times when I was starting with Ember. It definitely gets better the more you become familiar with all the different conventions.
The issue is that JavaScript is being given a larger load to carry than it was designed to hold. We need to upgrade to using Ruby with Meteor-esque frameworks, and fast.
At some point every programming technology of any power will drive you nuts. If it was so simple a non-programmer could do it, we would all be flipping burgers.
SOURCE CONTROL, DO YOU SPEAK IT?
In all seriousness, this is a major peeve of mine - the time that you're most confident that code can be deleted is when you're removing the pieces that depend on it. If the deletion really turns out to be wrong, you should be able to restore the code from source control. If you can't, stop using broken source control.
Leaving leftover dreck in your source files "just in case" is like stashing your leftover sandwich crumbs in your pocket at lunch. Clean up your mess!