I am Siva, a passionate java developer, open source enthusiast, blogger. I like to cover Java, Struts, Spring, Hibernate, Ajax Tutorials, How-To's and Best Practices. Sivaprasadreddy is a DZone MVB and is not an employee of DZone and has posted 34 posts at DZone. You can read more from them at their website. View Full User Profile

Applying IOC/DI to Method Design

01.20.2011
| 6267 views |
  • submit to reddit

Eventhough IOC is a generic design pattern, with the Spring framework the IOC/DI pattern became more popular. We can find lot of definitions for IOC/DI over internet, but the underlying concept is the same.


"Instead of a component being responsible for getting the required dependencies to perform a task, a container/factory should build and inject the dependencies into the component. Then the component can perform the sole activity for which it is responsible. The component need not care about from where it got its dependencies. Then the components code will be much more cleaner and testable"
.

Normally we use this principle to build and wire the services. We can also follow the same principle for method design which makes the methods testable.

Lets take a simple example of a DownloadServlet.
Suppose there is a DownloadServlet which gets the message as a request parameter and writes it to a file and presents it to the user as an attachment.

public class FileDownloadServlet extends HttpServlet
{
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
String message = request.getParameter("message");
String filename = "message.txt";
FileWriter fw = new FileWriter();

fw.write(response, message, filename );
}
}
public class FileWriter
{
public static void write(HttpServletResponse response, String message, String filename) throws IOException
{
response.setContentType("text/plain");
response.setHeader( "Content-Disposition", "attachment; filename=\"" + filename + "\"" );
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write(message.getBytes());
}
}

The above code works but it has some issues.
a) The FileWriter is tied to ServletAPI and hence can't be unit testable.
b) FileWriter.write() method is doing additional tasks apart from writing the content to the output stream.
   If you look at FileWriter.write() method, it is supposed to write the text to the given output stream only.
   But here it is preparing the output stream, which is a dependency to the method, to perform its task.
   It the sames as creating a DAO instance in a Service class. But IOC says DAO instance should be injected into Service by some container/factory.
   
Now let me refactor the FileDownloadServlet and FileWriter following IOC at method level.

public class FileDownloadServlet extends HttpServlet
{
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
String message = request.getParameter("message");
String filename = "message.txt";
FileWriter fw = new FileWriter();

response.setContentType("text/plain");
response.setHeader( "Content-Disposition", "attachment; filename=\"" + filename + "\"" );
OutputStream os = response.getOutputStream();
fw.write(os, message, filename );
}

}
public class FileWriter
{
public static void write(OutputStream outputStream, String message) throws IOException
{
outputStream.write(message.getBytes());
}
}

Here the OutputStream is injected to the FileWriter.write() method by its caller(FileDownloadServlet). Now FileWriter.write() method need not bother about what type of file it is, or what type of OutputStream it has to create. It will do its task only : writing content to output stream.

Now the FileWriter.write() method can be unit testable also.

public class FileWriterTest
{
public static void main(String[] args) throws Exception
{
OutputStream outputStream = new FileOutputStream(new File("c:/message.txt"));
String message = "Hello World!!!!!!!!!!";
FileWriter.write(outputStream, message);
}
}

So in addition to wiring the services of a system, we can apply the IOC/DI principle to design a more unit testable API also.

Reference: http://sivalabs.blogspot.com/2011/01/applying-iocdi-to-method-design.html

1.333335
Your rating: None Average: 1.3 (3 votes)
Published at DZone with permission of Sivaprasadreddy Katamreddy, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Suhasini Ch replied on Mon, 2011/01/31 - 1:22am

very nice and elegane example ,it will be very useful if you can provide a example

to solve cyclic dependency using IOC .

Thank you.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.