The next code smell I want to highlight is one of my personal pet peeves, Primitive Obsession. This means using a primitive or String for a value just because it sort-of fits, rather than using a well-designed object. Yes, there is effort in creating the object, but that effort pays off many times over. What do I mean? How about using a float to represent money just because it has a decimal point. That *always* causes problems. You always have to deal with imprecision and rounding errors. You need a Money class that can store exact values, handle multiple currencies and perform conversions. Another horrible idea is to use a String (or even worse, an int) to hold a phone number. You often need to parse out a country code or an exchange by splitting the String or dividing the int. You can express these concepts directly in a TelephoneNumber class. The same goes for using String to represent an address. Use an Address object to hold a name (which should also be an object), a house number, street name, apartment number, city, province. Postal code and country. The same goes for dates, times, ranges and other types. Of course, Java has already defined classes for those. Any time you have a value in a primitive and keep having to split it apart to use it, you really need to define an object.The appropriate refactoring is “Replace Data Value With Object”. Sometimes, we use a primitive to represent a type code, which can also cause problems. You should use an enum or a class. If you don’t depend on the type code to affect behavior of the system, use “Replace Type Code With Class.” If you do use it for branching, then you can consider “Replace Type Code With Subclasses”, or “Replace Type Code With State/Strategy”. Another smell is storing parts of a value in an Array, then having to pick out pieces by knowing the indices of those pieces. If you find yourself doing this, you can use “Replace Array With Object”. Sometimes, you might have pieces of a value in individual primitive fields and parameters. In this case, you can put them together with “Extract Class” or “Introduce Parameter Object.” Shoe-horning complex values into a primitive is always a bad idea. You may think it is “easier” or “less work”, but it always comes back to bite you. You can find descriptions of the refactorings at https://lnkd.in/gdJjNQcF
Jim McMaster’s Post
More Relevant Posts
-
🚀 I've just published Part 4 - 'Formatting' of my series, where I share my notes from the book 'Clean Code' by Robert C. Martin. This part highlights importance of code formatting and its impact on readability and maintainability. Discover best practices for structuring your code to make it cleaner and more understandable. Read it here: https://lnkd.in/dD9yGMcG #CleanCode
Clean Code : Part 4— Formatting
medium.com
To view or add a comment, sign in
-
Methods that are too long make code really hard to understand, and are a bad code smell. A good rule of thumb says a method should be no more than 10-25 lines of actual code, not counting comments, white space or curly braces on their own lines. Any method longer than that is a good candidate for breaking up into shorter methods. It matters how you do it, though. I once heard a (possibly apocryphal) story about a developer who cut his long method into arbitrary 20-line chunks named sub1, sub2, etc. This would not have been useful, even if it did satisfy the letter of the rule. It certainly did not clarify the code. A good method reads like a paragraph with the steps clearly named for their purpose. All these steps should be at the same level of abstraction. Don’t mix low-level statements with higher-level method calls. It is fine to extract a single statement into a method if the name of that method makes the code more clear. Loops are often good candidates for extracting into a method of their own. The way to split a method is to read it through, separating out the “things” it is doing. Then extract each of those “things” into a method that is named to describe that “thing”. If some of the extracted methods are still too long, rinse and repeat, breaking them the same way. One sure sign you need to extract a method is when you feel the need to write a comment describing what is happening. Comments can get out of date or out of position, but if you extract a well-named method you are durably describing the code. When breaking down a method like this, you might run into a problem where you have to pass a lot of parameters, which can be hard to follow. Martin Fowler suggests several possible refactorings to help, like “Replace Temp With Query”, “Introduce Parameter Object” and “Preserve Whole Object”. In some cases, you might need “Replace Method With Method Object”. When you have a complicated conditional, you often can simplify it with “Decompose Conditional”. You can find descriptions of all the refactorings mentioned above at Martin Fowler’s site, https://lnkd.in/gdJjNQcF. Everyone should bookmark that site and be familiar with the refactorings he describes. Your code will be better for it.
Encapsulate Collection
refactoring.com
To view or add a comment, sign in
-
Yet another code smell is the use of Switch Statements. These are procedural artifacts in OO code. In particular, in many cases you have several switch statements doing different things for the same values, often a type code. If you add a new type, or different behavior for an existing type, then you need to find and change all of them. The alternative to using switch statements is polymorphism. Often, a type hierarchy is a more elegant way to solve the problem. You want a set of subclasses that encapsulate the behavior. The first step is to “Extract Method” to get the switch statement into a method, then “Move Method” to a class. After that, you can “Replace Type Code With Subclasses” or “Replace Method With State/Strategy”. Then you can “Replace Conditional With Polymorphism” to break it all apart. Of course, if you have only a few cases in a single method and don’t expect them to change often, then the above is probably overkill. You still might want to “Replace Parameter With Explicit Methods” to eliminate the switch. One special case Fowler mentions here is when you repeatedly check for a null object before calling methods on it. If you find yourself doing that, then “Introduce Null Object” can save a lot of repetitive code. Create an object that returns sensible default values and create one of those instead of using a null value. You can find descriptions of the refactorings at https://lnkd.in/gdJjNQcF
Encapsulate Collection
refactoring.com
To view or add a comment, sign in
-
We have a few code smells left. Today, let's talk about Incomplete Library Class. This isn't a problem with *your* code, but is with a library class you are using. That class is just missing some functionality you need. Sometimes, library developers forget something, or you might have a use case they didn't anticipate. If this were your code, you could just add the method. But you might not be willing or able to modify the library. This is especially true when you update the library frequently and would need to add your method(s) with each update. If the function you need is only called from one client class, you can use "Introduce Foreign Method" to add a method to that client class that adds that function. The example Fowler cites is a Date class, where you *really* need a method to get the next date for the one specified. You would add a private Date getNextDate(Date date) method with that capability to the client class. If you need to add several functions, or even one that is called from several client classes, then you would use "Introduce Local Extension". This involves creating either a subclass or a wrapper for the library class, with all the methods you need. Then you would use the extension class in place of the library class wherever you need it. Descriptions of the refactorings are at https://lnkd.in/gxmaYiRv
Encapsulate Collection
refactoring.com
To view or add a comment, sign in
-
Refactoring by Martin Fowler is one of my favourite technical books. There's so much wisdom in there. I own the first edition, and it was only last week that I learnt about the second edition, published in 2019 😅 A free chapter with an example that showcases several Refactorings can be downloaded here 👇 https://lnkd.in/dY_cMHCZ Emily Bache created a repository with the code for this example, together with some tests. The code it's available in several languages: https://lnkd.in/dEBV9tzg And, since I thought it was a great idea and the example wasn't available in Ruby, I decided to contribute with a PR: https://lnkd.in/dB_zgyT3
To view or add a comment, sign in
-
The next code smell in the Refactoring book is Long Parameter Lists. These can make it confusing and difficult to call constructors and methods. This is especially true when you have several parameters of the same type, like private int calculateFoo(int x, int y, int z) It is very easy to pass the parameters in the wrong order. There are a few ways to reduce the size of the parameter lists. If you are getting multiple parameter values from the same object, consider passing the whole object instead using “Preserve Whole Object”. If we are getting parameters by calling methods on another object we know about, you can move those calls into the method with “Replace Parameter With Method”. As a last resort, when you have a lot of unrelated parameters, you can “Introduce Parameter Object” to bundle them into a single parameter. One solution I don’t like is to move method variables into fields to avoid having to pass them as parameters. Fields should belong to the whole class, not to an individual method. Using fields for this purpose also obscures the data the methods use. If the method can be called concurrently, data in the fields can be corrupted. I am ambivalent about using a parameter object, especially in constructors. First, it is easy for these to become dumping grounds for junk we might no longer need as the method changes. Second, passing too many parameters to a method is an indication it should be broken up, and the parameter object hides that code smell without actually fixing it. Finally, for constructors, a parameter object causes the method signature to lie about the dependencies of the class. This idea comes from the test experts at Google. Reading the signature should tell you what the class needs to do its job, and that just shows the parameter object. It does *not* show that we depend on all the things *contained in* the parameter object. This makes writing tests for the class more difficult and makes the code harder to understand. Using many parameters might make calling the constructor more difficult, but this is less of a consideration when we are using a dependency injection framework. Then, we offload the responsibility for keeping the parameters straight to the framework. If we really do need a lot of dependencies, especially if we don’t need all of them every time, using a Builder or static factory methods are both good options. You can see descriptions for the refactorings at https://lnkd.in/gdJjNQcF
Encapsulate Collection
refactoring.com
To view or add a comment, sign in
-
📕 Book Recommendation A significant portion of the performance issues I've encountered in web applications have been related to databases. It is really important to know how to identify bottlenecks and implement solutions for each type of problem. A few days ago, I finished reading this awesome book written by Andrew Brookins. The book creatively explains how to identify and solve these issues within the context of Django applications. It's definitely worth the read. Link: https://lnkd.in/e6BZKekd
To view or add a comment, sign in
-
My latest blog: Associating Method Categories with Emojis in IntelliJ and Javadoc Shhh! There's a tiny preview of my upcoming book on Eclipse Collections in this blog. Enjoy! 🙏 https://lnkd.in/eNuMnfPg
Associating Method Categories with Emojis in IntelliJ and Javadoc
donraab.medium.com
To view or add a comment, sign in
-
In each programming language strings are interpreted slightly differently. This makes it a little difficult to transfer your knowledge on string operations from one programming language to the next. Go is not different and it has its quirks one must know about before mastering string manipulation. Therefore, I strongly recommend every aspiring Go programmer to read this brief article on different approaches to iterating over strings in Go. It is written by my mentor Bob Hoeppner and he explains very well the 4 main ways to do it. You will also apply this knowledge to a concrete problem: Verifying ISBN!
Explore the 'Iterate runes' approach for ISBN Verifier in Go on Exercism
exercism.org
To view or add a comment, sign in
-
📚 Excited to announce the release of my Complete Python eBook! 📚 This is designed for both beginners and experienced programmers who want to master Python programming. It covers a wide range of topics, including: 1.Fundamentals: Learn the basics of Python syntax and programming concepts. 2.Intermediate Topics: Dive into functions, data structures, and modules. 3.Advanced Topics: Explore data science, web development, and machine learning. Whether you're starting your programming journey or looking to deepen your skills, this eBook has something for everyone. Ready to take your Python knowledge to the next level? Check it out and start learning today! https://lnkd.in/gBReUb5D https://lnkd.in/gb_KazWQ Feel free to share with anyone interested in mastering Python! Happy coding! 🐍💻 #Python #Programming #eBook #DataScience #WebDevelopment #MachineLearning
Complete_python_Ebook/Complete_python_Ebook.ipynb at main · ninja-developer-13/Complete_python_Ebook
github.com
To view or add a comment, sign in