What is "full-stack" development? What does a "full-stack" developer do?
Typically, developers who feel that they can effectively program across all layers of an application refer to themselves as "full-stack". While I've heard this explanation on numerous occasions, I'm reminded of the current state of affairs in the application development space every time I go through another round of interviewing candidates for a development position, or a recruiter knocks on my door conjuring up the term "full-stack" once again, not understanding the implications of their use of the term. Note that "effectively program" means proficiency in a particular area. The need for (i.e. not simply the desire of) someone else to clean up code after the initial development is done, whether to make the UI "pretty" or otherwise, indicates probable lack of proficiency.
As I write this blog post, there are actually 3 things from my experience that immediately come to mind.
The first is a particular discussion with a prior architect colleague a few years ago who argued that essentially all that matters on a development project is the Java code. Of course, we were working on a Java project at the time, so substitute whatever core technology applies in your domain. In response, I listed a number of other technologies that were being used on the project, and raised my hand, forming a small circle with my fingers to visually describe the amount of Java code that existed relative to the rest of the project (and the enterprise, for that matter), which I subsequently described by forming a large circle with my arms outstretched around the top of my head. Their response: "Everything else other than the actual Java code is 'infrastructure'." And what did "infrastructure" mean to this individual? "Everything else exists to support the Java code."
(In response to readers, note that other technologies being used on a given project can include an increasingly growing and evolving area of the enterprise called "DevOps", associated with the automation of software delivery and infrastructure changes, tooling of which can fall into a variety of areas such as continuous integration, version control, configuration, and monitoring. The idea here was to limit scope of this discussion to the actual application stack, which admittedly comes from a traditional viewpoint. While it might be debatable whether this type of work should be included in a discussion of full-stack development, however, in my view what is not debatable is whether everything else in the enterprise simply exists to support application code, or in this case, a subset of the code that is written for an application that likely provides job security for some. It does not - and this was the point of my referencing this earlier discussion.)
For the sake of brevity, the second actually consists of multiple events I've chosen to group together. While I could write on this subject at length, what this area of thought boils down to is whether a developer can claim any degree of expertise - or any level of experience, for that matter - if they have simply been "exposed" to a particular technology on a project. Unfortunately, I have personally seen this claim on numerous occasions. Resumes stating in which technologies a "development environment" consisted, rather than in which technologies developers gained hands-on experience. Or laundry lists of technologies in which developers have been exposed to some degree, sometimes writing very limited code with the given technologies, or not incorporating any of them into their projects themselves and just resorting to what someone else "set up" for them.
The third is how one or more databases or "data stores" fit into the picture. I have seen red flags in this area for quite some time now amongst those who refer to themselves as full-stack developers, as well as those who interestingly refer to themselves as "back-end" or "service" developers. Verbal exchanges typically explore use of some type of data persistence layer. The issue however that can arise relatively quickly is what "used Hibernate" or "used JPA" actually means. Typically, what this means is that the developer used a data persistence layer that someone else set up. While past usage of such code is a positive for any project, what happens when an undecipherable exception is thrown by the framework, or the database underlying the persistence layer changes? And has the given developer actually ever designed any significant portion of a database?
Below is a simplified version of a high-level architecture diagram that I recently created for a client, showing solely the layers of the AngularJS / Java application portion of the architecture. The "front-end" architecture consists of a view layer, router layer, controller layer, and service layer, which together comprise what might be considered a traditional application user interface for presentation logic, although since this was an SPA (single page application), the view layer itself is really what comprises the HTML, CSS, and AngularJS directives that represent different UI components and other JavaScript libraries such as D3.js depicted in the full diagram. Note that my discussion of "the first cluster" below intentionally truncates the service layer depicted here.
The "back-end" architecture consists of a controller layer, service layer, persistence layer, and database or other data store. A REST API (i.e. RESTful services) is the entry point for this part of the architecture, although it should be noted that not all architectures follow this style. Since application security and other important features are managed at this level, equating these layers to "back office" or "back room" operations is a bit of a misnomer. However, it is accurate to state that the abstractions created for user experience are not managed by these layers of the architecture. Controller and service layers exist here for similar reasons as in the front-end: business logic is serviced by data similarly to how user actions are serviced by the UI.
So what does this diagram represent? It represents the complete, or full, development stack for the application portion of the development project. To be considered a true full-stack developer implies that a given developer is adept, or at least relatively proficient, in all of these areas. My argument is that very few, if any, developers are consistently proficient across all of these areas. It's not like I'm the only one voicing this opinion, and others have written about the myth of the full-stack developer, so this is to be expected. Of course, there are many who disagree, as readers can see from the aforementioned blog post, but commenters also reminded me of the following saying, with quotations often forgetting the second phrase:
Jack of all trades, master of none,
though oftentimes better than master of one.
From an application development perspective, what this adage implies is that it is better to have expertise in multiple areas, rather than just one area. And between the lines, simultaneously specializing in some areas over others should be viewed as a strength, as is recognizing when someone else is more aptly suited to work in a particular area. From my experience, there seem to be clusters of expertise for developers working on a tech stack, described in the following paragraphs.
The first cluster is in an area of the tech stack traditionally referred to as "the UI". Because much of these layers consist of JavaScript in an SPA, developers with expertise in this cluster are typically proficient from the view layer down to the "front-end" controller layer (to be differentiated from the "back-end" controller layer). And it should be noted that a significant share of developer "boot camps" currently in the marketplace seem to concentrate in this cluster. Now, with all of the clusters presented in this blog post, there will be some disagreement as to the boundaries for each. As it stands, I have chosen to create clusters with an overlap of one layer between each, because it seems from my experience that this is typically the case. Some developers might exhibit greater overlap, some developers none. The ideal is that the cluster of experience for a given developer is not smaller than one of these three.
Taking a look at the tech stack from the reverse end, the second cluster is an area traditionally referred to as "services". For the sake of simplicity, only a database is depicted in the following diagram, mainly because data is the object of a data persistence layer, but interfaces to external systems originating in the "back-end" service layer (to be differentiated from the "front-end" service layer) should also be expected. Note that the database layer is depicted in a different color because it is an area a bit different than the other layers in the sense that it is not typically (or should not be typically) developed from the perspective of programmatic code, and I have chosen to discuss this layer separately later in this blog post.
So what is left? The layers essentially comprising the glue between the "front-end" and "back-end", overlapping on the controller layer for the former, and the service layer for the latter. As I was thinking over what I wanted to present in this blog post, I realized that while expertise in this third cluster is often combined for a given developer with either expertise in the second cluster (such as myself) or expertise in the first cluster, I find it increasingly common to come across developers with expertise in this third cluster who neither have proficiency in the first cluster or second cluster. And this essentially means that such developers exhibit neither UI expertise or database expertise. In a traditional waterfall development approach, developers falling in this third cluster could probably survive, but with increasingly agile approaches user stories are more effectively tackled when there is also expertise in either the first or second clusters. The reason this is the case is because user stories typically provide functionality for either human or system users, and/or provide functionality that accesses data for reading, writing, or updating.
In my discussion of the second cluster of expertise, I mentioned that I would separately discuss the database or data store. It also should be noted that the persistence layer - whether it be an object-relational mapping framework such as Hibernate or JPA, or a JavaScript framework tied to a non-relational database - is typically tightly coupled to the data. Services can abstract much of this for developers concentrating on clusters "higher" in the tech stack, but at some point someone needs to work on this area of development. The exception might be RAD (rapid application development) frameworks out there such as Ruby on Rails or Groovy on Grails, but such frameworks are rare (or should be rare) in most enterprise architectures, since these are typically good solely for UI proof of concepts that are replaced down the road for actual long-term implementations.
In addition to understanding relational or non-relational databases at a conceptual and implementation level, developers working on the database need to understand the domain of the application as well as long-term implications of design decisions, since changes to data structures have ramifications for the data persistence layer. With some non-relational database products, implications for data structures might be lessened, but then expertise is pushed up the stack when it comes time to interpret the data. While I was initially planning to write a separate blog post to flesh out one of the questions I wrote for an earlier blog post of mine, this seems to be a good time to discuss.
In this earlier blog post, under software development question #13 of 20, I made the following statement:
Many software developers do not value data because they take it as a given as being available, think of it as "the easy part", do not understand it, or do not wish to work on it.
Let's briefly discuss these 4 points.
The data is already available. For relatively less involved application development projects, data is often already available. An example of such a project is a pure portal project in which an application is built to access this already available data (already available by other means, perhaps by only another set of users). Because the data is already available (at least most of the data is already available, as a small amount of data may need to be added for areas such as security), expertise in implementing the data store is not needed, just interpretation of some subset of the data for user consumption.
The data is "the easy part". Unlike the first point above where data is already available, this second point is subjective. The terms "easy" and "hard" are always subjective, regardless of source, because these are relative terms. In my experience, it is often the case that if data is not already available and a developer determines that it is the easy part, there is usually some other underlying reason for their confidence that falls under one of the two points below. Data is the lifeblood of most organizations, and decisions made with regard to data typically have longer term affects than decisions made in the programmatic code of higher layers because application code is typically easier to rewrite relative to restructuring data.
The data is not understood. This third point is very common. Developers in the first cluster of expertise explained earlier in this blog post typically fall into this category, depending on lower layers to interpret data for them. This reason for not valuing data is distinct from the other 3 because no judgement is being placed on whether the data is available, whether working with the data is difficult, or whether desire to work with the data exists. The data is simply misunderstood, and so the developer seeks to distance themselves from it. On one project earlier in my career, I recall mentioning to a developer that it is common that some developers do not understand data and database concepts. Their response was simply that data specialists do not understand object oriented concepts in the programmatic code. While not a good defense, this way of looking at things speaks to some of the data resistance that lives in some organizations.
A desire to work on the data does not exist. The verbiage of this fourth point is a diplomatic way of saying that a particular individual just doesn't want anything to do with the data. On a number of occasions, for example, I've unfortunately heard developers quip "I don't care about that" in regard to a number of areas, but the most common area is the data. In some sense, we've come full circle in this essay. In my introductory comments, I described use of my fingers, hands, and arms to talk about the place of a given technology within a given project in the enterprise. When it comes to data, sometimes zero digits is what expresses developer desire to work with data.
In thinking about your past, current, and future software development projects, it needs to be realized that as much as architects seek to decrease complexity, the very nature of the frameworks used in tech stacks are often in themselves complex, and so the ability to abstract this complexity can be limited to some degree. Because of the expertise needed to work on a given tech stack, coming to the realization that developers often frequently work in clusters of expertise (for specific reasons such as skill set, desire, or perceived company value) can only increase the health of a project, the technology industry, and your work advancing the progress of these two domains.