Categories
Uncategorized

restapi (7) – talk about functional programming mode of thinking and habits

Before the National Day, c # .net involved in a project to re-experience a real sense of moving bricks: it seems more than a month without any thinking, constantly keyboarding add code. I think this may be true portrayal of the program ape most small and medium companies in the industry: workers moving bricks are sitting in front of computers. But not without any harvest, in the process of moving bricks, I seem to find some of the phenomena and causes of these phenomena and OOP thinking behind the habit patterns. And most of the IT companies, this company in the industry there is a certain amount of time (not start) so have some accumulation products and technologies, popular point is a bunch of ready-c # .net code. Then is the project deadline pressure. In order to complete the task on time, I can only in the original code base continues to add features, there is no opportunity to consider what kind of code patterns with the structure to achieve better results. In this process, there is an interesting phenomenon caught my attention: Basically, I just follow a certain process (mostly business requirements) increased by one link can achieve a fully functional, of course, I do not care about these links whether an impact on other parts of the software, or the future code maintenance will not be too much trouble, as long as the timely delivery on the line. Think of this approach is precisely the object-oriented programming or the so-called row to make programming features, namely: the state of the boot program through the command line by line change, the final state is the result of running the program, or function is achieved. Increase the code will eventually reach the intended line by line through the state, is not it. This is the OO programming mode of thinking: Because the program status is reflected in every line of code, you can always check to verify the idea, so OOP relatively easy to use (in terms of relative functional programming).

Recall functional programming: It seems difficult to follow the natural order of logical thinking to implement a function, which is due to functional programming is a nested indirect programming model, that is, the program is run in some kind of nested inside. Functional programming also known monatic-programming, i.e., programming in monad. monad’s what I call nesting, is a type of structure, the most common type is the Future. In modern programming in multithreaded programming is very common, in fact, often we can not do without a variety of Future. For example, the image: If the dirty water to achieve the primer from point A to point B as some function of the output of purified water programming, programming structures as piping network. Function must first prepare a variety of pipes, each pipe to achieve special functions, such as filtration, disinfection, and then combined to form a water supply pipe is connected.

During functional programming I always put the issue back and forth so clearly considered to have started working. First of all aspects of a feature will first sum up, these are some of the functions. Then try to unify these types of functions, like pipes mentioned above, because of the different specifications of the pipes are not connected. Similarly, different types of monad nested function of a combination can not be achieved. And input and output to realize these functions according to the needs, the last of these functions are combined to form a complete functionality. You see, there is a functional programming can not be done arbitrarily think that it is written, we must first consider the overall. So, functional programming has inherent advantages in code reuse and maintenance. This example also reflects functional programming mode of thinking.

Now I want to use a practical example to demonstrate the functional programming modes: a few examples discussed earlier, there is a front-end to httpclient httpserver upload pictures stored into the database server mongodb. Now find the client to upload the picture data streams having difficulty want to upload a picture download URL by httpserver download pictures and write their own mongodb. Just from this function is concerned, it should be composed of several aspects of the composition:

1, taking pictures downloaded from the URL data uploaded

2, download pictures, by request http request, access to the data stream from the picture in response

3. Get Picture series number by count function of mongodb

4, the picture is written mongodb

First, I need to put a few aspects of the formation function, and then unified function type. Undisputed, the best choice for Future [A] This function returns the type:

Assumed that the data format is json pass up, it must have a type of a data structure:

 

  case class UpData (pid: String, url: String)

 

You can obtain the uploaded data as follows:

 entity(as[String]) { json =>
      val upData: UpData = fromJson[UpData](json)
      ...
}

Get Picture Series Number: Back to Future [Long]

 

 

repository.count(upData.pid).toFuture[Long]

 

Photo: This returns the Future [ByteString]

 

    import akka.actor.ActorSystem
    import akka.http.scaladsl.model._
    import akka.http.scaladsl.Http

    def downloadPicture(url: String)(implicit sys: ActorSystem): Future[ByteString] = {
      val dlRequest = HttpRequest(HttpMethods.GET, uri = url)
      Http(sys).singleRequest(dlRequest).flatMap {
        case HttpResponse(StatusCodes.OK, _, entity, _) =>
          entity.dataBytes.runFold(ByteString()) { case (hd, bs) =>
            hd ++ bs
          }
        case _ => Future.failed(new RuntimeException("failed  getting picture!"))
      }

    }

Write mongodb: This function also returns the Future [?]

    def addPicuture(pid: String,seqno: Int, optDesc: Option[String]
                    ,optWid:Option[Int],optHgh:Option[Int],
                    bytes: Array[Byte]):Future[Completed] ={
      var doc = Document(
        "pid" -> pid,
        "seqno" -> seqno,
        "pic" -> bytes
      )
      if (optDesc != None)
        doc = doc + ("desc" -> optDesc.get)
      if (optWid != None)
        doc = doc + ("width" -> optWid.get)
      if (optHgh != None)
        doc = doc + ("height" -> optHgh.get)
      repository.insert(doc).toFuture[Completed]
    }

Well, now these functions are Future types, can be a combination of:

            val futSeqno: Future[Long] = for {
              cnt <- repository.count(upData.pid).toFuture[Long]
              barr <- downloadPicture(upData.url)
              _ <- addPicuture(upData.pid, cnt.toInt, None, None, None, barr.toArray)
            } yield cnt

futSeqNo is a combination of computing processes. Note its type still future: this means that we can not predict when it will complete the operation, especially if a large picture Or download speeds slow, it is likely to perform a complete before the download is complete (). Therefore, we must ensure that the picture after the download is complete httpclient returns response to the terminal, use onComplete to achieve:

            onComplete(futSeqno) {
              case Success(lv) => complete(lv.toString())
              case _ => complete("error saving picture!")
            }

Therefore, the whole macro-code is as follows:

        post {
          entity(as[String]) { json =>
            val upData: UpData = fromJson[UpData](json)
            val futSeqno: Future[Long] = for {
              cnt <- repository.count(upData.pid).toFuture[Long]
              barr <- downloadPicture(upData.url)
              _ <- addPicuture(upData.pid, cnt.toInt, None, None, None, barr.toArray)
            } yield cnt
            onComplete(futSeqno) {
              case Success(lv) => complete(lv.toString())
              case _ => complete("error saving picture!")
            }
          }
        }~

It is not very easy to read to understand? In fact, we detail the complex function behind her back. These functions are highly reusable, the results of this is before we take into consideration the hands.

 

Leave a Reply