現役ソフトウェアエンジニアが、C言語と後発の言語と、どちらが大変か不毛な議論をしていたので、 現役プログラマー目線で比較してみるという不毛な検証をしてみた。
ただ、C言語の開発環境は無いので、現在でも見かける古いコードとモダンプログラミングの違いしか比べるしかできなかったので勘弁して欲しい。
なお、C言語は、命令型プログラミング、構造化プログラミング、手続き型プログラミングなどと言われているが、 それらは後発の言語の登場によって、生まれた概念なので、モダンプログラミングの概念と 何が違っているのかを比べることで楽かどうを決めたい。
プログラミングを生業としているものが開発言語を選べないのは承知の上での不毛な議論である。
比較する言語、フレームワークは手元で確認できる以下4種類を選んだ。
古めの言語、フレームワーク
- JavaScript
- Swift+UIKit
モダンな言語、フレームワーク
- React+TypeScript+NodeJS
- SwiftUI
上記4種類に限定する。
開発するもの
交通量調査をやっているような人が車の台数を数えるために持っているようなカウンター
それぞれの言語のソースコードと動作
JavaScript
<!DOCTYPE html> <html lang="jp"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Tap Counter (JavaScript)</title> </head> <body> <h1 id="countDisplay">Count: 0</h1> <button id="incrementButton">Increment</button> <script> // HTML要素を取得 const countDisplay = document.getElementById('countDisplay'); const incrementButton = document.getElementById('incrementButton'); // カウントを保持する変数 let count = 0; // ボタンがクリックされたときの処理 incrementButton.addEventListener('click', () => { count += 1; countDisplay.textContent = `Count: ${count}`; }); </script> </body> </html>
動作
好印象ポイント
- ファイル1つに全てが収まる
悪印象ポイント
- 型定義が弱く下手に触ると動作しなくなる
- コードにUIとロジックが混ざっていて見づらい
Swift+UIKit
import UIKit class ViewController: UIViewController { // カウントを保持する変数 var count = 0 // ラベルとボタンを表示するための変数 let countLabel: UILabel = { let label = UILabel() label.font = UIFont.systemFont(ofSize: 24) label.textAlignment = .center label.text = "Count: 0" return label }() lazy var countButton: UIButton = { let button = UIButton(type: .system) button.setTitle("Increment", for: .normal) button.titleLabel?.font = UIFont.systemFont(ofSize: 20) button.addTarget(self, action: #selector(incrementCount), for: .touchUpInside) return button }() override func viewDidLoad() { super.viewDidLoad() // ラベルとボタンをビューに追加 view.addSubview(countLabel) view.addSubview(countButton) // 制約を設定 setupConstraints() } // 制約を設定するメソッド private func setupConstraints() { countLabel.translatesAutoresizingMaskIntoConstraints = false countButton.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ countLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor), countLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: -50), countButton.centerXAnchor.constraint(equalTo: view.centerXAnchor), countButton.topAnchor.constraint(equalTo: countLabel.bottomAnchor, constant: 20) ]) } // ボタンがタップされたときに呼ばれるメソッド @objc func incrementCount() { count += 1 countLabel.text = "Count: \(count)" } }
動作
好印象ポイント
- ボタンを押すロジックと、画面を描画するコードがなんとなくわかる
悪印象ポイント
- コードが長い
- UIのコードが超絶に見づらい
- コードにUIとロジックが混ざっていて見づらい
React+TypeScript+NodeJS
import React, { useState } from 'react'; const CounterApp: React.FC = () => { // カウントを保持するステート const [count, setCount] = useState<number>(0); // ステートされたsetCountをインクリメントする const incrementCount = () => { setCount(count + 1); }; return ( <div> <h1>Count: {count}</h1> <button onClick={incrementCount}>Increment</button> </div> ); }; export default CounterApp;
好印象ポイント
- コードが短い
悪印象ポイント
- 宣言型プログラミング(or リアクティブプログラミング)のため、どこで画面表示されているか慣れるまで分かりにくい
SwiftUI
import SwiftUI struct ContentView: View { @State private var count = 0 var body: some View { VStack { Text("Count: \(count)") .font(.largeTitle) .padding() Button("Increment") { count += 1 } .padding() } } } #Preview { ContentView() }
動作
好印象ポイント
- コードが短い
悪印象ポイント
- 宣言型プログラミング(or リアクティブプログラミング)のため、どこで画面表示されているか慣れるまで分かりにくい
結論
宣言型プログラミングのリアクティブな部分は、それなりにコメントや、仕様書が無いとわかりにくいものの、 その他のモダンプログラミング言語の明示的な型の定義や、コード修正によって意図しない動きを防ぐ安全性などの面で総合的に優れている。
と、今は感じている。