Sunday, October 25, 2015

Testing Asynchronous JavaFX Logic

How can the interplay of asynchronous processed calculations (e. g. with javafx.concurrent.Service or java.util.concurrent.CompletableFuture) with frontend logic be tested? Problems of an existing approach, possible solutions as well as advantages and disadvantages are discussed in this post.

My current passion is programming of JavaFX applications. A very common problem, not only when developing with JavaFX, is the implementation and testing of asynchronous functionality.

Developing and testing components can be quite straightforward (following a frontend specific pattern like MVVM) as long as execution is synchronous. A bit more complicated is testing classes that have dependencies on other classes which need to be processed asynchronous to not block the execution. Typically, UI programming provides examples for that see the figure. 


Frontend logic (green box) implements certain use cases that can be triggered from different roles (e. g. users) or involves those. Parts of the frontend logic of some use cases rely on a backend service (red box). Often frontend execution is bound to a UI thread (a single thread) - also in case of JavaFX. If it is blocked by long-lasting operations, the application’s UI freezes. Therefore all blocking operations, as for instance calls of backend services, should be executed in a separate thread. It’s not seldom that service interfaces work synchronously (blocking).
For the frontend logic to be tested we consider different aspects:
  1. First a frontend component should be tested at the level of the unit, so we can ensure the part of the use case the component is responsible for is implemented correctly. To exclude further sources of errors and to test only the unit’s logic all environment elements (dependencies) need to be mocked. For the unit test level the way of execution, i. e. asynchronous execution, doesn’t matter. Rather, is the focus on the expected reaction to the results of the backend service. 
  2. Beyond that the aspect of proper integration of the unit with its environment and the correct behaviour of asynchronous execution needs to be ensured. That is, the process flow of the fronted has to integrate with the asynchronous called backend service correctly. 
For latter we can do manual tests when using the application or do an automated UI test with TestFX or some other UI test framework. But under the assumption of Test Driven Development, I first want to test my use cases in unit tests. In case we could influence the API of the backend service, it would be nice to make it asynchronous. Nevertheless, in this post we consider the backend service and its synchronous API as given. For running the unit tests we need a synchronous call to long-lasting operations of the unit’s dependencies (backend service).

Starting Point

At the beginning I mentioned that there are different approaches to implement asynchronous execution. In the context of JavaFX the closest idea is to use javafx.concurrent.Service. javafx.concurrent.Service and also javafx.concurrent.Task implement the Worker-Interface which brings a lot of convenience for communicating the state of the execution between UI and background thread.

A colleague of mine gave a very interesting approach to that problem on his blog. In particular with testing Services there is the problem, that his solution seems to work only for a single call of such a service. The reason seems to be a suspicious thread check in the implementation of Service which is also named in the Javadoc at the top of the class, but not justified or explained:

void checkThread() {
    if (startedOnce && !isFxApplicationThread()) {
       throw new IllegalStateException("Service must only be used from the FX Application Thread");
    }
}

This is the reason why this works for simple cases. That is, when you only have to call a service once in a test case. However, when use cases need to be tested that come with state multiple service calls can be necessary to create or keep that state. At that point it became clear that this thread check logic is responsible for failing the tests a service is involved. The solution pattern of my colleague doesn't work for such cases.

My Use Case

To get the discussion a little bit more concrete, a class ClassToTest is given in the following code listing describing a use case (anyUseCase). For example, ClassToTest could be a ViewModel class (MVVM) or a Controller class (MVC) - according to the pattern.

public class ClassToTest {
    private Service<string> service = new Service() {
        @Override
        protected Task createTask() {
            return new Task() {
                @Override
                protected String call() throws Exception {
                    return new SomeService().longLastingOperation();
                }
            };
        }
    };

    public void anyUseCase(StringProperty resultStringProperty, IntegerProperty progressProperty) {

        progressProperty.setValue(-1);
        service.setOnSucceeded(e -> {
            resultStringProperty.setValue(service.getValue());
            progressProperty.setValue(1);
        });
        service.setOnFailed(e -> {
            resultStringProperty.setValue("An error occurred: no result");
            progressProperty.setValue(1);
        });
        service.restart(); // use restart when it was started before
    }
}

It uses a Service to execute the longLastingOperation asynchronous. So the UI thread runs on without any blocking. The long-lasting operation is started by the call method of a Task which in turn is created by Service.

Service is used for processes that need to be executed asynchronous repeatedly. For that, the  Service uses a single Task instance to execute a process asynchronous once. That is, Service can be reused, Task needs to be recreated for a new execution.

Optionally, callbacks can be set via setOnSucceeded and setOnFailed to deal with the results of the Service’s execution. When the execution of the long-lasting operation succeeds, the result shall be used for the a new value of the resultStringProperty. This property is bound to a label in the UI, so the result is shown to the user. Otherwise, in case of exception, the error shall be signaled to the user by setting an error message to the same property.

The problematic test

Here the JfxRunner is used as the test runner which provides the test with an JavaFX Application Thread (the UI thread). Looking at the following test shows that multiple calls to the used service causes errors in the test execution due to the checkThread method in the Service class.

// Using the solution pattern given by http://blog.buildpath.de/how-to-test-javafx-services/
@RunWith(JfxRunner.class)
public class ClassToTestTest {

    @Test
    public void testAnyBusinessCaseCallingTwice() throws ExecutionException, InterruptedException {
        StringProperty resultProperty = new SimpleStringProperty();
        IntegerProperty progressProperty = new SimpleIntegerProperty(0);

        // first call succeeds
        CompletableFuture longLastingOperationFuture1 = newFuture(progressProperty);
        cut.execLongLastingOperation(resultProperty, progressProperty);
        longLastingOperationFuture1.get();

        assertEquals("An expensive result", resultProperty.get());
        assertEquals(1, progressProperty.get());

        // second call fails as because of {@link Service#checkThread}
        CompletableFuture longLastingOperationFuture2 = newFuture(progressProperty);
        cut.execLongLastingOperation(resultProperty, progressProperty);
        longLastingOperationFuture2.get();

        assertEquals("An expensive result", resultProperty.get());
        assertEquals(1, progressProperty.get());
    }
    private CompletableFuture newFuture(IntegerProperty progressProperty) {
        CompletableFuture completableFuture = new CompletableFuture();
        progressProperty.addListener((b, o, n) -> {
            if (n.intValue() == 1) {
                completableFuture.complete(null);
            }
        });
        return completableFuture;
    }
}

The first call of the service passes without problems. But the second one fails.

First solution idea

If a class needs to be unit-tested it is necessary to mock its dependencies. A “simple” way to achieve this without a framework is to extend the dependency class (create a sub-class) and overwrite methods - according to the behavior expected by the test.

First of all, the idea was to use only the class javafx.concurrent.Task for asynchronous execution, so there would be no problem to test the behavior. We would simply sub-class Task and overwrite the call method whereas the trick is to change the visibility from protected to public. This gives us the ability to start Task synchronous and to stay in the current thread (unit test thread). Only for testing purposes the execution stays synchronously.
The problematic point is, that further important methods, needed for working with Tasks, are declared as final. For instance, the method setValue is final and also private. This takes us any possibility to overwrite it and to mock it.
Even, if the final-restrictions in Task would not exist, there is still the Service class simply starting Tasks asynchronous. Even, if the strategy overwriting the Service had worked, still there was the problem that a lot of methods needed to be overwritten. At the end the whole asynchronous logic of Service needed to be reimplemented synchronously. As this is a lot of overhead for only testing the reaction to the results of the service SomeService, we are trying to find another solution.

So the question is: How can we implement asynchronous execution of logic without resigning to test it?

Finding other solutions

To get the use cases tested, I talked to other colleagues who have experience with testing asynchronous methods. We came to the conclusion that we actually don't want to test the asynchronous execution by the Service, but the use case’s logic itself (at least in scope of unit testing).

The following solution shows an implementation that is based on the idea of calculating a value by a java.util.concurrent.Callable and then either dealing with the result of success or failure. You can see, the abstraction uses a similar semantic as Service does.

public class AsyncExecution {
    private Service service;

    public AsyncExecution onStart(Callable callable) {
        service = new Service() {
            @Override protected Task createTask() {
                return new Task() {
                    @Override protected T call() throws Exception {
                        return callable.call();
                    }
                };
            }
        };
        return this;
    }

    public AsyncExecution onSucceeded(EventHandler resultHandler) {
        service.setOnSucceeded(resultHandler);
        return this;
    }

    public AsyncExecution onFailed(EventHandler failureHandler) {
        service.setOnFailed(failureHandler);
        return this;
    }

    public void start() {
        service.restart();
    }

    public T getValue() {
        return service.getValue();
    }
}

Using that wrapper construction is easy. See the following listing where the long-lasting operation to be processed asynchronous is just passed via a Callable Lambda expression as callback to the onStart method.
When the method anyBusinessCase is called the same is done for success and failure callbacks. Then the asynchronous execution is started. The start method is implemented using Service for that purpose.

public class ClassToTest {

    private final AsyncExecution asyncExecution;

    public ClassToTest(AsyncExecution asyncExecution) {
        this.asyncExecution = asyncExecution;
        asyncExecution.onStart(() -> 
           new SomeService().longLastingOperation());
    }

    public void anyBusinessCase(StringProperty resultStringProperty, IntegerProperty progressProperty) {

        progressProperty.setValue(-1);

        asyncExecution.onSucceeded(e -> {
            resultStringProperty.setValue(asyncExecution.getValue());
            progressProperty.setValue(1);
        });
        asyncExecution.onFailed(e -> {
            resultStringProperty.setValue(
               "An error occurred: no result");
            progressProperty.setValue(1);
        });
        asyncExecution.start();
    }
}

The API is quite similar to the Service API. As all methods of the AsyncExecution are neither (packageprivate nor final, I'm able to mock these methods or the whole implementation to get the Callable executed synchronously in the test thread. The results are:
  1. the second test step where the Service is called the second times also passes - the test is green,
  2. and we do not need the JFXRunner anymore as we do not need a JavaFX application thread anymore. 
Out of the perspective to not reinvent solutions and to get familiar with code you could argue, that this approach means getting to know a new API for doing asynchronous operations. Therefore the this API is oriented on the existing one. Nevertheless, there are already similar APIs in the JDK dealing with that topic. Why don't I reuse these APIs?

Well, of course there are. For instance there is the CompletableFuture class and there is an Executor, that both can be used to influence the way of execution. Therefore we tried it in a short example. Below you can see an example implementation which also makes the tests passing green.

public class ClassToTest {

    public void anyBusinessCase(StringProperty resultStringProperty, IntegerProperty progressProperty) {

        progressProperty.setValue(-1);

        CompletableFuture.supplyAsync(() -> {
            try {
               return new SomeService().longLastingOperation();
            } catch (InterruptedException e) { throw new RuntimeException(e); }
        }).whenComplete((resultString, exception) -> Platform.runLater(() -> {
            if (exception != null)
               resultStringProperty.setValue("An error occurred: no result");
            else
               resultStringProperty.setValue(resultString);
            progressProperty.setValue(1);
        }));
    }
}

The class respectively the concept of CompletableFuture seems to be very powerful - look at the huge amount of different methods for processing computation and evaluation of results. You can chain multiple futures together to form a pipeline of different processing steps — see this blogpost for detailed examples of the potential of CompletableFuture.

A definitively negative aspect of it is exception handling. Within the different processing methods of CompletableFuture you must not throw checked exceptions. You are forced to use (unchecked) runtime exceptions to transport errors to appended processing steps.
Furthermore, the appended processing seems to be executed outside the JavaFX Application Thread. This is why you can see the Platform.runLater delegation in my example. The documentation on the part of Oracle could be a bit more comprehensive to better get to know the different possibilities and the usage of that class.
As bad testable and replaceable the classes may be, at the same time this shows the right to exist for javafx.concurrent.Service and javafx.concurrent.Task: the automatic synchronization of results (and other values) between background and UI thread.

Conclusion

As you can see, the usage of CompletableFuture (in the given environment with JavaFX Application Thread, properties and checked exceptions) isn’t really easy and only conditionally more elegant. On the opposite is the question how elegant service APIs with checked exceptions are - indeed they aren't to find rarely.
Whether to choose CompletableFuture, the JavaFX Concurrency API or something else depends on the needs of the project and own preferences. For frontend logic written in JavaFX it is obvious to choose the JavaFX Concurrency API. So much for the question which asynchronous implementations could be used.
Another aspect was to find a way to get frontend logic under test which uses asynchronous execution. When trying to find a solution for the named problem I mentioned that we could also subclass and overwrite Task and / or Service to get the execution synchronous. For latter this is quite a lot of work. Nevertheless a complete synchronous implementation of Service and Task would be nice to avoid such own workaround constructions.
Indeed, my preferred approach of wrapping the specific asynchronous execution delimits the usage of all the other features from the Worker-Interface (properties for messages, progress, etc.), in the code listing you can see the progress is set manually.
As the most of those features aren’t needed, this solution is sufficient for exactly this case and less labor-intensive. So it’s a trade-off.

To comprehend the shown example you can see the source code on Github. In the example application you will also find a small user interface that demonstrates the behavior and the consequences of the implemented threading approach. I have tried to make a commit for each step of problem occurrence and solution.

Friday, July 26, 2013

Our Way To The Final Logo Design

A while ago I wrote about how to design a successful app (to the post) whereby I referred to my own app project. I'm currently developing a recipe app for Android with my project partner Marlene Knoche (her blog). The basic concept for this app is about collecting personal recipes. Personal means that you got these recipes from other friends or your family (maybe your grandma). I personally wrote those recipes in a notebook (out of paper). typical problems with such paper books are:
  • When you use them, the paper gets dirty or even wet (from cooking), letters get blurred.
  • When the book is full you have to chose a new book or put in single sheets of paper.
  • You cant reorganize your recipes.
  • You typically document the instructions of a recipe only with words. There is no multimedia content
Maybe you know more problems, to me they are enough to build an app :-) So why build an own app, as there are a lot of apps for recipes out there? Most existing recipe apps don't meet my needs. Most apps let you capture your recipes, but you can't export or reuse them with other apps or tools. Other apps (like Evernote Food) give me that ability, but they are not providing me or any other user a fixed  data structure supporting at which contents to create for a recipe. Evernote Food especially is mixing up my recipe notes with traditional notes in the regular Evernote app, which I do not like. There are still more features that I want to realize in my own recipe app. But the most important is the export functionality. This export should be a high quality print layout. So that when you do a print export, you get a pdf file that contains a set of recipes arranged by yourself to be given to a print shop, that prints your own recipe book. This is a really great idea for a personal gift, too. So this is what I want to have.

 I already reached the end point of the logo design phase and currently I create the basic views and their design. The process of the logo design is what I want to reflect in this post.

Actually, the time to design the logo that finally is used in the recipe app was quite long and we've took a lot iterations to get clear of the base idea behind the logo design. To name it immediately at the beginning, it actually took that much time as the app name wasn't determined at all, too. This, as you will see, reflects in the variety of different design approaches.

Everything began with a spontaneous mind mapping session with my project partner. First we inspected names and design ideas of other recipe apps. The result of this overview was:
  • Most logo designs contained typical cooking symbols like cutlery, chef's hat, dishes, etc.
  • Often the logos are of a illustrative and iconic type.
  • All kinds of cooking metaphors are used to much.
Then we started brain storming and mind mapping.
This mind map indeed captures quite good the essential idea of the app. For defining a name and the logo it is necessary to have this idea in mind.
Then we noted all name ideas for the app. There came lots of good and bad ideas: Cook Stories, Food Stories, Cook Time, Media Meal, Food Print / Printfood, Augenschmauß ... these names are just some of the many ideas we had. But there was not really a great idea.
Some time later we had a nice idea:

GREATFOOD - sounds like Grapefruit, so a logo idea was born, too
I really liked the idea of the logo. But unfortunately there is a quite subtle connection to the NBC logo and there are already quite similar apps in the Google Play store. So we dropped that thought of the name and went on.
Next we just tried to create a logo and maybe we would derive of this the name. Here are only some results of all iterations we took:


The top right logo draft should correspond to the German word play "Mahlzeit", which actually means meal, but in German consists of the two parts meal ("Mahl") and time ("zeit"). As you may see we came to this idea with the kettle, the magic stick and the recipe note. To me and my project partner the graphic design of the logo looked beautiful. The colors we have chosen are fresh which correlates with the whole cooking and grocery topic. And by chance green is my favourite color.


Then we had an idea of the name for the app: "RezepTour". The problem with the logo was, when I showed it to other people (with the size of a real app logo on a device) they could not figure out clear enough what this app should be for. They said something like: "Is this a magic topper?" - the magic stick matches to that interpretation, additionally. To me it was a bit surprising that only few of them interpreted this app logo as it was intended, first.

So, next iteration!

Actually the next idea was quite spontaneous and is about the export and print feature of the app. Falling late into sleep the night before and thinking about the app - there it was: Printzept! The name sounds unique, the idea behind the name corresponds with the most important feature of the app. Like the previous name this one also is mixed out of two words: Print + Rezept (German: recipe). The logo design was done immediately next morning. I drew the name and some styled letters of it to paper.


My project partner opened the vector graphic program, looked at some free fonts and just created the logo that until now is our very final version ;-)


Some days ago I read a really informative and great article: http://www.adhamdannaway.com/blog/branding/a-systematic-approach-to-logo-design

According to this article I would classify this logo as a typographic logo. This actually distinguishes very much from existing recipe app logos. As mentioned above, most logo designs are of an illustrative or iconic type. The simplicity comes from the flat design and the reduced color selection. Knowing the name "Printzept" it is still readable or recognizable when the logo is shown in app icon size.

Unique & simple - I love it!

Thursday, April 4, 2013

App Design

In the recent time I thought a lot about app development and especially about the aspects of design and functionality. I asked myself: "How can I create an app that really impresses the user by its appearance and brings value to the user?". When you talk about getting value of the functionality of an app, you have to name the concrete topic or the issue what the app is about. OK - I want to create a recipe app for the Android platform. Only a few words to the intention that I have. Actually there is no recipe app that feels like an equal replacement for a physical cook book. Of course, there a lot of apps that simply let you create recipes or fetch them from the the web. But none of those lets you do more things (publish / share / high quality print / discuss) with your recipes nor there is any app that does it in an attractive way, too. If you find an app with some of the desired functionality it either costs money or it is ugly or slow (like the german Chefkoch.de-app). The next thing is, I want to collect my own recipes or recipes that I got from family or friends. So it is a very personal thing, just like a diary or a scrap book. The last point is that I want to have the option to export and share recipes. Maybe I want to print a physical recipe book of a collection of special recipes to give it as a present to a dear friend. So this print layout has to be in a high quality, just like the layout of a professional cook book that you can buy in a book store.

So far, this is the intention of the app. Now as I described the problem, I can talk about the issues that I discovered at the design of functionality and the user interface. Maybe you have heard the term of featuritis? First of all let's have a look at the definition at wikipedia (http://en.wikiquote.org/wiki/Featuritis). Featuritis is a phenomenon that you can discover quite often if you grab an arbitrary app from the Play Store. Often I can't figure out what are the main functions of an app. This is partially caused by a bad or overloaded view design and partially caused by a missing focus on the main intention of the app.
I also have had this problem when I developed my first apps. How can you face this problem?
First, one has to have a vision of the base idea of the app. Can you describe the functionality and the value of it in only a few sentences to other people? Are there other apps out there in the Play Store (or other app stores) that do the same or similar like your app should do? If yes, how can you distinguish yours from the other? Is there a use case or a reason why one should or would use your app instead another one? Serves the app a value to a user at all?
If you can answer these questions clearly and positively (this is what I tried to do in a short way above), you may begin designing and developing your app. Next you need a simple, catchy and expressive name and a logo. The logo and the name brings more motivation to me and lets me identify myself with the app to be developed. This is definitevly no easy step and very hard to describe rules for. So I will go on. ;-)

Maybe you have heard of the hierarchy of needs by Maslow yet? Actually this hierarchy (or pyramid) is related to the needs of a human being. In this hierachy physiological needs like breathing, food, sleep etc. form the base of the pyramid. Only if those needs are met, there come up further needs (security needs) like a secure home, employment and so on. There are still more steps that come after these two. As you may expect there is an adopted concept of this hierachy of needs for the domain of (app) design. You will see it in the following figure. I found this in a Google IO talk with the topic "Android Design For Success" (https://www.youtube.com/watch?v=2NL_83EG0no).
You also may have noticed that I already talked about the first step (utility and purpose) quite at the beginning. So, by going the second step, the real development can begin. Now you should start to think of the structure of your app and how the user will navigate through your screens later. To consider this step technical you should think of which fragments are needed, to present the information in the related views. You have to arrange the views and define which information should be presented in what kind of view. This brings us to the question: "How can you provide a consistent structure and layout?".  Each view transition should be logical and understandable to the user. Fulfill the expectations of a person, that knows how Android-4-apps behave!
When you have come so far, you can take the next step. Now you can bring a simple branding into your app. Provide it with your logo and some simple design resources, like icons. Furthermore think of the huge variety of devices, their formats and different versions (API level). You should ask yourself now: "What do I want to support and what kind of devices should get a special layout to accommodate their special abilities and properties?". Maybe you will have to add support libraries or frameworks like ActionBarSherlock. To integrate this libraries into your project you will only have to change some imports. There are also some little API differences that you will have to regard. Applying these changes should not be too complicated, but it would also be recommendable to do these things in the project setup.

If you have applied these rules to your project, your app should result in a consistently and useful designed app. Users should understand the idea of your app and know how to use its features. Also the design should be alligned to the Android platform guidelines. Especially if there are already some apps that seem to be equal to yours or claim to be for the same purpose, you will have to differentiate your app from all the others. Make the user remembering your app and try to bring enthusiasm to the user. To make the user remember your app, you will have to make your app unique. This is done in the fourth step. The key is common identity (CI)! the most popular companies have a special theme or design rules applied to color, font and forms in all products that represent the company. A simple example is Facebook: So simple. A single small, white "f" with a blue backgound. And of course the like-button all over the internet. Everyone knows and recognizes Facebook at these simply and clearly designed elements. This is what you have to find for your app or for your whole project. This should burn your appearance into the users brain.

The last point is in my opinion not the most important one for success, as you already fit into the design concept of the platform by distinguishing yourself from others by your CI at the same time. But I would call it to cause the wow-effect. I think Apple with its iPhones and the whole app platform did it as the first company. There are many apps that let the user feel the elegance of the gadget merged with the design and the functionality of an app. The app is unified with the gadged and the user is just impressed by a special app.  The positive feelings for the device are transferred to the app and vice versa. This is a very emotional moment which is caused by some simple methods. Let your app feel smooth. Add custom and organic transitions or other eye candy effects. Obviously such eye candy is not neccessary to make an app useful and therefore popular. But it serves the emotional and subjective character of the human mind and so puts rational aspects in another perspective. Don't get me wrong at this point. With eye candy I do not mean as much effects as possible. In contrast the trend to more simplicity and flat design shows that the simplest design might be usable and nice without having many effects or so called eye candy. It is about a natural look and feel of the user interface. This might be reached by using some animations, transitions or other effects, but it is no dogma. As it is with many other things, too: It is about the right balance! This may be the nice topping of the design of your app. Then your app will hopefully successful.

Saturday, February 23, 2013

Das OSIT-Modell

Beim Lesen des Web Magazins habe ich einen wirklich interessanten Artikel über das UI-Design gelesen. Beflügelt von den darin erläuterten Konzepten möchte ich ein wenig darüber schreiben bzw. überlegen wie man diese Konzepte auf die Entwicklung von (Mobile) UIs übertragen kann oder wo diese schon Anwendung finden.

In Ausgabe 1.2013 des Web Magazins stellt Prof. Wolfgang Henseler das Konzept NUI (Natural User Interface)  und als ein weiteres hilfreiches Modell für die Konzeption von UIs das OSIT-Modell vor.  Das folgende Zitat fasst recht kurz zusammen, was NUI ist und welche Intention dahinter steht:

"Von visueller Gestaltung zur Gestaltung von Verhalten. Dieser erste Einblick verdeutlicht sehr gut, wohin sich, neben den Geschäftsmodellen, das Design verändern wird. Nicht mehr die Gestaltung des Aussehens - Look - ist von entscheidender Bedeutung, sondern die Gestaltung des Verhaltens - Feel - rückt in den Mittelpunkt designerischen Denkens Spielte also bei den grafischen Benutzungsoberflächen die Grafik, das Visuelle, eine zentrale Rolle bei der Gestaltung, so verlagert sich dies bei Natural User Interfaces in Richtung Verhalten. Das bedeutet nicht, dass es in Zukunft keine visuellen Interaktionselemente mehr geben wird, nur ist eben deren Verhalten für den effektiven und effizienten Umgang mit der Software wichtiger als ihr Aussehen. ..."

Es geht also darum, das ein User Interface den Nutzer in seinen Arbeitsprozessen unterstützen soll. Es ist nur ein Vermittler in der Mensch-Maschine-Interaktion. Ein NUI fügt sich in das Verhalten des Benutzers ein und dessen Elemente halten sich dezent im Hintergrund. Erst, wenn der Nutzer ein Element für eine Aktion benötigt, erscheint es. Dafür ist jedoch das Verhalten des Nutzers von Bedeutung. Anwendungs- bzw. UI-Entwickler müssen dieses Verhalten analysieren, kennen lernen und dem entsprechend die Ui gestalten. Als ein Modell für das Beschreiben des menschlichen Verhaltens bzw. des Handels kann das OSIT-Modell herangezogen werden. OSIT ist ein Akronym aus den folgend aufgelistenten und erläuterten Worten:
  • Orientieren: Der Mensch versucht eine Übersicht über bestehende Objekte zu erlangen. Er will Kontrolle über die Situation erlangen. Er orientiert sich.
  • Selektieren: Der Mensch trifft Entscheidungen. Er wählt ein Objekt aus.
  • Informieren: Der Mensch will mehr Details / Informationen zu dem ausgewählten Objekt. Er betrachtet das Objekt genauer, oder näher.
  • Transagieren: Der Mensch macht mit dem Objekt etwas (Transaktion).
Das OSIT-Modell ist aus der Physiologie des Menschen abgeleitet und trifft deshalb auf alle Menschen gleichermaßen zu. Dieses gilt es bei der Verhaltensanalyse eines Anwenders oder einer Anwendergruppe zu nutzen. Eine resultierende Benutzerschnittstelle sollte diese menschlichen Verhaltensweisen berücksichtigen und unterstützen. Für die App-Entwicklung könnte die Anwendung des Modells auf die UI folgende Auswirkung haben.

Mobile Apps sind Programme und typisch für Programme ist, dass Nutzer häufig über diese mit Daten arbeiten. Neben den Daten als Objekte kann man auch die Funktionen einer App als Objekte betrachten. Diese gilt es dem Nutzer übersichtlich zu präsentieren. Der Nutzer muss einen Überblick über alle Daten oder Funktionen erhalten. Gibt es beispielsweise viele Daten, braucht der Anwender vielleicht eine Filterfunktion, die die Menge der Daten reduziert. Der Anwender muss eine Auswahl treffen können. Für Funktionen mag dies bedeuten, dass nur die Funktionen angezeigt, werden, die auch wirklich sinnvoll erscheinen. Die Funktionen werden kontextsensitiv angezeigt.
Der Nutzer trifft eine Auswahl unter seinen Optionen und wählt etwas aus. Dabei sollte dieser so gut wie möglich unterstützt werden. Im Bereich der Mobilen Systeme, wie Android oder iOS kann man schon häufig ein intelligentes Verhalten der UI feststellen. Diese brachten, denke ich, erst das Umdenken in Sachen UI-Design richtig in Gange.

Aktuell beschäftige ich mich mit der Entwicklung einer App, bei der ich solche hilfreiches Wissen gern anwenden möchte. Ich hoffe ich werde in diese Richtung gehend noch weitere interessante Ansätze, Modelle oder Konzepte entdecken.

Wednesday, September 19, 2012

Permissions of Linux file system and Samba

After my new solid state disk lost my linux server installation I had to find a solution to go on running my server on any kind disk or device. My seldom used USB stick now bridges the time span until my SSD returns from the producer. In this context I had to setup again the Samba share of my home server which I exlpaind in the last post. Now I got some new experiences with permissions and Samba which I want to exlpain now.


Actually my files are stored in ext4 Linux file system. Typically Linux or Unix file systems only have the model of only one owner, one group and the rest of the world (others).
As I want to share some of my files in my private network with other client systems, e.g. Windows, I'm using Samba, which is (not only) a windows conform file server. When Windows (or Samba) considers permissions of files, it does it with a much more complex concept. Finally the so called effective permissions are those permissions of a file being analyzed when a user wants to access it. The effective permissions are made up of the share permissions and NTFS permissions.
I don't want to explain how these permission concepts work (you can read this at http://www.mcmcse.com/microsoft/guides/ntfs_and_share_permissions.shtml). Instead I want to come to another Linux topic dealing with these different permission concepts of the different operating systems. As you maybe know NTFS permissions allow an administrator to adjust permissions on files very detailed. To overcome the simplicity of the user-group-others Linux file permissions model there are File Access Controll Lists (ACLs). In Combination with a special configuration of a Samba share you can configure permissions as much detailed as you can do it with Windows. But step by step.

First you have to do two things to work with ACLs:
  • Install ACL tooling (sudo ap-get install acl)
  • Mount the partition that contains the directory to be configured with ACLs with a special option. In order to do this open the file /etc/fstab (maybe you do a backup before editing) and add "acl" as another mounting option spereated by a comma to the entry for the corresponding partition. In my case the modified line lokks as follows:
UUID=<The uuid for the partition>   /media/data   ext4   defaults,acl   0   2

Now the task is again to create a new shared directory where different users can create, modify and delete files and directories. To do so first the directory is created.

$sudo mkdir /media/data/share

For the following steps it is expected to have a user_x (or any other ;-) ) and a group (maybe the group users) where all users belong to that shall be allowed to work with the shares. Now the owner and group of the directory is changed as follows.

$sudo chown -R user_x:users /media/data/share

To let all (by different user that are members of the group users) created files have the group set before the SetGroupID (SGID) bit is set with the following command.

$sudo chmod -R g+s /media/data/share

When a user_x creates a subdirectory (e.g. /media/data/share/music) in the share directory, you will notice that the directory would have the permissions rwxr-xr-x, if you only configure permissions with chmod like this:

$sudo chmod -R g+rwx /media/data/share

If you have come to this point you will maybe understand the difference between NTFS permissions and Linux file permissions. When you create a new subdirectory with NTFS the permissions of the parent directory are passed to the new created directory by default. If you do this with a Linux file system like ext4 the so called user mask (umask) is used to determine the permissions to pass to the new created directory. By default the umask is set to 022. This means groups and others will be denied write permissions. Here the ACLs help to mediate between the different concepts when you share data with different systems.

The ACL tools give you options to query and change ACLs. The following paragraph shows you how you can get the actual ACL for the music directory, that you maybe created directory.

$getfacl /media/data/share/music
# file: media/data/share/music
# owner: user_x
# group: users
# flags: -s-
user::rwx
group::r-x
other::r-x

You see that user_x is the owner and only he has the option to read, write and execute files. Members of the same group only are allowed to read and execute files. This means the user user_y also belonging to the group users, won't be able to create files in that new created music directory.

To let new files and directories inherit special permissions at creation point you can set so called default permissions that will be applied to new created files and directories. You can do it with the following command:

$sudo setfacl -Rdm g::rwx /media/data/share

The result can be checked with getfacl again:

$getfacl /media/data/share
# file: media/data/share
# owner: user_x
# group: users
# flags: -s-
user::rwx
group::rwx
other::r-x
default:user::rwx
default:group::rwx
default:other::r-x

If you create now the directory /media/data/share/videos you will see that the default permissions have been applied to the regular permissions of the directory. This is the base ACL configuration to be done when you then come to Samba.

In my last post I wrote the following two lines to be added to a share declaration in the file /etc/samba/smb.conf to get the multi system share solved.

create mask = 0775
directory mask = 0775

But with the ACLs as a tool for permission configuration and another option in Samba it is much better to configure permissions. Actually it is not really elegant to once setup permissions via linux tools and then do the same work again in a samba configuration file. It would be more comfortable when we could use our ACL configuration again. Fortunately I discovered the following two Samba settings to use the ACLs:

inherit permissions = yes
inherit acls = yes

This is the replacement for the above mentioned two lines. With setfacl you could also configure more special permissions like you would do it with NTFS. Here only a few examples:

$sudo setfacl -Rm u:bob:rwx /media/data/share

The user bob gets read, write and execute permissions, although he maybe isn't a member of the group users.

$sudo setfacl -Rm g:guests:r-x /media/data/share

The group guests gets only read and execute permissions. Assumed that others would haven't any permissions this makes sense.

I hope I could explain the problem and the solution for, of sharing data over different (file/operating) systems in a understandable way. If anyone discovers a mistake please let me know of it.

Monday, August 27, 2012

Home Server Setup - The Second

Last year i bought a sweet small cube that should be my new home server, running with linux, to do all the stuff I want to do at home. This post will be about the second setup of this server. The first installation was my first "Linux server experience". As I was a little bit frightened to fail on the command line I installed a desktop edition of ubuntu. A friend who introduced me into the Linux world always said: "A server with a GUI actually isn't a real server!". Of course! But I felt good with that and now as I got some experience with Linux on my server I am sure that I will make the whole "command line server thing" - so I'm using the Ubuntu Server edition.

The original reason for this post is the setup of the server relating to sharing media files with serveral users in the home network. As I had to discover there were still some problems on which I had to spend much time to solve them. So to give it a name: I wan't to tell about Samba and further file administration problems.

Before I can start with the linux specific stuff, I will explain the environment and the conditions in my home network. There are actually only two users: me and another one. I have, as one can imagine, a Linux machine and he (the other one) has a Windows machine. Although it doesn't effect the problem directly I have to mention that the other user uses a very well known smartphone of Apple and therefore also iTunes. But this is another problem. The server runs with Linux, too. Both client machines shall have access to shared directories on the server, for instance for:
  • music
  • videos
  • pictures
  • documents
  • backups.

That is to say, we both use the same media directories with different programmes from different platforms.

Now to the server side. The media data to share is stored on a RAID 1 array mounted at /media/data owned by the root user. The first steps to take are about creating the directories you wan't to share.

sudo mkdir /media/data/music
sudo mkdir /media/data/videos
... (also for the other directories)

The next step is to set up the users and groups that will be allowed to access shared media data. In this setup I will create the users user1 and user2, and the group share_media. Every user in this group shall get access to the data.

sudo groupadd share_media (create the group)

sudo adduser user1
sudo usermod -a -G share_media user1
... repeat the procedure for user2

At the moment the directory /media/data still is owned by the user root and the group root. To let the subdirectories be accessed by users of the created group, the directories have to be assigned the group share_media.

sudo chgrp -R share_media /media/data/*

This assigns the group to all children of /media/data. In my case the directory lost+found is also a child which should be owned by the root user. In this case you should replace * by the special sub directory name.
Now the time is right for installing Samba, a server that enables Linux to share files or directories with other Windows, MAC OS or Linux machines.

sudo apt-get install samba

For configuring Samba you have to open the configuration file /etc/samba/smb.conf in your favourite editor. I do it with vim. How vim works you can see here linuxconfig.org/Vim_Tutorial. Because the owner is root you have to prepend sudo again.

sudo vim /etc/samba/smb.conf

Typically many debian (the ancestor system of Ubuntu) configuration files consist of
  • comments marked by the sign "#"
  • sections surrounded by square brackets, example: [section name]
  • settings in the form of: key = value
Then you append your declaration for your shared directories at the end of this file. You may give some comments before that. You do this analogously for the other shared directories.

[Shared Music]
comment = A shared directory for music on the server.
path = /media/data/music
writeable = yes
browseable = yes
guest ok = no
valid users = @share_media
create mask = 0775
directory mask = 0775

Actually the last two lines were the most difficult thing costing me much time to figure out that I had to set these lines. The explanation for this comes a bit later when I talk about file permissions. Although we already have set unix passwords for our users we still must set up users and passwords for Samba. You do it like the following line shows.

sudo smbpasswd -a user1 (then type in the password for user1 again)
... repeat it for user2

Now you can restart the Samba server to get the changes applied.

sudo service smbd restart

When you try to access the shared directory from another machine in the network you should be promted to type in your user name and password. Actually without the mentioned second lines in the Samba share configuration you would only be able to read the shared directories. So now I will explain what these lines are about.

The typical umask (see en.wikipedia.org/wiki/Umask for understanding the term) is 0022 (or shorter 022). This means when directories are created the default permissions are rwxr-xr-x. So the owner (first 3 signs) is able to read, write and execute (when it is a directory the x means you can access it). Users in the same group (second 3 signs)  and other users (last 3 signs) are only allowed to read and to execute.
For the shared directory this would mean: When user1 creates a sub directory, user2 is not allowed to write in that directory (create files). This is not the way that I need it. So I had to define an other mask for Samba. The mask system used in smb.conf is another one than umask. There you still have 4 positions with numbers but each number is the sum of the 3 granted rights:
  1. read with number 4
  2. write with number 2
  3. execute / access with number 1.
So e.g. 7 means 4 + 2 + 1 (everything allowed) and 5 means 4 + 1 (read and execute). The line (0)775 means then analogous in the symbolic representation of permissions rwxrwxr-x.

Until now you have declared how Samba should handle the share and modification operations (rwx). But the shared directories still have the default permission values. These have to be set now.

sudo chmod -R g+rws /media/data/* (take care for lost+found explained above)

That's it. Now you should be able to create, modifiy and delete directories and files with different users from different systems.

Monday, January 9, 2012

Android und Maven

In einem aktuellen Projekt habe ich mit Webservices und Android zu tun. Wenn ich bisher mit Java EE zu tun hatte, habe ich Maven als Projektverwaltungstool benutzt. Nun möchte ich auch das Android-Projekt von Maven verwalten lassen. Im Netz habe ich unter folgendem Link einen extra Archetype für solche Maven-Projekte gefunden.
https://github.com/akquinet/android-archetypes/wiki/android-quickstart-archetype
Dort ist ein ganz einfaches Beispiel beschrieben, wie ein solches Maven-Projekt aufgesetzt wird. Dies sieht wie folgt aus:
 mvn archetype:generate
  -DarchetypeArtifactId=android-quickstart
  -DarchetypeGroupId=de.akquinet.android.archetypes
  -DarchetypeVersion=1.0.7
  -DgroupId=your.company
  -DartifactId=my-android-application 
Dies funktionierte ohne Probleme. Danach kopierte ich die Dateien eines bestehenden Android-Projekts in das durch Maven generierte Projekt. Die danach aufgetretenen Fallstricke möchte ich in diesem Post kurz erklären.
  1. Das ist zwar ein Standardfehler, bei meinen Android Projekten, aber er trat wieder auf. Wenn wieder mal Eclipse neu eingerichtet wird und dann das Android-Eclipse-Plugin für Android installiert wird, sollte man nicht vergessen den Installationspfad zum SDK zu setzen.
  2. Ebenso ist der Pfad in der Maven-Konfiguration des Android-Build-Plugins zu setzen.
  3. Das Build-Plugin fordert ebenso eine minimale Maven-Version, die ich ebenso nachinstallieren musste. Dies ist die Version 3.0.3.
  4. Im Android-Manifest sollte man die benötigte Android-API-Version (android:minSdkVersion)noch prüfen.