Life Codecs @ NamingCrisis.net

Ruminations. Reflections. Refractions. Code.

May 3, 2017 - Software dev Kotlin

Kotlin Quick Ref: Multiple Constraints/Bounds on Type Parameters

I’ve been using Kotlin the past few weeks, mainly to write JustLogIt!.

I very nearly thought Kotlin was missing a feature that Java has: multiple bounds or constraints on a type parameter. In Java, one can do:

interface A {}
interface B {}

// constrain the type parameter T to be a subtype of both A and B
class Foo<T extends A & B> {}

A feature I occasionally find very useful. The syntax is nowhere near the same for Kotlin, and only a very small example right at the end of the Generics documentation is provided:

https://kotlinlang.org/docs/reference/generics.html

Some discussion around the syntax can be found here:

https://discuss.kotlinlang.org/t/why-the-scattered-generic-types/1917

I had a more involved use-case:

class FragmentCanRequestPermissions<out T>(val fragment: T) :
    CanRequestPermissions, FragmentCompat.OnRequestPermissionsResultCallback
    where T: Fragment, T: FragmentCompat.OnRequestPermissionsResultCallback {
  ...
}

Thus, where defining constraints occurs at the end of other declarations.

Let’s see the more general syntax for when we have multiple type parameters, each having multiple bounds/constraints:

interface A
interface B
interface C
interface D
interface E
interface F

class Meow<ABC, CDE, DE>: A, F
where 
  ABC: A, ABC: B, ABC: C,
  CDE: C, CDE: D, CDE: E,
  DE: D, DE: E
      

In fact, as you might infer, the order of bound declarations does not matter:

class RandomOrderLikeAirportRandomChecks<ABC, CDE, DE>: A, F
where 
  ABC: A, CDE: D, ABC: C,
  DE: E, CDE: C, ABC: B, CDE: E,
  DE: D

// "Random". Yeah. Right.

Yes, I am on a plane.

Mar 18, 2017 - Software dev

Bye, bye Dreamhost

After nearly 10 years of hosting with Dreamhost (including this site) with mostly okay service — it had its bad days! — I decided to migrate everything over to Webfaction (affiliate link) which I have been using since around 2014 for a few things.

In the words of Dreamhost’s billing:

You are not within our 97 day money back guarantee (it has been 3585 days since 2007-05-25)!

Woot!

The following points tipped me over:

  • The ability to deploy long running services (called applications) that run on a port
    • This port can be exposed if needed, though rarely do you want this.
    • Instead you deploy websites whose requests are proxied through to these internal applications. With this, even on a shared host, I can (and do) run a memory-bounded JVM application on Jetty, for example. You can also run high-performing, low-footprint web servers to host your applications, and save memory.
    • Your stock standard static/php/cgi application also exists.
  • PostgreSQL Support by default! Seriously, Dreamhost, it is stupid how you don’t yet have this for shared hosting. Sticking with MyOrac^H^H^H^HSQL is most unsound.
  • A generous 1GB guaranteed memory for applications in the base USD 10/mo plan.
  • Like Dreamhost, it has SSH access. A crucial facility for developers, even on shared hosting.

I’m only on Webfaction’s basic plan, so have no comment on how they scale. But it’s a much more flexible, and competitively-priced shared hosting option.

Mar 14, 2017 - Software dev

Docker Container as a Shell

Most of my work is done either on a Macbook Pro, or my Linux desktop. As much as macOS is a Unix, with supporting tools like MacPorts, Linux is still richer as far as commandline utilities go.

Prior to native Docker support on macOS/OSX, you would resort to running Linux in a virtual machine, and having a share directory.

With Docker, we basically emulate the same, but obviously, native Docker on the Mac, or Windows 10 for that matter, is far more lightweight than a VM. Note that this is not a very container’ey use of Docker where everything you need is ready to deploy right from the image.

The approach I’m taking for this use case is basically to treat a Docker container as a lightweight VM, with adhoc tooling installed — essentially a rolling-release style VM, occasionally taking snapshots, and pushing up to the docker registry so it’s shareable across machines.

The overall approach is:

  • Pull down an existing container, I went with ubuntu
  • Tag it as your own and push to your docker registry. Follow instructions here on this step.
  • Pull down your tagged image
  • Create a script that will mount your home directory as a volume. Thereby providing you with a live workspace to execute your container utilities against. I have nearly all my work in my home directory, so this mount makes sense, but it’s simply a regular mount.
  • Create a user in the container, so you don’t constantly log in as root.
  • Commit and push the container’s changes as needed.

Your data is still in your host’s home, while the utilities are installed in the container.

Running docker commands is a pain if you do the above workflow often. Here I’m providing the scripts and utilities I wrote. Replace with your custom values as needed.

My Docker utility run script. Note that it’s already using my tagged ubuntu image. So the tagging and pushing step is a prerequisite.

#
# ubuntu-docker-start.sh
#

HOST_HOME=/Users/xdyme
CONTAINER_HOME=/home/xdyme/data
TZ=Australia/Melbourne
HOSTNAME=ubuntu-container
CONTAINER_NAME=ubuntu
IMAGE="kva1966/ubuntu:latest"

docker run -dt \
  --name ${CONTAINER_NAME} \
  -h ${HOSTNAME} \
  -e ${TZ} \
  --volume ${HOST_HOME}:${CONTAINER_HOME} \
  ${IMAGE}


I also added a bunch of utility aliases for common container tasks in ~/.bashrc:

#### Local Shell Container ####

alias d=docker
alias ubuntu-deploy-container='~/projects/checkouts/desktop-scripts/ubuntu-docker-start.sh'
alias ubuntu-commit='d commit ubuntu kva1966/ubuntu:latest'
alias ubuntu-push='d push kva1966/ubuntu:latest'
alias ubuntu-stop='d stop ubuntu'
alias ubuntu-start='d start ubuntu'
alias ubuntu-run='ubuntu-stop; d rm ubuntu; ~/projects/checkouts/desktop-scripts/ubuntu-docker-start.sh'
alias ubuntu-delete-container='ubuntu-stop; d rm ubuntu'

ubuntu-login-user() {
  username=$1
  homedir=/home/$username
  if [ -z $username ]; then
    username=root
    homedir=/root
  fi
  
  d exec -it -u $username ubuntu bash -c "cd $homedir; exec ${SHELL} --login"
}

alias ubuntu-login='ubuntu-login-user xdyme'
alias ubuntu-login-root='ubuntu-login-user'

#### END Local Shell Container ####


Some very basic .bashrc and .profile can be found when you login to the xdyme user on my container. Mainly git completion, and a nicer looking default shell.

Jan 27, 2016 - general philosophy

Who Do You Work For?

Corporations often talk about values. Expected behaviour and human traits that the corporation deems necessary to achieve its goals as a whole. It is expected that all levels of the organisation will display these traits. Of course, anything involving people is bound to have its own challenges. It is very difficult to instill values in people; more so adults.

The idea behind value statements is legitimate, and having this framework of character is certainly a step in the right direction. When the toplevel folks consistently display these values, employees down the chain either fall in place, or leave. I am, for the moment, ignoring matters of hiring the right people, a non-trivial problem worthy of its own post (many, many posts).

In effect, it is people that bring values and traits to life. Without enough people making these values pervasive, they mean nothing. Words on a corporate brochure.

Very few places I can think of — in fact, just one, my extended family, the BKC — have values so tangible, that, it would seem even if not one human were left in the place, those values would remain alive, palpable. One gravitates to the promoted values nearly by osmosis. Such places are the exception rather than the norm, of course. Given this, I have come to the epiphany, that for most other corporations, I cannot possibly work for the company. I work for people at the company. Together, we progress the organisation. The latter is nearly a side effect. But it is very much akin to having money as a side effect of providing value, not a particularly big idea by now one would hope.

Management experts like to use terms like “restructuring”, as if an organisation is a malleable construction of easily replaceable lego blocks. In 2016, that many places do not recognise just how organic, just how alive, and how cellular in nature corporations are, is a cause for sadness. Until the importance of people takes precedence, and not just as lip service, everything tends towards disorder, or at best, mediocrity.

One must consider that to start a company, to drive it to provide value and derive profit — the beginning — takes a huge amount of energy. Most company founders are smart and driven. To me, a state of mediocrity (or perhaps, complacency) is when only this initial impetus moves the company in, essentially, auto-pilot mode. When no more of the same drive and energy is applied to achieve continuous innovation.

I recall a Yow! event I attended recently, the speaker — I believe from Netflix — mentioned that execs from other companies often mentioned how they could not hire good people. To which the speaker responded that many of Netflix’s engineers were hired from these execs’ companies. The phrase “damning evidence” comes to mind.

Sep 28, 2015 - Uncategorized

The Second Law of Thermodynamics

Often simplified and paraphrased (mostly by software folks, like yours truly, and pop sci crowds) to “everything tends towards entropy”, the law is surprisingly applicable to wide range of scenarios. Which, I suppose, should not be surprising given the universe and humans forming the ecosystem are simply bags of vibrating, heat-producing molecules. The last statement was not meant to be cynical, nor do I subscribe to the view that consciousness is a purely emergent physical phenomenon, but I am abstracting for the sake of this post. But, I digress.

In software we see the law in the phenomenon known as Software Rot or Bit Rot, or some variation thereof. But, “as above, so below”, the same law applies to groups of people, to companies, to relationships. When a group stops making an effort to be better, then it does not simply stay in place, it tends towards a rotting state. Complacency is bad not because it stops you from progressing, it’s bad because it regresses you. Sometimes, I wonder if there is such a thing as a state of true rest.

Consider now, that if the ‘natural state’ tends towards entropy, what the effect of catalysts towards that state is?

“Is there a point to this post?”, I hear my readers (I should have at least two…) say. Sort of, just one of those days when you wonder why you are in the industry you are. I rarely drink, but, days like this I sympathise with the wise words of jwz, “This is why I sell beer“. People, including myself, simply do not learn.

Jul 19, 2014 - software dev

Set If Not Null ‘Pattern’ in Java 8

When working with business entities, many of them will involve a mix of complicated logic, and plain CRUD data. Often we will have some update or create method where an incoming DTO or Request object will have a subset of fields to source details to update the target entity. Even when trying to restrict the scope of the DTO to what an operation needs (an idea I am a big fan of), it may still be course-grained enough for that scope, and still have nullable/optional fields. The resultant code will need to do null checks and decide what to source and what to ignore. Simple example:

 1class User {
 2  private String firstName;
 3  private String lastName;
 4
 5  // ... getters ...
 6
 7  // private setters
 8  private void setFirstName(String value) {
 9      firstName = value;  
10  }
11
12  private void setLastName(String value) {
13      lastName = value;  
14  }
15
16  public void update(UserDto dto) {
17    if (dto.getFirstName() != null) {
18        setFirstName(dto.getFirstName());
19    }
20
21    if (dto.getLastName() != null) {
22        setLastName(dto.getLastName());
23    }
24  }
25/*
26Digression: generally, I avoid public setters entirely.. business
27objects need specific business methods to manipulate/update them. We
28should stop (yeah... like since 2000 at least) thinking of them as
29anaemic wrappers of fields.
30
31However... private setters can sometimes be useful for encapsulating
32internal checks.
33*/
34}

The issue here is with the null checks. Prior to Java 8, for simple values like Strings, there was no way to factor out the annoying null checks (well, not without more verbose artifacts like wrappers to create, or lose type safety and use reflection, blergh…).

What I really want to say is: setIfNotNotNull(fieldToSet, valueToUseIfNotNull).

Now, since String refs are immutable, we can’t pass them in to update in setIfNotNull(…), the local ref will simply be overwritten with a new value… enter our setters, which have a common format of void setFoo(T val). Making use of Java 8 Method References we can achieve what we want in a typesafe manner:

 1class User {
 2    // ...
 3
 4    public void update(UserDto dto) {
 5        setIfNotNull(this::setFirstName, dto.getFirstName());
 6        setIfNotNull(this::setLastName, dto.getLastName());
 7    }
 8
 9    // note the use of java.util.function.Consumer -- a suitable archetype
10    // for setter methods.
11    private <T> void setIfNotNull(final Consumer<T> setter, final T value) {
12        if (value != null) {
13            setter.accept(value);
14        }
15    }
16}

Voila!

Of course, you can use lambda expressions where we used method references, but in this case, the existing methods encapsulate the logic we need.

Now, to see how far I can take this… I am reminded of Simplicity, Clarity, Generality… it never ceases to amaze me that the timeless 3 traits, more often than not, support each other.

PS. to get up to date with Java 8, Java 8 for the Really Impatient does a stellar job. However, you will have to be patient in parts (I did anyway :P).

PPS. I am still coming to grips with Optional types, and hence have not mentioned this as an alternative to null checks.

PPPS. Sorry about using the term ‘pattern’, it was an attempt to sugar coat the phrase ‘crappy-as rote work’. (There, Tommy). 😛