Showing posts with label arena. Show all posts
Showing posts with label arena. Show all posts

Wednesday, 5 November 2014

Travis, o cómo elegir un CI para tu proyecto Java open source

Recientemente me incorporé al equipo de desarrollo de Arena, nuestro framework de MVVM UI pensado para que alumnos de diversas carreras universitarias den sus primeros pasos en el desarrollo de interfases de usuario. Hicimos un sprint para empezar a familiarizarnos con las herramientas y ahí detectamos algunos problemas en la forma de trabajo, que dificultaban un poco la incorporación de nuevos desarrolladores.
Los inconvenientes principales eran:
  • Para trabajar en un proyecto (hoy Arena se compone de 7 proyectos distintos) no había otra opción que compilar todos los demás, ya que al no estar sistematizado el deploy no siempre el SNAPSHOT se correspondía con la última versión del código. Entonces perdía un poco de sentido la separación en artefactos distintos.
  • Algunas veces se pusheaba al repositorio código que rompía los tests, o incluso no compilaba. Al no tener releases estables, podía darse el caso de que un deploy del SNAPSHOT rompiera los trabajos prácticos de los alumnos de una cursada, como sucedió alguna que otra vez.
  • Los artefactos se desplegaban en un repositorio propio y no en Maven Central, lo que implicaba un paso extra de configuración a la hora de preparar el entorno de desarrollo. Trataremos este tema en el siguiente post de esta serie.
¿Cómo solucionar esto? Automatizando estas tareas repetitivas por medio de un servidor de integración continua. No es el propósito de este artículo discutir los beneficios de esta práctica (para eso puede leerse este artículo de Martin Fowler), así que vamos a pasar directamente a la solución que puse en marcha.

Eligiendo un CI para Arena

Para los ansiosos, la implementación final de lo que contaré a continuación (incluyendo el próximo post) puede verse en el repositorio de Arena en GitHub. De todos modos, recomiendo leer cada una de las decisiones que tomé para entender qué es lo que hace el CI cada vez que se sube código nuevo al repositorio.

CIs Candidatos

Además de que fuera gratuito para Open Source Software (OSS), se necesitaba que cumpliera tres características:
  1. que fuera fácil de configurar y que no necesitara hosting propio.
  2. que soportara Java de forma nativa.
  3. que tuviera algún mecanismo para subir el settings.xml, necesario para poder hacer el deploy a Sonatype.
Entonces, en ese orden, descarté estos 3 productos:
  1. Jenkins, quizás el más conocido y flexible de los que voy a mencionar, pero con el overhead de tener que hostearlo en servidor propio y configurar todos los plugins.
  2. Semaphore, que suele ser mi opción preferida, pero como todavía no soporta Java “out of the box” es necesario bajar Maven en cada build.
  3. Y por último, drone.io, donde no encontré cómo solucionar el problema del settings.xml.
Finalmente mi elección fue Travis, obviamente en su versión para OSS.
(Un comentario al margen: Travis tiene también una versión para repositorios privados y, gracias a un acuerdo con GitHub, la ofrecen de manera gratuita e ilimitada para estudiantes mediante el student developer pack.)

Configurando Travis

La configuración de Travis está basada en el principio de convention over configuration. Para empezar a compilar y correr nuestros tests, basta crear un archivo llamado .travis.yml e indicar en su interior en qué lenguaje está realizado nuestro proyecto, en nuestro caso Java. El primer archivo de configuración se veía así:
language: java
¿En serio? ¿ya está? No del todo, pero ya estamos en condiciones de probar que funciona avisándole a Travis que monitoree el proyecto (esto se hace desde tu perfil) y luego haciendo un git push de algún cambio (aunque una mejor idea sería crear una branch de prueba y hacer un pull request).
Por defecto, Travis empezará a monitorear el repositorio y disparará un build por cada commit que se suba a cualquiera de sus branches, incluyendo pull requests. Una vez concluido dicho build, se encargará de notificar a GitHub el resultado, quien a su vez nos lo mostrará a nosotros como se ve en la siguiente imagen:
Pull requests validados por Travis
Con esa simple línea de configuración que le dimos, lo que se ejecuta es el default para Java, que consta de dos pasos:
  1. mvn install -DskipTests=true, baja todas las dependencias y compila el proyecto. ¿Y para qué le pone ese flag si también queremos que corra los tests? Cuando algo anda mal, Travis diferencia entre un build errored y uno failed, donde el primer estado está asociado con un error en la instalación (no compila, no se encontró alguna dependencia) y el segundo con alguna validación que se ejecuta (normalmente un test fallido). Entonces si llegara a fallar la instalación, ni siquiera se corren los tests y sabemos con certeza que el resultado es errored
  2. mvn test (no necesita explicación)
Hasta acá llega el primer post de esta duología. En el siguiente post explicaré los pasos necesarios para publicar la aplicación en el Maven Central Repository, utilizando Sonatype OSS como intermediario.
¡No dejen de compartir sus proyectos, ideas o experiencias en los comentarios!

Tuesday, 7 October 2014

Latest Arena Sprint

The last Saturday, we have had another Sprint of the Arena Project. 

Arena is one of the flagship projects of the Uqbar Foundation. 

Arena is an MVVM UI framework that strongly encourages the separation between model and ui classes. Although based on automatic bidirectional bindings and small single-responsability reusable controllers. Through this it clearly shape the core concepts of object design applied to UI-development.

It also implements a transparent AOP-based mechanism for object-level transactions and observability (object properties). This makes extremely easy the developer tasks in order to bind UI components with domain, by reducing repeatable domain code such as triggering events or handling transactions.

Arena is being used now since 2010 in several Argentinean Public Universities in order to teach the core concepts of object-oriented user interfaces.

The sprint was a really successful, 11 developers gathered to work in the project. 

The main objective of the Sprint was the integration of new developers to the project. Everybody getting a working development environment and through the use of pair programming everybody started improving Arena. 

The results of the sprint are amazing:


  • A new Continuous Integration effort has been started. The idea is to have an automatically integrated process to release and publish the changes. Every time a developer submit a change the process is fully automatic.
  • The whole project was migrated to Scala 2.11.
  • The documentation has been improved, with all the things the main developer show to everybody.
  • The site of Arena has been improved and fully integrated with the Maven building process.
  • We have started the process to integrate all the repositories and the migration to Git.
  • Also the process to get a copy of Arena into the main central repositories of Maven has been started.
  • Also a number of issues has been resolved and improvements added:
    • Now you can bind tooltips to the controls
    • The window can have a initial size.
    • The labels resize when the content is longer than previously
    • The tables can have a minimal number of rows to show.
    • You can know bind the visible property of panels.
    • The check boxes can be read only.
Even though the main idea was to integrate new developers to the project, we could achieve lots of issues and improvements.

Some nice pictures of the people working:








Saturday, 21 September 2013

Type-safe bindings (reflection) for Arena

Arena

Arena is UI framework strongly based on a pure MVC pattern through bindings and the ApplicationModel idea.

The UI elements are connected to the model through bindings, which are in charge of propagating changes between the two parties. If the model changes, then it will update the ui (view), and of course if the view changes because of user interaction (like changing a textbox value) then it will also change the model.
This simple idea reduces a lot of UI code, and introduces a new way for developing UI's.
Plus the fact that Arena makes your model object observables, transparently by means of AOP.

Sample Distance Converter Application


Here's a sample really small app whose functionality is to convert miles to kilometers.


Here's the model (in xtend language):

@Observable
class DistanceConverter {
    @Property Double miles
    @Property Double kilometers
   
    def convert() {
        kilometers = miles * 1.60934
    }
}


And here's the View, in terms of control objects.

class DistanceConverterWindow extends MainWindow<DistanceConverter> {
   
   
new() { super(new DistanceConverter) }

   
override createContents(Panel mainPanel) {
        title = "Miles To Kilometer Converter"

        mainPanel.layout = new VerticalLayout       
       
new Label(mainPanel).text = "Input in miles"
       
new TextBox(mainPanel)

       
new Button(mainPanel) => [
            caption = "Convert"
        ]

       
new Label(mainPanel) => [
             background = Color.ORANGE
        ]
       
new Label(mainPanel).text = " km"
    }
   

}


As you are probably thinking or maybe wondering, this is not the actually functional View implementation.
It is not actually connected to the model. If we start this app it will indeed show pretty much as the one on the screenshot but clicking on the button won't do anything. Changing the textbox neither. And we'll never actually see any converted kilometers.

That's because we are missing the Bindings. The stuff that glues together view + model.

Bindings


As you can see the UI is a direct view of the domain. Whenever the user changes the value of the textbox it will modify the "miles" property. When he presses the button it will call the "convert" method which doesn't receive any parameter (the converter already knows the input miles), and also doesn't return anything (because the converter also "remembers" the converted km value, it's one of its responsabilities).

All this wiring between the UI and the model is done through bindings.
Here's a sample  drawing:


Now lets change the UI code in order to express this bindings.

The textbox value will be sync'd with the "millas" property from the model

new TextBox(mainPanel) => [
            bindValueToProperty("miles")
        ]


The background colored label is also bound to the "kilometers" property. This time as the label is a "read-only" ui control it won't ever change the value from the model, it will just display it.

        new Label(mainPanel) => [
            background = Color.ORANGE
            bindValueToProperty("kilometers")
        ]


And at last the button's on click should execute the model's "convert" method.

        new Button(mainPanel) => [
            caption = "Convert"
            onClick [ |
this.modelObject.convert ]
        ]


Here we sue the power of xtend blocks/closures :)

Bindings, Reflection & Strings

Probably you are familiar with this kind of code. Frameworks are generic pieces of software, that provide some sort of functionality or lifecycle. But they don't do anything along. You "use" them. Or actually they "use" your code/objects. But anyway, eventually you need to instruct them in order to use your objects.
Because they know how to handle any object, but none in particular.

So they use metaprogramming techniques, and specifically Reflection API's in order to manipulate your objects.
Some examples of this are hibernate where you instruct it by means of mappings, for example in xml, or in the form of annotations. Or spring framework's xml, etc.

In our example Arena uses reflection for the bindings, in particular for reading and modifying the model's properties.

One of the big drawbacks of reflection in java is that there's no way to refer to a property in a safe way. The only way is to use a string, whose value is the "name" of property or method.

bindValueToProperty("miles")

So, what's the problem with it ?
Well, that you are in a statically compile-time checked language, but the compiler won't be able to help you on this one.
For it the "miles" is just that, a string. So it won't check if it's actually a valid property name, or if it exists a getMiles() method in the model class.

If you are building a middle/big sized application, and all the windows, panels and controls binds themselves in this way then you'll face a maintenance complexity.
For example:
  • if you change the name of the model's property in a refactor, then the IDE won't be able to help you changing this strings. And this will blow-up in runtime.
  • if you want to lookup references to a given method or property, then again the IDE won't help you. Then you might think that a property is not used by anyone, and go ahead and delete it. Again.. booom! only at runtime. Lucky you if you catch it before your user =)
So well, this is pretty bad ! But indeed we don't want to lose reflection. It's a very powerful mechanism !

Avoiding String problems when using reflection using constants

There are some tricks to tackle this problem list having the string declared as a constant string in only one place.
For example:

class DistanceConverter {
   
public static String MILES = "miles"
   
public static String KILOMETERS = "kilometers"
   
public static String CONVERT = "convert"
    ...

And now from the UI:

        new TextBox(mainPanel) => [
            bindValueToProperty(DistanceConverter.MILES)
        ]


So now we can look up references to the constant for usages. Also if we change the name of the property we'll only have to change the string value in on place, the constant.

But this still not perfect.
There's a better way :)
But first we need to see some other idea.

What's the mocking frameworks approach

Mocking frameworks face some similar problem. By nature they need to work with our own defined classes, but they cannot be coupled to them, of course. They don't know anything about our DistanceConverter for example.
But also they don't know what to expect and assert, so you need to instruct them.

But instead of using reflection with strings or a complicated API for expressing the expected behavior they use a quite interesting idea.
For example Mockito...

What's interesting here is the line:

when(mockedList.get(0)).thenReturn("first");

We are not actually interested in executing the "mockedList.get(0)". Instead we are "instructing" mockito telling him "when some calls the "get" method with a "0" as parameter, then you need to return the "first" string).

A normal string based reflection approach would be:

whenSomeoneCalls("get").on(mockedList).with(0).thenReturn("first")

(and this is still actually a good fluent API, could be really worst).

So, in conclusion, they found a way of actually using the type information and therefore the compiler in a statical way, to instruct a framework.

So the whole idea of this post was to get here. Can we do that same thing for Arena bindings ?

Type-Safe Arena Bindings

Yes we can !
This is just a really draft proof of concept that was done just in 30 minutes, so there's still a lot of work to be done, and many things to think about.
Let's get directly to the code:

        new TextBox(mainPanel) => [
            bindValue(
this, [ miles ])
        ]


        ...

        new Label(mainPanel) => [
            background = Color.ORANGE
            bindValue(
this, [kilometers])
        ]


Compare to the previous version. This one doesn't have any string for "miles" and "kilometers".

The new "bindValue" method receives an xtend block whose first and only parameter is the window's model object (that gets bound by means of generic types).

So [ miles ] here can be read as

[ it.miles]

Or

[ converter | converter.miles ]

Or even in the longest way

[ DistanceConverter converter | converter.miles ]

So in case you didn't notice this is code. We have a line of code that calls the "miles" property, and therefore it gets checked by the compiler.

But it's actually a trick. Pretty similar to the one that Mockito uses.
This code is not actually executed to get the property. We are not writting "[ miles ]" to execute it right away, but just to "instruct" arena "miles is the property I want you to bind to".

And it works flawlessly ! :)

In case you are interested in the implementation, what the "bindValue" does is:
  • receives your block
  • it gets the actual model (the converter) and with its class, it creates a new proxy instance. Kind of a "ghost" object of the same class.
  • it then calls your block with that proxy.
  • Your code sends the message "miles" (actually getMiles()).
  • The proxy "records" all the methods you called into it.
  • So, after the block finishes up, the next thing the bindValue does is to ask the proxy "hey, what property the guy accessed  ?".
  • In this case the proxy will tell "the miles property",
  • "Ah.. ok, then we need to bind to that one.
It's not as black magic as one thinks initially looking at Mockito. And it's all there. Just enter the "when" method and explore some code !

Further work

We still need to work on this, because we will like to add this feature to Arena's new version.
There are still many things to think about, like what if the developer writes some side-effect weird or long lines of code in the block ?.
How to support nested properties ? Like [ customer.address.street.number ]
Etc.
We should also remove the first parameter "this" on the bindValue method, but that's not easy because we will lose the typing of the closure (now bound to the window's generic type, the model class).

More about Arena

If you are interested in Arena framework here are a couple of links: