Now I'm a little worried that if my situation doesn't change, my career would suffer. I've started to watch a few videos online about design. But I'm not sure if they're going to really help as they usually talk about very basics which doesn't help in real world coding.
I usually take 3-4 tries with some significant amount of testing to get my code to a working state. I refer to stack overflow or ask my colleagues if I get stuck on some design / technology feature which I haven't seen before. I feel the above contributes to reduction in my speed of delivery and the rush to complete the deliverable on time, compromises the quality.
Are there any good ideas to improve one's coding / design skills significantly ? The challenge here is to deliver good quality code, while maintaining a decent speed of delivery.
When PRs are getting outright rejected it is because you are making incorrect assumptions or decisions in your code that don’t match with what the rest of the team knows or wants.
Before you make a decision, get another perspective.
One common pattern I see in not-quite-yet-senior devs is that they don’t necessarily recognize the moments when there is more than one option, and they are making a choice. This happens all the time in programming. You are constantly making decisions and committing to particular solutions. If you are not aware of the choices you are making - you are picking the first idea that comes to mind (or the first stackoverflow answer) - there’s a really good chance you are picking wrong.
Also try to develop your instinct for the assumptions you are bringing to the table. Did you assume this code was just one-off stuff for a simple offline process? Do others on the team expect it to be reused as a library later in an online service call path? That difference of perspective will lead to vastly different expectations for how that code should be written.
So: Take more time before you start coding to talk through the approach you were thinking of taking with someone. Then, as you start coding, watch out for moments when you can make a choice and again, get some input.
Doesn’t need to be a long design session. Just a five minute pull-aside to get a consult on an approach.
This is why pairing is so effective, by the way - you get constant access to a second perspective.
So more code reviews and design reviews for others and try to ask why whenever you don't understand what you are looking at. Asking questions is a sign of strength.
Spend a little more time on design, and whiteboard with a coworker before you implement. Draw the boxes and arrows of your approach and reason about where it will break. It will break on some axis sometime, tell yourself where it is.
Find a mentor. There are tons of folks who would spend an hour every week answering questions about design that you were too shy to ask in the bigger group.
Stop meetings when you don't understand a term. Ask for a clarification.
Talk to your manager, be open about wanting to improve this specific skill. Speaking as an engineering manager myself, one of the most fulfilling parts of my job is seeing someone ask for help and giving them a chance to stretch and learn.
Accept failures. A failure just means you learned something. I've seen some big failures and caused some big failures. I learned and moved on. That said, don't fail the same exact way more than once if you can help it.
Ask for peer feedback. Maybe no one else thinks you aren't performing. Maybe you've set up a false narrative about yourself.
Ask, specifically, "am I asking for help too soon or too late" and really listen to the answer.
For the first 3-6 months, companies probably care more about having newcomers get up to speed on matching the style & convention of the existing codebase.
It helps to do an architecture review of the codebase and understand the overall code design focus, and pay attention to how the code is typically structured. you could also look at other people's code reviews to see what the common areas of design thinking are.
Next time you're writing something of any significance, speak to the people on your team who will be reviewing the PR. If you aren't sure of how to design it, come up with a design collectively. If you do have an idea, ask them to approve it on a high-level before you write any code. The entire thing should be a collaboration, not you coding for however many days before finally exposing your code to your team in the form of a PR.
This can be easier said than done, depending on how communication works at your company and on your team, but if your team and the people reviewing your code won't guide you a bit before and during your implementation of something then again I don't think knowing a couple more patterns is going to solve this problem.
Ouch. It should be quite rare to change your design after code review. Something is wrong here - either you've done something really unusual or your PR reviewers are being overly critical.
If your design is off, or it is way out of step with the usual style of your team, it's very late to change that during PR. There's a huge time cost, and it would be dispiriting for you.
I suggest requesting some pairing during your work on your next feature to get you up to speed with what the team expect. It's far more efficient to get guidance beforehand than retrospectively.
If your team is not keen on the idea of pairing, then getting a colleague to discuss your approach before starting might be useful.
If you want some specific recommendations, learn some functional programming techniques and read the classic programming books. /Clean Code/ has dated badly in some ways (try to ignore some of the crazier ideas) but it is excellent at provoking thoughts about how to lay out code.
My personal routine: before pushing code on the repo, run git rebase -i, review all your commits and change them if anything looks wrong (the commit message, some random crap being mixed with the actual content of your commit, silly mistakes, etc.). It will cost you around 2 minutes per commit maximum, and your pull request's quality will increase dramatically.
Also, git add -p when committing to review your work as soon as possible.
Have you talked about this with colleges? It could be that they don’t see it the same way as you. And they are happy to work with you.
I think most companies are terrible at doing code reviews and focus way to much in the wrong thing. You, as a team should create value for the company, not talk about the cutting your slightly to long method up again and again.
For me this code review video really opens my eyes:
The longer I worked the more bugs I introduced and the more I looked for the bugs in the evening the worse it became.
Ensure a proper work-life balance and plenty of screen-free time. Do not spend the night gaming when you work onscreen all day already.
The ideal per day work hours are 4h! No joke. In case you have to work 8h or longer perform simple tasks in the remaining 4h (meetings, documentation, emails, errands).
Eat well, get enough sleep, exercise, meditate, go outside and the next day you will find the bug and fix it within 10 minutes.
Many programmers tend to be the prototypical zombies who never see the light of day and only survive on caffeine (give it up). Remember that you're human.
1.) It may be that you learn different standard of coding practices, they vary a lot between companies. Each company have groupthink of "this is definitely necessary" other companies never heard of or have completely opposite groupthink.
2.) It may be that you miss some fundamental skills, but it is hard to guess which it could be and point you to right direction without knowing more.
3.) Another orthogonal option: you might run into alpha coders making themselfs feel good and look great by overly criticising others. I am adding this as possibility, because that absolutely exists.
To distinguish 3, start taking notes of what feedback you get. First, if they are contradictory, then you know it is situation you are in. Second, that will allow you to not make similar mistake again, learn local culture and habits.
You sound to me like every early career employee experiencing imposter syndrome. That feeling might not ever really go away, but you're probably doing much better than you think.
As to design, it is also often very subjective. Some designs lead to less code: this at least is measurable. Others are outright clearer but this is less measurable. When discussing maintainability, stay focused on _realistic_ scenarios: what if we need to add an X, to handle Z in addition to Y. If you think a possible generalisation is not realistic, refer to your manager or with peers, head to head.
More important than design, get confidence that your algorithm is correct and show it. Show that you thought of corner cases and handled some of them, traced those you do not handle.
As to performance, be very clear about it: performance can only be _measured_. If you and a reviewer disagree on assumed performance, candidly ask if there is time to implement both alternatives and profile them. If you know your code will be less than efficient when some data gets too big, comment it in the code and explain why this is acceptable for now.
Oh and if there are comments on style, ask the coding conventions in force. When you have them _respect_them_ and refuse further changes on things that are left unspecified.
Finally, talk to people head to head (or by phone) and not only through the review system, where things escalate quickly. Sometimes you will learn new technical stuff, sometimes the reviewer will admit "maybe my proposition does not apply in your case". In any case you would have learned something and increased your understanding of the problem to solve.
Are these standards published? If not then how are you expected to meet "required standards" that are not published? If so then why are you not reviewing your code yourself prior to the PR? Is training and/or mentorship provided for you to come up to speed with the required standards? Something seems off about this situation.
1. Write the test first, start with the smallest cases.
2. Write the code to make the test pass, the first thing that comes to mind which works.
3. Refactor what you just wrote. Use functions to remove unnecessary intermediate variables, avoid repetitive code by extracting common patterns, turn literals into parameters constants, etc.
4. Add another test, usually an inductive step. If your base case, smallest input is n, try writing a test that should pass for n+1.
5. Repeat 2-3 until the new test passes.
6. Add the smallest edge cases that should return an error result or fail.
7. Repeat 2-3 until the new test passes.
Keep building up those tests as you go. They should form a low-level specification of a module, class, or function that suits your needs.
Some high-level principles to think about when coming up with tests:
1. Parse, don't validate! [0] Code that takes data in from the outside world should do it best to parse it into an acceptable structure as early as possible so that code down stream doesn't have to check if the data it receives is valid or not.
2. Push effects to the edge If something has to talk to the outside world make sure it happens in, ideally, one place. Writing tests first ensures that your code is easy to test so putting effect-full code all over the place is painful.
3. There are different kinds of correct. Know ahead of time what success will be for your task. Passing tests is one kind of correctness. Functional correctness of the system is another -- you will want to reach to tools like TLA+ or Alloy to write specifications for the latter.
4. Talk to your team. Sketch out your ideas first and shop them around and spit ball them with other experienced team members. Get their take on it before you start coding.
[0] https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-va...
update forgot the link
Chances are there are related things to work on that you haven't even noticed. And chances are ongoing feedback with someone with context about you is going to be much more useful than replies from internet strangers. I recommend finding a mentor. A nice side-effect is that thhis shows you're proactively addressing the shortcomings.
A big, decent organization will have the structures in place to help you learn this. I'd suggest bringing it up at your next 1:1: 'I'm a bit worried about how I did in these PRs
1. Designing/Picking your data structures
As you begin to code, your output and data needs might change; this might need you to change the design of your structures. Some novice developers, might think 'screw it, I've gone this far already. I've already spent a few days on this. No going back now.' If more time was taken in the beginning to plan and choose, you might be able to avoid this.
2. Refactoring.
Leave yourself some time to refactor before you push a commit. Those extra few hours or day will give you time to really go through your code and tidy it up. Think of your first commit as a first draft, then do a couple of revisions before you squash and push.
Good luck.
That's what you're doing.
Slow down. Spend more time planning what to build, discussing what the acceptance criteria mean, designing your code, writing tests, thinking about your data structures, etc.
It'll feel like your velocity is taking a hit but the fact you no longer have to do the work twice will likely mean you're actually delivering features much faster.
I feel like most times i could have chosen a better way to do things, but i have to get things done quickly because the todo list is so long. It's difficult choice between technical debt versus slow but beautiful/robust architecture.
Working in my own company i often weigh the options between pushing often and fast, having a good deployment process that you can easily rollback, good error notification and being good in a debugger versus slow mindful development.
Trust me i would like to slow way down and really think things through, make interesting diagrams, think about the philosophy of different process and scenarios, drink a good cup of coffee and look out the window for half an hour pondering - but i feel like that's a privilege i don't have right now.
Though i try to meditate and to take a step back every day to slow things down and get a better overview.
I also feel like internet surfing, stack overflow, and screen use in general trains you quickly to get a completely fragmented way of focusing and remembering that we all need to actively fight if we want to regain clarity, focus, insight or beauty in what we do.
Second, what is a decent speed of delivery? The thing that most affects speed of delivery is familiarity with the code base. The major, probably only reason senior devs are senior is because they are senior in that codebase. Pluck someone from Facebook and drop them in Google and they will face problems similar to you. Good ones will explore on their own, familiarise themselves, find mentors and build relationships to ask and guide themselves - and even write posts on HN to get guidance!
Thirdly, expecting speed of delivery is the fastest way to destroy a team - or a coherent codebase. People get panicked and either drastically drop their productivity or choose to code really safely, driving code reviewers / team leads to spend more time on managing - whereas removing project managers from the critical path and having an engineering quality as the prime driver is a major help (You night think you are being rejected because quality is too low (and that maybe) but what are the senior devs being driven by? deadlines or quality? That will affect the time they have for mentoring.
This fear is all pervasive - senior devs do t want to venture out of their comfort areas, partly due to time constraints (see project management) and partly fear of not knowing how to intersect with other codebases and people.
passing over code patches to another team is always an act of human relationships - you need time to get up to speed with the codebase, they need good patches to trust you and they need to give you time and mentoring to understand the code base and their taste.
Long story short - asking this is a good sign about you and a bad sign about the mentoring process you are under.
* Use a statically typed language that allows fast refactoring. Ideally a typed functional language like Elm, Reason, OCaml, or Haskell.
I recently shipped a complex Javascript project (without types) and it is one of the few instances of my decade-old professional career where I had that level of confidence in the robustness of a piece of code I wrote. It remained sturdy in production even in the presence of unforeseen conditions. This was thanks to the habits I picked up from typed FP: parsing and validating all data at the boundaries of the system, better design by modelling data to make inconsistent states impossible, and automatically handling all edge-cases at all times.
So even if you don't actively use such a language in your workplace, there really is a payoff to learning it in making you a better programmer overall.
That you're being challenged, while it's difficult and you might not see it now, is ultimately a good thing. The uncomfortable feeling you're describing is called growth. The caliber of people around you is forcing you to grow, and that's going to be very helpful to you as a developer.
Seek out a mentor and actively seek their advice. Most people love helping others. The most important thing is that you don't try to hide from them, but that you're willing to openly discuss your areas of weakness and seek improvement. It's hard, but people will appreciate that.
It's true, people won't have patience for someone who isn't honest and delivers what they see as low quality work at the last minute, but they have tons of patience and even respect for the person who actively solicits and integrates feedback.
To underline the importance of what you're saying - one of the most interesting learnings so far from the data we've seen (~400 developers using it for the last month to log issues in their code/processes, >1,000 survey responses) is that the average developer encountering an issue loses more than twice as much time in Planning and Deployment than in Writing Code. The reason the data shows for this is that when there is an issue in Planning it wastes a very larges amount of time.
The other trend we've seen is we ask developers how each Pull Request made them feel (Happy/Neutral/Sad). We have literally not yet had someone give feedback who felt sad! So you can make your team happy just by asking and listening :)
In coding, this means thinking through how you're going to structure it, have answers for what pieces of code use service calls and what needs to be its own modules. Think about the data and what it looks like: what fields and names does this have? Does it require a set or list collection?
Following up on that train of thought watch the Simple Made Easy talk and really try to internalize what he means when he talks about design.
Pick a certain starting point and follow it down the rabbit hole. Rinse and repeat.
A couple things I find helpful about this practice is: one, it let's you compare the over all architecture against the true implementation (which can vary), and two, it gets you comfortable with the implied standards--the things that can't/don't get written on a style guide (e.g. they keep prepared statements in a separate, common file)
Second: take your code reviews as a great learning opportunity. Don't let it take you down. You are probably getting the "Impostor Syndrome", and it is a good thing since you now know that you need to improve. Take the review process as feedback about how to improve. This is Deliberate Practice at its best.
No, I'm seriously.
- - - -
Read "Thinking Forth" by Brodie ( http://thinking-forth.sourceforge.net/ ) and "Programming Pearls" by Jon Bentley ( https://archive.org/details/ProgrammingPearls2ndEditionJonBe... ) and sleep on them.
This is probably the biggest problem. You are thrashing on a cycle of testing because your code didn't work properly the first time. Getting it right the first time, even if it feels slow, is usually faster than fixing it later.
In my experience this is what happens when developers focus on the "happy path", i.e. spending most of your time assuming your code will run in a perfect world, and writing tests to prove it.
You may want to try working backwards from the tests -- decide how your code should behave, especially in bad situations where inputs are null or your dependencies throw exceptions or your API calls fail. Write the tests, and then fix your code to make the tests pass. Use coverage tooling to make sure you covered what you thought you did.
If you still have problems, try asking some of your colleagues to spend half an hour with you to review your code before you submit it for review. Some of them will probably be happy to help the new guy, especially if you are trying to do a better job meeting their expectations.
The velocity is only important to managers when they are using it for comparison against other engineers when doing performance reviews. Focus on getting it right the first time.
You need to be able to explain the architecture of what you're programming, the reasons being:
- Code is processed by machines, but read by humans
- Code is read by many people, written by far fewer
- If you cannot explain design decisions, then expect criticism of it
- Naming is hard, but reading badly named code is even harder
As for taking 3-4 tries, I think that if you stick with it, you'll get better as time goes. Learning about design patterns, even if the tutorials seem worthless at first, might come in handy. Better to be aware of the patterns before you need them than after.
Are your solutions overbuilt? Poorly documented? Introducing new patterns where they aren't needed?
The biggest clue I've got to work with is:
> I refer to stack overflow or ask my colleagues if I get stuck on some design / technology feature which I haven't seen before.
I'm searching up the problem as many ways as I can before I even get started. Even if I think I know how to do something, there could be a better way to do it.
> the rush to complete the deliverable on time
If you're rushing, you're doing something wrong. Here's a secret: it's way more important to be reliable than it is to be fast. Who's setting the deadlines? Is there a way you can squeeze more time? A lot of junior devs underestimate things habitually.
Whiteboard a design with a colleague, socialize your ideas.
Open a “do not merge” pull request early and keep pushing changes to it. Keep your lead/mentor tagged and request early feedback.
In a large codebase there are usually many many conventions like “this is THE WAY we do such and such” and it’s important to pick these up. It can be difficult to find these they are not always well documented.
Really, practice. Build things. Write a lot of code for your job. Write a lot of code for yourself on whatever interests you. Put in the hours or keep putting them in if you already are and your knowledge will continue to compound.
For example, I work on a C# product. We have particular patterns for dependency injection, events, and multithreading. A newcomer from a different department once made a pull request that used static singletons and different event semantics.
In this case, the newcomer gave a lot of pushback because we do things differently than the textbook examples of C# that they're used to. Our way meets the design needs of our product, thus it's the "right" way. The way that this developer made changes would be "correct" in a different product with different design needs and conventions.
Normally, we avoid this by spending time with newcomers to explain the styles and patterns in our codebase. (In this case, this person from another department wasn't onboarded and just surprised us with a pull request.)
We do document our coding style and design patterns; but it's important to point out that documentation is no replacement for common sense.
If you've made it this far:
1: Professional programming isn't art or poetry; it's all about the finished product. Computer code is NOT a place for your self expression or creativity. (If that's important to you, go make some Wordpress themes or hack some other program to be skinned.)
2: It's important that professional code has consistent style and design patterns, otherwise it's extremely hard to read each time a module uses a different style.
2.5: Thus, the most important part of good style is trying to fit in with the existing style whenever possible. (IE, if you use tabs, but everyone else uses spaces, you need to switch to spaces.)
3: If this is a case of "growing pains," take the time to document your codebase's style, design patterns, ect.
At the basic level, I try to have...
1) Comments in code
2) Meaningful function and variable names
3) Breaking large piece of code into small functions or methods.
4) Committing the code to GIT/SourceControl whenever a small incremental step is completed.
5) Discussing your design/worlflow with lead before the development also helps to have common agreement.
Sometimes, the code reviewers have difficulty in reading the PR if it spans multiple files or projects. In that case, I had to sit with them and explain the workflow and later they are able to review the PR.
If this is happening once you're in an integrated environment, then it is too late. A strong test driven development culture in the organization can help with this, and improve design - but if it's not already there, it's hard to justify the investment without first proving you can write quality code.
When you think your code is ready to review, ask yourself what you could improve in twenty minutes or a half hour. If you’ve been working on something all day or for days, nobody is going to notice an extra thirty minutes.
Also code reviews are a training method at some places. They’re trying to normalize style and you don’t know it yet. Take the feedback seriously, yes, but don’t panic about it.
How long has it been since they hired somebody else? Stable teams can have serious blind spots about both the level of knowledge required to become effective, and they often aren’t used to having their ideas challenged (even if it’s only different idioms in code).
As an example from said pr, a new field was added named "other"... in this particular context this doesn't have any meaning at all.. I had to look into the sql changes to see what this data was then add the suspected real name as a suggestion in the code review... don't do things like that :D...
So, all that to say, look at your diffs and do your own code review before you submit it.. make sure what you want to do is clear and makes sense...
That means that a PR could be approved by Facebook and exactly the same code outright rejected by Microsoft.
My experience is that my code can be rejected by people with 5 years experience or less while I have almost 20 (professionally) simply because they have been in the organization and with the code longer.
It can still make you insecure, especially in your trial period.
Check the PRs and read the existing code from others inside the company. Presumably those meet the company's standards, and will give you hints how to structure yours.
Read a couple of industry standard books like Clean Code and Code Complete too.
So, instead of trying to get the definite code from the get go, start with a simple design (yagni and kiss) and evolve from that.
But there is no silver bullet. You can get faster but not by orders of magnitude. Quality code takes time.
Personally, I go after the feeling I had when I studied programming in the 90s. Simple algorithms that manipulate strings, ints, etc. and no so much after abstraction and composition.
If that works well and you and your team like each other, then you can go on. If that bare minimum is not working then find a new team a and start from day zero with this approach.
If you don't get support from your current manager start looking to switch teams to find a manager that is geared towards developing you and making you a success.
For your design phases, think thoroughly about all possible solutions and detail the pros/cons of each, then get it reviewed by your colleagues and iterate on that. The design phase might be slow, and it is OK. At least when you will end up implementing something it is likely to be of much better quality.
After a while this will become natural and your velocity will naturally go up.
something else you can try is to run your designs by a colleague before/during coding, preferably the same person that will do the code review
Another advice would be to explain as part of your PR (e.g., in the ticket) which design options you considered and why you chose the one you ended up with.
Also I've heard at FANG companies the first few months code reviews will get hammered to make sure people get in line. I'm not sure how accurate that is.
There might be in the CRs you're mentionning. In other words, my advice would be to get the most out of those CRs as you can. Ask questions, encourage people to be critic with you, understand their point of view and learn. If you CR is rejected, get to the core of why it happened technically.
Your team might just be more opinionated when it comes to design. Some teams I've worked on are very particular about things, some are not.
Also be aware that not all code reviews are good. Engineers have opinions and may wield code reviews as a tool to impose theirs on others. In those cases it doesn't reflect you or the quality of your work.
> I usually take 3-4 tries with some significant amount of testing to get my code to a working state.
That's pretty normal. Try to use TDD, that is, try to test your code ASAP.
can you give us some examples of this? Do you agree that your design didn't meet the standards?
Its entirely possible that your new team is being mean to you, I'v seen team politics play out in PR reviews.
(1) Does what it is supposed to do and nothing more;
(2) Is easy to read;
(3) Is easy to change;
(4) Is efficient enough.
Note that these points are somewhat strongly ordered. If you have to make a trade-off between "maximal efficiency" or "can be read by the rest of the team", you choose readability, unless "maximal efficiency" is required to meet a customer deliverable ("acceptance criteria").
Note the word "required". As in, "we have promised our customers to service requests in under 2ms, and these rather unreadable performance optimizations are the only way we can do this", not "the lead programmer likes 'efficient' code". That's not to say you should be stupid about performance -- see (4), above -- but that your goal is to deliver value to the customer, not to build a technical monument to Donald Knuth.
That prompts the next thing we need to talk about: what do we even mean by "high velocity"?
Clearly it isn't just writing a lot of code. Were that the case, we could measure productivity in LOC/day. And it isn't in always using the minimum amount of memory or smallest number of CPU cycles.
From a business perspective, "high velocity" means "delivering working features to our customers as fast as possible... forever".
That last bit is important. You aren't going to get one feature request, scratch that off in a frantic 48-hour marathon of caffeine and hackery, and then be done with the rest of your career.
New feature requests, changes to existing features, unexpected behavior that needs to be changed... these are life as a programmer. Smart programmers recognize this, and build their code to be easily changed.
Now, you can't do this by trying to anticipate every future need. Building code to support an uncertain future is where the vast majority of technical debt comes from, because 90% of the time, you'll just be flat-out wrong, either grossly, or in sufficient detail as to render your attempt to defend against change moot.
Instead, you follow a set of coding practices that help you design systems and build code that can respond to future change, without having to know anything about what those future requirements might be.
To that end, I highly recommend Sandi Metz's POODR[1] and 99 Bottles of OOP[2].
Yes, the title of the first book ends in "Ruby". Ignore that part, as it's probably the best primer I have ever seen on building code for the real world.
I have also found that strong TDD -- and yes, I'm lumping BDD in with this, don't be a pedant -- has helped me to learn to write much higher-quality code over the years. Code that is fully-tested can be changed with a high degree of confidence that you haven't broken something unintentionally, and writing tests first forces a lot of highly beneficial design choices.
GOOSGT[4] is a good place to get started with TDD.
Last but not least, recognize that all of the above are skills -- you will need to devote time, and a lot of repetition to learning them.
[1] https://www.poodr.com [2] https://www.sandimetz.com/99bottles [3] http://www.growing-object-oriented-software.com
I currently work at a place in the valley as a senior lead and it is _impossible_ for me to submit a PR without comments/nitpicks requiring fixes. My colleagues seem to always want to change something for some reason, whether or not it is a necessary change. The feedback comes in from all skill levels. Honestly most of the time these changes can be (and should be, IMHO) ignored because of YAGNI and Not Invented Here. I can't count the number of times I have re-designed and implemented something to be more generic/abstract only to have that abstraction whither for _years_ without being used. Oh - and implementing our own wrappers for third party libraries? We do it all the time.
The challenge that I face is every time I get frustrated enough to push back and escalate, ultimately when discussing code reviews and velocity with managers, my colleagues drop the "Q" word and it's an argument-ending trump card: quality. If anyone can argue that any trivial change increases the quality of the code base, or can argue that my PR lowers the repository code quality, the argument is over. Regardless of whether or not it's objectively true, if it's subjectively true the argument is over and ultimately any feedback has to be implemented. Management doesn't budge on quality.
Ultimately though, end users and customers don't care about code quality (but the do care about product quality, there is a difference).
I have worked at this company for 6+ years. The product is uninteresting to me, but the people are actually a really good fit for me. We otherwise work really well together when doing actual problem solving, requirements gathering, manager managing, customer support, etc. It's frustrating to not be able to write code in one pass, but I've learned to 'accept' it - it's the nature of the beast. It's definitely not like this everywhere; I've worked at places that were much better about code reviews and merging code. Code that takes a day to design and get requirements for and a day to code and test will usually take a full week to get merged (not uncommon for it to stretch to two weeks). If management is fine with our velocity, then I guess I ultimately don't care.
Anyway, I recounted all of this for you to give you another data point and perspective. Some places thrive on this sort of torturous review process. I've learned to live with it. It's entirely possible that there is no way for you to 'improve' your way out of review hell. Instead of focusing on reading books and improving your design skills (which you should do anyway!) you might need to learn how to navigate the code review landscape at this new place, either by accepting it or playing the game.
I don't know how to tell you to play the game except get more involved in the review process as early as possible. Figure out what is important to people. I've gotten into the habit of "pre-screening" my reviews with one or two of the most problematic reviewers. I've gotten to the point where I will commit a pass of pseudo-code and have them give me feedback. It makes them feel better and wastes less of my time when it comes time for actual review.
Having your PR rejected in a toxic environment can mean a lot of things, and a company sought after doesn't mean that it MUST be not toxic.
First, you have to make sure if both of YOU and YOU ENVIRONMENT is healthy. If both are healthy, proceed reading.
> The challenge here is to deliver good quality code, while maintaining a decent speed of delivery.
You made it sound like producing good quality code = slowness. FALSE. Seeming slow, good quality code boosts your team's velocity. BUT keep in mind: "quality" is "the standard of something as measured against other things of a similar kind; the degree of excellence of something". Your team has its standards, either is a derivative of other globally acknowledged standards such as https://blog.golang.org/go-fmt-your-code, https://github.com/microsoft/TypeScript/wiki/Coding-guidelin..., https://twitter.com/dan_abramov, etc, or self-made standards. You go follow them, make them happy!
Coding and design skill has a different definition than code quality. It is what punches up to the sky: the overall velocity, the success of the team, the balance of growth and culture retainment of the company, the development experience, the users' thumbs ups, amazements, and "this app is life changing" comments, the number of milestone celebration in All You Can Eat restaurants each years, the number of people rising up from junior to senior each years, etcetera etcetera.
Not only you make your team happy with the quality code based on their standards. You must always exercise to always improve your team, whether your team agrees or not AT THAT TIME. Keep searching for improvements, internally and externally. Occasionally fight with your team if you have to, if you have the right cause. And if it turned to be a wrong cause, accept and move on.
So...
> Are there any good ideas to improve one's coding/design skills significantly?
Yes. These are the tricks to a good code/software/system design and architecture:
1. Know the fundamentals! Go lower than frameworks and libraries! Analyze why existing codes are made that way! Think in strings, C, algorithm, data structure! Always pay attention top-down and bottom-up! Think in terms of time and space complexity! Separate complexity from complications! Be thorough.
2. Know the team! Know what is valuable for the team! Understand how your code impacts your team's velocity! Understand the mood of the team and use it! Contemplate how existing processes help or hinder the team! Consider suggesting to add or remove them if necessary! Make interfaces for others! Learn from the team! Cooperate with your team so that you guys can reach higher! Be critical to your team, conflicts can make you stronger! Be humble.
3. All that glitters is not gold. Some very popular libraries and tools that might not be as good as you think. Learn harder. Make something better if necessary. Think of both the big picture and the details at every step you make. Don't overweigh technicality over business requirement, and vice versa. Be critical.
> Now I'm a little worried that if my situation doesn't change, my career would suffer.
Be strong. Feel strong. But stay thorough, humble, and critical. And you need to care achieve them.
I've been there, laying afraid that my career might suffer. I've been in the reviewer's spot too, being too strict, forcing engineers to change the design, sometimes compromising the engineer's personal feeling.
BUT I've also successfully convinced and lead a rewrite the core of a pretty big project (which people are really afraid of the risk) so that the engineers feel safer when building on top of the core, and in turn make them tens times faster, while at the same time growing some newer engineers to the point of one of them being a lead of a team handling a pretty big project for a customer which is pretty prominent in the gaming industry, IN JUST HALF A YEAR. (sorry, but not sorry for bragging lol :D)
You never know what good things are coming to you when you start caring.
Some random nice stuff to learn that I remember might help you with the design stuff:
https://medium.com/@thisdotmedia/the-cost-of-premature-abstr...
https://raphlinus.github.io/ui/druid/2019/11/22/reactive-ui....
https://www.youtube.com/watch?v=yy8jQgmhbAU
https://blog.dropbox.com/topics/work-culture/kim-scott-inter...
First of all, there is probably a style guide for your programming language at your company. Read it front to back. Your IDE may be configurable to automatically bring code up to these standards. "Look and feel" and using consistent language features are very important for others to be able to easily digest your code and be comfortable with it.
Second, there are likely resources for learning your common libraries (like your RPC and presentation libraries for example). Go through those thoroughly. Make sure you understand the common patterns and how they are used in the product you are working on. Apply this learning to your design before you start writing code.
Now that you have context, look at the specific feedback you've received and look for resources internally and externally for how to improve the issues that have been raised. Have you been misusing language features? Writing incorrect unit tests? Improperly using abstractions? Scoping functions incorrectly? Make sure that the feedback you've received follows the style guide and tool use cases. Come up with a plan to address the legitimate issues. As others have mentioned, writing a checklist of pre-review items and doing your own code review is indispensable, as well as learning how to make use of any integration testing environments and debuggers that you have access to.
Finally, ask your team leadership for help. Have a chat with your manager. Do this after you have done the research so you have some specific examples of mistakes you've made in the context of coding practices at your company and your plans to address them, including asking for specific mentorship prior to implementation, like design review. Why to ask for management's help and not go to the devs directly? your performance is their job - where a senior dev may not realize it's their job to mentor you until the manager asks them to. Letting your team leadership know that you are being proactive to address this issue will go a long way and unlock more resources that you need. Design review could be whiteboard sessions but I personally prefer design documents describing what the feature will do, why it is needed, how it will work, and what the implementation milestones are. You bring this to the session for editing/feedback, don't go empty-handed and expect to design stuff on the fly.
Regarding your velocity concerns, this will/should come up during your conversations with your manager about your skill development. One good way to improve perceived velocity is to break down features into smaller milestones and complete those at a quicker cadence. Having a design document/review will help do this.
Asking how to improve is the first step. Good luck!
1. Make sure you understand the requirements for the issue at hand.
Make sure you correctly understand all of the work an issue is supposed to encompass and no more. Use all available documentation, issue descriptions, designs, notes, and any other resources. As a last resort, as in the project is not well documented, start putting together questions to ask someone. Craft your questions in advance and ask them strategically and it will save you time. This is not all on you, better documentation, grooming, and other processes can help you work faster, and it might be something worth bringing up at a retrospective or using any other avenue you have for feedback after some research into what exactly is going wrong and what other people have done to solve it.
2. If you haven't already, start looking into completing the issue from a technical standpoint.
No issue exists in a vacuum, and there is probably already existing technical architecture surrounding the issue, or something similar that is already being done. Good code conforms to the standards around it, and a good team codebase looks like it was written by one person. Not copying code, but using it as a general blueprint can help you get past code review by following unwritten established standards of the team. Of course, if there are written standards, check those too. Make sure you understand all of the technologies used by the code you're following, it probably has documentation. Try to understand any technical decisions that don't seem clear. Follow the guidelines in the previous point for asking questions if you need to. If any technical decisions need to be overturned, consider making refactoring part of the issue if at all practical (this is a whole other can of worms, so you'll forgive me if I don't get too deep into it).
Keep in mind that version control tools can help you understand why a decision was made, particularly if you learn to use tools like `git blame` and `git log` (assuming your team uses git), or even more powerful integrated tools like [vim-fugitive](http://vimcasts.org/blog/2011/05/the-fugitive-series/) or [magit](https://magit.vc/manual/magit/index.html#Top) if you use something like VIM or Emacs.
If there are any new technologies and technical decisions that are part of your issue, try to gain a rough idea of what your implementation will look like and try to learn as much about the technologies as possible. If you are not in a decision-making position, it is best to run your ideas past someone who does once they are concrete if you can. Of course, sometimes, it is easier to just start writing code. How low level or high level your planning is up to you, but it should probably depend on the complexity of the issue at hand. Don't be afraid to take a couple passes at it, better now than later.
3. Start implementing.
When you are actually writing code, a good process makes all the difference. Some people use [TDD](http://agiledata.org/essays/tdd.html) or write all of their inline documentation ([example](https://jsdoc.app/)) beforehand, which can help you quickly refine and complete your implementation details without actually writing any code yet. This, again, helps you rework your ideas early on in the process. I use a mix of documentation, testing, and any [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93prin...) that's available to me to test out code beforehand depending on the issue, which is not the most straightforward method. Try TDD at least once and see what works for you.
A good dev system can help a lot. If you can get the code into a working state and compile it often to test it, do so. Any other dev tools for testing, documentation, linting, debugging, etc. for the project, learn them and use them.
Once you're done making some changes, look over your code. Clean up anything you can, and don't be afraid to make another pass at it if you need to, especially early on.
Planning out how you're going to get things into a working state and split up your changes (commits in git) early can sometimes help, but sometimes it's easier just to clean up your commit history later as you're reviewing your changes (getting familiar with `git rebase` can help with this).
4. Submit your merge requests/pull requests.
If you can at all, get your code into a working, logically separated state often and submit small merge requests/pull requests often for review. This can help you correct your tragectory early on if you still need to take a different direction. Familiarity with git or the VCS you're using can help a lot with dealing with multiple branches of code. As with all things, give your pull request one final look-over before you submit it for review and clean up anything you need to.
tl;dr: understand everything you can, ask questions, plan ahead, take multiple passes early, and make small changes
..this is a "code" smell to me. if you are jr, then ok, otherwise you got some serious problems nad put your focus in the wrong places.
anyhow, one advice i can give you, or anybody else, is - when you're doing it right, it just flows. when you're banging your head against a wall, you took a bad turn in your decisionamking process a while back and need to retract your steps. this one usually can save you from writing about 80% of useless code. when you are bored and are not looking forward to write something, you are on the right track. if you feel creative and full of energy, you are thinking on your feet and have no idea where it will lead you. sure, this is the best part of coding, the creativity, but not in the business world. that is for your personal projects. boring is good. be creative in preparation, not once you're already undertaking a task.
Serious developer do not refer to stackoverflow. Developers should use stackoverflow only to lookup for names of functions or methods. Nothing else.
When you find what you are looking for, then you go reading the official documentations. In the extremely rare and specific case when the documentation is not there (and when you cannot change the library that you are using, why would you use a library without documentation?) then you go read the code.
If the majority of your time is spent copying and pasting (with slight modification) from stackoverflow you are extremely junior in that field.
I see it on myself, when I do backend work stackoverflow is not even on my tabs. But when I do some frontend for personal projects I just keep going back and forth.