Skip to content

Instantly share code, notes, and snippets.

@Jared-Prime
Created April 10, 2023 14:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jared-Prime/34082380c6375e1753c324ac8de82d76 to your computer and use it in GitHub Desktop.
Save Jared-Prime/34082380c6375e1753c324ac8de82d76 to your computer and use it in GitHub Desktop.
## Systems / SDLC / General
1. Can you describe a complex system architecture you have worked on in the past?
Ifbyphone Phoenix project:
- kamalio (kamailio) for SIP load balancing
- asterisk for call handling and routing
- mysql for survey data
- Ruby Adhearsion survey logic
2. What is a three-tier architecture? How is horizontal scalability typically applied to a three-tier architecture and what are some of the challenges?
I had forgotten this terminology previously, yet found [this IBM article](https://www.ibm.com/topics/three-tier-architecture) to express familiar concepts.
- Presentation (UI/UX)
- Application (business logic)
- Data (storage, retrieval)
3. What is your experience with cloud providers such as GCP or AWS? Can you describe a project you worked on that involved these technologies?
Most of my experience is in AWS. I held AWS Certified DevOps Engineer Professional until 2021, when I allowed the certification to lapse.
4. Can you describe your experience with microservices and how they have been implemented in a previous project?
I've used microservices in the looser definition of the term, however have not used the full microservice architecture, which involves service discovery meshes and the like.
5. How do you balance technical debt and feature development in a fast-paced environment?
This is an economic decision more than a technical decision. The key trade-off involves considering the risk/reward ratio of a refactoring effort. This may be assessed in terms of user experience, service reliability, service scalability, developer ergonomics, cost-of-ownership, performance, and/or security.
Refactoring is like vacuuming the floors: you should do it when the occasion arises, unless there's something more important first.
6. How do you stay up-to-date with emerging technologies and industry trends? Can you describe a recent technology that you have been researching or experimenting with?
I have a well-curated RSS feed and a diverse social media presence, mainly read-only.
Recent technologies:
- TimescaleDB, new work project I initiated
- curious about Nix and NixOS
- curious about Tailscale
I have not used many large language models or stable diffusion projects. I'm only marginally interested in them from a mathematical standpoint (I study quite a bit of linear algebra and calculus in my free time), and am observing from a distance for some reliable "best practices" to bubble up from people's experiences.
P.S 04/10/2023:
- installed Github Copilot this weekend in Goland to try it out
With Copilot and ChatGPT in general, still staying conservative with usage as I keep an eye out for "best practices" to bubble up. It works well for autocomplete, but like autocomplete, has the downside of interrupting flow of thoughts with suggestions. (fighting against it in this moment. It's not that the suggestions aren't relevant; it's that in writing these notes I'm discovering my own thinking on the topics rather than expressing a "correct" answer.) I think I may organize a learning session with the local chapter of Coffee and Code.
END P.S.
## Go
1. Have you worked with Golang's built-in concurrency primitives, such as goroutines and mutexes? When do you feel is an appropriate time to use goroutines, and how have you utilized them in your previous projects?
I like Bill Kennedy's trainings on this topic: https://pkg.go.dev/github.com/ardanlabs/gotraining/topics/go/concurrency/goroutines#section-readme
Philosophically, I define a goroutine as (1) an independent unit of work that (2) has been scheduled to run at the same time as other independent units of work. (1) paraphrases "concurrency" and (2) paraphrases "parallelism".
A mutex or "lock" is a primitive that can only be held once by one caller and must be released before another caller can hold it (disregarding semantics about read mutexes here). The purpose is to guard access to shared memory such that independent units of work do not simultaneous read, write, or mutate the memory, corrupting its intended accuracy.
2. Can you explain the concept of channels in Golang? How do they facilitate communication between different parts of a Golang application?
A Go channel is a language primitive that communicates data between goroutines.
3. Can you explain interfaces in Golang? How do you feel about the idiom “accept interfaces, return structs”?
An interface specifies a set of method signatures; a struct that implements the specified methods is said to satisfy the interface.
Accepting interfaces means passing an interface as a parameter to a function, with the intention of calling one of its specified methods. Returning structs means returning a concrete type from a function rather than an interface, in order to maintain specificity in the call stack (law of demeter?). There may be exceptions when a method signature in an interface needs to specify that the same interface gets returned from to the caller.
4. How do you approach testing in Go when the code under test may involve network calls to an API, or an otherwise expensive operation?
The advice from Sandi Metz still rings true here, where the programmer ought to maintain a "seam" in the code where roles are clearly defined and separated. This leads to dependency injection, such as accepting a pointer to a database connection or network client, on certain functions. These functions then can recieve mocks *or* only be called in integration tests, where a testcontainers stack hosts a mock service.
## Ruby / Rails
1. What patterns do you feel scale well in a large Rails application, and which don’t?
I'm definitely in favor of keeping code modular and thinking in terms of service objects. This makes it easier to separate functionality into associated services ("microservices") later on. There used to be a phrase "fat models, skinny controllers" that's outdated colloquially and also technically IMO. The problem is, putting too much logic in the model class definition can tightly couple behavior with the data.
One older concept that I think translates nicely between languages is a [query object](https://thoughtbot.com/blog/active-record-eager-loading-with-query-objects-and-decorators). The idea is to have a class (or struct) independent from the ORM model whose role is to encapsulate more complex data interactions. This way, the ORM model maintains direct translation between (borrowing terms from above) the data layer and the application layer, and teh query or service logic controls more sophisticated data manipulations before handing over to business control-flow.
2. What are some limitations of concurrency in Ruby? (if it doesn’t come up in the above Q)
Despite being able to program independent units of work ("concurrency"), as an interpreted language, Ruby doesn't have the full parallelism features to launch these units natively. There have been advances in using "green threads" in Ruby, but these still don't get the full benefits of operating system threads. My knowledge on this stops at the CPU scheduler :)
3. Can you discuss how you would optimize the performance of a slow Rails application? What tools and techniques would you use to identify bottlenecks, and how would you go about fixing them?
Monitor the performance of network calls, database queries, and runtime in method calls. I'd typically use a platform like NewRelic or Datadog to instrument the application, and analyze slow paths for various bottlenecks, going from the outside (initial network request to the API) towards the inside (eg looking at the `EXPLAIN` of a database query).
4. Have you worked with Ruby's metaprogramming features, such as `method_missing` or `define_method`? How have you utilized these features in your previous projects?
Yes, but years ago, but I haven't had a need to revisit metaprogramming.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment