31 July 2018

Strong Opinions

As Code Cop I meet a lot of developers and I have to tell some of them that their code is crap and that they need to drive down their technical debt. Others need to test more, maybe start doing TDD. There are a few who would not listen. Some of them are even proud of stubbornly not listening, they say that they have strong opinions about the topic. They do not seem interested in in another view on their code or design? Why is that? I have some ideas.

GorillaDunning Kruger Effect
The Dunning Kruger Effect is a cognitive bias in which people of low ability have illusory superiority and mistakenly assess their cognitive ability as greater than it is. In other words, beginners believe themselves senior and think that they know better. There is no need to listen to an outsider.

I know this effect myself: When I learnt my first programming language(s), as soon as I could write a few lines of code, I felt invincible. (I thought that) I could do everything. I ruled. I knew how to do it and I knew I was right and that there was no other way to do it properly. Today, after writing code for 20 years in more than 25 languages, I do not feel like that any more. Sometimes I would like to go back to my state of mind of the late nineties and I try to look at new languages like a child - with a beginner's mind - but I know too much details. I know there will be nasty details, even for that newest and hottest languages of today.

Expert Beginner
An expert beginner has quickly reached (what looks like) expert status. He or she voluntarily ceases to improve because of a belief that expert status has been reached and thus further improvement is not possible. (I recommend reading the whole series of Erik Dietrich, How Developers Stop Learning: Rise of the Expert Beginner and further posts of his series.) Expert beginners make up defending arguments because they are the experts.

I have met some of these. I vividly remember two senior developers who had been with one of my clients for more than 16 years. They were opposing me on everything I said. Sure they had a superior knowledge of the application they had built and maintained for so many years, and they knew the domain they were working in pretty well. I am sure they were adding value to the product. They both were strong influencers. As soon as they would speak their mind, all other team members would just agree. But, but, but... Sigh. They were still using Ant, did not know Maven, did not write unit tests, did not care for clean code and so on - they made me very unhappy.

Quadrants of Knowledge
The quadrants of knowledge seem connected to my previous points. The four quadrants are
  1. Known Knowns: What you know that you know
  2. Unknown Knowns: What you do not know that you know
  3. Known Unknowns: What you know that you do not know
  4. Unknown Unknowns: What you do not know that you do not know
When we advance our career in software delivery, we learn: We collect concrete knowledge (quadrant 1), we gain experience which allows us to have gut feelings about some things (maybe quadrant 2) and we hear about things that we have no idea about (quadrant 3). There are gazillion things in software that I have no idea of: ANTLR, APL, AWS, Category Theory, Distributed Computing, Elm, Gradle, Guava, Haskell, HBase, J2EE, Kubernetes, Mongo DB, Networking, Node.JS, Prolog, Security - these are just the first few that come to my mind. It is easier to list things which I do not know in areas that I do know. I have been Java developer for 15 years and there are so many things in the Java ecosystem which I have no clue about. On the other hand there are not many things I can say about C#, because I only know it little.

So the more we learn, the more we know that we do not know, increasing our Known Unknowns (quadrant 3). The philosopher Confucius (551–479 BC) even said, Real knowledge is to know the extent of one's ignorance. Like the Dunning Kruger Effect, beginners have no idea about the vast size of Known Unknowns quadrant and do not expect surprises or potential improvements.

Strong Opinions, Weakly Held
The ideas of the Dunning Kruger Effect, Expert Beginners and Known Unknowns offer some explanation why some junior developers are not open for discussions. I have also met senior and expert level developers who are the same. When attending Software Crafting unconferences, e.g. SoCraTes, attendees are eager to learn and open for discussion. After all, that is the idea of unconferences, right? Still, many of them have strong opinions about almost everything, e.g. Spring Boot is cool. No, Spring Boot is hell. ;-) Different from beginners, all of them know the problems of strong opinions and claim that they only hold onto them weakly.

Deal with itWeakly Held, what is that supposed to mean? Isaac Morehouse explains in These Four Words Will Help You ‘Hold Strong Opinions Weakly': You act as if they [your opinions] are true unless and until it is proven they are not. Maybe people like strong opinions because they give them the power of definiteness. Choices are much easier and life is more predictable with definiteness and absolutes. Holding opinions weakly also gives the power of openness. This sounds hard: Basing one's actions on some definite "truths" and re-evaluating these truths whenever they are challenged. Seems like a difficult balancing act, if not a contradiction. For sure that state of mind is not easy to get into. I still need to see someone with strong opinion - weakly held or not - to change his or her mind,

Rant
When I started this article, it was supposed to be a rant. As usual, writing down my thoughts helped me to structure the material in a better way. (I consider writing an act of learning.) So where is the rant? Here it is:

Person with strong opinion == arsehole who does not want to listen.

That is a bit harsh, I agree. Obviously beginners need to listen more and due to Known Unknowns I expect experienced and expert developers to be open to discussion on any topic at any time. The strong opinion itself is not the problem, but the resulting behaviour, especially if strong opinion is used as warning or justification of some sort. I witness strong opinion mainly as excuse to not discuss or challenge existing views.

What about me?
Of course I had strong opinions during my professional life. I did not earn the nick name of Code Cop for nothing. Someone even called me Code Nazi. And my opinions were definitely not weakly held. I like absolutes. (Now I see - as I just learned above - the power of definiteness.) I guess I still have some strong opinions, and they are not just opinions, they are dogma: a system of principles proclaimed as unquestionable.

I have changed and it seems that the Code Cop is getting soft. ;-) The extended experience and discussions have weakened my definiteness. There is always some special case, the almighty it depends. And since I am working with people, and try to help them, I am more compassionate. I understand their problems, the difficulty to get time for quality and the pain of legacy code. Sometimes I catch myself not recommending what I believe the technically best course of action because it will be a lot of unpleasant, hard work for the team. No, that is too soft. If they made a mess, they have to fix it. Time to fall back on dogma. (Sound of firing cannons in the background ;-) All the time these balancing acts...

25 July 2018

Only modified files in Jenkins

For a custom Jenkins build I needed to know all changed files since the last green build. I searched a lot and found a solution as combination of several StackOverflow answers. It took me some experimenting to get it working: I installed the Groovy plugin, configured the Groovy language and created a script which executed as system Groovy script. Here is the complete step by step guide for Jenkins 2.63, SVN and Groovy 2.4.11.

Jenkins only provides the current revision in the environment variable $SVN_REVISION. Of course Jenkins knows the information about changed files of each build as it is shown in the build status page. I guess a plugin would be able to access the model, but that is too much work. Fortunately the Jenkins Groovy plugin allows scripts to run under the system context having access to hudson.model.Build and other classes.

Groovy!Groovy Programming Language
The Groovy programming language is a dynamic language which runs on the JVM. It integrates smoothly with any Java program and is the first choice for scripting Java applications. While not strictly necessary I recommend downloading the SDK's zip and unpacking it on the host where you run Jenkins, usually into the folder where you keep your development tools. For testing and debugging I also install it on my local workstation (in the same location).

Groovy in Jenkins
Next comes the Jenkins Groovy plugin. Open Jenkins in the browser and navigate the menus:
  • Manage Jenkins
  • Manage Plugins
  • select tab Available
  • filter "groovy"
  • select Groovy
  • Install
(You will need Jenkins admin rights to do so.) Then tell Jenkins which Groovy to use and where to find it. To configure the Groovy language go to
  • Manage Jenkins
  • Global Tool Configuration
  • go to section Groovy
  • Add Groovy: Give it a name and set GROOVY_HOME to the folder you unpacked it, e.g. /tools/groovy-2.4.11.
  • deselect Install automatically
  • Save
Now Jenkins supports Groovy scripts.

Run a Groovy script in the build
Now let's use a Groovy script in the project. On the project page,
  • Configure
  • go to section Build
  • Add build step
  • select Execute system Groovy script
  • paste Groovy code into the script console
  • Save
Now when you trigger the build, the script will be executed.

Debugging the Script
Of course it does not work. How can I debug this? Can I print something to the console? Groovy's println "Hello" does not show up in the build log. Searching again, finally the gist by lyuboraykov shows how to print to the console in system scripts: Jenkins provides the build console as out variable,
out = getBinding().getVariables()['out']
which can be used like out.println "Hello". Much better, now I can debug. Let's wrap the out.println in a def log(msg) method for later.

The MisfitsGetting the changed files of the current build
StackOverflow answer by ChrLipp shows how to get the changed files of the current build:
def changedFilesIn(Build build) {
  build.getChangeSet().
    getItems().
    collect { logEntry -> logEntry.paths }.
    flatten().
    collect { path -> path.path }
}
This gets the change set hudson.scm.ChangeLogSet<LogEntry> from the build, gets the SubversionChangeLogSet.LogEntrys from it and collects all the paths in these entries - this is the list of all file paths of all changed items in all commits (LogEntrys). I guess when another SCM provider is used, another type of ChangeLogSet.LogEntry will be returned, but I did not test that. To better understand what is going on, I added explicit types in the final Groovy script, which will only work for Subversion projects.

Getting all builds since the last successful one
I want all changed files from all builds since the last green one because they might not have been processed in previous, failed builds. Again StackOverflow, answer by CaptRespect comes to the rescue:
def changedFileSinceLastSuccessfull(Build build) {
  if (build == null || build.result == Result.SUCCESS) {
    []
  } else {
    changedFilesIn(build) +
      changedFileSinceLastSuccessfull(build.getPreviousBuild())
  }
}
In case there is no previous build or it was successful the recursion stops, otherwise we collect changed files of this build and recurse into the past.

All Together
Let's put it all together,
def changedFiles() {
  def Build build = Thread.currentThread()?.executable
  changedFileSinceLastSuccessfull(build).
    unique().
    sort()
}
After collecting all duplicates are removed, as I do not care if a file was changed once or more times, and the list is sorted. In the end the list of changed files is saved as text changed_files.log into the workspace. (The full script is here.)

Leave space to VIPs and journalistsWhile developing the script, the Jenkins script console was very handy. As soon as the script worked, I created a file jenkins_list_changed_files.groovy, put that under version control and changed the build definition step to use the script's file name. Next time the build ran, the script file would be executed, or at least so I thought.

Script Approvals
Unfortunately system Groovy script files do not work as expected because Jenkins runs them in a sandbox. Scripts need certain approvals, see StackOverflow answer by Maarten Kieft. To approve a script's access to sensitive fields or methods navigate to
  • Manage Jenkins
  • In-process Script Approval (This is the one but last item in the list.)
  • Approve
The sandbox is very restrictive, the full jenkins_list_changed_files needs a lot of approvals:
field hudson.model.Executor executable
method groovy.lang.Binding getVariables
method hudson.model.AbstractBuild getChangeSet
method hudson.model.AbstractBuild getWorkspace
method hudson.model.Run getNumber
method hudson.model.Run getPreviousBuild
method hudson.model.Run getResult
method hudson.scm.SubversionChangeLogSet$LogEntry getPaths
method java.io.PrintStream println java.lang.String
new java.io.File java.lang.String
staticMethod java.lang.Thread currentThread
staticMethod org.codehaus.groovy.runtime.DefaultGroovyMethods flatten java.util.List
staticMethod org.codehaus.groovy.runtime.DefaultGroovyMethods println java.lang.Object java.lang.Object
staticMethod org.codehaus.groovy.runtime.DefaultGroovyMethods sort java.util.Collection
staticMethod org.codehaus.groovy.runtime.DefaultGroovyMethods withWriter java.io.File groovy.lang.Closure
Creating a new java.io.File might be a security risk, but even println is not allowed. Adding all these approvals is a boring process. The build breaks on each missing one until everything is well. As soon as you have all the approvals, you can copy Jenkins' scriptApproval.xml found in JENKINS_HOME (e.g. ~/.jenkins) and store it for later installations. Here is mine.

Conclusion
Jenkins' Groovy integration is very powerful. System scripts have access to Jenkins' internal model which allows them to query information about build, status, changed files etc. On the other hand, development and debugging is cumbersome and time consuming. IDE support helps a lot. Fortunately StackOverflow knows all the answers! ;-)

23 July 2018

Three Rules of Coaching Engagement

Last year software crafter and Kotlin enthusiast Oleksii Fedorov asked me about technical coaching. He was going to work with a small team and focus on technical enablement. He would do so by pair and mob programming with them for some time and later support them remotely if needed. During that time there would be no pressure or deadline to deliver new features so they could focus on improving.

Oleksii is a like-minded peer. I met him on several occasions in the past. He is fun to work with and considers teaching an integral part of pair programming. I did not expect any problems. He kept pushing me and made me think about my principles. In the end I came up with three points I like to make clear right from the beginning, i.e. set the ground rules of the engagement.

Drill Sergeant Giving Orders (maybe not coaching ;-)1. Manage expectations
Managing expectations is crucial. I learnt that the hard way during my Pair Programming Tour. Whenever I run a session, e.g. pair or mob programming and often also prepared workshops, I start with a discussion to collect expectations. For longer contracts I recommend to start with a dedicated meeting to do so. Usually expectations are fuzzy, like "I want to learn something", so keep pushing with questions like "How will you know it was worth it? How will you measure that you learned something?" and so on. In the end I want the team to come up with ways to measure their learning and define their own success metrics.

2. Learning is their responsibility
Oleksii planned for two weeks. In two weeks people will not change (much). Such a coaching engagement does not last long enough for much impact, rather it is a start of a (maybe even life long) journey of learning and improving. This is true from day one and during the initial meeting I make it clear that I am not a teacher. I will not push knowledge onto them to be forgotten the next day. To get something from working together, people have to participate, to engage, to invest time and effort into the topic. They will only get so much from it what they have put into it themselves. Learning is their responsibility.

3. Treat them as strangers
After removing the responsibility to teach anything - because learning is their responsibility - I feel less stressed. As coach I am still responsible for creating a safe space, providing content, managing exercises and a lot of other things. If someone does not want to participate or feels like doing something else, I have to be OK with that. Even being paid for "teaching" should not change that. My advice here is to treat the team members as "strangers", like we treat new visitors of a Coding Dojo. As a facilitator I try to help, but I will not oppose or coerce.

Feedback
Oleksii started the job soon afterwards. I was sure everything would work out fine. When we met again he told me that my three rules had helped him. 1. He collected expectations in the beginning and managed them while moving forward. 2. People understood that they had to invest and some participants even showed up for sessions during their free time. 3. People where entering and leaving sessions all the time, still he stayed relaxed.

13 July 2018

Categories of Architectural Refactoring

At the end of one of my refactoring workshops, we started discussing how to refactor
larger structures, sometimes even changing the architecture of a system. During that discussion we came up with four different categories of larger refactoring which use different techniques and serve different goals:
  • Replace whole parts
  • Change the structure of components
  • Similar change all over the place
  • Other changes
Seoul SkyscrapersWe struggled to find good names, so let me explain the different things a bit. When I talk about architecture, I mean Software Architecture of a single application, i.e. 1. the different software components and 2. their (inter-) dependencies making up the application. Components are sub-systems and usually contain one or more namespaces or packages. While we can discuss forever what exactly software architecture is and is not, I like the definition of IEEE which in addition to elements (1.) and relationships (2.) adds principles of its design and evolution. I describe these principles as 3. design guidelines which include smaller recommended usage patterns and coding conventions.

Martin Fowler and Neal Ford say that architecture is the stuff that's hard to change later and replacing parts of the architecture involves a lot of work: Imagine (the highly theoretical example of) changing the programming language a system is written in or (a more common example of) moving from a monolith to a Microservice based architecture. These two examples already fall into different categories.

Replacing whole parts of the architecture
Massive changes like changing the UI technology or targeting another platform are possible but a lot of code has to be rewritten. Substitute Algorithm is a classic Fowler refactoring, and so is Substitute Architectural Decision. (This is my third try to name these category of changes.) Architectural Decisions are made to support non-functional requirements like performance, security, connectivity etc and when revisiting them later - with more domain knowledge - better alternatives might come up. Real examples of changing Architectural Decisions include:
  • Replacing one relational database system with another
  • Replacing your relational database with a NoSQL one
  • Replacing UI technologies, e.g. moving from JSF to Vaadin
  • Changing API technologies, e.g. moving from SOAP to REST
  • Switching from a fat client to a client-server architecture
Depending on used frameworks and abstractions, some of these changes will be easy, others will not. Even when the necessary change is isolated, it likely touches more than one architectural component. For example moving to another data store might need changing all data access objects in all components which access the data store. The traditional approach is to change everything at once ("Big Leap") but it is possible to refactor the architecture in a safe way, using small steps. In Responsive Design (QCon 2009) Kent Beck describes several strategies to perform such changes:
  • Leap: Make the new design and use it immediately. (Only if the change is not too big.)
  • Parallel Change: Make the new design and run both new and old simultaneously.
  • Stepping Stone: Create a platform to bring the desired new design within reach.
  • Simplification: Only implement part of the design now and add complexity bit-by-bit later.
  • Hack it: Just do it and pay price later. (This is maybe not a real strategy ;-)
Changing the structure of architectural components
The next category is similar to Substitute Architectural Decision but is focused on the architectural building blocks - the components. Some examples are:
  • Introduce or extract new component, module or package
  • Remove or invert dependencies between components, e.g. remove cyclic dependencies
  • Introduce layering, add a new layer, clean up layering violations
  • Weaken potential trouble spots in the architecture, e.g. Butterfly, Breakable, Hub and Tangle
foundationThis category of changes is the "classic" Architectural Refactoring because that is how people call it. For example - in accordance to Martin Fowler's definition - Dave Adsit defines Architectural Refactoring as intentionally changing the structure of a system without altering its features. Similarly Sean Barow explains Architectural Refactoring as the deliberate process to remove architectural smells while not changing the scope or functionality of the code. So it is always structural and deals with components (1.), their relationships (2.) and their inner structure. Let's call it Refactor Architectural Structure to distinguish it from other architectural refactoring.

Sean Barow uses the term Code Refactoring for the refactoring defined by Fowler. Code refactoring focuses on software entities like classes, methods, fields and variables. Architectural refactoring involves code refactoring, which leads to confusion between the two. Working with dependencies needs extracting or moving classes, methods or fields. We can work each class or dependency at once, which supports an incremental approach.

Performing similar changes throughout the whole project
This is another category and it feels like Shotgun Surgery: A usually small change has to be repeated all over the place. While Shotgun Surgery is a code smell for feature logic, it is unavoidable if not required for consistent structure and usage defined by the architecture. For example let's assume we want to replace EasyMock with Mockito. Both libraries serve the same purpose and are used in a similar way, but their APIs are different. (Facing such a problem indicates that we are coupled to much to a used library - maybe we should have wrapped it, maybe not. But that discussion is outside the scope of this article.) Converting a single usage of EasyMock to Mockito is straight forward: We change the method invocations and execute the calls earlier or later in the test. The only problem is that we have hundreds of such cases. (Update 31st October 2018: Some people have pointed out that build tools and testing frameworks are not considered part of the architecture. In that case a migration between mocking libraries is misleading and I should have used another example. Still the idea is the same.) More examples of similar "Shotgun" changes are:
  • Upgrading a major version of a library with breaking API changes
  • Migrating between similar frameworks or libraries
  • Changing or unifying coding conventions and fixing violations
  • Consistently applying or changing aspects like logging or security
  • Applying internationalization
These changes do not change the overall structure, they just work on the implementation. They are similar to Refactor Architectural Structure, just deal with design guidelines, coding conventions and smaller usage patterns - item 3 from the definition of Software Architecture in the beginning. They are code refactoring applied in many places consistently across a whole code base.

These category is important, because some steps of both Substitute Decision and Refactor Structure need similar changes. The main challenge of these changes is the high number of occurrences. Changing conventions and aspects is a piece by piece work and can be done manually. Nevertheless some automation tool or script would help a lot. Even converting only basic scenarios, which often cover up to 80%, is a big win. Unfortunately some changes, e.g. migrating libraries, need to be done all at once. In such cases a Stepping Stone approach has worked well for me in the past: First wrapping the library piece by piece - incrementally - and then changing the wrapper and all invocations at once. Creating the wrapper is a lot of work. Again, automated migration removes the need for a wrapper. There are some options available, which I will cover in a future article.

I have not found a good name for this category. I used to call it Large Scale Refactoring, but I am not happy with that name. It is a similar or identical code refactoring applied to many places widespread throughout the code. It is a Widespread Architectural Change.

Other Architectural Changes
During our initial discussion, we also considered other refactoring. To be on the safe side, always allow a category of unknown things ;-). At the moment I have no real examples for them. These are smaller changes neither related to architectural decisions or structure nor are they widespread. I believe we find no examples because these are plain code changes and we do not consider them architectural even if they are related to the architecture of the applications in a way.

FavelaSummary
Next to the code we also can and should refactor the architecture of our applications. Architectural changes are expensive, still sooner or later things need to change if the application is in service just long enough. There are at least four categories of architectural refactoring:
  • Substitute Architectural Decision
  • Refactor Architectural Structure
  • Widespread Architectural Change
  • Other Architectural Changes
After discussing the topic with some friends, I wrote a followup with clarifications. I also used some tools to automate Widespread Architectural Changes.

3 July 2018

Using NATstyle from the commandline

Last year a new client contracted me to help them make their development process, their development environment and tooling "state of the art" (aka up do date). From the coding perspective that included - among other things - using a decent IDE, writing unit tests, having some Continuous Delivery pipeline in place and using static code analysis. I thought that it should not be too difficult, right? It was, but that is not the goal of this article. Today I want to describe the static analysis features and how to use it.

Earth Sapphire Progress Picture 30 july-2011NATURAL
The code base was NATURAL. NATURAL is an application development and deployment environment using a proprietary language maintained by Software AG. It was created in 1979. André describes it as Cobol's ugly, brain-damaged, BABBLING IN ALL-CAPS - but regrettably still healthy and strong - cousin.. ;-) Well, it is a procedural language structured using modules, subroutines and functions. It feels as old as it is. For example, module names are limited to eight (8!) characters and there is no way to structure the modules further. An enterprise application might contain 5.000 to 10.000 modules. To me NATURAL feels much like early Pascal: units (modules), subroutines and functions together with the eight characters DOS name limit. I really liked Pascal back then and I do not feel that bad about NATURAL. Probably also because I do not have to use it on a daily basis.

NaturalONE and NATstyle
NaturalONE is the Eclipse-based tool for NATURAL by Software AG. It looks pretty good, similar to what you would expect from Eclipse. It contains the usual features like Outline, Search, Debug and something called NATstyle. Now NATstyle - which probably on purpose sounds similar to the well known Checkstyle - is an utility to define and check the coding standard in your programs. It is used inside NaturalONE, see a NATstyle Demo by Software AG. (For more information refer to the Eclipse/NaturalONE help topic Checking Natural Code with NATstyle.)

Invoking NATstyle from outside NaturalONE
I like static code analysis and consider it a mandatory component of every delivery pipeline. As I said above, I wanted to have some static code analysis and was wondering if I would be able to run NATstyle in the pipeline? I did not find any information on the topic and was forced to experiment. I used NaturalONE 8.3.5.0.242 CE (November 2016) and figured out several ways, which were hardly documented, and might be subject to change. Likely there are other options available in newer versions of NaturalONE and NATstyle.

Invoking NATstyle from command line
NATstyle is just an Eclipse plugin inside NaturalONE. In my edition it is the folder C:\Natural-CE\​Designer\​eclipse\​plugins\​com.​softwareag.​naturalone.​natural.​natstyle_8.3.5.0000-0242. With the proper class path it is possible to invoke NATstyle's main method, which prints help on its usage:
Usage: com.softwareag.naturalone.natural.natstyle.NATstyle [-options]

where options include:
  -projectpath <directory> Specify where to find the Natural project.
  -rootfolder              Library root folder support enabled.
  -c <file>                Specify the configuration file.
  -o <file>                Specify the output file.
  -sourcefiles <srcList>   Specify list of source files to be loaded.
                           separated with ;
  -libraries <libList>     Specify list of libraries to be loaded.
                           separated with ;
  -exclude <libList>       Specify a list of libraries to exclude.
                           separated with ;
  -p <directory>           Specify where to find additional packages.
  -help                    Display command line options and exit.

Make sure the following classes can be found in your class path:

com.softwareag.naturalone.natural.auxiliary
com.softwareag.naturalone.natural.common
com.softwareag.naturalone.natural.parser
Nice, that looks like the developers from Software AG prepared NATstyle to be called stand-alone in my pipeline. +1. All the necessary classes can be found in the following plugins of Eclipse/NaturalONE:
  • Folder com.softwareag.naturalone.natural.natstyle_8.3.5.0000-0242
  • Jar com.softwareag.naturalone.natural.auxiliary_*.jar
  • Folder com.softwareag.naturalone.natural.common_8.3.5.0000-0242
  • Jar com.softwareag.naturalone.natural.parser_*.jar
  • Jar org.eclipse.equinox.common_*.jar
These are all bundles defined by Eclipse/OSGi. The list of dependencies of these bundles also contains the following Jars
  • org.eclipse.swt.win32.*.jar
  • org.eclipse.ui.console_*.jar
which (in my experience) are not needed to use NATstyle. NATstyle does not use any other OSGi features and we can set the needed class path by hand. Here is an example how to do that in the Windows shell when NaturalONE is installed:
set N1=C:\Natural-CE\Designer\eclipse\plugins
set CLASSPATH=^
%N1%\com.softwareag.naturalone.natural.natstyle_8.3.5.0000-0242;^
%N1%\com.softwareag.naturalone.natural.auxiliary_8.3.5.0000-0242.jar;^
%N1%\com.softwareag.naturalone.natural.common_8.3.5.0000-0242;^
%N1%\com.softwareag.naturalone.natural.parser_8.3.5.0000-0242.jar;^
%N1%\org.eclipse.equinox.common_3.6.200.v20130402-1505.jar

java com.softwareag.naturalone.natural.natstyle.NATstyle %*
See run_natstyle for the script I used to run NATstyle directly. Copying the needed folders and Jars to another machine works well. I recommend to create a Jar from the folders before copying them around. create_jar how to do that. Make sure not to include META-INF\*.RSA or META-INF\*.SF into the new Jars because the checksums do not match. copy_jars does the actual copying into the lib folder.

Invoking NATstyle from Ant
NaturalONE supports Ant for some automation tasks. There is no specific NATstyle Ant task, but calling it from Ant is straight forward. If the path <path id="natstyle.classpath"> is set up to contain all the Folders and Jars, NATstyle is executed via Ant's java task:
<java taskname="natstyle"
      classname="com.softwareag.naturalone.natural.natstyle.NATstyle"
      dir="${basedir}" fork="true" maxmemory="128m"
      failonerror="true"
      classpathref="natstyle.classpath">
  <arg value="-projectpath" />
  <arg value="../NatUnit/NatUnit_L4N" />
  ...
</java>
A new JVM needs to be forked because NATstyle calls System.exit() at the end. All parameters are the same as for the command-line invocation and are passed in via the <arg /> element. See ant_NatStyle.xml for the complete Ant script.

Reporting
NATstyle writes an XML report of all files if worked and found rule violations. The structure is
<NATstyle>
  <file type='...' location='...'>
    <error severity='...' message='...' />
    ...
  </file>
  ...
</NATstyle>
Inside the folder of NATstyle (i.e. com.softwareag.naturalone.natural.natstyle_8.3.5.0000-0242) there is a subfolder NATstyle. It contains sample files. Using the provided NATstyleSimple.xsl the report XML (e.g. NATstyleResult.xml) can be transformed into a human-readable format (e.g. NATstyleSimple.html). When using NATstyle stand-alone, you might want to copy this folder as well. XSLT transformation task is part of Ant and converts the XML to HTML.
<xslt basedir="${basedir}"
      destdir="${basedir}/report"
      style="${basedir}/NATstyle/NATstyleSimple.xsl">
  <include name="NATstyleResult_*.xml" />
</xslt>
See ant_NatStyleResultToHtml.xml for the complete Ant build script to convert the NATstyle result XML into a readable HTML report. Using your own stylesheet (.xsl) allows you to customize the report. See how to convert the report into more complex formats.

Next time I will show you how to write your own NATstyle rules.