البرمجة الوظيفية: لعبة أحمق تقتل إنتاجية العمالة. الجزء 1

ربما تكون قد سمعت بالفعل بما يسمى البرمجة "الوظيفية". ربما كنت تفكر في أنه يجب أن تحاول ذلك بطريقة أو بأخرى.

في أي حال من الأحوال القيام بذلك!



البرمجة الوظيفية مليئة بالعيوب ، وهي ليست مناسبة للمشاريع الحقيقية. سيؤدي تطبيقه إلى انخفاض حاد في إنتاجية العمل. لماذا هذا هكذا؟ لنكتشف ذلك.

▍ → الجزء 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/ar462483/


All Articles