From the blog

Open/Closed and the Single Responsibility Principle

single-responsibility
The SOLID principles of object-oriented design provide good guidelines for writing code that is easy to change, but for some of the principles, the motivation and value can be difficult to understand. Open/Closed is particularly vexing: software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification What does it mean to be extended but not modified? Does this principle lead inherently to deep, convoluted class hierarchies? There has been some discussion and criticism of SOLID and the Open/Closed principle recently, so we thought we’d share some of the Rescale development team’s experiences coming to an understanding of Open/Closed and using it to write classes whose behavior is easy to change. We view Open/Closed as a complement to the Single Responsibility Principle since it encourages developers to write classes with focused responsibilities whose behavior is easy to change with minimal code modifications.

An explanation

First off, let’s explore some of our initial questions. What does it mean for code to be extended? What does it mean for it to be modified? Code is modified when we change the code itself–by adding conditionals to methods, pulling in extra arguments, switching behavior based on properties of arguments, and so on. This is often developers’ first thought on how to make existing code accomplish a new task–just add another conditional. Code is extended when we change its behavior without modifying the code itself– by injecting different collaborators. For our code to even be amenable to such extension, we have to be following many of the other SOLID principles–injecting different objects for each aspect of the task we wish to accomplish. That in turn requires that each aspect of the task be accomplished by a different object, which is the heart of the Single Responsibility Principle–objects should do only one thing. Open/Closed encourages developers to write code that distributes responsibilities and provides the benefits of making behavior easy to change without growing long methods and large classes.

An example

Let’s illustrate all this theory with an example. At Rescale, we recently refactored a bunch of code to use a REST API client. API clients are often written with different methods for each type of request callers wish to make, and that’s how ours started. We had an interface like:

public interface APIClient {
    Analysis getAnalysis(long jobId);
    HardwareSummary getHardwareSummary(long jobId);
    ...
}

Each of the method implementations looked like:

public Analysis getAnalysis(long jobId) {
    String path = “/api/jobs/” + jobId + “/analysis/”;
    String response = makeHttpRequest(new URL(this.baseApiUrl, path));
    return parseJson(response, Analysis.class);
}

This was a pain to work with. Every time we wanted to get a new piece of data from the API we had to add a new, redundant method. This client wasn’t open for extension, and in order to change its behavior we had to modify the class. That stemmed from a muddying of responsibilities. Even though the method above looks simple, it actually has several different responsibilities and corresponding pieces of knowledge. It knows how to format paths for each request type. It knows how to make http requests to the API and knows how to parse json for each request. We decided to refactor this to give our API client just one responsibility–making requests. Instead, we would extend it by passing in Request objects that took over the other responsibilities. Now we have an API client interface with just one method:

public interface APIClient {
    public  T get(Request request);
}

Since each type of request is relatively static, we have static factory methods to create request objects.

public class Request {
    public static void Request forAnalysis(Job job) {
    ...
    }
}

And, thanks to Java generics, callers get back the correct type of object. We now have natural looking code like:

Analysis analysis = client.get(Request.forAnalysis(this.job));

And retrieving new information from the API is easy. We don’t have to modify the API client, we just extend it by passing in a different request.

Summary

There’s a lot of confusion about what Open/Closed implies, but it simply requires that objects have focused responsibilities and interact with other objects that are injected–that way developers are free to inject different collaborators to change behavior. Anyone who has worked in a large codebase has seen sections that were developed without Open/Closed in mind. This code is ostensibly simple and “just gets the job done”. The problem is that as the business desires inevitably change, the only way to change the job is to change the code. Methods accumulate conditionals and switch statements, classes accumulate fields, and the code becomes harder to understand at a glance. The poor design feeds on itself because the easiest way to accomplish a task is to simply add a few more lines to a method. If developers keep Open/Closed in mind, then they will be able to spot opportunities to create objects with extensible behavior and keep development costs from growing out of control.

Related articles

Expanding HPC in the Cloud to the Nordics

Overview and Key Comments EDRMedeso is a Premier Reseller Partner of Rescale and an Elite Channel Partner of ANSYS In this webinar, we dive into the maturity of the Cloud HPC market in the Nordics region. Frode Halvorsen, VP of […]

read more »

クラウドHPCの3つの隠れたメリット

Rescaleの米国中部地域担当セールスのJJ Jonesがポストしたブログ記事の翻訳です。 元記事は3 Hidden Benefits of Cloud HPCをご覧ください。 企業は、クラウド上のハイパフォーマンスコンピューティング(HPC)に移行し、柔軟で多様な、従量課金型のHPCリソースへのアクセスを実現しつつあります。同時に、これらの資産を管理することや膨大な資本と時間を費やすことの必要がなくなりました。シミュレーションをクラウドのHPCリソースへ移行することで、企業は以前からは想像もできない規模で多彩な標準タイプおよび特殊タイプのハードウェアを活用できます。クラウドを活用することで、エンジニアリングスタッフの潜在力を発揮し、イノベーションを次のレベルに引き上げることができます。クラウドHPCが成熟するにつれて、これらの明らかな利点は、HPCワークロードに対するクラウドへの動きを促進することです。しかし、定量化を明らかにしづらいその他の利点がしばしば見落とされていますが、それらは本当のクラウドの変革の力を表しています。 この記事では、クラウドに移行することで見過ごされがちな、変革上の3つの利点を見ていきます。 1.トップレベルのエンジニアのリクルーティングや雇用維持 多くの企業が、クラウド資源へアクセスできる環境を保有することが、高い能力を持つエンジニアのリクルーティングや雇用維持に役立つことに気付いています。業界(産業)に関係なく、技術者は仕事に最適なツールを求めています。最速のクルマを持つレースチームが確実に最も有能なドライバーを引き付けるように、最高のツールを提供する組織は最高の才能を引き付けることができます。チームに対して、クラウドで利用可能なシミュレーション機能にに対して深く幅広いアクセスを提供する企業は、現在のハードウェア環境に対する不満を防ぎます。新しい技術が利用できるようになると、エンジニアは既存の社内リソースが完全に償却されるのを待つことなく、流通する最新のテクノロジーにアクセスすることができます。これは、最高の才能を引きつけ維持する企業の能力に顕著な影響を与えています。最近のクラウドカンファレンスでパネルの中であるグローバルCIOが次のように述べました。「従来のインフラストラクチャを利用しているなら、偉大なプレイヤーは得られません」 2.組織のアジリティ 見過ごされがちなもう一つの利点は、クラウドが組織にもたらす全体的な柔軟性です。革新的なアイデアを提供したり、新説を打ち立てたりするためには、企業や従業員は最新のテクノロジーにアクセスする必要がありますが、設備投資は痛みを伴う(そして危険な)決定になる可能性があります。いったん組織が資金を確保し、長期的な調達プロセスを維持すると、現在の作業負荷を中断することなく移行するために人材配置をどうしたらよいのかという葛藤に直面します。クラウドによって、企業は必要に応じて素早く資産にアクセスすることができます。さらに、既存のワークロードを拡張してシミュレーション時間を短縮し、同時シミュレーションを実行することで、チームが日常的なタスクをより迅速に実行できるようになり、将来的に実行可能なタスクに集中できるようになります。この俊敏性と応答性は、企業が自社製品を次のレベルに引き上げることを可能にします。 上記の利点についての最も良い点は、それらを実現するためにクラウドに完全に移行する必要がないことです。既存の社内HPCリソースを使用している組織でも、引き続きそのリソースを使用可能です。才能のあるエンジニアに可能性を与えたり、新製品をリリースしたりする必要がある場合、クラウドの利用が突発させることも可能です。これを行うには、クラウドプロバイダーがターンキーであり、使用に長期的なコミットメントを必要としないことが重要です。(P.S. Rescaleはそうではありません!) 3.ITではなく、組織のコアコンピタンスにフォーカス 最後に、クラウドによって、組織はそのコアビジネスに集中することができます。あなたは飛行機や自動車を作ることができますし、薬を創ったり人工知能ツールをデザインすることもできますが、あなたはIT企業ではありません。企業は、膨大な時間とコストを費やすことに慣れてきており、正しいコンピューティングリソースがコアビジネスをサポートできるようになります。過去には選択肢がありませんでした。クラウドを完全に活用することで、組織はビジネスを推進する重要な戦略目標に集中して、必要なリソースの保守や管理をそのリソースを主要ビジネスとする人々に任せることができるようになります。ITチームは、従業員中心型のプロセスのサポートに集中するのを止めて、顧客中心型の収益創出活動に集中することができるようになります。 これらの隠されたクラウドへの移行の利点は、ROIの計算には簡単には現れません。これらのつかみどころのない側面の真の価値を数値化することは困難です。つまり、明白な利点は、クラウドへの移行を正当化するのにあまりに多く語られています。しかし、これらのつかみどこころのない利点は、組織がクラウドに移行すると必然的に現れます。これらは損益計算書に数値として直接表示されないかもしれませんが、市場シェアや収益性のような中核的なビジネス目標の長期的な上昇を目にすることによって、これらの存在を知ることになります。

read more »