功能编程:一种古怪的玩具,会降低劳动生产率。 第一部分

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

绝对不要这样做!



函数式编程充满缺陷,不适合实际项目。 它的应用将导致劳动生产率急剧下降。 为什么会这样呢? 让我们找出答案。

▍→ 第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. . , . ? .



! ?

Source: https://habr.com/ru/post/zh-CN462483/


All Articles