Today I was doing some refactoring in RAD (Rational Application Developer) and found my self looking over in the package explorer thinking gee I’ll have to move that method over to the class I just created to get rid of the two classes I’m factoring out. I looked over and thought I should be able to just drag it down into the other class. BAM like a champ when I grabbed that green orb it moved right over when I plopped it down on the new class, updated all the reference just like I would have done it via ALT+SHIFT+V and navigate around to the class I wanted it to go.
Normally I’m a keyboard Jedi but I guess I’ll be making an exception.
Labels: development, IDE, NTFT, RAD, TOOLS
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
I'm about mid-stream on a project built using Maven2 and using the Spring Framework to glue it together.
The cool kids at
Spring Source, recently announce the release of Spring 2.5. It seems best to try to upgrade now while the project is still in development than later (and deal with extra QA requirements).
At first my thinking is this should be easy, go to the
maven repository and see what the latest versions are, edit my pom, and rebuilt the project and see what happens.
For the most part, it is that easy.
But, then there are the 'other' little things.
An issue, unrelated to Spring is
Open Smphony's OSCache. Updating from 2.3 to 2.4 introduces a dependency on JMS that can't be resolved. Why should an object caching system depend on JMS? If it must, why can't they define the damn POM correctly so the dependency can be found? Its the standard JMS api jar for crying out loud.
Anyway, back to Spring 2.5. Changes made:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
<version>2.0.6</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>2.0.6</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>2.0.6</version>
<scope>compile</scope>
</dependency>
Becomes
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
<version>2.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>2.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>2.5</version>
<scope>compile</scope>
</dependency>
Then:
mvn clean package
is run, the test server started, and all appears well and good in the world.
Kudo's to the good folks at Spring Source. Backwards compatibility is a beautiful thing.
Update:I forgot to mention, the namespaces in the configuration files should get updated at some point as well. I didn't encounter any problems with the 2.0 namespaces and the 2.5 libraries. However, there are a few improvements, notably the JndiObjectFactoryBean, that are pretty darned useful.
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:cache="http://www.springmodules.org/schema/oscache"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springmodules.org/schema/oscache http://www.springmodules.org/schema/cache/springmodules-oscache.xsd" />
becomes
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:cache="http://www.springmodules.org/schema/oscache"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springmodules.org/schema/oscache http://www.springmodules.org/schema/cache/springmodules-oscache.xsd" />
WooHoo!
Now, if the Spring Modules guys could get their act together....
Labels: development, review, spring
There as been a lot of debate about the quote tag (<q cite="http://willcode4beer.com">my quote</q>). Many are upset that Internet Explorer doesn't render it correctly, others argue, "who cares". Though semantic mark-up is often at the center of the debate, often missed is, why have a quote tag in the first place.
To render quote marks doesn't really make a strong argument. The rendered quote characters can depend upon a user's language. Doesn't it make more sense to render quotes with the language of the article being read? Besides, the rendering can be fairly easily dealt with using behaviors or javascript (as my page on
fixing quotes in IE shows).
Back to the semantics. There is an attribute of the quote tag meant to refer to the source of the quote. The specification says that the attribute should be a URL. However, none of the browsers, including those that render quote characters, do anything with the CITE attribute.
The
blockquote tag doesn't suffer from the debate. However, its
cite attribute is still unused.
So, we have this wonderful piece of contextual, semantic information but, the browser provides no way for a user to make use of it, and the average user doesn't even know the information is available.
I built a
citation tool-tip script to make floating tool-tips with the cite attribute hyper-linked and with the tag title as a title in the tool-tip. But, isn't this really a work around of what the browser should be doing anyway?
Maybe the next step should be a browser plug-in/extension that can show a "citations" sidebar. This could easily show what is cited and provide navigation to the citation.
I wonder, how many people actually use the "
cite" attribute anyway...
--Paul
Labels: development, html, javascript, standards
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
This was presented by
Ian Spence. It was a fantastic session.
In his presentation on iterative development, he recommended iterations of 4-6 (preferably 4) week iterations. Each iteration runs the full scope of:
Requirements -> Analysis -> Design -> Implementation -> TestingOne of the key benefits is continuous measurement. Another is team members are focussed on short term goals (and we all know it is easier to focus on a short term goal than a long term one).
Other benefits are it allows you to cope with change very well, and as products are placed in front of customers, it becomes easier extract the requirements from the customer.
Iterative development can keep things with the highest priority at the top of the heap. If you find a bug in a critical part of the architecture early, then time is spent on fixing that before developing a trivial nice to have feature. So, maybe to make schedule, you ship
working software with fewer features, instead of buggy code with lots of features.
I am a fan of iterative development but, I've never thought of things in that context before.
-cool
The best quote of the presentation:
"The waterfall process is good if you've done it before, you are good at it, and you can do it in one go."The biggest risk with this process can come from the people.
You need continuous stakeholder (and customer) involvement. This is good but, we have all experienced the customer who only wants to be involved at the beginning and the end of a project. This could be the most difficult.
The team needs to be disciplined and collaborative. The challenge here is that since iterations are short, everybody on the team is being judged every 4 weeks. So, there isn't any room for slacking. This can cause a bigger issue than might be predicted.
The next risk, still a people issue, is to not let the iterations stretch beyond the planned iteration period. The companion issue is, don't jump ahead to the next iteration either. This really keys in to the collaborative part of team work. If folks get ahead in their work, instead of working ahead, it is much better if they help test.
There is a lot more on this topic I want to write about. But, I'll save that for another day.
-
Labels: agile, development, iterative development
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