A Philosophy of Software Design, by John Ousterhout, is a great read for anyone who wants to understand what actually causes systems to be complex and in turn, how to improve their own designs. At some point in this book, actually on page 169, they mention that this book is about one thing: complexity. How it happens and how to avoid it.
Increased complexity in a codebase makes it difficult to make changes without breaking features. It also makes it difficult to understand all the moving parts and how they work together.
Two resounding causes of complexity are identified as dependencies and obscurity. The book goes into detail about how to minimize or isolate them.
Another great point that I learned from this book is that development is not about building features but about building abstractions. Building the right abstractions also makes systems scalable, changeable, obvious.
This book is very easy to read and understand, the author explains the concepts in a simple and direct way and might only take you a week to read it, as it is only about 170 pages. So, give it a try!
Asynchronous calls allow client applications to react to changes on the server without impacting the users experience and without the need of the user to specifically interact with that interface to receive those updates.
It allows the system to process the results of a given request as soon as the information is received. It will not lock up the application during this period since the execution of this block of code is delayed.
Two ways to perform requests asynchronously in JavaScript are by using callbacks and by using promises. Note that these are both non-interchangeable, which means that you either use promises or callbacks, not both.
JavaScript promises vs callbacks, which is better? Let’s discuss.
I have been spending a large portion of my time reviewing my design for an application I’m working on… and part of it involves deciding whether what I wrote made sense.
When I was reading through my code, I saw that certain portions of the code had comments. They seemed innocent enough, basically explaining my thought process and what was the purpose of a given method or the next set of code lines. I thought that I was providing good information to whoever would need to read it (including myself).
However, as I’ve been learning more about good software development practices, I realized that the comments I wrote were written purely because the code wasn’t written intuitively. Without the comments, the lines of code were unclear. I wasn’t quite sure why I did what I did, especially since it was weeks since I first wrote it.
So, I found the following two actions to greatly help improve the readability of my code.
I watched a fantastic talk from J.B. Rainsberger called “Integrated Tests are a Scam.” It was an insightful discussion about the types of tests that we write during software development and the types of tests that actually help you ensure proper code coverage.
Software engineering can be incredibly complex. There are a variety of tools, software patterns, architectural decisions, and process flows. This can be daunting for a new engineer who wants to make an impact. It can help to take a step back and look at the bigger picture. Building software isn’t just about writing code.
Here, I write about simple ways to make an impact, even when you are starting out in your software development career.
Unit testing is a great idea. It provides for code coverage, is a resource for documentation, and, paired with TDD, it provides a vehicle for good design. There are a lot of articles and blogs talking about why unit tests are important; however, it’s hard to know how to write good unit tests. This blog will talk about how to build a suite of robust unit tests that still allow for refactoring.
Here are some tips and tricks that have allowed me to leverage the value of unit tests while still having the flexibility to refactor during the development process.
Dependency injection is a form of inversion of control. This means that a component’s dependencies are not part of a component’s internals, they are defined at the public-facing seam, or interface, of the component.
Dependency injection allows for a decoupled design and makes testing easier. It fosters clear boundaries between components and allows for the simple substitution of one concrete implementation of a dependency with another concrete implementation. It also allows for substitution of a dependency with a mock, or fake, during testing.
This blog details some techniques for using dependency injection in React.
Yup is a schema validation library. One would use it to add property validations that execute prior to form submission. It is also pretty easy to use, it’s just difficult to find concrete examples to model off of.
Because of this difficulty in finding good examples that showcase its syntax, I’ve compiled some common examples in Javascript.
Abstraction is about expressing ideas and simplifying complexity. However, it is quite often hard to understand what line not to cross. When does abstraction become too much and more binding than freeing?