Appreciating Scala – Java 2 scala example

August 24, 2013 by

One reason I appreciate the scala programming language is that it enables me to convert  a real life example of Java 7 code like this:

public static <T extends Annotation> String[] getMethodsWithAnnotation
  (Class<?> commandClass, Class<T> annotationClass)
  {
      ArrayList<String> result = new ArrayList<>();
      Method[] methods = commandClass.getMethods();
      java.util.Arrays.sort(methods, new Comparator<Method>() {
        @Override
        public int compare(Method m1, Method m2) {
            return m1.getName().compareTo(m2.getName());
        }});
      
      for(Method method : methods)
      {
         if (method.getAnnotation(annotationClass)!=null)
             result.add(method.getName());
      }
      
      return result.toArray(new String[result.size()]);  
}

into concise Scala code like this:

def getMethodsWithAnnotation[T <: Annotation]
  (commandClass: Class[_], annotationClass: Class[T]): Array[String] = {
    commandClass.getMethods
      .filter(m=>m.getAnnotation(annotationClass)!= null)
        .sortBy(m => m.getName()).map(m=>m.getName())
}

:-)

A new iOS App for software testers is born

May 30, 2013 by

My iOS App for IPhone and IPad is now freely available for download in the Apple AppStore. The App is a domain specific glossary made on behalf of the DSTB (Danish Software Testing Board) using the vocabularies from the ISTQB (International Software Testing Qualifications Board) in Danish and English. I aim to add more languages and an Android version as well if there is interest?

The App was officially released at the annual danish software testing conference today. At the same conference a competition was announced for who could find the “best” bug in the App. So for me it will be interesting to see what potentially 180+ professional testers can find of bugs (apart from the two minor issues we where aware of when we decided to release this in time for the conference) :-)

Screen Shot 2013-05-30 at 7.09.22 PM

P.S. If You have connections to your local ISTQB board and they are interested in a local version of the App in your language (possibly with a specific branding for your country) do let me know.

 

 

FYI: My presentation on Behavior Driven Development (BDD)

October 8, 2012 by

In case you are in the Copenhagen area and are interested in learning a bit about the many benefits of Behavior Driven Development (BDD), I am doing a 2 hour presentation on BDD for Dansk IT on the 30th October 2012 and a second 45 minute presentation for the Danish Software Testing Board (DSTB), at their general assembly on the 22th of November 2012.

About the presentation:

This presentation aims at testers, business analysts, developers and project managers that want to collaborate better and in a way that improves quality, agility and project economics.

Main subjects:

  • The communication gap between people of different professions using different processes, languages/notations, tools and skills.
  • How increased co-operation between testers, developers and requirements specialists are key for improving quality, agility and to reduce costs.
  • The agile method of Behavior-driven development (BDD) and how it relates to Test Driven Development (TDD).
  • Executable specifications, stories and scenarios.
  • Introducing BDD tool(s).
  • Testability, test automation and acceptance testing

A critique of Apple’s approach for iOS GUI localization and how to do it much better in your Apps

August 6, 2012 by

When developing software professionally it is critical to consider maintainability or in this case how additional/changed requirements (and bug-fixes) over time may be made easier/harder by your programming practices. Often quick dangerous gains are possible that are fast to implement in the short-run but becomes incredible burdensome over time as it makes future changes more and more difficult and costly. One such example is the famous anti-pattern of using “copy-paste” programming which, when used systematically, is a frequent symptom of lack of competence, lack of experience or an insufficient development environment/language.

So imagine my horror when diving into iOS programming for IPhone/IPad and finding out that the way Apple want you to localize your GUI is by effectively using “copy-paste”. More precisely, when using storyboards to define the GUI in Xcode, Apples wants you maintain separate versions for each language (storyboards are Apple’s latest GUI development feature in Xcode for iOS 5+)

Each storyboard contains a combination of gui-elements definitions, gui layout, interactions and outlet-connections to code elements. In other words, storyboard files are pretty comprehensive and complex. Storyboards (measured by their XML representation) are also pretty large. In my current iOS app, it is the largest source file bar none.

Small divergences between storyboards representing the same GUI but in different human languages, can result in program failures or crashes. Hence, having many localized storyboards for the same App makes the GUI potion of the app much more expensive to develop, test and change/maintain in much the same way the copy-paste anti-pattern does for code.

So what to do for iOS GUI localization when using storyboards?

It is pretty simple actually if you start by ignoring all Apple documents/tutorials on localizing storyboards/nibs and:

  1. Make sure you do not specify any languages under Localization in the storyboard settings.
  2. Make sure your storyboard file is not placed under any of the *.lproj localization folders (move it back into a suitable folder like your source root folder if necesary).
  3. Replace all texts/titles in the storyboard with placeholders (eg. “X” -> “<X>”) so you can still see what is what when editing the storyboard yet also see if something is unlocalized when running the app.
  4. Create storyboard outlets to properties in your code for all control elements that contain text.
  5. Make sure the project has the needed *.lproj localization folders. Add any missing languages under Project/Info settings.
  6. Make sure each *.lproj localization folder has a file called Localizable.strings as described by Apple for localized texts.
  7. Add localized texts strings for all your texts/titles in your Localizable.strings files in the typical key-value fashion as described by Apple for localized texts.
  8. In the viewDidLoad method, set the titles of all GUI elements to strings loaded from resource files. For example to localize the text on a button having an outlet property called ibButton, add code like this: ibButton.title = NSLocalizedString(@”myButton”, nil);
  9. Special case: The title used on the “Back” navigation item in navigation bars needs to be set in the controller before the controller which shows the navigation item. In the source controller use code like this: self.navigationItem.backBarButtonItem.title = NSLocalizedString(@”back”, nil)“.
  10. Run the app and verify that all placeholder texts are replaced by actual localized texts.

That is it. With just one storyboard (per device) you can easily add and maintain (and test) support for any number of languages in your iOS user interface!

My take on a software development success philosophy

July 2, 2012 by

Below I have compiled a list of  6 personal (overall) viewpoints about software development philosophy that I find particularly important when successfully running software projects. Some of them might be obvious (?), but then maybe not as I have observed that many projects don’t really adhere to them.  In fact, in many projects the opposite is done intentionally or not thus resulting in significant delays, cost overruns, unsatisfied users/customers and missed opportunities [reader: What is your take?] :

  • Quality pays – Time and resources spent on quality gives positive return on investment on development time, development costs, team and customer satisfaction etc . The earlier in development process resources are spent on quality related tasks, the better ROI. For example, is well known that finding bugs in requirements or design can be 100-1000 times less costly then in a shipped solution. Unfortunately, many projects are not managed with this fact in mind and many developers don’t have a good enough grasp of quality issues.
  • Careful risk-management is needed. – Too many projects are delayed, are over budget or completely fail to deliver. Managing the risks that can cause projects to fail is therefore essential. In particular, I find it important to limit scope of the solution/version worked on (not trying to do too many – possibly half baked – things at the same time), involve users from the beginning, consistent focus on writing well-crafted maintainable software (avoiding technical debt) and to address technical risks early on (like for instance scalability, performance or integration-issues).
  • People, development process, technology and clear goals are all important for success. Even great developers fail at projects if process is wrong, technology has major problems or goals are unclear. In particular, the value of a good R&D process is often underestimated. For larger projects, average developers all following a good software process will perform far better then great developers following a bad process.
  • Long-term priorities must be balanced with short time priorities. Quick workarounds, hacks and half-baked solutions may help to accomplish some business goals on the short term. However, unless addressed and reworked afterwards they risk permanently lowering the quality of the solution and imposing a technical debt that will effectively tax all future development. After many such short-term solutions, it is likely that development productivity will decrease substantially to the point where new features or bug fixes that should take hours will consistently take days or longer.
  • Use modern efficient technology as long as they are not bleeding cutting-edge. Be open to the use of technologies before they are mainstream if (and only if) they offer substantial benefits, are actively maintained, have a significant growing community, reasonable tool support and have books and training/support organisations behind them, Note that besides obvious technical benefits and savings, use of non/pre-mainstream technologies also helps attract the very best developers.
  • Investment in automation is key for efficient (agile) software development. Partly to save costs in the long run, partly to be more agile and responsive. In particular automate the build pipeline, deployment tasks and (most) technical tests used for regression. Beware that some automation efforts like for example GUI test automation requires special skills and tools to do right (high risk of failure or low ROI if done wrong).

Testable software architecture in a nutshell

May 3, 2012 by

Many software architects concentrate so much on the customer’s  requirements/needs, that they overlook other key sources of requirements from the professionals that work on creating and delivering the project like developers, testers, designers, deployment/production staff etc. Forgetting to map their extra requirements can result in substantial project delays, poor quality, cost overruns and failed projects altogether.

In this posting I will concentrate on testing issues and provide a bit of practical advice on what a good architect should always keep in mind regarding testability. Thus enabling high quality of the solution and making sure professional testers and developers alike can be effective.

Most importantly, the architecture, design (and requirements) of the system should be made explicitly testable. As an architect you start out with the basics of good design like separation of concerns & being able to code/run/test/debug objects in isolation. Then you make sure you have also designed for:

  • controllability: The degree to which it is possible to control the state of the component(s) under test before/after a test is run. Most importantly, a tester or automated sw test must be able to roll back changes in state, so that the test can be repeated (regression testing). This may involve designing a system providing additional transactions for tests, rollback scripts, new Api methods or gui controls to modify the system just for test purposes.
  • observability: The degree to which it is possible to observe (intermediate and final) test results.  Most importantly, a tester or automated sw test must be able to inspect all relevant data/values/attributes in the system to evaluate if the test succeeded or not . This may involve designing a system with extra Api methods or gui controls just for being able to read or display state.
  • automatability: The degree to which it is possible to automate testing of the component under test. Making sure a system is both controllable and observable usually goes a long way in enabling automate testing. But sometimes features in f.x. security/authentication  block the ability to automate testing. In these cases a separate “unsecure” mode may be needed for automated testing.

Note that designing for testability may seemingly contradicts user requirements – f.x. if the user specifies that one must never be able to delete a data item in the system and the controllability requirement insists that you make sure that all data items can be deleted. Here it is important that there is in fact no such conflict as the user requirements deals with the finished delivered system in production while the testability requirements are concerned with your development and test environments.

Howto: Java 7(ea) & Eclipse 3.7.1 on Mac OS X

October 5, 2011 by

I recall that when Java 6 first came out, Mac OS X did not support it at first and it was only when Java 6 got full support by Apple that I decided to switch to a Mac. Now, years later Java 7 is out on Windows/Linux/etc and I have been feeling a bit cheated by Apple since they won’t provide Java 7 and have in fact decided to drop Java support in OS X in the future.

Happily, the OpenJdk project does have Java 7 for Mac OSX under development with an official build from Oracle available here.

In related news, Eclipse Indigo SR1 (v3.7.1) has just been released with full JDK1.7 support for Mac OS X. It is available here.

To get Eclipse 3.7.1 to work with Java 1.7 (EA) on Mac OS X do the following.

1) Install Java 7 but leave the more complete+stable Java 6 as the default Java on Mac OS X.

2) Install Eclipse and let it run under Java 6.

3) Start Eclipse, select Preferences,  Installed JREs, Execution Environments and click on “add”.

4) Select standard VM.

5) In the field JRE home, do not attempt to browse for the Java 7 directory as this will not work. Instead just paste the installation dir of the installed Java 7 package +/Content/Home (fx. “/Library/Java/JavaVirtualMachines/JDK 1.7.0 Developer Preview.jdk/Contents/Home”) into the JRE home text field and press return.

6) Fix the JRE name in the field below to something suitable like “JDK1.7″ and click finish.

Now you should be able to create your Java 7 project in eclipse on your Mac OS X and you should be able to run/debug without problems…. Yes!

3 small steps for non-OSGI developers that want to stay OSGi compatible

May 21, 2010 by

Here is some advice if you do not know OSGI, but you would like your Java code to at least not be hostile towards OSGI environments (so that other OSGI developers can use your code and you might easier “upgrade” your code to OSGI later):

1) Do not use (or set/unset/inspect) the context class loader returned by Thread.getContextClassLoader(). The context class loader is only applicable to JEE applications. For OSGI in particular, any code that relies to the context class loader will generally fail (or more correctly might by accident work in a few OSGI implementation but will fail in most cases)…. Even if the context loader is non-null do not try to use the context class loader to load any classes as this might interferer with how OSGI resolves classes/versions. To put bluntly, the context class loader should be completely ignored for anything but JEE-only applications, where the context class loader is well defined.

2) Do not use Class.forname(“name”) which will not use the class loader setup by OSGI and cause of kinds of failures incl. ClassNotFound exceptions. You can use the classloader returned by any of the existing classes of your module to dynamically load your classes. F.x. you may use Myclass.class.getClassLoader().loadClass(“name”) instead.

3) Do not split your packages across multiple jars (i.e. where multiple jars have the same exact package and java has to combine the files from each jar to get the whole package content). While it works in OSGI, it is complicated and highly undesired.

P.S. Also, do not use the default package (no package) for your code as this will break OSGI. But seriously, who would do that anyway ?

That’s it, while your code might still not be full OSGI’fied it will at least be OSGI friendly.

Portable Eclipse projects & goodbye to unbound classpath container (JRE) errors

April 25, 2010 by

It is nice to have Eclipse projects under source control but unless you setup your project correctly you will have a high risk of getting JRE errors like “unbound classpath container” when you share your project with other developers.

  • For new projects make sure to select “Execution Environment JRE” when you create your projects – do not select project specific JRE or default JRE!
  • For existing projects select package view, right click on JRE system library, select “Execution Environment” and the appropriate environment.  F.x. JavaSE-1.6

Do’s and Dont’s for exception handling (moved posting)

April 19, 2010 by

… Or what every developer should know about the implementation of exception handling (in your compiler/os):

Modern Exception Handling (EH) in C++, JAVA, Ruby, Modular-3, C# and other modern programming languages is a great tool for handling errors but unfortunately it is sometimes abused by software developers that do not quite get what exceptions are really for or are just ignorant of possible implementations.

The handling of exceptions must be done at runtime by your compiler/os/virtual machine, since it is generally not possible to predict in advance which handler to transfer control to, identify which exception has been raised, where to perform object cleanup during the propagation of an exception and how much memory to pre-allocate for exception storage. Sometimes the EH runtime mechanism is compiler-specific and a part of compiler’s runtime library. In other cases, support for EH is provided through the operating system or virtual machine.

Common abuses of EH that affect performance include using exceptions as an alternative flow control mechanism (think sophisticated “goto’s” and you got the basic idea of this antipattern”)……. Don’t do that. It will only make the code harder to read. It will also make your code slower to execute since throwing exceptions are generally very expensive operations.

Another less apparent misuse of EH is usage of try-catch(-finally), or similar constructions your language may offer, inside the control flow of hotspots (such as inside time critical loops). Don’t do that, as a the try-catch-finally construction may have overhead even when you won’t expect it.

So why are throwing exceptions expensive and why may the try-catch-finally constructions (or similar) have overhead ? Well, it all depends on the language, the implementation of your VM or compiler (and sometimes on whether you use native code or not if your language allows it). Depending on your environment, just raising one exception can be from 10-100.000 times as slow as alternatively returning a simple return code from the method (in particular depending on if a dynamic registration approach or  a static table approach is used to support control flow transfer). And even if you don’t raise any exception, just having a try-catch-finally in your control flow can also be moderately expensive (but usually only enough to be a real problem inside hotspots).

Specifically, the case of overhead of try-catch-finally constructions when no exceptions occur is difficult to get rid of by compiler & virtual-machine implementers. Few implementations on selected virtual machine and chip architecture got it right and have 100% overhead-free implementations but many impose a overhead just for placing try/catch/finally constructions in your control flow. Basically this is because something like a “linked list” may have to be maintained internally by the compiler or VM each time the control flow enters or exits a try-catch-finally (unless you are luck to run om a fully static table driven implementation of EH).

For much more details about various possible implementations of exception handling and the impact on performance refer to this old thesis of mine here (not up-to-date for virtual machines though).

In conclusion, the morale of the story is:
* Do use exception handling for error handling only (not for control flow).
* Don’t use try-catch-finally constructs inside hot-spots (i.e. loops and such) if it can be avoided. Do the try-catch at a higher level that is called less often.
* If your particular java, c++, ruby, clr … implementation of exception handling on one chip architecture yields excellent performance even when you break the above rules you are just plain lucky. Change the version, vendor or chip architecture and you luck may desert you. Therefore don’t do it :-)

P.S. This post is not about good use EH in general…. But of cause, don’t forget to use exception handling when it is necessary and in particular do NOT ignore exceptions. I have also seen quite a few mistakes in code where exceptions are catched and then ignored. I have even seen senior developers do this in difficult places like event-handlers where one have to go the extra mile to actually handle the error (one way to do this is to create have the main thread manage errors and transfer exceptions to that thread in the event handlers ; but that is long story so I will reserve that for another blog posting)

Notice:

This post is slightly updated version of a posting originally from my old blog at “http://www.mortench.net/blog” which I will shortly retire for good.


Follow

Get every new post delivered to your Inbox.