At the Spring Experience, in several different sessions, there is quite a bit of coverage of different uses of annotations. I may have to update
my list.
One of the really interesting uses (maybe I'm just ignorant here) is to identify classes and methods to apply point cuts with AOP. This seems like the perfect use of meta-data. This one isn't necessarily a Spring thing, just cool.
The use of annotations in the MVC project have some good and bad. One good thing is the use of an annotation to identify a controller, rather than having the controller extend the
AbstractController. This means the class doesn't need to depend upon Spring classes. This should help preserve backward dependability (to your app) as the framework evolves.
Another cool thing is the ability to decide which method gets called by the value of a request parameter, via annotation. This changes to a more declarative model of programming that should make code easier to develop and much easier to test (less logic, less to test).
@RequestMapping(params = "action=delete")
public void removeSite(@RequestParam("site") String site,
&nbp;&nbp;&nbp;ActionResponse response) {
.
Then there is a scary part, using annotations to map URL patterns to controllers. This means the URL patterns will get scattered around the code base (hopefully in only one or two packages). The XML configuration isn't perfect but, personally, I'd like to see URL mappings in one place.
@RequestMapping("/myAction.do")
public void handleAction....
An interesting thing of the how annotations are used in Spring is in many places they help remove dependence on Spring classes and interfaces. "Use Spring but, don't
depend on it".
@PostContruct and
@PreDestroy (function are obvious from the name) are pretty cool.
@Resource both powerful AND dangerous (this one is for annotation driven dependency injection). Using this could make unit test more challenging.
@Autowired is a good way to reduce XML if auot wired beans don't scare you.
A little validation for my attitude with annotations. During Rod Johnson's presentation on The State of the Art Dependency Injection, he said that he like annotations but, not annotations that take strings (even the stuff in Spring). At least if I'm crazy, I'm not alone
:-) Update: reference to this post on DZone.
.
.
Labels: annotations, java, patterns, practices, spring, Spring Experience
I'm a little late jumping on to the Java5/6 bandwagon. I'm one of those big strong typing / type safety advocates. It comes from spending a lot of time on big projects where tracking down trivial errors is a process unto itself.
Naturally, I find the new generics to be a blessing. When you are in favor of type safety, casts always make you cringe.
I must admit that I basically ignored the annotation system for a while. When I did start using it, I saw things like
@Override
, "hey this is good to protect code while refactoring." I saw the Spring framework's @Required (ensure classes are properly configured). These seem like good things, communicate with the compiler, communicate with the frameworks. This establishes a rule in the first case and a requirement in the second.
Then things start to go grey. The
@SuppressWarnings
mostly finds itself being used when using code that does not support generics (J2EE :
request.getAttribute()). Ok it's a necessary evil, I admit.
Then EJB3 starts down a darker path.
@TransactionAttribute(TransactionAttributeType.REQUIRED)do we really want to define this in the class?
What about JNDI lookups
@Inject(jndi-name="java:comp/env/jdbc/test") ?
Finally, it gets down right ugly
@Resource(name="myDB", type="javax.sql.DataSource.class")
@Table(name="CUST", schema="RECORDS")
Finally, we start to see annotations with SQL in them
@SQL(statement="SELECT * FROM USERS WHERE {sql: where}")
Finally, there's the ultimate abuse (from
Google Guice):
@ImplementedBy(ServiceImpl.class)
public interface Service {
This one is so bad it doesn't need explaining.
Like many things, I think annotations can be very useful when used correctly. What bothers me most is when Sun is the one promoting obviously bad practices. Really, what's the difference in using annotations with SQL in them or just writing plain old JDBC? not much. If the configuration is in the code being configured, then what's the point of an annotation?
To be fair, I could agree with doing this if it was contained to configuration classes. By this, I mean a handful of classes that sit in a package all to themselves and serve to replace XML configuration. Configuration classes benefit by providing compile time type safety, and can exploit tools for auto-completion. But, sprinkling these kinds of annotations around the code base is going to make for maintenance nightmares.
The way I see it:
annotations to make code easier to configure :
Goodannotations to enforce local policies :
Goodannotations to define requirements (contract) :
Goodannotations
to configure :
BadUpdate: I've just received an email about
Loom and how it uses annotations for validation on beans (value objects to the rest of us). The idea being that the logic can exist in one place instead of at every tier (web, middle, data access). It can read the annotations to generate javascript for page level validation, and use the same annotations to validate the beans in the other tiers.
I haven't looked at Loom myself so, I'll reserve judgement but, on the surface this appears to be an interesting (read innovative) way to use annotations.
Update: while talking to a colleague, he mentions that much of the 'bad' use of annotations looks like C macros in sheep's clothing.
Update: reference to this post on DZone.
.
Labels: annotations, development, practices
There is a lot of talk about
how singles are harmful. Many of them make very good points. However, I think one thing that is generally missing from the discussion is a small pattern that is almost universally used when implementing singletons.
I mean of course, the
factory pattern.
Very few people provide public access to singleton variables, they are usually provided via an
instance() method. The class is its own factory object.
Why is this good?
It means you don't have to use singletons, though they could be an option. Say a class needs to operate on a non-thread safe class (an xml
transformer for example), or it uses a library of uncertain thread safety. Instead of having a static reference to the instance that is returned by the factory method, it could use a
ThreadLocal to ensure that each thread has its own instance. This gives the ability top address issues with threads while gaining the benefits of a singleton.
Another use of the factory pattern can be object pooling. If the object is pretty heavy weight, or requires a lot of set-up, you obviously don't want to have too many instances floating around or don't want to create them too frequently. You could write your own pooling implementation or use the
Jakarta Commons Pool.
If a singleton is the right thing to do, then it should obviously be used. Consumers of the class should not have to worry about whether or not it is a singleton. Of course, this also means you shouldn't be storing state information in the class (but, you knew that).
What does this mean for testing? A private constructor is still going to prevent over-riding the class to create "truly" new instances. This means another option will have to be taken.
Perhaps the easiest is to over-load the factory method with one that always returns a new object. If the scope of this method is limited to package level, then little more than the test case should have access. The problem here is, an overly cautious developer may discover the method and use it instead of the factory class.
I would propose testing the class the same as it will be used. If there is a concern about internal state, write tests to cover it. Besides, maintaining internal state in class provided by factory methods is generally a bad practice. Try writing tests to ensure this isn't happening.
Another option could be to refactor so that a separate factory object is used, and it could be over-ridden to provide a class for testing...
Though there are problems with singletons, don't throw out the baby with the bath water. The nature of a good singleton makes it easy to do things beside a single instance in a very transparent way.
Labels: development, p, patterns, practices, standards, testing
We all know that the way to become a better developer is to both study and practice our craft.
The reading happens from
books, blogs, news sites, and tutorials.
The practice? Sure, there is the day to day coding. Sometimes, we really need something with a scope beyond the day to day. You already know that really well anyway.
I have always steered junior programmers to
TopCoder. The idea is that the speed of competition can stimulate faster learning. Even if they don't compete, the practice areas are just plain good practice.
Project Euler also offers up a big set of small programming challenges. Just the thing to play with on the lunch break.
Another good site is
Dave Thomas' CodeKata blog. I really like the idea presented by Dave. Take a problem per week. Create a different solution (read implementation) each day of the week. Let's face it, we all know that most problems can have many different solutions. Why not explore the possibilities?
Here at the office, I've started a (completely voluntary) group version of the code katas. On Monday, I send out the problem (to a mailing list). Everybody works, mostly independently, on a solution per day. On Friday, we all get together over lunch and review each other's solutions over chips and salsa.
I have observed many benefits to this technique. Everybody learns by seeing other people's solutions. Many of the junior developers go around asking questions as they work on their solutions. Since it is
only an exercise, most everyone has lost the fear of the code review. Everyone is claiming to have fun. Communication between development teams is up. Code quality all around is improving. Participation is increasing
(though that may be due to the salsa).
Since we are a java shop, I send the problems out with a set of
jUnit tests. One test per day. I am also encouraging TDD by getting everyone to write test cases instead of using
System.out.printlnThe change is slow at first. The question is "
why not just print it out?"
My answer, "
What do you do after you get everything working?"
everybody's answer, "
delete the print lines", and they start to realize that my question was a set-up.
This brings in the key point (
the Socratic Method rocks). Those prints contained information, knowledge about how a piece of code is supposed to behave. When it is deleted, the knowledge is lost. There are also the all the standard arguments, like confidence in refactoring. For many, it takes some effort to change to a different method of thinking but, it appears to be gradually happening.
As the use of these exercises continues, I hope to introduce other systems for testing and development like,
EasyMock,
Fit, and jBehave.
So far, it looks like daily programming exercises are a good technique for code improvement and enhancing team cohesion. I'll post updates to report progress.
Update:I've just been informed of another programming contest site, like
TopCoder, called
Sphere Online Judge. Thanks
llimllib.
Update:
I've just read a post, Kata and Practice that shows one person's experience. An interesting read and it mentions another resource, The Coding Dojo.
Labels: community, continuing education, development, practices
Maybe this has been covered to death but, it still seems to be brought up.
- Constantly Study
- Study best practices, design patterns, refactoring techniques. Study the libraries and API's used in your development environment. Every other day I see re-implementations of methods provided in the java.util.Collections and java.util.Array classes. When you know whats available, you spend less time reinventing off the shelf code. Study anti-patterns, this helps avoid the most common mistakes.
- Master Your IDE
- Learn every keyboard shortcut in your development environment. One day, remove your mouse and hide it in your desk. Learn to use your environment without a mouse. Spend about 10 minutes every day learning to do something new with your development environment. When you know it inside and out, you can work more efficiently.
- Use your IDE for everything. Need to write a word doc, write the text first with a text file in your IDE, copy paste; email too.
- Some people even post lists of shortcuts. Most IDE's have them in the help pages. If not there, a quick google can reveal much.
- Extend and Customize Your IDE
- About every development environment in existence allows you to write extensions and plugins. You are constantly saying, I wish my IDE could do ... anyway. Write an extension to it. If you find yourself writing boring code, write a plugin to do it for you. "If it's worth doing once, write a program to do it."
- This is once of the least followed recommendations. C',mon, this is your tool, customize it to allow you to work better and faster.
- Master Your Environment
- Much like your IDE, spend some time learning your other tools, your operating system, anything that eats up your time during the day. If you use ANT for builds, try to learn something new about it. Do you know the keyboard shortcut to minimize a window on your operating system? Change active windows? Do you use them? Can you use your email program without a mouse?
- Learn New Programming Languages
- In the "Pragmatic Programmer", Dave Thomas recommends learning a new programming language every year. Each language is invented with a different goal in mind. Each provides a different way of approaching and thinking about a problem. Next time you are faced with a difficult programming problem, ask yourself how you would solve it using something other than your primary language. Change the way you think.
- Learn New Human Languages
- This is an extension of the point above. Different cultures have different ways of looking at the world. Learning a language can give a small insight into the culture. Learning about the culture can help you with the language. Gaining new ways of looking at the world can give you new insights into approaching problems and developing solutions.
- Being a good developer essentially means being good at solving problems. There are many useful problem solving techniques outside of the realm of programming.
- Re-Study Your Basic CompSci
- You don't need to do this constantly but, review this stuff every once and a while. Sure you know how to write a linked list, b-tree, finite state machine, etc. When was the last time you did? When was the last time you converted an array to a b-tree and back again? You might be surprised how quickly you can become rusty.
- Refactor Some Old Code
- Maybe your management won't let you refactor old code or check in the refactoring. Don't worry about it. Make a copy and refactor some code from an old project. By spending time thinking about how to make the code better, you will be more likely to do it right the next time you write new code. This makes a great programming exercise, its even better if you have some unit tests to verify changes as well.
- Learn about refactoring. I highly recommend Martin Fowler's book on the subject, "Refactoring".
- Write About Your Code
- I'm not just talking about documentation. Think about if you were trying to explain the code to a novice programmer. Even though what you write may be considered 'lame' by some, don't worry about it. The process of trying to explain what you've done will help you to understand it better. This is really a progression of the ask the duck technique.
- If you work in an environment where you can't publish such information publicly, then write it anyway, call it documentation, and pass it around to your fellow programmers.
- One key thing is to develop a thick skin about feedback. You may receive scathing remarks. Don't weat it, and don't respond. Don't let your emotions get ahold of you. Just try to remove the meat of the remark and try to use it constructively.
Fat Angus also has suggestions on
becomming a better developerbacklinks:A humorous take on the subjectLearning Never StopsAttestation tasks proposalBecoming a Better DeveloperLabels: continuing education, development, practices