7 Totsünden für Software Projekte

Das Scheitern von Projekten ist Gegenstand vieler Publikationen. Seit Jahrzehnten versucht man diesem Umstand durch verschiedenste Methodiken und Werkzeuge mehr oder minder erfolgreich beizukommen. Obwohl auf den ersten Blick die Gründe eines Misserfolges mannigfaltig scheinen, kann überwiegend schlechtes Management als Problemquelle identifiziert werden. So verweist auch der nachfolgend übersetzte Artikel von Yegor Bugayenko, welche Umstände dafür sorgen tragen können, das Projekte in schlechtes Fahrwasser geraten.

Wartbarkeit gehört zu den wertvollsten Tugenden moderner Software Entwicklung. Eine einfache Möglichkeit Wartbarkeit zu messen, besteht darin die Arbeitszeit zu messen, welche ein Entwickler benötigt um in einem neuen Projekt eigenständig ernsthafte Änderungen vorzunehmen. Je mehr Zeit benötigt wird um so schlechter ist die Wartbarkeit. In einigen Projekten ist diese Zeitanforderung beinahe unendlich. Was einfach ausgedrückt bedeutet, das diese Projekte schlichtweg nicht wartbar sind. Ich glaube das es sieben fundamentale und fatale Anzeichen gibt, das Projekte unwartbar werden. Hier sind sie:

Anti-Pattern

Unglücklicherweise sind die Programmiersprachen, welche wir benutzen zu flexibel. Sie ermöglichen zu viel und unterbinden zu wenig. Java zum Beispiel, besitzt keine Restriktionen ein ganze Anwendung mit ein paar tausend Methoden in nur eine Klasse zu packen. Technisch gesehen wird die Anwendung kompilieren und laufen, dennoch handelt es sich um das bekannte Anti-Pattern God Object.

Somit sind Anti-Pattern technisch akzeptierte Möglichkeiten eines Entwurfes, welcher allgemein als schlecht anerkannt ist. Es gibt für ede Sprache unzählige Anti-Pattern. Ihre Gegenwartin unserem Produkt is gleichzusetzen mit einem Tumor in einem lebendem Organismus. Wenn er einmal beginnt zu wachsen ist es sehr schwierig ihm Einhalt zu gebieten. Möglicherweise tirbt der gesamte Organismus. Möglicherweise muss die gesamte Anwendung neu geschrieben werden, weil sie unwartbar geworden ist.

Wenn nur einige Anti-Pattern zugelassen werden, werden denen möglichwereise schnell weitere folgen und der “Tumor” beginnt zu wachsen.

Dies trifft besonders auf objektorientierte Sprachen (Java, C++, Ruby und Phyton) zu, vor allem wegen ihrer Erblast aus prozeduralen Sprachen (C, Fortran und COBOL) und weil Entwickler zu einer imperativen und prozeduralen Denkweise neigen. Unglücklicherweise.

Übrigens empfehle ich zu der Liste von Anti-Pattern [2] einige Dinge ebenfalls als schlechte Programmierlösungen [3].

Meine einzige praktische Empfehlung an dieser Stelle ist lesen und lernen. Vielleicht helfen dieses Bücher [4] oder mein eigenes [5]. Eine generelle skeptische Einstellung zur eigenen Arbeit und keine Entspannungshaltung wenn es nur funktioniert. Genauso wie bei Krebs. Je früher es diagnostiziert wird um so größer ist die Chance zu überleben.

Unverfolgte Änderungen

Bei einem Blick auf die commit history sollte man in der Lage sein für jede einzelne Änderung sagen zu können was geändert wurde, wer die Änderung vorgenommen hat und warum die Änderung statt gefunden hat. Es sollte nicht mehr als einige Sekunden benötigen um diese drei Fragen zu beantworten. In den meisten Projekten ist das nicht der Fall. Hier sind einige praktische Vorschläge:

  • Benutze stets Tickets: Ganz gleich wie klein das Projekt oder das Team ist, selbst wenn es nur eine Person umfasst. Erzeugt stets Tickets (Z. B. GitHub Issues) für jedes Problem welches gelöst wird. Erläutert das Problem kurz im Ticket und dokumentiert die Lösungsansätze. Das Ticket sollte als temporäres Sammelbecken für alle Informationen die sich auf das Problem beziehen dienen. Alles was in Zukunft dazu beitragen kann die paar „komischen“ commits zu verstehen sollte in dem Ticket veröffentlicht werden.

  • Referenzieren von Tickets in den Commits: Unnötig zu erwähnen ist das jeder Commit eine Beschreibung (message) haben muss. Commits ohne Beschreibung gehören zu einer sehr unsauberen Arbeitsweise, die ich hier nicht mehr ausführen muss. Allerdings eine saloppe Beschreibung wird den Ansprüchen ebenfalls nicht gerecht. So sollte die Beschreibung stets mit der Ticketnummer beginnen, an der gerade gearbeitet wurde. GitHub beispielsweise verknüpft automatisch Commits mit den zugehörigen Tickets um die Nachverfolgbarkeit von Änderungen zu gewährleisten.

  • Nicht alles löschen: Git ermöglicht sogenannte „forched“ push, welche den gesamten remote Branch überschreiben.Dies ist nur ein Beispiel wie die Entwicklungshistorie zerstört werden kann. Oft habe ich beobachten können wie Leute ihre Kommentare in GitHub gelöscht haben, um die Tickets zu bereinigen. Das ist schlichtweg falsch. Lösche niemals alles. Behaltet eure Historie ganz gleich wie schlecht oder unaufgeräumt sie erscheinen mag.

Ad Hoc Releases

Jedes Stück Software muss vor einer Auslieferung zum Endkunden paketiert werden. Handelt es sich um eine Java Bibliothek ist das Paketformat eine .jar Datei die in die üblichen Repositorien abgelegt wurde. Ist es eine Webapplikation muss sie auf eine Plattform installiert werden. Gleich wie groß oder klein das Produkt ist es existiert eine Standartprozedur für testen, paketieren und ausliefern.

Eine optimale Lösung könnte eine Automatisierung dieser Vorgänge sein. Dies ermöglicht eine Ausführung über die Kommandozeile mit einer einfachen Anweisung.

$ ./release.sh ... DONE (took 98.7s)

Die meisten Projekte sind sehr weit entfernt von solch einem Ansatz. Ihr Releaseansatz beinhaltet einige Magie. Die Leute welche dafür verantwortlich sind, auch bekannt als DevOps, müssen lediglich einige Knöpfe drücken, irgendwo einloggen und Metriken prüfen et cetera. Solch ein Ad Hoc Releaseprozess ist ein sehr typisches Zeichen für die gesamte Software Entwicklungsindustrie.

Ich habe einige praktische Ratschläge zu geben: automatisiert. Ich verwende rultor.com dafür, aber es steht natürlich frei jedes beliebe andere Werkzeug dafür einzusetzen. Das einzig wchtige ist das der gesamte Prozess vollständig automatisiert ist und von der Kommandozeile ausgeführt werden kann.

Freiwillige statische Analyse

Statische Analyse [6] ist das, was den Quelltext besser aussehen lässt. Implizit sind wir bei dem Vorgang dazu eingeladen den Code auch effektiver zu machen. Dies gelingt allerdings nur wenn das gesamte Team dazu angehalten ist den Vorgaben der statischen Analysewerkzeuge zu folgen. Ich schrieb bereits darüber in [7]. Für Java Projekte hab ich qulice.com und für Ruby Projekte rubocop verwendet. Es gibt sehr viele ähnliche Werkzeuge für nahezu jede Programmiersprache.

Jedes Tool kann verwendet werden, solange es für alle Verpflichtend ist. In vielen Projekten in denen statische Analyse in Verwendung kommt, erzeugen die Entwickler lediglich aufgehübschte Reports und behalten ihre alten Programmier-Gewohnheiten bei. Solche freiwilligen Ansätze bringen keine Verbesserungen für das Projekt. Sie erzeugen lediglich eine Illusion von Qualität.

Mein Rat ist, dass die statische Analyse ein verpflichtender Schritt der Deployment Pipline ist. Ein Build kann nur dann erfolgreich sein, wenn keine der statischen Regeln verletzt wurden.

Unbekannte Testabdeckung

Einfach ausgerückt bedeutet Testabdeckung in welchen Grad die Software durch Unit- oder Integrationstests getestet wurde. Je höher die Testabdeckung ist, us so mehr Code wurde durch die Testfälle ausgeführt. Offensichtlich ist eine hohe Abdeckung eine gute Sache.

Wie immer kennen viele Entwickler den Grad ihre Testabdeckung nicht. Sie messen diese Metrik einfach nicht. Vielleicht haben sie einige Testfälle aber niemand vermag zu sagen wie tief diese die Software überprüfen und welche Teile nicht getestet wurden. Diese Situation ist weitaus schlimmer als eine niedrige Testabdeckung welche jedem bekannt ist.

Eine hohe Testabdeckung ist keine Garantie für gute Qualität, das ist offensichtlich. Aber eine unbekannte Testabdeckung ist ein eindeutiger Indikator von Wartbarkeitsproblemen. Wenn eine neuer Entwickler in das Projekt integriert wird, sollte er in der Lage sein einige Änderungen vorzunehmen und sehen wie die Testabdeckung sich dadurch verändert. Idealerweise sollte wie Testabdeckung auf gleiche Weise wie statische Analyse überprüft werden. Der Buld sollte fehlschlagen wenn die Voreinstellung unterschritten wird. Idealerweise beträgt die Testabdeckung um die 80%.

Nonstop Entwicklung

Was ich mit nonstop meine ist Entwicklung ohne Meilensteine und Releases. Egal welche Art von Software implementiert wird, sie muss Released und die Ergebnisse regelmäßig visualisiert werden. Ein Projekt ohne eine eindeutige Releasehistorie ist ein unwartbares Chaos.

Der Grund dafür ist, das Wartbarkeit nur dann möglich ist, wenn der Quelltext gelesen und auch verstanden wurde.

Wnn ich einen Blick auf die Sourcen werfe, den zugehörigen Commits und der Release Historie sollte ich in der Lage sein zu sagen was die Intension des Autors war. Was passierte im Projekt vor einem Jahr? Wie steht es mit dem aktuellen Status? Wie sind die künftigen Schritte geplant? Alle diese Informationen müssen bestandteil des Quelltextes sein und noch viel wichtiger, in der Git Historie.

Git Tags und GitHub Release Notes sind zwei wirkungsvolle Instrumente die mir diese Informationen zu Verfügung stellen. Nutze sie in vollem Umfang. Ebenso sollte nicht vergessen werden, das jede binäre Version des Produktes als ständiger Download verfügbar sein muss. Das bedeutet das ich in der Lage sein sollt die Version 0.1.3 herunter zu aden und zu testen, selbst wenn das Projekt bereits an der Version 3.4 arbeitet.

Undokumentierte Interfaces

Jede Software hat Schnittstellen, die verwendet werden sollten. Handelt es sich um eine Ruby gem, so existieren Klassen und Methoden die von Endanwendern Verwendung finden. Geht es um eine Webapplikation so gibt es Webseiten welche von einem Endbenutzer aufgerufen werden um mit der Anwendung zu interagieren. Jedes Software Projekt hat also ein Interface welches ausführlich beschreiben werden muss.

Wie mit den andern Punkten, welche bereits erwähnt wurden handelt es sich hierbei auch um Wartbarkeit. Als neuer Programmierer in einem Projekt beginnt die Einarbeitung bei den Interfaces. Jeder sollte daher verstehen was die Aufgabe des Interfaces ist und wie es benutzt werden kann.

Ich spreche von der Dokumentation für die Benutzer, nicht für Entwickler. Im allgemeinen bin ich gegen Dokumentation inerhalb der Software. An dieser Stelle stimme ich vollständig mit dem Agilen Manifest [7] überein. Funktionierende Anwendungen sind wichtiger als ausschweifende Dokumentation. Aber das meint nicht das Referenzieren auf eine externe Dokumentation welche für die Anwender gedacht ist.

Endanwender Interaktion mit der Anwendung muss sauber dokumentiert werden.

Handelt es sich um eine Bibliothek, so sind die Anwender Entwickler welche das Produkt verwenden und es nicht durch eigenen Code erweitern. Die Nutzung erfolgt ausschließlich als Black Box.


Diese Kriterien verwenden wir um Open Source Projekte für unseren Award [8] zu evaluieren.

Resourcen

[1] Orginal Artikel: https://www.yegor256.com/2015/06/08/deadly-sins-software-project.html

[2] https://en.wikipedia.org/wiki/Anti-pattern

[3] https://www.yegor256.com/2014/09/10/anti-patterns-in-oop.html

[4] https://www.yegor256.com/2015/04/22/favorite-software-books.html

Veröffentlicht unter Diaries in digital, Themes | Verschlagwortet mit , , , , | Kommentar hinterlassen

Treasure chest – Part 2

In our 2nd part about the application configuration we will discuss the implementation of the DAO and it’s corresponding service. We already demonstrated the usage of the domain object and how the basic implementation could extended. [<<] [2] [>>]

Now the days micro services and RESTful application are state of the art. Especially in TP-CORE the defined services aren’t REST. This design decision is based on the mind that TP-CORE is a dependency and not a standalone service. Maybe in future, after we got more experience where this library is included, we could rethink our current concept. For now we treat TP-CORE as what it is, a library. That implies for the usage in your project, you can replace, overwrite, extend or wrap the basic implementation of the ConfigurationDAO to your special necessities. This specialized Data Access Object is used in the ConfigurationService to provide more complex functionality. That implies the service layer is used to orchestrate several DAO calls. This calls are not limited just on a single DAO. Combinations of multiple DAO objects in Services are allowed. Lets start to discuss the fine granulated implementation of the DAO methods before we heading up to the higher level, the service.

In part one of this article we introduced already the ConfigurationDO and how it corresponds with the DBMS. The domain object or a list of domain objects will be in general the return value of our DAO. Of course actions like create could be void and throw just an exception in the case of a failure. For a better style the return type is defined as Boolean. This simplifies also writing unit tests. The GenericDAO provides the basic CRUD operations, we don’t need to repeat in every specialization again. The following image shows in an UML how everything is stick together.


Sometimes it could be necessary to overwrite a basic implementation. A common scenario is a protected delete. For example: a requirement exist that a special entry is protected against a unwanted deletion. The most easy solution is to overwrite the delete whit a statement, refuses every time a request to delete a domain object whit a specific ID. Only adding a new method like protectedDelete() is not a god idea, because a developer could use by accident the default delete method and the protected objects are not protected anymore. To avoid this problem you should prefer the possibility of overwriting GenericDAO methods.

To keep the portability changing the DBMS we use Hibernate (HBM) as JPA implementation and O/R mapper. This fact limit the expressions how we interact with our DBMS. In the Spring configuration for Hibernate, we decided to use the EntityManager instead of the Session, to send requests to the DBMS. Since version 5 Hibernate use the JPA 2 standard to formulate queries. In the future we have the idea to replace the Spring dependency injection framework and use instead Java CDI. A reason is reducing third party libraries to reach a better compactness. In the current circumstances, is this plan just a wish. The amount of mandatory code changes is huge and some important details still not solved. If you can provide a solution you’re invited to send a pull request and we will happily merge your enhancement. For now let us move ahead to talk about the simplest query we can send to the DBMS, before we discover more complex problems.

As default query to fetch an object, we use always as identifier the primary key (PK). For performance contains the index the PK. A simple expression fetching an object is written in the find method of the GenericHbmDAO. In the specialization as ConfigurationHbmDAO are more complex queries formulated. To keep a good design it is important to avoid any native SQL. Listing 1 shows fetch operations.

//GenericHbmDAO
public T find(final PK id) {
  return mainEntityManagerFactory.find(genericType, id);
}
//ConfigurationHbmDAO
public List getAllConfigurationSetEntries(final String module,
final String version, final String configSet) {

  CriteriaBuilder builder = mainEntityManagerFactory.getCriteriaBuilder();
  CriteriaQuery query = builder.createQuery(ConfigurationDO.class);
  // create Criteria
  Root root = query.from(ConfigurationDO.class);
  query.where(
    builder.equal(root.get("modulName"), module),
    builder.equal(root.get("version"), version),
    builder.equal(root.get("configurationSet"), configSet)
  );
  return mainEntityManagerFactory.createQuery(query).getResultList();
}

The readability of these few lines of source is pretty easy. The query we formulate for getAllConfigurationSetEntries() returns a list of ConfigurationDO objects from the same module whit equal version of a configSet. The MailClient is a easy understandable example for what the parameters stands. The implementation of MailClient is the class JavaMailClient in the application package, in the module core. The meaning of configSet we already explained in part 1 of this article. as a short reminder the MailClient contains several configuration entries, which belongs together. Those are mail server, user account, password and so on. As you can see this modifier is helpful to filter the result set to an appropriated size. A bit confusing is the version entry, because this do not representing the module version, instead stands for the service version and is defined in the interface of the service itself. In concrete the module TP-CORE in the artifact version 2.0 contains the MailClient in version 1.0. This implies every configuration change need a new version in the service and all entries in the database have to duplicated to this new version. The existing ones will not deleted. This allows us a simple rollback option, in the case is needed. This mechanism allows future implementations of secure updates without loosing modified application configuration entries. In Part 3 of this series we come closer with all the details in the MailClient example.

Everywhere in TP-CORE when we talk about version numbers we mean the rule set of semantic versioning. Based on this convention is a domain object called Version implemented. This object brings several benefits. Whit it we are able to compare, sort an validate version numbers. Artifacts who still in the status „under development“ are labeled with SNAPSHOT, as it is defined for Maven projects. A valid version is defined by the segments: major, minor, patch and label. The patch and label are optional. this means the numbers 2.0 and 2.0.0 are equal to each other. Furthermore allows the Version object extensions to define expressions for version ranges. Currently those expressions are not planned as requirement.

Another thing we can learn in this implementation is in our opinion the importance of testing database queries. The argument that those test slows the build process heavily down, is a good hint for a refactoring. Maybe the module is to general and contains to much functionalities. Listing 2 demonstrate how a test bed for the method getConfigurationByKey() could formulated.

@Test
void testGetConfigurationByKey() {
    ConfigurationDO config = configurationDAO.getConfigurationByKey("key", "Module_A", "2.0.1");
    assertEquals("Y.1", config.getValue());
}
@Test
void testGetConfigurationByKeyNoExist() throws Exception {
    assertThrows(Exception.class, () -> {
        configurationDAO.getConfigurationByKey("noope", "Module", "1");
    });
}

Beside the introduced methods exist some other helpful predefined functions in the ConfigurationDAO. The naming gives a well idea for what the method should used. If there some doubts, the API documentation gives also a good explanation. In the case you have a more precise description for some java docs, don’t hesitate to contact us. Here is a short election of some implemented functionality

  • restoreKeyToDefault()
  • getHistoryOfAEntry()
  • getAllDepecatedEntries()

This brings us now to the next layer and our service implementation. The ConfigurationService operates mostly on module perspective. The method resetModuleToDefault() give a good impression what that means. Of course in the service layer we are not limited to write a service for a special DAO like we did with the ConfigurationService and the ConfigurationDAO. As long a single service is atomic and not a composition of multiple services, different DAOs could mixed up in the implementation. To combine atomic services to complex workflows, processes or actions, you can use orchestration layer. Another important detail about testing are that service and orchestration layers doesn’t contain unit tests. This code have covered by acceptance tests, like it is described in the article: „Acceptance tests in Java whit JGiven„. There you will find more details about advanced testing strategies.

Resume

In this article we got deep insights how the DAO pattern in TP-CORE is used. We discussed all important architecture details of the involved layers and were the corresponding objects are located. With this information we are able to extend the ConfigurationDAO and its service. As next step we will see on a real example how the application configuration is used in the JavaMailClient implementation,to get a full understanding how helpful is TP-CORE for rapid development.

Veröffentlicht unter Diaries in digital | Verschlagwortet mit , , , ,

Treasure chest – Part 1

Almost every application needs some easy changeable configuration settings, allowing adaptions to their own needs. Options to change the behavior of the entire application during run-time are not always that easy, as it might seems. In this article we discuss how to overcome those problems by using the TP-CORE library.  [Part 2]

Through the years, different techniques to storage configuration settings got established. We can choose between database, property files, XML or YAML, just to give a few impressions of the options we could choose from. But before we jumping into all technical details of a possible implementation, we should got a bit familiar of some requirements.

Many times in my professional life I needed to touch this topic. Problems occur periodically after updates. The peak for me, I reached with Windows 10. After every major update many settings for security and privacy switched back to default, apps I already uninstalled messed up my system again and so on. This was reasons for me stop suffering and I chosen an alternative. Now with Ubuntu Mate I’m fine. Several times I also had to maintain legacy projects and migrate data to newer versions. A difficult and complex procedure. As result I questioned myself how this problem could handled in a proper way. My answer is formulated in TP-CORE Application Configuration, I will introduce here. A basic description for the used architecture you can finde in the article: Together Platform – Solutions in Java.

My decision to use a Database is driven by the requirement of having a history. Off course the choice have also some limitations. Obviously the configuration for the database connection needed to be stored somewhere else. In the case of TP-CORE it deals with a XML based Spring configuration. The template you will find: spring-dao.xml. The library supports different DBMS like PostgreSQL, MariaDB or Oracle. Using Spring, Hibernate and JPA in combination of some data design techniques allows a seamless DBMS change. An important detail for synchronizations between test, develop and production stage. A nice plus is the included connection pool 3CPO.

You may could argue a in-memory system like redis or document databases like couchDB would perform better. But the implementation of the generic Data Access Object pattern for a rapid development process in TP-CORE is the basic functionality used by ApplicationConfiguration. We wanted to keep a complex enterprise setup as much simple as possible. For this We decided don’t mix up to many technologies. This would have some negative effects, because the dependency list grows.

The first step, you need to do for including TP-CORE in your own project, add the dependency. For Apache Maven you can use the following listing:

<dependency> 
   <groupId>io.github.together.modules</groupId> 
   <artifactId>core</artifactId> 
   <version>2.0.1</version> 
</dependency>

All mandatory artifacts for Spring, Hibernate, JDBC and so on already are included. If you wish to discover the whole dependency list take a look at the TP-CM/build-workflow project. This defines the parent pom for all together repositories. An initial database script for postgers is placed TP-CM/dbms. Feel free to send pull requests for other DBMS. A short hint to the dbms POM is the inclusion of a Maven flyway configuration management for databases, you can use in your project too.

As a second step you need a database setup. We mention the spring-dao.xml template. If you wish to use the included configuration, you need to aware that:

  • you have a PostgreSQL 11 installation
  • running on 172.18.0.2:5432
  • a schemata called together
  • a user named together for the schema together whit the password together

Be careful running this setup, because of security risks in production environments. We recommend for a simple usage a docker installation. The password should be replaced by one of your own choice.

docker network create -d bridge –subnet=172.18.0.0/16 services

docker run -d –name postgres \
-p 5432:5432 –net services –ip 172.18.0.2 \
-e POSTGRES_PASSWORD=password \
-e PGPASSWORD=password \
-v /media/postgreSQL/data:/var/lib/postgresql/data \
postgres:11

In the database.properties are more connection strings to all provided DBMS stored. In the case you wish to compile TP-CORE by your own, you can modify this file to your preferred configuration. In the target directory is a processed spring-dao.xml based on the entries of the mentioned property file. This hint you can take also as a fast solution to generate your own spring configuration. As next you need to load the spring configuration into your application. Here we have two possibilities. If you have a standard Java app, you can add the following line to your main method:

ApplicationContext context = 
   new ClassPathXmlApplicationContext("/spring-dao.xml");

Web application are configured by the web.xml in the WEB-INF directory. there you need to add those lines:

<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>/WEB-INF/spring-dao.xml</param-value>
</context-param>

If you did all those steps well, your database connection should work proper. Hibernate creates for you the table structure. This will be also our next paragraph, a deep explanation of the Domain Object ConfigurationDO.

The most columns you see in the image above, are very clear, for what they got used. As first point we need to clarify, what makes an entry unique? Of course the UUID as primary key would fit this requirement as well. The effect that a primary key can not changed was also a vote for the decision to use an separate UUID. This identifier is auto generated by the application, when a new row got created. But using in your program all the time a non human readable id as key, to grab a value is heavily error prone and uncomfortable. For our use case we decided a combination of configuration key, module name and module version to define a key entry. A module is defined as a other library or artifact like an access control list or a administration.

The module name for TP-CORE is core. The functionality of the MailClient have configuration entries like: host, user and password. To group all entries of a function like the MailClient we introduced the config set. The config set for MailClient is named as email. This mechanism allows a better memory management, because of a efficient filtering for needed entries and not fetch the whole list. You could interpret a configSet as a service configuration. In the service interface you will find the a constant CONFIG_SET which is the used entry in the database for this specific service. The name of the module is stored in the Constraint class.

Each service has its own version. The incementation of the version number follows the semantic versioning. Always when a service configuration is changed, the version number of the service have to be updated. Here we see a bit how the history mechanism works, but the full details about history we touch later.

A very important information is that the configuration key is in the DBMS stored as SHA-512 hash. This is a simple protection against a direct manipulation of the configuration in the DBMS, outside of the application. For sure this is not a huge security, but minimum it makes the things a bit uncomfortable. In the application code is a human readable key name used. The mapping is automatic, and we don’t need to worry about it.

A configuration comes with a default or with a user modified value. This gives a protection of updating entries without overwrite the application settings. The mechanism is very simple. If a configuration value is not present, the application use the default. The flags deprecated and mandatory for a configuration key are very explicit and descriptive. Also the column comment don’t need as well any further explanation.

Resume

With all those information we completely discussed about the Domain Object and we got ideas what we are able to do with. As next step in part two, we come closer to the DAO implementation and the corresponding service. We will learn some basic about versions and how this fit together in the ApplicationConfiguration. The third and final part of this article discuss in detail the MailClient and how it is used the Application Configuration as real world example.

Veröffentlicht unter Diaries in digital | Verschlagwortet mit , , , , , , , | Kommentar hinterlassen

Next Generation Maven

A whitepaper proposal for new Maven lifecycle [2nd. Edit]

Apache Maven [1] already prove since more than a decade stability and relevance in countless professional software projects. By reason it is one of the most chosen tool for build and dependency management in the Java universe. An active community, good documentation, a huge pool of resources, many improvements and bug fixes are arguments for this choice.

But beside this world are other tools also available, which fighting heavy for the pole position, like Gradle. For that reason I start thinking how could be a improvement for Maven, whiteout leaving the actual path. What could be an wanted extension so many users miss. My main idea of this short document is to extend the actual processes with more lifecycles (workflows). I hope that I’m not the only one with this intention. Feel free and join this discussion to give your opinion.

Karl Heinz Marbaise described in his talk at EuregJUG 2019 [2] Maven as an plugin execution framework. With more lifecycles (or workflows) Maven could described as an workflow engine. If each step in the software development process could provided by a default Maven lifecycle, in the manner of lifecycle:phase:goal, a expression language for builds got created. Other lifecyles could be interesting too, like:

  • stage: deploy at test stage, quality stage etc.
  • inflate: create & run infrastructure of several docker containers

Currently Maven define tree different processes or workflows, called lifecycle: clean, build and site. The most structured lifecycle is build [5], which contains 21 steps or also know as phase. In respect to the build lifecycle I would like suggest a new lifecycle: release, because I feel it is missing. Well, we already have the release module. But I talk about a new and adoptable process, which follows the Maven DRY and COC concepts.

If we take our view to new approaches of DevOps, CI and delivery pipelines, it is our chance to define a new automated standard in the Maven way. The main goal of the suggested release liefcycle is a simplified deployment to the Maven Central Repository Server and the steps how to prepare a Release. This also includes alternative publishing to an own hosted repository server.

A small dependency to the current build lifecycle need to decide. In general it is possible to keep the phase deploy in the build lifecycle, as a fast shortcut. Another option is to move the deploy phase to the release lifecycle, because in my opinion this fits there better in. The install phase I think should stay in the build phase, because its copy the artifact to the local repository. A movement of the phase install would complicated the usage during the development.

One important part of a release process is the version number of the artifact. As default implementation I suggest the Semantic Versioning policy, to define a rule set how to handle the incrementation of a version number. The label SNAPSHOT still define artifacts under development. To visualize a simple release process and how it correspondent with a SCM like Git, I attach the following image.

Release Process for SCM branching and merging

Now let me introduce a first orchestration of several phases, plugins and possible goals for a release lifecycle:

  1. validate: POM – artifact version already exists?
  2. enforce: MVN / Java / SNAPSHOT
  3. build: result > artifact.jar
  4. test: acceptance tests, no UnitTest – BDD e.g. JGiven
  5. documentation: result > javaDoc.jar / swagger
  6. sign: PGP
  7. scm: Tag / Increment Version : semVer policy
  8. site: reporting – optional: publish
  9. deploy: mvn central / company or self hosted

Maven Resources:

Veröffentlicht unter Diaries in digital | Verschlagwortet mit , , , , , | 3 Kommentare

Talents wanted

During my career I registered myself on tons of job portals. After more than a decade experience I decided to write down my personal resume. Reasons why I want to share my stories are different. But the most valuable point for me is the common bad habit of recruiters and how the situation got year by year more worst. I hope other employees can reconsolidate their own current situation and will not feel alone anymore. As long no realistic public discussion about this topic is in process, nothing will change. Let me give you as employee, freelancer or company one short preview in advanced, before I continue to explain my arguments, don’t waste your time talking with recruiters. This brings you nowhere.

During my professional life I had a huge amount contact with persons, they called themselves as talent searchers. But don’t get confused. Those persons aren’t searching seriously for talents. The only interest they have is to find with less work a person fit somehow with a profile description. Of course the most important question this folks have is to find the cheapest worker for the future client. And cheating you with an unfair payment. Often they keep around 50% of the regular market price in their own favor. But which real service they deliver to you and the company you will work for.

Don’t be afraid, it is not that difficult to detect that black sheep’s when they try to contact you. A very strong indicator is the recruitment company has an office in London and a heavy background to India. Often they call you with a British number from a call center in India. So if you got a call from a person, is not the one contact you, on the job web pages, hang up and save your time and nerves.

Another point you should aware, when they need first your CV or profile to tell you how much they plan to pay to you. As first those persons don’t read your CV. They scan automatic for buzzwords and check the result how it match. Secondly in general they don’t know anything about the technical background of the role they try to stuff. Close to 99% after you accept such positions, you will realize that you are the last element in a long contractor chain. All those persons take some of the money away, you get with the work you provide to the final client. And ask your self, which real value those persons have to allow them takeing high amounts from the income, you deserve away. It is an unfair game they play with contractors and entreprises. It’s obvious, save your energy and ignore all tryouts to contact you.

Another thing I observed are a mass of websites who offer different kinds of positions. As I found out, it doesn’t matter how detailed you throw your personal information into this applications, the result is always equal. They not looking for high motivated experts. All they want is the most cheapest person for the profile they have to stuff. Save your time and don‘ t register. Often those pages hold not longer than 6 months and shortly they disappear. Be sure, as long you not willing to sell your self in conditions as a slave, for almost a payment close to the amount of the social help from the government, no one contact you.

A very important survivor rule, never – tell in any web page or to a interview how much you winning in previous jobs. Refuse any request to declare your personal financial situation. With this information they easily calculate when you are empty and then you will accept more worst conditions.

Once a company contacted me and ask if I would be willing to tell them the names of my previous bosses. They argue with this information they can verify the satisfaction of my services I gave. The promise he mention was, like this I could catch much faster new projects et cetera. The truth is, he wanted to get to collect new business contacts to make easilier new deals. Because the persons you had worked for are the ones who take decisions to hire others. Those information have a high capital value in the market. As long they didn’t pay you in advanced 1000€ for each contact, refuse this kind of requests.

Ofcours this is just the half of the story. If you think, well I will sell myself directly, very fast you realize it is not that easy. If you try to contact companies directly who are in search for employees, often they just want a permanent contract. Close to no chance for freelancer to join. But often those companies complain there no experts available. Real experts searching always for challenges to grow their skills. If you want to win them as part of your team, to got profit from their experience, you need to be flexible. Flexibility is not just a one way for employees. For companies searching success, is also a mandatory skill.

But now I don’t want waste to much of your time reading this resume, fulfilled of wierd stories how those black sheep’s cheat the whole marked. Let’s take a look on things we can manage to get a better situation in future.

As first, I have to say it exist trustful recruiters you can have a long and good business relation. May you ask, what makes them different and how you can detect them? Don’t worry with a bit of common sens you catch very easy if the one in front to you is a serious person. So let me first explain how such relations in general have to work.

Recruitment is like an agent for a music star. He help you to promote yourself and looking for clients to bring you in good positions. A relation of trust starts with helpful feedback. If your recruiter don’t give you a feedback about the services you had delivered, then don’t expect a long term business relation. He should be able to explain you why sometimes you got not selected for a position. Even he can tell you how you could increase your CV. He should understand the market and basic technical knowledge, to guide you secure into the future. As contractor you always need to learn new things. But what is the right decision? A good recruiter can see trends and he will talk whit you about that. In those cases you will be a very powerful and success team. because your business relation is not just based on a win win.

And yes I also have to show the opposite of the medal. Some employees are also terrible. Be responsible and deliver what you promised. If you give your word to somebody treats you fair and you cheat him just to win a few coins more, think twice. its ok to take the chance to raise your income. being fair means give your partners the chance to fill the space you left. communicate honest and early. If your services are that excellent, they will understand it. Maybe they willing to increase you rate to convince you to stay. but never use this as a strategy game for pushing up the price. they will find out and you will lose more than you win. the market is small. key players know each other.

As lesson learned we have to admit every party have own devils in the game. But it is not just worst. A lot of nice and loyal persons acting in the market. our challenge for the future will be a creation of a trustful network, to close doors for all who just try cheat. As result we got exciting projects, finished in time and budged whit high motivated teams.

Veröffentlicht unter Themes, Time Loop | Verschlagwortet mit , , , , , , | Kommentar hinterlassen

Cocina rica Mexicana

Eigentlich sollte man in Mexiko Landstraßen wegen der schlimmen Schlaglöcher meiden. Aber es gibt nun einmal kein anderen Weg ins verschlafene Pueblo Tecali. Ein gemütlicher Ort an dem man alle möglichen Sachen aus Onyx und Marmor zu erschwinglichen Preisen erstehen kann. Wie dem auch sei kam unser Auto mit quietschenden Reifen zum Stehen und ich glaubte schon wir waren kurz davor einen der vielen Straßenhunde ins Nirwana zu befördern. Erschrocken wachte ich aus meinem leichten Dösen auf und ehe ich ganz klar wurde, um zu Realisieren, das keine Gefahr drohte, meinte Lupita voller Emotion in einem durchdringenden Ausruf Pulque. Aha. Das muss es ja Wert sein, dem Herzinfarkt gerade noch von der Schippe gesprungen zu sein, dachte ich. Sogleich prasselte die Erklärung auch auf mich ein.

Der Kaktus aus dem man den Tequila gewinnt, kann man quasi melken. Natürlich morgens. Wo hier in Mexiko ja auch so viel vor 11 Uhr passiert. Der gewonnene Saft ist extrem süß und nennt sich Aqua de Miel oder auf deutsch Honigwasser. Das ganze beginnt auch recht schnell zu vergären und wird dann zu Pulque. Natürlich wären Mexikaner keine Mexikaner wenn sie das Ganze nicht veredeln würden. Also gibt es verschiedene Geschmacksrichtungen wie beispielsweise durch Vermischen mit natürlichem Erdbeer- oder Ananassaft. Doch sehr legger! Der Alkohol beruhigt auch wieder. Aber Vorsicht ab dem zweiten Liter setzt man sich der Gefahr aus die Verdauung anzuregen. Dann habe ich noch gelernt, wenn Pulque Fäden zieht und das Ganze eher an Austern erinnert, Finger weg. Dann ist die Qualität schlecht.

Nach der kleinen ungeplanten Rast geht‘s weiter mit unserem Trip für Tio Juan ein Geburtstagsgeschenk zu organisieren. Recht schnell erreichen wir auch den Zocalo von Tecali. Viel länger hätte es auch nicht dauern dürfen mit der ganzen Pulque im Magen. Der fängt auch schon an zu rebellieren. Schließlich ist Mittagszeit und man lebt ja nicht nur von Luft allein. Sehr praktisch, das wir direkt neben dem Hot Dog Stand geparkt haben. Das inspiriert noch mehr. Oh mein Gott. Na ich werd jetzt nicht gleich katholisch aber ja welch tolle Überraschung. Das hat nichts mit dem gemein was wie in Deutschland als Hot Dog kennen. Selbst für mexikanische Verhältnisse erinnert der Berg aus Salat und Wurst an ein Hamburger. Vergleichbares kenne ich nur von der Torta Cubana. Nein auch wenns so klingt, es ist kein Kuchen. So was heißt hier Pastel. Die Torta Cubana ist ein überdimensionales Sandwich aus Fleisch das mit reichlich extra Fleisch dekoriert ist. Dss ist selbst für ein Deutschen XXL Magen zu viel Füllmasse. Jedenfalls konnten wir der Versuchung uns über Hod Dogs herzumachen nicht widerstehen. Dafür wurden wir auch gleich vom Futterkoma überwältigt. La vida de puerco. Essen schlafen essen. Also gibt‘s Siesta im Auto, bis der Magen ein Minimum an Blut dem Kopf zurück erstattet. Als passendes Geschenk fand sich eine wunderschöne Onyx Tischleuchte, mit der wir unsere Heimreise nach Puebla abgetreten haben.

Bevor wir die Endstation unseres kurzen Ausflugs erreicht haben gilt es noch fix bei Tantchen in Los Zapos anzuhalten. Um sämtliche Details für die Geburtstagsfeier am Wochenende zu erfahren. Auch wenn der Antikmarkt im historischen Zentrum wunderschön ist und es ständig tolle Dinge zu entdecken gibt, ist die Anfahrt durch das Verkehrschaos in der Innenstadt ein Albtraum. Einschließlich der Parkplatzsuche.

Da wir gerade übers Essen sprechen. In Deutschland ist Chili con Carne immer recht beliebt. Gut, auf Parties zu denen Vegetarier geladen sind, verhält sich die Sache ein wenig anders. Dennoch hat das was wir sosehr mit Mexiko verbinden nichts mit der Küche hier gemein. Wer hier seine Urlaub verbringt, sucht nach dem deutschen Partyklassiker vergeblich. Zum Thema Chili gibt es auch noch einiges zu sagen, denn das kann zu einer richtigen Wissenschaft ausarten. Im Gegensatz zu unseren europäischen Gewohnheiten bedeutet in Mexiko scharf essen keine Selbstgeißelei, die ausschließlich aus Schmerzen besteht. Nein hier hat die Schärfe Geschmack, ein Grund weshalb

Chilistand auf dem Wochenmarkt.

Chilistand auf dem Wochenmarkt.

Mexikaner so versessen auf ihre Salsas sind. Aber Achtung, peligroso! Immer vorher probieren und ein Moment warten. Manchmal dauert es bis das Kribbeln im Mund zu einem Inferno wird. Um auf den Geschmack zurück zu kommen, so zählt zu meine Favoriten Chipotles. Eine Sorte die mittelscharf ist und sehr an BBQ erinnert. Einen großen bogen mache ich um Habaneros, das so ziemlich gemeinste womit man Würzen kann. Ich durfte das einmal als Spezialzusatz in Guaccamole unwissend verkosten. Wie man sieht ich habe überlebt. Jalapeño gelten eher die Klassiker und gehören förmlich auf jede Piccadita, die scharfe Version eines Taccos. Es gibt aber auch eine Variante, wo man die Samenkerne entfernt die Jalapeño sorgfältig wäscht und sehr langsam erhitzt. Als Resultat ist aus dem scharfen kleinen Biest eine zahme Frucht geworden, die sogleich mit einer Paste aus Tunfisch und Streichkäse füllt. Vorsicht Suchtgefahr. Natürlich gibt es noch viel mehr über die verschieden Chilis zu erzählen, aber belassen wir es an dieser Stelle damit.

Wenden wir uns nun kurz der ersten Hilfe zu und klären was zu tun ist, wenn die Schärfe übermächtig wird. Die üblichen Empfehlungen Brot oder Milch helfen ganz gut das Gefühl Feuer geschluckt zu haben zu bewältigen. Gemeiner ist es, wenn nach ein paar Stunden der Magen auf Grund der ganzen Schärfe rebelliert. Dann hilft nur eins. Ein Glas Wasser mit einem Löffel voller Bikarbonat. In Deutschland kennen wir das unter dem Begriff Kaisernatron.

Weil so eine Fiesta Mexicana eine sehr ernste Angelegenheit ist, wird wie überall auch gleich die ganze Familie mit eingebunden. Also gab es für uns den Auftrag am nächsten Tag mit ein paar Stühlen in Cholula aufzukreuzen um bei der Vorbereitung einer lokalen Spezialität mitzuhelfen. Im August /September ist Saison für Chili en Nogadas, die wegen der vielen Zutaten und der Aufwendigen Zubereitung vergleichsweise teuer sind. Nogadas sind frische Walnüsse, die erst geschält und dann zu einer Paste verarbeitet werden. Dazu kommen noch verschieden Früchte wie Annans und andere Leckereien. Aber bevor wir aufbrechen um unsere Anstellung als Hilfsköche anzutreten, stärken wir uns mit einer Cemita. Dabei handelt es sich um ein großes Brötchen gefüllt mit einem mageren Schnitzel, etwas Grünzeug und einer Salsa Macha Chipotle. Wer braucht schon McDonalds wenn man so etwas haben kann.

Mit etwas Verspätung sind wir dann auch in Cholula eingetroffen. Erstaunlich wie schnell man in der richtigen Umgebung die so gerühmte deutsche Pünktlichkeit abstreift. Es vereinfacht das Leben ungemein. Sich vorzunehmen einem Latino Pünktlichkeit bei zubringen ist wie der Kampf Don Quichotte gegen die Windmühlen. In Cholula, einem Stadtteil von Puebla steht übrigens die flächenmäßig größte Pyramide der Welt. Man sieht nur nicht viel, weil der Großteil nicht ausgegraben wurde und die Spanier auf der Spitze eine katholische Kirche errichtet haben. Am Fuße der Pyramide gibt es Kakao, nach Art wie die Azteken ihn getrunken haben, mit Wasser aufgeschäumt. Es ist etwas Komisch Mexiko hat seit Jahrtausenden Kakao kultiviert aber klassische Milchschokolade, wie wir sie in Europa haben wird importiert und ist entsprechend teuer und daher auch begehrt.

Wie ich gerade feststelle ist es auch schon recht spät geworden und heute, wo ich diese Zeilen verfasse ist auch die Geburtstagsfeier – zu der wir eingeladen sind. Also muss ich mich sputen, denn die Chili en Nogada sind sehr beliebt und daher auch ruck zuck weg. Dann bleibt mir nur noch mich mit Tequila oder Mezcal zu trösten. Damit lässt sich auch das anschlißende Karaoke aushalten. Also bis zum nächsten mal und ein kräftiges SALUT.

Veröffentlicht unter Roadshow | Verschlagwortet mit , , , , | Kommentar hinterlassen

At night at Coco Bongo

Wer an die Karibik denk hat nicht gleich Mexiko im Sinn und noch viel weniger die Maya Hochkultur. Aber die Halbinsel Yukatan ist lediglich zu ihrer westlichen Seite den Golf von Mexiko begrenzt. Im Osten verlaufen malerische Sandstrände entlang der karibischen See. Kuba ist auch nicht mehr weit. Von Cancun über Playa del Carmen und Tulum gelangt man entlang der Küste zur Lagune der sieben Farben nach Bakalar. Von dort ist es nur noch ein Katzensprung nach Belize, der ehemaligen britischen Kolonie, in der man kein Spanisch spricht. Die starke Währung (Belize Dollar), mangelnde Produktion von Gütern und den Unwillen den Euro als Zahlungsmittel zu akzeptieren machen einen Besuch eher unattraktiv. Zumal sämtlich Güter aus Mexiko importiert wurden und somit dreimal soviel kosten wie im Ursprungsland. Die starke asiatische Dominanz bei Geschäfts und Restaurantinhabern verbessert die Situation nicht merklich. Das Hünchen Curry entpuppt sich schnell einmal als Hüchen Maggie. Bleiben wir also besser in Mexiko um die Karibik zu genießen.

Im Norden auf Yukatan ist der internationale Flughafen Cancun. Mit der Busgesellschaft ADO erreicht man für ca 80 MX Peso das Stadtzentrum in ca. 30 Minuten. Die Haltestelle befindet sich vor Terminal 2. Stündlich gibt es eine Verbindung. Alternativ kann man auch für knappe 50 Euro das Taxi nehmen. Wer zwischen den verschiedenen Terminals wechseln muss kann den kostenlosen Shuttelservice nutzen. Taxifahren sollte man wie überall auf der Welt in touristischen Gebieten gehörig misstrauen. Cancun mit seiner Hotelskyline gehört zu den weltweiten Touristenhotspots. Das macht sich besonders bei den Preisen bemerkbar. Aber dazu später mehr.Die deutsche Condor bietet regelmäßige Direktverbindungen von Frankfurt nach Cancun. In Schwierigkeiten gerät man erst bei Problemen. Auf dem Flughafen gibt es kein öffentliches WIFI. Sobald Unannehmlichkeiten auftauchen ist man auf sich gestellt. Condor hat auf Cancun keine Ansprechpartner, so das man dem Willen des dortigen Swissport Personals vollkommen ausgeliefert ist. Daher ein sehr guter Rat: nie abwimmeln lassen und nicht vom Schalter weggehen. Deutlich sprechen und alles möglichst per Video aufzeichnen. In Mexiko haben die Menschen viel Geduld. Man streitet nicht, man sitzt es einfach aus.

Auch beim Geldwechsel merkt man schnell das man sich in einer Touristenhochburg befindet. Im Vergleich zum Rest von Mexiko sind die Wechselkurse 10 -15% schlechter. Es ist denn noch nicht zu empfehlen bereits in Deutschland zu wechseln. Die Kurse beispielsweise von der Reisebank, wie man sie auf jedem Bahnhof findet, sind noch unverschämter als beim schäbigsten Straßenwechsler in Playa del Carmen. Mit Kreditkarte kommt man allerdings recht weit. Am regulären Bankautomaten, nicht die Dinger die überall in den Einkaufszentren herumstehen, kann man sich vernünftig mit Bargeld eindecken. Sobald man diesbezüglich versorgt ist kann man sich auch gleich auf Entdeckungsreise begeben. Auch das Kleingeld für den Bus nicht vergessen. Wer nicht gezielt auf Souvenirjagd ist kommt mit ca. 600 Pesos pro Person gut zurecht. Das genügt für Essen, auch im Restaurant, und ein paar Cocktails.

Persönlich vermeide ich die Hauptsaison von Mai bis September. Zu dieser Zeit ist es noch heißer als in einem Backofen. Wer sich vom Ballermann Partyleben abgestoßen fühlt, sollte den Spring Break vermeiden. Dann verstopfen kanadische und amerikanische Teenager die Straßen um ausgelassen zu feiern. Es ist ein wenig Ausnahmezustand. Das führt uns auch gleich zum Nachtleben abseits der Hotelbars. Wie überall ist man gut beraten, teure Kameras, Uhren und andere Accessoires im Hotel zu belassen. Die Clubszene wird vom berühmten Coco Bongo angeführt. Der günstigste Eintritt liegt bei knapp 80 Euro und beinhaltet Rum, Tequila und Bier, auch mehr als man verträgt. Andere Drinks kosten extra. Nette Damen animieren die Gäste zu kleine Schnäpsen, die natürlich auch extra kosten. Daher ist man gut beraten immer vorher zu fragen was es kostet. Das bewahrt vor unliebsamen Überraschungen. Die Wartezeiten an der Bar sind vergleichsweise kurz. Verschiedenste Live Shows von ca. 10 Minuten Dauer, bieten ein enormes Spektakel. sofern man es trotz der vielen Menschen die sich vor der Bühne drängen, zusehen bekommt. Alternativ gibt es für den gleichen Preis Eintritt und Bar libre in den restlichen drei Clubs.

Wer zum ersten Mal nach Mexiko kommt kann in XCaret für knappe 80 € einen Crashkurs in mexikanischer Kultur erhalten. Mittagsbuffet ist inkludiert und das Essen hat eine gute Qualität. Wer es natürlich bevorzugt, anstatt der Konserve, plant einen Ausflug nach Chichen Itza. Man bekommt eine echte Maya Pyramide zusehen. Wirklich imposant anzuschauen. Man darf sich nur nicht von den ganzen Verkäufern am Wegessrand zu sehr ablenken lassen. Das Ganze geht auch ohne Touristen. Mitten im Urwald in Cobe. Dafür unzählige Schwärme von Moskitos, richtige Blutsauger. Auch Action findet man auf Youkatan. Damit meine ich keine Abenteuer, wie nach Mitternacht durch dunkle Straßen zu wandeln um sich seines Geldbeutels zu entledigen. XPlore by XCaret ist ein auf Action ausgelegter Freizeitpark, der mir persönlich von den meisten Angeboten am besten gefallen hat.

Den wohl schönsten Strand hat Tulum. Wo es nachts unter sternklarem Himmel nichts besseres gibt als mit einem Bier das Meeresrauschen zu genießen. Hier ist etwas Vorsicht geboten. In Mexiko ist das Konsumiren von Alkohol in der Öffentlichkeit sowie im Auto verboten. Das kann zu Geldstrafen führen. Und immer daran denken den eigenen Müll wieder mitzunehmen.

Die wohl beste Beschäftigung ist schwimmen gehen. Aber niemals die Sonne unterschätzen. Auch bei bewölktem Wetter fängt man sich sehr schnell einen schweren Sonnenbrand ein. Yukatan ist ein sehr schöner Fleck auf der Welt. Ein Urlaubsparadies in dem auch Mexikaner ihrem Alltag entfliehen. Wohlgemerkt die wohlhabenderen der Einwohner.

Veröffentlicht unter Roadshow | Verschlagwortet mit , , , , , | Kommentar hinterlassen