Thursday, June 13, 2024

Success as a Senior Developer

What qualities make a senior software developer successful?

Many of them are the same qualities that make anyone successful at work. Here, I break down the general qualities necessary for anyone and then drill down to particulars for software developers. 

General Qualities for Success at Work

  1. Presentation and Grooming:

    • Presenting well
    • Dressing appropriately
    • Being well-groomed
  2. Behavior and Interaction:

    • Acting appropriately
    • Being polite and friendly
    • Having a sense of humor
    • Genuinely being a 'team player'
    • Practicing cooperative habits
    • Turn-taking
    • Promoting other team members
    • Contributing to the mission
    • Upholding esprit de corps
    • Supporting supervisors and subordinates
  3. Professional Attitude:

    • Not necessarily being a superstar
    • Keeping abreast of changes in the zeitgeist and corporate culture
    • Being comfortable in your own skin
    • Being principled and respecting others' convictions
  4. Work/Life Balance:

    • Maintaining a reasonable work/life balance
    • Satisfying Maslow's hierarchy of needs
    • Having affiliations outside of work for personal support

Specific Qualities for Successful Senior Software Developers

  1. Technical Proficiency:

    • Mastery of relevant programming languages and tools
    • Understanding best practices
    • Keeping up with new technologies and methodologies
  2. Experience and Knowledge:

    • Extensive experience in the field
    • Understanding the full software development lifecycle
    • Familiarity with different types of projects and challenges
  3. Code Quality and Best Practices:

    • Writing clean, maintainable, and efficient code
    • Following coding standards
    • Utilizing design patterns
    • Conducting thorough code reviews
  4. Problem-Solving Skills:

    • Approaching problems methodically
    • Breaking down complex issues into manageable parts
    • Thinking critically about solutions
  5. Mentorship and Leadership:

    • Mentoring junior team members
    • Sharing knowledge and helping them grow
    • Inspiring and guiding the team
  6. Communication Skills:

    • Communicating clearly and effectively with team members, stakeholders, and clients
    • Explaining complex technical concepts to non-technical people
  7. Adaptability and Learning:

    • Staying curious and committed to continuous learning
    • Pursuing formal education, self-study, or experimenting with new technologies
  8. Attention to Detail:

    • Preventing bugs and errors through meticulous attention to detail
    • Conducting thorough testing and careful code review
    • Proactively identifying and fixing potential issues
  9. Project Management:

    • Understanding project management principles
    • Managing time, resources, and expectations effectively
    • Accurately estimating work and delivering on time
  10. Collaboration and Teamwork:

    • Building strong relationships with colleagues
    • Working effectively in a team
    • Understanding team dynamics and being open to feedback
  11. User-Centered Design:

    • Keeping the end-user in mind throughout the development process
    • Ensuring the final product is functional and user-friendly
  12. Ethical Responsibility:

    • Upholding ethical standards in work
    • Ensuring code and products do no harm
    • Respecting user privacy and security
  13. Defensive Development:

    • Developing defensively in terms of team formation, system design, protocols, budgeting, and scheduling
    • Anticipating and addressing potential issues based on Murphy's law
    • Focusing on error prevention, detection, handling, and regression testing

Wednesday, June 12, 2024

Programming Exceptions Vs Old Rules

This will be objected to and ignored by most, but take it from an old hacker who has production code in place decades after designing, writing, building, testing, and delivering it:

Try/Catch, thrown exceptions, and assert() are things I associate with poorly designed code — code likely to fail in non-trivial production. Avoid these idioms. If possible, avoid languages that support them. Suspect development paradigms that blissfully support these things.

By their nature, ‘exceptions’ are pathological instances of uncaught bugs. The discipline of putting these things in place violates an old rule of thumb as to how code should behave. It is something of a prior commitment to the acceptance of bugs. Bugs are enemy number one. A single defect can ruin an entire system that took man-years to build. A single defect opens security defects that can annihilate systems and cause tragic stress in individuals who, empirically, we know have no effective backups to roll back to. Serious code is serious business. Bugs are No Bueno.

And yeah, these are skewed to procedural rules of thumb. Guess what? It’s because they work. Most all of the code you actually use is built that way. Phone apps (not built that way) need to be updated constantly by mandate from Google and Apple. I still use Microsoft Image Composer, written in C. The binary release I use is, as of 2024, 27 years old. These days, languages and platforms themselves don’t last more than a few years, let alone the things built on them.

A few old rules of thumb:

Single Responsibility Principle: A function should do one thing well.

Single Point of Entry and Exit: A function should have a single point of entry and a single point of exit.

Error Handling: Always check and deal appropriately with return values.

Re-entrancy: All code should be re-entrant. State should never be global.

Murphy’s Law: “Anything that can go wrong will go wrong.”

Keep It Simple, Stupid (KISS): Simplicity should be a key goal in design, and unnecessary complexity should be avoided.

You Aren't Gonna Need It (YAGNI): Don’t add functionality until it is necessary.

Don't Repeat Yourself (DRY): Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.

Separation of Concerns: Different concerns should be separated to reduce complexity and improve maintainability.

Modularity: Break the code into modules or smaller components that can be developed, tested, and understood independently.

Encapsulation: Encapsulate the details that are likely to change.

Consistency: Follow consistent coding conventions and practices.

Code Readability: Code should be written to be read by humans first and computers second.

Avoid Premature Optimization: Optimize later, focusing first on code correctness and simplicity.

Re: Murphy’s law, “Anything that can go wrong will go wrong” The article on Wikipedia, ironically, gets it wrong. I wrote about it here while writing this response:

Murphy's law is NOT simply an adage
It can be downright scary (a) how much people trust Wikipedia and (b) how unreliable it can be. Looking to find a simple statement of Murphy...

** This applies to code blocks as well.

Murphy's law is NOT simply an adage

ChatGPT Image Generator gets it Wong QED
It can be downright scary (a) how much people trust Wikipedia and (b) how unreliable it can be. Looking to find a simple statement of Murphy's law to cut and paste into a post, I find this gem: 

- Murphy's law is simply an adage and is not grounded on logic or scientific laws.
That is not only incorrect, it is a profound misunderstanding of what the adage means in context and what necessary actions it implies. Software that does not account for edge cases and corner cases (that can go wrong) will inevitably fail (will go wrong). To the extent that you leave an avenue to failure in your software, whatever it may be, you have a defect that in the fullness of time *MUST* be encountered. This article does a disservice to starting and even journeyman programmers by incorrectly framing it as a sort of 'figure of speech'. It means they won't know what it really means in terms of implementation and importance. It also means, if this is their source of information, they won't even understand it or be able to explain it to anyone else. I am, in this regard, a primary source, so I won't change the article, but hopefully, if you are someone who always goes to the talk page (as I do, and as you should do), you will at least be aware that a professional production programmer with more than forty years experience learning the reality of Murphy's Law in practice has a different point of view and this additional explanation.

Murphy's law is true, deep, and somewhat subtle in its implications. It is a simple statement of tautological fact. By definition if it is something that *can* go wrong, it *must* go wrong eventually.

Note: The misspelling in the image, "If it can go wong", is an authentic example of Murphy's Law in practice, perfectly illustrating the principle itself. Even in a text about preventing errors, an error has crept in, demonstrating that anything that can go wrong, will go wrong. ChatGPT that generated the image confessed that it made the mistake honestly. 

Explanation with Probability[edit]

Edge Case Probability[edit]

  • Consider an event with two edge cases: E1 and E2.
  • Let P(E1) and P(E2) represent the probabilities of these edge cases occurring.
  • Suppose P(E1) = p and P(E2) = q.

Corner Case Probability[edit]

  • A corner case C occurs at the intersection of two or more conditions.
  • If the corner case depends on both E1 and E2 happening simultaneously, then:
 
  • Assuming E1 and E2 are independent:
 

Visualization and Interpretation[edit]

Probability of Edge Cases[edit]

  • Let's assume  (5% chance) and  (5% chance).
  • These probabilities might seem low, but they are significant enough to consider in testing.

Probability of Corner Case[edit]

  • The probability of the corner case C occurring, given  and :
 
  • This is 0.25% chance, much lower than the individual edge cases.
[subscribe]

Murphy's Law Illustration[edit]

Murphy's Law states that if something can go wrong, it will. Applied to our scenario:

  • Edge Cases: Each edge case has a 5% chance of occurring. These are already rare, but still within the realm of expected events.
  • Corner Cases: The probability of a corner case is much lower (0.25%). Due to its rarity, it might be overlooked during testing.

Mathematical Picture[edit]

Imagine a grid where:

  • The x-axis represents one condition (e.g., E1).
  • The y-axis represents another condition (e.g., E2).

Each condition has a small probability of occurrence. The intersection (corner) where both conditions meet has an even smaller probability.

Condition Not Met (¬E2)Condition Met (E2)
Condition Not Met (¬E1)Common ScenarioEdge Case (q)
Condition Met (E1)Edge Case (p)Corner Case (p \cdot q)

Summary[edit]

  • Edge Cases
  • Corner Case

Implication[edit]

  • While edge cases are relatively rare, corner cases are even rarer.
  • According to Murphy's Law, despite the low probabilities, over a large number of trials, even these rare corner cases will eventually occur.
  • Because of their rarity, corner cases might not be adequately tested, leading to unexpected failures in real-world scenarios.

This illustration helps in understanding why it's crucial to consider both edge and corner cases during testing and why Murphy's Law suggests that these cases will inevitably manifest over time. 

Success as a Senior Developer

What qualities make a senior software developer successful? Many of them are the same qualities that make anyone successful at work. Here, I...