What the actual fuck is this? I read this as "in order to do a hello world, you must first create a hello world service to create the hello world factory to create the hello world sercice so you can print hello world on the screen."
Well, you misunderstood, and now you're ranting according to your misunderstanding.
I'm not an Angular, expert, but I'm pretty sure that the situation is this:
1. "Hello world" does not require any dependency injection whatsoever. (ie. it does not require services, providers, or factories). Note: if this was not true, I would agree with this rant completely.
2. If and when you decide you want dependency injection, if what you want to inject is a simple value, you can just provide it directly, without using a service, provider, or factory.
3. If and when you decide that you want to provide a dynamically-generated value, you can specify a function instead which will get called whenever the value is requested. This is called a "factory."
4. If and when you decide that you want your factory to just "new" an object instead of running an arbitrary function to provide the value, you can register that object type as a "service."
5. If and when you decide that you want to configure that object type first, you can register it as a provider.
If you want to stay at step 1 forever to keep things simple, groovy.
This is a example of success, not failure: you pay for only as much complexity as you actually want to use.
As a newbie to all of this stuff (and yet still reading through this thread trying to keep up), thank you. This was the clearest explanation & summary I've read.
Note that you'll find nothing of the sort in the Angular docs. I believe this is at least part of what the author is really railing against. If the docs were crystal clear as to how Angular actually works, doing stuff in Angular would be a lot easier and keep devs from getting pissed-off enough to write rants like this.
> If you want to stay at step 1 forever to keep things simple, groovy.
You can use Grails with Groovy to go to steps 2-5, tho all Grails does is use Spring which it bundles. In fact Grails started off as a thin wrapper around other software like Groovy, Spring, and Hibernate, and was really intended as a vehicle for its despot to muscle in on the consulting and conference markets for the bundled products, tho it's since grown its own codebase by signing up volunteers willing to sign the onerous VMWare contributors agreement signing away all copyright and patent claims over to VMWare.
Sigh. I can't say anything about Angular because I've never used it. But this constant ridicule of "the Enterprise" is getting on my nerves. Obviously, software design patterns change a lot over the years. Old practices are abandoned -- sometimes more slowly than we'd wish -- and others replace them. But much of this criticism comes from the fact that the critics 1) use technologies that are not mature enough to have growing pains, and 2) don't really know how software is made in the real world.
RE 1, the factory/provider/whatever pattern, comes in real handy when 2 years from now, a crucial ODE library that your air-defense system uses, absolutely has to be replaced by something else. And it's not like a kid could write a quick re-implementation in Go over the weekend.
As for 2, many of these patterns have been designed for software that does not resemble web applications at all. Just to give a sense of how out-of-touch SV developers can be with regards to the software world at large, IBM, Oracle and SAP combined employ more people than Google, Facebook, Twitter and LinkedIn combined, ten times over; there are more Java developers in the world than the entire population of the entire Bay Area.
I'm not saying that the maligned "enterprise" patterns have a place in a client web framework, or that some of them aren't dated. All I'm saying is, stop treating some software patterns that you think are unnecessary just because all you build are CRUD web-apps as inherently stupid. They are not. One of the reasons people working on CRUD web-apps can "move fast and break things", and just "rewrite the whole thing in a couple of weeks", and say stuff like "what's wrong with a simple 'new'?" is precisely because the software they develop is, frankly, not that complicated.
I would also like to remind the author that his beloved Erlang was developed in the very same environment he thinks so little of.
Engineer and architect of large enterprise products here (2 million line Java/C# behemoths that do all sorts of weird and complicated financial shit).
Reality is actually as follows. Not joking I've done this job for 15 years and worked with several large companies including one you mention. Perhaps your experience is in the 1% of "enterprise" companies who have clue but this by far is the majority:
Bold statement here: 99% of the use cases of all these patterns are totally pointless and a waste of money and time. The add nothing to the product, they increase complexity, decrease performance. It's cheaper and more reliable to chop your product up and write each chunk in whatever separately with no official architectural pattern usage system-wide.
Typically in the real world, you're going to end up with:
1. Literally tonnes of DI/IoC code and configuration for an application with an entirely static configuration. This is either in XML or DSL form using builder patterns. Consumes 30 seconds or more to start the application up every time. Aggregate over 50 developers is 16 hours a day pissed out of the window.
2. Proxies for anaemic domain models that are fully exposed. Consumes 30 seconds to generate proxies that do sod all. Aggregate over 50 developers is 16 hours a day pissed out of the window.
3. Leaky broken abstractions everywhere actually destroying the entire point of the abstractions. Makes refactoring impossible and maintenance hell. It's better in some cases that they are not even there and that basic savvy is used over COTS patterns.
4. Acres of copy pasta. Why bother to write a generic implementation when you can copy the interface 50 times and change the types by hand?
5. Patternitis. So we need to use the BUILDER pattern to write the query to connect to the DOMAIN REPOSITORY for the AGGREGATE to call the CODE GENERATOR that fires up the ADAPTER to generate the SQL using the VISITOR PATTERN which farts out some SQL to the database PROVIDER (and a 90 layer stack dump when it shits itself). This is inevitably used in one small corner while everyone in the rest of the system hits a wall in the abstraction and says "fuck it" and writes SQL straight up and skips the layers of pain and because there are no code reviews (because people are all sitting there waiting for their containers to start up whilst posting cats on Facebook).
LINE 10 (remember this)
These things are never rewritten or refactored. They slowly evolve into a behemoth ball of mud which collapses under its own weight to the detriment of customers, a team of enterprise architects (usually from ThoughtWorks etc) usually appear at this point then attempt to sell outsourcing services who will "fix all the shit" for a tiny fee, leave a 200 page powerpoint (with black pages just to fuck your printer up). The company struggles on for a few years and is saved at the last minute by a buy out by a company at an early stage of the cycle who slowly port all the customers and buggy shit to their product platform. Then the team either dissolve and knowledge is lost or they take a cash sum from the sale and start up some ball of shit company that does the same again.
GOTO 10.
That's enterprise 101 because the people that have been hit by the clue sticks know better than to subject themselves to this and do work in SF and SV and London. Me: I'm a masochistic crazy person who wonders every day why I don't just go and write web sites for half the cash or flip burgers because it's less painful.
I agree with you for the most part - what you're describing is rampant abuse by cargo-code programmers that don't know better.
This doesn't mean GoF design patterns are specifically wrong. It's just that they are misused and applied in places they don't belong. When done properly, they should emerge organically as you code without you even realising it (That is to say good design patterns are emergent phenomena in good code, not the other way around).
It also doesn't help that the entire software industry is fixated on single-inheritance OO languages, which tend to encourage ridiculously bad designs.
> It's cheaper and more reliable to chop your product up and write each chunk in whatever separately with no official architectural pattern usage system-wide.
This nails good software design on the head. Don't write large software, write small independent reusable components and combine them together.
This is what dependency injection solves well - When done properly. (If it involves XML or config files it's not done properly).
I think, as Peter Norvig once pointed out, that design patterns are a symptom of an anemic language design. They cost us time and complexity for their benefits. Java wouldn't need half the patterns typically employed to work around the limitation that there are no first-class functions.
Eich himself admitted to avoiding adding classes to Javascript in his interview with Peter Siebel for Coders at Work:
SIEBEL: So you wanted to be like Java, but not too much.
EICH: Not too much. If I put classes in, I'd be in big trouble. Not that I really had time to, but that would've been a no-no.
It's a really good interview and I recommend the book. It seems like Javascript was supposed to be an Algol-syntax over a non-pure Scheme inspired core... but due to constraints was thrown together like most code is when there's a looming deadline.
My point was mostly a sarcastic insight into what it's like for these companies but you're right: there are valid uses and the fundamentals really are spot on. In fact I'm probably #1 fan of Martin Fowler who has spent many years researching, collating and understanding these patterns so they can be communicated to others effectively.
The problem is that it takes literally a decade to actually understand how to use these properly in one specific language (and possibly mostly effectively in another). Until you reach this point, your toolbox isn't filled with the sharpest tools as your team isn't going to be filled with 10 year+ senior staff across the board.
At that point, it goes to shit, every time. These patterns and techniques aren't just tools - they require experience right from the get go and a lot of people just aren't capable of nailing it even in a decade.
When done extremely poorly - enterprise projects can indeed end up as slow behemonths. I agree that this is often the case, but it doesn't mean that the design patterns backing powerful enterprise solutions are to be taken lightly.
Adapter pattern does have a huge, proxies do have legitimate uses, visitor pattern can be made to be extremely powerful. Ofcourse if you have a development sweatshop throwing out these left and right - yes then you will have an abstract mud ball that is impossible to maintain - and in the end defeats the original purpose of these patterns.
> ... totally pointless and a waste of money and time
Sure. Most, but far from all. But let's look at the bigger picture. In the move-fast/break-things corner of the world they write simple software with basic functionality but do it at tremendous speed and sublime efficiency.
And then they go out of business.
So I guess most of lines of code written anywhere are a waste of time and money. But that's just how it is. A more interesting question to ask is how much money is wasted and how much is made by both kinds of software development. I don't know the answer, but it's certainly not clear cut.
Thank you! I came here to say this, but you said it a lot more politely than I would have.
There's a lot of hate for certain design patterns because they are seen to introduce too much complexity or boilerplate in small projects - but are absolutely essential for large projects.
I hear this used a lot to defend Java and other enterprise nonsense but I have never seen an example of it in real life. 99% of the problems I see in large projects are creations of their own poor coding and design. There is a magical belief that using certain abstractions will fix this, but it seems more likely they are part of the problem.
> the factory/provider/whatever pattern, comes in real handy when 2 years from now, a crucial ODE library that your air-defense system uses, absolutely has to be replaced by something else.
Hmm; that's the point where your enterprise experience and mine diverge. Here are what I consider the key observations from the organisations I've seen:
The majority of uses of dependency injection seem to be an attempt by a developer to not commit to a technology choice, or to build and preserve some feeling of control over the selection of platforms and technologies. Often I think this is a result of technology platform choices being taken away from the developer, typically by some kind of architecture function. So we abstract away from databases, ORMs, XML binding libraries, network transports, messaging systems, basically anything that's not part of the core application. See Java Enterprise Edition deployment descriptors for an industrialised example.
At the same time, in any sufficiently complex enterprise environment, the chances of any of the platform technology choices changing rapidly is tiny because of the basic risk avoidance culture. And even if you do decide to try migrating to a new technology platform (e.g. database, app server, messaging platform etc), none of the existing deployed applications will migrate because the cost of retesting the application on the new platform is too high relative to the business benefit you can demonstrate.
It doesn't matter if you say "it's just a 20 line configuration change": the result of your configuration change is to switch from one implementation containing thousands of lines of code to another implementation containing thousands of lines of different code. Your ops team simply won't trust you to put that configuration change live without as much testing as when you put the original application into production. And if it's several months since the last production change, good luck getting hold of the people who can carry out the testing - they'll all be off doing other things.
So the developer is building abstractions to insulate from changes in technology that never happen, but at the same time the one kind of change that's guaranteed to come along over the lifetime of a deployed application is a change in business requirements. And this is typically the exact type of change that all the abstraction and configuration frameworks don't tackle, because it usually results in changes in the way that components interact with each other, not just substituting one interchangeable part for another.
So, who can gain from abstracting away from the technology platform? Well the main benefit comes when you want the same code to run in many different environments. So the main uses in descending order of likelihood:
* You might sell the same piece of software into multiple customers and want to support the variation in environments you'll find. Hello, IBM, Oracle and SAP, as you point out.
* You might have different configurations of your software for different environments (development, test, staging, production and so on), but you need to be careful to make sure your test results from one configuration are actually valid for another.
* You might actually need to run the same code in production in more than one environment. There are cases where this happens (e.g. in a desktop app vs. a web app, or a mobile app), but often its just as easy to build an API around the code and invoke it over the network.
So, in my experience the effort of implementing all this configurable decoupling is very rarely rewarded by a significant reduction in downstream effort.
> that's the point where your enterprise experience and mine diverge.
Yes, that's precisely the point: there are vastly different experiences in such a big world. Just like most books are crap and most movies are crap doesn't mean that good books aren't written and good movies aren't being made. Most software -- in any language and any environment -- is crap. But that doesn't mean you can discount off-hand solid principles that are sometimes absolutely necessary. SV web startups write software that is order-of-magnitude simpler than a lot of enterprise software. Most of these patterns are downright wrong for move-fast-break-things software; but much of the software world is nothing like that. The arrogance expressed in the blog post is completely unjustified, even if most of what you see is crap.
Erlang and Clojure were born in the minds of enterprise programmers; as were Java and probably Go (oh, and Watson!). OTOH, the web-software world has given us Rails and Node.js. So if you compare the best products of both worlds, I don't think enterprise programmers come out behind. This condescension from web developers towards enterprise developers is not only misinformed; it is blatantly misplaced.
You shouldn't take offense. If you work on large complicated Java/C# projects, by all means, bake in as many GoF patterns you can muster. Part of what the OP is hinting at is that in a lot of other languages, there is simply no place for these complicated patterns, but yet we see 'Enterprise' developers bringing their bad habits and bloat with them.
Well, I like Go, and it certainly has its use cases. But I personally worked on a hard-realtime safety critical mission Java project (if the program gave the wrong answer people could die, and if it gave the right answer late, tens of millions of dollars would be lost). We couldn't have done that without Java's concurrent data-structures (which Go doesn't have), without Real-Time Java's hard realtime guarantees, and it would have been very cumbersome without Java's brand of dynamic linking.
So sometimes Go is good enough, but sometimes you need the full power of the JVM.
They built Limbo just about the time Java got out. Limbo is a predecessor of Go and it's by far the language Go is closest to. Unfortunately Limbo (and Inferno) didn't have the success they hoped. It's really a shame.
That is the part of the problem as per original article, isn't it?
With all seriousness... I would like to agree with your statement. But I can't shake that nasty feeling of the "to save this village we have to burn it" undertone from your statement.
Edit: JavaScript got created without major influence of Java (it had more impact on marketing of JS than the language itself). Also I firmly believe that there was a lot of criticism of the then newly baked Java language that turned out to be prescient and to the point e.g.:[1]. Thus I would argue that as much as existence of Java has boosted development of virtual machines and compiler technology it has impeded development of language syntax and semantics.
Erlang is waaay older than Java, so are Python and Ruby. Smalltalk was the real game changer, Java not so much.
With regards to JWZ article. It is interesting how perspectives are changing in time. JWZ wrote:
" - Java-the-language is, overall, a very good thing, and works well.
- Java-the-class-library is mostly passable.
- Java-the-virtual-machine is an interesting research project, a nice proof of concept, and is basically usable for a certain class of problems (those problems where speed isn't all that important: basically, those tasks where you could get away with using Perl instead of C.)
- Java-the-security-model is another interesting research project, but it only barely works right now. In a few years, maybe they'll have it figured out or replaced."
Years later it seems that both Java security model and JVM were actually good ideas, while the language itself is considered as too rigid and too verbose.
It's the same pattern that repeats itself all over the place. We've seen it with Java, with Ruby, heck, even with PHP. And now with JS: As applications grow, we tend to search for tools to help us cope with the growth.
After doing similar (but still slightly different) things over and over, we start building abstractions and with every thing our abstraction can't deal with, we make them more complicated.
Whether you use the official name of your thing ("factory") or you just run with your own idea and term - the outcome is always the same.
As a library, you feel the need to be abstract enough to cope with every feature request ever asked from your library and there will be tons of feature requests and tons of little parts people want to customize.
And honestly, don't we all prefer using some public API of a self-contained library to patching said library (think of the maintenance as that library gets updated)?
This isn't about ruining a language. This is about making the right choice of library or about the decision of building your own little customized thing that exactly fulfills your requirements (and nothing else), but as your requirements change, you're going to add abstractions yourself and suddenly you're back at the AbstractSingletonProxyFactoryBean, though you might have chosen a different name that nobody but your team understands.
As a library author, try to resist the feature creep; try to be opinionated ("I'm really sorry, but logging isn't pluggable. You want to log to your XML based logging server? That's fine, but you'll have to build your own thing or use a different framework") then you remain accessible and buzzword-free, even though that might cost you some users in the short term.
An abstraction is not useful, in fact it's downright harmful, if it does exactly the same thing as what it abstracts over, but more verbosely.
A lot of these patterns you're used to seeing in Java stem from Java's static nature.
Here's a car factory in javascript:
function makeCar(dealerName) { return new Car(dealerName); }
And here's a configured car factory:
var myCarProvider = makeCar.bind(null, "my dealer");
It makes precisely zero sense to create abstractions that reimplement core language features. That would be like writing a C function to add two uint8_ts, or a macro that expands to inline assembly to convert a float to an int32_t. You already have these things built-in, you don't need a gorillion enterprisey patterns.
This of course has nothing to do with staticness, and everything to do with Java's lack of first-class functions. In any flavor of ML, for example, nonzero-argument versions of this pattern are slightly cleaner (the exact pattern is unnecessary due to immutable state).
> or a macro that expands to inline assembly to convert a float to an int32_t
This sort of thing is actually useful on occasion, because it allows you to specify the exception handling you actually want (what to do on inf/-inf/NaN). Of course, it's better do it with a pure C function, but it's still a "reimplementation of a language feature".
Of course, you only ever do this when you want subtly different behavior than the language provides, so I think your larger point still stands.
The whole point of having first-class functions is that you can assign them. The problem a factory solves is precisely the lack of this assignability (which is why a constructor function is wrapped in a class).
Please put in the effort to understand at least the basic idea of dependency injection before deriding it in favor of "simpler" solutions that do not solve the same problem.
The specific pattern DI can solve here is:
- one module provides some capability by name
- another module makes use of that capability by name
- the two modules have no knowledge of each other, and no higher-level glue code is required to connect them together (and construct the appropriate objects at the right times).
Your "solution" does not satisfy the requirements because it requires you to manually construct the objects in the correct order. DI on the other hand will automatically analyze the graph of dependencies, invoking the appropriate factories in the right order.
Sorry to say, but klmr is right. Since functions are first-class objects and references are evaluated late, these issues are already managed by JS and native scopes. There's no need to recreate this functionality in a framework. You might just want to consider the entry point to your code.
P.S.: What this really is about: Unit tests originally designed to go with C/C++ do not work well with late binding. In fact this is a concept totally foreign to these languages. It's essential to understand that these kind of frameworks serve in the first line the purpose of test suites and only in second place the needs of developers. (Developers should not mistake themselves for test suites.)
> To which you would probably reply: "But that's exactly what FactoryFactory/DependencyInjection/... pattern is!"
Actually no. DI does a lot that your simple examples do not. Notably, it understands the graph of dependencies between decoupled compoments and constructs provided values in the correct order.
DI is a design pattern. A design pattern is a conventional way to structure code to solve a particular type of problem. A way to structure code is not a thing that can analyze graphs.
Maybe you're talking about some particular DI framework. That would be a library with functions and classes to make implementing the DI pattern easier. There are many such frameworks, and some of those frameworks may well do automatic graph analysis. But, graph analysis is not inherent in the pattern.
Your specific framework is not the general pattern.
Except you don't touch on other aspects of what makes IoC containers useful in the real world.
I've seen XML configurability used as an extension point for code that would otherwise be closed. I've seen bugs happen because the lifecycle of objects have been mismanaged. You're conflating that things can be done more elegantly using functional programming to think it belongs in a functional paradigm.
IoC containers in .NET are easier to use and more elegant because of functional programming constructs, but their existence doesn't remove the need to have them.
> I've seen XML configurability used as an extension point for code that would otherwise be closed.
Take a step back, and think why that 'extension point' had to be closed to begin with. You're probably going to find either an architectural flaw, or a problem with your tooling that should not have required this sort of thing in the first place.
Also disturbing is that you are using XML to add a degree of expressiveness missing from whatever tooling you are using.
Hmm. So small example on what I saw recently was being able to swap the authorization/authentication piece from hitting a service to users defined in XML for locally running the project. Architecture flaw? No. Problem in tooling? If you have a convincing enough argument, yeah. Does Spring feel like it lets you do too much in XML? Hell yes. It's awesome when it works. It feels too convoluted when you don't need it.
i don't think you actually understand these patterns or how they're used. it's useful when you have multiple implementations of `Car` that you want to use under different circumstances. Or when `Car` is dependent on static configuration that might depend on the host it's running on, or might be different in development/testing/production.
I don't think you understand functional programming.
function makeAppropriateCar(cargo) {
if(cargo == "people") return new Automobile();
else if(cargo == "boxes") return new Truck;
else ...
}
function makeLocalCar(settings) {
var car = new Car({'color': settings.get('new_car_color')});
car.set_origin(settings.get_hostname());
return car;
}
function makeDebuggingCar() {
if(global_settings.DEBUG && !global_settings.PRODUCTION)
return new Car({'loglevel': LOGLEVEL_DEBUG});
else if(global_settings.DEBUG && global_settings.PRODUCTION) // testing
return new Car({'loglevel': LOGLEVEL_INFO});
else // production
return new Car({'loglevel': LOGLEVEL_WARNING});
}
Ok, now try maintaining that when there are 15 types of cars and cars are used in dozens of services. You're imperatively expressing a dependency graph that you could (and would benefit from) defining declaratively at a larger scale.
I'd recommend reading the user guide for Guice for balance before you respond. It's worth seeing how nice DI can be.
This example actually really sucks. Advocating for case statements shows that either you've never worked on a truly large project or you've never had to go back and modify your own code 2 years after the fact.
If you really understood functional programming, you'd see an if/case statement as an opportunity to replace conditional with a function.
I started to write up an example, but since we're talking about the imaginary abstract Vehicle implementation, it's not worth dignifying.
If programmers didn't switch jobs every 12-18 months and didn't see 100K LoC as a "large project", these "all frameworks suck" rants might turn into useful discussions of how one can organize code such that it's understood by more than the original author. That goes for frameworks too. If you have to rely on one of the core developers responding to a post on Google Groups or SO as your support mechanism, you've made the world less simple.
> As applications grow, we tend to search for tools to help us cope with the growth.
Actually, we tend to search for tools to help us not learn another language better suited to the domain we found ourselves in.
The point that JavaScript is prototype-based and, therefore, some of these patterns make little or no sense (or could be expressed in much simpler terms) appears to be lost.
Great, thanks. Hey, by any chance do you think there's no single greatest language, and that people should use the right tool for the job? Terrific, me too.
Saying "language has nothing to do with this" misses the point of this post entirely. It's about how people bring the same unwieldy practices wherever they go regardless of the language.
The title of the post was "you have ruined javascript" and I maintain that JS has in-fact not been ruined just the same as all other languages haven't.
Abstraction bloat in libraries is not something that's specific to languages and a language can't be ruined by libraries suffering from abstraction bloat (unless all of them suffer cough java cough)
It makes me so happy so see some hate for Angular. I decided to specialize in front-end web development a few years ago because the state of back end frameworks was so abominable. I escaped to HTML, JS, and CSS so I could quietly develop in peace. Now we have Angular, Knockout, Bootstrap - please for the love of all that is good, just stop. This nonsense is nothing but mountains of technical debt. When I tell this to framework fanboys, they counter with "But you can get things running so quickly using frameworks." This is the definition of technical debt (doing things fast now at the expense of doing things slow later) but it is also complete nonsense. I challenge anyone to a contest to create a quick font-end site where you can use as many Rube Goldberg contraptions as you like and I only use jquery. So then when they back down because they know they will lose their excuse is "But Chris, you are just so smart - the average dummy developer can't do what you do." My final rebuttal is "If you agree that I am such a genius, why won't you listen to my advice?"
My experience is completely the opposite. I used to wire together a bunch of jQuery spaghetti code but as my front end applications became more and more complicated it became massively unmaintainable. Probably due to the fact that I didn't organize things very well, but isn't that what a framework is supposed to do - give you guidelines for how to organize things?
You can keep manually updating the DOM every time you get data back from the server but if you don't mind I'll keep using frameworks like Angular that take care of those mundane details for me while giving me a sane way to help me organize and test my front-end application.
We actually did this - we built our entire app using just jquery - and then we spent a month tracking down issues with applying state changes to the DOM before we gave up and rewrote the thing in Angular. We had a few bugs at first but they were quickly fixes and then we had had a much more solid application, since we only had to worry about keeping our data structures straight and the two way binding would take care of showing/hiding the elements, updating values, etc. Whole classes of bugs we were spending ages tracking down before which happened after a particular sequence events just couldn't happen anymore.
If you are doing something simple and quick by all means just use jQuery or plain JS - the advantage of the more powerful frameworks comes into play when building bigger things with complex scenarios happening. The challenge to make a quick front-end site is meaningless - the more meaningful challenge would be to write a complex real time application with both and compare, which of course we have already done.
You built a poor application, then rebuilt it - one would expect the second one to be better no matter what frameworks you used. I still believe I could do it faster and end up with a more maintainable code base.
The tools I use to keep my code maintainable are good practices, frequent refactoring, and clear thought. No library can replace those. Why do you need a 2 way binding to take care of showing and hiding elements? Only a 1-way binding is required. I am currently working on an app that uses Knockout and we are having horrible performances issues - all of these 2-way bindings are checking for everything all the time. There are fixes for this - fixes that would not be needed if we didn't build it with duplo.
My experience after building almost a dozen single page apps using JS frameworks and sometimes just jQuery has been the complete opposite. With jQuery, things are easy to get going at first, then difficult later when you need to do more complex things. Two-way binding especially has been extremely helpful.
Bootstrap is a bit different in that it gives you a good base to work from. Also, for many more things than design hipsters would have you believe, it can be used pretty much as-is.
Angular.js, OTOH... I looked at it a while back and did not like just how much it forces you into its way of doing stuff.
Yeah... My personal experience with Bootstrap is somebody built a site using their grid system that I took over. My boss wanted to add a bar across the top but because all elements had class names corresponding to their position ("row1" etc.) the only way to do that was to rename every single HTML element. This would have been a two minute fix using vanilla CSS. If I had all the time back I spent resetting line-heights bulldozed by Bootstrap CSS I could have built an entire new site.
I use bootstrap quite a lot and I have no idea what you're talking about regarding the class names. That probably wasn't a bootstrap-related problem.
Overriding the styles is a bit of a PITA, but using the LESS or Sass version solves this.
I keep reaching the conclusion that frameworks are evil and libraries are awesome. Frameworks promise to organize your code and keep things structured, but the inherent verbose nature of JS frameworks ends up harming more than the structure helps.
Ultimately, if naked JS is too difficult to manage due to the lack of types and interfaces, I much prefer to use another language that translates to JS, rather than attempting to force it onto the JS language, because it always becomes messy and half-baked.
Although it's ranting about Java frameworks rather than JavaScript a lot of the complaints look rather familiar. Having said that, I don't think anything in the JS world has reached the baroque complexity once regarded as normal in the enterprise Java world.
[NB Note my comments on that discussion - I had not long finished rescuing a monster of a Java enterprise application where the simplest thing needed to go through about 30 layers of abstraction (I did actually count them) from a page being submitted to the underlying message being sent over MQ - it seemed to be a point of honor to combine every feature of J2EE with every design pattern to do the simplest things. Having multiple huge jar files in the classpath each 97% identical to the other just added to the sense of adventure when you clicked on something.]
I know it's a bit unfair to pick on that particular document - but I'm worried as a long recovered abstraction addict to what degree I actually thought things like that were ever a good idea.
You mentioning Java actually reminds me, what I find bizarre about the recent trend in javascript is that they're creating the boiler plate on purpose. In Java the boilerplate was a creation of the language, but in javascript it's a creation of the community! It's like some sort of sick joke.
The stuff I hate most is the boilerplate that means you find crappy little singletons everywhere when all that was needed was a function. And for the love of god, a function that's named and not pointlessly assigned by a var because you're mono-linguistic and haven't realised yet what the actual point of functions are yet.
Huge chunks of the javascript in the web site I've taken over were done by someone who loved these patterns, this is an example of his favourite one, pointless and led to colossal code bloat as he used it over and over for basic handlers.
function instantSearch() {
var instantSearchObject = {
config: {
animSpeed: 250
},
init: function () {
this.findComponents();
this.bindEvents();
},
findComponents: function () {
this.searchBlockCollection = $('.search, .entry-search');
this.searchInputCollection = this.searchBlockCollection.find('input:text');
},
bindEvents: function () {
var self = this;
this.searchInputCollection.on({
'focus': function () {
var currentInput = $(this),
currentSearchSuggestionsBlock = currentInput.parent().siblings('.search-suggestions');
currentSearchSuggestionsBlock.slideDown(self.config.animSpeed);
},
'blur': function () {
var currentInput = $(this),
currentSearchSuggestionsBlock = currentInput.parent().siblings('.search-suggestions');
currentSearchSuggestionsBlock.slideUp(self.config.animSpeed);
}
});
}
}.init();
}
Nigh on 30 lines of code, so few lines that actually do something. I tend to refactor them when I can so I can see what they're actually doing, the following code should do exactly the same thing (without me testing it):
function bindSearchBox() {
$(".search input, .entry-search input")
.on("focus", function () {
$(this).siblings('.search-suggestions').slideUp(250);
})
.on("blur", function () {
$(this).siblings('.search-suggestions').slideDown(250);
});
}
Hmmm, even just refactoring that tiny bit of code shows that there might even be a bug there, or at least pointless code, I'm not sure why he's sliding the search results up on focus, they don't stay open.
There are a lot of JavaScript frameworks around build by Java developers that couldn't be bothered to check what the language they are working with is about and how it works.
Thus they went and tried to "fix" JavaScript by trying to make it more Java like and thus unleashed abominations such as Dojo or Prototype.js upon the world.
What I personally really do enjoy is "var self = this;". Now you just overwrote the system variable pointing to the global object. What was this good for? Oh, the other language doesn't use "self" as a system variable, so it must be worthless in JS? Hmm.
Now we just have to define "var global = (function() {return this;}).apply(null);" and we have a reference pointing to the global object! Pure magic! Really? Are you serious? Sorry to hear so. (No, I was not suggesting to use some kind of more elaborate pattern for this. See, there is "self" ...)
(When ever you see "var self = this;", take your things and run.)
Err, that's totally ok. That's useful for keeping a reference to the object scope in a closure. You can't really write advanced javascript without it.
AFAIK in all the c-style languages `this` is the usual self reference. Python & Ruby are self. VB.Net is Me.
But javascript screwed `this` up and this is especially apparent when you use events where `this` ends up being the caller instead of the callee. Having a self reference in the closure allows you to fix the problem.
I think people ended up using self for a reason, it's strange enough in a C-style language that you're not expecting it to be anything, but familiar enough to be obvious. The other common ones over the years have been `_this` & `that`.
There are patterns in javascript and patterns. We need Crockford to write, "Javascript Patterns: The Good Ones".
BTW: your case on "this" is not JS, it's the the DOM interface (not part of the language). From the point of view of the DOM it's probably right: The element applies itself to a callback function (the event-handler), which is triggered by the DOM interaction. The right question is: Who is the callee?
The JS built-in solution to this problem is "Object.handleEvent". (Since anything is an object, this is a general approach.) Anyway, there is no need to overwrite one of the few predefined variables to store a reference to anything, may it be to "this" or any other.
Hmm. JS was before Ruby and Python, so it couldn't have screwed up something to be found there. (BTW: HyperTalk was also "me".)
The very nature of "this" in JS is because of late binding, probably the most important feature of JS. Since references are evaluated late, the need arises to store the reference in a variable for use in a later call. Since these are first-class objects, no problem. The standard name for this used to be "that".
My point was on the total ignorance regarding the language. Why would you want to call the variable "self", overriding built-in semantics? Why not use "window" or "document" for a change? Obviously you would not want to do this, even, if their values could be restored by the use of another closure.
The praxis of naming this "self" is just an import from other languages, proving that the author in question didn't care for the semantics of the language she/he uses. Would you do the same by a compiler directive in C, overwriting built-in semantics? Could this become a pattern? Probably not. Would you redefine "/dev" in a Unix shell for other than a hoax? Probably not.
(BTW: I do not see a need to down vote a comment that points out a feature in language semantics. With server-side scripts and web-workers the global object isn't always the browser window. There is more and more need for this reference, while it becomes obfuscated by a pattern rather questionable. And I'm rather shocked to see this pattern having become quite popular. There isn't even a handful of global system variables in JS, "Math", "Date", "this", and "self" are the only ones common to all platforms. How hard is it to respect these? There are even use cases for overwriting these, e.g. test, but then you've just rendered them useless, if you chose to overwrite them in your code.)
Edit: And in case you wouldn't see a point a made here, think of code maintainability. Let's suppose you're reading some random lines of code. "Math.sqrt", you would assume to know what this is. Provided, you're in a browser, the same would apply to "self.location". But, hey, you can't be sure nowadays.
I'm not familiar with your other examples but I object to ncurses being called a framework. In my understanding of the word a framework defines to some extent how your code needs to be organized and architectured, I don't think ncurses fits this description. It's more like a terminal-based drawing library.
Thats what people typically market it as, but when you use it, it has mor in common with various GUI toolkits. Lots of windowing, and the like, but not much drawing.
To me, there's really only two choices. You can use someone else's framework, or you can create your own. For applications above a certain level of complexity you are forced to choose one of those paths. There simply is no way to avoid it. Both are valid choices of course, each with their own pros and cons. But don't fool yourself into thinking frameworks are somehow evil. What I think you mean when you say that is "other people's frameworks are evil" and your frameworks (that you build with libraries) are awesome. That may be true, but keep in mind, when you build your own framework, you now have become the maintainer and de-facto teacher for both your application and your home-rolled framework you created to build it. As long as you're cool with globbing on those responsibilities and you feel confident you can help other developers get up to speed on your custom framework's architecture, then it's a fine choice.
"AngularJS fits the definition of a framework the best, even though it's much more lightweight than a typical framework and that's why many confuse it with a library."
They can call it a framework all they like, and obviously that word means different things to different people, but I've found AngularJS is more useful when described and treated as a library - a library for building a front-end framework.
AngularJS might exhibit some of the trappings of a framework (e.g. inversion of control), and it has some of the components a front-end framework would need: routing, templating, networking... but these components aren't tied together in a way that impresses an overall architecture. Calling Angular a framework leads developers to assume architectural decisions have been made when they haven't.
Also above the fold: "AngularJS is a toolset for building the framework most suited to your application development"...
Even internally they're insecure about it. I think library is a more useful definition because it encourages developers to think about architecture before they start building application specific stuff.
You have to be very careful if you don't let it manage all your DOM changes, and in general everything is done via it, so it is basically a framework.
AngularJS is much better than what we had before, but it is still not great, and a bit clunky .. hopefully the lessons will be learned and in the next cycle we'll get some nicer slimline things instead (though this cycle could take a few more years to run through).
So long as you never run into an edge case the framework was not designed to deal with. But oh, the framework itself makes it very hard for you to have a workaround. But that only happens... very often.
The difference between a framework and a library, IMO, is control.
You forfeit control to the framework in exchange for less code. But then you depend on it for your every feature.
Also, when the next big framework comes along that promises you even less code writing. It usually is non-trivial to make them work together, if at all. you just might end up with a legacy framework on your hands or face a complete rewrite.
Disclaimer, I work with legacy code written on top of JSF 1.2 and Richfaces 3. It probably seemed more organized and modular at the time. It's not.
The author might be confused by AngularJS, but all of the projects I have converted from simple JS to Angular have more than halved the amount of code needed, and made the applications much more easy to maintain.
i completely agree. I'm 100% against bureaucratie , but accusing angular of being bloated is a bit unfair. It does has its weird part (like the service/factory pointed in OP) but in general code is much much lighter using the framework.
As opposed to , let's say, spring, which transforms a simple project into a gigantic mess of configuration files and abstract annotated code.
I can sympathize with the article, but on the other hand, when you reach a certain level of complexity, OO kind of forces you to use dependency injection. Which means providers and factories of some sort for short-lived objects, at least if you want to have testable code. I don't know if it's "enterprise hand-holding bullshit", but having seen code with and without DI, the DI one is definitely easier to work with and refactor. This doesn't mean Angular is not over-engineered, since I don't use it I have no opinion on the matter.
Whether you use OO, Procedural, of Functional programming, you're still going to end up with some variant of IoC in order to keep your abstractions clean.
I really am not seeing a problem anywhere. OO and the structure that follows from it, which is what ends up being seen in this instance, seems like a perfectly reasonable way to write these programs. Programming in an inherently object-based thing like the DOM without objects.. why?
Saying "OO is Evil" is the flavour of the month. Functional Programming is the new cool kid on the block. This would, in theory, be a good thing.
Unfortunately legions of Javascript fanboys have recently noticed that they don't have the keyword 'class' in the language, but they do have functions and have decided this means that it's a functional programming language, and they knew better than everyone all along.
They'll then follow it up with some perfectly nice procedural code and tell themselves it's functional with a nice little pat on the back.
I don't know if any of the "cool kids" believe Javascript is a functional language. Can one write code in a functional STYLE in Javascript? (can they write higher order functions, can they write functions with no side-effects, could they build monads) Sure, it's entirely possible - just like it is in Ruby, Python, and pretty much any decent language. I think what some of the push is, is to write javascript in more of a functional style as they feel it's more elegant. (I could be way off base though... I haven't been "cool" in years)
It feels like nobody is addressing WHY angular uses DI/IoC.. In something like Java or .NET, you use it to a large extent because it separates code nicely and makes it easier to test.
In JS, one big problems is that you want your code to live in different files, and to do this, you either create your own ghetto object namespaces that hold your classes, or use requirejs.
In the case of Angular, they decided to handle this for you, so they provided IoC/DI as a means to accomplish this. They are merely doing this to make up for things that are missing in javascript as a language.
In their defense, it actually works kind of nice compared to the other two approaches imho.
It's even worse. In Java the whole factory/provider approach was down to a limitation of the type system. Yes they (we) went completely overboard with it and the ridicule is deserved.
But what on earth is the justification for using that pattern in a dynamically typed language that lets you tack anything onto an existing object without controlling its creation?
I too was interested in what decisions spurred this design with application using Angular at one point, and there is a talk from ng-conf by one of the core developers of Angular that I think illuminates this: https://www.youtube.com/watch?v=_OGGsf1ZXMs
It boils down to managing complexity in complex web apps.
I feel like these articles come up every few weeks. people don't understand angular (particularly why DI is useful) and criticize it for being verbose or confusing, usually using the provided sample code -- would it hurt to spend some time actually trying to understand the framework than to dismiss it on face because it looks kind of like something people don't like in Java?
This would happen less if the sample code highlighted the benefits more.
Sample code which shows me how complex something simple is kind of fails at that - and worse, it fails to let me grok why the way they're doing it is better. Where does it all fit in? What will this translate too?
To some extent I wonder if we make the mistake of using "hello world" too readily, whereas what we want to do is show the end product and then start with what that does to simple processes to make it work.
Some people consider it verbose? Wow. After starting with backbone and then later on discovering angular, I can confidently say it is not as verbose as other well known frameworks (such as backbone).
"Dependency injection" is just a silly term for formal parameters. Wow, we can make a function more generic by minimizing the number of free variables! Who knew?
I switched to angular explicitly for the dependency injection. Registering a singleton so it can be passed in to other functions and mocked out easily in tests is something I find extremely useful.
Whether the framework should provide three different ways to register the object is another matter (a design decision along the harder-to-grok vs accommodate-variety axis) but, frankly, if you don't like factories, don't use them.
I don't really agree with the sentiment. I think JavaScript is being pushed harder and in much larger apps these days, which is why these frameworks and design patterns have cropped up. Try getting a large team, building a large app writing cohesive code without some of these patterns. It's true, though, maybe Angular takes it a little too far...but maybe not, I don't know, each project is different in size, scope.
At first, we rewrote an app using mostly just JQuery, but it quickly turned into spaghetti. Then we added four more devs to the team because it's a pretty large project and this is when you need to start reeling in peoples coding style, and applying some design and patterns so that when a new person comes along in 8 months, they aren't totaly WTF?
The author sounds like he's working on a small team (maybe just with himself, since he's writing bot the video streaming/encoding backend along with the front-end), and therefore his style of coding while effective for a team of one or two, likely won't scale up.
I have no idea why the author tries to judge a framework by a stackoverflow post. A lot of the examples are needlessly verbose and some are even wrong, like the "providerprovider" he rightly mocks.
Well, how about we look into the actual documentation?
Next up he still does not seem to understand the difference between Services, Factories and Providers. That's cool and all and might even prompt some to, you know, investigate further and assume that maybe they haven't understood it correctly yet before clicking "must blog now" button. He jumps the shark (straight to ridicule) by making up his very own nonsense:
> Of course we we can configure providers if we need to configure our applications. How else could we configure our applications and make them configurable for our enterprise scale configurable applications.
You know, actually the distinction makes perfect sense. A provider is an object that you know you will want to configure globally before it is being used (data source providers, url routers etc.). A service sits on the other end of the spectrum and is being called freshly right when you need it (more in the direction of the pure objects he has in mind). Factories sit in between those two - they cannot be configured ahead of the application, but allow for more internal functionality instead of just returning an object.
Having the distinction helps people editing the code figure out what they want to do and others, in turn, to understand what the other programmer was up to. Yes, you can use them somewhat interchangeably, but that's life for you: things overlap. How well and strict they are used is up to the programmer.
Now, I'm not bashing plain, custom OOP Javascript - If that's your thing, by all means do it, knock yourself out! But what's with the hating on people who seem to have a different approach? Wouldn't it be healthier to first try to understand where they are coming from? Surely they can't all be totally in love with wasting their time on "ruining it".
----
In the end what this comes down to is that the author doesn't seem to have sufficient experience with the kinds of environments that make the structures in AngularJS not just pleasant, but actually a life saver. That's fine - we don't need to all have the same perspective. I just don't get this style of argumentation that boils down to "don't understand, must bash".
He also makes fun (as does one of the SO comments) of this quote from the (old?) angular docs:
> An Angular "service" is a singleton object created by a "service factory". These service factories are functions which, in turn, are created by a "service provider". "The service providers are constructor functions". When instantiated they must contain a property called $get, which holds the service factory function.
You know what? Fuck it. When I tried to understand the Servicy/Factory/Provider distinction, I stumbled upon the same SO post and you know what ended up being the perfect way of understanding it? Forcing myself to go back to that paragraph right there until I understood it.
> No, you are not reading a thesis, you are reading the angular docs apparently. If it were a thesis it would probably be trying to explain a solution to some sort of problem instead of describing a made up solution to a made up problem. (Actually, that's not strictly true because academics are in a world of their own too but close enough).
> It's okay, I don't really do enterprise any more.
I'm as sceptical as the next guy about frameworks, hate "enterprise" with a fiery passion and I escaped academia before it fried my brain.
But I don't think myself too cool to do my due dilligence before dismissing something that I very obviously don't understand yet.
I think most people here know and understand the patterns involved here: Factory and Provider Model. From this knowledge, I guess the post is easily recognizable as exaggerated. This does not invalidate the gist of his argument. What the post author complains about (and I agree with him) is:
1. These patterns add complexity from the get-go of an app. He ridicularizes, and picks both an extreme example and an extreme Angular solution, but the message is sound.
2. These patterns have failed us in the past. Anyone who has worked on large enterprise projects has dealt with the immense complexity and, surprisingly, with the lack of configurability in the end result (a failure of the pattern objective).
I'd add a last point, not explicitely stated:
3. Last, but definitely not least, Javascript does not need these! Javascript is not a classic object oriented language.
Let me try my hand at supporting my last point. Imagine you want your database connection to be globally configured. You also want code needing a connection to be decoupled from the exact implementation. Just refer to a mythical DBConnection object in the DB client code:
connection = DBConnection.singleton()
And have it so that the DBConnection object instance exists prior to being called (instantiate it in the configuration stage of the app):
DBConnection = { prototype: new PgsqlConnection(...) }
Javascript being classless[1] and supporting prototype based object inheritance invalidates many of the assumptions behind patterns in use in classical OO languages. This is even more relevant when we are talking about flawed patterns.
[1] Yes, ECMAScript 2 and beyond have classes. It's an error, never got traction in the real world, and I hope it never does.
> Javascript does not need these! Javascript is not a classic object oriented language.
No language needs these. To me the GOF patterns have always been wisdom as opposed to a solution. When you are dealing with the interaction between complex systems you can refer to the knowledge that GOF patterns provide.
GOF patterns basically say "this is one way to solve problem X." It is my belief that they never say "this is the actual way to solve problem X." In fact I've found that they are often bad solutions within the context of the problems I solve. Exact copies of them only work in rare academic scenarios.
TLDR; You'll find lots of GOF inspiration in my code, however, you'll never find a text-book GOF implementation in my code.
The message is: we cannot just take "design patterns" from one language and shove them into another. All a "design pattern" is, is standard way to mitigate a lack of abstraction. If the language itself had a way to, say, create singletons (for instance, by having a singleton keyword), the need for that particular pattern would disappear.
Likewise, design patterns for javascript should be based around the points where the abstraction is lacking. Therefore, they'll be likely very different.
Angular is being adopted by a lot of enterprise-y / small business shops, specifically because it can be used (just like typical enterprise code) to have "coders" who don't know how to code, write software.
What's that, you've never used javascript before? Don't worry, just write this one directive, and we'll have someone else test it in UAT. There, now the most harm that dev can do is isolated to one behavior on a page.
So I read this post as an indictment against that style of coding, and for someone who just escaped enterprise consulting, it rings true.
Because the truth is, between jquery / react / backbone / npm and the basic js module pattern, you really don't need angular. Angular just provides a consistent framework for people who don't want, have time, or skill to write an organized front end on their own.
And considering how fast angular is taking over the shops I've seen, the 'you killed it' message might not be so far off.
Angular is being adopted by a lot of enterprise-y / small business shops, specifically because it can be used (just like typical enterprise code) to have "coders" who don't know how to code, write software.
I've heard this claim applied to a lot of technologies, but in the five years I spent in the enterprise software world, I never once saw it happen. People might try to have non-coders write code. For about five minutes. It never lasts longer than that.
What you do see, on the other hand, are a bunch of uninspiring programmers who will find a way to write strictly procedural code in any language or framework.
edit: just realized this might have been a communication problem. I meant coders that have the resumes of programmers, but are specifically hired cheap because they aren't actually programmers, just people reaching for the salary. The kid right out of college with some vb skill. 80 people on visas from some Indian contracting company.
---
Definitely depends on the level of quality of the enterprise shop. When I was doing consulting, part of the new employee hiring process for a new developer at the client site was to open a Microsoft support ticket to help the "dev" install visual studio.
Gotcha. Makes sense that it's just a terminology problem. How uninspiring does a programmer have to be before you can no longer call them a programmer? :)
If you claim .Net programming skills, being able to install visual studio might be a good first step : D
As for a serious answer? Who knows. That said, I know some people dislike eric raymond, but I still keep a warm feeling in my heart for http://www.catb.org/~esr/faqs/hacker-howto.html, if only because its one of the first things I stumbled upon way back.
I disagree: coders who don't know how to code won't be using Angular, they'll be chopping-and-paste JQuery all over the place (assuming an application of significant size/scope)
I'm not disqualifying your post, actually. Directives are pretty horrific to write (I prefer KnockoutJS's bindingHandlers because they are so simple), but I am disagreeing that frameworks are necessary in a large codebase with lots of developers working on them. And that people's codebases are worse off for using Angular than a free-for-all nothing at all. (This comment particularly was directed at the fact that Angular actually has a lot of challenging concepts for your average web developer.)
I agree with both of your points. I was also attempting to point out that large companies with sub par programmers also use specific frameworks as a crutch in order to put boxes around how much of a code base a particularly inept programmer can screw up simultaneously. Angular lends itself to that in the js space.
It's more than "coders who don't know how to code", it's also managers who don't know how to read code or review diffs. Sadly, there are lots of experienced coders whose planning horizon stops as soon as the code works i.e., they don't maintain code or think in those terms as long as it's working. This is often why shops use these overreaching frameworks.
Systems administration is no different, which is why so many servers are now either straight-jacketed in OS packages + chef/puppet/ansible or such a mess they're the equivalent of spaghetti code.
IMO this is fundamentally a failure of higher education (EE/CS, IS ...).
> You know what? Fuck it. When I tried to understand the Servicy/Factory/Provider distinction, I stumbled upon the same SO post and you know what ended up being the perfect way of understanding it? Forcing myself to go back to that paragraph right there until I understood it.
Yeah, that paragraph is difficult if you don't actually read through it and understand what it's saying. However, if you read through it with the intent of understanding it, it makes sense. And I think that really highlights the problem: the author wasn't reading to understand. At the point he got to that paragraph, he was already frustrated or upset, or whatever, and wasn't attempting to understand anything.
Key point: don't read documentation while frustrated. Take two minutes, relax, kick back, and read it with the understanding that it can teach you something.
I'm in the position of having written frameworks. I read that paragraph and though "Exactly! This is necessary for dynamic object binding using containers" etc. Nothing unusual at all. It depends upon context. As a professional I find it odd the OP brags about remaining ignorant of a common topic in his field.
Simplicity is actually really difficult to achieve. The only anti-intellectualism is Angular offloading that burden on it's developers. There are many other binding frameworks that have put more effort into both their use and their documentation. Hell, in the time you've read this you could already be a ractive.js expert.
It's easy to not use a C-based language and forget that there are many fundamental patterns that are still applicable, even if they look different. The purpose and intent behind a pattern is generally more important than the actual name used or the code structure. The factory pattern defines what it does (essentially code that creates objects without the caller needing to know the details), not the syntax behind it.
I see this happen all the time, even in functional languages.
I don't think the author jumps to conclusion prematurely. He hates all this factory, provider, blah, blah nonsense, and I can identify with the feeling.
It seems like your response is based around "it's not easy to understand or comprehend, but can be with plenty of skullduggery". That's not what we need in the programming world. Things don't need to be made inaccessible for the sake of being inaccessible.
Hmm -- there's no indication for the author not understanding the patterns. The point is, JS does not need these patterns (which are usually imported concepts from other languages), there are unique ways to do it in JS. (Think of late binding.) The critique is, JS is becoming that enterpisey like backends used to be at the time of the dot-com-bubble. It's the framework bubble.
Developers have become used to loading several K lines of code, just to remote control quite simple tasks, that could have been done natively by a humble number of lines of code. It's high time to point out that there isn't any emperor inside the new cloths! (Just a bunch of woven code.)
...When someone has a bunch invested (time) in a thing, it's understandable (not necessarily justifiable) to be defensive about anything that challenges that thing.
And the converse of that is that when someone spends a lot of time deliberately not learning a thing (as the author of the article seems to have done), it's understandable for them to be defensive about the utility of those things.
The author makes one fundamental error, which is the assumption that any of those things are necessary. You don't need to "create a hello world service to create the hello world factory to create the hello world sercice so you can print hello world on the screen". You can just print hello world to the screen. You can do it in the template, in the console, wherever.
You don't need layers of abstraction for simple tasks like "printing hello world", but when you have things that do need those layers of abstraction, they're there, and they're appropriate. The alternative is to write uglier code, which it seems the author prefers.
That said, I don't mean to discount preference in this debate, which many seems to have done. If it isn't to the author's taste, then cool. If he'd rather write small, pluggable modules, that's cool too. Those small, pluggable modules have their limitations though, and the author either hasn't run into them, or refuses to acknowledge that, at least for some use cases, small, pluggable modules aren't actually the best choice.
You should check the background of the author, I can guarantee you that he has more then enough experience...
In most cases the necessity for factories and providers in IOC-containers are an indicator that your software is badly architected. Lots of us have walked that path in the past, and now know how to handle this.
I hate to bring you the news, but your comment might actually indicate that you are on the beginner expert level.
So much of the bad stuff in enterprise-style web frameworks is basically a software reinvention of classic bureaucracy. Concepts like inversion of control are meaningful, but applied in accreting layers they turn APIs into a re-enactment of Kafka's The Castle.
The application developer is left holding the receiver of the telephone that supposedly allows him to receive calls from the Castle. If only he can get the right person at the other end of the line, then everything will certainly be sorted out! The Castle is there to serve the developer, so of course there is someone at the Castle who cares: it must be that he just hasn't got the word yet...
"My dear Land Surveyor," replied the Superintendent, "how on earth should I know all the sons of all the under-castellans?"
"Right," said K., "then you'll just have to take my word that he is one. I had a sharp encounter with this Schwarzer on the very day of my arrival. Afterwards he made a telephone inquiry of an under-castellan called Fritz and received the information that I was engaged as Land Surveyor. How do you explain that, Superintendent?"
"Very simply," replied the Superintendent. "You haven't once up till now come into real contact with our authorities. All those contacts of yours have been illusory, but owing to your ignorance of the circumstances you take them to be real. And as for the telephone. As you see, in my place, though I've certainly enough to do with the authorities, there's no telephone. In inns and suchlike places it may be of real use, as much use say as a penny in-the-slot musical instrument, but it's nothing more than that. Have you ever telephoned here? Yes? Well, then perhaps you'll understand what I say. In the Castle the telephone works beautifully of course, I've been told it's going there all the time, that naturally speeds up the work a great deal. We can hear this continual telephoning in our telephones down here as a humming and singing, you must have heard it too. Now this humming and singing transmitted by our telephones is the only real and reliable thing you'll hear, everything else is deceptive. There's no fixed connexion with the Castle, no central exchange transmits our calls further. When anybody calls up the Castle from here the instruments in all the subordinate departments ring, or rather they would all ring if practically all the departments -1 know it for a certainty - didn't leave their receivers off. Now and then, however, a fatigued official may feel the need of a little distraction, especially in the evenings and at night and may hang the receiver on. Then we get an answer, but an answer of course that's merely a practical joke. And that's very understandable too. For who would take the responsibility of interrupting, in the middle of the night, the extremely important work up there that goes on furiously the whole time, with a message about his own little private troubles? I can't comprehend how even a stranger can imagine that when he calls up Sordini, for example, it's really Sordini that answers. Far more probably it's a little copying clerk from an entirely different department. On the other hand, it may certainly happen once in a blue moon that when one calls up the little copying clerk Sordini will answer himself. Then finally the best thing is to fly from the telephone before the first sound comes through."
Don't know about this link, but I read a translation of The Castle to my native language, and it was clearly his best book ever, although it was not finished. However, it always confused me why it didn't have more rightfully deserved attention.
This article really hits the nail on the head. In the comments, many people confuse layers of indirection with dependency injection. Those are 2 separate things, you can have dependency injection and not have 100 layers of indirection that confuse the hell out of people.
And while we're at it. Why the is there a term "Dependecy injection"... it's freaking argument passing to functions, and it's been around a really really long time. I'd expect this kind of crap from the JVM and other OO only worlds, but JS is more functional then it is OO, you have higher order functions...why the hell would you want to think in OO terms?
For me, the most helpful feature of AngularJS is the separation of DOM and data.
If you just want to use that feature, but you do not want all the framework stuff, you actually can. Here is my way of doing it: https://github.com/julius/AngularLite
Disclaimer: I actually like the framework stuff. I just made this to use it in an existing project (which is too big for a total conversion into the framework structure).
For all the negative comments about FactoryProviderBeanCreator whatever style of enterprise-programming: There is a point to it all.
The point is software exists mostly within its socio-economic context - software is mostly made for people by people and will be used by people.
The SingletonProxyFactoryBean enterprise-programming tries to solve people-problems, it tries to waddle through dependencies between libraries, frameworks, language specifications, implementations, organizational structure and various teams within an organization.
This angular.js enterprisy-feel tries to do the same - push responsibility onto the others, or separate responsibility down (separation of concerns) where nobody actually has to do anything but "configure". Or "run" it. Or just "buy" it.
Thats the ultimate goal of enterprise and this style of programming - which eventually leads to somebody being required to know a language on top of a language on top of a language to adapt it to the business needs.
Its the same reason why abominations such as SAP and Microsoft Dynamics (or basically any closed source very expensive suite of software) exist - those products are on the altar of Enterprise, they fit well to the organization and culture of capitalism. They fulfill the goal of "just buy it" or "just install it" and it will do _everything_ a manager or team thinks of. So the programmers make it so - sure the program doesnt actually do anything without the correct set of configurations and options, but now its not an application thats developed inhouse, its a product we buy and can get support for, kind of.
I think there is a different point to it all: Java doesn't have first-class functions.
In OCaml (and without doubt other programming languages as well), you can use a function to make "objects"/"values" that you want made ("constructors"). If you want to parametrize the function ("factory"), you just partially apply it to some arguments. If you need to make other objects before you can make the desired object ("dependency injection"), you pass other functions as arguments. If you want to do something else instead of creating a new object (e.g. "singleton pattern"), you write a different function.
Its not a Java problem as this JavaScript demonstrates.
Its not a language feature X problem.
There is something which drives people to make a factory for a dynamic and another static language. Instead of writing the thing they want they write a thing to give them what they want.
'They fulfill the goal of "just buy it" or "just install it" and it will do _everything_ a manager or team thinks of.'
That's really not how SAP or any of the Dynamics products get implemented...
Actually, ERP systems are a good example of applications where the complexity pretty much comes from the requirements - they tend to have staggeringly long lists of things they must do. I wouldn't knock SAP or any of the Dynamics products - they are complex because they have to be.
Screw the technical merits of arguments for and against frameworks in general or Angular.js in particular - that's not really the point. By internet standards, it's a great article because it has an interesting topic, personal narrative, a strong opinion, a bit of humour, consistent tone, and a reasonable style. In the tradition of wistful paeans - the author is longing for a more wholesome past when JavaScripts roamed unfettered by barbed wire across a pastoral landscape of virgin DOM's [yes, intentional] and free of proletarian factory classes.
It's entertainment not evangelism. Nobody whose work-a-day problems are soothed by Angular will go native because of it. It's sermon about 'those people' and the choir's Schadenfreude...and then once the act writing this comment hit 'Schadenfreude', I had to ask myself is it a good article by HN standards?
Empirically, probably yes. Theoretically no. The problem with Schadenfreude is that it comes at the price of another's misfortune, and that is a route to the meanness that both entertains the internet and harms StackOverflow. Telling people that you are laughing at them is the hell of junior high bullying - it's just that cool kids get paid to do Erlang and the kids in Toughskin dungarees are getting mocked for using JavaScript boiler plate.
It dawned on me that the best HN articles are written in the spirit of mudita - finding joy in the good fortune of others, not their misery unless our humor is black and shares their burden.
Another case of "I don't understand something so I'm going to just say it's too complex and stupid". The author completely misses the point of service injection in Angular, and then goes on to offer a simpler "solution" that doesn't even remotely do what service injection is trying to do.
Here's the thing - Inversion of Control exists for a reason. Once your codebase gets to a certain size it becomes far, far more manageable to work with loosely coupled components that have no direct knowledge of each other.
These abstractions are a good thing. Lord knows how many projects I've had to fix because some idiot decided that "Architecture" was just some silly crusty of enterprise thing, and "Frameworks" are too opinionated - so instead they decide to ignore 50 years of industry conventions and write a spaghetti code pile of shit (But at least there are no factories!)
Whether you're using procedural, functional, or object-orientated style - A large codebase is still going to be unmaintainable if you don't understand how to write loosely coupled components. (More specifically, don't write a large program - write lots of small ones and compose them together).
You may be confusing abstraction and indirection.
Of course writing large software is hard, and of course we want to make it easier. The real question is whether we want to do it the same way in Javascript that we did in Java, and the answer's probably no.
Also, a large codebase can be very easily maintainable with tightly coupled components. The only reason you would want to loosely couple them is if you have a reasonable belief that you might want to swap out the implementation at some point, and even then you can usually do it fairly transparently by adding the indirection when it comes to it.
> Also, a large codebase can be very easily maintainable with tightly coupled components
Agreed, but having worked on large codebases it's usually easier to plan ahead and decouple from the start - it can be hard to decouple components later when you didn't plan for it. It's also much easier to properly unit test when you can trivially inject a mock.
Of course this is only relevant if you're building a large project. The typical web app just doesn't need it.
I wish a more thoughtful criticism of angular without all the vitriol was getting up-voted to the top of HN rather than this drive-by blog post. It's clear that anti-framework people are up-voting to validate their own world views.
"Enterprise sucks, frameworks suck, X language sucks..." You don't like, but other people like it, get over it. Just don't use them and stop complaining all the time.
>You don't like, but other people like it, get over it. Just don't use them and stop complaining all the time.
Yes, it's like there's these things called "opinions" and people are posting theirs and trying to compete for mindshare.
Instead everybody should just do whatever thing he prefers, and nobody should attempt to convince others that this or that way is better. We are all unique snowflakes, after all, and it's not like an industry or profession needs best practices...
Everything is an opinion. Instead of dismissing it because it is not universal, you can think it through, take the good stuff and compare it to the good stuff from opposing opinions. Then you find the middle ground that suits your context best. That's how people learn - they read and study all extremes and then make decisions. The post is very useful, even if only for making the Angular community stop and think twice about stuff.
I suppose what's really tiring is that this sort of writing is upvoted by enough people to make it hit the front page.
The magic formula is basically : "Bait title" + "personal opinion that is not necessarily backed by any real world experience and expertise".
There won't be that many good developers that actually worked on projects with a huge code base and that support the notion that DI, frameworks and so forth are "bad". The other half up-voted this post and the top comments apparently.
I like it because it's about technology and it's entertaining. I used to complain about the content but now I accepted what comes up and learned to ignore any title with "2048" in it.
This indictment of angular and 'enterprise' frameworks is pretty one-sided and self-righteous. I hate the bureaucratic and restrictive nature of some frameworks too, but you can't dismiss the entirety of them and the problems some of them solve because of it.
It's very easy to criticise without suggesting or showing any better alternative. For example... if you are a software manager with the 'power' to choose an entire stack for a new product, what would be your choice and how would you justify it on criteria such as: availability of documentation, developer skillset, testing, security, performance, platform compatibility, time to market etc?
Unfortunately all this type of 'boring' shit that enterprises deal with, they have to deal with for a reason. If you don't like that then you have a problem with the structure of the economy, larger businesses, and their politics as well as the technology.
Good article, I do a lot of Java coding that isn't complex at all, the stuff he shows in the article looks like the EJB people got hold of JavaScript and went wild. That's sad because I'm getting back into the front-end more and finding jQuery has stood the test of time and is actually fun to use.
Second vote for Knockout.Js. We use it as a base for building up out own framwork/patterns. It's got a couple of benefits, too:
1) It's easier for non OO-devs to understand, especially when coming from a JQuery-only background. Because it's mostly dealing with two-way data-binding, and separating your DOM from yoru code via a ViewModel.
2) it's a lot easier to make custom bindingHandlers than it is Angular's Directives. (And you'd be surprised - or not - at how many web devs even stuggle with KOs simple bindingHandlers syntax)
3) it's easier to work with straight JQuery widgets without a lot of re-wrapping kung-fu, so when you find a component you want to use, you can get it into your project in a straightforward way. (In a pinch you can write some functions on you KO ViewModels that access JQuery directly)
4) You might/might not be creating a SPA app that requires the routing API
5) You're free to build your own service layer for interacting with your crazy service (we have legacy Soap-based WSDL that we manipulated into JSON)
All of this could be build in Angular, too, and that would have some potential benefits, mostly potentially around testability, but won't only have integration tests, so...
I think the OP and some of the people in the comments thread just don't have the kind of experience needed to realise why Angular is the way it is. The OP does not seem to be a JS developer, definitely not with experience in larger applications or in larger / multiple teams working on the same codebase. Checking his profile, all I'm seeing is short weekend projects and a small (code size based) library; definitely not the kind of thing where using AngularJS would help out with.
Just saying; if your only experience is small solo projects (instead of >10K loc, team-based projects etc), then yes, AngularJS will quickly smell of enterprise and eww, especially if based on just that one SO post from a long time ago.
If however you've trudged through unmaintainable jQuery code, wrote >30K multi-team BackboneJS applications, etc, then angular is a relief. It allows you to stick to patterns, to isolate your logic, to not have an excuse to not write unit tests anymore, and to actually write an application instead of struggle with your framework or how your views get rendered and when.
> Start thinking for yourselves, ditch this shit before it’s too late and learn how to write some actual fucking code. The information is out there, you can do it. If you need handholding with factories and providers and service provider factories then consider that the world doesn’t need your bullshit code and go and get a job you’re actually good at. Stop ruining it for the rest of us.
It's unfortunate that this post was written in a provocative manner with a very inflammatory tone, because once you look past its rant-y nature, I think it raises an interesting argument.
From what I could tell, the gist of the post seems to be that instead of relying on someone else's pre-made, out-of-the-box general framework solution (which you have to heavily configure to your specific needs, and is so complicated that you end up needing to hire highly trained consultants), you can create simpler, more elegant solutions simply by writing them yourself from scratch.
I'm not going to agree nor disagree with that argument, I'm only trying to state what I think the gist of it is.
Thank you Rob. Although there are perhaps some things to nit-pick about your post, I think you have expressed something important about recent changes (last 5 years) to attitudes in the JS community.
This is silly. It basically amounts to "waaaah I don't know angular!" because they saw funny words I a stack overflow example.
Factories etc., in angular are not the same as the Java equivalents. And you're usually not going to be using providerProviders in your application code, that stuff goes in libraries that, yes, need to be configurable.
Angular is a boon for writing testable, changeable javascript apps. Just because one of the features happens to use words you don't like in java doesn't mean JavaScript is ruined.
I don't think unit tests should dominate the architecture of your applications. I hear this a lot from the angularjs crowd.
I also disagree with architecturing your applications for things that might need to be changed in the future (but probably won't). That is something from enterprise and Java world and a lot of people including myself dislike it. I know people who love it though and that's fine, as long as I don't have to work with them. :)
Yes, most of the code will never change. But some of it will, and it's sometimes hard to predict what that will be. So, to an extent, all of your code needs to be written so it's changeable in the future. It doesn't have to be enterprise java style to be flexible -- just well encapsulated, and testable code helps with that.
Also, it seems like people in this thread who haven't used angular see that word -- factory -- and think of endless crappy java abstractions. You are overestimating the overhead that angular is bringing into your application in this case. A factory is just a component that can be shared between controllers. It's a singleton, like a lot of sharable components in vanilla Javascript applications, just with a defined way of being injected into the controller, and a way of declaring dependencies.
If your problem is with object oriented programming in general well... I can't help you there.
This is just plain absurd. We are not in a one-size-fits-all industry. Far from it. Just because you don't quite understand the benefit of a very specific framework (that, incidentally, you know virtually nothing about) does NOT mean it is not useful, or that it has "ruined" anything. We pick the best tools for the job. In some cases that actually IS Angular. In many cases, it is not. But to make broad generalizations like this does nothing but show a lack of understanding.
It's not the language, it's the people... Most developers are... not very good. It's a fact of life. Abstractions are a phase in learning how to code: I am not surprised that people reinvent the wheel in [insert-currently-trendy-platform].
I am surprised that people think that a LANGUAGE can make any difference. Languages are tools, stop pretending they make any difference and fix the people :-)
No. The purpose of a programming language is to remove the incidental complexity leaving only the intrinsic complexity of the task. All languages have the same expressive power in principle, but it is intrinsically easier to perform certain tasks in certain languages.
For the application I'm developing I've decided to keep it simple. Instead of relying on a complex framework with a lot of abstract concepts and layers, I'm using jQuery Mobile, Riot.js events and Handlebars templates. The actual application code is plain old JavaScript and I can actually understand what's going on at any given time.
The OP got a two-fer: mixing the arguments for/against Angular and the arguments for/against JavaScript frameworks in general. I think they are separate conversations, which is evident below (or above) depending on which threads your read.
Came here expecting to be annoyed at yet another post suggesting we use yet another framework. Pleased to see to see a reasonably cogent (if not a little overly antagonistic) example of why all these frameworks are crap.
It's like a decorative tuning of a broken car. But it was already broken to begin with. The problem is that everyone is too familiar with how to drive that specific brand of broken cars.
I've come to the conclusion that this non-programming programmer "design pattern" fad is a way of obfuscating mathematical and computational concepts while making them no less hard (as we see by them often being poorly used) but seem less hard (and, paradoxically, more intelligent due to buzzword compliance) to the businessmen who, because of programmers' weak professional identity, call the shots.
Curried function? Too mathematical. Let's call it a Factory.
Tree-walking algorithm? Let's call it a Visitor.
Sinusoidal curve? Again, too mathy. Let's call it the Vibrator pattern.
Lots of words get spilled, mediocre employees remain employed, good people leave or get fired while trying to fight the current of stupidity, and nothing gets done. Brilliant! Now, you can go a step further by creating a system to monitor those mediocre employees, making them basically employable while bringing down the top, and call it "Agile" when it's the exact opposite of agility.
A factory and curried function are quite different concepts even if some functionality overlaps. Ditto with tree walking patterns and visitors. Abuse is quite common, because many people are exposed to one and not the other, so use the name hey know other than the one they don't know. Naturally human.
Well, yes, but then that's all patterns are: terms used to represent a way of doing something. It's sort of marketing for methods - and whoever did the marketing for "curried function" just didn't do a good enough job, maybe.
obfuscating mathematical and computational concepts while making them no less hard
It seems to me that what makes some programming tools better than other is that they hide mathematical and computational complexity while making solving problems easier - nothing is going to make the computationally hard or intractable not hard or intractable.
Attempts to hide computational and mathematical complexity is pretty much the theme for a whole history of programming languages. It certainly is its genesis story -
at which point the history of debates over programming languages begins, and it seems to me that this debate is largely because what I call 'hiding computational and mathematical complexity' you are free to say obfuscates it. It's how we get the yin and yang of C and Scheme making 70's scene - malloc and and full lexical scoping both simplify someone's life and make someone's unbearable.
I always know that there's a bad OOP example when automobiles are involved. It means it's a marketing piece not a tutorial - managers have cars and as a lowest common denominator of technical knowledge know they have four wheels, provided we ignore the one in the trunk. In other words, we've already lost because the person writing the explanation doesn't know the difference between hiding complexity and obfuscating it [How many cylinders in a Mazda Rx-8? Where does the Leaf fit in?].
On the flip side, what can we expect? Math is hard for a lot of people because it builds sequentially. Teenage hormonal distractions have probably prevented more people from moving beyond ciphering to algebra and beyond than anything save for access to educational resources.
FactoryProviderProviderProviders in the form of frameworks don't necessarily require understanding of higher order functions - like garbage collection, some lazy programmer wrote a program to handle it, and this turns out to be useful because people can use it without really understanding what it is, and being able to use things which are not computationally understood is pretty much the driving force behind the rise of OOP - how many people talk about dispatch when discussing an object's methods?
OOP is a sexier Cobol - cars and their wheels makes for more interesting story than employee records. Even better, outside of the automobile industry, there aren't going to be pointed questions related to domain knowledge (a real risk when discussing employee records with a business person). This and the fact that OOP code is less accessible to the non-programmer than Cobol [which was designed for the boss to follow] gives us Java in any language.
Determining if the conceptual merger of Java and JavaScript described by the author is ironic is left as an exercise for the reader.
For all the talk of abstraction by so many programmers, I wonder how many of us just really want metaphors. Ways of organizing and relating to code that are at least vaguely familiar.
But then some programmers start talking about abstract math and category theory, and many people recoil because it is too abstract, or because it is so abstract that it is more general than the most immediately obvious metaphor (Functors are kind of like boxes, but not always. You should think of them like computational contexts instead).
Of course metaphors have their place; there is no need in making things less relatable just because. But at some point you may have to abandon the comfort zone of trucks being a specialization of a more general car blueprint.
I think it's more concrete. FactoryProviderProviderProviders provide a common set of procedures for programmers to provide programs [sorry, second cup of coffee]. All that framework makes the landscape familiar and allows the procedures which worked for generating Java code to work when a person wants to generate JavaScript. It provides space for algorithms for writing programs.
The tradeoff is that it will never be done in a way that optimizes on logical insight. Simple currying would be simpler but the boss still might not understand it, and it's better culturally if the boss doesn't understand sixty lines of boiler plate than twelve lines of mathematical reasoning.
The advantage is that the programmer can know, if I do these things I will get close to the result without worrying over much about the degree to which I might lack deep understanding. On HN there are plenty of people comfortable with the idea of factories as curried dispatch constructors. But that's not the typical case.
Simple currying would be simpler but the boss still might not understand it, and it's better culturally if the boss doesn't understand sixty lines of boiler plate than twelve lines of mathematical reasoning.
That's the whole problem, the notion that "the boss" needs to understand how the code works. OOP patterns are designed to "model" real-world business objects and processes so that they can be documented on a UML diagram that business analysts and managers can look at to grasp how the software works without having to understand how computers work. This is a big reason why the software gets unnecessarily complex--the real world is infinitely complex.
Most of the time, what you actually need the software to do is not nearly as complex, though, so it would be better to just write simpler code that does the thing that needs doing rather than models all the things. But in that case it's harder for the non-technical boss to understand the logic without a handy metaphor.
The layer of abstraction that seems to be most frequently violated in enterprise contexts, is the software developer's job itself.
For whom is the idea that the boss needs to understand the program a problem and why?
The typical answer is for programmers and because then the boss might have specific technical input rather than requirements and under bad management that could be a problem - i.e. keeping the boss from understanding the code is a defence to mitigate bad management which has the added benefit of UML diagrams a likely first place for a bad manager to cut costs.
Much of the last 40 years has seen software engineers exchanging the human parsablility of Cobol for the utter impenetrability of regex's - culminating in Perl which was so impenetrable to even programmers that Java had to be invented. Anyway, the idea that a computer language should allow an intelligent lay person to follow an algorithm written in it died with Cobol. It - the idea not Cobol - might be worth revisiting in language design.
Of course the idea I was trying to express is that the boss will feel better at not understanding 60 lines of boilerplate javascript than not understanding a dozen lines of elegant Haskell.
It's bad for everyone involved because the programmer loses the ability to make decisions about how to structure the program he/she is working on, and the manager and/or business analyst waste lots of time worrying about intricate technical details of someone else's job, when they should be tending to their own responsibilities. It's a violation of separation of concerns and a disrespect for the software developer's domain expertise.
The trend I have seen in enterprise software is that, because good software developers are expensive and in high demand, the business attempts to commoditize them by having lower paid, semi-technical staff (like business analysts) do everything except for write the actual code, limiting the developer's job description to simply translating a diagram and a list of features and business rules into Java--like some sort of human compiler.
That approach is doomed to produce terrible software forever, because you can't write good software without thinking deeply and understanding both the problem to be solved and the tools available to solve it. And you just can't commoditize a job that requires that much thinking.
On the other hand, I do agree that software development needs to be made easier than it currently is. It is currently very hard because the current tools we have are built on layers upon layers of leaky abstractions that still require a highly trained and experienced individual to understand first, in order to be productive. Making programming languages more easily comprehensible to humans, is a big part of that. Programming languages are for humans, after all.
Well, you misunderstood, and now you're ranting according to your misunderstanding.
I'm not an Angular, expert, but I'm pretty sure that the situation is this:
1. "Hello world" does not require any dependency injection whatsoever. (ie. it does not require services, providers, or factories). Note: if this was not true, I would agree with this rant completely.
2. If and when you decide you want dependency injection, if what you want to inject is a simple value, you can just provide it directly, without using a service, provider, or factory.
3. If and when you decide that you want to provide a dynamically-generated value, you can specify a function instead which will get called whenever the value is requested. This is called a "factory."
4. If and when you decide that you want your factory to just "new" an object instead of running an arbitrary function to provide the value, you can register that object type as a "service."
5. If and when you decide that you want to configure that object type first, you can register it as a provider.
If you want to stay at step 1 forever to keep things simple, groovy.
This is a example of success, not failure: you pay for only as much complexity as you actually want to use.