Nowadays it is relatively easy to become a software developer, but being a truly professional one is not that simple. Learn here how to be the developer that every company and every client wants to have.
Being a professional developer is crucial in the software industry. Many developers are not working in a professional manner and this will bring a lot of trouble for both the client and developer in the future: maintenance, scalability, performance, security, these are just a few issues that will emerge and will put the project in danger.If that happens it is usual that no developer will want to fix it, and the client or company will be left with a useless project and a lot of money wasted.
We as developers always seek to be better, but sometimes we do not know the practices or principles to achieve this. In this post, I will guide you through some practices and principles that will make you achieve that professional level and be a developer that clients and companies feel secure hiring. This post also goes to clients and companies to know what to look for in a developer and know how to recognize a professional developer.
How do I know if I am a professional software developer?
Based on our practices and principles we will answer this question. But, be that as it may, we need to be professional in this working environment and take our jobs seriously. Not only our civilization depends upon our work, but also software is everywhere in our daily life! There are a ton of examples of how much software is around us: cooling systems, our cellphones, automatic doors, microphones, cars, traffic lights, etc.
That is why we need to emphasize the professional branch of our work. It is not something to be taken lightly, the future will be built by us developers and we sure want a good one, not one in which things from the past were easier to use.
1. Use SOLID principles
SOLID principles are a set of golden rules used in OOP. They set the standard of how to program in OOP languages. In fact, SOLID programs scale better, cost less time to work with, and they can more easily respond to change. This last feature is key because in the present and future everything is constantly changing and if your code is not ready for change, then you will have a lot of trouble coming your way. Furthermore, employers will always prefer a candidate with a strong grasp of SOLID principles.
*The 5 principles of SOLID:
- Single-responsibility principle
- Open-closed principle
- Liskov substitution principle
- Interface segregation principle
- Dependency inversion principle
“A class should only have a single responsibility, that is, only changes to one part of the software’s specification should be able to affect the specification of the class.”
The principle states that each class, module, or function in your program should only do one job, and that each should have full responsibility for a single functionality of the program. Another condition is that the class should contain only variables and methods relevant to its functionality.
Classes can work together to complete larger complex tasks, but each class must complete a function from start to finish before it passes the output to another class.
“Software entities … should be open for extension, but closed for modification.”
The principle calls for entities that can be widely adapted but also remain unchanged. This leads us to create duplicate entities with specialized behavior through polymorphism.
Through polymorphism, we can extend our parent entity to suit the needs of the child entity while leaving the parent intact.
Liskov Substitution Principle
“Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program.”
This principle says that any class must be directly replaceable by any of its subclasses without error; each subclass must maintain all behavior from the base class along with any new behaviors unique to the subclass. Likewise, the child class must be able to process all the same requests and complete all the same tasks as its parent class.
Interface Segregation Principle
“Many client-specific interfaces are better than one general-purpose interface.”
The Interface Segregation principle requires that classes only be able to perform behaviors that are useful to achieve its end functionality — classes do not include behaviors they do not use.
In fact, this relates to the first SOLID principle in that together these two principles strip a class of all variables, methods, or behaviors that do not directly contribute to their role. It is important to keep in mind taht methods must contribute to the end goal in their entirety.
Dependency Inversion Principle
“One should depend upon abstractions, not concretions.”
This principle states that high-level modules should not depend on low-level modules. Instead, both should depend on abstractions (interfaces) and abstractions should not depend on details. Details, such as concrete implementations should depend on abstractions.
2. Apply Clean Code
There are many definitions of what clean code is. For example. the most popular definition is that clean code is code which is easy to understand and change. Specifically, code is clean if it can be understood easily by everyone on the team. Clean code can be read and enhanced by a developer other than its original author.
There are some points and practices that clean code suggest in order to achieve this level of professional code. Here you have them :
- Follow standard conventions
- Keep it simple. Simpler is always better. Reduce complexity as much as possible
- Boy scout rule. Leave the campground cleaner than you found it
- Always find the root cause. Always look for the root cause of a problem
- Keep configurable data at high levels
- Prefer polymorphism to if/else or switch/case
- Separate multi-threading code
- Prevent over-configurability
- Use dependency injection
- Follow the Law of Demeter. A class should know only its direct dependencies
- Be consistent. If you do something a certain way, do all similar things in the same way
- Use explanatory variables
- Encapsulate boundary conditions. Boundary conditions are hard to keep track of. Put the processing for them in one place
- Prefer dedicated value objects to primitive types
- Avoid logical dependency. Do not write methods which work correctly depending on something else in the same class
- Avoid negative conditionals
- Choose descriptive and unambiguous names
- Make meaningful distinctions
- Use pronounceable names
- Use searchable names
- Replace magic numbers with named constants
- Avoid encodings. Do not append prefixes or type information
- Do one thing
- Use descriptive names
- Prefer fewer arguments
- Have no side effects
- Do not use flag arguments. Split method into several independent methods that can be called from the client without the flag
- Always try to explain yourself in code
- Do not be redundant
- Do not add obvious noise
- Do not use closing brace comments
- Do nor comment out code. Just remove
- Use as explanation of intent
- Use as clarification of code
- Use as warning of consequences
Source code structure
- Separate concepts vertically
- Related code should appear vertically dense
- Declare variables close to their usage
- Dependent functions should be close
- Similar functions should be close
- Place functions in the downward direction
- Keep lines short
- Do not use horizontal alignment
- Use white space to associate related things and disassociate - weakly related
- Do not break indentation
Objects and data structures
- Hide internal structure
- Prefer data structures
- Avoid hybrids structures (half object and half data)
- They should be small
- Do one thing
- Small number of instance variables
- Base class should know nothing about their derivatives
- It is better to have many functions than to pass some code into a function to select a behavior
- Prefer non-static methods to static methods
- One assert per test
- Rigidity: the software is difficult to change. A small change causes a cascade of subsequent changes
- Fragility: the software breaks in many places due to a single change
- Immobility: you cannot reuse parts of the code in other projects because of involved risks and high effort
- Needless complexity
- Needless repetition
- Opacity: the code is hard to understand
3. Use Test Driven Development
TDD (Test Driven Development) is a way of developing software. For instance, clean code that works is the goal of TDD. When developing using TDD you should start by writing a failing automated test before you write any code. In this case, there are two rules when it comes to TDD:
- Write new code only if an automated test has failed
- Eliminate duplication
The two rules imply an order to the tasks of programming.
- Red - Write a little test that does not work, and perhaps it does not even compile at first
- Green - Make the test work quickly, committing the necessary sins during the process
- Refactor - Eliminate all of the duplication created to get the test to work
Red/Green/Refactor is the TDD mantra.
This order is also described as:
- Write a test…
- Make it run…
- Make it right…
Remember, the goal of TDD is clean code that works. First, we'll solve the "that works" part of the problem. Then, we'll solve the "clean code" part. This is the opposite of architecture-driven development, where you solve "clean code" first, then scramble around trying to integrate into the design the things you learn as you solve the "that works" problem.
A more detailed version of the TDD cycle is:
- Quickly add test
- Run all tests and see the new one fail
- Make a little change
- Run all tests and see them all succeed
- Refactor to remove duplication
Quickly getting to green
There are three techniques for quickly getting to green. Keep in mind that in TDD you should not spent more than 1 minute in red!
- Fake it: Return a constant and gradually replace constants with variables until you have the real code
- Obvious implementation: Type in the real implementation. You can also alternate between obvious and fake it on the go. If everything is moving smoothly, use obvious but when you get an unexpected red bar switch to fake it and then repeat
- Triangulation: Abstract only when you have two or more examples. By analogy when we triangulate, we only generalize code when we have two examples or more. When the second example demands a more general solution, then and only then we generalize
Solo programming vs Team programming
When you are solo programming, leave the last test broken. Of course, when you come back to the code, you then have an obvious place to start. And, if you are programming in a team, leave all the tests running after each session.
How many tests should you make?
In TDD, more tests doesn’t mean better coverage. In this case, the tests have to be focused on the cases that can occur and also edge cases. At the end of the day if you make more tests than needed, those extra tests will break with the same bug. Indeed, they will make no difference in the bug detection. So, when making tests you should focus more on the cases and scenarios rather than the number of tests you will make.
4. Follow The Green Band
Robert Cecil Martin aka “Uncle Bob” is an American software engineer known for the creation of SOLID principles and Clean Code. He wears a green band as a promise to himself to behave in a professional manner. In fact, this green band represents a number of principles and practices:
- We will not ship garbage (He uses a much stronger word to describe it.)
- We will always be ready
- Stable productivity
- Inexpensive adaptability
- Continuous improvement
- Fearless competence
- Extreme quality
- QA will find nothing
- Nothing fragile
- We cover for each other
- Honest estimates
- Learn to say “No”
- Continuous aggressive learning
We will not Ship Garbage
Many of us have done this and is not correct! Above all, we should go back to our houses proud of the work we did on the day. So far, that professional work and good practices will help the company to work better, have more quality software products, and make more money. Most of us have returned home feeling dirty because of all the bad code we wrote and shipped.
We will Always be Ready
When the business wants to deploy, we should be ready. There should not be any delay or wait a month or to wait for QA to finish. Also, there should not exist any stabilization phase because the code should be stable always and be ready to deploy. In fact, a week for something to be deployable is okay but more than that or months is a no go.
It is pretty common to start with a good productivity but slowly it begins to slow down and the company starts to involve more programmers. Certainly, this is a mistake because it makes things only worse. Naturally, week by week we should analyze and check that our productivity keeps the same pace.
Software is supposed to be easy to change. There should not be any excuses, our design should support any new requirements. In the end,change should not cost a lot, if it does, then something is wrong.
Of course we should keep improving during the project of our code, both processes and productivity. If we see a dirty code we should clean it, we should not be afraid of it. If you see a bad process then fix it! Always improve.
Do not be afraid to touch code that looks scary, do not walk away from it. Just because you know that if you touch it and it does not work then it becomes your responsibility you do not have to be afraid of this. On the contrary: Clean it and fix it!
Going fast does not mean producing less quality or making a mess. The only way to go fast is to keep your quality as fast as possible. Undoubtedly, you cannot go fast with bad code. When there is pressure the things you do are what you really believe in. If you believe that writing good code makes you go faster then when pressure comes you will write it even better.
QA will Find Nothing
QA should not find anything, QA is not our debugger or our bug finder. Do not release your code until it is ready and it works. Usually, devs ship to QA knowing it is not ready and use QA personnel to find bugs. This is not right! Of course from time to time some bugs will not be found by you, but it should be unsual when this happens.
There should not be any manual tests, or practices. Everything should be automated, as the system gets larger we will have more tests and if there is a budget for manual tests. Then, there will come a time in which the budget will be less and some tests will have to be ignored; this is not an option.
We do not want to be afraid of any part of the code or a particular module that every time you touch it, it breaks. This should not be the case. You should be able to touch anything in your code and be strong to support change.
We Cover for each Other
We need to be able to explain our stuff to everybody else and make sure we have a backup just in case we “disappear” for some reason. When a person goes on vacation we should be able to advance in their branch, not the other way around. In other words, figure out a way to cover for each other; e.g., it can be pair programming.
A date is a lie, you cannot be that accurate. In fact, we want a range; what are the odds that you can actually make it before a certain date?
Learn to say “No”
If someone puts pressure on a due date and changes things to make it work, you should also know how to say “no”. If numbers do not match when delivering a project, it is okay to say “no”. Most importantly, you should learn the difference between telling the truth or just being lazy. If you know that something is not possible you should say “no”.
Continuous Aggressive Learning
One of the primary jobs of a software engineer is to learn. Primarily because this is an industry that moves at a tremendous pace of speed, and new languages and processes appear all the time. If a dev gets a little bit behind they might not recover from that.
Languages come in waves, to be a good developer you should be good at riding those waves. You should look at the next wave so you are ready to hop on to the next one and keep surfing. If you expect your employer to teach you all of this, then you are wrong. You need to be learning by yourself. For this purpose, expect to spend another 20 hours a week on your professional knowledge. That is what professionals do.
Nobody is addressing right now the need to turn youngsters into professionals, letting them know what good and bad code is. Share your knowledge to the new programmers! We should teach them what we know and turn them into professionals. Be an example, so others follow your practices.
- SCNA 2012: Robert Martin — The Reasonable Expectations of Your CTO. (2012, 21 octubre). [Vídeo]. Vimeo. https://vimeo.com/54025415
- Martin, R. C. (2009). Clean code: A handbook of agile software craftsmanship. Upper Saddle River, NJ: Prentice Hall.
- Beck, K. (2003). Test-driven development: by example. Addison-Wesley Professional.
- S.O.L.I.D. Principles of Object-Oriented Programming in C#. (2020). Educative. https://www.educative.io/blog/solid-principles-oop-c-sharp?aid=5082902844932096&utm_source=google&utm_medium=cpc&utm_campaign=blog-dynamic&gclid=Cj0KCQiAj9iBBhCJARIsAE9qRtBbT1lBZHywb4VBl7BX66p0jmTT0evT1KaQ4DkHXdLcc5G01ohcXBkaAhurEALw_wcB