refactoring   7550

« earlier    

Alan Mellor's answer to What are the best books for programmers that are not language-specific (understanding general concepts)? - Quora
What are the best books for programmers that are not language-specific (understanding general concepts)?

Alan Mellor, Programmed since 8 bit. Just use more bits now.
Answered 12h ago

It’s my usual three: Refactoring by Martin Fowler. How to de-tangle your legacy code from hell. Or your own code if you don’t follow:

Clean Architecture by Robert C Martin. Explains how SOLID works at the design level.

And you’ll find this easier to apply if you apply:

Growing Object Oriented software guided by tests by Steve Freeman and Nat Pryce. Show a huge, practical case study of writing tests firsts in order to steer your design into nicely decoupled SOLID lumps
programming  books  book  oop  solid  clean  architecture  refactoring 
3 days ago by theskett
Repeat yourself, do more than one thing, and do more than one thing — programming is terrible
If you ask a programmer for advice—a terrible idea—they might tell you something like the following: Don’t repeat yourself. Programs should do one thing and one thing well. Never rewrite your code from scratch, ever!.

Following “Don’t Repeat Yourself” might lead you to a function with four boolean flags, and a matrix of behaviours to carefully navigate when changing the code. Splitting things up into simple units can lead to awkward composition and struggling to coordinate cross cutting changes. Avoiding rewrites means they’re often left so late that they have no chance of succeeding.

The advice isn’t inherently bad—although there is good intent, following it to the letter can create more problems than it promises to solve.

Sometimes the best way to follow an adage is to do the exact opposite: embrace feature switches and constantly rewrite your code, pull things together to make coordination between them easier to manage, and repeat yourself to avoid implementing everything in one function..

Repeat yourself, but don’t repeat other people’s hard work. Repeat yourself: duplicate to find the right abstraction first, then deduplicate to implement it.

With “Don’t Repeat Yourself”, some insist that it isn’t about avoiding duplication of code, but about avoiding duplication of functionality or duplication of responsibility. This is more popularly known as the “Single Responsibility Principle”, and it’s just as easily mishandled.

Gather responsibilities to simplify interactions between them

The only real difference between pushing something together and pulling something apart is that some changes become easier to perform than others.

The choice between a monolith and microservices is another example of this—the choice between developing and deploying a single service, or composing things out of smaller, independently developed services.

The big difference between them is that cross-cutting change is easier in one, and local changes are easier in the other. Which one works best for a team often depends more on environmental factors than on the specific changes being made.

Although a monolith can be painful when new features need to be added and microservices can be painful when co-ordination is required, a monolith can run smoothly with feature flags and short lived branches and microservices work well when deployment is easy and heavily automated.

Modularity is more than reducing things to their smallest parts.

A layer of small components with no shared features creates a need for a layer above where these features overlap, and if absent, the user will create one, with bash aliases, scripts, or even spreadsheets to copy-paste from.

Even adding this layer might not help you: git already has a notion of user-facing and automation-facing commands, and the UI is still a mess. It’s always easier to add a new flag to an existing command than to it is to duplicate it and maintain it in parallel.

Similarly, functions gain boolean flags and classes gain new methods as the needs of the codebase change. In trying to avoid duplication and keep code together, we end up entangling things.

Although components can be created with a single responsibility, over time their responsibilities will change and interact in new and unexpected ways. What a module is currently responsible for within a system does not necessarily correlate to how it will grow.

Modularity is about limiting the options for growth

A given module often gets changed because it is the easiest module to change, rather than the best place for the change to be made. In the end, what defines a module is what pieces of the system it will never responsible for, rather what it is currently responsible for.

This means recognizing which bits are slightly more entangled than others, knowing which pieces need to talk to each other, which need to share resources, what shares responsibilities, and most importantly, what external constraints are in place and which way they are moving.

In the end, it’s about optimizing for those changes—and this is rarely achieved by aiming for reusable code, as sometimes handling changes means rewriting everything.

Rewrite Everything

The reason rewrites are so risky in practice is that replacing one working system with another is rarely an overnight change. We rarely understand what the previous system did—many of its properties are accidental in nature. Documentation is scarce, tests are ornamental, and interfaces are organic in nature, stubbornly locking behaviors in place.

If migrating to the replacement depends on switching over everything at once, make sure you’ve booked a holiday during the transition, well in advance.

Successful rewrites plan for migration to and from the old system, plan to ease in the existing load, and plan to handle things being in one or both places at once. Both systems are continuously maintained until one of them can be decommissioned. A slow, careful migration is the only option that reliably works on larger systems.

The reason we say “Never Rewrite Code” is that we leave rewrites too late, demand too much, and expect them to work immediately. It’s more important to never rewrite in a hurry than to never rewrite at all.

null is true, everything is permitted

The problem with following advice to the letter is that it rarely works in practice. The problem with following it at all costs is that eventually we cannot afford to do so.

It isn’t “Don’t Repeat Yourself”, but “Some redundancy is healthy, some isn’t”, and using abstractions when you’re sure you want to couple things together.

It isn’t “Each thing has a unique component”, or other variants of the single responsibility principle, but “Decoupling parts into smaller pieces is often worth it if the interfaces are simple between them, and try to keep the fast changing and tricky to implement bits away from each other”.

It’s never “Don’t Rewrite!”, but “Don’t abandon what works”. Build a plan for migration, maintain in parallel, then decommission, eventually. In high-growth situations you can probably put off decommissioning, and possibly even migrations.
dry  srp  programming  bestpractices  refactoring  maintenance  modularity  onethingwell 
4 days ago by cdzombak
wix/vscode-glean: The extension provides refactoring tools for your React codebase
The extention provides refactoring tools for your React codebase: extract JSX into a new component, convert Function to Stateful React Components and more! In addition, you can extract regular Javascript/Typescript code between files, while handling exporting the selected code from the old location and importing in the new one!
vscode  react  refactoring 
9 days ago by tamouse

« earlier    

related tags

+  2018-08-06  a:tef  abstractions  active-record  advice  agile  analysis  arch  architecture  article  best-practices  bestpractice  bestpractices  blog  book  books  bowler  c++  cartoons  clean  cleaning  cleanup  cli  code-design  code  coder  codesmell  codesnippets  coding  comment  commenting  comp5911m  compressibility  compression  computers  copypaste  course  courses  craft  css  cssbasics  cultural-norms  databases  ddd  decorator  design-patterns  design  designpatterns  dev  devcinema  developer  development  documentation  domain  dry  dzone  effective  engineering  enterprise  error  examples  exceptions  export  facebook  facebook_opensource  fowler  fridayfrontend  generator  github  go  golang  goroutine  graphql  growing  gtd  guide  handler  html  ifttt  important  improve  improvement  instapaper  java  javascript  jquery  jupyter  kata  katrinaowen  kent-beck  learning  legacy  library  maintainability  maintenance  martin-fowler  martin  microservices  migration  model  modularity  monolith  notebooks  object-oriented-design  object  onethingwell  oop  oriented  p:programming-is-terrible  patterns  performance  php  pipeline  pocket  practices  preload  presenter  principles  productivity  programming  project  publishing  python  query  quick  rails  react  ref  refactor  reference  regression  reliability  render-props  ror  ruby  sass  semantic  semantics  skill  software-design  software-development  software-engineering  software  softwareengineering  solid  srp  structure  style  survey  sweng  swift  switch  tdd  technicaldebt  test  testing  thought-provoking  tips  to-watch  to-write-about  todo  tolearn  tool  tools  toread  totry  tounderstand  tutorial  tutorials  ui  updated  validation  vscode  web  weekly.rc  wham  work 

Copy this bookmark: