It’s the open-closed principle!. Duh!

So, this has been my “facepalm moment” of the week. Not the only one I had this week, but the most remarkable one.

I was trying to explain what the Open Closed Principle is all about to a colleague. You know, “modules should be open for extension, but clsoed for modification”. You know, the good stuff.

As usual, I was trying to find a good example to illustrate the point of the OCP, and as usual, I was having a hard time finding it. Side note: finding good examples to illustrate abstract concepts is hard; if the example is too simple, everyone misses the point, if the example is too convoluted, everyone falls asleep.

And suddenly, the duh-facepalm-eyerolling moment! How can I be so dumb, the perfect example of the OCP is sitting right there, looking at us!

Now imagine we have a mechanism for transporting model objects across the wire, based on JSON:

1

2

3

4

5

6

7

8

9

10

protocolJSON{

func to_JSON()-&gt;[String:Any]

}

finalclassJSONDataSender{

func send(data:JSON){

print("Sending data ",data.to_JSON())

}

}

Well, we want to be able to send Contacts using this JSONDataSender, so we should make Contact implement the JSON protocol, right? True, but devil is in the details, and in this case, the simplest solution would require modyfing the source code of the Contact struct to add the new behaviour:

1

2

3

4

5

6

7

8

9

10

structContact:JSON{

let id:String

let name:String

let phoneNumber:Int

func to_JSON()-&gt;[String:Any]{

return["id":id,"name":name,"phoneNumber":phoneNumber]

}

}

Which would be a blatant violation of the Open Closed Principle (the object had to me modified in order to add behaviour to it). Tsk, tsk, tsk…

What’s the problem with that approach? Well, we might want to serialize to a protocol buffer, instead of JSON. Or write Contacts to a plist file, or to a SQLite database, or whatever. So every time we wanted to add that extra behaviour, we would need to edit the Contact source. Again, tsk, tsk, tsk.

However, if we don’t modify the original Contact, but add an extension:

1

2

3

4

5

6

7

8

9

10

11

12

structContact{

let id:String

let name:String

let phoneNumber:Int

}

extension Contact:JSON{

func to_JSON()-&gt;[String:Any]{

return["id":id,"name":name,"phoneNumber":phoneNumber]

}

}

We would have extended the object without actually modifying it. Again, the object would be open for extension and closed for modification. And adding subsequent behaviours would be a matter of adding more extensions. So, to me, and from now on, this counts as the perfect example to illustrate the Open Closed Principle (in Swift).