はじめに
今までRuby(Rails)を中心に開発していたのですが、Java(SpringBoot)をキャッチアップし始めたので、その所感について発信します。
言語・FWの違いは色々なサイトで紹介されているので、今回は実体験ベースで書いていきたいと思います。
あくまで個人の所感や体験談です。実際に学ぶ内容や過程は人それぞれです。
個人の目標に合わせて今回の投稿を参考にして頂ければと思います。
Javaを学ぼうと思ったきっかけ
理由は大きく分けて2通りあります。
事業目線
Ruby(Rails)はスタートアップなどで小規模なアプリを短期間で開発するのが得意だと思います。
なので「自分(もしくはクライアント)が作りたいサービスをすぐ形にしたい」という欲求が強かったと思います。
それが満たされてきた後に、「自分が開発していくサービスは社会のどんなところで役に立つのだろう?」と考えるようになってきました。
(元々インフラ系出身なので、社会貢献度の高い仕事にも関心があります)
そこで、より大規模なプロジェクトで広く採用されているJavaを習得することで、エンジニアとしてできることが増える。
あとは求人やプロジェクトの数も多いので、自分のキャリアにおける選択肢の幅も広がると思いました。
技術目線
後述のRubyとJavaの違いにも書きますが、Javaのオブジェクト指向設計や静的型付けなどのRubyとは異なる概念や設計思想を知り、プログラミング全般の理解を深めたいのもあります。
Rubyでは、ライブラリやFWを使うことで内部の処理をそこまで意識しなくても作れてた部分もあると思います。
そのRubyの直感的に書ける柔軟性というメリットの裏にあるRuby独特の曖昧さにモヤっとする時があります(これ、どういう仕組みなんだろう?みたいな)
そこでJavaをキャッチアップすることでRubyのオブジェクト指向プログラミングもより深く理解できればと思っています。
RubyとJavaの違い
設計思想
Java
-
堅牢性と安全性
Javaは静的型付け言語であり、コンパイル時に厳密な型チェックを行うことで、実行時エラーを減らし、堅牢なシステム構築を重視しています。 -
移植性
Javaは「Write Once, Run Anywhere(一度書けば、どこでも実行できる)
」という思想に基づいており、Java仮想マシン(JVM)上で動作することで、異なる環境でも同じように動作します。 -
大規模開発への対応
Javaは、大規模なエンタープライズシステム開発で広く利用されており、高いパフォーマンスと安定性が求められる分野に適しています。 -
オブジェクト指向の徹底
Javaは、オブジェクト指向プログラミングの概念を徹底的に追求しており、クラス、オブジェクト、継承、ポリモーフィズムなどを厳密に扱います。
// 型宣言の例
String name = "太郎";
int age = 30;
Ruby(Ruby on Rails)
-
プログラマーの幸福
Rubyは、プログラマーが楽しく、快適にプログラミングできることを重視しています。
コードの可読性や柔軟性を高めるための機能が豊富に提供されています。 -
柔軟性と表現力
Rubyは動的型付け言語であり、コードの柔軟性と表現力を重視しています。
プログラムの実行時に、型の整合性チェックを行います。 -
規約より設定
Ruby on Railsなどのフレームワークでは、「Convention over Configuration(規約より設定)
」という思想が採用されています。
これにより、開発者は定型的な設定を記述する必要がなく、ビジネスロジックに集中できます。 -
シンプルさと簡潔さ
Rubyは、コードをシンプルかつ簡潔に記述できることを重視しています。
そのため、文法が柔軟で、冗長なコードを減らすことができます。
# 型宣言の例
name = "太郎"
age = 30
もしJavaとRubyを擬人化したら...?
これはあくまで僕なりの例ですが、以下のように捉えています。
- Java→
堅実で真面目な上司
- Ruby→
仲の良い友達・親友
上記はあくまで特性であり、どちらが良い悪いかの優劣を判断するものではありません。
これによっても人との相性や向き不向きが分かれそうだなって思いました。
プログラムの実行方法
Java(コンパイル言語)
- 人間が記述したソースコードを、コンピュータが直接実行できる機械語に変換(コンパイル)します。この変換は、プログラムを実行する前に行われます
- Javaの場合、ソースコード(.javaファイル)は、Javaバイトコード(.classファイル)と呼ばれる中間言語にコンパイルされます
- コンパイル済みのプログラムは、インタプリタ言語よりも実行速度が速いです。なぜなら、実行時に毎回コードを解釈する必要がないからです
- コードを修正するたびにコンパイルが必要なため、開発サイクルが長くなることがあります。しかし、コンパイル時にエラーを検出できるため、実行時のエラーを減らすことができます
Ruby(インタプリタ言語)
- プログラムを実行するたびに、ソースコードを一行ずつ解釈しながら実行します。コンパイルのような事前変換は行いません
- インタプリタ言語は、コンパイル言語よりも実行速度が遅いです。なぜなら、実行時に毎回コードを解釈する必要があるからです
- コードを修正してすぐに実行できるため、開発サイクルが短く、プロトタイプ開発などに適しています。しかし、実行時にエラーが検出されることが多いため、テストが重要になります
文法の違い
メソッドの定義
Java
public static String greet(String name) {
return "こんにちは、" + name + "さん!";
}
public static
は、クラスのメンバ(変数やメソッド)をクラス自体に紐付け、*インスタンス化せずにアクセス可能にする修飾子です
Ruby
def greet(name)
"こんにちは、#{name}さん!"
end
「Rubyではpublic
を定義しなくても良いの?」と疑問に思った方もいるかもしれません。
そこでRubyのリファレンスマニュアルなどを確認してみました。
デフォルトでは def 式がクラス定義の外(トップレベル)にあれば private、クラス定義の中にあれば public に定義します。これは Module#public、Module#private、 Module#protected を用いて変更できます。
Ruby 3.4 リファレンスマニュアル クラス/メソッドの定義 「呼び出し制限」より抜粋
def foo # デフォルトは private
end
class C
def bar # デフォルトは public
end
def ok # デフォルトは public
end
private :ok # …だが、ここで private に変わる
def initialize # initialize は private
end
end
Rubyでは、このような柔軟なオブジェクト指向モデルと動的型付けによって、publicなどを明示的に指定しなくても、クラスメソッド、モジュール、トップレベルメソッドを使用してJavaと同様の機能を実現しているのだと思いました。
(間違ってたら教えてください)
クラスの定義
Java
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String introduce() {
return "私の名前は" + name + "、年齢は" + age + "歳です。";
}
}
コンストラクタは、クラスと同じ名前のメソッドとして定義されます。
*コンストラクタ
:オブジェクトの初期化を行う特別なメソッドであり、クラスのインスタンス生成時に暗黙的に呼び出されます。
Ruby
class Person
def initialize(name, age)
@name = name
@age = age
end
def introduce
"私の名前は#{@name}、年齢は#{@age}歳です。"
end
end
Rubyでは、オブジェクトの初期化は、initializeという名前のメソッドでおこないます。
コンストラクタもこのinitializeで定義されます。
Ruby 3.4 リファレンスマニュアル ライブラリ一覧 組み込みライブラリ Objectクラス initialize (private)
SpringBootとRailsの違い
こちらではJavaのFWであるSpringBootと、RubyのFWであるRuby on Railsを比較しています。
MVCアーキテクチャの違い
SpringBoot
- MVCアーキテクチャを基本としつつも、Railsより柔軟な設計が可能です
- RESTful APIの開発に重点を置いており、JSONやXMLなどのデータ形式を扱いやすいです
Rails
- MVCアーキテクチャを厳格に適用し、モデル、ビュー、コントローラーの役割を明確に分離します
- このフレームワークによってRESTfulな設計に基づいたルーティングが強力にサポートされています
CRUD操作の違い
SpringBoot
JPA(Java Persistence API)やMyBatisなどのORM(Object-Relational Mapper)により、データベース操作をオブジェクト指向で行えます。
- Spring Data JPAというライブラリを使うことで、リポジトリインターフェースを定義するだけでCRUD操作を実装できます
Rails
- Active RecordというORMにより、データベース操作をオブジェクト指向で行えます
- scaffoldという機能で、CRUD操作のコードを自動生成できます
テーブル・マイグレーション
SpringBoot(Java)
- FlywayやLiquibaseなどのライブラリを使用して、データベースのマイグレーションを管理することが一般的です
- SQLスクリプトまたはJavaコードでマイグレーションを記述し、データベースのスキーマを更新します
例:V1__create_users_table.sql
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL
);
Rails
- Active Recordマイグレーションという仕組みを使用して、データベースのスキーマ変更を管理します
- マイグレーションファイルは、Rubyのコードで記述され、データベースの変更内容をバージョン管理します
db/migration/20250201165640_create_users.rb
class CreateUsers < ActiveRecord::Migration[6.1]
def change
create_table :users do |t|
t.string :name, null: false
t.text :email, null: false
t.timestamps
end
end
end
MVCコード例
モデル(エンティティ)
SpringBoot(Java)
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Article {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String title;
private String content;
// ゲッター、セッター、コンストラクタなどをこの下に記載
}
*エンティティ
:データベースのテーブルをJavaオブジェクトとして表現したものです。
データベースのテーブルとマッピングされるオブジェクトであり、データベースとのやり取りを行います。
対してモデルは、アプリケーションのビジネスロジックやデータ処理を担当する部分です。
ドメイン駆動設計(DDD)に従って、エンティティとモデルを分離することが可能です。
どちらを使用するかは、アプリケーションの設計と目的によって異なります。
Rails
class Article < ApplicationRecord
end
Railsでは、Active RecordパターンというORM(Object-Relational Mapper)が、JavaのEntityに相当します。
データベースのテーブルとモデルが1対1で対応し、モデル自身がデータベースへのアクセスとデータの操作を行います。
つまり、Railsのモデルは、データベースのエンティティとしての側面と、アプリケーションのビジネスロジックを担うモデルとしての側面を併せ持っています。
Railsガイド 1.1 Active Recordパターン
RailsはDDDを前提としたFWではないため、Javaのようにエンティティとモデルを明確に区別して実装するという概念が薄いかもしれませんね。
コントローラー
SpringBoot
- アノテーションを使用して、URLとメソッドのマッピングやレスポンスデータをJSONまたはXML形式で直接返すことができます
- Java(特にSpring Boot)では、Railsのような独立したルーティングファイル(
routes.rb
など)は通常使用されません。代わりに、アノテーションを使用してルーティングを定義します
*アノテーション
: コードにメタデータ(付加情報)を埋め込むことで、設定やコードの記述量を減らし、開発効率を向上させるための機能です。
@Controllerや@GetMappingなど、@から始まるコードです
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
@Controller
public class ArticleController {
@Autowired
private ArticleRepository articleRepository;
@GetMapping("/articles")
public String index(Model model) {
model.addAttribute("articles", articleRepository.findAll());
return "articles/index";
}
@GetMapping("/articles/{id}")
public String show(@PathVariable Long id, Model model) {
model.addAttribute("article", articleRepository.findById(id).orElse(null));
return "articles/show";
}
@GetMapping("/articles/new")
public String newArticle(Model model) {
model.addAttribute("article", new Article());
return "articles/new";
}
@PostMapping("/articles")
public String create(@ModelAttribute Article article) {
articleRepository.save(article);
return "redirect:/articles";
}
}
Rails
- Rubyのクラスとして実装されます
- ルーティングによって、URLとアクション(メソッド)のマッピングが行われます
class ArticlesController < ApplicationController
def index
@articles = Article.all
end
def show
@article = Article.find(params[:id])
end
def new
@article = Article.new
end
def create
@article = Article.new(article_params)
if @article.save
redirect_to @article
else
render 'new'
end
end
private
def article_params
params.require(:article).permit(:title, :content)
end
end
ビュー
SpringBoot
- Thymeleaf、JSP、FreeMarkerなどのテンプレートエンジンを使用してビューを生成します(Thymeleafが使用されることが多い)
以下はThymeleafの例です。
<!DOCTYPE html>
<html>
<head>
<title>記事一覧</title>
</head>
<body>
<h1>記事一覧</h1>
<ul>
<li th:each="article : ${articles}">
<a th:href="@{/articles/{id}(id=${article.id})}" th:text="${article.title}"></a>
</li>
</ul>
</body>
</html>
Rails
- ERB(Embedded Ruby)というテンプレートエンジンを使用してビューを生成します
<h1>記事一覧</h1>
<ul>
<% @articles.each do |article| %>
<li><%= link_to article.title, article %></li>
<% end %>
</ul>
ドキュメント
SpringBoot
-
SpringBoot
- Spring Bootの公式ドキュメントであり、包括的で詳細な情報を提供しています
- 自動設定、依存性注入、セキュリティなど、Spring Bootの強力な機能を最大限に活用するための情報が満載です
-
Spring Framework
- Spring BootはSpring Frameworkの上に構築されているため、Spring Frameworkのドキュメントも参考になります
-
Pleiades Spring Boot Tutorial
- Spring Bootの基本的な概念と使い方を日本語で解説するチュートリアルです
- 初心者向けに、Spring Bootの概要から基本的な機能、Webアプリケーション開発までをステップバイステップで学ぶことができます
-
Spring Guides
- Spring Bootを含むSpringプロジェクトの様々なテーマに関する実践的なガイドを提供します
- RESTful Webサービス、データベースアクセス、セキュリティ、クラウドなど、様々なトピックに関するチュートリアルが用意されています
Rails
-
- Railsの公式ドキュメントであり、Railsの仕組みを体系的に学べる大型コンテンツです
- Active Record、ルーティング、ビューなど、Railsの主要な機能について詳細な説明と実践的な例が豊富に掲載されています
-
- RailsのAPIドキュメントであり、各クラスやメソッドの詳細な仕様を確認できます
- Ruby on Rails ガイドと併用することで、Railsの機能をより深く理解できます
-
- Webサービスを作りながらゼロからデプロイまでのWebサービス開発が学ベル大型チュートリアルです。(自分も初学者の頃お世話になりました🙇♂️)
Railsドキュメントは公式ドキュメントではないみたいです。
学習を通して感じたこと
「食わず嫌い」はなるべくしない
Javaは型などの制約が多く、個人的に今まで敬遠していた部分もありました。
もっというと、初学者の頃は「フロントエンドは好きだったけど、バックエンドはあまり興味ありませんでした(←おい)」
でも今はバックエンドメインでやってますし、フロントエンド(Vue, React)もたまに書いたりしてます。
特別好きでなくてもなんだかんだで続けてみると、意外とハマったり愛着を持つこともあります。
いままで興味なかったことでも手を挙げてやってみると、新しい発見があったりもします。
だからとりあえずやってみる。今後続けていきたいかはその後で考える。
プログラミング初学者がバックエンドへの関心を持つには?
WebページのUI(見た目)を考えるのは楽しいですし、すぐ目にみえる結果が出るのでとっつきやすいと思います。
それと同じくらい、以下のようなことを考えるとバックエンドへの興味も高まるでしょうし、より自分の視座が高まると思います。
参考記事をページの最後に紹介してあります。
- Webアプリケーションの仕組みを知る
- データベースの基礎知識(SQL、RDBMSなど)を学ぶ
- 興味あるバックエンド言語(Java、Python、Ruby、PHP、Node.jsなど)から始める(趣味からでも良い)
言語のキャッチアップをゲームに置き換えて考える
リセマラしても同じレベルでつまづく
ポケモンの例で言うと、あなたが最初のジムリーダーに負けて挫折したとします。
それで違うシリーズでやり直したとしても、また同じ場所でつまづくかもしれません。
逆に、一つのシリーズで殿堂入りまでできれば、他のシリーズでも比較的楽にクリアできるようになるかもしれません(ゲームの仕様やポケモンは変わっても、やることは大体同じなため)
これをプログラミング言語のキャッチアップに置き換えるとします。
一つの言語やFWで基礎やMVCを学んでCRUDの実装などを覚え、1つの言語で開発できるようになれば、学習コストがかかりますが他の言語やFWでもできるようになるはずです(逆も然り)
だから多少時間がかかったとしても、自分が納得する目標に達成するまでやり続けることも大切だと思います。
あくまでも持論です。個人のスキルレベルやプロジェクト環境によって異なる場合があります。
職人気質✖️ビジネス思考
自分の場合、家族が工業関係の仕事に就く人が多かった影響か、職人気質な思考もあるかもしれません。ちょっと古い思考かもしれませんが、「この道何十年」みたいに一つの仕事を極められる人は尊敬します。
とはいえ、現代のような変化の早い時代だと、一つの仕事だけでは取り残されてしまう。
やや職人気質な自分と、会社(社会)から求められることにどう折り合いをつけるかはよく悩みます。
そうして考えた自分なりの最適解が「どのプロジェクトでも通用するスキルを持つエンジニア」になること。
通用するスキルは何も、開発スキルに限ったことではないと思います。
コミュニケーション能力、問題解決能力、タスク管理、などビジネス的なスキルも含まれる。
それらをプログラミングと同じくらい職人的にこだわって考えてより良くしていくっていうのが、自分なりのモチベーションを保つ方法です。
プログラミングも目的ではなく手段の一つ
RubyもJavaもPHPも、クライアントの要望を満たすサービスを作るための一手段であると自分に言い聞かせています。
なので「自分は今までRailsやってきたからRailsで開発したい」ではなく、
「クライアントが求めているのはどんなサービスかな?」
「アプリを作るのに適切なフレームワークやアーキテクチャは何かな?」
「今、社内(プロジェクト)の課題に対して、自分はどのような立ち回りをするべきかな?(自分本位になりすぎてないかな?なども内省)」
という目線も持ってやっていきたいと思います。
おわりに
長期的にはRailsやJavaと特定の言語に限定せず、必要に応じて求められている技術をキャッチアップしていければと思います。
Javaはまだまだ初学者なので、今後も学び続けていきたいと思います。
最後まで読んで頂き、ありがとうございました。
参考記事
Webアプリケーションとは?仕組みや開発の流れ、サービス例も紹介
Webアプリケーションの全体像を掴む
コンパイルとは?|コンパイルとは何か、仕組みについて3分でわかりやすく解説
ふわっと理解するDDD ~ドメイン駆動設計~
Ruby on Rails ガイド
Ruby on Rails API
Pleiades Spring Boot Tutorial
Spring Guides