Author Archive: boriny

Dear Scrum, a Sprint feels like running. Please get your terminology right!

It’s been a long time since I wrote the last (technical) entry. The reason for that is that my work changed a lot: I switched from a software project to product development, my role changed from developer/architect to project lead something. Finally, I ended up as Product Owner in a team developing a great software product (I will come back to the product in following posts).

No doubt: Scrum comes with a lot of great ideas! They are even applicable on a product development process. But on the other hand, there are some strange terms and metaphors which may lead to misunderstandings (at least they were misunderstood in the two or three teams that I was part of) in the Scrum process. Taking these terms/metaphors too literally may be contra-productive. Let me point this out:

The first term is the self-organizing Development Team. What I witnessed as misunderstood is the term “self-organizing”. I survived development processes where “self-organizing” was interpreted as “each decision must be taken unanimously”. It ended up in endless discussions without any result. It felt like (and it was as productive as) the UN Security Council. In contrast to this, I think the “Team” metaphor is excellent. The DFB (German Football Association) states that it is an important skill for team coaches to identify the team leaders and to build team hierarchies. The Scrum Guide says the same in other words: “Development Teams are structured … to … manage their own work”. They are structured! “Equal rights for everyone” is definitely a structure, but I don’t think it’s always the best structure for a Development Team.

The second term is the metaphor Sprint. A sprint (in sports) is breath-taking and exhausting. I don’t want my Team to be exhausted. The metaphor suggests that Scrum will raise your development speed, and that is sometimes the expectation of Stakeholders or Scrum Team Members. That is as true as a partitioning a marathon run into 422 consecutive sprints of 100 meters will make you run the marathon faster. You’ll end up in hospital.

toomuchtasks
By the way: I found this item on a flipchart in a meeting room right after a Sprint Retro.
I prefer “iteration” over “Sprint”. Am I too old-fashioned?

The next point is the term Scrum itself. A Scrum is a situation in a Rugby match where  the players of the two teams “close up with their opponents so that the heads of the front rows are interlocked.” … and then they push and shove and kick in order to get the ball. In a Scrum product development, who is the opponent team? Which person do I have to kick (or who pushes me)? I really don’t like this metaphor.

Last point: The Scrum Guide states that Scrum is a framework for developing and sustaining complex products. It defines the role Product Owner. So, if you apply Scrum on your software development process, please ask yourself: Am I developing a product? If not, what are the consequences if applying Scrum?

So, Scrum enthusiasts and doubters, I herewith invite you to “close up with me so that our heads are interlocked. “. In other words: I’m looking forward to your comments.

Separate JUnit`s log-output per testcase

Note to self:
When lost in the log of a TestSuite, this simple example of a JUnit Runner may help.

package com.thyssenkrupp.tkse.qbic.tests.runner;
import org.apache.log4j.Logger;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
public class LoggingBlockJUnit4ClassRunner extends BlockJUnit4ClassRunner {
  private static final Logger LOG = Logger.getLogger(LoggingBlockJUnit4ClassRunner.class);
  public LoggingBlockJUnit4ClassRunner(Class< ? > klass) throws InitializationError {
    super(klass);
  }
  @Override
  protected void runChild(FrameworkMethod method, RunNotifier notifier) {
    LOG.info(">>> Running " + method.getMethod().getDeclaringClass().getSimpleName() + "." + method.getName());
    super.runChild(method, notifier);
    LOG.info("<<< End Run " + method.getMethod().getDeclaringClass().getSimpleName() + "." + method.getName() + "\n\n");
  }
}

Xtext Usability: Hovers on keywords

Xtext is making it’s way becoming a framework not only for domain specific languages spoken, authored and read by programmers, but also by real (business-) domain experts themselves. Sometimes these guys have reservations such as “a (textual) editor can never provide as much guidance as a form can”. The weirdos among them even want intuitive and fail-safe ready-to-go solutions instead of one week training bootcamps. This post is the start of a series introducing Xtext features meeting such requirements.

The first one is about hovers on keywords. Christian has posted a nice tutorial about how to costumize Xtext’s standard hovers, e.g. A custom Xtext hover

Out of the box, Xtext supports hovers only for identifying features of model artifacts, i.e. the name of an object or crosslinks to other objects: The hover in the example above pops up when the cursor is over “Hover” (the name of a Greeting), but not when it is over “Hello” (which is a keyword belonging to a greeting).

I’m going to show how to adjust Xtext’s Domain-Model Example to show hovers on keywords, such as
KeywordHover

We adjust the HoverProvider and the EObjectHover

package org.eclipse.xtext.example.domainmodel.ui.hover;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.internal.text.html.HTMLPrinter;
import org.eclipse.jface.text.IRegion;
import org.eclipse.xtext.Keyword;
import org.eclipse.xtext.ui.editor.hover.html.XtextBrowserInformationControlInput;
import org.eclipse.xtext.xbase.ui.hover.XbaseHoverProvider;
import com.google.inject.Inject;

public class MyXbaseHoverProvider extends XbaseHoverProvider {
	/** Utility mapping keywords and hovertext. */
	@Inject MyKeywordHovers keywordHovers;

	@Override
	protected XtextBrowserInformationControlInput getHoverInfo(EObject obj, IRegion region, XtextBrowserInformationControlInput prev) {
		if (obj instanceof Keyword) {
			String html = getHoverInfoAsHtml(obj);
			if (html != null) {
				StringBuffer buffer = new StringBuffer(html);
				HTMLPrinter.insertPageProlog(buffer, 0, getStyleSheet());
				HTMLPrinter.addPageEpilog(buffer);
				return new XtextBrowserInformationControlInput(prev, obj, buffer.toString(), labelProvider);
			}
		}
		return super.getHoverInfo(obj, region, prev);
	}

	@Override
	protected String getHoverInfoAsHtml(EObject o){
		if (o instanceof Keyword)
			return keywordHovers.hoverText((Keyword) o);
		return super.getHoverInfoAsHtml(o);
	}
}


 

package org.eclipse.xtext.example.domainmodel.ui.hover;

import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.text.IInformationControlCreator;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.xtext.Keyword;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.ui.editor.hover.IEObjectHoverProvider;
import org.eclipse.xtext.ui.editor.hover.IEObjectHoverProvider.IInformationControlCreatorProvider;
import org.eclipse.xtext.util.Pair;
import org.eclipse.xtext.xbase.ui.hover.XbaseDispatchingEObjectTextHover;

import com.google.inject.Inject;

public class MyXbaseDispatchingEObjectTextHover extends XbaseDispatchingEObjectTextHover {

	@Inject
	MyKeywordAtOffsetHelper keywordAtOffsetHelper;

	@Inject
	IEObjectHoverProvider hoverProvider;

	IInformationControlCreatorProvider lastCreatorProvider = null;

	@Override
	public Object getHoverInfo(EObject first, ITextViewer textViewer, IRegion hoverRegion) {
		if (first instanceof Keyword) {
			lastCreatorProvider = hoverProvider.getHoverInfo(first, textViewer, hoverRegion);
			return lastCreatorProvider == null ? null : lastCreatorProvider.getInfo();
		}
		lastCreatorProvider = null;
		return super.getHoverInfo(first, textViewer, hoverRegion);
	}

	@Override
	public IInformationControlCreator getHoverControlCreator() {
		return this.lastCreatorProvider == null ? super.getHoverControlCreator() : lastCreatorProvider.getHoverControlCreator();
	}

	@Override
	protected Pair<EObject, IRegion> getXtextElementAt(XtextResource resource, final int offset) {
		Pair<EObject, IRegion> result = super.getXtextElementAt(resource, offset);
		if (result == null) {
			result = keywordAtOffsetHelper.resolveKeywordAt(resource, offset);
		}
		return result;
	}
}


We also need to calculate the offsets of keywords and to specifiy the actual hover texts

package org.eclipse.xtext.example.domainmodel.ui.hover;

import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.xtext.Keyword;
import org.eclipse.xtext.nodemodel.ILeafNode;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.eclipse.xtext.parser.IParseResult;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.util.Pair;
import org.eclipse.xtext.util.Tuples;
/** Inspired by {@link org.eclipse.xtext.resource.EObjectAtOffsetHelper} */
public class MyKeywordAtOffsetHelper {
  public Pair resolveKeywordAt(XtextResource resource, int offset) {
    IParseResult parseResult = resource.getParseResult();
    if (parseResult != null) {
      ILeafNode leaf = NodeModelUtils.findLeafNodeAtOffset(parseResult.getRootNode(), offset);
      if (leaf != null &amp;&amp; leaf.isHidden() &amp;&amp; leaf.getOffset() == offset) {
        leaf = NodeModelUtils.findLeafNodeAtOffset(parseResult.getRootNode(), offset - 1);
      }
      if (leaf != null &amp;&amp; leaf.getGrammarElement() instanceof Keyword) {
        Keyword keyword = (Keyword) leaf.getGrammarElement();
        return Tuples.create((EObject) keyword, (IRegion)new Region(leaf.getOffset(), leaf.getLength()));
      }
    }
    return null;
  }
}


package org.eclipse.xtext.example.domainmodel.ui.hover

import org.eclipse.xtext.example.domainmodel.services.DomainmodelGrammarAccess
import com.google.inject.Inject
import org.eclipse.xtext.Keyword
// This is <a href="https://www.eclipse.org/xtend/">Xtend</a> , not Java
class MyKeywordHovers {
	@Inject DomainmodelGrammarAccess ga;
	def hoverText(Keyword k) {
		val result = switch (k) {
			case ga.entityAccess.entityKeyword_0: '''
				An entity represents real business objects. It <ul>
				<li> can <code>extend</code> another entity,i.e. inherit the features of another entity. 
				<li> has attributes, specification syntax <code>&lt;name&gt; : &lt;type&gt;</code>  
				<li> has operations, specification syntax <code>op &lt;name&gt; (&lt;List of Parameters&gt;)) : &lt;Returntype&gt;</code>
				</ul>
			'''
		}
		result.toString;
	}
}


We don’t forget to bind our implementations for Xtext’s dependency injection

public class DomainmodelUiModule extends AbstractDomainmodelUiModule {

	// ...
		
	@Override
	public Class<? extends org.eclipse.xtext.ui.editor.hover.IEObjectHover> bindIEObjectHover() {
		return MyXbaseDispatchingEObjectTextHover.class;
	}

	@Override
	public Class<? extends org.eclipse.xtext.ui.editor.hover.IEObjectHoverProvider> bindIEObjectHoverProvider() {
		return MyXbaseHoverProvider.class;
	}
}

Automated Javadoc compliance checking with Eclipse and Checkstyle – how and why (NOT!?)

No doubt: Javadoc comments are important. With the support of an IDE providing hovers and views showing Javadocs of the third party code that I’m just using  (or the one that my half-genius co-worker wrote two weeks ago and that I will never understand/or did I code this weird stuff?) they boost my programming performance. Since it’s a boost, isn’t it a good idea to utilize a tool that checks the existence and compliance of Javadoc automatically while coding? This one is about a good intention gone bad:
Once, I was in a developer team and they were enthusiastic about Checkstyle validating the Javadoc compliance – quite similar to David Carver who blogged about Checkstyle JavaDoc Compliance Checking. Here are just two illustrative examples of comments that had been written by that team:

  • Useful Constructor-Javadocs
    /** Creates an instance of MyClass. */
    public MyClass() {
    }
    /** @param someParam */
    public MyClass(int someParam) {
    }
    
  • Copy-Paste-Javadocs
     /**
     * Adds two addends.
     *
     * @param s1 an addend
     * @param s2 another addend
     * @return the sum of s1 and s2.
     */
     public int subtract(int s1, int s2) {
       return s1 - s2;
     }
    

I’ve seen comments that were empty, nonsense, redundant (either within the comment or redundant to the code itself), obvious, outdated, wrong and/or annoying. I even found a lot of real gems: Comments that were really helpful and important.  The prob was that independent of the content, Checkstyle considered each of them “compliant”. I ended up not trusting any of them and analyzing  the sourcecode instead of reading untrustworthy Javadocs. Another thing was that those strict Javadoc compliance rules in combination with tough deadlines prevented me from writing clean code: Instead of separating reusable steps of an algorithm into methods with a clear scope (“extract method” is usually one of my favorites) , I inlined these fragments because otherwise I had to javadoc my extracted methods, i.e. I had to write Checkstyle-compliant Javadoc which might more confuse than help my co-workers. And to make matters worse, the error markers of the Eclipse Checkstyle-Plugin which covered other markers (e.g. breakpoints) and it showed hovers with Checkstyle-complaints regarding the Javadoc instead of hovers showing the actual Javadoc (remember: That is one feature that boosts my performance. In this project, it had an opposite effect.)

So here’s my point:

  • You must not force anyone to write superfluous Javadocs.  You may want to read what Adam Bien wrote about How to JavaDoc (efficient and maintainable) (don’t be scared, it’s only ~ 30 Lines).
  • You must not use an automated Javadoc compliance checker without a process that covers quality assurance of the Javadoc content. If you are strict, be strict!
    If your coding guidelines are strict regarding Javadoc compliance, use an automated compliance checker. Assuming that strict guidelines indicate a high level of quality requirements, I think that in this case, reviews are not such a bad idea at all!

CFEngine workbench based on Eclipse and Xtext

Here’s a screencast showing a CFEngine-workbench that I built earlier this year.

CFEngine is a tool for system administrators that “has a powerful language and tools to define the desired state of your infrastructure”. The workbench is driven by the idea (some may think it’s crazy) of transfering the usability that software developers enjoy in IDEs into the usage scenarios for SAs .

Visualize Xtext models with PlantUML

In this post I show how (ab)use PlantUML to visualize Xtext models. Warning: This is about diagrams, not about UML.

PlantUML Intro

PlantUML is an “Open Source tool .. to draw UML using a simple and intuitive language”.
Let me just draw an example class diagram to demonstrate how it feels:
This PlantUML specification

@startuml
abstract class Superclass << general >>;
abstract AbstractCreator{
  {abstract} create() : Superclass
}
Superclass <|-- Subclass
note left of Superclass : Instantiation not possible 
ConcreteCreator-up-|> AbstractCreator 
ConcreteCreator : create() : Superclass
ConcreteCreator .> Subclass
@enduml

results in this diagram:
plantumlex1

PlantUML also provides an Eclipse plugin which dynamically visualizes the “current active diagram, i.e. the diagram where the text cursor is located”. Better than that, this plugin provides an extension which lets you contribute a diagramTextProvider for a given editor. This means you can specify custom visualizations (limited by the PlantUML’s “UML”-capabilities) for any editor input. And the best of it: It works dynamically, i.e. while typing.

Prereq: Adjust PlantUML plugin

The above mentioned diagramTextProvider – extension requires the specification of a providerClass, i.e. a class which creates the plantuml diagram spec for a given editor input. This class has to implement net.sourceforge.plantuml.eclipse.utils.DiagramTextProvider. For some reason, the plugin does not export this package, so you may want to add something like

Export-Package: net.sourceforge.plantuml.eclipse.utils

to the plugin’s manifest.

Update: The PlantUML guys adjusted the manifest already, so you can skip this step with the latest PlantUML-Version (see comment below)

Create Xtext Project

Create a new Xtext Project (accept all defaults).  Adjust the grammar to make it look like this

// dont adjust grammar header
Model: greetings+=Greeting*;
Greeting: from=ID 'says' message=STRING 'to' to=ID;

and run the GenerateMyDsl.mwe2-worklow.

Create diagramTextProvider

Navigate to the ui project of your language. Add a dependency to the PlantUML-plugin to the MANIFEST.MF:

Require-Bundle: ...,net.sourceforge.plantuml.eclipse;

In the plugin.xml, add the following extension point:

   <extension point="net.sourceforge.plantuml.eclipse.diagramTextProvider">
      <diagramTextProvider 
      fileExtensions="mydsl" 
           providerClass="org.xtext.example.mydsl.ui.plantuml.MyDiagramTextProvider">
      </diagramTextProvider>
   </extension>   

Implement MyDiagramTextProvider as follows:

class MyDiagramTextProvider extends AbstractDiagramTextProvider {
	
	def DomainmodelDiagramTextProvider() {
		fileExtensions = "mydsl";
		editorType = typeof(XtextEditor)
	}
	
	override String getDiagramText(IEditorPart editorPart, IEditorInput editorInput) {
		// Retrieve the "semantic" EMF from XtextEditor
		val document = (editorPart as XtextEditor).getDocumentProvider().getDocument(editorInput) as XtextDocument;
		val Model model = document.readOnly[
			return contents.head as Model
		]
		
		// Collect names specified in textual model into Set
		val allNames = new HashSet 
		model.greetings.forEach[if(from!=null) allNames.add(from); if(to!=null) allNames.add(to)]
		
		// draw some actors and labelled arrows
		'''
			actor «FOR n:allNames»:«n»: as «n»
			«ENDFOR»
			«FOR it:model.greetings.filter[from!=null && to!=null && message!=null]»
				«from»->«to»:«message»
			«ENDFOR»
		'''
	}
}

Some notes on this implementation:

Try it

Run the Xtext/PlantUML plugins. It looks like (note: the editor is dirty … it really works dynamically):
xtextGraphviz