0

Applying a design pattern

I believe it is only with experience that you learn if applying a design pattern would be beneficial or not. And at what stage it should be considered. For instance, if writing a piece of code, you can see which pattern your code is following, and then apply it. Rather than thinking that I will write a piece of code using an X pattern.

 

“Design patterns can be extremely helpful in crafting beautiful code, but the way in which they’re applied often determines their usefulness. Applying a design pattern in the wrong scenario can push you into a corner, ultimately leading to more disarray than would have been present if it weren’t for the design pattern. I’m going to pick on the singleton pattern a bit. (Pack, 2012)”

 

Pack (2012) discusses a situation where “applying a design pattern” can be discouraging.

“Let’s create a file system singleton that writes some text to /dev/null:


require ‘singleton’

class DevNullSingleton
  includeSingleton

 def write(text)
   File.open(‘/dev/null’, ‘w’) do |file|
      file.write text
   end
 end
end


We can use the singleton by referencing its instance:

DevNullSingleton.instance.write(‘Something to dev null’)

Realistically, this has the same semantics as setting a global constant if we didn’t want to use Ruby’s singleton library:


DEV_NULL = DevNullSingleton.new
# … later in the code …
DEV_NULL.write(‘Something to dev null’)


So, now our application grows, and we need another file system writer that outputs to /tmp. We’re posed with a few options.

We can rename our singleton and allow the #write method to accept a path. The API looks like this:


FileSystemSingleton.instance.write(‘/dev/null’, ‘Something to dev null’)
FileSystemSingleton.instance.write(‘/tmp’, ‘Something to tmp’)


This is bad. If we want to write numerous things to /dev/null, we have a large degree of duplication:


FileSystemSingleton.instance.write(‘/dev/null’, ‘Something to dev null’)
FileSystemSingleton.instance.write(‘/dev/null’, ‘Something ele to dev null’)
FileSystemSingleton.instance.write(‘/dev/null’, ‘Another thing to dev null’)


Alternatively, we can create a new singleton class that writes to /tmp:


class TmpSingleton
  includeSingleton

 def write(text)
   # …
 end
end


But now, every time we want to write to a different location on the file system, we need to create a new singleton class. Not great, either.

Probably, the better option is to break ties with the singleton and start instantiating classes normally:


class FileSystem
 def initialize(path)
   @path = path
 end

 def write(text)
   File.open(@path, ‘w’) do |file|
      file.write text
   end
 end
end


Now, when we want to write multiple times to /dev/null, we instantiate only once and use it as we would any other class:”


dev_null = FileSystem.new(‘/dev/null’)
dev_null.write(‘Something to dev null’)
dev_null.write(‘Something ele to dev null’)
dev_null.write(‘Another thing to dev null’)


References:

Pack, M. (2012) The First Step to Applying Design Patterns: Don’t. Available at: http://mikepackdev.com/blog_posts/36-the-first-step-to-applying-design-patterns-don-t (Accessed: 20 September 2017)

ayesha

Leave a Reply

Your email address will not be published. Required fields are marked *