qnoid.com This is a personal website, at the outskirts of the web, away from social media and publishing platforms. en-us Creative Commons Attribution 3.0 License (CC-BY 3.0) Wed, 01 Jan 2025 14:29:50 +0000 Mon, 24 Feb 2025 15:36:20 +0000 http://cyber.law.harvard.edu/rss/rss.html Hugo -- gohugo.io 1140 https://qnoid.com/ 2025 https://qnoid.com/2025/01/01/2025.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2025/01/01/2025.html Hope for the best; expect the worst.

]]>
Wed, 01 Jan 2025 14:29:50 +0000
Chaos https://qnoid.com/2024/12/12/Chaos.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2024/12/12/Chaos.html In the last 15 years, I have lost all of my savings twice now and gone into a significant debt twice more. Each time I have rebuilt my life back up. In the last 15 years, I have only earned a salary in 10 of these and had no other income to live by. In the last 15 years, I have faced anxiety and depression and came back from the brink.

I have done all that while moving across countries, cities, uprooting my life and dealing with fear, uncertainty and instability in the process. How do you expect a man to grow in such harsh conditions? How do you expect him to feel safe? What do you think it does to him? What do you make of him? Is he a free spirit? Do you really want to live his life? Does he come across as a jerk? Can you accept him for who he is? Is he worthy to be celebrated as a human? Does he deserve love? Can you really love him?

How do I expect order when I am made of chaos?

]]>
Thu, 12 Dec 2024 23:56:58 +0000
In case of emergency break (empty) glass https://qnoid.com/2024/11/23/In-case-of-emergency-break-empty-glass.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2024/11/23/In-case-of-emergency-break-empty-glass.html Somehow, I made it. I am lucky son of a bitch. I know it. I prey that my luck does not run out in this lifetime. At times, it feels that’s all I have. A lucky star. Perseverance? Yes. Patience. Plenty. Grit? Check. Still, you can be capable and demonstrate all of that yet still fail the dice roll.

I was well past the deadline of giving notice to my flat. Which in practice would mean being liable for money I wouldn’t have and had to borrow while also getting my ass kicked back down the ladder. Imagine playing high stakes poker. It’s the last round. You have lost all of your money and this is the final hand. You decide to bet the house on a last ditch attempt to win everything back. You win the hand.

I started a new role in June, on a 6 months probation. I started building myself back up again. Saving money to prepare for the next emergency.

It’s been almost 6 months and for the past couple of weeks I finally had a feeling of peace and stability. I would even go as far as to say I had been the happiest and most relaxed I had ever been since a brief period in my twenties.

Then calamity came knocking at my door.

On Thursday night at 23:00, I heard a loud, persistent, urgent knock on the front door. Bang! bang! bang! I opened the door to see a man from the fire brigade instructing me to leave the property. The building on which I am housed was at a risk of a collapse. I had 5 minutes to go. No time to pack a bag. Things were happening so fast before I knew it I was one of about 70 people in a Sports Leisure Centre with a blanket and a chair to sit on. I spent the night barely getting any sleep.

With very little explanation and a lack of timely, prompt and regular updates, my mind started filling in the blanks for me. All I could think of was the worst. I couldn’t believe that having just spent the last year building my life back up, it could all just crumble again in an instant.

I thought of how I could lose all my possessions should the building collapse to the ground. How I would have to use months of savings to find temporary accommodation, buy clothes and basic household items. How this was putting at jeopardy my job and how I could lose it. How I would have to build myself back up yet again.

I started feeling very vulnerable, tired and powerless. All I wanted in that moment was to have a shower, take a nap and to feel safe in the presence of a friend, family or a loved one.

I looked at the glass screen of my phone, opened up the contacts app and starting scrolling through my contacts.

  • This person seems upset with me and don’t know why.
  • This person hasn’t responded the last few times I have reached out to.
  • This person is just an acquaintance.
  • This person is an ex.
  • This person and I have lost touch.
  • This person is going through some hard time right now.

It slowly dawned on me that there is no-one I feel close enough to, don’t fear rejection, one who lives in close proximity, one I can reach out to, one I can rely on. I am by myself. Which, to be fair, has felt true for most of my life. I was staring at an empty glass. I felt like crying.

After 24 hours I finally made it back home. It’s corny but it’s true. Home sweet home. I channelled my mom’s attitude who knows how to have fun, lift others and be full of life even when she is hurting. I had a hot shower, trimmed my hair, shaved my beard, put on a shirt, my perfume and headed out to clear my head. I wanted to be in the presence of others, feel connected and alive.

I wanted to feel human again.

]]>
Sat, 23 Nov 2024 14:50:20 +0000
Countdown https://qnoid.com/2024/05/13/Countdown.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2024/05/13/Countdown.html I don’t know how to write this post. I can write it as a rant. I can write it to be hopeful, put a positive spin on it. I can write it in a way that is reflective, poignant and sad. I am upset. That much I know. I am upset that I find myself in a situation I thought I had escaped or at the very least moving away from.

Between my 9 years relationship coming to an end, resigning from a workplace that was making me miserable, the UK economy being in a dire state and the job market in the tech industry facing its biggest crisis probably since the dot com boom, I am heading towards bankruptcy.

Fuck that.

Today I basically need to give notice to my flat and with that start the clock. I have 2 months to find a job or pack my shit and fuck off of London. That means going back to Greece and live with my mom. The last time I lived with my mom was 30 years ago. What happens after that? Who fucking knows. I’ll just go for a swim.

I don’t know what needs to go into this post. I have stated how I want this website to be mostly about human stories. How life is fucking messy. I am just not in the mood to be reflective right now when I am in the middle of my life crashing down like a house of cards.

I know very well the challenges I have been facing ever since I was a child. I always did. I am aware of the risks I am taking and what makes my life hard. I am fortunate to be in good health so it’s easy to tell me I am being over-dramatic; offering unsolicited opinions and lecturing from the comfort of your perfectly knit life you have wrapped in a bow telling me I have a choice.

Fuck off.

]]>
Mon, 13 May 2024 11:39:09 +0100
Delta’s 10-year journey to the top of the App Store https://qnoid.com/2024/05/07/Deltas-10-year-journey-to-the-top-of-the-App-Store.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2024/05/07/Deltas-10-year-journey-to-the-top-of-the-App-Store.html David Pierce at TheVerge has an interview of Riley Testut about Delta’s 10-year journey to the top of the App Store on the latest episode of the VergeCast.

To distribute Delta Riley went through the effort of creating an alternative App Store, AltStore. AlStore on the iPhone which is now officially supported by Apple as of iOS1 17.4 is made possible thanks to EU regulation.

Riley’s perseverance, ingeniously, courage and resolve are commendable. Alongside Shane Gill they accomplished more than I could ever do with Windmill.

I tip my hat to you both 🎩.
Well fucking done.


  1. Soon on iPadOS too. ↩︎

]]>
Tue, 07 May 2024 18:00:04 +0100
Debugging Closed Source Code https://qnoid.com/2024/04/11/debugging-closed-source-code.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2024/04/11/debugging-closed-source-code.html NSLondon kindly offered me a slot to talk about a whodunnit mystery at NSLondon 2024.2.

I have been absent from the developer scene in years, cause life! I had a great time and got a buzz out of giving this talk. My favourite moment was when people clapped at the big reveal! Thank you! It was good to see some familiar faces from back in the NSConf1 days 👋🏽.

I want to give a special shout out to Daniel Jalkut who gave a talk at NSConf (sometime between 2013 and 2015) where he went on to debug Mail.app. Daniel2 was the first one to talk about frames and registers that I had come across. He was an inspiration. I hope this talk can act as an inspiration to others!

Slides

References


  1. Scotty if you are reading this, I miss NSConf! ↩︎

  2. Check out his apps at redsweater ↩︎

]]>
Thu, 11 Apr 2024 10:42:39 +0100
A decade of progress in finance is only the beginning https://qnoid.com/2023/06/25/A-decade-of-progress-in-finance-is-only-the-beginning.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2023/06/25/A-decade-of-progress-in-finance-is-only-the-beginning.html Ever since coming to the UK, first time in 1998 as a student, there has always been a need to exchange currencies and send money across borders. Back then, my mom would have to convert Greek Drachma1 and wire them to a UK bank account as British Sterling. In the nineties, making a bank transfer from one country to another, in a different currency was an opaque process, associated with high costs with very little transparency on the fees and how it all worked. The cost was tens of pounds (thousands of drachmas) and it would take days for the transfer to complete. Banks were pretty much responsible and in control of currency exchanges and money transfers in a market with a dominant position.

As late as 2010, about 10 years later and the introduction of the Euro in Greece, Sterling in the UK, transferring money to a Greek Euro bank account would still cost tends of pounds and take days to complete. The only difference is that going to a branch wasn’t required anymore. You could setup, make and monitor the progress of a transfer all with the power of the internet, using mobile or web banking. Roughly, you would come to expect the following in terms of the time taken and associated cost:

  • £XX (tens) of pounds in fees from a UK bank to “convert and make” a transfer
  • €X of euros in fees from a Greek bank account to “accept” the transfer
  • X days for the transfer to complete and the money to become “available” in your account

Say, to send £1000, you would have to pay £30 to a UK bank, €5 to a Greek bank and wait 3 business days for the money to become available. It was widely accepted and understood that a transfer on a Friday evening, could mean your money was outside of your control and unavailable until Tuesday.

Over the last 10 years there’s been many changes in banking that albeit slowly, have lead to a steady overhaul of the banking system over time. Changes to KYC2, the introduction of the E-Money Directive3, SEPA4, the Cross-border Payments Regulation and the migration to IBAN for bank accounts to name a few.

In my opinion, these changes in the regulatory framework is what eventually forced banks and new participants in the market to innovate using technology.

To the point where, today, I can send £1000 from a UK bank account with a total cost of £4.49 and have the money available within seconds to my Greek account, even on a Sunday. I believe this is only the beginning of the banking transformation and one factor that can play a role and have a knock-on effect on how we think of money/currency, what is the role of a bank account, where/how we get paid/credit, how a tax residency is defined.

As someone in tech and with some experience working in fintech5, I find this prospect more exciting and the environment ripe for the next innovation in banking/finance. Keep in mind that technology followed regulation reform that paved the way; not the other way around.

]]>
Sun, 25 Jun 2023 11:15:47 +0100
Back in London https://qnoid.com/2022/05/20/back-in-london.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2022/05/20/back-in-london.html It’s almost been 5 years since I left. Yet it feels like I never did. I am getting goosebumps writing this. The Smiths is playing on Spotify. Take me home tonight. Take me out tonight. Because I want to see people and I want to see life.

I see the light UK drizzle outside. Tears of happiness are running down my eyes. I can’t believe I’m back. I made it. I’m back. Back in my old flat. That’s a funny story. With my old furniture back. A bit rundown but the same. Like my body.

I had no idea. I would have never imagined. I wouldn’t believe you if you told me. Five years ago, I was running away. Now I’ve run home. It’s been less than a week yet it feels like a month. Feels like I’ve never left. I am fortunate. I know I am. I am also a survivor. I can’t believe I’ve survived this but I did.

In these past 5 years I found my father. In these past 5 years, I did years of therapy to get to the bottom of my anxiety and depression. In these past 5 years I got to know myself better that ever before.

I am glad I did this. Even though I didn’t know I had to. I neither had the insight nor the awareness 5 years ago. Imagine having to “put on hold” your life as it is today and go away for 5 years to work on yourself, pay your dues, pay back the debt from the time you’ve borrowed to keep going. I was in my late thirties. I now am in my early forties. I feel good! I feel good because of how much I’ve grown. I feel good knowing this is behind me.

As I was getting ready to leave Athens, I met with a friend. He said to me, “This is the most relaxed I’ve ever seen you as you are about to pack up and leave again.”

I am not running away anymore.

]]>
Fri, 20 May 2022 10:31:44 +0100
A change is gonna come https://qnoid.com/2022/05/02/change.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2022/05/02/change.html

]]>
Mon, 02 May 2022 15:19:51 +0300
Interview on the CERN Alumni Podcast https://qnoid.com/2021/03/26/cern.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2021/03/26/cern.html CERN AlumniCast - Interview (Part 1) with Rachel Bray.

Rachel asked me to give an interview as an alumni about my experience arriving and working at CERN.

We talk about the circumstances that lead to my arrival at CERN, my life there as a technical student and how CERN defined my career trajectory for the next 10 years. Also, the great people that supported me and taught me valuable lessons at the age of 21 that shaped me as a professional.

Rachel was really accommodating and asked questions that dug deep into the human psyche. It’s a story I was happy to share and I would like to thank Rachel for giving me the opportunity to do so.

]]>
Fri, 26 Mar 2021 08:46:47 +0200
Developing Applications for iOS using SwiftUI https://qnoid.com/2021/02/11/Developing-Applications-for-iOS-using-SwiftUI.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2021/02/11/Developing-Applications-for-iOS-using-SwiftUI.html Stanford has shared the Spring 2020 course online for free. You can find lecture videos, presentation slides and assignments that will teach you the basics and guide you on your way to becoming an iPhone developer. This is how I started as an Apple Developer back in 2009.

Know that doing the course is only the beginning. You will still have to dedicate time and effort practicing what you have learned. Building verylargebox as a side project was what helped me build confidence and accumulate experience.


Developing for mobile was fast becoming an essential part of your business strategy at the time. The iPhone was still in its infancy in 2011 so not much experience was needed or expected. It might be a higher bar to clear today but demand, as far as I can tell, is still high. As a seasoned software engineer it was easier for me to get a job and get started so keep that in mind.

If you are young and only just starting out as a software engineer, see if you can get a some work experience through school. Alternatively, reach out to companies that do iOS and ask whether they offer any short term internships.

  • AIESEC - “AIESEC is a global platform for young people to develop their leadership potential through international internships and volunteer opportunities.”
]]>
Thu, 11 Feb 2021 08:18:23 +0200
To live without fear https://qnoid.com/2021/01/30/To-live-without-fear.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2021/01/30/To-live-without-fear.html In May of 2015 I visited a long time friend in Israel. It was my first time there. Our friendship dates back to the late 90s where we studied together at University. All these years, he kept asking me to visit. I was nervous. Israel had a long history of conflict and turmoil.

I finally took the plunge and booked a flight. I stayed for a week and I remember feeling unsettled at least for the first few days. Anticipating that something bad was going to happen at any moment. At the same time, I was impressed by the industrial development I could bear witness to.

This wasn’t a country paralysed in fear. People weren’t just dragging their feet. They where studying, working, falling in love, raising children, building and decorating their houses, going for coffee, surfing at the sea. They celebrated life, making the most of it.

In my head I couldn’t reconcile the two. How can people, under constant threat, live life seemingly carefree?

– “Are you not afraid?” I asked.
– “To live in fear is to not live your life.” Eli responded.

It was a profound statement to hear back then. Still, I believe there is more to what Eli said. To live without fear is to live life in solidarity. It’s ok to be afraid; you are not alone.

]]>
Sat, 30 Jan 2021 14:59:56 +0200
Two more examples of Encoding and Decoding Custom Types in Swift https://qnoid.com/2021/01/20/codable.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2021/01/20/codable.html Overview

Swift provides a Foundation API to serialise from and to JSON “by implementing the Encodable and Decodable protocols on your custom types”.

The team at Apple has also written a great article about Encoding and Decoding Custom Types that provides a few examples to get you started and a few ones that require “a custom implementation of Encodable and Decodable”. I want to add two more examples that may not be immediately obvious after you read the article.

Both examples build upon the knowledge you have on encoding and decoding custom types from the article above. So consider that a prerequisite. The first one shows how to decode only part of a JSON document. This can be useful when working with an API where you are only interested in part of the response.

The second example is useful typically in an API that uses JSON to encode a “data” or “error” response. In this case, the HTTP response code is typically 200 OK yet the actual JSON response communicates whether the request has been successful, returning the data requested or unsuccessful in which case an error is returned in the JSON payload.

Decode only part of a JSON document

{
  "user": "qnoid",
  "created_at": "2021-01-19T18:47:01+0200",
  "text_entries": [{
      "text": "Hello!"
    },
    {
      "text": "¡Hola!"
    }
  ]
}

In the example above, we are only interested in the text entries returned and have no need for the rest of the data. Consider an Entry type describing each text entry that stores the “text” and a TextEntries type that holds the Array of entries:

struct Entry: Codable {
    let text: String
}
struct TextEntries {
    enum Key: String, CodingKey {
        case entries = "text_entries"
    }
    
    let values: [Entry]
}

In the example below, the TextEntries type is extended to conform to the Decodable protocol by implementing its required initialiser, init(from:):

extension TextEntries: Decodable {
    
    init(from decoder: Decoder) throws {
        let response = try decoder.container(keyedBy: Key.self)
        var entries = try response.nestedUnkeyedContainer(forKey: .entries)
        
        var values = [Entry]()
        while !entries.isAtEnd {
            let entry = try entries.decode(Entry.self)
            values.append(entry)
        }
        
        self.values = values
    }
}

The TextEntries type can now be decoded using the JSONDecoder:

let entries = try JSONDecoder().decode(TextEntries.self, from: data)

Let’s dymistify. JSONDecoder uses the initialiser in the TextEntries type to decode the data. In our case, the root object in the JSON is a collection of name/value pairs 1. The try decoder.container(keyedBy: Key.self)‌returns the data stored in this decoder as represented in a container keyed by the given key type.”. In simple terms, the code will try to interpret the root object as a dictionary where its keys are typed by the TextEntries.Key enum type. The TextEntries.Key defines only one key present, namely the case entries (“text_entries” in JSON), as this is the only one we are interested in. The response variable represents that dictionary.

Next, we want to extract the array of text entries. Hence the call to nestedUnkeyedContainer(forKey:) which returns an UnkeyedDecodingContainer type. You can think of the UnkeyedDecodingContainer as an iterator where every call to decode() decodes the type at the current index, starting at 0, then increments the index. When the iterator is exhausted, isAtEnd will return false.

At the end of the initialiser, the values are initialised with every entry in the “text_entries” Array and a TextEntries instance is returned.

entries.values.map { entry in
    entry.text
}

Decode a custom success/error JSON response

{
  "success": true,
  "contents": {
    "text_entries": [{
        "text": "Hello!",
      },
      {
        "text": "¡Hola!",
      }
    ]
  }
}
{
  "success": false,
  "error": {
    "code": 1,
    "message": "User not found"
  }
}

In this case you have two possible JSON responses thus the decision as to which one to decode must be done at runtime. One is considered a success with the “contents” (or “payload”) holding the data you are interested in. The other one is a failure that includes an “error”. The Result type is ideal to describe this “exclusive or” truth and the init(catching:) initialiser is fitting in trying to decode a successful response or throw the returned error in case of a failure. Let’s see how that looks in practice.

Consider the Error type that stores the “code” and “message”:

struct Error: Codable {
    enum Key: String, CodingKey {
        case error
    }

    let code: Int
    let message: String
    
    init(from decoder: Decoder) throws {
        let response = try decoder.container(keyedBy: Key.self)
        let contents = try response.nestedContainer(keyedBy: CodingKeys.self, forKey: .error)
        
        self.code = try contents.decode(Int.self, forKey: .code)
        self.message = try contents.decode(String.self, forKey: .message)
    }
}

The Error type can now be decoded using the JSONDecoder:

let error = try JSONDecoder().decode(Error.self, from: data)

Now consider the Contents type with an “entries” property of type TextEntries:

struct Contents {
    enum Key: String, CodingKey {
        case contents
    }
    enum CodingKeys: String, CodingKey {
        case entries = "text_entries"
    }

    let entries: TextEntries
}

extension Contents: Decodable {
    init(from decoder: Decoder) throws {
        let response = try decoder.container(keyedBy: Key.self)
        let contents = try response.nestedContainer(keyedBy: CodingKeys.self, forKey: .contents)
        
        self.entries = try contents.decode(TextEntries.self, forKey: .entries)
    }
}

As a reminder, the Contents is at the root object in the JSON data. First, we obtain the container as keyed by the “contents” key, followed by the “text_entries” as the TextEntries type:

struct TextEntries {
    let values: [Entry]
}

extension TextEntries: Decodable {
    init(from decoder: Decoder) throws {
        var entries = try decoder.unkeyedContainer()
        
        var values = [Entry]()
        while !entries.isAtEnd {
            let entry = try entries.decode(Entry.self)
            values.append(entry)
        }
        
        self.values = values
    }
}

Notice how in this case the TextEntries decoding is part of the Contents decoding hence the call to unkeyedContainer() as this is done under the “text_entries” key2. The Contents type can now be decoded using the JSONDecoder:

let contents = try JSONDecoder().decode(Contents.self, from: data)

contents.entries.values.map { entry in
    entry.text
}

Before we can write the closure expected by init(catching:) for the Result type, the Error type must be declared as a Swift.Error that we can throw:

extension Error: Swift.Error, CustomNSError {
    public static var errorDomain: String = "com.qnoid"
    
    var errorCode: Int {
        return code
    }
    
    var errorUserInfo: [String : Any] {
        [NSLocalizedDescriptionKey : message]
    }
}

With both Content and Error types defined, here is how we can now construct a Result.

let result = Result<Contents, Swift.Error> {
        do {
            return try JSONDecoder().decode(Contents.self, from: data)
        } catch {
            //log `error` in the catch block
            throw try JSONDecoder().decode(Error.self, from: data)
        }
    }

Effectively, the closure will try to decode the Contents type. In case that fails, there is an assumption3 that instead this is a failure response and the included Error is thrown. Keep in mind that the try to decode the Error might fail, in which case the Result type will throw the Swift.Error as thrown by the decode(from:) function.

This is the calling code:

do {
    let contents = try result.get()
    contents.entries.values.map { entry in
        entry.text
    }
}
catch {
    error
}

Resources


  1. As opposed to an ordered list of values. ↩︎

  2. This is a good hint that serialising a type is highly coupled with the decoding algorithm itself and should take into consideration. ↩︎

  3. Even though, this contract is well defined, consider logging the error thrown instead of silently ignoring it. ↩︎

]]>
Wed, 20 Jan 2021 19:39:07 +0200
People, teams, creativity and innovation https://qnoid.com/2021/01/04/teams.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2021/01/04/teams.html

I watched a few documentaries on the history of video games and the rise of an industry.


I am a sucker for these types of documentaries. Documentaries that provide a retrospective, hearing the stories from the people that made history. Nostalgia definitely played a part in my enjoyment as well. I grew up in the 80s and the 90s so I saw the video game industry unfold before my eyes.

What I find most fascinating is how people came together and how their creativity flourished. I wish I could know more about both the personal and societal circumstances that lead to that. Granted, back then the boom of personal computing and the video game industry was just getting started. Still, what I want to know is how people had the time, support, resources, attitude and appetite to take risks and pursue their dreams?


The gaming industry hasn’t stopped as far as I can tell. My guess is that there are way more indie developers now. On the other end of the spectrum, video game productions are growing bigger and bigger. There doesn’t seem to be a shortage in diversity and development of video games.

The rest of the tech scene looks and feels much different. You have “indie hackers” chasing monthly recurring revenue. Startups thinking of becoming the next billion dollar company. Venture Capitalists betting money left and right playing the odds of winning back tenfold on an acquisition or a public listing.


We live in a world that is more connected, technology is more accessible, the bar to entry for manufacturing and production is lower yet Facebook, Apple, Amazon, Microsoft and Google pretty much dominate.

It seems like we have all become numb, waiting for the next big tech event, year after year to hear about the “new innovations” and latest products.

What happened to the tinkerers, creatives, rebels and dreamers in the tech industry? What will it take to create a movement? I’m dying to be part of one right now.

]]>
Mon, 04 Jan 2021 16:19:24 +0200
Bravery https://qnoid.com/2020/12/22/Bravery.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2020/12/22/Bravery.html Bravery is looking despair in the eye. Feeling hopeless yet not letting fear overcome you. Knowing that there is nothing you can do for the people you love and care about yet still facing that fear head on. Even if that is merely not collapsing under that enormous pressure.

]]>
Tue, 22 Dec 2020 17:20:19 +0200
What it takes https://qnoid.com/2020/11/26/What-it-takes.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2020/11/26/What-it-takes.html The music that YANNI produces has this amazing quality of moving me to tears, getting me pumped, making me melancholic and inspiring me. I have been listening to his music since the 90s and it still has the same effect on me.

Just recently I came across a Q&A with Yanni at The Grammy Museum with journalist Steve Hochman at the Los Angeles, USA dated September 18, 2014. Here are a few things that stood out and spoke to me on personal level for different reasons. I do recommend that you watch the whole session. I have edited the responses for brevity down to the specifics that caught my attention.

On creativity and judgement. How the two don’t go together.

Question: “Being a creative soul, is your mind constantly working? Are you able to quiet your mind and if so, how?”

“You must not judge it. Judgement and creativity are opposites. They cannot exist together. Because as soon as you judge what’s coming in, you are outside looking at yourself and the creative moment has just ended.”

On the importance of technology being accessible. How something as “primitive” as a short wave radio has technological merit and can be empowering as long as freedom of expression exists and there is no centralised control.

Question: “You came from a place that was a fairly small town and you didn’t speak any english when you came here. I am curious what music you were exposed to there?”

“We didn’t have a turntable or a tape recorder so the only music I could hear was on the radio. […] At night I would stay, I have a short wave radio and since I was living in southern Greece, I had access to all of the music from Italy, Rome I could hear all the stuff, all the way to north Africa, Morocco, Middle East and I would sit there and I would listen to all types of music.”

On depression, the importance and significance to feel worthy as a human above all of your titles and achievements. His depression kicked in having reached new heights at the time. Performing live at the Acropolis and being the only westerner to perform at the Taj Mahal and the Forbidden City at the time.

“There was a time in my life that I got lost. I went through a depression. […] I run home to Greece, stayed with my mom and dad and didn’t play the piano for a whole year. I did not touch it. I just wanted to know that I could be a normal human being. That there was a Yanni without the music.”

On what every artist strives for and how time is the ultimate judge.

“I was thinking, when I started writing music. What could I possibly do that could last more than a week. Maybe a year. People are going to hear a song then a year later they can go ok, next one, I can’t hear this one anymore. Every artist strives for that. We all strive to create things that stand the test of time. […] Ultimately, I will never know. I can’t decide that. You have to decide that and the ultimate judge is time and I have nothing to do with it.”

I feel tired. Tired and lost.

  • Yanni - No borders, no boundaries - “A 60-min documentary from PBS show, narrated by Christopher Plummer. This is a unique film journal describing the extraordinary effort, purpose and achievement of Yanni’s groundbreaking performances at Taj Mahal, India and Forbidden City, China, 1997.”
  • Coding - “It’s like the 80s all over again, where you plug in a machine, and you can instantly start coding. I for one miss that.”
  • Coding challenges as part of an interview - “Nobody is watching me type and judging.”
  • Over a year since Apple gave me an ultimatum on Windmill - “I got especially emotional hearing an audio clip of a book seller pleading to Jeff Bezos to restore their business operations so that they could earn their livelihood.”
  • An Apple Developer for 10 years - “On a personal level, Windmill allows me to have freedom of expression, be creative and pursue excellence.”
]]>
Thu, 26 Nov 2020 16:06:24 +0200
Knowledge https://qnoid.com/2020/11/26/Knowledge.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2020/11/26/Knowledge.html One of the things I remember being told that has stood the test of time, goes back to my University years. It is about what is expected of you at each stage of your higher-level education and where the knowledge you achieve leads you.

First and foremost, to obtain a bachelor, you must prove that you can research. In other words, gather enough information on a subject that will help with your understanding of the problem.

As a practitioner of software engineering, that could be doing research on design patterns and being able to write code in the one that is best suited for the task at hand.

For a master’s degree. Not only you have to research but also draw your own conclusions from that research. You have to be able to put two and two together. You need to prove that you have mastered the knowledge enough that you can wield it.

Each individual knowledge of generics, asynchronous programming and http may not be enough. You will need to be able to combine them in a meaningful way to write an http client capable of sending requests, serialising responses and calling back with results.

For a PhD, you have to read on existing research, draw your own conclusions, do your own research that leads to something new which in turn can be added back to the knowledge pile. That could be because you realise that existing knowledge is not enough. You need to break new ground.

In a programming language that you use, that could be working on the interpreter or the compiler to introduce new features to the language that help you write code that previously wasn’t possible.

It is fair to say that each stage takes hard work. It certainly can’t be done on a whim. It takes time to do research, evaluate, comprehend, apply and expand your knowledge.

This mantra of knowledge gathering and application isn’t unique to a University study. It is very much true as part of a professional career too. It has been my guide to a professional conduct and in critically evaluating my place on a subject matter.

]]>
Thu, 26 Nov 2020 13:32:13 +0200
Tired https://qnoid.com/2020/09/12/Tired.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2020/09/12/Tired.html Sat, 12 Sep 2020 14:19:53 +0300 Back to the 80s and the 90s https://qnoid.com/2020/09/11/Back-to-the-80s-and-the-90s.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2020/09/11/Back-to-the-80s-and-the-90s.html Between listening to Poolside FM1 and watching the PlayStation Revolution documentary it felt good to escape the constant news cycle, twitter2 and coping with my mental struggle.

Everyone at Poolside FM, know that joining you at the pool has brought joy to my life.

Thank you.


  1. The fact that “Poolside FM was conceived one awfully rainy summer in the Highlands of Scotland” blows my mind. ↩︎

  2. Please, someone, anyone, come up with a replacement to the current form of social media already. ↩︎

]]>
Fri, 11 Sep 2020 14:40:36 +0300
Apple's letter to developers https://qnoid.com/2020/08/22/apple-letter-to-developers.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2020/08/22/apple-letter-to-developers.html Paraphrasing

The App Store is not simply a marketplace – it is part of a larger bundle of tools, technologies and services that Apple makes available to developers to develop and create great applications for iPhone, iPad and other Apple products. We know you knows this. You have been a major beneficiary of this investment and support. You have made great use of Apple-provided tools, such as TestFlight, VOIP, Stickers, iCloud document storage, ARKit, Messages Extension, ReplayKit, and Push Notifications. To highlight one example, for years now, you have used Apple’s groundbreaking programming language, Swift. […] Apple doesn’t charge separately for the use of Swift or any of the other tools that you have used to develop great apps on iOS.

Not only has Apple supplied tools and technologies for you to build your apps, but it also provided a marketplace—the App Store—to help make them a success. Because of the App Store, you have been able to get this app and other apps into the hands of millions instantly and at no cost, as Apple charges nothing upfront to distribute apps that are free to download. […] Of course, you could not have achieved this success without great apps, but it nonetheless underscores the value Apple brings to developers like you.

Still, you have many ways to reach consumers, including through Android stores, PC-based platforms, consoles (Xbox, Nintendo, Play Station) and your very own app marketplace.

Apple has hundreds of thousands of developers distributing apps on the App Store, and Apple is proud that it offers them all, from the student in her living room to some of the largest companies in the world, the same terms and opportunities.

The App Store is not a public utility.

Sincerely,
Apple

Exhibit E, Email exhibits from Epic v. Apple.

]]>
Sat, 22 Aug 2020 13:10:08 +0300
Oh how far the apple has fallen from the tree https://qnoid.com/2020/08/18/apple-tree.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2020/08/18/apple-tree.html

]]>
Tue, 18 Aug 2020 17:02:51 +0300
What has become of Apple? https://qnoid.com/2020/08/18/what-has-become-of-apple.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2020/08/18/what-has-become-of-apple.html At some point in the last few weeks the ability to run code on both an iPhone and an Apple TV I own has not been possible. In Apple Developer terms, Xcode fails to codesign with an error “Signing for [project name] requires a development team. Select a development team in the Signing & Capabilities editor.”. Under “Preferences”, “Accounts”, I get a “No Teams” message for the Apple ID I use as an Apple Developer.

Assign a project to a team, Xcode Help

This issue went completely off the radar, for weeks, as I have been focused on writing a framework instead, hence never had the need to run code on a device. I reached out to Apple for help and 10 days later here is the gist from their response.

I escalated your issue to the senior desk, and have been advised to tell you that Apple Developer Program Support only provides direct assistance to Developers that hold active Apple Developer Program memberships.

Effectively Apple says it cannot help because I am not a paid member.

Leaving aside the fact that I had been an Apple Developer for 10 years until I stopped this year, since when does the “I cannot run code I write on hardware I own” started being a paid, active Apple Developer Program membership support ticket?

Apple may claim that all you need is “just an Apple ID” to “access Xcode, software downloads” and “test your apps on devices” in their Apple Membership support page yet it casually dismisses the fact “I cannot” under the pretext of “not an active Apple Developer”.

Now, I believe this to be some misconfiguration on Apple’s backend combined with the level of support you have come to expect from an enteprise company that Apple has become, still this is an indication on where Apple’s priorites lie.

Apple has been on a very slippery slope over the years, methodically excercising control on distributing and running software on Apple platforms while at the same time trivialising and commercialising software.

Are we on a path where being a software developer will only be a profession exercised as part of an established business? With distribution only controlled by Apple and the only means to deliver software via the App Store? In this dystopian future how much freedom do we have over devices we own and code we write as independent software engineers?

The main reason I stopped the development of Windmill wasn’t because Apple rejected Windmill on the iPhone. I stopped because Apple made it pretty clear it wasn’t happy with Windmill and brought forward violations of my Apple Developer Membership agreement.

With Apple now threatening to cut Epic off from iOS and Mac Developer tools by closing down their Apple Developer account based on violations of the App Store agreement, this is exactly the kind of retaliation I feared at the time.

It’s upsetting, sadenning, madenning and troubling because I love the Swift language, the Apple SDK, the devices and the development platform yet Apple seems hell bent on ruining it all with its petulance, not having the courage to accept it is in the wrong.

I’ve been a self-employed dev ever since I became an adult (over 35 years). The Apple platform has been my main base of income for the last 30. I’m invested in this platform. And suddenly Apple wants to change the rules - from being a provider of a platform and infrastructure to the one controlling who can use that platform and who can’t - I feel immensely threatened by this. This is not progress, this is the opposite. Thomas Tempelmann

Update (23 Aug 2020)

I pushed back

I should be able to run code on devices I own. You don’t need to be part of the Apple Developer Program, https://developer.apple.com/support/compare-memberships/

None of the support documents you have provided help with the issue. I am unable to sign any code I write to run on any of the devices I own. That is a Mac, an iPhone and an Apple TV right.

While I understand Apple cannot provide “free support” to non paid members, this isn’t something that the Apple Developer Forums can help me with.

This is something that only Apple can and needs to act on. Please escalate this.

Appreciated

Only to get the same response

As previously advised our department, Apple Developer Program Support is an administrative team that assists our Developers with the creation and maintenance of their Apple Developer Program memberships. Therefore, the support we have provided up to this point is the limit to what we can provide given that that your membership is not active. Thank you for your understanding.

I pushed even more

You are putting a $99 ransom fee so that I can get support on what is meant to be working as expected.
Xcode reports “No Teams” for the Apple ID when I should be assigned to a “Personal Team” so that I am able to launch apps on devices I own.

https://help.apple.com/xcode/mac/11.4/index.html?localePath=en.lproj#/devaf282080a>

This is unacceptable.

You have clearly demonstrated that you are [not] able to solve this.
I demand you assign someone else about this case.

At which point I was assigned a “senior advisor with Apple Developer Programme Support” who resolved the issue in 3 days.

So that was a total of 16 days. Make of that what you will. The writing is on the wall. The risk is only growing larger. The risk of being locked out of your account, the risk of being asked to pay Apple 30% of your revenue, the risk of not being able to write code for your devices.

I want to run miles away from what Apple has now become.

]]>
Tue, 18 Aug 2020 11:27:43 +0300
Over a year since Apple gave me an ultimatum on Windmill https://qnoid.com/2020/07/30/windmill.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2020/07/30/windmill.html

Yesterday, I watched live a session by the House Judiciary Subcommittee on “Antitrust, Commercial, and Administrative Law | Online Platforms and Market Power, Part 6: Examining the Dominance of Amazon, Apple, Facebook, and Google.”

It so happened that yesterday, was the 1 year anniversary of the post Where is Windmill on the iPhone?.

Hearing the committee standing up for small business owners and individuals trying to support their family and employees, calling out corporations’ tactics on excercising control with a firm grip over people’s freedoms to operate on a free market while also hindering innovation brought back memories.

I got especially emotional hearing an audio clip of a book seller pleading to Jeff Bezos to restore their business operations so that they could earn their livelihood.

It’s fair to say that Apple got the least amount of attention and scrutiny by far.

Apple arguably got off the lightest of any of the companies in today’s hearing, if only by volume of questions: Tim Cook got just 35, compared to 59 for Bezos, 62 for Mark Zuckerberg, and 61 for Sundar Pichai

Casey Newton - Antitrust finally gets its hearing

With this enquiry as a landmark, I feel now is the time to share a few more details on what happened behind the scenes last summer as I was fighting to earn a living having spent countless months working on Windmill burning through the last of my savings. I want to also share some emails that capture my thoughts and emotions as I was going through the motions. I will also share, in full, the letter of appeal that I sent to the App Review Team.

Timeline

May 20, 2019: Windmill is approved on TestFlight for beta testing.
May 22, 2019: Windmill is “Waiting for Review” in the App Store.
June 12, 2019: I send a “Status Request”.
June 22, 2019: I email Phil Schiller bringing the case to his attention.
June 22, 2019: I get a call from the App Review Team where I am being given the reasons why Windmill on the iPhone will be rejected.
June 22, 2019: Windmill is “Rejected”.
June 26, 2019: I send an 8 pages “Letter of Appeal” to the App Review Team with the following:

  1. An overarching description that explains, what Windmill does, why I think it’s useful for developers, why it does not violate the App Store Guidelines and Apple Developer Program License Agreement, how Apple benefits by approving Windmill.
  2. The security considerations and implementation details that went into Windmill, for full transparency in an effort to make Apple feel comfortable about Windmill.
  3. In detail, why I believe Windmill complies with the App Store Review Guidelines and the Apple Developer Program License Agreement
  4. Final thoughts

July 3, 2019: “Based on the current material, the original rejection feedback remains valid.”
July 3, 2019: I send a message to the App Review Team asking for clarification on what grounds Windmill is rejected and for feedback to help me work towards making Windmill compliant.
July 9, 2019: I get a call from the App Review Team where I am being told that Windmill, “holistically” is not appropriate. This decision was made in collaboration with the App Review Board.
July 12, 2019: I email a developer tools evangelist at Apple asking for help to find a way forward with Windmill and for some some course correction to be done.

I never hear back.

Correspondance

Hello Phil,

My name is Markos and I am an independent Apple Developer living in Athens, Greece.

Apple’s developer relations and customer service has been overwhelmingly positive throughout the years, kudos for that.

In this rare case however, the App Review process seems to have fallen a victim of a scripted, no individual stepping forward, corner case where it just falls apart.

I will just give you the gist of it.

Windmill has been In Review for 21 work days, i.e. since the 23rd of May. I made a Status request 7 work days ago, i.e. since the 12th of June, It’s been about 12 hours since I have asked for some visibility on the status.

I wanted to bring this to your attention as this is now the cause of anxiety. I would very much appreciate you looking into this. I don’t expect a personal reply.

Thank you
.-
Markos

Seemingly, this email prompted the call I received on the very next (US) day.

I strenuously tried to understand Apple and listen to its concerns in an effort to meet its demands even though there was very little guidance in making Windmill compliant. At the same time, I vigorously made the case for Windmill’s approval. Alas, it eventually became clear to me that the call was a “courtesy” call. The decision had already been made and I was just being told how it is going to be.

I was confident this was a misunderstanding. That Windmill was not seen by Apple as a serious endevour given that I was just an indie developer. I was not ready to give up. I started drafting a letter of appeal with some feedback from fellow developers.

On 24 Jun 2019, at 12:29, Markos Charatzas markos@qnoid.com wrote:

Having had some time to think about the rejection, I now get the impression that Apple strongly believes Windmill on the iPhone to be no different to TestFlight which couldn’t be further from the truth.

Also, since Apple itself hasn’t really been much in support of the development process outside of Xcode, I worry that it may not believe in the value of Windmill. It does not help that Apple has a tendency of having a narrative that everything must fit into it.

2 days later, I sent a Windmill Letter of Appeal to the App Review Team. Windmill gets rejected again.

From:  Apple
Date: 09/07/2019, 19:13
2. - 5 Performance: Software Requirements
3. - 1.2 Business: Payments - Subscriptions
5. - 2.5 Legal: Intellectual Property - Apple Products Other - Other
Date: 03/07/2019, 07:02

Hello Markos,

Thank you for your detailed response and ongoing patience.

Based on the current material, the original rejection feedback remains valid.

However, if you believe your app is compliant with the App Store Review Guidelines, you are certainly well within your right to file an appeal to the App Review Board. As a member of the Apple Developer Program, you may exercise this option at any time.

Best regards,
[Redacted]
App Store Review


Date: 03/07/2019, 07:37
Hello [Redacted],

It is not clear to me whether the App Review team believes Windmill is still in violation of every App Store Review Guideline as well as the Apple Developer Program License Agreement. Can you please clarify whether Windmill is in compliance with some or all? Your feedback can help me work towards making Windmill compliant.

In regards to filing an appeal to the App Review Board. Given that the form to submit an appeal, only accepts plain text, how can I best send the letter in the PDF format?

Appreciated,
Markos


Date: 05/07/2019, 13:13
Hello [Redacted],

I would love to get on a call with you so that I can better understand how to proceed. Not sure what your schedule is like. I am generally available in the next few days and happy to talk during the weekend like last time.

By the way, I noticed that the number to contact you, [+1-XXX-XXX-XXXX], does not support FaceTime audio. It would make a positive difference to have that option available.

Regards,
Markos


From:  Apple
Date: 09/07/2019, 19:13
2. - 5 Performance: Software Requirements
3. - 1.2 Business: Payments - Subscriptions
5. - 2.5 Legal: Intellectual Property - Apple Products Other - Other

Hello Markos,

Thank you again for your time on the phone today, and further discussing the App Review Guidelines.

Whereas we are unable to provide you with specific development feedback for your app, we are dedicated to evaluating any revisions you would like to make in the form of a future resubmission.

Best regards,
[Redacted]
App Store Review

In the phone call I stated my intention to appeal. While I was told it was certainly within my right, I was given the impression that it wouldn’t make much of a difference. The decision was made having already consulted and factored in feedback from people outside the App Review Team.

It was on that final call, where it became pretty clear that Apple wasn’t willing to work with me on this. It was a call to tell me how this is going down. It is striking how differently Apple conducts itself on a call versus in writing; in public versus in private. The call sounded eerie familiar to the one made to Kapeli back in 2016 in regards to Dash. Dash and Apple: My Side of the Story.

“Has Apple ever retaliated against or disadvantaged a developer who went public about their frustration with the App Store?”

Going public

Having been given an ultimatum by Apple, I was encouraged by fellow developers to go public with the story. I was hesitant.

On 24 Jul 2019, at 08:07, Markos Charatzas markos@qnoid.com wrote:

  1. What is the end goal? Apple to reverse course and approve Windmill on the iPhone? Apple to change its stance, that holds privately, when it comes to how Command Line Tools can be used? Apple to have a public debate about developer tools on and about iOS?

  2. What is the case I am making and on what grounds? What’s possible to ship as an Apple Developer on Apple platforms, how the App Store is the only way to distribute iOS apps and the role of Apple as a gatekeeper? How that hinders innovation, competition and user choice?

These subjects have been debated for some time and right now are at the forefront even. How and why would they make a difference now?

Writing what Windmill does, how it’s helpful to developers, why it was rejected is only the setup. I don’t see that being sufficient to either get others’ support or for Apple to take this seriously.

Apple’s stance has caused me grief and a nihilistic view about the future of Windmill. At the same time, having Apple’s decision that Windmill holistically violates the Developer License Agreement hanging over my head is something I want to get off of me.

To be honest, I don’t feel comfortable, confident or keen on taking Apple, leading a movement or becoming a martyr in the process. I wish I could just go back to building Windmill and helping businesses get on board. I just feel that I can’t do that either.

Thank you for going through this with me.


On 24 Jul 2019, at 22:56, Markos Charatzas markos@qnoid.com wrote:

It’s possible that I’m overly emotional and choose to complicate things. I generally want to be well calculated and get things right. Even more so when I’m about to go on the public record with Apple when my developer license is on the line. It doesn’t help that have been beaten down by Apple twice already on this case.

This comes after more than 4 weeks of the App Review Team, the App Review Board and possibly Phil Schiller looking into Windmill on the iPhone. Also taking into account the 8 pages letter where I did say to Apple what the app does, how it works, and why the app would be helpful to other developers. I just can’t see how that alone would rally people. I might just be pessimistic.

After that letter, Apple decided to come after Windmill on the Mac saying I violate my developer license by building on top of the command line tools. This is more than simply an iPhone app being rejected.

The way I understand it, Apple does not want to set a precedent or open the door for others to exploit.

Keep in mind that Windmill on the Mac is the only 3rd party native macOS app that offers “continuous delivery”. The other one is Xcode bots by Apple itself. Any other service that uses the command line tools is on the web hence outside of Apple’s influence. Thus yet again being the only one directly affected by this. I believe you are using CircleCI so you know what I’m talking about.

I left London behind, a high paying job and have sacrificed at least 2 years of my life to build Windmill. I feel a lot of pressure and have a lot to lose on this so it doesn’t come easy.

It would help if you could tell me what you see in Windmill? What do you think is at stake? How does the decision by Apple to allow or sustain the rejection affect you as an Apple developer? Why do you think others would care? Why do you care? :) knowing that can help me build confidence.


On 26 Jul 2019, at 22:31, Markos Charatzas markos@qnoid.com wrote: Thanks!

So far I’ve had 2 more people giving me feedback.

One of them is [Redacted], who is definitely looking at this from a different, if not pessimistic angle. Which is good! Cause that means he does a great job covering the blind spots.

He made me think harder about what Apple is probably concerned about with Windmill. Creating a distribution mechanism which is available to the public, outside of the control of Apple and lacking the safety of the App Store. No matter how limited ad-hoc distribution may be.

Hard to debate about this as it brings the discussion back to the pros and cons of having the App Store as the only way to distribute apps…

Do you think there is a way to address this in the post without sounding like I’m not acknowledging the risk or sound insensitive to what Apple is concerned about?

I now think the “Final thoughts” section should be completely overhauled to touch on this issue and better communicate what I’m looking to get out of this by inviting a public debate/discussion.

I’m also thinking about removing both the “Timeline” and “Compliant” sections to keep the post shorter. I am not sure they add to anything. What do you think?


On 26 Jul 2019, at 23:12, Markos Charatzas markos@qnoid.com wrote:
But in some way, it does. Windmill today is a public offering/service. It doesn’t matter what Windmill is designed to be used for but how it is implemented and how it could be used for.

It is precisely why Apple had to say that the Command Line Tools Package is only meant to be used by developers alone.

I feel like I’ve completely misread the situation with Apple up until now.

Say, if an organisation had built Windmill for internal use. The server used for distribution would be under their control and probably in their internal network.

Windmill on the iPhone would probably be distributed using an Enterprise Certificate, internally to the employees of the organisation or using ad-hoc distribution. It doesn’t matter, it’s internal.

It completely changes how organisations would use Windmill. In this case, I am not even sure a public post is useful.

What an epiphany.

Are you following my train of thought at all? :)

I have removed the receipient in the emails above to focus on my thoughts, considerations and reasoning instead. For the final exchange though, I would like to include it as I believe it makes an important point about the App Store as the only means of distributing iOS apps.

I think I’m following you. The topic is way outside my normal areas of expertise, though.

So, to be clear — could Windmill be used to distribute apps to the public, circumventing TestFlight and the App Store?


On 27 Jul 2019, at 14:18, Markos Charatzas markos@qnoid.com wrote:

You can’t use Windmill to distribute apps to the public, circumventing TestFlight and the App Store any more than you can without using Windmill.

It’s nuanced.

The rest is history.

]]>
Thu, 30 Jul 2020 15:54:16 +0300
Fear, support and endurance in the face of adversity https://qnoid.com/2020/05/10/endurance.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2020/05/10/endurance.html A dear friend lost his father recently. On the day of the service, I went by his house early morning as we had to drive for about an hour to attend the funeral. In that hour long drive, there were moments of laughter, quietness, reflection, sadness. All interwined with one another.

As he was facing the casket, I stood by, just a few steps behind and to his side, holding onto his shoulder. He was the one that had to deal with an insurmountable event. The one that had to find ways to cope with this unbeareable loss. He knew, nothing and noone could bring his father back. He knew that he had to learn to live without his presence. Find ways to navigate his life that has just been upended by forces outside of his control.

Yet, in that moment, he wasn’t alone. He could feel my presence and the presence of others close to him. Every step he took to his father’s grave, was a step he took in the presence of others. Not feeling alone, made this ordeal somewhat bearable.

Unlike death, which is very much real, hardship can be in disguise. Seeing a loved one struggling, feeling powerless to help them can be very frightening at times. A prolonging struggle will only grow that fear. Fear that you are not doing enough to help, fear that something bad is going to happen to them on your watch.

My friend knew I couldn’t bring his father back. He knew he had to deal with what life had thrown his way, alone. There was nothing to say or do in this very moment. Being there was powerful enough.

Something so simple as being present, may seem hard to fathom outside ceremonial moments like these. Sometimes, what is being asked of you is not to come up with a solution or to offer a piece of advice. Sometimes, comfort found in your presence is what people look for as they endure hardship.

Anxiety looks different in men - “Be compassionate”

]]>
Sun, 10 May 2020 11:36:42 +0300
Programming https://qnoid.com/2020/05/05/Programming.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2020/05/05/Programming.html I felt like learning something new. This time web related. Eventually, I arrived at Kotlin. Between my background experience as a Java Web Developer and an Apple Developer, I thought Kotlin sounded like a good investment and fun to play with.

With Kotlin I should be able to bring forward all that Java EE knowledge I have while also learning a new language. Given that Kotlin is also used for native Android development, combined with the experience of building iOS apps, I could also expand to another mobile platform in the future.


Some combination of cryptic error messages that I had to decode before I could have a development environment ready, open-source plugins no longer supported, out of date documentation, buggy releases, patchy tools meant that I had to jump through hoops before I could write even a single line of code.

I won’t go into detail of every problem I run to. What I will say, is that it took hours of debugging, googling, reading through support forums, trial and error before I could finally focus on the task. Building something while learning a new language.

I have over 15 years of experience as a Software Engineer and it still took me hours to go through every issue. How would a newcomer deal with any of that? How accessible is programming today? How is it fun? What happened to:

10 PRINT "Hello, World!"
20 END
  • Coding - “It’s like the 80s all over again, where you plug in a machine, and you can instantly start coding. I for one miss that.”
  • Open-source - “I am not sure what to make of open-source software anymore.”
  • PICO-8
  • GB Studio
]]>
Tue, 05 May 2020 21:56:48 +0300
Debt and borrowed time https://qnoid.com/2020/04/30/Debt-and-borrowed-time.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2020/04/30/Debt-and-borrowed-time.html I have been trying for weeks to write this one technical blog post on how Windmill secured over-the-air downloads on iOS. I just can’t.

My brain just tells me no, it refuses. It tells me I need to spend more time looking for a job. I am wasting precious borrowed time. I am piling up debt that I need to pay back. It tells me that I need to make some progress getting my life back in order.


I haven’t been in this situation since 2009 - 2010. Just before I decided to leave Greece and return back to the UK. I was in debt while also being in limbo. I didn’t want to leave Greece even though it was a dead end.

The way I was able to cope with the debt I was piling up was by thinking of it as borrowing time from the future. My future. It was just too much to think of it as monatery value. I was going to repay it back, eventually.

This wasn’t a strategic decision on my part. It wasn’t like taking a loan to use as an investement. It was a coping mechanism.


Whatever savings I had to support me while building Windmill have run out since the end of September 2018. Back then, with only the free version of Windmill on the Mac available, I decided to look for a job. You would think that with all that talk about the brain drain in Greece it would have been easy. It wasn’t, it hasn’t and still isn’t.

With the support and encouragement from my partner, I decided to push forward with the development of Windmill on the iPhone. This is precisely the moment where I started borrowing time, again.


It has now been 19 months of borrowed time.


This is not the complete picture though. This time around another human is carrying more than their fair share and while they do, I feel like I am holding them back. This is something that I struggle with as it goes against my beliefs in equality and opportunity.

]]>
Thu, 30 Apr 2020 12:15:12 +0300
Coding challenges as part of an interview https://qnoid.com/2020/04/28/coding-challenges.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2020/04/28/coding-challenges.html Brent Simmons writing about coding challenges as part of an interview process.

I’ve read a bunch of the advice on this, and the advice says things like: “Start talking. Restate the problem. Talk out an approach. Consider how much space/time it will use. And then start writing code.”

I feel like Brent is speaking for myself when he says:

Which is of course not at all how I solve problems.

He then goes on to explain in detail how he typically approaches a problem domain that he is unfamiliar with when writing code. Which sounds very familiar to how I go on about writing code too. Furthermore,

And — even more critical — I don’t have a 45-minute time constraint. Nobody is watching me type and judging. I’m writing code to solve a problem, rather than writing code to get a job.

There’s a huge difference between “solve this performance problem with a binary search” and “pass this test so you can feed your family.”

This hits the nail on the head. I too had to solve similar coding excercises during an interview only to suffer from anxiety. I get tunnel vision and I am unable to demonstrate clear thinking.

Thank you for saying this Brent. I take comfort reading that a developer like you, at the top of their game, is faced with the same challenges as I do. It tells me I am not alone.

]]>
Tue, 28 Apr 2020 09:21:01 +0300
I miss London https://qnoid.com/2020/04/23/london.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2020/04/23/london.html I miss London. I miss walking around. I miss the night sky. I miss walking around Fitzrovia, past that little chapel hidden away in a residential block where apartments have full glass windows. I miss walking up Primrose Hill, turning around and looking at the skyline. I miss Covent Garden. I miss SOHO. I miss the lions at Trafalgar Square. I miss London so much.

I feel like the clock has turned back 10 years. All the sacrifices made, all the time and effort I put to change my life around. Everything that lead me to London, has just vanished.

I am in Athens but I don’t really want to be here. You would think that after 10 years of being away, coming back would feel like coming home but it doesnt. The UK felt like home. You would think friends would cherish your return, be close, want to spend time with you, be there. They are not. They are married, have grown older, are depressed, working overtime. You would think a family home would be there for you. To celebrate the holidays, to spend the weekend. There is none.

I am tired.

It’s hard to go back. The UK has left Europe. There is so much uncertainty and I am no longer 29. The last 2 years have been nothing but struggle. I want to take back control yet I end up waiting. Waiting yet again for someone’s approval, someone to tell me my worth, what I deserve.

I am tired.

It feels like I am back to where I was 10 years ago. In debt, lost, waiting. Only now I am 39 going 40.

I am tired.

I want to reinvent myself. I miss you London. You belong in the past. I still miss you.

]]>
Thu, 23 Apr 2020 22:26:27 +0300
The Windmill source code is now public https://qnoid.com/2020/04/08/windmill-source-code-public.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2020/04/08/windmill-source-code-public.html I have made the decision to release the source code of Windmill.

  • Windmill on the Mac
    Windmill on the Mac is a native macOS application written in Swift 5 on Xcode 10 targetting macOS 10.14. The codebase is about 16k LOC.

  • Windmill on the iPhone
    Windmill on the iPhone is a native iOS app written in Swift 5 on Xcode 10 targetting iOS 12.2. The codebase is about 5k LOC.

  • Windmill REST API
    The Windmill REST API is a Java EE 8 implementation written in Java 8 using JAX-RS. The codebase is about 7.5k LOC.

History

I started working on Windmill as a side project in 2014. In 2017 I decided to commit full time and in February 2018, Windmill on the Mac 1.0 was released. In July 2019 Apple rejected Windmill on the iPhone and took issue with Windmill in principle. I didn’t make any money on Windmill and was not in a position to take it forward given these cirmustances thus formally ending its development in January 2020.

Why make the source code public?

Effectively, by Apple putting Windmill on notice, the only way I can distribute Windmill on the Apple platforms is at the source code level. Even though this does not serve the mission to make continuous delivery accessible, whatever value Windmill brings even as source code, is better than none at all.

The development of Windmill did come to an abrupt end and didn’t get a fair chance to become what I had envisioned. It would bring me joy to know that developers will benefit from it by learning something new. It’s a way to give back to the community.

Windmill is not some example software after all. It is production grade that spans across the desktop, mobile and the server. The software engineering behind it is still relevant and the technologies used modern.

I was diligent, took great care and put a lot of attention in building succint, performant, reliable, and bug free software across multiple platforms. I believe the source code of Windmill has something to offer whether you are a beginner or a senior in software development in any of the 3 platforms.

What does making the Windmill source code public mean?

As a product, my gut feeling tells me that unless a company with the available resources gets behind it, Windmill will not go far. I am hopeful but don’t expect much.

As software, I believe not that much. These are times where running software, on your computer (desktop or mobile), unfettered is near impossible. In order to run Windmill on your Mac and the iPhone you will need an Apple Developer account. Since Windmill is built for developers, chances are you do have one. Still.

Windmill is built to take advantage of and be tightly integrated with the Apple ecosystem. It makes use of Push Notifications, Background Mode, CloudKit and In-App Purchases. You can strip away and refactor some of the code but the point still stands. Distributing, modifying and running software outside walled gardens isn’t as straight forward.

The Windmill REST API is no different. The implementation relies heavily on AWS infrastructure. It will also take some elbow grease to get up and running.

What not to expect

Releasing the source code of Windmill does not make it open-source. I don’t plan on contributing any time or energy developing it further. To support it as open-source would demand of me even more resources and attention which I don’t have the luxury of.

Don’t expect any instructions on how to build and run the code.
Don’t expect the code to be extensively documented.
Don’t expect me to respond to any issues raised or pull requests made.

I don’t plan to publish any Windmill architecture diagrams, security considerations or design documents either.

How to make the best of the source code

Study it.

As a Swift developer, the macOS app1 should be the most juicy one for you.

Have a look at the ProcessManager type on how to launch a Process, wait and receive data in the background from both standard out and err. The ProcessManager also allows you to recover a Process that has exited with an error code. As an example, look at how ActivityBuild creates a RecoverableProcess.

The Windmill type makes extensive use of the design pattern as described in A series of steps post. Take a closer look at the ActivityBuilder type to see how Windmill uses it to create the pipeline to a succesful build.

As fas as the iOS app goes, have a look at PaymentQueue and SubscriptionManager on how to process transactions when purchasing a subscription that requires validating a receipt on the server.

I have already documented how to replace the rootViewController of the UIWindow that Windmill on the iPhone also makes use of.

As a Java developer, the REST API should prove useful as a reference implementation of the Java EE 8 spec. The most interesting tidbit is likely the use of an EntityGraph to retain the lazy associations of an @Entity while performing queries that require exclusively independent associations to materialise. In the case of the Windmill REST API, that would be the AccountResource#list that materialises a list of Export types and the SubscriptionResource#isSubscriber that materialises a list of Transaction types for a Subscription.

Own the code.

At the very minimum Windmill on the Mac should serve as a replacement to Jenkins. For any developers that still use Xcode 10 to build and test their app, this is as straightforward as building and signing the app using your Apple account. The iCloud capability can be disabled as it’s only relevant when used alongside the iPhone app.

If you are using Xcode 11, it will take some effort to add support since Apple has changed the result bundle format. At the very least Windmill needs to be updated to support the new format.

If you do put in the time and effort, it should be possible to have Windmill on the Mac, on the iPhone and on the server running which will give you app distribution.

What did the future hold for Windmill?

Windmill was really at its infancy. Allowing developers to distribute their app and have over-the-air installation was the first step in making its development sustainable.

I had plans to develop an TV App to act as a dashboard for teams and have company wide notifications.

I wanted to add support for nightlies, the ability to substitute resources during packaging and support conditional compilation to allow for different builds.

Finally, I wanted to tackle distributed building, support multiple configurations (e.g. to maintain multiple releases) and integration with 3rd party libraries.

Feel free to use these guidelines as a roadmap.

The licence

Created by Markos Charatzas (markos@qnoid.com)
Copyright © 2014-2020 qnoid.com. All rights reserved.

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:

This software is provided ‘as-is’, without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.

  1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
  2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
  3. This notice may not be removed or altered from any source distribution.

Final words

I still believe in Windmill and would love for a company with the resources to step in and take it forward.

I am available for hire. I am based in Athens, Greece and able to invoice from a UK company if needed.


  1. I should point out that this was my first ever macOS app. It is highly probable that I have made some amateur mistakes while learning about the responder chain, how to manage multiple windows and handle the menu bar. Consider this a fair warning. ↩︎

]]>
Wed, 08 Apr 2020 09:37:31 +0300
Hugo https://qnoid.com/2020/04/07/Hugo.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2020/04/07/Hugo.html I have been using Jekyll for quite some time. Quite possibly since the beginning of this blog. I have now migrated to Hugo. There wasn’t a strong reason to do so. Jekyll was serving me just fine up until now. I even used Jekyll for the Windmill website.

Why do it then? I just felt like doing something productive and wanted something to tinker with. Hugo seems more geared towards building a website as opposed to just a blog and I would like this website to evolve.


It took me about 2 days to migrate. I didn’t use any of the existing tools as I wanted to get familiar with Hugo. The most time consuming was making sure, yet again, that permalinks don’t change. In the 10 years of this website’s lifespan, I had to deal with this at least 2-3 times that I can remember.

Hugo apparently generates permalinks in the form of https://qnoid.com/hugo/#main compared to what this website has been using, https://qnoid.com/Hugo.html#main.

To be honest, I don’t recall the later format being a concious decision on my part but obviously didn’t care enough at the time. I don’t even know what the “canonical” format for URLs is. I didn’t want to open this can of worms.


I made sure to salvage the permalink for most of the posts. For those that had some obscure formatting due to using the title of a post at the time, I didn’t bother. Life is too short. The good news is that the most prominent posts weren’t affected so cheers to that.

While feeling the pain of salvaging the permalinks, I did begin to wonder. How can we better handle permanent redirects? I kinda wish for a way to “track” a resource across a URL the way Git can track a file across name changes.


Now that I have migrated the website, I have a big announcement coming up about the future of Windmill.

]]>
Tue, 07 Apr 2020 12:56:53 +0300
Coding https://qnoid.com/2020/02/29/Coding.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2020/02/29/Coding.html

What’s the point in life? To have fun? I’ve certainly had fun with this Next and that is good enough for me. But if you want the wider story, then I think there are several avenues.

For some, this could simply be a programming platform free from all the libraries, framework and constraints of modern day system.

It’s like the 80s all over again, where you plug in a machine, and you can instantly start coding. I for one miss that.

There is something about the brutal simplicity, which just draws you in, and then, because this isn’t a complex beast, you can actually gain an understanding of what you are doing.

Even using a high level language like BASIC you can see how your commands affect the system. It’s an elegance we lack these days.

Sure, you could use a retro system for that, but this is a new machine, with a new community excited to see what they produce. It’s not a rehash. It’s current but it’s grounded in the past.

I miss that too.

ZX Spectrum Next | Nostalgia Nerd

]]>
Sat, 29 Feb 2020 00:00:00 +0200
Evolution https://qnoid.com/2020/02/08/Evolution.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2020/02/08/Evolution.html I want to evolve this website to something more than just a blog.

A website that is deeply personal yet it’s not about me.
A website that is about forming relationships, removing barriers, breaking taboos.
A website that raises awareness to issues that trouble me.
A website that recognises contributions made by others and elevates them.
A website that helps people make sense of their lives and deal with their struggles.
A website that brings your attention to people in need.
A website that is connected to other people through the vastness of the World Wide Web.
A website of what it means to be human.

I also want a website that can outlive me. That can be used for historical purposes, for people to look back and understand what life was like in the late 20th century, early 21st. A digital cave if you like. Full of footprints, drawings, sounds, videos.

For the past few days, I have started working towards making a website like this. It is still in its infancy but there is enough to share.

Welcome to my life.

]]>
Sat, 08 Feb 2020 00:00:00 +0200
The next 10 years https://qnoid.com/2020/01/23/future.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2020/01/23/future.html BScIT (aka Biscuit) class of 2003 at the University of Sunderland.

There is a whole story of how I ended up working at CERN but that’s for another day. What’s relevant is that at CERN, in 2001, I was “christened” a Java Developer. I had no prior experience in Java or related backend stack (e.g. databases). Fast forward to 2003, back in Greece, that experience landed me a job at Forthnet which created a career trajectory as a Java Developer.

Starting with Java EE as a junior developer gave ample room to grow. I practiced object oriented programming. I got a grasp of HTTP and the web. I learned about databases, multithreading, linux, servers and infrastructure. Even though I was a junior developer, I was given plenty of autonomy and responsibility. The last professional role I held as a Java developer was in 2011. That’s roughly 10 years of dedication to the platform, though just recently I wrote a full blown Java EE 8.0 application that served as the backend for Windmill. It felt like riding a bicycle.

Becoming an Apple developer was a different story altogether. Steve Jobs’ announcement of the iPhone, inspired me. I took the “CS 193P iPhone Application Development” at Stanford University of my own volition. Java and the web had failed on the promise of a rich web application and mobile as a platform had just become ready to take off. I saw it as an investment to further grow as a professional and it paid off. I spent the next 10 years as an Apple Developer.


A few days ago I watched a documentary where I learned about the World Robot Olympiad and the non-profit organisation WRO Hellas. WRO Hellas provides training to academics, educational material and robot parts to aspiring robotics engineers living in Greece. It also organises national competitions for mentees to compete. Seeing so many young people passionate about robotics and programming, got me thinking about what I want to be engrossed in for the next 10 years.

I am not sure. I would love to hear your thoughts at markos@qnoid.com.

]]>
Thu, 23 Jan 2020 00:00:00 +0200
Open-source https://qnoid.com/2020/01/21/Opensource.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2020/01/21/Opensource.html I am not sure what to make of open-source software anymore.

I am not referring to free and open-source software nor open-source with a commercial license. There is also open-source, like NetNewsWire and Homebrew which are free and developed in the open. I am not talking about those either.

I am referring to open-source software addressed to developers. Open-source software where a developer is the end user of code. Code that is available to bring in as a dependency to software you write.

I am a user of open-source code. Having said that, adding a dependency to a 3rd party is the exception, not the rule. I believe in writing the code or at the very least, owning it. Own it as in, know how it works, understand it, maintain it as and when required.

As a potential creator of open-source code, I stop and think now. Am I sharing code that will act as a dependency? What are my responsibilities as the original author? How do I manage its development? What purpose does it serve? What risks does it pose? Why does it need to be open source?

Is it merely for educational purposes? I prefer knowledge sharing as opposed to code sharing and I would rather share that knowledge through deliberation, writing and code examples that get to the crux of the matter.

That is not to say that code sharing can’t act as knowledge sharing. I have most certainly expanded my knowledge and understanding by reading open-source code.

So, what value does open-source code really bring? Is it about writing it once, used by many? Providing a reference implementation? Time saving? Setting a quality bar, an example? Addressing social inequalities by giving equal access to code?


I have been thinking of releasing the source code of Windmill. That is, the code for the macOS app, the iOS app and the backend code written in Java.

The Java implementation could be a useful reference for anyone building a Java EE 8.0 application.

The macOS and iOS implementations are both “real world” apps that might prove useful as learning material.

The alternative would be for the source code to forever stay in my MacBook Pro as a relic. Still, I am not sure.

Related

]]>
Tue, 21 Jan 2020 00:00:00 +0200
The curtain falls on Windmill https://qnoid.com/2020/01/03/Windmill.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2020/01/03/Windmill.html

This is it. I am officially ending Windmill. The writing has been on the wall for some time now. I will begin by dismantling the infrastructure that supports Windmill on the iPhone. I will also make a public announcement on the Windmill website. I expect the website to stay up until the domain expires if not sooner.

Windmill made continuous delivery accessible, without compromising on security or privacy and without the added cost that comes with paying for a cloud service. I am very proud of the work I put into Windmill.

Even though some things where outside of my control, I have no regrets. I did pursue my dream and dedicated more than 12 months of working full time as well as all of my savings.

I did it my way. It is now time to take care of the one I love.

For hire.

]]>
Fri, 03 Jan 2020 00:00:00 +0200
Game Awards https://qnoid.com/2019/12/13/Game-Awards.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/12/13/Game-Awards.html

I watched The Game Awards last night. The whole show was oozing with talent, creativity and positivity. I came away feeling inspired.

Special shoutout to

Kudos Geoff Keighley and team for putting on an amazing show and for being a gracious host.

]]>
Fri, 13 Dec 2019 00:00:00 +0200
MacBook Pro random shutdown fix https://qnoid.com/2019/12/09/NoCrashMBP.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/12/09/NoCrashMBP.html I mentioned in the past how the MacBook Pro Retina, 15-inch, Late 2013 would randomly shutdown and shared my experience with an Apple Premium Service Provider in Athens, Greece.

I have been running RealMacMods, NoCrashMBP for over 3 weeks now and I haven’t experienced any random shutdowns ever since.

From the RealMacMods website.

The CPU has several power states and voltages. Some CPUs have become unstable at the extremely low voltage on one of it’s cores. The CPU will sometimes briefly dip into that power state, and if it happens to be on the core wherein it is unstable you will see the “silent” crash. Screen goes black, a few seconds later it dies completely. This condition was observed with external test equipment, as well as through internal cpu voltage monitoring.

Continued

This utility runs in the background and keeps it from ever hitting that extremely low state/voltage.

Indeed the “NoCrashMBP” app adds a load, at times up to 20% on a 4 core CPU that the MacBook Pro I own has. I haven’t taken any measurements on the impact it has on battery. Compared to ~€750 service cost, I’ll take the reduced battery performance.

I hope that the MacBook Pro lasts for at least 1-2 years. I’ve only had it since April 2014.

Keep in mind that just because this solution worked in my case, it does not mean it will work on yours. For me, spending €9, when I was already at a loss of €340 was a small price to pay. Especially when I was told I had to pay an extra €750 to replace the logic board.

]]>
Mon, 09 Dec 2019 00:00:00 +0200
Apple Premium Service Provider https://qnoid.com/2019/11/15/Apple-Premium-Service-Provider.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/11/15/Apple-Premium-Service-Provider.html There is no official Apple presence1 in Greece. As a result, there are no mail orders, no mail-in option to repair and you have to rely to a 3rd party to service your Apple Hardware.

About 2 months ago, I noticed that the battery on the MacBook Pro (Retina 15-inch, Late 2013) had swollen. I took it to an Apple Premium Service Provider in Greece where I was told that the issue is indeed the battery and would need to be replaced at a cost of €341,81 (€215.33 for the battery plus €126.48 labour cost).

I agreed to the service. After all, the MacBook has a 2.3 GHz Quad-Core Intel Core i7 processor, 16 GB 1600 MHz DDR3 and 512GB SSD PCIe 2.0. It still holds up pretty well to do development so the cost of €340 is minimal compared to the value I get out of it.

As soon as I got the Macbook back, it started to shutdown at random times. The screen would go dark (with some light illuminating), the fans would start to spin and eventually it would shut down. Upon powering it on again, there was never a Panic Report but only once; in the tens of shutdowns.

panic(cpu 2 caller 0xffffff7f928da528): “ino 37945100 no extent covering dstream alloced_size 806912 (fsize 805656) pos/len 868809:0\n”@/BuildRoot/Library/Caches/com.apple.xbs/Sources/apfs/apfs-945.275.7/nx/jobj.c:11881

Kernel Panic Report

Every hardware diagnostic run by the service provider came back green.

Eventually, it took me 2 months to finally get the engineering team at Apple to trace2 it to a faulty logic board (error 128 they said 🤷🏽‍♂️).

Update

Apparently, you can use log show --predicate 'eventMessage contains "Previous shutdown cause"' to check the shutdown cause.

End Update

I was referred back to the service provider. I am now told, a replacement3 logic board will cost about ~€750. At a total price of €1090 to repair the MacBook Pro, repairing it doesn’t sound as appealing or worth.

Other than the fact that I cannot afford a new MacBook Pro right now, the bitter taste left in my mouth is directly related to the relationship that Apple has with service providers in a country like Greece.

You see, the tools provided to the service provider gave no indication of a faulty motherboard4. As a result, I ended up paying €340 only to end up with a Mac that will randomly shutdown. As far as I am concerned, prior to the battery replacement, the MacBook Pro worked as expected. I am now €340 lighter and have a faulty MacBook Pro.

Keep in mind that a service provider is an independent, 3rd party. The manager doesn’t have the luxury, the privilege nor the overall profits of Apple to take the hit or provide leeway.

And here is where I take issue with the service options offered by Apple in Greece. The service provider does not have all the required tools to make an overall assessment which in this case has cost me.

In the end, this arrangement is a mark against the reputation of Apple. For Apple to take pride in customer satisfaction in Greece, it must take all the necessary steps to have an Apple Store in Athens.

Update

I have now bought the software listed in one of the related links below. At $10 is a low risk to take. I will report back once I have used the Mac for some time.


  1. No Apple Retail Stores, no option to trade-in, no Today at Apple, etc. ↩︎

  2. Long story short, after getting in touch with Apple Care, I was sent a “Capture Data” app which performs a “Sysdiagnose” with “Full Disk Access”. ↩︎

  3. Since the MacBook Pro is now considered Vintage, a replacement logic board is not guaranteed to be available. ↩︎

  4. Even if I assume that the faulty logic board is a result of the swollen battery, I don’t quite understand why as a customer I have to bare that cost too. ↩︎

]]>
Fri, 15 Nov 2019 00:00:00 +0200
The state of Apple hardware I currently own https://qnoid.com/2019/11/10/Apple-State.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/11/10/Apple-State.html I own a MacBook Pro Retina, 15-inch, Late 2013. At the time I bought it, April 2014, I maxed out both the RAM at 16GB and HD at 512GB SSD.

About 2 months ago, I noticed the battery had swollen, so I had it replaced at a cost of ~€340. Since then, I have been experiencing random shutdowns, ranging from every few hours to couple of days. There has been an incredible amount of back and forth with Apple and their Authorised Service Provider in Greece1. I won’t trouble you with the details2 suffice to say that I am unable to do any software development on it.

The iPhone X, running iOS 13.2.2, over time seemingly exhausts its network connection pool with Apple services. App Store downloads are stuck forever, sharing a Note via iCloud comes back with a “Connection Error” etc. At this point, I need to restart the device.

When talking on said iPhone X via the AirPods (1st Gen), people will complain that they have trouble hearing me. At random times, I sound like talking from a distance.

Apple TV (4th Generation) is working fine overall tho I do come across glitches on tvOS from time to time.


  1. There is no official Apple presence in Greece i.e. Apple Store and no support for mail-in. Effectively you are being treated as a second grade customer while in Greece. ↩︎

  2. At this stage, I have sent some sysdiagnose logs and waiting for a response. ↩︎

]]>
Sun, 10 Nov 2019 00:00:00 +0200
The future of Windmill https://qnoid.com/2019/10/29/Windmill.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/10/29/Windmill.html The last update on Windmill was really the news about Windmill on the iPhone getting rejected. I have yet to put any more work on Windmill.

Windmill on the Mac is a standalone, native, macOS app1 that has always been free to download and use. Developers don’t even need to have an account. I genuinely don’t know how many developers do actually use2 it. I never actively tracked downloads, users, monitored engagement or any other usage metrics. It has been a deliberate decision not to.

Windmill on the iPhone on the other hand, requires significant infrastructure and a backend server. I have been using AWS for that. Even though Windmill on the iPhone never saw the light of day in public, the infrastructure did cost money to operate during setup, development, testing, beta. It still does to this day since I never dismantled it.

Up until now, I have been paying for AWS using credits that Amazon used to offer to startups. The credits have now been depleted3 so starting in October, I will have to foot the bill4. A couple of days ago I also got a reminder that the Windmill domain will expire soon.

I never made any money on Windmill while working on it full time. Also, I haven’t had a salary since summer 2017. Any savings I had, run out about 12 months ago. Still, it feels hard to bring down the whole thing just like that. I still haven’t come to terms with the rejection by Apple and haven’t had the head space to decide what to do with Windmill.

I still believe in both the Windmill vision and the product. I just don’t have the money and resources to dedicate on time that has now become borrowed.

The future of Windmill is uncertain.


  1. Interesting fact: The codebase is 16k LOC. ↩︎

  2. If you do, please let me know via email at markos@qnoid.com ↩︎

  3. Do you know if there is a way to get extra AWS credits? ↩︎

  4. A good friend and for what is worth a prominent member in the Apple community, was kind enough and generous to offer to “sponsor” the cost of AWS. I don’t feel comfortable accepting money while the future of Windmill isn’t any clearer. ↩︎

]]>
Tue, 29 Oct 2019 00:00:00 +0200
3 months off Twitter https://qnoid.com/2019/10/29/Social-Media.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/10/29/Social-Media.html It has been about 3 months since I have deleted my Twitter account. I had been an avid user for 10 years.

I don’t miss it and I am happier.

At the time it felt important. I could reach out to others and others could reach out. I was “in the know”.

I am enjoying the focus. No one seems to be missing “qnoid” either.

It’s all good!

]]>
Tue, 29 Oct 2019 00:00:00 +0200
Taking back control of my life's narrative https://qnoid.com/2019/10/03/Control.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/10/03/Control.html

This is a deeply personal post. It is a way for me to process, come to terms with, move forward and take back control of my life. I don’t have any advice to offer or lessons to teach yet. I am still caught into this. I don’t know how this story ends.

I was raised by a single mother.

Born in the eighties. My mother was a hairdresser, running her own beauty salon just around the corner from a single bedroom flat where we both lived, in Athens. She was just 21 when she gave birth.

I grew up being quite independent. I had my own keys to the flat. I used to come back from primary school, an eight minutes walk, eat food mom had prepared for me, watch TV, study for school, study English with a private teacher, draw cartoon covers, use a computer.

Mom was working 6 days a week. When I wasn’t at home alone, I would be spending time with my best friend next door or at the beauty salon. I remember asking her to give me a “perm” hairstyle like everyone else.

These are memories I have; I was also told differently.


My “parents” separated when I was 4. My “father” used to pick me up after school in the evenings when my mother was working.

My mom had stayed good friends with him after they separated. He was living just a couple of blocks away from my mom. I could visit him whenever I wanted.

He is the one that bought me my first computer at the age of 8.

I never felt close to him. He was rarely around. He never advised me, gave me guidance, showed much affection or interest, took me to the park, parent me.

I don’t remember much of him at that age.

As a teenager and through adulthood, our relationship was no different. I had conversations with friends about it in an effort to understand. What was their relationship like with their dad? They would tell me how their father isn’t that close to them either. How they would argue or not share much affection.

Still, their answers, reasoning and life didn’t look the same to me like how I was feeling. I could tell they had a father figure. At the age of 35 I told the man, in tears, that he had been absent for all my life. That I needed him to be there for me. I got no reaction at all.

A few months later, the universe would conspire to reveal the truth.


It had been less than a year since my engagement had broken down and now I had been dealt this hand. I was technically living in Edinburgh at the time. I had quit my last job and had been on the move for close to 6 months. Savings were running out so I decided to move to London.

In the years that followed, every time I would be back in Greece, I would share with friends what little I knew. They wouldn’t act surprised as if they knew something more. It felt like being in The Truman Show. I just couldn’t deal with what curveball the universe had just thrown at me.

In a twist of fate I ended back in Athens almost 3 years later. I don’t know how I managed to pull whatever strength I had left in me. It was fucking hard. I decided to confront this man and face reality.

Thirty-eight years later, the truth had finally come to light.

This man wasn’t my father.


I never met my father, neither had a father figure in my life. I was raised by women.

My mother.

My grandma.

My godmother.

By all the women coming to the beauty salon, telling me stories, showing me affection. By all the women looking after me when I was sick or had to spend an evening with when mom was away.


A man’s lie for close to 40 years, that he was willing to take with him to the grave, defined what turn my life would take right at the minute I was born. At 02:10 that fateful Monday summer morning in 1980.

I am not the type to second guess or have regrets about my choices in life. Still, I can’t help but think how different my life would have been.

This is a choice that someone else made about what path my life should take. I had no say in this. This was not a choice I made. To this day, I am still facing the repercussions.

At the age of ten, my mom had her second marriage which lasted for four years.

My stepdad was a bully.-

]]>
Thu, 03 Oct 2019 00:00:00 +0200
Respect the baby steps https://qnoid.com/2019/09/24/Respect-the-baby-steps.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/09/24/Respect-the-baby-steps.html

“Respect the baby steps.” - Dimitra

I have gotten used to having to deal with big changes that are happening in my life.

In the begining, those changes were dealt like a deck of cards. Until I started embrasing them. I have become the orchestrator. I am not afraid of change. I even get a kick out of it. I swallow change.

These are a few1 highlights of change.

I left Greece when I was 18 to study in Sunderland, UK. It was a planned, coordinated move. I wanted to study computing after all. My girlfriend at the time, had already been there for a year. It was meant to be an easy move. Two months into it, we had a falling-out. I made the choice to move out.

Saint Peter’s Campus, Sunderland University

I dealt with it. Packed my stuff. Talked to the students’ union. Made financial arrangements. Within a few days I was living in a new flat in different university halls. It was a traumatising experience but I took it in stride.

Three years later, I decided to take a placement year at CERN. My British peers were reluctant to leave the UK. To me it was yet another country to live in. I flew in Geneva. Since there was no direct bus from the airport to the campus, I had to get off at Route de Meyrin.

I remember, standing at a bus stop, in the middle of the night, thinking that if something was to go horribly wrong2, it would take days before anyone found out. I was all alone and hadn’t met anyone personally yet.

With the aid of a secretary, I got an upfront payment and found a place to stay in Saint-Genis-Pouilly. About halfway through the tenancy, I moved to Ferney-Voltaire. I had to and I just did.

CERN campus, 2001 - 2002

In May of 2010 while living in Greece, I got an offer to join an Edinburgh based startup for 4 months. Within a day, I had accepted and booked tickets. 3 days later I had a suitcase packed, locked the door to my flat and left.

People were left wondering:

“Are you moving back to the UK now or what?”.

I didn’t know the answer. All I knew was that I had a job for 4 months. I ended up living and working in Edinburgh for 5 years.

In October of 2014, my engagement broke down. At the time, I was visiting Greece when I realised I had to find temporary accomodation in Edinburgh to stay and be back at work just a few days later. In just over 2 weeks I had completely changed my life!

Let me spell this out. I flew in Edinburgh, stayed in temporary housing while going to work every morning, did viewings, got out of a hairy situation, found a flat, made arrangements to move in, got my personal belongings and moved in to my new place. I did it all within 17 days! I even made sure to have internet on day 1. 🤷🏽‍♂️

First night at the new flat

On the last week of July 2015, after 6 months of failing to take control of my life, I decided it was time to move to London. To kick me into overdrive, I simply booked a one way train ticket to King’s Cross and said to myself:

“You are going to London in 5 days. Deal with it!”.

I gave notice to the landlord, arranged for a moving company, packed 5 boxes and left without having a job lined up. One month later, I started working for Soldo. The office at the time was near Baker Street and I had found a flat just 20 minutes away on foot, in London. It was bonkers!

Leaving on a one way ticket to London

Fast forward in December 2017 I moved to Australia. A few months in I had to retreat to Greece. All in the midst of building Windmill. You get the deal by now.


I do not respect the baby steps.

I do not appreciate what it takes to carry each of those big changes. I do not sit to think how difficult it is to take those steps. I brush them to the side. I don’t think much of them. As far as I am concerned. I just need to do whatever needs to be done to go from A to B. Get on with it and move on. That’s what I have been doing. That’s what I am good at, I guess.

About 2 months ago I started going to therapy. In the past weeks I had to face my worst fears. Having to deal with feelings and suppressed emotions that I have never dealt with in the past is terrifying.

I have also decided to exit egg so that I can focus on what matters.

This brings the biggest change in my life. It is long, tough and requires an even greater fortitude. I have to recognise and accept the effort each step will take. To pace myself.

To respect the baby steps.

✊🏽👶🏽🦶🏽


  1. There are plenty, plenty more. ↩︎

  2. It’s laughable to think of it now. This is Switzerland after all. I remember the front page story of a local newspaper that read “Mini market robbed!”. Oh, the horror. ↩︎

]]>
Tue, 24 Sep 2019 00:00:00 +0200
Kiva https://qnoid.com/2019/09/21/KIVA.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/09/21/KIVA.html Back in 2015, as a birthday present, I got a Kiva gift card. It’s one of the best gifts I have ever received.

Kiva allows you to micro-loan people around the world that are at a financial disadvantage.

A family in Dushanbe, Tajikistan to help pay their daughter’s tuition.

A farmer in Kaduna, Nigeria to help them increase yields.

A group in Prey Veng, Cambodia to help buy a water filter to provide safe drinking water.

A shop owner in Sembabule, Uganda to buy more stock to sell.

I have to admit, at first I found it overwhelming and difficult to decide. There are so many people that could use whatever little help I could provide. How do I make a choice? What country? What cause? Who needs it the most?

I still don’t know how to answer this. I’d just tell you to pick one to get you started. Maybe you can relate to the person and their struggle. Maybe you want to tip the scale in gender inequality. Maybe you want to help people get out of poverty first. Maybe education is important to you.

I suggest you start with a short period loan (8 months or less) that with your contribution will be fulfilled. That way you will see the results of your micro-loan come to fruition sooner.

Regardless, you will no doubt help people in need and make the world a little bit better in the process.

It’s amazing how many people you can help over time starting with just a small fund that you relend. I started with $50 and over time I have built up the micro-fund to $150. With that amount of money I have been able to finance 21 loans at a total of $700 over the years.

Next time you have the chance to buy a birthday present to someone consider offering them a Kiva gift card instead. It can change their life and the life of others.

Greetings from Tanzania! Thank you for supporting Jackson, a hard working retailer at his own retailer shop with a loan. I’m pleased to inform you that he is doing extremely well and with the loan received, Jackson used the loan to buy food items, detergents, soft drinks, few stationary items, plastic bags, slippers, and utensils . He used the additional profit to pay his loan dues, school fees, covered household expenses such as water bills and electricity and reinvested for his business to grow. Jackson is very grateful for the loan and thankful to everyone who had supported him.

]]>
Sat, 21 Sep 2019 00:00:00 +0200
Reasons I have resigned, quit or was let go of a job. https://qnoid.com/2019/09/17/Connection-reset-by-peer.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/09/17/Connection-reset-by-peer.html I thought I’d share this. I get the feeling, we don’t talk openly about it. Not that we should. Quite the opposite. Why share then? I hope people will see that leaving a role is part of life and there is nothing more to it.

I believe it’s inappropriate to ask this question, it won’t get you any meaningful answers and it may lead to awkward conversations and I do mean as part of an interview.

So here are some of the reasons:

  • No room for personal development and future growth.
  • Not a good culture fit.
  • Politics, corporate structure, didn’t care enough at that point.
  • Change in technical direction, management style that meant engineering would have a lesser role. Wasn’t willing to go down that path.
  • Not supported enough, change in business priorities.
  • The writing on the wall lead 3 people to resign in the same week.
  • Wasn’t commited enough or “loyal” to the company, I think?
]]>
Tue, 17 Sep 2019 00:00:00 +0200
An Apple Developer for 10 years https://qnoid.com/2019/09/06/Apple-Developer.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/09/06/Apple-Developer.html

Back in September of 2009, I was let got of a role as a Java Developer. I had come to Athens looking for a job a few months prior. Instead of looking for another role, I decided to move back to Crete.

At that time, Stanford University was running “CS 193P iPhone Application Development” on iTunes U. I took the opportunity to invest in learning what seemed like the future. I was just an avid Mac and iPhone owner for some time.

Up until that moment I had been a Java Developer with a Web focus. Backend to frontend. An iPhone app was unlike anything I had seen on the web. I think, at that time, the most impressive website I had come across was Google Maps and its use of AJAX. It was jaw dropping.

Still, compared to the predominantly stateless nature of a website, building an app for the iPhone enabled me to better express my creativity and build a better experience with less effort as a developer. The user experience possible was immensely better to what I could come up by building a web app.

I remember working on an assignment as part of the curriculum created by Evan Doll and Alan Cannistraro at Stanford. It was a single view app where you could draw a polygon shape. If memory serves me well, the only control was a slider to define the number of angles. As you moved the slider with the touch of your finger, you could instantly see the shape morphing from a triangle, to a square, to a pentagon, a hexagon etc. This interactivity and responsiveness at the palm of your hand felt insanely exciting at the time. I was hooked!

In May 2010 I moved to Edinburgh, Scotland. Even though I was working full time as a Java Developer, I wanted to be an Apple Developer1! In my spare time I was working on verylargebox. A mobile app that enabled local store owners to share their products with anyone in the city.

In June 2011, I landed my first role as an iOS Developer even though I wasn’t really hired based on what I could do as one. It was an entry level role, still it put a smile on my face. I could finally have an Apple Developer section on my resume!

Fun fact: I subscribed to iOS Dev Weekly on the 24th of October 2012 and it was already at Issue 65!

In July 2013, I released verylargebox as a free app. I finally had my very own iPhone app on the App Store, I was proud!

Even though I never pursued verylargebox as a business idea, it raised my status as an Apple Developer. I had an app! I felt like I was part of the Apple community.

Soon after, I joined Tesco Bank where I was responsible for the technical delivery of Tesco Bank Mobile Banking on the iPhone.

As an Apple Developer, 2014 was special. I traveled to NSConf at Leicester where both Evan Doll and Alan Cannistraro would be there. This was an opportunity to personally meet and greet the people that nudged me to become an Apple Developer.

My bond with Apple as a developer grew stronger and stronger. With every interaction and exposure, I became more involved with the people, more invested in the technology, more attached to Apple.

The same year, I won the WWDC lottery and got a chance to meet in person some of the developers at Apple that I have been interacting with on Twitter.

I also remember witnessing the winners of Apple Design Awards and dreaming of the day I could develop an app worthy of an award.

It was around that time, in 2014, when the idea of Windmill popped into my head. At Tesco Bank, I had hacked together a continuous delivery pipeline using Jenkins and Apple’s Command Line Tools and I thought there must be a better way to do this.

One of the very early iterations of Windmill. Notice, how this is only a menu bar item. Humble beginnings as an Apple Developer for the Mac.

Of course, I had a full time job at the time. I could only afford to work nights and weekends. Still, I pushed through. With every line of code written, with every technical note read, with every WWDC video watched, I made progress.

Years passed. I moved to London. The year was 2016, I had just left my job and I was thinking of quitting the software industry too.

Still, I had Windmill to carry me forward. In 2017, I decided it was time to commit to it full time. In September of the same year, I took a leap of faith and jumped into the unknown, being all poetic.

In the years that followed, I had to move from the U.K., to Australia, to Greece. It was shitty and tough.

In between all that (and a lot more on a personal level; not the post to disclose) one thing stayed consistent. My dedication to see Windmill through and in the process take control of my life and destiny.

I pushed long and hard to get Windmill on the iPhone out. I started working on it in January 2019 and submitted it to Apple at the end of May. It was rejected.

Windmill on the iPhone was a way for me to finally start making a living after 2 years of not making a salary and almost a year since my savings have been depleted.

I haven’t done any progress since Apple rejected Windmill.

I am definitely experiencing a burnout, still there seems to be something more at play that I’ve been trying to explain.

Every time I make an effort to think how to overcome this hurdle and continue with the development of Windmill, my brain switches off.

You see, Windmill as I envision it, is more than just a Mac app. Literally and figuratively speaking. It’s hard to put this into words, no matter how much I try. It’s a vision after all. My dent in the universe.

Windmill is on a mission to make continuous delivery of iPhone apps ubiquitous and accessible to developers and businesses.

I don’t feel motivated knowing what is possible will be subpar, constrained, unwelcome, unappreciated and on the bad side of Apple. I feel crippled as an Apple Developer to make the best of all available platforms and technologies.

On a personal level, Windmill allows me to have freedom of expression, be creative and pursue excellence.

To some extend this a cautionary tale about falling in love with a brand when an organisation is behind it. When the needs of the business precede those of the individual. Still, there is more. In the case of Apple and its developers, this is about our livelihood.

For Apple, this was just an app that was submitted, went through due process and was rejected. For me, this is a moment in time that will define what turn my life takes next.

Thinking back to that September of 2009 when life set me on a path to become an Apple Developer. It feels like that path is ending.-


  1. I would really like to thank Andrew Williams who really supported me in my early efforts as an Apple Developer. You have been an inspiration Andy. ↩︎

]]>
Fri, 06 Sep 2019 00:00:00 +0200
Anxiety looks different in men (The Wall Street Journal) https://qnoid.com/2019/08/13/Anxiety-Looks-Different-in-Men.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/08/13/Anxiety-Looks-Different-in-Men.html Source: Anxiety Looks Different in Men By Andrea Petersen

When a man explodes in anger over something seemingly insignificant, he may appear like just a jerk. But he could be anxious.

Anxious “men may present as loose cannons, but they are worriers,” says Kevin Chapman, a clinical psychologist in Louisville, Ky. “Aggression tends to be more socially acceptable to many men than anxiety.”

In general, men are less likely to receive treatment for mental health issues. “We’ve been socialized from a very young age to see emotional vulnerability as a weakness,” says Michael Addis, a professor of psychology and director of the Men’s Well-Being Research Group at Clark University in Worcester, Mass. “Seeking help is seen as a sign of weakness as well,” for some men.

How to Help

—Be compassionate. Don’t view him as being stubborn, see him as a human being who is struggling with a heavy burden of expectations.

]]>
Tue, 13 Aug 2019 00:00:00 +0200
Anthony Bourdain - Parts Unknown https://qnoid.com/2019/08/12/Antony-Bourdain-Parts-Unknown.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/08/12/Antony-Bourdain-Parts-Unknown.html Have restarted watching Parts Unknown.

Antony’s narration alongside the superb editing and direction of the show is so immersive that I am immediately transported to the place where he is at.

Antony’s genuine curiosity alongside the background research on both the history and the present of a city provides an incredible insight into its political circumstances and people’s daily lives.

From Koreatown in Los Angeles to Detroit and Mississippi Delta, south to Mexico City, across the Atlantic Ocean to Libya, north to Russia, east to Punjab, further into Hong Kong and Tokyo, his contribution in learning more about the world is immense.

Teaching us to be open by default, tolerant, curious, caring, respectful to other cultures. Inviting us to travel more, not as tourists but as inquiring minds looking to expand our view of the world. To learn from each other simply by having a conversation while eating together.

I believe it is a show where everyone can learn from and should watch in their lifetime. I don’t know what it takes for a Television show to be preserved in the Library of Congress but I really think that Parts Unknown should be preserved for its significance and importance.

Anthony, I dearly miss you. Wish I could have saved you.

Chapter One.

To fall in love with Asia is one thing.
To fall in love in Asia is another.
Both have happened to me.

The Star Ferry to Kowloon at night.
Lights of Hong Kong behind me.
It’s a gift, a dream, a curse.

The best thing, the happiest thing, yet also the loneliest thing in the world.

]]>
Mon, 12 Aug 2019 00:00:00 +0200
Brain drain https://qnoid.com/2019/08/06/Brain-drain.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/08/06/Brain-drain.html I left Greece in May of 2010. I didn’t leave because of the crisis which neither had been felt at the time nor people knew how destructive it would be or how long it would last.

I left because of the archaic work mentality and ethos, the lack of options, progress and professionalism. I left because it didn’t feel like Greece wanted to change or wanted someone like me1 to help bring change.

In March of 2018 fate brought me back. Hard times followed but somehow I managed to endure.

By the end of September of 2018 my savings had been depleted and I didn’t want my partner to carry all the load. In the months that followed, before I decided to start the work on Windmill on the iPhone, I reached out to organisations that were either hiring for a role I could apply (e.g. iPhone Developer) or thought I could contribute in some other capacity.

Here is one of the messages I sent at the time. I have removed a few details to preserve the anonymity of the individuals/companies.

My name is Markos and I have a software engineering background.

I have been at the helm of Tesco Bank and Soldo to bring organisational change and deliver their iPhone apps.

I have recently moved to Athens from London and I am looking to get involved in the startup ecosystem with the goal of providing aid based on my experience and expertise.

I would love to have a coffee and meet personally in order to explore this further.

I am looking forward to hearing from you.

Every single one responded. I followed up by emailing my CV to give even more insight into my background. A couple of them never responded after that.

Those who did respond, we arranged to meet. It became clear that unless there was an open, available role, there wasn’t much need for me. One of the responses I got went even further than that.

  • “I don’t know you and you have no LinkedIn.”

Here is another experience from applying and interviewing as an iPhone Developer.

  • “Why do you want to work as an iPhone Developer?”
  • “I am a software engineer. This is part of my skillset and expertise.”
  • “Yes but. You are overqualified.”

That is not the first time I am hearing this alongside the “You don’t look like a developer.”, which would be funny if it wasn’t stereotypical.

In another interview, I was confronted with what I would mildly call a hiring process from the past. Questions where in rapid fire mode.

  • “Where do you see yourself in 5 years?”
  • “What is something you are proud of?”
  • “What are you bringing to the table?”
  • “Why do you want to work for us?”

With very little room left for a discussion in-between. Impersonal, prejudicial, biased and formulaic.

When I finally got the opportunity to have a dialogue, (“We’ve got 10 minutes left if you want to ask any questions.”) I challenged by asking the tough questions only to get generic, hollow responses back and PR speak that pat themselves in the back.

For the past few years, there has been all this talk in Greece around the brain drain. It so happens that I am here after all these years. Equipped with skills, carrying the experience, bringing in the knowledge and for what it’s worth, developing a product. What are some of the reasons to keep staying in Greece?

What is the proposal that Greece makes? Where are the opportunities? How do Greeks find them? Why should Greek emigrants come back?

Maybe this needs to be a coordinated effort between the state and the private sector. A combination of sponsorship, campaigning, incentives at the state level and opportunities, contributions, assessment done at the private level.

Greece as a country, alongside organisations and individuals need to understand that they must be willing to change and be ready to fight for, be challenged, do their homework, adapt and give way to Greek emigrants if they want to reverse the brain drain.

Just doing some thinking out loud, having been back for over a year now.


  1. I left Greece as soon as I finished high school to study Information Technology at Sunderland University in the UK. I spent 1 year working at CERN in Geneva during my placement year. I even started working in the UK after I finish my studies. I decided to return to Greece in 2003, I wanted to live, contribute, shape and be part of its future. ↩︎

]]>
Tue, 06 Aug 2019 00:00:00 +0200
Stavros Niarchos Foundation Cultural Center https://qnoid.com/2019/08/05/Stavros-Niarchos-Foundation-Cultural-Center.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/08/05/Stavros-Niarchos-Foundation-Cultural-Center.html

A multifunctional, environmentally sustainable center of education, arts, sports and recreation.

The Stavros Niarchos Foundation - Cultural Center, based in Athens is home to the Greek National Opera and the National Library of Greece.

You might have come across it when Obama gave a speech about Democracy on his last trip as the President of the United States in Greece during his last days in office.

For all of August, there are Guided Tours at the SNFCC.

Even if you have visited the SNFCC, the guided tour will give you an oral history of its origins, backstory, architecture as well as backstage access to the Greek National Opera.

I decided to take the tour and came out inspired, elevated and joyful.

A few notable insights.

The Culture Center itself runs on solar energy that covers 100% of its consumption during the summer and 20% during the winter.

In the National Library, there are about 800K books available with an overall capacity of 2 Million.

Also accessible to the public are,

  • Two fully equipped audio recording studios.
  • One fully equipped studio for shooting, recording and editing video.
  • Reading rooms.
  • Available space for researchers to study, publish and digitise any archives.
  • Desk space. Extremely busy during exam reading season.
  • A computer hall.

At the Greek National Opera,

  • The main stage is 16x16 meters.
  • Each seat has a screen to show subtitles in English, in Greek, with more coming. The screen is aligned with the viewer and the stage for optimal reading!
  • There are 3 additional stages of the same size that move in and out of the main area to support multiple plays in a single day.
  • There is an “alternative stage” room that can be reconfigured on demand to host a variety of music events.
  • There is a room for ballet practice.
  • A soundproof room for choirs.
  • A room to accommodate and record an orchestra.

There are many many more tidbits that you can learn on the tour so I won’t spoil everything here.

Until the end of August, there is also a Photo Exhibition in honour of Yannis Behrakis who only recently passed away. I urge you to visit that too. His photographic journey is incredibly moving, powerful and topical.-

APW: Eyewitness / Yannis Behrakis: Exhibition

]]>
Mon, 05 Aug 2019 00:00:00 +0200
Despair https://qnoid.com/2019/08/01/Despair.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/08/01/Despair.html For the past 3 weeks, there is a growing feeling of despair. I feel powerless, I feel like it’s meaningless to fight for the life I want to have, I feel like there is little support to help me push through and the obstacles just keep coming.

For the past 3 weeks, I’ve been in limbo.

I decided to shut down Twitter after 10 years. The last few months I have been gradually tweeting less and never kept more than 30 days of tweets on my timeline.

It was the last remaining social media presence1. It’s been over a year since I deleted Facebook and Instagram.

Social media has become more and more hideous to the point that it makes me feel like shit. I don’t need this. There is a plethora of reporting done by major publishers and research if you need to understand more.

Personally speaking, this idea of social status (followers, likes and shit) along with the lack of social cues only leads to more entitlement and less courtesy. Let me put it differently.

On social media, you don’t know anyone long or good enough to be shitty. So take your vile behaviour and go take a breather before you start attacking.

I’ve had it. I prefer the safety and comfort of my website. The discussions that can be done across people’s blogs and the personal, private, thoughtful relationship I can have over email one-on-one.

It doesn’t help that as society we are absolutely fucking clueless on how to deal with people that are mentally struggling and I’ve been struggling in the past 3 weeks, again.

A few days back, I can’t remember where now, I think it was an interview of Tarantino, he said something along these lines.

We don’t push people when they have twisted their ankle. We don’t go up to them telling to move on. Why do we do that with people that are struggling mentally? Why do we push them?

I am really naive as a person. I take everything that people tell me at face value. I believe everything I see. I don’t have a hidden agenda and I tend to believe that people do not need to have one either. Why would you if you can just be honest? Fear.

Right now, I am at a loss. I don’t know how to move forward in my life. It’s coming up to 2 years since I left London, I have been disappointed so much by the software industry and I have heavy doubts there is a business out there where I can professionally and personally grow, find purpose, work among great people and be me all at the same time.-


  1. I also used to have LinkedIn and had it deleted years ago. “I was told” I need to have a presence for “business development”, so I opted to create the account again recently. Jeez. ↩︎

]]>
Thu, 01 Aug 2019 00:00:00 +0200
Where is Windmill on the iPhone? https://qnoid.com/2019/07/29/Windmill-on-the-iPhone.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/07/29/Windmill-on-the-iPhone.html Approximately 10’ minutes reading time.

Moving the needle

I am hearing from the developer community there is a broader concern around the restrictions and the limitation on the tools Apple provides and allows. I want to kick-off a discussion about this to address these shortcomings. How should Apple enable developers to improve on the tooling for the iOS development ecosystem? I’d love to hear your thoughts.

Some of the questions to get the conversation going:

  • How are existing developer tools limited when building for Apple Platforms?
  • Are you using a 3rd party developer tool and why?
  • Did you feel the need to build a developer tool, why?
  • How should Apple improve on its tooling and resources made available to developers?
  • Do you think iOS should have a dedicated “Developer Tools” section?

I will add what you’re saying below. Please mention @windmill_io to help me track your responses.

I wish Apple were better at collaborating with the developer community, instead of just controlling it. If Apple stopped trying to do everything itself, focused on just building a great platform, and let us solve our own problems, everyone would win.

Apple should be in the business of fostering creative solutions to lots of different problems instead of shutting them out.

Let’s see if planting the seed of making the language and some frameworks open source can grow into a more open ecosystem of tooling. The closeness of Xcode is one of the things that annoys me the most.

I don’t understand all the issues here, I admit, but I start by thinking that useful developer tools should be allowed on the App Store.

Apple’s loss ultimately when people stop innovating for their platforms

Table of Contents

Introduction

Windmill on the iPhone allows an organisation with an iPhone app under development to make that app available for distribution on any devices they own, as documented in the iOS Deployment Reference.

It makes use of ad-hoc distribution to make it dead easy to get started as a small- to medium-size business, with app distribution to half a dozen or so devices, while progressing towards TestFlight.

It allows businesses to distribute their app continuously while still in development, at regular time intervals, on demand, or as a reaction.

  • As individual contractors, it enables them to show progress to a client offsite and deploy bug fixes, at will, in time-critical moments.
  • As part of a team, it enables them to have nightly builds to get daily feedback from a product owner.
  • As part of an organisation, it enables them to have weekly meetings with the business and marketing team to do a demo, discuss, and plan next week’s development.

Windmill on the Mac continuously monitors the codebase, as made available in a git repository, so that every time a developer pushes a code change, it ensures the app still works. A developer starts using it as soon as they start working on an iPhone app.

It runs on Apple hardware that the organisation owns, on their premises. Therefore, it does not expect them to hand over their Apple Credentials, Distribution Certificate, Private Key, and Provisioning Profile, making it more secure than systems asking developers to hand these files over and keep them stored on their behalf.

Windmill can scale up to a platform where an organisation runs multiple instances of Windmill on the Mac on the available hardware to define a workflow and enforce security requirements.

An organisation in a small office with 2 developers and 1 product owner would have each developer running Windmill on their development Mac monitoring their respective feature branch, as well as an instance of Windmill running on a dedicated Mac mini monitoring the master branch.

This way, each developer gets feedback on their own codebase while the Mac mini holds the Distribution Certificate and Private Key to distribute releases and report on merges. This allows an organisation to have an overall view, a shared knowledge and centralised security on their app. Does the app compile? Are tests available and passing? Can the app be installed on a device? Can we release on the App Store?

Rejected

Unfortunately, Apple has firmly rejected Windmill on the iPhone. Windmill on the Mac does not seem to have Apple’s blessing either.

To Apple’s credit, they did take their time evaluating Windmill on the iPhone and Windmill overall.

Windmill on the iPhone was in Review for over 20 work days and an additional 5 after I sent an eight-page “Letter of Appeal” to the App Review Team with the following:

  • An overarching description that explains what Windmill does, why I think it’s useful for developers, why it does not violate the App Store Guidelines and Apple Developer Program License Agreement, and how Apple benefits by approving Windmill.
  • The security considerations and implementation details that went into Windmill, for full transparency in an effort to make Apple feel comfortable about Windmill.
  • In detail, why I believe Windmill complies with the App Store Review Guidelines and the Apple Developer Program License Agreement.
  • Some thoughts on how the Mac and the iPhone are governed by two very distinct sets of rules and how the App Store on iOS does not even have a dedicated “Developer Tools” section.

I have been on a call with the App Review Team at Apple twice. I was told that Windmill on the iPhone is “not acceptable” to be on the App Store. Additionally, taking a “holistic” look at Windmill I was told that “conceptually” it is in violation of the Apple Developer Program License Agreement.

I also emailed an Apple Developer Tools Evangelist asking for help to find a way forward with Windmill and for some course correction to be done. That was more than 2 weeks ago. I haven’t received a reply.

It’s been really hard to come to terms with this. I fought really hard for Windmill.

I both understand where Apple is coming from and I don’t.

Update

I was reminded of one very specific reason that I was given too.

Guideline 5.2.5 - Legal - Intellectual Property

YOUR APP IS TOO SIMILAR TO TESTFLIGHT, WHICH CREATES A MISLEADING ASSOCIATION WITH APPLE PRODUCTS. WE ENCOURAGE YOU TO REVIEW YOUR APP CONCEPT AND EVALUATE WHETHER YOU CAN INCORPORATE DIFFERENT CONTENT AND FEATURES TO BRING IT INTO COMPLIANCE WITH THE APP STORE REVIEW GUIDELINES.

I understand

Apple seems to take issue with the fact that Windmill is meant to be used for development, in-house, but Windmill on the iPhone was meant to be made available on the App Store.

More importantly. Apple took the stance that the Command Line Tools Package is only meant to be used by developers in-house and not by 3rd parties to provide support for continuous integration systems - continuous delivery in the case of Windmill.

Before you gasp, here is the nuance as I understand it1.

Apple takes issue that Windmill makes it effortless for developers to create a distribution mechanism for their apps outside the control of Apple and the safety of the App Store and TestFlight.

Hosting of pre-release software through means outside of the app store and facilitating developers to use their certificate, provisioning profile to do so is not permitted.

Even though ad-hoc distribution is limited, Windmill imposes strong security requirements and is designed for in-house use only.

After all, Windmill is available to every developer. Not just organisations with the know-how. Its mission is to make continuous delivery of iPhone apps ubiquitous and accessible to developers and businesses in an effort to improve consistency, a high level of understanding and agreement across the industry.

It doesn’t seem to matter what Windmill is designed to be used for but what it could be used for. It is precisely why Apple had to say that the Command Line Tools Package is only meant to be used by developers alone.

Xcode command line tools are only provided by Apple to developers to automate building, testing and distributing their app.

Had an organisation built Windmill for internal use, distribution would be under their control, used exclusively for their apps, and operating in their internal network.

Windmill on the iPhone would probably be built and distributed using an Enterprise Certificate, internally to the employees of the organisation or using ad-hoc distribution. In this case, it wouldn’t matter since it’s internal to the organisation.

Even Xcode Server, Apple’s home grown offering to in-house continuous integration and distribution comes bundled with a web server, “where you and members of your development team can use a web browser to view the status of bot integrations and download assets and products.” See Monitor and Manage Bots.

I don’t understand

Windmill does not operate outside of the boundaries as defined by Apple.

  • It expects that an organisation is registered with the Apple Developer Program.
  • It expects an installation of the tools in any development Mac where Windmill is used. Windmill itself does not come bundled with the Command Line Tools Package.
  • It manages signing based on the Apple Developer Team of the developer, organisation.
  • It uses whatever Distribution Certificate and Provisioning Profile is managed by Xcode.
  • It is limited by ad-hoc distribution device limits.

Windmill could not be used to distribute apps to the public, circumventing TestFlight and the App Store anymore than a developer can do today without Windmill or using existing services that offer ad-hoc distribution on the web.

Windmill plays by every Apple rule. It does not ask a for Apple credentials. It does not manage signing outside of Xcode. It does not ask for the private key and distribution certificate. It does everything that a developer could do today, with better security and privacy than an equivalent service on the cloud. There is a whole industry providing automation and distribution as a service for Apple platforms on the web.

Windmill may be the only third-party native macOS continuous delivery app available on Apple platforms but it probably comes last in offering such a service to developers.

Reconciliation

I wish Windmill on the Mac was also on the App Store. Reviewed, approved, endorsed and recommended by Apple. The decision to build Windmill on macOS and iOS has become a liability.

With Windmill, I effectively asked Apple to weigh in on the matter and Apple has decided that the risk far outweighs the benefits that Windmill has compared to existing offerings outside the Apple ecosystem.

It is possible that Windmill can only live within the confines of the Apple Business Manager with Windmill on the iPhone as a Custom App. Which does not help fulfil its mission.

Collectively as an iOS community, we have spent an insane amount of time and put an immense amount of effort in automating the delivery of our apps by writing flaky scripts in bash using Jenkins, reverse engineering the Xcode project file format, writing blog posts with our findings. Yet we are none the wiser and have barely made a dent. - iOS Automation - The Current State of Affairs

I completely misread the situation with Apple. It does not make it any easier that Apple has a tendency to be overly protective of the ecosystem. I understand why, I just wish Apple had embraced Windmill.

I had made plans to take Windmill even further, beyond distribution, onto other Apple platforms. Now, I am not sure what I can do while Apple stays silent.

One more thing

Windmill is the culmination of the experience I have accumulated as a developer over the past 15 or so years. On top of that, it took months of research and development on the Mac, on the server, and on the iPhone, paying great attention to the user experience as well as security and privacy that would not and cannot be made possible without deeply integrating with Apple’s tools, platforms and services.

I can’t help but feel disappointed and highly discouraged after all the work I’ve put in improving the tooling available to developers.

I would like to express my deepest gratitude to everyone at the Seattle Xcoders group. They have been very supportive all this time when I struggled mentally and needed them the most.

Thank you Brent, Jared, Tom, Tim, Marc, Jeff for providing invaluable feedback, improving this post significantly in the process.

Special thanks to Daniel Jalkut.

A call for discussion

Beyond the personal and financial setback this is causing me, I am hearing from the developer community there is a broader concern around the restrictions and the limitation on the tools Apple provides and allows.

I want to kick-off a discussion about this to address these shortcomings. How should Apple enable developers to improve on the tooling for the iOS development ecosystem? I’d love to hear your thoughts.

Related


  1. Apple didn’t really explain their reasoning. ↩︎

]]>
Mon, 29 Jul 2019 00:00:00 +0200
Windmill enters egg https://qnoid.com/2019/06/24/Windmill-enters-egg.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/06/24/Windmill-enters-egg.html Approximately 3’ minutes reading time

Back in March, I decided to attend an open day organised by egg. It is a business incubator, operating in Athens with a mission to encourage, support and promote entrepreneurship, primarily targeting Greeks, living in Greece.

I am happy to announce that Windmill has been accepted to join egg!

Ever since the inception of Windmill, I have been adamant on what path I prefer1 following. I want to bootstrap Windmill into a sustainable business. That is, with the exception of a business loan, receive no outside investment in return of equity or follow a traditional “startup” path to grow the business.

In the midst of building Windmill on the iPhone, I decided to apply2 to egg. I meticulously went through the website, watched talks given by the egg staff and business partners in an effort to understand its culture and attitude towards starting a business.

I was drawn to egg primarily for evangelising sensibility in starting a business as well as for appearing genuine in helping Greeks looking to build a future in Greece. Still, I wanted to make sure this was a good fit for Windmill going forward.

Here is what egg offers and how I believe it can help.

  • Office space. Even though I have created a dedicated office space at home, the isolation has been tough to endure. I am looking to benefit from the discussions, interactions and a sense of belonging to everyone else there. For reference, every year about 25 businesses operate within egg.
  • Mentorship. As part of your tenure, you are assigned a mentor. At this stage, it is not clear who this mentor will be or their expertise. Still, having someone dedicated where you can refer to in an effort to bootstrap your business can prove really useful.
  • Business Bootcamp. You receive about 100 hours of training in Marketing, Business and Finance. This structured education will no doubt help solidify some of my limited understanding.
  • Opportunities. Being part of a business incubator is bound to create opportunities in business, marketing, potential partnerships etc. I will certainly be keeping my eyes peeled.
  • Support. Last but not least, you do get access to accounting and legal services as well as help with incorporating. No doubt I could be doing all this outside of egg, still I have enough on my plate already so I would rather not have to figure it out on my own.
  • Once you have incorporated, there could be an option to get a business loan in favourable terms. This will come in handy, primarily for hiring as well as marketing and advertising services.

Back in 2017, when I decided to leave London and give Windmill a fair chance, I wanted to spend about a year to see if it made any business sense pursuing it.

I never would have imagined the possibility of running a business in Greece, yet here I am.

Windmill has come a long way and receiving an offer to join egg is yet another validating step.

I have a good feeling about this.


  1. I don’t hold a business degree and have no prior experience in starting a business. At this early stage, I am not even sure if it’s possible and depending on what the growth of Windmill looks like, I may not have a choice. That doesn’t change the fact that my strong preference is to bootstrap Windmill into a sustainable, viable, private company. ↩︎

  2. I had to submit a business plan, do a public presentation, create a pitch deck and do a 5 minutes Q&A with a panel before getting to an offer. Thank you Matt Farrugia for reviewing and guiding me through this. ↩︎

]]>
Mon, 24 Jun 2019 00:00:00 +0200
Swift 5.0.x String Performance https://qnoid.com/2019/05/16/Swift-5.0.x-String-Performance.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/05/16/Swift-5.0.x-String-Performance.html Turns out, in Swift 5.0.x, String(utf8String:) and String(bytes:encoding:) are not “optimised” compared to String(validatingUTF8:).

In other words. In Swift 5.0.x, any String.append(:) calls can potentially take a performance hit.

Similarly, any NSTextView.string.append(:) operations will also suffer.

This is what that performance hit looks like in my case, where a DispatchSourceRead is feeding a NSTextView every time there are bytes available to read.

        let fileDescriptor = fileHandleForReading.fileDescriptor
        let readSource = DispatchSource.makeReadSource(fileDescriptor: fileDescriptor, queue: self.queue)
        
        readSource.setEventHandler { [weak readSource = readSource] in
            guard let data = readSource?.data else {
                return
            }
            
            let estimatedBytesAvailableToRead = Int(data)
            
            //before: var buffer = [UInt8](repeating: 0, count: estimatedBytesAvailableToRead)
            var buffer = [CChar](repeating: 0, count: estimatedBytesAvailableToRead)
            let bytesRead = Darwin.read(fileDescriptor, &buffer, estimatedBytesAvailableToRead)
            /*
            Making sure that the buffer ends with a 0 since the bytes read are not guaranteed to.
            `String(validatingUTF8:)` has a requirement that the "cString is A pointer to a null-terminated UTF-8 code sequence."
            */
            buffer.append(0) 
            
            //https://twitter.com/Catfish_Man/status/1128934439096971264
            guard bytesRead > 0, let availableString = String(validatingUTF8: buffer) else {
                return
            }
        
            (completion ?? DispatchQueue.main).async {
                self.output(part: availableString, count: availableString.utf8.count)
            }
        }

Use NSTextView.textStorage.append(:) and convert your String to an NSAttributedString using NSAttributedString(string:).

//before: textView.string.append(output)
textView.textStorage.append(NSAttributedString(string:output))

This is what the performance looks like after the code change.

Couldn’t be more grateful for David Smith responding to my request as well as Marcin Krzyzanowski and Paul Goracke for nudging me to take a look at NSTextStorage.

This had the potential to be a huge time sink.

Swift 5.1 will be released sometime after March 18, 2019.

.-

Update

Started noticing some crashes on String(validatingUTF8:) with a Fatal error: UnsafeMutablePointer.initialize overlapping range when using it with an UnsafePointer<CChar>. Instead using the implementation as defined in the Discussion under the String documentation. Will report back.

Update 2

Re the Fatal error: UnsafeMutablePointer.initialize overlapping range. I hate having bad code around, even if it’s bad sample code. It’s been a learning experience for sure.

String(validatingUTF8:) has a requirement that the “cString is A pointer to a null-terminated UTF-8 code sequence.”. This code on the other hand makes no guarantees that this will be the case.

var buffer = [CChar](repeating: 0, count: estimatedBytesAvailableToRead)
let bytesRead = Darwin.read(fileDescriptor, &buffer, estimatedBytesAvailableToRead)

Sure, it initialises the character array with 0 (i.e. null1) but read may fill that array and not end with a 0.

Back to the String(validatingUTF8:) initialiser. If you look at the source, it uses UTF8._nullCodeUnitOffset(in:) which “Is an equivalent of strlen for C-strings” which gets the length of the string (based on the presence of a null terminating character of course, we are going deep in C now). I was guessing that strlen takes a trip down memory lane© looking for that null terminating character and ends up way beyond an “acceptable” length. What is acceptable you say?

For that we have to take a look at the source code of UnsafePointer

public func initialize(from source: UnsafePointer<Pointee>, count: Int) {

    _debugPrecondition(count >= 0,
        "UnsafeMutablePointer.initialize with negative count")
    _debugPrecondition(UnsafePointer(self) + count <= source ||  source + count <= UnsafePointer(self),
        "UnsafeMutablePointer.initialize overlapping range")

Builtin.copyArray(
  Pointee.self, self._rawValue, source._rawValue, count._builtinWordValue)
// This builtin is equivalent to:
// for i in 0..<count {
//   (self + i).initialize(to: source[i])
// }
}

So I decided to take the red pill, go down the rabbit hole and see for myself.

for i in 1...100_000 {
    var buffer = [CChar](repeating: 1, count: 4096)
    let string = OverlappingRange(validUTF8:buffer).string
    print(string)
}

Welcome to the Matrix2.-

“Remember…all I’m offering is the truth. Nothing more.”


  1. Brought back the memories of learning C++ back at the University on a Borland C++ editor. ↩︎

  2. One run took 2 seconds for the UnsafeMutablePointer.initialize overlapping range but that wasn’t very exciting. ↩︎

]]>
Thu, 16 May 2019 00:00:00 +0200
A series of steps https://qnoid.com/2019/05/07/A-series-of-steps.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/05/07/A-series-of-steps.html Approximately 9’ minutes reading time

This post expects that you are familiar with object lifecycles, closures, functional programming, memory management, asynchronous execution, URLSession and Process in the Swift language and the Mac/iOS SDK.

Update

11 May 2019, added custom operator and a reference to SE-0253.

Table of Contents

Introduction

The backbone of Windmill on the Mac is a series of steps1, that execute serially.

Checkout -> Build -> Test -> Archive -> Export

A few things to note.

  • The output of one step may act as the input to the next.
  • A step executes asynchronously.
  • Each step must be successful before the next one is taken.
  • Steps only make forward progress. If one step fails, the whole series is considered to have failed and no more steps are taken.
  • The implementation of each step may differ. e.g. one step might be launching a Process, another one might start a URLSession.

The problem domain may sound familiar2 to that the NSOperation and NSOperationQueue solve. Apple has an excellent WWDC talk describing how powerful and useful can be in the context of dependencies; See Advanced NSOperations.

Windmill, does not make use of NSOperations for the following, arguably subjective reasons.

  • I wanted a more refined control over object lifecycles; i.e. what dependencies/relationships a step has, what arguments it needs to run, what it expects as an input.
  • I wanted the concepts of a step, success, output/input, optional next step to be prominent and part of the API design.
  • I wanted steps to have low coupling. Being able to reuse a step and create a different series of steps.
  • I wanted a step to allocate memory lazily as part of its execution rather than as part of its allocation.
  • I wanted the relationship between steps to look like it’s “modelled” at compile time.
  • I wanted less of an architecture and more of a design pattern.
  • I wanted an abstraction that is “lightweight” rather than another execution layer on top of launching a process and/or making an HTTP request.

Let’s take a step back.

Prefix

#!/bin/swift
import Foundation

let message = "Hello World!"

let process = Process()
process.launchPath = "/bin/echo"
process.arguments = [message]
process.launch()
echo.swift You can use swift echo.swift in the command line to run it.

The code above prints the message "Hello World!" asynchronously.

#!/bin/swift
import Foundation

let group = DispatchGroup()
group.enter()

let session = URLSession.shared

let message = "SGVsbG8gV29ybGQh"
var request = URLRequest(url: URL(string: "https://httpbin.org/base64/\(message)")!)
request.httpMethod = "GET"
request.addValue("text/html", forHTTPHeaderField: "accept")

session.dataTask(with: request) { (data, response, error) in
    guard let response = response as? HTTPURLResponse else {
        preconditionFailure()
    }
    
    switch (response.statusCode) {
    case 200:
        if let data = data, let message = String(data: data, encoding: .utf8) {
            print(message)
        }
    default:
        print("failure")
    }

    group.leave()
    
}.resume()

let result = group.wait(timeout: .now() + 10)
print(result)
get.swift You can use swift get.swift in the command line to run it.

The code above makes an asynchronous HTTP GET request to decode a base64 message.

Let’s see how the code samples above would typically be used in an app. A Base64Service which might look familiar with what you find in the “network layer”.

class Base64Service  {

    typealias DecodeCompletionHandler = (Result) -> Void

    let session: URLSession

    init(session: URLSession = URLSession.shared) {
        self.session = session
    }

    func decode(queue: DispatchQueue? = nil, encoded message: String, completionHandler: @escaping Base64Service.DecodeCompletionHandler) {

        var request = URLRequest(url: URL(string: "https://httpbin.org/base64/\(message)")!)
        request.httpMethod = "GET"
        request.addValue("text/html", forHTTPHeaderField: "accept")
        session.dataTask(with: request) { (data, response, error) in
            guard let response = response as? HTTPURLResponse else {
                preconditionFailure()
            }
        
            switch (response.statusCode) {
            case 200:
                if let data = data, let message = String(data: data, encoding: .utf8) {
                    (queue ?? DispatchQueue.main).async {
                        completionHandler(.success(message: message))
                    }
                }
            default:
                (queue ?? DispatchQueue.main).async {
                    completionHandler(.failure)
                }
            }
        }.resume()
    }
}

An EchoService type.

class EchoService  {

    typealias EchoCompletionHandler = (Result) -> Void

    func echo(queue: DispatchQueue? = nil, message: String, completionHandler: @escaping EchoService.EchoCompletionHandler) {
        let process = Process()
        process.launchPath = "/bin/echo"
        process.arguments = [message]
        process.terminationHandler = { process in
            
            let isSuccess = process.terminationStatus == 0

            (queue ?? DispatchQueue.main).async {
                if isSuccess {
                    completionHandler(.success(message: message))
                } else {
                    completionHandler(.failure)
                }
            }
        }

        process.launch()
    }
}

The Base64Service can be used like so:

let base64Service = Base64Service()
let encoded = "SGVsbG8gV29ybGQh"

base64Service.decode(encoded: encoded) { result in 
    
}

The EchoService can be used like so:

let echoService = EchoService()
let message = "Hello World"

echoService.echo(message: message) { result in
	
}

Run-of-the-mill so far.

With both services at hand, we want to be able to use them so that given an encoded message, we can:

  1. Decode the message.
  2. On success, echo the decoded message.

Let’s see how that would look.

let echoService = EchoService()
let base64Service = Base64Service()

base64Service.decode(encoded: "SGVsbG8gV29ybGQh") { result in 
    
    guard case .success(let message) = result else {
        return
    }

    echoService.echo(message: message) { _ in
    
    }
}

Baby Steps

Now that we have a better sense of what we are working with, let’s break it down.

The output of one step may act as the input to the next.

Notice how the message argument to the EchoService#echo(queue:message:) travels from the successful result of the Base64Service.

The message is the “output” of the Base64Service and the “input” to the EchoService. In that sense, you can think of an InputOutput type as a key/value storage that can be used to pass data between steps. Similar to how the NotificationCenter uses the userInfo whenever it posts a Notification.

typealias InputOutput = [AnyHashable : Any]

From that, the definition of a step is trivial.

Steps only make forward progress.

typealias Step = (_ io: InputOutput) -> Swift.Void

Let’s look at the implementation of the EchoStep.

import Foundation

struct EchoStep {

    weak var echoService: EchoService?

    func make(queue: DispatchQueue? = nil, next: Step? = nil) -> Step {
        return { io in

            guard let message = io["message"] as? String else {
                preconditionFailure()
            }

            self.echoService?.echo(queue: queue, message: message) { result in
                guard case .success(let message) = result else {
                    return
                }

                next?(["message":message])
            }
        }
    }
}

Think of the EchoStep as merely a type that creates a Step that echoes a message and also defines its input/output. It has an EchoService as a dependency but does not own it since the lifecycle of the EchoService3 is not directly related to the step execution.

Look closely at the EchoStep#make(queue:next:) implementation which returns a Step and think back to its type alias.

typealias Step = (_ io: InputOutput) -> Swift.Void

It returns a function, that accepts a single InputOutput type as its input and has no return statement. It expects the io argument to have a “message” value.

Equally, notice how the Step, passes it’s output to the next step, which in this case is the message it echoed. It’s important to understand that the InputOutput type is a short lived instance only meant to be used in creating the step. It is not meant to be long lived, passed throughout the whole series of steps or as a global variable where every input/output is kept there.

This is how you would create a new EchoStep and use it

let echoService = EchoService()
let echoStep = EchoStep(echoService: echoService)

let echo = echoStep.make()
let message = "Hello World!"

echo(["message":message])
EchoStep, A-series-of-steps.playground

There is one more thing.

Each step must be successful before the next one is taken.

Notice how the EchoStep#make(queue:next:) above accepts an optional next Step type that only calls on the condition of a successful callback.

With that in mind, let’s define a new type SuccessfulStep, which creates a “successful” Step and optionally passes the next one.

typealias SuccessfulStep = (_ next: Step?) -> Step

This type will become useful later as part of building a series of steps. For now, take a look at the DecodeStep.

struct DecodeStep {

    weak var base64Service: Base64Service?

    func make(queue: DispatchQueue? = nil, next: Step? = nil) -> Step {
        return { io in

            guard let encoded = io["message"] as? String else {
                preconditionFailure()
            }

            self.base64Service?.decode(queue: queue, encoded: encoded) { result in 
    
            guard case .success(let message) = result else {
                return
            }

            next?(["message": message])
            }
        }
    }

    func successful(queue: DispatchQueue? = nil) -> SuccessfulStep {
        return { next in 
            return self.make(queue: queue, next: next)
        }
    }
}

Focus on the DecodeStep#successful(queue:) -> SuccessfulStep. This function accepts every argument the #make one does, except the next Step.

The #successful function is useful to better express a series of steps. It’s best demonstrated in auto-completion.

Notice how DecodeStep(base64Service: base64Service).successful() defines a SuccessfulStep. It does not create one. This allows you to defer passing the next Step until after you have created it. Alternatively, you would have to write the code backwards, starting with creating the echo Step first.

Keep in mind that this is still the creation phase. Nothing is executed until you take the series step and call it with an InputOutput parameter.

series(["message":"SGVsbG8gV29ybGQh"])
DecodeStep, A-series-of-steps.playground

Try passing an invalid base64 encoded String and see what happens.

Now that we can chain a series of DecodeStep, let’s use them to decode a twice encoded base64 String.

let base64Service = Base64Service()
let echoService = EchoService()

let decodeOnce = DecodeStep(base64Service: base64Service).successful()
let decodeTwice = DecodeStep(base64Service: base64Service).successful()

let echo = EchoStep(echoService: echoService).make()

let series:Step = decodeOnce(decodeTwice(echo))
series(["message":"U0dWc2JHOGdWMjl5YkdRaA=="])

One thing you may be struggling with is how the heck does this line of code work?

let series:Step = decodeOnce(decodeTwice(echo))

Especially if you are not already familiar with functional programming. It’s ok! Let’s go through this.

The decodeOnce instance is a function (a SuccessfulStep). Once you call it, (i.e. decodeOnce(...) it resolves to a Step, that step is the one the DecodeStep makes. So the series instance is a Step function that you can call. (I have specifically declared its type so that this is clear.)

The decodeTwice instance is also a SuccessfulStep, once you call it, it resolves to a Step also made by the DecodeStep. It’s the next step in the series.

Finally, the echo instance is a Step (also a function). It’s the second next step in the series.

Error handling

You may have noticed that throughout the code, there isn’t much error handling. This was done on purpose since I wanted to focus on the design pattern of steps.

Having said that, you can easily incorporate error handling either through a delegate and/or notifications.

As an example, consider the following:

guard case .success(let message) = result else {

    self.delegate?.failure(error: StepError.failed("decode"))

    return
}

Mattt has an excellent article on Error4

Conclusion

typealias InputOutput = [AnyHashable : Any]
typealias SuccessfulStep = (_ next: Step?) -> Step
typealias Step = (_ io: InputOutput) -> Swift.Void

As long as you remember these 3 types, you can apply this pattern across your codebase.

Windmill 3.0 also uses it to distribute an export efficiently, securely and in a performant upload that requires 3 steps.

There is also nothing preventing you from combining async with sync steps.

Sample Project

Source on GitHub

Feedback

Would be nice if instead of brackets, it was possible to define a custom operator. However, as far as I know, that requires an explicit type instead of a typealias. If you have a suggestion, please let me know and will update this post.

Custom Operator

Here it is using an explicit type. Effectively, you wrap a function in a struct type, rather than simply create a typealias of the function. This way, you can also define a custom operator. In our case, that would be a SuccesfulStep.

infix operator -->: AssignmentPrecedence

public struct SuccessfulStep {
    let success: (_ next: Step?) -> Step
    
    call(_ next: Step?) -> Step {
        return success(next)
    }
}

extension SuccessfulStep {
    static func --> (success: SuccessfulStep, next: @escaping Step) -> Step {
        return success.call(next)
    }
}

I just came across Daniel Steinberg’s talk, You’re doing it wrong in which he mentions the Swift Evolution Proposal 0253 - Introduce callables which is coming. AFAICS, effectively you will be able to call a struct type as if it is a function. Which makes the struct SuccesfulStep retain it’s nature as if it was a typealias! Here is how a series of steps now looks inspired by Matt Gallagher release of CwlViews.

let series = decode --> echo

and

let series = decodeFirst --> decondSecond --> echo

I have also updated the source code.

Would also be nice if there was some type safety for the InputOutput arguments as well as its “type” required for each step.-

Acknowledgements


  1. In practice there are more steps than these. For this post, I’ll keep it simple by focusing on the user facing ones. ↩︎

  2. NSHipster has an intro to NSOperation ↩︎

  3. Most likely the echoService is owned by a UIViewController or at the very least, it is a leaf in its memory graph. Most likely, you don’t want to take the echo step (i.e. self.echoService?.echo) if, say, the UIView to display the message has been deallocated. ↩︎

  4. Localized​Error, Recoverable​Error, Custom​NSError ↩︎

]]>
Tue, 07 May 2019 00:00:00 +0200
Climate <strike>Change</strike> Emergency https://qnoid.com/2019/04/13/Climate-Change.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/04/13/Climate-Change.html Approximately 5’ minutes reading time

Excellent articles by The New York Times on the Climate Issue of April 9, 2019.

The first one is about economics and policy in relation to climate change. The second is about law, ethics and capitalism.

I found them both fascinating, especially the second one. In an alternate universe, I practice law as an attorney and have a background in philosophy.

Here are my takeaways. Market economics like “Price elasticity of demand” might make sense in theory, but in practice may not work as expected. Even more so when used in an effort to bring social change.

When a product becomes more expensive, people use less of it. Carbon pricing is an elegant mechanism by which market economics can work on behalf of the climate rather than against it. But if the idea’s straightforwardness is its great economic advantage, it has also proved to be its political flaw. Energy, for utilities and transportation, is a major cost of living. And across the industrialized world, the middle class and the poor have been struggling with slow income growth.

The Yellow vests movement, still ongoing, is a prime example of social unrest in response to carbon tax. In a financially strained society, people perceived the carbon tax as unjust rather than being persuaded to look for cheaper alternatives to warm their house and drive their cars.

The question is whether any policy is both big enough to matter and popular enough to happen.

Arizona, Michigan and Nevada tried to rally people behind clean energy while at the same time putting the responsibility squarely on energy companies. The goal was to incentivise people to opt for clean energy while at the same time making renewables more profitable for businesses through the use of performance standards. Keep the last part in mind; off to Peru.

On Dec. 13, 1941, a piece broke off a hanging glacier and fell into Palcacocha, creating a great wave that overwhelmed a natural dam and sent a flood surging toward Huaraz, a provincial capital in the Peruvian Andes, about 14 miles below. A third of the city was destroyed and at least 1,800 people were killed.

Since then, the government has posted guardians to watch the lake, measuring water levels, reporting on avalanches etc. due to the risk of flooding. In the meantime, local farmers that depend on the lake have concerns over the diminishing clean water.

“I depend, in every sense, on the mountain,” he told me. “It is everything.”

A man named Saúl Luciano Lliuya, “who had never left his country”, took it upon himself to travel to Germany and file a lawsuit against an energy company for sharing some of the responsibility. The “crazy” thing is that this German energy company does not operate in Peru nor there is evidence that is directly responsible for the ice melting. Still, the lawsuit is about the impact its operations have on the climate on a global scale!

Beginning in the 1990s, courts began to find tobacco companies liable for the health effects of cigarette smoking, even though smokers used their products willingly and even though the first 800 or so lawsuits against the companies failed.

Back then, the tobacco industry in its defence claimed that people made a choice to smoke hence it can’t be held responsible. Eventually, a subpoena to turn over internal documents proved that companies knew smoking was harmful. In an effort to maximise profits, appease shareholders and stay afloat, individuals practiced the art of deceit.

Today, this is one of the arguments energy companies are making too. People choose how to warm their homes and drive their cars. But do they, when income inequality is so prevalent in societies today?

And when New York City filed suit against BP and others, the companies responded that the city, because of its use of the oil industry’s products in its own police cars and garbage trucks and so on, shouldn’t be able to sue because it had what’s known as “unclean hands.” If everyone is at fault, the argument goes, no one can be held responsible.

The same argument you’ll hear from a kid caught eating a cookie from the jar, pointing the finger back at you exclaiming “You made them!”

But the parallels aren’t perfect. Unlike tobacco, energy companies have argued, the existence of the fossil-fuel economy has provided considerable advantages to society.

Except when energy companies lobby for coal, crude oil, fracking in an effort to keep existing profits, unless compelled by law to do otherwise. Think back to the campaign on clean energy and regulation based on performance standards.

That companies actively prevented the development of alternative energy sources and the regulation of carbon-intensive ones, thus politically and economically propping up a polluting system. “It’s incorrect to say that there’s a strong public demand for fossil fuels,” Sher, the plaintiffs’ lawyer, told me. “What we have is a desire for energy.”

Markets may decide on the price of goods and services. Individuals may act out of self-interest causing harm and resulting in people’s death but as long as morals guide us and justice prevails, I am hopeful for the future. “The arc of the moral universe is long, but it bends toward justice.”-

]]>
Sat, 13 Apr 2019 00:00:00 +0200
Moving the needle https://qnoid.com/2019/03/15/Moving-the-needle.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/03/15/Moving-the-needle.html Approximately 3’ minutes reading time

For the past few months, I have been working on Windmill 3.0 which enables Windmill on the Mac to publish your iOS app.

Effectively, every time you make a code change, Windmill will also publish your app so that you can install it on your iPhone.

This feature requires a subscription and a Windmill account.

I wanted to make this as streamlined and integrated as possible.

Here are the requirements.

  • There shouldn’t be a strong ordering between creating an account and purchasing a subscription.
  • A subscription enables publishing and listing of apps.
  • As long as a subscription is active, publishing and listing of apps must be enabled.
  • Access to publish and list apps must be protected by an access token.
  • The access token must have the same security requirements as any. Being cryptographically secure, have an expiry date, able to revoke it, not reused across clients.
  • The number of steps required to create an account, subscribe and gain access to publish and list apps should be kept at a minimum.
  • A user should be involved as little as possible and only where and when required.
  • No user passwords!
  • Anonymous.

And an important limitation.

  • Windmill on the Mac is not sandboxed1 therefore it cannot use StoreKit to purchase or restore a subscription.

I won’t go into the technical details in this post.

For now I’ll just say you need to have done a ton of background reading, gained a great deal of knowledge and experience using both Apple’s platforms and SDKs, as well as

at a high level,

at the low level,

Suffice to say that it takes a well coordinated software engineering dance that I had to choreograph every turn across the App Store, mobile, server and the desktop.

I almost cried seeing it work for the first time.

What I have to show you is what it looks like to the end user.

Here is Windmill on the iPhone. I have just added an SKPayment into the SKPaymentQueue and about to approve the purchase.

The listed app you see is because I have already been a subscriber in the past and already have one app published.

Nothing “special”. One thing to keep in mind. At this point the user may or may have not signed in to their iCloud account. Assuming that they have, here is what happens next.

Windmill on the Mac is notified that a valid subscription exists. Based on this “claim”, it acquires an access token and starts publishing2.

That’s it! There is nothing more before or after. Seriously. When the user first opens the app, here is what they see.

There is no step to create an account. Just a nudge to log in and turn iCloud Drive on.

Here is what the account screen shows for a subscribed user.

I am very proud of this.-

Write code. Blow minds.


  1. As of right now I don’t even know if it is possible, what it would take or whether it makes sense. As an indie developer I simply can’t afford it in both time and resources. ↩︎

  2. There is one more precondition based on the specification of Windmill. The “export” stage must have been successful. If the “export” stage hasn’t run yet, Windmill will effectively wait before it starts publishing. ↩︎

]]>
Fri, 15 Mar 2019 00:00:00 +0200
iOS automation - the current state of affairs https://qnoid.com/2019/03/13/iOS-automation-the-current-state-of-affairs.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/03/13/iOS-automation-the-current-state-of-affairs.html Approximately 10’ minutes reading time

Maxwell Anselm writing about Life in the slow lane.

I want to take this opportunity to say why I believe going back to Jenkins alongside writing and maintaining scripts is a step backwards, re-iterate what the goal of Windmill is and what has been guiding its development.

Before I go into the details, I do wholeheartedly understand where Maxwell (among others in my mind) is coming from. I have been an iOS Developer since 2009 and in the past I too have used Jenkins (with bash scripts) to automate the delivery of iOS apps. For the record, I have also used Xcode Bots and Buddybuild. I have never used fastlane; I am just familiar with it.

Building from the Command Line with Xcode

As it stands, if you want to build (test, export, archive, etc.) an Xcode project, you have to use Xcode’s command-line tools. I believe this is great!

  • It demonstrates that Apple is keen on providing developer tools beyond an editor and a simulator and hopes you can help with that. It tells me it’s been listening to the voice of the community to support continuous integration systems.
  • It puts the responsibility to develop and maintain the command-line tools squarely on Apple. We should cherish, embrace and encourage Apple to do this. Apple is better positioned to know what’s coming, build to specification and provide support for developers in a timely fashion.

I have witnessed the progress Apple has made which, to me, demonstrates commitment.

  • xcodebuild has unified Xcode actions providing consistency and interoperability between them. Back in 2014, you had to use xcrun PackageApplication to export an IPA. Today xcodebuild -exportArchive -archivePath xcarchivepath -exportPath destinationpath -exportOptionsPlist path mirrors Xcode’s workflow and is compatible with xcodebuild archive.
  • Apple strives for feature parity across Xcode and its command-line tools. e.g. You can notarize your app from the command line.
  • Sessions on automation and command-line tools are part of WWDC. e.g. What’s New in Signing for Xcode and Xcode Server
  • Apple writes documentation like the Technical Note TN2339 and drops hints on what the command-line tools are there for.

Note: build-for-testing and test-without-building provide support for continuous integration systems. - “Building from the Command Line with Xcode FAQ, Updated: 2017-06-19

That’s not to say that Apple gets everything right. I too have fought with and found running tests from the command-line to be unreliable. Having to restart the CoreSimulatorService as a result. Windmill is prone to this too.

I won’t claim to know what’s at fault here. I do believe Apple knows it reflects bad on them. Xcode engineers are working on this after all. Plus, it puts every tool that relies on them in a bad light.

Dependencies

Windmill relies heavily on existing conventions as set by Apple and aims to establish a best practice on how to automate building, testing and distributing apps. At this stage, what Windmill is able to achieve and to what extent is defined by Apple. There is no way around it. This is a conscious decision. To pretend otherwise would be to rely on reverse engineering, side effects, undocumented features and observable behaviours. For bringing that basic level of automation it should be enough. - “Announcing Windmill

With that in mind, I made the conscious decision to build Windmill with Xcode’s command-line tools and those tools alone1.

It’s unfortunate that as of today we can’t completely rely on xcodebuild to provide automation for Xcode projects. It is precisely for this reason why we need to keep giving feedback to Apple so that it can continue developing and supporting the command-line tools.

For example, it is not possible to know whether an Xcode project has a test target (i.e. has tests to run) until you have tried to run those tests. In other words, you have to run xcodebuild test-without-building, trap the error by querying the exit code and “assume” the project has no tests.

For Windmill, I had to write a ProcessManager2 that executes a Process and can recover from an error code.

Another example is when the output of xcrun simctl list devices --json changed, effectively being unable to find the available iOS simulators.

This is what Apple had to say:

While we try to not be unnecessarily disruptive, the format of that output is subject to change over time as features are added and we need to adjust it.

Which is fine! As long as changes like this are better communicated, documented, formally specified, deprecated and retired like any API.

Reliability

Which brings us to reliability and Maxwell’s strong argument against fastlane or any automation tool built on top of Xcode’s command-line tools for that matter.

Seeing this stuff makes me nervous, because I worry that fastlane is doing a bunch of extra work that

  • at best, I don’t care about or
  • at worst, is going to cause problems that I have to fix (don’t laugh, read on…)"

The -showBuildSettings tells you what deployment target a project is or what its product name is. It helps finding the correct simulator to use since xcodebuild requires you to specify what destination to use with build-for-testing.

Xcode reads all of that from the project file under “Build Settings” and defaults to a scheme (or a target) and gives you a list of simulators appropriate for your project. xcodebuild is a command-line tool after all and Xcode is a GUI app.

Still, why should Maxwell care about all of this? As far as he is concerned he does know what scheme to build for his project and what destination (i.e. simulator) to test against.

It is true that when you build a tool for the many, you do need to accommodate for cases that go beyond the needs of the one. This rings more true when you build an automation tool that has to be reliable, predictable, consistent across environments and configurations.

To pick the correct device to build and test for that means being able to do so across Xcode installations and upgrades, removal of simulators, changes in the deployment target of your app, etc than merely choosing what destination may be valid right now.

Establishing a process that automates all aspects of the delivery of your app for quality assurance in order to save time, money and effort demands more than simply knowing what scheme to build your project with; as you may have witnessed in an effort to ditch, in this case, fastlane.

More importantly, it is about making continuous delivery ubiquitous, accessible, understood by everyone in your team so that together you can progress further.

Collectively as an iOS community, we have spent an insane amount of time and put an immense amount of effort in automating the delivery of our apps by writing flaky scripts in bash using Jenkins, reverse engineering the Xcode project file format, writing blog posts with our findings.

Yet we are none the wiser and have barely made a dent.

Yes, some of it is not critical or essential to any one of us as individuals but working on and having a tool that has these goals in mind will lead to a better tool for everyone in the long run. It will allow us to move on to whatever the next challenge in delivering iOS apps is.

Complexity

“I felt like I had to babysit it every day, constantly diagnosing whether build or test failures were legitimate. Consequently the rest of my team never trusted it.” - Maxwell Anselm, Life in the slow lane

When Windmill first came out, it didn’t surface any errors so you had to go through the logs to find out what went wrong. In this regard, it was no better than a bare-bone Jenkins installation showing you the log of a build job. As a developer, you had to manually go through the output of xcodebuild to figure out what went wrong.

Since Windmill is a developer tool, developers were eager to debug it! “If only I could see what command Windmill is running, I can try and replicate the issue”.

You see, I knew right then3 that Windmill was failing to live up to its mission. You shouldn’t have to debug Windmill!

Since version 2.0, Windmill mirrors the Xcode log. xcodebuild does not provide a formatted output so I had to build it and actively maintain it for each release. This costs time, effort and it’s not streamlined to Xcode upgrades. Still, I am willing to pay that price for Windmill to deliver on its promise.

I have put an insane amount of effort and time to make sure Windmill mirrors Xcode’s behaviour so that when Windmill fails it does in the exact same way as Xcode.

Windmill has a long way to go before it can be the tool I envision. As an example, right now Windmill is reactive only to code changes.

If a distribution certificate expires, Windmill will surface that error the next time you commit a code change rather than at the time it expires or even better, warn you in advance.

Why use anything else but xcodebuild?

People don’t realise how much time they have spent installing, building, maintaining, communicating, debugging their way to, at the very least, automate building and testing their iOS app until they decide they’ve had enough.

In Maxwell case, his post on Distributed iOS builds with Jenkins was in Aug 3, 2018 and “Life in the slow lane” in Mar 12, 2019.

Speaking for Windmill, I have taken the strong stance to build it on the following premise.

  • Have a native, macOS app with an unparalleled user experience in an effort to make continuous delivery accessible.
  • Lean on and don’t stray away from Xcode’s command-line tools provided functionality.
  • Don’t resort to hacks to make Apple’s command-line tools work.
  • Rely on the macOS SDK and macOS toolchain. e.g. PropertyListSerialization to convert a property list to and from several serialized formats.
  • Link to Apple’s documentation and encourage developers to have an understanding of how things work where necessary.
  • Minimise the use of informal contracts, i.e. parsing of standard output.
  • Don’t overstep any boundaries, i.e. Xcode’s ability to manage automatic signing.
  • Embrace Xcode’s provided functionality, i.e. store archives in the Organiser.
  • Don’t create abstractions on top of existing concepts, e.g. what an archive is on iOS.
  • Mirror and match Xcode behaviour to provide consistency across, e.g. how build errors and test failures are surfaced and communicated.
  • Be a good citizen on macOS as a native app.

That’s not to say that Windmill is 100% foolproof. See its version history.

Still, what Windmill offers today, even at version 2.0, is of great value, especially if you all you need is a basic level of automation while developing your app.

In the end, I have made the decision to place my faith in Apple by building a native macOS app with Xcode’s command-line tools and invest so much in the Apple ecosystem. Until Apple comes up with something better.-

PS. I am using Windmill on macOS while developing Windmill on the iPhone and I am loving it! There is a chance of bias.
PPS. If you want to be part of the Windmill on the iPhone beta, sometime in the unknown future, please send me an email at qnoid@windmill.io.


  1. Windmill does depend on other macOS tools like python and awk as a necessary evil where xcodebuild falls short as well as frameworks like ObjectiveGit and Alamofire at the application level. ↩︎

  2. Let me know if you have an interest in this for your macOS app and I will put the time aside to publish the source code alongside some documentation on how to use it. ↩︎

  3. I knew this was a limitation of Windmill 1.0 at the time and had plans on addressing it in Windmill 2.0. ↩︎

]]>
Wed, 13 Mar 2019 00:00:00 +0200
Standing on the shoulders of giants https://qnoid.com/2019/03/06/Standing-on-the-shoulders-of-giants.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/03/06/Standing-on-the-shoulders-of-giants.html Alamofire

        return sessionManager.upload(multipartFormData: { multipartFormData in
            multipartFormData.append(export.url, withName: "ipa")
            multipartFormData.append(export.manifest.url, withName: "plist")
        }, with: urlRequest, queue: self.queue, encodingCompletion: { result in
            
            switch result {
            case .success(let upload, _, _):
                upload.validate().responseData(queue: self.queue) { response in
                    switch (response.result, response.result.value) {
                    case (.failure(let error), _):
                        switch error {
                        case let error as AFError where error.isResponseSerializationError:
                            DispatchQueue.main.async{
                                completion(nil, nil)
                            }
                        case let error as AFError where error.isResponseValidationError:
                            switch (error.responseCode, response.data) {
                            case (401, let data?):
                                if let response = String(data: data, encoding: .utf8), let reason = SubscriptionError.UnauthorisationReason(rawValue: response) {
                                    DispatchQueue.main.async{
                                        completion(nil, SubscriptionError.unauthorised(reason:reason))
                                    }
                                } else {
                                    DispatchQueue.main.async{
                                        completion(nil, SubscriptionError.unauthorised(reason: nil))
                                    }
                                }
]]>
Wed, 06 Mar 2019 00:00:00 +0200
A life filled with music https://qnoid.com/2019/03/06/A-life-filled-with-music.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/03/06/A-life-filled-with-music.html

I can recall that eye-opening feeling paired with excitement from discovering my music library all over again.

I had an iPhone 3G when I bought my first iPod Classic. For the first time I was able to carry with me all my iTunes Music library.

Every song I listened to was a trip down memory lane oozing with emotion.

Walking on top of Wearmouth Bridge on a cold winter night in Sunderland, listening to a Blind Guardian cover of Dio’s Don’t Talk To Strangers.

Spending Easter with a loved one in Coventry listening to Brian May.

Dancing to Found An Angel at The Palace Night Club on Newcastle Road.

Feeling haunted by Eminem - Stan ft Dido.

Crying to Angels by Robbie Williams.

Being melancholic to Street Spirit by Radiohead.

Music spoke to me, made me cry, comforted me, filled me with joy, caused me to reflect.

I have been a subscriber to Spotify since 2009. Music is more accessible than ever yet it sits in the background. It has lost its impact.

In an effort to increase play time (i.e. revenue) music services have lost touch with what role music plays.

You feel (want to feel) happy? Here is a “Happy Hits” playlist. Are you at the gym? Here is a “Motivational” playlist. Want to retreat to yourself? Here is a “Sad Songs” playlist.

This isn’t about owning versus streaming music. It’s not about albums vs playlists. This is about feeling connected to music. This is about “owning” a music library that reflects, encompasses, enriches life. Your life.-

]]>
Wed, 06 Mar 2019 00:00:00 +0200
Greek residency as a European citizen https://qnoid.com/2019/03/05/Greek-residency-as-a-European-citizen.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/03/05/Greek-residency-as-a-European-citizen.html Today I learned from an immigration lawyer (Recommended!) that as a European citizen to be formally recognised as a resident in Greece (i.e. that is if you plan on staying for longer than 3 months) you must:

  • have health insurance, either private or the European health card (e.g. for a UK Citizen, Apply for a European Health Insurance Card)
  • have proof of permanent residence in Greece
  • have four, thousand euro (€4000) in a bank account, readily available for withdrawal.

That is, so as not be considered an illegal(?) immigrant.
That is, to call Greece home.
That is, in the European Union where ”free movement and residence rights” exist.

EU freedom of movement and residence

Based on the “Directive 2004/38/EC”, EU countries could may well ask you to leave or even deport you after 3 months. As far as I can see, the only reason they might not is purely on good faith among them.

To my mind, the European Union must be more integrated.-

]]>
Tue, 05 Mar 2019 00:00:00 +0200
Primitive testing of a REST API in bash https://qnoid.com/2019/02/26/Primitive-testing-of-a-REST-API-in-bash.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/02/26/Primitive-testing-of-a-REST-API-in-bash.html I have been developing the Windmill REST API using JAX-RS and wanted a very basic, lightweight way to ensure the API hasn’t regressed.

I have been using curl to quickly check the API anyway so I thought I’d take it a step further.

#!/bin/bash

set -e

function assertTrue()
{
if [ ${1} -eq ${2} ]; then
echo *SUCCESS*
else
echo "*FAILURE* expected: ${1} actual: ${2}"
exit 1
fi
}


echo "Given valid subscription access; Assert GET exports 200 OK"
HTTP_CODE=$(set -x;curl -s -o /dev/null -w "%{http_code}" https://api.windmill.io/account/qnoid/exports -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJpc1ZhbGlkIn0.rqED0v7meSp72MBaeQtyXce3S_dJoh_eo6iIV2Rpt3s")

set +x;assertTrue 200 "${HTTP_CODE}"

echo "Given invalid subscription access; Assert GET exports 401 Unauthorized"
HTTP_CODE=$(set -x;curl -s -o /dev/null -w "%{http_code}" https://api.windmill.io/account/qnoid/exports -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJpc1ZhbGlkIn0.3zjr4euU206esZpd0w6Au4o5qYk4ydiuAKXE6SClUaw")

set +x;assertTrue 401 "${HTTP_CODE}"

Which gives the following output

Given valid subscription access; Assert GET exports 200 OK
++ curl -s -o /dev/null -w "%{http_code}" https://api.windmill.io/account/qnoid/exports -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJpc1ZhbGlkIn0.rqED0v7meSp72MBaeQtyXce3S_dJoh_eo6iIV2Rpt3s'
*SUCCESS*

Given invalid subscription access; Assert GET exports 401 Unauthorized
++ curl -s -o /dev/null -w "%{http_code}" https://api.windmill.io/account/qnoid/exports -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJpc1ZhbGlkIn0.3zjr4euU206esZpd0w6Au4o5qYk4ydiuAKXE6SClUaw'
*SUCCESS*

In case of a failure, execution stops right away with the following output

Given valid subscription access; Assert GET exports 200 OK
++ curl -s -o /dev/null -w "%{http_code}" https://api.windmill.io/account/qnoid/exports -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJpc1ZhbGlkIn0.rqED0v7meSp72MBaeQtyXce3S_dJoh_eo6iIV2Rpt3s'
*FAILURE* expected: 200 actual: 401

It’s very primitive and not hardened but it should work in the meantime.-

]]>
Tue, 26 Feb 2019 00:00:00 +0200
How to replace the `rootViewController` of the `UIWindow` in iOS https://qnoid.com/2019/02/15/How_to_replace_the_-rootViewController-_of_the_-UIWindow-_in_iOS.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/02/15/How_to_replace_the_-rootViewController-_of_the_-UIWindow-_in_iOS.html Approximately 11’ minutes reading time

This is an advanced topic. It requires extensive background knowledge and experience. Unless you feel confident with what’s being discussed here, consider and be mindful of intricacies and unknown unknowns when implementing presentation transitions, state preservation and restoration on iOS.

Errata

18 February 2019, commit “7d3cccf

  • The RootViewController had its Container View as a subview rather than being the view. Though technically is allowed, in this case it is not a requirement.
  • The RootViewController.viewDidLayoutSubviews() used to call self.transition(from:to:) which in certain layouts it leads to an unwanted animation. Instead, it now uses self.switch(source:destination:) to position its child view controller.

Table of Contents

Introduction

Have you ever needed to build an app that:

  • expects the user to go through a lengthy registration process then land on a “home screen”?
  • has an extensive tutorial that the user can go through before they start using the app?
  • goes through a series of on boarding screens, possibly keeping track of user progress?

Registration Flow

In the above example, once the user has gone through registration, you want to discard every view controller involved in the sequence as well as replacing the rootViewController with a new UIViewController that comes after registration.

Main View Controller

Notice how there is no use case where the user can navigate back to registration. There is no “Back” or “Dismiss” button in the MainViewController that can act as the root. For that reason, you should consider it best practise to discard any UIViewControllers and their respective views so as to bring overall memory usage down and establish a new baseline when a user has registered.

View Controllers’ Presentation and transitions

Let’s start with firing a Notification when the user selects “Done”.

class DoneViewController: UIViewController {

	static let NotificationDone = NSNotification.Name(rawValue: "Done")

	@IBAction func didTouchUpInsideDone(_ sender: Any) {
		NotificationCenter.default.post(name: DoneViewController.NotificationDone, object: nil)
	}
}

Since the AppDelegate holds a reference to the UIWindow and by extension the rootViewController, it can act as an observer. Upon firing, it merely sets the rootViewController property to the new one.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

	NotificationCenter.default.addObserver(self, selector:#selector(done(notification:)),name:DoneViewController.NotificationDone,object: nil)
	
	return true
}
    
@objc func done(notification: Notification) {
	let storyboard = UIStoryboard(name: "Main", bundle: Bundle(for: type(of: self)))
	self.window?.rootViewController = storyboard.instantiateInitialViewController()
}

Let’s see how that looks.

Notice how there is no transition between the DoneViewController and the MainViewController. This plays a far more important role that it currently seems as you’ll see later. Let’s peak behind the scenes on the view hierarchy.

First Attempt View Hierarchy

Even though the code replaces the rootViewController for the window, notice how the DoneViewController is still in the view hierarchy under a UITransitionView seemingly owned by the UIWindow. Here is a close look at the memory graph.

First Attempt Memory Graph

It looks like the RegisterViewController and all of its children are still very much present. Let’s try something else now. Before replacing the rootViewController, use a presentation transition to present the view controller we are interested in.

@objc func done(notification: Notification) {
    let storyboard = UIStoryboard(name: "Main", bundle: Bundle(for: type(of: self)))
    
    guard let viewController = storyboard.instantiateInitialViewController() else {
        return
    }

    let presentedViewController = self.window?.rootViewController?.presentedViewController
    
    presentedViewController?.present(viewController, animated: true) {
        self.window?.rootViewController = viewController
    }
}

From UIViewController.present(_:animated:completion:), emphasis mine.

In a horizontally regular environment, the view controller is presented in the style specified by the modalPresentationStyle property. In a horizontally compact environment, the view controller is presented full screen by default.

Since an iPhone, in portrait, is a horizontally compact environment, “the views belonging to the presenting view controller are removed after the presentation completes.” In this case, the presentedViewController (i.e. the DoneViewController) becomes the presentingViewController to the MainViewController, hence the DoneViewController will be removed from the view hierarchy.

Second Attempt View Hierarchy

The view hierarchy indeed shows only the MainViewController present. Still, the UITransitionView should give you a clue as to what to expect in the memory graph.

Second Attempt Memory Graph

The DoneViewContoller is still very much allocated. The RegisterViewController as well as all of the UIViewController instances are also allocated (not seen in the screenshot). Finally, let’s dismiss the whole view hierarchy, as part of presenting the MainViewController, before replacing the rootViewController.

From UIViewController.dismiss(animated:completion:), emphasis mine.

If you present several view controllers in succession, thus building a stack of presented view controllers, calling this method on a view controller lower in the stack dismisses its immediate child view controller and all view controllers above that child on the stack.

@objc func done(notification: Notification) {
    let storyboard = UIStoryboard(name: "Main", bundle: Bundle(for: type(of: self)))
    
    guard let viewController = storyboard.instantiateInitialViewController() else {
        return
    }

    let presentedViewController = self.window?.rootViewController?.presentedViewController
    
    presentedViewController?.present(viewController, animated: true) {
        self.window?.rootViewController?.dismiss(animated: false) {
            self.window?.rootViewController = viewController
        }
    }
}

Here is the view hierarchy; no UITransitionView in the window.

Third Attempt View Hierarchy

And here is the memory graph.

Third Attempt Memory Graph

Well, that looks promising. Let’s see how it looks. The video on the right gives you a freeze frame.

What’s happening here? In an effort to remove every UIViewController from the view hierarchy and memory graph, the code completely ignores the presentation. The present and dismiss calls are happening independently and on separate transition contexts.

Let’s break it down.

  • The DoneViewController is presenting, modally, the MainViewController. At the end, the DoneViewController is removed from the view hierarchy and deallocated.
  • The rootViewController (i.e. RegisterViewController) dismisses the UINavigationController all the way to the just presented MainViewController, which takes us back to the initial state where the UIWindow is showing the RegisterViewController.
  • The RegisterViewController is being replaced by the MainViewController as the rootViewController.

State Preservation and Restoration

Before looking into how to best replace the rootViewController there is one more thing to consider.

Up until now, we’ve only been talking about replacing the rootViewController and its descendants as part of an “initial” launch. As long as the app isn’t terminated, upon switching to it, its view will be restored. Still, the change in the view hierarchy is not permanent. As soon as the app is terminated by iOS due to memory pressure, the next time the user launches the app, the rootViewController will revert to RegisterViewController as if it was launched for the first time.

This is where state preservation and restoration feature comes in. One thing to keep in mind is that every ancestor UIViewController, including the one whose state you want preserved and restored must have its restorationIdentifier set.

View Controllers with restoration identifiers set

The simplest way to test preservation and restoration is via Xcode. Launch the app, navigate to the view controller with a restorationIdentifier to preserve. Then:

  • Put the app into the background
  • Stop the app’s execution by pressing the stop button in Xcode
  • Launch the app

What you can’t see from the video is that shortly after I put the app in the background, I stop the execution via Xcode. Effectively the app is now considered to be terminated by iOS.

That looks good. Let’s try it on the MainViewController now.

You can briefly see the snapshot of the MainViewController that was taken just before the app moved to the background. Followed by the “Initial UI”.

Obviously the state preservation and restoration isn’t working as expected. I haven’t been able to gather enough information so I am only guessing that state preservation and restoration is coupled to the presentation and transition context. In other words, it’s not enough to simply set a new rootViewController and expect it to be restored. Whatever UIViewController to be restored possibly needs to be a descendant of the “Initial UI”. If you do know more, I would very much like to hear from you.

Container View Controller

With what I know and can see so far, it appears that once the rootViewController has been set, UIKit does not provide for a way to replace it. As such, any presentation and transitions must originate from the rootViewController itself.

A Container View Controller is merely a UIViewController that introduces (or rather exposes) the concept of “child” view controllers. We came across the concept of a child view controller during presenting and dismissing view controllers.

Container view controllers are most often used to facilitate navigation and to create new user interface types based on existing content. In almost every way, a container view controller is like any other content view controller in that it manages a root view and some content.

One way to think about a container view controller is how a UITabBarController manages the presentation of the view for each UIViewController set in its viewControllers property. Every time you select a tab, the corresponding view appears into the window’s bounds and the control is passed to its respective UIViewController.

Thinking back to what we were set out to do. We want to bring into the window the view of another view controller while replacing an existing stack of view controllers. Which sounds awfully lot like how a UITabBarController behaves.

Container View Hierarchy

With the container view controller now acting as the root, the view of the RegisterViewController effectively is embedded in the view of the RootViewController. Visually, nothing has changed.

Now that a UIViewController manages the view hierarchy presented, we can replace notifications in favour of an unwind segue. Nothing to see in the DoneViewController. The unwind segue is defined in the storyboard.

class DoneViewController: UIViewController {

}

The AppDelegate has all of the code related to the notification removed. Here is the code for the RootViewController.

class RootViewController: UIViewController {

private func transition(from: UIViewController, to: UIViewController) {
    from.willMove(toParent: nil)
    self.addChild(to)
    
    self.transition(from: from, to: to, duration: self.transitionCoordinator?.transitionDuration ?? 0.4, options: [], animations: {
        
    }) { (finished) in
        from.removeFromParent()
        to.didMove(toParent: self)
    }
}

@IBAction func unwindToRootViewController(_ segue: UIStoryboardSegue) {

	let storyboard = UIStoryboard(name: "Main", bundle: Bundle(for: type(of: self)))
	
	if let registerViewController = self.children.first(where: { $0 is RegisterViewController }), let mainViewController = storyboard.instantiateInitialViewController() {
	self.transition(from: registerViewController, to: mainViewController)
	}
}

Let’s see it in action.

Note that as part of the transition, the DoneViewController is effectively dismissed. Hence the animation that “presents” the MainViewController is the same as if the call was mainViewController.dismiss(animated: true) while the DoneViewController was presented.

The respective view hierarchy and memory graph

Container View Hierarchy

Container Memory Graph

How about state preservation and restoration.

One thing to keep in mind when preserving a UIViewController that acts as the container, is that your code is responsible for saving any references to its child view controllers. Here is what it looks like.

override func encodeRestorableState(with coder: NSCoder) {
    super.encodeRestorableState(with: coder)
    
    self.children.forEach { child in
        if let restorationIdentifier = child.restorationIdentifier {
            coder.encode(child, forKey: restorationIdentifier)
        }
    }
}
    
override func decodeRestorableState(with coder: NSCoder) {
    super.decodeRestorableState(with: coder)
    
    if let mainViewController = coder.decodeObject(of: [MainViewController.self], forKey: "MainViewController") as? MainViewController {
        self.addChild(mainViewController)
    }
}

When the RootViewController is instantiated as part of the “Initial UI”, the RegisterViewController will also be present in its “children” property. Therefore as part of the layout, we need to make sure the MainViewController is the only one in the view hierarchy.

override func viewDidLayoutSubviews() {
    let registerViewController = self.children.first(where: { $0 is RegisterViewController })
    let mainViewController = self.children.first(where: { $0 is MainViewController })
    
    switch (registerViewController, mainViewController) {
    case (let registerViewController?, let mainViewController?):
        self.switch(source: registerViewController, destination: mainViewController)
    default:
        break
    }
    
    super.viewDidLayoutSubviews()
}

private func `switch`(source: UIViewController, destination: UIViewController) {
        
    source.willMove(toParent: nil)

    destination.view.frame = self.view.bounds
    self.view.addSubview(destination.view)
        
    source.view.removeFromSuperview()
    source.removeFromParent()

    destination.didMove(toParent: self)
}

This time, the MainViewController is restored as expected.

For completeness, here are the visual hierarchy and memory graph of the app after the restore process is done.

Container View Hierarchy

Container Memory Graph

Considerations

Keep in mind that the user can, at any time, kill the app. At this point, the restoration process will not happen and the rootViewController will revert back to the one in the “Initial UI”. This will also happen if your app crashes.

ISTR that removing the app from the multitasking UI specifically disables state restoration, on the grounds that the user only does this when there’s something wrong with the app and thus it’s better to start from a clean slate. - Quinn “The Eskimo!”, Apple Developer Relations, Developer Technical Support, Core OS/Hardware

You should anticipate, embrace and gracefully handle your app reverting to its “Initial UI”.

As an example, in the case of a registration, it is possible that you store some authorization token to give access to the user. On startup, you can detect that and allow the user to login with the existing credentials.

One thing to consider is that if you decide to hardcode the decision as to what rootViewController to show, you effectively limit the choices you can give to a user to recover for a “bad state”. If the user cannot merely terminate the app, they will have to re-install.

Consider giving the user the ability to fallback in stages:

  • While the user is using the app:
    • to revert to a previous state; e.g. logout
  • By removing the app from the multitasking UI:
    • to remove any existing state, either through preservation or in memory; e.g. recover from a crash
  • By un-installing:
    • to erase any hard persisted data. e.g. an authorization token so as to start over.

Conclusion

tl;dr. You should use a Container View Controller as the rootViewController and swap one child UIViewController for another.

Should you wish to preserve the rootViewController, consider the native iOS support of preserving and restoring state.

Keep in mind that state preservation and restoration goes beyond what UIViewController is present. UIKit views can also have preservable state. As an example, a UIScrollView preserves its zoomScale, contentInset, and contentOffset properties, effectively “so that the content appears scrolled to the same position as before”.

That can be useful for persisting any registration steps as the user goes through, browses through a collection of photos or reads a long text.

I would like to thank @marc, @jsorge, @tekl of Seattle Xcoders for their input and for keeping me sane through this. Even though I am remote, Seattle Xcoders has welcomed me as if I am based in Seattle.

Shoutout to Andy. It may have taken 3 years but we did it!

One more thing

This is one of the many technical challenges that I am tackling as part of making Windmill on the iPhone the best experience it can be.

I have been busy working towards Windmill 3.0 which brings publishing of your apps during development.

You can download Windmill for free.-

Sample Project

github.com/qnoid/rootViewController

References

Related

]]>
Fri, 15 Feb 2019 00:00:00 +0200
Hiring for diversity https://qnoid.com/2019/01/25/Hiring-for-diversity.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/01/25/Hiring-for-diversity.html Approximately 3'30’’ minutes reading time

Ask yourself a question. “Do we hire for diversity”? If the answer is “We hire based on merit”, chances are you aren’t doing enough.

By leaving diversity to chance, you assume and expect a uniform distribution of people with different race, age, gender and social status to arrive at your doorstep.

This is not the case. Take tech as an example.

Source: WOMEN AND MINORITIES IN TECH, Wired

As this chart shows, white men dominate college computer science departments. By a lot. One of the reasons for this may be the way companies try to recruit talent. Stanford researchers observed more than 75 recruiting sessions held by more than 60 companies and identified countless seemingly obvious ways the recruiters might be alienating female recruits, from sexist jokes to presentations displaying only slides of men.

I encourage you to read the whole article on Wired which is an excellent piece, on how the use of words, access to resources (e.g. computers at home) and salary inequality play a role.

Start by measuring the distribution among your current hires. One way to do this is by creating an anonymous, optional questionary. It’s important that you have a discussion first. Make sure everyone understands what the intent is and buys into it.

ustwo, a London agency, has gone a step further and created a public Diversity Dashboard to, as far as I can see, demonstrate commitment, raise awareness and to be held accountable.

Keep in mind that those numbers may also reveal a bias in hiring, while you believe you are merely focusing on merit.

A 2015 study followed up on this, and found that candidates with black-sounding names from elite universities did only as well as those with white-sounding names from less-selective schools.
Source: Is Blind Hiring the Best Hiring?, The New York Times

It may be possible that you are unknowingly exhibiting bias during your hiring process by expecting people to “fit in” rather than to “come as they are”. Feeding into a cultural conformity as opposed to diversity.

Who is present at an interview and how people express or respond can equally discourage people to come forward or be allowed to proceed. Having a diverse representation when you start from a non diverse background can be challenging.

Once again, ustwo has created a Head of Diversity role to tackle lack of equal representation head on and drive change.

We are completely overhauling our hiring process. This will include standardised questions and mixed interview groups. We will seek ways to ensure we are meeting a diverse range of candidates which we hope will lead to an increase in hiring of underrepresented candidates.
Whitney Berry, Head of Diversity, ustwo

Below I am only suggesting a list of actions that you could take, across different areas to help diversity flourish.

Education

  • Work with local authorities to provide training to unemployed young people that have dropped out of education (NEET).
  • Work with Universities to provide internships/placements to minority groups.

Hiring

  • Take action to avoid discrimination based on gender/age/race when screening candidates.
  • Involve a diverse group of people in the hiring process.
  • Actively seek to hire minorities for head/management/leadership roles.

Support

  • Support meetups and groups that give a voice to under represented people (e.g. LGBT) and invite them to talk in house to raise awareness.
  • Fund people in need either directly or via a matching contribution to employees; KIVA.
  • Fund charities and institutions that defend people’s rights to education and employment.
  • Fund diversity tickets at conferences.
  • Give people time off to volunteer in causes that have a social impact.

Day to day operations

  • Be open, encourage and support ideas and views that challenge norms.
  • Measure, track and have visibility on data that shows how diverse the company is.
  • Provide parental leave as a work benefit.

Further Reading

  1. Should universities give preference to applicants from poor backgrounds?
  2. Tokyo medical school admits changing results to exclude women
]]>
Fri, 25 Jan 2019 00:00:00 +0200
User Accounts https://qnoid.com/2019/01/17/User-Accounts.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/01/17/User-Accounts.html Approximately 2'30’’ minutes reading time

Windmill thus far has been devoid of the concept of a user account. There hasn’t been a need since Windmill has been a standalone macOS app. With the arrival of Windmill on the iPhone the requirement to have a “user” account becomes more apparent.

On the iPhone, a user should be able to view the IPA file for each app that has been exported. There are two parts in enabling this functionality.

  • Publish an export for a given “user”.
  • Return a list of exports for a given “user”.

Both to be supported by a server that provides a REST API.

Requirements

The simplest thing would be to have a user create an account using a username and a password. I take a few issues with this approach.

No passwords.

First and foremost I consider asking a user for a password a compromise in security for the following reasons.

Cross device, platform support.

Windmill is a native macOS app. Windmill on the iPhone will be a native iOS app. A user should be able to use Windmill from macOS, iOS and possibly the web.

A solution needs to be able to work, potentially, for every Apple platform as well as the web.

Anonymous.

Ideally, I would like to take user accounts a step further and provide this functionality without even asking for an email. An email can be used to identify an individual and is data that can be exploited by a malicious third party should it become compromised.

In Summary

  • No password. The server should be able to authenticate a user without the need of a password.
  • Cross device/platform support. The user should be able to use Windmill from a different device and/or platform. e.g. Safari on the Mac, Windmill macOS, Windmill iOS.
  • Anonymous. User shouldn’t have to enter an email to identify with the service.

Plus, it should be as seamless as possible with very little friction and overhead.

After some research and discussion1, it looks like CloudKit might be able to check all the boxes.

I will have to investigate further.

See also

Some database operations require that users sign in using their Apple ID. Your web app will need to handle these authentication errors and present the user with a dialog to sign in. Apple will present the actual sign-in page through a redirect URL so that the user’s credentials remain confidential. If the user chooses to sign in, the response contains a web authentication token that you use in the subpath of subsequent requests. - “CloudKit Web Services Reference, 2016-06-13”


  1. Thank you Matt Farrugia for offering some of your time to bounce these ideas off of you. ↩︎

]]>
Thu, 17 Jan 2019 00:00:00 +0200
Public Spaces https://qnoid.com/2019/01/09/Public-Spaces.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/01/09/Public-Spaces.html Approximately 2'30’’ minutes reading time

Yesterday I felt like having a conversation. I wanted to talk about user authentication on iOS. How to implement it without asking the user for a password. I wanted to do even better and have anonymous user accounts.

I was excited! Like a little kid that comes home from school and wants to talk to his parents about something new. Then, I stumbled. Who do I talk to about this? I am not at an office. I am not sitting at a co-working space. I am not attending a developers’ conference. Suddenly, I paused. Where is everybody? How do I reach out?

I thought of Twitter first. One reason I love Twitter is how it makes everyone accessible. You can direct your message at anyone and everyone. So I did, knowing full well that the chances of someone coming back are slim.

Twitter is more about sharing your thoughts, talking about what’s happening now. Twitter is async by nature. It’s not a way to have a discussion. Let alone getting a reply to jump on a call to have a conversation.

Then I thought of Slack. I am a member of some channels and occasionally spend some time on Athens iOS Meetups. I also decided to visit the Seattle Xcoders channel. Surely these are the places you can find iOS developers to have a chat with.

Not really. Just because people can be found there, doesn’t mean they are available. When you step into the room people don’t have to greet you. In fact, such a behaviour is not netiquette. Saying “g’day”, “καλημέρα”, “bonjour” messages is just noise1. Asking a question doesn’t mean it will get acknowledged. At best, what you will have is an async, robotic chat. With any form of expression narrowed down to written dialog. No eye-popping dialogue, no raising eyebrows, no gesticulations, nodding, human interaction.2

Finally, I thought of email. I will admit this was getting silly. Still, I looked around on people’s websites that I felt I wanted to talk to. Not much. No email information. No contact me. No happy to talk. Nothing. In fact, I’m guilty of that too!

Huh? In an online world, where we are all connected and accessible, where is everybody?

With social media focusing on individual expression and ways to satisfy our need for external validation where do we gather to exchange thoughts, ideas, knowledge?

In a world filled with co-working spaces and open plans offices why do we wait for lunch or a coffee break to converse? How accessible are these spaces to the public?

Are we all too busy working, driven by numbers maximising output that both our willpower and availability have diminished?

Where are our public gathering spaces used for civil discourse?


  1. Walking into a Kafenio at a Greek village would cause the following in order. Visual assessment of the individual, acknowledgement, greeting, getting familiar, showing interest in what one has to say. ↩︎

  2. Thank you Marc Schwieterman for having a word with me. ↩︎

]]>
Wed, 09 Jan 2019 00:00:00 +0200
Cookie free https://qnoid.com/2019/01/09/Cookie-free.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/01/09/Cookie-free.html Approximately 1 minute reading time

In an effort to make this site cookie free, have now completely removed Google Analytics, converted any Twitter embed links to quotes with a link to the original tweet and enabled “Privacy-enchanced mode” for embed YouTube

Privacy Enhanced Mode allows you to embed YouTube videos without using cookies that track viewing behavior. This means viewing inbox isn’t collected to personalize the viewing experience. Instead, video recommendations are contextual and related to the currently played video. Videos playing in a Privacy Enhanced Mode embedded player won’t influence the viewer’s browsing experience on YouTube.

To use Privacy Enhanced Mode, change the domain for the embed URL in your HTML from https://www.youtube.com to https://www.youtube-nocookie.com as shown in the following example:

Embed videos & playlists, YouTube Help

Make sure to clear any existing cookies for this website. Here is how to Manage cookies and website data in Safari on Mac.

If you notice any cookies on this website, please let me know by sending me the URL and the type of cookie you see.

Good riddance I say!

.-

]]>
Wed, 09 Jan 2019 00:00:00 +0200
Nothing but a dream https://qnoid.com/2019/01/07/Nothing-but-a-dream.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2019/01/07/Nothing-but-a-dream.html Approximately 5 minutes reading time

In 2017 I decided to leave London. I was suffering with anxiety and that feeling of not belonging had come to haunt me once again. Regardless, I was hopeful, positive, optimistic and was looking forward to the future. A future I very much had romanticised. I wanted to believe. That innate need to find my calling was still burning strong after all. That’s not to say the decision to leave was irrational or not weighted. To this day I believe it was the best decision I could have made given the circumstances. At the time it felt possible. In hindsight the chances of that future materialising were really really slim.

After years of disappointment with the software industry I wanted to take a different path. A path to personal growth, doing good, generating value and bringing positive change in this world. A way to find my place in the universe.

I love to create. I love that software development gives me the power to create. I don’t love software development in and of itself. I love software development that is purposeful. I love software development that satisfies a need. I love software development in the service of the people.

I also need to be able to make a living. Given that software development as a skill has the potential to earn you money I decided Windmill could help me with that. It was important that the two came hand in hand, doing something purposeful while also making a living.

Since I wasn’t looking for employment, I had to minimise expenses while living off my savings. I also wanted to eliminate distractions. I gave away, donated most of my personal belongings and went on my way with a suitcase, a carry on bag, my laptop and around £15k of savings heading east to Australia.

I travelled on a tourist visa, which granted me access for 3 months into the country. Once there, I would apply for a “Skilled independent visa”, which by the way takes 7-8 months to be granted from the application date. Effectively this visa gives you permanent stay and the right to work. In order to be invited to apply you need to accumulate a certain number of points. You get points based on your age, education, work experience, English language etc.

To prove knowledge of the English language I had to take a test on reading, writing, listening, speaking. This is a test that, even as a native speaker, you can’t just walk in and out expecting to get an almost perfect score. You have to study and prepare so that you are familiar with what will be asked of you. I didn’t and my anxiety got the better of me.

There is a quota on the number of visas issued each year. Everyone is sorted, descending, based on the number of points. Invitations are sent out starting from the top. If the number of applicants is high, someone that has even the minimum required of points may never get an invite. At the time, the effective minimum required me to score an almost perfect score on every subject in the English language. On top of that, the number of applicants was only getting higher which meant that no matter what, there was no way to accumulate the number of points required.

Now this created a very real situation that had to be dealt with. There was a high chance that sooner or later I had to leave the country. Suffering from what I would call mild depression at the time wasn’t helping either.

There was one more thing. The decision to visit Australia from the UK had to do with the fact that my partner has a dual citizenship. She too was on a path of self discovery and needed some time off to figure what she wanted to do next. It was also an opportunity for her to spend more time with family and friends after many years away. Having a home to stay while going through this transition in our lives was really really important. It provided stability and safety, gave us peace of mind.

Suffice to say it didn’t play out the way we both expected. By that time, it had been 3 months since we moved to Australia and 6 since we had left London. Yet again forced to make a decision not under the best of terms, with anxiety and depression looming.

We could stay in Australia, where the cost of living wouldn’t be significantly cheaper than London, where only my partner had the right to a full time job and a high risk of having to deal with a situation where I’ll be forced to leave the country.

Or retreat back to London, a city that I love dearly, but demands your full attention, with Brexit incoming, give up on our dreams, ignore the reasons that lead to our departure.

Lastly, move to Athens with lower cost of living, doubling down on our dreams, using the remaining savings we had left to rent and fully furnish an apartment.

Bruised and scarred, we opted to move to Athens.

Within 4 weeks we flew out of Australia and into a rented apartment. It turns out you can’t outrun anxiety and depression.-

]]>
Mon, 07 Jan 2019 00:00:00 +0200
Anxiety and Depression https://qnoid.com/2018/11/23/Anxiety-and-Depression.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2018/11/23/Anxiety-and-Depression.html Approximately 7 minutes reading time

For a very, very, very long time, I have been suffering primarily from anxiety and on separate occasions with depression. It may appear as is if comes and goes though I would describe it as dormant, lingering under the surface. About 6 months ago it slowly creeped up on me. This time it hit the hardest. It was crippling, unbearable and nasty.

Since about 6 weeks ago it feels like I am on a path of recovery. If you have been suffering from anxiety and depression I want to tell you that I feel you. It is not your fault. Take your time; hang in there; don’t be hard on yourself. You are not alone.

For everyone else who is close to someone with anxiety and depression as a friend, family, a co-worker, a boss, a member of society; this one is for you.

I know it is hard for you too. It is tough dealing with someone who looks into the void, seemingly unable to make even minimum effort, show any signs of care for the world. Who wishes to die. Who can be abrupt, angry and bitter. They don’t choose to be that way. They don’t want to live this way. They are drowning, screaming for help.

I want to share this with you. It comes from a personal experience while dealing with anxiety and depression. How I reacted and perceived behaviours and attitudes. What worked and didn’t work for me. It is not for the faint of heart.

Be gracious.

During that time, I was at my most vulnerable. Feeling exposed, hyper sensitive and on alert. The slightest form of confrontation felt like a warrant for a fight or flight response. An innocent joke, being judgemental, a comment on what I did, did not, had to or should not do, had a negative, disproportional impact on my mood and emotional state. Often I would shy away from discussions, events, situations in order to avoid it all.

I did not enjoy it when people picked on my behaviour, forced me to engage, asked me repeatedly how I was feeling, how long is “this” going to last, confronting me, coercing me to deal with “it”, man-up.

As long as people accepted that I wasn’t feeling good, were calm in their demeanour when I was upset and angry, game me space to breathe and didn’t force their expectations on me, they didn’t make things worse.

Be patient.

Everything was meaningless, worthless, a downward spiral into a well where there is absolutely zero joy and nothing worth doing.

Pushing me to get moving, asking me to do things, even more so on your time isn’t helping. Having an opinion as to what is meaningful or what I should be doing, isn’t good either.

Instead, it helped me cope when I was told to take as much time as I needed, was re-assured and was just let be.

Be loving.

There were times where a daunting feeling would weigh upon me in just a split second. A feeling of imminent doom. A darkness consuming me for no reason. I would start feeling terrified, especially in a crowd.

There are absolutely zero ways to reason about this.

A hug, a holding hand, telling me everything will be ok, taking me somewhere where I felt safe was the best way to handle it.

Be caring.

I was in no mood to cook, clean the house, make the bed or anything really. For reference, I have had a relatively high degree of independence since I was little (less than 10 years old) and have learned to live far and away from home, on my own, being self-sufficient since I turned 18.

Cooking a nice meal, cleaning and tidying up not only removed the worry but also created a nice environment to be living in. It may seem like it didn’t make a difference but it helped.

I would wake up in the middle of the night with panic attacks, gasping for air, feeling like I was dying.

Even though I rarely asked, I am much too proud and considerate, it made me feel better when someone woke up alongside to provide comfort, help me with breathing and calm me down.

Be fearless.

I wanted to die.

Even though I never made any attempts, I did have suicidal thoughts. It is a tough thing to hear. Even writing about it gives me the chills and makes me emotional.

Telling me to snap out of it only put more pressure on me. Telling me to take control made me think people weren’t listening. Downplaying it made me feel insignificant. Asking me how is this going to solve anything made me feel even more trapped and didn’t really present me with a way out.

Whoever was on the receiving end had to be fearless and calm. I needed empathy. I needed to hear how important I was to them.

Be level-headed.

There were days where I was willing to have a conversation about it and be more open. Still, talking about it would make me feel really uncomfortable, shaking, filled with adrenaline.

Pulling the rug from under my feet was not good. Presenting me with what-ifs’ or making me face reality wasn’t cool. “What if you get fired?”, “What if your partner leaves you?”, “You won’t have money to pay rent”, “You can’t keep doing this for long”.

All these only served to amplify my anxiety and fear. At times it would also make me angry and upset.

In this case, I am the one being moody with irrational fears. You need to be thinking clearly. Don’t take it personally. Don’t feel like you are being attacked. Do not take away whatever emotional support I am hanging on to. As hard as this situation may be, remember, this is not about you.

Ask people before you do anything that could upset them. e.g. like turning up on their doorstep unexpected or worse sending a public servant.

Be there.

I felt alone and at times I even felt abandoned. People were busy with work, their kids and family, their significant other or just needed time for themselves.

Not having people there for me to the extend that I needed them was the hardest to cope with. It wasn’t enough to just go to the movies once every month, to meet again after 2 weeks, to give me a 5 minute call to check on me or to talk via social media.

Being there regularly and often would have helped tremendously. Having somebody present was really important. Even when they did absolutely nothing but sit there on the same room as me. It gave me comfort.

People coming and going didn’t help either. It made me feel unworthy and made me think people didn’t care enough. Sending me a message of “Hey, is everything ok?” after weeks/months was not enough.

Having said all that, keep in mind that no matter of your good intentions chances are you alone can’t treat someone that suffers from anxiety and depression. It is not your job anyway so don’t feel the pressure to do so.

Each of you plays a different role, whether a childhood friend, a sibling, a partner, a parent. Being gracious, patient, loving, caring, fearless, level-headed and present will go a long way.

Final words.

This experience has given me the impression that overall we have no idea how to deal with people that suffer from depression and anxiety. Even worse, our behaviour at times can be detrimental to those suffering.

It also appears to me there is a real lack of knowledge on what depression or anxiety really is. People thought I was just having a bad day or I was just being bombastic.

It does not help that we don’t talk about it more. There seems to be a stigma and a taboo associated with mental illnesses that makes people want to shut down. Living in a fast paced, demanding, increasingly isolating world does not help either.

Dealing with anxiety and depression requires us to be accommodating, supportive and empathetic towards each other or else we risk stretching the social fabric that connects us too thin.-

While writing this post, I kept thinking of people suffering with anxiety and depression. Some that I know of, had the courage to come forward, write, share and be open about their struggle. At the time, it made me realise I am not alone, gave me hope. I also can’t help but think of the people that didn’t make it. How this post might have given them a voice. A lifeline.

In the US, 18.1% of the population every year suffers from anxiety disorder. Facts & Statistics, Anxiety and Depression Association of America

In Europe, 25% of the population suffer from depression or anxiety each year. Depression in Europe: facts and figures, World Health Organisation

]]>
Fri, 23 Nov 2018 00:00:00 +0200
Thinking of quitting the software industry https://qnoid.com/2016/12/01/Thinking-of-quitting-the-software-industry.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2016/12/01/Thinking-of-quitting-the-software-industry.html Approximately 12 minutes reading time

I love software development. I believe technology is an enabler.
I am also getting tired of this industry.

At the age of 36, beginning to feel tired about the lack of principles, lack of professionalism and education in the software industry.

My first computer was a Sinclair ZX 128K +2. I remember writing a few lines of BASIC but that was about it when it comes to programming. Owning an AMIGA didn’t make any difference as I would mostly play games on it. With a PC, I started tinkering with DOS, editing config.sys and autoexec.bat files, primarily to manage memory to, guess what, run games. With the arrival of Windows 95 I spent a lot of time understanding how hardware and software worked together, albeit at a high level. I would format the hard drive almost every week due to messing up the OS. The back of the PC never had its screws tight as I would open the case, move cards around PCI slots, change PATA cables, overlock the CPU, install better RAM, etc. Come to think of it, I was constantly optimising.

Have felt really bad in the past for not having a CompSci degree or for not being that good with algorithms. Please don’t fall for this.

In 1998 I went to study at the University of Sunderland towards a BEng Computer System Engineering degree. After the 1st year, I switched over to a BSc Information Technology. I believe I did it with a career prospect in mind.

"qnoid" is the name of a demo game that wrote in VB back in 1999 as a first year student at Sunderland University.

One of my first software development assignments was to build an application using Visual Basic. I wrote a simple loop to move a “spaceship” left and right while deflecting a ball within the window. I wasn’t given a high mark because the tutor assumed previous programming experience, hence the handicap. Funny.

Did you notice the sound effect when the game ends?

In 2001, I was offered a work placement at CERN. This is where I got my first real world experience in building software. I was thrown into Java EE, databases, XML and the web. I had no prior knowledge of any of these technologies whatsoever.

Had to read a lot, practice even more, write code, take notes, repeat.

My office at CERN My office at CERN. Books and notes all over the desk.

The following year, I went back to University to finish my studies. That year I was taught Java as a programming language. I remember the whole class (100+ students) struggling to understand basic principles. What is an object, what is a class, what makes it abstract, what is an interface, where and how are applicable. Even though I knew what the tutor was talking about, I too had trouble forming a well rounded understanding. Hell, I remember myself at the end of the year (“2 years” into Java), during the exam telling my tutor “I finally understand what an interface is”. Still, I was ignorant of the how, the where and the why.

I finished University and got a job as a “Java Web Developer” at an Internet Service Provider working mostly for projects related to the tourism industry (don’t ask). There was a project manager and a single developer. That would be me. A database admin was generally available to ask questions but not attached to a project. Same for a system admin. Also senior developers, colleagues working on other projects, willing to answer my ignorant questions.

Tho @Macropoulos is an amazing macro photographer, most knowledge that have of bash originates from him way back in 2004. Thank you Stavro.

I had no idea how to build software.

I knew how to hack code. Did I understand anything about software design? No. How to manage a growing codebase? No. How to deal with technical debt? No. Why I had seemingly decided to opt for design X, decided on Y or go with approach Z? Of course not.

My critical thinking in software development had developed very little all these years at University.

I remember constantly re-writing the codebase as I was going along in an effort to get a better understanding of how code fits together including trade-offs. I would print Java articles off the Internet to read every day.

My office at Forthnet Notice the printed article to my right. Yeap. Had a stack of these.

I discovered ORM, faced the “N+1 selects” problem and learned about caching. I had an urge to understand how things work, take them apart, examine, put it all back together.

I fondly remember the “Head First Design Patterns” book with its “There are no dumb questions” section. That book developed my critical thinking even more. Same goes for Effective Java.

I stayed for almost 4 years on that job, learning and practicing constantly. Around 2008, I also started teaching Java to final year University students. They were utterly lost, drawing parallels to my time at University 5 years ago, damn!

When started the iPhone Stanford course in 2009 didnt imagine giving a talk on a iOS conference right after @edog1203

I held 3 more roles as a Java Developer, until 2011, working in academia and research, the media industry, finance.

In the meantime, in September 2009, I started attending the iPhone Stanford course on iTunes and a year later started building verylargebox.

I went to work as an iOS Developer at NCR, lead the technical delivery of Tesco Bank’s Mobile Banking app for the iPhone and just recently as Head of Mobile at Soldo.

Throughout my career, every time I went into a new work environment, I’d come across a different mindset. Whether that was from developers, managers, directors; technical or not, involved in the software delivery process none the less.

Some didn’t believe in the merits of software testing or any software engineering principles, others in database normalisation or denormalization for that matter.

http://xkcd.com/1285/ Thrown in there, arguments of the “tab vs spaces” type.

Some felt strongly about procedural programming with very little structure, others fixating on functional and reactive programming.

If you come from an OO background and want to get a grasp on FP, one of my favourite talks from this year's @nsconf https://t.co/ej9p9NMqOV

Software development processes varying from non existing to very inefficient. Long discussion meetings, ad hoc phone calls, emails. No planning, no management, no roles, no ownership. It’s like watching amateur football where everyone chases the ball.

Learned a lot on project management and software delivery by working alongside @mattfarrugia in the past. Thank you Matt!

Why do so many people involved in the software industry believe that software development is subjective?

FWIW, this is what it's like to hire for a Lead iOS developer. Worse than the worse customer acquisition strategy.

candidates graph

The bar is low. As far as I can tell and see, education (higher education, online courses, training, schools) falls short in all of these below.

  • Academics are detached from the software industry.
  • Professionals who do know, do not necessarily make good teachers/mentors.
  • Not enough practicing your craft.
  • Teaching how to write code rather software development as a discipline.
  • Failing to develop critical thinking.

Whether they come from language, platform, hardware, network, interaction. Know the fundamentals, use critical judgment. Should be enough.

It does not help that the industry is still evolving. There are new paradigms, languages, platforms and challenges all the time. Still, by now we should have a solid foundation on which to start from and agree upon. People have very little interest in studying history when the technology always stays fresh and exciting. Repeating the same mistakes in the process, debating on issues that have already been settled, going down the same path in a different language, platform, domain.

The software industry is growing, without any signs of stopping any time soon, generating an unsatisfied demand for people. On top of that, there is money and there is plenty to go around.

Private investments, government funding or simply because software is driving businesses everywhere that are profitable there is very little understanding of how wasteful a software development process is, concern about the quality of people through the door, incentive to invest in the people.

Software is driving the economy and is unregulated.

Brilliant slide by @unclebobmartin at @xup_uk. Let this fictional front page suck in for a minute.

“Regulating pieces of software as if they were taxis or hotels makes no sense at all and wouldn’t help protect consumers or stimulate the economy,” said James Waterworth, vice-president of CCIA, a lobby group for the tech industry.

European court takes up the question: what is Uber? https://t.co/tbe0p2G0m0 — Financial Times (@FinancialTimes) November 28, 2016

So how is all that affecting the industry as a whole and me personally?

It is creating a culture of rockstars and ninjas and the chances of finding a good, solid team to deliver software are slim. We spend more time arguing, cranking code, boosting our egos, rather than focusing on solving problems, building software, growing personally, professionally and the industry as a whole.

It is considered acceptable not to be a professional as long as you produce software, regardless of whether it’s delayed, of questionable quality as long as it satisfies the business needs. It’s all been factored in the operating cost for the company.

This is an industry where mediocracy rules with no sense of collectiveness and no-one being held personally accountable in their profession. Salaries are going up, no-one is grabbing us by the collar and software is still eating the world.

This is an industry where I am finding it hard to grow, do good, generate value and bring positive change in this world.

Building the perfect team @nytimes is worth a read; amusing that Google was looking in data. https://t.co/EmZrLoFQ1B

]]>
Thu, 01 Dec 2016 00:00:00 +0200
Timing's a bitch https://qnoid.com/2016/10/17/Timings-a-bitch.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2016/10/17/Timings-a-bitch.html

After 5 years in Scotland the time has come to move on. Starting tomorrow will be based in London. Looking for both a flat and a role.

It was my first Monday in London. Had arrived only 3 days ago, on a train to King’s Cross from Edinburgh.

Less than a week ago, I had put the word out that I am moving to London. I was overwhelmed by the number of calls and emails. An ex googler with a “well funded” startup building a “hyperlocal” app. A guy with “an idea”, having applied to a Y Combinator fellowship programme looking for a technical founder. Someone working on “some really exciting things” looking for a CTO. A corporation building a “digital team”. VP of Engineering roles in well known startups. Recruiters, HR specialists and “talent people”.

On the 3rd of August 2015, 13:16, I got an email that stood out from the crowd right away. The founder introduced himself, let me know how he had found my details, described the startup’s goal, its target market, funding and size. On top of that, he said what got him interested in “me”. Why he thought I was the man for the job. Finally, he told me he is happy to talk more over Skype if I’m interested.

During the Skype call, I basically “interviewed” the founder. On a call that lasted about 2 hours, he spent 90 minutes answering any questions I had. Finally, I said:

-“So, do you have any questions for me?”
-“I know all about you”, he said.

I am now thinking, ok the guy has seen a CV, how much can he really tell just by looking at a CV.

-“I have read your posts, watched your talks, etc.”

A few months later I would notice his email on the database of verylargebox. He had also used my product.

We arranged to meet in Rome along with the CTO and the CMO. I will just say that it was intense! The whole thing started at 4pm (flew out of London at 09:05) and I went back to my room at 2 in the morning. We talked product, we talked delivery, we talked security, we talked business, processes, culture, I loved it!

A month later I started working at Soldo with two primary responsibilities. Establish a mobile team in London and deliver version 2.0 for both the iOS and Android app.

Ecstatic to be joining a FinTech startup as head of mobile. A great honour to have this role offered. Can't wait to make things happen.

Delivering quality software

Delivering quality software takes more than a good team. Everyone involved must possess a collective understanding on how to deliver. You need a strategy. You must educate people, put processes in place, create habits, establish communication channels. People must want the change, asking for and willing to go through it.

It takes a lot of trust, faith, insight, sensibility, intelligence from anyone to let you “have it your way”. There are four stages the person has to go through with you.

  1. Acknowledging there is a problem. It is possible that what you are talking about isn’t even on their radar.

  2. Understanding how you are trying to solve it. This can prove challenging if you don’t share the same background, knowledge, expertise, understanding.

  3. Giving you the go ahead. Acknowledging and understanding isn’t necessarily enough to give you the green light to proceed. There are priorities, availability and on occasion politics. This could lead to months of waiting time to never happening.

  4. Going out of their way to make it happen. This requires a change on their part. Not just operational but a change in behaviour and attitude.

Having planted the seeds, I was now ready to start hiring a team.

At @soldo have found people with sensibility, that are inclusive, open to discuss, willing to change & do better. Wish you could see this.

Hiring is hard.

It took 3 months just to find a “junior” iOS Developer and 5 months for a “lead” one. Damn! There are many contributing factors to this.

  • Quality of candidates is low. Have already written on the subject.
  • Soldo as a workplace was not on the developers’ radar. Even personally reaching out to developers didn’t make a difference. When people have so much choice they will go for the one that ticks all the boxes. Working for a startup that you haven’t heard of is not your natural first choice.
  • Lack of engineering team in London. Unfortunately, Soldo does not have an engineering team based in London. This makes it harder to attract talent. You must be part of the community, it does not happen overnight and more than one man need to be up for it.

The numbers below are over a period of 8 months.

Timing

Eventually it became clear that it was not happening. Building a startup, your priority is to find product/market fit while remaining sustainable.

Soldo already had an iOS and Android app that served this purpose. Building version 2.0 however important, eventually was not a priority in the grand scheme of things.

I have decided to leave Soldo at the end of the month. Still, I am fortunate to have been part of the Soldo family for over a year.

Regardless, the overwhelming acknowledgement that I have received from everyone at Soldo is unlike anything I have received so far in my life.

I can not thank you enough.

Soldo’s future is indeed bright.

]]>
Mon, 17 Oct 2016 00:00:00 +0200
A primer in HTTP caching and its native support by iOS https://qnoid.com/2016/04/10/A-primer-in-HTTP-caching-and-its-native-support-by-iOS.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2016/04/10/A-primer-in-HTTP-caching-and-its-native-support-by-iOS.html Introduction

This post is based on Xcode 7.3 and iOS 9.3

All the information in this post can be found in the iOS documentation but the support for computing if a response is “fresh”.

This post pieces all the information together to form a primer in HTTP caching and its native support by iOS. This is by no means an exhaustive post on HTTP caching on iOS.

Still, this is useful if you want to understand what iOS gives you out of the box, especially if you are using an Amazon S3 via HTTP. (i.e. to store and retrieve images).

What does the iOS documentation say

NSURLSession uses the NSURLSessionConfiguration.defaultSessionConfiguration, which uses the NSURLCache.sharedCached for its URLCache.

From NSURLSession’s documentation,

For a data task, the NSURLSession object may call the delegate’s URLSession:dataTask:willCacheResponse:completionHandler: method. Your app should then decide whether to allow caching. If you do not implement this method, the default behavior is to use the caching policy specified in the session’s configuration object.

From NSURLSessionConfiguration’s documentation

Set this property to one of the constants defined in NSURLRequestCachePolicy to specify whether the cache policy should depend on expiration dates and age, whether the cache should be disabled entirely, and whether the server should be contacted to determine if the content has changed since it was last requested.

The default value is NSURLRequestUseProtocolCachePolicy.

Figure 1 NSURLRequestUseProtocolCachePolicy decision tree for HTTP and HTTPS,

NSURLRequestUseProtocolCachePolicy decision tree for HTTP and HTTPS Copyright © 2016 Apple Inc. All rights reserved. Updated: 2015-10-06

Briefly put:

  1. If a cached response does not exist for the request, the URL loading system fetches the data from the originating source.
  2. Otherwise, if the cached response does not indicate that it must be revalidated every time, and if the cached response is not stale (past its expiration date), the URL loading system returns the cached response.
  3. If the cached response is stale or requires revalidation, the URL loading system makes a HEAD request to the originating source to see if the resource has changed. If so, the URL loading system fetches the data from the originating source. Otherwise, it returns the cached response.

How-to

Let’s see it in action. Given this sample code,

        let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
        
        let sessionDataTask = session.dataTaskWithURL((NSURL(string: "http://qnoid.com/assets/images/avatar.jpg")!)) { [weak imageView = self.imageView] data, _, _ in
            
            guard let _imageView = imageView else {
                return
            }
            
            dispatch_async(dispatch_get_main_queue()){
                _imageView.image = UIImage(data: data!)
            }

        }
        
        sessionDataTask.resume()

This is the HTTP trace (mitmproxy trace)

enter image description here

Notice that this response (i.e. coming from an AWS S3 bucket, “Server: AmazonS3”) has an ETag but only a Last-Modified header.

Let’s see if NSURLCache has stored both the Etag and the Last-Modified headers. In Xcode, press SHIFT+CMD+2 to open “Devices”.

Under “Installed Apps” select the app, right click, “Download Container…”

enter image description here

Open the terminal, navigate to the location of the container. Use grep to search. Bash will find a string even if it’s inside a binary. Et voilà!

enter image description here

With the NSURLRequestUseProtocolCachePolicy decision tree and the response headers in mind, let’s see how iOS uses this information to decide whether to use a cached response or not.

This response does not “require revalidation every time” (e.g. a header of “Cache-Control: must-revalidate” is not present) so iOS will check if “response stale”. According to the documentation above, iOS considers a respone stale if it’s past its expiration date. The server however does not specify an explicit expiration time, “using either the Expires header, or the max-age directive of the Cache-Control header.” (13.2.1 Server-Specified Expiration)

When Server-Specified expiration is not available, HTTP states that “In order to decide whether a response is fresh or stale, we need to compare its freshness lifetime to its age”.
13.2.4 Expiration Calculations, Heuristic Expiration

However, this is an implementation detail as “the cache MAY compute a freshness lifetime using a heuristic”. The spec goes on to suggest an algorithm like so.

Also, if the response does have a Last-Modified time, the heuristic expiration value SHOULD be no more than some fraction of the interval since that time. A typical setting of this fraction might be 10%.

Turns out the cache used in NSURLSession does compute a fresness lifetime (Apple Developer Forums, an account is required), using the algorithm suggested in the spec.

Using the above response as an example, let’s calculate the freshness_lifetime.

  freshness_lifetime = (date_value - last_modified) * 10% =>
  
  ([Sat, 09 Apr 2016 10:26:51 GMT] - [Sun, 17 Jan 2016 14:15:33 GMT]) * 10% =>
  
  [82 days, 19 hours, 11 minutes and 18 seconds] * 10% =>
  7,153,878 * 10% = 715388 seconds = 8 days 6 hours 43 minutes 8 seconds

“The calculation to determine if a response has expired is quite simple:”

  response_is_fresh = (freshness_lifetime > current_age)

where current age can be loosely calculated as

current_age = now - date_value

So the response will go stale in 8 days 6 hours 43 minutes 8 seconds from the date it was put in the cache.

With all that in mind, let’s go through the NSURLRequestUseProtocolCachePolicy decision tree from the beginning.

  1. The request is made
  2. “Cached response exists”?
    1. No
    2. “Fetch the response”
    3. Put it in the cache along with the “Date, “Last-Modified” and “Etag” headers

A day has passed.

  1. The request is made
  2. “Cached response exists”?
    1. Yes
    2. “Require revalidation every time?”
      1. No
      2. “Response stale”?
        1. No
        2. “Return the cached response”

In case of a non stale (i.e. fresh) response, no request is made as the response is returned from the local cache. Don’t expect to see a network call. That’s good!

8 days 6 hours 43 minutes 9 seconds have passed.

  1. The request is made
  2. “Cached response exists”?
    1. Yes
    2. “Require revalidation every time?”
      1. No
      2. “Response stale”?
        1. Yes
        2. “Issue a HEAD* request”
        3. “Changed?”
          1. No
          2. “Return the cached response”

Notice how iOS issues a GET rather than a HEAD method. AFAICS, this is to avoid issuing two network requests in order to fetch the resource.

enter image description here

In the case of a 304 Not Modified, there is no content as the response will be returned from the local cache.

enter image description here

Conclusion

NSURLSession, NSURLSessionConfiguration and NSURLCache support caching of entity tag validators (aka ETag) and cache invalidation based on how “fresh” a resource is.

A few notes.

  • Once a response has been added in the cache; the longer the time since “Last-Modified”, the longer it will take to become stale. e.g.

    • “Last-Modified” in the last 24 hours, stale in ~2.4 hours
    • “Last-Modified” in the last 30 days, stale in 3 days.
    • “Last-Modified” in the last 180 days, stale in 18 days.
  • The later a response is added to the cache; the longer it will take to become stale.

  • You have no direct control when the cache expires; strictly speaking with only a “Last-Modified” header you have no control over when the cache updates. e.g. Once a resource has been cached, if the resource is updated on the server, it will only be fetched by iOS only when the cached response becomes stale.

Consider all the above before deciding whether the default configuration supports your needs.

Source code

Kudos

mitmproxy

Further reading

13 Caching in HTTP, Hypertext Transfer Protocol – HTTP/1.1

]]>
Sun, 10 Apr 2016 00:00:00 +0200
Diversity and Inclusion https://qnoid.com/2016/03/28/Diversity-and-Inclusion.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2016/03/28/Diversity-and-Inclusion.html Approximately 7’39’’ reading time

One of the things I have struggled with in the past is this.

How do you know if an individual has a well rounded understanding of an issue when stating their view?

This gets more difficult when your view is different.

How do you know an individual has factored in your view when stating theirs?

How do you know others, hearing that individual’s view, understand that this view might or might not have taken into account yours?

You don’t.

The only way to know is to put you in a room. You, that individual and all the others; so that every one states their view.

At the end,

  • Every individual in that room has a well rounded understanding.
  • Every individual has now factored in your view.
  • Every individual knows that every view has been factored in.

This is on the basis that everyone is acting out of duty.

You might argue that just because everyone has stated their view, it does not mean that they have now factored in yours.

Even more so when an individual still holds the same view. Seemingly not factoring in yours.

The Internet

As the internet becomes more social, people are connected more than ever before. Despite being more connected than ever, the means by which views are communicated fall short overall.

Humans have long used writings to communicate.

Rosetta Stone
Rosetta Stone © Hans Hillewaert, via Wikimedia Commons

And images.

Cueva Manos
Cueva Manos By Mariano (Own work), via Wikimedia Commons

Exploration and trade over the centuries exposed people to a plethora of customs, traditions, sciences and knowledge.

Even today, travelling to a foreign country is not enough to give you a good understanding of its society. You need to spend years before you can fully grasp, appreciate and aknowledge its contributions and shortcomings to this world.

The internet has evolved at an extreme pace but at the same time is failing to bind us together. Breaking down physical barriers, faster than legislation can adjust and the means of communication can mature.

No matter how primitive in nature, greetings, gestures, facial expressions, body language and the tone of our voice have helped us come together as species.

Origin of language

Virtual Reality “I just joined Samsung to launch their new Galaxy smartphones and talk about the future of virtual reality.“ - Mark Zuckerberg

Social media has an every increasing role and a responsibility to boot in bringing people together.

As an example, Twitter fails to facilitate a round table discussion and is prone to the Echo chamber effect.

An individual’s high number of followers amplifies their influence at an exponential rate. This is a powerful way to spread your view or publicly shame, but can easily lead to peer pressure, used as means of coercion and bullying.

You should think twice before using a retweet like a whistle to get the attention of the angry mob, opting for Ochlocracy in the process.

The Internet is still in its infant stage. You need to be respectful, demonstrate empathy, be mindful of cultural differences, communication bariers, mental and emotional state else you risk ousting people.

The importance of diversity and inclusion

Sounds contradictory that access to vast information leads to biased people with less reasoning. Critical thinking goes out of the window.

When you support a cause or you are personally affected, your views can easily turn to beliefs. Beliefs that you fight hard for and feel strongly about.

Beliefs are not inheritely bad. Beliefs give a sense of purpose, influence, provide stability to enable progress. Don’t challenge your beliefs for too long though and you risk stagnation.

By merely believing that a view holds true, a view is right, without allowing for a debate, you risk more than “being wrong”.

Look for and embrace your polar opposites in life. Those who will challenge your thinking, critical of your work. Will only make you better.

You risk applying it on a case where it does not hold. Potentially failing to support that cause you believe so strongly about.

You risk creating prejudice by enforcing your beliefs on another individual.

You risk making an individual’s view biased or worse, driven by fear.

You risk not being exposed to the diversity of views that can shape your understanding.

A view of an individual comes from their experiences. Experiences that are shaped by life and also interpreted differently. Views that vary based on culture, race, social status and individuality.

Culture shock much? Some Syrian newcomers are staying at a hotel where the #VancouFur furry convention is going on. pic.twitter.com/rPi6HN72Lz — Ziya Tong (@ziyatong) March 8, 2016

The world is shaped today from all these views coming together, being challenged, influenced, co-existing.

To deny those views is to deny our freedom.

It is a collective effort that lies with you

While making sure we don’t kill each other in the process or become extinct. A long time of being civilised while in need to be primitive.

Going back to my original question.

How do you know if an individual has a well rounded understanding of an issue when stating their view?

I now think of it like this.

How do you ensure an individual has a well rounded understanding of an issue when stating their view?

As an individual you have a responsibility to be mindful and careful when you communicate your view. Avoid being dogmatic, polarising.

Given that your goal is to educate then do so by having a discussion and explain to an individual your view. This isn’t about being politically correct or restraining. This is about being mindful of differences and aware of context.

Rather than assuming or letting your bias kick in, establish a context first by asking the “right” questions. Listen. Process. This will give you both a better understanding and increased chances to make a change.

Spread views that have the above qualities.
Look for views that have the above qualities.

Even though information is more accessible than ever, getting an overall understanding to form an opinion on matters is hard.

Protect views that are being oppressed. Speak up and defend every individual’s right to their view. A world where having a different view is heresy is no different that a world with a single view.

Consider how the media can shape a view and people with a social status can influence.

Consider how companies operate, politicians debate and countries legislate.

Consider the current issues that the world is facing today.

Challenge.

Even this article, now that you have finished reading it. Understand how it applies, what is not tackling, why and where it falls short by omission. Share your view.

We have evolved because of diversity.
We have come this far by being inclusive.

]]>
Mon, 28 Mar 2016 00:00:00 +0200
We need to raise the bar on software development https://qnoid.com/2016/01/14/We-need-to-raise-the-bar-on-software-development.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2016/01/14/We-need-to-raise-the-bar-on-software-development.html 3 Sep 2016: Have reworded some of the questions after noticing I had to followup with an explanation. Have also added 15 more that IMO an experienced iOS developer should know.

Been heavily involved in the hiring process, evaluating CVs, asking technical questions, creating coding exercises, interviewed developers.

In the past, I used to teach object oriented programming in Java. Mainly to University students who were struggling in class and wanted some outside help. What I found as the main reason people were failing was they didn’t have a solid understanding of the basic principles of software engineering.

In the last 2 permanent job roles, in my long career, I have been heavily involved in the hiring process. Writing job descriptions, evaluating CVs, screening candidates by asking technical questions, going through coding exercises, interviewing developers for both cultural and technical fit.

You know something isn’t right when out of tens of CVs, only a handful pass the screening phase and a low single digit get an offer. It’s a funnel, a heartbreaking one.

The screening phase is really just a list of straight forward technical questions that you would expect everyone applying for the role to know. Contractors with £500 day rates, people looking for a permanent role, “juniors”.

For iOS, there are questions like this one:

Q: What does ARC stand for, how does it work and what are the benefits of using it?
A: Automatic Reference Counting. It works by inserting “retain” and “release” calls to objects, at compile time, where required with the benefit of “knowing” things like scope and usage. Effectively, it provides memory management for the trivial cases.

and another one:

Q: What is a retain cycle? How would you avoid it?
A: A retain cycle occurs when two instances have a “strong” reference to each other. You can avoid it by declaring one as “weak”.

To be clear. These questions are meant to be answered briefly, be complete and precise enough to demonstrate basic understanding. They are not in depth, not tricky, not to have a debate and definitely don’t prove much on senior status. Listening to how an answer is formulated says a lot about a canidate’s understanding, knowledge and confidence.

By asking questions on the fundamentals, it is easy to tell when people have a fixed, narrow understanding of these. A typical answer that keeps coming up when asking “Where would you use a protocol?” is “In a table view.”. (thinking of its datasource)

We all have our own share of responsibility for this.

As a manager, for asking your development team “to go faster” and “get things done”. Measure how long software delivery takes. Identify where and why you are wasting time; restructure. Give your developers room to breath, support them to grow professionally. You need to let them take their time to read that chapter in the book, to watch that conference talk, to practice what they know. Factor that in the time it takes to deliver software.

As a digital agency, for not educating your customer on technical debt, not managing expectations, risk and priorities. At least deliver quality software. Don’t just please the customer for the paycheque.

As an experienced developer, for not providing estimates, speaking up on technical debt, raising awareness on how to deliver quality software. You need to let your manager know how long implementing that requirement will take to get it done. That includes testing; and documentation; and every other business requirement. i.e. localisation, accessibility support. If you don’t have the faintest idea, ask for time to do your research.

As a teacher/mentor/knowledge bearer, for showing lack of responsibility, being careless, skipping over the details, not dedicating time to address questions. Explain the “why” and show the “how”. Spend the time and effort to properly explain. Develop people’s critical thinking. Teach them how to think for themselves.

Finally you, the developer, study, practice, challenge, repeat. Read books, attend courses. Get structured, formal education. Watch a talk on the subject. Preferably from the source. For iOS, that’s WWDC. Use ASCIIwwdc to search.

Read blogs, watch talks and keep an eye for references, bibliography, solid arguments. Mike Ash, nsconf, NSScotland, NSSpain, iosdevweekly

Follow subject experts on Twitter. Ask your team to code review.

Be critical! challenge! ask questions, compare and contract your own understanding.

A final year student from @univofstandrews impressed me the most with his iOS skills at @milkroundabout. Be curious, read up and write code!

In my opinion, here are 25 questions you need to know.

  1. What does ARC stand for, how does it work and what are the benefits of using it?
  2. What is a retain cycle? How would you avoid it?
  3. What is a weak and what is a strong reference?
  4. What would you use an enum for?
  5. What is a protocol useful for?
  6. What is a protocol extension useful for?
  7. What is the delegate pattern? Give an example.
  8. What is a block?
  9. How can blocks create a retain cycle? How do you avoid it?
  10. What would you use a NSNotification for?
  11. What are the basic navigation concepts in iOS? Can you describe where you would use each?
  12. What is a UIViewController responsible for? How would you typically implement one?
  13. What is an IBOutlet and an IBAction?
  14. Why is a UITableView good at displaying a long list of items?
  15. What is auto-layout? Where does it help?
  16. What is a storyboard? What is a xib? Where would you use each?
  17. Under what scenario would you choose a xib over code or vice versa?
  18. What is a file’s owner?
  19. What is a unit test?
  20. What is a precondition, a postcondition, an assertion?
  21. What are the four most common HTTP verbs related to a RESTful web service?
  22. Give a brief description of what a RESTful webservice is.
  23. What is JSON?
  24. How do you know that a network request was successful?
  25. What is a network timeout?

Advanced

  1. What do you have to be mindful of when testing an asynchronous network call?
  2. What is the risk in blocking the main thread when performing a lengthy operation such as network access or a heavy computation?
  3. What is the difference between a NSOperationQueue and a dispatch_queue? Describe a scenario where you would use each.
  4. What is the difference between dispatch_async and dispatch_sync? Describe a scenario where you would use each.
  5. What are dispatch_group(s) useful for? Describe a scenario where you would use them.
  6. What is a ”Zombie object"? How would you use it?
  7. What is a memory leak?
  8. What is unbounded memory growth?
  9. What is an autorelease pool? Describe a scenario where you would use one.
  10. Given that an app uses a lot of memory, give some general advice on how to bring overall usage down.
  11. What are the risks associated with high memory usage?
  12. What is a memory warning? How would you typically handle it?
  13. How would you deal with a sudden spike in memory usage?
  14. What are the risks of a high CPU usage?
  15. How would you deal with bursts in CPU usage?

Related talks

]]>
Thu, 14 Jan 2016 00:00:00 +0200
To be celebrated as a human https://qnoid.com/2015/12/09/To-be-celebrated-as-a-human.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2015/12/09/To-be-celebrated-as-a-human.html

Grandma’s death made me realise that you don’t have to achieve perfection in order to be celebrated as a human; what a weight to have lifted.

Grandma1 was stubborn.

Born in the thirties of the 20th century, she was married and had 3 children. She looked after her parents as they grew older, raised her niece and her firstborn grandson. A spouse till her mid fifties when her husband abandoned her.

At that age she got a job at Tupperware to make ends meet.

Through her work she got to travel to London, attend events at the Hilton Athens Hotel (a lot of the time with her grandson by her side to look after) was appointed team leader and given a corporate car.

She started her life in her fifties and at the age of 81, at her funeral, every single person was standing up and her colleagues donated money to charity on her name.

People again and again praised her great mind, reached out to her for advice and admired how she could hold a conversation about any subject.

I do wonder and hope to achieve, if only at the slightest, the greatness of this woman.

Who I am today, I owe a great deal to her.


  1. The last child, youngest daughter of a family coming from Trabzon and Çeşme and moved to Corinth↩︎

]]>
Wed, 09 Dec 2015 00:00:00 +0200
The price of freedom https://qnoid.com/2015/02/25/The-price-of-freedom.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2015/02/25/The-price-of-freedom.html John Locke in his work on political philosophy, defines the “the state of nature”; as in “the state that all people are in naturally”:

“People in this state do not have to ask permission to act or depend on the will of others to arrange matters on their behalf.” - State of nature, Second Treatise: John Lock, 1689

However, the second you are born, you give a tacit consent to live in a society and enter into a “Social contract”; emphasis mine.

Social contract arguments typically posit that individuals have consented, either explicitly or tacitly, to surrender some of their freedoms and submit to the authority of the ruler or magistrate (or to the decision of a majority), in exchange for protection of their remaining rights.

With that contract you effectively trade that freedom in exchange to feel safe.

As you come into this world, your family is there to nurture you. You are fed, learn to walk, taught how to speak and in exchange you ask for permission whenever you wish to take matters in your own hands. You are slowly being conditioned on your way to integrate with society. If you happen to be lucky in the “ovarian lottery” - you will be granted access to food, water and given basic human rights such as the right to education.

As you leave the safety of your family and begin to integrate with society, you have to contribute your worth to the common welfare. It is that duty that imposes a civic virtue in order to claim your right to society; emphasis mine.

Civic virtue is the cultivation of habits and personal living that are claimed to be important for the success of community. Civic virtue is also the dedication of citizens to the common welfare of their community even at the cost of their individual interests.

It is the price of admission. The price you pay to feel safe in the community else risk ostracism.

Living in a civil society, means you now greatly depend on the will of others before you take action. While that holds true for everyone, it greatly depends on your social status.

Since by civic virtue you are dedicated to the common welfare of society and you earn your social status based on your contribution then how much individual freedom do you really have left to pursue your individual interests?

A greedy society, a society that has an appetite solely driven by its desire to maximise its welfare, puts at risk that very social contract that asks people to enter into.

“…no one knows his place in society, his class position or social status, nor does anyone know his fortune in the distribution of natural assets and abilities, his intelligence, strength, and the like.” - A theory of Justice: John Bordley Rawls, 1971

I am lucky to be born in Europe. I am fortunate not to be poor. I am privileged to have received higher education. I am favoured to be working in IT.

Yet, it took me 35 years to be able to buy 9 months of “some” freedom to “not have to ask permission to act or depend on the will of others to arrange matters”.

It has been hard to get here and as I look forward, being part of a greedy society that always asks for something in return is not a society that is worth having.

I don’t want to live in a society that recklessly sacrifices individual freedom, where as an individual you don’t really matter unless you always have something to offer, a society that constantly asks for something in return, that treats every human interaction as a transaction, that instills fear of losing social status. I want to live in a society that puts its faith in people and supports them to do their best. A society that contributes in the making of great people so that in itself can achieve greatness.

]]>
Wed, 25 Feb 2015 00:00:00 +0200
Bitwink https://qnoid.com/2014/08/28/Bitwink.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2014/08/28/Bitwink.html For the last 7 months had the chance of working alongside members of the Bitwink team. Bitwink does iOS development and is available for hire in Edinburgh, Scotland.

Out of the whole team, it was @gordonchristie, @adurdin and @mattfarrugia that spend the time with. In case you haven’t heard of them before, Gordon Christie is “that guy” that built the hugely popular Edinbus. Andy Durdin every now and then writes about the quirks in games and is the man behind @GameDevEd. Matt Farrugia gave an awesome talk at NSScotland in 2013 on “How to get hired by Black Pixel” and is the Bitwink owner. You’ll find them hanging around macmacdev every 2nd Thursday of the month.

Now, all too often you’ll read on people’s CVs and companies’ portfolios how they can deliver software on time, on budget and to the complete satisfaction of everyone involved, so let’s get this out of the way first.

Building quality software is HARD!

You have to manage milestones, risk and priorities. You have to give estimates on how long things will take and revise them. You have to understand what you are building, step in, take responsibility, let prejudices aside and trust your team. You have to communicate effectively, within your team, across teams, suppliers and stakeholders. You have to keep an eye on code quality, review, make compromises. You have to take quite a beating and still deliver.

You need good men.

Gordon is thoughtful, brings sense where there is madness and he is the voice of reason. He is methodical, his every move is a well calculated one.

Andy is one hell of a software engineer. He is relentless and will deal with whatever software problem you throw his way. He always finds a way to get things done.

Matt brings it all together. He knows his people very well. How they think, what makes them tick, what’s required for them to perform at their best. He is diligent, measured, focused. He knows how to deliver software. He is a leader.

These guys are no ninjas or rockstars; the are smart and know how to do their job. They are Professionals.

Gordon, Andy, Matt, I have learned so much working alongside you and have come out a better man and a better developer. It was an honour and a privilege to work with you and I am grateful. Thank you.

]]>
Thu, 28 Aug 2014 00:00:00 +0200
Why arent we password free yet? https://qnoid.com/2014/02/22/Why-arent-we-password-free-yet.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2014/02/22/Why-arent-we-password-free-yet.html

By using a password, you actually give up security control and risk your users' data. Stop asking for one now.

Turns out if you buy a new iPhone, you are required to answer your security questions before making any purchases on the App Store with your Apple ID (Sunday, 22 December 2013 10:52). The password that you have already set up is not enough to verify your identity in this scenario.

Verification Required

Security Questions

Security Confirmation
Because this is the first time making a purchase on this device, you must verify your identity by answering the following questions before you can complete your purchase. If you have forgotten your answers, contact Customer Support

Not sure why Apple believes a password might have been compromised with the new device. Usually security questions are used as means to reset a password in case you have forgotten it. It’s an alternative way to identify who you are. Unfortunately not as convenient as the password.

Security questions are usually more than one (personally have seen up to 8!) and the user rarely gets to choose what they are. Since their purpose is to identify the user, they are naturally “trying” to touch on personal, private data (i.e. favourite actor, personal hero, childhood nickname). Effectively the user is coerced into answering them, all too often choosing arbitrary answers via association or totally random characters. Because they are created at the same time the account is set up and rarely used the chances of forgetting them increases with every day passing by. In this case that was about 2 years ago.

So what if you do not answer?

You did not provide the correct answer to one or both of your security questions. If you continue to provide incorrect answers, your Apple ID will be locked and you will be unable to make any purchases while it remains locked.

Security Questions

Notice the

If you have forgotten your answers, contact Customer Support.

If you fail to recall your security questions, then a combination of things like your date of birth, address, and 4 last digits of your credit card as entered in your profile is enough to prove who you are.

By the way, the account to this date has not been used to make a purchase on the App Store.

Have you forgotten your password?

Another way of identifying a user is via an email. The idea being that the user who set an email for her account, has secure and sole access to her email.

Let’s see how that looks. An anonymous user requests to identify via email in order to access her account. That is a single prompt for her email address.

Forgotten Password

The assumption is that the user owns the email of her account, hence plausible to identify her.

The user enters her email,

Email link

the email contains a link that the user needs to follow to identify herself,

Verify email

since the user has identified, can also create a new password to secure her account,

Create new password

and access it.

Logged In

Take a look at your stats and see how many of your users are using the forgotten password link or the percentage of users calling in due to having forgotten their password.

The leak

The truth is, no matter how secure a password can be, your users are most likely reusing them. As a result, security is no longer under your control.

Back in October 2013, Adobe’s customers IDs and encrypted passwords were compromised. Less than 2 months later, Adobe’s database of passwords was used to hack Github. Essentially, Adobe’s leak compromised Github. Oh, let’s not forget plain text offenders.

Enter password policies

Password policies are a best effort to keep passwords secure and as a side effect protect against compromises like Adobe’s. However, a password policy can’t guarantee that the password will be unique to your service and passwords that use common character substitution are equally vulnerable. Also, enforcing a strong policy can potentially harm user acquisition and will likely increase the chances of a user forgetting her password.

You don’t need a password

Let’s look back to the “forgotten password” cycle.

  1. An anonymous user wants to access her account.
  2. User asks to identify via email (forgotten password).
  3. User enters her email.
  4. User receives a verification link.
  5. User authenticates by following that verification link.
  6. User creates password.
  7. User is logged in.

Since most services now use long lived sessions, the user will rarely have to enter her password again. Yet just by using a password your service is vulnerable to attacks like Github’s.

Let’s think of better ways to identify a user instead

Email isn’t designed for user identification. Google just recently bought SlickLogin. SlickLogin uses a distinct sound to identify a user. Apple already uses a fingerprint to identify a user on an iPhone 5S.

On mobile, you can use residence based authentication.

Every second you keep a password database around, you are putting your data and others’ at risk. Stop asking your users to create a password.

Focus your efforts on how to best identify a user.

Update: Some metrics provided by Luke Wroblewski on passwords back in January 2012 and statistics on top three passwords. Some highlights:

  • 86% of U.S. companies use password authentication.
  • 70% of people do not use a unique password for each Web site.
  • Around 82% of people have forgotten a password used on a Web site.
  • Password recovery is the number one request to help desks for intranets that don’t have single sign-on portal capabilities. 2/3 of people with leaked accounts at both Sony and Gawker reused their passwords on both sites.
]]>
Sat, 22 Feb 2014 00:00:00 +0200
We need to talk about fizzbuzz https://qnoid.com/2013/12/20/We-need-to-talk-about-fizzbuzz.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2013/12/20/We-need-to-talk-about-fizzbuzz.html Originally wrote “Why Can’t Programmers.. Design Software?” on forrst. It spur a discussion that made some people think about software design; that was the goal.

Wow. Well, that is certainly the most enterprisey Java approach to the problem I’ve ever seen. It seems a bit excessive. Aiming for abstraction at the cost of readability.

Overengineering is how I’d call this. Though the specific use-case is an obvious abuse, the general idea behind isn’t that bad…

I think that this is a fantastic approach. Could someone call this excessive or overengineering? Of course, in the context of FizzBuzz. However, not in the context of software design in general. Far to often we (and I’m more than guilty of this) jam tons of lines of procedural code inside of our classes without thinking of reuse or any sort of abstraction. The point of this post (as far as I can tell, correct me if I’m wrong, @qnoid) is to actually think about what you’re doing, not just blindly build a solution as fast and in as few lines as possible.

Lately have been noticing a lot of traffic coming from @Something_Awful. Felt like writing a follow up because as time goes by, even more developers will come across the post and totally miss the point.

  • Q: Should you write an implementation of fizzbuzz in this way?
  • A: No.
  • Q: Should you shoehorn OO arbitrarily to a software design?
  • A: No.

Personally, like to draw the design early. It helps guide developers and show intent.
Is there a risk of over engineering? Absolutely. Even though grammar does help with OO there are concepts that give little room for doubt when it comes to designing software in OO (i.e. object lifecycles). At the end of the day it comes down to experience.

Here is another fizzbuzz implementation that really adds something new to the table.
Not a clue what “deterministic finite automata” is, but it sounds cool.

]]>
Fri, 20 Dec 2013 00:00:00 +0200
On sacrifices https://qnoid.com/2013/08/11/On-sacrifices.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2013/08/11/On-sacrifices.html verylargebox took almost 3 years before its public release on the 20th of July 2013. 978* days to be exact.

Picture a box — verylargebox (@verylargebox) November 18, 2010

The actual time was around 6 months based on a 40h/week schedule. This is taking an idea existing solely in a couple of spoken words all the way to an app tangible by anyone. Once the release date had been set the last month turned really challenging. Ensure everything falls into place, communicate with both a designer to visually enrich the app and a video production company for the video promo, “recruit” testers to drive the app before submitting.

You might be wondering what about the 30 months of overhead? Well, that’s having a 9-5, suffering from 3 burnouts of 3-6-6 months, taking care of loved ones, dealing with personal matters, trying to have a social life.

Making something from scratch is tough; both mentally and physically. You skip the gym, you stop eating healthy, you pull all nighters, you start ignoring friends, you loose touch with the outside world, you effectively sit on a chair and ignore everything coming your way. You have to make personal sacrifices along the way as you must put the hours; there is no way around it.

The truth is that verylargebox would have possibly taken even more time to build if it wasn’t for the myriad QA on StackOverflow, the dozens of blog posts and tutorials available and the open source community.

Yet, it’s not only about writing software. It’s about achieving your dreams and aspirations, saving that extra weekend to be with loved ones, taking care of yourself, moving the whole industry forward one step at a time.

It is for those reasons that have open sourced 3 libraries (VLBCameraView, VLBScrollView, VLBAlertViews) and have already described residence based authentication that the box is made of.

verylargebox would probably have failed had it not be for all the support from friends. An encouraging talk, that snippet of code, the long conversation after midnight, putting you back on track, doing the chores for you, pushing you to do better. Even questioning the very thing that you do, forcing you to put things into perspective and keep the faith.

Thank you Maria, Leonida, Sam C, Keith, Andrew, Guy, Mike, Yaniv, Sam E, Stephanie, Bryan, George P, Aristoteli, Mark R, Ali, Colin, Philip, Jon, Matt, Max, Michali, Niko S, Pari, Pano, Taso, Jamie, Brian. Without you verylargebox would not have been real today.

The road ahead is even tougher. Hope to find the strength to pull it off.

.-

Note: “hg init” happened 3 days earlier.

]]>
Sun, 11 Aug 2013 00:00:00 +0200
On mobile https://qnoid.com/2013/06/13/On-mobile.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2013/06/13/On-mobile.html Marco Arment made some great points on the state of iOS 7 but had an urge to make something clear.

Great points by @marcoarment on the state of iOS. If you don’t get why, watch “Building user interfaces for iOS 7” marco.org/2013/06/11/fer…

The disruption has happened already

It all started in June 29, 2007 when the original iPhone was introduced. At the time when people were using their smartphones to make phone calls, send text, take photos, listen to music.

It’s not that mobile phones weren’t well equipped. They were relatively advanced. Bluetooth, GPRS, GPS, back camera, front facing camera, large storage; you name it.

Mobile phones had split per-so-nalities and the Internet was something you would “go to”. Phones were merely a window to the Internet rather than being part of it. The main (ref?) business was selling ringtones; a profitable business none the less. In their pursuit to expand market share, companies had lost focus. Developers weren’t really looking.

On October 17th, 2007 Steve Jobs announced ^1 the forthcoming availability of the iOS SDK. The following WWDC the App Store was introduced and in July, 2008 it was released changing the face of mobile as we knew it.

The iPhone transcends each individual SDK

Since then, Apple has invested heavily in the iOS SDK. Each year a new version is released with a new set of APIs. Collectively they make iOS and what the iPhone is today. Even though each version deserves its own release, to focus on a single feature set is short sighted in my opinion.

2008 2009 2010 2011 2012
Cocoa Touch CoreData AirPlay Core Image Social Framework
AV Foundation MapKit AirPrint Twitter Pass Kit
CoreAudio GameKit Local Notifications CoreBluetooth Reminders
CoreLocation Event Kit Newsstand UI State Preservation
Accelerometer Core Motion Auto Layout
CoreAnimation Data Protection
Quartz 2D Core Telephony$

iOS SDK Release History

Looking back through the lifespan of the iPhone, Foursquare was released in 2009 and Instagram on October 6th, 2010. Both looked past a feature set on what was possible with mobile and ended up disrupting local recommendations and image sharing respectively. Don’t expect Foursquare or Instagram to even budge with the release of iOS 7.

iOS 7 is worth it, but only as much

Indeed the App Store is crowded with almost a million apps. Big players like Facebook, Google (Google+), Yahoo! (Flickr), Amazon and ebay, along with many small ones. But even though they are on mobile, the extent to which they utilise it is poor. The main reason they are there in the first place is the large user base present which will only grow. Apple touted half a billion users. That’s a number you cannot ignore.

With the arrival of iOS 7 this fall, Apple’s marketing team will surely promote apps that elevate the new feature set, satisfying the thirst of people buying the new iPhone and those upgrading to the latest iOS. You should do well to be on that wave and get a free ride by Apple. A big opportunity indeed. But that’s about it.

Mobile begs for some innovation

To treat mobile as just another platform, mirroring existing services, porting established ideas or looking for a category to fill is not innovative.

Mobile is the pinnacle of personal computing. People carry them around spending a great deal of time. Even though mobile users have become familiar with tapping, swiping, pinching and are comfortable enough to share their location and photos, as an industry we still have a lot to learn and have barely scratched the surface of what’s possible in mobile computing.

^1 Even though Steve was reluctant initially.

]]>
Thu, 13 Jun 2013 00:00:00 +0200
Sound Debugging https://qnoid.com/2013/06/08/Sound-Debugging.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2013/06/08/Sound-Debugging.html Interview at NSBrief: #123: NSConference 6 with Saul Mora

Have filed bug report under rdar://16341784 See openradar.appspot.com/radar?id=5346823308836864*

Xcode’s ability to play sounds has been underused. Sound patterns can help debug notifications and visualize execution on unfamiliar code.

In this series of posts will explain what sound debugging is, show where it is useful, how it compares to traditional methods (e.g. logging) and bounce a few ideas on how it might help with testing, measure performance, debug concurrency and the teaching of algorithms.

Breakpoints that play sound

In case you didn’t know, XCode has the ability to play a sound on a breakpoint. Combined with the option to “Automatically continue after evaluating” you can effectively create a score based on code execution.

The idea behind sound debugging is based on the timing of these sounds; i.e. for an execution path with two breakpoints, you get this sound:

Let’s name those two sounds “funk” and “hero” respectively. Now, the sequence of two sounds doesn’t tell you much without knowing the code they are associated with. What do those sounds actually “mean”?

Here is the cheat sheet.

funk: an instance of QNDSubject was created.
hero: an instance of QNDSubject was notified.

Now you can “visualise” code. Whenever you hear those two sounds, you know that “an instance of QNDSubject was created” and (by being the only instance) that “was notified”.

Both without taking a look at the source code. Let’s look at the two parts of source code that the score relates to.

First the QNDSubject class where the instance is created.

@implementation QNDSubject

+(instancetype)newSubject
{
    QNDSubject *subject = [QNDSubject new];
    [subject wasCreated];

    [[NSNotificationCenter defaultCenter] addObserver:subject
                                             selector:@selector(wasNotified)
                                                 name:QND_NOTIFY_SUBJECT
                                               object:nil];
    
return subject;
}

-(void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:QND_NOTIFY_SUBJECT
                                                  object:nil];
}

-(void)wasCreated
{
    {}
}

-(void)wasNotified
{
    {}
}
@end

Second, the notification.

    QNDSubject *subject = [QNDSubject newSubject];
    
    [[NSNotificationCenter defaultCenter] postNotificationName:QND_NOTIFY_SUBJECT object:nil];

Even though the code base is relatively small in this case, it still requires more than one look to understand its execution.

  • Find the class whose instance you are interested in.
  • Look for the code that creates this instance.
  • Is the QNDSubject#wasCreated called?
  • Does it register for notifications?
  • Does the notification fire?

No matter how “clean” code is, it is still hard to read between the lines.

There are two reasons in this case why a sound clip works better in visualising code than actually looking at code itself.

  • The time taken to listen to the sound clip is smaller than the time taken to read the code.
  • The proximity of the two sounds is closer compared to every line of code that makes up the execution.

Now, in such a small code base, logging would likely help as much 1.

Where sound debugging really shines is in large 2, unfamiliar codebases (or even a week? old) where the need to track multiple points of execution is required. Even more so, when such code is mostly based on async execution and is loosely couple using delegates and notifications.

Some examples where sound debugging can help you:

  • Order of execution.
  • An instance is being reused or created each time.
  • A tap is handled more than once.
  • An object is destroyed.
  • A timer is invalidated or not.
  • An instance no longer listens for notifications.

A second part will follow.

Source Code

Origin: Had to come up with sound debugging when needed to debug an app where one operation “sometimes” timed out before another one had been executed.

Had just been brought in an unfamiliar and vast code base, involving lots of complex, async code and notifications. Knowing only two methods, (#didTimeOut and #executed) placed a breakpoint in each and listened.

After a couple of executions, was confident 3 that the timeout always came first. That gave a lead as where to look at and to the eventual fix.

Being in an unfamiliar code base found it easier to use sound breakpoints as stepping stones rather looking at method names to get a better understanding of what’s involved in the tap of a button.


  1. Even then, logging is still slower for your brain to process and also more prone to errors to your eyes; i.e.
    wasCreated
    wasNotified ↩︎

  2. As the code base grows, the practicalities of logging diminish. Your eyes might require to constantly jump in and out of the logs and all too often you need to indent logs so that they stand out. ↩︎

  3. When dealing with async/concurrent code you can “never” be sure of timings that are outside your control. ↩︎

]]>
Sat, 08 Jun 2013 00:00:00 +0200
How to implement a reusable UIView https://qnoid.com/2013/03/20/How-to-implement-a-reusable-UIView.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2013/03/20/How-to-implement-a-reusable-UIView.html There seems to be a lot of confusion around custom views on iOS that can be used both at compile time under Interface Builder and at runtime.

Even though a lot of posts exist that show how to design a UIView with a custom hierarchy using Interface Builder, there seems to be unnecessary complexity on what comes next.

1. Design the look and feel and view hierarchy in Interface Builder

The first thing to do is create a xib file (TBView.xib) as to design in Interface Builder the look and feel of your custom view along with its hierarchy.

By convention, this nib should hold a single top-level view.

The code to load any views that are in a xib file is the following.

    NSBundle *mainBundle = [NSBundle mainBundle];
    NSArray *views = [mainBundle loadNibNamed:@"TBView" 
                                        owner:nil 
                                      options:nil];

Where views is a collection of every top-level view in the xib file. (in this case a single one)

Will come back later to see what role the owner plays in loading the view.

2. Create a subclass of UIView as your custom view

In order to use the above look and feel in your custom view and be able to do so under Interface Builder^1 you need to create a subclass of UIView.

    #import <UIKit/UIKit.h>

    @interface TBView : UIView

    @end

By convention, the name of your subclass should be the same as the xib file.

3. Using it at compile time under Interface Builder

In your UIViewController’s xib, drag a view and set the “Class” as “TBView” in the “Custom Class” section under “Identity Inspector”. (CMD+OPTION+3)

By convention, this view should have the same size as the look and feel design.

Any view in a nib file that is part of the view hierarchy is initialised using NSCoding#initWithCoder: hence this is the spot where you load the #view from the xib and add it as a subclass.

    -(id)initWithCoder:(NSCoder *)aDecoder
    {
        self = [super initWithCoder:aDecoder];
        if(!self){
            return nil;
        }

        NSBundle *mainBundle = [NSBundle mainBundle];
        NSArray *views = [mainBundle loadNibNamed:NSStringFromClass([self class]) 
                                            owner:nil 
                                          options:nil];
        [self addSubview:views[0]];
        
    return self;
    }

Notice how we are using the name of the class, which is the same as the xib by convention to load the view.

This is how the hierarchy looks like.

$0 = 0x0756c810 >
       | >
       |    | >

4. Using it at runtime given a frame

Simply override UIView#initWithFrame: and use the same code to load the view from the xib and add it in the hierarchy.

    - (id)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if(!self){
            return nil;
        }
        
        NSBundle *mainBundle = [NSBundle mainBundle];
        NSArray *views = [mainBundle loadNibNamed:NSStringFromClass([self class]) 
                                            owner:nil 
                                          options:nil];
        [self addSubview:views[0]];

    return self;
    }

You can now create a new instance of that view as usual.

    TBView *view = [[TBView alloc] initWithFrame:frame];

5. File’s Owner and IBOutlets

If you need to keep references to any of the views in the xib, you can use the custom view as the File’s Owner and define any IBOutlets as properties of that class.

        NSBundle *mainBundle = [NSBundle mainBundle];
        NSArray *views = [mainBundle loadNibNamed:NSStringFromClass([self class]) 
                                            owner:self 
                                          options:nil];
        [self addSubview:views[0]];

As part of loading the views from the xib, the view will have its IBOutlets set.

By convention, the custom class should be the File’s Owner thus keeping all related code in a single class that can be reused.

Here is a macro that you can use in both initalisers to load a single view hierarchy that is available in the main bundle.

    #define loadView() \
    NSBundle *mainBundle = [NSBundle mainBundle]; \
    NSArray *views = [mainBundle loadNibNamed:NSStringFromClass([self class]) 
                                        owner:self 
                                      options:nil]; \
    [self addSubview:views[0]];

Source Code

References

NSNibAwaking Protocol Reference
Nib Files

^1: You can equally load the top-level view as designed in Interface Builder and use it at compile time.

]]>
Wed, 20 Mar 2013 00:00:00 +0200
How to debug a "class JKserializer is implemented in both" case (Part 2) https://qnoid.com/2013/02/12/How-to-debug-a-class-JKserializer-is-implemented-in-both-case-part-2.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2013/02/12/How-to-debug-a-class-JKserializer-is-implemented-in-both-case-part-2.html In the first part, found out that the executable included two definitions of the JKSerializer class. The one, used at compile time, corresponding to version 1.4 of JSONKit and another, deriving from 1.5 which was present at runtime.

In order, 1.5 came up first in the class dump, followed by the 1.4 as used by the app. Not sure how class-dump derives that order but does appear to be relevant as we’ll see further on.

The next thing is to find all the files where JKSerializer is actually coming from. This can either be a source file or a static library that includes JSONKit.

Using find with grep, every file under the current directory that has “JKSerializer” in its contents will match, printing its name in the process.

    find . -type f -exec grep -q "JKSerializer" '{}' \; -print

Running the above under the project’s directory, yields the following files.

./External/BugSense-iOS.frame-ork/Versions/A/BugSense-iOS
./JSONKit/JSONKit.m

So it seems that BugSense includes JSONKit as part of its distribution. Could that be version 1.5? Looking at the symbol table on the file for the i386 architecture (the one running on the simulator)

    nm -arch i386 ./External/BugSense-iOS.framework/Versions/A/BugSense-iOS | less

You will find the culprit.

+[JKSerializer serializeObject:options:encodeOption:block:delegate:selector:error:]

That explains the second definition of the JKSerializer class in the executable. What about the randomness of the crash though?

It turns out that it depends on the order of linking the binary with libraries under Xcode. If BugSense comes first on the list, its definition of JKSerializer takes precedence. Moving the libJSONKit.a library on top, no longer causes the crash.

Kudos to atnan for his article on lipo and ar tools and also a contributor to JSONKit.

Extra Tidbit The way the compiler (LLVM) resolves any symbols is by using a symbol table. Using nm, you can list the contents of the symbol table.

nm "/Users/qnoid/Library/Application Support/iPhone Simulator/5.1/Applications/9CEF83D3-C9DE-4951-95DF-CC1A3DB223F8/TBUndefined.app/TBUndefined"

Looking for JKSerializer, you can find the two class definitions. (as previously shown by the class dump)

	1044 < 0005c0b4 S _OBJC_CLASS_$_JKSerializer
	1045 < 0005bca4 s _OBJC_CLASS_$_JKSerializer

The only difference between the two being that one is defined a a local symbol while the other one as global. Would like to know how that is decided and if what role (if any) plays in resolving the class.

Symbol tables are usually implemented as hash tables.

Looking at the source code of the symbol table for LLVM, under line 71 you can see a lookup by name to the underlying hash table. This implementation of the hash table does not use a key for looking up a value in the corresponding bucket. Not iterating through the bucket, seemingly returning the first definition of JKSerializer, the 1.5 version one.

]]>
Tue, 12 Feb 2013 00:00:00 +0200
How to debug a "class JKserializer is implemented in both" case (Part 1) https://qnoid.com/2013/02/12/How-to-debug-a-class-JKserializer-is-implemented-in-both-case-part-1.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2013/02/12/How-to-debug-a-class-JKserializer-is-implemented-in-both-case-part-1.html Recently came across the following warning while running an app on the simulator.

objc[3946]: Class JKSerializer is implemented in both **/Users/qnoid/Library/Application Support/iPhone Simulator/5.1/Applications/9CEF83D3-C9DE-4951-95DF-CC1A3DB223F8/TBUndefined.app/TBUndefined** and **/Users/qnoid/Library/Application Support/iPhone Simulator/5.1/Applications/9CEF83D3-C9DE-4951-95DF-CC1A3DB223F8/TBUndefined.app/TBUndefined**. One of the two will be used. Which one is undefined.

The thing to note is how the warning points to the exact same location. Specifically the TBUndefined executable. What this means is that the class definition somehow found its way twice in the executable.

A seemingly random crash would also occur when calling NSDictionary#JSONString. Random as in, every now and then the app would be in a state where it would crash. But once in this state, the crash was consistently reproduced. In both cases, the warning above was depicted.

When the crash occurred, the following error was emitted in the console.

2013-02-11 22:57:19.754 TBUndefined[3946:c07] +[JKSerializer serializeObject:options:encodeOption:error:]: unrecognized selector sent to class 0x5bca4

This is seemingly contradictory to the warning. On one hand the JKSerializer class appears to be defined twice. While on the other, one of its method definition is missing.

First thing to do is find where the JKSerializer class is defined. Turns out, this class is part of JSONKit under the JSONKit.m file along with the expected method definition. (It’s worth noting that JSONKit was compiled as a static library, part of a set of dependencies as defined using Cocoapods)

At this point decided to take a look at the executable itself for the definition of JKSerializer. Steve Nygard has created a great tool, class-dump, that generates declarations of classes, protocols and categories in a Mach-O file.

The executable can be found at

/Users/qnoid/Library/Developer/Xcode/DerivedData/TBUndefined-dksnnnn-dsvgfybkturbkhxboi-b/Build/Products/Debug-iphonesimulator/TBUndefined.app/TBUndefined

Running a

	class-dump TBUndefined > TBUndefined.dump

and searching for JKSerializer under TBUndefined.dump we do find the two definitions as hinted by the warning. Take a look at the methods.

First Occurrence

	@interface JKSerializer : NSObject
	/* properties omitted for brevity */

	  + (id)serializeObject:(id)arg1 options:(unsigned int)arg2 encodeOption:(unsigned int)arg3 block:(id)arg4 delegate:(void)arg5 selector:(id)arg6 error:(SEL)arg7;

	/* instance methods omitted for brevity */
	  
	@end

Second Occurrence

	@interface JKSerializer : NSObject
	  
	/* properties omitted for brevity */

	  + (id)serializeObject:(id)arg1 options:(unsigned int)arg2 encodeOption:(unsigned int)arg3 error:(id *)arg4;

	/* instance methods omitted for brevity */

	@end

As you can tell, the method in question, appears to have a different definition to the one the code is calling. Having 3 extra arguments, block:delegate:selector:.

	+ (id)serializeObject:options:encodeOption:block:delegate:selector:error:;

Turns out, this is the JSONKit 1.5 definition.

In the next part, we’ll see how that definition ended up there and explain the randomness of the crash.

I have created a sample project that demonstrates the above behaviour as a reference.

Kudos

mikeash for contributing so much valuable knowledge to the community for free via his blog.
alloy for creating Cocoapods.

]]>
Tue, 12 Feb 2013 00:00:00 +0200
iOS implementation of user authentication without a password https://qnoid.com/2012/12/09/iOS-implementation-of-user-authentication-without-a-password.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2012/12/09/iOS-implementation-of-user-authentication-without-a-password.html

iOS implementation of user authentication without a password as specified and mocked up previously.

]]>
Sun, 09 Dec 2012 00:00:00 +0200
Mockups on user identity https://qnoid.com/2012/11/10/Mockups-on-user-identity.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2012/11/10/Mockups-on-user-identity.html User identity

The idea of a user identity is a simple one with a goal to eliminate the requirement of a user entering a password. Any other requirement, including storing, transmitting and hashing should stay the same.

Introduction

As soon as a software is installed that supports user identities, a user is presented with a screen to identify.

Introduction

Identify

The user enters her email and a new residence identifier is generated 1 both securely persisted on the client. On an iPhone that should be the keychain. A request is sent to the server to approve the new residence.

The server sends an email to the user to verify the new residence. Once the residence has been approved, its identifier and the user email are hashed and persisted. This becomes the residence of the user identity which is used for a future identification.

Identify

Sign in

The now owner of the identity, can use it to sign in remotely to the server and retrieve her data. The user identity along with the residence identifier should be transmitted using a secure channel and compared against the hash stored in the server.

Sign in

Deleting an identity

To delete an identity, slide across on an iPhone.

Delete

The identity is permanently removed from this residence.

Loose ends

  1. In the web, a secure client storage doesn’t exist. Discussion

  1. The most simple form of the residence identifier can be a [UUID][5]. ↩︎

]]>
Sat, 10 Nov 2012 00:00:00 +0200
A post about user identity that is thought provoking on user authorisation and security, or just utter bullshit https://qnoid.com/2012/11/10/A-post-about-user-identity-that-is-thought-provoking-on-user-authorisation-and-security-or-just-utter-bullshit.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2012/11/10/A-post-about-user-identity-that-is-thought-provoking-on-user-authorisation-and-security-or-just-utter-bullshit.html User identity

Disclaimer: I am no security expert.

Use case

Provide a way for a user to identify himself before remotely accessing a multi-user software that requires to associate the user with her data.

Introduction

There are two forms of user identification.

  1. Non authorised by the user
  2. Authorised by the user

Definitions

Non authorised identification is a user saying who he is.
Authorised identification is a user saying who he is and trusting her.

For brevity, non authorised identification will be known simply as identification.

In essence, an authorised identification is a two stage identification. In the first stage the user provides an alias that is known of, usually in the form of a username. In the second stage the user provides proof to his claim, usually in the form of a password.

Imagine sitting behind a large door. A user comes and knocks.

  • “Who is this?”
  • “This is John” <- Identification
  • “Prove it!”
  • “Here is my passport” <- Authorised

Identity

The identity of the user is her email. An email is required both for identifying it to its owner and for verifying a new residence. An identity can have many residences.

Residence

Each identity is paired with a residence. A residence vouches for the user identity. Should the residence be removed, the identity can no longer be vouched for.

Characteristics of a residence

A residence has an identifier which needs to adhere to the following principles.

  1. Private.
    The identifier of a residence is private even to its owner.

  2. Unique.
    A residence identifier needs to be unique from a pool of residences.

  3. Secure.
    The identifier needs to be securely stored.

Creating a new residence.

Assuming the owner of the identity wants to create a new residence from which she can access the software.

The user requests for the new residence to be added. Subsequently, verifies the new residence via email. The new residence can now vouch for the user’s identity.

Delete a residence

The owner should be able to remove a residence. If a residence is deleted, the identity is also permanently removed as a residence.

Mockups

Some mockups as to how it looks in practice.

Inspired by

  1. Yahoo! & Sprint Displayed Passwords at Scale. What Happened?
  2. Sign On
  3. Persona
]]>
Sat, 10 Nov 2012 00:00:00 +0200
How to trace and debug an iOS crash (Part 2) https://qnoid.com/2012/10/21/How-to-trace-and-debug-an-iOS-crash-part-2.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2012/10/21/How-to-trace-and-debug-an-iOS-crash-part-2.html Dead end

Having reached a dead end, decided to take a look at the client side in an effort to understand more about the request/response cycle.

First thing was to enable logging for the headers and body of both the request and the response.

    > GET /foo HTTP/1.1  
    > "Accept-Encoding" = gzip;  
    > "Accept-Language" = [languages];  
    > Range = "foo=0-10";  
    > "User-Agent" = "[App Bundle Id]/ (unknown, iPhone OS 4.3.3, iPad, Scale/1.000000)";

    < HTTP/1.1 200 OK  
    < Content-Type: plain/text  
    < X-pad: avoid browser bug  

Notice the “Content-Type: plain/text” (though the “X-pad: avoid browser bug” did look interesting on its own way).

QUESTION: How and why the content type of the response was changing from the expected “application/json”?

EVIDENCE

1. > GET /foo HTTP/1.1
2. < [empty body]
3. Response "Content-Type: plain/text" (Application Layer)

Back to basics

Continuing with the elimination process, it was the iPad’s turn this time, substituting with curl

    [curl] -> [AWS Load Balancer] -> [AWS EC2 Single instance)

In an effort to reproduce the request as sent by the iPad, failed to receive the “desired” response, instead the received response was the expected “application/json” one.

    curl -v -A "[App Bundle Id]/ (unknown, iPhone OS 4.3.3, iPad, Scale/1.000000)" -H "Accept:" -H "Accept-Encoding: gzip" -H "Accept-Language" = "[languages]" -H "Range: foo=0-10" www.domain.com/foo

Bare in mind that the request headers above were obtained using

    NSLog(@"%@", [request allHTTPHeaderFields])

With no access to the iOS source, it’s difficult to know if every header is indeed in the returned NSDictionary. Hence decided to bring back to the equation the iPad and go down to the Network Layer to see the raw data.

Dumping the tcp

    [iPad 4.3.3 WiFi] -> [Mac] -> [AWS Load Balancer] -> [AWS EC2 Single instance)

In order to trace the network traffic as sent from the iPad, all you need is to have your Mac connected to the same network and share that network connection from OS X.

    Apple -> System Preferences -> Internet Sharing  
    "Share your connection from: Ethernet"  
    "To computers using: Wi-Fi"  
    "Computer name: [computer name]"  

Connect the iPad to the Wi-Fi [computer name] and have tcpdump running.

    sudo tcpdump -i en0 -s 0 -B 524288 -w ~/Desktop/DumpFile01.pcap

Here is what the tcpdump revealed.

    > HEAD /foo HTTP/1.1
    > Host: [AWS Load Balancer]
    > User-Agent: [App Bundle Id]/ (unknown, iPhone OS 4.3.3, iPad, Scale/1.000000)
    > Accept-Encoding: gzip
    > Accept-Language: [languages]
    > Accept: */*
    > Cookie: [cookies]
    > Content-Length: 0
    > Connection: keep-alive

    > HTTP/1.1 200 OK
    > Date: [timestamp]
    > Server: [server]
    > Content-Range: foo=0-10/11
    > Connection: Keep-alive
    > Content-Type: text/plain
    > X-Pad: avoid browser bug

followed by

    > GET /foo HTTP/1.1
    > Host: [AWS Load Balancer]
    > User-Agent: [App Bundle Id]/ (unknown, iPhone OS 4.3.3, iPad, Scale/1.000000)
    > Accept-Encoding: gzip
    > Accept-Language: [languages]
    > Range: foo=0-10
    > Accept: */*
    > Cookie: [cookies]
    > Connection: keep-alive

    < HTTP/1.1 200 OK
    < Date: [timestamp]
    < Server: [server]
    < Content-Range: foo=0-10/11
    < Content-Type: application/json
    < Connection: Keep-alive
    < transfer-encoding: chunked

Indeed there is a “plain/text” response but this is coming from a HEAD request on the same URL. What follows is the “application/json” one to the GET.

QUESTION: If the response is coming back as expected at the network layer, why are responses getting mixed up at the application layer?

Could that be a threading issue? A race condition? Why is it happening only on the iPad 4.3.3?

To make sure that this wasn’t a race condition, put a breakpoint on the completionBlock of the HEAD request to check the response. The response was the expected one.

Checking the response from GET however, turned out to be the same one as the HEAD.

QUESTION: Why would iOS 4.3.3 return a seemingly cached response?

EVIDENCE

1. > GET /foo HTTP/1.1
2. < [empty body]
3. Response "Content-Type: plain/text" (Application Layer)
4. Response "Content-Type: application/json" (Network Layer)
5. Cached response on GET /foo (Client side)

While debugging the above, came across a neat trick on how to query an http server for its version

A third part will follow

]]>
Sun, 21 Oct 2012 00:00:00 +0200
How to trace and debug an iOS crash (Part 1) https://qnoid.com/2012/10/20/How-to-trace-and-debug-an-iOS-crash-part-1.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2012/10/20/How-to-trace-and-debug-an-iOS-crash-part-1.html There has been a crash

While preparing for an iOS release, observed a crash on an iPad (iOS 4.3.3, WiFi). The crash was fairly consistent to be considered random but once in a while, it would work as expected. On the other hand, an iPad 3 (iOS 5.1, WiFi/3G) wouldn’t exhibit the same behaviour.

The crash was triggered at the completion block of an AFHTTPRequestOperation while parsing a (JSON) response with an empty body to a NSDictionary using JSONKit.

This was an unexpected behaviour since an empty body response was not defined in the request/response contract.

FACTS

1. iPad 4.3.3 WiFi

EVIDENCE

1.  > GET /foo HTTP/1.1  
2.  < [empty body]

The setup

The iOS app in question, was pointing at an Amazon EC2 Load Balancer which had a single EC2 instance attached.

    [iPad 4.3.3 WiFi] -> [AWS Load Balancer] -> [AWS EC2 Single instance)

The request was an HTTP GET expecting a JSON response but getting one with an empty body instead.

    > GET /foo HTTP/1.1  
    < HTTP/1.1 200 OK  
    < [empty body]

The request had a constant set of headers and a content. e.g. no user input was involved.

Elimination game

In a scenario where multiple factors are involved, you need to play the elimination game to find the culprit.

Hence, started by removing the load balancer and see if it makes any difference. Effectively the iOS app was now sending requests directly to the EC2 instance.

    [iPad 4.3.3 WiFi] -> [AWS EC2 Single instance]

As a result the crash would no longer manifest.

    > GET /foo HTTP/1.1  
    < [JSON]  

FACTS

1. iPad 4.3.3 WiFi  
2. AWS Load Balancer

At this point, you need to work backwards.

QUESTION: Under what circumstances would the load balancer return an empty body?

The question does not really have a straightforward answer. A hint was given by @goldstein that maybe multiple instances are attached to the load balancer with one of them sending the bogus response. This however didn’t seem to be the case. At least as shown by the AWS Console.

To verify this assumption, used traceroute. Traceroute will report if multiple addresses are assigned to a given host.

    traceroute [AWS Load Balancer]  
	Warning: [AWS Load Balancer] has multiple addresses;

Executing traceroute for a couple of times, will give you all the different ips. In this case they were two (2), one of which was the known EC2 instance.

QUESTION: Why would the load balancer report 2 ips attached if only 1 is assigned according to the AWS console?

Even weirder was that the second ip reported wasn’t anywhere to be found under the AWS console. A “phantom” ip.

Looking closer at the load balancer configuration, they were 2 availability zones defined.

    availability zone (instance = 0, healthy = NO)  
    availability zone (instance = 1, healthy = YES)

Removing the “unhealthy” availability zone, solved the “multiple addresses” issue.

QUESTION How is that explained?

ASSUMPTION When the [AWS EC2 Single instance] was initially created, it was assigned the reported phantom ip. At that point, it was attached to the load balancer with the given availability zone. Later on, an elastic ip was set while the instances were reduced down to one (1).

Haven’t reproduced the above steps to verify this assumption.

Traceroute, reported both the original and elastic ip attached to the load balancer.

Although the load balancer was now correctly pointing to one instance, the crash wasn’t resolved.

Kudos to @goldstein for his insight to AWS.

Continue to part 2

]]>
Sat, 20 Oct 2012 00:00:00 +0200
Metrics of an object oriented world https://qnoid.com/2011/06/08/Metrics-of-an-object-oriented-world.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2011/06/08/Metrics-of-an-object-oriented-world.html

Decided to do a talk about OO; but this time wanted to provide some actual metrics to back it up.

Took measurements per “iteration”, e.g. when a new functionality is added in the code base. For each iteration counted methods and types respectively.

Though in the beginning adding types has some overhead, it only takes 3 iterations to achieve 83% reusability. For reusability counted the number of types reused vs the total number.

Would be interesting to do some more metrics and find how many iterations should take (on average) and how many types to find a true golden ratio and what that is. However it might be the case that numbers vary greatly depending on the problem domain.

An IDE plugin to show you how the reusability ratio increases as you add types would be a great tool to assist developers and give a new dynamic on coding.

Even though when starting to write code we have a higher level of understanding of the problem (iterations are not that short), usually as developers we take the procedural route and think in terms of methods. It demonstrates how complex the object oriented programming paradigm is, even though it has been around for decades.

Resist the urge to jump straight to code. Lay down your thoughts first using pen and paper and start thinking in terms of objects, there are benefits both in the short and long term.

Source

Note On the 3rd iteration there are actually 5 methods. (not 4 as depicted on the slide)

Further Reading

Urban Legends - O is for Object (Part 1)

The Myth - O is for Object (Part 2)

Revelations - O is for Object (Part 3)

On Reusability (Part 1) - Misconceptions

On Reusability (Part 2) - Misconceptions

Don’t Lose Your Train of Thoughts series

iterations

methods

//1st iteration
private List<String> load() 
public String findByValue(String value)

//2nd iteration
public String findByReverse(String reverse)

//3rd iteration
private List<Integer> load() 
public Integer findByValue(Integer value)

types

//1st iteration
public final class Service<T> 
public interface Predicate<T> 
public final class Implementation

//2nd iteration
public final class Evals 
public interface Eval<T>

//3rd iteration
public final class PredicateBuilder<T>
]]>
Wed, 08 Jun 2011 00:00:00 +0200
Making wordings of numbers 27 going twentyseven https://qnoid.com/2011/05/19/Making-wordings-of-numbers-27-going-twentyseven.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2011/05/19/Making-wordings-of-numbers-27-going-twentyseven.html
public final class Wording
{
private final Map<Integer, String> wordings;

public Wording(Map<Integer, String> wordings)
{
    this.wordings = wordings;
}

public String of(int number){
return this.of(number, 10);
}

private String of(int number, int mod) 
{
    if(number == 0)
        return "";
    
    int value = number % mod;

    /*
     * if there is no value for a digit skip to the next mod.
     * e.g.  
     * missing units
     *  120 % 10 = 0
     *  
     * missing tens
     *  100 % 100 = 0 //missing tens
     */
    if(value == 0) {
    return this.of(number, mod * 10);
    }
    
    StringBuilder sb = new StringBuilder();

    String wording = this.wordings.get(value);
    
    sb.append( wording );
    
    int remaining = number - value;

    String stringOf = this.of(remaining, mod * 10);

    sb.insert(0, stringOf);
    
return sb.toString();
}
}


public class WordingTest 
{
public static final Map<Integer, String> wordings = 
    new HashMap<Integer, String>()
    {
        {
            this.put(7, "seven");                   
            this.put(20, "twenty");
            this.put(100, "onehundred");
        }
    };

private void assertOf(String name, int number) 
{   
    Wording wording = new Wording(wordings);
    
    Assert.assertEquals(name, wording.of(number));
}

@Test
public void stringOfSeven() throws Exception 
{
    assertOf("seven", 7);
}

@Test
public void stringOfTwentySeven() throws Exception 
{
    assertOf("twentyseven", 27);
}

@Test
public void stringOfOneHundred() throws Exception 
{
    assertOf("onehundred", 100);
}

@Test
public void stringOfOneHundredTwenty() throws Exception 
{
    assertOf("onehundredtwenty", 120);
}

@Test
public void stringOfOneHundredSeven() throws Exception 
{
    assertOf("onehundredseven", 107);
}

@Test
public void stringOfOneHundredTwentySeven() throws Exception 
{
    assertOf("onehundredtwentyseven", 127);
}
}

Just recently came across this case needing to convert a number to its wording. For example, given the number 27 produce “twentyseven”.

One way to tackle this is to dissect the number to its digits one by one, starting by the lower ones.

(0)			2		7
(hundreds)	tens 	units

Using a lookup table on units, tens, hundreds will allow us to get the wording for a single number.

	Map<Integer, String> units = new HashMap<Integer, String>();
	units.put(7, "seven");

	Map<Integer, String> tens = new HashMap<Integer, String>();
	tens.put(20, "twenty");

The real question then becomes, what algorithm will give us the number of the right magnitude? In other words, how can we get the units, the tens and the hundreds of a number?

For that we will take advantage of the mod operator with a touch of recursion to traverse the whole number.

First a reminder on the mod. Whenever you mod a number, the value you get back is anywhere within the range of the modulo, starting from 0.

	27 % 10		= 	7 	(units)
	20 % 100 	= 	20 	(tens)
	0  % 1000 	=	0 	(hundreds)

With that in mind, starting from 10 as the modulo we get the value of the units, thus its wording.

Every time subtracting the current value from the number to be left with the next scale.

	27 - 7 = 20

and modding again with the next modulo

	mod * 10

until we get a 0 as the number, which is the stop condition.

What about numbers that are missing digits like 100 which will give a 0 as soon as we mod them? Well, there are a couple of ways to go about it.

  • Add a lookup value of an empty string to 0. This although works, breaks the semantics of the lookup.
  • Check for a null and use an empty string instead. In this case you will have the overhead of allocating the StringBuilder and that of the append.
  • Skip to the next mod.

There is however a serious limitation to the above. How do you go on about numbers between 11 (“eleven” and not “tenone”) through 19? What about the number 0?

Developers challenge: Implement the above in your preferred language while also coming up with an answer to the above limitation. The first one to write a solution and a test that proves it, gets a postcard from Edinburgh.

How would you improve the algorithm to produce better wordings? Do you have another algorithm to share for figuring out the wording of a number?

As always, you can find the source code of the post over at github.

Kudos to @nelstrom, the person behind Vimcasts.org. Drew recently visitted Egypt and was pleased to find out that numbers are read left to right as opposed to arabic script and figuring out their wording.

]]>
Thu, 19 May 2011 00:00:00 +0200
How to think of... a hash table (Part 3) https://qnoid.com/2011/05/11/hash-table-part-3.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2011/05/11/hash-table-part-3.html
/**
     * The well known hash table, now with rehashing support
     */
    public final class HashTable 
    {
        private BucketList bucketList;

        private HashTable(BucketList buckets) 
        {
            this.bucketList = buckets;
        }

        private void rehash() {
            this.bucketList = BucketList.newBucketList(this.bucketList);
        }

        /*
         * If we run out of buckets let's make some more 
         */
        private void ensureAvailableBuckets() 
        {
            if(this.bucketList.isLoaded()) {
                this.rehash();
            }
        }
        
        public void put(int key, int value) 
        {
            this.ensureAvailableBuckets();
            
            int index = this.bucketList.bucketOf(key);      

            this.bucketList.put(index, key, value);
        }
    }

    /**
     * A bucket list as you can tell has a hash function
     */
    final class BucketList
    {
        private final HashFunction hashFunction;
        private final Value[] buckets;
        private int count;  //keeping track of values added to know the load factor

        private BucketList(Value[] buckets, HashFunction hashFunction) 
        {
            this.buckets = buckets;
            this.hashFunction = hashFunction;
        }   

        float load(){
        return this.count / this.size();
        }

        int bucketOf(int key) {
        return this.hashFunction.indexOf(key, this.size());
        }

        boolean isLoaded() {
        return this.hashFunction.isLoaded( this.load() );
        }

        int size() {
        return this.buckets.length;
        }

        public void put(int index, int key, int value) 
        {       
            Value current = this.buckets[index];
            
            this.buckets[index] = new Value(key, value, current);
            this.count++;
        }
    }

The hashtable indeed works as expected. We do have a key to retrieve a value, we do handle conflicts when putting one under the same index.

However, in a hashtable there is more than just looking up values based on keys. Take a look at the first bucket.

0 > [0, 3, 6, 9]

Given the fixed size of the hashtable imagine what would happen if we were to store only values with keys that came up with an index of 0.

0 > [0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30 ...]

The bucket would grow so large that every time we would have to iterate through the whole list to find the value for the given key. Also the remaining 2 buckets would go to waste.

Unless you have a collection of values that you need to store with predefined keys so that you can come up with the perfect hash function that distributes them evenly, you need to think of a way to grow your bucket list and at the same time recalculate the index for each value, what is known as rehashing.

    /**
     * A hash function is a bucket list's close friend 
     */
    public interface HashFunction
    {
	public int indexOf(int key, int bucketSize);
	public boolean isLoaded(float load);
	public int newSize(int size);
    }

The reason you need to calculate the index again for each value when rehashing is because every time you get and put a value given the key, the hashtable needs to figure out the index based on its size, which after resizing, has changed. Therefore it will come up with a different answer as to where the value is.

	/* initial size of 3 */
	hashtable.put(6, 6); 
	//6 % 3 = 0
	
	/* after resizing to 5 */	
	hashtable.get(6);
	//6 % 5 = 1

As you can tell, rehashing can be quite expensive since not only there is a need to iterate through every value in the hashtable but also recalculate every index.

	public static BucketList newBucketList(int size, HashFunction hashFunction) {
	return new BucketList(new Value[size], hashFunction);
	}

	public static BucketList newBucketList(BucketList bucketList) 
	{
		int size = bucketList.hashFunction.newSize( bucketList.size() );
		
		BucketList newBucketList = 
			newBucketList(size, bucketList.hashFunction);		
		
		for (Value value : bucketList.buckets)
		{
			while(value != null) 
			{
				int index = newBucketList.bucketOf(value.key);
				newBucketList.put(index, value.key, value.value);
				
				value = value.next;
			}				
		}

	return newBucketList;
	}

What you get in return though is spreading the values across all the buckets, which was the problem that lead to all this.

The question then becomes when is the right time to rehash? The most obvious answer would be when there is one value in every bucket and no buckets are left. There is however something that is called a load factor which shows how full your hashtable is. The load factor is simply the ratio between the number of values and the hashtable size.

In the next part we’ll see how the size of a hash table has an affect on rehashing, given a “bad collection” of keys.

]]>
Wed, 11 May 2011 00:00:00 +0200
How to think of... a hash table (Part 2) https://qnoid.com/2011/04/07/hash-table-part-2.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2011/04/07/hash-table-part-2.html
public final class HashTable 
    {
        private BucketList bucketList;

        private HashTable(BucketList buckets) 
        {
            this.bucketList = buckets;
        }

        public int get(int key) 
        {
            int index = this.bucketList.bucketOf(key);

        return this.bucketList.get(index, key);
        }

        public void put(int key, int value) 
        {
            int index = this.bucketList.bucketOf(key);      

            this.bucketList.put(index, key, value);
        }
    }


    /**
     * Buckets for all
     */
    final class BucketList
    {
        private final Value[] buckets;

        private BucketList(Value[] buckets) 
        {
            this.buckets = buckets;
        }   

        int bucketOf(int key) {
        return key % this.buckets.length
        }

        /**
         * Searches the bucket in the specified index for the value of the given key
         * @param index the bucket that holds the value
         * @param key the key of the value
         * @return the value in the bucket that has the specified key or -1
         * @see #bucketOf(int)
         */
        public int get(int index, int key) 
        {
            for (Value value = this.buckets[index]; value != null; value = value.next) 
            {
                if(value.key == key){
                    return value.value;
                }
            }
        
        return -1;
        }
        
        /**
         * Stores the value for the given key to the specified bucket.
         * If an existing value is already present, store it next to the one 
         *  
         * @param index the index of the bucket
         * @param key the key of the value
         * @param value the value
         */
        public void put(int index, int key, int value) 
        {       
            Value current = this.buckets[index];
            
            this.buckets[index] = new Value(key, value, current);
        }
    }

Start at the beginning with Part 1

Let’s take a step back for a minute and take a look at the array.

[0, 1, 2]

Imagine that each value in the array represents a “bucket”. That is a collection of values (rather than a single one). So each time you put a value in that bucket, it grows.

 9 
 6	7  
 3	4  5
 0  1  2
 ^  ^  ^
[0, 1, 2] //bucket index

Rotating the view 90 degrees to the right will reveal that each bucket really is just an array

0 > [0, 3, 6, 9]
1 > [1, 4, 7]
2 > [2, 5]

This will allow us to store more than one value under the same index. Notice how 0 and 3 are both under index 0. Calculating the index of the bucket is not enough any more when querying for the value since there is the possibility of getting more than one.

That is why we need a class to hold the value as well as the actual key associated with it.

	/*
	 * In each bucket basically is a linked list
	 */
	class Value
	{
		private final int key;
		private final int value;
		private Value next;		
	}

Having a reference to the next value in the bucket will allow us to grow and iterate the array without the overhead of maintaining it.

So given the index and the key, we find the bucket and then iterate until we match the key to get the value. Remember that each key is really unique.

	public int get(int index, int key) 
	{
		for (Value value = this.buckets[index]; value != null; value = value.next) 
		{
			if(value.key == key){
				return value.value;
			}
		}
	
	return -1;
	}

In that sense in every put as well as creating a new Value with the key and value we need to assign the current one as the next in the list.

	public void put(int index, int key, int value) 
	{		
		Value current = this.buckets[index];
		
		this.buckets[index] = new Value(key, value, current);
	}

That all works great but our hash table is of fixed and very small length. We need to deal with the fact that our buckets will grow longer and longer in time.

]]>
Thu, 07 Apr 2011 00:00:00 +0200
How to think of... a hash table (Part 1) https://qnoid.com/2011/04/07/hash-table-part-1.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2011/04/07/hash-table-part-1.html
/*
     * For now, think of a hash table as something like that 
     */
    public interface HashTable
    {
        /**
         * Retrieves the value from the hash table given the key
         * 
         * @param key the key used to put the value
         * @return the associated value as specified in {@link #put(int, int)}
         */
        public int get(int key);

        /**
         * Stores the specified value under the given key.
         * Any value stored previously on the same key is overriden.
         * 
         * @param key the key to associate the value with
         * @param value the value
         */
        public void put(int key, int value) 
    }

The hash table seems to be the dominator of data structures as it is being used to solve a variety of CompSci problems such as caching. On a day to day basis we can use it when there is a need to make a choice or to operate on a Set (though hidden). Now, rarely there is a need to implement a hash table from scratch but having a deep understanding of how a hash table works can greatly help us make the most out of it when the time comes.

The basic idea is that you have an array to store values. Given that an array has an index that you can use to store and retrieve a value, it all works.

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

What happens though if you want to use your own key that you can query on? So you have a hashtable of size 3 and you want to put the value of 0 under the key 0.

	HashTable hashtable = new HashTable(3);
	hashtable.put(0, 0);

Now given that the underlying structure is an array, the hashtable needs to figure out which index to use in the array to put the value in. Since the array is of size 3 the possible indexes are 0 to 2.

[0, 1, 2]
|---3---|

A simple way to get a number within that range is to mod the key with the length of the hashtable. So in this case

0 % 3 = 0 // key  % length = index

So the hashtable uses index 0 to store the value.

	public void put(int key, int value) 
	{		
		int index = key % this.size;
		this.values[index] = value;
	}

The next time you ask for the value stored under the key 0

	hashtable.get(0);

the hashtable calculates the index again and gives you the value stored

	public int get(int key) 
	{
		int index = key % this.size;

	return this.values[index];
	}

It all works great until you have a key which gives you the same index.

	hashtable.put(0, 0); // 0 % 3 = 0
	hashtable.put(1, 1);
	hashtable.put(2, 2);
	hashtable.put(3, 3); // 3 % 3 = 0

That’s when you have a collision which you need to deal with.

]]>
Thu, 07 Apr 2011 00:00:00 +0200
How To Think Of... Binary Search https://qnoid.com/2011/03/31/binary-search.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2011/03/31/binary-search.html
/**
     * Divide and conquer
     */
    public class BinarySearch 
    {
        /*
         * Let's start looking from the beginning of the array 
         * 0 till the last index which is length - 1.
         * e.g. an array of size 10 has positions from 0 to 9.
         */
        public int indexOf(int[] numbers, int what) {
        return this.indexOf(numbers, what, 0, numbers.length - 1);
        }
        
        private int indexOf(int[] numbers, int what, int fromIndex, int toIndex) 
        {
            if(fromIndex > toIndex)
                return -1;
            
            /*
             * Let's take the average by shifting bytes.
             * How does that work?
             * 
             * For indexes of 0 to 9 we have 9 >>> 1
             * 9 in binary is 1001, therefore
             * 
             * 1001 >>> 1 = 0100
             * 
             * which is equal to 4
             * Notice how we are moving each bit 1 position to the right.
             * So 
             * 1 becomes 0
             * 0 becomes 1
             * 0 becomes 0
             * 1 falls off and becomes 0
             */
            int average = (fromIndex + toIndex) >>> 1;
            
            int guess = numbers[average];
            
            if(guess == what){
                return average;
            }
            
        return what < guess?
                indexOf(numbers, what, fromIndex, average-1):
                indexOf(numbers, what, average+1, toIndex);
        }
    }


    /**
     * Let's assert that it works
     */
    public class BinarySearchTest 
    {
        public void assertIndexOf(int[] numbers, int what, int index) 
        {
            BinarySearch search = new BinarySearch();
            
            int indexOf = search.indexOf(numbers, what);
            
            Assert.assertEquals(index, indexOf);
        }
        /**
         * Makes the following asserts
         * <ul>
         *  <li> returns -1 on an empty array</li>
         *  <li> returns the index on an odd elements array</li>
         *  <li> returns the index on an even elements array</li>
         *  <li> returns the index on an odd elements array with a direct hit</li>
         *  <li> returns the index on an odd elements array after 1 division</li>
         *  <li> returns the index on an even elements array after 1 division</li>
         *  <li> returns the index on an even elements array after 2 divisions</li>
         *  <li> returns -1 on a non empty array -ithout the element</li>
         * </ul>
         */
        @Test
        public void indexOf()
        {   
            assertIndexOf(new int[]{}, 0, -1);
            
            assertIndexOf(new int[]{0}, 0, 0);
            
            assertIndexOf(new int[]{0, 1}, 0, 0);
            assertIndexOf(new int[]{0, 1}, 1, 1);       
            
            assertIndexOf(new int[]{0, 1, 2}, 0, 0);
            assertIndexOf(new int[]{0, 1, 2}, 1, 1);
            assertIndexOf(new int[]{0, 1, 2}, 2, 2);
            
            assertIndexOf(new int[]{0, 1, 2, 3}, 0, 0);
            assertIndexOf(new int[]{0, 1, 2, 3}, 1, 1);
            assertIndexOf(new int[]{0, 1, 2, 3}, 2, 2);
            assertIndexOf(new int[]{0, 1, 2, 3}, 3, 3);
            
            assertIndexOf(new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, 10, -1);     
        }   
    }

Seems like algorithms and data structures are a weak point for many. Some data structures are used extensively in our day to day code (like an array or a hashtable) while algorithms usually remain hidden under the hood. In any case we rarely come any closer than that and although that’s usually not the problem, Google, Microsoft and Amazon interviews rely heavily on them.

Through these posts we’ll try to explore some of them, understand them and hopefully learn something valuable in the process than just memorising them.

Starting with Binary Search. As the name implies binary search is an algorithm for finding an element. In order to use the binary search we need to have an array of elements.

There is however a pre-condition associated with the array. It needs to be sorted. Let’s see why by taking an array with numbers starting from 0 to 9.

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Pick a number (Let’s say 5 but keep it secret for now).

Is it 4? (the average of 0 + 9 is ~4)

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
             ^

No.

Is it lower than 4? No.

Since it’s higher than 4 let’s look between 5 and 9 this time.

Is it 7? (the average of 5 + 9 is 7)

[5, 6, 7, 8, 9]
       ^

No.

Is it lower than 7? Yes.

Since it’s lower than 7, let’s look between 5 and 6 this time.

Is it 6? (the average of 5 + 6 is ~6)

[5, 6]
    ^

No.

Is it lower than 6? Yes

Since it’s lower than 6, let’s look between 5 and …5 this time.

[5]
 ^

Is it 5? (the average of 5 + 5 is 5)

Yes.

Notice how given an index to start from and an index to end we always take the average to look for the number. That effectively reduces the numbers to look for by a factor of 2 every time.

Also notice how every time that we don’t find the number we reduce the range to look for.

  • If the number is lower that the one we guessed we look from the start till the average minus 1.
  • If it’s higher we add 1 to the average and look till the end index.

What’s missing is when to stop looking for the number. If you follow the pattern you will notice that at some point the index to start looking from will be be greater than the end index. That’s when you stop.

So you might ask yourself. In an OO language like Java how useful is that? After all it is objects that we are dealing with. For that reason there is the Comparable interface that you need to implement with a single method that returns an int. It’s up to you to decide whether an object ranks lower or higher than an equivalent.

Note: Do you know that Java has a bug up until version 5.0 when it comes to calculating the average?

“Can’t even compute average of two ints” is pretty embarrassing.

Source

]]>
Thu, 31 Mar 2011 00:00:00 +0200
How To Think Of... Macros https://qnoid.com/2011/03/14/macros.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2011/03/14/macros.html
/**
     * Emulates a method as described in the {@link Robot} which can
     * be executed.
     * 
     * Any arguments to the method are encapsulated by the implementation.
     */
    public interface RobotMethod
    {
        /**
         * Execute the method on the robot
         * @param robot the robot to execute the method on
         */
        public void execute(Robot robot);
    }

    /**
     * All available {@link RobotMethod}s
     */
    public class RobotMethods
    {
        private static final class LogMethod implements RobotMethod
        {
            private final String message;

            private LogMethod(String message)
            {
                this.message = message;
            }

            @Override
            public void execute(Robot robot) {
                robot.log(this.message);
            }
        }

        private static final class AlertMethod implements RobotMethod
        {
            @Override
            public void execute(Robot robot) {
                robot.alert();
            }
        }

        private static final class MoveMethod implements RobotMethod
        {
            private final int y;
            private final int x;

            private MoveMethod(int y, int x)
            {
                this.y = y;
                this.x = x;
            }

            @Override
            public void execute(Robot robot) {
                robot.move(this.x, this.y);
            }
        }

        public static RobotMethod newMove(int x, int y) {
        return new MoveMethod(y, x);
        }

        public static RobotMethod newAlert() {
        return new AlertMethod();
        }

        public static RobotMethod newMessage(String message) {
        return new LogMethod(message);
        }
    }

    /**
     * Tracks all the methods executed in a {@link Robot}
     */
    public final class Bug implements Robot
    {
        private final List<RobotMethod> history = Lists.newArrayList();
        private final Robot robot;

        /**
         * @param robot the robot to track
         */
        public Bug(Robot robot)
        {
            this.robot = robot;
        }

        @Override
        public void alert()
        {
            this.robot.alert();
            this.history.add( RobotMethods.newAlert() );
        }

        @Override
        public void log(String message)
        {
            this.robot.log(message);
            this.history.add( RobotMethods.newMessage(message) );
        }
        
        @Override
        public void move(int x, int y)
        {
            this.robot.move(x, y);
            this.history.add( RobotMethods.newMove(x, y) );
        }

        /**
         * Executes all the methods in the same order as were called
         * on this robot
         *  
         * @param robot the robot to execute all methods on
         */
        public void playbackOn(Robot robot)
        {
            for (RobotMethod method : this.history) {
                method.execute(robot);
            }
        }        
    }

    /**
     * Let's track some robots
     */
    public class BugTest
    {
        private final RobotTracker robotTracker = 
            new RobotTracker();
        
        private final RobotFactory robotFactory = 
            new RobotFactory(this.robotTracker);
        
        @Test
        public void playbackOn() throws Exception
        {
            final String message = "Hello";
            final int x = 1;
            final int y = 1;
            
            Robot buggedRobot = this.robotFactory.newRobot();
            
            buggedRobot.alert();
            buggedRobot.log(message);
            buggedRobot.move(x, y);
                    
            Bug bug = this.robotTracker.latestBug();
            
            RobotImpl mimic = new RobotImpl();        
            bug.playbackOn(mimic);
            
            Assert.assertEquals(message, mimic.log());
            Assert.assertEquals(x, mimic.x());
            Assert.assertEquals(y, mimic.y());
        }
    }

Imagine that you are a spy and have been assigned the task to infiltrate a robot factory to plant a tracking device which will allow you to place a bug in every robot produced by the factory and record every action it makes. That bug can then be used to replicate all the actions the robot made on another identical robot.

    /**
     * Let's infiltrate the factory
     */
    public class RobotFactory
    {
        private final RobotTracker robotTracker;
    
        RobotFactory(RobotTracker robotTracker)
        {
            this.robotTracker = robotTracker;
        }

        public Robot newRobot()
        {
            Robot robot = new RobotImpl();

            /* bug will be placed and go unnoticed  */         
        return this.robotTracker.wasCreated(robot);
        }
    }

The Robot is described as follows

    public interface Robot
    {
      public void alert();        
      public void log(String message);    
      public void move(int x, int y);
    }

There are a couple of things that need to be taken care off. First is how can you tell when a robot alerts, logs or moves? In other words, how do you trace a method call? The simplest way is to use composition.

    public final class Bug implements Robot
    {
      private final Robot robot;

      /**
       * @param robot the robot to track
       */
      public Bug(Robot robot)
      {
          this.robot = robot;
      }

      @Override
      public void alert()
      {
          /*
           * Alert was just called!
           */
          this.robot.alert();
      }

      /* cont.d */
    }

Notice how the Bug class must implement the Robot interface so that it can perform the same actions as the robot. (It also helps go unnoticed) The second challenge is how do you “save” a method call when a method is not a first class citizen?

For that we need an interface to describe a method that executes on a Robot

    public interface RobotMethod
    {
        public void execute(Robot robot);
    }

The reason there is a need for an interface is that each implementation differs on which method it calls on the Robot yet we want to treat them all the same when executed on a robot.

    public void playbackOn(Robot robot)
    {
        for (RobotMethod method : this.history) {
            method.execute(robot);
        }
    }

Notice how the implementation of the RobotMethod also keeps the parameters needed to execute a specific method.

Finally use a simple List to keep track of all the methods executed in order simply by adding them to the list.

In summary

  • create a class that implements the same interface as your Robot
  • have a reference to the actual robot
  • delegate each method call to the robot
  • on every method call create a new instance from the class describing the method that was executed
  • add that instance to the list

Challenge

Calling developers to write a post showing an implementation on another language (ruby/javascript)

The principle of the command pattern can be used to implement an undo/redo feature but you also need to think of any state changes

Source

]]>
Mon, 14 Mar 2011 00:00:00 +0200
On reusability (Part 2) ...Misconceptions https://qnoid.com/2011/03/09/On-reusability-part-2-Misconceptions.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2011/03/09/On-reusability-part-2-Misconceptions.html
/**
     * An interface defining a single method you want to reuse
     */
    public interface MathOperation
    {
        public double op(double number);
    }

    /**
     * All available operators
     */
    public class MathOperations
    {
        /*
         * In an OO world an Object is a first class citizen.
         * To have an object you need a class
         */
        private static final class Multiplication implements MathOperation
        {     
            private final double multiplier;

            private Multiplication(double multiplier)
            {
                this.multiplier = multiplier;
            }

            public double op(double number){
            return number * this.multiplier;
            }
        }

        private static final class Addition implements MathOperation
        {     
            private final double amount;
            
            private Addition(double amount)
            {
                this.amount = amount;
            }
            
            public double op(double number){
            return number + this.amount;
            }
        }

        /*
         * Reusable! operations  
         */
        public static final MathOperation MULTIPLY_BY_2 = 
            new Multiplication(2);
        
        public static final MathOperation MULTIPLY_BY_PI = 
            new Multiplication(Math.PI);
        
        public static Addition addition(double amount){
        return new Addition(amount);
        }

        public static MathOperation multiplication(double multiplier) {
        return new Multiplication(multiplier);
        }
    }

    /**
     * All available formulas for your perusal
     */
    public class Formulas
    {
        public static final Formula AREA_OF_CIRCLE = Formula.newFormula(
                MathOperations.MULTIPLY_BY_2,
                MathOperations.MULTIPLY_BY_PI
        );
    }

    /**
     * Describes a list of operations
     */
    public final class Formula
    {
        /**
         * Create a new formula which applies the operators in the order
         * specified
         * 
         * @param operators the operators to apply in sequence
         * @return a new formula for the spcified operators
         * @see MathOperations
         */
        public static final Formula newFormula(MathOperation... operators){
        return new Formula( Lists.newArrayList(operators) );    
        }
        
        private final List<MathOperation> operations;

        private Formula(List<MathOperation> operators)
        {
            this.operations = operators;
        }

        public double apply(double number)
        {
            for (MathOperation operation : this.operations){
                number = operation.op(number);
            }
            
        return number;
        }
    }


    /**
     * Code that is fun to use
     */
    public class FormulaTest
    {
        @Test
        public void areaOfCircle() throws Exception
        {        
            double r = 1;
            
            Assert.assertEquals(
                    2 * Math.PI, 
                    Formulas.AREA_OF_CIRCLE.apply(r));        
        }

        @Test
        public void formula() throws Exception
        {
            int n = 9;
            
            Formula formula = 
                Formula.newFormula(
                    MathOperations.addition(1),
                    MathOperations.multiplication(n),
                    MathOperations.division(2)
                    );
            
            Assert.assertEquals(45.0, formula.apply(n));        
        }
        
        @Test
        public void areaOfTriangle() throws Exception
        {        
            int base = 10;
            int height = 10;
            
            Formula areaOfTriangle = 
                Formula.newFormula(
                    MathOperations.multiplication(height),
                    MathOperations.division(2)
                    );
            
            Assert.assertEquals(50.0, areaOfTriangle.apply(base));        
        }    
    }

Methods aren’t reusable. Objects are.

    public static final MathOperation MULTIPLY_BY_2 = 
        new Multiplication(2);
    
    public static final MathOperation MULTIPLY_BY_PI = 
        new Multiplication(Math.PI);

Notice how

    public double multiplyBy(double number, double multiplier){
    return number * multiplier;
    }

turned into a class

    public final class Multiplication
    {     
        private final double multiplier;

        public Multiplication(double multiplier)
        {
            this.multiplier = multiplier;
        }

        public double multiply(double number){
        return number * this.multiplier;
        }
    }

At first you might gasp that a single method has turned into a class. Misko Hevery actually has something to say about this

Recently I got an email from someone pointing out that doing proper Single Responsibility Principle, often resulted in classes which had exactly one method. Odd? Well, actually, it is a function in disguise.

There isn’t such a thing as a class that does too little. If there is a reason for a class to exist it will manifest in your code whether you choose to ignore it or not. Worse it won’t stay hidden but will plague the design of the rest of your code.

Classes not only aid in your design but also sed light on the problem domain you are currently trying to solve. They allow you to see further. If you don’t have classes, you can’t think of relationships.

Adding methods, whether static or not, keep your code from evolving. They are not extensible since you need to add a new one every time and don’t allow your code to be treated uniformly creating unnecessary complexity which could have been avoided otherwise.

        for (MathOperation operation : this.operations){
            number = operation.op(number);
        }

So the next time you are tempted to add a new method, stop. Think whether it really makes sense or is a mere illusion to feed your appetite for code.

Notice how you can easily introduce more Operations effectively extending Formula through composition

Disclaimer This might look like a trivial example that rarely applies in a real life scenario. In my experience this is not the case. Think of bytes and sockets, sql and jdbc connections, queries and services, http requests and clients, messages and message dispatchers.

Source

]]>
Wed, 09 Mar 2011 00:00:00 +0200
On reusability (Part 1) ...Misconceptions https://qnoid.com/2011/03/07/On-reusability-part-1-misconceptions.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2011/03/07/On-reusability-part-1-misconceptions.html
/**
     * This isn't OO
     */
    public class Numbers
    {
        /*
        public static double multiplyBy1(double number)
        public static double multiplyBy10(double number)    
        public static double multiplyBy100(double number)    
        public static double multiplyBy1000(double number)
        */
        public static double multiplyBy(double number, double multiplier){
        return number * multiplier;
        }
        /*
        public static double add1(double number)
        public static double add10(double number)    
        public static double add100(double number)    
        public static double add1000(double number)    
        */
        public static double add(double number, double value){
        return number + value;
        }    
    }

    /**
     * Naive identification of a class
     */
    public class Number
    {
        private final double number;
        
        public Number(double value)
        {
            this.number = value;
        }

        /*
        public double multiplyBy1()
        public double multiplyBy10()    
        public double multiplyBy100()    
        public double multiplyBy1000()
        */
        public double multiplyBy(double number, double multiplier){
        return number * multiplier;
        }

        /*
        public double add1()
        public double add10()    
        public double add100()    
        public double add1000()    
        */
        public double add(double number, double value){
        return number + value;
        }    
    }

    /**
     * This is the result of failing to identify a class in {@link Numbers} 
     * that models a math operation thus having to handle different types of
     * formulas.
     */
    public class AbusingTheIfFormula
    {
        public static final int AREA_OF_CIRCLE = 1;
        public static final int AREA_OF_TRIANGLE = 2;
        public static final int N = 3;
        
        private final double base;

        /**
         * On which type does it make sense?
         */
        public AbusingTheIfFormula()
        {
            this.base = 0.0;
        }
        
        /**
         * @param base only related to a specific type
         */
        public AbusingTheIfFormula(double base)
        {
            this.base = base;
        }

        /**
         * You are forced to abuse the if now
         */
        public double op(double number, int type)
        {
            if(AREA_OF_CIRCLE == type){
                
                number = Numbers.multiplyBy(number, Math.PI);
                number = Numbers.multiplyBy(number, 2);
                
            return number;
            }
            else if(AREA_OF_TRIANGLE == type)
            {
                if(this.base != 0.0)
                {
                    number = Numbers.multiplyBy(base, number);
                    
                return number / 2;
                }
            }
            else if(N == type)
            {
                double original = number;
                number = Numbers.add(number, 1);
                number = Numbers.multiplyBy(original, number);
                
            return number / 2;
            }
            
        throw new UnsupportedOperationException("Uknown type: " + type);
        }
    }

    /**
     * Trying to come up with a way out of this mess
     */
    /**
     * An interface is forced to handle different kinds of formulas since 
     * we failed to identify an Operation class from {@link Numbers} 
     * that we can actually reuse.
     */
    public interface Formula
    {
        public double op(double number);
    }

    /**
     * Is it really about different formula implementations? Unfortunately since 
     * there isn't an <b>operation class</b> to have a relationship with a 
     * formula one, the only way is to implement different classes for different 
     * formulas. Naively "reusing" {@link Numbers#multiplyBy(double, double)} 
     * affecting any class related to it while still losing on actual reusability of
     * operations. 
     */
    public class Formulas
    {
        public static class AreaOfCircleFormula implements Formula
        {
            public double op(double radius)
            {
                double value = Numbers.multiplyBy(radius, 2);
                
            return Numbers.multiplyBy(value, Math.PI);
            }
        }
        
        public static class AreaOfTriangleFormula implements Formula
        {
            private final double height;

            public AreaOfTriangleFormula(double height)
            {
                this.height = height;
            }

            public double op(double base)
            {
                double value = Numbers.multiplyBy(base, this.height);
                
            return value / 2;
            }
        }
        
        public static class NFormula implements Formula
        {
            public double op(double n)
            {
                double value = Numbers.add(n, 1);
                value = Numbers.multiplyBy(value, n);
                
            return value / 2;
            }
        }
    }

Or why extracting a method is overrated and abused

One of the most frequent [eureka][7] moments we get as developers when writing code is when finding a method to extract in order to reuse it.

In an OO world however there is only as much gain since you can only use that method within that class. The problem resides in that a function is not a first class citizen.

Simply put, you need to carry the class that defines that method in every place you want to use it. This is easier said than done though depending on how you’ve designed your class. Especially if you’ve assigned more than [1 responsibilities][8] to it.

So what you end up doing “at best” is introduce a static method, at worst copy and paste. There is a real issue here though and that is failing to identify a class that has manifest in your code leading to an explosion of methods.

This not only makes your API hard to use but also forces you to write more, sometimes even complicated code. Solely on the fact that in an OO world you have the concept of class relationships which is equally important to the class.

When you see procedural code, you only think procedural. So next time you start coding, look for the class!

Try it with your code to see what objects you come up with and how a correctly identified class simplifies things.

Source

[7]: http://en.wikipedia.org/wiki/Eureka_(word) “This exclamation is most famously attributed to the ancient Greek scholar Archimedes; he reportedly proclaimed “Eureka!” when he stepped into a bath and noticed that the water level rose — he suddenly understood that the volume of water displaced must be equal to the volume of the part of his body he had submerged.” [8]: http://en.wikipedia.org/wiki/Single_responsibility_principle “The single responsibility principle states that every object should have a single responsibility, and that responsibility should be entirely encapsulated by the class”

]]>
Mon, 07 Mar 2011 00:00:00 +0200
Why can't programmers... design software? https://qnoid.com/2011/02/23/Why-cant-programmers-design-software.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2011/02/23/Why-cant-programmers-design-software.html

There is a followup to this post. We need to talk about FizzBuzz.

/**
     * Use to convert numbers to fizz/buzz representations
     */
    public final class FizzBuzzOperator
    {
        private final FizzBuzzStrategy fizzbuzzStrategy;
        
        /**
         * @param fizzbuzzStrategy the strategy to use to find the 
         * {@link FizzBuzzOperation}
         */
        private FizzBuzzOperator(FizzBuzzStrategy fizzbuzzStrategy) {
            this.fizzbuzzStrategy = fizzbuzzStrategy;
        }

        /**
         * Returns the fizz/buzz representation of the given number
         * 
         * @param number the number to use
         */
        public String op(int number){
        return this.fizzbuzzStrategy.fizzBuzzOf(number).toString();
        }
    }

First time I found out about FizzBuzz was when I came across Jeff Atwood’s blog post Why Can’t Programmers.. Program?. As you would expect (since CodingHorror draws a lot of developers) answers begun to spur on how you can go on implementing it. On a closer look however you will notice that most (if not all) of those answers are on the basis of a switch/if statement and then try to apply the most obscure “optimisation” to come up with fewer lines and less characters failling to see the real issue. [Disclaimer]

What if I told you that the answer to the FizzBuzz algorithm is only one line of code without any if and it looks like that

    public String op(int number){
    return fizzBuzzOf(number).toString();
    }

Not surprisingly it starts out with a single interface

    public interface FizzBuzzOperation
    {
      public boolean applies(int number);
      public String toString();
    }

With 3 enums

    public enum ModFizzBuzz implements FizzBuzzOperation
    {
    FizzBuzz(15),
    Buzz(5),
    Fizz(3);
  
    private final int mod;
  
    private ModFizzBuzz(int mod) 
    {
      this.mod = mod;
    }

    public boolean applies(int number) {
    return number % this.mod == 0;
    }
    }

And that’s all. Really. What’s left out is what strategy you need to use to find the corresponding FizzBuzzOperation. So here is one:

    public static final FizzBuzzStrategy DEFAULT = new FizzBuzzStrategy() 
    {
        private List<ModFizzBuzz> fizzbuzzes = 
            Lists.newArrayList(
                    ModFizzBuzz.FizzBuzz, 
                    ModFizzBuzz.Buzz, 
                    ModFizzBuzz.Fizz);
        
        @Override
        public FizzBuzzOperation fizzBuzzOf(final int number)
        {
            for (FizzBuzzOperation fizzbuzz : this.fizzbuzzes) {
                if(fizzbuzz.applies(number))
                    return fizzbuzz;
            }
            
            /*
             * Default FizzBuzzOperation - if none applies - 
             * returns the number as a String
             */
        return new FizzBuzzOperation() 
        {       
            @Override
            public boolean applies(int number){
            return true;
            }

            @Override
            public String toString() {
            return String.valueOf(number);
            }
        };  
        }
    };

So here a new challenge. Find the most efficient FizzBuzzStrategy and get a postcard from Edinburgh as well as a budge(1) on truly mastering FizzBuzz.

Here is the interface you need to implement

    /**
     * Implementations should provide an algorithm to find a 
     * {@link FizzBuzzOperation} for a number
     */
    public interface FizzBuzzStrategy
    {
         /**
         * Given a number we need to find the corresponding 
         * {@link FizzBuzzOperation}
         * @param number an arbitary number
         * @return the {@link FizzBuzzOperation} to apply
         */
        public FizzBuzzOperation fizzBuzzOf(int number);
    }

As with every software engineering problem you don’t really see the big picture if you are always in “low level” code. Another reason why you need to think in terms of objects

Note: There is also a “FizzBuzz” post that can be used to post solutions in the forrst started by @acrookston which got my attention and decided to write this post

Disclaimer: Jeff was really trying to make a point about writing an algorithm not doing software design, which is a personal view.

1: Wish there was a way to award budges @kyle

Source

]]>
Wed, 23 Feb 2011 00:00:00 +0200
It's about software design - IASD https://qnoid.com/2011/02/20/software-design.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2011/02/20/software-design.html
/* 
     * IASD (It's about software design)
     */
    public class FilterTest 
    {
        @Test
        public void findByName() throws Exception 
        {
            Person john = new Person("John", 20);
            Person markos = new Person("Markos", 30);

            Condition<Person> isNamedJohn = Conditions.hasName("John");
            
            Person actual = Filters.of(john, markos).find( isNamedJohn );
            
            Assert.assertEquals(john, actual);      
        }
        
        @Test
        public void findByAge() throws Exception 
        {
            Person john = new Person("John", 20);
            Person markos = new Person("Markos", 30);       
            
            Condition<Integer> between17and25 = 
                new IntegerConditionChain()
                        .gt(17)
                        .lt(25);
            
            Condition<Person> agedBetween17and25 = 
                Conditions.age( between17and25 );
            
            Person actual = Filters
                .of(john, markos)
                .find( agedBetween17and25 );
            
            Assert.assertEquals(john, actual);      
        }
        
        @Test
        public void findByNameAndAge() throws Exception 
        {
            Person johnAged20 = new Person("John", 20);
            Person johnAged21 = new Person("John", 21);
            Person johnAged29 = new Person("John", 29);
            Person johnAged30 = new Person("John", 30);
            Person markosAged30 = new Person("Markos", 29);
            
            Condition<Integer> between20and30 = 
                new IntegerConditionChain()
                        .gt(20)
                        .lt(30);

            Condition<Person> namedJohnBetween20And30 = 
                new PersonConditionChain()
                        .hasName("John")
                        .age(between20and30);
            
            List<Person> actual = Filters
                .of(johnAged20, 
                    johnAged21, 
                    johnAged29, 
                    johnAged30, 
                    markosAged30)
                .list( namedJohnBetween20And30 );
            
            Assert.assertEquals(2, actual.size());      
            Assert.assertEquals(
                    Lists.newArrayList(johnAged21, johnAged29), 
                    actual);        
        }   
    }

Find it amazing how a single method interface can be the inspiration to a good software design.

Here is the culprit.

	public interface Condition<T>
	{
		public boolean apply(T type);
	}

The idea is that you can apply a condition to any type and see if it adheres to that.

Notice how the usage of generics elevates the design. Using an Object instead would have made the code vulnerable to ClassCastException and fragile to piece together with other classes. An interface instead would force client code to implement it, pose a limit on the conditions you can apply and is rather stiff.

Then came the Filter allowing you to extract the types that satisfy the conditions of yours.

	public interface Filter<T> 
	{
		public T find(Condition<T> condition);
		public List<T> list(Condition<T> condition);
	}

Then the requirement to apply a list of Conditions.

	public interface ConditionChain<T> extends Condition<T>
	{
		public boolean apply(T type);
		public ConditionChain<T> addCondition(Condition<T> condition);	
	}

Without differentiating from the Condition interface thus being able to accomodate for it in the existing API.

With implementations providing public methods to specific conditions that make sense on the type

	public final class IntegerConditionChain implements ConditionChain<Integer>
	{	
		public IntegerConditionChain gt(final int that) 
		{
			this.addCondition(new Condition<Integer>(){
	
				@Override
				public boolean apply(Integer value) {
				return value > that;
				}
			});
			
		return this;
		}
	
		public IntegerConditionChain lt(final int that) 
		{
			this.addCondition(new Condition<Integer>(){
	
				@Override
				public boolean apply(Integer value) {
				return value < that;
				}
			});
			
		return this;
		}
	}

It’s your turn now to DRY the design by introducing a class that encapsulates the implementation of the methods related to the ConditionChain thus increasing cohesion and lowering coupling for creating specific conditions without abusing inheritance.

While doing so you get to win a postcard from Edinburgh.

Source

]]>
Sun, 20 Feb 2011 00:00:00 +0200
Take a step back. Take a deep breath. Take pen and paper https://qnoid.com/2011/02/10/Take-a-step-back.-Take-a-deep-breath.-Take-pen-and-paper.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2011/02/10/Take-a-step-back.-Take-a-deep-breath.-Take-pen-and-paper.html
public final class CRUDServiceImpl<T> implements CRUDService<T> 
    {
        private final PersistenceManager pm;

        public CRUDServiceImpl(PersistenceManager pm)
        {
            this.pm = pm;
        }

        @Override
        public void store(T model) {
            pm.makePersistent(model);
        }
        
        @Override
        public List<T> list(QueryStrategy<T> queryStrategy)
        {
            Query query = pm.newQuery(queryStrategy.type());

            queryStrategy.configure(query);
                
            /*
             * Effective Java 2nd Edition, Joshua Bloch, Item 24, page 116
             */
            @SuppressWarnings("unchecked")
            List<T> result = (List<T>)query.executeWithArray(queryStrategy.arguments());
        
        return result;
        }

        @Override
        public T unique(QueryStrategy<T> queryStrategy)
        {
            List<T> list = this.list(queryStrategy);
            
            if(list.isEmpty())
            {
                /*
                 * It is a good idea to provide as much information as possible 
                 * to the exception. That way the client code can take action. 
                 */
                throw new ObjectNotFoundException(queryStrategy.type());
            }
            
        return list.get(0);
        }
    }

    /**
     * QueryStrategies ready for consumption
     */
    public final class QueryStrategies
    {
        public static final class GreetingStrategies
        {
            public static QueryStrategy<Greeting> latestByAuthor(User author) 
            {
                QueryConfiguration configuration = 
                    new QueryConfigurationBuilder()
                        .filter("author == :author")
                        .ordering("date desc")
                        .build();
            
            return new QueryStrategyBuilder<Greeting>(Greeting.class)
                        .args(author)
                        .configuration( configuration )
                        .build();
            }
            
            public static QueryStrategy<Greeting> mostRecent(int toExl) 
            {
                QueryConfiguration configuration = 
                    new QueryConfigurationBuilder()
                        .filter("date desc")
                        .toExl(toExl)
                        .build();
                
                return new QueryStrategyBuilder<Greeting>(Greeting.class)
                    .configuration( configuration )
                    .build();
            }                
        }
        
        private QueryStrategies(){}
    }

    /*
     * Let's see how it looks from the client side
     */
    public class CRUDServiceImplTest
    {
        private final PersistenceManager pm = pmf.getPersistenceManager();
        private final CRUDService<Greeting> service = new CRUDServiceImpl<Greeting>(pm);
        
        @Test
        public void getLatestByAythor() throws Exception
        {
            User author = new User() {};
            
            QueryStrategy<Greeting> queryStrategy = 
                GreetingStrategies.latestByAuthor(author);
            
            Greeting greeting = service.unique(queryStrategy);
        }
        
        @Test
        public void mostRecent() throws Exception
        {
            int count = 10;
            
            QueryStrategy<Greeting> queryStrategy = 
                GreetingStrategies.mostRecent(count);
            
            List<Greeting> greetings = service.list(queryStrategy);
        }
    }

The inspiration for this post comes from @sirsean “Writing DAO classes for JDO on Google Appengine just got easier”.

Whenever you realize you are writing too many if(s) or you somehow repeat yourself, you need to TTT.

  • Take a step back
  • Take a deep breath
  • Take pen and paper

But hey I don’t have time for that!. I don’t have to think about extensibility, reusability, maintenance or testing. I just need something quick and dirty this is trivial!

Back to code. It seems like everytime we use the Query instance, we have to configure it. The problem however is that Query is something we don’t get access to until we hit that line of code

    Query query = pm.newQuery(vhQuery.getClazz());

which unfortunately is within that BaseVHDao class and specifically in the BaseVHDao#list method. That leaves us with no option but to configure it right there with little room for extending or reusing that configuration as we are limited to:

  • Modify that method slightly (violating Open/Closed Principle)
  • Extend from BaseVHDao (abusing inheritance)
  • Create a new method by copying/pasting and changing it slightly (maintenance nightmare)
  • Create a new method which encapsulates the common code and re-use (not fun)

OR use delegation.

There are 2 advantages of using delegation in this case.

  • Don’t have to expose Query to client code
  • It is easily extensible

Since we need to support different configurations we introduce a simple interface like

    public interface QueryStrategy<T>
    { 
         public void configure(Query query); 
	}

Java Note: By making the QueryStrategy typed as well notice how we enforce a strong typing with the CRUDService. That way we effectively only pass valid QueryStrategy(ies)

Now what about args and clazz that we also need to have available? Let’s add them to that interface.

	public interface QueryStrategy<T>
	{
		public void configure(Query query);
		public Class<T> type();
		public Object[] arguments();
	}

That looks great. However, what started as a one method interface to configure the query ended up somewhat “stiff” should we wish to extend a QueryStrategy for the same type and arguments. So let’s add the final piece in the puzzle. (Disclaimer)

	public interface QueryConfiguration
	{
		public void configure(Query query);
	}

In case you can’t see the relationship between them, it’s composition. Let me make it clearer.

	public final class QueryStrategyImpl<T> implements QueryStrategy<T> 
	{
		private final QueryConfiguration configuration;

		@Override
		public void configure(Query query) {
			this.configuration.configure(query);
		}
	}

Source

Disclaimer In this example it’s not that big of a deal but it’s good to keep an eye for things that might change and draw your lines early. The good thing is that even if you don’t add the extra interface right now, your API is designed to accept that change without affecting the client and with minimal refactoring cost.

If you are a designer here is a challenge to win a postcard from Edinburgh

]]>
Thu, 10 Feb 2011 00:00:00 +0200
How To Think Of... Aspects https://qnoid.com/2011/02/03/aspects.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2011/02/03/aspects.html
public class AspectSets
    {
        /**
         * Create a new Set which is strong on duplicates 
         * 
         * @param <E> the type of the {@link Set}
         * @param elements the elements to create the set from
         * @return a new Set which is only keen on holding added 
         * elements more than once.
         */
        public static <E> Set<E> newSetOnDuplicates(final E[] elements)
        {
            final Aspect<E> isUnique = Aspects.uniqueAspect();
            
            /*
             * Using a set to handle multiple duplicates
             * (elements that occur more than 2 times)
             */
            return new HashSet<E>( Lists.newArrayList(elements) )
            {
                private static final long serialVersionUID = 
                                                      -8073479479226481874L;

                /**
                 * Add the element only if its a duplicate
                 */
                @Override
                public boolean add(E e) 
                {                
                    if(isDuplicate(e))
                        return super.add(e);
                    
                return false;
                }

                private boolean isDuplicate(E e) {
                return !isUnique.apply(e);
                }
            };
        }
    }

    public class Aspects
    {
        /**
         * @param <E> the type of the objects
         * @return a new Aspect on unique objects
         */
        public static <E> Aspect<E> uniqueAspect()
        {
        return new Aspect<E>()
            {
                /*
                 * Holding all unique elements
                 */
                private final Set<E> uniques = new HashSet<E>();
                
                /**
                 * @return true if element is unique
                 */
                @Override
                public boolean apply(E e) {
                return this.uniques.add(e);
                }
            };
        }
    }

    /**
     * Survival of the fittest
     */
    public class AspectSetsTest
    {
        @Test
        public void newSetOnDuplicates() throws Exception
        {
            String[] animals = {"cat", "cat", "cat", 
                                "dog", "dog", 
                                "parrot", 
                                "lion", 
                                "zebra", "zebra"};
            
            Set<String> duplicatesOnly = AspectSets.newSetOnDuplicates(animals);
            
            Assert.assertEquals(3, duplicatesOnly.size());
            Assert.assertEquals(
                    Sets.newHashSet(
                            new String[] {"cat", "dog", "zebra"}), 
                            duplicatesOnly);
            
            Assert.assertTrue(duplicatesOnly.add("lion"));        
            Assert.assertEquals(4, duplicatesOnly.size());
            Assert.assertEquals(
                    Sets.newHashSet(
                            new String[] {"cat", "dog", "zebra", "lion"}), 
                            duplicatesOnly);
            
            Assert.assertFalse(duplicatesOnly.add("monkey"));        
            Assert.assertEquals(4, duplicatesOnly.size());
            Assert.assertEquals(
                    Sets.newHashSet(
                            new String[] {"cat", "dog", "zebra", "lion"}), 
                            duplicatesOnly);
            
            Assert.assertTrue(duplicatesOnly.add("monkey"));
            Assert.assertEquals(5, duplicatesOnly.size());
            Assert.assertEquals(
                    Sets.newHashSet(
                            new String[] {"cat", "dog", "zebra", "lion", "monkey"}), 
                            duplicatesOnly);
        }
    }

As inspired by @sealabcore’s “Return only duplicate values from ruby array.”

Instead of extending from HashSet (Disclaimer)

    public class DuplicatesOnlySet<E> extends HashSet<E>
    {
        private final Set<E> uniques = new HashSet<E>();

        public  DuplicatesOnlySet(Collection<? extends E> c) 
        {
            super(c);
        }

        @Override
        public boolean add(E e) 
        {                
            /*
             * This is getting called at the constructor 
             * thus you will get a NPE since
             * {@link #uniques} isn't initialised yet.
             */
            if(!this.uniques.add(e))
                 return super.add(e);
        
        return false;
        }
    }

and falling into the trap of a NullPointerException.

Or using composition forcing you to create delegate calls to the backing Set and making sure all necessary method calls go through your modified #add(E e) method, you can use the notion of aspects.

Note that the constructor

    public HashSet(Collection<? extends E> c)

is actually calling the #addAll(Collection<? extends E> c) method which in return calls #add(E e) thus filtering the elements on construction.

What’s cool is that the way its integrated, any method used to traverse the returned Set will give you the expected elements. (Note)

Although we haven’t effectively changed the contract of the Set (“A collection that contains no duplicate elements”), its implementation certainly differs, so make sure you document that

Disclaimer

Technically speaking we do extend from HashSet only anonymously

Source

]]>
Thu, 03 Feb 2011 00:00:00 +0200
The beauty of software design - Designers Challenge https://qnoid.com/2011/02/02/The-beauty-of-software-design-Designers-Challenge.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2011/02/02/The-beauty-of-software-design-Designers-Challenge.html
public class GrindTest
    {    
        @Test
        public void grindMelons() throws Exception
        {
            int noOfMelons = 2;
            
            List<Fruit> melons = Fruits.nFruits( 
                                            noOfMelons, 
                                            Fruits.newFruit(Seed.MELON) );
            
            Grinder<Fruit> newGrinder = Grinders.newGrinder(melons);
            
            /*
             * Let's do some grinding
             */
            Iterable<Seed> seeds = newGrinder
                                    .grind( Blades.FRUIT )
                                    .items();
            
            Assert.assertEquals(
                    noOfMelons * Seed.MELON.noOfSeeds(), 
                    Iterables.size(seeds));
        }
        
        @Test
        public void grindBoxes() throws Exception
        {
            int noOfLoquats = 10;
            int noOfBoxes = 2;
            
            List<Fruit> loquats = Fruits.nFruits( 
                                            noOfLoquats, 
                                            Fruits.newFruit(Seed.LOQUAT) );
            
            List<Box> boxes = Boxes.of( loquats ).times(noOfBoxes);        
            
            Grinder<Box> newGrinder = Grinders.newGrinder(boxes);
            
            /*
             * Grinding till we get the seeds 
             */
            Iterable<Seed> seeds = newGrinder
                                    .grind( Blades.BOX )
                                    .grind( Blades.FRUIT )
                                    .items();
            
            Assert.assertEquals(
                    noOfBoxes * noOfLoquats * Seed.LOQUAT.noOfSeeds(), 
                    Iterables.size(seeds));
        }
    }

It seems that designers draw all the attention in the forrst. Can’t blame them, their designs are pleasant to the eyes. They show emotion. They have soul. Code listings look really borring, lacking any enthusiasm or creativity.

This post won’t bother you with principles on how to think of object oriented code. It’s about the art of software design.

Challenging designers to come up with a design that visualises the code above and reflects its quality and win a postcard from Edinburgh.

Calling all developers to come up with code that’s fun to use, tells a story and elevates software design.

Source

]]>
Wed, 02 Feb 2011 00:00:00 +0200
Urban Legends ...O Is For Object (Part 1) https://qnoid.com/2011/01/28/Urban-legends-o-is-for-object-part-1.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2011/01/28/Urban-legends-o-is-for-object-part-1.html

An urban legend, urban myth, urban tale, or contemporary legend,
is a form of modern folklore consisting of stories usually believed by
their tellers to be true.

After all these years of Object Oriented Programming being taught at universities, cou-nt-less number of books written on the subject, advocates, conferences et. al. you would expect that pretty much by now developers would be convinced of its merits and know to a great extend how to apply its principles.

However this is not the case. Every now and then a discussion will spur about how it’s OK to violate basic principles, how OO makes code difficult to understand and the main argument usually boils down to “there is no need to over-engineer”. Then comes the drama. There isn’t enough time, it costs money, there is no need to do it.

After all this time as developers we fail to see the facts and accept hard core evidence that other computer scientists are presenting us with. Stop pretending like it’s a matter of “personal taste”. This is about software engineering.

Software engineering (SE) is a profession dedicated to designing, implementing, and modifying software so that it is of higher quality, more affordable, maintainable, and faster to build. It is a “systematic approach to the analysis, design, assessment, implementation, test, maintenance and reengineering of software, that is, the application of engineering to software.”

As a developer you should care and feel responsible for the code you are producing.

]]>
Fri, 28 Jan 2011 00:00:00 +0200
The Myth ...O Is For Object (Part 2) https://qnoid.com/2011/01/28/The-myth-o-is-for-object-part-2.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2011/01/28/The-myth-o-is-for-object-part-2.html
/**
     * The result of a myth
     */
    public class UrbanLegend
    {
        public String string;
        
        private String one;
        private String another;
        private Calendar date;
        private boolean status;

        public UrbanLegend(String one, String another, Calendar date, boolean status)
        {
            DateFormat dateFormat = new SimpleDateFormat("ddMMyyyy");
            StringBuilder builder = new StringBuilder();
            
            if(status)
            {
                builder.append(one);
                builder.append(another);
            }
            else
            {
                builder.append(another);
                builder.append(one);
            }
        
            builder.append(dateFormat.format(date.getTime()));
            String string = builder.toString();
            
            this.one = one;
            this.another = another;
            this.date = date;
            this.status = status;
            this.string = string;
        }

        public int tell(int type, String string) throws Exception
        {
            DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");

            String oneName = null;
            String anotherName = null;
            
            if(one == "EDI"){
                oneName = "edinburgh";
            }
            else if(one =="LON"){
                oneName = "london";
            }
            
            if(another == "EDI"){
                anotherName = "edinburgh";
            }
            else if(another =="LON"){
                anotherName = "london";
            }        

            String from = null;
            String to = null;
            
            if(status)
            {
                from = oneName;
                to = anotherName;
            }
            else
            {
                from = anotherName;
                to = oneName;            
            }
            
            switch (type)
            {
            case 0:                    
                System.out.println("Walking down to " + to + " from " + from);
                return 0;
            case 1:
                System.out.println("Flying down to " + to + " from " + from + " in " + string + " class on " + dateFormat.format(date.getTime()));
                
                if(string == "economy")
                {
                    return 200;
                }
                else if(string == "business")
                {
                    return 500;
                }
            default:
                throw new Exception("Invalid type " + type);
            }        
        }
    }

    /**
     * You have to live with it
     */
    public class UrbanLegendTest
    {
        private static final DateFormat dateFormat = new SimpleDateFormat("ddMMyyyy");  
        private static final Calendar now = Calendar.getInstance(); 
        private static final String STRING = 
            String.format("%s%s%s", 
                    Destination.EDINBURGH.code(), 
                    Destination.LONDON.code(),
                    dateFormat.format(now.getTime()));

        @Test
        public void tell() throws Exception
        {
            boolean status = true; //making a choice!
            String string = "business"; //making a choice!
            int type = 1; //making a choice!
            String one = "EDI";
            String another = "LON";
            Calendar date = Calendar.getInstance();

            UrbanLegend myth = new UrbanLegend(one, another, date, status);
            
            Assert.assertEquals(STRING, myth.string);
            Assert.assertEquals(500, myth.tell(type, string));
        }
    }

Though the code is fictional its characteristics unfortunately aren’t. You’ve most likely encountered code like this before plenty of times. In your code base, over at github in startups and large corporations. It has no boundaries. You most likely wrote something like this yourself in the past. Why do you keep writing it?

You struggle as you make an effort to understand it. Align with it as you go back and forth. Trying to digest it all at once. Don’t blame you. This code is hard to follow. The fact that you don’t know the problem is trying to solve doesn’t make it any easier. Can you even tell what the business domain is?

How much time did it take you to write it? Go back and read it again. Can you tell now? Again. How much time did it take you to understand it? Now go away and come back tomorrow. Read it again. Do you still remember what it does? How much time in total do you think it takes everyone reading that code to understand it? How much time will it take you to extend it? To maintain it? To test it. Can you test it? It will only get messy. You want to throw it away. How much time will it take you to write it again? How much time have you wasted?

Ask yourself. What’s wrong with it? It must be something really great this code is doing. Why else would it look that horrible?

Code doesn’t have to look like that.

This isn’t about not knowing what problem is trying to solve. Nor how complicated it might be.

What does

    int type = 1;

even mean? How is this related (if so) to

    String string = "business";

All you can tell is that 1 leads to

    case 1:
        System.out.println("Flying down to " + to + " from " + from + " in " + string + " class on " + dateFormat.format(date.getTime()));

You have to follow all that code down to switch just to find out what it means. Looking back, you knew right there when you made the choice, you don’t need that switch! But there is only that much you can do with an int in an OO world.

Like that string. With a no clear cut relationship between that and the type. Will changing one break the other? Is it relevant? How do you enforce their relationship?

What about all that unrelated code that you have to move out of the way to get a clear picture of what this is all about?

Writing code isn’t subjective. It’s about software design.

Source

]]>
Fri, 28 Jan 2011 00:00:00 +0200
Revelations ...O Is For Object (Part 3) https://qnoid.com/2011/01/28/Revelations-o-is-for-object-part-3.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2011/01/28/Revelations-o-is-for-object-part-3.html
/**
     * It's a revelation
     */
    public final class Route
    {
        public static final class RouteBuilder
        {
            private final Destination from;
            private final Destination to;
            private Calendar date = Calendar.getInstance();
            
            public RouteBuilder(Destination from, Destination to)
            {
                this.from = from;
                this.to = to;
            }
            
            public RouteBuilder onDate(Calendar date)
            {
                this.date = date;
                
            return this;
            }

            public Route build() {
            return new Route(this.from, this.to, this.date);
            }
        }

        private final DateFormat dateFormat = new SimpleDateFormat("ddMMyyyy");
        
        private final Destination from;
        private final Destination to;
        private final Calendar date;

        private Route(Destination from, Destination to, Calendar date)
        {
            
            this.from = from;
            this.to = to;
            this.date = date;
        }

        private void appendDate(StringBuilder builder, Date date, DateFormat dateFormat) {
            builder.append( dateFormat.format(date) );
        }

        private void appendCode(StringBuilder builder, String code) {
            builder.append(code);
        }

        public int via(TransportMethod method) {
        return method.route(this.from, this.to, this.date);
        }
        
        public String bookingCode()
        {
            StringBuilder builder = new StringBuilder();
            
            this.appendCode(builder, this.from.code());    
            this.appendCode(builder, this.to.code());    
            this.appendDate(builder, this.date.getTime(), this.dateFormat);
            
        return builder.toString();
        }
    }

    /**
     * And a well thought design
     */
    public class RouteTest
    {
        private static final DateFormat dateFormat = new SimpleDateFormat("ddMMyyyy");  
        private static final Calendar now = Calendar.getInstance(); 
        private static final String BOOKING_CODE = 
            String.format("%s%s%s", 
                    Destination.EDINBURGH.code(), 
                    Destination.LONDON.code(),
                    dateFormat.format(now.getTime()));
        
        @Test
        public void via() throws Exception
        {
            TransportMethod transportMethod = TransportMethods.BUSINESS_FLYING;                
            Destination from = Destination.EDINBURGH;
            Destination to = Destination.LONDON;

            Route route = new RouteBuilder(from, to).build();

            Assert.assertEquals(BOOKING_CODE, route.bookingCode());
            Assert.assertEquals(500, route.via(transportMethod));
        }
    }

This isn’t about time, money or need. This is about software design

The code above isn’t “better” because it’s eloquent. Nor because it adheres to SOLID principles. It’s because it uses the most basic concept in OO. The Object.

It didn’t derive thinking about extensibility, reusability, maintenance or testing. It wasn’t conceived after a long architectural design discussion. This is OO at its purest form.

Don’t ignore it. Embrace it. It’s liberating.

Source

]]>
Fri, 28 Jan 2011 00:00:00 +0200
The constructor ...Don't abuse the constructor https://qnoid.com/2011/01/22/constructor.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2011/01/22/constructor.html
/** 
     * Don't abuse the constructor
     */
    public class Person 
    {
        private final String name;
        private final int age;
        
        public Person(String[] args) 
        {
            this.name = args[0];
            this.age = Integer.parseInt( args[1] );
        }
        
        public Person(byte[] name, Calendar dob) throws UnsupportedEncodingException
        {
            this.name = new String(name, "UTF-8");
            this.age = Years.yearsBetween( new DateTime(Calendar.getInstance()), new DateTime(dob)).getYears();
        }

        /*
         * How do you test that without getting in the constructor mess? 
         */
        public boolean isOlderThan(int age){
        return this.howOldAreYou() > age;
        }
        
        public int howOldAreYou(){
        return this.age;
        }
        
        public String whatsYourName() {
        return this.name;
        }   
    }

    /**
     * It's a pain to test!
     */
    public class PersonTest 
    {
        @Test
        public void newPersonOfArray() throws Exception 
        {
            String name = "Markos";
            int age = 30;
            
            String[] args = {name, String.valueOf(age)};        
            Person person = new Person(args);
            
            Assert.assertEquals(age, person.howOldAreYou());
            Assert.assertEquals(name, person.whatsYourName());
        }
        
        @Test
        public void newPersonOfByteArrayAndCalendar() throws Exception 
        {
            byte[] name = new byte[]{'I', 'n', 'f', 'a', 'n', 't'};     
            Calendar dob = Calendar.getInstance();
            
            Person person = new Person(name, dob);
            
            Assert.assertEquals(0, person.howOldAreYou());
            Assert.assertEquals("Infant", person.whatsYourName());              
        }
    }

    /**
     * Nice and clean
     */
    public class Person 
    {
        private final String name;
        private final int age;
        
        public Person(String name, int age)
        {
            this.name = name;
            this.age = age;     
        }
        
        public boolean isOlderThan(int age){
        return this.howOldAreYou() > age;
        }
        
        public int howOldAreYou(){
        return this.age;
        }
        
        public String whatsYourName() {
        return this.name;
        }   
    }

    public class Persons 
    {
        public static Person valueOf(String[] args)
        {
            String name = args[0];
            int age = Integer.parseInt( args[1] );

        return new Person(name, age);
        }

        public static Person valueOf(byte[] itsName, Calendar dob) throws UnsupportedEncodingException
        {
            String name = new String(itsName, "UTF-8");
            int age = Years.yearsBetween( new DateTime(Calendar.getInstance()), new DateTime(dob)).getYears();
            
        return new Person(name, age);
        }
    }

    /**
     * Smooth and clean testing!
     */
    public class PersonTest 
    {
        @Test
        public void howOldAreYou() throws Exception 
        {
            Person person = new Person(null, 30);
            
            Assert.assertTrue( person.isOlderThan(29) );        
            Assert.assertFalse( person.isOlderThan(30) );       
            Assert.assertFalse( person.isOlderThan(31) );       
        }
    }

It’s a common misconception that since constructors are there to construct an object it’s only resonable to have related code also there. You should do well to keep your constructors for assignments and nothing more. Depending on the amount of “work” done in a constructor you’ll either end up wasting resources when you shouldn’t or deal with some nasty bugs while also making testing much harder.

In this example although a Person is defined by its name and age a String array is passed in instead. Indeed this might well be what you have (through a main method or an input field) and might think that saves you from having to convert it every time you want a Person but think again.

All you really need to construct a Person is a name (String) and an age (int). So even if you do have those, you still need to convert them to a String array only to have the constructor convert them back. That means knowing how the array is constructed, (name at index 0, age at index 1) which is an irrelevant and possible fragile invariant to have on the Person.

In the same manner you force unrelated dependencies (Calendar?) leading to high coupling, making your code harder to understand (how’s a byte array related to a Person?) and sacrificing constructor chaining. You also risk exposing that burden to any classes related to Person. Especially subclasses which don’t have a choice but to accept those constructors.

In most cases all you need is some factory methods that do the conversions for you. That way you’ve effectively seperated conversion and construction and kept your class clean. Depending on how complicated the conversion is you may realise you need a new class altogether, like a parser.

On stackoverlow there is a great answer in case things get really out of hand and you start throwing exceptions from the constructor.

Kudos

Joel Spolsky and Jeff Atwood for their contributtion of StackOverflow.
Yoda Time for an excellent replacement to the abysmal date API.

PS. When creating a String from a byte array make sure you always specify the encoding!

Source

]]>
Sat, 22 Jan 2011 00:00:00 +0200
State Machine ...Don't Abuse The If https://qnoid.com/2011/01/19/state-machine.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2011/01/19/state-machine.html
/**
     * Abusing if like there is no tomorrow
     */
    public class User
    {
        private static final String REGISTERING = "registering user '%s'";
        private static final String NOT_REGISTERED = "user '%s' not registered";
        private static final String ALREADY_REGISTERED = "User %s already registered";
        private static final String ALREADY_LOGGED_IN = "User %s already logged in";    

        private final String username;

        /*
         * Notice how your class is filled with non-final fields making it harder to
         * debug, make it thread-safe and extend.
         */
        private boolean registered;
        private boolean loggedIn;

        /**
         * @param username
         */
        public User(String username)
        {
            this.username = username;
            this.registered = false;
            this.loggedIn = false;
        }

        void nowRegistered() {
            this.registered = true;
        }

        void nowLoggedIn() {
            this.loggedIn = true;
        }

        public void register()
        {
            if(this.isRegistered()){
                throw new IllegalStateException( String.format(ALREADY_REGISTERED, this));
            }
            else
            {
                System.out.println( String.format(REGISTERING, this));
                this.nowRegistered();
            }
        }

        public void login()
        {
            if(this.isLoggedIn()){
                throw new IllegalStateException( String.format(ALREADY_LOGGED_IN, this) );            
            }
                    
            if(!this.isRegistered()){
                throw new UnregisteredUserException( String.format(NOT_REGISTERED, this) );
            }
            else
            {
                System.out.println( String.format("'%s' logged in", this) );
                this.nowLoggedIn();            
            }            
        }

        public boolean isRegistered() {
        return this.registered;
        }

        public boolean isLoggedIn() {
        return this.loggedIn;
        }

        @Override
        public String toString() {
        return this.username;
        }    
    }

    /**
     * Define your states
     */
    public enum UserState
    {
        UNREGISTERED,
        REGISTERED,
        LOGGED_IN;
    }

    /**
     * Common interface for your User and its states
     */
    public interface User
    {
        public void register();

        public void login();

        public boolean isRegistered();
        
        public boolean isLoggedIn();
    }

    /**
     * User can only register
     */
    class Unregistered implements User
    {
        private static final String REGISTERING = "registering user '%s'";
        private static final String NOT_REGISTERED = "user '%s' not registered";
        
        private final TheUser user;
        
        Unregistered(TheUser user)
        {
            this.user = user;
        }

        @Override
        public void register() 
        {
            System.out.println( String.format(REGISTERING, this.user));
            this.user.nowRegistered();
        }

        @Override
        public void login() {
        throw new UnregisteredUserException( String.format(NOT_REGISTERED, this.user) );
        }

        @Override
        public boolean isRegistered() {
        return false;
        }

        @Override
        public boolean isLoggedIn() {
        return false;
        }
    }


    /**
     * User can only login
     */
    class Registered implements User
    {
        private static final String ALREADY_REGISTERED = "User %s already registered";

        private final TheUser user;

        Registered(TheUser user)
        {
            this.user = user;
        }
        
        @Override
        public void register() {
        throw new IllegalStateException( String.format(ALREADY_REGISTERED, this.user));
        }

        @Override
        public void login()
        {
            System.out.println( String.format("'%s' logged in", this.user) );
            this.user.nowLoggedIn();
        }

        @Override
        public boolean isRegistered() {
        return true;
        }

        @Override
        public boolean isLoggedIn() {
        return false;
        }
    }

    /**
     * User cannot login or register
     */
    class LoggedIn implements User
    {
        private static final String ALREADY_REGISTERED = "User %s already registered";
        private static final String ALREADY_LOGGED_IN = "User %s already logged in";

        private final TheUser user;
        
        LoggedIn(TheUser user)
        {
            this.user = user;
        }

        @Override
        public void register() {
        throw new IllegalStateException( String.format(ALREADY_REGISTERED, this.user));
        }

        @Override
        public void login() {
        throw new IllegalStateException( String.format(ALREADY_LOGGED_IN, this.user) );
        }

        @Override
        public boolean isRegistered() {
        return true;
        }

        @Override
        public boolean isLoggedIn() {
        return true;
        }
    }

    /**
     * A user implemented as a state machine
     */
    public class TheUser implements User
    {
        public static final class TheUserBuilder
        {        
            private final String username;

            public TheUserBuilder(String username)
            {
                this.username = username;
            }

            /**
             * @return a new unregistered user
             */
            public TheUser build()
            {            
                TheUser user = new TheUser(this.username);
                
                User unregistered = new Unregistered(user);
                User registered = new Registered(user);
                User loggedin = new LoggedIn(user);
                
                user.addState(UserState.UNREGISTERED, unregistered);
                user.addState(UserState.REGISTERED, registered);
                user.addState(UserState.LOGGED_IN, loggedin);
                
                user.setState(unregistered);
                
            return user;
            }
        }

        /*
         * All possible states
         */    
        private final EnumMap<UserState, User> states = 
            new EnumMap<UserState, User>(UserState.class);
        
        private final String username;
        
        /*
         * The current state and only nonwfinal field
         */
        private User state;
        
        public User(String username)
        {
            this.username = username;
        }

        private void addState(UserState type, User state) {
            this.states.put(type, state);
        }

        private void setState(User state) {
            this.state = state;
        }

        private User getState(UserState type) 
        {
            User state = this.states.get(type);
            
            Preconditions.checkNotNull(state, 
                    String.format(UNSPECIFIED_STATE, state, state));
            
        return state;
        }

        private User registeredState() {
        return this.getState(UserState.REGISTERED);
        }

        private User loggedInState() {
        return this.getState(UserState.LOGGED_IN);
        }

        void nowRegistered() {
            this.setState( this.registeredState() );
        }

        void nowLoggedIn() {
            this.setState( this.loggedInState() );        
        }

        @Override
        public void register() {
            this.state.register();
        }

        @Override
        public void login() {
            this.state.login();
        }


        @Override
        public boolean isRegistered() {
        return this.state.isRegistered();
        }

        @Override
        public boolean isLoggedIn() {
        return this.state.isLoggedIn();
        }

        @Override
        public String toString() {
        return this.username;
        }
    }


    /**
     * Let's put it to the test
     */
    public class TheUserTest
    {
        @Test(expected=UnregisteredUserException.class)
        public void testUnregistered()
        {
            User user = new TheUserBuilder("cherouvim").build();                
            user.login();        
        }
        
        @Test
        public void testRegister()
        {
            User user = new TheUserBuilder("cherouvim").build();                
            user.register();
            
            Assert.assertTrue( user.isRegistered() );
            Assert.assertFalse( user.isLoggedIn() );
        }

        @Test
        public void testLogin()
        {
            User user = new TheUserBuilder("cherouvim").build();                
            user.register();
            user.login();
            
            Assert.assertTrue( user.isRegistered() );
            Assert.assertTrue( user.isLoggedIn() );
        }
    }

This is possibly the most hideous usage of if since not only makes your code hard to follow but also you have to keep track of your object’s state since execution flow changes every time. All in your head that is.

In addition it’s hard to figure out how the object behaves at each state as well as how the transitions between them happen. Because of that it makes it a pain to debug and to extend.

What you need to do instead is think of all the possible states your object can have and create an implementation for each. This way each state effectively encapsulates only what’s responsible for. Notice how each state also sets the next valid state of your object depending on what method you called, making your object look as if it’s a different one. For that you need to have a reference to your actual class.

As a result each state mirrors your class interface. If a method isn’t valid for a particular state make sure that you throw an IllegalStateException. In that case you’ll know early that something unexpected happened, which is most likely an error on how you wired your code.

Effectively you end up with state being the only non final field in your class.

Summary

  • Create an interface with all the methods related to the object’s state
  • Create an implementation for each state
  • Have a single field in your actual class holding the current state
  • Delegate each call to the current state

As to how to identify the state machine itself, it really goes back to the beginning

Kudos

Ioannis Cherouvim who is a Java developer and regularly writes blogs posts about using Java effectively.

The source code is available on github as stated previously. Feel free to fork it and add a LoggedOut state which allows the user to logout and set the appropriate state

]]>
Wed, 19 Jan 2011 00:00:00 +0200
Inheritance ...Don't Abuse Inheritance https://qnoid.com/2011/01/16/inheritance.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2011/01/16/inheritance.html
/**
     * The Terminator feels no pain, 
     * has no emotions, 
     * and will stop at nothing to accomplish its mission.
     */
    public interface Terminator
    {
        /**
         * Reduces the health of the terminator by the damage taken as specified 
         * by this terminator.
         * 
         * Note that this terminator takes no damage after the fight.
         * 
         * @param terminator the terminator to take the damage
         * @return true if terminated
         * @see #damageBy(int)
         */
        public boolean destroy(Terminator terminator);

        /**
         * @return how much health the terminator has
         */
        public int health();

        /**
         * Reduces the health of the terminator by the damage taken.
         *  
         * @param damage the damage to take
         * @return true if terminated
         * @see #health()
         */
        public boolean damageBy(int damage);

        /**
         * @return true if health equals or below 0
         */
        public boolean isTerminated();
    }

    /**
     * Can only give punches
     */
    public class StiffTerminator implements Terminator
    {
        private final String model;
        
        /*
         * Is that the only thing a terminator can destroy with?
         */
        private final Punch punch;
        private int health;
        
        /*
         * Forced 'protected' by the fact that we need to extend the 
         * {@link #destroy(Terminator)} method
         */
        protected StiffTerminator(String model, Punch punch, int health)
        {
            this.model = model;
            this.health = health;
            this.punch = punch;
        }

        /*
         * Will need to accommodate for a change in the destruction
         */
        @Override
        public boolean destroy(Terminator terminator) {
        return this.punch.punch(terminator);
        }
        
        @Override
        public int health(){
        return this.health;
        }

        @Override
        public boolean damageBy(int damage) 
        {
            this.health -= damage;
            
        return this.isTerminated();
        }
        
        @Override
        public boolean isTerminated() {
        return this.health <= 0;
        }    

        @Override
        public String toString() {
        return this.model;
        }
    }

    /*
     * You don't really need another terminator for this...
     */
    public class ShakyTerminator extends StiffTerminator
    {
        private final Shotgun shotgun;

        protected ShakyTerminator(String model, Shotgun shotgun, int health) 
        {
            /*
             * Notice how you are forced to use null for the punch which reveals
             * a not well thought class design
             */
            super(model, null, health);
            this.shotgun = shotgun;
        }

        @Override
        public boolean destroy(Terminator terminator) {
        return this.shotgun.shoot(terminator);
        }
    }

    /**
     * The menacing terminator
     */
    public class TheTerminator implements Terminator
    {
        public static class TheTerminatorBuilder
        {
            /*
             * See /2010/09/30/Honour-your-builders-Don't-lose-your-train-of-thoughts.html#main
             */
            public TheTerminator build(){
            return new TheTerminator(this.model, this.destructionMode, this.health);
            }        
        }
        
        private final String model;
        private final DestructionMode destructionMode;
        private int health;
        
        private TheTerminator(String model, DestructionMode destructionMode, int health)
        {
            this.model = model;
            this.health = health;
            this.destructionMode = destructionMode;
        }

        @Override
        public boolean destroy(Terminator terminator) {
        return this.destructionMode.destroy(terminator);
        }

        /* cont. */
    }

    /**
     * Use to define different destruction modes for the terminator.
     * 
     *  @see DestructionModes
     */
    public interface DestructionMode
    {
        /**
         * This has been extracted as a result of the 
         * {@link Terminator#destroy(Terminator)} method likely to change to 
         * accommodate different destruction modes.
         * <br>
         * Thus it mirrors the method in its whole.
         *  
         * @param terminator to destroy
         * @return true if terminated
         */
        public boolean destroy(Terminator terminator);
    }

    /**
     * All available destruction modes
     */
    public class DestructionModes
    {
        /**
         * Logs in memory any terminators encountered
         */
        public static final DestructionMode NONE = new DestructionMode() 
        {       
            private final StringBuilder MEMORY = new StringBuilder();

            @Override
            public boolean destroy(Terminator terminator) {
                MEMORY.append(terminator);
            return false;
            }

            /* (non-Javadoc)
             * @see java.lang.Object#toString()
             */
            @Override
            public String toString() {
            return MEMORY.toString();
            }
        };
        
        /**
         * @return a new destruction mode with a punch
         */
        public static DestructionMode punch(final Punch punch)
        {
        return new DestructionMode() 
            {        
                @Override
                public boolean destroy(Terminator terminator) {
                return punch.punch(terminator);
                }
            };
        }
        
        /**
         * @return a new destruction mode with a shotgun
         */
        public static DestructionMode shotgun(final Shotgun shotgun)
        {
        return new DestructionMode() 
            {        
                @Override
                public boolean destroy(Terminator terminator) {
                return shotgun.shoot(terminator);
                }
            };
        }
    }

    /**
     * Testing TheTerminator
     */
    public class TheTerminatorTest
    {
        private static final Skynet SKYNET = Skynet.instance();

        @Test
        public void fight() throws Exception
        {
            TheTerminator t800 = SKYNET.newT800(Punches.WEAK);        
            TheTerminator t1000 = SKYNET.newT1000(Punches.STRONG);
            TheTerminator hkScout = SKYNET.newHKScount();
            
            Assert.assertFalse( 
                    String.format("Terminator '%s' is destroyed by '%s'", t1000, t800), 
                    t800.destroy(t1000)
                    );
            
            Assert.assertTrue( 
                    String.format("Terminator '%s' not destroyed by %s", t800, t1000), 
                    t1000.destroy(t800)
                    );
            
            Assert.assertFalse( 
                    String.format("Terminator '%s' not destroyed by %s", t800, hkScout), 
                    hkScout.destroy(t800)
            );
            
            Assert.assertFalse( 
                    "Terminator shouldn't be destroyed", 
                    hkScout.destroy(t800)
            );
        }
    }

Inheritance is one of the most popular class relationships and really powerful indeed. After all it allows you to reuse whole classes. However, with great power comes great responsibility and it’s good to keep inheritance as the last resort or as part of a well thought design.

Take a look at the StiffTerminator#destroy(Terminator) method. You can tell there is a need for different ways to destroy a terminator. Yet at the same time you don’t want to duplicate the rest of the code. Thus the first thing that comes to mind is to inherit.

ShakyTerminator extends StiffTerminator adding a Shotgun as a field therefore making Punch not only obsolete but also irrelevant. Yet due to the nature of inheritance it is required that you specify its value. You can choose to pass in null. However you do have to make sure null is a valid value by the StiffTerminator design which may well affect any of your subclasses. Else you have to introduce it as an argument to your ShakyTerminator constructor,

    protected ShakyTerminator(String model, Punch punch, int health, Shotgun shotgun) 

introducing extra and unnecessary complexity.

In addition you need to elevate the access modifier of the StiffTerminator from private to protected. You start sacrificing encapsulation. Not only you’ve made all those sacrifices but your code starts to looks messy.

The truth is that you don’t have to create a new Terminator class! If you look closely you’ll see that you need to somehow make the Punch#punch(Terminator) polymorphic. That is definitely one way to look at it. In that case you need to introduce an interface

	public interface DestructionMode
	{
		public boolean punch(Terminator terminator);
	}

and have your Punch implement it

    public class Punch implements DestructionMode

as well as any other classes.

Though this will work in some cases it’s not always possible (3rd party classes), not in context or there are a couple classes involved. The fact of the matter is it’s more about composition and less of polymorphism.

Now, you still need to introduce an interface but your classes don’t need to directly implement it. Rather you introduce a new class - implementing that interface - for each composition. Anonymous classes can be of great use in this case.

What you end up with allows you to have more readable, flexible and high reusable code instead.

Summary

  • Identify the method(s) that are subject to change in your class
  • Introduce a new interface with all the identified methods
  • Add a new field of that type in your class and as an argument to the constructor
  • Delegate each call to your interface method respectively
  • Create one class for every implementation using composition to encapsulate the dependencies

Inheritance on the other hand is really good with abstract classes

Kudos

James Cameron for the Terminator
Creative Commons for making sharing easier
Gihub for making a truly amazing social code repository

Starting with this post, the complete source code will be available in github for every post I make under a Creative Commons Licence with an attribution that requires a link back to the qnoid. Will also try and add the source code for all my previous posts. Hope this will give you better understanding and allow you to experiment further

Source Code

]]>
Sun, 16 Jan 2011 00:00:00 +0200
Encapsulation ...Don't Abuse The If https://qnoid.com/2011/01/11/encapsulation.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2011/01/11/encapsulation.html
/**
     * Destined to sink
     */
    public class Titanic
    {
        private final WallStreet wallstreet = new WallStreet();
        private final Pharaoh pharaoh = new Pharaoh();
        private final Oilwell oilwell = new Oilwell();
        private final Cowboy[] cowboys = new Cowboy[]{new Cowboy()};
        
        public void sail(String direction)
        {
            if("NORTH".equals(direction))
            {
                wallstreet.moneyNeverSleeps();
            }
            else if("SOUTH".equals(direction))
            {
                pharaoh.curse();
            }
            else if("EAST".equals(direction))
            {
                oilwell.drill();
            }
            else if("WEST".equals(direction))
            {
                for (Cowboy cowboy : this.cowboys) {
                    cowboy.shoot();
                }
            }
            else{
                throw new UnknownDestination();
            }
        }
    }

    /**
     * Smooth sailing
     */
    public class CruiseLiner
    {
        private static final String UNKNOWN_DESTINATION = 
            "There is no destination in the direction '%s'. " +
            "Did you specify it as such in CruiseLiner#newCruiseLiner " +
            "when constructing the cruise liner?";

        /**
         * Create a new {@link CruiseLiner} which is able to sail to the specified
         * destinations
         *  
         * @param destinations the destinations that can set sail to
         * @return a new {@link CruiseLiner}
         * @see Destinations
         */
        public static CruiseLiner newCruiseLiner(Destination... destinations)
        {
            EnumMap<Direction, Destination> map = 
                new EnumMap<Direction, Destination>(Direction.class);
            
            for (Destination destination : destinations){
                map.put(destination.direction(), destination);
            }
            
        return new CruiseLiner(map);
        }
        
        /*
         * A map by direction for each destination 
         * No need to specify any other dependencies here. Great!
         */
        private final EnumMap<Direction, Destination> map;
        
        private CruiseLiner(EnumMap<Direction, Destination> map)
        {
            this.map = map;
        }

        public void sail(Direction direction)
        {
            //Use the map to get the destination you want for the given direction
            Destination destination = this.map.get(direction);
            
            if(destination == null){
                throw new UnknownDestination(
                        String.format(UNKNOWN_DESTINATION, direction));
            }
            
            //let the destination specify what to do once the cruise liner sails there
            destination.sail(this);
        }
    }

    /**
     * Get your directions together
     */
    public enum Direction
    {
        NORTH,
        SOUTH,
        EAST,
        WEST, 
        UKNOWN
    }

    /**
     * Encapsulate your destinations by introducing a common interface 
     */
    public interface Destination
    {
        public Direction direction();
        
       /**
        * Implement this method with what you would do at each destination
        */
        public void sail(CruiseLiner cruiseLiner);
    }

    /**
     * Constant destinations with each specifying its required dependencies
     */
    public class Destinations
    {
        public static final Destination NORTH_AMERICA = new Destination() 
        {
            private final WallStreet wallstreet = new WallStreet();

            @Override
            public void sail(CruiseLiner cruiseLiner)
            {
                wallstreet.moneyNeverSleeps();
            }

            @Override
            public Direction direction() {
            return Direction.NORTH;
            }
        };
        
        public static final Destination SOUTH_AFRICA = new Destination() {
            
            private final Pharaoh pharaoh = new Pharaoh();

            @Override
            public void sail(CruiseLiner cruiseLiner)
            {
                pharaoh.curse();
            }

            @Override
            public Direction direction() {
            return Direction.SOUTH;
            }
        };
        
        public static final Destination MIDDLE_EAST = new Destination() {
            
            private final Oilwell oilwell = new Oilwell();

            @Override
            public void sail(CruiseLiner cruiseLiner)
            {
                oilwell.drill();
            }

            @Override
            public Direction direction() {
            return Direction.EAST;
            }
        };
        
        public static final Destination GREAT_WEST = new Destination() {
            
            private final Cowboy[] cowboys = new Cowboy[]{new Cowboy()};

            @Override
            public void sail(CruiseLiner cruiseLiner)
            {
                for (Cowboy cowboy : this.cowboys) {
                    cowboy.shoot();
                }
            }

            @Override
            public Direction direction() {
            return Direction.WEST;
            }
        };
    }

    /**
     * Let's cruise
     */
    public class CruiseLinerTest
    {
        private final Destination[] DESTINATIONS = 
            new Destination[]
            {
                /*
                 * Use constants!
                 */
                Destinations.NORTH_AMERICA, 
                Destinations.SOUTH_AFRICA,
                Destinations.MIDDLE_EAST,
                Destinations.WILD_WEST
            };
        
        @Test
        public void sail() throws Exception
        {
            CruiseLiner cruiseLiner = 
                CruiseLiner.newCruiseLiner( DESTINATIONS );
                        
            cruiseLiner.sail( Direction.NORTH );
            cruiseLiner.sail( Direction.SOUTH );
            cruiseLiner.sail( Direction.EAST );
            cruiseLiner.sail( Direction.WEST );
        }
        
        @Test(expected=UnknownDestination.class)
        public void sailUnknown() throws Exception
        {
            CruiseLiner cruiseLiner = 
                CruiseLiner.newCruiseLiner();
            
            cruiseLiner.sail(Direction.UKNOWN);
        }
    }

It is shocking to see this basic abuse of an if so frequently. In the @qnoid, over at github and bitbucket, on freshly baked projects. Especially when all it takes is to use a Map instead of an long if statement and take advantage of delegation.

It usually manifests in the controller where you have a single method to handle different operations and though it resembles polymorphism is less about it and more about composition.

Again you might say it is nothing serious and you can choose to ignore it but it does make your code less extensible, harder to maintain, less readable and destined to sink.

If (pun intended) you add all the dependencies related to the different actions for each block you end up with one monolithic class. That’s ugly. On a lighter note, using strings isn’t type safe and thus error prone. Think how many times in the past you’ve had to debug for hours because of a single typo. Not fun.

Assuming you’ve used an enum you shouldn’t have any troubling mapping it with

    Direction direction = Direction.valueOf( name );

So next time you are tempted to use a long if block just use a map where each key is the name of your action and the corresponding value is an object of a class implementing a common interface with a single method.

PS. Get used to the habit of creating constants out of your classes.

Source

]]>
Tue, 11 Jan 2011 00:00:00 +0200
Heterogenous Containers... JSON (Part 3) https://qnoid.com/2011/01/09/heterogenous-containers-JSON-part-3.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2011/01/09/heterogenous-containers-JSON-part-3.html
/**
 * A collection of pairs ordered based on the order of their {@link Element}s
 * 
 * @see ElementBuilder
 */
public class PairSet implements Iterable<Pair<?>>
{
    /**
     * Create a new JSON object with the specified pairs
     * 
     * @param pairs the pairs to the JSON object
     * @return a JsonObject with the specified pairs
     */
    public static final PairSet of(Pair<?>... pairs)
    {
        PairSet pairSet = new PairSet();
        
        for (Pair<?> pair : pairs) {
            pairSet.add(pair);
        }
        
    return pairSet;
    }    

    /*
     * Using TreeMap implementation for sorting
     */
    private final Map<Element<?>, Pair<?>> pairs = 
        new TreeMap<Element<?>, Pair<?>>();
    
    /**
     * Adds a new pair value
     * @param <T> the pair type
     * @param pair the pair to add
     */
    public <T> PairSet add(Pair<T> pair)
    {
        this.pairs.put(pair.element(), pair);
    return this;
    }
    
    @Override
    public Iterator<Pair<?>> iterator(){
    return this.pairs.values().iterator();
    }
        
    /**
     * 
     * @param <T>
     * @param element the type of the pair
     * @return the pair instance
     * @see Element#type()
     */
    public <T> T get(Element<T> element) {
    return element.type().cast( this.pairs.get(element).value() );
    }

    public int size(){
    return this.pairs.size();
    }
}


/**
 * A non-complex JSON object
 */
public class JsonObject 
{
    public static JsonObject of(Pair<?>... pairs) {
    return new JsonObject( PairSet.of(pairs) );
    }

    private static final Element<Type> LAST_ELEMENT = Elements.TYPE;
	
    private static final String LEFT_BRACE = "{";
    private static final String RIGHT_BRACE = "}";
    private static final String COMMA = ",";
	
    private final PairSet pairs;

    JsonObject(PairSet pairs) 
    {
        this.pairs = pairs;
    }
	
    private boolean isLast(Pair<?> pair){
    return LAST_ELEMENT.equals(pair.element());
    }
	
    private void appendEveryPairOf(StringBuilder builder, PairSet pairs)
    {
        for (Pair<?> pair : pairs) 
        {
            builder.append( pair );            
            appendCommaIfNotLast(builder, pair);
        }
    }

    private void appendCommaIfNotLast(StringBuilder builder, Pair<?> pair)
    {
        boolean isLast = isLast(pair);
        
        if(!isLast){
            builder.append( COMMA );
        }
    }

    /**
     * 
     * @param <T>
     * @param element the element which is present in the JSON object
     * @return its value
     */
    public <T> T valueOf(Element<T> element){
    return this.pairs.get(element);		
    }
	
    @Override
    public String toString()
    {
   	  StringBuilder builder = new StringBuilder();
		
	  builder.append(LEFT_BRACE);
		
	  appendEveryPairOf(builder, this.pairs);
		
	  builder.append(RIGHT_BRACE);
		
    return builder.toString();
    }
}


/**
 */
@RunWith(Theories.class)
public class PairSetTest
{
	private static final Integer ID_VALUE = 1;
	
	private static final Pair<Integer> ID_PAIR = 
	    Pair.newPair(Elements.ID, ID_VALUE);
	
	private static final String NAME_VALUE = "Kyle Bragger";
	
	private static final Pair<String> NAME_PAIR = 
	    Pair.newPair(Elements.NAME, NAME_VALUE);
	
	private static final Date DATE_VALUE = 
	    Calendar.getInstance().getTime();
	
	private static final Pair<Date> DATE_PAIR = 
	    Pair.newPair(Elements.DATE, DATE_VALUE);
	
	private static final Type TYPE_VALUE = Type.DEVELOPER;
	
	private static final Pair<Type> TYPE_PAIR = 
	    Pair.newPair(Elements.TYPE, TYPE_VALUE);
	
    private static final Pair<?>[] PAIRS = 
        new Pair<?>[]{
            ID_PAIR, 
            NAME_PAIR, 
            DATE_PAIR, 
            TYPE_PAIR};
    
    @DataPoints
    public static final Element<?>[] ELEMENTS = 
        {Elements.ID, Elements.NAME, Elements.TYPE, Elements.DATE};
    
	/**
     * @param pairs
     * @param element
     */
    private <T> void assertNotNull(PairSet pairs, Element<T> element) 
    {
    	T value = pairs.get(element);
	    
    	Assert.assertNotNull(value);
    }

    @Test
    public void of() throws Exception
    {
        PairSet pairs = PairSet.of( PairSetTest.PAIRS ); 
        
        Assert.assertEquals(4, pairs.size());        
    }
    
    @Theory
    public void get(Element<?> element) throws Exception
    {
        PairSet pairs = PairSet.of( PairSetTest.PAIRS );
        
        assertNotNull(pairs, element);
    }
}


/**
 */
public class JsonObjectTest 
{
    private static final Integer ID_VALUE = 1;
    
    private static final Pair<Integer> ID_PAIR = 
        Pair.newPair(Elements.ID, ID_VALUE);
    
    private static final String NAME_VALUE = "Kyle Bragger";
    
    private static final Pair<String> NAME_PAIR = 
        Pair.newPair(Elements.NAME, NAME_VALUE);
    
    private static final Date DATE_VALUE = 
        Calendar.getInstance().getTime();
    
    private static final Pair<Date> DATE_PAIR = 
        Pair.newPair(Elements.DATE, DATE_VALUE);
    
    private static final Type TYPE_VALUE = Type.DEVELOPER;
    
    private static final Pair<Type> TYPE_PAIR = 
        Pair.newPair(Elements.TYPE, TYPE_VALUE);
    
    private static final Pair<?>[] PAIRS = 
        new Pair<?>[]{
            ID_PAIR, 
            NAME_PAIR, 
            DATE_PAIR, 
            TYPE_PAIR};
    
	private static final String toString =
		String.format({{"{%s"}},%s,%s,%s}", ID_PAIR, NAME_PAIR, DATE_PAIR, TYPE_PAIR);

    @Test
    public void string() throws Exception 
    {
 	JsonObject jsonObject = JsonObject.of( PAIRS );
		
	Assert.assertEquals(toString, jsonObject.toString());
    }
	
    @Test
    public void valueOfId() throws Exception 
    {
    	  JsonObject jsonObject = JsonObject.of( PAIRS );
		
	  Assert.assertEquals(ID_VALUE, jsonObject.valueOf(Elements.ID));
    }

    @Test
    public void valueOfName() throws Exception 
    {
   	  JsonObject jsonObject = JsonObject.of( PAIRS );
		
	  Assert.assertEquals(NAME_VALUE, jsonObject.valueOf(Elements.NAME));
    }

    @Test
    public void valueOfType() throws Exception 
    {
 	  JsonObject jsonObject = JsonObject.of( PAIRS );
		
	  Assert.assertEquals(TYPE_VALUE, jsonObject.valueOf(Elements.TYPE));
    }

    @Test
    public void valueOfDate() throws Exception 
    {
	  JsonObject jsonObject = JsonObject.of( PAIRS );
		
	  Assert.assertEquals(DATE_VALUE, jsonObject.valueOf(Elements.DATE));
    }
}

This is the final post of the “How to think of JSON” series using heterogeneous containers.

In this example the PairSet plays the role of such a container backed by a TreeMap. The TreeMap implementation is used to keep our elements sorted based on their natural ordering which in this case merely helps us assert the JsonObject#toString method.

Note how the PairSet class also implements the Iterable interface thus the

    Iterator<T> iterator();

method which allows us to use the enhanced for loop.

        for (Pair<?> pair : pairs) 
        {
            builder.append( pair );            
            appendCommaIfNotLast(builder, pair);
        }

Make sure you incorporate it in classes that represent collections of objects.

As it all comes together (Element, ElementFormat, Pair, PairSet) we end up with a JsonObject class which not only allows us to query for any JSON element to get its value back to the right type but get a properly formatted String representation.

Once acquainted feel free to leave your comments below on how heterogeneous containers think can aid your design.

Source

]]>
Sun, 09 Jan 2011 00:00:00 +0200
Heterogenous Containers... JSON (Part 2) https://qnoid.com/2011/01/07/heterogenous-containers-JSON-part-2.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2011/01/07/heterogenous-containers-JSON-part-2.html
/**
     * Each {@link Element} has one format which is used to return its string 
     * representation.
     * 
     * Implementations should provide the corresponding format.
     * 
     * @see ElementFormats#defaultFormat()
     * @see ElementFormats#newDateFormat(java.text.DateFormat) 
     */
    public interface ElementFormat<T>
    {
        /**
         * 
         * @param <T> the type of the element
         * @param element the element related to the value
         * @param value its value
         * @return a String representation
         */
        public String format(Element<T> element, T value);
    }

    /**
     * A resource for various element formats
     */
    public class ElementFormats
    {
        /**
         * A default JSON format as
         * <code>
         *  "name":"value"
         * </code>
         */
        public static final <T> ElementFormat<T> defaultFormat()
        {
        return new ElementFormat<T>() {
                @Override
                public String format(Element<T> element, T value){
                return String.format("\"%s\":\"%s\"", element.name(), value);
                }
            };
        }

        /**
         * Creates a new format for Date {@link Element}s. 
         * The specified date format will be used to format the date of the element. 
         * 
         * @see DateFormat#format(Date)
         */
        public static final ElementFormat<Date> newDateFormat(final DateFormat dateFormat)
        {
        return new ElementFormat<Date>() {        
                @Override
                public String format(Element<Date> element, Date value) {
                return String.format("\"%s\":\"%s\"", element.name(), dateFormat.format(value));
                }
            };    
        }    
    }


    /**
     * A JSON pair that is associated with an element and has a value
     * 
     * @param <T> the type of the pair which derives from the Element is associated with
     * @see Element
     */
    public final class Pair<T>
    {
        /**
         * Create a new JSON pair
         * 
         * @param <T> the type of the JSON pair 
         * @param element the element of the pair
         * @param value its value
         * @return a new Pair
         * @see Elements
         */
        public static final <T> Pair<T> newPair(Element<T> element, T value)
        {
            Preconditions.checkNotNull(element);
            Preconditions.checkNotNull(value);
        return new Pair<T>(element, value);
        }
        
        private final Element<T> element;
        private final T value;
        
        /**
         * @param element
         * @param value
         */
        private Pair(Element<T> element, T value)
        {
            this.element = element;
            this.value = value;
        }
        
        public Element<T> element() {
        return this.element;
        }

        public T value() {
        return value;
        }

        @Override
        public String toString() {
        return this.element.format(this.value);
        }

        /**
         * Effective Java 2nd Edition, Joshua Bloch, Item 8
         */
        @Override
        public int hashCode() 
        {
            int result = 17;
        result = 37 * result + this.element.hashCode();
        result = 37 * result + this.value.hashCode();
        return result;
        }

        @Override
        public boolean equals(Object that) 
        {
            if(this == that){
            return true;
        }
            
        if(!(that instanceof Pair)){
            return false;
        }
            
        Pair<?> pair = (Pair<?>)that;
            
        return this.element.equals(pair.element) && this.value.equals(pair.value);
        }
    }


    /**
     * Testing the format of elements
     */
    public class ElementTest
    {
        private static final Date DATE_VALUE = Dates.of(22, 1, 2010);
        
        @Test
        public void formatId() throws Exception
        {
            Assert.assertEquals("\"id\":\"1\"", Elements.ID.format(1));
        }
        
        @Test
        public void formatName() throws Exception
        {
            Assert.assertEquals("\"name\":\"Kyle\"", Elements.NAME.format("Kyle"));
        }
        
        @Test
        public void formatType() throws Exception
        {
            Assert.assertEquals("\"type\":\"developer\"", Elements.TYPE.format(Type.DEVELOPER));
        }
        
        @Test
        public void formatDate() throws Exception
        {
            Assert.assertEquals("\"date\":\"Jan 22, '10\"", Elements.DATE.format(DATE_VALUE));
        }
    }

During the first part on “How to think of JSON” we identified the Element as the heterogeneous type that we need to handle. Also talked briefly about ElementFormat.

In this part we introduce the Pair class which merely holds an element and its value. This will allow us to come up with a JSON object next.

As you can see anonymous classes support the ElementFormat interface with their dependencies listed as arguments to the static method (e.g. DateFormat)

In this case there is no reason to have separate classes since all your relationships are tied to the interface and as a result you reduce the API noise.

Bare in mind that you have to use final for arguments that are used in an anonymous class or you get a compiler error.

A nice way to concatenate strings is to use the String#format() method which sort of mimics the C way

    String.format("\"%s\":\"%s\"", element.name(), value);

Notice the backslash used for escaping a quote.

There is also 2 things to consider here about generics. The method

     public static final <T> ElementFormat<T> defaultFormat()

has a type which makes it a generic method allowing us to use it in the generic Element class as the default. Note however that T of Element and T of defaultFormat are still considered different types and in no way enforced by the Java compiler. It’s our implementation of the Element class that makes the connection between them.

    public final class Element<T>
    {
        public static class ElementBuilder<T>
        {
            private ElementFormat<T> format = ElementFormats.defaultFormat(); 

            public Element<T> build(){
            return new Element<T>(this.type, this.name, this.order, this.format);
            }
        }

        private final ElementFormat<T> format; 
    }

In the same way the type of the Pair defines the type for the value which is also the same as that of the Element

        Element<Date> dateElement = Elements.DATE;
        Date value = Calendar.getInstance().getTime();
        Pair<Date> pair = Pair.newPair(dateElement, value);

Continue to Part 3

Source

]]>
Fri, 07 Jan 2011 00:00:00 +0200
Heterogenous Containers... JSON (Part 1) https://qnoid.com/2011/01/05/heterogenous-containers-JSON-part-1.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2011/01/05/heterogenous-containers-JSON-part-1.html
/**
     * A JSON element describing its type and name.
     * 
     * @param <T> the type of the element
     * 
     * @see Elements#newStringType(String)
     * @see Elements#newNumericType(String)
     * @see Elements#newDateType(String, java.text.DateFormat)
     * @see Elements#newBooleanType(String)
     * @see Elements#newEnumType(Class, String)
     */
    public final class Element<T> implements Comparable<Element<T>>
    {
        /**
         * By default ordering isn't taken into account and the element's format is
         * {@link ElementFormats#defaultFormat()}
         * 
         * @see Element#format(Object)
         */
        public static class ElementBuilder<T>
        {
            private final Class<T> type;
            private final String name;
            private ElementFormat<T> format = ElementFormats.defaultFormat(); 
            private Integer order = 0;
            
            /**
             * @param type the element type
             * @param name its name
             */
            public ElementBuilder(Class<T> type, String name)
            {
                Preconditions.checkNotNull(type);
                Preconditions.checkNotNull(name);
                this.type = type;
                this.name = name;
            }

            /**
             * Use to specify a custom format
             * @param format the format of the element
             * @see ElementFormats
             */
            public ElementBuilder<T> format(ElementFormat<T> format)
            {
                Preconditions.checkNotNull(format);
                this.format = format;
                
            return this;
            }

            /**
             * Use to specify the ordering of the elements
             * @param order will be taken into account when iterating over a 
             * {@link PairSet}
             */
            public ElementBuilder<T> order(Integer order)
            {
                Preconditions.checkNotNull(order);
                this.order = order;
            return this;
            }

            /**
             * @return a new Element the specified type
             */
            public Element<T> build(){
            return new Element<T>(this.type, this.name, this.order, this.format);
            }
        }
        
        private final ElementFormat<T> format; 
        private final Class<T> type;
        private final String name;
        private final Integer order;
        
        Element(Class<T> type, String name, Integer order, ElementFormat<T> format)
        {
            this.type = type;
            this.name = name;
            this.order = order;
            this.format = format;
        }

        public Class<T> type() {
        return type;
        }

        public String name() {
        return name;
        }    
        
        @Override
        public String toString(){
        return this.name;
        }
        
        /**
         * Formats the value of this element based on the format specified. 
         * This will be used when creating its string representation  
         * 
         * @param value the value to format
         * @return a String formatted as specified by the {@link ElementFormat}
         */
        public String format(T value) {
        return this.format.format(this, value);
        }

        @Override
        public boolean equals(Object that) 
        {
        if(this == that){
            return true;
        }
            
        if(!(that instanceof Element)){
            return false;
        }
            
        Element<?> element = (Element<?>)that;
            
        return this.name.equals(element.name);
        }

        @Override
        public int hashCode() {
        return this.name.hashCode();
        }

        /* (non-Javadoc)
         * @see java.lang.Comparable#compareTo(java.lang.Object)
         */
        @Override
        public int compareTo(Element<T> element) {
        return this.order.compareTo(element.order);
        }  
    }

    /**
     * Access to constant JSON elements and creation
     */
    public class Elements
    {
        public static final Element<Integer> ID = newNumericType("id", 1);
        
        public static final Element<String> NAME = 
            newStringType("name", 2);
        
        public static final Element<Date> DATE = 
            newDateType("date", new SimpleDateFormat("MMM dd, ''yy"), 3);
        
        public static final Element<Type> TYPE = 
            newEnumType(Type.class, "type", 4);

        public static final <E extends Enum<E>> Element<E> newEnumType(Class<E> type, String name, int order){
        return new ElementBuilder<E>(type, name).order(order).build();
        }
        
        public static final Element<String> newStringType(String name, int order){
        return new ElementBuilder<String>(String.class, name).order(order).build();
        }
        
        public static final Element<Date> newDateType(String name, final DateFormat dateFormat, int order){
        return new ElementBuilder<Date>(Date.class, name).order(order).format( ElementFormats.newDateFormat(dateFormat) ).build();
        }
        
        public static final Element<Integer> newNumericType(String name, int order){
        return new ElementBuilder<Integer>(Integer.class, name).order(order).build();
        }
    }

You should already be familiar with the idea of heterogeneous containers and what it takes to kick off. In the next series of posts we’ll see how we can think of JSON in such terms.

In the Element class above there are a couple more things other than the type and the name like a builder, an ElementFormat, an equals/hashCode implementation and a Comparable interface so let’s talk about them one at a time.

The builder is there to help us create new Element(s). The main advantage over using the constructor is that it provides reasonable defaults for the ordering of an element and its format. Thus from the client code it looks like only a type and a name is needed for an Element.

        public ElementBuilder(Class<T> type, String name)
        {
            Preconditions.checkNotNull(type);
            Preconditions.checkNotNull(name);
            this.type = type;
            this.name = name;
        }

The ElementFormat is used for creating the string representation of an Element for a given value. The need for a formatter comes from the fact that some values (e.g. a Date) need to be formatted outside of their #toString implementation. Nevertheless the string format is always of

    "name":"value"

with the value being formatted each time. Bare in mind that the Element class merely describes a JSON element in terms of its type and name without holding its actual value.

You should do well to override equals/hashCode, especially when dealing with the Collections framework as you might be getting some unexpected results when doing add/remove operations.

    if(!(that instanceof Element)){
    return false;
    }
Element<?> element = (Element<?>)that;

Notice how the equals/hashCode implementation uses the raw type of the Element class for the instanceOf operator but the wildcard type for the cast. Josh Bloch once again has a thorough explanation on this.

Finally Comparable used with the order property is merely for making testing slightly easier (coming later on) and not really a requirement. Unless you do want your JSON elements sorted in which case is an easy way to go :) In that case you could have instead opted for the builder to increment the ordering for every element created.

Kudos

Google for the guava-libraries (see Preconditions)

Continue to Part 2

Source

]]>
Wed, 05 Jan 2011 00:00:00 +0200
Heterogenous Containers... JDBC (Part 3) https://qnoid.com/2010/12/23/heterogenous-containers-JDBC-part-3.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/12/23/heterogenous-containers-JDBC-part-3.html
/**
     * Use to query for {@link Person}s
     */
    public class PersonService
    {
        /**
         * All columns related to the person.
         */
        private static class Columns
        {
            public static final Column<Integer> ID = 
                Column.newIntegerType("id");
            
            public static final Column<String> NAME = 
                Column.newStringType("name");
            
            public static final Column<Date> DATE =
                Column.newDateType("date");

            public static final ArrayList<Column<?>> ALL = 
                new ArrayList<Column<?>>()
                {
                    {
                        this.add(Columns.ID);
                        this.add(Columns.NAME);
                        this.add(Columns.DATE);
                    }
                };
        }
        
        /**
         * Implementation of a template handler 
         * to create a new Person out of a Row
         */
        private static final ResultSetHandler<Person> PERSON_TEMPLATE_HANDLER = 
            new ResultSetListHandler<Person>(Columns.ALL) 
            {    
                @Override
                protected Person newType(Row row)
                {
                    Integer id = row.get(Columns.ID);
                    String name = row.get(Columns.NAME);
                    Date date = row.get(Columns.DATE);
                                    
                return new PersonBuilder()
                        .id(id)
                        .name(name)
                        .date(date)
                        .build();
                }                               
            };
        
        /**
         * Handler to use when retrieving a list of {@link Person}s
         */
        private static final ResultSetHandler<List<Person>> PERSONS_HANDLER = 
            new ResultSetListHandler<Person>(PERSON_TEMPLATE_HANDLER);

        private static final String SELECT_PERSONS = 
            "SELECT id, name, date, FROM person";

        private final DataSource datasource;
        
        PersonService(DataSource datasource)
        {
            this.datasource = datasource;
        }

        public List<Person> list() throws SQLException
        {
            QueryRunner queryRunner = new QueryRunner(this.datasource);
            
        return queryRunner.query(SELECT_PERSONS, PERSONS_HANDLER);
        }
    }
On our quest to explore the possibilities of heterogeneous containers under JDBC we introduced two higher level concepts above a ResultSet. Those of a Column and a Row, adding to the existing dbutils apache framework by taking advantage of ResultSetHandler(s).

From the client code side all we have to do is define the columns related to the type we’d like to query on as well as implement TemplateResultSetHandler to create an instance of it from a Row. Finally use a MultipleResultSetHandler to list all using a QueryRunner.

Going further you could introduce an annotation

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column
{
    Class<?> type();
    String name();
}

to define columns on the actual type like

public class Person
{
      @Column(type=Integer.class, name="id")
      private final Integer id;
}

and with a little help from BeanUtils you can map them to your type thus making a step towards creating a simple CRUD framework.

Hopefully these posts gave you a better understanding over heterogeneous containers as well as spur some ideas on how to use them to your benefit.

Next on Heterogenous Containers, How to think of JSON.

You can read more about the builder pattern as part of the Don’t lose your train of thoughts series

Source

]]>
Thu, 23 Dec 2010 00:00:00 +0200
Heterogenous Containers... JDBC (Part 2) https://qnoid.com/2010/12/20/heterogenous-containers-JDBC-part-2.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/12/20/heterogenous-containers-JDBC-part-2.html
/**
     * This class provides a way to retrieve all the values in a result set based
     * on the columns specified and create a new object of type {@code T} based on 
     * that values
     *
     * Classes extending this class should provide an implementation for the 
     * template method {@link #newType(Row)} which must return the object based on 
     * the row's columns
     * @see ResultSetHandler
     */
    public abstract class TemplateResultSetHandler<T> implements ResultSetHandler<T>
    {
        private final List<Column<?>> columns;

        /**
         * @param columns all columns available in the ResultSet
         */
        public TemplateResultSetHandler(List<Column<?>> columns)
        {
            this.columns = columns;        
        }

        /**
         * This method will iterate through all the columns 
         * (as specified in the constructor) in the result set and provide a single 
         * callback to the {@link #newType(Row)} with a Row object holding all the 
         * column values.
         * 
         * @param rs a ResultSet pointing to the row holding the next instance of {@code T}
         * @return an object of type T as returned by the {@link #newType(Row)}
         * @see ResultSet#next()
         */
        @Override
        public final T handle(ResultSet rs) throws SQLException
        {        
            Row row = new Row();
            
            for (Column<?> column : this.columns) {
                row.put(column, rs.getObject(column.name()) );
            }
            
        return this.newType( row );
        }
        
        /**
         * Template method to be overridden and provide the type of object related
         * to the given row.
         * 
         * @param row the row 
         * @return a new object based on the column 
         * @see Row#get(Column)
         */
        protected abstract T newType(Row row);    
    }

    /*
     * Our implementation of a ResultSetHandler (part of DbUtils)
     */
    public class ResultSetListHandler<T> implements ResultSetHandler<List<T>>
    {
        private ResultSetHandler<T> handler;
            
        /**
         * @param handler
         */
        public ResultSetListHandler(ResultSetHandler<T> handler)
        {
            this.handler = handler;
        }

        /**
         * This method will iterate through the result set and return a list of 
         * objects as defined in the {@link ResultSetHandler} used in the 
         * constructor
         * 
         * @see ResultSet#next()
         * @see ResultSetHandler#handle(ResultSet)
         */
        @Override            
        public List<T> handle(ResultSet rs) throws SQLException
        {
            List<T> results = new ArrayList<T>();
            
            while(rs.next()){
                results.add( this.handler.handle(rs) );
            }
            
        return results;
        }        
    }

During the first part of this post we identified 2 classes that we’ll use as the corner stone for taking advantage of a heterogeneous container under JDBC.

DbUtils has a ResultSetHandler interface where it clearly states that

Implementations of this interface convert ResultSets into other objects.

which pinpoints exactly where we would want to write the algorithm which populates the a Row instance as well as have a callback to a template method to create its corresponding object.

That template method is what will allow subclasses to create objects with the given Row which is populated with all the values required in a type safe manner!

You may notice that we call ResultSet#getObject(String) to retrieve the value for a given column and think that this is wrongly specified. If you read the Javadoc closely though you will notice that the type of the object is right there and is what allows us to take advantage of the heterogeneous container concept.

This method will return the value of the given column as a Java object. The type of the Java object will be the default Java object type corresponding to the column’s SQL type, following the mapping for builtwin types specified in the JDBC specification.

However in order to fail early we choose to cast the object in Row#put.

Also the reason to have the call to ResultSet#next outside of the TemplateResultSetHandler is to handle both single (mostly unique) results and list queries.

In the third and final part of the post we’ll see how it all looks like from the client code side.

Source

]]>
Mon, 20 Dec 2010 00:00:00 +0200
Heterogenous Containers... JDBC (Part 1) https://qnoid.com/2010/12/20/heterogenous-containers-JDBC-part-1.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/12/20/heterogenous-containers-JDBC-part-1.html
/**
     * Defines a column in a table of a specified type under a given name.
     */
    public final class Column<T>
    {
        public static final Column<Integer> newIntegerType(String name){
        return new Column<Integer>(Integer.class, name);
        }
        
        public static final Column<Long> newLongType(String name){
        return new Column<Long>(Long.class, name);
        }
        
        public static final Column<Date> newDateType(String name){
        return new Column<Date>(Date.class, name);
        }
        
        public static final Column<String> newStringType(String name){
        return new Column<String>(String.class, name);
        }
        
        public static final <E> Column<E> newColumn(Class<E> clazz, String name){
        return new Column<E>(clazz, name);
        }
        
        private Class<T> clazz;
        private String name;
        
        public Column(Class<T> clazz, String name)
        {
            this.clazz = clazz;
            this.name = name;
        }

        public Class<T> type() {
        return clazz;
        }

        public String name() {
        return name;
        }
    }

    /*
     * This class emulates a database row holding the columns' values
     */
    public class Row
    {
        /*
         * A column can be of arbitrary type therefore we use 
         * a heterogeneous map
         * to hold the different types of values 
         */
        private final Map<Column<?>, Object> columns;

        Row()
        {
            this.columns = new HashMap<Column<?>, Object>();
        }

        /**
         * Returns the value for the specified column 
         * 
         * @param column the column to get the value for
         * @return the value of the column
         */
        public <T> T get(Column<T> column) {
        return column.type().cast( this.columns.get(column) );
        }

        /**
         * Adds a new column value
         *
         * @param column the column related to the value
         * @param value the value under that column
         * @throws InvalidColumnType if the column type specified for 
         * the value is wrong
         */
        public <T> void put(Column<T> column, Object value)
        {
            Class<T> type = column.type();
            /*
             * early cast just in case the column type is wrongly specified
             * as opposed to the actual
             */
            try{
                T typed = type.cast(value);
                this.columns.put(column, typed);
            }
            catch(ClassCastException e){
                throw new InvalidColumnType(
                        String.format(
                                "Actual type for column '%s' is %s", 
                                column.name(), 
                                value.getClass().getSimpleName()
                                ));
            }            
        }
    }

On the preamble we identified a list that allows us to add any type of object and retrieve it back to its actual type. Let’s see how we can benefit from a similar typesafe heterogeneous container in conjuction with JDBC which has been around well before generics.

First thing is to define a Column class which merely describes a table column. All it takes is its name and its type. In JDBC you use a ResultSet to retrieve the value of a column as you iterate through it.

So the Column class not only specifies the column name you need to get the value from but will also give you the right class to cast it to the correct type!

Second is a Row class which is the actual heterogeneous container holding each column and its value. We’ll use that as we iterate through the ResultSet to put the value for each column. This Row instance is what we’ll also use to query for a column and get its value in the actual type.

In general when thinking of such containers there are two things to have in mind.

  • a Map that’s used as a storage for your heterogeneous type objects
  • a Class instance to allow you to cast to the actual type

In the second part we’ll see how it all comes together in conjunction with Apache’s DbUtils library to make plain JDBC fun.

Kudos to the Apache Foundation which has been around since 1999 providing all that great open source software making developers’ lives easier.

Source

]]>
Mon, 20 Dec 2010 00:00:00 +0200
Heterogenous Containers... Preamble https://qnoid.com/2010/12/12/heterogenous-containers-preamble.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/12/12/heterogenous-containers-preamble.html
public interface Person { }

    public class Designer implements Person { }

    public class Developer implements Person { }

    /**
     * A heterogenous list
     */
    public class HeterogenousList<E> 
    {
        private final Map<Class<?>, E> elements = 
            new HashMap<Class<?>, E>();

        public void add(E e) {
        this.elements.put(e.getClass(), e);
        }

        public <T extends E> T get(Class<T> type) 
        {
            E element = this.elements.get(type);
        
            if(element == null){
                throw new NoSuchElementException(String.format("No element of type: %s", type.getSimpleName()));
            }
            
        return type.cast( element );
        }
    }

    /**
     * Let's see how it feels like
     */
    public class PersonsTest 
    {
        @Test
        public void homogeneous() throws Exception 
        {
        Developer developer = new Developer();
        Designer designer = new Designer();
            
        List<Person> persons = new ArrayList<Person>();     
        persons.add( developer );
        persons.add( designer );
            
        int DEVELOPER_INDEX = 0;
        int DESIGNER_INDEX = 1;

        Person theDeveloper = persons.get(DEVELOPER_INDEX);
        Person theDesigner = persons.get(DESIGNER_INDEX);
            
        Assert.assertEquals(developer, theDeveloper);
        Assert.assertEquals(designer, theDesigner);     
        }
        
        @Test
        public void heterogeneous() throws Exception 
        {
        Developer developer = new Developer();
        Designer designer = new Designer();
            
        HeterogenousList<Person> persons = new HeterogenousList<Person>();      
            persons.add( developer );
        persons.add( designer );
            
        Class<Developer> DEVELOPER_INDEX = Developer.class;
        Class<Designer> DESIGNER_INDEX = Designer.class;        

        Developer theDeveloper = persons.get(DEVELOPER_INDEX);
        Designer theDesigner = persons.get(DESIGNER_INDEX);
            
        Assert.assertEquals(developer, theDeveloper);
        Assert.assertEquals(designer, theDesigner);     
        }

        @Test(expected=NoSuchElementException.class)
        public void noSuchElementException() throws Exception 
        {
        HeterogenousList<Person> persons = new HeterogenousList<Person>();      
        persons.add( new Developer() );
            
        Class<Designer> DESIGNER_INDEX = Designer.class;        
            
        persons.get(DESIGNER_INDEX);        
        }

        public void incorrectType() throws Exception 
        {
        HeterogenousList<Person> persons = new HeterogenousList<Person>();      
        
            //compile error
        persons.get(String.class);      
        }
    }
Joshua Bloch asked us to consider typesafe heterogenous containers. You should do well to read about them but loosely speaking you can think of such a data structure as a list. A heterogenous that is.

Since Java 5 with the introduction of generics you could specify the type of a list.

That way the compiler makes sure you don’t accidentaly add an object of different type than expected as well as you get the right one back when you ask for it.

However, you are still limited to the inherited type of the object you add.

Instead with a heterogenous container you get the actual type back.

The only difference is that the index of your list now becomes the type rather an int specifying its position.

The

T extends E

merely specifies that any type requested must be a subclass of the type specified in the list. This saves you from passing arbitrary types, yet you still need to accommodate asking for valid types that aren’t added to the list.

In the posts to come we’ll explore the possibilities of such containers.

Source

]]>
Sun, 12 Dec 2010 00:00:00 +0200
What Type Of Msc Do You Think Will Prove More Valuable? https://qnoid.com/2010/10/21/What-type-of-MSc-do-you-think-will-prove-more-valuable.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/10/21/What-type-of-MSc-do-you-think-will-prove-more-valuable.html Coming from a BSc Information Technology degree (class of 2003) I didn’t do an MSc at the time so as to get some experience first before actually deciding on one. So I really see it both as an opportunity to extend my knowledge further and as an asset for what I’d like to achieve.

The degree that I have is not a strong computer science degree. It hasn’t really become a limiting factor so far in terms of finding a job or getting things done, though I do fail miserably when it comes to data structures and algorithms.

Moving forward I’d like to venture into starting my own company so I’m really looking for the most valuable MSc to achieve my goal.

The most obvious choice is an MSc in Business Management with Entrepreneurship which will help me understand more about what it takes to start your own business. Napier University seems to be closely tied to entrepreneurship which might also help during take off. On the other hand there are many examples of people that didn’t really need an MSc for their succesful startup, so it doesn’t look like it’s that “valuable”.

The second choice is doing a purely technical skill driven MSc like Learning from Data. Managing data is becoming more important than ever and it doesn’t look like it’s going to become obsolete any time soon. The nature of the startup that I’d like to kickoff will rely heavily on data so it’s probably an important MSc to have. Also, in case I crush and burn this MSc will probably prove more valuable in exploring new job opportunities.

The third one is a joined one between IT and Philosopy or Social Sciences in general. Definitely the less valuable from all three but will help in broadening my ideas on how IT can help local societies grow. (which is also part of what I’d like to achieve through the startup)

So I’d really like to take an advice based on your experiences. Whether you already have a startup and think one of the (two) MSc did or could help you or purely from your own perspective.

Do you hold an MSc yourself? Did it prove valuable and how?

]]>
Thu, 21 Oct 2010 00:00:00 +0200
How To Think Of... Recursion https://qnoid.com/2010/10/18/recursion.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/10/18/recursion.html
/**
     * An integer with extended operations 
     */
    public class ForrstInteger
    {
        private final int number;
        
        /**
         * @param number
         */
        public ForrstInteger(int number)
        {
            this.number = number;
        }

        /**
         * Multiply the number that many times.
         * 
         * @param number the number to multiply
         * @param times how many times to multiply it
         * @return the total after multiplying the number or 0 if times is 0
         */
        private int multiply(int number, int times)
        {
            if(times == 0){
                return 0;
            }
            
        return number + this.multiply(number, --times);
        }
        
        /**
         * Multiplies the number by times
         * 
         * @param times how many times to multiple the number
         * @return the multiple of the number
         */
        public int multiply(int times) {
        return this.multiply(this.number, times);
        }
    }

    /**
     * Let's prove our recursion theory
     */
    @RunWith(Theories.class)
    public class ForrstNumberTest
    {
        @DataPoints
        public static final int[] numbers = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        
        @Theory
        public void multiplyByOne(int number)
        {
            int actual = new ForrstInteger(number).multiply(1); 
            
            Assert.assertEquals(number, actual);
        }
        
        @Theory
        public void multiplyByZero(int number)
        {
            int actual = new ForrstInteger(number).multiply(0); 
            
            Assert.assertEquals(0, actual);
        }
        
        @Theory
        public void multiplyByTimes(int number, int times)
        {
            System.out.print( String.format("%s * %s = ", number, multiply) );
            int actual = new ForrstInteger(number).multiply(times); 
            
            System.out.println(actual);
            Assert.assertEquals(number * times, actual);
        }
    }

Recursion seems to scare people away but if you follow these simple rules it can become your best friend. Although it does sound complicated, its sole purpose is to simplify a problem.

The most difficult thing about a recursion is to identify a problem as such. You will know you have encountered a recursion when you see a pattern being repeated again and again.

Isn’t that a loop you say? Well the main difference with a normal loop is that the result of a recursion solely depends on the outcome of the recursion itself. Confused?

Take for example multiplication. If you think about it, multiplication is a disguised addition.

2 * 4 = 2 + 2 + 2 + 2 = 8

So to come up with 8 as the result you had to follow this pattern

0 + 2 = 2
2 + 2 = 4 
4 + 2 = 6 
6 + 2 = 8 

Which means add 2 everytime, 4 times starting with 0.

Let’s take it backwards for a minute.

6 + 2 = 8 //how did you come up with 6?
4 + 2 = 6 //how did you come up with 4?
2 + 2 = 4 //how did you come up with 2?
0 + 2 = 2 //You don't have to calculate 0! (**Hint**)

The problem is that you don’t know which number to add to 2 every time since you haven’t calculated yet! So what you really have is something like this

2 + x = 8 
2 + x = 6 
2 + x = 4
2 + 0 = 2 //notice the pattern changing by adding 0 this time.

Do you notice the recursion?

2 + x

where x is the next number to add until it’s the 0 which ends the recursion. Which is your stop condition!

So in essence once you have identified a recursion problem there are 2 things you have to think.

  • What is the recursion
  • What is the stop condition

Failing to identify a stop condition will most likely lead to an infinite loop and a possible StackOverFlowError or OutOfMemoryException. Both pretty nasty.

Now try and identify the recursion needed to raise a number to a given integer power. (don’t bother more than an integer power, though it involves much more than that)

The first one to reply to this post with a solution (and a test to prove it!) will receive a Kudoz postcard from Edinburgh :)

Can you find any other recursions? Leave your comments below.

Update: Don’t bother with NaN or infinite values like the Math#pow(double, double), just do it for 0 to 10 like the test above. Just follow the recursion example and it’s easy to come up with it :)

Source

]]>
Mon, 18 Oct 2010 00:00:00 +0200
Evaluation ...Don't Lose Your Train Of Thoughts https://qnoid.com/2010/10/13/evaluation-dont-lose-your-train-of-thoughts.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/10/13/evaluation-dont-lose-your-train-of-thoughts.html

It’s time for your code

The Don’t lose your train of thoughts started out with quite an excitement and some early critisism :) (even became a popular post at the time!) but unfortunately didn’t stir the community as mush as I would have hoped. Wishing there was more interaction with people leaving comments, raising their concerns or providing just some feedback.

It did however create enough content with 8 posts about software design all coming out from a single paragraph of text.

Some liked by many but talked by none, other didn’t seem as popular.

As far as the community goes, one went missing, one was bitter, couple had a go at things and shared their thoughts, while others were puzzled and confused.

It even managed to inspire so as to write object oriented code and that’s quite an achievement.

Each post would usually take around 45’ to write. Though there was a rough idea where it was going, it was written on the spot and only went through some editting to get the form and style right making sure it’s coherent and easy to follow.

Was surpised that although the examples were Java based they didn’t scare people away and even coders with a different background liked them.

It lasted roughly a month at an approximate average rate of 1 post per 3 days generating in total (at the time of writing)

  • 86 Likes
  • 23 Comments
  • 552 Views

Also identified what I refer to as the the @kyle effect. It looks like every time kyle liked a post it spur the interest of people as there was a tremendous spike on views. Trying to interprent that, is either because @kyle has a lot of followers and people usually look for posts through the “Activity from friends” tab (hence more exposure) or that @kyle has a greater appeal :)

There is one exception to that rule when he was “late to the party”.

That might also mean that as the community grows it might get more difficult to discover relevant posts.

In any case the above are only personal guesses as I don’t have any metrics on how people interact with the site.

Kudoz to YOU for participating in this!

]]>
Wed, 13 Oct 2010 00:00:00 +0200
Conclusion ...Don't Lose Your Train Of Thoughts https://qnoid.com/2010/10/12/conclusion-dont-lose-your-train-of-thoughts.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/10/12/conclusion-dont-lose-your-train-of-thoughts.html The Don’t lose your train of thoughts series is over. In case this is the first time you hear about it, it was a series of posts about how you go on designing software in an OO world. All the way from analysing requirements to design, development and testing along with a lot of reasoning on how to go on about things.

It all started with the SurvivalKit specification. The great thing about the series was that nothing was scripted, and there were no actors or stooges leaving a comment, or asking all the questions :)

Each post was “created on the fly” trying to mimic real world software development conditions. Still bare in mind that it was example code and not complete by any means.

Another characteristic was making the code as “copy/paste safe” as possible. Example code shouldn’t violate basic principles which could cause people inheriting bad practices.

Finally, tried not to go astray so as not to confuse people with superflous details. A non technical jargon was also used for greater appeal.

Below is the TOC for the series

Don’t get sad as there are plenty of posts in the queue to write about, expanding on some ideas roughly touched in the series. There is still the Don’t Abuse The If and coming up the Don’t Abuse Inheritance and Don’t Abuse The For as well as plenty other standalone but hopefully as inspiring.

Do get in touch on what you are interested in seeing on qnoid.com when it comes to object oriented and software design or even write your own code that you want to talk about!

An aftermath post will follow with some general remarks and statistics about the series

]]>
Tue, 12 Oct 2010 00:00:00 +0200
Factory type ...Don't Lose Your Train Of Thoughts https://qnoid.com/2010/10/11/factory-type-dont-lose-your-train-of-thoughts.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/10/11/factory-type-dont-lose-your-train-of-thoughts.html
/**
     * Use it to create survival kits!
     * 
     * Don't be afraid to use the {@link SurvivalKitBuilder} to create your own
     * custom configuration of a kit! 
     */
    public class SurvivalKitFactory
    {
        /**
         * By default a survival kit contains a t-shirt of your specified size, 
         * a mug, a wristband and 2 stickers. Hubba, hubba!
         * 
         * @param size the size of your kit
         * @return a freshly made survival kit just for you
         */
        public SurvivalKit newSurvivalKit(Size size) 
        {
        return new SurvivalKitBuilder()
                .add(
                    new TShirt(size, Material.COTTON), 
                    new Mug(), 
                    new Wristband())
                .add( Collections.nCopies(2, new Sticker(Material.VINYL)) )
                .build();
        }
        
        /**
         * @return a SurvivalKit without the TShirt
         */
        public SurvivalKit newValueSurvivalKit() 
        {
        return new SurvivalKitBuilder()
            .add(
                new Mug(), 
                new Wristband())
            .add( Collections.nCopies(2, new Sticker(Material.VINYL)) )
            .build();
        }
    }

The builder for the SurvivalKit came handy for as long as we had only a single configuration to create.

However, defining the SurvivalKitItem now allows us to have kits with varying items. Thus different configurations.

So how can our builder accomodate for that change? Let’s find out.

You could put in a flag along with a switch statement which produces a different kit every time but that would mean that you are abusing the if. Could you use the Strategy pattern then in the same manner? You could, but there is a much more elegant way to go about it, that is use a factory.

You might think that the factory makes the builder obsolete. Far from it. It’s actually complementary by using the builder to create different configurations for the kit.

Notice how the builder provides the methods to customize the kit in addition to reasonable constants and defaults. The factory on the other hand holds all the new operators that make up a kit each time.

Not only you have encapsulated construction of the SurvivalKit that way but also provided custom instances.

Be careful not to abuse it by providing every possible custom configuration for the kit. Your client code should still be able to use the builder as intended.

]]>
Mon, 11 Oct 2010 00:00:00 +0200
Marker Interfaces ...Don't Lose Your Train Of Thoughts https://qnoid.com/2010/10/08/marker-interfaces-dont-lose-your-train-of-thoughts.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/10/08/marker-interfaces-dont-lose-your-train-of-thoughts.html
/**
     * A new and improved SurvivalKit supporting any items you like!
     */
    public class SurvivalKit
    {
        /**
         * Helps you build a survival kit and customize it the way you like!
         */
        public static final class SurvivalKitBuilder
        {
            public enum Size
            {
                TWO_XL, XL, LARGE, MEDIUM, SMALL;
            }

            private static final int COST = 29;        
            private final Collection <SurvivalKitItem> items;

            /**
             */
            public SurvivalKitBuilder()
            {
                this.items = new ArrayList<SurvivalKitItem>();
            }
            
            /**
             * @param items the items to add
             * @return the builder for chaining
             */
            public SurvivalKitBuilder add(SurvivalKitItem... items)
            {
                this.add( Arrays.asList(items) );
            return this;
            }
            
            /**
             * @param items the items to add
             * @return the builder for chaining
             */
            public SurvivalKitBuilder add(List<? extends SurvivalKitItem> items) {
                this.items.addAll(items);
            return this;
            }

            /**
             * @return a new SurvivalKit containing all the items
             */
            public SurvivalKit build() {
            return new SurvivalKit(this.items, COST);
            }
        }
        
        /**
         * Having a collection of items will eliminate the need for null
         * plus we can use the {@link SurvivalKit} to include even more
         * items in the future without changing a single line of code!
         * 
         * Future items can be added to the survival kit!
         */
        private final Collection <SurvivalKitItem> items;
        private final int cost;

        /**
         * @param items what will your kit have
         * @param cost what it costs
         */
        private SurvivalKit(Collection<SurvivalKitItem> items, int cost)
        {
            this.items = items;
            this.cost = cost;
        }

        /**
         * @return the items
         */
        public Collection<SurvivalKitItem> getItems() {
        return items;
        }

        /**
         * @return the cost
         */
        public int getCost() {
        return cost;
        }    
    }

    /**
     * The "marker" interface
     */
    public interface SurvivalKitItem
    {

    }

    /**
     * Mark your items!
     */
    public class TShirt implements SurvivalKitItem{}

    public class Wristband implements SurvivalKitItem{}

    public class Sticker implements SurvivalKitItem{}

    public class Mug implements SurvivalKitItem{}

The survival kit has been great so far. We identified its class and also defined a builder to help us create new kits the fun way.

That was until Kyle decided that there can be one without a TShirt. So how would you go on about it?

There is the option to create a new SurvivalKit class without the TShirt. But in doing so you have to also think of all the relationships that it has. Like SurvivalKitOrder or the ForrstController. Will you create extra classes for those relationships as well? Your code isn’t that DRY anymore.

You could use a base survival kit which includes everything but a TShirt and have your SurvivalKit extend that, adding a TShirt. You are abusing inheritance now.

You can simply use your existing SurvivalKit class and just use a null value anytime you don’t want a TShirt. By doing so though you will end up having to check every time you access the TShirt if it’s null or not. What’s worse is if you have to make a decision based on that when you really shouldn’t.

How will you handle a future SurvivalKit that may have less or even more items (Hint) that go with it? You start to notice that this doesn’t scale well.

The real question you have to ask yourself is, “How much different are those SurvivalKit(s)?”. Talking about different survival kit’s is more directly related to different implementations rather on the properties that make it up.

If you rethink of what defines a SurvivalKit you will come to realise that it’s merely the items that is has. So you could say that the TShirt, the Mug, the Wristband and the Sticker are all SurvivalKitItem(s).

From the description of the kit we can’t really tell anything about a SurvivalKitItem yet we can simply define a marker interface that designates all the items that can be added to the kit.

All you have to do is have each implement the SurvivalKitItem interface.

You can see that the SurvivalKit#build no longer returns a new kit. So where do we specify the custom kit that we want?

]]>
Fri, 08 Oct 2010 00:00:00 +0200
Parse a date with a variable format https://qnoid.com/2010/10/05/Parse-a-date-with-a-variable-format.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/10/05/Parse-a-date-with-a-variable-format.html
/**
     * Don't use *Util classes as they are deemed to have throw away code
     */
    public class DateUtil
    {
        private static final DateFormat ddMMyyyyDashed = new SimpleDateFormat("dd-MM-yyyy");
        private static final DateFormat yyyyMMddDashed = new SimpleDateFormat("yyyy-MM-dd");
        private static final DateFormat ddMMyyyySlashed = new SimpleDateFormat("dd/MM/yyyy");
        private static final DateFormat yyyyMMddSlashed = new SimpleDateFormat("yyyy/MM/dd");
         
        public static Date textToDate(String text) 
        {
            Date date = null;
     
            try {
                date = ddMMyyyyDashed.parse(text);
            } catch (java.text.ParseException e) {
            }
     
            try {
                date = yyyyMMddDashed.parse(text);
            } catch (java.text.ParseException e) {
            }
            try {
                date = ddMMyyyySlashed.parse(text);
            } catch (java.text.ParseException e) {
            }
            try {
                date = yyyyMMddSlashed.parse(text);
            } catch (java.text.ParseException e) {
            }
     
            System.out.println("Date is: " + date);
        return date;            
        }
    }

    /**
     *
     * A date format that can be used to parse a date using a number of 
     * {@link DateFormat}s
     */
    public class CompositeDateFormat
    {
        private static final DateFormat ddMMyyyyDashed = new SimpleDateFormat("dd-MM-yyyy"){
            {
                this.setLenient(false);
            }
        };
        private static final DateFormat yyyyMMddDashed = new SimpleDateFormat("yyyy-MM-dd"){
            {
                this.setLenient(false);
            }
        };
        private static final DateFormat ddMMyyyySlashed = new SimpleDateFormat("dd/MM/yyyy"){
            {
                this.setLenient(false);
            }
        };
        private static final DateFormat yyyyMMddSlashed = new SimpleDateFormat("yyyy/MM/dd"){
            {
                this.setLenient(false);
            }
        };

        /**
         * @return a new {@link CompositeDateFormat} which will parse any date in
         * <ul>
         *  <li>dd-MM-yyyy</li>
         *  <li>yyyy-MM-dd</li>
         *  <li>dd/MM/yyyy</li>
         *  <li>yyyy/MM/dd</li>
         * </ul>
         * 
         * format
         * 
         * @see #parse(String)
         */
        public static CompositeDateFormat newDateFormat(){
        return newDateFormat(ddMMyyyyDashed, yyyyMMddDashed, ddMMyyyySlashed, yyyyMMddSlashed);
        }
        
        /**
         * Create a new CompositeDateFormat which will parse the dates in the same order as the DateFormat(s) are supplied
         * @param dateformats the date formats to include when parsing a date using
         * this format
         * @return a new {@link CompositeDateFormat} with the specified formats
         */
        public static CompositeDateFormat newDateFormat(DateFormat... dateformats){
        return new CompositeDateFormat(dateformats);
        }     

        private final DateFormat[] dateformats;
        
        /**
         * @param dateformats the date formats to use when parsing a date
         */
        private CompositeDateFormat(DateFormat... dateformats)
        {
            this.dateformats = dateformats;
        }

        /**
         * Will try and parse the source using any of the date formatters.
         * On the first one that succeeds will skip the remaining. 
         * @see DateFormat#parse(String)
         */
        public Date parse(String source) throws ParseException 
        {
            for (DateFormat df : dateformats)
            {
                try {
                    return df.parse(source);
                }
                catch (ParseException e) {
                    //better log this
                }
            }
            
        throw new ParseException("Please make up your mind already ", 0);
        }
    }

    /**
     * A test to come with it
     */
    @RunWith(Theories.class)
    public class CompositeDateFormatTest
    {
        @DataPoints
        public static final String[] DATES = {"05-10-2010", "2010-10-05", "05/10/2010", "2010/10/05"};
        
        @Theory
        public void parse(String source) throws Exception
        {
            CompositeDateFormat newDateFormat = CompositeDateFormat.newDateFormat();
            Date date = newDateFormat.parse(source);
            
            Assert.assertNotNull(date);
        }
        
        @Test(expected=ParseException.class)
        public void parse() throws Exception
        {
            CompositeDateFormat newDateFormat = CompositeDateFormat.newDateFormat();
            newDateFormat.parse("Can't touch this!");
        }
    }

A friend of mine came across this somehow difficult situation where he had to parse a date only that he has no way of knowing the format.

In cases like these we usually apply “[brute force][9]” to overcome them as they look rather trivial and can’t be bothered.

However, it’s good if we hold our train of thoughts as this will lead to a code that is [easier to extend, reuse, maintain and even understand][10] in days to come.

So what’s wrong with the DateUtils class? Well, a couple of things.

Not extensible

Not reusable

  • You [can’t reuse][11] instances of the DateUtil class since the method is static.
  • It doesn’t extend DateFormat so you have to add new code to accommodate for your DateUtil which is merely a different implementation for parsing dates. ([Disclaimer])

Validates the contract of Format#parse(String)

  • The contract of the method #parse(String):Date defines a throw ParseException in case an error occurs during parsing. Your client code using any date format to parse the dates might look like it’s behaving correctly since it’s not catching an expected Exception.
  • You are forced to check for null every time you use that way of parsing dates.

As you can see following principles isn’t all that subjective as you might think. So the next time you decide to violate any at least do it for the right reasons. If there are any that is.

[Software development shouldn’t be a throwaway process.][12]

Disclaimer Your custom class should extend the DateFormat class. However, [DateFormat as an abstract class][5] forces you to also override both

  • #format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition)
  • #parse(String source, ParsePosition pos)

which on its own is a chapter on API design. Ideally an interface should have been present which holds the single method #parse(String):Date which you should implement.

Kudoz [Heinz Kabutz][7] who wrote an article on the [cost of causing Exceptions][8]. Not performance wise, my personal opinion is that the DateFormat should have a method #isParsable(String) which can be used instead.

Update While writing this post it came to my attention that all of the date formats should have [lenient][6] to false as you risk interpreting a date with a wrong format. Another reason why you should test even trivial code!

By default, parsing is lenient: If the input is not in the form used by this object’s format method but can still be parsed as a date, then the parse succeeds. Clients may insist on strict adherence to the format by calling setLenient(false).*

Also the order of the DateFormat(s) can play an important role as you may find yourself parsing a date wrong for cases where the day is <=12 and a SimpleDateFormat(“MM-dd-yyyy”) comes before a new SimpleDateFormat(“dd-MM-yyyy”). Though in some cases a different ordering isn’t sufficient.

[5]: {{ ref “2010-08-02-abstract-class.md#main” >}} “What’s the real role behind an abstract class and ho- it relates to an interface” [6]: http://bit.ly/blRBCF “What is lenient” [7]: http://www.javaspecialists.eu/archive/archive.jsp “The Java Specialists ne-sletter celebrated its 10 years this year” [8]: http://www.javaspecialists.eu/archive/Issue187.html [9]: https://qnoid.com/2011/01/28/The-myth-o-is-for-object-part-2.html#main [10]: https://qnoid.com/2011/01/28/Revelations-o-is-for-object-part-3.html#main [11]: https://qnoid.com/2011/01/28/Urban-legends-o-is-for-object-part-1.html#main “A misconception on the subject of reusability” [12]: https://qnoid.com/2011/02/23/Why-cant-programmers-design-software.html#main “Why Can’t Programmers.. Design Software?”

]]>
Tue, 05 Oct 2010 00:00:00 +0200
Builder type ...Don't Lose Your Train Of Thoughts https://qnoid.com/2010/09/30/builder-type-dont-lose-your-train-of-thoughts.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/09/30/builder-type-dont-lose-your-train-of-thoughts.html
/**
     * Survival Kit #1
     * Rock some awesome Forrst schwag and show your support for the community.
     */
    public class SurvivalKit
    {
        /**
         * Use to construct a new survival kit.
         * 
         * The most popular size of a survival kit has been the large so far.
         * So to speed up the process the default size will be {@link Size#LARGE}
         * You can chance it if you want, don't worry.
         */
        public static final class SurvivalKitBuilder
        {
            public enum Size
            {
                TWO_XL, XL, LARGE, MEDIUM, SMALL;
            }

            /**
             * Reasonable constant
             */
            private static final int COST = 29;

            /*
             * Use the most popular size as the default one
             */
            private Size size = Size.LARGE; 

            public SurvivalKitBuilder size(Size size)
            {
                this.size = size;
            return this;
            }

            /**
             * What you get
             * 
             * An awesome cotton twshirt to wear & make your friends jealous
             *  
             *  A coffee & tea mug for enjoying a delicious beverage while 
             *  browsing the site
             *  
             *  A wristband for those intense games of curling
             *  
             *  Two awesome vinyl stickers from our friends at Sticker Giant
             * 
             * @return a new {@link SurvivalKit}
             */
            public SurvivalKit build() 
            {
                TShirt tShirt = new TShirt(this.size, Material.COTTON);
                Mug mug = new Mug();
                Wristband wristband = new Wristband();
                List<Sticker> stickers = Collections.nCopies(2, new Sticker(Material.VINYL));
                
                /*
                 * No disrespect for Joshua Bloch (thanks for the signed copy of
                 * effective java!) on his take on Builders, but I believe that 
                 * listing dependencies explicitly on the constructor allows for 
                 * greater flexibility and is more straightforward.
                 * 
                 * You are effectively hiding the constructor anyway from your 
                 * client code and you are actually calling the constructor 
                 * on a single place.
                 * 
                 * Joshua you can have an argument with Misko Hevery next door 
                 * if you don't take my argument or even the Greek goddess Demeter:P
                 */
            return new SurvivalKit(tShirt, mug, wristband, stickers, COST);
            }
        }
          
        private final TShirt tShirt;
        private final Mug mug;
        private final Wristband wristband;
        private final Collection<Sticker> stickers;
        private final int cost;
        
        /**
         * Leveraging private to package level access so as to make it easier 
         * to test different implementations and/or related functionality 
         * on the survival kit.
         * 
         * Just make sure your test is on the same package! :D 
         * 
         * @param tShirt
         * @param mug
         * @param wristband
         * @param stickers
         * @param cost
         */
        SurvivalKit(TShirt tShirt, Mug mug, Wristband wristband, Collection<Sticker> stickers, int cost)
        {
            this.tShirt = tShirt;
            this.mug = mug;
            this.wristband = wristband;
            this.stickers = stickers;
            this.cost = cost;
        }

        /**
         * @return the tShirt
         */
        public TShirt tShirt() {
        return tShirt;
        }

        /**
         * @return the mug
         */
        public Mug mug() {
        return mug;
        }

        /**
         * @return the wristband
         */
        public Wristband wristband() {
        return wristband;
        }

        /**
         * @return the stickers
         */
        public Collection<Sticker> stickers() {
        return stickers;
        }
        
        /**
         * @return the size
         */
        public Size size(){
        return this.tShirt.size();
        }
        
        public int cost(){
        return this.cost;
        }
    }

    /**
     * Making sure a survival kit doesn't miss anything.
     */
    public class SurvivalKitTest
    {
        @Test
        public void newSurvivalKit() throws Exception
        {
            SurvivalKitBuilder survivalKitBuilder = new SurvivalKitBuilder();
            SurvivalKit survivalKit = survivalKitBuilder.build();
            
            Assert.assertNotNull(survivalKit.tShirt());
            Assert.assertEquals(Size.LARGE, survivalKit.size());
            Assert.assertNotNull(survivalKit.mug());
            Assert.assertNotNull(survivalKit.stickers());
            Assert.assertEquals(2, survivalKit.stickers().size());
        }
    }

When first identified the SurvivalKit we specified all the properties that make it up.

Now that’s a lot of properties! (@kyle made sure a survival kit has everything we need) which means that every time we need to add a new survival kit to an order we have to create everything that comes with it. Not only that but there is a risk of mistyping the cost, which pottentialy could make the kit more expensive, or cheaper than what it’s actually worth. Not fun.

So you could go on creating survival kits; every time you need to dispatch one specifying the items that comprise it or you could use a builder.

The great thing about the #build method is that it can encapsulate the complexity of creating a SurvivalKit. The client code doesn’t need to know how to go on creating a TShirt or a Mug. All is interested in is a survival kit and that’s what it gets!

The #build method also provides a place to return objects in the required state while any “setter” method in the builder can be used to perform assertions on the property to set. So in essence a builder helps you create immutable objects since once the object is “built” you can’t change it. (notice how the setters are missing from the SurvivalKit)

As an extra bonus you get to specify constant values for any of your properties. (e.g. the cost!)

Make sure that you document your builder on any default values it might use as well as the state that the object is returned in.

Up next we’ll see how a factory can help you produce different variations of a SurvivalKit and finally see the real reason behind the need for a SurvivalKitItem. Can you guess?

Disclaimer

The builder specified above is great if you have a single “configuration” of survival kits and that’s usually the case. We’ll see why the builder is complimentary to the factory and not a replacement altogether.

Kudoz

Joshua Bloch in Effective Java and his take on the builder pattern.
Misko Hevery for his great blog on testability.

]]>
Thu, 30 Sep 2010 00:00:00 +0200
Followup to Recursively find and filter files in Java https://qnoid.com/2010/09/28/Inspired-to-inspire-Followup-to-Recursively-find-and-filter-files-in-Java.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/09/28/Inspired-to-inspire-Followup-to-Recursively-find-and-filter-files-in-Java.html
/**
     * Polymorphic enums
     */
    public enum TypeFilter implements FileFilter {

        FILE
        {
            @Override
            public boolean accept(File file){
            return file != null && file.isFile();
            }
        }, 
        
        
        DIR
        {    
            @Override
            public boolean accept(File file){
            return file != null && file.isDirectory();
            }
        },     
        
        ALL
        {    
            @Override
            public boolean accept(File file){
            return file != null;
            }
        };
    }

    /**
     * Use to obtain different implementations to {@link FileFilter}s
     */
    public final class FileFilters
    {
        /**
         * A single instance will do since there our objects don't have any state
         */
        private final static FileFilters INSTANCE = new FileFilters();
        
        public static FileFilters fileFilters(){
        return INSTANCE;
        }        
        
        /*
         * Make it explicitly private so client code doesn't have to create one
         */
        private FileFilters(){}
            
        public RegExFilter newRegExFilter(String pattern){
        return new RegExFilter(pattern);
        }
        
        public RegExFilter newSuffixFilter(String suffix){
        return this.newRegExFilter("^.*" + Pattern.quote( suffix ) + "$");
        }
        
        /**
         * Create a new file filter that returns true if all filters are satisfied
         * 
         * @param filters the filter to include
         * @return a composite file filter
         */
        public FileFilter all(final FileFilter... filters)
        {
        return new FileFilter() {
                    
            @Override
            public boolean accept(File pathname)
            {
                for (FileFilter fileFilter : filters)
                {
                    if(!fileFilter.accept(pathname))
                        return false;
                }
                
            return true;
            }
        };
        }
    }

    /**
     * Extending file through composition
     */
    public class EnhancedFile
    {
        private final File file;
        
        /**
         * @param file the file to extend
         */
        public EnhancedFile(File file)
        {
            this.file = file;
        }

        private final List<File> getFilesRecursive( File file, FileFilter filter ) 
        {
            /*
             * If the file is normal end the recursion.  
             */
            if(file.isFile())
                return new ArrayList<File>();
            
            List<File> files = new ArrayList<File>();
            
            for ( File subdir : file.listFiles( TypeFilter.DIR ) ) {
                files.addAll( this.getFilesRecursive( subdir, filter ) );
            }
            
            files.addAll( Arrays.asList( file.listFiles( filter ) ) );
            
        return files;
        }
        
        public final List<File> getFilesRecursive( FileFilter filter ) {
        return this.getFilesRecursive(this.file, filter);
        }
    }

    /**
     * Verifying the signature of FileFilters#all
     */
    public class FileFiltersTest
    {
        private static final FileFilters FILE_FILTERS = FileFilters.fileFilters();

        @Test
        public void all() throws Exception
        {
            /*
             * Quoting @cahnory from @imperez post
             */
            String pattern = "([^:]+:(\\/\\/)?)?([^@]+@)?([^?/]+)/";        
            FileFilter all = FILE_FILTERS.all(TypeFilter.ALL, FILE_FILTERS.newRegExFilter(pattern));
        }
    }
Did you know that you can define (even @Override) methods to enums pretty much in the same way as classes?

Instead of having the #accept(File) method checking on the “type” to decide on the operation, you can move the operation to the type itself! :D

Personally I believe the SuffixFilter is a bit of an overhead to implement with inheritance to just encapsule the

"^.*" + Pattern.quote( suffix ) + "$"

Maybe a Factory is more appropriate. Which can also be used to create other file filters as well.

The #all makes it easy to have your RegExFilter decoupled from the TypeFilter.

Try to avoid static Util classes as are harder to extend or test. Instead you can use composition to “extend” a File to add more methods

Also notice how the stop condition for the recursion is easier to identify.

Kudoz to @imperez for his Regex to find the first part of a url post and @cahnory followup comment. Though it doesn’t apply to files, I did remember his post while looking at yours :)

]]>
Tue, 28 Sep 2010 00:00:00 +0200
Reusability ...Don't Lose Your Train Of Thoughts https://qnoid.com/2010/09/27/reusability-dont-lose-your-train-of-thoughts.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/09/27/reusability-dont-lose-your-train-of-thoughts.html
/**
     * Feel free to reuse!
     */
    public enum ShippingMethod
    {
        US_CANADA(0),
        INTERNATIONAL(10);

        /**
         * Dispatches the order to the specified address.
         * 
         * @param order the order which might contain several kits
         * @param adress the address for delivery
         * @return a unique identifier for the order used for tracking
         */
        public String dispatch(SurvivalKitOrder order, Address adress){
            
            //There goes another one
        }
    }

    /**
     * The almighty controller.
     * Dispatching orders since 1 month ago
     */
    public class ForrstController
    {
        /**
         * This method will decide on the shipping method, create 
         * a new SurvivalKitOrder and an Address and initiate the dispatch!
         */
        public void purchase()
        {
            ShippingMethod method = ShippingMethod.INTERNATIONAL;
            
            SurvivalKit survivalKit = new SurvivalKit(
                                                    new TShirt(Size.LARGE, Material.COTTON),
                                                    new Mug(),
                                                    new Wristband(),
                                                    Collections.nCopies(2, new Sticker(Material.VINYL)), 
                                                    29);

            Collection<SurvivalKit> survivalKits = new ArrayList<SurvivalKit>();
            survivalKits.add( survivalKit );
            
            SurvivalKitOrder order = new SurvivalKitOrder("F0RR7T", survivalKits);
            Address adress = new Address();
            
            //Woohoo we have started shipping!
            method.dispatch(order, adress);
        }
    }

When thinking about the ShippingMethod class we talked about the importance of designing immutable classes thus allowing us to create constant objects and reuse them freely. Also while trying to identify the relationships to the SurvivalKitOrder class in order to dispatch it we hold back from defining a rather complicated one.

Now the ShippingMethod is your point of reference. It’s what you can reuse again and again to dispatch (Hint) an order to an address. The SurvivalKitOrder and the Address is what varies each time. So whenever a new purchase is made, you choose the ShippingMethod and create a new SurvivalKitOrder and an Address.

Designing for reusability through constants is “the key to success”. If you look back at the design of your classes you will come to realize that not only you have defined the minimum required relationships between them but in doing so you have effectively avoided any concurrency issues in the process.

The reason for that is that any shared objects (the shipping method) are constants and anything that varies (order, address) is new to each thread.

The question that remains is where do you create a new order and an address and how does it all come together? That’s where the controller steps in. The controller itself could be mapped to a URL that handles purchases and gets all the address details from the form.

This effectively also closes the circle for the #purchase method which has now found its place.

Next in the series is “Honour Your Builders” where we’ll see how you can go on creating survival kits the fun way. Don’t miss it.

Disclaimer

This is example code to make you think of class relationships and reusability. The ShippingMethod#dispatch will most likely require some other class relationship to do the dispatch, so in the real world you’ll might have to take that into consideration as well.

]]>
Mon, 27 Sep 2010 00:00:00 +0200
Do you think that GAE alone is enough to justify learning Python over Ruby? https://qnoid.com/2010/09/16/Do-you-think-that-GAE-alone-is-enough-to-justify-learning-Python-over-Ruby.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/09/16/Do-you-think-that-GAE-alone-is-enough-to-justify-learning-Python-over-Ruby.html Considering the fact that you don’t have to get involved in setting up a server or even buying a domain, do you think that fact alone is enough to choose one over the other?

]]>
Thu, 16 Sep 2010 00:00:00 +0200
Can an Abstract Class and an Interface play nice together? https://qnoid.com/2010/09/13/Can-an-Abstract-Class-and-an-Interface-play-nice-together.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/09/13/Can-an-Abstract-Class-and-an-Interface-play-nice-together.html
/**
 * Pity me
 */
public class Driver
{
    public void drive(Porsche porsche)
    {
        porsche.drive();
    }
}

/**
 * Had to learn how to drive a Yugo after the crisis hit me
 */
public class Driver
{    
    public void drive(Porsche porsche)
    {
        porsche.drive();
    }
    
    public void drive(Yugo yugo)
    {
        yugo.drive();
    }
}

/**
 * Gas for all!
 */
public class Driver
{
    public void drive(GasolineCar gasolineCar)
    {
        gasolineCar.drive();
    }    
}

/**
 * Not again....
 *
 */
public class Driver
{
    public void drive(ElectricalCar electricalCar)
    {
        electricalCar.drive();
    }
    
    public void drive(GasolineCar gasolineCar)
    {
        gasolineCar.drive();
    }
}

/**
 * "I'm the King of the world"
 */
public class Driver
{
    public void drive(Car car)
    {
        car.drive();
    }    
}

/**
 * All I wan't to do is drive...
 */
public interface Car
{
    public void drive();
}

/**
 * Nitro baby!
 */
public class NitroCar implements Car
{
    private final Car car;    
    
    public NitroCar(Car car)
    {
        this.car = car;
    }

    private void applyNitro()
    {
        System.out.println("Applying Nitrous Oxide");
    }

    @Override
    public void drive()
    {
        this.applyNitro();
        this.car.drive();
    }
}

/**
 * Let's put this nitro to the test
 */
public class DriverTest
{
    @Test
    public void drive() throws Exception
    {
        Driver brianOConner = new Driver();
        
        Car eclipse = new MitsubishiEclipseRS();
        Car nitroCar = new NitroCar(eclipse);
        
        /*
         * "O'Conner appears to be ahead in the race, having equipped his Eclipse with Nitrous Oxide" (as quoted by Wikipedia The Fast and the Furious (2001 film)
 article)
         */
        brianOConner.drive( nitroCar );
    }
}

What if your driver’s licence said you can only drive a Porsche?

The money crisis is on and you have to sell your precious little horse for a new Yugo Zastava[Disclaimer]. You have to learn how to drive that as well.

In OO terms you are now presented with two options.

  • Add another method that allows you to drive the Yugo.
  • Extract an abstract class that allows you to drive any car

Now ask yourself this. How “abstract” will that abstract class be? Will you go as far as to define an AbstractCar class? What methods will this class define and how usefull will inheritance prove to be after all? Will you define an abstract GasolineCar that will at least give you some basic implementation on how such a car operates when you drive it?

So you go on and just use an abstract GasolineCar class since all cars run on gas anyway.

The electrical revolution is upon us and all of a sudden both your Porsche and Yugo are overshadowed by Toyota. Yet, you are left with driving just GasolineCar(s).

Now again you have two options.

  • Add another method that allows you to drive the ElectricCar
  • Extract an abstract class that allows you to drive any car

See a pattern here? It ain’t fun driving any more.

You give up and introduce an AbstractCar class after all to decouple the Driver from any implementation, but ask yourself this (rather rhetorical) question. If that abstract class merely defines an abstract drive method (or even a set of abstract methods) and nothing more, isn’t that what an interface is all about?

In this example obviously there is a need to drive different (implementations of) cars. You shouldn’t neccesary have to create an interface for every implementation that you have but use your best judgement and reasoning on where it’s suitable to do so. When designing an API will make more sense as you see a reason to make it extensible. In any case structure your code in such a way that when presented with the task you can easily introduce an interface later.

Most likely you will be introducing an abstract class to encapsulate a common algorithm for all your inheriting classes but tightening yourself to an abstract class is tightening yourself to an implementation which isn’t that obvious at first sight.

Think of an interface as a way to describe behaviour for your classes without any sort of definition of how the methods relate together. e.g. what can you do with all the cars? Drive them!

As a bonus to coding to an interface you can easily extend your cars (even at runtime!) by using composition over inheritance. All of a sudden you are fast and furious.

The above isn’t by any means a play of Greek tragedy in some theater in Epidaurus. Though an example it is very much real.

Disclaimer

No disrespect for the Yugo Zastava

]]>
Mon, 13 Sep 2010 00:00:00 +0200
Why is 8 numbers considered a "strong" password? https://qnoid.com/2010/09/07/Why-is-8-numbers-considered-a-strong-password.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/09/07/Why-is-8-numbers-considered-a-strong-password.html Just curious as to why 8 numbers are accepted as a password in linux (CentOS if it matters) and not 8 characters on a nonwdictionary word.

It’s 10 vs 26 per digit after all. (52 counting CaSe SeNsItIvE)

]]>
Tue, 07 Sep 2010 00:00:00 +0200
Reasoning ...Don't Lose Your Train Of Thoughts https://qnoid.com/2010/09/06/reasoning-dont-lose-your-train-of-thoughts.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/09/06/reasoning-dont-lose-your-train-of-thoughts.html
/**
     * First iteration
     */
    public class SurvivalKitOrder
    {
        /*
         * Tracking code
         */
        private final String code;    
        private final Collection<SurvivalKit> survivalKits;
        
        /*
         * All we need
         */
        public SurvivalKitOrder(String code, Collection<SurvivalKit> survivalKits)
        {
            this.code = code;
            this.survivalKits = survivalKits;        
        }

        /**
         * Does it make sense? 
         */
        public void purchase(ShippingMethod shippingMethod, Address address)
        {

        }    
    }

    /**
     * Ill conceived class
     */
    public class SurvivalKitOrder
    {
        private final String code;    
        private final Collection<SurvivalKit> survivalKits;
        private final ShippingMethod shippingMethod;
        private final Address address;
        
        /*
         * Are the relationships over yet?
         */
        public SurvivalKitOrder(String code, Collection<SurvivalKit> survivalKits, ShippingMethod shippingMethod, Address address)
        {
            this.code = code;
            this.survivalKits = survivalKits;        
            this.shippingMethod = shippingMethod;
            this.address = address;
        }

        /**
         * On second thoughts maybe not...
         */
        public void purchase()
        {

        }    
    }
While identifying the survival kit class we left out a presumably important method like purchase.

The initial hunch was to define it in the SurvivalKit class though a survival kit seems to better relate with an order (hint).

Looking at the SurvivalKitOrder there is a code property and a collection of SurvivalKit(s). (people might want to order more than 1 kit after all) Should we define the purchase method in the SurvivalKitOrder? Let’s see.

First of all, in order for the purchase method to work we need to have both the ShippingMethod and the Address to dispatch. Should the SurvivalKitOrder class use the ShippingMethod and Address through its purchase method?

Ask yourself the following questions.

  • Would you send the same order to the same address using a different shipping method?
  • Would you send the same order to a different address on the same shipping method?
  • Would you send the same order to a different address all together?

In any case, an order it’s not something you would reuse, since each must have a unique code. Thus you will need to create a new one every time.

So it only makes sense that you define both the ShippingMethod and the Address as properties to the SurvivalKitOrder. (after all an order must have a shipping method and an address associated)

Single responsibility is one thing and indeed SurvivalKitOrder sole responsibility is dealing with a purchase but don’t forget about the importance of well defined class relationships. The SurvivalKitOrder suddenly has a strong (e.g. can’t have one without a ShippingMethod and an Address) relationship with 2 other classes. Now there is nothing inheritly wrong with that, but there might be a better way. After all you don’t need another complicated relationship in your hands.

Leave your thoughts below on where you would define the purchase method. Don’t forget your reasoning behind it.

Disclaimer

As in every object oriented design there is a reasoning behind it all. Depending on the problem you are trying to solve most likely will differ. Not everything related to software engineering should be treated as gospel and as a developer you should apply critical thinking before making any decisions. Use that.

]]>
Mon, 06 Sep 2010 00:00:00 +0200
Do small code presentations https://qnoid.com/2010/09/01/Do-small-code-presentations.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/09/01/Do-small-code-presentations.html Every time a team or a single developer releases a piece of code for internal consumption, an overall presentation is a good thing to have.

That way you get the chance to

  • avoid going through every desk and explain intent or usage
  • state reasoning behind implementation
  • give an example on how it should be used
  • show how it can be extended

The presentation should be complimentary to comments (e.g. Javadocs) and unit tests.

]]>
Wed, 01 Sep 2010 00:00:00 +0200
Use types ...Don't Abuse The If https://qnoid.com/2010/08/30/types.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/08/30/types.html
/**
     * A lame dragon that can't make up his mind
     */
    public class IndecisiveDragon
    {
        public static final int FIRE_BREATH = 0;
        public static final int POISON_BREATH = 1;

        /*
         * Should be final but the default constructor forces us to forfeit
         */
        private int breath;
        private int damage;
        
        /**
         * Avoid naive constructor!
         * Forces breath and damage not to be final, and doesn't specify reasonable defaults.
         * Also, fails to show intend. What's a dragon without its breath?
         */
        public IndecisiveDragon(){}

        /**
         * @param breath which type of breath the dragon shall deal 
         * @param damage how much damage the breath should deal
         * @see #FIRE_BREATH
         * @see #POISON_BREATH
         */
        public IndecisiveDragon(int breath, int damage)
        {
            this.breath = breath;
            this.damage = damage;
        }
        
        /**
         * Rain chaos with just a breath  
         * @return the damage dealt by the dragon
         */
        public int breathe()
        {
            /*
             * Picture this as an if doing String comparisons and it only gets worse
             */
            switch (this.breath)
            {
            case FIRE_BREATH:
                System.out.println( String.format("Breathing mighty fire dealing %d damage", this.damage) );
            return this.damage;            
            case POISON_BREATH:
                System.out.println( String.format("Unleasing poison dealing %d damage", this.damage) );
            return this.damage;            
            default:
                System.out.println("Pants...Dealing no damage"); 
            return 0;
            }
        }
    }

    /**
     * A mighty dragon that can have custom {@link Breaths}
     */
    public class MightyDragon
    {
        /*
         * A dragon *has* breath
         */
        private final Breath breath;

        /**
         * @param breath give me breath
         * @see Breaths
         */
        public MightyDragon(Breath breath)
        {
            this.breath = breath;
        }

        /**
         * Rain chaos with just a breath  
         * @see Breath#breath()
         */
        public int breathe(){
        return this.breath.breathe();
        }
    }

    /**
     * The mighty breath
     */
    public interface Breath
    {
        /**
         * @return the damage dealt
         */
        public int breathe();
    }

    /**
     * Lot's of breaths for your perusal
     */
    public final class Breaths
    {
        /**
         * Making constants out of breaths is goooooooood.
         */
        public static final Breath FIRE_BREATH = new FireBreath(30);
        public static final Breath HEAVY_FIRE_BREATH = new HeavyFireBreath(20);
        public static final Breath POISON_BREATH = new PoisonBreath(50);
        public static final Breath NO_BREATH = new NoBreath();
    }

    final class FireBreath implements Breath
    {
        private final int damage;
        
        FireBreath(int damage)
        {
            this.damage = damage;
        }

        @Override
        public int breathe()
        {
            System.out.println( String.format("Casting mighty fire dealing %d damage", this.damage) );
        return this.damage;      
        }
    }

    final class PoisonBreath implements Breath
    {
        private final int damage;

        PoisonBreath(int damage)
        {
            this.damage = damage;
        }

        @Override
        public int breathe()
        {
            System.out.println( String.format("Unleasing poison dealing %d damage", this.damage) );
        return this.damage;      
        }
    }

    final class NoBreath implements Breath
    {
        @Override
        public int breathe()
        {
            System.out.println( "Pants...Dealing no damage" );
        return 0;      
        }
    }

    final class HeavyFireBreath implements Breath
    {
        private final int damage;
        private int multiplier;
        
        
        /**
         * @param damage
         */
        HeavyFireBreath(int damage)
        {
            this.damage = damage;
        }

        /**
         * Increments the multiplier and multiplies it to the damage
         * @param damage the damage to multiply
         * @return a multiplied damage
         */
        private int inhale(int damage) {
        return ++multiplier * damage;
        }

        @Override
        public int breathe() 
        {
            int damage = this.inhale(this.damage);
            System.out.println( String.format("Inhaling up to %d times dealing %d damage", this.multiplier, damage) );
        
        return damage;     
        }
    }


    /**
     * Here be dragons
     */
    public class MightyDragonTest
    {
        @Test
        public void breathe() throws Exception
        {
            MightyDragon harmlessDragon = new MightyDragon(Breaths.NO_BREATH);
            MightyDragon fireDragon = new MightyDragon(Breaths.FIRE_BREATH);
            MightyDragon poisonDragon = new MightyDragon(Breaths.POISON_BREATH);
            MightyDragon heavyFireDragon = new MightyDragon(Breaths.HEAVY_FIRE_BREATH);
            
            Assert.assertEquals(0, harmlessDragon.breathe());
            Assert.assertEquals(30, fireDragon.breathe());
            Assert.assertEquals(50, poisonDragon.breathe());
            Assert.assertEquals(20, heavyFireDragon.breathe());
            Assert.assertEquals(40, heavyFireDragon.breathe());
            Assert.assertEquals(60, heavyFireDragon.breathe());
        }
    }
Most of us would go mental having a dragon as a pet but what’s even more fun is creating your own! Now, designing your own dragon will most likely make you over excited causing you to simply dump code.

Take a look at the IndecisiveDragon class. This class has a breath property which is merely an int acting as a flag to designate the type of breath your dragon has. Having an int for that purpose not only poses a risk for arbitary breaths (thus making it harder to debug) but makes extending the dragon with a new breath even harder. Not to mention how scary your dragon can grow. And you don’t want that dragon turned against you.

In order to cope with the different types of breaths the #breathe method has a switch statement which depending on the value does something different. The important thing to notice is that a dragon has a breath therefore the #breathe method merely executes one branch per dragon (1 dragon - 1 breath, more on multiplicity later)

Finally, there is a naive default constructor which is used to just create a dragon and be done with it. Most likely this happens at a later stage when adding a method to the IndecisiveDragon class that has nothing to do with breath(s) or even the dragon itself in most cases.

Say hello to the MightyDragon. This dragon clearly states it’s relationship with a Breath type which not only ensures type safety among breaths but allows you to extend your class without modifying it making it easier to choose between different breaths. Notice how you delegate the code to the breath thus in essence applying polymorphism since every breath is implemented differently.

When creating a MightyDragon you are forced to explicitly choose 1 breath which the dragon shall have. (In OO terms this is actually the Strategy design pattern)

What’s also important to notice is how the HeavyFireBreath class defines an extra method related to the #breathe which otherwise would have ended up either inside your dragon class or part of the switch statement.

As a added bonus you get constants out of breaths which is gooooood.

Leave your comment below on how it helped you make your life a bit better without another if

Disclaimer

Again this is a trivial example. FireBreath, PoisonBreath and NoBreath aren’t really that different since they all return the damage dealt, so a single class would suffice. In any case the breath interface allows you to extend your dragon (adding custom breaths) without modifying its internal(s) [organs].

Kudoz

Mark Shuttleworth

Source

]]>
Mon, 30 Aug 2010 00:00:00 +0200
Immutability ...Don't Lose Your Train Of Thoughts https://qnoid.com/2010/08/26/immutability-dont-lose-your-train-of-thoughts.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/08/26/immutability-dont-lose-your-train-of-thoughts.html
/**
     * A nice little enum defining our shipping methods
     */
    public enum ShippingMethod
    {
        US_CANADA(0),
        INTERNATIONAL(10);

        private final int fee;
        
        /**
         * @param fee how much does it cost 
         */
        private ShippingMethod(int fee)
        {
            this.fee = fee;
        }

        /**
         * @return the fee of the shipping method
         */
        public int fee() {
        return this.fee;
        }
    }

    /**
     * You can use a class too!
     */
    public final class ShippingMethodImpl
    {
        public static final ShippingMethodImpl US_CANADA = new ShippingMethodImpl(0);
        public static final ShippingMethodImpl INTERNATIONAL = new ShippingMethodImpl(10);

        private final int fee;
        
        /**
         * No need to have the constructor public.
         * 
         * @param fee how much does it cost 
         */
        private ShippingMethodImpl(int fee)
        {
            this.fee = fee;
        }
        
        /**
         * @return the fee of the shipping method
         */
        public int fee() {
        return this.fee;
        }    
    }

    /**
     * Hopefully we don't send out international orders for free!
     */
    public class ShippingMethodTest
    {
        @Test
        public void enumz() throws Exception
        {
            ShippingMethod usCanada = ShippingMethod.US_CANADA;
            ShippingMethod international = ShippingMethod.INTERNATIONAL;
            
            Assert.assertEquals(0, usCanada.fee());
            Assert.assertEquals(10, international.fee());
        }
        
        @Test
        public void classes() throws Exception
        {
            ShippingMethodImpl usCanada = ShippingMethodImpl.US_CANADA;
            ShippingMethodImpl international = ShippingMethodImpl.INTERNATIONAL;
            
            Assert.assertEquals(0, usCanada.fee());
            Assert.assertEquals(10, international.fee());
        }
    }

Class relationships are really important and noone wants a “complicated” one. Now although grammar does help sometimes it is still hard to decide which class should relate to which thus you end up not thinking too much about it and dump them on a need to have basis.

One way to think of classes is in terms of the object state they enforce. So in essence you have classes of two kinds. Muttable (the value of its fields can change) and immutable (you can tell from their final fields; see Disclaimer). It’s good practice not to mix the two since mixing a mutable with an immutable will give you a mutable one at the end :(.

The reason you should strive to design immutable classes is that are easier to maintain, (no state to worry about!) encourage reusability (objects are effectively constants!) and last but not least are thread safe. (woohoo, no concurrency bugs!)

Let’s take a look at the survival kit to identify classes that qualify for immutable. The text talks about 2 distinct shipping methods. US_CANADA and INTERNATIONAL. See a pattern here? With ShippingMethod as your class, you can have 2 objects, one for US_CANADA and second one for INTERNATIONAL. Yes constants (use CAPITAL to get your point across). In Java you can use an Enum for defining constants.

Summary:

  • Start with private final fields.
  • Don’t have (possible) immutable classes with mutable properties.
  • Make constants out of your immutable classes and reuse them.

There is still a long way to go before we start sending survival kits out, so leave your feedback below on how you would specify any further class relationships, now that you have acquired that extra knowledge.

Also, Misko Hevery gives you another clue as to how to think about your class relatiosnhips when it comes to dependency injection

Disclaimer

Not strictly true. final is about not changing the reference of an object while the object itself might still change. Take an array for example, though you might not be able to assign a different one, you can still change its contents.

Kudoz

Misko Hevery

]]>
Thu, 26 Aug 2010 00:00:00 +0200
Class Relationships ...Don't Lose Your Train Of Thoughts https://qnoid.com/2010/08/23/class-relationships-dont-lose-your-train-of-thoughts.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/08/23/class-relationships-dont-lose-your-train-of-thoughts.html During the introduction we established a simple way to identify objects and their respective classes via looking at nouns and verbs in a text.

Second most important thing when it comes to crafting good OO code is class relationships. Can’t really stress enough how important this is. Classes can grow pretty scary. Don’t underestimate this technique if you are trying to design software that you aren’t familiar with its problem domain. Though very basic its simplicity in identifying class relationships is powerful enough to help you write structured OO code.

Failing to identify proper class relationships can lead to unnecessary complexity, multiple responsibilities (driving you crazy), even manifesting concurrency problems.

Looking at the [Survival Kit class][1] you may have noticed that apart from its cost all its other properties are a TShirt, Mug, Wristband and 2 Sticker(s). As you can tell these are classes. (the most straight forward way to identify a class in code is because its first letter is capitalized, so know your code conventions)

In other words, each SurvivalKit has a TShirt, Mug, Wristband and 2 Sticker(s). So whenever you see a has in a text know that you have a class that is a property in another (most commonly known as composition).

The second relationship comes when a class is another. Take a look at everything a SurvivalKit has. You could say that each of them is a SurvivalKitItem(s). When a class is another class it simply inherits all its properties and methods. Now, there should be a good reason to use the is relationship (aka Inheritance) when it comes to classes so use it wisely.

Finally there is uses. Uses most of the time is related to method arguments. Therefore one class is an argument to another’s class method. Would you say that the #dispatch method (which as of now is left stranded) should expect another class as an argument?

With the above in mind, how would you design the SurvivalKitOrder class? With which classes should it have a relationship and what type? (is, has, uses)

Would you incorporate inheritance using a SurvivalKitItem type. If yes, how and why? Leave your comments below.

Disclaimer

Things are simplified on purpose. You need to walk before you can run.

]]>
Mon, 23 Aug 2010 00:00:00 +0200
Whiteboard https://qnoid.com/2010/08/20/Whiteboard.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/08/20/Whiteboard.html Use the whiteboard at your work to post daily tips. (Look for inspiration in your daily code)

  • Tip should be a single line
  • Give facts
  • List benefits
  • Write an example

That way you can improve overall code quality by raising awareness but also helps pinpointing bad code without getting personal ensuring code consistency across the team.

]]>
Fri, 20 Aug 2010 00:00:00 +0200
Preamble ...Don't Lose Your Train Of Thoughts https://qnoid.com/2010/08/15/preamble-dont-lose-your-train-of-thoughts.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/08/15/preamble-dont-lose-your-train-of-thoughts.html
/**
 * Describing all glasses of water in the known world
 */
public class GlassOfWater 
{
	private final Material material;
	private final Weight weight;
	private int capacity;
	
	/**
	 * When creating a new glass of water you have to say what material, how
	 * much it weights and how much water it can hold.
	 * 
	 * Pretty much like "Simon says"
	 * 
	 * @param material the material of the glass
	 * @param weight its weight
	 * @param capacity how much water can it hold
	 */
	public GlassOfWater(Material material, Weight weight, int capacity) 
	{
		this.material = material;
		this.weight = weight;
		this.capacity = capacity;
	}

	/**
	 * @return true if you can smash it, is it made of glass?
	 */
	public boolean smash() {
	return this.material.equals(Material.GLASS);
	}
	
	/**
	 * @return true if you can lift it, is it light?
	 */
	public boolean lift() {
	return this.weight.equals(Weight.LIGHT);
	}
	
	/**
	 * Drink responsibly
	 *  
	 * @param amount how much do you want to drink
	 * @return what's left.
	 */
	public int drink(int amount){
	return this.capacity -= amount;
	}
}

/**
 * Let's prove our theory that you can indeed lift/smash and drink from a glass 
 * of water
 */
public class GlassOfWaterTest 
{
	@Test
	public void test() throws Exception 
	{
		/**
		 * Here is your glass of water object.
		 */
		GlassOfWater aGlassOfWater = new GlassOfWater(Material.PLASTIC, Weight.HEAVY, 330);
		
		/**
		 * Let's drink some, water level drops
		 */
		int remainingWater = aGlassOfWater.drink(330);
		
		Assert.assertFalse( aGlassOfWater.lift() );
		Assert.assertFalse( aGlassOfWater.smash() );
		Assert.assertEquals( 0, remainingWater );
	}
}
This is the first part of the series (Introduction to object oriented programing) about taking a paragraph of text and identifying objects that are the corner stone of an object oriented program.

Before I go into the actual text let me first establish some basic rules about what is an object. Go get a glass of water. It’s the first step to understanding OO programming. Go on, I’ll be waiting.

Would you say that the glass of water is an object?

If so, how would you describe it? It’s made of a material (glass/plastic), has some weight (heavy/light) and holds some amount of water as in; its capacity. It has properties.

What can you do with it? Smash it, lift it, and last but not least drink from it. It has methods.

Now, take a good look at yours. Is it broken? Is it floating in mid air? Is it half full? Drink some. Is it half empty now? In one word. It has a state.

Oh, and it has a name. Let’s call it aGlassOfWater.

Now there are quite a lot of glasses of water out there. Therefore in order to define them we use a class.

A class merely describes what a glass of water really is. Thus, its properties and methods. (indirectly describes its possible states as well but leave that for now)

Oh, and it has a name. Let’s call it GlassOfWater.

What about time? Or color? Are these objects? What classes would they describe them? Leave your thoughts below in the comments.

After that, take a look at the survival kit. That will be the basis of our OO analysis.

]]>
Sun, 15 Aug 2010 00:00:00 +0200
Polymorphism ...Don't Abuse The If https://qnoid.com/2010/08/15/polymorphism.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/08/15/polymorphism.html
/**
     * Good luck with that. Especially when it grows from a scary one to a mean one.
     */
    public class ScaryCalculator
    {
        /**
         * Hard to maintain. 
         * Need to read through the if(s) and identify the code and variables that
         * you are interested. Not pleasant.  
         * 
         * Hard to extend.
         * Every time you need to add an operation you have to look at that scary
         * method and find a way to stick your code in it without messing with the 
         * rest. Not fun.
         * 
         * Not reusable.
         * You can't reuse any of the operations on a different class. Not efficient.
         */
        public int calculate(int x, int y, String operator)
        {
            if("+".equals(operator)){
                return x + y;
            }
            else if("-".equals(operator)){
                return x - y;
            }
            else if("*".equals(operator)){
                return x * y;
            }
            else if("/".equals(operator)){
                return x / y;
            }
            
            throw new UnsupportedOperationException(operator);
        }
    }


    /**
     * Hello polymorphism!
     */
    public class FunCalculator
    {
        /**
         * Interface to the rescue. Each operation is implemented differently.
         * So depepnding on the operation you pass in, you get a different result!
         * Oh the joy of polymorphism. (Maintenable)
         */
        public int calculate(int x, int y, Operation operation) {
        return operation.make(x, y);
        }
    }


    /**
     * Want to support a new Operation? Implement this interface! (Extensible)
     */
    public interface Operation
    {
        /**
         * Free to do any operation you like
         */
        public int make(int x, int y);
    }

    /**
     * Classes implementing that interface
     */
    public class Addition implements Operation
    {
        @Override
        public int make(int x, int y) {
        return x + y;
        }
    }

    public class Subtraction implements Operation
    {
        @Override
        public int make(int x, int y) {
        return x - y;
        }
    }

    public class Multiplication implements Operation
    {
        @Override
        public int make(int x, int y) {
        return x * y;
        }
    }

    public class Division implements Operation
    {
        @Override
        public int make(int x, int y) {
        return x / y;
        }
    }

    /**
     * Encapsulates the decision on which operation you get based on the operator.
     * Operations for everyone! (Reusable) 
     */
    public class OperationFactory
    {
        /**
         * Use a Map as an index for your operations!
         * Want to extend to include a new one? Simply put it in the Map!
         */
        private final Map<String, Operation> operations = 
            new HashMap<String, Operation>(){
                {
                    this.put("+", new Addition());
                    this.put("-", new Subtraction());
                    this.put("*", new Multiplication());
                    this.put("/", new Division());
                }
            };

        /**
         * @param operator what's your choice?
         */
        public Operation newOperation(String operator) 
        {
            Operation operation = this.operations.get(operator);
            
            /**
             * An innocent if
             */
            if(operation == null)
                throw new UnsupportedOperationException(operator);
            
        return operation;
        }
    }

    /**
     * Let's put it to the test
     */
    public class CalculatorTest
    {
        @Test
        public void make()
        {
            int x = 2;
            int y = 2;
            
            OperationFactory operationFactory = new OperationFactory();
            
            Operation addition = operationFactory.newOperation("+");        
            Operation subtraction = operationFactory.newOperation("-");        
            Operation multiplication = operationFactory.newOperation("*");
            Operation division = operationFactory.newOperation("/");        
            
            FunCalculator calculator = new FunCalculator();
            
            Assert.assertEquals(4, calculator.calculate(x, y, addition));
            Assert.assertEquals(0, calculator.calculate(x, y, subtraction));
            Assert.assertEquals(4, calculator.calculate(x, y, multiplication));        
            Assert.assertEquals(1, calculator.calculate(x, y, division));
        }
    }
If. One of the fundamental keywords in a programming language and most abused (close second is inheritance [Disclaimer]). Has been there since the dawn of programming so people are fond of it. A joy for juniors as it gives them power to put some logic in their code.

Now, there is nothing wrong with if per se. There are some valid cases where an if is what you need but I have come to realise [Disclaimer] that one if per method should be adequate. (A couple are ok, as long as are part of the same branch)

Usually one of the most common wrong usage of an if is failing to identify polymorphism.

Take a look at the ScaryCalculator#calculate(int, int String) method.

There are actually 2 things going on in the code.

  • the decision on which operation to make
  • the different operation based on the String operator.

When you see a code structured like that you have most likely encountered polymorphism. (You are blessed) What this means is that you have objects that the have a common method but implemented differently.

  1. identify what those objects are. Operation(s); that’s your interface.
  2. identify the common code. Make the operation; that’s your interface method.
  3. identify the different operations that you have. Addition, Subtraction, Multiplication, Division; these are your classes implementing that interface each encapsulating the relative operation code.

Also, use a map for an index if what you actually need is a choice!

There are a couple of other wrong usages of if that will try to explore in the Don’t abuse the If series, but please feel free to explore them yourself or comment below.

The Don’t lose your train of thoughts series are far from over

Disclaimer

Not based on scientific research but from experience.

This is example code. Not quality code (limited to 2 numbers, String literals instead of enums) but the advice still stands. Take this instead.

]]>
Sun, 15 Aug 2010 00:00:00 +0200
Introduction ...Don't Lose Your Train Of Thoughts https://qnoid.com/2010/08/15/introduction-dont-lose-your-train-of-thoughts.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/08/15/introduction-dont-lose-your-train-of-thoughts.html
/**
     * Survival Kit #1
     * Rock some awesome Forrst schwag and show your support for the community.
     */
    public class SurvivalKit
    {     
        private final TShirt tShirt;
        private final Mug mug;
        private final Wristband wristband;
        private final Collection<Sticker> stickers;
        private final int cost;
        
        public SurvivalKit(TShirt tShirt, Mug mug, Wristband wristband, Collection<Sticker> stickers, int cost)
        {
            this.tShirt = tShirt;
            this.mug = mug;
            this.wristband = wristband;
            this.stickers = stickers;
            this.cost = cost;
        }

        /**
         * @return the tShirt
         */
        public TShirt tShirt() {
        return tShirt;
        }

        /**
         * @return the mug
         */
        public Mug mug() {
        return mug;
        }

        /**
         * @return the wristband
         */
        public Wristband wristband() {
        return wristband;
        }

        /**
         * @return the stickers
         */
        public Collection<Sticker> stickers() {
        return stickers;
        }
        
        /**
         * @return the size
         */
        public Size size(){
        return this.tShirt.size();
        }

        /**
         * @return the cost
         */
        public int cost(){
        return this.cost;
        }
    }

If you are totally unfamiliar with the notion of objects you should read the preamble first

To start building an OO program you need objects. The most basic way to identify objects in a text is looking at the nouns.

Take a look at the survival kit. Some of the nouns identified are tshirt (cotton), mug (coffee, tea, beverage, site), wristband, sticker (vinyl) and the survival kit itself. Also, shipping (fee - implied, cost - disguised as an image)

Now since objects are used to do things with or on them the second step is to identify their methods. Look at the verbs for that. wear, enjoy, browse, purchase. Some might be disguised like make friends jealous or even implied dispatch once a purchase is made.

Now all you have to do is make the association between which objects have which methods and create your classes. Some will be straight forward, others not so much.

You might be tempted to define a purchase method in the survival kit but let me ask you this. What is a purchase method supposed to do? Most likely will calculate the cost of the order and dispatch the item to a given address based on a shipping method.

An important thing to have in mind when crafting your OO code is to design classes with single responsibility.

You might think, hell that will only create so many classes! Well, if a class has a reason to exist you should do well to create one. There isn’t such thing as too many classes when there is a reason. Even if you don’t create a class, it will still manifest itself in your code. The ability to correctly identify the right number of classes only comes with experience.

If you are instead troubled that you will end up creating a vast API that will be cumbersome to use and difficult to understand there are other ways to hide those classes or design patterns to make using your API easier.

Although a basic methodology, you will be surprised how effective it is even for those technical specs or system requirements that you read. Especially when you are clueless about the problem domain.

Till the next post, leave your comments below on which class you would define a purchase method and what are some of the objects/classes you have identified in the survival kit.

Part of the Don’t lose your train of thoughts series.

]]>
Sun, 15 Aug 2010 00:00:00 +0200
You need to know grammar, not math to do Object Oriented programming https://qnoid.com/2010/08/11/you-need-to-know-grammar-not-math-to-do-object-oriented-programming.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/08/11/you-need-to-know-grammar-not-math-to-do-object-oriented-programming.html Now this is part of a greater series of posts that will follow, about how you go on writing code in an OO world. All the way from analysis to testing covering all sorts of topics and coding practices following a tutorial style.

It strikes me as odd (though I see the reason) that a lot of developers find it hard to correctly identify classes, objects, class relationships, responsibilities etc.

Seems to me like they quickly try to put their thoughts into code in fear of losing them and as a result have working code -yes- but quite as messy as their thoughts.

Now all the posts (including this one) that will follow on the series will not try to be clever. But hopefully act more like a reminder on what OO programming is all about.

It may sound controversial and some might gasp when I say this but; what precedes OO programming is grammar not math. That’s OO 101. (though it doesn’t seem to be part of any University’s module guide)

So what to expect. The series will take a paragraph of text from any source on the internet (could be a wikipedia article, a news story or even a qnoid post) and transform it to object oriented code.

The series will be called “Don’t lose your train of thoughts, so don’t miss a post!

Disclaimer

As always, the code that will be part of the series is “example code”. Do take it seriously, but only as much. Take the advice, not the code.

Kudoz

Derren Brown (inspired for the title “Train of Thoughts” from one of his “Trick of the Mind” episodes)

]]>
Wed, 11 Aug 2010 00:00:00 +0200
Be Pissed, Be Polite. Always Say "Good Bye!" (the Reason Behind 'finally' In A Try:catch) https://qnoid.com/2010/08/05/the-reason-behind-finally.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/08/05/the-reason-behind-finally.html
/**
 * You are asking for trouble here
 */
public void buyMuffin(LocalStore localStore, Flavour flavour)
{
    try
    {
        localStore.buyMuffin(flavour);
    }
    catch(MuffinNotFoundException e)
    {
        System.out.println("Pissed!");
    }
        
    System.out.println("Good bye!");
}

/**
 * Not my problem I don't have any money!
 * (InsufficientFundsException not handled)
 * You aren't being polite.
 */
public void buyMuffin(LocalStore localStore, Flavour flavour)
{
    try
    {
        localStore.buyMuffin(flavour);
    }
    catch(MuffinNotFoundException e)
    {
        System.out.println("Pissed!");
    }

    System.out.println("Good bye!");
}

/**
 * I don't give a damn! Still have to be polite though.
 */
public void buyMuffin(LocalStore localStore, Flavour flavour)
{
    try
    {
        localStore.buyMuffin(flavour);
    }
    catch(MuffinNotFoundException e)
    {
        System.out.println("Pissed!");
    }
    finally
    {
        System.out.println("Good bye!");
    }
}

/**
 * Just want my muffin
 */
public void buyMuffin(LocalStore localStore, Flavour flavour)
{
    try
    {
        localStore.buyMuffin(flavour);
    }
    finally
    {
        System.out.println("Good bye!");
    }
}

There has been a lot of debate about exceptions and their usage in the Java world. This post is not about it.

A foreword on what exceptions really are in case you are still confused.

Consider yourself going to your local store to buy a muffin (an addict here).

Now I prefer a chocolate one but the local store might not have one. So I walk in, go to the muffins section and… there is none! Something unexpected happened (hint an Exception). Yeah I’m pissed but I still have to be polite and say goodbye on my way out.

Now the only way to ensure that; is the ‘finally’ clause in a try/catch block. Here is why.

Without a ‘finally’ this might very well work. You do handle the exception right there and you still get to say “Good bye!” at the end. There are 2 things to consider though.

  • the LocalStore#buyMuffin(Flavour) method might very well change (especially if it’s third party code) introducing a new exception to the mix (InsufficientFundsException since people were just buying muffins without having enough money to pay). You aren’t being polite anymore.
  • you may not be responsible for handling the situation of not having enough money to buy a muffin. Your dad/employer/clients are. (in the “real world” an example would be to have a common class to log the exceptions)

Now in both cases not having a finally clause will simply break your code sooner or later. (Picture this with database connections and you have a serious leak there)

Disclaimer Take the advice. Not the code. It’s just an example.

]]>
Thu, 05 Aug 2010 00:00:00 +0200
I'm a developer, you are a designer, we get along. We are both Person(s) after all https://qnoid.com/2010/08/02/abstract-class.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/08/02/abstract-class.html
public interface Person
{
    /**
     * We can both make posts. Woohoo.
     */
    public void makePost(Post post);
}


/**
 * Abstract class encapsulating the highly sophisticated algorithm of writing a
 * post. Developer, Designer, doesn't matter. 
 */
public abstract class AbstractPerson implements Person
{
    protected abstract void title(Post post);

    protected abstract void pasteCode(Post post);
    
    protected abstract void description(Post post);
    
    protected abstract void tags(Post post);
    
    @Override
    public void makePost(Post post)
    {
        title(post);
        pasteCode(post);
        description(post);
        tags(post);
    }
}

/**
 * Developer
 */
public class Developer extends AbstractPerson implements Person
{
    @Override
    protected void title(Post post)
    {
        post.title("I'm a developer, you are a designer, we get along. We are both Person(s) after all.");
    }

    @Override
    protected void pasteCode(Post post)
    {
        //Java code about abstract classes and interfaces. Didn't want to create an endless recursion.
    }

    @Override
    protected void description(Post post)
    {
        /*
         *What's the difference between an Abstract class and an Interface? 
         *Radical. A common misunderstanding and a source of confusion. 
         */
    }

    @Override
    protected void tags(Post post)
    {
        post.tags("java");
    }
}

/**
 * Designer
 */
public class Designer extends AbstractPerson implements Person
{
    @Override
    protected void title(Post post)
    {
        post.title("Padded column Compass mixin");
    }

    @Override
    protected void pasteCode(Post post)
    {
        /*
         * cool CSS snippet
         */
    }

    @Override
    protected void description(Post post)
    {
        /*
         * Unfortunately, Compass @column mixin is a bit inefficient, since it 
         * just sets width so it requires a nested div to set padding without 
         * breaking the grid.
         */
    }

    @Override
    protected void tags(Post post)
    {
        post.tags("CSS");
    }
}

What’s the difference between an Abstract class and an Interface? Radical. A common misunderstanding and a source of confusion.

I’m a developer, you are a designer. That’s fine. We should both be able to make posts in Forrst. We are Person(s) after all.

An interface is all about behaviour. What can both a Developer and a Designer do in Forrst? That’s right, make posts. That’s our common behaviour here in Forrst, what makes us interchangeable.

Now I will be most likely writing about Java and you will be showcasing your million dollar design, but we both have to go through the same process of writing our post.

  • Specify a title
  • Paste some code
  • Enter a description
  • Put some tags

Now that’s a pretty nifty algorithm that we both have to go through to write a post and that’s what a base class is good at. Encapsulating common code.

However, since we won’t be writing the same stuff anyway though (title, code, description, tags), it’s destined to be abstract.

A follow up post titled Why I don’t drive a Porsche tries to put the final nail in the coffin on when/how to use an interface compared to an abstract class

Disclaimer: Another trivial example, don’t put that in production code please. Special thanks: @sugarenia for the designer’s code

]]>
Mon, 02 Aug 2010 00:00:00 +0200
Focus on your test, leave buggage behind https://qnoid.com/2010/07/29/Focus-on-your-test-leave-buggage-behind.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/07/29/Focus-on-your-test-leave-buggage-behind.html
public class MySelfTest
    {
        @Test
        public void goOutWithYourMates() throws Exception
        {
            MySelf mySelf = new MySelf();
            
            /**
             * Not DRY
             */
            mySelf.getOver( new ExGirlfriend() );
            
            Assert.assertTrue( mySelf.goOutWithYourMates() );        
        }
        
        @Test
        public void playStarcraft() throws Exception
        {
            MySelf mySelf = new MySelf();

            /**
             * Not DRY
             */
            mySelf.getOver( new ExGirlfriend() );
            
            Assert.assertTrue( mySelf.playStarcraft() );        
        }
    }

    /**
     * DRY yourself
     */

    /**
     * Create implementations of this interface with your conditions
     */
    public interface Condition
    {
        /**
         * Put the condition logic here 
         */
        public void apply();
    }


    /**
     * Introduce Preconditions
     */
    class Preconditions
    {
        static Condition all(final Condition... conditions)
        {
        return new Condition() {            
                @Override
                public void apply()
                {
                    for (Condition condition : conditions)
                    {
                        condition.apply();
                    }                
                }
            };
        }
        /**
         * @return
         */
        static Condition buggageShouldBeLeftBehind(final MySelf mySelf, final Girlfriend girlfriend)
        {
        return new Condition() {        
                @Override
                public void apply(){
                    mySelf.getOver( girlfriend );
                }
            };
        }
    }

    /**
     * Leave buggage behind
     *
     */
    public class MySelfTest
    {
        @Test
        public void goOutWithYourMates() throws Exception
        {
            MySelf mySelf = new MySelf();
            
            Preconditions.buggageShouldBeLeftBehind(mySelf, new ExGirlfriend()).apply();
            
            Assert.assertTrue( mySelf.goOutWithYourMates() );        
        }
        
        @Test
        public void playStarcraft() throws Exception
        {
            MySelf mySelf = new MySelf();

            Preconditions.buggageShouldBeLeftBehind(mySelf, new ExGirlfriend()).apply();
            
            Assert.assertTrue( mySelf.playStarcraft() );        
        }
    }
Use a class to define your Preconditions.

You don’t pollute your test class with methods not related explicitly to your tests and avoid boilerplate code.

Preconditions class

  • encapsulates the Condition(s)

while making your code

  • readable
  • reusable

Can apply to any conditions you would like to encapsulate really.

Disclaimer: It’s a trivial example to make you think of an alternative way to apply pre/post conditions to your tests.

]]>
Thu, 29 Jul 2010 00:00:00 +0200
Everytime you write an init method a developer gets an Exception ...Simply Don't https://qnoid.com/2010/07/22/Everytime-you-write-an-init-method-a-developer-gets-an-Exception-simply-dont.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/07/22/Everytime-you-write-an-init-method-a-developer-gets-an-Exception-simply-dont.html
	public class Plane
    {
        private boolean engineStarted;

        /**
         * Don't do that
         */
        public void init()
        {
            this.startEngine();
        }
        
        /**
         * 
         */
        public void startEngine(){
            this.engineStarted = true;
        }
    }

    public class PlaneFactory
    {
        /**
         * @return a new {@link Plane} ready to take off
         */
        public Plane newPlane()
        {
            Plane plane = new Plane();
            plane.startEngine();
            
        return plane;
        }
    }

Don’t write #init methods. They only add an extra place for the client code to look for and lead to frustration when trying to figure out what went wrong.

Instead use a factory method to return an object to the required state and document that.

]]>
Thu, 22 Jul 2010 00:00:00 +0200
Apply polymorphism or you will drive yourself crazy https://qnoid.com/2010/07/22/Apply-polymorphism-or-you-will-drive-yourself-crazy.html?utm_source=blog+rss+feed&utm_medium=rss&utm_campaign=rss+feed https://qnoid.com/2010/07/22/Apply-polymorphism-or-you-will-drive-yourself-crazy.html
	public class Psychiatrist
    {
        private final Pharmacy pharmacy;

        private Psychiatrist(Pharmacy pharmacy)
        {
            this.pharmacy = pharmacy;
        }

        public Prescription takeCare(MultiplePersonality personality)
        {
            // MultiplePersonality may have been created with a 
            // String, Integer or just a Boolean

            // try to get a String from MultiplePersonality object
            String string = personality.areYouAString();
            if (string != null) {
                this.pharmacy.isAString(string);
                return this.pharmacy.getPrescription();
            }

            // or try to get an Integer from MultiplePersonality object
            Integer integer = personality.areYouAnInteger();
            if (integer != null) {
                this.pharmacy.isAnInteger(integer);
                return this.pharmacy.getPrescription();
            }

            // or try to get just a Boolean from MultiplePersonality object
            Boolean nuts = personality.areYouNuts();
            if (nuts == null) {
                throw new RuntimeException();
            }
            
        return null;        
        }
    }

    /**
     * Instead use this
     */

    public class Psychiatrist
    {
        private final Pharmacy pharmacy;

        private Psychiatrist(Pharmacy pharmacy)
        {
            this.pharmacy = pharmacy;
        }

        public Prescription takeCare(Personality personality) {
        return this.pharmacy.getPrescription(personality);        
        }
    }

    public class Pharmacy
    {
        public void isAString(String string)
        {

        }

        public void isAnInteger(Integer integer)
        {

        }

        public Prescription getPrescription(Personality personality)
        {
            personality.whatAreYou(this);

            //decide upon prescription
        }
    }

    /**
     * With a Personality for each
     */
    public class IntegerPersonality implements Personality
    {
        private final Integer integer;

        private IntegerPersonality(Integer integer)
        {
            this.integer = integer;
        }

        @Override
        public void whatAreYou(Pharmacy pharmacy) {
            pharmacy.isAnInteger(this.integer);
        }
    }

    public class StringPersonality implements Personality
    {
        private final String string;

        private StringPersonality(String string)
        {
            this.string = string;
        }

        @Override
        public void whatAreYou(Pharmacy pharmacy) {
            pharmacy.isAString(this.string);
        }
    }

    public class SanePersonality implements Personality
    {
        @Override
        public void whatAreYou(Pharmacy pharmacy) {
            throw new RuntimeException("I'm sane!");
        }
    }

Don’t try to do to much. (Class Relationships). Identify polymorphism in 3 steps. (How to identify polymorphism)?

  • find the common operation (e.g. #whatAreYou)
  • find how is every operation different and put it in a method in each own class (e.g. #isAString, #isAnInteger, “is nuts”)
  • introduce an interface for the above classes with that common method

That’s all really. Try it with a Calculator example now.

Using polymorphism will

  • eliminate the need for multiple if(s)
  • eliminate the check for null
  • eliminate the exceptional case (in this case to return null)

Plus on each Personality class you get

  • final fields
  • single responsibility
  • encapsulation

Disclaimer: This is actual (disguised) code as seen on a very popular API. There are even more problems to discuss about it but let’s just focus on one thing at a time.

]]>
Thu, 22 Jul 2010 00:00:00 +0200