您可能已经听说过所谓的“功能”编程。 也许您甚至在考虑应该以某种方式尝试它。
绝对不要这样做!

函数式编程充满缺陷,不适合实际项目。 它的应用将导致劳动生产率急剧下降。 为什么会这样呢? 让我们找出答案。
▍→
第2部分函数式编程不能满足公司的多方面要求
要创建真正的企业级软件,需要一系列复杂的刚性和约束性要求,这些要求与软件解决方案中嵌入的预期抽象数量有关。 面向对象的编程使开发人员可以使用许多抽象机制,这些机制可以完全满足组织对软件系统的要求。我认为上述文字看起来并不特别清楚。 但是很快一切都会落到位。
所谓的“功能”编程没有创建抽象的常规机制。 事实是,它是基于数学规则的(这些规则是可以理解的,在教育机构之外的现实世界中并没有应用)。 与OOP不同,函数式编程不会试图满足组织提出的所有众多,艰巨和复杂的软件要求。
下面的代码片段演示了使用函数式编程时普遍存在的问题:
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. . , . ? .
…
! ?
