Settings

Theme

The inverse of IoC is Control

comoyo.github.com

65 points by ingridod 13 years ago · 65 comments

Reader

roam 13 years ago

Don't use IoC if you don't need it, but I'll explain why we need it in our case: some customers require different implementations.

That's where the DI part comes from -- to enable us to load a different dependency based on the customer. Now, you could provide a different bootstrapper class per customer or start building a mega class with a lot of ifs-and-buts(elses), or you specify this kind of stuff in a configuration file.

We opt for configuration files. We opt for IDEs that can interpret Spring configuration files which means typos or incorrect dependencies do show up. This allows us to swap out implementations in case shit goes down without having to recompile, connect over a VPN to a remote desktop and hop through a few more hoops to get our class file on the other side. If you're not running your own apps on infrastructure you control (we should be so lucky), you have to take this sort of stuff into account. I'd love to be able to say "This is how stuff's set up. Deal with it."

(And when shit goes down, it is usually not at the place you were expecting it to happen, which means all kinds of configuration options for your bootstrapper would probably still fall short.)

  • zupatol 13 years ago

    I agree with using IoC for different implementations, but I'm puzzled by those who want to use it everywhere, because it supposedly makes the code easier to test.

    Guice is a nice IoC framework, but look at what they say on their website:

    "Think of Guice's @Inject as the new new."

    http://code.google.com/p/google-guice/

    • nkohari 13 years ago

      Testing is kind of a side effect. When you design your code with IoC in mind, you naturally will create more logical separations and avoid tight coupling -- which in turn will make your code easier to test. (Source: I wrote Ninject. :)

    • edwinnathaniel 13 years ago

      If your code has a hard-static dependencies to web-service call, you can't test it easily (and repeatedly). Especially when the actual service is down.

      If your code has a hard-static dependencies to DB call, you now have excuses not to write test against it because "it's hard to prepare the environment to do such things."

      Not all projects are as small as a Todo-List written using Rails.

      Medium-to-Large size projects with large DB schemas exist in which it will take hours to run your Rails tests: "testing-my-active-record-models-as-unit-tests"

  • philbarr 13 years ago

    Exactly, you should really think about when and if you need IoC, just like with any other technique. It can be really useful. Unfortunately, if misused, it can lead to an absolute nightmare.

    The problem is that when people learn about new techniques then they end up wanting to use those techniques in their next project. It reminds me of something a doctor said to me once, "Every time a new disease is identified there's an epidemic." Meaning that when doctors have something they can now identify as the new disease they are much more likely to do so since they've just heard about it, when before they would have identified it as "flu".

    • bjhoops1 13 years ago

      Or as a senior developer I know often said, "To the man with a hammer, everything looks like a nail."

  • MatthewPhillips 13 years ago

    Why not just split out the shared code into libraries and make your main() be different for each customer?

    • jedbrown 13 years ago

      Then updates to the customer's configuration requires modifying code, compiling it, and shipping the result. It's easy to put an interface on configuration file modification and in many cases, updates can be applied without needing to restart a running system.

      • MatthewPhillips 13 years ago

        That's the problem with soft-coding, you trick yourself into believing that modifying a configuration file is not modifying code, but it is. It's code that isn't compiled, isn't regression tested.

        As far as re-shipping, nearly every language nowadays has a method for automatic updates. Here is what Chrome uses: https://code.google.com/p/omaha/

        • bunderbunder 13 years ago

          It's absolutely modifying code.

          But it's modifying code that your support team is allowed to modify in the field. By contrast, depending on the business policies in place any code that has to go through a compiler might also have to go through meetings, reviews, QA testing, a release cycle, IT department scheduling, acceptance testing, blah blah blah.

        • jedbrown 13 years ago

          By this logic, every user is "programming" when they change their facebook account settings or configure the appearance of their desktop. Call it what you want, but configuration via "config files" of some sort (perhaps managed by a GUI) is a totally different beast from modifying 'main'.

  • ollysb 13 years ago

    There really isn't much difference between using a bootstrapper class or a spring xml file, they're still both configuration files and should be equally convenient to maintain.

    One of the advantages spring gives you in your scenario is multiple options for configuring your app. So in your case you can use annotations for parts of the app that don't change and then specify the parts that are different for each customer using xml(I seem to recall you might even be able to wire up a spring container using vanilla java).

    Spring actually brings a lot more to the table, properly qualifying it as an IOC container. It offers mechanisms for applying cross-cutting aspects such as transaction and security management.

nahname 13 years ago

IoC is automating the code required to wire up objects that are properly decomposed.

When you spend a long time learning how to effectively work with static languages, a few things come out. Dependency inversion and composition.

Where does this leave us? It often means we have classes that need one or more other objects when they are instantiated. This often results in chains of objects. For example,

  new Repository(new SessionFactory(new Configuration()))
Writing that code is pretty painful. Rather than dealing with long chains of dependencies, manually wiring everything up. You define mappings and let an IoC container do it for you.

Why not just wire everything up manually in static functions and be done with it? It is really hard to change static code and often impossible to test it in a language like Java/C#. There is almost nothing you can do to test a piece of code that calls out to User.find(1) in one of it's methods.

Why are there no IoC practices in ruby? Primarily because the second point is no longer true (you can test everything easily). I still think there is merit in knowing the dependency chain rather than just calling User.find(1) and hoping that something somewhere conjures up a database connection and configures everything correctly, at the correct time.

IoC is control and automation. Those are both powerful tools to any programmer.

  • bborud 13 years ago

    > new Repository(new SessionFactory(new Configuration())) > Writing that code is pretty painful.

    If you think you are making things less painful by obfuscating the code snippet above I would challenge you to think about what you are doing. The above is incredibly clear. There is no doubt what is happening and if you screw up the compiler will yell at you.

    If you obfuscate it through annotations and force readers of your code to try to reason about how the system will behave runtime, you have added exactly zero value. You have only degraded the readability and understandability of the system.

    A little extra typing never killed anyone.

    • bunderbunder 13 years ago

      > If you obfuscate it through annotations and force readers of your code to try to reason about how the system will behave runtime, you have added exactly zero value. You have only degraded the readability and understandability of the system.

      I'd argue a few things here:

      1. An IoC container that relies on annotations or XML configuration is not an IoC container that you should be using. Unless you're using an IoC container to help with field configuration, component registration needs to be done through a fluent API so that it's strongly typed and right there in the code where everyone can see it. A well-crafted registration routine should be every bit as readable as the hand-coded factory it replaces, if not more so.

      2. Code that's architected in such a way that you need to understand explicit details about the order or manner in which objects are instantiated is code that is not ready to be used with an IoC container. The SOLID principles are a non-negotiable prerequisite of any IoC container. If you haven't drank that Kool-Aid, an IoC container doesn't really have a lot to offer.[1]

      3. It's not about making individual snippets of code less painful. It's about making the long-term maintenance of the application - or, for preference, an entire suite of applications - less painful.

      1: http://kozmic.net/2012/10/23/ioc-container-solves-a-problem-...

    • nahname 13 years ago

      You don't annotate anything. It simply becomes the following,

        ...
        public Repository(ISessionFactory factory)
        ...
      
      The repository never knows about IoC or where things come from. Nor should it.
  • bunderbunder 13 years ago

    Everything you're saying is true. But so is a lot of what the author said. Especially in the last section.

    I've run into situations with Windsor along the lines of what he describes, and it really is a distressing situation to be in. You're happily coding along, whipping the project together, hacking decorators, auto-registering everything with a great set of conventions, and generally having a grand old time. And then something goes kachunk and suddenly it's damn near impossible to figure out how to tell the container exactly how everything needs to be wired up without creating a raft of custom dependency providers to deal with special cases that the container just wasn't designed to handle properly. And the configuration becomes increasingly diffuse, devolving into a mishmash of conventions, manual registrations, and registrations that are implied by custom implementations of IFooResolverProviderFactory, until eventually you realize that you're working with a modern-day edition of what Dijkstra was talking about when he wrote GOTO Considered Harmful. And at that point it might be time to tearfully say goodbye to the IoC container and hand code some abstract factories, because not only will they be less opaque but you'll soon discover to your own horror that they actually reduce the SLOC count.

    But - butbutbutbutbut - where I depart with the author is in thinking that this means that IoC containers are bad. Quite the contrary. Avoiding an IoC container because your dependency graph might, just might turn out to be more complicated than what the container was designed to handle is a premature optimization. And will probably lead to worse code than what you'll get if you start out with an IoC container and are forced to give it up later, since using an IoC container really does encourage SOLID code.

    I guess what I'm saying is, IoC containers are only "mostly amazingly great." It's still a young technology with some kinks to work out. Even venerable old Windsor is still experiencing significant API flux. They don't necessarily have an answer to every use case yet, even if they are getting damn close.

    Oh, and writing libraries. If you're a library, you are not the composition root, by definition. And if you're not the composition root, you don't get to use an IoC container. Sorry. Have a facade.

VexXtreme 13 years ago

I have found that in a lot of cases IoC ends up being completely misused and abused in really horrible ways. One of the more common antipatterns I encounter is creating an interface for every single thing in the application ("because hey, the implementation might change and it'll be easy to swap out"). No, if you're building a webshop or a task management application, abstracting and injecting your business logic or domain objects is as stupid as it gets.

I always keep hearing this argument "but something will change". No, it won't. Is it really worth introducing all this boilerplate nonsense into the application just for the off chance of something changing at some point? And even if that happens, don't you think you're better off just doing whatever modifications are necessary vs. putting all this crap into your application?

The only scenario where I've found IoC to make sense is when an application depends on a module and that module REALLY needs to be swapped out with another one. I once had that with a stock market analysis application that depended on X service for data feeds, but X service suddenly stopped working and I could just inject Y service instead without having to change anything else. But even in that case IoC container would've been redundant as plain old DI does the job just fine. That was the only thing in the application that I wrote that way because I didn't want to hard code an external dependency (that I have no control over) into my application.

But what I keep encountering is the cargo cult approach to programming where IoC is done for the sake of IoC and everything is injected for the sake of being injected, with no rational explanation as to why. It's quite terrible really.

  • specialist 13 years ago

    > creating an interface for every single thing in the application

    Ditto turning everything into a "service" a la WSDL and now SOA. CORBA lives!

wcoenen 13 years ago

It turns out that there is a problem with instantiating everything manually in main if you have a lot of components: it becomes non-trivial to figure out the order of instantiation.

This problem will typically surface whenever you add a dependency between existing components. If the dependency is currently instantiated after the changed component, it will have to be moved up so it is instantiated earlier. But then it turns out the dependencies of that component also need to be moved up etc.

To deal with this you then have to calculate a "dependency rank" for each component (i.e. 0 for components without dependencies, and x+1 for components where the max rank among the dependencies is x) just to figure out a new order that works.

This problem doesn't exist if you use a dependency injection container with configuration in code, because the order of component registration is not important.

  • mercurial 13 years ago

    Yeah, what you'd end up recreating is a directed graph of dependencies, and make it needlessly fragile.

    You don't need the big machinery for smaller projects, though. What I end up doing in Python is having builder methods in __init__.py which can instantiate objects from the package (possibly instantiating objects from sub-packages in the process), with any dependency not in the package or sub-packages being a parameter. You get some granularity in your dependency injection, you avoid magic and you don't need to use the builder methods if you don't want to. It may not scale to large class hierarchies, but for mid-size projects it's fine.

jt2190 13 years ago

According to Martin Fowler [1], Inversion of Control is an alternative to using a Service Locator:

  > In the Java community there's been a rush of lightweight
  > containers that help to assemble components from
  > different projects into a cohesive application.
  > Underlying these containers is a common pattern to how
  > they perform the wiring, a concept they refer under the
  > very generic name of "Inversion of Control". In this
  > article I dig into how this pattern works... and
  > contrast it with the Service Locator alternative. The
  > choice between them is less important than the principle
  > of separating configuration from use.
[1] http://martinfowler.com/articles/injection.html

(edit: Also, the Spring Framework has had alternatives to XML configuration for years: http://www.ibm.com/developerworks/webservices/library/ws-spr...)

unwind 13 years ago

I'm pretty sure IoC here refers to "inversion of control" (http://en.wikipedia.org/wiki/Inversion_of_control). I had to look it up though, I find it a bit silly that even the original article doesn't spell this out in the first sentence.

I guess it's super-obvious from context (and the claim of the title) so I guess I'm just not very smart, today. Oops.

gertgoeman 13 years ago

I think the title's a bit misleading though... This guy is obviously talking about dependency injection.

Things like callbacks, observers, events, ... are also types of IoC.

skrebbel 13 years ago

A lot of people in this thread point out that modern IoC containers are good because they can automatically wire up your component tree for you, which is such a hassle to figure out and code manually in a place like main().

This component tree is the core of your application architecture. If the classes are well named, a big part of the application structure should become clear to someone reading your hand-coded main(). Also, if this is such a pain to figure out, why are you using components at all?

I find the idea of splitting functionality into classes but having no clue how these classes relate to one another a tad scary, really. I usually have a picture of the entire component tree on the wall near our team. It's great for pointing at when discussing design, and it's trivial to draw.

Writing a main() really shouldn't be more work than copying that picture into code. A tad tedious, but never more than an hour of work. Why add all that IoC complexity for saving 60 minutes. ? Why replace an excellent starting point for new team members to dive into code by a library that does magic?

Deployment variability doesn't cut it for me. Nearly always, you can foresee which things may need to be variable, and which aren't. Explicitly make those configurable, instead of all classes and their arguments like you'd do in Spring. In your main(), just if or switch over these config settings to instantiate the right class. Again, very readable, and you strongly convey intent to code readers.

jhartmann 13 years ago

Sure you have to use it where it makes sense, but IoC containers and frameworks like Spring can really make things easier. If you have to talk to anything complex (pick your messaging poison), need to keep transactions across these items, need to run under multiple different web containers and swap out configuration you are going to have some messy code to handle all of this sort of stuff. For enterprise integration problems I will pick Spring any day. For instance I can write a complex messaging bridge between two different messaging systems using nothing but some xml configuration. The mess of doing all the JNDI lookups, getting all my XA transactions right, handling firing messages after certain things happen all can be done without explicitly putting things all over the code. The beauty of IoC containers and AOP programming is that you can mix in a well tested piece of code across all your application with minimal effort. You can mixin authentication, transaction management, request cleanup, caching, etc. without making major changes to your app.

I know there are many people here that might crucify me for the opinion but I call bullshit. They just have never had to work on something sufficiently complex where IoC and frameworks like Spring can become a huge time savings. Obviously with any tool you have to make sure you don't chainsaw off your leg, and its really stupid to do certain things with any tool. The black magick of aop and IoC can make reasoning about things a little harder, but the shear power of the tool makes solving hard problems in complex applications tractable. Try auditing transaction management in an application with 10 thousand tables written by hundreds of people of various experience levels. Or just use spring transactions and inject the well tested behavior across the entire application.

bborud 13 years ago

Most places I have seen DI frameworks being used, they solve a problem the programmer shouldn't be having in the first place.

  • filpen 13 years ago

    Interesting. Do you mind expanding on this? What problems were they trying to solve?

    • bborud 13 years ago

      I don't buy that wiring up code explicitly in plain old java without the help of an injection framework is as painful as some people seem to think -- and if it really is: I suspect the reason is bad design or that they just haven't given the problem much thought. That happens.

      If people need the assistance of a framework to wire up their application, it is probably because the API design sucks ass and there are too many moving parts the programmer is forced to pay attention to. (And when I say API design: all code design is about APIs -- every time you create a class or an interface you are creating an API of some sort). Good APIs hide and abstract. And good implementations take care of things you don't need to see or know.

      And I say if, because most of the time, applications are not so complicated that you need help to manage wiring them up. Most of the projects I have worked on the past 15 years can usually be wired up in less than 40-50 lines in a Main.java. I have worked on some projects that needed considerably more, but interestingly, managing that code was never a problem.

      Explicit wiring you can read from start to finish beats vague declarative shit that you may be able to figure out if you pay close attention.

      • filpen 13 years ago

        Thank you for clearing that up, much appreciated.

        I also noticed that most of the time the container tends to be used as a Service Locator indiscriminately around the code base, which tends to create more problems than it solves. On the other hand, I think it is a good refactoring step if your plan is to eventually move all the composition logic at the entry point of the application.

        Coming from .NET, I tend to do the wiring as close as possible to the entry point as well, but I still use a container because it makes object lifecycle management much easier, and with convention over configuration it is trivial to associate interfaces to implementations: this not only reduces wiring up code for complex applications to a few lines, it also makes the rest of the application container-agnostic, which is quite cool.

        • bborud 13 years ago

          > t also makes the rest of the application container- > agnostic, which is quite cool.

          Not least because containers have a tendency to fall out of fashion. For instance if you suggest using Spring for a large project now, people will queue up to punch you like a meat pinata.

_pmf_ 13 years ago

I found that a sweet spot between wiring-by-code and wiring-by-container-and-configuration-dsl is using a dynamic language for wiring (say, Rhino, which is very lightweigth): you have the flexibility of wiring-by-code and can easily change the configuration purely by deployment (without recompiling anything)

  • RyanZAG 13 years ago

    Just curious, but what's wrong with recompiling? If you make a typo in your Rhino file on production, your whole app is now failing. Surely it makes more sense to just take the 5 minutes to recompile (or hopefully 30 minutes and test it out in dev first)?

    I don't really understand what problem using the dynamic language is trying to solve there, and you've just added in a whole new branch of different code that won't work with static analysis, and will need to be maintained in addition to your normal code.

    • _pmf_ 13 years ago

      In my case, I have an Eclipse-based product (toolchain for embedded development) that must be reconfigured per client or even per project (on site); i.e. it is more about dynamically creating very specific variants of a product. Using client/project-specific plugins would be the alternative for me, but this has much more overhead.

      • RyanZAG 13 years ago

        Are you not packaging un-used code into your embedded binaries then? You'd also have to manually test the reconfigured client before deploying it, I think.

        Seems better to make an automated build system off a database of configurations - a simple sql table with the different settings that could automatically build versions for all clients. You'd get static compile time checking of each build, and it would allow for easily running automated tests against each client's version.

        So you'd end up with no un-used code, a database of client configuations, and static compile time checking. Seems win-win.

        Sorry for 'assuming your problems', feel free to ignore. Interesting situation though.

galaktor 13 years ago

Younger IoC frameworks aim for configuration in code, allowing for a much more dynamic usage.

Examples (c#) * Autofac * Ninject

  • jakubholynet 13 years ago

    We use Guice which also allows that. But that doesn't address some of the key points he makes, such as - runtime x compile time wiring - wiring is based on types so injecting differently set up instances is difficult (we have a hell of Providers and different annotations to pick the right kind of instance injected) - non-transparency of the wiring process (sice it is performed by the magical IoC container)

    I agree with a lot of what he writes. At the same time I believe there are cases where I would appreciate some kind of automation for wiring (f.ex. if I want a fresh instance for each session or request). And there are certainly cases when runtime wiring - as in the mentioned case of plugins - is useful.

    • galaktor 13 years ago

      I'm mostly familiar with Autofac, and there are many other ways to wire your app other than by type

      * by interface * by enum * by parametrized constructor (Func<..>) * by (arbitrary) string * per process / per thread / per whatnot

    • steverb 13 years ago

      Ninject actually does allow you to wire up with criteria beyond type based on the context into which the object is being injected.

InvisibleCities 13 years ago

First of all, the author doesn't hate IoC and Containers, he hates XML registration (with good reason). I can't say anything about Java, but in C#, when you use modern IoC frameworks like StructureMap and AutoFac, all registration of components takes place in code, using generics and lambdas. This allows you to easily wrap your services in interfaces, de-coupling code and making things much more testable, especially if you use a good mocking framework like Rhino. When you combine DI/IoC with ideas like the Onion Archtecture (http://jeffreypalermo.com/blog/the-onion-architecture-part-1...), writing readable, testable, flexible, maintainable applications becomes supremely easy.

FreshCode 13 years ago

Do I understand correctly that the writer's main concern is that DI configuration is done in XML files, or that configuration takes place at run-time, instead of compile-time?

  • filpen 13 years ago

    I also don't get what the author's issues are. Half of the article seems to be against XML configuration, and I don't come from a Java background but it seems that there are containers for Java that do not necessarily require an XML configuration, or is it not the case?

    • twistedpair 13 years ago

      Hmm... guess the author is not familiar with @Autowired, @Resource, @Component... etc. You don't need XML fun. And, he complains about 2 of the same type... behold @Autowired(name="bar"), @Autowired(name="bah"). Miracle? No, just DI.

tkellogg 13 years ago

Maybe you should be using C#. As a community we fight hard to reject xml configuration, favoring type safe lambda expressions instead. Anything that ignores the type safe guarantees that C# offers quickly does. There was briefly a spring.net but it quickly died for this reason.

  • SideburnsOfDoom 13 years ago

    Agreed. Is the author's problem with IoC or with XML config? hard to tell, but they're really not the same thing.

    IoC containers in C# have rejected config in XML, in favour of config in code, using either generics and lambdas (e.g. register Component.For<IFoo>.ImplementedBy<Bar> ) or via scanning (e.g. AllTypes.FromAssembly(x).BasedOn<Foo>().WithService.FirstInterface() ).

    Spring.net was an exception and in comparison it really sucked.

    IoC Config in code is much better. But can't this be done in java too?

    • mercurial 13 years ago

      That's what Guice does, and newer versions of Spring too (though I'm not sure if you can go full Java and drop the XML entirely).

michaelochurch 13 years ago

Java culture (IDE-dependence, AbstractFactoryVisitorFactory patterns, Maven and XML monstrosities) is hideous. It's based on the idea that reading code is a lost cause. You can no longer trust code, so you need all these wonky tool configurations to compensate for the fact that you're trying to make an army of inept programmers build something that is (unless it fails) going to become the next generation's legacy bloatbomb.

  • eranation 13 years ago

    I think the issue is that there is no such thing as Java culture, there is Enterprise culture which is responsible for all that you said above. But there is a start of a new "Java culture" which is encouraging, see what Google did with Guava, see the Java version of Play framework, even Spring framework 3+ is not that bad, no XML, all annotations, JPA is nice as well. Look at stuff done by Yammer, Twitter, Google and other Java/Scala based companies.

    I wouldn't go and dismiss one of the most popular Enterprise frameworks, as a user of Spring / Hibernate for last 7+ years, it makes a lot of sense to me in the enterprise context, just like Ruby on Rails and Play Framework makes sense to me in the SaaS contect, for instance, having Play framework with a Spring module is a nice interim solution for bringing newer technology to the enterprise world.

    It all depends on what you need to be doing. Spring is great for a large enterprise app, that have long lifetime, needs to connect to legacy stuff, needs common enterprise integration patterns etc.

    Also if you check SpringSource latest stuff, you'll find out they are investing in lot's of cool new things, e.g. the scripted text editor - (https://github.com/scripted-editor/scripted/) and are influenced a lot by the Rails, Django, Node.js and Play communities.

    The enterprise world is not that stupid, it's perhaps just a bit behind but it's still making tons of money from it's software, in billions, and it's more likely to be written in Spring / Hibernate than with Rails / ActiveRecord.

    Just give it some time and patience.

  • twistedpair 13 years ago

    Always love all the Java hate on ycomb. I'm not sure how a dynamically code hotswapping Ruby app with 10k classes and 1k domain objects works, but I suspect many of the same patterns emerge as have been solved in Java.

    • michaelochurch 13 years ago

      Large single programs should almost never exist. There are exceptions, but the typical bloated business app is not one of them.

      Managerial idiots like overambitious single-program IT projects because it makes it easier to allocate "headcount" when the programmer-to-program relationship is inverted (many programmers to one program, instead of the right way, which is one programmer working on many programs).

      The truth is that every programming approach fails you when you do this. For one example, static typing fails on versioning issues and compile-speed problems, while dynamic typing ends up with silent failures and integration bugs.

      There is one case I can think of where large single programs work, and that's in the database space. You have a lot of requirements (transactional integrity, concurrency, performance in a heterogeneous world) and they all have to work together. It has also taken decades for some of the brightest technical minds out there to get it right.

      • hythloday 13 years ago

        Large networks of small programs fail in exactly the same way: static typing fails on versioning issues (an RPC call carries inherently less type information than a function call) and compile-speed problems (compiling 200 small services can take just as long as compiling one behemoth). We also don't have mature tooling for the "network program" you're talking about.

        I don't know what your metric of "large program" is, but AAA games often weigh in at 10-100 million lines and are typically architected as a single large codebase with auxiliary small programs, and doing them any other way is not a sensible approach.

      • twistedpair 13 years ago

        WADR, most enterprise billing, invoicing and accounting systems are also such cases where it is not desirable or practical to sprinkle the business logic across dozens of silos.

    • netghost 13 years ago

      In languages like ruby, python, and probably to some degree go, you tend not to need as many classes. Things like Factories, Adaptors, and Proxies tend to disappear or become pretty trivial.

      Eventually programs written in these languages can grow huge, but it takes longer, and the preference tends to then be to break a program down into smaller libraries (gems, eggs, etc.) and separate applications that communicate with each other.

  • wheaties 13 years ago

    Not all of Java culture is like this. There's a ton of really great code out there. Take a look at any Android library. There's no damned Spring anywhere.

    Or switch to Scala like me.

    • michaelochurch 13 years ago

      I agree with you. I don't think there's one Java culture anymore. So what I mean by "Java culture" is POJOs, Factories, Maven, and IDE-dependence. Commodity-developer, large-single-program nonsense that corporations invented to compensate for mediocre engineers. Android is bringing a lot of good engineers into Java, and Scala and Clojure are also bringing a lot of good people into that ecosystem.

      I think the issue with the enterprise, large-single-program Java world is that there isn't a feedback cycle. Curious, motivated engineers hate that kind of environment because they want to see things actually work. Clojure and Scala have the REPL, but large-program Java development doesn't.

  • fusiongyro 13 years ago

    > It's based on the idea that reading code is a lost cause.

    I would argue that it is based on the idea that there's going to be too much code to read it all, and that knowing you need to use something shouldn't automatically entail knowing how to create something.

  • factorialboy 13 years ago

    In our defense, have you tried reading Java code?

    • michaelochurch 13 years ago

      Wait, people actually read Java code? I thought that's what IDEs were for.

      For a serious response, I've seen tons of Java code of varying quality. Most was worse than horrible, but I have seen well-written Java. The Java code for Clojure is excellent, for one example. Most corporate Java code is indistinguishable from profanity.

    • twistedpair 13 years ago

      I grant you that. I try to abide by everything in "Effective Java 2" but some of the code I come across in my daily work makes me ill. I wish I could say such code was uncommon, but someone will always try to use a hammer as a screwdriver if it still compiles.

martinced 13 years ago

IoC is an usual technique and buzzword from the C#/Java + XML + ORM + SQL hell.

There are many programmers working in the Real-World [TM], powering great apps and webapps, using saner technologies who have never heard of the term.

I wrote my own IoC container (a clone of picocontainer IIRC) to see what the fuss was about when the term started to become fashionable. No big deal. It can help reproduce various states (for examples in testing environments) to more easily test your app.

Sure people will say: "You need an IoC container to do DI, what you're talking about is DI, not IoC".

But, fundamentally, it is once again related to "state" and the difficulty to recreate a state in {dev,pre-prod,prod,whatever}.

So it's once again a "solution" missing the bigger picture.

Sure, people stuck in the "stateful OO" mindset will love IoC and, honestly, if you're stuck in such an hell IoC can be useful. With the caveat that IoC makes it much harder to reason about what's going on when some shit hits the fan.

"Every problem can be solved with another layer of abstraction, except the problem of too many layers of abstraction"

But there's light at the end of the tunnel. There are other ways to design great apps.

And to make you feel even better: being "smart" as nothing to do with knowing every technology out there ; )

Keyboard Shortcuts

j
Next item
k
Previous item
o / Enter
Open selected item
?
Show this help
Esc
Close modal / clear selection