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
/
9Pros and Cons of Using WordPress
/
-1How to Fix the “There Has Been a Critical Error in Your Website” Error in WordPress
/
2How To Fix The “There Has Been A Critical Error in Your Website” Error in WordPress
/
-1How to Create a Privacy Policy Page in WordPress
/
8WordPress Website Maintenance Guide For Beginners
/
8How Long Does it Take to Learn JavaScript
/
1The Best Way to Deep Copy an Object in JavaScript
/
-3
4
-5Adding 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
/
-8How to Enable or Disable a Button With JavaScript: jQuery vs. Vanilla
/
4How to Enable or Disable a Button With JavaScript: jQuery vs Vanilla
/
-2Confirm Yes or No With JavaScript
/
-4How to Change the URL in JavaScript: Redirecting
/
-215+ Best WordPress Twitter Widgets
/
-127 Best Tab and Accordion Widget Plugins for WordPress (Free & Premium)
/
1221 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)
/
325 Ridiculously Impressive HTML5 Canvas Experiments
/
-4
1How to Implement Email Verification for New Members
/
4How to Create a Simple Web-Based Chat Application
/
630 Popular WordPress User Interface Elements
/
-4Top 18 Best Practices for Writing Super Readable Code
/
1Best Affiliate WooCommerce Plugins Compared
/
-1218 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
/
-1830 CSS Best Practices for Beginners
/
4How 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
/
-618 Best WordPress Membership Plugins and 5 Free Plugins
/
425 Best WooCommerce Plugins for Products, Pricing, Payments and More
/
210 Best WordPress Twitter Widgets
1 /
1112 Best Contact Form PHP Scripts for 2020
/
-320 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
/
-312 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
/
-2Create a Blog for Each Category or Department in Your WooCommerce Store
/
38 Best WordPress Booking and Reservation Plugins
/
-15Best Exit Popups for WordPress Compared
/
19Best Exit Popups for WordPress Compared
/
-311 Best Tab & Accordion WordPress Widgets & Plugins
/
-1012 Best Tab & Accordion WordPress Widgets & Plugins
1New Course: Practical React Fundamentals
/
2Short Course: Better Angular App Architecture With Modules
/
3Preview Our New Course on Angular Material
/
4Build Your Own CAPTCHA and Contact Form in PHP
/
-2Best Practices for ARIA Implementation
/
-5Accessible Apps: Barriers to Access and Getting Started With Accessibility
/
-4Dramatically Speed Up Your React Front-End App Using Lazy Loading
/
1715 Best Modern JavaScript Admin Templates for React, Angular, and Vue.js
/
-1615 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
/
710 Best WordPress Facebook Widgets
13Hands-on With ARIA: Accessibility for eCommerce
/
6New eBooks Available for Subscribers
/
-9Hands-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
/
-3Create Interactive Gradient Animations Using Granim.js
/
10How to Build Complex, Large-Scale Vue.js Apps With Vuex
1 /
-2Examples of Dependency Injection in PHP With Symfony Components
/
-5Set Up Routing in PHP Applications Using the Symfony Routing Component
1 /
8A Beginner’s Guide to Regular Expressions in JavaScript
/
9Introduction to Popmotion: Custom Animation Scrubber
/
-6Introduction to Popmotion: Pointers and Physics
/
-10New Course: Connect to a Database With Laravel’s Eloquent ORM
/
-6How to Create a Custom Settings Panel in WooCommerce
/
-14Building the DOM faster: speculative parsing, async, defer and preload
1 /
420 Useful PHP Scripts Available on CodeCanyon
3 /
51How to Find and Fix Poor Page Load Times With Raygun
/
1Introduction to the Stimulus Framework
/
-12Single-Page React Applications With the React-Router and React-Transition-Group Modules
/
1
612 Best Contact Form PHP Scripts
1 /
-3Getting Started With the Mojs Animation Library: The ShapeSwirl and Stagger Modules
Getting Started With the Mojs Animation Library: The Shape Module
/
-1Getting Started With the Mojs Animation Library: The HTML Module
/
5Project Management Considerations for Your WordPress Project
/
-88 Things That Make Jest the Best React Testing Framework
/
5Creating an Image Editor Using CamanJS: Layers, Blend Modes, and Events
New Short Course: Code a Front-End App With GraphQL and React
/
1Creating 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
/
4
-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
/
-1A Gentle Introduction to HOC in React: Learn by Example
/
3A Gentle Introduction to Higher-Order Components in React
/
-6Creating Pretty Popup Messages Using SweetAlert2
/
7Creating Stylish and Responsive Progress Bars Using ProgressBar.js
/
1718 Best Contact Form PHP Scripts for 2022
/
-2How to Make a Real-Time Sports Application Using Node.js
/
-2Creating a Blogging App Using Angular & MongoDB: Delete Post
/
-16Set Up an OAuth2 Server Using Passport in Laravel
/
2Creating a Blogging App Using Angular & MongoDB: Edit Post
/
1Introduction to Mocking in Python
/
1Creating a Blogging App Using Angular & MongoDB: Show Post
/
10Creating a Blogging App Using Angular & MongoDB: Home
/
6
3Creating a Blogging App Using Angular & MongoDB: Login
/
11Creating 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
7Persisted WordPress Admin Notices: Part 2
/
-2Create Your First Angular App: Storing and Accessing Data
/
5Persisted WordPress Admin Notices: Part 1
/
-2Error and Performance Monitoring for Web & Mobile Apps Using Raygun
/
6Using Luxon for Date and Time in JavaScript
7 /
-4How 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
/
15Beginner’s Guide to Angular 4: HTTP
/
13Rapid Web Deployment for Laravel With GitHub, Linode, and RunCloud.io
/
9Beginners Guide to Angular 4: Routing
/
-10Beginner’s Guide to Angular 4: Services
/
1Beginner’s Guide to Angular 4: Components
/
2Creating a Drop-Down Menu for Mobile Pages
/
7Introduction to Forms in Angular 4: Writing Custom Form Validators
/
5Getting Started With Redux: Connecting Redux With React
/
15Getting Started With Redux: Learn by Example
/
14Getting Started With Redux: Why Redux?
/
11How to Auto Update WordPress Salts
/
-4How to Download Files in Python
/
-2
-21Eloquent Mutators and Accessors in Laravel
1 /
15
-11
1210 Best HTML5 Sliders for Images and Text
/
8Site Authentication in Node.js: User Signup
/
-1Creating a Task Manager App Using Ionic: Part 2
/
3Creating a Task Manager App Using Ionic: Part 1
/
1Introduction to Forms in Angular 4: Reactive Forms
/
1
4Introduction to Forms in Angular 4: Template-Driven Forms
/
424 Essential WordPress Utilities to Manage Your Site
/
-325 Essential WordPress Utilities to Manage Your Site
/
-10Get Rid of Bugs Quickly Using BugReplay
1 /
-17Manipulating HTML5 Canvas Using Konva: Part 1, Getting Started
/
610 Must-See Easy Digital Downloads Extensions for Your WordPress Site
/
-122 Best WordPress Booking and Reservation Plugins
/
-5Understanding 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
5Performant Animations Using KUTE.js: Part 5, Easing Functions and Attributes
/
-8Performant Animations Using KUTE.js: Part 4, Animating Text
/
-10Performant Animations Using KUTE.js: Part 3, Animating SVG
/
-8New Course: Code a Quiz App With Vue.js
/
-2Performant Animations Using KUTE.js: Part 2, Animating CSS Properties
/
2
9Performant 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
/
-4
2Site Authentication in Node.js: User Signup and Login
/
10Working With Tables in React, Part Two
/
-17Working With Tables in React, Part One
/
3How to Set Up a Scalable, E-Commerce-Ready WordPress Site Using ClusterCS
/
-3New Course on WordPress Conditional Tags
/
3TypeScript for Beginners, Part 5: Generics
/
1
-10Building With Vue.js 2 and Firebase
6 /
12
-8
1Best Unique Bootstrap JavaScript Plugins
/
-6
-1Essential JavaScript Libraries and Frameworks You Should Know About
/
6
3Vue.js Crash Course: Create a Simple Blog Using Vue.js
/
-14Build a React App With a Laravel RESTful Back End: Part 1, Laravel 5.5 API
/
3API Authentication With Node.js
/
-4Beginner’s Guide to Angular: HTTP
/
8Beginner’s Guide to Angular: Routing
/
-3Beginners Guide to Angular: Routing
/
-4Beginner’s Guide to Angular: Services
/
2Beginner’s Guide to Angular: Components
/
1How to Create a Custom Authentication Guard in Laravel
/
5Learn Computer Science With JavaScript: Part 3, Loops
/
-5Build Web Applications Using Node.js
/
1Learn Computer Science With JavaScript: Part 4, Functions
/
4Learn Computer Science With JavaScript: Part 2, Conditionals
/
12Create Interactive Charts Using Plotly.js, Part 5: Pie and Gauge Charts
/
-8Create Interactive Charts Using Plotly.js, Part 4: Bubble and Dot Charts
/
15Create Interactive Charts Using Plotly.js, Part 3: Bar Charts
/
-11Awesome JavaScript Libraries and Frameworks You Should Know About
/
-6Create 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
/
-8Getting Started With End-to-End Testing in Angular Using Protractor
/
10TypeScript for Beginners, Part 4: Classes
/
-17Object-Oriented Programming With JavaScript
/
410 Best Affiliate WooCommerce Plugins Compared
/
6Stateful vs. Stateless Functional Components in React
/
8Make Your JavaScript Code Robust With Flow
/
-2Build a To-Do API With Node and Restify
/
6Testing Components in Angular Using Jasmine: Part 2, Services
/
3Testing Components in Angular Using Jasmine: Part 1
/
-1Creating a Blogging App Using React, Part 6: Tags
/
-10React Crash Course for Beginners, Part 3
/
3React Crash Course for Beginners, Part 2
/
5React Crash Course for Beginners, Part 1
/
2Set Up a React Environment, Part 4
1 /
9Set Up a React Environment, Part 3
/
-9New Course: Get Started With Phoenix
/
-8Set Up a React Environment, Part 2
/
2Command Line Basics and Useful Tricks With the Terminal
/
8How 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
/
-4Pagination in CodeIgniter: The Complete Guide
/
23JavaScript-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
/
510 Elegant CSS Pricing Tables for Your Latest Web Project
/
-9Getting 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
/
1410 More Popular HTML5 Projects for You to Use and Study
/
-22Understand the Basics of Laravel Middleware
/
-1Iterating Fast With Django & Heroku
/
10Creating a Blogging App Using React, Part 4: Update & Delete Posts
/
5Creating 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 /
-5Creating a Blogging App Using React, Part 1: User Sign-In
/
69 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
/
-3Dynamic Page Templates in WordPress, Part 3
/
-4Angular vs. React: 7 Key Features Compared
/
6Creating a Grocery List Manager Using Angular, Part 1: Add & Display Items
/
1New eBooks Available for Subscribers in June 2017
/
7Create Interactive Charts Using Plotly.js, Part 1: Getting Started
/
10The 5 Best IDEs for WordPress Development (And Why)
/
-233 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?
/
-7How to Register and Use Laravel Service Providers
/
9
waly Good blog post. I absolutely love this…