[{"content":"Picture this, you open a PR and the AI report is already waiting. Three findings, all minor. You skim the diff, approve, and move on. A month later someone asks why that service retries three times instead of failing fast. The author doesn’t know, because an agent wrote it. You don’t know either, and you approved it.\nI review PRs with an AI code review workflow (gist) that maps the blast radius of each change with CodeGraph, a local tool that turns the codebase into a queryable graph of callers and callees, and reports findings by severity. It catches real bugs. It can’t tell me why the code is the way it is.\nThe gap Link to heading Review was never mostly about bugs. Microsoft found that most review comments are about maintainability, alternatives, and knowledge sharing, what Brian Houck calls the invisible output of code review. I wrote about it back in 2020, in Every code has its audience: review is how knowledge moves between engineers, juniors reviewing seniors included.\nAn AI reviewer covers the visible output. The invisible one is getting harder to keep. The agent throws its reasoning away before anyone sees the PR, and PRs grew 64% while review time didn’t. Houck, citing Margaret-Anne Storey, calls the result intent debt: the gap between what a system does and what anyone understands about why. There’s a personal cost too. In my experience, using AI dulls the brain, especially for juniors, and review was one of the few places they picked up judgment.\nSo I changed where I spend my attention.\nThe Intent Header Link to heading A reader’s reply to one of my posts put a finger on the problem: design-time intent usually stays in a meeting or a chat thread and never reaches the diff. Without it, an AI review can only confirm that the code is consistent with itself. The fix it suggested, which I adopted, is to attach a short intent statement to the PR. I call it the Intent Header:\nIntent: the input, the expected result, and what must not happen. Decisions: what was chosen, what was rejected, and why. Acceptance criteria: derived from the intent. Proof: a log line that shows the behavior actually happened. For a password reset, it might look like this:\nIntent: A user who requests a reset gets one email with a link valid for 30 minutes. Must not happen: a second email for a repeated request within a minute; a link that works twice. Decision: rate limit in the API, not the mail queue, because queue retries would bypass it. Acceptance: two requests within a minute -\u003e one email; a used link -\u003e 410. Proof: password_reset.sent user=\u003cid\u003e deduped=false The author, the reviewer, and the agent on either side all check against the same statement, and the reasoning stays in the history after the merge. It’s close to what Addy Osmani calls a “statement of purpose” for agentic review, and it’s the written “why” I argued for in Code comments are your code autobiography. It also answers the question an engineer told me they ask on every PR: what would break if this didn’t work, and how did you check that it didn’t?\nRead the tests first Link to heading The sharpest pushback on that thread said review is a transition-era practice: AI acts as the gatekeeper, end-to-end tests validate, and the merge goes straight to production. The first half isn’t far from reality. Meta’s RADAR already auto-merges low-risk changes, though it still sends the risky ones to people.\nTests have a limit of their own. They check only what someone thought to test, and an agent that can’t make a test pass can change the test until it does. Another reply pointed out that coverage won’t catch this, since it says which lines ran, not whether any assertion would fail if the logic were wrong. Mutation testing does: it breaks the code on purpose and checks whether the tests notice. I’m a fan of short feedback loops, but a loop is only as good as the tests in it. That’s why I think the test changes in a PR should be read before the code changes.\nAnd even if one day nobody reads code, someone still has to define what the system should do and why. That’s exactly what the Intent Header holds.\nWhere the rest of my attention goes Link to heading I still read the code. As I wrote in The Joy of Negative Code Lines, AI is for acceleration, not abdication. I still click Merge, so I need to be able to explain the change. Design before code. Understand the requirements, walk through them, and raise risks and gaps before anyone writes a line. Data over hunches. Real numbers from the database or traffic analytics. Same rule as in effort estimation: don’t assume, measure. Deep design reviews. Hard questions, so the reasoning gets written down and challenged by someone other than its author. Challenge the task. Some tasks shouldn’t be built at all, as I wrote about complex features and cargo culting. The cheapest code to review is code nobody needed to write. The Bottom Line Link to heading Houck closes his piece with this: “AI should absolutely reduce the time we spend reviewing code. It just shouldn’t reduce the amount we learn from it.”\nIf you automate your reviews, decide where the learning goes. For me, it goes into design reviews and the Intent Header at the top of every PR.\n","id":0,"tags":"codereview ai softwareengineering technicaldebt","title":"AI Approved the PR. Nobody Knows Why the Code Works.","url":"/posts/ai-approved-the-pr-nobody-knows-why-the-code-works-a7f71e96dd63/"},{"content":"Every engineer has a “Mystery Case” story. 🔍\nFor a long time, mine was a service that would run perfectly for weeks, and then, always at the most unexpected times, would violently consume memory and die.\nI didn’t just ignore it. I fought it.\nI analyzed logs, optimized code to reduce allocation pressure, and even claimed a “False Victory” once, deploying a fix I swore was the root cause. The crash stopped for a week, then came back.\nWe kept restarting the system by hand to keep it running, but we didn’t know what was really causing the problem. We tried hard to find out why, but checking things manually wasn’t enough. There was just too much data to look through, which hid the important facts. Trying to piece it together ourselves took way too much time and effort. Because we didn’t have a better tool to help us, we got stuck.\nRecently, I finally solved the case. Not by traditional debugging. I did it by using AI to connect a conversation between my varios “disconnected” tools.\nHere is the breakdown of the investigation.\nPhase 1: Evidence Gathering (Finding the Needle in the Telemetry Haystack) Link to heading I exported the raw metric data and treated the AI as a Pattern Matcher.\nMy Prompt: “Analyze this dataset. Find the exact timestamps where memory allocation spikes \u003e 20% in under 60 seconds.” The Result: It identified two specific seconds in time. I took those timestamps and asked the AI to generate a targeted query for my log aggregator (which have its own agent). The logs lit up. Every single memory spike aligned perfectly with a specific “System Refresh Event.”\nIn hindsight, this looks obvious. But in a codebase with millions of lines, “obvious” is a luxury you only get after you know exactly where to look.\nPhase 2: The Interrogation (The “Chat-to-Profiler” Bridge) Link to heading Knowing when it happened was half the battle. I needed to know what was exploding.\nThe crash was happening deep in our core infrastructure. This wasn’t “bad code”; it was battle-tested bedrock logic that has scaled with us for years, making any modification a high-stakes operation requiring surgical precision.\nIn previous attempts, analyzing a production dump meant a deep, manual dive into a memory profiler. While modern profilers are powerful, they still require you to do all the heavy lifting. This time, I used a Model Context Protocol (MCP) to turn my profiler into a conversational partner. Instead of hunting through heap snapshots myself, I had a dialogue:\nAI: “I detect a high volume of duplicate objects on the heap.”\nMe: “That’s impossible, those should be cached and reused.”\nAI: “The cache references are unique. They are not being reused.”\nIt wasn’t magic. I had to guide the AI, filtering out hallucinations and refining the context, but it handled the syntax while I focused on the semantics. It pointed me to a race condition I had looked at a dozen times but never truly saw.\nPhase 3: The Implementation (Architecting the Cure) Link to heading The root cause was a classic “Stampede”: clearing old data before the new data was ready.\nI knew the concept of the fix (a “Relay Race” pattern), but implementing high-concurrency caching logic in a critical subsystem is risky.\nI used the AI to implement the solution :\nThe Prompt: “Refactor this cache logic to support a ‘Versioned Handoff’. Ensure thread safety during the swap between Version 1 and Version 2.” The Result: The AI generated the boilerplate for the atomic swapping mechanism. But I didn’t just copy-paste. I established an “AI Tribunal” (Github Copilot ,running cluade, for logic, Gemini for architecture) and performed a rigorous human code review to ensure the locking mechanism was sound before it ever touched the staging enviroment.\nThe Takeaway Link to heading Don’t replace yourself; multiply yourself. I used AI to handle the “grunt work” of parsing data and generating boilerplate. Orchestrate, don’t just chat. Connect your tools. Let the metrics talk to the logs, and let the profiler talk to the code. Respect the “Boring” Solution. The fix wasn’t a fancy new framework; it was a simple, boring Relay Race pattern. The case is finally closed. The fires are out, and production is quiet again, exactly how a well-engineered system should feel\n","id":1,"tags":"programming debugging artificialintelligence llm","title":"Connecting LLMs to my debugging flow to fix a memory crash","url":"/posts/connecting-llms-to-my-debugging-flow-to-fix-a-memory-crash-eb42bbb2d174/"},{"content":" A guide to safely deleting code and reducing technical debt Link to heading There is a common bias in our industry: the instinct to add.\nAs developers, when we face a problem, our default reaction is to write a new function or add a new library. It feels like progress. But while code drives value, it also carries a continuous maintenance cost.\nEvery line you write is a line that must be read by teammates, covered by tests, and secured against vulnerabilities. The most efficient system is the one that delivers maximum value with minimum code.\nThe “Just In Case” Hoarder Link to heading We’ve all seen the “Fear of Deletion” in code reviews. A method is obsolete, but someone comments it out instead of deleting it: “Better keep it, just in case.”\nThis turns your codebase into a digital junk drawer. “Zombie Code” adds noise to searches and confuses new engineers trying to understand the domain.\nHow to Verify (The Toolkit) Link to heading The hardest part of deleting code is the fear of breaking something hidden. “Find All References” isn’t enough. Here is how to verify usage safely:\n1. The Static Check: Start with your IDE. If a method is private, trust the compiler. If it’s public, use tools like NDepend or SonarQube to spot “dead branches” visual inspection misses.\n2. The External Audit: Check the edges. Are frontend analytics still firing events for that feature? Are HTTP logs showing hits on the old API endpoint? Are cloud metrics showing activity on that specific S3 bucket? If the edges are silent, the core is likely dead.\n3. The Database Audit: Code can look valid while the data is stale. Check database statistics. If a table hasn’t had an INSERT or UPDATE in two years, the logic managing it is ghost-code.\n4. The “Scream” Test (Metrics): If you are unsure about an internal method, emit a custom metric: Metrics.Increment(\"deprecated_feature_usage\"). If the counter stays at zero for a full business cycle, you have your answer.\nThe AI Assistant (Your Cleanup Partner) Link to heading Don’t ignore LLMs during cleanup. They are a force multiplier for verification.\nThe “Explain This” Test: Paste suspicious legacy code into an AI and ask: “Identify potential side effects if this were removed.” It often finds hidden dependencies. The “Safety Net” Tests: Before deleting complex logic, ask the AI to “Write comprehensive unit tests for this function.” Having tests that fail after you delete the code confirms you understand its impact. Generate the “Red PR”: Once you identify dead code, ask the AI to do the grunt work: “Refactor this file to remove the unused LegacyProcessor class and all references.” Remember: AI is for acceleration, not abdication. You still click “Merge.”\nThe Sunset Strategy (Rollout Plan) Link to heading Verifying is one thing; deleting is another. You need a safety net.\nPhase 1: The Warning: Don’t rely on quiet runtime logs. Mark code @Obsolete to warn other developers in their IDE, and clearly communicate removal dates in your changelog and team channels. Phase 2: The “Soft Delete” (Feature Flag): Wrap the entry point in a Feature Flag and turn it off. This is your instant rollback mechanism if a critical user complains. Phase 3: The Observation: Keep the flag off for a safe period (e.g., 2 sprints). Ensure you have alerting on that disabled path. Silence is golden. Phase 4: The Code Delete: Once the observation period passes with zero issues, delete the code, the flag, and the tests. Phase 5: The Data Cleanup: Deleting code often leaves behind orphaned data. Wait a few extra sprints to be absolutely sure, then archive the data to cold storage before finally dropping unused tables or columns. Your schema should reflect reality, not history. The Bottom Line Link to heading There is a unique satisfaction in opening a Pull Request where the Lines Removed count is higher than Lines Added—it means you have simplified the mental model without sacrificing functionality. If code isn’t running in production, it is just noise; verify with data, and hit delete.\n","id":2,"tags":"Refactoring Technical Debt Software Engineering Code Quality Best Practices","title":"The Joy of Negative Code Lines","url":"/posts/the-joy-of-negative-code-lines-5440ae1f26a6/"},{"content":" Debuggability is highly underrated Link to heading In the words of Brian Kernighan, the famous computer scientist and author of the book “The C Programming Language”:\nDebugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.\nThis quote reflects a common experience many developers face while trying to write “smart” code. They often end up with complex solutions that are hard to maintain and debug. This is a common mistake, driven by the desire to demonstrate skills (and maybe to appear clever).\nSo… just write boring and straightforward code. Organize it into small, independent modules with clear interfaces and low coupling. This makes it easier to isolate and debug issues within specific components without being affected by the rest of the system.\nHow to organize a drawer the right way\nCode is written once but read many times\nMake your code readable and self-documented. This means code that follows good naming conventions, uses descriptive variables and function names, and includes clear comments (if needed).\nWhen implementing your solution, you must think about how it will be executed. You probably focus on the happy trail, but you should also consider how it will fail and how you will debug it in production. Not doing so results in a mistake that can waste a lot of time and effort looking through complicated code to figure out and fix the problem.\nTo address this challenge, one must shift her mindset and prioritize debuggability from the start of the project.\nThis means leaving breadcrumbs, also known as logs, storing data in machine-readable format to enable efficient parsing and analysis, capturing valuable information about the application’s state, execution flow, and any errors or exceptions. There are several error-handling mechanisms that catch and report issues as early as possible, making it easier to identify and fix bugs. The logs from the different components and services will be collected into a centralized system for easier aggregation and querying.\nIn some cases, logs alone don’t give us the complete picture of how a system is doing. It’s a good idea to use metrics, which help us understand the system’s health, performance, and behavior more completely. I’m a big fan of metrics because they give us a clearer view. You can detect anomalies and track quantities over time. Based on the collected data, you will build monitoring dashboards that provide real-time visibility (and alerting system).\nAnother tool in the debugability arsenal is tracing, which tracks the flow of “requests” across different services and components, enabling us to visualize and analyze the end-to-end journey of a request and pinpoint bottlenecks or failures.\nFurthermore, investing in administrative tooling that reflects the system’s state by exposing APIs or CLIs can greatly enhance debuggability by allowing developers and administrators to interact with the system, query its state, and perform various tasks such as triggering debug modes, capturing snapshots, or executing diagnostic commands.\nLastly, live debugging tools like Rookout, Datadog, and Lightrun allow you to debug code in production without any code changes. This is quite amazing and it is done by incorporating their agent into your code that does dynamic instrumentation. This agent is a bridge between your code and their environment. It monitors the code’s execution and identifies points in the flow (such as function calls or variable assignments), and it does some optimization not to instrument everything based on the learned history of “hot” paths to minimize the performance hit.\nSimple code works better than complicated code. Link to heading To conclude, writing boring and straightforward code, combined with various observability techniques, which should be included as early as in the design stage, can significantly enhance your system’s debuggability.\n","id":3,"tags":"softwaredevelopment codequality softwareengineering debugging","title":"Write Boring Code","url":"/posts/write-boring-code-e6a80c8311bb/"},{"content":"A few months ago, we had a hackathon at my work.\nAt the opening event, one of my colleagues said to me:\nHackathons are similar to building LEGO model without instructions.\nIt stuck with me. I pondered about it.\nWhat crossed my mind is that hackathons are playgrounds for software engineers, where creativity is key. Imagine being handed a box of LEGO bricks, and the instructions are taken away; what would you build? Probably, whatever comes to your mind.\nThat’s the magic of hackathons — they push you to think beyond boundaries, innovate, and craft something extraordinary from seemingly random pieces. Just as LEGO bricks offer endless possibilities, hackathons provide a platform for boundless innovation.\nThere are no rules; your imagination is the only limit. Without a set path to follow, hackathons encourage participants to explore new territories, experiment with fresh ideas, devise effective and unique solutions, and, along the way, have FUN.\nYou start with an array of tools — technologies, APIs, datasets — and the goal is to create something innovative and functional. This process fosters creative problem-solving and rapid prototyping, crucial skills in the dynamic software development landscape.\nTo sum up, hackathons serve as platforms for software engineers to push boundaries, explore new ideas, and work together in diverse teams to create groundbreaking solutions. Ultimately, they encourage a culture of continuous learning and experimentation.\n","id":4,"tags":"hackathons softwaredevelopment careergrowth softwareengineering","title":"Building LEGO without instructions","url":"/posts/building-lego-without-instructions/"},{"content":"Everyone makes mistakes. If someone says otherwise, they’re probably not being straight with you. It’s bound to happen whether you’re new to a job or have been there for a while. You can find plenty of horror stories on Reddit and HackerNews. Take, for example, this post with a collection of those stories:\nAsk HN: What’s the worst you’ve ever screwed up at work? | Hacker News\nI felt that gut-wrenching moment when you realize a mistake has been made. The sinking feeling in your stomach, the twinge of shame, or the self-critical thoughts might flood in.\nBut here’s the thing: mistakes are a natural part of the journey, and what matters most is how we navigate and learn from them. In this post, I’ll try to explain why.\nAcknowledge and Own Up Link to heading The first step is crucial — acknowledge the mistake. It’s tempting to sweep it under the rug or pass the blame, but trust me, that only makes things worse. Take responsibility and be brutally honest about what went wrong. Embrace the uncomfortable truth; it’s the only way forward.\nShow that you’re proactive and committed to resolving the issue. Follow up and keep your team updated on your progress. Communicate clearly and frequently until the problem is solved.\nMoreover, in my experience, there’s a hidden gem amid chaos — a chance to observe how people react. It’s like a crash course in understanding your company’s DNA. The way individuals handle mistakes reveals volumes about the organization’s culture.\nUncover the Why Link to heading Once you’ve owned up to the mistake, dive into detective mode to understand why it happened. Was it a knowledge gap, lack of training, or a hurried decision? This isn’t about pointing fingers but gaining insights.\nThink of it as peeling an onion — layer by layer, get to the core of the issue. Was there a miscommunication or a systemic flaw? I can suggest using the 5 Whys technique. This is how it works:\nStart with the problem statement and ask why it happened For each answer, ask why again until you reach the root cause Repeat the process for different aspects of the problem until you have a comprehensive picture of the situation. Understanding the why isn’t just for personal growth; it’s about making your team and organization more resilient.\nBy figuring out the root cause, you not only learn from your own slip-ups but also contribute to a shared knowledge base. Keep it simple, grab your metaphorical magnifying glass, and unravel the mysteries behind your mistakes.\nFix It, Learn from It Link to heading Fixing the mistake is an obvious step, but don’t just gloss over it.\nDon’t just patch the error; analyze it like a Git blame gone rogue. What went wrong? Was it a logic gap, a memory leak, or maybe a sneaky exception lurking in the shadows? Understanding the root cause is the key to unlocking points for future levels.\nIf you need a guide on how to start when it you against the issue, I once wrote a post about it:\nA letter to the lonely developer\nProvide a high-level overview of what you did to resolve the issue, and accompany it with your key takeaways. Turning the page without reflecting on the lesson learned is a missed opportunity for personal and professional growth.\nPrevent Future Slip-Ups Link to heading Now armed with insights, take proactive steps to prevent a repeat performance.\nKnowledge is the ultimate firewall. Invest in training, devour documentation like it’s your favorite Stack Overflow thread, and consider adding unit tests like shields against future regressions, allocating more time for tasks, implementing new processes, or adding logs and metrics for better visibility.\nThe power of the unit tests\nRemember, prevention is the ultimate hack to keep bugs at bay.\nReflect and Share Link to heading Don’t let your hard-earned lessons be solo commits. Take a moment to reflect on the entire experience. Consider what could have been done differently and how you can improve professionally. Conduct a retrospective meeting with your team to discuss the mistake and the lessons learned. Use a structured format, such as the Start-Stop-Continue model, to identify what worked well, what didn’t work well, and what can be improved. Encourage everyone to participate and share their perspectives and suggestions.\nLook into the past, improve the future\nDocument your reflections and share them internally as part of a post-mortem. Transform your learning into collective wisdom, turning it into “stronger” code (and fewer regressions).\nBelow is a collection of some examples from very respectful companies:\nPost mortem examples - GitHub repo\nLastly, embrace the “fail fast, iterate faster” mentality. Treat mistakes as experiments gone sideways, valuable data points in the grand algorithm of your career.\nIn Conclusion Link to heading Mistakes are an inevitable part of the developer’s journey, but they are also invaluable learning experiences. Acknowledge, understand, fix, prevent, and reflect — these steps can turn a negative situation into a positive opportunity for growth. Remember, it’s not about avoiding mistakes altogether; it’s about handling them with resilience and turning them into stepping stones on your path to success. After all, everyone makes mistakes — it’s the journey of learning from them that truly matters.\n","id":5,"tags":"softwareengineerlife softwaredevelopment softwareengineering fuckupnights","title":"TIFU at Work: Learn and Move On!","url":"/posts/tifu-at-work-learn-and-move-on/"},{"content":" A humoristic post generated with the help of ChatGPT Link to heading Do you wanna see me test? U wanna see me unit test? Link to heading In the world of software development, unit testing is an essential process that ensures our code behaves precisely as we expect. But let’s be honest; unit testing is not the most glamorous part of coding. It’s the backstage crew, the hidden orchestrators behind a great performance. And just like the Eurovision Song Contest, our unit tests must be pitch-perfect to score the highest points in reliability and robustness.\nUni Tess — The personification of unit tests, a meticulously organized individual by stable diffusion\nUnit Tests: The Unsung Heroes Link to heading Think of your software as a competitor in the contest. The software, like the singer, is the face of the performance, taking center stage and getting the applause. But behind that successful performance, there’s a lot of practice and fine-tuning. That’s where our unit tests come in. These tests, the unsung heroes, ensure that each piece of the code (the lyrics, the melody, the rhythm) works correctly. If the tests pass, it’s time for our code to hit the stage!\nThe power of the unicorn by stable diffusion\nEmbracing the Power of the Unicorn Link to heading In “Unicorn,” Noa Kirel sings about harnessing the “power of a unicorn,” symbolizing strength and uniqueness. This can be seen as a metaphor for our unit tests. Each test is unique and powerful in its own way, checking a specific part of our code. Combined, they provide the strength and assurance that our software functions correctly.\nMuch like Noa Kirel found her “horn” to embrace and used her experience as a young artist to promote strength and togetherness, we too, as developers, must embrace our unit tests. They may face criticism (usually from developers who think they’re not worth the time), but we know their true value. They promote “coexistence and togetherness” in our code, ensuring that each piece works together harmoniously.\nHitting the High Notes with Unit Tests Link to heading “Unicorn” made it to a 3rd-place, showing that a strong performance combined with meaningful lyrics can make an impact. Similarly, well-thought-out unit tests can help your software reach its highest potential and avoid any sour notes (bugs) during the performance (runtime).\nA well-tested software is like a chart-topping hit; it’s reliable, it’s loved by users, and it’s less likely to crash in the middle of the performance. It may not be a unicorn, but in the software world, it’s pretty close!\nThe Encore Link to heading So, the next time you write unit tests, think of yourself as a Eurovision contestant preparing for a big performance. Each test you write is a line in your song, a step in your dance routine, or a note in your melody. Embrace its power, harness the strength of your tests, and get ready to take the stage.\nAnd remember, in the grand Eurovision of software development, your unit tests could be the difference between a standing ovation and a silent auditorium. So, let’s hit those high notes, and may the best code win!\n","id":6,"tags":"softwaredevelopment humor unittesting softwareengineering","title":"The Power of the Unit Tests","url":"/posts/the-power-of-the-unit-tests/"},{"content":" Essential tips and resources for a successful job hunt Link to heading I was laid off from my previous job. It came out of nowhere; I decided to take this change as an opportunity and make the best of it. Luckily, I received incredible support from my connections, and I want to give back by sharing some valuable lessons and resources I’ve gathered along my job search journey.\nThis blog post is based on a Twitter (Hebrew) thread I created, detailing my experience and offering practical advice to fellow software engineers (and not only) facing a similar situation.\nUpdating Your Resume Link to heading First and foremost, updating your resume is crucial. Use guides and resources like the one shared by Shahar Avigezer (written by Erik Sapir) and the one by Rina Artstain to help you craft a professional and polished resume showcasing your skills and experience. When you finish your resume, the optimal way to submit it is with a referral. But if it is not an option, just run your CV through the CV Compiler to see how it scores with applicant tracking systems and what needs to be improved (ATS robot)\nLeveraging Your Online Presence Link to heading Consolidate your online activity into a “business card” with links to your LinkedIn, Twitter, and others. This way, you can showcase additional accomplishments and interests that may not fit your resume. It also demonstrates your professionalism and personal brand. A few years ago, I read a post written by Kshitij Singh on how he created such a landing page, and I followed his guidelines in his repo below:\nGitHub - singhkshitij/My-Landing-Page: Minimal Portfolio Page Built with React\nThe result:\nPersonal Website\nPreparing Your Pitch Link to heading Before applying for job positions, write a “tell me about yourself” document, as described in the book “Cracking the Coding Interview”. It should cover your current role and academic background (if applicable) and delves into the role’s details. Finally, hobbies — especially those related to the tech world or “unique”- could serve as conversation starters or perhaps break the ice.\nFurthermore, the book suggested focusing on 2–3 challenging projects you’ve worked on. Write down a list of mistakes you’ve made (we all do them), what you had fun doing, and which conflicts you took part in. Eventually, it will assist you in writing phrases in the SAR (Situation, Action, Result) framework to tell a compelling story about your achievements.\nOrganizing Your Job Search Link to heading Use tools like Notion to keep track of your job applications and interviews. This will help you stay organized and focused during your search, ensuring you’re on top of each opportunity. I’ve used the following templates:\nTrack down the list of job applications: Notion Template Gallery - Job applications\nA personal CRM to keep all your leads: Simple CRM | Notion Everything\nResearching Potential Employers Link to heading Before applying for a job, research the company by checking its location, reading investment analysis, and searching for articles on sites like Geektime and Crunchbase. Search review-based websites like Glassdoor to get an idea of what it’s like to work there. Prepare a list of questions (🙏 Shahar Avigezer) to ask the recruiter to refine your job search better:\nWhat will my day-to-day look like? How will I receive tasks? What percentage of meetings will I have per week? What is the percentage split between front-end and back-end work? And from whom? Also, do some work with yourself to understand better what you’re looking for by asking the following:\nWhat does Work-Life Balance (WLB) mean for me? What hybrid work model works best for me, and how? What next role do I aspire to take on in the coming years? Which programming language or framework do I prefer for front-end and back-end development? Being well-informed will help you make better decisions and impress potential employers.\nPreparing for Interviews Link to heading I recommend the following two websites to help you study for code interviews:\nThe interview school by Adilet Zhaxybay: Home\nThe tech interview handbook: Technical Interview Guide for Busy Engineers | Tech Interview Handbook\nThey offer guides, practice LeetCode questions, and tips on various aspects of the interview process. Preparation is key to standing out and performing well during interviews.\nSystem Design Interviews Link to heading Brush up on key topics and watch the system design interviews video series by Sheeran:\nFollowed by the introductory video on the importance of this type of interview, what they’re looking for in a candidate, breaking down the problem into details, and how to improve in this area by Jackson Gabbard (Synthace):\nPractice solving problems using resources like the Grokking Modern System Design course by The Educative Team and tools like excalidraw. The more practice you get, the more confident you’ll showcase your skills.\nGrokking Modern System Design Interview for Engineers \u0026 Managers - Learn Interactively\nNote someone uploaded an old version of the course to GitHub, which is enough for practicing, though some recent concepts are probably missing:\nDucvoccer/Ducvoccer.github.io\nNegotiating Your Offer Link to heading If you receive a job offer, use resources like the document by Aviad Herman, The Salary and Offer Negotiation Preparation section in the Tech Interview Handbook, and Iftach Bar’s lecture on salary expectations to help you negotiate a fair package.\nIf you receive stock options, consult threads(#1, #2) by @beersehva and Boaz Berman and use tools like EquityBee’s calculator to estimate their value.\nOption Grant Benchmark Tool | EquityBee\nConclusion Link to heading I hope these tips and resources will be helpful to you on your job search journey. Remember that finding a new job can be challenging, but you can turn it into a new opportunity with perseverance, a strong network, and the right tools. Good luck!\n","id":7,"tags":"softwaredevelopment joboffer softwareengineering interview","title":"Navigating through the job search","url":"/posts/navigating-through-the-job-search-599b1bc4221f/"},{"content":" How we used integration tests to improve confidence in our code Link to heading Picture this: your product owner brings you a set of new requirements, and together you review them. After some preparation and initial work, you get your design reviewed and approved by relevant stakeholders. Then, you enter your focus zone and start implementing it. While doing so, you want to gain confidence, so you add tons of unit tests to cover it, manually test it, and refactor your code based on your tests’ results until you feel comfortable with the outcome.\nBut still, you’re left wondering, “how do I get to a strong level of confidence in this code?”\nIn this post, I’ll discuss what I did when faced with the above situation and how my team and I improved the quality of (and our confidence in) our code.\nIntegration tests: what are they, and why do them? 🤔 Link to heading There is a straightforward answer to the second part of the above question: integration tests help ensure happy customers.\nDevelopers take several approaches to test their code to ensure its integrity. Choosing the suitable testing method depends on your context. Nevertheless, some tests are required for every software. These tests are represented as a layer-based model, known as the testing pyramid proposed by Mike Cohn.\nPersonally, I think the image below (by Atlassian) emphasizes what we would like to achieve when choosing a specific testing approach by following each of the layers of the pyramid.\ntest pyramid\nHence, we chose to implement integration tests to answer the question, “Are we building the system right?”\nWhy did we choose integration tests? These tests determine whether the parts of the solution work together as expected. Integration tests implementation is relatively easy and can prevent errors that are hard to catch later on. In addition, integration tests help to validate builds faster, reduce the time to ship, avoid human error, adhere to continuous integration (CI) practices, and minimize cost. As a result, everyone is happier in the long run because bugs are detected earlier, and larger problems are avoided. This increases our confidence and results in higher-quality code.\nHow did we build them? 👷🏻‍♀️👷🏻‍♂️ Link to heading At Igentify, our services are deployed as Docker containers. In a nutshell, containers isolate apps from their environment, solving the “it works on my machine” problem. Docker has a powerful API, which makes it easy to automate its setup and deployment.\nWe use the famous Testcontainers library that provides lightweight, throwaway instances of anything that can run in a container. The Testcontainers library is test-friendly, open-source, and supports multiple programming languages. Since Igentify’s services are being deployed as containers, we already have a Dockerfile, and Testcontainers simply create a new temporary image for it on-the-fly.\nHead to testcontainers website to find out more.\nIf you’ve read this far, you’re likely interested in diving into more technical details 🤓\nAs an example, if the design of your system is:\nService A is a container that talks to the “world” using a message broker in the form of RabbitMQ It gets a message from the RQ_Queue , processes it, requests a pre-signed s3 URL, and stores its result in the bucket using that URL When finished, it responds to RS_Queue with the output Service A Design\nAt a high level, the RabbitMQ container is being replaced by TestContainers’ RabbitMQ module, and its configuration is being filled by Service A context, which is being initiated by @SpringBootTest annotation. The blob service is essentially a web server that gets requests via REST calls. As part of its API, the blob service generates pre-signed URLs for uploading to cloud storage, which in our case, is an AWS S3 bucket.\nSo, how can a web server be controlled in a test environment? API mocking. In practice, it means you replace the real implementation with a local web server for your testing purposes. We use a well-known library named WireMock, where you simply mock the various requests and responses, and you are able to instruct storing files directly to your local drive, bypassing the cloud storage. Two birds with one stone.\nFind more information about Wiremock’s flexible API mocking.\nThe final piece of the puzzle is to add a consumer for the RS_Queue to get the response and use JUnit5 to assert the expected output, resulting in a self-contained environment for testing. The input should be meticulously selected to cover success and\\or failure scenarios.\nEventually, the integration test diagram looks like this:\nService A integration tests\nThe last step was incorporating the integration tests into our continuous integration in the Jenkins server. Currently, we run it every build, but in the future, we will trigger it once a branch is merged into the main (current) branch. That will help us gain certainty that we didn’t break anything. A Jenkins run\nFinal Thoughts Link to heading In this post, we reviewed how we’ve designed integration tests for our Java Spring Boot application with the help of TestContainers and WireMock libraries. We showed how we could easily interact with actual data while being as close as possible to the product, giving us confidence in our code.\nI believe these libraries bring a lot of immediate value with a rich set of functionalities. I encourage you to give them a try. Overall, integration tests are a crucial part of any software development, as they help to ensure a more robust product, resulting in happier customers.\nWe used integration tests while building version 7 of our Igentify digital genetic platform, which we released last month. We plan to expand the capabilities of these tests in future releases of our software. If you’re interested in learning more, please let us know here.\n","id":8,"tags":"sofwaredevelopment integrationtest softwareengineering codequality","title":"Failing fast to increase feedback loops","url":"/posts/failing-fast-to-increase-feedback-loops-6d08f013fa9b/"},{"content":" Or let’s talk about cohesion Link to heading TL;DR To make a system cohesive, you must ensure that the parts that go together are close to one another.\nI sometimes find that the cohesion (and coupling) concept is often considered way too academic, and developers tend to talk about other well-known concepts, such as DRY, YAGNI, KISS, and SRP. The list is long, and I can continue with more acronyms all day 😂 So, I’ve chosen to challenge myself and simplify it.\nI hope I succeeded.\nHave you decided to continue reading?\nLet’s talk about why it’s crucial or, in Kent Beck’s words:\nYou wanna strive for higher cohesion which reduces the coupling and complexity of the systems. What 😱? Let’s be formal for a moment:\nCohesion is the degree to which the elements inside a module belong together.\nCoupling is the degree of interdependence between software modules.\nNow it’s time for an analogy. Imagine you’re in the kitchen, it’s cold outside, and you wanna make a hot choco, so you open the silverware drawer, and it’s a total mess. Not only will it be hard to organize, but it’s not clear what belongs where and how to find it.\nOn the contrary, when everything is in its place, you can easily find a knife if needed or store a new spoon. In my eyes, that’s cohesion, lowering the general mess.\nThe terms cohesion and coupling are tightly related. They are often considered opposites, which isn’t accurate. Coupling is about connections; cohesion is about belonging together. The challenge is that cohesion is discovered in a context and cannot be created initially, meaning — you keep refactoring your code to keep objects in context.\nThe ideal scenario (also visible in the picture above) is when objects are arranged by functionality, or in other words, in a domain-driven context. When done correctly, it will result in loose coupling (there is no direct connection between a fork and knife besides the fact they are kitchenware).\nNow… if you’ve reached this point, some code examples can be helpful. Let’s start with coupling:\nTight Coupling\nWhen running the snippet above, the output is ID is null. You can run it yourself here.\nSo what’s going on? Each of the validity checks is being bypassed since Student and School classes are tightly coupled in such a way that School has intimate knowledge of Student’s internals and can set its data members. This design could be better. A quick solution will be declaring studentId with private access, forcing other classes to call the public getter and setter methods to access it, as follows:\nLoose Coupling\nIn this case, the output is (run it from here):\nYou can't initialize studentId to a null ID is not initialized But how does all of that relate to cohesion 🤷🏻‍♂️ ?\nLet’s get back to the Student and School example. If a class does all the work at once (God object), it results from high cohesion (and high coupling). Basically, there is a strong connection between the object in the same context.\nLow Cohesion\nWhile trying to adhere to the single responsibility (or separation of concerns) principle, the interface should be broken into several classes, each targeting different functionality (domain-driven), making it easier to maintain and update.\nHigh Cohesion\nConclusion Link to heading Simply put, cohesion means that a class should represent a single concept. However, remember that achieving full decoupling is only possible with damaging cohesion and vice versa.\nA system architecture that is easy to understand, easy to change, easy to maintain, and to test, is characterized by high cohesion and loose coupling. This combination contributes to the reduction of accidental complexity and enables the creation of well-defined modules.\nUltimately, I want readers to take away that following those principles leads to a system that is easier to maintain and refactor in the future. This is where the actual value lies, and that’s why you should care about cohesion.\n","id":9,"tags":"softwaredevelopment cohesion softwareengineering softwaredesign","title":"How to organize a drawer the right way?","url":"/posts/how-to-organize-a-drawer-the-right-way-4db782c07976/"},{"content":"I’m stuck; I’ve no muse about what to write. I can’t find any idea.\nAha… the famous writer’s block.\nWhat do I do in those cases? From where does the inspiration to write about stuff come from? Where do I find ideas? How do I find the time?\nRegarding the second, you make time — it is all a matter of prioritization. I’ve written about time management in the past, and those methods help me to focus.\nArrange your time and your mind will follow\nThe ideas? come from various sources. I keep an extensive list of podcasts, newsletters, blogs, etc., which I follow to gain more knowledge or, as I call it, the quest for growth, more on that:\nIn the quest for growth material\nBesides that, I found ideas in unique places. I look for questions on Q\u0026A-based websites such softwareengineering.stackexchange, workplace.stackexchange or quora.\nSometimes I get ideas from my colleagues or people I follow on Twitter. Actually, Twitter is an interesting place to collect them; I tend to tweet my thoughts, and occasionally a debate might evolve; this can be a trigger to blog about.\nAnyhow, whether it’s a blog, podcast, or any other source. First, I collect the subjects I think I’d like to write about on a dedicated Notion page, a sort of ideas log. Afterward, I follow the method I wrote about here to sort it out:\nDigital Notes are your life dashboard\nThis means that whenever I feel like writing or creating, I already have an arsenal of ideas.\nSo now I have a prioritized list, the fun part can begin. I pick the first item and start to research it online and collect the info on the subject’s page.\nMy digital notebook of ideas\nOnce I feel ready I start writing, which is about the time I feel I consumed enough sources to write about the subject and express my opinion on it. Don’t get me wrong: research is critical, but sometimes, you just have to stop and start writing and see what happens.\nThe draft is ready? I read the whole thing repeatedly and then again 😂 and fix whatever doesn’t get along with my main narrative.\nforget about it\nFinally, I use Grammarly to find any typos and grammar mistakes and if the sentences don’t fit the defined Grammarly goals. I usually pick an informal general audience with a casual domain. My writing style (intent) usually tells a story (as you might have noticed).\nGrammarly goals setting\nLastly, the reviewers, a bunch of close friends, and colleagues happily read my drafts and share their inputs, and based on their feedback (loops), I’ll rewrite the final draft.\nBasically, writing is all about reading and then more writing. As the old saying goes, “the only kind of writing is rewriting”.\n","id":10,"tags":"writerblock writersonwriting ideas softwaredevelopment","title":"Where Do I Get Writing Ideas From?","url":"/posts/where-do-i-get-writing-ideas-from-2jk2/"},{"content":" Various methods I use to gain new knowledge Link to heading A few years ago, I started my journey; picture this, a recent undergraduate SW engineer on his first full-time day job. My team mainly consisted of seniors; I saw those “giants” that both have vast product knowledge and tons of it in software development. They even found the time to be up to date with general tech news. I thought to myself, how do they do that? How can I learn new stuff which is not directly learned on the job? What are their methods? How do they find the time for that?\nAs part of my search for growth material , I’ve tried various methods that work for me, and I still do improve them from time to time. In the following post, I’ll elaborate on them. I covered my time management methods in other posts:\nArrange your time and your mind will follow Digital Notes are your life dashboard newsletters\nNewsletters Link to heading I’ve found newsletters as my preferred way of staying on top of new and relevant software engineering topics. Here are the ones I keep reading every week out of the many newsletters I have tried:\nTLDR Newsletter by Dan Ni. TLDR is a daily newsletter with links and TLDRs of the most interesting stories in tech 📱, science 🚀, and coding 💻! Level Up from Pat Kua. Level up is a weekly newsletter for tech leaders. A collection of ten (or more) interesting links on leadership, technology, organizations, and processes. Software Lead Weekly by Oren Ellenbogen. A weekly email for busy people who care about people, culture, and leadership. The Pointer. A reading club for software developers, curated by Suraj Kapoor. Emailed Tuesdays \u0026 Fridays with 6–7 links with a tl;dr for each article. Programming Digest, curated by Jakub Chodounsky. A weekly newsletter with the five most interesting stories in programming 👩‍💻, data 💾, and technology 📱. Console by David Mytton \u0026 Max Jennings. A weekly digest of the best developer tools and beta releases for developers. The above is what works for me; if you’d like more, head to the awsome-weekly repo with an extensive list of weekly newsletters from the software world.\nGitHub - jondot/awesome-weekly: An “awesome” type curated list of quality weekly subscription newsletters from the software world\n![](/images/in-the-quest-for-growth-material-1mfk/4.gif)Brain explodes —src But.. but, how can you consume that much information? Link to heading Our goal is to make reading fun and ensure that the content is relevant to you. If it’s boring, procrastinate. With that in mind, skim before you read!\nA learning technic that I’ve learned in my master’s degree for reading (lots of) academic articles and understanding what’s relevant or not.\nFirst, read the headline up to the first paragraph. Then, jump to the conclusion and read it. Fluent recognition of words is the key which improves as you consume more content and your vocabulary is getting larger.\nNow you’ll be able to decide if the article is interesting. If it does, go over it again, but this time, you are going to read it while you’ve already established the article’s contextual concept, the essence. Slow down on areas of interest and ignore irrelevant info.\nTech for the rescue Link to heading Usually, I collect more articles than I’m able to read in a week. I place them using the 1percentgrowth app by Shem Magnezi:\n1% Growth\nwhich I recently switched to from Pocket:\nPocket\nThose apps not only gather your articles but also recommend based on your past readings other hidden gems which relevant for you. A significant benefit of the pocket app is that it allows listening to articles utilizing text to speech engine. This is a true productivity boost. If you decide to use a different service — you can always rely on audioread, which turns your reads into podcasts:\nTurn Reads 📖 into Podcasts🎧\nOr if you read on your computer’s browser, the lovely ‘Read Aloud’ extension is helpful as well:\nRead Aloud: A Text to Speech Voice Reader\nAnd last but not least is wordtune, which creates a tl;dr version of the article to understand more and faster:\nWordtune Read\nPodcasts everywhere\nPodcasts Link to heading I frequently listen to (Hebrew) podcasts; I usually play them on x1.4 speed, though I try to play with it and see If I can make it to x2. TBH, this is hard. Below is my listening list:\nReversim by Ran Tavori and Ori Lahav. Probably one of the iconic podcasts for developers. It covers tech, software, and development culture. Geekonomy co-hosted by Reem Sherman and Doron Nir. They interview a special guest in each episode, which brings an interesting subject to talk about. NoTarbut by Avi Etzioni \u0026 Iftach Bar. A podcast about the day-to-day of developers’ teams. CyberCyber by Ido Keinan and Noam Rotem. A great way to stay up to date on the recent hacks and cyber security concepts. Hitech troubles by Arbel Zinger and Eran Yacobovitch, which, in their words, is about the people of the Israeli hi-tech. The big picture co-hosted by Aviad Ben-Yehuda and Nir Sabato. In each episode, this unique podcast covers the business strategy of one tech company. BarvazGumi hosted by Vicky Kalmanovich and Linoy Shkuri. Interesting guests that talk about what makes development fun! Osim Tochna is hosted by Boaz Lavi, who brings subjects about code, programming languages, cursed bugs, and machine learning. There are more to listen to, and I try to review the list to keep it relevant for my interests (like the Root Cause, which stopped recording new episodes).\nplain old RSS feed\nRSS feed Link to heading Yeah, I’m aware of the fact this is quite an old concept but still relevant. There are plenty of RSS clients. I’ve found the Feedly free version more than enough for my needs:\nFeedly - More signal, less noise\nI apply the same skimming method. However, since it’s about tech news, reading the headlines will give you the gist of it.\nWhat’s in my RSS list? This is where I get up to date with recent tech news, in English and as well Hebrew sites — here are my favorites:\nXDA developers (English) Ars Technica (English) 9to5Google (English) gHacks Tech News (English) Gtricks (English) Scott Hanselman’s Blog (English) Micahel’s coding spot (English) TheMarker headlines Geektime TGspot Coffee spot Software Archiblog Internet Israel Tech12 Also, it is helpful to follow groups of interest on Reddit, Quora, or Facebook, but that created an information overload for me, so I’ve decided to stop using them, and nowadays, I mainly follow the Tech Twitter hashtag and focus on reading content by interesting influencers such as Rina Artstain, Ran Bar-Zik, Oren Ellenbogen, etc. The list can go on and on, head to my profile for more.\nTo conclude Link to heading Calm down, don’t stretch your limits. You can go nuts from FOMO ( I didn’t cover Books as a learning source…).\nMake sure to ask yourself what’s in it for me or what am I looking to learn here? Protect your time before you start consuming it. Ensure the information fits your expected growth and be hyper-aware of biases (be judgmental).\nExplain the content in your own words (I usually tweet about my takeaways). Ask yourself questions after you’re done. Did it remind me of something else? Did it change the way I think? What did I learn from it that I didn’t know before? etc. That way, you can increase the chances it sticks with you, and later, you’ll be able to pull it out.\n","id":11,"tags":"softwaredevelopment growthmindset careertips softwareengineering","title":"In the quest for growth material","url":"/posts/in-the-quest-for-growth-material-1mfk/"},{"content":"In every team I was part of, a debate started on this point: should the developers write automation tests as part of the development process? They’ve just finished implementing the requirements and wrote some unit tests; now, should they also write automated tests?\nWell, the answer, “it depends”.\nDepending on the people’s skillset, teams’ structure. When you have manual/exploratory testers with no skills/time/resources/etc. to write automated tests, you can rely on developers. Thus it is much more productive if developers write the tests for the new feature they’re developing.\ntypes of automation tests (Atlassian)\nSuppose your testing team has the skills and resources to develop automated tests. Each group uses different libraries and design patterns. Obviously, in that case, it is more practical for developers to create new features and testers to produce the tests.\nHaving said that, the more important question to be asking is if it is okay for the developer to be the only person writing automated tests for the feature they are working on?\nThe answer depends greatly on your organization, your resources, the likelihood of missing a defect, the kind of automated test being written, the development style, who’s time is better utilized on which task, and of course, office politics (which alas are unavoidable). Generally speaking, there should be at least one other person who tests the code along with the developer.\ninattentional blindness\nIt’s all too easy for a developer to assume, “this one area can’t possibly cause any problems, so I don’t have to test it.” or “I already tested this last week, so it has to be okay.” This called inattentional blindness, where familiarity with the code through development causes potential problems to be missed.\nStill, this doesn’t mean they shouldn’t create those tests. They may still be the best person to write the automation. For example, if the rest of the development team is occupied. The testing team consists mainly of manual testers. The developer who wrote the feature is the best person to write the automation. Because of this, I would suggest that the most effective practice is to have a tester assist in identifying which test cases offer the most value and specify the parameters. From there, the developers can implement those test cases.\nTo sum up Link to heading My experience has been that developers must write automated tests for their features, especially when those types of tests require an intimate knowledge of the application’s internals, which testers may not have access to.\nThough it creates a conflict since, on the one end, you’d like someone to write unbiased tests, while on the other end, developers will write quality tests quicker, and it will empower their sense of ownership. Furthermore, keep in mind, not every team has the benefit of recruiting dedicated tests engineers, so eventually, developers have to join the party.\nOn the contrary, It would be more effective to employ testers for this task if those tests do not require any internal knowledge, like in the case of functional, API, or GUI tests. In addition, the development team’s time constraints would come into play, like when a new project is starting, hence it’s wiser to spread the effort to prevent bottlenecks.\ncode quality\nNo matter who writes the automated tests, someone else should review them to check for code quality, missed scenarios, and high code coverage.\nRemember that the ultimate goal is to create high-quality software. Anything you do that gets you closer to that goal will be great.\n","id":12,"tags":"softwaretesting automationtesting softwaredevelopment automation","title":"Should Devs Write Automation Tests?","url":"/posts/should-devs-write-automation-tests-5fb4/"},{"content":" My humble effort on managing your career Link to heading A few months ago, I switched jobs. As part of this move, I have changed my daily programming language from C#, which I have been using for over eight years, to Java. It might confuse some people and raise a few eyebrows here and there asking why I would drop my experience just to start with a new language.\nIn what follows, I will explain the rationale for doing so and the process involved.\nAre you insane? Why did you do that? Link to heading whyyyyy\nWhat made me abandon a language (re-hyped in recent years) that I’m familiar with all the bits and bytes in favor of a completely different one that I’ll have to learn from scratch?\ntl;dr I was up for the challenge, going out of my comfort zone to learn new concepts and grow, and no imposter syndrome will stop me!\nImposter syndrome\nFrom my point of view, C# and Java are almost similar, the gap between them appears trivial compared to other languages, but that’s geeking out (I won’t dive into the differences):\nComparison of C Sharp and Java - Wikipedia\nThe real reason is that I wanted to have experience in a different programming ecosystem. JVM comes with an almost identical language, which means I could relatively fast gain a very marketable skill, that in the future, will open up opportunities in other JVM-based languages such as Scala, Kotlin, Clojure, etc. It gave me that sense of freshness that comes with learning something new and being back the newbie for a period of time (which is not always easy emotionally).\nFurthermore, I used it as an excuse to start developing stuff over a different OS; if you haven’t read about that switch, go ahead:\nDeveloper story: Getting used to macOS as long time Windows’s user\nAs a side note, until recently, the demarcation line between the OSes is well aligned with the technologies. But, nowadays, you can even use Linux over Windows too:\n{% youtube b1YBx1L8op4 %}\nFinally, from my perspective, the JVM community is more dynamic. It creates more valuable tools and plugins than the .NET community, which I may use on a daily basis. Saying that, as a result of Microsoft’s strategy shift, there has been a massive change in .NET over the last few years, and I assume the .NET community will close the gap.\nSo, How did you do that? Link to heading Did I do that?\nThe switch from C# to Java programming language was simple. Gaining experience in the tricks, limitations, and so on… is just a matter of time, and my years of software development will sure come in handy.\nOn the other hand, going from .NET to Java SE (“The java platform”) and from CLR to JVM is a bigger leap. While some concepts are similar, it is actually an entirely different set of APIs that are organized differently. Besides that, I also changed from working on monoliths to using something that is based on microservice architecture, so the language and platform themselves have to be added to the OS, the tools (like Docker), and the inherent difficulties that come with distributed systems. That’s quite a challenge. That’s exactly what I was hoping for.\nA big hurdle is the multitude of libraries/frameworks that make similar things and various sets of Java APIs attempting to handle some of this mess. The .NET universe is much simpler in this regard (there is a clear choice of a tool for whatever you want to do). A sort of “what does not kill you makes you stronger” situation.\nTo wrap it up Link to heading Overall, the experience of switching programming ecosystems is an essential milestone in your growth. It paves the road for potential career changes in the future (since You prove to yourself that “I can do it!”). Doing so is really mind-stretching, unleashing your mind from the borders established by the tech stack you’ve used to.\nPeople react in different ways when they hear about switching technologies. In my opinion, many people place far too much weight on languages, platforms, and tools, and not enough on the purpose of using them, the actual development of the product, and the experience gained from developing it.\nOr in other words, the code is the mean for the business and not the end (goal).\n","id":13,"tags":"careeradvice softwareengineering careergrowth softwaredevelopment","title":"Switch Tech Stacks: Boost Your Career Growth","url":"/posts/switch-tech-stacks-boost-your-career-growth-3g6h/"},{"content":"This is the last post in the simplify docker series ( if you haven’t read the previous ones, go ahead and read them, it will make more sense afterward — part I \u0026 part II). This time I’ll cover networks, docker-compose, docker volumes, and more.\nWhat is it all about with docker-compose? Link to heading Docker-compose allows you to define and run multi-container Docker applications. With Compose, you configure your app’s services using YAML files (more on YAML here). Afterward, you can start all the services your configuration created with just a single command.\nThe following example is from TechWorld with Nana GitLab. BTW, Nana’s youtube channel is highly recommended. Below is her docker’s tutorial:\nIn the below example, We would like to run a MongoDB container along with a mongo-express container. As we’ve seen in previous posts, the (longer) way to do it is:\ndocker run -d -p 27017:27017 -e MONGO_INITDB_ROOT_USERNAME=admin -e MONGO_INITDB_ROOT_PASSWORD=password --name mongodb mongo docker run -d -p 8081:8081 -e ME_CONFIG_MONGODB_ADMINUSERNAME=admin -e ME_CONFIG_MONGODB_ADMINPASSWORD=password -e ME_CONFIG_MONGODB_SERVER=mongodb --name mongo-express mongo-express The equivalent YAML compose version is cleaner and readable:\nversion: '3' services: mongodb: image: mongo ports: - 27017:27017 environment: - MONGO_INITDB_ROOT_USERNAME=admin - MONGO_INITDB_ROOT_PASSWORD=password mongo-express: image: mongo-express ports: - 8080:8081 environment: - ME_CONFIG_MONGODB_ADMINUSERNAME=admin - ME_CONFIG_MONGODB_ADMINPASSWORD=password - ME_CONFIG_MONGODB_SERVER=mongodb To use, simply run: docker-compose -f filename.yaml up , to delete it, replace up argument with down .\nTurn the volume up Link to heading Each docker has a different file system, separated from the hosting environment. As we previously saw, when exiting a container, most of its files are deleted (unless you use the commit command). So, you can use volumes to save the files or point to files in your local system to be used within the container. To do so, you need to connect between both files systems as follows:\ndocker run -v /path/in/host:/path/in/container -it image_name The above command will run a container that /path/in/container is mapped to /path/in/host in our local file systems. Another option is to use a unique named volume, where the docker sets the local file system location and the user sets the location in the container as follows:\ndocker run -v name:/path/in/container -it image_name To get the information of the named volume, we can use the command\ndocker volume inspect volume_name and for removing it do: docker volume rm volume_name . A direct follow-up is how to copy to and from the container (the COPY command that we saw earlier is not the answer, it only copies to the image and not the running container). The below command is used to copy into the container:\ndocker cp \u003csrc_path\u003e \u003ccontainer\u003e:\u003cdest_path\u003e * container - the ID or name of the container Where the following is used to copy from the container:\ndocker cp \u003ccontainer\u003e:\u003csrc_path\u003e \u003cdest_path\u003e * container - the ID or name of the container Be connected Link to heading Communicate with each other\nAnother essential concept is networks; you can create an isolated network for several containers. By default, Docker creates one for each docker run. Still, in some situations, you would like to name it and set the same network for more than the container; thus, they will be able to communicate with each other.\nTo see all the created network run the command:\ndocker network ls To create a network:\ndocker network create network_name And finally, to fire a container with this network:\ndocker run --net network_name -it image_name Another useful command is to run a container based on a different container’s network to enable communication between the two, just pass the container id or name to the–net flag. We have seen how containers communicate with each other so far, but what if you want to share data from an external source? For this case, we will define the internal ports that the container listens to. In docker run -p 5050:80 image_name command, it defines that the hosting system port 5050 is bonded to the container’s port 80.\nDocker image size diet Link to heading reduce image size\nDocker image size can quickly inflate to 2,5 and even 15GB. A best practice is to reduce it for a couple of reasons:\nSmaller size means easier to move from place to place Less space on the local file system Usually, images are stored in a cloud repository. Meaning the smaller their size, the lower it costs Security — install only what you need So how can you do an image’s size diet?\nMulti-stage meaning multiple images (“FROM”) on the same Dockerfile and define which one to build on the build command. To do so, it is highly recommended to name each layer (using the “AS” command) and then choose which layer to build using:\ndocker build — target=target_name -t container_name . Base your images on smaller size images. You can use distribution such as the alpine Linux or Google’s distroless. Image investigator Link to heading One last thing before wrapping this guide, I would like to recommend an open-source utility named Dive. Among its many features, you can explore each layer’s content, file sizes, and more. Basically, It helps you analyze docker images. Eventually, providing enough info to think of ways to reduce image sizes.\nTo conclude Link to heading This post and previous ones are just the tip of the iceberg of what Docker can do. I hope I simplified it enough, and if you made it this far, you should have the basic skills to get started.\nEnjoy!\n","id":14,"tags":"devops docker softwaredevelopment dockercompose","title":"How to use docker-compose, volumes, networks, and more","url":"/posts/how-to-use-docker-compose-volumes-networks-and-more-4a24/"},{"content":" I covered the basics of creating and building Docker images in part I (if you haven’t read that yet, I would recommend it since this part is based on it). In this part, I’ll explain how to run and delete an image of the container you’ve built.\nlet’s continue\nRunning an image is as simple as docker run -it image_name:tag . Let’s break it down; tag is the one you set when building it; note that if you remove it, then docker assumes you point to the latest. The meaning of -it isinteractive terminalWhich is loading the terminal driver in an interactive mode in a foreground mode, basically a way to run commands on the docker from our terminal. Thus, in our case docker run -it my_app will suffice.\nOnce we run the container, docker names it (weirdly) and set an id. To get this information, rundocker ps And below is its output:\nCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 71ed79a8d99f my_app “/bin/bash” 6sec ago Up 5sec eager_elbakyan to simply stop a container, we can use the command docker stop container_id where in our case, docker stop 71ed79a8d99f. It’s also possible to enter exit in the terminal to get the same outcome. Duly note, this command doesn’t delete the container — more on that as we advance.\nFurthermore, if you’d like to get all types of containers, just run docker ps -a and now it will be shown with an exit status. If you’d like to rerun it, just type docker start container_id, btw docker allows using the name instead of the container_id and, it is possible to set the name of the image as follows: docker run -it — name dvir_app my_app\nSometimes we would like to run a container without connecting to it; in this case, we can use the -d flag (detached): docker run -d image_name .\nIf eventually, we would like to connect the docker, we’ll just need to run: docker exec -it container_id /bin/bash and simple as that, we will get a terminal into our running docker. More commands can be found at the official site:\nDocker run reference\nAmong the commands I’ve written above, there are a few more popular:\ndocker run --rm -it image_name will remove the docker’s file system after we close the container.\ndocker run —-env my_life=”/now/or_never.txt” -it image_name Usually, we use some environment variables on our container, the —-env flag helps you set it during a run.\nWe can use the --entrypoint flag to change the entry point set in the docker image. for example, if the docker image is set to run a service, but we would like to get a bash terminal before it runs it, we can simply set it like this:\ndocker run -it --entrypoint /bin/bash image_name or in a shorter version docker run -it image_name /bin/bash .\ndelete everything\nLastly, I would like to touch the how to delete an image/container. Those files usually weigh quite a lot, so most of keeping our system clean and sharp. The command docker rmi image_name/id will delete the image; if we would like to remove a container, simply type docker rm image_id . Both won’t clear the space of those files, so a different command needs to be used:\ndocker image prune , it will clean the dangling image (as I wrote in part I). A deadlier command is docker system prune Which removes all stopped containers, unused networks, dangling images, and build cache.\nFinally, to destroy everything and start from scratch docker system prune -a , more on that can be found on the official documentation:\ndocker system prune\nThere are also official Docker images of all the well-known distributions, such as Ubuntu, Postgres, and more, which are stored in a repository called docker hub:\nDocker Hub Container Image Library | App Containerization\nYou can even upload your container there. So, how can you download from it?\nJust do docker pull. For example, if we want to download ubuntu, we’ll search it in the hub and reach it: https://hub.docker.com/_/ubuntu. All the listed images are visible on the tag tab, and we will choose depending on the need. Eventually docker pull ubuntu:latest will pull the latest image from the docker hub (since we haven’t specified the exact repo, the default is the hub).\nThat’s it for this part; I hope you’ve found it relevant and as simplified as it can be. More on networks, volumes, using docker-compose, etc. on part III.\n","id":15,"tags":"docker devops dockerimage softwaredevelopment","title":"How to run, delete a Docker image","url":"/posts/how-to-run-delete-a-docker-image-52dm/"},{"content":" I’ve heard a lot about dockers, even had some experience with it as part of my graduate degree. Still, as the old saying goes, learning is by doing. By doing, I mean using the stuff you want to learn as part of your daily work (instead of using it as part of a course in a semester since it will be forgotten). Actually, this is a technology that, in my perspective, should be in some familiarity level in each software engineer’s tech stack.\nThis is the first part in a series about simplifying Docker usage. In this blog post, I’ll talk about Docker, a container platform that allows to create containers’ images, build them, and more. Duly note that Docker is not unique, you can find containerd, rkt , lxd, and others, but it is one of the popular container platforms out there.\nOk, I’m convinced— what’s a container? Link to heading container magic\nContainers are software units that package up code and its dependencies so that applications can run quickly and efficiently across different environments. Wait? Some would read it and say that I’m talking about a virtual machine. While it may sound the same, they are different in their purpose. A container is mobile and light. It abstracts the application layer while a VM takes more space, and its whole purpose is to virtualize physical hardware, as can be seen in the image below:\nContainer vs. VM\nBasically, the container solves the “it works on my machine” syndrome.\nIt works on my machine\nGetting started Link to heading First, install docker from here Get Docker\nNow, when dealing with docker, there are two essential terms, image, and container. To create a new container, one should write a Dockerfile (I learned the hard way the d should be a capital letter), and it describes how the container will be built. Using docker build an image will be generated out of it. This image can be moved from place to place; it is ready to use as is. Image can be a building block for other Dockerfiles.\nFor using the image, we’ll do docker run which creates a container out of the image. It is possible to run multiple instances of the container.\nDockerfile a recipe for an image Link to heading FROM ubuntu:latest RUN apt-get update \u0026\u0026 apt-get -y install sysstat ENTRYPOINT [“/bin/bash/”] In the first line, the FROM states the image on which our image relies; we can start from scratch too, but it is more common to point to a specific operating system. This is why it is called a base image. Here its ubuntu:latest.\nIn the second line, the RUN is used. Its purpose is to run a command while the image is being built. In my example, it will run an update of apt-get and then installs sysstat. This command always creates a new intermediate image layer on top of the previous ones. That’s why it is always recommended to chain all the RUN commands together.\nLastly, ENTRYPOINT will run a command in command-line (with arguments as opposed to CMD command — more on that on part II). In this case, it will run bin/bash Meaning once the image is up, we will get a bash terminal open and running.\nnow what?!\nSo, how can we use it?! Link to heading We will use a docker command. Each starts with docker and for building the recipe we’ve just created, we’ll do docker build -t image_name:tag_name path_to_Dockerfile, the -t flag adds a terminal driver for outputting the stdout to the terminal. In the GIF below,image_name is my app and tag is 1.0 and right after appears a dot (oh, the mighty dot), which is there for a reason (not a typo), meaning path_to_Dockerfileis the current location. BTW, you don’t have to set a tag; docker will mark it as latest automatically. Tags provide a versioning mechanism for the same image recipe.\nAfter it finished, we can run docker images, and we’ll see the following output contains the name, tag, the unique image ID, date, and size:\nREPOSITORY TAG IMAGE ID CREATED SIZE my_app 1.0 875ae82e46c7 39 minutes ago 105MB If I rerun the command without the tag, docker will recognize it as the same image (by the ID) and mark it with the latest tag:\nREPOSITORY TAG IMAGE ID CREATED SIZE my_app 1.0 875ae82e46c7 47 minutes ago 105MB my_app latest 875ae82e46c7 47 minutes ago 105MB Again? It will show that Docker is smart enough to identify that no change was done, resulting in the same image version. It can be inferred based on the creation time, which we’ve built the initial image.\nTo delete, simply run docker rmi my-app:1.0, then the list will show only one image. Another critical point to understand is what happens when you create an image with the same name and tag with new logic. The old one is set with value in name and tag, but the ID is kept the same.\nREPOSITORY TAG IMAGE ID CREATED SIZE my_app latest ab422fb19450 4 seconds ago 105MB \u003cnone\u003e \u003cnone\u003e 875ae82e46c7 7 hours ago 105MB This state is called dangling (between life and death).\nDangling images\nTo delete the dangling images, just do docker image prune.\nThat’s it for this part; I hope you’ve found it relevant and as simplified as it can be. More on running images, using docker repository, etc. on part II\n","id":16,"tags":"softwaredevelopment docker dockerfiles devops","title":"How to create \u0026 build a Docker image","url":"/posts/how-to-create-build-a-docker-image-56o3/"},{"content":" When practicing CI/CD, does code freeze still matter? Link to heading Assuming you are familiar with the concept of code freeze, which is that dedicated time in a project when we (developers) are supposed to be more strict in making changes to the code or other resources for the good of moving the project towards a release or the end of an iteration.\nI’ve recently wondered about that concept; I asked myself why do we need to stop everything when we have a full-scale CI\\CD pipeline. Well, you can just pick one of the versions and set it as the release candidate.\nI researched and asked around, below you can find my conclusions.\nCode freeze? Aha? Link to heading source\nFirst thing, first, defining what code freeze is. Wikipedia defines it as:\na freeze is a point in time in the development process after which the rules for making changes to the source code or related resources become more strict\nThe page underlines 3 common types of freezes:\nA specification freeze is when all parties agree that no new requirements, specifications, or features will be added, as well as stop coding.\nIn a feature freeze , all development of new features is suspended so that all effort is focused on finding and fixing bugs and improving the user experience. A feature freeze helps improve the program’s stability by preventing the introduction of new, untested source code, resources, and their interactions.\nLastly, a code freeze , where no changes are allowed to the source code, ensures that the code areas known to work correctly will continue to do so. Code freezes are more common in the final stages of development when a specific release or iteration is being evaluated.\nDo we need it at all? Link to heading Code freeze?\nNow that we all synced what it is, the question is whether it’s relevant nowadays, where most (I assume) organizations practice a sort of CI\\CD pipeline? the answer is not so simple; it depends on the domain and the product’s needs.\nTake for example what happens at Igentify (where I work), the product we develop is regulated as required in the health tech domain. We apply a feature freeze for that purpose, so all features will be stable, the code is shifted to a dedicated branch, and (manual and automated) tests are applied before release. If any bugs were found, we fix them ASAP. In the meantime, new features are being developed in the main (current) branch. So, newer development doesn’t stop; it gets lower priority, and the pace is slower.\nWhereas this notion contradicts the concept of the CD (commit == new version) where you can just take whatever is ready (in terms of code, tests, etc.) from a specific branch and deliver it to production. For instance, if a bug was found, quickly fix it, push and deliver to that branch. In a way, It creates a buffer between developers and production. They can continue to do their work without knowing there is a freeze at all.\nIn some cases, it is worth “breaking” the CD concept to mitigate a release risk. For example, I’ve learned that Big Tech companies such as Google do code freeze on the holidays since most of the employees are with their families, which results in less workforce to overcome production issues.\nA word of caution ⚠️ Link to heading test, testing, and some more testing\nWe should stay on guard about the frequency of using a freeze, it may point to unreliable tests , hence strengthening the testing chain will reduce the need for it. Moreover, some might argue that your processes have problems since you say certain contributions can’t integrate. There are many possible reasons, such as:\nNo automated tests. Slow and\\or flaky tests. Long feature branches. Unagreed design changes. Broken builds are not being immediately reverted. Developers don’t work on the latest main trunk. Whatever it is, you’re not doing CI if you cannot integrate without stopping the whole team.\nFinal words Link to heading The target is to release\nThe truth is that there are no absolutes here.\nThe point of continuous integration and tests is to shorten the feedback loops and give programmers more visibility. As a result, there are fewer problems in testing and builds, but this doesn’t mean you don’t do the other parts of your development cycle — they’re just more efficient and effective, as development-related issues are more likely to be caught earlier in the process.\nNevertheless, a high degree of confidence does not mean something should go into the release without passing through the same final stages, and the code freeze is a critical element of this. To ensure the baseline for what you ship is as expected, you will still need it (or at least a branch).\nNote that, simpler cases probably don’t require freezing. The CI process should ensure that a development branch’s state can be released. Though, there can be MANY reasons why some specific code cannot yet be released into production. It is possible that other dependencies are required to be released at the same time or for any business reasons.\nIn any of the cases, IMHO, the release risk has to be managed, in some cases on the account of reducing the CD rate, though we shall strive not to harm it and find other ways.\n","id":17,"tags":"agile codefreeze scrum softwaredevelopment","title":"Is Code freeze still relevant?","url":"/posts/is-code-freeze-still-relevant-9c077495b64/"},{"content":" It’s like learning to ride bicycles whole over again Link to heading As long as I recall my relationship with computers, I’ve been using Windows. I customized everything to the perfection that fits my needs. Whether it’s keyboard shortcuts, specific applications (like this one) that helped do my work, scripts, and more. If it can be modded or automated — I’ve done it.\nRecently it all changed. 😱😱😱\nI decided to take a new position. I confronted the fact that my daily usage will rely on macOS, which was unfamiliar territory for me. What to do? How will I get used to it? Will I be able to be productive as I was while using Windows?\nWell, I approached this problem like an engineer. Research the hell out of it; go one need by one to resolve it.\nlike an engineer\nHomebrew to the rescue ⛑️ Link to heading IMHO, Homebrew should be the first application to install on your Mac. Basically, it’s a package manager that lets you install software tools and developer frameworks from the command line (similar to chocolatey on Windows). As a cmd (or, to be accurate, Windows Terminal) replacement, I decided to play with the terminal that shipped with the system. However, after a while, I just installed iTerm2 with Homebrew.\niTerm2\nThis highly customizable terminal provides a comprehensive set of features, with split pane windows, easy text selection, autocomplete, mouseless copy, paste history, and instant replay(to rewind). iTerm has a perfect match in the Oh My Zsh plugin, which customizes the themes and configurations of the terminal.\nIf you’d like more pre-configured customization (Adir Cohen🙏🏻 ), you can run the all-in-one script that installs iTerm2, Oh My Zsh, and more, from here:\njldeen/dotfiles\nManage your copypasta 🍝 Link to heading On Windows, I heavily relied on ditto (even blogged about it), which isn’t supported on Mac, and I was looking for a suitable replacement. I found comfort with CopyQ, which has similar features (such as storing text, HTML, images, or any other custom formats):\nCopyQ\nWindowing-based multitasking Link to heading It is a well-known fact, keep your hands on the keyboard to boost productivity by minimizing mouse or trackpad use. Switching to full screen or snap windows side by side to allow multi-tasking can be painful using the mouse to resize the different windows. Rectangle does exactly that. This free and open-source tool manages your screen and application’s windows in a hassle-free manner.\nUsing Rectangle is as simple as a keystroke\nIf a picture worth 1000 words, what is a video worth? Link to heading I find sharing screenshots, videos, and gifs very helpful in different situations, like when you need assistance with something that doesn’t work correctly or demonstrate your work. To take screenshots on your Mac, you have the native option, which I heavily rely on:\nscreenshots\nJust click on the combo above and drag the crosshair to select the area to capture. While a screenshot is a built-in option, taking video\\gifs isn’t. I found that Kap, which reminds me of SnagIt capabilities, is an open-source screen recorder that is clean, simple, and does precisely what you’d expect from a screen capture application, just taking captures 😀.\nOS customization Link to heading I think this video really made the difference for me while going from Windows to Mac. In Lucas’s own words:\nIt has everything from right-click to file explorer to uninstalling programs and more… in the most efficient way possible.\nNo notepad++ , don’t panic — VSCode Link to heading Commonly used by developers, Visual Studio Code is an excellent replacement for notepad++; with extensions and a bunch of other unique capabilities, this is a productivity boost for sure.\nTo wrap up Link to heading Overall, I feel my experience is almost the same between PC and Mac. After customizing the stuff I need and getting used to the new keyboard scheme, I can say that I have become more and more comfortable with Mac. Furthermore, I now get why people love it — clean and simple design with a strong spec.\nOne final note, in the end, the apps you choose will be totally dependent on your work, and you’ll need to learn how to customize your set of tools to become a power user.\n","id":18,"tags":"windows developertools macos productivity","title":"Developer story: Getting used to macOS as a long-time Windows user","url":"/posts/developer-story-getting-used-to-macos-as-long-time-windows-s-user-30o0/"},{"content":" What is YAML? And how it works? Link to heading Recently I switched jobs, and as part of this change, I’ve been introduced to a whole new tech stack. RabbitMQ 🐰, Java Spring, Docker, etc. (meaning more subjects to write about 😂). Most of the technologies I use on a daily basis consume YAML as their configuration. In this post, I’ll try to illustrate what I’ve learned (and from where) while trying to understand this new world.\nLearn the YAML way\nIt is what it is 🤨 Link to heading YAML stands for Y AML A in’t M arkup L anguage, originally named Yet Another Markup Language. The name was chosen because it requires much less markup than other traditional languages, such as XML. It distinguishes it as more data-oriented rather than markup-oriented. YAML spec says it better:\nYAML™ (rhymes with “camel”) is a human-friendly, cross language, Unicode based data serialization language designed around the common native data structures of agile programming languages.\nWell, what is it used for? 😒 Link to heading It has become widespread for writing configuration files because it uses a human-readable, intuitive, and flexible language. It can be used with almost any application that needs to send or store data (and has no code execution capabilities — Secure?). YAML is a superset of JSON, which means any valid JSON is a valid YAML file. It has several advantages over JSON; it can self-reference, support complex datatypes, embedded block literals, support comments, and more. JSON VS YAML\nFurthermore, I’ve recently learned that one of the most common usages for YAML in the java world is an autogenerated code using swagger (API deployment). YAML defines the classes, and swagger generates the code. But that is a separate story for a different post.\nHow does it work? 💪🏻 Link to heading The basic building block of YAML documents is a key-value pair. The nesting is based on indentation (similar to Python), making it resistant to delimiter collision. Just keep in mind, whatever you do, DO NOT USE TABS. Yaml hates tabs, and it won’t work. Tip: use a YAML linter, whether an online one or a plugin in your IDE. Writing YAML\nIt is insensitive to quotes and brackets, making special characters more easily defined, especially for strings. To better explain the above concepts, you can find below some simple examples, which I found essential to know when starting to use YAML:\nVariables are defined using a colon and space :\ninteger: 17 string: \"17\" float: 17.0 boolean: Yes A list or array can be defined using an inline format that’s similar to JSON or a conventional block format:\n--- # To Do List in Block Format - Homework - Walk with the dog - Dog should eat homework --- # To Do List in Inline Format [Homework, Walk with the dog, Dog should eat homework] You can denote a string with a | symbol, which keeps newlines , or a \u003e symbol, which folds them:\ndata: | Each of these Newlines Will be broken up data: \u003e This text is wrapped and will be formed into a single paragraph Do you want to know more?\nThe YAML complete documentation can be found on its official site. It is worth going over to be familiar with it. Also, there are plenty of online tutorials; I’ve found this one to be a great source:\n{% youtube 1uFVr15xDGg %}\nTo Wrap Up 🌯 Link to heading YAML is a data-oriented language and a superset of JSON that comes with multiple built-in advantages. It became an industry standard for configuration files. But overall, it is human-readable, which makes it easy to use and maintain. Just be gentle with these whitespaces.\nYAML\n","id":19,"tags":"devops softwaredevelopment configuration yaml","title":"A brief introduction to YAML","url":"/posts/are-we-all-yaml-engineers-now-538j/"},{"content":" But I’m a (scope) creep…what the hell am I doin’ here? Link to heading Here is a situation that I am pretty sure every team or individual contributor has encountered throughout his career. You get well-defined requirements, review them, ask questions, adjust them with your product owner, and prepared one heck of SW design. Soon after, the implementation phase begins, and a few hours or days before the end of the story, the business calls and asks for an extra feature (or change) to be implemented. WHAT?!\nWhy now?\nUsually, the project manager\\product owner is responsible for filtering out these requests as “must-haves” or “nice to have”, but there are cases where the business wants to squeeze all these features into a release. This is the case of **scope creep ** — or the kitchen sink syndrome .\nIts roots come from poor change control, lack of proper initial project objectives, weak project management, poor communication, and lack of initial product versatility. This situation is a risk in most projects, often results in unexpected incurred costs (budget overrun), and has a significant effect on the team’s motivation, on the project’s timeline by introducing complex change late in the release plan and enforcing retest on impacted areas too.\nHow to manage it? Link to heading “It is impossible to control scope creep, so always work on the highest-priority features.” (Bleiweiss, A., Bupp, J., Johnson, D., Meister, J., Murphy, B., Temchin, M., \u0026 Oldfield, P, 2009)\nNow that been said, other activities that can be done:\nTry to establish a change request process before the project begins. Say something to the effect of “Here’s what we’re going to deliver. If you want something else added, you can write it down, submit it, then we’ll figure out how much it’ll cost you, and you can decide whether you really want it.”\nEnsure everyone understands the “cost” of requesting additional changes after committing to initial work. For each request, provide (every time) a revised due date, cost in time estimation, and what is going to be delayed\\dropped to squeeze this latest request. Making sure that this request has consequences is fundamentally the way to go. The motif is to do more by doing less.\nPlease add more features\nInvest in requirements gathering , be sure to ask questions, raise any concerns and try to address them with all stakeholders reaching well-defined requirements. Keep in mind that you should be flexible for changes, knowing that many unknowns can be found along the way.\nFor addressing weak project management, get them highly involved. Define project scope with them, provide regular communication. It might be a short mail summarizing what’s done this week or a weekly check-in meeting. Share with them just enough information to empower them to take decisions, but not so much that they are overwhelmed.\nCan you add a few changes\nAs for communication, I’ve written a post about it in the past. Everyone working on the project must be on the same page. Expectations and the work that needs to be done must be articulated clearly to have a mutual understanding of responsibilities, boundaries, and timelines.\nUse tools to manage the project’s schedule, needs, and documented requirements. It allows each task to be clearly defined, prioritized, and assigned. To keep track, define a check-in meeting on the cadence that meets the team’s preferences. It is excellent for keeping track of things, remind people that they are part of a team with a shared vision that supports each other.\nTo wrap it up Link to heading A healthy respect for boundaries and clear communication are a few of the things you and your team need upfront to avoid scope creep. Making these priorities upfront will save you a lot of time, energy, money, and stomach aches along the way.\n","id":20,"tags":"softwaredevelopment requirements softwareengineering scopecreep","title":"How to deal with the kitchen sink syndrome","url":"/posts/how-to-deal-with-the-kitchen-sink-syndrome-51ap/"},{"content":" It’s complicated; Dealing with workplace drama. Link to heading Everybody, at some point, will encounter a challenging colleague. Being able to deal with a person like that is part of developing conflict resolution skills and learning to overcome those setbacks.\nIn the following paragraphs, I will try to illustrate how I deal with these situations.\nWhat do you mean by difficult people? 🤔 Link to heading To be honest, we have to know that not everyone we struggle with is someone who tries to give us a hard time, as every relationship will have friction moments. Even though it’s hard to put people’s nature into categories, the below image illustrates some traits that can be classified as “difficult” in people we meet (and I bet you can think of more):\ntypes of toxic people\nUnderstand what’s really going on 🙄 Link to heading First, try not to assume that everyone is against you; this might be true in some cases, but you should also try to understand what is really happening. Furthermore, assume best intentions (until they prove otherwise). It allows us to work toward a solution.\nSecond, I would take a different perspective, what if you are part of the problem? Think if you find that you believe that everyone you work with is creating a problem, you might be the problem. Try moving forward (easier said than done, but acknowledging that is the first step) and get them out of your head.\nAnother option is to try seeing the situation from the other person’s point of view. Sometimes, just understanding where they are coming from creates the opportunity to respond with empathy.\nIf the above doesn’t work out, you might be dealing with a toxic person. If such a case, as much as possible, don’t take what they are doing as a personal attack; it is not you that they “hate”; it is everything different than their beliefs. They are just looking for a target. Rise above.\nWhatever you do, don’t respond emotionally; you’ll play into their hands. The problem is theirs and not yours. Find people who care about you to speak about it and lean on them, but keep the circle small and don’t share it with everyone. Be intentional about where you ask for help.\nOk, ok — so what to do? 🙋🏻‍♀️ Link to heading Focus on solutions, not problems. Communicate! Try to communicate in person whenever possible. You might not have been clear with them in the past. So try involving someone you trust to act as a mediator, a buffer between you and them who prevents you from responding poorly to them and not engaging emotionally.\nBe honest\nBe honest, share what you see as the difficulty without assigning blame. The goal is to come to a common ground so that you both understand clearly the real issues. Be clear, direct, and brief. Share what you are dealing with and ask the other person to help you understand their position.\nNevertheless, be aware that not every issue you have with another person will be resolved. Try to understand, reconcile, then leave knowing that you did everything you could.\nA mentor’s advice (it might be your manager, colleague, or someone else you trust) can help you navigate the next steps. Since each situation is different, it is hard to say the next steps ahead of time. Yet, the right person can provide great direction so that you can move forward. Just remember to keep the circle small.\nGratitude\nLastly, Gratitude makes us happier. Redirect yourself toward the positive. In time, I learned that surrounding yourself with positive people, thinking about everything you do enjoy about your job, and talking about those things with other people help fight toxicity.\nConclusion 🤗 Link to heading Getting along with difficult people can be challenging, but it doesn’t have to dominate your day. See things clearly and act intentionally. Let facts guide you, not emotion, and seek to grow through difficulty while helping others.\n","id":21,"tags":"toxic work careeradvice softwareengineering","title":"How to cope with a difficult colleague","url":"/posts/how-to-cope-with-a-difficult-colleague-456/"},{"content":" First, make it right. Then make it fast. Link to heading Premature Optimization\nBack in the seventies, Knuth wrote the above quote in his paper “Structured Programming with go to Statement” at times when computational power was slower and expensive than nowadays. Nevertheless, it doesn’t mean you shouldn’t take it in your consideration. Note that the quote doesn’t stand for itself, and to get its true meaning, you should read the paragraph that follows this famous saying:\nYet we should not pass up our opportunities in that critical 3%. A good programmer will not be lulled into complacency by such reasoning, he will be wise to look carefully at the critical code; but only after that code has been identified. It is often a mistake to make a priori judgments about what parts of a program are really critical, since the universal experience of programmers who have been using measurement tools has been that their intuitive guesses fail.\nGood Measure\nTo me, what it really means, there are obvious optimizations (like not doing string concatenation inside a loop). Still, anything that isn’t a trivially clear optimization should be avoided until it can be measured. Failed to do so can introduce unexpected bugs and can result in high efforts to overcome them.\nThat being said, measurements can lie. Focusing on hot-paths and optimizing them might cause you to miss that it is a symptom of poorly designed code. There is a simple solution: be sure to design first. Thus, a more holistic approach will be finding those places that don’t correlate with your design and adjust them accordingly.\nNote that until you‘ve written code that you can measure, you’ll have to make some performance decisions before anything exists. Sometimes these decisions are difficult to change if you get them wrong. For this reason, it’s good to have a general idea of what things cost, so you can make reasonable decisions when no hard data is available.\nPremature Optimization\nFurthermore, I saw cases that premature optimization was used (or abused) as an argument for not designing your entire application architecture to run fast in general, scale, and be easily optimizable—basically, an excuse not to optimize code at all. Don’t be confused. Designing a solution is your engineering responsibility.\nHow early to optimize and how much to worry about performance depends on the task. When writing a script that runs a few times and only by you, I would worry less about performance. But if you work on a service with many users and will be used in different ways — be sure to optimize to cover all the diverse use cases efficiently.\nHowever, a balance must be struck between performance and readability, maintainability, elegance, extensibility, and so on.\nTo Wrap up\nSlow performance can’t be blamed on the language or tool or CPU or memory. It’s a delicate balance of so many things, which is why it’s nearly impossible to optimize early.\nThe developer has to balance between design and optimization. To my understanding, he should design first, code, and profile it to see which parts should be optimized, and do it iteratively. Here’s a great example.\nA simple and elegant design is often easier to optimize at these earlier stages, and profiling may reveal unexpected performance problems that would not have been addressed by premature optimization.\n","id":22,"tags":"softwaredesign softwareengineering softwaredevelopment optimization","title":"Is premature optimization really the root of all evil?","url":"/posts/is-premature-optimization-really-the-root-of-all-evil-35d9/"},{"content":" On the focused effort of making a working prototype Link to heading There are many ways you can determine whether a new feature will add value to the product or turn out to be a complete waste of time. For instance, you can undertake user research, analyze the demands of the market, and study existing solutions. However, we (developers) have a fantastic tool in our sleeves: Developing a running project that demonstrates the proposed solution’s key ideas is your optimal option — in my opinion. Whhhhhhhhhhhhhhhhhy\nHere’s why.\nJust one small thing: what do I mean by “demo”?\ndemo\nWell, a demonstration, also known as a customer acceptance test, is usually performed by showing the product or feature to stakeholders within your organization shortly after completing it.\nIts main goal is to make sure everyone knows what you will be releasing and reduce the risk of investing time in the wrong direction. It should keep everyone on the same page and lead to a better product and happier customers. Thus, the demo plays an essential part in your decisions.\ndemo oriented\nTherefore, focus on developing the most valuable features and code them as quickly as possible, but don’t compromise over quality. Write down any shortcuts and obstacles you’ve found on the way. It will help you in the future when it’s time to decide which product to put on the road map.\nIf done often, demos create accountability, a drive to deliver, which supports the team’s continuous improvement. Furthermore, as a by-product, the demo allows the team to be proud of what they’ve developed and have dedicated time to celebrate small wins. A word of advice: be careful of demos that are too polished. You might create a false impression among participants that you’re ready to launch when that might be far from the truth. To prevent confusion, clarify which shortcuts have been taken and what is left to be done.\nProof of Concept\nUntil now, I’ve been talking about demos in the software development life cycle. But there’s another way to do demos — a PoC, or proof of concept. PoCs are usually done in the developers’ environments, without any software ( QA ) testing, with some cut corners at times, but with the goal of getting quick feedback. The purpose is to keep the team “in shape”, meaning preserving their ability to quickly create solutions while deep diving into new tech stack, development methodologies, and more. This method is highly recommended to busy Individual Contributors who don’t find enough time to play with the code.\nSimply put, I believe demos, regardless of how they are done, are an excellent way of sharing knowledge with others, learning new stuff, and generally keep improving one’s work.\n","id":23,"tags":"softwaredevelopment softwareengineering programming demo","title":"How demo-oriented programming makes you better","url":"/posts/how-demo-oriented-programming-makes-you-better-44mo/"},{"content":" Why a retrospective meeting is a best practice for any team Link to heading Does the team complain about bottlenecks that slow them down? The same things happen over and over again? Luckily there is a simple practice that, in my experience, can help instantly. What I actually mean is, does your team take part in a retrospective meeting? No?! 😱 Make sure to adapt it ASAP, no matter which software development methodology you follow.\n“Those who don’t learn from the past are doomed to repeat it.” — George Santayana Link to heading A retrospect meeting is a safe place. Everyone can say what’s on their mind without being judged for their opinions or getting negative feedback, making it a psychological safety environment. Plus, It gets everyone involved.\nA safe place\nBesides, this kind of session pushes each team member to look back (and not forward as done daily), share their views, and eventually, learn as a team from their mistakes. Encouraging to build trust in each other is highly valuable for any team (more on that). Another essential point is that it creates a place where we can celebrate our small wins by pointing out what went well and making sure we keep doing that.\nFurthermore, retros have an immediate feedback loop that promotes a virtuous circle. The team collaborates to identify low-hanging fruits and add them to the backlog.\nSmall, concrete retro items beat a growing backlog\nAnything that can be solved instantly (next sprint or so) makes everyone happier (satisfied and motivated). Having more clarity on what needs to be done next, thus continuously improving the team.\nJust play it safe; it’s easy to jump into the blame-game trap and weak excuses, so be careful and focus on self-reflection as individuals and as a team.\nThere are plenty of tools to facilitate retros (though you can do without since the idea behind it is what matters). I’ve experienced ideaboardz, a free tool to create your own board, where each participant can create and share his thoughts. Simple and gets the job done. You can test here:\nIdeaBoardz - test Conduct collaborative brainstorming sessions with distributed teams\nI’ve read many recommendations about parabol but haven’t tried it myself. This tool focus on making m̵e̵e̵t̵i̵n̵g̵ work session great and its UX shows it. It has a free layer which suffices up to two teams. Among its features, you’ll find guidance through the different stages of the retrospective (icebreaker, reflections, grouping, voting, discussing). And it sends you a meeting summary at the end, so no-one needs to take notes—a must.\nA different but similar tool, reetro, has many features in its free versions, such as action tracker, export to various formats, and integration to Jira or Azure DevOps. So consider that too. Lastly, if you look for activities and ideas for making agile retrospectives more engaging — go to funretrospectives.\nTo wrap it up Link to heading Retros create a change (in the long run), and due to their nature, changes tend to feel unclear and overwhelming. Thus, in my experience, you’ve got to start somewhere and tweak along the way. Regardless of your current practices, retros will create transparency for future activities, leading to continuous improvement.\n","id":24,"tags":"","title":"Look into the past, improve the future","url":"/posts/look-into-the-past-improve-the-future-4jbk/"},{"content":" The importance of a well crafted, humane onboarding process Link to heading You’ve prepared a new resume, searched for challenging positions, submitted your CV to various companies, participated in many interviews, asked your interviewers about the working environment, considered your culture fit. Eventually, you’ve received several job offers, prioritized and weigh them down …. and finally, you’ve agreed to take one. 🤗\nFound a new job, yay\nThe exciting day has arrived — your first day on the job.\nI bet you remember it, the thrill of starting a new place, a new position. You feel it in your bones. You want to bring value ASAP, but how? What’s the schedule of each day? where should I go now? Who can answer all those questions popping on your mind? You are confused. You feel a “reality shock”. All your expectations are shuttered.\nSo, what now? Onboarding to the rescue! Link to heading Now what?!\nNowadays, it is commonly known (as studies show #1, #2, #3) that employee recruitment isn’t ended after signing the offer. A hiring method that relies on employer brand, position marketing, and an onboarding plan is an effective recruitment process that considers the candidate in its center, helping him socialize better.\nA well-defined onboarding plan starts before the first day when HR representatives sit down with the hiring manager to assemble a plan that covers:\nSetting a schedule — Set the training timeframe, coordinate with all involved functions (direct manager, buddy, etc.). Arrange ahead of time a working environment, including laptop, mouse, keyboard, and different IT permissions. It will prevent any bureaucracy from bogging her down. Find a Buddy — Look for patience, emotional intelligence, good communication skills, and knowledge around the organization’s informal channels (each org. has them) when searching for the right “buddy”. She should show her around on the first days, have lunch with her, and make sure to answer any raised question. Identify the best fit for this role, it has a significant impact on the new recruit’s success. Training material — Should include scheduled meetings with key players and different team members. Furthermore, consider lectures, presentations, and video courses about general organization information and specific material for the job. All is taken into account by the hiring manager according to the job description. A gesture — everybody likes to get attention, sending a welcome aboard gift will do the trick 😊, it might be anything office-related. Whatever you find respectful. Make sure she’ll get it before day one. People, people, people Link to heading It’s all about the people\nThe new employee socialization is essential. It provides her higher satisfaction leading to better performance, lowering the potential of her quitting the job, eventually creating a virtuous circle.\nI’ve participated in several “buddy plan” and came to the conclusions that the following principles should be adopted in any onboarding process:\nBe part of the team’s daily life — the goal is to give the new team member the feeling she brings value. Assign some tasks that fit her knowledge and experience. The tasks’ execution is accompanied by one of her colleagues, thus preventing any frustration from her side. Along the way, many questions will be answered, and knowledge will be gained. As more tasks are being accomplished well, the more her self fulfillment will grow. Socialize better — the hiring team should introduce the new employee to different social circles. Another option is to create a safe place for new employees. Where they can talk to each other, ask questions, which they don’t feel comfortable asking in their team, go to eat lunch together, keeping in touch with employees hired in the same week (or so), and in such a way, empower each other. Besides, add her to all different official distribution lists and non-official (Whatsapp group, etc.) ones too. Communication is the key — create open and honest discussions. Allow enough time for questions, respond to them immediately. Remove any raised obstacles; it communicates that you are being cared for. Be sure to share your feedback accordingly. Sticking to the above will be comprehended as a good experience, resulting in a better connection to its mission. Knowledge sharing — write down all the required knowledge in one place. There are plenty of tools (SharePoint, Notion, Google Docs, etc.) that fit this task. The tool will hold all the required information that any team member needs to know when doing her job. She can check there when any question is being raised, serving a twofold purpose: keeping the team balanced (instead of being bombarded with questions) and encouraging independence from the new employee side. The onboarding process that answers the above needs provides a clear-cut message; You were hired by a company that cares for your success, which provides peace of mind to quickly join the team and, most importantly, fulfill your potential, which you were hired for.\n","id":25,"tags":"softwaredevelopment careerdevelopment hr onboarding","title":"Congratulations and welcome aboard!","url":"/posts/congratulations-and-welcome-aboard-3iba/"},{"content":" Me against a bug, reminding myself how to solve any defect Link to heading Dear developer,\nDon’t give up, keep up with your efforts to find other ways to understand the bug’s root cause. I know it can be frustrating. The agonies with the process can be ruff. But, you’ve got it, you solved many in the past, and you will solve this one too. It is part of your job.\n5 stages of debugging\nInvestigate the crime scene 🕵️ Link to heading Embrace all your experience, the collective knowledge you gained with your past ventures. Rely on previous bug records that you assume related to the defect’s scenario, you might find some hidden gems that will help you think of a way to cope with it. Check any logs the application writes, search for any abnormal behavior (such as errors, exceptions, etc..). Collect that interrelated items into your brain (or better write them down).\nUse version control , read the history of the files you suspect the issue resides within. Rollback through versions’ history, up to a point it is no longer reproduced. Thus, helping you to understand the specific version in which the issue was first observed.\nIdentify main suspects (controllers, buttons, interactions, etc.) that participate in the scenario, have a strong understanding of the steps that produce the bug, try to identify its frequency, whether an always reproduced anomaly and in which conditions. Get familiar with what is the expected behavior.\nWisely spread breakpoint using a good debugger (invaluable) and do line breaks steps. Navigate through stack trace on the application’s main flow (for example input and output around the code’s area), use dedicated IDE extensions that assist you while debugging (such as OzCode).\nNo clue what the problem is? Ask someone ; it might be a coworker, a friend, or an online community. Show them the information pieces you’ve collected. Generally Explain what the program does, what it should be doing in this particular instance, and what it’s actually doing.\nShare code snippets of what you’ve narrowed down using the IDE while asking for guidance: “I identified the issue is created by the following code, it’s setting the value to X when it should be Y, but I can’t see why that’s happening”. There is nothing like a fresh pair of eyes to solve the riddle.\nFurthermore, books (for #1 or #2) on advanced debugging skills can be your friend too. Reading will help you think of creative solutions. I bet you’ll find some tricks out of your sleeve afterward.\nRepeat the above until you’ve got that **eureka ** moment.\nNow that you’ve identified the root cause, what else? 🙄 Link to heading Found it!\nTry creative ways to solve it. If you find yourself struggling, go to the framework API documentation (such as Microsoft docs) or read through your project design documents , both might reveal the hidden parts.\nSearch for similar solutions using your favorite search engine (e.g., DuckDuckGo), filter relevant results — you might find blogs, books, and tons of information on related subjects. It is not a shame to read answers in StackOverflow, so use it wisely.\nApply various techniques, such as registering to main flow events, adding helpful log printouts, reading the framework’s source code (in case available). Consider if refactoring is needed to reduce coupling, don’t just fix a bug, fix the entire class, so you’ll never be able to create similar bugs again.\noverkill\nOne last thing, it’s a kind of an overkill, but if all odds are against you, use a reflector (it depends on the language), which enables debugging without source code (unless not allowed — obfuscation) to pinpoint the issue. I highly recommend using dnSpy , which I previously blogged.\nManaged to fix it? 🧩 Link to heading Done\nThe battle hasn’t finished — add unit tests to prevent a “make a fix, cause a problem elsewhere” situation. Update the design document if needed, run automatic or manual sanity tests to verify the fix. Add code comments to explain the context (the “why”) of the fix (more on that).\nQuestion your methods, you may be able to learn and get better , so ask yourself:\nHow could I have avoided this waste of time? What did I overlook in the first place, and why? What unvalidated and/or wrong assumptions did I rely on? It will improve your abilities. Furthermore, sharpening your gut instinct. Eventually, over time you learn to automatically notice all those minor signals that are too easily overlooked, leading you quickly to the right answer. In the end, it’s all about deliberate practice.\nShare what you’ve learned during the whole process, prepare some slides, and have a post-mortem session with your colleagues, so others will benefit from your experience too.\nLastly, don’t forget Alan J. Perlis words:\nThere are two ways to write error-free programs; only the third one works.\nSincerely (until next time),\nYour future-self\n","id":26,"tags":"","title":"A letter to the lonely developer","url":"/posts/a-letter-to-the-lonely-developer-458f/"},{"content":" My personal experience to jump off the bandwagon (effect) Link to heading Imagine the following situation. One of your experienced colleagues talks about doing some work, which she’s passionate about and sure it will provide better results for the team. She has fire in her eyes when she talks about replacing technology X with Y.\nYou feel it right into your heart. Your colleagues seem to agree with her. She’s so right. Though, she hasn’t proven the business value of her idea (just the technical aspects of it). You are tempted to agree too. That moment, I was there many times.\nCause everybody does that\nThe latter was coined by Steve McConnell, Code Complete’s author:\nCargo cult software engineers justify their practices by saying, “We’ve always done it this way in the past,” or “our company standards require us to do it this way” — even when those ways make no sense. They refuse to acknowledge the tradeoffs involved in either process-oriented or commitment-oriented development.\nCargo cult (science) was termed by Richard Feynman, who was inspired by the WWII stories of the South Seas people. They’ve built a runaway, a control tower, and even an airplane from bamboo sticks, in the hope the god-like airplanes will arrive again and drop the marvelous cargo. They did everything by the book, but it didn’t work — something essential was missing.\nBack to my experience — I’ve identified a cargo cult moment, but what’s now, how to deal with it? What should you do next time? In the following lines, I’ll try to illustrate my actions as I learned in time.\nValue Link to heading What value do you add?\nAmong our responsibilities as developers, we’ve been hired to help the business making the right decisions. The software we develop brings value. Using any of the currently hyped frameworks, just to say you are using the cutting edge, attractive, everybody speaks about, doesn’t mean a thing if it doesn’t bring value. As simple as that.\nSo, what to do? Don’t take things for granted; question the suggested idea:\nWhat is it going to solve? Why will it make us more productive? How will it bring new customers? Will it scale? Do the benefits outweigh the cost? Do we need specific training? If you can’t get the answers from her, find the person who can. Either, other developers, project managers, or any stakeholder you may find relevant, just don’t keep them unanswered. Leave no stone unturned in the search for knowledge.\nFurthermore, it is highly suggested to allow enough time to prototype the idea to get more insights, and some of the questions answered.\nAnyhow, I bet you can find more questions; please do share in the comments section.\nDon’t get confused by the experience Link to heading Experience\nTitles and positions won’t make everything your colleagues say true. Sure, they might have more experience, more knowledge — but, remember, everybody makes mistakes. Sometimes, as an outsider to a problem, you are free of misconceptions and assumptions, which helps you see the details clearly and in a different way.\nDon’t weigh down the solution based on the person proposing it; otherwise, it creates a bias — so separate between the two. Consider the pros and cons of the idea, share it with them — it is in your responsibility. They expect it from you.\nDon’t be afraid to be proven wrong, defend your idea, and treasure the moment, you can learn from any experience. So be positive about it.\nFinal words Link to heading Cult culture can destroy any software projects. Thus, being aware of the bias created by it gives you an edge to avoid its effect.\nBe proactive. When identified, reduce the impact by allowing yourself enough time to search for more information, set (alone) focus time to reduce unreasonable judgment influence, play devil’s advocate for important decisions, and make sure to ask many questions.\n","id":27,"tags":"bandwagoneffect softwaredevelopment softwareengineering cargocult","title":"Everybody was cargo culting","url":"/posts/everybody-was-cargo-culting-46n5/"},{"content":"The aspects of code complexity are broad; one of them result from the design of our code. Design weight is the cognitive effort reading and maintaining your code — a metaphor used for emphasizing how it weighs down your progress.\nThe main symptom (as I encountered) is code that forces you to remember specific areas to connect the dots between them. While relying on your memory has its benefits but also a capacity, leading to losing details, causing you to re-read with an effort to memorize it, reducing motivation to be engaged with the product.\n“Keep it simple, as simple as possible, but not simpler.” — Albert Einstein\nIn an analogy, simple code is like bicycles, while a complex code is like a jet plane. The bikes are simple to use, once you’ve learned to balance yourself, you’ve basically mastered the whole thing, while the jet takes extensive training to use and understand. You have to go back and forth until you gain knowledge and enough confidence to use it.\nKISS\nKISS (Keep It Simple, Stupid), I bet you’ve heard it in the past (and keep forgetting it). It’s one of those sentences that are easier to say than done. In the following paragraphs, I’ll try to illustrate six principles in which adhering to them may assist you to apply simplification:\n1. Refactor is an ongoing activity Link to heading Use YAGNI heuristic — an acronym stands for “You Aren’t Gonna Need It” (coming from extreme programming). Reduce costly design elements based on future benefits. Also, pay attention to “emergent design” — meaning improve code structure consistently. Don’t forget to use unit tests and automated regression tests as a robust safety net to make rapid changes.\n2. Challenge complex features Link to heading Set a dedicated meeting with the product manager, UX designer, SW architect, and other project key players. Share with them your concerns and check the possibility for change, you’ll be surprised how random some of the requirements may be.\n3. APIs, like diamonds, are forever Link to heading Forever ever\nYou can always add functionality to your software, but the other way around isn’t so simple. Skimp with requirements. Before implementation, perform a requirements review meeting with all the project’s stakeholders and delete the less valuable ones. Otherwise, you find yourself with a lot of code to maintain, among with public APIs, which make it difficult to make changes.\n4. Occam’s Razor — more facts, fewer assumptions Link to heading Make as few assumptions as you can (as explained by Michael Lant), avoid basing your design on them. Ask as early as you can, “Are you certain that everything you are doing is truly being done in support of the project objectives?”\nIn the case of some, the answer will be no; remove anything that doesn’t support the project’s goals. According to Michael, choosing which assumption to use is based on your experience. This is where the real work gets started.\n5. End Of Life Link to heading EOL\nFind what’s not necessary anymore and retire it. Perform user research to have a better understanding of used features and concepts. Identify the unused ones and remove them.\n6. Domain-Driven Design (DDD) Link to heading This notable approach by Eric Evans (as published in his book with the same name) comes to the rescue. Evans suggests a way to deal with the bias created when requirements from the domain expert (DE) are going into a specification by simplification chain.\nFrom the DE to PM/Marketing/PO, each modifies the requirements to professional language. Then the Architect/Tech Lead does the shift to the system’s infrastructures for the SW engineers, which “now understand” and can do the work.\nWell, that’s true on theory. In real-life scenarios, it may go the wrong way. Where information is being lost, and details are being filled naturally by our educational guess instincts.\nIn DDD, creating a ubiquitous language for all stakeholders is a must. Using it, everyone can understand each other, for creating an accurate conceptual model. Thus, investing in deeply learning the domain, classify objects into Entities (usually UML is being used) along with identifying entities’ patterns to aggregate them by context. Eventually, reducing any future mistakes that may increase complexity.\nIf you’d like to go deeper on that, head to Sara Miteva’s blog-post:\nhttps://dev.to/microtica/the-concept-of-domain-driven-design-explained-1ccn\nTo conclude Link to heading Simplicity has its price. Invest your efforts, and you’ll profit a maintainable product and happy teams. Eventually, it’s all about people and continuous improvement.\n","id":28,"tags":"domaindrivendesign designweight softwaredesign softwareengineering","title":"The Burden of Software Design","url":"/posts/the-burden-of-software-design-3cbj/"},{"content":" Tools and techniques for exploring an unknown (large) codebase Link to heading You’ve received a new responsibility or walked into a new job where there is existing code to work with. The source control has been introduced to you, realizing you have a lot to learn. Now what? Asking yourself, how should I become acquainted with the new codebase? Which for some, may be intimidating. Below I’ll attempt to illustrate my techniques for getting familiarity with the code, leading to structured knowledge.\nDon’t panic, relax, it takes time Link to heading Ahhhhha!\nIt’s a process that takes time. Start with debugging the main flow of the application. How do you know where to start? I suggest inputs and outputs. Find the entry point, the one that starts the whole program. If you can’t find it, go ahead and debug a delimited functionality, such as a button’s click.\nFlow with the code, do line breaks steps. Navigate through the stack trace to see where the primary methods are and continue from there. As I experienced it, it may take weeks before you’d feel safe making any change, and months before feeling “comfortable” with the code. Eventually, comprehending the code’s meaning in business terms.\nHigh level Link to heading What’s you don’t see\nApproaching a comprehensive software architecture can be overwhelming. I highly advise using tools to generate a dependency graph to top-down explore it. First, visualize the graph between the different assemblies. This will give you an idea of how features and layers are organized. Then dig into namespaces dependencies to have a finer-grained idea of code structure. And finally, you can look at classes’ dependencies to understand how a set of classes collaborates to implement a feature. There are several tools to generate a dependency graph, like NDepend for .NET, for example.\nAnother approach is to use a source analysis tool to determine various module sizes, complexity metrics, and more to get a feel for the project and help identify the non-trivial areas, tools such as the TIOBE software quality framework.\nDocumentation Link to heading Be aware!!!\nGo through the documentations. Some may be good, some may be bad. It depends on the team’s culture (and processes) to maintain them. But no matter how lack of information it is, read them. If they don’t exist — write it by yourself. Later, it will be easier to refer to it and make sure you do so (by not answering questions and pointing to them). Update rigorously by you or any of your team members.\nBe stupid Link to heading There Are No Stupid Questions\nOften the power of communication is underestimated. Don’t be afraid to sound stupid — ask the code’s authors or if they aren’t available, find the experienced ones, I bet they’ll have what to say.\nShare with them the assumptions you made about the code, every conclusion you’ve come to about how it works and what it does. Hear their insights, let them mentor you, consider pair program with them. It will save you many hours in the long run.\nUnfamiliar tech stack Link to heading If the implementation is based on technologies/languages/frameworks, you’re not familiar with, shift between the code and tutorials on the related technologies. Read or watch the tutorial, then go look at the implementation to see how it is reflected in the system, noting any similarities and differences. Helping you understand the design and the circumstances leading to it.\nBaby steps Link to heading baby steps\nIntroduce small changes and see what breaks. Clean the code one step at a time. Add comments to explain what you think the code does. Using a refactoring tool (Resharper 🙄) apply changes to variable names to make them readable.\nReduce code clutter by deleting commented out code, meaningless comments, and so forth. Remove code duplication where possible. Get rid of magic numbers and apply code conventions. Finally, add tests where possible. Not all changes will be kept, but it will help in the orientation process.\nAsk to be assigned with investigating defects — it’s an opportunity to gain knowledge from the users’ perspective while solving (and understanding the meaning of the software). Furthermore, unit tests help you practice with the code usages, so make time to accomplish them too. Both, allow you to go into the code with a purposeful target which assists you to focus since it’s a contained task.\nTo conclude Link to heading The goal is to reduce the unknowns, your best choice is to simplify the source to reduce its complexity. By adhering to the above concepts, you should get the grasp out of it, know where to focus, and with few steps have better focus.\nRegularly clean the code, always test new functionalities, and allow time for refactoring.\nP.S. If you want to dive deeper with additional concepts, the highly recommended book “Working Effectively with Legacy Code” by Michael Feathers is a must.\n","id":29,"tags":"bestpractices code softwaredevelopment softwareengineering","title":"Diving into the deep code waters","url":"/posts/diving-into-the-deep-code-waters-57p9/"},{"content":" Considering security measures through development stages Link to heading Software development is a complicated task that balance business and technical needs. Furthermore, the organization has to ensure the product complies with laws, regulations, and customer’s requirements while presenting robustness to cyber-attacks based on the customer’s risk-taking willingness.\nHence, I found it important and relevant than ever before based on the growing risks to develop while security in your mind. Nowadays, the accepted approach integrates security measures through all the product development through different stages.\nIt allows us to have an up to date knowledge against new threats, addressing it quickly, reducing the cost and time of finding issues later on in the process, overall lowering the probability of significant weaknesses that may harm the product’s quality. Thus, security is integrated into each step of the software development life cycle (SDLC).\nbug costs on different product life\nBelow, I’ll try to outline various sources and my own experience related to the subject as part of the development phase in the SDLC, assuming a deep work was made to involve security on previous steps (requirement gathering and design), eventually moving from SDLC towards Secure-SDLC.\nSSDLC\nDefine quality gatekeepers Link to heading Somebody forgot to close the gate\nBased on planning steps (which includes proactive steps as threat modeling, security requirements, and security design), define quality gates that effectively identify and block various malfunctions. It may be preventing the addition of external open-source code to the product until approved or no weaknesses were found. Audits by third-party security experts should be considered too. Automation is a must. Some of the well-known security and control measures are:\nVulnerability assessment to identify, quantify and prioritize ongoing risks Dependency track monitors component usage across all versions of every application in its portfolio to proactively identify risk across the organization. Linting to identify any coding standards violation and enforcing well known best practices. There are plenty of tools addressing the need for each programming language ( Coverity, TICS, FxCop, CodeScene, and even the various IDEs — Visual Studio, Pycharm, IntelliJ,and more…) Software Composition Analysis to detect open source vulnerabilities with higher accuracy, for example, Synopsys’s Blackducktool. SAST (Static Application Security Testing), which scans the code for security flaws also referred to as static code analysis. One of the well-known tools in the industry is Fortify DAST (Dynamic Application Security Testing), as far as I know mainly applied to web applications using a black-box test on the front-end to find potential security vulnerabilities by attacking the user interface. Note, unlike SAST, it doesn’t have access to source code (for example Sentinel Dynamic by WhiteHat security) IAST combines the strength of both SAST and DATS methods Runtime application self-protection (RASP) which activity track (by logging) the application’s actions and determine attacks (for example Antivirus software Validate user input, for example, apply XML firewall that protects XML based interfaces (such as REST). It scans in and out traffic to filter content, limit the number of requests, and more. As a role of thumb, use OWASP best practices. Apart from the above points, keep yourself up to date and patched (tools, malware scanners, IDE). It’s no use to test with the old AV or to run with the vulnerable OS.\nSeparation of the working environment Link to heading perfect separation\nA common principle is to apply segmentation and segregation practices to verify that “live” data is only available on production environments, which means developers work on dummy data specifically. It allows them to create a barrier from any weakness to enter into the product.\nFurthermore, meticulously define the needed privileges for each user using JIT admin and just enough administration methodology. Monitor the different environments’ activity (CI\\CD, devs, cloud storage, etc…); any change in privileges, unknown code, new user accounts, unfamiliar IDE’s plugin and more, are just some of the monitoring activities that organizations may choose to lower risks.\nTrain SW Teams for secure coding Link to heading The purpose is twofold; gain knowledge and promote awareness (to be honest, this is one of the blog-post goals). Include learning material on security as part of each team member’s development plan and make sure it is part of the onboarding process.\nCoding best practices Link to heading Don’t know what it does but I’m afraid to delete it\nDevelop according to agreeable coding standards, use tools to verify it. Apply for mutual code review and use dedicated unit tests that cover security issues. That way, each SW engineer is responsible for his code’s weakness.\nFinally, the team’s security trustee has to approve the code against the requirements. Internal audits should be conducted too to identify risks, and design review should be coordinated with all different disciples.\nBugs’ documentation Link to heading Documenting bugs is more of a best practice, which is also true for security issues. Keep records of found bugs, including investigation conclusions, screenshots, logs, and any other supportive information. It may help in the future while encountering a similar issue.\nTamper resistance Link to heading If any uncontrolled change in configuration files happened, send the information to the security representatives automatically and shut down the infected system until approved. Maintain a list of all files in the system; it helps to check unfamiliar changes. Another alternative is to apply AAA protocols that govern access control and application control (e.g., allow list).\nRisk management Link to heading The motto of all successful businesses\nDefine a committee to review the frequent changes in the system, including bug classification. In high rate SW development methodologies such as in Agile, it is hard to keep pace with modifications, and a dedicated authority can mitigate it. Furthermore, metrics (KPIs) that measure trends and anomalies, leading to better root cause analysis should be executed to analyze the risk.\nAnti-reversing techniques Link to heading Either copying the source code or reverse-engineering it are common techniques for stealing your product. Hence, to defend against such abuse, the following method can be used considering no harm to functionality:\nObfuscation is the process of creating a source code that is difficult for humans to understand. Note that while it may take time to reverse this action, it is not impossible. Anti-disassembly takes advantage of the disassembler assumptions. It uses dedicated code (jump tables) or piece of data to cause disassembly analysis tools to produce incorrect source code. Anti-debugging using various methods to block debugging the applications’ code, for example, exploiting system APIs to identify the existence of a debugger or identify code changes by debugger’s breakpoint and many other methods. Packeting is the process of compressing assemblies for making it difficult to reverse engineer it. Finally, it is used mainly for IP protection, and one should not rely on these techniques alone to hide some secrets (like encryption key).\nKeep track with configuration Link to heading The configuration may change along the time. Document the various specs and verify the requirements and needs. There are plenty of automated tools that can assist in that task.\nEncrypt the communication Link to heading \u003c Just to be safe\nUse standard protocols and libraries. DO NOT “re-invent” the wheel (security) — use of controls to protect data at transit and data at rest.\nDo Backups! moreover, do them frequently and test them.\nOverall Link to heading The above are recommendations, which consolidate a few of the known practices in the security field. Here, I decided to touch mainly the development phase (of the SDLC), but further actions can be done in each part of the life cycle. Eventually, lowering the risk of being infiltrated and creating insights about how important is developing with security in mind.\nAs closing words, I highly advise automating everything you can and make it part of the process (continuous improvement), keep in mind that manual tests are prone to human errors.\nP.S. the information above and more can be found at The Open Web Application Security Project (OWASP) which is a nonprofit foundation that works to improve the security of software, here.\n","id":30,"tags":"software-engineering software-development software-life-cycle security","title":"Preserve, Protect \u0026 Defend Your Code","url":"/posts/preserve-protect-defend-your-code-1d5k/"},{"content":" Effort estimation — it’s complicated Link to heading On the dilemma of evaluating software development effort Link to heading For the past few months, estimating effort, a long-standing dilemma of the software industry, bothers me. How should we, as SW engineers, deal with the accuracy of effort estimations? The answer is complicated and has implications over developers’ career growth, having an impact on personal development. There is much at stake.\nSo, I felt the urge to take action. I decided to share my doubts about it over twitter.\nWhich led to an interesting (IMHO) debate over this subject. Below I’ll try to outline the various arguments.\nNo Silver Bullet, Estimation is hard. Link to heading First, I’ll start with Michael Shpilt’s reply, saying that effort estimation is probably one of the hardest things in software, he’s right. Suggesting that to reduce the risk of failing to estimate accurately, one should be knowledgeable about the application’s domain.\nBesides, the estimator should choose ahead of time who are the developers that going to participate in the required feature development. Stating that choosing the best-fitted team-members based on their codebase familiarity will help in reducing the risk.\nI tend to agree on the necessity of specific knowledge in the application’s domain, as without it, things might go the wrong way; it is crucial to the success of the development.\nAs for choosing specific people, it is a task that should be done gently, estimations shouldn’t be based on particular people’s involvement. It may result in a lack of motivation among the team because only specified individuals get specific assignments. Feelings should be considered too, we are not machines. If you insist on proceeding with this procedure, make sure to communicate why to soften the message.\nFurthermore, as broader the unknown, the higher chance a senior developer will be able to mitigate the risk. Leading to the point that inexperienced engineers won’t be able to gain knowledge about unfamiliar parts of the system. I guess the truth is somewhere in between.\nTal Joffe mentioned the excellent [talk] (https://summit2019.reversim.com/session/5c7859231503d900172c583e.html)(in Hebrew) given by Itay Maman on Reversim 2019 summit. Itay has made his slides available (🙏), which may assist for non-Hebrew speakers.\nIn his talk, various points are being raised, helping to lower a few of the risks mentioned above. Tal’s takeaways summarized it well. He says that the lecture’s main delivered message is the need to focus on high-level estimation.\nMeaning tasks should be broken into buckets of effort — a few hours/one day/few days/more. The “More” is Tal’s version for tasks that take longer than a few days, forcing him to break them down to smaller tasks and repeat the process.\nI tend to agree with him. Smaller tasks allow accurate estimates and create opportunities to share the development effort between team members, including the inexperienced engineers (and as a by-product gain knowledge and mentor them).\nHowever, Itay has pointed out that it will only shift the estimation’s difficulty to the challenge of identifying the smaller chunks, making it work only in theory. There is no panacea here - It’s harder than you think (IHTYT).\nIs #NoEstimates the answer? Link to heading NoEstimates as summarized by Magnus Dahlgren\nAs stated by Gal Zellermayer, you should start with the why? It will help you understand the need, forcing you to adjust your estimation methodology accordingly.\nSome are very thoughtful, others are guesstimates. Some are detailed oriented, others are high level. Maybe it is just for self-improvement, or maybe you don’t need it.\nThis approach is especially true when there is no baseline to compare with.\nAnother essential fact raised by Ophir Harran as a reply to Gal’s tweet. In his words, accepting failed estimation is vital over time to improve accuracy; otherwise, you buffer 3x to mitigate, and that cripples teams.\nCouldn’t agree more on that, it may lead to the false perception that effort estimation == duration, which is the root of all evils 👹.\nIt creates the impression that teams should finish their development tasks based on a given number. Without considering it was an estimate (which might be inaccurate depending on the number of unknown factors). Moreover, it might start a blame game (Also mentioned by Itay) between team members on who should take responsibility for the delay\\failure to deliver. Resulting in, paying the price of quality hit and surging technical debt, leading to customer dissatisfaction.\nOmer Raviv joined both of them in recommending Woody Zuill’s approach, #NoEstimates. If you haven’t watched his talk, go ahead and watch it. It’s a must.\nOmer said that it may sound dramatic at first. Still, it might be just a call to explore other ways to solve things without asking how long will it take while avoiding spending time overestimations.\nIn his talk, Woody suggests to select the most essential feature, break it down into a smaller neutral piece of work, develop. Iterate till you ship it or until it is no longer critical.\nNoEstimates in a nutshell\nHe even replied to my tweet. Explaining that in his talk, he shares how he works without estimates. But does not insist that it is the only way to work without estimates, or as Martin Fowler said in his blog:\nIf they are going to affect significant decisions, then go ahead and make the best estimates you can.\nOverall Link to heading My main takeaway is that as SW engineers, we should always question the practices we use, be open-minded about it. If we’ll say “It’s always been done that way”, we won’t progress. Having doubts over our work procedures will push us forward, making us a bit better every time.\nThis reminds me that software is made by humans, so consider it when you take any action.\nAHA and, don’t assume! define metrics, measure, and then forecast.\nAssumptions\n","id":31,"tags":"software-development software-engineering time-management noestimates","title":"Effort estimation — it’s complicated","url":"/posts/effort-estimation-it-s-complicated-4bdb/"},{"content":" My humble opinion on the necessity of a check-in process Link to heading Are you familiar with the situation of getting a code review that is being delayed by your peer reviewer’s nitpicking for filling his code perfection aspirations? Unable to commit due to build server failure? Personal preferences overruled over technical facts?\nLet me see your unit tests\nAll the above are examples of the necessity of a well-defined procedure, guiding us in various situations we encounter daily. It defends our best interest, helps us understand how to handle them based on the collective experience of all SW engineers before us.\nIn the following lines, I won’t deal with the essential need for code reviews and how to perform them, a fact that being dealt in various articles (#1, #2, #3), even by the humble writer of these lines (link). Here, I focus on the crucial need for writing down the day to day team’s code review best practices.\nBureaucracy — again 🤦 or Why do we need it? Link to heading Bureaucracy\nThe primary purpose of a code review is to make sure that the overall code’s health is improving over time. For achieving this goal, numerous trade-offs have to be balanced. Hence a well-defined process for both code review parties assists in bridging any gaps, settle down conflicts and allowing to move faster.\nWhich decreases the chances of something going horribly wrong during implementation. At the end of the day, making the code better without mental investment how to perform it.\nSo, What should it cover? Link to heading It really depends on the team, its daily routines, the development environment, the chosen development methodology, and more preferences in which the team has decided to focus.\nI highly recommend having a meeting with the entire team to consult what should make it in, since it is an essential part of the SW engineers’ work. It has a significant effect on everyone, reflected in the team’s motivation.\nThe guidelines should be brief, written in plain simple language, may include graphics (screenshots, etc…), summarizing the team’s (and the organization) best practices.\nOK, say I’m convinced How do you suggest to maintain it? Link to heading It doesn’t matter. just make sure it is written down, either on a document or on a dedicated web-page; there are plenty of ways to share information these days. With one important rule, it should be in a highly accessible location. Otherwise, it will reduce its effectiveness, collect dust and basically not relevant.\nShared location\nOverall Link to heading By doing so, you’ll increase team productivity, improve the codebase quality. And as a by-product of this process, inexperienced engineers will be mentored — leading to a highly effective team, better products, and happier customers.\nIMHO, one of the best examples for such a code review guidelines, which covers the above points is the comprehensive document created by Google Developers, “How to do a code review”.\n","id":32,"tags":"best-practices documentation code-review software-engineering","title":"Code review guidelines light the way","url":"/posts/code-review-guidelines-light-the-way-1e4/"},{"content":"You can achieve almost anything by teamwork. Listening is a vital characteristic of a leader. Effectively communicating your thoughts is essential, as well. How you interact can positively and negatively affect the relationships you have in your work (and personal life too).\nEffective communication is defined by various articles (#1, #2, #3, and more), and I challenge myself not to repeat them. I would like to give a different perspective on the matter. Since some of the articles focus on how to communicate better, ignoring the fact that people need effective communication for a critical purpose — improving their relationships and interactions with other people.\nUltimately you need to figure out what works best for you. These are just things that I have found helpful.\nPositive attitude Link to heading Usually, when you interact with people, it somewhat related to your needs. Try to focus on communicating them positively, avoid other person’s flaws and mistakes as much as possible. Otherwise, they’ll feel attacked and criticized, thus naturally leading them to be defensive and even shutdown.\nIf you choose the other way around, it will be hard to have a collaboration. Any feedback won’t be acceptable, and information from their side won’t be shared.\nPrefer the usage of “I” and focus on your specific demand positively (For example: “I need your help with a code review”). Avoid using blaming language, including using “you” and generalizations (such as always and never_)_.\nBe mentally present Link to heading Listen, the other person has something to say. Make your attention on him to understand what he’s saying. Be patient, don’t judge or be defensive — even if you don’t agree with him.\nUnderstanding is not always enough; you should be there emotionally too. Try to see the situation from the speaker’s eyes and grasp his emotions about the subject.\nBesides, be authentic, meaning you shouldn’t pretend something that you are not — that simple.\nEventually, when people feel heard, deeper connections can develop.\nAlways check the temper Link to heading Before you speak, try to gauge in which emotional state your listeners are. Have tact; it will help you deliver your message effectively. Otherwise, you’ll be that irritating person who no one wants to talk with.\nNote that some people are gifted with high emotional intelligence; others have to work on themselves to achieve it.\nno tact\nNO, is the answer Link to heading Identify when you don’t want to do something and reply with a justified “no”, say “yes” only when you mean it. Don’t do it if you look to avoid upsetting the other person since you’ll end up upsetting yourself.\nEvery “no” can be justified politely — people respect and trust others who stand up for themselves.\nReject victim mentality Link to heading Acting in a victim role is about denying any responsibility for your actions. You choose not to do something about your situation deliberately. And people know to recognize it.\nBy doing so, you’ll miss opportunities that could help you become better as people will refuse to collaborate with you.\nAs humans, when things get complicated, we naturally raise our walls and go into a pessimistic mental state — leading us to start complaining about something, anything. Try to resist the urge. Nevertheless, if you find it challenging — choose people you trust, and even then, don’t exaggerate.\nBe wise, not right! Link to heading Pick your battles carefully. Don’t try to win arguments, ignore things.\nTo become a better person, save your energy for what matters to maximize your well-being.\nDon’t assume anything; be slow to judge. It is impossible to read people’s minds and understand what they ponder about. Try not to overthink about assumptions; usually, they come from your insecurities and toxic beliefs, by that you’ll free your mind (and weaken them for next time).\nTreat others with respect Link to heading Maintain proper eye contact when talking to each other. Keep in mind that eyes can show emotions without saying a word, so reflect a positive attitude.\nFurthermore, if you tend to be sarcastic, duly note that it delivers contempt, resentment, and passive-aggressive. It is an “acquired taste” of humor, hence choose your audience carefully and use it wisely. That being said, as a role of thumb, your best option is not using it.\nBesides, I’ll state the obvious, don’t insult people — they are more sensitive than they appear to be.\nLastly, for both cases, don’t accept this kind of behavior from anyone.\nBe articulate Link to heading One of the optimal ways for improving your ability to express yourself is through writing (and a lot). While thinking about what you are going to write, you usually brainstorm, organize your thoughts into subjects, extracting the essence from them. And finally, picking the proper wording (as the saying goes — “The only kind of writing is rewriting” ).\nKeep in mind, practice makes it better — so, write as much as you can. It will take time and eventually be fruitful.\nApologize with actions Link to heading Dealing with people’s feeling can sometimes ‘hurt’ them, you’ll find yourself in the position you regret your actions, and when you do, apologize.\nsorry\nSaying ‘sorry’ isn’t enough, be specific. Make sure you won’t repeat the same mistake. Share your progress, it will help the other side understand your steps.\nFinal words Link to heading Pay attention to how people respond to you; those who react positively are the ones to collaborate more with. For others, you should adjust your behaviors for reaching out. Either way, creating trust through communication.\n","id":33,"tags":"tips softskills leadership developers","title":"Building trust through effective communication","url":"/posts/building-trust-through-effective-communication-208c/"},{"content":" My humble opinion on who should be included in your code review Link to heading An educated guess that from time to time, you’ve encountered the question of who should be involved in code reviews. Well, my colleagues and I found ourselves dealing with it, and the arguments about what’s the proper way, go in various directions; Hence I’ve decided to get to the bottom of this critical subject and write my views.\nOne clarification before you’ll continue reading, I assumed that the readers agree with code reviews necessity as part of software development, while writing the following lines (examples supporting this fact — #1, #2 and #3).\nCan you please review my code?\nNow that’s being said. I’ll try to illustrate my experience and beliefs about being a code reviewer.\nTitle or Seniority? It depends Link to heading I want to talk about the elephant in the room or, in other words — the fundamental concern when choosing who should perform a code review. Whether she should have a specific title (tech lead, architect, etc.) or seniority (which sometimes points on the title too).\nIn my perspective, one of the primary objectives of code reviews is knowledge sharing (others are better communication, find potential issues, improvements, and more). It implies that for choosing a suitable person, one should be capable of sharing insights about it. Hence, the audience should be tuned (one or more participants, depending on the scope).\nAn example is when a less experienced engineer (as defined by his employer) with broad knowledge on a specific development language, reviewing a more experienced engineer (titled as Senior). Only for a reason the code being developed is written in that particular language.\nBeyond the tech-stack experience, the domain has to be considered too. Take, for instance, a developer with 15 years of experience but with 1 or 2 years in the industry’s domain, can find herself receiving feedback on her code by a less experienced engineer with only five years, all in the same industry. Just for the fact he has vital domain knowledge.\nSo less experienced out? Link to heading No!\nI believe that everyone in the team should be involved on both sides of code reviews. I can’t tell you how many times I’ve had to explain a piece of code to someone and suddenly come up with a much better way of doing it by the end of the explanation.\nIf a “Junior” programmer cannot understand a senior’s code, then that in itself is a good measure of the code. In that case, maybe pair programming should be suggested in the future (and better testing 🤔), to bridge the gap. Anyhow, yes, there are times which only a few understand the code, but hopefully, those are exceptions. Imagine what happens when an issue is being raised on that specific piece of code, and the people who understand it are not available.\nProbably confusing\nTo overcome this concern, making sure less experienced team members are participating in code reviews as much as possible. It is crucial for their career development and for the whole team’s success. In such a way, they’ll be able to learn the code review process, the codebase and even an opportunity to ask questions and understand what is expected from them in not only code reviews, but in the code that they’ll produce. A fact which turns any code review an excellent learning opportunity.\nA word of caution, though; the audience should be limited to allow proper reviews. Also, keep in your mind that there’s a risk with reviews being bogged down with non-issues, based on the developer’s learning curve — so patience should be embraced and open-mindedness for this approach.\nOverall Link to heading A code review side effect is twofold; it helps everyone understand the code base, thus shares the knowledge and forming collective ownership. It creates the opportunity for less experienced developers to learn new and/or better techniques from more experienced developers.\nCode review an essential step\nFurthermore, a byproduct of this procedure is that the seniors refine their understanding, which ensures everyone can follow the code and having more eyes that can catch mistakes. Oh, and eventually, the team grows into a more experienced one.\n","id":34,"tags":"software-development code-review personal-development software-engineering","title":"Every code has its audience","url":"/posts/every-code-has-its-audience-55e1/"},{"content":" Investigating .NET assembly loading (binding) issues Link to heading Once in a while, you encounter that peculiar problem when you run your application and receive an exception saying TypeLoadException or FileNotFoundException even though the DLLs that your application relies on, are right there!\nThe first suspect that may jump to your head is an assembly binding issue since it happens at the moment you run your application. It might be a mix of old DLLs with new ones, mismatch in version numbers or cultures, missing assemblies at the application’s folder, or even a probing failure, either of each — fusion log viewer can assist in identifying the case.\nfuslogvw\nThis lifesaving tool is installed as part of Visual Studio installation on your development system and has to run with administrator privileges.\nAccording to MSDN, this viewer:\nThe Assembly Binding Log Viewer displays details for assembly binds. This information helps you diagnose why the .NET Framework cannot locate an assembly at run time. These failures are usually the result of an assembly deployed to the wrong location, a native image that is no longer valid, or a mismatch in version numbers or cultures.\nThe basics Link to heading I highly recommend to change the default log location (at Internet Explorer cache) into a custom clean folder; this can be done on the ‘Log Settings’ dialog. Thus you bypass issues with the default location that causing the log to stop showing new entries because IE cache can get corrupted and prevent read and write operations by the .NET binding infrastructure.\nPersonally, I prefer to log only binding failures. In such a way, I’m able to see only the required information for understanding my problem, prevent disk flooding, and causing each .NET application slowdown (since logs are being gathered). Once turned on, you can immediately identify your failure. Just double click on the selected entry and the following information will be displayed:\nThe specific reason the bind failed, such as “file not found” or “version mismatch”. Information about the application that initiated the bind, including its name, the application’s root directory (AppBase), and a description of the private search path, if there is one. The identity of the assembly the tool is looking for. A description of any Application, Publisher, or Administrator version policies that have been applied. Whether the assembly was found in the global assembly cache. A list of all probing URLs. Below a synthetic example I created:\n\\*\\*\\* Assembly Binder Log Entry (2020–01–26 @ 16:28:09) \\*\\*\\* The operation failed. Bind result: hr = 0x80070002. The system cannot find the file specified. Assembly manager loaded from: C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\clr.dll Running under executable C:\\Example.exe — — A detailed error log follows. === Pre-bind state information === LOG: DisplayName = Foo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null (Fully-specified) LOG: Appbase = file:///C:/ LOG: Initial PrivatePath = NULL LOG: Dynamic Base = NULL LOG: Cache Base = NULL LOG: AppName = Example.exe Calling assembly : Example, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null. === LOG: This bind starts in default load context. LOG: No application configuration file found. LOG: Using host configuration file: LOG: Using machine configuration file from C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\config\\machine.config. LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind). LOG: Attempting download of new URL file:///C:/Foo.DLL. LOG: Attempting download of new URL file:///C:/Foo/Foo.DLL. LOG: Attempting download of new URL file:///C:/Foo.EXE. LOG: Attempting download of new URL file:///C:/Foo/Foo.EXE. LOG: All probing URLs attempted and failed. \\*\\*\\* Assembly Binder Log Entry (2020–01–26 @ 16:28:09) \\*\\*\\* The operation failed. Bind result: hr = 0x80070002. The system cannot find the file specified. Assembly manager loaded from: C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\clr.dll Running under executable C:\\Example.exe — — A detailed error log follows. === Pre-bind state information === LOG: DisplayName = Foo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null (Fully-specified) LOG: Appbase = file:///C:/ LOG: Initial PrivatePath = NULL LOG: Dynamic Base = NULL LOG: Cache Base = NULL LOG: AppName = Example.exe Calling assembly : Example, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null. === LOG: This bind starts in default load context. LOG: No application configuration file found. LOG: Using host configuration file: LOG: Using machine configuration file from C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\config\\machine.config. LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind). LOG: Attempting download of new URL file:///C:/Foo.DLL. LOG: Attempting download of new URL file:///C:/Foo/Foo.DLL. LOG: Attempting download of new URL file:///C:/Foo.EXE. LOG: Attempting download of new URL file:///C:/Foo/Foo.EXE. LOG: All probing URLs attempted and failed. According to the log, the assembly binder searches for Foo, whether it is a DLL or an executable. First, it looks for an application configuration file to understand where to load its dependencies (probing), when it can’t find it, the default host configuration is loaded and then looks for Foo locally. When not found, an exception is being thrown.\nYou can do additional basic operations such as delete one entry or all of them and refresh the interface to get new entries.\nFurthermore, you can bind for native images created by Ngen (Native Image Generator), under the ‘Log Categories’ group. If you desire to get details of apps running in the Windows app container, then enable the immersive logging option.\nFusion++ Link to heading Thanks to Andreas Wäscher, we don’t have to deal with all of these settings. He developed, in his own words, a modern alternative for fusion log viewer, named Fusion++ that can be downloaded from here:\nhttps://github.com/awaescher/Fusion\nAfter running it, just hit the ‘Record’ button to capture assembly logs, and when done, click on ‘Stop.’ His app parses all the log files, highlights the parsed warning and failure to quickly identify issues, as seen below in the same tailored failure example:\nHighlighted error in Fusion++\nLook how easy to find what went wrong. An error line is marked in red, and when you double click on it, you can see the loading failure.\nFurthermore, logs are being saved into the Windows Temp folder to easily clean them using ’Cleanup Windows Tools,’ besides it allows seeing previously recorded sessions. More advanced features are the grid annotations that indicate events over the app scrollbar and the parser range selector.\nParser range selector\nTo conclude, Assembly load failures and binding redirects can make any .NET developer frustrated, thus this open-source desktop app touches a soft spot and acts as a real game-changer. It allows you to spend your time wisely, instead of diagnosing binding errors. So, go ahead and use it.\n","id":35,"tags":"software-development debugging dotnet csharp","title":"Fusion Log Viewer: The binocular to assembly binding","url":"/posts/fusion-log-viewer-the-binocular-to-assembly-binding-4fe0/"},{"content":"As time goes by, I’ve started to find myself overwhelmed with things I would like to achieve. I looked for a solution to track my progress and goals. I tried various tools and found that writing each item and organize them in lists works for me. I felt immediate relief and “in-control” of my things. Curios of the reason why — it has drawn me to read about it and realizing that when writing things down, it frees your mind, clear space for more important topics. I encountered David Allen’s book, Getting Things Done, where he calls this process “Core Mind Dump”.\nFurthermore, it acts as a stress relief, which helps creative thoughts and ideas to flourish (since your mind is free), or in Allen’s words (in his book Ready For Anything):\n“When mental space has too many distractions and unmanaged agreements and loops, flow is limited. Clear the pipes and you attract and foster new, productive thinking that almost happens by itself.”\nThe list book cover\nAnother inspirational person is Yuval Abramovitz, who wrote the interesting book, “The List”. I recommend seeing his TED talk, which encourages you to write everything down in a list and by that fulfilling your dreams.\nIn the next paragraphs, I’ll illustrate my daily routines, and hopefully, others might find it useful. My favorite platform is Google Keep. Still, any other of the vast range of To-do applications may do the work too (a glimpse into the plethora).\nOne list\nOne list rule them all Link to heading One of the frequent mistakes that people who do keep tasks-lists do is managing them in various tools. Usually done for separating between work and personal goals. One of the best tips I’ve received is holding all of them in one place for better prioritizing your daily routine.\nToo many lists in different tools, inflict users’ confusion due to the context-switch between the various platforms.\nSo, if you need to track the context of your tasks, tag them. In Google Keep, you can tag each note, and in the future, it allows you to filter based on the tag to focus on the relevant information. Besides, I add color too, so when looking on the whole notes dashboard — I can get the sense of how many notes from each category exist.\nSimple note\nThe routine Link to heading Routine\nWhen a new chore or arrangement jumps into your timeline, immediately capture it. You can add an image, voice record, or share it with your collaborators. Just make sure to write the relevant context-wise information to complete it. For example, in case you would like to call customer service, add the phone number into the note’s details. In such a way, you’ll be able to complete the task quickly without the need to search for additional data.\nEvery morning starts with going over my lists, so ensure you block the time in your calendar. This routine helps me to plan my day and track my progress. I add reminders to things I would like to finish today, tomorrow, or in the longer run — based on their importance. I rearrange yesterday’s open tasks and ask myself what can be postponed — all against the priority I set (which is flexible too).\nEventually, I just set the date and time against my calendar availability. Upon saving the reminder, the note’s schedule is integrated into my google calendar (recall, one tool for better prioritization).\nSo, how to manage the long run tasks? I use the Eisenhower Matrix method; these goals are usually the “important and not urgent” ones. As part of my routine, every two weeks, I look at them and decide if it’s time to handle — whether I should delegate, eliminate, or do it. If “Do” has been chosen, I’ll break it down into smaller tasks and back into my daily routine. In any of the selected paths, headspace and the sense of achievement are gained.\nEisenhower Matrix\nOne last note, I make sure to not invest too much time in doing my daily routine (up to 10 minutes); otherwise, it might become a burden.\nTo conclude Link to heading Besides helping you think big (aim high), process your thoughts, and be more committed to your goals. Writing To-Do lists gives you a record of the past, which provides a valuable insight into your thinking process. Moreover, you gain a sense of achievement and satisfaction when a task is marked as done. While crossing things off your list, you’ll feel productive and, in turn, enhance your productivity, creating a virtuous cycle.\n","id":36,"tags":"notes-to-self lists productivity time-management-tips","title":"Digital Notes are your life dashboard","url":"/posts/digital-notes-are-your-life-dashboard-2ep9/"},{"content":"Back in 2016, I saw a demo at a conference about a new visual studio extension that presumes to change the way an engineer debugs, they called it, magic debugging. Little that I know, it turned my debugging way of thinking upside down, indeed a magical approach.\nBefore I’ll continue, I owe a disclaimer for the readers. A previous colleague of mine is one of OzCode’s co-founders (Omer Raviv). Although it might harm the credibility of this blog-post, I’ll take the risk; for the reason that these lines were written by a happy user 🤓. My goal is to share with you my perspective on some of OzCode’s helpful features and why you should try it out too.\nWhat can OzCode do? Link to heading The primary purpose of this visual studio extension is to help you debug code and find the root cause of problems, a sort of online ReSharper. In the next paragraphs, I write about my favorite features, yet OzCode has more to offer.\nDataTip Link to heading One of the valuable features is the DataTip; it replaces the dole visual studio tool-tip with much information, and it helped me in various defect debugging situations.\nIt contains a swift search functionally. It will go through any object’s fields and values and into several levels in the object’s hierarchy. Note that you can define as many levels as you want.\nEach item is presented by the ToString() implementation of the class (seen as OzCodeDemo.Customer in the gif below_)_, but here comes OzCode to the rescue with the neat feature — reveal. By staring properties, you’ll be able to the ones that interest you the most.\nAnother useful option is the Export feature. You can extract each object internal into JSON/XML/C#, a helpful capability for creating mocked objects during unit testing, which saved me time. Also, the basic VS functionality is not neglect, you can instantly copy value or add a quick watch.\nLINQ Debugging Link to heading LINQ is one of the used features in C#, while one of his pitfalls is when debugging it. Developers have tried to overcome this by evaluating part of the query using Visual Studio’s QuickWatch window, placing (conditional) breakpoints in the lambda expressions for assessing each element individually, or by logging your progress. As you can see, it’s pretty cumbersome to debug it, so OzCode solves that exact need.\nWhen hovering over LINQ expressions, you’ll see bubbles containing numbers. You can click on each bubble to analyze the evaluated LINQ expressions, each term in his stage. Combine it with the Reveal feature, and you are a rockstar.\nLINQ expression debugging\nTime Travel Link to heading Time travel — jump into specific iteration\nOzCode simulates the results of future code execution without actually running it. In such a way, you’ll be able to detect bugs by jumping into specific loop iteration to the exact moment of failure without the need to step over your code in real-time. Using the heads up display feature that highlights the evaluated value of your code, a powerful feature by itself (extremely UX-oriented), you can investigate what happened. It saves you time for re-running a defect’s scenario multiple times while hunting for root-cause.\nNote that time travel doesn’t work when accessing external resources such as a database or native code since it can’t be simulated without affecting the application’s state.\nTracepoints Link to heading Another useful feature is Tracepoints, which allows logging your debugging scenario into the editor’s viewer. Thus, quickly analyze any issue, even a multi-threaded one, as can be seen in the image below where different messages arrive from various processes and threads’ Ids.\nTracepoint viewer — demonstrate multithreaded info\nCompare Link to heading You can even compare objects and collections in memory. One excellent option is to take a snapshot and compare the same object across different points in time.\nCompare in action\nException trail and prediction Link to heading This feature has proved himself as valuable (for me) over and over again. It allows you to view all relevant exception information. Furthermore, inner-exception can navigate easily along the StackTrace, all in an interactive and clean UI.\nException trail\nUsing the heads-up display, you get an alert that an exception is going to happen. When encountered, you can quickly skip and ignore it for smooth debugging or decide to handle it.\nAn exception is about to happen\nShow all instances Link to heading Search for any object in memory. That simple.\nIt might be used to understand if an object is still alive and why.\nThere are more features in OzCode, which I’ve not described, such as — quick attach to process, custom expressions, quicker breakpoints, and more. That being said, one can leverage his debugging skills and bring more value efficiently while using it, making OzCode a must-have tool in any C# developer’s toolbox.\nNote that, a free trial can be downloaded from here\nFurthermore, OzCode team made sure to create a digital walk-through of all their features (which I’ve used as part of writing this blog-post), accessible here: https://github.com/oz-code/OzCodeDemo\n","id":37,"tags":"software-development csharp visual-studio debugging","title":"OzCode: A New Way to Debug Your Code","url":"/posts/ozcode-a-new-way-to-debug-your-code-l6n/"},{"content":" Being productive by taking control of your time Link to heading A gym workout, a reminder to walk the dog, meeting with your colleagues on that project presentation, a dentist appointment — are all on the same page. You can’t separate artificially between your work and personal calendars. Why? Because that’s how your life works. The goal is to see what your actual day looks like, to blend between work and personal life for finding the right balance that fits you. Or as Jeff Bezos answered to Thrive Global on steps he takes to improve his productivity and performance:\n“I think work-life harmony is a good framework, I prefer the word ‘harmony’ to the word ‘balance’ because balance tends to imply a strict tradeoff.”\nFor that purpose, most of us use a digital calendar. But whether you get the most out of your day is the real question here. In the following lines, I’ll try to share some of my calendar’s preferences to plan the ideal week.\nRemind your future self Link to heading Current calendar applications have many features, among them are notifications and reminders. I advise to use them wisely, most people set a new event and let the app choose the default notification behavior, and when pushed, they ignore it. Well, doing so, is missing the whole point of the notification — to remind you of the needed information on the relevant context, at the best time you need it.\nFor example, in case of setting a morning event, to call customer service for technical support. A productive way is adding the customer service’s number and a short sentence in the description to remind you what is the goal of the meeting. In such way, you’ll save time, call immediately (from the push notification) and align your mind on the purpose of the call without having to pull it off from your memory.\nBe in control of your time Link to heading Control your time\nDefine your working days and hours. Regularly check if your calendar’s setting fit your daily routine, if any change happened — be flexible and update your timeline. On each morning, I advise you to go over your daily agenda and see if any meeting should be moved or canceled. Make sure to reply to each session with your response (and its motivation).\nFurthermore, schedule recurrent meetings for daily tasks such as commute time to work and back to home or lunchtime. Set it as out of the office or busy time. In such a way, others won’t schedule a meeting at that time.\nThe spouse calendar Link to heading I don’t recall who recommend it to me, but this useful tip changed my life, for real. So, thank you, anonymous helper🙏. It’s straightforward to set up, all commonly used calendars that support sharing your schedule with others. In return, you’ll get more control in less fuss.\nThus, each party is up to date with the other party’s schedule. Bring into your attention, that both sides should be proactive and update their schedule — otherwise it will miss the whole point.\nSchedule the time you need Link to heading Block time-slots needed for you to invest in your personal growth. Use them to learn new material by reading, testing new technologies, or whatever you find enriching.\nJedi who fights the darkness of human irrationality\nDan Ariely once said:\n“It turns out that most people are productive in the first two hours of the morning. Not immediately after waking, but if you get up at 7, you’ll be most productive from around from 8–10:30.”\nSo make sure to schedule these blocks when you’re most productive.\nAlso, use them to plan a regular basis time-out, it’s healthy and makes you perform better. It may be fitness activity, a coffee with a colleague, “just” doing nothing or meditation — whatever assists you in clearing your mind.\nCategorize event Link to heading Organize each event into a category. Such as Family, Work, Personal health, etc. Assign a color for each group. When needed, it will allow you to filter events of a specific type. Also, it may help you to understand from what your week is formed by looking on dominant colors.\nAnother helpful tip I found along the way is, enriching recurrent events with emojis. For example, “meatless Monday 🌿”, “Going to the gym 🏋️” or “Commute time 🚌”. Cause everything’s better with emojis 🤓.\nTo wrap-up Link to heading These small changes in your daily routine will push forward and boost your productivity; any calendar application out there can be good enough. Invest the effort now and get more time to have free time.\n","id":38,"tags":"leadership time-management software-engineering productivity","title":"Arrange your time and your mind will follow","url":"/posts/arrange-your-time-and-your-mind-will-follow-4ljh/"},{"content":"As individual contributors, occasionally we encounter various situations where we need to lead without formal authority (sometimes we’ve been asked to). Formal training on leading others without the power to do so is rare. The fact, finding the right candidates for this critical task is challenging for any management, doesn’t assist much in the circumstances. The root cause relies on the required skill set for being one since a potential candidate doesn’t follow typical hiring procedures and job description.\nAs once said by Donald McGannon: Leadership quote\nHence, I’ll try to frame five practical ways of recognizing leadership without being a manager:\nPositive attitude influence Link to heading Colleagues that genuinely help their teammates beyond their role, treat others with respect, and strive for open and honest discussions are potential leaders. Furthermore, they usually create pleasant atmosphere across the team by humor, sharing success stories, and echoing their coworkers’ triumphs.\nThrive to continuous self-development Link to heading Individuals who keep track with recent industry changes and drive themselves for continuous development. Maintaining side projects, contribute to open-source, reading job-related material from multiple sources, all are some examples of thinking out of the box for self-improvement. Creating a routine of improving your “stack” not only boosts your career but also plays as a role model for the team.\nBeing an authority Link to heading It’s all about knowledge sharing — that simple. Individuals that speak at conferences or write a professional publication, whether it’s internal or external to their workplace are the ones who demonstrate authority in their domain. Nowadays, social media has the potential to inspire others by blog-writing, online presenting, or even maintaining a social media profile where you can echo your thoughts. In any way they choose, it motivates team members to learn and contribute.\nSee the big picture Link to heading If you care — your clients and stakeholders will notice it. Acting with integrity and communicating based on mutual trust are the foundation stones of leadership. Those to follow, have a “can do” attitude supporting the company’s values and reputation. They are visionaries of actions that have to be done first, such as volunteering for complicated activities or being involved in decision making. Which will lead them to see the big picture, results in sharpening their leadership skills.\nSee the big picture\nMentoring others Link to heading Being a mentor is an opportunity to grow for both parties (as I previously blogged about). The experienced teammate shares his knowledge with the less practiced one. It’s a chance to improve your presentation, writing, and training skills. If done wisely, the mentor receives recognition for his contribution by the mentee, and eventually identified as a leader in the specific domain.\nFinal words Link to heading Being a leader shouldn’t be limited to upper management and those who hold a people manager role. Individual contributor leaders should be formally recognized and empowered. Organizations have to provide sufficient training which focuses on leading people without being in a management function. Cherish any employer doing that.\nAs I see it, investing in this type of skill set will yield a stronger collaboration within the teams, a higher satisfaction level, and longer retention of the overall organization.\n","id":39,"tags":"teamwork team individual-contribut software-team","title":"Leading with no authority","url":"/posts/leading-with-no-authority-khl/"},{"content":" The differences between being a tech lead and a senior engineer Link to heading At the time, being an entry-level SW engineer, my colleagues and I were curious about the individual contributor career path. There are many questions to be answered, but some repeated frequently. Among them were — What is the meaning of being a tech lead? How’s it different from being an experienced team member who is familiar with all the bits and bytes of the language, framework, and domain that he uses daily?\nI’ve heard various answers to these questions, such as — A senior is a job role while a tech lead is a team role. Or that a senior is an engineer who has enough expertise to lead in technical tasks as design, providing effort estimation, performing code reviews, mentor others, and more. On the other hand, tech lead is a person on the team, which in charge of the technical decisions and approaches, a sort of software architect. Besides, he does management tasks, i.e., motivation, career guidance, coordination, and planning. Aha, and that you can be both at the same time.\nWell, it is quite challenging to draw the line between the two positions. Both share the same qualities, with one significant different — seniors are suggested to demonstrate those skills, whilst a tech lead is expected to master them.\nIn the paragraphs below, I’ll try to focus on several key attributes that, in my opinion, emphasize the differences between each role.\nExpertise Link to heading What do you know, and how well do you know it. For example, take a programming language. A senior would say: “I know language x, I’ve worked with it for some years, so I’m experienced with it”, but for a tech lead the expectations are bit varied:\nOne that can quickly identify the optimal way of solving a problem. Whether it will be a defect fixing or during a code review, a tech lead would instantly say, “you should try Y”. He bases his opinion on his vast domain experience, project timeline, and the teammate’s proficiency (taking into consideration her growth-path). Knowing isn’t enough. How you gain knowledge is more important. After careful consideration, one should make sure to attend the right tech conferences, read insightful books, develop some side projects, participate in meetups, and find mentors that fit him. Thus, enhancing his ability to understand any concept, platform, or whatever it may be to make his work better. Be up to date with any emerged software engineering trends (frameworks, platforms, concepts, languages, etc…). Either by reading diverse sources, listening to podcasts, or any different suitable approach for you. Furthermore, maintaining a profile at one of the SW engineering blogs, where you answer questions about those trends, not only for helping others but for expanding your understanding. You become an expert that teaches others, and it is known as the best way to learn. Creating an online opensource repository. Basically, for learning language X, developing a sample project, even a simple hello-world, just for the sake of getting your hands dirty, would teach you a lot. In the future, others might comment on, share, or contribute. Pushing yourself forward. You know what you don’t know, and every passing day you think about how to bridge that gap and understand more about it. Lastly, It isn’t about being a world-renown expert, saying that you appreciate who are the leading personas in your field and follow their steps for trying to become one. In my experience, a tech lead would have at least three expertise that fall into the above checklist.\nInfluence Link to heading As a senior, your influence is, in no doubt, essential. You affect your team members through various technical discussions and by collaborating with other teams too. Whereas, a tech lead is expected to have both and to influence customers, adjacent groups, and the organization’s leaders. He should know when to share information, as well as when to lend an ear. His everyday work is to help others improve their skills set by guidance and mainly listening (a vital skill of being a leader).\nMagic\nImpact Link to heading The value you deliver. For example, You’ve found a problem and can think of a solution for solving it. You may have solved it by yourself, but what would be more fundamental, is leading into acceptable completion. Also, the impact might be a new initiative no one has thought of or even a significant refactoring of existing code that improves the product’s quality. Those actions (and more) are translated into a high quantity of business value.\nYou could find technical expertise as your primary focus, you can be the leading software engineer in your domain, being known for your knowledge, but you aren’t a tech lead. A careful balance is a key between the presented three areas and it’s on the individual contributor to make sure he grows in each one of them.\n","id":40,"tags":"career-ladder leadership senior-engineer tech-lead","title":"On the differences between being a tech lead and a senior engineer","url":"/posts/on-the-differences-between-being-a-tech-lead-and-a-senior-engineer-1j3f/"},{"content":" Collect the small wins along the way\nBoost motivation, productivity, and creativity by celebrating daily progress Link to heading Teams must celebrate the small wins. It’s easy to forget there were probably more than a few minor achievements along the way that led to larger ones. We all have been there, caught up in what wasn’t achieved, or focusing on the big “accomplished” picture, eventually forgetting the path to getting there. The satisfaction of incremental progress is perceived as a success; thus, it makes any team motivated for the next goal.\nThe Power of Small Wins Link to heading Teresa Amabile quote\nCelebrating every little step success was termed “Progress Principle” by Teresa Amabile and Steven J. Kramer from Harvard Business School in their study — “The Power of Small Wins.” Its results have revealed how much reaching small wins on a regular basis is crucial for people who work on complex problems. These small achievements encourage a productive work environment in the long run.\nWays to Celebrate the everyday Link to heading Celebration\nThe leaders of each team should monitor the projects’ progress and know when to stop for celebrating a finished objective, no matter how small it may be. This practice goal is twofold — progress is being tracked, and positive feedback is given.\nIt’s upon the leaders to make time at group meetings for team members to share their progress, and for the leaders to acknowledge employees’ success. Recognizing a job well done keeps the team encouraged, and in particular, address individuals that find a good word meaningful (over a reward).\nVisualizing progress is essential too; it may be a project management application or using a whiteboard at the office, whatever fits the daily usage. Demonstrating what was done up to this moment reflects what was achieved successfully.\nFurthermore, leaders should find the right cadence for making a small gesture, whether that be ordering pizzas to the office or gather the team for a drink.\nPure happiness\nIn the appropriate time frame, it will achieve high motivation and create anticipation for the next time.\nThe takeaway Link to heading Any progress, even the minor one, is what makes a great day at work. By taking steps to recognize these small wins, teams can benefit from the power of real motivation, which sparks innovative ideas and significant breakthroughs.\nPS: A simple habit for getting you started is the “two- minutes rule,” as mentioned in David Allen’s bestselling book, Getting Things Done. If it takes less than two minutes, do it right away and then cross it off your list. No matter how minor it is — you’ll surely feel great (and relieved) immediately.\n","id":41,"tags":"productivity personal-development habit-building leadership","title":"Small Wins Matter","url":"/posts/small-wins-matter-1b9o/"},{"content":"Everybody has to eat, right? Families like to eat together, and friends frequently meet for dinner, and colleague regularly socialize over lunch.\nRecent research by Cornell University found that employees who ate meals together had significantly better team performance at work than those who didn’t.\n“During the study, we noticed that not sharing mealtimes was a signal that something deeper was wrong with the way the group worked , something that was then reflected in the team’s performance.” — according to Kevin Kniffin, Professor of Economics at Charles H. Dyson Cornell University, who published the research.\nEat alone\nIt means that eating alone makes you less efficient. Furthermore, I deduce that the importance of a team’s lunch ritual is comparable to eating with your family. It should be ingrained into the team’s culture to take the time to sit down and have meals together.\nAs a result, organizations that invest in cafeterias improve employee’s performance and collaboration. The right infrastructure provides a conversation starter in a space where colleagues can share their lunch and communicate better.\nBy now, I’m pretty sure you’ve already noticed that most of your awaken time is shared with this group of people. Practically, you see them more than your family which, and I guess, will be more fun if you know them better.\nHence, socializing with colleagues doesn’t end with a team’s lunch. From time to time, meeting outside of work in a bar, restaurant, or whatever fits the team’s unique DNA will lead to a stronger bond between team members.\nSculpt Team DNA\nIMHO, every manager seeks for the secret of cultivating teams, that elusive chemistry which makes high achieving teams. A few years ago, a study named “The New Science of Building Great Teams” looked at 21 organizations and 2500 employees over seven years, concluded that the following make a great team:\nRegularly face-to-face communication. Psychological safety environment, where everyone can talk and listen equally. I mean everybody, not just the leaders do the talking. Social time is critical; it accounts for more than 50% of positive changes in communication patterns — a game-changer between high-performing and low-performing teams. Teams who tend to share knowledge between team-members perform better. All of the above is facilitated simply by just eating together. A big surprise? I guess no; since it creates a fertile ground for them to flourish.\nA significant hurdle to cross is deciding where to eat since each one has his own taste and food preferences. A suggested approach is using one of the collaborative tools which allow creating a Form (kind of survey) or a repetitive message where everyone shares what’s on their mind. The chosen option will be the one that the majority voted.\nLunch\nFor example, a connection between the Microsoft Teams and Micorosft Flow services can be the solution. Flow generates a scheduled message into a specific Team’s channel where all team members are enlisted and can vote on their preferred choice. As can be seen below:\nFlow recipe\nNaturally, on regular ( up to two-pizza size 🍕) team, it’s easier to schedule a shared lunch. In the case of a larger group, such cadence can be hard to achieve without a proper framework in place. Where only some days are defined as whole-team lunch, otherwise it will rarely happen due to the tendency to split into smaller groups with shared preferences.\nEventually, eating together creates an open dialogue that generates an informal talk and sparks innovative ideas. The firmer the bond between fellow workers, the more prolific the team gets.\n","id":42,"tags":"team-building software-team food coworking","title":"The Social Glue of the Team’s Lunch","url":"/posts/the-social-glue-of-the-team-s-lunch-32ed/"},{"content":"Writing about your code is redundant; the code is all you need. I can invest my time on unit tests or develop other features, and other excuses of why writing code comments is a waste of time. It’s a common belief among developers.\nWell, you’ve invested all your efforts in cultivating the design of your code, why should you comment it, right? As a result, code documentation is either absent or useless.\nWhile in some cases, it is true that writing code comments can be counterproductive. Yet, we are the only ones who can benefit the most out of it if being done right.\nCode comments as a contract Link to heading A self-documented code doesn’t exist. You can write meaningful variables names, methods, classes, etc. but as good as it gets, it doesn’t make your code automatically describe the meaning of it.\nYes, sure during the implementation while sharpening it to perfection, you are in the context of it, but what would happen in a month from now? How much will you remember? Can you trust your future self to be in the same mindset when approaching it?\nRealizing what you thought when you wrote this piece of code would assist you in the time ahead. Proper code documentation is making a contract with the maintainer to be, which is probably you.\nCode comments are an inherent part of clean code Link to heading In some cases, code comments can point on code smells. If you find yourself writing that the method does this “and” that while writing your method’s code documentation. You probably should refactor the method, since it has to do one thing and one thing only. Therefore, break the code into two methods and immediately mend the code comments to fit the change. In such way, you adhere to a clear code concept.\nFurthermore, digging into the code to better understand the context of the method is an unnecessary waste of time, while you could easily read the method header and quickly recall the what (obvious) and why parts of the method and in particular focus on the how it does what it was written for.\nTake for the example the comment in the below gist, it just states the obvious and tells what it does — basically, it repeats the property’s name, which makes it redundant. While removing it will have the same effect as not writing it in the first place:\nA better comment will have more details which state what the code can’t tell us. Well, you can say — why should I write it? The property’s name and logic are straightforward; it just returns weight. But hey, nothing is ever simple in software. A useful comment can save us the time and cognitive efforts of digging deeper into the code for the method’s context, as can be seen below:\nThis approach has a different mindset that you should adopt. Each method has something to tell, at least one new detail that the code doesn’t state, whether it’s a side effect, restriction, or any other abnormality. Writing about these detail will lead the developer to confront with the hidden details of its implementation and in times refactor the “code smell” parts. Thus, not only it helps the future readers of the code but also assists the writer to gain a better understanding of its implementation and improve it.\n“Code never lies, comments sometimes do.” — Ron Jeffries Link to heading Have you ever heard that sentence? Indeed, comments get outdated when the code changes. The fact they do is because they are not considered as part of the code itself while they should. The code comments are coupled to it. It is in the developer’s responsibility to update it too. A fact should be checked during a code review.\nSelf-documenting code\nOne last thing, the scope of the code is not relevant whether you should or shouldn’t put a comment on it. By that I mean, private access modified code should be documented too. Otherwise, we neglect the actual users of it, ourselves.\nWithout a doubt, for some developers, it will take time, practice, and getting used to this new way of thinking. But, in the long run, you’ll reap the rewards — in terms of code quality and a better understanding of your code circumstances, and eventually, your code will tell his story, its autobiography.\n","id":43,"tags":"softwaredevelopment softwareengineering cleancode refactoring","title":"Code comments are your code autobiography","url":"/posts/code-comments-are-your-code-autobiography-3c7n/"},{"content":"Mentoring means cultivating and inspiring others, usually less experienced in the specific field of expertise. IMHO, an experienced engineer must hold the mentoring skill, as it’s critical to the careers of new SW employees and the success of the entire team. This skill is earned by hard work (that made you experienced), and it helps you to develop your career.\nThe trust between the mentor and mentee is that hidden ingredient in the recipe of building great teams, and in my perspective, being one is a privilege.\nOn Mentorship Link to heading Mentoring includes both new team-members and existing ones, who have advanced in their career into different roles. Once you’re no longer the new guy doesn’t mean that you shouldn’t be the mentee anymore 😉.\nThe new guy\nMentoring comes in a variety of shapes, whether through pair programming, code reviews, or 1:1 meeting. It’s not a must, but try to establish all kind of learning streams — you’ll benefit from it.\nOn these meetings, the experienced engineer can leverage her knowledge, presentation skills, and writing ability. Furthermore, make sure you deliver the right message; Don’t miss this growth opportunity for you and your mentee.\nFor me, mentoring is putting others before yourself. It is about caring for each other and having fun from the learning process. What I’m about to say sounds a bit of a cliché, but being a better person by reaching out is more important than being better on your career. People notice your behavior and cherish your help and that’s what makes you better at what you do.\nAs the blog-post continues, I try to illustrate my mentorship’s experience in both parties. Enlisted below several characteristics and behaviors that I’ve noticed at my mentors and mentees, in which I advise to follow for the success of the process.\nBeing A Mentor Link to heading To be a good mentor has several “variables” that fit together.\nFirst of all, listen to your mentee’s thoughts.\nBe Patient, sometimes it can take time to open up and ask questions. Treat people who know less than you with respect.\nMake yourself available, be sure it is clear that he can contact you about any subject, whether it is job-related personal concerns or professional matters.\nYou’ll find the time and let him know the preferred schedule slots. Be there on time and fully present. Otherwise, it will miss the whole point and may lead to distrust.\nIt is recommended to define an urgency ladder for clear expectations, my preferred approach: email \u003c chat \u003c mobile text \u003c phone call \u003c f2f.\nThat said, it’s not enough to be available. Respond to any attempt of reaching out. Ask broader questions that will make your mentee think about the full picture, context, and consequences.\nTry not to be judgmental; be open about failure. Failure is a growth opportunity, help him learn from it. Bring some examples from your failures’ experiences and how you grew up from them. Solidarity and sympathy help to break the ice…\nBreak the ice\nBeing A Mentee Link to heading On the other side, being a good mentee requires you to reach out, push yourself forward to get knowledge. Be curious, ask questions.\nBe flexible, adjust your time to your mentor schedule; Inquire for the preferred meeting frequency and time slots. Don’t take it personally that often your mentor is busy. Be respectful of her time.\nOn meeting, arrive on schedule and be fully involved. Come with concrete points to discuss and get to them as quickly as you can.\nTake notes, learn from the answers. Having said that, take anything with a grain of salt, put in question the given answers. Don’t blame if the advice or answer wasn’t accurate, remember that you are responsible for your actions.\nThink outside the box; look for ways where you can also be helpful. Follow up, let your mentor know that you have taken her advice; mainly if it was necessary.\nOn mentoring\nTo sum up Link to heading A mentor acts as a role model. You are not born this way, you have to learn to be one. For some, it will be more comfortable, and for others, it may take more time. So yes, you’ll have setbacks that will push you further to learn better practices.\nMentoring each person is different, and you’ll have to find your way to reach them. This fact is what makes it both exciting and challenging. Overall, being a mentor makes you better at your work and in times, advance your career.\n","id":44,"tags":"programming management mentorship software-engineering","title":"The Privilege of Mentoring","url":"/posts/the-privilege-of-mentoring-1gfd/"},{"content":" Binding issues? Struggle with that hard to solve UI bug? Trying to understand how to fit the entire string into TextBox’s dimensions? These situations and many others are common for us, .NET and WPF developers.\nMost of the times, issues, as mentioned above, are solved by using a debugger.\nImagine it; you want to change the size of a specific graphic element. Well, you open the relevant project (using Everything tool 😉) in your favorite IDE, make some changes, compile, deploy, and rerun the application. Then you attach a debugger. Investigate and rerun the whole process again until you solve the issue.\nWell, It takes time. A LOT of it.\nSnoop was developed by Pete Blois to ease the pain of debugging your WPF application. This open source WPF spying utility, now maintained by Cory Plotts, allows on the fly visual tree changes, troubleshooting binding failures, and more…\nxkcd: Compiling\nSpying on your app Link to heading Download and install Snoop from its Github repository:\nsnoopwpf/snoopwpf\nLaunch Snoop and drag the snooping cross-hair to your WPF application.\nSnoop window, the snooping cross-hair is marked with a red rectangle\nSnoop window, the snooping cross-hair is marked with a red rectangle\nA new window is opened. On the left, the application’s visual tree is displayed while on the right, the property editor is visible for each element in the list. Below a GIF that demonstrates the primary usage of Snoop. It can be seen that one of TextBlock’s Text property content is being edited on the fly.\nSnooping example\nFeatures Link to heading Ctrl+Shift keyboard buttons and hovering over the desired element is a productivity boost. It causes Snoop to jump immediately to the hovered element’s properties, which saves you the effort of going down the visual tree to find the desired control, as seen below:\nCtrl+Shift trick\nAnother trick is to search the property you would like to change in the filter box. Furthermore, a useful feature is the “Show only visuals with binding errors” option found in search-bar drop-down located above the visual tree view.\nShow only visuals with binding errors\nIt shows components with binding issues. In such way, it saves time to identify any binding failure using your IDE.\nMoar Features\nThere are more features in Snoop which are less used (IMHO). For example, the power-shell which is a console where you can write methods and interact with the UI through commands. Events tab that lists all the fired events per your limited choice and triggers tab for debugging any changes happened for control or style through a trigger, whether it is a property trigger, DataTrigger or EventTrigger.\nSummary Link to heading Although its UI is not much user-friendly, I’ve found it to be handy for finding missing bindings and tweaking layout parameters. As well, overcoming the effort of debugging an unfamiliar complex user interface since Snoop projects the visual tree and allows to navigate in it quickly.\nFurthermore, Similar WPF spying utilities exist (such as Mole and WPF inspector), but Snoop has an active open source development, and it saves you the headache of using your IDE for debugging your application. I cannot imagine developing WPF interfaces without it.\nBTW, HawkEye (Maintained by Olivier Dalet) is another opensource tool with similar capabilities that allows snooping your WinForms application.\n","id":45,"tags":"debugging wpf open-source software-developing","title":"Snoop Around Your Visual Tree","url":"/posts/snoop-around-your-visual-tree-c6c/"},{"content":"A lot has been said on OpenPose. This real-time multi-person groundbreaking keypoints detection method has many features, along with:\n2D real-time multi-person keypoint detection 3D real-time single-person keypoint detection Calibration toolbox Single-person tracking Supporting Python API, Unity Plugin, Cuda, OpenCL, and CPU only Moreover, more features are in the works by the team (Gines Hidalgo, Zhe Cao, Tomas Simon, Shih-En Wei, Hanbyul Joo, Yaser Sheikh, and Yaadhav Raaj) at Carnegie Mellon University. The below link is being updated occasionally for new frameworks’ changes. Besides, it contains an installation guide, troubleshooting, and a quick start section. So, go ahead, have a look, and play with it.\n[CMU-Perceptual-Computing-Lab/openpose](https://github.com/CMU-Perceptual-Computing-Lab/openpose “https://github.com/CMU-Perceptual-Computing-Lab/openpose)\nWhat 🙋? Link to heading One of the caveats of OpenPose framework is to identify a partial human image as determined by my Master’s supervisor, Professor Hagit Hel-Or. The system’s model was trained on human figures taken from several datasets (COCO and MPII), while the images contain different people on various backgrounds, most of them don’t include only “part” of a person image (for example, only shoulders).\nIt means the algorithm fails to identify the connected graph of all identified body parts. While a body part is an element of the human body (like hand, neck, hip) and a pair is two connected parts.\nThe image below, taken from the excellent Medium blog-posts series by Ale Solano displays the skeletons as represented by the COCO dataset (pairs and parts): Parts and Pairs indexes for COCO dataset\nI recommend reading Ale Solano’s series for more details on OpenPose pipeline which I don’t plan to drill down into as part of this blog-post.\nMy goal in this opensource project is to allow using the vast capabilities of OpenPose system on images containing only partial body parts. The following GIF emphasizes the framework’s limitation:\nOpenPose Limitation\nWhy 🤷? Link to heading I intended to learn various concepts to enrich my technical stack, like using machine learning, get a better understanding of computer vision concepts, and using OpenPose. I did all the above while having fun and eventually contributing to the opensource community.\nAs a side effect, by sorting out OpenPose limitation, it may help other researchers who hesitate using it.\nSay, for example, you would like to identify a person’s key points, or as said in the computer vision jargon, skeleton. However, the image appears cut or intentionally contains only part of the human body. One application may be for physical therapy to identify treatment improvements. More usages exist depending on the user’s purpose.\nHow 🤓? Link to heading The proposed method (credit to my Master’s supervisor) is to add the missing body part into the image wisely. Afterward, run the OpenPose framework on the reconstructed image. The result is then manipulated to show the skeleton on the original body image.\nThe following images show the algorithm flow on an original image of human legs:\nA partial (legs) image is given An upper (dummy) image is matched to the original body part, and a merged image is created An OpenPose skeleton is generated for the combined image The skeleton result is reduced to the original image only As can be seen below:\nAlgorithm flow from left to right\nThe reconstructed image is created by first identifying the object in the original image, using a tensorflow trained model (DetecorAPI with faster_rcnn) based on COCO dataset. The model returns a bounding box of the detected object. Then by using the box’s dimensions, the dummy image is being manipulated to the original image characteristics by an affine transformation.\nEventually, the two images are being stitched together, and OpenPose is being triggered on the new image.\nThe below video demonstrate the result of a walking person video:\nOriginal Video\nSkeletonized Video\nTo sum up, OpenPose has great potential for endless applications, enabling motion detection without dedicated hardware like Kinect, a 2D camera is enough. Overcoming on one of the framework limitations can step us forward for that goal, and this is the real power of the opensource community.\nI hope you’ll find it interesting (👏).\nThe project’s code can be found here:\nDeJaVoo/partial-openpose\n","id":46,"tags":"machine-learning openpose tensorflow deep-learning","title":"Estimating partial human poses","url":"/posts/estimating-partial-human-poses-178n/"},{"content":"Copy-pasting is one of those things that you do every day while working on a computer. By doing so, each time you invest a small portion of your daily routine.\nSay you want to share a photo\\text\\whatever with a friend from a website, you copy it, either by right-clicking on it and copying it to the clipboard or using Ctrl+C and then paste it to your favorite sharing application and after doing so, you’ve realized you want to share it again with another person. Unfortunately, the data is no longer at your clipboard, and now you have to annoyingly crawl your way back to the webpage again to do the whole thing all over again. I’m sure you familiar with that situation.\nCopy and paste again\nHere comes Ditto to the rescue. An open sourced super tool, hosted at SourceForge that saved me A LOT of time by collecting my clipboard history. It enhances the Windows clipboard copy-pasting experience with various capabilities, and if you make sure to incorporate them into your daily routine, you can boost your productivity.\nAlternatively, as mentioned on Ditto’s home page:\nDitto is an extension to the standard windows clipboard. It saves each item placed on the clipboard allowing you access to any of those items at a later time. Ditto allows you to save any type of information that can be put on the clipboard, text, images, HTML, custom formats…\nGetting started Link to heading Just download and install Ditto. The tool runs in the background, and while copy things to the clipboard using Windows copy capabilities, Ditto gathers all copied data into its log.\nThen, open Ditto by clicking its icon in the system tray or by pressing the predefined hotkey (by default it is configured to Crtl + `).\nWhen opened double click or press Enter on the selected item from the list you would like to paste into the proper scope of your work, as can be seen in the below GIF:\nDitto in action\nDaily usage and features Link to heading The list of features as noted by sabrogden, Ditto’s developer:\nSearch and paste previous copy entries Keep multiple computer’s clipboards in sync Data is encrypted when sent over the network Accessed from tray icon or global hotkey Select entry by double click, enter key or drag drop Paste into any window that excepts standard copy/paste entries Display thumbnail of copied images in the list Full Unicode support (foreign display characters) UTF-8 support for language files (create language files in any language) Uses SQLite database (www.sqlite.org) My favorite feature is using the search option; you can look for text contained in each record or use a wildcard and even using a regular expression (for the braves among us) is supported; I use it daily.\nRegex magician\nFurthermore, I reconfigured the default hotkey into (Win key +`), which I’ve found more comfortable and proper use of the Win key.\nKeyboard shortcuts\nDitto allows configuring the max number of saved copies, the expiration time for copied entries and basically, you can tweak its behavior for your needs. I love the dark theme and the option to choose any font (I use the hack font) for the displayed text.\nFurthermore, an advanced user can configure sharing his clipboard items between computers on the same network using IP or Computer names. Another useful feature is the option to mark a record as a sticky clip, in such way you’ll keep the most important ones at the top\\bottom; defining a hotkey for that purpose is helpful. Group copy is supported too; you can group several clips and add a predefined shortcut to copy them at once.\nOne of the tool caveats is when using a password manager, even a one that makes sure to delete clipboard right after copy-pasting a password. It means any copied passwords are being kept in Ditto’s log until explicitly deleting them, either by manually removing them or by reaching the number of saved copies. Mitigation for that risk is to prevent Ditto from accessing the network by blocking its traffic via the Windows’s firewall configuration.\nOverall, If you’re looking to boost your typing productivity then install Ditto, you won’t regret it.\n","id":47,"tags":"productivity software-development clipboard windows","title":"Ditto, the clipboard manager that saved me","url":"/posts/ditto-the-clipboard-manager-that-saved-me-1j8h/"},{"content":"Occasionally you’ll get into a situation where a problem happened in your application, and you don’t have access to your source code and\\or symbols.\nAt that moment, one of your better options is to decompile your code and debug it. IMHO, one of the best free tools out there is dnSpy, developed by 0xd4d (respect).\nAccording to him, dnSpy is an improved ILSpy decompiler that enhanced by Roslyn (C# / Visual Basic) compiler and many other open source libraries. This tool supports editing and debugging assemblies (any .dll or .exe file) even if you don’t have any source code available, isn’t that amazing?\nQuick setup Link to heading Head to https://github.com/0xd4d/dnSpy/releases and download one of the latest releases depending on your needs, whether it’s .NET Core, .NET framework or Unity debugging.\nMake sure Microsoft Visual C++ Redistributables are installed, if not you can find at https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads.\nOther than that, each of the releases relies on a different framework, so make sure to install them too.\nNote that, the developer mentioned that Windows 7: Must have KB2999226 and KB2533623 installed.\nKeep it simple, stupid Link to heading Using dnSpy is quite easy. Same experience as using Visual Studio. It sure feels that the developer put effort into making it that way.\nYou can start debugging your assembly by pointing to the assembly path, insert a breakpoint where you want, and that’s it.\nAnother option is to attach to a running process, similar to Visual Studio experience. Just launch dnSpy in X86 or x64 architecture, depending on the assembly.\nIn the video below, you can see that Visual Studio experience I’ve previously mentioned. I wrote a simple application that adds a number and a new line to a StringBuilder. dnSpy allows me to step into assemblies (which decrypt themselves at runtime) and debug line by line. Locals, watch, autos windows are supported too.\nMore features are supported such as the ability to edit an assembly in such way you’ll be able to edit the current assembly’s metadata, methods and, classes.\nEdit current method\nYou are even able to add new methods, classes or members (in C# or Visual Basic).\nGimme more… Link to heading The assembly editor supports changes for low-level IL method body and metadata tables using a hex editor. You can go back and forth between decompiled code and IL, all you have to do is a click on an address in the decompiled code, and you are at the IL method body or the opposite way by pressing F12 in an IL body to go back into the decompiled code.\nAlso, dnSpy can search for methods, assemblies, and strings as done in Visual Studio. Find all class and method usage, callers, and more.\nBasic IntelliSense implementation is supported, and even the C# Interactive window is available too.\nFor more information and advanced topics, go to the Wiki page, where 0xd4d describes how to add extensions, building dnSpy by yourself and, debug Unity games.\ndnSpy got the looks; you can choose between blue, light and dark themes (and a dark high contrast theme). The tool is translated into ten different languages, which is quite impressive for an open source; it sure demonstrates the strength of the community. As well, if you’d like to contribute and translate dnSpy to your native language, a dedicate crowdin project is active at https://crowdin.com/project/dnspy.\nYou Got It Dude Meme\nTo wrap it up, although there are other excellent alternatives (such as dotPeek, JustDecompile), dnSpy is an open-sourced handy tool that has straightforward user experience for anyone familiar with one of the leading IDEs. As far as I see it, dnSpy is a must for any SW engineer’s toolbox.\n","id":48,"tags":"software-engineering disassembly csharp dotnet","title":"When in Doubt, Reverse Engineer It","url":"/posts/when-in-doubt-reverse-engineer-it-1jdk/"},{"content":"Microsoft announced ML.NET last May, and as an advocate user of the .NET framework with experience in Machine Learning, I knew that I’d have to give it a try knowingly that Python various frameworks (such as scikit-learn) rule this domain.\nML.NET is a free, cross-platform, open source machine learning framework explicitly made for .NET developers. The preview release includes learners to handle binary classification, multi-class classification, and regression tasks. Additional ML tasks like a recommendation system, clustering, anomaly detection, ranking models, and deep learning architectures have been added.\nIn this blog-post, my purpose is to play along with ML.NET capabilities and eventually demonstrating its ease of use. My goal is to predict a heart disease for a given patient based on an opensource dataset.\nGetting started Link to heading Assuming Visual Studio 2017 is installed on your system, open a new console application (.NET core) project:\nAfterward, go to the ‘Tools’ menu and choose ‘Manage NuGet Packages for Solution…’:\nThere, browse for ‘Microsoft.ML’ and choose the latest stable version (at the time of writing these lines, the stable version is 0.11.0) to install it for the current solution. As a side note, if you prefer using the package manager console, just run the following command:\nInstall-Package Microsoft.ML -Version 0.11.0\nNow that all prerequisites are in place, we can start doing some machine learning magic.\nThe Heart Disease Dataset Link to heading For the binary classification task, I used the Heart Disease UCI dataset from Kaggle datasets; It contains 14 columns and 303 records.\nScreenshot from Kaggle\nHeart Disease UCI\nI’ve manually split the CSV file into two files, smaller one for the test data and a larger one for the training data. Below, the test data CSV as an example.\n#####Test Data CSV\nML.NET provides mapping attributes to model the dataset structure. It means each header is mapped to a LoadColumn attribute as follows:\nTraining the model Link to heading Training a model based on a given dataset requires to define a context as an entry point or as defined by ML.NET API:\nThe MLContext is a starting point for all ML.NET operations. It is instantiated by the user, provides mechanisms for logging and entry points for training, prediction, model operations, etc.\nAfterward, the training and test datasets are loaded using the context, based on the mapped structure.\nTransform the data and add a learning algorithm for this task numeric values are assigned to text because only numbers can be processed during model training. In this case, the problem I try to predict is a type of Binary Classification (two classes, has and hasn’t diseased). The selected model is based on Decision Trees because they can be easily interpreted (by humans) as rules, have excellent performance and don’t require any assumptions on the data.\nEventually, the model is trained by using the fit method:\nWe’ve trained our model with a few steps, as simple as that.\nBTW, the framework provides capabilities for saving your model. According to the tutorial it is recommended to save it as a ZIP file.\nTesting Link to heading Given the trained model, prediction can be made. For that purpose, a sample class containing a list of patients is given as input to the model for prediction.\nThe result prediction structure shall be defined too, as follows:\nIn the below gist, I load the model from disk, create a prediction engine based on the resulting structure (defined above) and using the engine I predict the probability for heart disease on the list of patients.\nWhich returns the following (Prediction Output):\nIn terms of the result accuracy, the code hits 78.95% accuracy, below are more evaluation parameters generated by the model’s Evaluate method:\nOverall, ML.NET has it all, flexible, robust and supported by a big company that provides the engineering vision behind it. I recommend you to try it too, and for sure I’ll use it again soon.\nThis blog-post was written based on the Heart disease Classification coding sample with some modification; more ML.NET Samples can be found at:\nMachine Learning Samples Samples for ML.NET, an open source and cross-platform machine learning framework\n","id":49,"tags":"machinelearning softwaredevelopment softwareengineering","title":"ML.NET: Heart disease prediction","url":"/posts/ml-net-heart-disease-prediction-11n8/"},{"content":"Few years ago a teammate changed my perspective of my daily computer’s usage experience. Until that moment, I used to go and explore folder and files using Windows Explorer as Microsoft intended, but something was wrong with it, too many clicks and the start menu search need some improvements. Overall, it felt so different than my common internet browsing experience, where you open your favorite search engine and start typing whatever you’re looking for. Then the eureka moment came, he introduced me to Everything.\nOne small tool, a giant step for productivity Link to heading This small nifty tool focuses on performance. It has a small installation file, clean and straightforward user interface. It relies on quick indexing which allows fast results with minimal database footprint and real-time updates of the file system.\nThe usage is simple, you type in a search box which files and folders you’re looking for, and the results are shown thanks to the index file instantly. According to voidtools, Everything only indexes file and folders’ names, which takes a few seconds to build its database. For example, a fresh install of Windows 10 (about 120,000 files) takes about 1 second to index. 1,000,000 files takes about 1 minute. That’s fast.\nThe footprint is tiny, a fresh install of Windows 10 uses about 14 MB of ram and less than 9 MB of disk space. While 1,000,000 files uses about 75 MB of ram and 45 MB of disk space. It means software performance was in the mind of voidtools’s developers and looks like a real effort was made to address it.\nPlain simple usage Link to heading Everything is opened by double-clicking the tray icon, a desktop shortcut or my personal favorite, a Hotkey. I defined Ctrl+Alt+F for instant searching.\nUnder ‘Indexes’ settings in the options menu, I recommend defining which folder to index from whatever location you’ll choose (it can be a network folder too) and which NTFS (C:\\, D:\\ ,etc.) drives to include.\nIndexes: Folders and NTFS drives\nEverything contains basic and advanced features. You can use wildcards.\nFor example, searching t*b results in all files and folders starting with t and ending with b.\nBoolean operators are supported too.\nAND is the default Boolean operator. To search either of two search terms simply add a | between the terms. IMHO, the excluding operator ( ! ) is the most useful one.\nWith this basic functionalities, you can filter specific file types by writing the file extension (for example *.mp3), search only files under a specific folder (for example \\temp) and much more…\n“Everything” is a filename search engine for Windows.\nAdvanced search Link to heading You can search for files’ content (which is not indexed and therefore slower). An example is when you’d like to find emails, modified this week, containing the text “banana”:\n*.eml dm:this week content:banana\nID3 tags and FLAC tags search are an option:\nyear:2002..2005\ngenre:electronic\nregex:album:^[a-n]\nwildcards:title:red*\ntrack:\u003e10\nyear:\u003e=2000\nFurthermore, you can use regex to override search syntax. Regex must be enabled from the Search menu:\nRegex operators\nVoidtools kindly added A LOT of examples which can be used to learn additional search behaviors.\nAs a final note one small tip, Everything.ini stores all the settings for Everything, so I recommend to back it up in your favorite cloud storage and upon a new computer installation just point to the .ini local copy.\nEverything is a freeware and can be downloaded from the link below.\nEverything\n","id":50,"tags":"productivity software-development productivity-hacks personal-development","title":"It’s all about Everything","url":"/posts/it-s-all-about-everything-1lf5/"}]