In the article 5 things you need to know in a programming interview, Zhia Hwa Chong gives some useful tips for those starting their programming careers or those who are preparing for an interview. A quick summary of these tips are as follows:
- “Always Think Ahead” – Referring to making sure when solving a problem to always look ahead and think about potential improvements. For example, he specifically says to think about edge cases, scaling issues, problem areas, and other topic-specific issues (e.g. handling collisions in a hash table).
- “There’s more than one answer” – Each interview problem always has more than one solution, however, some of these solutions may not be optimal. It’s important to be able to write a working solution, but you should also look to improve upon it.
- “OOP is not dead” – Make sure to think object-oriented (e.g. don’t cram everything into one method, don’t reuse code, etc.). Following these practices creates cleaner code, simplifying the code and makes it easier to understand.
- “Craft your résumé” – Make sure to not skip preparing a great resume.
- “Communicate early and communicate often” – Talk through the problem with your interviewer so they can understand your thought process and push you in the right direction.
- “Use abstraction” – Using abstraction to hide complicated implementation details creates clean and easy to understand code. Afterwards if requested, you can implement any abstracted details.
Reaction to Content
I chose this topic because it’s something that is currently very relevant to me, as I’ll be graduating next May and hope to get something lined up before then. I had already seen many variations of these tips before, but I think reading this is useful for reinforcing them. While not necessarily applicable to all interviews, most popular tech companies follow the white-boarding process that this blog is giving tips for. For anyone looking to work for any of those companies, following these tips would definitely be valuable. However, they only cover things you should do during your interview, not topics that you would need to prepare for long before it, such as data structures, algorithms, general problem solving skills by solving similar problems, etc.
In the article A Gentle Introduction To Graph Theory, Vaidehi Joshi goes over some of the basic concepts in graph theory, such as the difference between trees and graphs, undirected graphs vs. directed graphs, vertices and edges, and unordered vs. ordered pairs in graphs. She also provides great illustrations for the differences between each of these topics.
Later in the article, there are great real-world examples of what graphs are used for. For example, she talks about how two different social networks, Facebook and Twitter, are each different types of graphs. In this case, Facebook is an undirected graph because a connection on Facebook has to be a bidirectional connection. Twitter, on the other hand, is an example of a directed graph, because you’re able to “follow” someone without them following you back, meaning it can be unidirectional. The other example that she used that I found useful was comparing the web (traversing between web pages) to one big graph. So as you navigate back and forth between different URLs, you’re just navigating throughout one massive graph. For example, each article on Wikipedia contains key words that link to other articles, which could even potentially lead back to the original article.
Reaction to Content
I chose this topic because I wanted to get a quick refresher on it. While I’ve been exposed to this type of data structure before and seen some of the algorithms used for traversing through graphs, I haven’t really used them outside of coursework. Also, I feel as though I didn’t really have a great understanding of this topic until now. Seeing the examples provided in the article of real world applications of graphs I think was very useful for me to understand their purpose.
Overall, I think this article in particular is a great introduction to graphs, going over basic types of graphs and the concepts needed to understand them. While I already had a decent understanding of graphs, it was useful to reread some of the concepts and reinforce my understanding of them. However, there are many more topics that are important to grasp in order to understand graphs fully, such as the different types of traversal algorithms used for graphs as well as other different types of graphs like weighted graphs or trees.
In the article Introduction to A*, Amit goes over two graph traversal algorithms: Dijkstra’s Algorithm and Greedy Best-First-Search Algorithm, providing a great visualization of how these algorithms work as well as cases in which they excel and in which they struggle. A summary of his description of these algorithms are as follows:
- Dijkstra’s Algorithm – guaranteed to find the shortest path from the starting point to the goal, longer run-time because it visits vertices continuously expanding outward from the starting point until it reaches the goal.
- Greedy Best-First-Search Algorithm – works with an estimate (heuristic) of how far from the goal any vertex is, selecting the vertex closest to the goal. Not guaranteed to find the shortest path, but runs much quicker than Dijkstra’s Algorithm.
He then explains what the A* Algorithm is, taking advantage of the best of both of these algorithms. This is done by combining the pieces of information that Dijkstra’s Algorithm uses (favoring vertices that are close to the starting point) and information that Greedy Best-First-Search uses (favoring vertices that are close to the goal).
Reaction to Content
This article is the first part of a larger series by Amit about pathfinding, however I believe that reading this article alone is good enough for a quick overview about what the A* algorithm is as well as providing excellent visualizations for the three mentioned algorithms. These visualizations are definitely helpful for understanding how these algorithms work as well as what their potential advantages and downfalls are.
I chose this topic in particular because it’s an interesting part of a subject area that I have interest in (game programming) and also is an important topic in CS in general (graphs and graph traversal algorithms). It’s a useful refresher for some of the topics that I learned in my algorithms course. Also, seeing how a potential algorithm in a game could decide how to best traverse towards a goal taking into account any obstacles in the way is interesting think about.
I think the rest of the series would likely be a good read to get a deeper insight into the A* algorithm.
In the article Exploring Dynamic Programming, Ross Rhodes goes over three examples of dynamic programming in increasing difficulty: nth Fibonacci Number, Traversing a Matrix, and Matrix Chain Multiplication. These are problems that have straightforward but very inefficient approaches that can be solved via dynamic programming techniques such as memoization, which is an optimization technique that stores the results of expensive function calls and returns the cached result when the same inputs occur again. For example, in the case of calculating the nth Fibonacci Number for multiple different values for “n”, rather than performing those calculations again you can instead store already calculated values.
Although the three examples provided are each examples of dynamic programming, they each have moderately different approaches to solving their respective problems. As Rhodes says at the end of the blog post, these examples only scrape the surface of what dynamic programming can be used for.
Reaction to Content
I chose this topic for this week’s blog post because it was something I hadn’t been exposed to significantly. While I’ve known of the technique and its applications, I hadn’t used it for anything other than a similar application of the Fibonacci example provided. The other two examples provided are notably more complicated and helped to provide provide more insight into what situations dynamic programming can be used to solve.
Overall, while I think this article was useful for understanding dynamic programming, I think the best way to understand it is to solve problems using these techniques and to come up with your own solutions for them. That way you can really internalize these concepts and you can spot when you’ve run into a problem in which dynamic programming could be used. Just reading through these examples alone and trying to follow through the thought process won’t necessarily be enough when you have to solve a unique problem on your own.
I think this topic is definitely something that should be understood, as even if you somehow never ran into a real-world situation that dynamic programming would be useful for, understanding it will only make you a better programmer. And if nothing else, it’s likely to come up at some point in an interview.
In the article Machine Learning vs. Deep Learning Explained, Bartek Ciszewski explains the difference between Machine Learning (ML) and Deep Learning (DL). He gives a quick overview these two terms are and also talks about the broader field of Artificial Intelligence (AI). He also gives examples of what machine learning and deep learning can be used for as well as providing real world examples of DL, such as Google’s Go playing program, which is capable of inventing its own moves.
Reaction to Content
I chose this topic because it was an interesting topic that I had looked into in the past but haven’t really done much research on yet. This article in particular was mainly useful as a refresher, providing a basic overview of the difference between machine learning and deep learning. Some of the real-world examples that he brought up (AlphaGo, self-driving cars, early automatic cancer detection, etc.) are definitely things that I think would be interesting topics to read about in order to get a deeper understanding of how deep learning works.
Overall, this article didn’t change how I thought about this subject. For those who haven’t seen these concepts before I think this article would be a useful place to start. The examples he provided for machine learning algorithms are helpful for understanding what it could be used for, but it seems like it’s very difficult to provide a simple example of what a deep learning algorithm could be used for due to how complex of a topic it is. As Ciszewski stated in his summary, neural networks are usually “black boxes,” so even the people who created the deep learning algorithms don’t entirely understand how the machine is able to do what it is being designed to do.
This video How Machines Learn, by CGP Grey, is another useful resource that helped me understand the topics discussed in the article better, by providing more use cases for them as well as giving a visualized high level overview of how these algorithms work.
I think in order to truly understand how deep learning works, I’ll have to look into example algorithms and go from there.
In the article Introduction to Test Driven Development (TDD), Scott Wambler talks about what Test Driven Development (TDD) is, as well as many other topics related to it such as traditional testing, documentation, test-driven database development, and scaling TDD via Agile Model-Driven Development (AMDD). He also goes over why you would want to use TDD as well as some of the myths and misconceptions that people may have about it.
A basic description of TDD is that it is a development technique where you must first write a test that fails before you write new functional code.
A simple formula that Wambler included to help understand TDD is as follows:
TDD = Refactoring + Test-First Development (TFD)
Here’s a quick overview of TFD which he provided:
Reaction to Content
I chose to search for articles of this topic because I wanted to really understand how to properly perform test-driven development. For what project that I decide to work on next, I wanted to be able to follow an effective process so as to improve and avoid writing “spaghetti code”. I imagine there are other development methods that may be better suited for what I want to do, but this is one of the ones that I hadn’t had a great understanding of until reading this article. Hopefully I’ll be able to properly use this method to write clean, well-documented code in the future.
While I knew of TDD before reading this article, I never really took the time to actually learn how to do it. I think that this article was very useful in helping me understand what TDD is and what are the advantages of using it, but while I believe that I understand it conceptually, I’ll probably need to look up examples, maybe follow a tutorial to make sure that I don’t do it wrong and end up building bad habits.
One of the things in the article that I had some trouble understanding was when he referred to tests used in developer TDD as “developer tests” and that they were inaccurately referred to as unit tests. I think that he may be referring to unit tests as a section of tests included in developer tests as a whole, but I’m not completely sure.
In the blog post Writing Great Unit Tests: Best and Worst Practices, Steve Sanderson talks about the best and worst practices when writing unit tests. He goes over the true purpose of unit tests (each examining a unit of your code separately and as a whole cohesively working together to provide value that is more complex and subtle than the sum of its independently tested parts, not for finding bugs), as well as the purpose of integration tests (automate the entire system to detect regressions). At the end of his post, he also gives several useful tips for writing great unit tests, such as making each test orthogonal, or independent, to all other tests.
The reason I chose to talk about this blog post is because I think it’s definitely something that’s commonly overlooked by developers. As Sanderson said at the beginning of his post, “Even if you’re a brilliant coder with decades of experience, your existing knowledge and habits won’t automatically lead you to write good unit tests.” For people looking to get into software development, I think it’s important to learn how to write great unit tests early on so as to avoid having to clean up a self-inflicted mess in the future.
I found it interesting when he described the difference between unit tests and integration tests, as well as the problems that bad unit tests can cause. This image found in his post is useful for visualizing this:
The last section in which he gives practical advise for writing great unit tests is also something that I think will be useful in the future, although I think the formatting may have been messed up.
One thing that I have a hard time not necessarily agreeing with but understanding is how he said that unit testing isn’t for finding bugs. I think that, for example, if you were to make a change to the way a function performs its task (perhaps to optimize the code) while not trying to affect the end result, one of your unit tests failing because of this could be classified as “finding a bug.”