aspose file tools*
The moose likes Design and the fly likes Learning To Design Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Soft Skills this week in the Jobs Discussion forum!
JavaRanch » Java Forums » Engineering » Design
Bookmark "Learning To Design " Watch "Learning To Design " New topic
Author

Learning To Design

Alvin Parker
Ranch Hand

Joined: Oct 01, 2013
Posts: 39
I am doing my best to write better software. Having been a long-time Java programmer and then learning ActionScript, I've come to appreciate some of the workings of ActionScript. I'm a self-taught programmer (about 13 years ago I learned not counting BASIC in high school). AS quickly taught me what async means and was a shock having worked in Java.

Now I've been into AS for a number of years and there are some lessons I have learned from it that I have applied to my latest server-side workings. I want to be able to identify and learn design patterns better. I want to know when I should use them and when I should not (or when better alternatives are available). If any are inclined to help me, I'd like to post what I did for this latest project and to get feedback on if I could do it better and what is right and wrong about my design. Here are the bullets.

1. The program has an entry point which starts a Thread pool and a ServerSocket.
2. Client connects to ServerSocket - ServerSocket gets a Thread and starts "MainService"
3. One MainService exists for each Client that connects. MainService is an IService:



4. A single handler is created by MainService. That handler is MainServiceHandler and it's an IServiceHandler



5. MainServiceHandler is sort of a "super handler" in that it has a reference to every kind of handler (in a Map) that is needed for my implementation. In each IServiceHandler's handleMessage() I implement any custom flow needed and then invoke the service.
6. When the service is done running, the MainService is notified. It in turn simply hands the message off to MainServiceHandler which causes some other handler to fire which causes some other IService to run and so forth until the workflow has been completed.

By designing in this way, I feel I've created a fully async flow. In each of my IService.startService() methods, I get a Thread from the Thread pool and then have it execute the IService runnable in question. Nothing moves forward until that Thread is done.

There are awkward parts to my design, I'm sure. I could have made another layer of abstraction and added IServiceHandlers to that object, for instance. But, in general, is my design sensible? I did it this way for a few reasons :

1. I can report where I am in process with this flow so I can feedback to the client as to percent done.
2. I have created a flow graph so to speak. If I have to modify anything, it will be contained to three objects - the MainServiceHandler, the IServiceHandler and IService in question. MainServiceHandler pretty well describes the entire implementation.
3. It should be obvious and simple to future developers how to extend the system with more services - even though it's probably a more verbose process than it has to be.
4. I can be sure that some long running processes complete before the system moves on.
5. I should never have deadlock issues as there's only one Thread in service (per client) per IService and they run iteratively.

Besides helping me understand if there's a better way to accomplish software construction, I have a question about frameworks as well.

For the first time, I integrated Guice into this process. I was excited to use it and I see some benefits to it. However, it seems Guice primarily gives you a centralized Object map and makes code really verbose and take longer to develop. Given that all of my objects, other than the IServiceHandler implementations don't take dependencies in their constructors, does it make any sense for a framework like Guice to be introduced to the process I describe above? What do I gain by this?



Versus this :



Thanks for entertaining my questions.
Jeanne Boyarsky
author & internet detective
Marshal

Joined: May 26, 2003
Posts: 31054
    
162

You gain the ability to make the code easier to test. With dependency injection, the code just knows about the interface IAMFMessageReaderService. Which means your test class is free to pass in a mock object rather than the one your code happens to be using.

I bolded the keywords that you can google for more information on those subjects. Sometimes part of learning is just finding out the right questions to ask or terms to look up!


[Blog] [JavaRanch FAQ] [How To Ask Questions The Smart Way] [Book Promos]
Blogging on Certs: SCEA Part 1, Part 2 & 3, Core Spring 3, OCAJP, OCPJP beta, TOGAF part 1 and part 2
Alvin Parker
Ranch Hand

Joined: Oct 01, 2013
Posts: 39
Thanks Jeanne. I can see how DI can make testing and extending easier. I appreciate your feedback.
Kim Chen
Greenhorn

Joined: Jan 06, 2014
Posts: 1

This is not work for me, please check and update.

Thanks
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 5270
    
  10

The first design choice that jumps out at me that I would question is having IService extend Runnable. This is related to design principles that deal with the separation of concerns: Interface Segregation Principle and Single Responsibility Principle. Requiring implementations of the IService interface to also be Runnable seems like you're inappropriately coupling/mixing two different concerns. After all, a class can implement more than one interface in Java so why force a Service implementation to be Runnable as well?

Also, I'm not a big fan of the "I" prefix for interfaces convention, but that's a personal preference. I prefer to use packages and concrete prefixes, e.g. JdbcFooDao, Hib3FooDao, XmlFooDao (possible implementation classes of the FooDao interface). In the same way that the Java Collections has ArrayList and HashMap as implementations of the List and Map interfaces, respectively.


Junilu - [How to Ask Questions] [How to Answer Questions]
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 5270
    
  10

Another smell is that all the method names have "Service" in them -- kind of redundant since the interface itself is already called "IService" (again, I'd prefer just "Service" for the interface). Code that results from such a definition tends to be repetitious and wordy:
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 5270
    
  10

Another smell: stopService() is declared to throw Exception -- this seems too general for this particular method and suggests that you don't know what the exact behavior is you want. Maybe leave Exception out of the throws clause until you have more specific checked exceptions that you can specify for this particular method.
 
 
subject: Learning To Design