May 27, 2018

Facing the Challenge of Customizability

In software development, we differentiate between a product and a project. The distinction goes as follows:1

- A product is developed for the market. The software company invests money into the development of a product with the goal to sell it to a large number of customers. Investing in this sense means advancing money, which may or may not reap returns when the product is finished. A product therefore offers good rewards (write once, sell many times), but also carries a sizable risk (the market doesn't care).

- A project is developed for a single client according to their needs. Typically the development firm will still need to advance the money required for the project. The risk however is much lower, because there is a customer who will pay the full development cost of the software. The returns on the other hand are lower, too, because the project software cannot be sold to other customers.

Many software companies have found their happy place doing both: They provide standard products for the market and projects to tailor their standard products to specific customer requirements. This tailoring is typically called customizing - and it is one of the biggest challenges to be faced in designing a product.

In my years as software developer, I have encountered various products which have been heavily customized, and most of them had at least one of the following problems:

- Everything is private
This can be one of the most frustrating things to encounter as developer tasked with customizing a product. The product defines a few "entry points", which however do not give you the freedom you need. At every turn you have to ask the product development team to give you an additional entry point or to make yet another method publicly available. This can easily make a two day project an odyssey of multiple weeks.

- Everything is public
While this is the exact opposite of the previous bullet point, it is exactly as bad for the company. If a method is public, someone will use it (and forget that they did). A public interface can never be changed without worry that some customizing will break. And if the customizing was important, what seemed to be a small change in the product can quickly become a political nightmare. This leads to a major deadlock: if everything is public, nothing can be changed. Product development grinds to a hold.

- The product architecture is a mess
A messy architecture is bad enough in product development alone. At some point, changes to a bad code base become ever harder, the risk of breaking existing functionality becomes ever greater. How is one supposed to implement complex customer specific features into such a code base without breaking everything? And how to not make the customizing even messier than the already bad code base? Even worse, customers sometimes request a customizing added on top of an existing customizing. That's like a bad meal with awe-full sauce and an even worse spicing.

- An extraordinary sales department
Some salesmen can sell just about anything - and they do it, too.2 Even though the developers hair stands on end because he can barely make the requirements work. This will often lead to ugly workarounds with strange side-effects.

- Putting the "product"-badge on customizings
Depending on the agreements with the client, a software company may be allowed to include customizings as part of their product. This is great if the customizing is taken as a feature that gets thoughtfully embedded into the product. If customizings just get "slapped" into the existing code one after the other, however, the product more than likely becomes a mess after a while. The reason is simple: A customizing does not usually have to take all the products features into account. It is very clear which features the customer needs and uses. To keep costs for the customizing down, only the necessary changes are made. Why would you make the customizing work with feature x if the customer does not intend to ever use said feature? Putting this customizing into the products code base however leads to a problem: A different customer may very well use feature x, which is now incompatible.

Many of these challenges can only be met with some strong self-control and good foresight. There are, however, various ways to takle these issues:

- During development of a new product, it must be clear whether the software should be customizable or not. If in doubt, go with yes.3

- Any software should have a clear architecture. This is especially true if others should customize the software. I personally believe that the exact architecture is not as important as the consistency of said architecture. Once a new team member (in product or project development) has a grasp of one part of the application, they should be able to apply that knowledge to all other areas of the software.

- Consider the implementation of a plugin system. Plugins are a powerful way to allow for customizability. In the extreme case that all product functionality is bundled in multiple layers of plugins, everything can be changed for the customer (the architecture does become harder to understand, though).

- Use automated (regression) testing. Not only does automatic testing help in the development of the product or the specific customizing. The real power becomes apparent when automatic regression testing can be applied to the product and all customizings at once. Whenever product development has (again) broken the interface, automatic tests of customizings catch the error before it gets rolled out to the customer. This makes both the product developer as well as the project developer sleep easier at night, because they can be pretty sure their stuff still works the next day.

- During customizing, think about product features which will not be compatible with the customizing - and document this fact4. If someone later moves the customizing into the product, incompatible features have a greater chance to become apparent.

- Do not make everything public/private. Every part of the application has to be examined in regards to the necessity of it being customizable. Everything that needs to be customized must have a clear public interface (an API if you will). This interface must be created in such a way, that it a) provides all required functionality, b) can be extended whenever we forgot something in a).5 If product development is in doubt which parts of the interface have to be public, wait for the first customizings to come around. In my experience it is better to make too many things private than to make too many things public. There has to be an easy ways for project developers to get their public interfaces done when they need them, however. This leads me to the next and most important point:

- Talk to your colleagues (coffee makers are a great place for that). In my experience there is oftentimes a barrier6 between product and project development. Especially if the two are separate departments. However, only the customizing department knows what they really need.

In my opinion, the challenge of customizability is a big one. Customizing is one of the biggest sources of income for many software companies, but there is no one right way to make it work. Still, I hope I have offered you some food for thought to enhance the work of your product development and project development alike.

1 This is a simplified distinction, of course. As per usual, reality provides many gradients in between products and projects. The software company could, for example, sell a customizing at a discount but in turn get the clients allowance to sell it to other customers as well.
2 Don't take this one too seriously. As is usually the case, neither is the salesmen at fault, nor the development team. There are customizings, however, which better had not been done. And some better communication between departments could works wonders to prevent such cases.
3 Allowed answers are: yes and maybe.
4 This documentation could even be a test in the form of: If feature x is active, break the test with an appropriate message.
5 In my mind, this is one of the hardest nuts to crack. One good way to tackle this problem is the combination of a plugin system and dependency injection. Plugins get their dependencies injected, which in turn have a public interface that can easily be extended. This topic can fill books, however, and can not be fully discussed here.
6 The size of this barrier ranges from garden fence to Great Chinese Wall. Only open communication can lead to good software, especially in the early stages of a products market adoption.
May 21, 2018

Think About Your Future

We are a lucky bunch, you know that? In 2018, software developers in Germany earn an average of 52,000 €.1 By comparison, the average salary over all employees in Germany is 41,000 €.2 Looking at various professions, IT is considered one of the most lucrative job markets.3 In addition, management positions in IT add an above average amount to the already good salary.4

I just got my pension award and I was a bit baffled. Inflation as well as raises in salary and pensions removed, my net pension would only be 1/2 of my current net income. And I am by no means worse off than others.5 That is a steep drop in quality of live!

And here is where I consider us lucky: As a software developers (with more than average salaries), we can prepare for the future, set aside some money to support our quality of live in our pension. That is what I urge you to do!

I do not want to make any suggestions on the ways you want to invest money to add to your pension. There are experts for that and I am not one of them. I want to point out one more thing, however: the earlier you start, the better - think about compounded interest.

May 13, 2018

GitHub to NuGet with AppVeyor

AppVeyor DashboardAs I have written in my last post, I now have a number of .NET projects on GitHub. As all of these are libraries, I wanted to make them easily available through NuGet (not least because I myself use them regularly and want them accessible at all times). Enter the world of continuous integration (CI) services.

There are two mayor CI service providers with great GitHub integration: Travis-CI and AppVeyor. Being a .NET developer, there is a serious downside to Travis, though: their servers run Linux and support only Mono and .NET Core. AppVeyor, however, provides Windows servers with all the .NET framework one might ever need, free for open source projects. Happy days!

Integration is easy enough: Select your GitHub project, add the NuGet deployment provider and enter your NuGet API key. For my projects, I also create a release branch and set AppVeyor up to build all branches, but push NuGet packages only for the release branch. Also, I found it necessary for some .NET Standard projects to run "dotnet restore" as pre build script in order to update all dependencies.

All in all, I can highly recommend you give AppVeyor a try - especially if you are a .NET developer.
May 11, 2018

Programmer's Digest on GitHub and NuGet

Programmer's Digest has found its way to GitHub and NuGet!
GitHub: https://github.com/programmersdigest
NuGet: https://www.nuget.org/profiles/programmersdigest

There, you will find a variety of open source projects (licensed under Apache License 2.0) ranging from object relational mapping over dependency injection to parsing of the SWIFT MT940/942 bank transaction format. Currently, all these projects are written in my preferred language C# and based on .NET Standard 2.0 where possible.

All projects are derived from software I am writing in my spare time and try to once and for all solve some specific problems I face again and again. As such all are actively being worked on and updated whenever the need arises. There may however be prolonged times of inactivity, when there are no known bugs and new features are not required.

Feel free to help improving these projects with bug reports, advice or even better, code. If you want to use any of these projects in your own, just grab them from NuGet.

I will in the near future present each of my projects in a separate article, explaining the hows and whys and maybe some interesting tidbits to be found in the code (and a rant or two may be incoming as well).
July 30, 2015

JavaFX with Scala

JavaFX with Scala

One of the big advantages of Scala is its interoperability with Java. Wouldn't it be nice to write JavaFX applications using Scala? Well, you can (otherwise this article would be short, indeed). In this article, I will show what to do to bring JavaFX and Scala to a happy union.

The goal is to write a small JavaFX application, whose UI is defined in FXML-files and can thus be created using SceneBuilder. Additionally, we want to use the comfort of dependency injection via the @FXML attribute, which thanks to the interoperability of Scala and Java is not hard to do at all. To keep things simple, we take a view first approach, i.e. the view defines the controller to use and the FXMLLoader does all the initialising.

First, we need to get JavaFX to load. Let's start just like we would in Java, by creating a class inheriting from Application.

// File: eu.derprogrammierer.jfx.FxApp.scala
package eu.derprogrammierer.jfx

import javafx.application.Application
import javafx.stage.Stage

class FxApp extends Application {
override def start(primaryStage: Stage): Unit = {
primaryStage.setTitle("Fx App")
primaryStage.show()
}
}

In this example, we set the window title and subsequently show it. Later we will also fill the window with some content.

In your average JavaFX application, there is also a static main() function which in turn calls the static launch() function on FxApp. However, since Scala does not implement static functions, we will have to use a companion object for the class FxApp instead. Companion objects do not automatically implement functions of the base class, though. Which is why the following port of the typical Java code will not work.

object FxApp extends Application {
def main (args: Array[String]): Unit = {
launch(args:_*) // Cannot resolve symbol launch
}
}

Luckily Application provides a more generic function for us to use, such that we can call launch on the Application base class and give it the type of our FxApp to specify the actual instance type.

// File: eu.derprogrammierer.jfx.FxApp.scala

...

object FxApp {
def main (args: Array[String]): Unit = {
Application.launch(classOf[FxApp], args:_*)
}
}

The application can now be started and displays an empty JavaFX(!) window. This is nice and all, but we really want to put some content into this empty window, and there is still that thing about FXML, right?

Well, before we can dive into FXML we require a controller to be used in our view. A basic controller implementation is very similar to what you would do in Java.

// File: eu.derprogrammierer.jfx.view.MainViewController.scala
package eu.derprogrammierer.jfx.view

import javafx.fxml.FXML
import javafx.scene.control.{Label}

class MainViewController {
@FXML private var testLabel: Label = _

def initialize(): Unit = {
testLabel.setText("Initialized!")
}

def handleTest(): Unit = {
testLabel.setText("Test successful!")
}
}

As you can see, our view will contain a single label named "testLabel". Its text is changed in the initialize()-method. Also, there is a handler handleTest() which changes the text. This handler is supposed to be executed when clicking a button.

Note that IntelliJ IDEA recommends changing testLabel into a "val", which does however break the JavaFX injection. It is also not possible to drop the @FXML attribute on public fields like you could do in Java. This is due to the way Scala handles public fields. A public field in Scala is actually a getter and setter method wrapped around a private field. This is not noticable for normal programming. However, when using reflection to access fields, as is done for FXML, this can have some major implications!

Main.fxml in SceneBuilder

Our controller is now in working order, so we can finally start to create a view (FXML, yessss!). To do that, we add a file "MainView.fxml" to the package "view". In SceneBuilder we drag an AnchorPane into the empty window. We place a button and a label in the middle of the pane.

Action handleTestLabel fxid

The button gets the action "handleTest" and the label gets the fx:id "testLabel" (both of which should seem familiar from the controller).

MainView Controller Class

Also, our view wants to have a controller, so we enter the complete name of our controller into the field "Controller class".

What's left to do is to load the view in the class FxApp. For this, we change the function start() as follows:

override def start(primaryStage: Stage): Unit = {
primaryStage.setTitle("Fx App")

val fxmlLoader = new FXMLLoader(getClass.getResource("view/MainView.fxml"))
val mainViewRoot: Parent = fxmlLoader.load()

val scene = new Scene(mainViewRoot)
primaryStage.setScene(scene)
primaryStage.show() }

This requires some additional imports, too:

import javafx.fxml.FXMLLoader
import javafx.scene.{Scene, Parent}

You can now run the program again and you will find the label correctly initialized. Clicking the button changes the text of the label to "Test successful!". A successful test indeed!

You now have a fully usable JavaScalaFX application. I will leave it up to the reader to make a "Hello World!" example from that.