”A designer knows he has achieved perfection not when there is nothing left to add, but when there is nothing left to take away” ~Antoine de Saint-Exupery
Apple ended today the wave of speculations and rumors about the next generation of iPhone with the unveiling of the new iPhone 3G (S) at WWDC 09. The new iPhone 3G (S) closed the gap currently present on the iPhone platform with the instruction of long expected features like Faster Overall Performance, Video Recording, better Camera, cut/copy/paste and landscape keyboard (features present in some of iPhone competitors). Unfortunately Tethering, one of the best features added to the new platform, won’t be immediately available to the US market due to registrations imposed by AT&T.
In summary iPhone is still the most advance mobile platform on the market; and the combination of a great product and an aggressive cut in prices should keep it as the dominant platform for the now.
It should be an interesting and different JavaOne this year. I’m looking forward to the sessions and interaction with other people, but more than that, I’m looking forward to understand how the Java Community is taking the acquisition of Sun by Oracle.
This year the state economy will play an important role, the Early Bird was pretty much extended until the initial day of conference which is possible indication of low or moderate number of attendance.
I will be blogging, twitting and publishing pictures as the conference progress.
Direct Web Remoting (DWR) is a popular option for enabling Ajax support on Java based applications. This post illustrates the minimum configuration need to use DWR on a Spring MVC based application.
Configuring DWR
Add dependencies to pom.xml:
DWR has a very small foot print from the dependencies point of view. In order to use DWR you need to add the dwr.jar on your classpath. The following code snippet illustrates how this is done using Maven.
Create and configure dwr-servlet.xml:
As indicated by Spring MVC standards you must create a mapping for each Servlet. The following code provides the configuration for the dwr-servlet.xml.
Create DwrFacede:
For the purpose of this sample we are illustrating how to retrieve an user using DWR. It is recommended to create a Façade to consolidate all the methods exposed using DWR, this will facilitate the management and mapping tasks.
public interface DwrFacade {
User findUser(String login);
}
Create and configure dwrContext.xml:
It is a good practice to keep all DWR definition in a separate context file. On this file two important definitions need to be provided. <dwr:configuration> indicate how DWR will marshal any custom type (i.e. User.java); DWR is pre-configured to handle Java types likes Long, String, etc… so no need to define those here. The other important part of the configuration is the declaration of which methods are going to be available for remote calls, for example: <dwr:include method=”findUser” />.
Configure applicationContext.xml:
On this sample, applicationContext.xml is the file initially loaded by Spring; since all dwr related definitions are on the dwrContext.xml, this file needs to be imported on the applicationContext.
...
<import resource="dwrContext.xml"/>
...
Executing the sample:
Open a web browser and go the following URL http://[server]:[port]/quickstart-dwr-spring-mvc
Download a complete fully functional copy of the source here.
As software become a commodity and the number of people writing software significantly increase, the need for ethic and professional values in the software community become more important than ever. Hopefully this great initiative by Robert C. Martin will make people re-think what been a software professional means bringing even higher standards to the industry.
Join us!,… Resistance is futile you will be assimilated.
Unit testing is an integral part of modern software development; it is difficult to imagine building reliable software in a cost effective way without the use of this valuable technique.
Most developers produce some kind of unit test script immediately after the creation of a component as a verification mechanism; approach that work pretty well most scenarios. But, working in this fashion don’t allow us to fully take advantage of all the benefits unit testing may bring, due to the fact that the test is only used as a verification and not as a tool to assist the developer in the understanding of the problem to be solved.
Test-driven design (TDD) calls for the creation of tests prior the implementation of the components. TDD considers testing an integral part of the detail technical design. Developing tests first (before producing any significant production code) helps in the understanding of the responsibilities and scenarios related to a component, inevitably improving the overall quality of the design.
“If it’s worth building, it’s worth testing. If it’s not worth testing, why are you wasting your time working on it?” - Scott W. Ambler
A test has multiple purposes, it provides a verification mechanism, it helps to identify refactories opportunities and also serves as an important part of the documentation of the component by illustrating the different conditions and scenarios handle by it.
Automation is a key part of good testing. Performing manual testing is not only unreliable but expensive and time consuming. Adopt tools that allow the automation of unit testing, integration testing and regression testing. Measure progress by introducing test converge tools to the build cycle to ensure the effectiveness of the test effort, but more important learn and understand what the metrics mean and take appropriate actions to achieve expected results.
All tests produced by a development organization should be considered an asset. Automated tests act as a safety net, providing a reliable way to introduce new features and changes to any code base in a cost effective way.
Good code is key for the long term success of any software based system. We all strive to produce it; we all believe we do our best when crafting it; we all like it; … but,
What is good code?
The fact that it compiles and actually works (and is in production) does not made any code good code. A good code based displays the following characteristics:
It’s clean - the code is predictable; each line of code is what you expect it to be. You never find yourself asking what does this line means?, why is here?.
It’s simple - it doesn’t matter the domain; it doesn’t matter how complex are the use cases; good code should be simple. There are always simple and elegant solutions for complex problems if the right design principles are applied.
It focus on the problem it solves.
It’s DRY (don’t repeat yourself).
It has Interface Segregation - the code based contains well defined fine grained interfaces that are client specific.
It demonstrates good separation of concern.
It’s been implemented using a pattern-based design.
It contains well defined conceptual boundaries.
It demonstrates appropriate dependencies management.
It’s documented.
It has decent test coverage - code that is not backed by an appropriate number of automated tests is not considered good code.
Most of the things described above are well known by most people, achieving them it is a total different story. So, what is involve on crafting good code?
Achieving good code
The following design principles, architectural qualities and general guidelines provide you with a start point for achieving good code.
Design principles
(Robert C. Martin; Agile Software Development: Principles, Patterns and Practices)
Class Design:
Single responsibility - a class should have one, and only one, reason to change.
Open closed - you should be able to extend a classes behavior, without modifying it.
Liskov substitution - derived classes must be substitutable for their base classes.
Interface segregation - make fine grained interfaces that are client specific.
Dependency inversion - depend on abstractions, not on concretions.
Packages Cohesion:
Release reuse equivalency - the granule of reuse is the granule of release.
Common closure - classes that change together are packaged together.
Common reuse - classes that are used together are packaged together.
Couplings between Packages:
Acyclic dependencies - the dependency graph of packages must have no cycles.
Stable dependencies - depend in the direction of stability.
Stable abstractions - abstractness increases with stability.
Architectural quality
(Inspired in some of the talks by Juergen Hoeller)
Conceptual Boundaries:
A module is a collection of specific packages combined into a logical conceptual unit. Modules are characterized by low coupling and high cohesion.
Modules are a conceptual unit.
A module is a unit of comprehension.
Separation of physical tiers is not a conceptual modules separation.
Typically modules are driven by deployment needs (usage scenarios) but that does not fit under the conceptual module definition.
Module should be driven by domain boundaries (conceptual boundaries related to a specific problem).
Layers:
Layers allow the organization of different modules into a hierarchical structure.
Layers are driven by visualization intent.
Modules are vertical slice; layers are horizontal structures; in many scenarios there are orthogonal to each other.
Layers must keep unidirectional dependency.
General Guidelines
Document conceptual boundaries in architecture documents. Establish well defined naming conventions.
The core structures needs to be in the proper conventions upfront.
Trade-off happened during the evolution of the code base, you want the code to evolve without deterioration, try not to compromise the architectural quality of the system/modules.
Enforce very strict architectural guidelines. Try to keep Backward compatibility, but re-evaluate if it’s compromise architectural quality.
Embrace unit testing and contentious integration. Automatic testing is a must have.
Shot for the higher test coverage possible (anything between 80% and 90% is good). 100% is unreal, most coverage tools won’t give you that number.
Adopt and use code metric and analysis tools. Plan refactories based on the results obtained from the metric and analysis tools.
If up to this point you still believe you have been producing good code, look at the mirror and tell me if the following symptoms sounds familiar; Is your system suffering from any of these?
Rigidity - tendency for software to be difficult to change.
Fragility - tendency of the software to break in many places every time it is changed.
Immobility - inability to reuse software from other projects or from parts of the same project.
Viscosity - comes in two forms: viscosity of the design (it’s easier to implement a hacks than mentioning the spirit of the design/architecture), and viscosity of the environment (development environment is slow and inefficient so people prefer to take shortcuts or move away from the process).