Thursday, August 30, 2018

Why Java 10 local type inference is bad

For an overview of Java 10's local type inference see https://developer.oracle.com/java/jdk-10-local-variable-type-inference

The problem with local type inference is that the developer reading the code no longer has any idea of the shape of the object. We have reduced a developer's visibility to the name of the variable. For a developer to understand the type/shape/form/function they need to introspect back to wherever it was delivered or instantiated from.

In one of the examples given:

Map<String, List<String>> countryToCity = new HashMap<>();
// ...
for (Map.Entry<String, List<String>> citiesInCountry : countryToCity.entrySet()) {
  List<String> cities = citiesInCountry.getValue();
  // ...
}

We could rewrite this with var and reduce the repetition and boilerplate, like this:
var countryToCity = new HashMap<String, List<String>>();
// ...
for (var citiesInCountry : countryToCity.entrySet()) {
  var cities = citiesInCountry.getValue();
  // ...
}

It takes 3 introspective hops to determine the type of the cities var. If the value of the countryToCity has been provided from another method (which is extremely likely) then it will require 4 introspective hops. 

This is a massive diversion of the developer's focus.

Just because other languages have turned down this path does not mean that Java should.

I'm sure that there is a very (very) small set of problems for which local type inference is a worthwhile trade off. But in general, this is a VERY bad step for the Java language. It increases the cognitive load for the developer, and we already juggle way too many balls.

If you are using the syntax outlined above, do not expect an interview at any of my companies.

Sunday, February 7, 2016

Opportunity or crash - where to for the electricity grid when the battery bunny comes along

I've just received the first quarterly electricity bill that includes generation from the Solar PV on my roof. What I want to highlight is that we are about to reach an inflection point in the electricity market. With the correct legislation society will benefit greatly, but with the current legislation (and the legislation in QLD is relatively common world wide) society is in for some rough and painful times.

Note that the prices/regulations are those for QLD, Australia, where we have net metering. But the concepts are applicable everywhere.

To sum it up, to consumer electricity pricing looks like:

  • Network access cost - $/day
  • Electricity usage cost - $/kWh
  • Electricity generation - $/kWh (net or gross)
    • Net metering - you only get back for excess energy you feed into the grid.
    • Gross metering - you get paid for all electricity you generate.
So once you know how much energy you consume and generate it becomes very easy to determine the return on investment installing solar PV would provide. For us it dropped our yearly bill from $2,000 to $545 for an outlay of $8,000. 

That's an 18% low volatility after tax return on investment.
Ie it's a no brainer. See PV Return on Investment for the breakdown.

So legislation has provided a good economic platform to encourage solar uptake. And this shows, with PV generation in Australia roughly 4 times the size of the United States. So we are outperforming the US by a factor of 40 on a per capita basis.


Where it becomes interesting is if we look at what would be required to remove/reduce that remaining $545/year. Since we have net metering in QLD, I only get paid $0.08/kWh for generation I contribute back to the grid while getting charged $0.22/kWh for any that I pull from the grid. THis means that I have 2 strategies available to further reduce my electricity cost.
  1. Add more solar panels. But I already have the largest inverter allowable on a residence in QLD, and anyway I am already generating about 10kWh/day more than our total consumption.
  2. Store some of the excess energy we are generating so that I don't need to pull from the grid at night.
Option 2 works well for us and there are now a range of home solar batteries that will provide the approx 7kWh we use each night.


So let's look at what happens as people start to take up the small 7-10kWh batteries that are now available to remove/reduce that final $545/year.

There are two options
  1. Stay grid connected.

    This option is best for the consumer as if you drain your battery during heavy night time usage or after poor production days that you can still call on the grid for top up.

    It is also best for society as it means that the grid is being filled with a decentralized, de-carboned energy source during the day when most industry and business use occurs.
  2. Disconnect from the grid.
The problem we have is that on current prices this gives
  • 4.8% after tax return to stay connected
  • 6.8% return to disconnect.
While not stellar returns, they are both better that leaving the money in the bank, and they are after tax returns too so multiply by 1.47 to give a rough before tax return.

But the rub is that you are better off disconnecting

The current legislation does a good job encouraging PV solar, but it doesn't consider the impact as people start to take up battery storage. And they will. Figures above are based on today's prices. Battery costs are coming down in line with Moore's law and mass production brought on my phones, laptops and cars.

So what needs to be done?

Well we want to keep encouraging people to install solar. But we also want to encourage them to install batteries but to stay grid connected, as this makes the grid more resilient and also offers far cheap on demand power than gas fired generation.

How to achieve that?
  • Increasing the feed in tariff towards the usage cost reduces the ROI for either battery storage option. So this is not the answer.
  • Likewise reducing the consumption cost makes the return for either battery storage option less attractive. So this is not the answer.
  • Reducing network costs does decrease the disconnect ROI without affect that of staying connected. But those poles and wires need to be paid for AND it doesn't do anything to encourage battery uptake. So this doesn't look like an optimal solution.
  • Increasing the feed in tariff, but only if a reasonable size battery is in place. This has the advantage of encouraging battery uptake inline with the increase in feed in tariff and it doesn't have any adverse impact on any of the other outcomes. If it were to match the usage charge (which by defacto means that it would become gross metering), then return for my scenario would be 11.2%  compared to 6.8% for disconnected, so reason enough to stay connected.
    This looks like it might be the solution we are looking for.
So, think about it . Feedback is welcome.

And contact your state and federal pollies (in Australia it is the state pollies that will mainly determine this, though a smart federal pollie may throw his weight around and make things happen at a federal level too) and point them to this article.

The next 2-4 years will be make or break for the grid in Australia. 
Let's keep us connected and powerful (no pun to see here, move along).

And for those that would like a great state of the battery phenomenon in Australia, Catalyst did a great 25 minute segment http://www.abc.net.au/catalyst/stories/4398364.htm

Friday, May 29, 2015

Oracle did NOT invent the electrical socket

Lots of my non-tech friends have asked me what is going on with the stoush between Google and Oracle over the APIs used in Android. Most of them don't really understand what an application programming interface (API) is, and after the response from the White House, it seems like the WH doesn't understand either. So I'll lay out here how I normally relate an API back into the material world in the hope that this progresses the discussion.

An API is a description of a means of communicating or interfacing between 2 otherwise separate systems. Systems in this case can vary in scale and scope, but the common use case is between some computer code that you wrote and some library of computer code that someone else wrote.

A good way of looking at this in the material world is to think of an API like the electrical socket in the wall. It has a particular number of pins, shaped, spaced and oriented in a particular way. For those who haven't travelled you might be surprised to know that there are currently 15 different types of sockets used world wide. Here are 14 of them (didn't dig to find out which one is missing).


Ie each type of socket corresponds to an API

Devices with leads ending in a particular plug only fit into (and work with) sockets with the matching configuration. And that's how 2 separate systems work with each other. In the example above, system A is the power network supplying power into my house, system B is any device that wants to draw on that power.

Oracle (Sun Microsystems actually - Oracle just has deep pockets) came along and created the Java language along with a bunch of standard code libraries that anyone using Java could make use of. In order for you to use these libraries they needed to have an API, otherwise you couldn't talk to them.

This is the same as Oracle laying power cable to your door and providing electrical sockets for you to plug your devices into. In this analogy, Oracle created an environment in which there was a reason/market for others to create devices to plug into their electricity network. And they did, big time. There are millions of apps written in Java, just like there are millions of different devices to plug into the wall socket.

Then Google came along, laid their own power cable to everyone's door, provided their own power and <shock/><horror/> they used the same socket layout as that originally used by Oracle. To follow the analogy, they did this so that anyone with an existing device could choose to plug it into either electricity network. If Google didn't do that you would need to have 2 kettles, one with each type of plug, 2 fridges, 2 TVs (well many of you already have that) or at least have 2 adapters for every device (but then you have just pushed the problem back to the socket on the device), OR you have to lock yourself into one network or the other.

Oracle's claim on the API infers ownership over any device created by others that uses that API (This is the network lock in mentioned above). Why would your power company have any ownership of the kettle you plug into the socket?

This is especially pertinent to code libraries written by others (and there are millions of them) as they all have to use low level building blocks in order to do things. Oracle provided a description of those standard code libraries and the first implementation. Others (Google is but one) have come along later and provided their own implementation. Because everyone is using the same APIs a developer can choose the libraries they require and the implementation on which they want to run.

This leads to large amounts of innovation as everyone can choose the most appropriate components while still owning their own creations.

As an indie software developer, for Oracle to think that code that I have created is in some way owned by them and that I can't take my own code and run it elsewhere is outrageous. And is the total antithesis of co-operative competition.

There is more to this argument, but that is it in a nutshell.

Saturday, January 10, 2015

Be wary of Android SDK updates

Android SDK contains all of the build tools and libraries necessary to create Android apps.

The Android SDK Manager is used to pull updates to those tools and libraries and Google supplies the libraries via 2 artifact repositories. This is a good thing as you get the benefits of artifact versioning etc. (NB I won't rant here about why these artifact repositories should be global instead of machine local - suffice to say it is a barrier to dev, particularly open source dev).

The problem is that the Android SDK Manager doesn't behave like a well mannered repository manager when it is updating it's 2 repos.

It should just download the new library versions and place them within the repo.

Instead it removes the repo and recreates it from a combination of

  • new libraries
  • existing libraries that it thinks should be there
If you have added artifacts to your Google repos, to get around Issue#72807 for instance, then you will have lost those artifacts and will need to recreate them.

So lessons from this:
  1. Don't rely on Android SDK Manager to be a good citizen. Store those modified Google artifacts in a separate repository of your own (mea culpa).
  2. Google - fix Issue#72807 so we don't have to individually create modified Google artifacts. With the advent of PlayServices-6.5.87 there are 17+ more artifacts that have invalid dependency information.

Wednesday, December 17, 2014

Google TagManager for Android

TagManager, what's that? Actually that's a pretty fair question.

Google hasn't done a great job of explaining what TagManager is, why you care and how to use it very well, especially for Android. This is probably because TagManager has come from the world of web marketing and has really only recently received some Android love.

But now that TagManager is part of Google Play Services (and if you aren't using Google Play Services yet you should really be asking why you aren't) integrating it into your app is a breeze.

Firstly: What is it and why should you use it?

I won't dig into the full details of TagManager, I'll let you explorer those later. Where I think you'll get most value out of TagManager initially is by using it to specify app config values for which you might want to push out new values to all your users. Eg I only show interstitial ads after 20% of games played in one of my apps. But maybe I want to be able to play with that after I have shipped. TagManager will let me do that by updating the config in its web interface and publishing a new version of the TagManager Container.

How to integrate TagManager

You'll need to sign up for TagManager (etc), create a Container and for app config variables create a MACRO of type value-collection. Start here https://developers.google.com/tag-manager/android/v4/

Don't worry too much about the weird names that TagManager uses (MACRO etc). There is a revamp due to be rolled out Jan 2015 that brings a nicer UI and names that are a lot clearer.

Once you have created and downloaded your TagManager Container to res/raw (heads up - the default name for the Container file does not follow Android resource naming conventions and you will have to change it), you can start adding code.

Start with your Application class and add the following:

// Make sure we always have a TagContainer instance
private TagContainer tagContainer = new TagContainer(null);

public TagContainer getTagContainer() {
    return tagContainer;
}

// Call this from Application#onCreate
private void configureTagManager() {

    final TagManager tagManager = TagManager.getInstance(this);
    final PendingResult<ContainerHolder> pending = tagManager.loadContainerPreferNonDefault(GTM_CONTAINER_ID, R.raw.gtm_mycontainer_v5);
    pending.setResultCallback(new ResultCallback<ContainerHolder>() {
        @Override
        public void onResult(ContainerHolder containerHolder) {
            tagContainer = new TagContainer(containerHolder);
            if (containerHolder.getStatus().isSuccess()) {
                Log.i(TAG, "GTM container loaded");
            } else {
                Log.w(TAG, "Failure loading GTM container : " + containerHolder.getStatus().getStatusMessage());
            }
        }
    });
}


We introduced the TagContainer class here to make our life simple. It looks like:

public class TagContainer {

  private static final String SHOW_FULL_SCREEN_AD_PERCENTAGE = "showFullScreenAdPercentage"; 

  private final ContainerHolder containerHolder; 

  public TagContainer(ContainerHolder containerHolder) {  
    this.containerHolder = containerHolder; 
  } 

  /**
   * Defaults to 0.20
   */
  public double showFullScreenAdPercentage() { 
    final Container container = getContainer(); 
    return container == null ? 0.20 : container.getDouble(SHOW_FULL_SCREEN_AD_PERCENTAGE); 
  } 

  private Container getContainer() { 
    return containerHolder == null ? null : containerHolder.getContainer(); 
  }
}
And finally add it into the code where you want to use the value:

    if (coinToss < getTagContainer().showFullScreenAdPercentage()) {
        // show interstitial
    }

Voila, instant app config.

The End Game

So now you can ramp the ad percentage up or down without needing to release a new version of your app. Just update the TagManager web interface, publish the new version of the Container and within 12 hours it will ave rolled out to all your users.

So for those of you who have been managed your own server and transport for app config, here's your chance to cut down on the code you need to manage.

And now that you have that ability, what else do you want to be able to tweak in your app after deployment?

Wednesday, November 26, 2014

Handling missing Android support-v4:{20-21} Jars

Some of the newer Android/Google libraries have been published with invalid dependency information. It looks like an endemic issue, but the ones that have caught me so far have been

  • com.google.android.gms:play-services:6.1.71
  • com.android.support:appcompat-v7:21.0.0

The problem is that these libraries declare a dependency on support-v4:20 or support-v4:21 but don't specify the type of that dependency. The default type for a dependency is JAR, but Google published support-v4:20 and 21 as AAR libraries.

This means that when you build, the build mechanism has no way of knowing that you really wanted to pull in support-v4:20 AAR and so will fail with missing dependencies.

This has been raised with the AOSP as Issue#72807 so please star it if it irritates you as much as me.

My suggestion for working around these are to define your own replacement artifacts that using the same AAR files but contain a POM defining valid dependencies. Don't forget to define them as an entirely new version. I have tagged mine as "-b" version

Here are those I am using:

For com.google.android.gms:play-services:6.1.71-b

<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.google.android.gms</groupId>
  <artifactId>play-services</artifactId>
  <version>6.1.71-b</version>
  <packaging>aar</packaging>
  <dependencies>
    <dependency>
      <groupId>com.android.support</groupId>
      <artifactId>support-v4</artifactId>
      <version>20.0.0</version>
      <scope>compile</scope>
      <type>aar</type>
    </dependency>
  </dependencies>
</project>

For com.android.support:appcompat-v7:21.0.0-b

<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.android.support</groupId>
  <artifactId>appcompat-v7</artifactId>
  <version>21.0.0-b</version>
  <packaging>aar</packaging>
  <dependencies>
    <dependency>
      <groupId>com.android.support</groupId>
      <artifactId>support-v4</artifactId>
      <version>21.0.0</version>
      <scope>compile</scope>
      <type>aar</type>
    </dependency>
  </dependencies>
</project>


NB if you have externally facing projects where you can't have a dependency on a play-services version that you have constructed yourself (with the correct dep), then you can manually exclude support-v4:jar from the play-services dep in your project, and then add the support-v4:aar dep yourself. Thanks to +Hugo Visser for this suggestion.

<dependency>
    <groupId>com.android.support</groupId>
    <artifactId>appcompat-v7</artifactId>


    <version>21.0.0</version>
    <type>aar</type>
    <exclusions>
        <exclusion>
            <groupId>com.android.support</groupId>
            <artifactId>support-v4</artifactId>
        <exclusion>
    <exclusions>
</dependency>
<dependency>
    <groupId>com.android.support</groupId>
    <artifactId>support-v4</artifactId>


    <version>21.0.0</version>
    <type>aar</type>
</dependency>

Saturday, March 2, 2013

Connecting any interstitial provider with Admob mediation

Admob mediation provides a way to code your Android app to include banner or interstitial ads just the once but to change the networks supplying those ads on the fly.

I'm going to show you just how easy it is easy to write an adapter that can receive interstitial requests from Admob mediation and serve up interstitial impressions from an ad network.

We need to implement CustomEventInterstitial which performs all the work.

  • requestInterstitialAd() retrieves an ad
  • showInterstitial() displays that ad
  • destroy() performs any cleanup

One thing to remember when retrieving your ad is that you need to notify the mediation layer about whether retrieval was successful or not. So you attach a listener to the ad and when the listener fires, relay that event back to the mediation layer via the mediation listener. Also, if for any reason your network has no ability to retrieve an ad (eg wrong SDK version) then you should report the failure back to the mediation layer immediately so that it can ask the next ad network in the queue for an impression.

Here's the source for requestIntersitialAd()


    
Pretty simple! And to display the ad is even easier.



There's no really much to cleanup here, so that's all the coding.

Make sure to:

  1. Include the libraries for your target network when building your app 
  2. Add Proguard config so leave you mediation adapter intact as the Admob mediation layer will be looking up it via reflection. 
  3. Create a CustomEvent in you Admob mediation config that points to your adapter and passes in the network id for your app.

So now you can serve up ads from any ad network all via Admob mediation. Full source code for the above along with several other mediation adapter and an example app can be found at https://github.com/william-ferguson-au/Admob-CustomEvents

Enjoy