Depending how the code was written adding new services to it can be difficult.
For instance, let's say we are building a rails application that gets integrated to cloud storage vendors.
A naive implementation would be to directly integrate to a cloud storage specific APIs.
In this case when new cloud storage vendors are added it is very probable that several nasty case... when ... end statements would be inserted in code.
When a new cloud storage service is added the developer must remember all places where those growing case-like statements are inserted. This makes the system more susceptible to errors due to changes in several parts of the code. This problem is explained in detail by the shotgun surgery anti-pattern (http://en.wikipedia.org/wiki/Shotgun_surgery)
The rest of the system shouldn't be aware that a new cloudstorage service was added. That is where a combination of design patterns come in handy:
1) Cloud Storage Facade
2) Cloud Storage Adapter Locator
3) Cloud Storage Adapters
Note that this combination of patterns can be used to abstract many other types of services. Cloud storage service was just an example used here.
For instance, let's say we are building a rails application that gets integrated to cloud storage vendors.
A naive implementation would be to directly integrate to a cloud storage specific APIs.
In this case when new cloud storage vendors are added it is very probable that several nasty case... when ... end statements would be inserted in code.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def list_folder(cloud_storage,folder) | |
case cloud_storage | |
when "dropbox" | |
list_dropbox_folder(folder) | |
when "box" | |
list_box_folder(folder) | |
when "google-drive" | |
list_googledrive_folder(folder) | |
else | |
raise InvalidCloudStorageService(cloud_storage) | |
end | |
end |
The rest of the system shouldn't be aware that a new cloudstorage service was added. That is where a combination of design patterns come in handy:
- a facade to provide a simple interface for cloud storage operations
- a service locator to find the right cloud storage adapter
- a cloud storage adapters that make each vendor API compliant to a single defined interface that can be understood by the facade
1) Cloud Storage Facade
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class CloudStorageFacade | |
def initialize | |
@cloud_storage_adapter_locator = CloudStorageAdapterLocator.instance | |
end | |
def find_adapter(cloud_storage) | |
@cloud_storage_adapter_locator.find(cloud_storage) | |
end | |
def list_folder(cloud_storage,folder) | |
adapter = find_adapter(cloud_storage) | |
adapter.list_folder(folder) | |
end | |
# other cloud storage operations are declared here | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class CloudStorageAdapterLocator | |
def initialize | |
@adapters = {} | |
end | |
def self.instance | |
@@instance ||= CloudStorageAdapterLocator.new | |
@@instance | |
end | |
def find(cloud_storage) | |
@adapters[cloud_storage] | |
end | |
def register(cloud_storage,cloud_storage_adapter) | |
@adapters[cloud_storage] = cloud_storage_adapter | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class DropboxStorageAdapter # which implements Cloud Storage Adapter protocol | |
def list(folder) | |
# specific dropbox API code goes here | |
# note that the output must be translated to | |
# a format that is known by the facade | |
end | |
# other cloud storage operations declared here | |
end | |
# register the adapter right after and keep everything in one file | |
DropBoxAdapterLocator.instance.register(DropboxStorageAdapter.new) |