I spent the last month reading "Clean Code" so I could finally understand why the dev community is constantly arguing about it. Alongside it, I finished "Are Your Lights On?" (Gause & Weinberg). Reading them together felt like learning how to build a house while simultaneously understanding why people keep building them in the wrong place. The experience? Very eye-opening, but frustrating. The "elephant in the room": Clean Code is an enterprise Java book from the early 2000s. As a JavaScript dev, wading through Java examples felt like reading a foreign language. But once I looked past the boilerplate, the over-arching wisdom beat the noise. I did get some of it in the end, but Java is vastly different from JavaScript in its usage and purpose. The core practices I took away (from "Clean Code"): 1) DX is a choice: Clean code isn’t a burden; it’s a gift to your future self. It’s the difference between a 5-minute sloppy fix to "get a working solution" and a 5-hour nightmare trying to debug it later. It just takes a little patience and care in the moment. 2) The Boy Scout Rule: Leave the campsite cleaner than you found it. You don't have to rewrite the world; just improve the line you’re currently touching. 3) Concurrency is the FINAL BOSS of programming: It offers incredible power, but it goes south fast, and it's pitfalls are hard to reproduce or debug. I’ve learned to respect the "how" as much as the "what." Efficient problem solving (from "Are Your Lights On?"): 1) Solving the wrong problem is the ultimate waste: You can write perfect code, but if it doesn't solve the core issue, it's useless. I cannot beat this dead horse enough. 2) The "communication" fix: We often spend hours trying to "hack" a system from the outside when the solution is just a conversation away with the original creator. 3) The "easy path" trap: Sometimes the most "senior" thing you can do is push back on a high-paying solution that doesn't actually help the user. The general verdict from me: If you’re a JS dev, don’t let the Java scare you off. Extract the core principles discussed (naming things, small functions, single responsibility) and leave the boilerplate behind. Java has changed a lot since the book came out anyway. Next up for me: The Pragmatic Programmer. What book changed your developer experience for the better? #SoftwareEngineering #CleanCode #JavaScript #ComputerScience #CareerJourney #GoldsmithsUoL
Clean Code and Are Your Lights On? Book Review
More Relevant Posts
-
I used to write code that worked. But nobody — including me — could understand it 3 months later. Then I adopted these clean code habits. And everything changed. Here are 7 habits that made me a genuinely better Java Full Stack Developer 👇 1. Name things like you're writing a story Bad: int d = 7; Good: int deliveryDaysLimit = 7; Your variable names should explain WHY they exist — not just what they hold. If you need a comment to explain a variable, the name is wrong. 2. One method. One job. No exceptions. If your method name has the word "and" in it — split it. processOrderAndSendEmail() ❌ processOrder() + sendOrderConfirmationEmail() ✅ The Single Responsibility Principle isn't just for classes. It's for every line of code you write. 3. Stop writing comments that explain WHAT — write comments that explain WHY Bad: // Loop through users for (User u : users) { ... } Good: // Skip inactive users to avoid sending promotional emails to churned accounts for (User u : users) { ... } The code already shows WHAT. Only you know WHY. 4. Keep methods short — the 20-line rule If your method is longer than 20 lines, it's doing too much. Break it down. Extract logic. Give each piece a meaningful name. Small methods are easier to test, easier to read, and easier to debug at 2 AM. Trust me on that last one. 5. Don't return null — ever Null is the source of more bugs than almost anything else in Java. Return Optional. Return an empty list. Return a default object. But never silently return null and let the caller figure it out. Future-you will be grateful. 6. Write the test first — even when you're in a hurry I know. Deadlines are real. But skipping tests to "save time" is borrowing time from your future self at a very high interest rate. Even one unit test per method forces you to think about edge cases before they bite you in production. 7. Refactor ruthlessly — leave code cleaner than you found it The Boy Scout Rule: Always leave the codebase a little better than you found it. You don't need a dedicated refactor sprint. Just fix one bad variable name, extract one messy method, or remove one dead comment every time you touch a file. Small improvements compound into a codebase you're proud of. Clean code isn't about being perfect. It's about being kind — to your teammates, to your future self, and to whoever inherits your code at midnight when something breaks. Which of these habits do you already follow? And which one do you struggle with the most? Drop it in the comments 👇 #Java #CleanCode #SoftwareEngineering #FullStackDeveloper #SpringBoot #CodingTips #BestPractices
To view or add a comment, sign in
-
🚦🧊 JAVA IMMUTABILITY: THE WORDS MOST DEVS MIX UP: Unmodifiable, Immutable, Shallowly/ Deeply immutable, final 🔸 TL;DR In Java, unmodifiable does not mean immutable. And final does not mean the object can’t change either. If you confuse terms like mutable, unmodifiable view, immutable, shallowly immutable, and deeply immutable, you can easily design APIs that look safe but still leak state and bugs. 👉 I put together a carousel cheat sheet to make this crystal clear. Swipe through it. 🔸 TAKEAWAYS ▪️ Mutable = state can change after creation ▪️ Unmodifiable = this reference blocks mutation, but backing data may still change ▪️ Immutable = state cannot change after construction ▪️ Shallowly immutable = outer object is fixed, inner objects may still mutate ▪️ Deeply immutable = the full reachable state is frozen ▪️ Collections.unmodifiableList(...) is not the same as List.copyOf(...) ▪️ final freezes the reference, not the object ▪️ Records are concise, but they are not automatically deeply immutable 🔸 WHY IT MATTERS A lot of Java codebases say “immutable” when they really mean “harder to mutate accidentally.” That shortcut creates confusion in code reviews, APIs, concurrency discussions, and interviews. Precise vocabulary = better design. And better design = fewer side effects, safer models, cleaner code. ☕ 🔸 SWIPE THE CAROUSEL I turned the whole taxonomy into a simple PPT carousel with: ▪️ one term per slide ▪️ code snippets ▪️ short explanations ▪️ the distinctions that actually matter in real projects 👉 Swipe the carousel and tell me: Which term do you think developers misuse the most: unmodifiable or immutable? #Java #JavaProgramming #SoftwareEngineering #CleanCode #BackendDevelopment #Programming #Developers #Architecture #CodeQuality #JavaDeveloper #TechEducation #CodingTips
To view or add a comment, sign in
-
𝗧𝗵𝗲 𝗕𝗮𝘀𝗶𝗰𝘀 𝗼𝗳 𝗝𝗩𝗠 𝗮𝗻𝗱 𝗩𝟴 You want to know how Java and JavaScript work. Let's break it down. Programming languages are classified into two main types: statically typed and dynamically typed. - Statically typed languages check types before execution. - Dynamically typed languages determine types at runtime. There are also two main execution models: compiled and interpreted languages. - Compiled languages translate code into machine code before execution. - Interpreted languages execute code directly. But here's the thing: most languages use a hybrid approach. They combine compilation and interpretation to achieve better performance. This is where Just-In-Time (JIT) compilation comes in. It analyzes the code, identifies hot paths, and compiles them to machine code for better performance. The Java Virtual Machine (JVM) and V8 engine are two examples of this hybrid approach. - The JVM is a virtual machine that runs Java bytecode. - The V8 engine is a JavaScript engine that executes ECMAScript and WebAssembly specifications. So, what's the difference between JVM and V8? - The JVM is an abstract machine that runs bytecode, while V8 is a real implementation of the ECMAScript and WebAssembly specs. - The JVM has a public spec for its bytecode, while V8 does not. In the end, understanding how Java and JavaScript work can help you appreciate the complexity of programming languages. You can learn more about the JVM and V8 engine through the following resources: Source: https://lnkd.in/gi8Pne8w Optional learning community: https://lnkd.in/gmwngSRR
To view or add a comment, sign in
-
I spent the last month doing something I had been postponing for a long time — 𝐬𝐡𝐢𝐟𝐭𝐢𝐧𝐠 𝐟𝐫𝐨𝐦 𝐌𝐄𝐑𝐍 𝐬𝐭𝐚𝐜𝐤 𝐝𝐞𝐯𝐞𝐥𝐨𝐩𝐦𝐞𝐧𝐭 𝐢𝐧𝐭𝐨 𝐉𝐚𝐯𝐚 𝐛𝐚𝐜𝐤𝐞𝐧𝐝. Coming from a JavaScript ecosystem (and earlier C++), I underestimated how different the mental model would be. In MERN, things move fast. You write code, spin up APIs, and you're good to go. Java, on the other hand, forces structure, discipline, and a deeper understanding of what's happening under the hood. 𝐓𝐡𝐞 𝐛𝐢𝐠𝐠𝐞𝐬𝐭 𝐜𝐡𝐚𝐥𝐥𝐞𝐧𝐠𝐞 𝐟𝐨𝐫 𝐦𝐞? 𝑨𝒏𝒏𝒐𝒕𝒂𝒕𝒊𝒐𝒏𝒔. Not just learning them — actually understanding what they do behind the scenes. At first, it felt like “magic”: @𝘈𝘶𝘵𝘰𝘸𝘪𝘳𝘦𝘥, @𝘙𝘦𝘴𝘵𝘊𝘰𝘯𝘵𝘳𝘰𝘭𝘭𝘦𝘳, @𝘚𝘦𝘳𝘷𝘪𝘤𝘦 — things just worked, but I had no clarity why. And that’s dangerous if you're trying to build real backend systems. Once I started digging into how annotations drive dependency injection, configuration, and the entire Spring ecosystem, things finally started to click. 𝐑𝐞𝐚𝐥𝐢𝐭𝐲 𝐂𝐡𝐞𝐜𝐤: 𝘐𝘴 𝘴𝘩𝘪𝘧𝘵𝘪𝘯𝘨 𝘧𝘳𝘰𝘮 𝘔𝘌𝘙𝘕 𝘵𝘰 𝘑𝘢𝘷𝘢 𝘵𝘰𝘶𝘨𝘩? Yes — but not for the reasons most people think. It’s not about syntax. It’s about mindset. • In MERN, you’re used to flexibility. In Java, structure is enforced. • In Node.js, you control flow explicitly. In Spring, a lot is handled for you — if you don’t understand it, you’ll feel lost. • Debugging is different. You’re not just fixing code — you’re understanding frameworks. • Boilerplate vs abstraction trade-off hits hard initially. Most people quit not because it’s “too hard”, but because they stay at the surface level and never break through that confusion phase. 𝐅𝐨𝐫 𝐚𝐧𝐲𝐨𝐧𝐞 𝐭𝐡𝐢𝐧𝐤𝐢𝐧𝐠 𝐨𝐟 𝐬𝐰𝐢𝐭𝐜𝐡𝐢𝐧𝐠: Don’t overthink it — but don’t expect it to be easy either. What actually works: - Don’t just “use” Spring — understand what it’s doing - Spend time on core Java, not just frameworks - Accept slower progress in the beginning 𝐒𝐢𝐦𝐩𝐥𝐞 𝐫𝐨𝐚𝐝𝐦𝐚𝐩 (𝐛𝐞𝐠𝐢𝐧𝐧𝐞𝐫 → 𝐚𝐝𝐯𝐚𝐧𝐜𝐞𝐝): • Core Java (OOP, collections, exception handling, streams) • JVM basics (how Java actually runs — this matters more than you think) • Spring Boot fundamentals (REST APIs, project structure) • Dependency Injection & Annotations (this is the turning point) • Database integration (JPA/Hibernate) • Build real projects (not tutorials) • Basics of system design + scalable backend concepts I’m not “done” — but I’ve crossed the hardest part: getting comfortable with being uncomfortable again. Next step: going deeper into Spring, system design, and writing production-level backend code. If you're in that transition phase too, you're not stuck — you're just early in the learning curve. #JavaDevelopment #SpringBoot #BackendDevelopment #SoftwareEngineering #JavaBackend #DeveloperJourney #TechCareer #Upskilling #ContinuousLearning #ProgrammingChallenges
To view or add a comment, sign in
-
Coming from a Java + Spring Boot background, I’ve built and consumed REST APIs for years. Recently, while experimenting with FastAPI, I stumbled upon a subtle but very interesting difference in how request routing works—and it genuinely made me pause and think. Consider this scenario: In FastAPI, if you define routes like: /books/{book_title} /books/harry and you place the dynamic route first, a request to /books/harry will be handled by the dynamic path, not the static one. Why? 👉 FastAPI resolves routes in the order they are defined. The first matching route wins—even if a more specific route exists later. As a Java developer, this felt counter‑intuitive at first. In Spring Boot, the framework does things differently: Routes are not resolved by order Spring calculates path specificity A static route like /books/harry will always win over /books/{bookTitle}, regardless of how methods are ordered So the same API behaves differently across frameworks—not because one is wrong, but because of different design philosophies: FastAPI / Python → explicit, developer‑controlled, minimal magic Spring Boot / Java → convention‑driven, framework‑managed, intelligent dispatching 📌 Key takeaway for me: When working with FastAPI, route ordering matters. Static routes should be defined before dynamic ones to avoid unexpected behavior. This small difference reinforced something important: Understanding the framework internals matters just as much as knowing the language. Learning new stacks like FastAPI as a Java developer has been both refreshing and humbling—and these nuances are what make the journey exciting. Curious to hear from others who’ve switched between ecosystems—what surprised you the most? #Java #SpringBoot #FastAPI #Python #BackendDevelopment #RESTAPI #LearningJourney #SoftwareEngineering
To view or add a comment, sign in
-
There are several things in life that I often ask myself "how in all that is good and satisfying in this world did *this* (insert thing here) ever get off the ground?" I feel this way about old bands on the classic rock station a lot. It's just noise and terrible mixes and coked up lead singers trying to sound like they're terrible on purpose but it's artistic (GnR, ACDC, etc...no one sings like that. it's stupid.) I recently decided to try java by getting on youtube and just following a few tutorials. I come from the world of PHP and Python. Let me tell you what...I understand that java may have been the only choice for a while and that's why it was adopted...but holy crap why is it still here? Like...candles were the only choice for lighting for a while but as soon as light bulbs were a thing, candles went away pretty quickly. The whole tooling pipeline for java is insane. You apparently need to know which SDK is supported by which JDK, and which builder (maven or gradle) supports the SDK and JDK pair. And all of them let you choose an infinite combination of broken settings because the system doesn't tell you what's incompatible until you run it. The default settings chosen by InteliJ don't get installed by default so it's trying to run a software stack that is not only incompatible with your configs but also doesn't exist because even though it's selected by default, did not get installed with the editor. THEN, I get a (seemingly) convenient pop up in the bottom right telling me that "Spring is a suggested plugin, click here to configure". Sure, why not? I'm building a spring project, let me install this auto-detected and suggested plugin. Click the configure link...the only plugin I'm shown is a kubernetes plugin. The recommended plugin from the tool tip is not even in the list of suggested plugins when the tool tips own pop up is opened. Like............I'm just sort of speechless. And this is using start.spring.io to build the packages and bundle everything. I'm not even trying to do some janky off-brand build here. I've been dealing with dependencies and tool set ups for over an hour and I haven't even written a single line of code. Again...while being guided by a tutorial step by step. How has the programming world not revolted against this to a higher degree? I'm happy to receive comments and helpful tips to get me started better...but I'm a 10 year-experienced developer in multiple other tool sets and I have never in my life seen something this insane.
To view or add a comment, sign in
-
I just published my first library. An unofficial Java SDK for the NoviCloud REST API. Built solo. I deliberately picked this API as a test case for working with AI agents - predictable structure, 18 endpoints. A good fit to see what agent-assisted development actually looks like on a real project. No pretty UI, no demo video, no landing page. Just a library you add as a dependency and it works. What's inside: • 18 API endpoints fully covered (products, sales, documents, stock, reports, and more) • 548 tests - unit and WireMock integration, every endpoint tested for success, errors, pagination, and retry • 62 architectural decision records - every design choice documented with rationale • SonarQube A/A/A - zero bugs, zero vulnerabilities, zero code smells • OpenAPI-first code generation with hand-crafted immutable records on top • Retry with exponential backoff and jitter, JPMS modules, AutoCloseable client • Demo app with four run modes and standalone usage examples • AGPL-3.0 on GitHub (dual licensing available on request), available on Maven Central This SDK is also a product of my AI journey. I'm four weeks into AI_devs 4 course, working through Anthropic certifications, and starting 10xDevs in May. Everything I've been learning about agents - I tested here. My first attempt used a different agent setup. Endpoint by endpoint, feature by feature - the way you'd normally build it. It was slow, brittle, and eventually all of it went to the bin. The knowledge about the API stayed, the code didn't. What worked was the opposite: horizontal slices. One concern across all 18 endpoints at once. Retry logic for everything. Then pagination. Then tests. It completely inverts how you think about building software. But there's a ceiling. At some point I said "I don't think prompting alone gets me further." A big part of the work was manual - verifying API behavior against documentation, building test fixtures from real responses, catching edge cases. That work fed back into the SDK just as much as the generated code. I know Java. I reviewed every change and pushed back when the agent cut corners. The 62 ADRs exist because I made those calls. Agents are force multipliers, not replacements. Without experience behind them, you get something that runs but is fragile and ugly under the hood. At some point you have to stop polishing and ship. Whatever slipped through, that's what 1.0.1 is for. If you're a dev - I'd love your feedback. Tear it apart. If you're a recruiter - yes, this is what I build in my spare time. If you're using NoviCloud - check the license (AGPL-3.0), but the code is there. Link to the repo in the first comment. Happy to answer any questions. #opensource #java #ai #aiagents
To view or add a comment, sign in
-
-
𝗞𝗼𝘁𝗹𝗶𝗻 makes functional programming feel natural—and 𝗦𝗔𝗠 is part of that story. If you’re coming from Java, 𝗦𝗔𝗠 (𝗦𝗶𝗻𝗴𝗹𝗲 𝗔𝗯𝘀𝘁𝗿𝗮𝗰𝘁 𝗠𝗲𝘁𝗵𝗼𝗱) interfaces might feel familiar. But in Kotlin, things get even cleaner with lambda expressions and SAM conversions. Dive into the 𝗯𝗹𝗼𝗴 𝗳𝗼𝗿 𝗱𝗲𝘁𝗮𝗶𝗹𝗲𝗱 𝗲𝘅𝗮𝗺𝗽𝗹𝗲𝘀 𝗮𝗻𝗱 𝗰𝗼𝗱𝗲 👇 https://lnkd.in/gbuNP_PM In this blog, I’ve explained: • What a SAM interface means in a Kotlin context • How Kotlin simplifies usage with lambdas • Interoperability with Java functional interfaces • Practical examples you can plug into your code The real win? Less boilerplate, more readable logic. If you're still writing verbose implementations where a lambda would do, you're missing Kotlin’s elegance.
To view or add a comment, sign in
-
Seriously I am considering stop using Lombok in my new java projects. To be honest, It help quite a bit to avoid Boilerplate of code. Por ejemplo @Slf4j, @RequiredArgsConstructor, @Getter, @Setter, @Value, etc. But Lombok comes with trade-offs that compound over time: - Lombok hooks into javac internals. Every major JDK release risks breakage, and the fix cycle can block your upgrade path. - Security and supply chain risk: Every dependency is a potential vulnerability. Lombok runs as an annotation processor inside your compiler and has deep access to your build. Even if Lombok itself is safe today, it’s one more artifact in your supply chain to monitor, and one more entry point if compromised. If you were around for the Log4j CVE during the 2021 holidays, you know how painful an urgent dependency patch can be. The fewer dependencies you carry, the smaller your blast radius when the next CVE drops. - IDE support gaps: Annotation processing surprises new team members. Code navigation, refactoring tools, and static analysis don’t always see Lombok-generated code. - Debugging blind spots: Stack traces reference generated methods you can’t step into or read in source. - Dependency on a single library: Lombok is maintained by a small team. If the project slows down, your codebase depends on it. For more details you have to read this post autored by Loiane G. https://lnkd.in/e54x8G8V
To view or add a comment, sign in
-
Java has been my primary language for years. Statically typed, multithreading built-in, and one killer feature — the Reflection API: the thing that lets you reach into the guts of an object at runtime. It's what powers Spring, Hibernate, Jackson, and countless other tools and libraries we use every day. Dependency injection, JSON mapping, ORM magic — reflection is the engine underneath most of it. Then I tried Flutter. Flutter runs on Dart, and Dart's equivalent — Mirrors — is disabled. What used to be a no-brainer suddenly required planning. Every data class now needs a toJson() and a fromJson() method written by hand — or generated by tools like json_serializable. At first it felt like a step backward. But here's the thing — there's a reason Mirrors was disabled. Reflection is slow. Every app launch, the JVM is doing expensive runtime introspection. If you've ever stared at a large Spring app refusing to wake up in the morning... you know the feeling. ☕ That's exactly why frameworks like Micronaut and Quarkus exist. Instead of digging into the guts of objects at runtime, they generate all that code at compile time. The result? Blazing fast startup with none of the overhead. Flutter's constraint wasn't a limitation — it was a design choice that pointed toward a better pattern. Sometimes the wall you hit is actually there to protect you. This reminds me of Sourat Al-Kahf — the meeting of Prophet Musa (Moses) and Khodr (Al-Khidr). Every time Khodr did something that seemed wrong or harmful, there was a deeper wisdom behind it that Musa couldn't see yet. The constraint that frustrated him was quietly serving a greater purpose. Sometimes in tech — and in life — the limitation that slows you down is the very thing pushing you toward a better way. #Java #Flutter #SoftwareEngineering #BackendDevelopment #Dart #MobileDev
To view or add a comment, sign in
More from this author
Explore related topics
- Building Clean Code Habits for Developers
- Advanced Debugging Techniques for Senior Developers
- Key Skills for Writing Clean Code
- SOLID Principles for Junior Developers
- Improving Code Clarity for Senior Developers
- How to Resolve Code Refactoring Issues
- The Significance of Clean Code
- Principles of Elegant Code for Developers
- How to Write Clean, Error-Free Code
- How to Refactor Code Thoroughly
Explore content categories
- Career
- Productivity
- Finance
- Soft Skills & Emotional Intelligence
- Project Management
- Education
- Technology
- Leadership
- Ecommerce
- User Experience
- Recruitment & HR
- Customer Experience
- Real Estate
- Marketing
- Sales
- Retail & Merchandising
- Science
- Supply Chain Management
- Future Of Work
- Consulting
- Writing
- Economics
- Artificial Intelligence
- Employee Experience
- Workplace Trends
- Fundraising
- Networking
- Corporate Social Responsibility
- Negotiation
- Communication
- Engineering
- Hospitality & Tourism
- Business Strategy
- Change Management
- Organizational Culture
- Design
- Innovation
- Event Planning
- Training & Development