This is part 2 of a small series about code smells and possible refactorings. The target audience I had in mind are newbies who heard about this topic and who maybe wanted to wait a bit before entering these advanced waters. The following article covers “Feature Envy”, “Shotgun Surgery” and “Divergent Change”.
What you’ll quickly realize with code smells is that some of them are very close cousins. Even their refactorings are sometimes related—for example, Inline Class and Extract Class are not that different.
With inlining a class, for example, you extract the whole class while you get rid of the original one. So kinda extract class with a little twist. The point I’m trying to make is that you shouldn’t feel overwhelmed by the number of smells and refactorings, and certainly shouldn’t get discouraged by their clever names. Things like Shotgun Surgery, Feature Envy and Divergent Change might sound fancy and intimidating to people who just got started. Maybe I’m wrong, of course.
If you dive a little into this whole topic and play with a couple of refactorings for code smells yourself, you’ll quickly see that they often end up in the same ballpark. A lot of refactorings are simply different strategies to get to a point where you have classes that are concise, well organized, and focused on a small amount of responsibilities. I think it’s fair to say that if you can achieve that, you’ll be ahead of the pack most of the time—not that being ahead of others is so important, but such class design is simply often missing in code from people before they’re considered “experts”.
So why not get into the game early and build a concrete foundation for designing your code. Don’t believe what may be your own narrative that this is an advanced topic that you should put off for a while until you’re ready. Even if you’re a newbie, if you take small steps you can wrap your head around smells and their refactorings a lot earlier than you might think.
Before we dive into the mechanics, I want to repeat an important point from the first article. Not every smell is inherently bad, and not every refactoring is always worth it. You have to decide on the spot—when you have all the relevant information at your disposal—if your code is more stable after a refactoring and if it’s worth your time to fix the smell.
Let’s revisit an example from the previous article. We extracted a long list of parameters for #assign_new_mission
into a parameter object via the Mission
class. So far so cool.
M with feature envy
class M def assign_new_mission(mission) print "Mission #{mission.mission_name} has been assigned to #{mission.agent_name} with the objective to #{mission.objective}." if mission.licence_to_kill print " The licence to kill has been granted." else print " The licence to kill has not been granted." end end end class Mission attr_reader :mission_name, :agent_name, :objective, :licence_to_kill def initialize(mission_name: mission_name, agent_name: agent_name, objective: objective, licence_to_kill: licence_to_kill) @mission_name = mission_name @agent_name = agent_name @objective = objective @licence_to_kill = licence_to_kill end end m = M.new mission = Mission.new(mission_name: 'Octopussy', agent_name: 'James Bond', objective: 'find the nuclear device', licence_to_kill: true) m.assign_new_mission(mission) # => "Mission Octopussy has been assigned to James Bond with the objective to find the nuclear device. The licence to kill has been granted."
I briefly mentioned how we can simplify the M
class even more by moving the method #assign_new_mission
to the new class for the parameter object. What I didn’t address was the fact that M
had an easily curable form of feature envy as well. M
was way too nosy about attributes of Mission
. Put differently, she asked way too many “questions” about the mission object. It’s not only a bad case of micromanagement but also a very common code smell.
Let me show you what I mean. In M#assign_new_mission
, M
is “envious” about the data in the new parameter object and wants to access it all over the place.
In addition to that, you also have a parameter object Mission
that is only responsible for data right now—which is another smell, a Data Class.
This whole situation tells you basically that #assign_new_mission
wants to be somewhere else and M
doesn’t need to know the details of how missions get assigned. After all, why wouldn’t it be a mission’s responsibility to assign new missions? Remember to always to put things together that also change together.
M without feature envy
class M def assign_new_mission(mission) mission.assign end end class Mission attr_reader :mission_name, :agent_name, :objective, :licence_to_kill def initialize(mission_name: mission_name, agent_name: agent_name, objective: objective, licence_to_kill: licence_to_kill) @mission_name = mission_name @agent_name = agent_name @objective = objective @licence_to_kill = licence_to_kill end def assign print "Mission #{mission_name} has been assigned to #{agent_name} with the objective to #{objective}." if licence_to_kill print " The licence to kill has been granted." else print " The licence to kill has not been granted." end end end m = M.new mission = Mission.new(mission_name: 'Octopussy', agent_name: 'James Bond', objective: 'find the nuclear device', licence_to_kill: true) m.assign_new_mission(mission)
As you can see, we simplified things quite a bit. The method slimmed down significantly and delegates the behaviour to the object in charge. M
does not request mission data specifics anymore and certainly stays away from getting involved in how assignments get printed. Now she can focus on her real job and doesn’t need to be disturbed if any details of mission assignments change. More time for mind games and hunting down rogue agents. Win-win!
Feature envy breeds entanglement—by that I don’t mean the good kind, the one that lets information travel faster than light spookily—I’m talking about the one that over time might let your development momentum grind to an every more approaching halt. Not good! Why so? Ripple effects throughout your code will create resistance! A change in one place butterflies through all kinds of stuff and you end up as a kite in a hurricane. (Ok, a bit overly dramatic, but I give myself a B+ for the Bond reference in there.)
As a general antidote for feature envy, you want to aim for designing classes that are concerned mostly about their own stuff and have—if possible—single responsibilities. In short, classes should be something like friendly otakus. Socially that might not be the healthiest of behaviours, but for designing classes it often is a reasonable guideline to keep your momentum where it should be—moving forward!
The name is a little bit silly, isn’t? But at the same time it’s a pretty accurate description. Sounds like serious business, and it is! Luckily it’s not that hard to grasp, but nonetheless it’s one of the nastier code smells. Why? Because it breeds duplication like no other, and it’s easy to lose sight of all the changes you’d need to make to fix things. What happens during shotgun surgery is you make a change in one class/file and you also need to touch many other classes/files that need to be updated. Hope that doesn’t sound like a good time you’re in for.
For example, you may think you can get away with one little change in one place, and then realize that you have to wade through a whole bunch of files to make either the same change or fix something else that is broken because of it. Not good, not at all! That sounds more like a good reason why people start to hate the code they’re dealing with.
If you have a spectrum with DRY code on one side, then code that often needs shotgun surgery is pretty much on the opposite end. Don’t be lazy and let yourself enter that territory. I’m sure you’d rather open one file and apply your changes there and be done with it. That’s the kind of lazy you should strive for!
To avoid this smell, here’s a short list of symptoms you can look out for:
What do we mean when we talk about code that is coupled? Let’s say we have objects A
and B
. If they are not coupled then you can change one of them without affecting the other. Otherwise you’ll more often than not also have to deal with the other object as well.
This is a problem, and shotgun surgery is a symptom for tight coupling as well. So always watch out for how easily you can change your code. If it’s relatively easy it means that your level of coupling is acceptably low. Having said that, I realize that your expectations would be unrealistic if you expect to be able to avoid coupling all the time at all costs. That’s not going to happen! You will find good reasons to decide against that urge—like replacing conditionals with Polymorphism. In such a case, a little bit of coupling, shotgun surgery and keeping the API of objects in sync is well worth getting rid of a ton of case statements via a Null Object (more on that in a later piece).
Most commonly you can apply one of the following refactorings to heal the wounds:
Let’s look at some code. This example is a slice of how a Spectre app handles payments between their contractors and evil clients. I simplified the payments a bit by having standard fees for both contractors and clients. So it doesn’t matter whether Spectre is tasked to kidnap a cat or extort a whole country: the fee stays the same. The same goes for what they pay their contractors. In the rare case an operation goes south and another Nr. 2 has to literally jump the shark, Spectre offers a full refund to keep evil clients happy. Spectre uses some proprietary payment gem that is basically a placeholder for any kind of payment processor.
In the first example below, it would be a pain if Spectre decided to use another library to handle payments. There would be more moving parts involved, but for demonstrating shotgun surgery this amount of complexity will do I think:
Example with shotgun surgery smell:
class EvilClient #... STANDARD_CHARGE = 10000000 BONUS_CHARGE = 10000000 def accept_new_client PaymentGem.create_client(email) end def charge_for_initializing_operation evil_client_id = PaymentGem.find_client(email).payments_id PaymentGem.charge(evil_client_id, STANDARD_CHARGE) end def charge_for_successful_operation evil_client_id = PaymentGem.find_client(email).payments_id PaymentGem.charge(evil_client_id, BONUS_CHARGE) end end class Operation #... REFUND_AMOUNT = 10000000 def refund transaction_id = PaymentGem.find_transaction(payments_id) PaymentGem.refund(transaction_id, REFUND_AMOUNT) end end class Contractor #... STANDARD_PAYOUT = 200000 BONUS_PAYOUT = 1000000 def process_payout spectre_agent_id = PaymentGem.find_contractor(email).payments_id if operation.enemy_agent == 'James Bond' && operation.enemy_agent_status == 'Killed in action' PaymentGem.transfer_funds(spectre_agent_id, BONUS_PAYOUT) else PaymentGem.transfer_funds(spectre_agent_id, STANDARD_PAYOUT) end end end
When you look at this code you should ask yourself: “Should the EvilClients
class be really concerned about how the payment processor accepts new evil clients and how they are charged for operations?” Of course not! Is it a good idea to spread the various amounts to pay all over the place? Should the implementation details of the payments processor be showing up in any of these classes? Most definitely not!
Look at it from that way. If you want to change something about the way you handle payments, why would you need to open the EvilClient
class? In other cases it could be a user or customer. If you think about it, it doesn’t make any sense to familiarize them with this process.
In this example, it should be easy to see that changes to the way you accept and transfer payments create ripple effects throughout your code. Also, if you wanted to change the amount you charge or transfer to your contractors, you’d need additional changes all over the place. Prime examples of shotgun surgery. And in this case we’re only dealing with three classes. Imagine your pain if a bit more realistic complexity is involved. Yep, that’s the stuff nightmares are made of. Let’s look at an example that is a bit more sane:
Example without shotgun surgery smell and extracted class:
class PaymentHandler STANDARD_CHARGE = 10000000 BONUS_CHARGE = 10000000 REFUND_AMOUNT = 10000000 STANDARD_CONTRACTOR_PAYOUT = 200000 BONUS_CONTRACTOR_PAYOUT = 1000000 def initialize(payment_handler = PaymentGem) @payment_handler = payment_handler end def accept_new_client(evil_client) @payment_handler.create_client(evil_client.email) end def charge_for_initializing_operation(evil_client) evil_client_id = @payment_handler.find_client(evil_client.email).payments_id @payment_handler.charge(evil_client_id, STANDARD_CHARGE) end def charge_for_successful_operation(evil_client) evil_client_id = @payment_handler.find_client(evil_client.email).payments_id @payment_handler.charge(evil_client_id, BONUS_CHARGE) end def refund(operation) transaction_id = @payment_handler.find_transaction(operation.payments_id) @payment_handler.refund(transaction_id, REFUND_AMOUNT) end def contractor_payout(contractor) spectre_agent_id = @payment_handler.find_contractor(contractor.email).payments_id if operation.enemy_agent == 'James Bond' && operation.enemy_agent_status == 'Killed in action' @payment_handler.transfer_funds(spectre_agent_id, BONUS_CONTRACTOR_PAYOUT) else @payment_handler.transfer_funds(spectre_agent_id, STANDARD_CONTRACTOR_PAYOUT) end end end class EvilClient #... def accept_new_client PaymentHandler.new.accept_new_client(self) end def charge_for_initializing_operation PaymentHandler.new.charge_for_initializing_operation(self) end def charge_for_successful_operation(operation) PaymentHandler.new.charge_for_successful_operation(self) end end class Operation #... def refund PaymentHandler.new.refund(self) end end class Contractor #... def process_payout PaymentHandler.new.contractor_payout(self) end end
What we did here is wrap the PaymentGem
API in our own class. Now we have one central place where we apply our changes if we decide that, for example, a SpectrePaymentGem
would work better for us. No more touching of multiple—to payments’ internals unrelated—files if we need to adapt to changes. In the classes that deal with payments, we simply instantiated the PaymentHandler
and delegate the needed functionality. Easy, stable, and no reason to change.
And not only have we contained everything in a single file. Within the PaymentsHandler
class, there is only one place we need to swap out and reference a possible new payment processor—in initialize
. That is rad in my book. Sure, if the new payment service has a completely different API, you need to tweak the bodies of a couple of methods in PaymentHandler
. It’s a tiny price to pay compared to full-on shotgun surgery—that’s more like surgery for a small splinter in your finger. Good deal!
If you’re not careful when you write tests for a payment processor like this—or any external service you need to rely on—you are possibly in for serious headaches when they change their API. They “suffer from change” as well, of course. And the question is not will they change their API, only when.
Through our encapsulation we’re in a much better position to stub our methods for the payment processor. Why? Because the methods we stub are our own and they only change when we want them to. That is a big win. If you’re new to testing and this is not completely clear to you, don’t worry about it. Take your time; this topic can be tricky at first. Because it’s such an advantage, I just wanted to mention it for the sake of completeness.
As you can see, I simplified payment processing quite a bit in this silly example. I could have cleaned the final result some more as well, but the point was to clearly demonstrate the smell and how you can get rid of it through abstraction.
If you’re not completely happy with this class and see opportunities for refactoring, I salute you—and am happy to take credit for it. I recommend you knock yourself out! A good start might be dealing with the way you find payments_id
s. The class itself also got a bit crowded already…
Divergent change is, in a way, the opposite of shotgun surgery—where you want to change one thing and need to blast that change through a bunch of different files. Here a single class is often changed for different reasons and in different ways. My recommendation is to identify parts that change together and extract them in a separate class that can focus on that single responsibility. These classes in turn should also have no more than one reason to change—if not, another divergent change smell is most likely waiting to bite you.
Classes that suffer from divergent change are ones that get changed a lot. With tools like Churn, you can measure how often particular parts of your code needed to change in the past. The more points you find on a class, the higher the probability that divergent change might be at work. I also wouldn’t be surprised if exactly these classes are the ones that cause the most bugs overall.
Don’t get me wrong: getting changed often is not directly the smell. It’s a useful symptom, though. Another very common and more explicit symptom is that this object needs to juggle more than one responsibility. The single responsibility principle SRP is an excellent guideline to prevent this code smell and to write more stable code in general. It can be tricky to follow, but nevertheless still worth the grind.
Let’s look at this nasty example below. I modified the shotgun surgery example a bit. Blofeld, head of Spectre, might be known to micromanage stuff, but I doubt he would be interested in half the stuff this class is involved with.
class Spectre STANDARD_CHARGE = 10000000 STANDARD_PAYOUT = 200000 def charge_for_initializing_operation(client) evil_client_id = PaymentGem.find_client(client.email).payments_id PaymentGem.charge(evil_client_id, STANDARD_CHARGE) end def contractor_payout(contractor) spectre_agent_id = PaymentGem.find_contractor(contractor.email).payments_id PaymentGem.transfer_funds(spectre_agent_id, STANDARD_PAYOUT) end def assign_new_operation(operation) operation.contractor = 'Some evil dude' operation.objective = 'Steal a boatload of valuable stuff' operation.deadline = 'Midnight, November 18th' end def print_operation_assignment(operation) print "#{operation.contractor} is assigned to #{operation.objective}. The mission deadline ends at #{operation.deadline}." end def dispose_of_agent(spectre_agent) puts "You disappointed this organisation. You know how Spectre handles failure. Good bye #{spectre_agent.code_name}!" end end
The Spectre
class has way too many different things it is concerned about:
Seven different responsibilities on a single class. Not good! You need to change how agents are disposed of? One vector for changing the Spectre
class. You want to handle payouts differently? Another vector. You get the drift.
Although this example is far from being realistic, it still tells the story of how easy it is to unnecessarily amass behaviour that needs to change frequently in a single place. We can do better!
class Spectre # ... def dispose_of_agent(spectre_agent) puts "You disappointed this organisation. You know how Spectre handles failure. Good bye #{spectre_agent.code_name}!" end end class PaymentHandler STANDARD_CHARGE = 10000000 STANDARD_CONTRACTOR_PAYOUT = 200000 #... def initialize(payment_handler = PaymentGem) @payment_handler = payment_handler end def charge_for_initializing_operation(evil_client) evil_client_id = @payment_handler.find_client(evil_client.email).payments_id @payment_handler.charge(evil_client_id, STANDARD_CHARGE) end def contractor_payout(contractor) spectre_agent_id = @payment_handler.find_contractor(contractor.email).payments_id @payment_handler.transfer_funds(spectre_agent_id, STANDARD_CONTRACTOR_PAYOUT) end end end class EvilClient #... def charge_for_initializing_operation PaymentHandler.new.charge_for_initializing_operation(self) end end class Contractor #... def process_payout PaymentHandler.new.contractor_payout(self) end end class Operation attr_accessor :contractor, :objective, :deadline def initialize(attrs = {}) @contractor = attrs[:contractor] @objective = attrs[:objective] @deadline = attrs[:deadline] end def print_operation_assignment print "#{contractor} is assigned to #{objective}. The mission deadline ends at #{deadline}." end end
Here we extracted a bunch of classes and gave them their own unique responsibilities—and therefore their own contained reason to change.
You want to handle payments differently? Now you won’t need to touch the Spectre
class. You need to charge or pay out differently? Again, no need to open the file for Spectre
. Printing operation assignments is now the business of operation—where it belongs. That’s it. Not too complicated, I think, but definitely one of the more common smells you should learn to handle early.
I hope you got to the point where you feel ready to try these refactorings in your own code and have an easier time identifying code smells around you. Beware that we just got started, but that you already tackled a couple of big ones. I bet it was not as tricky as you once might have thought!
Sure, real-world examples will be a lot more challenging, but if you have understood the mechanics and patterns to spot smells, you’ll surely be able to adapt quickly to realistic complexities.
The Best Small Business Web Designs by DesignRush
/Create Modern Vue Apps Using Create-Vue and Vite
/How to Fix the “There Has Been a Critical Error in Your Website” Error in WordPress
How To Fix The “There Has Been A Critical Error in Your Website” Error in WordPress
/How Long Does It Take to Learn JavaScript?
/The Best Way to Deep Copy an Object in JavaScript
/Adding and Removing Elements From Arrays in JavaScript
/Create a JavaScript AJAX Post Request: With and Without jQuery
/5 Real-Life Uses for the JavaScript reduce() Method
/How to Enable or Disable a Button With JavaScript: jQuery vs. Vanilla
/How to Enable or Disable a Button With JavaScript: jQuery vs Vanilla
/Confirm Yes or No With JavaScript
/How to Change the URL in JavaScript: Redirecting
/15+ Best WordPress Twitter Widgets
/27 Best Tab and Accordion Widget Plugins for WordPress (Free & Premium)
/21 Best Tab and Accordion Widget Plugins for WordPress (Free & Premium)
/30 HTML Best Practices for Beginners
/31 Best WordPress Calendar Plugins and Widgets (With 5 Free Plugins)
/25 Ridiculously Impressive HTML5 Canvas Experiments
/How to Implement Email Verification for New Members
/How to Create a Simple Web-Based Chat Application
/30 Popular WordPress User Interface Elements
/Top 18 Best Practices for Writing Super Readable Code
/Best Affiliate WooCommerce Plugins Compared
/18 Best WordPress Star Rating Plugins
/10+ Best WordPress Twitter Widgets
/20+ Best WordPress Booking and Reservation Plugins
/Working With Tables in React: Part Two
/Best CSS Animations and Effects on CodeCanyon
/30 CSS Best Practices for Beginners
/How to Create a Custom WordPress Plugin From Scratch
/10 Best Responsive HTML5 Sliders for Images and Text… and 3 Free Options
/16 Best Tab and Accordion Widget Plugins for WordPress
/18 Best WordPress Membership Plugins and 5 Free Plugins
/25 Best WooCommerce Plugins for Products, Pricing, Payments and More
/10 Best WordPress Twitter Widgets
1 /12 Best Contact Form PHP Scripts for 2020
/20 Popular WordPress User Interface Elements
/10 Best WordPress Star Rating Plugins
/12 Best CSS Animations on CodeCanyon
/12 Best WordPress Booking and Reservation Plugins
/12 Elegant CSS Pricing Tables for Your Latest Web Project
/24 Best WordPress Form Plugins for 2020
/14 Best PHP Event Calendar and Booking Scripts
/Create a Blog for Each Category or Department in Your WooCommerce Store
/8 Best WordPress Booking and Reservation Plugins
/Best Exit Popups for WordPress Compared
/Best Exit Popups for WordPress Compared
/11 Best Tab & Accordion WordPress Widgets & Plugins
/12 Best Tab & Accordion WordPress Widgets & Plugins
1New Course: Practical React Fundamentals
/Preview Our New Course on Angular Material
/Build Your Own CAPTCHA and Contact Form in PHP
/Object-Oriented PHP With Classes and Objects
/Best Practices for ARIA Implementation
/Accessible Apps: Barriers to Access and Getting Started With Accessibility
/Dramatically Speed Up Your React Front-End App Using Lazy Loading
/15 Best Modern JavaScript Admin Templates for React, Angular, and Vue.js
/15 Best Modern JavaScript Admin Templates for React, Angular and Vue.js
/19 Best JavaScript Admin Templates for React, Angular, and Vue.js
/New Course: Build an App With JavaScript and the MEAN Stack
/Hands-on With ARIA: Accessibility Recipes for Web Apps
/10 Best WordPress Facebook Widgets
13 /Hands-on With ARIA: Accessibility for eCommerce
/New eBooks Available for Subscribers
/Hands-on With ARIA: Homepage Elements and Standard Navigation
/Site Accessibility: Getting Started With ARIA
/How Secure Are Your JavaScript Open-Source Dependencies?
/New Course: Secure Your WordPress Site With SSL
/Testing Components in React Using Jest and Enzyme
/Testing Components in React Using Jest: The Basics
/15 Best PHP Event Calendar and Booking Scripts
/Create Interactive Gradient Animations Using Granim.js
/How to Build Complex, Large-Scale Vue.js Apps With Vuex
1 /Examples of Dependency Injection in PHP With Symfony Components
/Set Up Routing in PHP Applications Using the Symfony Routing Component
1 /A Beginner’s Guide to Regular Expressions in JavaScript
/Introduction to Popmotion: Custom Animation Scrubber
/Introduction to Popmotion: Pointers and Physics
/New Course: Connect to a Database With Laravel’s Eloquent ORM
/How to Create a Custom Settings Panel in WooCommerce
/Building the DOM faster: speculative parsing, async, defer and preload
1 /20 Useful PHP Scripts Available on CodeCanyon
3 /How to Find and Fix Poor Page Load Times With Raygun
/Introduction to the Stimulus Framework
/Single-Page React Applications With the React-Router and React-Transition-Group Modules
12 Best Contact Form PHP Scripts
1 /Getting Started With the Mojs Animation Library: The ShapeSwirl and Stagger Modules
/Getting Started With the Mojs Animation Library: The Shape Module
Getting Started With the Mojs Animation Library: The HTML Module
/Project Management Considerations for Your WordPress Project
/8 Things That Make Jest the Best React Testing Framework
/Creating an Image Editor Using CamanJS: Layers, Blend Modes, and Events
/New Short Course: Code a Front-End App With GraphQL and React
/Creating an Image Editor Using CamanJS: Applying Basic Filters
/Creating an Image Editor Using CamanJS: Creating Custom Filters and Blend Modes
/Modern Web Scraping With BeautifulSoup and Selenium
/Challenge: Create a To-Do List in React
1Deploy PHP Web Applications Using Laravel Forge
/Getting Started With the Mojs Animation Library: The Burst Module
/10 Things Men Can Do to Support Women in Tech
/A Gentle Introduction to Higher-Order Components in React: Best Practices
/Challenge: Build a React Component
/A Gentle Introduction to HOC in React: Learn by Example
/A Gentle Introduction to Higher-Order Components in React
/Creating Pretty Popup Messages Using SweetAlert2
/Creating Stylish and Responsive Progress Bars Using ProgressBar.js
/18 Best Contact Form PHP Scripts for 2022
/How to Make a Real-Time Sports Application Using Node.js
/Creating a Blogging App Using Angular & MongoDB: Delete Post
/Set Up an OAuth2 Server Using Passport in Laravel
/Creating a Blogging App Using Angular & MongoDB: Edit Post
/Creating a Blogging App Using Angular & MongoDB: Add Post
/Introduction to Mocking in Python
/Creating a Blogging App Using Angular & MongoDB: Show Post
/Creating a Blogging App Using Angular & MongoDB: Home
/Creating a Blogging App Using Angular & MongoDB: Login
/Creating Your First Angular App: Implement Routing
/Persisted WordPress Admin Notices: Part 4
/Creating Your First Angular App: Components, Part 2
/Persisted WordPress Admin Notices: Part 3
/Creating Your First Angular App: Components, Part 1
/How Laravel Broadcasting Works
/Persisted WordPress Admin Notices: Part 2
/Create Your First Angular App: Storing and Accessing Data
/Persisted WordPress Admin Notices: Part 1
/Error and Performance Monitoring for Web & Mobile Apps Using Raygun
Using Luxon for Date and Time in JavaScript
7 /How to Create an Audio Oscillator With the Web Audio API
/How to Cache Using Redis in Django Applications
/20 Essential WordPress Utilities to Manage Your Site
/Introduction to API Calls With React and Axios
/Beginner’s Guide to Angular 4: HTTP
/Rapid Web Deployment for Laravel With GitHub, Linode, and RunCloud.io
/Beginners Guide to Angular 4: Routing
/Beginner’s Guide to Angular 4: Services
/Beginner’s Guide to Angular 4: Components
/Creating a Drop-Down Menu for Mobile Pages
/Introduction to Forms in Angular 4: Writing Custom Form Validators
/10 Best WordPress Booking & Reservation Plugins
/Getting Started With Redux: Connecting Redux With React
/Getting Started With Redux: Learn by Example
/Getting Started With Redux: Why Redux?
/How to Auto Update WordPress Salts
/How to Download Files in Python
/Eloquent Mutators and Accessors in Laravel
1 /10 Best HTML5 Sliders for Images and Text
/Site Authentication in Node.js: User Signup
/Creating a Task Manager App Using Ionic: Part 2
/Creating a Task Manager App Using Ionic: Part 1
/Introduction to Forms in Angular 4: Reactive Forms
/Introduction to Forms in Angular 4: Template-Driven Forms
/24 Essential WordPress Utilities to Manage Your Site
/25 Essential WordPress Utilities to Manage Your Site
/Get Rid of Bugs Quickly Using BugReplay
1 /Manipulating HTML5 Canvas Using Konva: Part 1, Getting Started
/10 Must-See Easy Digital Downloads Extensions for Your WordPress Site
22 Best WordPress Booking and Reservation Plugins
/Understanding ExpressJS Routing
/15 Best WordPress Star Rating Plugins
/Creating Your First Angular App: Basics
/Inheritance and Extending Objects With JavaScript
/Introduction to the CSS Grid Layout With Examples
1Performant Animations Using KUTE.js: Part 5, Easing Functions and Attributes
Performant Animations Using KUTE.js: Part 4, Animating Text
/Performant Animations Using KUTE.js: Part 3, Animating SVG
/New Course: Code a Quiz App With Vue.js
/Performant Animations Using KUTE.js: Part 2, Animating CSS Properties
Performant Animations Using KUTE.js: Part 1, Getting Started
/10 Best Responsive HTML5 Sliders for Images and Text (Plus 3 Free Options)
/Single-Page Applications With ngRoute and ngAnimate in AngularJS
/Deferring Tasks in Laravel Using Queues
/Site Authentication in Node.js: User Signup and Login
/Working With Tables in React, Part Two
/Working With Tables in React, Part One
/How to Set Up a Scalable, E-Commerce-Ready WordPress Site Using ClusterCS
/New Course on WordPress Conditional Tags
/TypeScript for Beginners, Part 5: Generics
/Building With Vue.js 2 and Firebase
6 /Best Unique Bootstrap JavaScript Plugins
/Essential JavaScript Libraries and Frameworks You Should Know About
/Vue.js Crash Course: Create a Simple Blog Using Vue.js
/Build a React App With a Laravel RESTful Back End: Part 1, Laravel 5.5 API
/API Authentication With Node.js
/Beginner’s Guide to Angular: HTTP
/Beginner’s Guide to Angular: Routing
/Beginners Guide to Angular: Routing
/Beginner’s Guide to Angular: Services
/Beginner’s Guide to Angular: Components
/How to Create a Custom Authentication Guard in Laravel
/Learn Computer Science With JavaScript: Part 3, Loops
/Build Web Applications Using Node.js
/Learn Computer Science With JavaScript: Part 4, Functions
/Learn Computer Science With JavaScript: Part 2, Conditionals
/Create Interactive Charts Using Plotly.js, Part 5: Pie and Gauge Charts
/Create Interactive Charts Using Plotly.js, Part 4: Bubble and Dot Charts
Create Interactive Charts Using Plotly.js, Part 3: Bar Charts
/Awesome JavaScript Libraries and Frameworks You Should Know About
/Create Interactive Charts Using Plotly.js, Part 2: Line Charts
/Bulk Import a CSV File Into MongoDB Using Mongoose With Node.js
/Build a To-Do API With Node, Express, and MongoDB
/Getting Started With End-to-End Testing in Angular Using Protractor
/TypeScript for Beginners, Part 4: Classes
/Object-Oriented Programming With JavaScript
/10 Best Affiliate WooCommerce Plugins Compared
/Stateful vs. Stateless Functional Components in React
/Make Your JavaScript Code Robust With Flow
/Build a To-Do API With Node and Restify
/Testing Components in Angular Using Jasmine: Part 2, Services
/Testing Components in Angular Using Jasmine: Part 1
/Creating a Blogging App Using React, Part 6: Tags
/React Crash Course for Beginners, Part 3
/React Crash Course for Beginners, Part 2
/React Crash Course for Beginners, Part 1
/Set Up a React Environment, Part 4
1 /Set Up a React Environment, Part 3
/New Course: Get Started With Phoenix
/Set Up a React Environment, Part 2
/Set Up a React Environment, Part 1
/Command Line Basics and Useful Tricks With the Terminal
/How to Create a Real-Time Feed Using Phoenix and React
/Build a React App With a Laravel Back End: Part 2, React
/Build a React App With a Laravel RESTful Back End: Part 1, Laravel 9 API
/Creating a Blogging App Using React, Part 5: Profile Page
/Pagination in CodeIgniter: The Complete Guide
/JavaScript-Based Animations Using Anime.js, Part 4: Callbacks, Easings, and SVG
/JavaScript-Based Animations Using Anime.js, Part 3: Values, Timeline, and Playback
/Learn to Code With JavaScript: Part 1, The Basics
/10 Elegant CSS Pricing Tables for Your Latest Web Project
/Getting Started With the Flux Architecture in React
/Getting Started With Matter.js: The Composites and Composite Modules
Getting Started With Matter.js: The Engine and World Modules
/10 More Popular HTML5 Projects for You to Use and Study
/Understand the Basics of Laravel Middleware
/Iterating Fast With Django & Heroku
/Creating a Blogging App Using React, Part 4: Update & Delete Posts
/Creating a jQuery Plugin for Long Shadow Design
/How to Register & Use Laravel Service Providers
2 /Unit Testing in React: Shallow vs. Static Testing
/Creating a Blogging App Using React, Part 3: Add & Display Post
/Creating a Blogging App Using React, Part 2: User Sign-Up
20 /Creating a Blogging App Using React, Part 1: User Sign-In
/Creating a Grocery List Manager Using Angular, Part 2: Managing Items
/9 Elegant CSS Pricing Tables for Your Latest Web Project
/Dynamic Page Templates in WordPress, Part 3
/Angular vs. React: 7 Key Features Compared
/Creating a Grocery List Manager Using Angular, Part 1: Add & Display Items
New eBooks Available for Subscribers in June 2017
/Create Interactive Charts Using Plotly.js, Part 1: Getting Started
/The 5 Best IDEs for WordPress Development (And Why)
/33 Popular WordPress User Interface Elements
/New Course: How to Hack Your Own App
/How to Install Yii on Windows or a Mac
/What Is a JavaScript Operator?
/How to Register and Use Laravel Service Providers
/
waly Good blog post. I absolutely love this…