Edited the about file, new post on probability and testing

This commit is contained in:
Jacob Windle 2019-05-23 17:52:22 -04:00
parent 96664ec2f7
commit 383669a2d7
2 changed files with 74 additions and 2 deletions

View File

@ -6,11 +6,11 @@ draft: false
# Summary
Software engineer that loves to solve hard problems in interesting ways. Currently, I do full-stack Ruby on Rails with React.js, and I work on a networked Python application. I'm working at [Verodin, Inc.](https://verodin.com) helping companies measure the effectiveness of their cybersecurity in a continuous manner.
Software engineer working currently for Kickback Rewards Systems doing all manner of things. Currently into ETL, embedded C and full-stack Python with React and Django. Worked full-time as a software engineer for the past 5 years, doing full-stack Python work in Django, Ruby on Rails, React, Jenkins, Docker builds, embedded C, Machine Learning, System Administration, CI/CD pipelines, TDD and more. When not working I'm with Rebecca, my better half, or out trying to be active in some way. Moved to TN after living in VA my whole life and excited for where life will take me.
# Interests
Tech-wise, there will always be more to know, and more to do. Currently I am interested in statistics and machine learning, and how to apply these fields to common problems I encounter. I also am a programming language fanatic. My favorite programming languages include but are not limited to: Julia, Python, C, Scheme, Racket, Ruby, Javascript, and R.
Embedded C, Go, Entrepreneurship, Volunteering, Sports
# [Resume](https://jake-windle.gitlab.io/cv.pdf)

View File

@ -0,0 +1,72 @@
---
title: "Adding probability to testing: Golang"
date: 2019-05-23T17:17:17-04:00
draft: false
tags: ["go", "testing"]
---
In my work as a Software Engineer at Kickback Rewards Systems, I recently wrote an application that essentially reads packets from a TCP stream.
It's amazing to me that writing a concurrent application that reads bytes from a TCP stream is SO EASY with Go, in less than 150 LOC!
We've had similar applications in C and Python that are much larger than that at my company!
Anyway, this application merely needed to mock the functionality of the production system, so that we could test the transmission of a new packet
type from our client code. The client expected some entity acting as the server in a socket connection that would first read bytes from the stream
to determine the length of the payload, then the payload itself. The server has to respond to the client in a similar manner, length preamble, and
payload of response.
An interesting requirement arose amid development of this mock server. The requirement was that the server should simulate an actual internet connection,
sometimes terminating the client's connection
too early, sometimes delaying a response to the client, and sometimes just not responding at all. The trick to this though is that this wacky behavior
needed to be inconsistent, something that happened seemingly randomly. To accomplish this, I developed a neat pattern using closures and function
pointers.
Enter our goroutine, which is obviously not my real production code:
```go
// Main and rest of program not included, it's not important to this example.
// Our goroutine.. called in the main socket listening loop
func handleConn(conn net.Conn) {
// Do some work and respond.
}
```
This is a pretty standard pattern, develop a function intended to be used as a goroutine, and call it in some loop passing a connection from a successful
`net.Listener.Accept()` call. What I did to add a little chaos to this function, was utilize a little bit of closure trickery >:). To introduce any
amount of chaos to your application, a function like this will do:
```go
// Flip a coin, and do the action on tails...
func chaos(action func()) {
if rand.Intn(10) > 5 {
// Executing our function pointer.
action()
}
}
```
On its own, this function may seem harmless. One may ask why you would want to flip a coin then do something if we achieve a certain result. The answer
to that is simple, and that's where closures come in. Let's modify my goroutine from before to do something nasty.
```go
func handleConn(conn net.Conn) {
// Now let's introduce some... chaos
chaos(func() {
fmt.Println("Oh no, something bad happened!")
conn.Close()
// don't worry about this.
runtime.Goexit()
})
fmt.Println("Phew, nothing's gonna happen, let's continue.")
// Do the work.
}
```
The way this works is simple, we pass an anonymous function as the argument to chaos, noted above as type `func()`. This anonymous function that we
create has access to any variables defined in its enclosing scope. `conn`, a function parameter, is defined in the same scope as the anonymous function,
thus it is perfectly valid to reference it from within the function. Now, when the function is executed in `chaos` like this: `action()`, it is still
holding a valid reference to the conn object, resulting in `conn.Close()` being called terminating the client's connection with the server. Use this
pattern any time you would like to introduce a little bit of chaos to your testing.