Vous avez peut-être déjà entendu parler de la programmation dite «fonctionnelle». Peut-être pensez-vous même que vous devriez l'essayer d'une manière ou d'une autre.
Ne faites en aucun cas ça!

La programmation fonctionnelle est pleine de défauts, elle ne convient pas aux vrais projets. Son application entraînera une forte baisse de la productivité du travail. Pourquoi en est-il ainsi? Voyons.
▍ →
Partie 2La programmation fonctionnelle ne peut pas répondre aux exigences de l'entreprise à multiples facettes
Pour créer un vrai logiciel d'entreprise, il faut un ensemble complexe d'exigences strictes et contraignantes liées au nombre attendu d'abstractions intégrées dans la solution logicielle. La programmation orientée objet permet au développeur d'utiliser de nombreux mécanismes d'abstraction, qui sont capables de satisfaire pleinement aux exigences des organisations en matière de systèmes logiciels.Je pense que le texte ci-dessus ne semble pas particulièrement clair. Mais très bientôt tout se mettra en place.
La programmation dite "fonctionnelle" n'a pas de mécanisme normal pour créer des abstractions. Le fait est qu'elle repose sur des règles mathématiques (ces règles, ce qui est tout à fait compréhensible, ne trouvent pas d'application dans le monde réel, situées hors des murs des établissements d'enseignement). Contrairement à la POO, la programmation fonctionnelle ne tente pas de répondre à toutes les exigences logicielles nombreuses, dures et complexes que les organisations font.
L'extrait de code suivant illustre les problèmes répandus lorsque la programmation fonctionnelle est utilisée:
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. . , . ? .
…
! ?
