terça-feira, 27 de abril de 2010

Agile Design

INTRODUCTION
As a developer, I've always been fascinated by software design. Usually defined as the activity to specify software components (classes) and its interactions, I consider it both interesting and challenging. When I first get in touch with agile principles (SCRUM and XP in particular) I realized that there is a huge gap between what I learned back at college and what the methodologies enforce.

UP FRONT DESIGN
I learned back at college that design is the software engineering phase that bridges requirements specification and the coding. The analyst defines WHAT to do, the design HOW to do it and the programmer just DO it. The design phase products are documents and diagrams to be used by the programmer to code the software as the analyst idealized it. This approach is called up front design and it doesn't come without its drawbacks and challenges.

  • It is very hard (if not impossible) to come up, in advance, with such a design that both meets all requirements and is flawless.
  • It would be necessary to come up with a design so flexible to accommodate the dreaded change of requirements. Even if possible, what would be the cost, in terms of complexity, of such design?
With SCRUM there's not such thing as design phase. There's a meeting when the product owner detail the sprint backlog items so the analysts can start documenting, the testers can start write tests cases and the developers can start coding. That simple. There's no design at all? Well, not as I learned back at college.

EVOLUTIONARY DESIGN
If its not possible to come up with a design that meets all the requirements, that is flawless and its impossible to avoid requirements changes, what could justify the effort (usually a big one, considering the complexity and level of abstraction required) spent with an up front design? Accepting that coding is design, agile methodologies come up with an approach called evolutionary design.

With that approach, design and coding walk side by side. The design evolves according to the functionalities been developed needs. There's no a formal role as designer nor a particular moment to do the design. Every developer design and redesigns every day.

YAGNI
One of the most intriguing concepts related to evolutionary design is known as YAGNI (You Aren't Gonna Need It). “Always write only the code you need right now, never the one you thing you're gonna need tomorrow.” Even when you are absolutely sure you're gonna need the code and the cost of implementation is zero: just write it when you actually need it.

YAGNI is counter-intuitive because it goes against what is believed to be the greater benefit of a good design: anticipation of complexity and consequent risk mitigation. Nevertheless, there are very good arguments in favor of such approach:
  • Respects the clients ROI: write code that doesn't aggregate any value to the functionality under construction means to disregard the PO prioritization and , in consequence, the client's ROI.
  • Time saving: Time used to write code that is only going to be used in a later iteration may be missed when it comes to deliver the functionalities promised to the actual iteration.
  • Possible changes: To write code in advance is unnecessary risk because the understanding may have been incorrect or the logic/rule may simply change, what originates the need to rewrite the code.

MAKE IT WORK
By now the reader may have came to the conclusion that a evolutionary design projects may end up with no design at all, or a very poor design.

Critics accuse evolutionary design to be over-dependent on the maturity of the team, what is somewhat the true. On that matter, XP defines the role of a coach, who is a more experienced programmer responsible for guiding other developers in technical issues (including design).

Besides, there is a number of practices, from the agile environment or not, I believe should be judiciously used to maintain design quality:
  • Emphasis on tests (unit tests, integration tests, etc): It gives you some confidence during design changes.
  • Continuous Integration: keep the team synchronized with code and find out possible bugs earlier.
  • Pair Program: If the functionality is complex, maybe a god idea to get two developers working on it.
  • White box analysis: Its a good idea to keep an activity of code review to detect design issues that not necessarily show themselves as bugs.
  • Good practices list: To keep a list of design good practices so the developers can refer to it when in doubt. The list could evolve as the project goes and experience is gain.

CONCLUSIONS
The agile wold has no place to up front design on its conceptual manner, as a well defined phase and trying to anticipate all details  of the development of a functionality, but it could benefit from some of it features such as better risk management and strong standardization.

Evolutionary design is an alternative approach indicated by the agile principles, but it must be applied together with other practices in order to keep the quality of the design.

REFERENCES
Great Martin Fowler article on design and XP (http://martinfowler.com/articles/designDead.html)

Article on up front design problems (http://architects.dzone.com/news/great-lies-design-vs)




segunda-feira, 26 de abril de 2010

Design Ágil

INTRODUÇÃO
Como desenvolvedor, sempre fui fascinado por design de software. Comumente definida como a atividade de especificar os componentes de software (classes) e suas interações, considero a tarefa desafiadora e bastante interessante. Quando comecei a entrar em contato com princípios de desenvolvimento ágil (em especial SCRUM e XP), percebi que havia uma grande incompatibilidade entre o que aprendi na faculdade (e acreditava ser a forma correta de fazer design) e o que pregam as metodologias.

UP FRONT DESIGN
Aprendi na faculdade que design é fase da engenharia de software que faz a ponte entre a especificação de requisitos e a construção propriamente dita. O analista decide O QUE fazer, o projetista decide COMO fazer e o programador FAZ. O produto da fase de design são documentos e diagramas que o desenvolvedor irá usar para construir o software que o analista idealizou. Esta abordagem hoje é chamada de up front design e sem dúvida não é livre de seus problemas e desafios:

  • É muito difícil (senão impossível) criar antecipadamente um design tal que atenda todos os requisitos (funcionais e não-funcionais) e esteja livre de falhas.
  • Seria necessário criar um design que fosse flexível suficiente para acomodar as temíveis mudanças de requisitos. Mesmo que seja possível, qual seria o custo em complexidade de um design assim?

No SCRUM não há fase de design. Há uma reunião onde o product owner explica para o time em detalhes as características de cada item do sprint backlog e a partir daí analistas começam a documentar, testers especificam casos de testes e programadores começam a desenvolver. Simples assim. Não tem design? Não da forma como aprendi na faculdade.

EVOLUTIONARY DESIGN
Se não é possível gerar um design que atenda a todos os requisitos, seja livre de falhas e se não é possível evitar mudanças de requisitos, o que justifica o esforço (geralmente grande devido a natureza complexa da atividade) despendido na criação de um up front design? Entendendo que codificar é projetar as metodologias ágeis propõem algo chamado evolutionary design.

Nesta abordagem, o design e codificação andam lado a lado. O design evolui de acordo com as necessidades das funcionalidades sendo construídas. Não há o papel formal de projetista nem um momento específico para desenvolver o design: Todos os desenvolvedores fazem e refazem o design todos os dias.

YAGNI
Um dos conceitos mais intrigantes relacionados a evolutionary design é conhecido pela sigla YAGNI (You Aren't Gonna Need It). “Sempre escreva apenas o código que você precisa agora, nunca o que você vai precisar amanhã” Mesmo que você tenha absoluta certeza de que vai precisar daquele trecho de código e que o custo de escreve-lo seja zero: Deixe para fazê-lo quando for necessário.

YAGNI é contra-intuitivo porque vai contra aquilo que acredita-se ser maior benefício de um um bom design: antecipação de complexidade e consequente redução de riscos. Entretanto, existem bons argumentos em favor desta abordagem:

  • Respeito ao ROI do cliente: Escrever código que não agrega valor a funcionalidade em construção é desrespeitar a priorização do product owner e consecutivamente o ROI do cliente.
  • Economia de tempo: O tempo usado para escrever código que só será usado posteriormente pode fazer falta na hora de entregar as funcionalidades previstas para esta iteração.
  • Possíveis mudanças: Escrever código antecipadamente é um risco (desnecessário) porque o entendimento pode ter sido equivocado ou a lógica/regra pode mudar, gerando a necessidade de reescrever o código.  

FAZENDO EVOLUTIONARY DESIGN FUNCIONAR
Neste ponto, o leitor já deve ter percebido que um projeto que usar evolutionary design corre grandes riscos de acabar mesmo é sem design, ou com um design muito pobre.

Críticos acusam evolutionary design de ser super-dependente da maturidade do time, o que tem um fundo de verdade. Neste sentido, o XP define o papel do Coach, que seria um desenvolvedor mais experiente com a responsabilidade de orientar o time nas decisões técnicas (inclusive de design).

Além disso, existe uma série de práticas, do próprio mundo ágil ou não, que acredito devam ser empregadas criteriosamente de forma a manter a qualidade do design:
  • Ênfase em testes (unitários, de integração, etc..): É importante ter uma boa margem de segurança quando são feitas mudanças de design.
  • Integração contínua: Integrar o código do projeto como um todo (mantendo o time em sincronia) buscando detectar o mais cedo possível possíveis problemas de design.
  • Pair program: Se a funcionalidade for muito complexa, colocar 2 desenvolvedores responsáveis por ela pode ser uma boa ideia.
  • Análise caixa branca: Incluir uma tarefa de inspeção de código a fim de detectar design inadequado (devido ao auto custo, a análise poderia ser feita por amostragem apenas)
  • Lista de boa práticas: Manter uma lista de boas práticas que sirva de orientação aos desenvolvedores. Tal lista seria incrementada ao longo do projeto com a experiência adquirida. 

CONCLUSÕES
O mundo ágil não tem lugar para up front design em sua forma conceitual, como uma fase bem definida e buscando “prever” todas as nuances do desenvolvimento de uma funcionalidade, mas poderia se beneficiar de algumas de suas caraterísticas como redução de riscos e forte padronização.

Evolutionary design é a abordagem alternativa que os métodos ágeis indicam, porém ele deve ser empregada em conjunto com outras práticas que garantam a qualidade do design do software a ser construído.

REFERÊNCIAS
Excelente artigo de Martin Fowler sobre design e XP (http://martinfowler.com/articles/designDead.html)

Artigo sobre problemas de up front design (http://architects.dzone.com/news/great-lies-design-vs)












quinta-feira, 15 de abril de 2010

Flush-mode: Conversation

INTRODUCTION

Jboss Seam is a Java framework for web development which integrates technologies such as Asynchronous JavaScript and XML (AJAX), JavaServer Faces (JSF), Java Persistence (JPA), Enterprise Java Beans (EJB 3.0) and Business Process Management (BPM) into a unified full-stack solution, complete with sophisticated tooling. Its main feature is to easy the use of the technologies it integrates.

I thought about writing a post about jboss seam's main features and why I like it so much, but I won't do it for two reasons:
  1. There are already a lot of material on that topic (here, here, here, here, and here).
  2. The Jboss seam as we know it is coming to its end. The framework is so successful that it was, at least most part of it, incorporated by the JEE6 specification (mainly JSF2 and CDI). The future of the framework is at CDI's portable extensions, integrating the functionalities which were not standardized.



Nevertheless, I believe the actual version is still gonna be used for some time, so its worth to share a few clues related to specific points of the framework. This post in particular is about one of the main features of Jboss Seam: conversations.

CONVERSATION

The concept of conversation was not created by Seam, but it was the seam framework the first one to introduce it as a first class construct. In few words, a conversation is a context to hold application state, which scope is longer than a single request but shorter than the user's http session. A conversation represents a task the user can perform in the application and it is seam's default unit of work.

Under the hood, seam attaches the entity manager to the conversation context, so the entities remain persistent through the unit of work.  Also, it disables the automatic flush of the entity manager  (flush-mode: manual) so the changes don't get propagated to the database prematurely. That responsibility now stands with the developer, which issues a entity manager's flush at the end of the conversation.



The problem with that approach is the potential decrease of business method's re-usability as one method can be the last step of some conversation but not in another. 

AN EXAMPLE

Let's picture an human resources application which domain includes, obviously, employees and departments. It's acceptable to presume that such application includes a CRUD functionality to both models, being possible, in the latter one, to select a chief employee. The employee model includes a flag to determine whether she is a chief or not.

Accepting that a set of business rules are to be applied on a employee update (a conversation), we could come up with the following pseudo-method, responsible for the execution of such rules.

public void editEmployee(Employee employee){

peformRule1();

peformRule2();

peformRule3();

//Synchronize changes in the model with the database at the end of the conversation
this.entityManager.flush(); 


}


On the conversation responsible for editing departments, one of the steps would be exactly to update the chief employee (through the pseudo-method we just saw) and there's where the problem raises because this method executes an unexpected flush before the conversation is over.

public void editDepartamento(Department department, Employee employee){

peformRule1();

peformRule2();

employee.setChiefe(true);

//peforms an unwanted flush
editEmployee(employee); 

peformRule3();

//Synchronize changes in the model with the database at the end of the conversation
this.entityManager.flush(); 


}


For such a simple example, one could suggest some solutions such as force the employee's update to be the last step of the department's editing conversation, or to include a flag parameter to the employee editing method indicating whether it should perform a flush or not. None of these solutions is, nevertheless, adequate. What it's really needed is a way to ensure that the flush will be performed only at the end of a successful conversation, decoupling the database synchronization of the business logic.

//Refactored employee's editing method, receiving a boolean paramether inidicating whether the flush should be executed. Not the best solution!
public void editEmployee(Employee employee, Boolean peformFlush){

peformRule1();

peformRule2();

peformRule3();

if (peformFlush){
this.entityManager.flush(); 
//Synchronize changes in the model with the database at the end of the conversation
}

}

FLUSH MODE CONVERSATION

Even thought it doesn't exists built-in, seam provides mechanisms so we can get the same effect. The following solution is based on seam built-in events, specially one that's rose every time a conversation come to its end. We observe that event, performing a flush when it's needed.

@Name("endConverationObserver")
@Scope(ScopeType.CONVERSATION)
public class EndConverationObserver {

 @In
 private Boolean flushEntityManager;

 @In
 private EntityManager entityManager;

 @Observer(value = "org.jboss.seam.endConversation", create = true)
 public void DetermineflushEntityManager() {
  if (flushEntityManager) {
   this.entityManager.flush();
  }

 }

}

The weak point of such solution appears with the knowledge that not all ended conversations must perform a flush. Particularly, canceled conversations must not or the data will be synchronized with the database anyway. That's why a flag was included, so the component could ask the context whether it should perform the flush or not. It is the programmer's responsibility to feed the context with such boolean variable, whose default value would be true. It could be done, for example, in the actionListener of the cancel button.


@Name("editEmployeeController")
@Scope(ScopeType.CONVERSATION)
public class EditEmployeeController{

 @Out
 private Boolean flushEntityManager;

 @In
 private EntityManager entityManager;

 public String cancel() {
  this.flushEntityManager = false;
                return "editCancel"

 }

}

CONCLUSION

In this post we talked about seam's conversations and how they are usually implemented. An alternative approach was proposed, seeking to increase business methods reusability. Such approach uses bult-in mechanisms to decouple the database synchronization of the business methods.  

domingo, 11 de abril de 2010

flush-mode: Conversação

INTRODUÇÃO

Jboss Seam é um framework Java focado no desenvolvimento web que integra tecnologias como Ajax, Java Server Faces (JSF), Java Persistence (JPA), Enterprise Java Bean (EJB) e Business Process Management (BPM) em uma única solução apoiada por uma série de ferramentas sofisticadas. Sua principal característica é facilitar o uso das tecnologias que integra.

Pensei em fazer um post descrevendo as principais características deste framework e porque eu gosto tanto dele, mas não vou fazê-lo por 2 motivos:
  1. Já existe muito material assim por ai (aqui, aqui,aqui,aqui e aqui).
  2. O Jboss seam como existe hoje está com os dias contados. O framework foi tão bem sucedido que acabou sendo, em sua maioria, absorvido por especificações da plataforma JEE6 (em especial CDI e JSF2) O futuro do framework está em extensões portáveis para CDI integrando as funcionalidades não incorporadas a especificação.
No entanto, acredito que a versão atual ainda será usada por algum tempo, portanto, vale compartilhar algumas dicas referentes a pontos específicos do framework. A dica deste post é sobre uma das características mais marcantes do framework: conversações.

CONVERSAÇÃO

O conceito de conversação não foi inventado pelo jboss seam, mas foi este framework o primeiro a incorporá-lo como construção de primeira classe. Resumidamente pode-se dizer que uma conversação é um contexto onde o estado da aplicação pode ser armazenado, cujo escopo é maior que uma requisição mas inferior a sessão do usuário. Uma conversação representa uma tarefa que o usuário pode realizar na aplicação e é a unidade de trabalho padrão no jboss seam.

Por baixo dos panos, o seam inclui o entity manager no escopo de conversação, de forma que as entidades permaneçam persistentes durante toda a unidade de trabalho e desabilita o flush automático, (Flush-Mode: Manual) de forma que as alterações realizadas não sejam propagadas para o banco prematuramente. Esta responsabilidade é repassada ao desenvolvedor, que deve executar manualmente o flush no fim da conversação.



O problema com esta abordagem é que potencialmente pode reduzir a reusabilidade dos métodos de negócio, que em determinados momentos podem ser o último passo da conversação e em outros não.

UM EXEMPLO

Imaginemos por exemplo uma aplicação de RH cujo domínio inclui, obviamente, colaboradores e departamentos. É aceitável presumir que tal aplicação inclua, entre outras, uma funcionalidade de edição de colabores e outra para edição de departamentos, sendo possível, nesta última, apontar o colaborador responsável pelo departamento. A entidade que representa os colaboradores possui um marcador indicando determinado colaborador é um chefe ou não.

Se aceitarmos que uma série de regras de negócio deve ser executada durante a edição de um colaborador (uma conversação), podemos imaginar o seguinte pseudo-método, responsável pela execução destas regras.


public void editarColaborador(Colaborador colaborador){

executarRegra1();

executarRegra2();

executarRegra3();

//sincroniza as alterações na model com a base de dados no fim da conversação
this.entityManager.flush(); 


}


Na conversação referente à edição de departamentos, um dos passos seria justamente a edição do colaborador. O método negocial previamente definido deverá, portanto, ser invocado, e é ai que surge o problema porque este método executa o flush do entityManager o que é desejável apenas no fim da conversação da edição de departamentos.

public void editarDepartamento(Departamento departamento, Colaborador colaborador){

executarRegra1();

executarRegra2();

colaborador.setChefe(true);

//executa flush inadvertidamente
editarColaborador(colaborador); 

executarRegra3();

//sincroniza as alterações na model com a base de dados no fim da conversação
this.entityManager.flush(); 


}


Para este caso simples, algumas soluções podem ser propostas, como forçar que a edição do colaborador seja o último passo da conversação de edição de departamentos ou a inclusão de um parâmetro boleano no método de edição de colaborador indicando se o flush deve ou não acontecer. Nenhuma destas soluções, entretanto, é a adequada: o que precisamos mesmo é assegurar que o flush irá ocorrer apenas no fim de uma conversação bem sucedida, desacoplando a sincronização da lógica nos métodos negociais.


//Método de edição de colaborador refatorado para receber um parâmetro boleano indicando se o flush deve ou não ser executado. Não é a melhor solução!
public void editarColaborador(Colaborador colaborador, Boolean executarFlush){

executarRegra1();

executarRegra2();

executarRegra3();

if (executarFlush){
this.entityManager.flush(); //sincroniza as alterações na model com a base de dados
}

}

FLUSH-MODE: CONVERSATION

Apesar de não existir de forma built-in, o jboss seam disponibiliza alguns mecanismos que permitem obter efeito semelhante. A solução a seguir baseia-se no fato do seam levantar alguns eventos por padrão, entre eles um que indica o fim de uma conversação. A Idéia, portanto, consiste em disponibilizar um componente que observa este evento, fazendo o flush quando necessário.

@Name("endConverationObserver")
@Scope(ScopeType.CONVERSATION)
public class EndConverationObserver {

 @In
 private Boolean flushEntityManager;

 @In
 private EntityManager entityManager;

 @Observer(value = "org.jboss.seam.endConversation", create = true)
 public void DetermineflushEntityManager() {
  if (flushEntityManager) {
   this.entityManager.flush();
  }

 }

}


O ponto fraco desta solução emerge na percepção de que nem todo fim de conversação deve incluir sincronização com o banco. Em especial, as conversações canceladas não devem ter seus dados sincronizados! Para isso, foi incluída uma flag que indica se a sincronização deve mesmo ser efetuada, com o valor padrão igual a true. Se a sincronização não for desejada, o usuário deverá indicar isso setando o valor da variável para false. Isso pode ser feito por manipulação direta do contexto ou por meio de uma variável a ser ejetada.

@Name("editColaboradorController")
@Scope(ScopeType.CONVERSATION)
public class EditColaboradorController{

 @Out
 private Boolean flushEntityManager;

 @In
 private EntityManager entityManager;

 public String cancel() {
  this.flushEntityManager = false;
                return "editCancel"

 }

}

CONCLUSÃO

Neste post falamos sobre conversações no jboss seam e da maneira como geralmente são implementadas. Uma abordagem alternativa foi sugerida, buscando manter a reusabilidade dos métodos de negócio entre as conversações. Tal abordagem faz uso de recursos do próprio framework, como eventos bult-in e variáveis de contexto, para desacoplar a sincronização dos dados com o banco das regras de negócio.

segunda-feira, 5 de abril de 2010

Scrum and the context

When Scrum become popular a few years ago, promoted a sharp turnaround in the development community. That's because, much more than a new methodology, Scrum advocates a new approach, a new philosophy in software development - strongly based on the ideas of the agile manifesto.

By encouraging practices like having a customer representative directly involved in the design or maintenance of self-managed teams Scrum directly influences the structure, the culture of organizations – it interferes in what is called the team context: the environment in which it falls. Obviously these changes are usually costly and sometimes impractical.

As agile methodologies grow in popularity, also grows the questioning of its efficacy. In this context, rises a group that advocates grater rigidity in the team’s context maintenance. According to this group, establishing that an agile methodology is made up of a predefined set of practices, without taking the context into account is nonsense since some of these practices could turn into pure bureaucracy – the one thing agile methods seek to eliminate!

Also it’s important to notice that the agile manifesto says nothing about keeping the customer close to the development team or even on shorter construction cycles. These are concepts of Scrum and it is certainly possible to have an agile team without these characteristics.

On the other hand, saying that the methodology must bow to the context is inappropriate. Due to its innovative nature, adopting an agile methodology requires at least some cultural and structural adaptation. If it is to ignore the breadth of the change that the introduction of an agile methodology requires, you’re certainly better off not starting at all!

The ideal path, I beleave, is the middle way: adaptation of the context as appropriate and judicious adoption of practices always taking the context into account. What then would be the measure of this balance? The team of course. After all, we must not forget that individuals and their interaction are more important processes and tools.
References
 http://xprogramming.com/blog/2009/01/30/context-my-foot/
http://www.noop.nl/2009/02/the-decline-and-fall-of-agilists.html
http://jamesshore.com/Blog/The-Decline-and-Fall-of-Agile.html
http://martinfowler.com/bliki/FlaccidScrum.html

domingo, 4 de abril de 2010

A Page to rule them all - English Version

Can you imagine a web application/site composed entirely of a single page? This is the proposal of the Single Page Interface Manifesto, published recently by Jose Maria Arranz Santamaria.

Driven initially by curiosity, I decided to check out this manifesto. This post summarizes the proposal of the manifest and the discussions that it motivated.

Motivation


The Internet was conceived as a way of sharing scientific papers, which usually contains references to other related documents. Hence its pages and links based nature.

Today the Internet holds much more than scientific documents. The ability to generate content dynamically opened the door for general purpose web applications. Truth be told, today the HTTP protocol is used to support things it definitely was not designed to.

This is why developing for the Web has always been so complex. One can say that a good portion of the evolution of web development occurred in the direction of becoming more like desktop development – which is more simple and natural. In this sense, we saw the emergence of front controllers that "capture" requests for pages that do not exist, creation event-based web frameworks, and extensible use of Ajax for creating more "desktop-like" interfaces.

SPI (Single Page Interface) would be the last step of this journey. The idea is to have a web application running entirely on a single page, just like a desktop application runs on a single main window. This approach would end a series of problems that takes the web developers' sleep away: back button, caching, navigation and forms' automatic completion, just to name a few.

Principles


The main idea behind SPI is replacing the concept of "page" for concept of "state". An application consists of a set of states (primary and secondary) that determine, among other things, the interface to be displayed.

The state control is made through URL references (the final part, which comes after '#'). Any changes in this part of the URL do not cause reloading of the page.

Ajax is a fundamental technology for SPI - without it such approach would be unworkable. In fact an SPI application makes heavy use of Ajax calls to avoid full page reload.

Of course such approach would not go without its criticisms. One can´t ignore the difficulties in integration with search and booking of visits. The manifesto proposes solution to such problems in the form of various Javascrit codes.

Following the paradigm associated with the development of web applications, this new approach could be called model 4.

Conclusion


I consider the SPI idea valid as an alternative approach for individual cases, primarily the ones involving complex interaction with the user - that would result in complex navigation rules on pages based web applications.

The fact that the solutions presented in the manifest consists mostly of "workarounds" exposes the need for maturation of the approach.

Despite the manifest to show the technical feasibility of the approach, much more is needed to gain space in the community: Productivity. There must be frameworks and toolkits that embrace SPI.

After all the idea is quite intriguing. Would that be the future of web development?

sábado, 3 de abril de 2010

New Times for Java SE 7

In the Java world, working with dates – and time in general - has always been quite problematic. A series of design problems makes use of current API complex and bug prone. JSR-310 to the rescue! The new date and time API, still in development and to be integrated into version 7 of the Java SE platform, promises to finally end this headache that 11 out of 10 Java developers certainly have had to endure.

Problems with the Current API


Everybody agree that the Java’s date and time current API, exposed mainly through java.util.Date and java.util.Calendar classes, presents a series of inconveniences. Among them:
  • No classes representing concepts rather common as a date without time, time without date or even a period or interval. Because of that, the developer ends up using the API in a manner different from that for which it was designed.
  • The objects are not immutable, requiring external synchronization in a multi-thread environment.
  • Classes are limited to represent the date as an incremental number from an initial time (epoch). Besides being counter-intuitive, this approach makes difficult to manipulate the objects adequately.
These are exactly some of the problems that the JSR-310 proposes to solve.


JSR-310 Features


The main features of JSR-310 are:
  • Based on ISO-8601 - International Standard for representing dates and times.
  • Thread-safe - Its main objects are immutable.
  • More cohesion and readability-classes and their methods’ responsibilities are better defined and their names represent these responsibilities more clearly.
  • More Extensible - The API provides a set of extension points through which - mainly through the Strategy design pattern - You can customize and extend the behavior of the API, facilitating certain tasks of daily life.
  • Two different scales: machine (representing the passage of time using a single incremental number) and Human (representing the passage of time through the value of a number of fields, such as year, month, hour, etc.).

Concepts and main classes


The JSR-310 was built on some basic concepts, which reflects on the main classes of the API.

Instants

Instants represent a specific moment in a timeline with nanosecond precision. An example of an instant would be "June 3, 1983 the 12:03:00.0 UTC". Alternatively, a moment can be defined as a shift, in nanoseconds, from a default starting point - the epoch (which remains midnight on January 1, 1970).

There are several classes that represent a moment in the JSR-310 API : Instant, OffSetDateTime and ZonedDateTime.

Instant is one of the most basic API classes. It uses the machine scale. It should be seen as a substitute for java.util.Date. It has methods for comparison with other Instant and addition and subtraction of certain duration (remembering that the class is immutable)

Instant now= Clock.systemDefaultZone().instant();

Instant oneMoreMinute= now.plusSeconds(60); //returns a new Instant!

Boolean test = now.isAfter(oneMoreMinute); //false 




OffSetDateTime represents a day, time of day and a shift of the UTC (coordinated universal time). It uses, therefore, human scale.

OffsetDateTime today= Clock.systemDefaultZone().offsetDateTime();

OffsetDateTime birthday= OffsetDateTime.of(2009, MonthOfYear.NOVEMBER, 24,19,20,15,ZoneOffset.hours(-3));

System.out.println(today); //2009-11-24T19:20:15-03:00


ZonedDateTime is similar to OffSetDateTime, incorporating the ID of an area, such as America/New_York. This information is important as the offset from UTC may vary throughout the year according to the region (during daylight saving time, for example). When capturing these variations is important for business, a ZonedDateTime should be used.

TimeZone timeZone = TimeZone.of("Europe/Paris");
ZonedDateTime now= Clock.system(timeZone).zonedDateTime();
System.out.println(now); //current time in Paris time zone

Partial

Partials are representations of date/time witch are not sufficient to specify one point on a timeline. "December 25" or "12:15" are examples of partials.  Since they don’t determine a specific instant, it´s impossible to represent them as a nanosecond shift from epoch.

Some examples of partial in the API: MonthDay (representing a day in a month), Localtime (time with no date!) And LocalDate (Date without time!).

MonthDay easter= MonthDay.of(MonthOfYear.APRIL, 4);

LocalDate today= Clock.system(TimeZone.UTC).today();
Year year= today.toYear();
boolean leap= year.isLeap(); // is the current year leap?

LocalDateTime birthday= LocalDateTime.of(1983, MonthOfYear.JUNE, 3, 12, 00);

System.out.println(birthday);

LocalDateTime oneMonthAfter= birthday.plusMonths(1);

System.out.println(oneMonthAfter);

System.out.println(birthday.isBefore(oneMonthAfter)); //true 


Durations

Duration represents a certain amount of time with nanosecond precision. Very similar to the concept of Period, differs from it because it represents a certain amount of instants. In the API, the main class that represents duration is Duration.

long seconds= 60L;

Duration duration = Duration.seconds(seconds); // creates a one minute duration  

Instant instant1 = Clock.system(TimeZone.UTC).instant(); //current instant

Instant instant2 = instant1.plus(duration); //new instant crated adding a duration to another instant


Duration duration2 = Duration.durationBetween(instant1, instant2); // duration created from 2 instants

boolean equals = duration.equals(duration2);//true

System.out.println(equals);

Periods

As durations, periods represent a certain amount of time. Periods are represented, however, through a number of fields (year, month, time). In the API, periods are represented mainly by the class Period.

Period thePeriod = Period.years(8); // creates a eight years period 

LocalDate data = Clock.system(TimeZone.UTC).today();  

LocalDate eightYearsFromNow=  data.plus(thePeriod); //Adds the period to the current date.

System.out.println(eightYearsFromNow);




Customizing Behavior


As mentioned early, the JSR-310 offers some extension points, so that you can customize its behavior and implement some functionality in a more easy and straightforward way. Some of these extension points are:
  • Adjusters: Used to "adjust" dates, returning another date with a certain desired characteristic (a specific day or time, for example). The API provides some built-in Adjusters, like the one used to adjust a date to the last day of the month, for example.
  • Resolvers: Indicate how to handle an invalid date (if any operation resolve to Feb. 29 in a not leap year, for example). In this case the API also has default implementations, the most common being the one that resolves to the next valid date.
  • Matchers: Perform Boolean queries and dates and times, to know if the date has a specific characteristic (one day or time specific, for example). As in other cases, standards implementations are provided, to determine, for example, if the date belongs to a given year.

Conclusion


This post was about the main features of JSR 310, the new Java API for date and time that might be delivered together with the 7th version of the platform’s standard edition. This API provides significant improvements over the current API, as it was observed throughout the post.

References


http://wiki.java.net/bin/view/Projects/DateTimeEDR1 - JSR-310 Home at jana.net. Here you can find reference, user guide, java docs a reference implementation. Remember thught that the specificaion is still at development!


Revista Java Magazine yearVII 69 edition - Excellent article on the JSR-310.

The Law of the Leaky Abstraction - English Version

Some time ago, looking for interesting content on the Internet, I came across the excellent article "The law of the leaky abstraction." I liked it so much that I decided to make of it subject of the first post in the Java.lang.Blog.

I recommend everyone to read the article, but briefly, it calls attention to the fact that the abstractions we create in the computer world, whose goal is usually encapsulate determined complexity, end up leaving, under some circumstances, this complexity 'leak' ie, we end up having to deal with the complexity anyway.

Thus, the author proposes the law of the leaky abstraction, set out as follows:

All non-trivial abstractions, to some degree, are leaky.

I will not go into the many abstractions we use in the computing environment. In fact, the article does that very well (Do not miss it!). I would, however, invite readers to reflect on the JEE platform’s abstractions. Are they also victims of the law of leaky abstraction?

I think so. And to illustrate, I’ll cite two examples in the JEE specification key technologies: JSF and EJB. Also, I'm sure the reader will be able to identify other leaks in the JEE platform.

Leaks and Java Server Faces (JSF)

Like most web frameworks, JSF tries to disregard the "details" pertinent to the development of such applications, such as form submission and type conversion. The framework would have us believe, for example, that you can simply associate a method or property on a managed bean (server-side) at the click of a button or value of an input interface (client side).

Although laudable, this abstraction is subject to leakage. What happens when the property in the managed bean is not a String? Some conversion is necessary. And what if this conversion fails for some reason? If the user decides to type "fg%# 4" in an input field connected to an Integer in the managed bean property? Unless the developer has instructed the framework how to notify this type of failure, the user will remain clicking on the submit button and the same page will remain being re-rendered as no method will be called on the server side at all. Realize the leak?

The developer must now infiltrate the complex JSF life cycle and understand, in this potentially new context, how the framework handles conversions and how to handle possible failures.

Leaks and Enterprise Java Beans (EJB)

Despite having gone out of vogue in recent times, one of the central issues of EJB technology is support for distributed systems. Even when running on a remote machine, EJB clients are able to call these components as if they were local. The complexity of the remote method call (RMI) is therefore abstracted by this technology.

This abstraction, however, is also subject to leakage - and in a very subtle way: parameters to methods calls on a remote EJB must be serializable. That's because these objects must travel through the network, being rebuilt on the remote machine that trully houses the EJB component. Thus, the fact that the EJB component is remote becomes apparent as the parameters to its methods are required to be serializable, featuring the leak.

Remember that this leak was more visible in the earliest versions of the specification, when an EJB client was required to deal with checked exceptions related to remote calls (RemoteException and subclasses). This aspect has been improved from version 3.0, replacing the checked exceptions with unchecked equivalents.
Consequences

Some consequences of the law of the leaky abstraction:

  1. Abstractions do not help us much as we imagine. In an environment that so constantly refers to this feature, this is something important to keep in mind.
  2. Paradoxically, the more layers of abstraction are created to simplify the development, the more difficult becomes the task of becoming a proficient developer. This is perhaps the most intriguing result. Will the efforts to simplify the development on the Java platform would be having the opposite effect than expected?
  3. Be wary of tools that promise, as in magically, simplified development and multiply the productivity of the team (code generators, someone?). The abstractions in which these tools are based could leak and when that happens, often the cost is quite high.