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_ids. 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
/
3Create Modern Vue Apps Using Create-Vue and Vite
/
8Pros and Cons of Using WordPress
/
-5How 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 to Create a Privacy Policy Page in WordPress
/
7WordPress Website Maintenance Guide For Beginners
/
8How Long Does It Take to Learn JavaScript?
/
-1How Long Does it Take to Learn JavaScript
/
1The Best Way to Deep Copy an Object in JavaScript
/
-2
4
-6Adding and Removing Elements From Arrays in JavaScript
/
-2Create a JavaScript AJAX Post Request: With and Without jQuery
/
85 Real-Life Uses for the JavaScript reduce() Method
/
-9How to Enable or Disable a Button With [removed] jQuery vs. Vanilla
/
3How to Enable or Disable a Button With [removed] jQuery vs Vanilla
/
-3Confirm Yes or No With JavaScript
/
-4How to Change the URL in [removed] Redirecting
/
-315+ Best WordPress Twitter Widgets
/
-227 Best Tab and Accordion Widget Plugins for WordPress (Free & Premium)
/
1121 Best Tab and Accordion Widget Plugins for WordPress (Free & Premium)
/
-1130 HTML Best Practices for Beginners
/
-731 Best WordPress Calendar Plugins and Widgets (With 5 Free Plugins)
/
525 Ridiculously Impressive HTML5 Canvas Experiments
/
-4
1How to Implement Email Verification for New Members
/
4How to Create a Simple Web-Based Chat Application
/
730 Popular WordPress User Interface Elements
/
-4Top 18 Best Practices for Writing Super Readable Code
/
2Best Affiliate WooCommerce Plugins Compared
/
-1018 Best WordPress Star Rating Plugins
/
1510+ Best WordPress Twitter Widgets
/
320+ Best WordPress Booking and Reservation Plugins
/
5Working With Tables in React: Part Two
/
-3Best CSS Animations and Effects on CodeCanyon
/
-1730 CSS Best Practices for Beginners
/
3How to Create a Custom WordPress Plugin From Scratch
/
310 Best Responsive HTML5 Sliders for Images and Text… and 3 Free Options
/
-516 Best Tab and Accordion Widget Plugins for WordPress
/
-518 Best WordPress Membership Plugins and 5 Free Plugins
/
525 Best WooCommerce Plugins for Products, Pricing, Payments and More
/
110 Best WordPress Twitter Widgets
1 /
1212 Best Contact Form PHP Scripts for 2020
/
-420 Popular WordPress User Interface Elements
/
-410 Best WordPress Star Rating Plugins
/
-412 Best CSS Animations on CodeCanyon
/
-112 Best WordPress Booking and Reservation Plugins
/
120 Best WordPress Calendar Plugins and Widgets
/
-212 Elegant CSS Pricing Tables for Your Latest Web Project
/
824 Best WordPress Form Plugins for 2020
/
-214 Best PHP Event Calendar and Booking Scripts
/
-1Getting Started With Django: Newly Updated Course
/
-1Create a Blog for Each Category or Department in Your WooCommerce Store
/
28 Best WordPress Booking and Reservation Plugins
/
-15Best Exit Popups for WordPress Compared
/
19Best Exit Popups for WordPress Compared
/
-411 Best Tab & Accordion WordPress Widgets & Plugins
/
-1212 Best Tab & Accordion WordPress Widgets & Plugins
1 /
3New Course: Practical React Fundamentals
/
2Short Course: Better Angular App Architecture With Modules
/
3Preview Our New Course on Angular Material
/
5Build Your Own CAPTCHA and Contact Form in PHP
/
-1Object-Oriented PHP With Classes and Objects
/
1Best Practices for ARIA Implementation
/
-5Accessible Apps: Barriers to Access and Getting Started With Accessibility
/
-3Dramatically Speed Up Your React Front-End App Using Lazy Loading
/
1815 Best Modern JavaScript Admin Templates for React, Angular, and Vue.js
/
-1515 Best Modern JavaScript Admin Templates for React, Angular and Vue.js
/
319 Best JavaScript Admin Templates for React, Angular, and Vue.js
/
3New Course: Build an App With JavaScript and the MEAN Stack
/
11Hands-on With ARIA: Accessibility Recipes for Web Apps
/
810 Best WordPress Facebook Widgets
13Hands-on With ARIA: Accessibility for eCommerce
/
6New eBooks Available for Subscribers
/
-10Hands-on With ARIA: Homepage Elements and Standard Navigation
/
10
-5Site Accessibility: Getting Started With ARIA
/
5How Secure Are Your JavaScript Open-Source Dependencies?
/
-4New Course: Secure Your WordPress Site With SSL
/
-3Testing Components in React Using Jest and Enzyme
/
-9Testing Components in React Using Jest: The Basics
/
-515 Best PHP Event Calendar and Booking Scripts
/
-2Create Interactive Gradient Animations Using Granim.js
/
9How to Build Complex, Large-Scale Vue.js Apps With Vuex
1Examples of Dependency Injection in PHP With Symfony Components
/
-5Set Up Routing in PHP Applications Using the Symfony Routing Component
1 /
9A Beginner’s Guide to Regular Expressions in JavaScript
/
9Introduction to Popmotion: Custom Animation Scrubber
/
-5Introduction to Popmotion: Pointers and Physics
/
-9New Course: Connect to a Database With Laravel’s Eloquent ORM
/
-5How to Create a Custom Settings Panel in WooCommerce
/
-14Building the DOM faster: speculative parsing, async, defer and preload
1 /
320 Useful PHP Scripts Available on CodeCanyon
3 /
51How to Find and Fix Poor Page Load Times With Raygun
/
1Introduction to the Stimulus Framework
/
-11Single-Page React Applications With the React-Router and React-Transition-Group Modules
/
1
712 Best Contact Form PHP Scripts
1 /
-3Getting Started With the Mojs Animation Library: The ShapeSwirl and Stagger Modules
/
1Getting Started With the Mojs Animation Library: The Shape Module
/
-3Getting Started With the Mojs Animation Library: The HTML Module
/
4Project Management Considerations for Your WordPress Project
/
-78 Things That Make Jest the Best React Testing Framework
/
3Creating an Image Editor Using CamanJS: Layers, Blend Modes, and Events
/
-1New Short Course: Code a Front-End App With GraphQL and React
/
2Creating an Image Editor Using CamanJS: Applying Basic Filters
/
-13Creating an Image Editor Using CamanJS: Creating Custom Filters and Blend Modes
/
-1Modern Web Scraping With BeautifulSoup and Selenium
/
1Challenge: Create a To-Do List in React
1 /
-2Deploy PHP Web Applications Using Laravel Forge
/
-3Getting Started With the Mojs Animation Library: The Burst Module
/
6
-1010 Things Men Can Do to Support Women in Tech
/
-3A Gentle Introduction to Higher-Order Components in React: Best Practices
/
-5Challenge: Build a React Component
/
-4A Gentle Introduction to HOC in React: Learn by Example
/
3A Gentle Introduction to Higher-Order Components in React
/
-6Creating Pretty Popup Messages Using SweetAlert2
/
5Creating Stylish and Responsive Progress Bars Using ProgressBar.js
/
1818 Best Contact Form PHP Scripts for 2022
/
-3Creating a Blogging App Using Angular & MongoDB: Delete Post
/
-15Creating a Blogging App Using Angular & MongoDB: Show Post
/
9Creating a Blogging App Using Angular & MongoDB: Home
/
8
4Creating a Blogging App Using Angular & MongoDB: Login
/
13Creating Your First Angular App: Implement Routing
/
13Persisted WordPress Admin Notices: Part 4
/
-3Creating Your First Angular App: Components, Part 2
/
4Persisted WordPress Admin Notices: Part 3
/
4
9Persisted WordPress Admin Notices: Part 2
/
-2Create Your First Angular App: Storing and Accessing Data
/
4Persisted WordPress Admin Notices: Part 1
/
-2Error and Performance Monitoring for Web & Mobile Apps Using Raygun
/
5Using Luxon for Date and Time in JavaScript
7 /
-7How to Create an Audio Oscillator With the Web Audio API
/
-5How to Cache Using Redis in Django Applications
/
220 Essential WordPress Utilities to Manage Your Site
/
-6Introduction to API Calls With React and Axios
/
16Beginner’s Guide to Angular 4: HTTP
/
12Rapid Web Deployment for Laravel With GitHub, Linode, and RunCloud.io
/
10Beginners Guide to Angular 4: Routing
/
-8Beginner’s Guide to Angular 4: Components
/
3Creating a Drop-Down Menu for Mobile Pages
/
6Introduction to Forms in Angular 4: Writing Custom Form Validators
/
4Getting Started With Redux: Connecting Redux With React
/
15Getting Started With Redux: Learn by Example
/
15Getting Started With Redux: Why Redux?
/
10Understanding Recursion With JavaScript
/
-2How to Auto Update WordPress Salts
/
-4How to Download Files in Python
/
-3
-21Eloquent Mutators and Accessors in Laravel
1 /
15
-10
1210 Best HTML5 Sliders for Images and Text
/
7Site Authentication in Node.js: User Signup
/
-3Creating a Task Manager App Using Ionic: Part 2
/
3Creating a Task Manager App Using Ionic: Part 1
/
2Introduction to Forms in Angular 4: Reactive Forms
/
2
4Introduction to Forms in Angular 4: Template-Driven Forms
/
224 Essential WordPress Utilities to Manage Your Site
/
-325 Essential WordPress Utilities to Manage Your Site
/
-11Get Rid of Bugs Quickly Using BugReplay
1 /
-16Manipulating HTML5 Canvas Using Konva: Part 1, Getting Started
/
610 Must-See Easy Digital Downloads Extensions for Your WordPress Site
/
-322 Best WordPress Booking and Reservation Plugins
/
-4Understanding ExpressJS Routing
/
-615 Best WordPress Star Rating Plugins
/
11Creating Your First Angular App: Basics
/
-1Inheritance and Extending Objects With JavaScript
/
-9Introduction to the CSS Grid Layout With Examples
1 /
4
6Performant Animations Using KUTE.js: Part 5, Easing Functions and Attributes
/
-9Performant Animations Using KUTE.js: Part 4, Animating Text
/
-13Performant Animations Using KUTE.js: Part 3, Animating SVG
/
-8New Course: Code a Quiz App With Vue.js
/
-1Performant Animations Using KUTE.js: Part 2, Animating CSS Properties
/
3
8Performant Animations Using KUTE.js: Part 1, Getting Started
/
110 Best Responsive HTML5 Sliders for Images and Text (Plus 3 Free Options)
/
-3Single-Page Applications With ngRoute and ngAnimate in AngularJS
/
-13Deferring Tasks in Laravel Using Queues
/
-5
2Site Authentication in Node.js: User Signup and Login
/
11Working With Tables in React, Part Two
/
-17Working With Tables in React, Part One
/
4How to Set Up a Scalable, E-Commerce-Ready WordPress Site Using ClusterCS
/
-4New Course on WordPress Conditional Tags
/
3
-13Building With Vue.js 2 and Firebase
6 /
14
-8Best Unique Bootstrap JavaScript Plugins
/
-8
-2Essential JavaScript Libraries and Frameworks You Should Know About
/
7
1Vue.js Crash Course: Create a Simple Blog Using Vue.js
/
-13Build a React App With a Laravel RESTful Back End: Part 1, Laravel 5.5 API
/
5API Authentication With Node.js
/
-5Beginner’s Guide to Angular: HTTP
/
7Beginner’s Guide to Angular: Routing
/
-4Beginners Guide to Angular: Routing
/
-4Beginner’s Guide to Angular: Services
/
3Beginner’s Guide to Angular: Components
/
1How to Create a Custom Authentication Guard in Laravel
/
6Learn Computer Science With [removed] Part 3, Loops
/
-5Build Web Applications Using Node.js
/
1Learn Computer Science With [removed] Part 4, Functions
/
4Learn Computer Science With [removed] Part 2, Conditionals
/
11Learn Computer Science With [removed] Part 1, The Basics
/
-2Create Interactive Charts Using Plotly.js, Part 5: Pie and Gauge Charts
/
-9Create Interactive Charts Using Plotly.js, Part 4: Bubble and Dot Charts
/
16Create Interactive Charts Using Plotly.js, Part 3: Bar Charts
/
-12Awesome JavaScript Libraries and Frameworks You Should Know About
/
-5Create Interactive Charts Using Plotly.js, Part 2: Line Charts
/
-8Bulk Import a CSV File Into MongoDB Using Mongoose With Node.js
/
-6Build a To-Do API With Node, Express, and MongoDB
/
-7Getting Started With End-to-End Testing in Angular Using Protractor
/
9TypeScript for Beginners, Part 4: Classes
/
-17Object-Oriented Programming With JavaScript
/
510 Best Affiliate WooCommerce Plugins Compared
/
6Stateful vs. Stateless Functional Components in React
/
8Make Your JavaScript Code Robust With Flow
/
-3Build a To-Do API With Node and Restify
/
6Testing Components in Angular Using Jasmine: Part 2, Services
/
1Testing Components in Angular Using Jasmine: Part 1
/
1Creating a Blogging App Using React, Part 6: Tags
/
-9React Crash Course for Beginners, Part 3
/
3React Crash Course for Beginners, Part 2
/
8React Crash Course for Beginners, Part 1
/
2Set Up a React Environment, Part 4
1 /
10Set Up a React Environment, Part 3
/
-11New Course: Get Started With Phoenix
/
-9Set Up a React Environment, Part 2
/
1Command Line Basics and Useful Tricks With the Terminal
/
5How to Create a Real-Time Feed Using Phoenix and React
/
-4Build a React App With a Laravel Back End: Part 2, React
/
3Build a React App With a Laravel RESTful Back End: Part 1, Laravel 9 API
/
-5Creating a Blogging App Using React, Part 5: Profile Page
/
-1Pagination in CodeIgniter: The Complete Guide
/
21JavaScript-Based Animations Using Anime.js, Part 4: Callbacks, Easings, and SVG
JavaScript-Based Animations Using Anime.js, Part 3: Values, Timeline, and Playback
/
-1Learn to Code With [removed] Part 1, The Basics
/
410 Elegant CSS Pricing Tables for Your Latest Web Project
/
-8Getting Started With the Flux Architecture in React
/
-2Getting Started With Matter.js: The Composites and Composite Modules
/
2Getting Started With Matter.js: The Engine and World Modules
/
1510 More Popular HTML5 Projects for You to Use and Study
/
-23Understand the Basics of Laravel Middleware
/
-3Iterating Fast With Django & Heroku
/
8Creating a Blogging App Using React, Part 4: Update & Delete Posts
/
4Creating a jQuery Plugin for Long Shadow Design
/
-11How to Register & Use Laravel Service Providers
2 /
-13Unit Testing in React: Shallow vs. Static Testing
/
4Creating a Blogging App Using React, Part 3: Add & Display Post
/
14Creating a Blogging App Using React, Part 2: User Sign-Up
20 /
-6Creating a Blogging App Using React, Part 1: User Sign-In
/
79 More Popular HTML5 Projects for You to Use and Study
/
16Creating a Grocery List Manager Using Angular, Part 2: Managing Items
/
89 Elegant CSS Pricing Tables for Your Latest Web Project
/
-1Dynamic Page Templates in WordPress, Part 3
/
-2Angular vs. React: 7 Key Features Compared
/
6Creating a Grocery List Manager Using Angular, Part 1: Add & Display Items
/
2New eBooks Available for Subscribers in June 2017
/
6Create Interactive Charts Using Plotly.js, Part 1: Getting Started
/
10The 5 Best IDEs for WordPress Development (And Why)
/
-133 Popular WordPress User Interface Elements
/
2New Course: How to Hack Your Own App
/
-11How to Install Yii on Windows or a Mac
/
4What Is a JavaScript Operator?
/
-6How to Register and Use Laravel Service Providers
/
8
waly Good blog post. I absolutely love this…