Anda mungkin sudah pernah mendengar apa yang disebut pemrograman "fungsional". Mungkin Anda bahkan berpikir bahwa Anda harus mencobanya.
Dalam hal apapun jangan lakukan ini!

Pemrograman fungsional penuh dengan kelemahan, tidak cocok untuk proyek nyata. Penerapannya akan menyebabkan penurunan tajam dalam produktivitas tenaga kerja. Kenapa begitu? Ayo cari tahu.
▍ →
Bagian 2Pemrograman fungsional tidak dapat memenuhi persyaratan perusahaan yang beragam
Untuk membuat perangkat lunak kelas perusahaan yang nyata membutuhkan serangkaian persyaratan yang ketat dan mengikat terkait dengan jumlah abstraksi yang diharapkan yang tertanam dalam solusi perangkat lunak. Pemrograman berorientasi objek memungkinkan pengembang untuk menggunakan banyak mekanisme abstraksi yang mampu sepenuhnya memenuhi persyaratan organisasi untuk sistem perangkat lunak.Saya percaya teks di atas tidak terlalu jelas. Tetapi segera semuanya akan jatuh ke tempatnya.
Apa yang disebut pemrograman "fungsional" tidak memiliki mekanisme normal untuk membuat abstraksi. Faktanya adalah bahwa itu didasarkan pada aturan matematika (aturan-aturan ini, yang cukup dimengerti, tidak menemukan aplikasi di dunia nyata, yang terletak di luar tembok institusi pendidikan). Tidak seperti OOP, pemrograman fungsional tidak berupaya memenuhi semua persyaratan perangkat lunak yang tangguh dan kompleks yang dibuat oleh organisasi.
Cuplikan kode berikut menunjukkan masalah yang tersebar luas di mana pemrograman fungsional digunakan:
import { filter, first, get } from 'lodash/fp';
const filterByType = type =>
filter( x => x.type === type );
const fruits = [
{ type: 'apple', price: 1.99 },
{ type: 'orange', price: 2.99 },
{ type: 'grape', price: 44.95 }
];
const getFruitPrice = type => fruits =>
fruits
|> filterByType(type)
|> first
|> get('price');
const getApplePrice = getFruitPrice('apple');
console.log('apple price', getApplePrice(fruits));
, , !
, .
! - , , , . , , , .
, , , .
, . , , . , , :
class Fruit {
constructor(type, price) {
this.type = type;
this.price = price;
}
}
class AbstractFruitFactory {
make(type, price) {
return new Fruit(type, price);
}
}
class AppleFactory extends AbstractFruitFactory {
make(price) {
return super.make("apple", price);
}
}
class OrangeFactory extends AbstractFruitFactory {
make(price) {
return super.make("orange", price);
}
}
class GrapeFactory extends AbstractFruitFactory {
make(price) {
return super.make("grape", price);
}
}
class FruitRepository {
constructor() {
this.fruitList = [];
}
locate(strategy) {
return strategy.locate(this.fruitList);
}
put(fruit) {
this.fruitList.push(fruit);
}
}
class FruitLocationStrategy {
constructor(fruitType) {
this.fruitType = fruitType;
}
locate(list) {
return list.find(x => x.type === this.fruitType);
}
}
class FruitPriceLocator {
constructor(fruitRepository, locationStrategy) {
this.fruitRepository = fruitRepository;
this.locationStrategy = locationStrategy;
}
locatePrice() {
return this.fruitRepository.locate(this.locationStrategy).price;
}
}
const appleFactory = new AppleFactory();
const orangeFactory = new OrangeFactory();
const grapeFactory = new GrapeFactory();
const fruitRepository = new FruitRepository();
fruitRepository.put(appleFactory.make(1.99));
fruitRepository.put(orangeFactory.make(2.99));
fruitRepository.put(grapeFactory.make(44.95));
const appleLocationStrategy = new FruitLocationStrategy("apple");
const applePriceLocator = new FruitPriceLocator(
fruitRepository,
appleLocationStrategy
);
const applePrice = applePriceLocator.locatePrice();
console.log("apple", applePrice);
, . — .
. - , .
. , , .
, , . , -.
-, , .
, .
, «» . , . , , . , .
. :
// :
// calculator.js:
const isValidInput = text => true;
const btnAddClick = (aText, bText) => {
if (!isValidInput(aText) || !isValidInput(bText)) {
return;
}
}
// :
// inputValidator.js:
export const isValidInput = text => true;
// calculator.js:
import { isValidInput } from './inputValidator';
const btnAddClick = (aText, bText, _isValidInput = isValidInput) => {
if (!_isValidInput(aText) || !_isValidInput(bText)) {
return;
}
}
— , . , ? — ?
- :
// :
public class CalculatorForm {
private string aText, bText;
private bool IsValidInput(string text) => true;
private void btnAddClick(object sender, EventArgs e) {
if ( !IsValidInput(bText) || !IsValidInput(aText) ) {
return;
}
}
}
// :
public class CalculatorForm {
private string aText, bText;
private readonly IInputValidator _inputValidator;
public CalculatorForm(IInputValidator inputValidator) {
_inputValidator = inputValidator;
}
private void btnAddClick(object sender, EventArgs e) {
if ( !_inputValidator.IsValidInput(bText)
|| !_inputValidator.IsValidInput(aText) ) {
return;
}
}
}
public interface IInputValidator {
bool IsValidInput(string text);
}
public class InputValidator : IInputValidator {
public bool IsValidInput(string text) => true;
}
public class InputValidatorFactory {
public IInputValidator CreateInputValidator() => new InputValidator();
}
! , 22. . , , , .
«» - , . — .
- (, , ).
- :
class CountryUserSelectionStrategy {
constructor(country) {
this.country = country;
}
isMatch(user) {
return user.country === this.country;
}
}
class UserSelector {
constructor(repository, userSelectionStrategy) {
this.repository = repository;
this.userSelectionStrategy = userSelectionStrategy;
}
selectUser() {
let user = null;
for (const u in users) {
if ( this.userSelectionStrategy.isMatch(u) ) {
user = u;
break;
}
}
return user;
}
}
const userRepository = new UserRepository();
const userInitializer = new UserInitializer();
userInitializer.initialize(userRepository);
const americanSelectionStrategy = new CountryUserSelectionStrategy('USA');
const americanUserSelector = new UserSelector(userRepository, americanSelectionStrategy);
const american = americanUserSelector.selectUser();
console.log('American', american);
for (const u in users)
. - , . , , .
, , , , , -. , , «» :
SELECT * FROM Users WHERE Country=’USA’;
, SQL-, - . SQL? - ? , . — , .
- — . «» . , , , .
. , . , , . . ( ) . , - ,
garfield.fishHead
— , . , ,
garfield.swim()
()
garfield.layCaviar()
(). ,
! , , . , , !
. , . — .
, , . , , . «». , - . , . —
.eat(veggies)
, ,
.doHomework()
, . — . , , ? , !
, , .
Manager
. , , , , , , « Netflix ».
, , ? , , .
- , , ,
Factory
. , , —
MonaLisaFactory
,
WallFactory
.
, — «» , . , .
, , , .
, , , . .
-, - , , . ( «») . 30 , . - .
— Domain-Driven Design, , . , Resharper, - — .
20-30 . , , 30 , . - . - , , . ?
? , . JavaScript. . , . ? .
…
! ?
