The secret of how to be miserable is to constantly expect things are going to happen the way that they are "supposed" to happen.
You can have faith, which carries the understanding that you may be disappointed. Then there's being a willfully-blind idiot, which virtually guarantees it.
Tim Bee wrote:Look at this example and tell me it is not overly complex.
http://www.journaldev.com/2410/spring-dependency-injection-example-with-annotations-and-xml-configuration
Tim Bee wrote:Thanks for the answer..
How do you do test driven development in an agile environment?
Tim Bee wrote:Also, would you used Dependency Injection if there was no immediate need for it?
Junilu Lacar wrote:
There are entire books about doing TDD, the best one, IMO, is actually about the "4 Rules of Simple Design" by Corey Haines. Other references I use are Martin Fowler's "Refactoring" book, Josh Kerievsky's "Refactoring to Patterns", Steve Freeman and Nat Pryce's "Growing Object-Oriented Software Guided by Tests" (the GOOS book), Michael Feathers' "Working Effectively with Legacy Code" (the WELC book), Robert C. Martin's "Clean Code" and "Agile Software Development: Principles, Patterns, and Practices" (the PPP book), and Eric Evans' "Domain Driven Development" (the DDD book). The last one by Eric Evans is really about design thinking, which permeates everything you do in TDD.
HTH
Tim Bee wrote:
My point is, you are supposed to come up with all of the tests before you start coding. But in an agile environment, things are continually changing. So tests that are written at the beginning may not be valid by the end of the project and some new functionality may require different tests.
I realize that you can add new tests as you go along but I think the concept of writing all of the tests before you start development when you know everything may change seems intellectually dishonest.
Tim Bee wrote:I think the concept of writing all of the tests before you start development when you know everything may change seems intellectually dishonest.
Junilu Lacar wrote:Regarding asking yourself "What bug do I want to deal with next?" then writing a test that fails to show that you indeed have a bug ... this is not even a new idea.
The eminent computer scientist and winner of the 1972 ACM Turing Award, Edsger W. Dijkstra, wrote: Program testing can be used to show the presence of bugs, but never to show their absence!
So this idea has been around for a while and it's the exact mindset you need to adopt so TDD really works. Again, this mindset turns the "normal" way of thinking about testing on its head. This another strategy for handling complexity and working in simplicity. TDD helps you focus on the important things you want your software to do and tends to keep you from unnecessary "gold plating". I have found it an excellent way to handle complexity.
Tim Bee wrote:What this does seem to indicate is that there is some conflict between programming only what needs to be programmed and building flexibility for the future. I'm sure you are going to tell me that is done in the refactoring stage.
Sandi Metz on Twitter wrote:Don't write code that guesses the future, arrange code so you can adapt to the future when it arrives
Tim Bee wrote:I never saw anything about just writing the tests for a small part of the project, like a class or new feature. I thought they were supposed to be written for the entire project, which seems cumbersome.
Tim Bee wrote:Then the ClientApplication uses the getBean method of the ApplicationContext to instantiate the MyApplication object app.
Junilu Lacar wrote:
Tim Bee wrote:Then the ClientApplication uses the getBean method of the ApplicationContext to instantiate the MyApplication object app.
Close. You shouldn't assume that instantiation is happening with the call to getBean() -- the instance could already be there and you're just getting back a reference to it. All the call is really saying is, "Hey, ApplicationContext, give me a reference to a bean of class MyApplication" - the client doesn't care how that reference is materialized, whether through instantiation or through a lookup in a table of existing instances or through some other kind of magic.
Junilu Lacar wrote:As with many things in software, there's a balance to be struck. Flexibility does in fact comes with a cost.
Dave Tolls wrote:It's injected by Spring based on the DIConfiguration class (in this case).
So it would be an EmailService, if I've scanned that code correctly.
Tim Bee wrote:
Dave Tolls wrote:It's injected by Spring based on the DIConfiguration class (in this case).
So it would be an EmailService, if I've scanned that code correctly.
But when it is injected, doesn't just the constructor class get executed? I'm not sure why some setter class has been run.
Junilu Lacar wrote:
Tim Bee wrote:
Dave Tolls wrote:It's injected by Spring based on the DIConfiguration class (in this case).
So it would be an EmailService, if I've scanned that code correctly.
But when it is injected, doesn't just the constructor class get executed? I'm not sure why some setter class has been run.
First, let's be clear with our terms. Classes don't get executed. Classes get instantiated. An instantiation of a class results in an instance / an object.
Methods and constructors get called or invoked, which then causes the statements inside them to be executed.
The constructors in the example have been commented out. That means that the example uses setter injection. When Spring injects a MessageService object into MyApplication, it does so by calling the @Autowired public void setService(MessageService svc) method. Only the statements in that method are executed. Nothing more.
I think Dave is right: in the example, the instance of MessageService that gets auto-injected into an instance of MyApplication is the EmailService, which is provided by an instance of the DIConfiguration class.
In ClientApplication, the main method first loads up the annotation-based ApplicationContext, which then causes Spring to go and do its automagic component scan and dependency injections. The call to getBean() on line 12 gives back a fully ready to rock and roll instance of MyApplication.
Junilu Lacar wrote:
Tim Bee wrote:
Dave Tolls wrote:It's injected by Spring based on the DIConfiguration class (in this case).
So it would be an EmailService, if I've scanned that code correctly.
But when it is injected, doesn't just the constructor class get executed? I'm not sure why some setter class has been run.
First, let's be clear with our terms. Classes don't get executed. Classes get instantiated. An instantiation of a class results in an instance / an object.
Methods and constructors get called or invoked, which then causes the statements inside them to be executed.
The constructors in the example have been commented out. That means that the example uses setter injection. When Spring injects a MessageService object into MyApplication, it does so by calling the @Autowired public void setService(MessageService svc) method. Only the statements in that method are executed. Nothing more.
I think Dave is right: in the example, the instance of MessageService that gets auto-injected into an instance of MyApplication is the EmailService, which is provided by an instance of the DIConfiguration class.
In ClientApplication, the main method first loads up the annotation-based ApplicationContext, which then causes Spring to go and do its automagic component scan and dependency injections. The call to getBean() on line 12 gives back a fully ready to rock and roll instance of MyApplication.
Tim Bee wrote:
When I comment out the @Autowired annotation, it does not get called and I get an error when processMessage is called. I assume it (@Autowired) not only determines which version of MessageService to use but also executes it.
Consider Paul's rocket mass heater. |