stitcherLogoCreated with Sketch.
Get Premium Download App
Listen
Discover
Premium
Shows
Likes

Listen Now

Discover Premium Shows Likes

Complete Developer Podcast

287 Episodes

59 minutes | 4 days ago
Overview of the Enneagram
The term personality is derived from the Greek word “persona” which means mask. Our personalities are the personas or masks we have built over time to protect our true nature. They are made up of the reactions and responses we’ve found to be effective in things like pleasing our parents as children, fitting in as teenagers, meeting cultural expectations. These responses help use to navigate through a variety of situations and become automated. Over time these adaptive strategies grow in complexity to the point it can be hard to differentiate the personality from the true nature. An enneagram (little e) is a nine-pointed geometric figure. It consists of a circle with a triangle inscribed and an irregular hexagonal figure within the circle. The Enneagram (big E) uses the figure to describe the relationship between various personality types that are numbered 1-9 to associate with a point on the hexegonal figure or triangle within the circle. Personalities are fun and interesting to study. However, people are so much more than just a type, number, or description. They should be used to better understand ourselves and those around us. It can be easy to fall into the trap of saying, well she’s a nine so she’ll be a push over because she doesn’t like conflict or I’m a seven so I don’t take anything seriously. These types are ways of categorizing ourselves to help us understand the way we respond or react to situations. They don’t always reflect the inner drive because while that nine may desire to avoid conflict but they may also have an idea that will make development on a project much easier or be passionate about things that they don’t mention for fear of being shot down or having to argue. The benefit of learning these types and about personalities is so that we can work with and through them to get to the inner person with whom we are interacting. Episode Breakdown Background on the Enneagram History of the Enneagram The enneagram is very old, noone is sure where the idea for it started. It’s current form has been traced to the Christian monk and mystic Evagrius Ponticus. The idea of the Seven Deadly Sins comes from his work. The nine-pointed geometric figure shows up in relation to personality in other areas of the world as well. In the early 20th century a Russian philosopher named George Gurdjieff used the enneagram to teach on esoteric subjects not related to personality. In the 1970’s a teacher from Chile, Oscar Ichazo learned of it, made significant contributions by combining what he had learned about the enneagram with studies of inner work he’d learned in South America and Asia. One of his students was Claudio Naranjo, an American trained psychiatrist. Naranjo brought those teachings to the United States and taught them to a group of Catholic priests and seminary students. Criticisms of the Enneagram There are two main criticisms of the Enneagram. One from the scientific community and the other from the religious community. It has been accused of being psuedoscience because the types are claimed to be too subjective and difficult to validate. However, to combat this the book “The Enneagram: A Journey of Self Discovery” compared the types to the work of Karen Horney, a psychoanalyst. Because of it’s early connections with mysticism there has been some religions scrutiny over use of the Enneagram for personal growth from several larger organizations including the Roman Catholic Church. Different Types of Enneagrams Originally Ichazo created over 100 different enneagrams to relate to each number, however when the idea came to the US it was reduced to four: Virtues, Passions(Deadly Sins), Holy Ideas, and Ego-Fixations. The virtues represent the natural state of the person in that number in their healthiest state of being. They don’t have to be forced, it is how they exist when healthy. The passions are the emotional responses to not being in the healthy state. They are how we express the sense of loss of peace when not in the natural state represented by the virtues. They are the basis for the Seven Deadly Sins. The ego-fixations are the path from healthy virtues to unhealthy passions. They are given as a warning for each number to watch out for to avoid falling into the unhealthy passion. The Holy Ideas show the way from the passions to the virtues. They are given as something to focus on to move from the unhealthy passion back to the healthy virtue. The current typing system combines these for each of the numbers on the enneagram to provide a full picture of a personality. The Triads The Enneagram numbers are divided into three triads based on a ruling emotion for that number. Each number relates to that ruling emotion differently. This doesn’t mean it is the only emotion felt by that number, just the primary driving force. The Gut Triad (8, 9, 1) is motivated by anger. The one will internalize anger focusing on themselves whereas the eight will externalize it focusing on others. The nine is motivated by avoidance of anger. Honesty and directness define the Gut Triad. The Heart Triad (2, 3, 4) is motivated by feelings. Twos outwardly express feelings and focus on those of others finding it difficult to understand or express their own. Whereas the fours focus internally on their own feelings but have difficulty understanding others feelings. Threes have trouble recognizing that feelings exist in themselves or others. They are more image conscious than the other triads. The Head Triad (5, 6, 7) is motivated by fear. Fives externalize fear whereas the sixes will internalize it and be motivated by their own fears. Sevens have trouble remembering to be afraid of things and tend to be the most adventurous of the numbers. This triad tends to think a lot before they act. Structure of Episodes Main Characteristics Each episode will start off with a description of the main characteristics of the Enneagram type. This will cover the basics of that type including some statements to help you identify them in your life. We’ll also discuss the primary desires and motivating factors for the personality type. For each type we discuss we’ll go into detail about their basic fear and how to avoid or manage it. Also we’ll discuss basic desires and how they can be met. Then we’ll give a description of a healthy, average, and unhealthy person of that particular type. Finally, under main characteristics we’ll discuss the type’s associated Deadly Sin, how it can affect the person, and the temptation that leads to that sin. Wings and Things The Enneagram personality types are not distinct sets of personality. They are interrelated with aspects of various types interacting to create a full personality. Each number on the Enneagram has two wings, the numbers immediately surrounding it. Most people will fall somewhere between their type and one of it’s wings. They will have a few of the characteristics of that wing that interacts with their primary number or type. The lines coming from each number on the Enneagram figure point to other numbers. These are the numbers associated with the traits that a person takes on when they or either under stress or when healthy and secure. In each episode we’ll discuss how the type takes on the negative characteristics of the type it goes to under stress and the positive qualities of the type it goes to when healthy along with how that relates to the particular type. Interacting With Others Finally we’ll have a section where we talk about how the type interacts with others. This can be for how they interact and how to interact with someone you know who is that type. We’ll spend most of our time talking about how to interact in the work place. This will include aspects of working together on a team, how different types interact, and how to lead and motivate each type. Developers aren’t complete without friends and family, so we’ll also discuss how to interact with friends and family members both if you are that type and if you know someone who is that type. Relationships are also important so we’ll look at how each type interacts in a relationship and how to interact with them if you find yourself in a relationship with someone of that type. Tricks of the Trade Embrace ambiguity and models that don’t perfectly work over seeking models that work perfectly (which may not exist). Life is messy and if you want to move forward, it’s more likely that you will do so by starting with something good enough and then refining, versus hanging out and trying to come up with something perfect before even starting. Links Join Us On Patreon Level Up Financial Planning Donate to Beej’s Mission Fund Memo: Put “BJ Burns” in Memo The Road Back To You: An Enneagram Journey To Self-Discovery Enneagram Institute Wikipedia The post Overview of the Enneagram appeared first on Complete Developer Podcast.
63 minutes | 11 days ago
Recovering Motivation
Practically everyone you talk to these days is struggling to varying degrees. Lives have been thrown into chaos, and there is a tremendous amount of confusion as old routines are drastically and often suddenly altered. Worse still, most of us feel like we have no control over the way our lives are going. This can make it very difficult to keep your motivation going. As time goes on, not only does your motivation take a hit, but you start to feel bad about the lack of forward motion. Eventually it gets more difficult to get ANYTHING done, much less the stuff that really matters. However, while you can’t change the situation, you can change the way you react to it. Even with our present situation and the all the associated weirdness, there are still things you can do to recover your motivation and get moving again. The situation is far from hopeless, and it’s entirely possible that these times constitute the best opportunity you’ve ever had for real person growth, provided that you can get going again. There’s also a danger here. A lot of conversations about motivation assume that you are going to achieve some sort of productivity nirvana. That’s unlikely to happen in the present circumstances (or if we are honest, in ANY circumstances you are likely to encounter). Lots of discussions by motivational gurus will proceed as if nothing bad is going on. That’s not a realistic assessment of most people’s situations at most times. Rather, a decent approach to repairing your motivation consists of accepting reality as it is and then doing what you can with it, instead of pretending that you have total control over your situation. Things don’t always work out perfectly. And it’s completely normal to periodically feel a loss of motivation. Given the current strains on society, it’s not only normal, but expected. However, if you have big goals, you probably don’t want to to wallow in misery until things get better. Part of taking charge of your own life is figuring how to correct your own motivation so that you can keep moving forward. It may not be perfect, but much of life isn’t. Episode Breakdown Remember the beginning At some point, you may have made a decision to do whatever you are doing right now. Try to remember how that felt and why you were motivated at that point. Are those motivations still valid and reasonable? Alternatively, you may not have explicitly decided on your current situation. Thinking back may help you realize it. This could easily be the reason you feel demotivated to continue. Regardless, one of the most important keys to recovering your motivation is to remember what previously motivated you and to evaluate whether that reason for motivation still applies. If it doesn’t you either need to find something else to motivate you, or you need to re-evaluate whether you want to continue what you are doing. Look for changes and adjust to them. You may also be feeling a lack of motivation because circumstances have changed. Take some time to figure out what has changed recently, and whether that change means that your goals have a different possible outcome. You might also find that changed circumstances mean that your current project is even important and valuable than you thought. This can help you recover motivation. It may also be trivial to simply adjust to changes. For instance, if you schedule suddenly changed, you might find that changing your sleep schedule to match it makes sense (if the project is important enough). Get moving on easy tasks instead of critical ones. Sometimes motivation needs a bit of a kickstart, or easy win. Odds are good that if you’re stuck, you’re probably not stuck on the easiest or most pleasant thing on the list. While this can be difficult to justify to management, this can also take the form of simply taking a smaller chunk of your current task and handling before even considering the rest. This is why agile teams tend to break things down. The other thing about simple, smaller tasks, is that you can more quickly get positive feedback which will help your mood, or help you more effectively reason about the problem you are dealing with. Look for and adjust health issues. A lot of times, motivation goes away because you feel like crap. In addition to the previous bit about sleep times, things like your diet, exercise levels, alcohol consumption, or even just aches and pains can significantly alter your feelings of well-being. While health issues aren’t always the easiest thing in the world to fix, there are often simple things that you can do that can make things less miserable, even if it doesn’t totally fix the problem. In particular, pay attention to your diet, your sleep, and any nagging aches and pains. Improve those and you may find that you are better equipped to deal with other difficulties. Hormonal levels (such as low-T in men) are also worth checking. Allergies and food sensitivities are another area where small changes can have big payoffs. Lean on your support network. Don’t try to do everything by yourself. While you probably can, it’s not efficient. This is especially true if you are stuck trying to figure out something simple. For almost everything you do, you are going to have someone in your support network who can do it better, who has more experience, or just has an approach that you don’t. Find them and ask for help. You also have people in your support network that care about you (hopefully). Sometimes when things get too difficult, it’s worth reaching out to them and just talking. While this isn’t easy in the current COVID environment, even a zoom call is better than nothing. You might also want to look at “outsourcing” some of your work, especially the parts you don’t like to do. This can free up your focus so that you can work on more important items. Concentrate on benefits, not on difficulties. Spend some time listing out the downsides and difficulties of what you are doing, then take that list and figure out what advantages those difficulties give you. Not only does this do a wonderful job of telling you which things aren’t worth doing in the first place, but it can also give you a lot of perspective on the relative importance of each thing you are doing. By focusing on the upsides, you can spend more effort on things that are more likely to matter and less on things that won’t. You may also find that if you do this, you can make the upsides even more profound with slight adjustments to what you are doing. Remember your larger purpose. It’s very easy to get caught up in minutea, especially in longer-term projects. If the project is going to make a large, positive impact on your life, it’s easy to forget that when you are tracking down yet another NullReferenceException. It’s also very easy to get lost in the weeds and end up doing things that don’t move you towards a larger goal. If you are starting to get stuck and lose motivation, keeping the larger goal in mind may help you formulate alternatives to what you are currently doing. You may also find that your larger purpose can be served immediately with some quick wins. These quick wins can not only help motivate you, but can often result in learning things that change your overall course for the better. Finally, it’s worth re-examining your larger purpose often, just to make sure that it is still a goal worth attaining. Remove negative influences. Motivation can also be destroyed by having negative or toxic people around you. Note that some people can be absolutely wonderful about most things, but will continually talk down about your major life goals. That’s still toxic. There are also other more subtle behavior patterns that you might want to remove from your close circle, such as people with poor boundaries, who constantly have drama, or who are regularly negative about other things. Limit the number of decisions you make while executing. Sometimes the problem is decision fatigue, rather than actual burnout. Reducing the number of decisions you have to make in a given day can often help with that. Plus, you’ll often find that most decisions really don’t have any bearing on anything useful at all. For these, you save time by choosing a sensible default and sticking with it. Try to separate the phases of your work that involve making decisions from the phases of your work that involve acting on those decisions. This can greatly reduce the stress of both. Embrace the power of making a “good enough” decision that lets you get moving, if you find yourself in analysis paralysis. Most things can be undone if you expect that it might be required to do so. Track small wins Your motivation WILL lag if you feel like you aren’t making progress. Odds are good, however, that you probably are making at least some progress towards your goals. This is why it’s useful to track even small wins. It’s much easier to troubleshoot ways to move faster than it is to come up with ways to move at all. Tracking small wins is also a good way to determine whether you are focusing on the right things or not. If you aren’t tracking what you are doing, it’s easy to lose sight of the amount of time you are spending on tasks, which means you won’t know if you are being distracted by minutea. Tricks of the Trade Running into a problem developing can drain you, especially if you are already suffering a lack of motivation. You may be stuck on something or just out of ideas. The trick to overcoming these times is in your attitude. It helps if you’ve had success before in a tough stop, or even been on a team. Look at it as a game or puzzle, know that there is a solution you just have to find it. Almost everything we do has been done before so there is going to be a solution, even if it’s not elegant. All you have to do is find it, then you can refine to make it elegant. Links Join Us On Patreon Level Up Financial Planning The post Recovering Motivation appeared first on Complete Developer Podcast.
61 minutes | 18 days ago
Programming Paradigms
According to the dictionary a paradigm is “a typical example or pattern of something, a model.” in reference to language it is “a set of linguistic items that form mutually exclusive choices in particular syntactic roles.” Programming paradigms classify programming languages based on the features of the language or the rules around how code is written in that language. Languages can be classified into multiple paradigms with some languages being specifically designed to be multi-paradigm. This allows the programmer to choose how to best implement the language or the framework around that language to meet the needs of the program or app they are writing. Many of these languages have a primary paradigm such as being primarily object oriented but allowing for other paradigms like procedural or functional. To understand how languages work we’ll start with looking at the Turing machine designed by Alan Turing in 1936. This is a mathematical model of computation defining a machine that manipulates symbols on a strip of tape based on a table of rules. Within this construct any computer algorithm can be simulated with a Turing machine. Along the same lines a programming language is said to be Turing Complete if it can be used to simulate any Turing machine. What that basically boils down to is that a language is Turing Complete if it can simulate or create any given computer algorithm. Programming paradigms are ways of thinking about programming languages or sets of languages. There are many paradigms out there and they are not mutually exclusive. However, there are a few exclusive dichotomies which languages tend to fall into. Sometimes languages are designed to fit into a paradigm whereas other times they were built for a purpose and then are placed in a paradigm. These are just a few of the myriad of programming paradigms available for study. While it’s easy to think of a particular language as being one paradigm or the other it is important to know the history of the language and how it can be used. Many modern languages allow for multiple paradigms, even if they were originally written with a particular one in mind. Use the information here to better understand the languages and frameworks you use and how they relate to others that you interact with on a regular basis. Episode Breakdown Structured vs Non-Structured The earliest Turing complete programming paradigm was non-structured. The non-structured paradigm can be found in both high level and low level languages. The flow of programs in non-structured languages use jumps to labels or addresses. In many of these languages line numbering is important with “goto” statements being the jump that moves to the line number or label. Non-structured programming is therefore hard to read and produces spaghetti code, though it’s proponents, such as Donald Knuth, argue that structured programming can be just as hard to understand. Structured programming was designed to improve the flow and readability of programs. It became popular after a letter by Edsger Dijkstra was published titled “Go To Statements Considered Harmful”. The Structured Programming theorem states that a group of flowcharts, or more generically control flow graphs, can compute any computable function by combining subprograms in one of three ways: sequence, selection, or iteration. Sequence combines subprograms in a linear fashion with one performed followed by another. Selection uses a boolean expression to decide which subprogram to perform. Iteration repeatedly runs a subprogram as long as a boolean expression is true. Structured programming uses control flow constructs like if/else, loops, blocks, and subroutines to guide the flow of a program rather than unstructured jumps to different areas of code. Subroutines are a callable unit of code such as a function or method that allows a sequence of instructions to be referenced by a single statement. Block structured languages have syntax for formally enclosing sets of instructions into blocks of code that are wrapped by some sort of block identifier and closer like {} in C based languages or BEGIN…END in Pascal. While you won’t see GoTo statements in modern languages, you’ll be hard pressed to find fully structured languages too. There are several deviations from structured programming that modern languages use to be more efficient. The most often used deviation is the return statement or the early exit from a loop or function. In many cases multiple exits from a function are desirable, even Kent Beck and Martin Fowler suggested having multiple exits in their book on refactoring. The biggest concern is memory leakage because of lack of clean up from leaving too early, but this is handled in most modern managed languages. A specific type of early exit that violates the single exit principle of structured programming is exception handling. Proponents of error handling in structured programming state that at the time Dijkstra wrote the rules of structured programs that error handling was not in place. A less common deviation is the state machine which will have several states that are not easily converted into structures. State changes tend to be implemented with a jump to the new state. This can be seen in parsers, communication protocols, and the Linux kernel. Imperative vs Declarative Imperative programming changes the state of the program or machine through code written by the programmer. Imperative programming focuses on how a computer performs operations by expressing commands for the computer to perform. Recipes are a good example of a real world imperative paradigm. Each step in the recipe is an instruction and the real world holds the state. In low level imperative languages statements are instructions that can be translated down to the native machine language. State is then defined by what is in memory. At the lowest level, hardware implementations are all imperative as it is designed to execute imperative machine code to change the state of the machine. Higher level languages use assignment statements to assign values in memory for later use allowing the program to evaluate complex expressions. They also apply the aspects of combining subprograms, blocks, and subroutines of structured programming with selection, iteration, and sequence. Procedural languages apply the imperative paradigm by grouping sets of instructions into procedures. Procedural programming is a form of structured programming where the state changes are localized to explicit arguments or procedures. Procedures, sets of instructions, are a series of steps for a computer to follow when executing a program. They may be called at any point in a program, even from other procedures or recursively. Modularity is important in procedural programming as it limits the interaction the procedure has with the execution environment by specifying input arguments and return values. Scoping in languages is a way to keep procedures from accessing variables of other procedures. Object Oriented languages group sets of instructions based on the parts of the state on which they operate. Objects in Object-Oriented programming contain both data and the code that acts upon that data. Data is stored as fields, properties, or attributes and code is in the form of methods or procedures. Object oriented programming (OOP) creates objects that interact with one another via side effects to perform the necessary tasks of a program. Side effects alter the state of variables outside of the local method or object. In class-based languages every object is an instance of a class with the classes containing the definition for the data types and any methods working on that object’s data. The objects are then specific instances of those classes. Classes don’t exist in prototype-based languages, objects are the main entity. Each object has a prototype, just one, which itself is an object. The data attributes and methods of a prototype are applied to all objects inheriting from that prototype. Declarative programming is a way of designing and building programs that declare the desired results without describing the control flow or how the program gets to that result. One of the main aims with declarative programming is to reduce or even completely remove side effects. This is accomplished by explicitly defining what a program must do in terms of a problem domain instead of defining how the program must do it. Declarative programming has a strong resemblance to mathematical and formal logic. Programs are viewed as theories of formal logic with the variables and some procedures as premises and the computations performed as deductions. Constraint programming involves declaring a set of constraints on a variable or group of variables. Constraints are not steps in a recipe to get to a solution but properties of the solution to be found. Algorithms are not so much run as computations are solved by applying values to the variable to meet the constraints of the program. Domain-specific languages are languages that are specialized to a particular domain, such as markup languages and regular expressions. HTML only describes what should be on a webpage, not how it is rendered. The advantage of domain specificity is that the language does not have to be Turing complete, meaning it is easier for it to be completely declarative. Functional languages use expression trees to declare values as a series of function applications. An expression tree is an abstract data type where a binary tree structure is used to define an expression. Each node will either be terminal or have up to two children. In functional languages functions are treated as first class citizens in that they can be passed as arguments, returned from other functions, and bound by names. Smaller functions are combined modularly to create a composite program of multiple functions. It comes from the use of lambda calculus which is a system of mathematical logic that uses functions to express computations. Lambda calculus was proven to be equivalent to a Turing machine by Alan Turing himself. Purely functional programming treats functions as mathematical in that they cannot be affected by mutable state or side effects from other functions. This means that when an argument is passed into the function it will always return the same result. For example the function f(x) = x^2 always returns 4 when x=2. Logical languages are based on formal logic, using a system of facts and rules to declare an answer to a question. Programs in logical languages are sets of sentences that describe rules or facts about a problem. The rules are written as clauses for formal arguments and read declaratively. Facts are rules without a body. Programming in logical languages is basically controlled deductions. Programs are separated into control components and logic components where the logic component determines the output of the program. Stricter logical languages like Datalog are only declarative with their execution completed by a proof procedure not controlled by the programmer, whereas less strict languages like Prolog have a procedural interpretation that can be manipulated by the programmer. A Horn clause is a clause with only atomic formulae or literals. Meaning that the rules and facts are all strictly self contained without any subclauses within them. This is the simplest, most basic form, of a logical program. Function-Level vs Value-Level “Programming languages appear to be in trouble. Each successive language incorporates, with a little cleaning up, all the features of its predecessors plus a few more. […] Each new language claims new and fashionable features… but the plain fact is that few languages make programming sufficiently cheaper or more reliable to justify the cost of producing and learning to use them.” ~ John Backus In his Turing Award lecture, John Backus described a new philosophy in programming design. Backus was a computer scientist who invented the first high level programming language (Speedcode) and lead the team that developed FORTRAN. He also invented BNF or Backus-Naur Form for the notations of formal language syntax. His Turing Award lecture which lead to the distinction between value-level languages and function-level languages was titled “Can Programming be Liberated from the von Neumann Style?” While his intent was to promote and gain interest in the FP language he developed as fully function-level the paper had more effect in gaining interest in functional programming. The von Neumann style of languages implements the von Neumann architecture which applies to any computer that stores programs where getting instructions and data manipulation cannot occur at the same time. Most modern languages apply von Neumann architecture. Value-Level languages describe how to combine certain values with others values until an ultimate result or final value is found. All von Neumann Style, and therefore most programming languages, are value-level languages. Expressions on the right side of an assignment statement. These build values that can be stored or used to build other values. Value-level programming studies look at the values within value-forming operations and their algebraic properties. Study of data types is a subset of studying values and focuses on the axioms or algebraic laws around the values. Even functional languages based on lambda calculus are value-level languages. The functions return a value, which can be another function, to be stored passed into another function to form yet another value. Function-Level languages are variable free, instead they apply programs to program-forming operations or programs. Programs are built from other programs that are given on the outset by combining them via functions or program-forming operations. Instead of creating successive sets of values function-level languages create successive sets of programs. Function-level programming allows for bottom-up semantics by enforcing very strict functions. It also doesn’t lift lower value-level to higher function-level images of an existing value-level. The difference between functional languages and function-level languages is that function-level languages have a hierarchy that goes from atoms to functions that take in one atom and return another to higher-order functions that will take in one or two functions and return another function. Tricks of the Trade A paradigm is ten times as good as “my two cents”. Don’t force a paradigm onto a language that it doesn’t support. You’ll hurt your team and your own career if you do. Links Join Us On Patreon Level Up Financial Planning Wikipedia University of Texas John Backus Paper The post Programming Paradigms appeared first on Complete Developer Podcast.
58 minutes | 25 days ago
Predictions 2021
Last year we started the episode with a joke about this being the most fun Predictions because 2020 would be in hindsight. This year most of us are glad to see it go. Even with the year we’ve all had, this is still one of the most fun episodes we record each year. Both Will and BJ look forward to reviewing their predictions from the previous year and creating new ones. It’s important to stay up to date with the changes in technology, especially in your particular field. 2020 was not the year any of us expected, but its challenges have also opened the door to a lot of opportunities. Even with all the stuff going on almost all of our predictions came true. Much of this has to do with our predictions being about technology and the industry around it. If anything the events of this past year have cemented our dependency on technology in our daily lives. While 2020 was not the year many of us hoped it would be, we here at Complete Developer Podcast are excited to see what 2021 has to bring. BJ’s Predictions We’re going to see a lot more people working remote from distant locations. 2020 has taught the doubters that remote work is a valid option in many industries. I was already remote before 2020 but we recently learned that we won’t have an office to come into and that we’ll just be coming in when needed. Friends in other industries have seen their offices shut down and employees told they can work from anywhere because they are able to get the job done and don’t need to pay for the office space. Hawaii seeing a downturn in tourism is offering to help people fly out there to work remote. There will be a rapid increase in paranoia and anti-science rhetoric as more is understood about the COVID-19 virus and early assumptions are shown to be false. As vaccines enter the human trials we’ve already seen a rise in the anti-vax movement. Virology, epidemiology, and medicine are highly specialized fields but you will see people and even news media take things out of context or not understand the science or process behind something and then try to make a judgement on it. No more whiteboard interviews. With remote work on the boom and the industry moving forward while still distancing, we’ve seen that tech interviews do not need to include the white board. There will be new tools developed to better assess a candidate’s abilities and thought processes when coding. Many of the training and pair programming tools have been repurposed for interviews during the pandemic. We’ll see more of these tools developed and marketed for remote interviewing. We’re going to see a shift in music culture. Not only will we see a lot of new and creative music coming from artists who are already popular but we’ll see different types of music becoming popular. Garage bands and people who previously hadn’t been big in the music world will start to become popular. Already music stores have seen an increase in interest in the guitar. Prior to COVID it had been on the decline but is seeing a renewed interest. Will’s Predictions Look for medically inclined tampering with your life (in ways harmful and not) to increase in the next year. It’s not just covid, but a variety of things that people would have been wary of will probably come to pass in the next year, including things like temperature scanning when entering places with crowds, etc., and more stringent enforcement of vaccine mandates. The political heat over where the line is will continue to ratchet up as well in response. However, it also means that there is a much bigger market for things that will be positive in the long run. Regulatory pressure is going to be brought to bear more forcefully on big tech companies, particularly on social media companies. There are few electoral parties on the planet that like them or find them beneficial and they’ve made enemies everywhere while alienating their own users, showing decreased value to advertisers, and becoming easier game for large players in the market. This could represent a very interesting time for upstarts in those markets. People are going to be less neutral about remote work. Either they’ve done it and they hate it, or they’ve done it and they like it a lot. Expect multiple major shifts IT hiring as a result – they are going to be keeping their eye open for things that caused a problem during the lockdown. “They”, in this case can refer to both the interviewer, and the interviewee, as both have learned a lot this year. Travel and big events (including large conferences) will still be locked down at the end of year in some places, and there will be less of it. Some events will go away, while others will morph into online-only events. There will, however, probably be a fair bit of travel right after whenever COVID dies down, simply because people are going stir-crazy. All this assumes that there is no major war that breaks out. Tricks of the Trade Learn to pivot when things get “interesting” like this year was. You cannot resist broad change, but you can pivot it with it and add its energy to your own. Links Join Us On Patreon Level Up Financial Planning The post Predictions 2021 appeared first on Complete Developer Podcast.
56 minutes | a month ago
Resolutions 2021
The theme for this year was perception. We looked at how we perceive the world around us and how those with whom we interact perceive us. Episodes will focus on different ways of thinking about problems and situations. Sometimes a change in perspective or how you perceive a situation can show a previously un-thought-of solution. We are about to review our goals for this year. This had been an interesting year for many of us. Since no-one could have predicted the pandemic and quarantine some of our goals were just not possible. We are adding a category to our results: Postponed Due To COVID. This year has been interesting to say the least. It has caused many of us to reevaluate how we live our lives and do our jobs. Remote work has become the norm, not just a special perk. Lots of things were canceled or missed this year, but 2021 is a new year with new and exciting things to come. Here at Complete Developer Podcast we are working diligently to create our best year yet and we encourage you to do the same while learning about and understanding yourself. Resolutions 2021 Beej Speak at a conference again. I miss conferences…I miss climbing the wall at Vandy, or playing Developers Against Humanity until 1am, or sitting at the hotel bar chatting with other speakers and attendees. I also miss the thrill of public speaking, even if I have to change my talks or write new ones to be online I’m going to submit and speak at a conference this year. I’ve already submitted to a few conferences that have opened their CFP (Call For Proposals). Start writing my story. I’ve kind of already gotten started if you count the poem I wrote for the creative group I’m in or the talk on dealing with depression I wrote. What I mean here is that I’m going to start writing a book. I’m not sure if it will be “based on a true story” or an autobiography yet. Take on more of a leadership role at work. Because of COVID I ended up becoming one of the team leads on the tech team at church. I’m in charge of cameras, radios, social media during live streams, and misc. At work, while still in the advanced (senior) developer role, I’ve taken the lead on a couple projects. This year I plan to thrive in these roles and take on more leadership responsibilities with the long term goal of getting promoted to a lead position. Join the praise/worship team at church. This is still a driving goal of mine. I’ve improved on my guitar skills, focusing my efforts on rhythm guitar instead of just learning riffs and licks. I’ve got the two try out songs down and play along with the recordings of the praise team. In my lessons my instructor has started work on site reading where he’ll have a song either tabbed out or the chords and have me play the whole thing from site. New equipment to improve my home office set up. For my birthday Will gave me a quad monitor setup. I need a new desk and the chair I’m using is at least a decade old if not more. I’m planing to periodically purchase new office furniture and equipment throughout the year so that I’ll have a solid setup by the end of 2021. I’m going to stop drinking alcohol in 2021. I spent the first half of my life so far not drinking and the second half doing so. I don’t have any problem with drinking, I’m just going to give not drinking a try again. I want to see how it affects my IBS and my mood over the course of the year. Also, it’s a bit of a gimme here because the praise/worship team at church has a leadership honor code that involves not drinking. It’s completely voluntary but required to be in a leadership role at church. Will Build another product, either a book or a course. I’ve not decided yet and getting some things in place with the podcast and related stuff (such as the email list) has to happen first. I’ll be self-publishing anything else I do. Do more extensive tech-adjacent writing. I got presented with an interesting opportunity last week and I think I could get more. Rework my home office to be more comfortable and usable. It’s good now, but I need to quit being cheap and spend a little more money really making it and the old recording room more usable. I need a new chair as well – the current one was an inexpensive one I picked up on sale and isn’t doing too well after a couple years. This probably also means getting a decent gaming system, and a mac for recording, along with getting some more electrical drops and better lighting in the room. Eat better – my diet has been kinda crap since COVID started. I gained a little bit of weight earlier in the year, but dropping back on the soda straightened that out. But I still get fast food way more often than I did a year ago. Part of that is because my daughter is in the house, and it complicates lunch and limits my options (due to having to feed her as well). Digital reorganization. Web hosting goes to Amazon, domains move off godaddy, consolidating email accounts, getting financial stuff managed a little better, and consolidating password storage. During my time stuck at home, I identified a bunch of stuff that probably needs to be organized better and there’s a laundry list of stuff that would make me more efficient if I had it fixed. Greatly increase my non-formal exposure to Russian language. I’m practicing a ton during the week, but it’s almost all exercises and stuff from books. I want to start getting into maybe watching some shows, reading fiction, etc., since my vocabulary is at a point where that is realistic. Network Break even, not have to pay for the podcast or Dev Launchpad out of pocket. Our current output is around $500 per month, most of which is podcast editing. We plan to get to a point with sponsorships and Patreon donations to be able to cover this every month. Rebuild DevLaunchpad. There is a lot more potential there than what we’ve done with it and now that Will has gotten a couple books out, we have some ideas that will really help that thing be more useful to the community (and he has time to work on these). Get into coaching other developers. This is something that both Will and BJ are passionate about. We are mentors and run a meetup group designed to help developers in their careers. Theme for 2021 Since most of 2020 has involved a lot of time alone or away from other people the theme for this coming year (2021) will be understanding yourself. We’re going to do this by looking at the Enneagram personality test. The Enneagram breaks down personality into 9 interrelated catagories or types. Over the course of 2021 we’re going to explore each one of these types. We’ll dive into one per month. Next month we’ll have an episode introducing the types and what we’ll look at each month. Will is a Type 1 or the Reformer. Ones are highly ethical with a strong sense or right and wrong. They tend to be well-organized and maintain high personal standards but can become critical to the point of perfectionism if unhealthy. Their basic fear is being corrupt or evil. They desire to be good, have integrity and balance. Healthy ones take on some of the positive traits of the seven (the enthusiast) such as spontaneity and joyfulness. Unhealthy ones under stress can become moody and irrational taking on the negative aspects of the four (the individualist). Beej is a Type 2, the Lover or the Helper. Twos are friendly, empathetic, warm-hearted, and self-sacrificing. They are driven to be close to people, but may end up becoming people pleasers just to feel wanted or needed abandoning their own needs. Their basic fear is not having any friends or being unworthy of love. They desire to be loved and appreciated for what they do as well as to be able to express their feelings for others. Healthy twos take on the positive aspects of the four (the individualist) such as self-nurturing and emotionally aware. Stressed or unhealthy twos can become aggressive or dominating, taking on the negative characteristics of the eight (the challenger). Tricks of the Trade 2020 was a Rorschach test and an apocalypse (in the original sense of the word). It has unveiled many things that we didn’t realize and has made so many things more real. Take the lessons you learned from it and make your life better. Links Join Us On Patreon Level Up Financial Planning Enneagram Descriptions Ennegram Test The post Resolutions 2021 appeared first on Complete Developer Podcast.
61 minutes | a month ago
Surprises When Becoming A Team Lead
Being a team lead is a natural step from many mid-level and senior positions. It’s also a bit of a culture shock if you haven’t done it before. In many organizations, you may get promoted to a position and expected to deliver, without anyone giving you a clue about what is expected. Worse still, you are going to have to learn quickly, or you could very easily lose your job. If you have a sense of pride in your ability to code and think it is extremely important, you might be surprised at some of the other things that are expected of team leads. Not only do you have to be far more careful to be professional and fair to your coworkers, but you may find yourself in a position to lead them in various ways, including mentoring. You’ll also probably find that a lot of activities that you don’t particularly enjoy are considered extremely important for your job. Finally, you may also have bad habits that you need to correct in order to be an effective team lead. Until this point in your career, most steps in your career have consisted of doing more (or more difficult) work than what you did in the previous position. While this happens in a team lead position, these positions do tend to add a lot of responsibilities that have little to do with code. If you plan to eventually be higher up in management, such a position is a great introduction to the skills that you’ll need for those higher positions. However, make no mistake, a team lead position is the first step in a career change away from software development and you need to be serious in how you approach it. A transition to a team lead position is a huge step. Not only is it a better position in many respects, but it’s often the first step towards moving into real management positions later in your career (provided you want that). However, by its nature it’s also the first step towards a complete change in your career. As such, there are some things that will almost certainly surprise and frustrate you about that position. However, if you are prepared, you are more likely to be able to handle the position well. Episode Breakdown Interpersonal relationships change. Previously you interacted with your coworkers as equals. Now, however, there is a tinge of management in anything you say, whether you want it there or not. This can make relationships less warm and make people cautious around you. This also means that you have to be careful to avoid even the appearance of favoritism, because it is corrosive to the team. Worst of all, your friends may not understand that. If you are still coding, you still have to pull your weight or your team WILL discuss it when your back is turned. This probably means longer hours or greater discipline (possibly both). Communications with your team will change. You are effectively the leadership of the team (hence the whole “team lead”) term. Suggestions you might have casually (or even jokingly) made before can be taken seriously now. This has the potential of backfiring if you don’t watch your mouth. Team members will start coming to you for help now. They might have before, but they are going to feel especially abandoned if you don’t help them. You also have to be careful to keep communication lines open. You are now the nexus of communication between your team and those that are higher up. You want to make sure that your team doesn’t feel the need to route around you to get things done. You will need to check your ego at the door. You can be right about absolutely everything and be a terrible team lead if you communicate poorly. If you are sure you are right about everything, not only are you wrong about a lot, but you won’t find out you are wrong until it really hurts. Expectations of your work change. You’ll likely still be expected to be as productive as you were previously. This often occurs while you are still being expected to mentor/lead a team and attend lots of other meetings. Your team will also have the expectation that you will protect them to some degree from the rest of the organization and that you won’t mislead them. Expectations will need to be set in both directions. While managers are typically either a “crap funnel” or “crap umbrella”, as a team lead, you are often expected to be both. Your manager expects to be able to delegate to your team without fuss, and your team expects you to keep them from being overloaded, distracted, and blamed for failures. You need to be more careful about both your code quality and the way you review the code of others, because you are expected to avoid stupid mistakes, and you probably have time and attention constraints now that make you more likely to make them. Culture is now your problem Your team looks to you for an example and for guidance. This means that a lot of things that were previously acceptable no longer are. This also means that you are going to have be a bit more tactful and political with the way you handle things. If you’ve gotten into the habit of bashing other team members or other teams, you have a big problem. You also need to watch how you present your work ethic. Looking lazy or regularly overworking can now impact your coworkers, as they are liable to emulate your behavior. Interpersonal mistakes are more likely to get you in hot water with management, because you can much more easily cause turnover and lawsuits. You still aren’t “real” management. You probably don’t have the ability to fire people as a team lead, and you almost certainly don’t have the ability to hire them either. Nevertheless, you are quite likely to get blamed for either situation, because your team members will see you as part of management, rather than as part of the team. Management will also probably blame you for the actions of your team, but not give you any real authority. Your pay scale probably also reflects all these things. What leads actually do is different than what you think. While leads are generally expected to code, there are also a lot of non-coding responsibilities on your plate. You’ll be expected to act as a go-between between your team and management in both directions. You’ll also be expected to assume some responsibility for the productivity of your team. You’ll be expected to mentor other developers and help them get unstuck from problems. You will probably also have some reporting responsibilities, either to your manager, or to their manager. Your schedule changes a lot. You might have long periods of focuses work before. You might still get them now, but they will be rarer, as you are transitioning to more of a manager’s schedule. You’ll probably also find that your ability to schedule things over the longer term is also more difficult, because you’ll probably get pulled into more meetings with less warning than you might have had as a developer. Expectations around work/life balance may change as well. You may face expectations of longer workdays and more availability during your time off. This can also mean that you end up dealing with emails after work and the occasional crisis. As a leader, you may want to do this, just to keep pressure off your team. Responsibilities change and you have to delegate what you used to do. While you probably still are coding, if you want to move up, that means that you need to train your people up to the point where they can replace you when you move up. You also probably have less time and more responsibilities on your plate. This means that the rest of the team will necessarily have to do some of the work that you used to do. Delegation alone won’t work, however. You’re going to have to learn to both delegate, and to set reasonable expectations. You have to be willing to see that those expectations are met as well. Make sure that your methods of communication are up to snuff when you delegate work. You don’t want to have to scramble to find out where things are when YOUR manager asks you. Your network at work changes. Instead of your network being mostly developers and other adjacent positions, when you become a team lead, you need to be actively building your network outside of the IT department. You are also on a different playing field in regards to office politics. You may have to worry about your own team members, and you will be jockeying for position with other teams while trying to protect your team. Being able to work well with other team members is going to be even more important, because failure is more expensive at this level. Your networking with other departments should probably include eating meals with them and socializing. What you DON’T do changes. You shouldn’t be making jokes about the quality of someone else’s work, jokes about firing people etc. Once you have even minimal power, those jokes can be taken as threats. You also have to stop gossiping, if that’s a thing you do, because now that not only sets a bad example, but the results of it can land on your team. You can’t be seen visibly slacking off, or at least not often. You may not always be busy, especially if you have gaps between meetings, but you’ll need to look busy to avoid resentment. You also can no longer afford to tolerate certain personality types. For instance, perpetual complainers and “smart boys” because they quickly become backstabbing toxic monsters and they’ll damage your team morale. Tricks of the Trade Different roles on teams mean thinking about things differently. This episode was about moving up to a lead role and how you will have to change your thinking for doing that. The concept applies to other areas of your team though. The various members have different goals and functions so what a BA thinks is important may not even be something that the QA or DBA even think about. Learning about the other roles on your team can help you to understand what motivates them and what they think of as important. The same concept applies outside of the work place. Different people have various goals not only in their work life but also in their personal lives. Understanding these motivations will help you to understand the people around you, helping to the reach their goals will encourage them to help you reach yours. Links Join Us On Patreon Level Up Financial Planning The post Surprises When Becoming A Team Lead appeared first on Complete Developer Podcast.
59 minutes | a month ago
Becoming Teachable
“One of the greatest compliments I’ve ever received was being told I am teachable.” ~ BJ Burns The most talented guitarist will stagnate and fall behind the much less talented player who is teachable and treats playing as skill to be honed. The same goes for software development. Even the most talented senior developer will not be as good as an average junior developer who is teachable and hungry to learn more. The true greats, like Slash or Hendrix, are a combination of talent and teachability that leads to growth in skill. Teachability is an aspect of humility. It is the ability to accurately assess and recognize your skills and talents knowing that there is more to learn, even if you are at the top of your field. Senior developers who are teachable take on the attitude of a junior when learning a new skill. Being teachable means that when someone comes along with new knowledge, even someone with less overall knowledge than you, that you take on the role of a student to learn the new thing. Teachability is not about how you learn or your ability to learn but an attitude toward learning. A teachable person is a lifelong student who has a desire to learn and apply what they’ve learned. It is an ability to unlearn what does not work and relearn a new way of doing something. Being teachable will rapidly advance your career as you will show your peers and managers that you are willing to set aside your ego for the betterment of yourself and your team. Even as a seasoned developer being teachable will help you to keep up with the changes in technology and engender you to the newer developers as you lead by example allowing them to teach you things about the newer tech. Teachability is a skill as much as it is a personality trait. It is one of the easier things about our personalities that we can change. It takes a little bit of work and some self-reflection to be able to improve teachability but it is possible. On the same note, it’s an easy skill to loose if you are not careful about maintaining it. Use this information to help you understand your own level of teachability and improve it so that you are considered teachable by your peers, mentors, and managers. Not only will it improve your career but it will lead to a happier life as you continue to learn and grow. Episode Breakdown Characteristics of an Unteachable Person An unteachable person doesn’t want to grow or learn because they don’t think they need any improvement. Sometimes this is from arrogance but a lot of the time it comes from knowing a lot and not realizing there is more to learn. Ignorance An unteachable person won’t expose themselves to new thoughts or experiences that will challenge what they “know” to be the truth or the “best and only” way to do something. They think they already know all there is to know about a topic or that they know enough and do not need or have time to learn more. The unteachable person doesn’t take notes or ask questions in training sessions (unless it is to profess their own knowledge) and are basically unengaged in learning environments. Pride Beyond just being shy or not wanting to bother a more experienced developer, the unteachable person won’t seek guidance even when they are stuck or need help on something like legacy code where the author is still employed there. They refuse to ask any questions that might make them look uninformed or inexperienced, which in turn makes them look even more inexperienced. There are two types of unteachable coders, the one has never heard of StackOverflow whereas with the other all of their code is copy/pasted from there. Arrogance An unteachable person refuses to be wrong or even admit the possibility they might not be right, they attempt to justify their thoughts or actions to the point of giving obvious excuses. The unteachable will refuse to accept any form of criticism and many times will become defensiveness when you try to correct them. They must win (or at least to not lose) every argument to the point of refusing to give up or walk away until they have the “last word.” Characteristics of a Teachable Person A teachable person desires to learn and grow even when they are an expert on a subject. They are humble about their knowledge and don’t let it get in the way of their ability to learn more. Values Learning The teachable person’s greatest enemy is the knowledge they have already gained. Thinking they already know something means that a person doesn’t have anything more to learn. For the teachable person learning is more that just an accumulation of knowledge, so no matter how much knowledge they have there is more to learn. The purpose of learning is to be able to act on what was learned, not for the pure knowledge that comes from learning. If a person doesn’t act on what they have learned, then they have not truly learned anything. High Curiosity Quotient A teachable person has an almost unrelenting drive to learn new information and gain new knowledge, they are life-long students. They constantly seek out new worlds and new opportunities, going where no person has gone before. Star Trek jokes aside, the teachable person is highly curious, always looking for new things to learn. The teachable person energetically seeks facts, while Wikipedia rabbit trails can cost them time they are always asking questions and looking up the answers. Humility The teachable person sees everyone as a teacher or mentor and can learn from them no matter their current situation in life. Humility creates the opportunity for learning; it occurs when a person accepts criticism from others even peers and those junior. The teachable person takes responsibility for their mistakes whether they are pointed out by others or noticed on their own. Failure is never easy, yet a teachable person admits failure and sees it as a learning experience with knowledge to be gained so they do not fail in the same way again. Mentors The most successful and most teachable people have built relationships with those who have higher levels of knowledge and expertise and are willing to share that with them. To the teachable person, the value of personal experience and a relationship with someone who has gained that experience through years in the field far outweighs the vast plethora of cold facts that can be found with the right Google search. Teachable people also mentor others, many have gained great knowledge through their insatiable curious learning and great wisdom through the application of this learning. They are not only willing but desire to share their knowledge and wisdom with other teachable people who seek their mentorship. Listening Skills A person is not listening nor learning when they are speaking, even people who do talk a lot can be good listeners if they use the time when they are not talking wisely. A teachable person listens attentively to others and only asks questions for clarification and understanding. They pay attention in training seminars taking detailed notes on the topic and ask clarifying questions or restate the point made in their own words to confirm understanding. Becoming Teachable In order to become teachable you have to accept that you do not know everything or even most things. To maintain that teachability you must keep the attitude and understanding that there is always more to learn. Develop Active Listening Skills “It takes two to speak the truth – one to speak and one to hear.” ~ Henry David Thoreau Active listening begins with preparation; remove distractions, focus on the person speak and what they are saying, and put any other thoughts out of your mind: focus completely on the speaker and what they are saying. Use silence to your advantage by seeking to understand before being understood, meaning listen first and explain later or not at all if not needed. Watch for non-verbal cues and wait for the person speaking to pause before you ask clarifying questions. When asking questions make sure they are relevant and used to ensure understanding, not to show your own knowledge of the subject. Summarize the main points the person speaking makes by reiterating them back in your own words allowing for the speaker to correct any mistakes you may have in understanding them. Learn the Learning Process Learning is a recursive process, the teachable person is not ever done learning they just have a deeper level or a new topic to apply to the learning process. The process starts by acting on what you have learned previously, this could be a new skill or a way to improve a skill you already have. Next evaluate your performance or how you did when acting on the new information that you’ve learned. Specifically look for mistakes that you may have made when acting on what you learned. Look for a better way to do the thing you are doing, use your mistakes to guide your learning. This may be learning how to improve an existing skill or it may involve learning a new skill all together. Finally, call the learning function passing in the new information. The learning process is a cycle and now that you’ve learned from your mistakes on the previous action it’s time to act again. This facilitates the next learning process. Find Teachable Moments Learning is not relegated to training sessions and educational seminars. Opportunities to learn are in everyday situations all the time. To truly be teachable view every conversation and every problem you solve as an opportunity to learn something new or gain a new skill. For the teachable learning isn’t a passive skill that you watch for but something active. Seek out and plan for teachable moments. Take charge of your learning by reading books and blogs, attend conferences (virtual these days), and spend time around people who inspire you to grow and stretch your own understanding. Make Teachable Moments Count It takes more than just seeking teachable moments, if you are not careful you can miss the whole point of what you are learning by not putting it into action. Many people will attend a fascinating training session or conference talk but never apply what they learned because they “can’t do it at work” and don’t do it on their own. For these people the focus is on the learning event and not on the process of learning. That process starts with action and ends with the learning event because the learning is to facilitate the action. When in a learning event such as a conference talk take active notes detailing the actions you need to take such as changes to be able to apply what you are learning, where the best place to apply the lessons are, and what do you need to share with your team or management. Immediately after the event (training session or conference talk) make a to-do list based on what you learned and the notes taken. Schedule a followup on your notes so that you take action. Use Self-Reflection to Ask if You Are Teachable To maintain the teachability you have to ask yourself regularly, “Am I teachable?” or “Am I still teachable?” In his article on teachability, John Maxwell lists out ten questions that you need to regularly ask yourself in order to maintain teachability. Answering “no” to any one of these questions means that you have areas that need improvement in your ability to be teachable. Answering “no” to several of these does not mean that you are not teachable, just that you have work to do to improve your teachability. It means that you have things to learn and be taught. Links Join Us On Patreon Level Up Financial Planning Teachability Characteristics of a Teachable Person John Maxwell Forbes Inc Ways To Be More Teachable Editor’s Notes: The post Becoming Teachable appeared first on Complete Developer Podcast.
59 minutes | 2 months ago
Dependencies in Unit Testing
Unit tests are a great way to make sure that your code is more stable. Not only do they let you check your assumptions when you make changes, but they also tend to force you to structure your code in a way that keeps it cleaner. As you get more test coverage, this pays off by making it easier to do larger reorganization of your code with less fear of breakage. The cleaner structure can also make it easier to diagnose problems in the code without doing a bunch of manual tracing. Finally, unit tests can serve as a bit of “living documentation” for the expectations around your code, which can often make it easier for newer developers to pick it up. However, the previous advantages are something you will only enjoy so long as your code doesn’t interact with a file system, database, network, third party app, or physical hardware. Each of these situations can introduce intermittent errors, limits to the number of calls you can execute, interference from state changes, and they all will generally slow down your tests. As you get more tests, these disadvantages pile up and make it less likely that unit tests will be run, because they become time consuming and unreliable. Fortunately, because we are talking about unit tests, it’s expected that you are only testing how your code reacts to different conditions, rather than testing underlying conditions that may not be reliable. This means that you can effectively “fake” a dependency in such a way that your tests only touch the code that you are trying to test. Moreover, if you do it right, this approach can also make your tests faster, which makes your team more likely to run them in the first place. Managing dependencies in unit tests is something you pick up over time. Like most other code, your approach to dependencies in a unit test scenario should start with something simple and only add complexity when it is valuable and necessary. Episode Breakdown Working with Dependencies in Unit Testing Unit tests versus other types of tests It’s probably necessary at the start to explain the difference between unit tests and other test types, simply because a lot of so-called “unit tests” are anything but. A “unit test” tests a single, logical unit of code, not including its dependencies. It’s intended to be fast, to only have its results change based upon the way that the code works, and to make it easy to determine where and why a failure occured. An integration test tests the way that multiple pieces of code work together. It’s intended to be a bit slower, more vulnerable to latency, and most importantly, to test how several pieces of code work together. It may be harder to troubleshoot than a unit test and it WILL almost certainly run slower. A performance test tests how a system responds to load, how quickly a process can run, and how resources are used by the process. Generally, this is done over several components, although sometimes you will see single-unit performance benchmarking in the wild. Functional Tests focus on the business requirements of the application being tested. They only check final outputs, rather than intermediate steps. End-to-End tests attempt to replicate the behavior of a user on a system and make sure that longer workflows work properly. Why dependencies make things difficult. Dependencies introduce latency. Making calls to real dependencies will slow down your unit tests, sometimes drastically. Dependencies introduce breaking changes that aren’t relevant to your tests. Dependencies may change under the hood, causing your test to fail, even if the actual code being tested is not the issue. While it’s helpful to catch this, it’s annoying to troubleshoot. Dependencies can introduce intermittent errors to your code. If the dependency itself has some kind of limits (or worse, if it deals with hardware), it may periodically “flake out”. This could be due to anything from a temporary network issue to a drive being full or a service limit being reached. Dependencies themselves have their own dependencies, some of which may be hard to discern. While you do need to make sure that these things work, it’s extremely wasteful to do so while you are rapidly iterating on your own code. You may not even be able to perform a reasonable test of dependencies in your code from your development machine. This is especially common when you are using third party services, such as payment processors, that have onerous security restrictions around them. Why dependency injection and polymorphism matters. If you are using dependency injection, you request an instance of an object from a container that knows how to build it. This keeps you from making your code overly coupled to the types that it uses, rather than just their interface contracts. Polymorphism is important here, because it allows you to swap out a different implementation of the same interface contract in different situations. Taken together, these two techniques can make it much easier to isolate the code under test, without your tests having to deal with any complexity due to the dependencies of your code. This can also make it a lot easier to create unlikely or difficult scenarios that your dependencies may create in the wild, in a predictable manner. This can make it much easier to test how your code will react in less likely scenarios, such as service outages. Understanding Test Doubles When explaining the types of test doubles, we’ll be taking the case of a UserRepository that allows searching, sorting, filtering, adding, updating, deleting, etc. of a set of users. The real thing would use a database, but the test double avoids that problem. In a real world situation, you start with a stub and continue to add complexity only when it serves the purposes of the test. Stubs Extremely lightweight. Returns predefined outputs regardless of inputs. A good example of this for a UserRepository would be one where the FindUsers method returns the same set of data, regardless of the filter criteria passed in. Fakes Like a stub, but can change behavior based on input. Can mimic all possible behaviors base on input. A good example of this for a UserRepository would include several different static sets of users that are returned under different filter criteria. Note that because you are not using the real implementation, this is a good place to have certain incoming data values that trigger a certain type of result. For instance, user ids that are divisible by 10 could return an administrative user while others return regular users. Spy An advanced version of a fake which is stateful. This can be used for things such as retry logic or for determining that a method was called multiple times. An example of this for a UserRepository would be where the repository returns a static set of items, but removes an item from that set if you delete it in order to mimic behavior. Note that you are again not using the real behavior, that this means you can also track the frequency of calls to the code under test, which is useful if a particular method is costly in some way. Mock Like a spy, but with more flexibility. Behavior can be changed dynamically based on scenarios. Gives full control over the the behavior of the mocked objects, including objects that the mock returns. For a UserRepository, you might use a mock when you want certain user ids to return different kinds of users, users in particular states, or different kinds of errors. The logic for this can get very complex very quickly, and you probably don’t want to use a mock right off the bat. You may be forced to set things up specifically in the order that the caller will invoke this components as well, making your tests brittle. Using Test Doubles Why not always use Mocks/Spies/Fakes? Tests become more complex and brittle the more complex you get. Tests become harder to read. Tests can become overly dependent on the code under tests. Tests may not give useful diagnostic criteria on the reasons for failure. The more complex the test scenarios are, the longer they take to write, and the more maintenance is required when you make changes. Use cases for each of these. Stub – you are starting out, testing the happy path, and just want to get some semi-realistic data back to see that the basics are covered. Fake – rather than just the happy path, now you need to test a few simple scenarios that require variation in output based on input. Spy – You’ve started testing things that can change state and you need to be able to assert that certain methods were called, and how often they were called. Mock – You are testing complex scenarios that may involve error states, complex workflows, or annoying interface designs. Why to avoid doing any of this? Sometimes test doubles are harder than other approaches. When you can’t create a test double for a dependency due to the way it is implemented. This is common for sealed types or cases where dependency injection is not being used. You are doing something other than a unit test. If you aren’t trying to isolate the code under test, then you probably don’t need a test double. The interface you are working with is “syntax magic” over the top of the REAL dependency (fluent interface sitting over a DbSet in Entity Framework, for instance). You may want to mock the underlying thing and use the real version of the interface to avoid headaches. Tricks of the Trade Be watchful of how you say things to people. You may mean one thing but it be interpreted as something different. This is especially true in todays world of remote work where most communication is via text so intonation and emphasis aren’t available. Sarcasm is definitely not your friend here. Even when you are on a call or in person you don’t know what the other person has going on or the conversations they may have had before you spoke to them. Links Join Us On Patreon Level Up Financial Planning The post Dependencies in Unit Testing appeared first on Complete Developer Podcast.
62 minutes | 2 months ago
Staying Calm In Stressful Situations
Stress leads to mistakes, increases in bug reports, and pull requests not being accepted. When under stress we don’t perform at our optimum. We tend to focus too much on the problem and not how to solve it or what to do to reduce the issue if it can’t be solved right away. In times of high stress people tend to regress to behaviors used in childhood when facing an emotional threat. For some this may be running and hiding under the bed whereas for others it means getting defensive and arguing. To the uninitiated the ability to stay calm in stressful situations appears as an inborn trait that only a select group of people possess. However, science, specifically the science of the brain, has shown evidence that remaining calm under pressure is a skill that can be learned. Stress can be motivating or debilitating. Some people naturally thrive under pressure, they wait until the last possible minute to get their work done because they enjoy the challenge. Others have learned how to work under strain because they have found themselves in that situation and have a desire to succeed or they take on more than they can handle and either have to fail or learn to be successful under stress. No matter the reason, there will be times you find yourself in a stressful situation. Use these techniques to not only survive the situation but to be ready for when it comes and you will be able to thrive even in a stressful environment. Episode Breakdown Understanding Your Response to Stress Do You Fight or Do You Flight? When under stress our bodies go into an acute stress response also known as fight or flight. This is a physiological reaction to a perceived threat, real or not, that involves the sympathetic branch of the autonomic nervous system. Physical symptoms of an acute stress response can include dilated pupils, tunnel vision, dry eyes, pale or flush skin, sweating, increased heart rate, quick, shallow breathing, dry mouth, and muscle tension. Emotional manifestations include but are not limited to fear, anxiety, and aggression. When under stress people have shorter fuses and tend to react rather than respond. Since many times these reactions are not appropriate for the stress inducing situation (public speaking for example) the body doesn’t get a release and can end up in a feedback loop that creates chronic issues (such as depression, heart disease, GI disorders, and lots more) due to sustained stress response. Understand the biochemistry behind stressful feelings. The human body is a system of checks and balances that regulates itself through feedback loops. Long term stress can create or occur because of a dysregulation of the system designed to prepare you for dealing with dangerous situations. Your amygdala is the part of the brain that recognizes danger and releases hormones that tell hypothalamus to get ready. The hypothalamus then signals the pituitary gland to release hormones that then have the adrenal gland (on top of the kidneys) to release cortisol. Cortisol sometimes gets a bad rap as the “stress hormone” when in reality it is the over stimulation of the adrenal glands or too much cortisol that is the problem. In the right amounts cortisol helps to regulate blood pressure, reduce inflammation, regulate your blood sugar, and boosts energy when needed. Label the emotions you are feeling. In order to avoid a reaction that could get you into trouble or issues with chronic stress you need to break the feedback loop that is sustaining the stress. Psychological and neurological research has found that labeling emotions takes the stress inducing anxiety out of them and actually reduces the amount of stress hormones produced. By giving your emotions a name and a label you are taking back control of the situation. Many times stress comes from lack of control, labeling how you feel returns control to you. See stress as a way to highlight your values. Another thing that stress can do is to show you where you place your values or what is important to you. If something is not important you will not be stressed about making sure it goes well, but if you care about something such as your career then you may stress about giving a presentation at work. When you experience the signs and symptoms of a stress reaction, after you’ve labeled your emotions and know what is going on, ask yourself what your body is telling you or what is it about this situation that you care about. Knowing this about stress can not only help you identify areas of value, but also help you to know when you may have stressful events coming up so that you don’t overload them. For example, if you have a crush on someone and care about your career you might not want to schedule a first date the night before a job interview. Prepare Ahead of Time Take care of your body. Environment is one of the biggest variables in determining behavior. Different environments are set up for different types of success, you don’t go to a NASCAR race to try and study biochem just like you wouldn’t go to a library to practice Skillet songs on your guitar. Your body is the immediate environment of your brain so you want create an internal environment promoting healthy responses to stress. To prepare your body you need to look at what you put in, what you put out, and how you recuperate. “You are what you eat” may be a bit cliche, however what you eat does affect who you are and can even affect how you respond to stress. Exercise reduces stress! Bottom line here, there’s no way around it, being active is going to set you up to better handle stressful situations. A lot of people think they are too stressed or have too much to do to exercise, yet making the time to get some activity in each day will reduce stress and anxiety so that you are better able to focus during working hours. How you sleep is much more important than how much you sleep. Eight hours is a recommendation based on average sleep patterns, however some people need more or less. The idea is to get the most out of sleep by maximizing your time in REM or deep sleep. Cultivate an attitude of gratitude. Gratitude means having a readiness or willingness to thank someone, return a kindness, or show appreciation. Research by Robert Emmons of the University of California Davis found that practicing gratitude significantly reduced levels of cortisol, some even by up to 23% of previous levels. Another study at UCLA’s Mindfulness Awareness Research Center found increased levels of mood elevating neurotransmitters such as serotonin and dopamine when subjects practiced gratitude. Having an attitude of gratitude means turning this willingness to thank someone or to show appreciation into a regular thing, make a positive habit out of it. To start working toward this habit spend some time each day writing in a “gratitude journal” the things that you are thankful for that particular day. Train your mind. Just like you can train your muscles by lifting weights you can train your mind through meditation. More than just sitting cross-legged and saying “Ohm!”, meditation can involve active imagery, progressive relaxation, breath awareness, and even body movement such as yoga or TaiChi. Training your mind improves vagal tone, or the strength of the vagus nerve which is part of the parasympathetic branch of the autonomic nervous system…the part that works opposite the sympathetic. A study at Harvard even showed growth in the hippocampus, the area of the brain that regulates emotion, and reduced volume in the amygdala. What to do in the moment Use breathing techniques to take back control. Interrupt the feedback loop that increases stress by forcing your body to behave as if it were not stressed. Deep breathing is the opposite of what your body is expecting when the sympathetic nervous system is active since it is preparing for quick shallow breaths. Consciously taking deep breaths that involve your diaphragm will stimulate a parasympathetic response that acts to calm down the stressful feelings. To do this slowly breath in until you feel you abdomen rising then exhale even slower than you inhaled, count while breathing and try to get yourself to where your exhales are twice as long as the inhales. Reset your focus on solutions, don’t catastrophize. Instead of focusing on the problem that is causing the stress look to the solution to that problem, be it working overtime, asking for help when you are over your head or stuck, or even finding a new job. Realistically looking at the worst case scenario can help you to put the stressful situation into perspective. Understand that there will be things that you cannot control such as your boss, coworkers, or even the traffic on the way into work on the morning of an important meeting. Focus on what you can control, so if you know you have an important meeting in the morning get to bed early and then set your alarm to go off well before you need to be up and if going into the office leave with more than enough time to get there. Set yourself up for success. When stressors come randomly or unexpectedly, like a sudden major issue in production, start with finding the things you can do to mitigate the situation then look at the more difficult or near impossible tasks. Re-label your emotions. Now that you know what it is you are feeling you can break the emotional side of the feedback loop by re-labelling and changing the meaning of the emotions you have already identified. A researcher at the National Institute of Mental Health (NIMH), Esther Sternberg, recommends renaming the emotions to change the connotation from negative to positive. In this method fear would become anticipation, worry would instead be concern, dread is seen as caution, flustered is another way of being excited, and alarmed is just a cautious curiosity. By renaming your emotions you take control of what you can in your brain and then convince the rest to follow suit. Using this successfully takes a little practice especially since at first it feels like you are trying to trick yourself into not being stressed. Tricks of the Trade Practice poverty. – Seneca Links Join Us On Patreon Level Up Financial Planning INC Stress.org Life Hack The post Staying Calm In Stressful Situations appeared first on Complete Developer Podcast.
59 minutes | 2 months ago
Antipatterns in Domain Driven Design
Per wikipedia, “DDD is the concept that the structure and language of software code (class names, class methods, class variables) should match the business domain.” Essentially the idea is that the code and the business logic that it implements will have a shared vocabulary that makes communication between the developers and the stakeholders easier by moving implementation details out of the code that handles business logic. The primary focus of the application is on the core domain and its domain logic. Designs are based on a model of the domain, rather than on a model of the implementation details (such as database structure) that is required to support the domain. This approach allows rapid iteration involving both the domain experts and the development team. It also makes it quicker and easier to onboard developers, as they can look at the code to understand business rules. DDD has a few core principles that are observed. Until you really get very deep into, a useful way to think about it is that it is the application of OOP to business rules. While this is not entirely accurate, it is how you end up with most of the anti-patterns we are about to discuss. Most of these problems really arise because developers have halfway implemented DDD, but haven’t taken it as far as they need to in order to be able to reap all the benefits. If you work for a company that is trying to use DDD, but hasn’t quite internalized all the lessons of it, you’ll probably run into one or more of these anti-patterns as you go through their codebase. It’s important to remember that they at least tried and got part of the way. You simply need to get them the rest of the way to successfully using this excellent approach to building software. Episode Breakdown Primitive obsession Primitive obsession occurs when language primitives (such as strings, integers, etc.) are used instead of small objects for simple tasks. Because the validation and rules around the type aren’t sufficient for your use case, you’ll have to add more rules that live outside the object. A good example of this is using a string for an email address. While email addresses are definitely strings, not all strings are email addresses. This makes it possible for an invalid email address to be set, and also means that you have to keep the validation around email addresses somewhere else. Create custom types (often value objects) to encapsulate the types you are trying to express in code. Include validation logic with the type. You will likely have to make conversions between the primitive type and your type at the edges of your system. This would include API endpoints, database, and file interactions which are not part of your core business rules. Anemic domain models An anemic domain model occurs when entities are built as simple bags of readable properties. This forces the entity logic into other locations in the code. The entities define little or no behavior themselves and can be put into a bad state from outside themselves. An example of this might be a Person object with name, address, phone number etc. on it. If someone wants to change the address, they either interact directly with the properties on the object itself, or make a call to an object that does it for them. This could mean that the object ends up in an invalid state, for instance, if the city in the address was changed, but the postal code was not. Remove setters on public properties, then create methods for discrete actions on the entity to replace what callers were doing. Alter the callers to use these methods. Get rid of empty constructors and create parameterized ones that initialize the entity in a valid state. You’ll probably find that some callers are difficult to refactor, because they orchestrate changes over a set of entities. You may also have issues around constructors if your framework of choice initializes objects for you and expects empty constructors. ID leakage Entities in a system should know their identifiers. Objects that need to retrieve those entities should know about the IDs. Other entities should have references to the entity instead of the ID. Otherwise they will be forced to interact with the persistence layer when they need the entity. For instance, let’s assume you have a Invoice entity that contains a set of line items, each of which have an InventoryItemID on them. If you are trying to determine how much the entire order weighs, you’ll have to pull in the InventoryItems by their IDs, which means that your entity layer is now overly coupled to your persistence layer. Replace ID references with references to the actual entity. Lazy load if necessary for performance. This can be interesting if the object being referenced is large or takes a lot of time to load, as it can cause performance issues. You may have to slightly bend the rules of DDD in order to get good performance. Entanglement between commands and queries The concerns between the “write” side of an application and the “read” side of an application are not the same. The command (write) side probably needs access to the entire entity model. The query (read) side only needs parts of the entity and related entities. If you entangle the two sides, you’ll either have very slow reads due to bringing back too much data, or your writes won’t have all the data they need. Let’s say that you have the Invoice and LineItem entities in a model as before, with the LineItems also having a reference to the InventoryItem to which they are tied. If you have the command and query side entangled, a query to get the invoice totals for the last year means loading EVERYTHING under the invoices, even if that doesn’t make sense. Queries should generally not load up the entity model. They are simply a projection off of the entity model that is tailored to what is required by the caller. This can collide in a bad way with the way many developers misunderstand DRY. Devs will want to reuse the code that loads an entity up for query purposes, even though these are two entirely disparate reasons for loading the data. This will tangle your command and query infrastructure up in a bad way and hurt performance. Lack of bounded contexts Sometimes an entity is used in very different ways by different parts of a system. An Order entity, for instance, looks very different from the Inventory side of things than it does for fulfillment or billing. A naive implementation might tie these two concepts together in such a way that a change in either area impacts the other negatively. Let’s assume you have an Order entity that is used by your warehouse inventory system, your fulfillment system, and your billing system. Your billing system and warehouse management system change due to expanding your company into other countries, and your billing system is forced to change due to tax law changes. If it’s all the same entity, it’s all the same project, which could mean expensive compromises on your warehouse/fulfillment systems due to regulatory compliance issues on the billing system. Use bounded contexts so that a multi-faced entity is broken into multiple logical entities for each of the business contexts you are trying to handle. Keep their functionality separate. This can be brittle if your organizational structure is still unstable, or if you had a single context entity that got huge and entangled. The latter is especially nasty politically, because it’s hard to show a business value for rewriting working code until that code is already costing money by causing problems. By then, you are getting blamed for the problems. Implementation driving the domain model Your domain model should be broken up based on the business model, not based on the database structure. This may mean that a single entity spans multiple tables, that inheritance is in the mix, or even that attributes are loaded/saved from disparate data sources. In a fulfillment system you have an Order entity, but there are two subtypes, OnlineOrder and PhysicalOrder, which refer to how those orders are processed and delivered. However, because you have multiple tables in the mix, the OnlineOrder and PhysicalOrder are separate types with references to their base Order, which represents another table. Essentially this is an active record model. The model structure cannot change independently from the persistence structure. Separate storage from the entities being stored. You might have some that belong to a single table, and you might not, but the table structure is completely irrelevant. This can be interesting with some ORMs because they do a poor job of handling relationships within a single entity, especially with inheritance in the mix. Exposing entities at the edge Your domain model should live in an inner ring of your app and shouldn’t go outside of it. You have an order type, with line items, etc. under it. An advisory is suddenly required by law for certain kinds of items in certain contexts. If you are exposing the full entity at the edge, this change will break the interface contract for callers. Convert entities to DTOs before sending them over the wire to a caller or to another system. This gives you another layer where you can decouple your implementation from that of the client. If you do this, be sure and have good testing around the conversion to (and possibly FROM) DTOs, as this is another place where you can easily forget something important. Transit of invalid state An entity should always be in a valid state, never an invalid one. This includes just after deserialization, construction, and while changes are being made to it. Invariants should be enforced across the lifetime of the object. You have an order entity (noticing a pattern here?) and your system expects the Total value to never be negative. Due to adding coupons to the system, however, a situation arises where the order total is negative. Rather than being caught, the errors are saved to the database and only caught 20 days later when the accountants notice a discrepency in the books. Don’t have public setters. Always have methods that change state and coordinate the changing of multiple properties, based on logical criteria. For instance, in the previous method, rather than simply adding a coupon item with a negative value to decrease the total, you might create an ApplyCoupon method that applies a coupon up to the point where the total is zero. This sounds easy to accomplish, but sometimes ORMs will get in your way due to constraints on constructors. This can also be an issue if older records were valid under a certain set of conditions and newer ones are not. You will have to figure out how to mitigate this. Mutable value objects Like entities, value objects should enforce their invariants during their lifetime. However, because they may be passed around among entities, they also shouldn’t support changes in state, as that adds a lot of low value complexity. Imagine a situation where you have a system that has a directory of people with their addresses. You also keep track of marriages. When someone gets married, your system has a place to match the spouse’s addresses. If Address is a value type and you allow its contents to be changed, you either risk the spouse addresses getting out of sync or you have to write a bunch of code to keep them in sync. Extract reusable sets of fields into value types. Make them immutable. Always point to the same instance when you mean the same set of values. This can be tricky if you are using an ORM that doesn’t support immutable value types, because you may get multiple instances for the same thing. However, if your language allows you to override the equality operator, you may be able to get around the problem by simply comparing the contents. Tricks of the Trade A lot of times we get upset at the wrong person or thing when something negative happens. Getting mad at a host because a restaurant is full or at your laptop because the Windows update broke something is an anti-pattern of problem solving. Instead of getting frustrated or acting out look for a solution to problems. It’s not easy, especially when emotions get involved so start just with recognizing that you are upset and then work to identify the source of the problem. Links Join Us On Patreon Level Up Financial Planning The post Antipatterns in Domain Driven Design appeared first on Complete Developer Podcast.
56 minutes | 2 months ago
OWASP Top Ten API Vulnerabilities
APIs or Application Programming Interfaces are an important part of any modern web application. When properly designed they securely expose data to authenticated and authorized users. However, not everyone designs them the same, which is why OWASP came up with a list of the top security vulnerabilities to avoid. Read more › The post OWASP Top Ten API Vulnerabilities appeared first on Complete Developer Podcast.
59 minutes | 3 months ago
Dysfunctions of Successful Teams
Dysfunctions that you see in an established and successful team are often the result of doing things RIGHT for years or even decades. Read more › The post Dysfunctions of Successful Teams appeared first on Complete Developer Podcast.
52 minutes | 3 months ago
Understanding Fear
Fear is something we all face from time to time. It can be a motivating factor or debilitating. Your understanding and how you handle fear determines which one. Read more › The post Understanding Fear appeared first on Complete Developer Podcast.
57 minutes | 3 months ago
Logical Fallacies: Omission and Ambiguity
The third and final episode in our series on logical fallacies delves into improper use or rhetoric. Both Fallacies of Omission and Fallacies of Ambiguity are used to redirect an argument away from the topic at hand or evidence that might disprove one side. Read more › The post Logical Fallacies: Omission and Ambiguity appeared first on Complete Developer Podcast.
61 minutes | 3 months ago
Backward Compatibility
We've all had the experience of trying to use a piece of software, library, API, or database, only to have it fail miserably because something changed in a recent update. Not only are such changes disruptive, but because they often require rewrites, they can leave us looking for an alternative. Read more › The post Backward Compatibility appeared first on Complete Developer Podcast.
55 minutes | 4 months ago
Your Most Effective Work Times
Whether you are an early bird or night owl, your sleep chronotype or best time to get rest affects how productive you can be. Understanding this and how to manage your time will help improve your productivity and job satisfaction. Read more › The post Your Most Effective Work Times appeared first on Complete Developer Podcast.
60 minutes | 4 months ago
Leveraging Legacy Technology
While working with legacy tech can be a dead end if you let it, there are some things you can do to make the experience beneficial for your career. Read more › The post Leveraging Legacy Technology appeared first on Complete Developer Podcast.
51 minutes | 4 months ago
Logical Fallacies: Component Fallacies
Part two of our series on logical fallacies gets into the form of the argument. These formal fallacies may contain correct information or premises but the order or form of the argument is incorrect. Read more › The post Logical Fallacies: Component Fallacies appeared first on Complete Developer Podcast.
50 minutes | 4 months ago
Schrodinger’s Cache
We've all been there. A webpage that was working stops working, or one that was broken suddenly starts working without any obvious changes. If you've had this happen, one of the first things you should probably suspect is a caching issue. Read more › The post Schrodinger’s Cache appeared first on Complete Developer Podcast.
65 minutes | 4 months ago
Complete Developer Network
When we started Complete Developer Podcast we never expected it to grow into what we have today. It's been 5 years since we published our first episode back when we were recording with one Blue Yeti mic between the two of us. Read more › The post Complete Developer Network appeared first on Complete Developer Podcast.
COMPANY
About us Careers Stitcher Blog Help
AFFILIATES
Partner Portal Advertisers Podswag
Privacy Policy Terms of Service Do Not Sell My Personal Information
© Stitcher 2020