I have joined a new company where the efforts to clean the code occasionally is almost nill. They have been adding new features on top of the old spaghetti code. It takes hours to build a simple feature.

The team has been using ReactJS of 2015 with backend written in NodeJS. There are multiple state management libraries being used and the code is tightly coupled with jQuery, as well.

I have recently joined and I don't have much work in the company. What should be my first steps in improving this code base?

Write your answer…

5 answers

I recently heard a talk by a developer who inherited a similar situation when he became the sole developer at a company. The codebase was a large blob of code. Git had only been used once for a single commit long ago. And testing was done via a sandbox folder on the live server.

He took a microservices approach to incrementally improving the code base. Basically he pealed off discrete business functions which needed improvement, or created new verticals in the code for new functions, one at a time. And kept the code base as modular as he could. He gradually replaced the code base over time rather than rewriting everything at once.

Some of his advice included things like resist the urge to rewrite code that is working. Use third-party solutions for business functions when it works. He used Square Space for the home page/marketing pages, in part to let the non-developers make copy changes while continued to work on the custom code.

I think you are probably in a pickle though without the help of the rest of your company. Have you spoken with your senior developers and managers? Do they recognize a problem? Are they open to solutions?

This answer was selected for the crypto reward by the Hashnode community on Wed, 11th Apr 2018.

Learn more about "Crypto rewards program."

Cup1
Spot On2
Cool1
Clap6

I'd go with this too if taking the time to throw it all in the trash and start over clean isn't in the cards.

Though the minute I see 'react' involved, that's the FIRST thing I'd be telling the client or boss needs to be done. Pitching the entire disaster and starting over is often the correct and best answer...

... but it's not always the one you are allowed to choose. As such dividing things into smaller tasks as Kevin Kelly suggests so that you can replace sections one at a time is often the only route available to you.

Sucks, huh?

Reply to this…

Hashnode is building a friendly and inclusive dev community. Come jump on the bandwagon!

  • 💬 A beginner friendly place

  • 🧠 Stay in the loop and grow your knowledge

  • 🍕 >500K developers share programming wisdom here

  • ❤️ Support the growing dev community!

Register ( 500k+ developers strong 👊)

This exact incident has happened with me.

Our company once hired a contractor (let's call this person, "The Lord") for a platform (The platform itself had 4 web projects and 2 mobile projects, and The Lord was responsible for 2 web projects).

The Lord had some peculiar habits, (my then reporting manager then told me that The Lord has "different" take on coding solutions)

  1. The Lord wouldn't push code. Because Version Control System is for mere mortals. The Lord shipped a flash drive. I was supposed to "push" The Lord's code to the company's repository using my credentials. (Basically the projects spills my name, every time something breaks.)

  2. The Lord wouldn't complete tasks, Because completing tasks is for mere mortals, and freqently in the platform we'd notice some things not happening. When we dived into the code, we'd find

    // TODO
    // Task details: some thing is not going to happen
    // Please write xyz code to do the task
    

    This became so annoying, that I finally ended up searching for all //TODO ( // TODO, //To be done ) to fix it, once and for all.

  3. The Lord believed in transparency. This is what the entire component structure of the web app looked like:

    <GrandParentComponent {...state}>
        <ParentComponent {...this.props}>
            <ChildComponent {...this.props}/>
        </ParentComponent>
    </GrandParentComponent>
    

    Basically the entire redux store was loaded on the parent most component, And ALL of the props were flushed down from parent to the child, all components knew how to do everything. To give you a perspective the logout button knew, how to logout, login, add user, delete user, add organization, remove organization, assign users to the organization, and maybe run rm -rf / on the server.

  4. The Lord had strong gripes with inheritance. There was a component that was something like this:

    <SuperAwesomeReactComponent someEntity={someEntity} {...this.props} that={this}/>

    Not just the fact that someEntity was already nested inside this.props . The Child component had code segments from both the worlds: this.setState and that.setState.

Things I learnt from this experience:

  1. Be honest with your seniors regarding this, I am lucky enough to have seniors who agreed that I was in some deep s#it. I clearly communicated with them, that it will take more than usual time for me to ship this, for I am a mere mortal.
  2. DO NOT throw away code. Specially if the work done on the same can be measured in months. Try to rewrite some parts of it and make code more and more simpler for you (and potentially others).
  3. Try to reuse, rearrange and retain existing code, to it's extreme extent. It will use the maximum amount of creativity in the way, you may not be enthused. (It's like using wrench to hammer nails down.)
  4. K.T. (Knowledge Transfer) can sometimes be useless. In The Lord's hour long KT (on a weekend, when The Lord was busy with other commitments), in which The Lord spent 40 minutes on how code generated by boilerplate works.

I will keep updating as I get more thoughts.

To give you a perspective the logout button knew, how to logout, login, add user, delete user, add organization, remove organization, assign users to the organization, and maybe run rm -rf / on the server.

I've been arguing against this approach for a long time.

Components should only know about painting stuff to the DOM and receiving user input. Period.

The store should know only about managing central state. Period. A lot of examples put the API logic with the store logic.

The rest of the logic should be somewhere else. I've started to develop a pattern where I have modules in my front end app that actually do the different jobs (auth, api, etc) and then I have mediators which are the puppetmasters of the application modules and mediate all traffic between components, state, and modules.

Reply to this…

The first thing that I would do is analyse the current requirements of the project, which sections have the worst performance, which can split in small components, analyse the current behaviour and research the best solution for the current project problems. After that, write a report and show to the team, take their opinions and add to the report the new solutions that you colleague suggest. With this report open a side project taking the best of the current project and merge/update it with solutions in that report.

Adding to Kevin, make sure you speak to your senior developers before you start to rewrite because in any case your superiors shouldn't refuse your rewritten code pushing to production despite your code is tested and working flawlessly due to company's weird policies and processes, it would then be a waste of your time.

Well, I'm just going to assume there are no tests surrounding the code. As a newcomer, you're going to be fairly unfamiliar with how things work, so one of the things you could do write tests that assert existing behaviour. This gets code under test, gets you familiar with how things work right now, and gives you a base from which to refactor.

In general, an "if it ain't broke, don't fix it" approach is the pragmatic one in your situation, but but there are going to be times when stuff is broken and needs to be fixed. In that case, you might expand the scope of the fix to include a refactor of that specific component. The peril there is when your refactor starts to sprawl unnecessarily or excessively. If you feel like maybe your refactor has begun to necessarily expand its scope beyond what you anticipated, it's time to re-evaluate just how pragmatic it is to refactor at all.