简体   繁体   English

功能编程和局部功能状态分配

[英]Functional programming and local function state assignments

I recently converted a code to what I think is partly at least, functional javascript. 我最近将代码转换为我认为至少部分是功能性javascript。 It's a web form validation process. 这是一个Web表单验证过程。 At each step of the process, the functions perform their own layer of validation and modify the data before passing it to the next function. 在流程的每个步骤中,功能都会执行自己的验证层,并在将数据传递给下一个功能之前对其进行修改。

1) My first question is... can the code below be considered at least 'partly' functional ? 1)我的第一个问题是...下面的代码可以至少被认为是“部分”功能吗?

You will notice that in requiredFields I created two assignment... states. 您会注意到,在requiredFields中,我创建了两个Assign ...状态。 They are local to the function, and the function doesn't have external side effect.... 它们是该函数的局部函数,并且该函数没有外部副作用。

2) Is this kind of local assignement bad practice in the context of functional programming paradigm ? 2)在函数式编程范式的背景下,这种本地分配是不好的做法吗? Is this considered a 'local side effect ?' 这被认为是“局部副作用”吗?

Here is the model: 这是模型:

function linkmodel() {
    return {
        title: { 
            content: undefined,
            validation: {
                type: "string",
                required: true,
                minLength: 1,
                maxLength: 3,
                validationErrorMessage: "Your title must be a valid string between 1 and 35 characters"
            }
        },

        email: {
            content: undefined,
            validation: {
                type: "email",
                required: true,
                minLength: 1,
                maxLength: 60,
                validationErrorMessage: "Your email must be between 1 and 50 characters"
            }
        },


        link: {
            content: undefined,
            validation: {
                type: "url",
                required: true,
                minLength: 1,
                maxLength: 500,
                validationErrorMessage: "Your link name must be a valid email between 1 and 50 characters"
            }
        },

        description: {
            content: undefined
        }
    }
}


export default linkmodel

And here is the validation system: 这是验证系统:

app.post( "/", function( req, res ) {
  let form = new forms.IncomingForm()

  form.parse( req, function( err, fields, files ) {

    // Lodash launching the function flow
    let errorMessageBag = _.flow( objectWithFieldsToValidate,
                                  requiredFields,
                                  stringLengthValidationCheck,
                                  emailValidation )

    let result = errorMessageBag(fields, linkmodel()) // That's the end result
    console.log( "result", result ) 
  })



  // Return object containing all fields to validate and their criterias
  function objectWithFieldsToValidate( fields, model ) {
    // Remove all model fields that have no validation criteria in model. Description is one of those.
    let modelFieldsToValidate = _.pickBy( model, function( value, key ) { return value.validation !== undefined })

    // Remove from form field any entry that doesn't have a corresponding key in model
    let formFieldsToValidate = _.pick( fields, Object.keys( modelFieldsToValidate ) )
    _.forOwn( modelFieldsToValidate, function( value1, key1 ) {
      _.forOwn( formFieldsToValidate, function( value, key ) {
        if ( key1 === key ) {
          modelFieldsToValidate[ key ].content = value
        }

      })
    })
    return modelFieldsToValidate
  }

  // Take care of required fields
  function requiredFields( objectWithFieldsToValidate ) {
    let okField = {}
    let errors = {}

    // error: field required but empty: add it to errors literal object
    _.forOwn( objectWithFieldsToValidate, function( value, key ) {
      if ( objectWithFieldsToValidate[ key ].validation.required === true && objectWithFieldsToValidate[ key ].content === "" ) {
        errors[ key ] = objectWithFieldsToValidate[ key ].validation.validationErrorMessage
      } else {
        // no error: add field to litteral okField
        okField[ key ] = value

      }
    })
    return ( { "okField": okField, "errors": errors })
  }


  function stringLengthValidationCheck( requiredFields ) {
    let validatedFields = requiredFields
    _.forOwn( validatedFields.okField, function( value, key ) {
      // Error: field length is not valid
      if ( !validator.isLength( value[ "content" ],
        { min: value[ "validation" ].minLength, max: value[ "validation" ].maxLength }
      ) ) {
        // Add error message to errors errors literal object
        validatedFields[ "errors" ][ key ] = value[ "validation" ].validationErrorMessage
        // Remove problematic field from okFields
        delete validatedFields[ "okField" ][ key ]
      }
    })

    return validatedFields
  }


  function emailValidation( stringLengthValidationCheck ) {
    let validatedFields = stringLengthValidationCheck
    _.forOwn( validatedFields.okField, function( value, key ) {
      // Error
      if ( value["validation"]["type"] === "email" && !validator.isEmail( value[ "content" ])) {
        // Add error message to errors
        validatedFields[ "errors" ][ key ] = value[ "validation" ].validationErrorMessage
        // Remove problematic field from okFields
        delete validatedFields[ "okField" ][ key ]
      }
    })

    return validatedFields
  }

3) If you see way to improve this code, I would appreciate to see what a better functional refactoring you can come up with, still using lodash. 3)如果您看到改进此代码的方法,我将不胜感激地看到仍然可以使用lodash可以提供更好的功能重构。

As a comment above suggests, specific code review may not be a topic for SO, but to answer the general part of your question: yes, a function with no externally visible side effect can be considered "functional" in a broader sense---say, "behaviorally functional"---even if it internally uses assignments. 就像上面的评论所建议的那样,特定的代码审查可能不是SO的主题,而是要回答您问题的一般部分:是的,从外部看,没有外部可见副作用的功能可以视为“功能”-说“行为功能”-即使它内部使用分配。

A possible problem here may be how to verify that the side effects are indeed internal only and are not visible from the outside. 这里可能的问题是如何验证副作用确实仅是内部的,而从外部看不到。

Another, theoretically interesting fact is that there exist some functions that are behaviorally functional but can be implemented only with (internal) assignments. 另一个从理论上讲有趣的事实是,存在一些具有行为功能的功能,但只能通过(内部)分配来实现。 See the paper for more details (if you have no access to papers in the ACM Digital Library, try searching the Web for the title and/or author of the paper). 请参阅该论文以获取更多详细信息(如果您无法访问ACM数字图书馆中的论文,请尝试在网上搜索该论文的标题和/或作者)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM