Tag: Programming

  • 5 Strategies For Making Progress on Side Projects

    cress keyboard
    Credit: Wikipedia

    I get asked on a regular basis how I manage to maintain a blog (and other side projects) on top of my job, especially since I almost never write anything specifically about my job. I actually wish I was better at and more productive on my side-projects, but that might be step zero – to let go of trying to be perfect and just focus on achieving something.

    Schedule

    I don’t have a social media strategy as much as I have a schedule. I use Buffer to schedule interesting articles I find to my Twitter feed to share 3 a day (the limit of 10 on a personal account is sometimes annoying, but I use it as a barrier on batching up too far in advance). This is one of the least important things, and one it is very hard to measure the ROI of, but has the side effect of capturing interesting things I find and making it easier to locate them again. If I’m too busy, the buffer empties out and don’t have anything to share, I don’t really mind. I read a lot, so this will typically sort itself out pretty quickly.

    My blog has the far more important schedule. After about 6 months of posting 3x a week and building up some leeway in posts that are written but haven’t gone out yet, I was able to move to a schedule of Monday: travel and personal, Wednesday: tech-related, alternating general tech and more women-focused ones, Friday: reviews, notes from talks I’ve attended, the odd how-to (like this one). Sundays I post a weekly round up which serves partly as a way to collect all the interesting things I’ve shared on Twitter.

    The leeway of having at least an extra week’s worth of content is really helpful, and for the last few months this has meant that I can write about pretty much whatever I wanted at any point, and then just slot it in, as it would eventually balance out.

    The schedule is king, not the content. I think producing something on this regular a basis is more important than how good I think any of it actually is. Firstly, because you only get better with practise. Secondly, I am a poor judge of what people will actually relate to – some of my most popular posts I was convinced would have no value to anyone else.

    Lists

    My side project TODO lists is much more fine grained than the TODO list that fits on one postit at work, and includes incredibly minor things, like “change colour of X”, and “add section for Y”. It is also broken down by project. This is because the gaps between things are bigger, and returning to something really easy will get me started, and hopefully moving on to bigger things as I get into it. Also because I have no-one else to catch anything that I miss. If I forget to change the colour of X, no UX designer will ever file a bug against me.

    It doesn’t matter how you do it, but when something isn’t your primary focus, you need a clear record of next steps. The hardest thing is accepting you need to document what is next when you’ve been so absorbed that you are convinced you will remember. You won’t.

    Ship Small and Often

    I think we can be afraid to launch our half-finished thoughts out into the world. But for side projects, I think it’s important to chill out about that and just ship where we are at. If you look through my image filter posts, you can see it building up bit by bit (including failed ideas). My Distractedly Intimate talk (and writing) builds on this and this and this and this.

    Share, and iterate. Let go of perfection. Keep going. If you’ve learned something, or created something (even if it doesn’t have unit tests, or isn’t production ready) put it out there. I believe in execution over ideas, and I think being precious about keeping ideas to yourself in case someone else gets there first is pointless.

    One By One

    This comes back to execution over ideas. I’m not short on ideas, and being “inspired” can be a really effective procrastination technique. I document my ideas, if they are exciting enough that I might want to pursue them later, but stay focused on one project at a time modulo urgency (i.e. I might take some time away from my “main” project to focus on a talk I’m prepping).

    The hardest thing is finishing. Finishing doesn’t even mean launching – it means got what I wanted to out of this project. For my image filter project, I did my experiments and learned what I wanted to but didn’t feel the need to make it into an “app”. I’d achieved my goal, and wanted to focus on something else. So I moved on to other things, but came back to it and turned it into an app when something else came up that built on it – a thing with an external deadline, so it pushed other projects out due to urgency. When that is over, I’ll go back to my next closest-to-finished-thing.

    The point is – it’s hard to do side projects, making it a side project makes it far more possible. Limiting myself to one also means that I define what “finished” is.

    Strategic Saturdays

    It’s really easy for me to write a blog post, at most it will take a couple of hours. 30 minutes before work is will product a first draft at least, or between dinner and the gym in the evening.

    It’s harder to find the time for things like coding, or longer-form writing, things that I feel like I need space in which to complete and focus on them. This is what I describe as “strategic” time. I don’t expect to find this during the week, my goal is to carve out 4 hours of strategic time over the weekend. This should also be a peak working time, which for me is the afternoon. So ideally I’ll do some smaller things or something fun in the morning, hit my stride after an early lunch, and head to the gym in the evening. Or start with a shorter workout, have brunch, and then focus time.

    I call these “Strategic Saturdays” after a course I took in December, because I also sometimes use this for work-work. When I step outside my day-to-day and put together a proposal for something longer term, this is often a small focused 2-4 hour block that I carve out of my weekend. But I’ve found that unlike allowing my day-to-day job to bleed into my weekend, this has a much better ROI.

    I can find one such block in a weekend, and not every weekend. So it’s important to use it well. Really focus on that most important project, whatever it happens to be, and really get in the groove. If I’ve used it well, I can often make incremental progress during the week, but if I’ve used it really well then I don’t need to.

    So What?

    I think side projects are helpful for a number of reasons: raising my profile externally (and sometimes internally), learning things that I’m interested in but not doing day-to-day, managing burnout by spending some time on things that I have more control over.

    They are a luxury. I can make this time because I don’t need to work insane hours at my actual job, and because I have no dependants. So, I don’t subscribe to the idea that everyone should have one or that it’s some kind of measure of anyone’s ability to do a technical job.

    But, I do think if you have something you really want to build, or write about, or both, you can do it without giving up your entire non-work life to it. This is how I manage that. Your results may vary.

  • 6 Signs of Over-Engineering

     

    tangled mess
    Credit: Flickr / Martin LaBar

    Sub parts of the Thing are described as “shared” or “reusable”… but no-one else is using them.

    The Thing has lots of unit tests, but few (or no) integration tests because they are so much harder to write.

    No one can explain clearly what the Thing does, because the generalised use case has obfuscated the actual problem it was originally supposed to solve.

    It would be helpful to see a UML diagram of the Thing, because no one can even begin to map the dependencies in their head. Or on paper.

    More time is spent worrying about elaborate corner cases than use cases.

    The word “framework”.

  • My Completely Unscientific GitHub Survey

    I was a software engineer without a GitHub account. I know, shocking, because everyone is supposed to have one – and actually the reason why I had to get resulted in me receiving a set of questions which assumed I would have a GitHub account, but Twitter account was optional.

    I didn’t have a GitHub account because I had never felt any need for one, and my reaction to needing one was slight panic, because I had this impression that it was a space where women got harassed. Of course, this is a statement that could be applied to The Internet in general, and I Internet a lot. Or Twitter, and I tweet a lot. But those things I would feel a sense of loss to do without.

    Also, I really had my fill of men patronising me and assuming I didn’t know what I was talking about during University, and it’s not like this experience has stopped since then. I don’t need to put myself in a position for men to make me feel like I shouldn’t be an engineer. The voice in my head is doing a perfectly adequate job, and does not need a chorus line.

    Anyway, I thought about why I had GitHub pegged as a Bad Space, and I came up with three main things:

    And so I tweeted.

    I have to get a github account. I've so far avoided it in part as my impression is that it's a place where women are harassed. Am I wrong?

    Pleased to say that I got replies from 6 women saying that their experience has been fine.

    Which is obviously completely unscientific, and not a representative sample. But it was enough to quash the feeling of dread I had. So hey, now I have a GitHub account.

  • My Inspiration App: App Concept

    Rules of being creative #7
    Credit: deviantArt / BlackLuna

    My app idea – a place to collect things that inspire, that can be found searching their tags, location, or type. I understand that people can and do use any number of other apps for this – Twitter favourites, for example, this is just supposed to be a purely happy and motivating place on our most intimate device – the phone.

    This has probably done elsewhere (I haven’t looked) but fulfils certain requirements that make it (I think) a good first project.

    Why This Project

    • Tapping into share intent. I like the idea of an app being an expansion pack for other apps – something that is possible on Android, but not so much on iOS. I want to build the kind of app that I could only build on Android.
    • Visually minimal, content is king. I care a lot about how things look, but have pretty minimal UX skills myself. Therefore, less UX the better.

    Components to Figure Out

    • Storage. Inspirations need to be stored (offline experience – do not plan on starting with a server) and searchable by tags (although ideally free text search on associated notes, too).
    • Subscribe. This is the initial way in for data, subscribe to the share intent and find ways to extract different kind of content – images, text (snippets, web pages, emails), people, places. Are there other intents that I want to subscribe to? Also need to be able to create something without an intent – just a note to self, or comment in conversation.
    • Sync. I’m not initially aiming to have a server and sync across devices (nice add on, though, if this project keeps interesting me), but I don’t want all data to be lost when the user gets a new phone. I think I can use the standard backup for this, but I am not sure – need to investigate.
    • Display. Obvious – if the user can’t see it, whatever data is there doesn’t matter. I want users to be able to look for tags, or just a random “I feel low, inspire me!”.
  • Getting Set Up on Android

    I used the event Programming Languages I’ve Been Meaning To Try But Haven’t Gotten Around To Yet at the Stripe offices (organised by Star Simpson) in San Francisco to get going on Android.

    Aside – I love the concept of this event. Great opportunity to hang out with your laptop, the only goal being to suck less at something by the end of the day. I would love to do this every month. Lots of women about, which was great! And I loved the Stripe offices – they have real Dr Pepper!

    I think I was in the spirit rather than the actual definition of the event because I’m familiar with Java (I even have readability in the kind written at work). And actually I’ve been doing some Android programming, but what I haven’t done – but want to – is write an Android app from scratch. I plan to do a bunch of posts on my experiences, from application concept to… however far I get.

    I started by downloading the SDK bundle – this comes with Eclipse and is all set up and ready to go. Really easy!

    Then I went through the Building Your First app tutorial, I made the default list-detail view and got it running on the emulator and my phone (much faster than the emulator).

    Then I gave Android Studio a go, as one of my friends said it was a lot faster.

    I just imported the existing project from Eclipse (even though it didn’t really do anything). Again, I got it running on the emulator (still slow) and the device (not noticeably faster than from Eclipse).

    I’m not completely sure which one to use, I’m used to Eclipse but Android Studio seems pretty easy. I think it should be be fine to switch between them though, so I will give Android Studio a go for a while.

    Some Gotcha’s

    • Don’t forget to start the Android emulator before trying to run your application.
    • Getting to Developer mode on a physical Android requires going to settings, about phone, and then tapping “build number” until it says “you are now a developer” – 7 times. You’ll then probably want to turn on USB debugging in the Developer Options menu that appears in settings.
    • I set a high minimum version to make things easier (didn’t matter in this, but will later when I’m making my actual app) – make sure your device is meeting this! I hadn’t used that Android in a while, so the OS was out of date.

     

  • More Experiments Around RGB Averaging

    I decided to replicate the showing/hiding the dominant hues in images with showing/hiding around the average RGB values instead.

    I created a class called RGBColor (just holds red, green, and blue values), similar to the one I created called HSBColor. I could have used the java.awt.Color class, but that insists on a range of 0-1 for the values, and I wanted to avoid conversions between that and the 0-255 that Processing uses by default. Or, better, allow me to set the colorMode to be in range 1-100, so that my tolerances were percentages – I found this made it easier to pick good values there.

    Images Showing Colors Around “Average” RGB

    Images Hiding Colors Around “Average” RGB

    Source Code

    package ui;
    
    import model.RGBColor;
    import color.ColorHelper;
    import processing.core.PApplet;
    import processing.core.PImage;
    
    @SuppressWarnings("serial")
    public class AverageRGBImageViewApplet extends PApplet {
    
    	PImage img;
    	static final int rgbTolerance = 50;  // Adjust this.
    
    	public void setup() {
    		size(640,480);
    		background(0);
    		img = loadImage(/* Your image file here */);
    		colorMode(RGB, 100);
    		processImage();
    	}
    
    	public void draw() {
    		image(img, 0, 0, 640, 480);
    	}
    
    	private void processImage() {
    		RGBColor color = ColorHelper.rgbColorFromImage(img, this);
    
    		for (int i = 0; i < img.pixels.length; i++) {
    			int pixel = img.pixels[i];
    			RGBColor pxColor =
    				new RGBColor(red(pixel), green(pixel), blue(pixel));
    			// Adjust this conditional to show/hide around average rgb.
    			if (!rgbInRange(color, pxColor, rgbTolerance)) {
    				float brightness = brightness(pixel);
    				img.pixels[i] = color(brightness);
    			}
    		}
    	}
    
    	private boolean rgbInRange(RGBColor colorA, RGBColor colorB, int tolerance) {
    		return Math.abs(colorA.r - colorB.r) < tolerance &&
    			Math.abs(colorA.g - colorB.g) < tolerance &&
    			Math.abs(colorA.b - colorB.b) < tolerance;
    	}
    }

    ColorHelper.java

    package color;
    
    import processing.core.PApplet;
    import processing.core.PImage;
    import model.RGBColor;
    
    public class ColorHelper {
    
    	public static RGBColor rgbColorFromImage(PImage img, PApplet applet) {
    		img.loadPixels();
    		int numberOfPixels = img.pixels.length;
    		float totalRed = 0f;
    		float totalGreen = 0f;
    		float totalBlue = 0f;
    
    		for (int i = 0; i < numberOfPixels; i++) {
    			int pixel = img.pixels[i];
    			totalRed += applet.red(pixel);
    			totalGreen += applet.green(pixel);
    			totalBlue += applet.blue(pixel);
    		}
    
    		// Calculate final rgb values.
    		float r = totalRed / numberOfPixels;
    		float g = totalGreen / numberOfPixels;
    		float b = totalBlue / numberOfPixels;
    		return new RGBColor(r, g, b);
    	}
    }
  • Eliminating the Dominant Hue from an Image

    I thought it would be interesting to invert the idea of showing only the dominant hue, and show everything but that instead. I used the exact same code, but inverted the if statement so:

    if (!hueInRange(hue, lower, upper))

    became

    if (hueInRange(hue, lower, upper))

    Effect is as follows, as with most of these, my favourite effect is on the painting – does it work better because it is a more studied use of color? I’m going to make something that will compare and contrast the effects, and allow me to loop through pictures so I can look for interesting results.

  • Folders of Images, Compare and Contrast

    Now I’ve experimented with things, I wanted to make something that would allow me to compare different effects on the same photo, and loop through a folder of pictures looking for nice effects.

    I overrode mousePressed() to change the image on click.

    The big challenge here was running out of Java Heap space once I had more than one image being processed – most of the images are around 2MB each. This meant I couldn’t just read in the image 3 times and manipulate it (or not manipulate it), and even drawing the original first then manipulating it meant I had two manipulated images. I tried a few things here, starting with just increasing the heap size, to no avail. Eventually what I did was resize the image down to the size I was going to display, and creating new images of that size, and then copying the pixels over.

    That resolved the issue, except when looping through the images and taking screenshots – I have no idea why this would affect things. For the most part, it worked fine though.

    It’s nice to compare the effects side-by-side, see the different bits that are highlighted, depending on the effect. Sometimes it just looks like the weather is completely different. I really love the night-time photos, and the effect that makes them black and white… apart from the lights. Including in this post my favourites and those I found most interesting.

    One suggestion I’ve had is to ignore pixels that are at extremes in saturation/brightness (i.e. close to black or white), but having looked at the effects on more images, I’m not convinced that is going to make things better.

     img 1
    img 2

    img 3
    img 4
    img 5
    img 6
    img 7
    img 8
    img 9
    img 10
    img 11
    img 12
    img 13
    img 14
    img 15
    img 16
    img 17
    img 18
    img 19
    img 20
    img 21
    img 22
    img 23
    img 24
    img 25
    img 26
    img 27
    img 28
    img 29
    img 30
    img 31
    img 32
    img 33
    img 34
    img 35
    img 36
    img 37
    img 38
    img 39
    img 40

    Source Code

    ColorHelper.java

    package color;
    
    import processing.core.PApplet;
    import processing.core.PImage;
    import model.HSBColor;
    
    public class ColorHelper {
    
    	public static HSBColor hsbColorFromImage(PImage img, PApplet applet, int hueRange) {
    		img.loadPixels();
    		int numberOfPixels = img.pixels.length;
    		int[] hues = new int[hueRange];
    		float[] saturations = new float[hueRange];
    		float[] brightnesses = new float[hueRange];
    
    		for (int i = 0; i < numberOfPixels; i++) {
    			int pixel = img.pixels[i];
    			int hue = Math.round(applet.hue(pixel));
    			float saturation = applet.saturation(pixel);
    			float brightness = applet.brightness(pixel);
    			hues[hue]++;
    			saturations[hue] += saturation;
    			brightnesses[hue] += brightness;
    		}
    
    		// Find the most common hue.
    		int hueCount = hues[0];
    		int hue = 0;
    		for (int i = 1; i < hues.length; i++) {
     			if (hues[i] > hueCount) {
    				hueCount = hues[i];
    				hue = i;
    			}
    		}
    
    		// Return the color to display.
    		float s = saturations[hue] / hueCount;
    		float b = brightnesses[hue] / hueCount;
    		return new HSBColor(hue, s, b);
    	}
    }

    CompareAndContrastHue.java

    package ui;
    
    import java.io.File;
    
    import color.ColorHelper;
    import model.HSBColor;
    import processing.core.PApplet;
    import processing.core.PImage;
    
    @SuppressWarnings("serial")
    public class CompareAndContrastHue extends PApplet {
    
    	int fileIndex = 0;
    	private String[] fileNames;
    	private static String filePath = "../data/images/";
    
    	static final int hueRange = 320;
    	static final int hueTolerance = 40;
    	private static final int imageWidth = 384;
    	private static final int imageHeight = 268;
    
    	public void setup() {
    		size(3*imageWidth, imageHeight);
    		background(0);
    		noLoop();
    		colorMode(HSB, hueRange - 1);
    		// Read in images.
    		File dir = new File(filePath);
    		fileNames = dir.list();
    		nextFileIndex();
    	}
    
    	public void draw() {
    		PImage img = loadImage(filePath + fileNames[fileIndex]);
    		img.loadPixels();
    		img.resize(imageWidth, imageHeight);
    		HSBColor color = ColorHelper.hsbColorFromImage(img, this, hueRange);
    		image(img, imageWidth, 0, imageWidth, imageHeight);
    
    		// Display image only showing dominant hue.
    		drawImage(createImage(imageWidth, imageHeight, HSB), img.pixels, color,
    				0, 0, imageWidth, imageHeight, false);
    
    		// Display image excluding dominant hue.
    		drawImage(createImage(imageWidth, imageHeight, HSB), img.pixels, color,
    				2 * imageWidth, 0, imageWidth, imageHeight, true);
    	}
    
    	public void mousePressed() {
    		nextFileIndex();
    		redraw();
    	}
    
    	private void drawImage(PImage img, int[] pixels, HSBColor color,
    			int x, int y, int width, int height, boolean showDominantHue) {
    		img.loadPixels();
    		// Manipulate photo, grayscale any pixel that isn't close to that hue.
    		for (int i = 0; i < img.pixels.length; i++) {
    			int pixel = pixels[i];
    			float hue = hue(pixel);
    			if (hueInRange(hue, color.h, hueTolerance) == showDominantHue) {
    				float brightness = brightness(pixel);
    				img.pixels[i] = color(brightness);
    			} else {
    				img.pixels[i] = pixel;
    			}
    		}
    		image(img, x, y, width, height);
    	}
    
    	private void nextFileIndex() {
    		while (true) {
    			fileIndex++;
    			if (fileIndex < fileNames.length) {
    				if (fileNames[fileIndex].toLowerCase().contains(".jpg")) {
    					break;
    				}
    			} else {
    				fileIndex = 0;
    			}
    		}
    	}
    
    	private static boolean hueInRange(float hueA, float hueB, int tolerance) {
    		return Math.abs(hueA - hueB) < tolerance;
    	}
    }
  • Visualising A Photo Series

    Whenever I’m scrolling through pictures I’ve taken, it seem like they are in sections – here’s when I was near the beach, he’s the park, the night sky and fireworks. I thought if you visualised the way that the dominant colors changed, patterns would emerge.

    I found the perfect layout for this, the sunflower layout, and then did nothing about it for… a long time. I claim the craziness of work and life. Also, I knew nothing about color, and had no idea how I would go about extracting the dominant color from an image.

    But I did some research and figured it out, the trick was working with hues rather than RGB values.

    And voila, here is another way to see the story of my trip to North Korea.

    Sunflower Visualization from Photos Taken in North Korea
    Sunflower Visualization from Photos Taken in North Korea

    Maybe the main thing I can see from this experiment is that I don’t take as colorful photos as I like to imagine I do. Also, that I took a lot of photos in North Korea (the major bottleneck to my blog posts about it).

    So I put together another collection of images – almost everything I’ve taken since mid-June aside from in North Korea, including the shipwreck, my trips to Tasmania, Queenstown (skiing!), Hong Kong, Tokyo and photos I’d taken around Sydney and visualised that with the result below.

    Sunflower visualization from photos taken between mid-June and late-August (aside from NK)
    Sunflower visualization from photos taken between mid-June and late-August (aside from NK)

    This is where I discovered that it doesn’t work well with panoramas (I had recently discovered the panorama feature on my iPhone and had taken a few, typically at 5-7MB in size) which threw an exception, because it was out of Java heap space. I’d need to make the code more efficient to process panoramas – for now, I just left them out.

    I’d like to add more to it, maybe clicking on an element in the layout could bring up the photo, with only the dominant color (with some tolerance) exposed. Maybe animate it with the image that’s being processed displayed alongside. I’d love to pull in my most recent pictures on Twitter and display them this way. I think, how many images are needed to create something cool looking may make that prohibitive, though. For now, I’m happy that I’ve got something working.

    Processing one image like this doesn’t take a noticeable amount of time, however this first (NK) one is made from 1048 images, and 2.26GB of data. On my 13″ Macbook pro… it takes a while.

    Note – I made an HSBColor class that just holds hue, saturation, and brightness.

     

    Source Code

     

    import java.io.File;
    
    import processing.core.PApplet;
    import processing.core.PImage;
    
    @SuppressWarnings("serial")
    public class SunflowerImages extends PApplet {
    
    	private static String filePath = "../data/nkimages/";
    	private String[] fileNames;
    
    	static final int hueRange = 320;
    	private static final int radius = 9;
    	private static final int scale = 7;
    
    	private static final double goldenangle = Math.PI * (3 - Math.sqrt(5));
    
    	private static final int wh = 500;
    
    	public void setup() {
    		size(wh, wh);
    		background(0);
    		noLoop();
    		colorMode(HSB, hueRange - 1);
    		// Read in images.
    		File dir = new File(filePath);
    		fileNames = dir.list();
    	}
    
    	public void draw() {
    		int n = 0;
    		double a = 0;
    
    		for (String file : fileNames) {
    			PImage img = loadImage(filePath + file);
    			if (img == null) {
    				continue;
    			}
    			print("processing image: " + file + "\n");
    
    			double h = Math.sqrt(n)*scale;
    			double x = wh/2 + Math.sin(a) * h;
    			double y = wh/2 + Math.cos(a) * h;
    
    			stroke(100);
    			HSBColor color = extractColorFromImage(img);
    			fill(color.h, color.s, color.b);
    			ellipse((float) x, (float) y, radius, radius);
    
    			a+=goldenangle;
    			n++;
    		}
    	}
    
    		private HSBColor extractColorFromImage(PImage img) {
    			img.loadPixels();
    			int numberOfPixels = img.pixels.length;
    			int[] hues = new int[hueRange];
    			float[] saturations = new float[hueRange];
    			float[] brightnesses = new float[hueRange];
    
    			for (int i = 0; i < numberOfPixels; i++) {
    				int pixel = img.pixels[i];
    				int hue = Math.round(hue(pixel));
    				float saturation = saturation(pixel);
    				float brightness = brightness(pixel);
    				hues[hue]++;
    				saturations[hue] += saturation;
    				brightnesses[hue] += brightness;
    			}
    
    			// Find the most common hue.
    			int hueCount = hues[0];
    			int hue = 0;
    			for (int i = 1; i < hues.length; i++) {
     				if (hues[i] > hueCount) {
    					hueCount = hues[i];
    					hue = i;
    				}
    			}
    
    			// Return the color to display.
    			float s = saturations[hue] / hueCount;
    			float b = brightnesses[hue] / hueCount;
    			return new HSBColor(hue, s, b);
    		}
    }