Recent Posts
Archives

Archive for the ‘en-US’ Category

PostHeaderIcon [VivaTech 2019] What’s Your Next Bet

A 22-minute fireside chat at VivaTech 2019, moderated by Harry Stebbings, Founder of Stride VC and The Twenty Minute VC, featured Pär-Jörgen Pärson, General Partner at Northzone, available on YouTube. Connected via LinkedIn and LinkedIn, Harry and Pär-Jörgen discussed VC decision-making. This 1000–1200-word post, for VCs, startup founders, and tech enthusiasts, explores lessons from market cycles and Spotify’s success.

Pär-Jörgen, having weathered the 2001–2003 dot-com crash (95% value loss) and 2008–2009 cleantech wipeout, emphasized resilience. These cycles taught him to prioritize sustainable growth over hype-driven valuations. Europe’s VC ecosystem, now complete with angel-to-growth financing, avoids early exits (e.g., $60 million sales once deemed successes). In 2018, six of eight global IPOs were European, reflecting a maturing market. Pär-Jörgen advises founders to choose investors wisely, ensuring alignment for tough times, as market booms tempt over-valuation risks.

Aligning Interests in VC

Pricing, Pär-Jörgen argued, hinges on aligned interests, often undermined by high valuations with anti-dilution clauses. These misalignments strain founder-VC partnerships during downturns. He recommends founders stress-test investor alignment pre-investment, prioritizing resilience over maximizing valuation. Northzone avoids consensus-driven decisions, relying on individual conviction to back founders like Spotify’s Daniel Ek. This approach, coupled with transparent, meritocratic fund structures, has driven Northzone’s success, including three multi-billion-dollar exits, despite long-term performance uncertainty in VC.

Lessons from Spotify’s Growth

Pär-Jörgen’s early bet on Spotify, led by Daniel Ek, hinged on Daniel’s vision and ability to oscillate between granular details (e.g., instant playback UX) and strategic abstraction. Initially reluctant to lead, Daniel’s paranoia and customer focus—balancing creators, consumers, and labels—built a two-sided marketplace over a decade. Spotify’s near-death moments, resolved in hours, underscore the value of experienced VCs who remain calm. Pär-Jörgen’s latest unannounced investment in group travel reflects his knack for spotting young, serial founders with high-growth potential.

PostHeaderIcon [DotCSS2018] DotCSS 2018: Aga Naplocha – Igniting Innovation Through Unconventional CSS

Aga Naplocha, a dynamic UX consultant and co-founder of The Awwwesomes, captivated the audience at DotCSS 2018 with her exploration of CSS as a canvas for audacious creativity. Frustrated by the monotony of grid-locked interfaces, she advocates for leveraging underutilized CSS features to infuse web projects with vitality and originality. Naplocha’s session serves as both a lament for stale aesthetics and a blueprint for reinvention, urging designers and developers alike to draw from diverse inspirations.

Rediscovering Inspiration Beyond Digital Echo Chambers

Naplocha opens with a personal anecdote of creative paralysis, where a routine assignment unearthed a profound dissatisfaction with ubiquitous layouts—endless columns and rectangles that stifle imagination. This epiphany, amplified by a satirical critique from 2015 decrying web design’s blandness, prompted her to unplug from online trend mills like Dribbble and Behance. Instead, she turned to analog sources: vintage magazines borrowed from a friend, whose eclectic collages and asymmetrical compositions rekindled her zeal.

This detour into print media revealed parallels to the web’s untapped potential, where content could dictate form rather than conform to it. Transitioning back online, Naplocha encountered brutalist websites—raw, rule-defying sites that prioritize uniqueness over polish. Exemplars like Bloomberg’s bold, GIF-laden articles demonstrate how even corporate entities can embrace eccentricity, blending vibrant hues and retro flair to elevate mundane narratives. She posits that such nonconformity, though occasionally UX-taxing, injects essential weirdness into the digital tapestry, challenging the hegemony of sanitized grids.

Furthermore, Naplocha emphasizes simplicity as the gateway to collaboration. By distilling complex visions into elemental CSS—eschewing heavy libraries—she bridges the chasm between novice designers and seasoned coders, democratizing innovation.

Harnessing CSS for Expressive, Nonconformist Layouts

Delving into technical territory, Naplocha unveils CSS clipping and masking as scissors for digital paper, enabling precise visibility control without raster dependencies. Clipping carves crisp, vector-based boundaries via paths or polygons, ideal for geometric precision, while masking modulates transparency pixel-by-pixel for gradient fades and layered illusions. She illustrates with a fixed-position header that unveils text through a scrolling mask, creating depth akin to overlapping transparencies—achievable with minimal code, yet profoundly impactful for prototyping.

Distinguishing the duo, Naplocha notes clipping’s efficiency for sharp edges versus masking’s computational heft for nuanced opacity. She extends this to shape-outside, liberating text from rectangular tyranny by wrapping around custom contours, such as circular initials or polygonal SVGs. A caveat: floated elements require explicit dimensions for coordinate anchoring, and complementary clipping ensures silhouettes align seamlessly.

Naplocha ties these techniques to broader movements, like SVG filters for glitch artistry or variable fonts for fluid expressiveness. Her finale spotlights a pure-CSS perspective skew on architectural copy, crediting James Bosworth’s CodePen, and rallies for side projects as low-stakes proving grounds. From the Stedelijk Museum’s stark brutalism to a Parisian brutalist basketball court, she curates real-world muses, echoing Henri Matisse’s creed that “creativity takes courage.” In her view, CSS’s arsenal empowers us to architect wilder webs, fostering environments where experimentation trumps convention.

Links:

PostHeaderIcon [DevoxxPL2019] GraphQL in the Java Ecosystem: A Comprehensive Exploration

Lecturer

Vladimir Dejanović is a seasoned software professional with over a decade of experience in the IT industry, having contributed to diverse projects since 2006. As Senior Director of B2C Technology at PVH, a fashion technology firm overseeing brands like Tommy Hilfiger and Calvin Klein, he focuses on scalable systems and innovative solutions. Beyond his corporate role, Vladimir founded and leads the Amsterdam Java User Group, fostering community engagement in Java technologies. He is recognized as an Oracle Code One Star and Java Rockstar, frequently delivering presentations at international conferences on topics like GraphQL and Java development.

Abstract

This article delves into the intricacies of GraphQL as applied within Java environments, examining its specification, implementation strategies, and practical applications through code demonstrations. It analyzes the advantages of GraphQL over traditional REST APIs, such as enhanced query flexibility and schema validation, while addressing potential pitfalls like cyclic dependencies and security concerns. Drawing from real-world examples, the discussion highlights methodologies for schema design, resolver integration, and performance optimization, underscoring GraphQL’s role in modern API development and its implications for system architecture.

Understanding GraphQL: Beyond the Basics

GraphQL emerges as a pivotal specification in API design, originating from Facebook in 2015 to address inefficiencies in data fetching encountered during mobile application development. Unlike conventional REST APIs, which often result in over-fetching or under-fetching of data, GraphQL empowers clients to request precisely the information needed, thereby optimizing network usage and enhancing performance. The specification defines a query language that allows for declarative data retrieval, where clients specify the structure of the response, aligning closely with application requirements.

At its core, GraphQL is not a full-fledged framework but a set of guidelines that various languages implement differently. In Java, implementations like GraphQL Java provide the engine for processing queries, while tools such as GraphQL Java Kickstarters facilitate integration with existing infrastructures, such as Spring Boot. This flexibility means developers must be cognizant of implementation-specific nuances, including coverage of the specification and additional features not mandated by the core rules. For instance, while the specification mandates schema validation, implementations may vary in handling extensions like custom scalars or error propagation.

The schema definition language (SDL) stands out as GraphQL’s most potent feature, surpassing alternatives like OpenAPI in expressiveness. It requires a mandatory schema that describes types, fields, and relationships, ensuring both client and server adhere to a contract. Upon connection, the server transmits the schema, enabling clients to validate requests locally before transmission, which reduces invalid traffic and conserves resources. This schema-first approach, preferred for its mockability, allows teams to prototype APIs independently: backend developers define the schema, while frontend teams use mocks to simulate responses.

Consider a practical scenario involving a conference application with entities like attendees, speakers, and talks. The schema might define types as follows:

type Attendee {
  id: ID!
  name: String
}

type Speaker {
  id: ID!
  name: String
  twitter: String
}

type Talk {
  id: ID!
  title: String
  description: String
  speakers: [Speaker]
}

Here, the exclamation mark denotes mandatory fields, and arrays indicate relationships. This structure not only documents the API but also enforces consistency, preventing outdated documentation—a common issue in REST environments.

Implementing Queries and Resolvers in Java

Transitioning to code, integrating GraphQL in Java involves wiring the schema to business logic. Using Spring Boot and GraphQL Java, one initializes a servlet mapped to “/graphql”, parsing the schema and registering resolvers. Resolvers act as the bridge, implementing interfaces like GraphQLQueryResolver for read operations.

For the conference example, a Query class might look like this:

@Component
public class Query implements GraphQLQueryResolver {
  private final TalkService talkService;
  private final SpeakerService speakerService;
  private final AttendeeService attendeeService;

  @RequiredArgsConstructor
  public Query(TalkService talkService, SpeakerService speakerService, AttendeeService attendeeService) {
    this.talkService = talkService;
    this.speakerService = speakerService;
    this.attendeeService = attendeeService;
  }

  public List<Talk> allTalks() {
    return talkService.findAll();
  }

  public List<Speaker> allSpeakers() {
    return speakerService.findAll();
  }

  public List<Attendee> allAttendees() {
    return attendeeService.findAll();
  }
}

This setup enables queries like fetching all talks with specific fields:

query {
  allTalks {
    id
    title
    description
    speakers {
      name
      twitter
    }
  }
}

The response mirrors the query structure in JSON, promoting predictability. Clients can alias fields (e.g., renaming “title” to “myTitle”) or conditionally include them using directives like @include(if: $variable), where variables are passed separately for dynamic behavior.

Resolvers for relationships, such as linking talks to speakers, extend GraphQLResolver:

@Component
public class TalkResolver implements GraphQLResolver<Talk> {
  private final SpeakerService speakerService;

  @RequiredArgsConstructor
  public TalkResolver(SpeakerService speakerService) {
    this.speakerService = speakerService;
  }

  public List<Speaker> speakers(Talk talk) {
    return speakerService.findAllSpeakersForTalk(talk);
  }
}

This modular approach allows for granular control, but it introduces risks like cyclic queries if bidirectional links (e.g., speakers to talks) are added without safeguards. Such cycles can lead to infinite loops, necessitating depth limits during validation.

Mutations: Enabling Data Modification

While queries handle reads, mutations facilitate writes, mirroring CRUD operations but with GraphQL’s precision. Defined similarly in the schema:

type Mutation {
  addTalk(input: TalkInput!): Talk
}

Mutations require explicit input types to encapsulate parameters, ensuring type safety. In Java, a Mutation resolver implements GraphQLMutationResolver:

@Component
public class Mutation implements GraphQLMutationResolver {
  private final TalkService talkService;

  @RequiredArgsConstructor
  public Mutation(TalkService talkService) {
    this.talkService = talkService;
  }

  public Talk addTalk(TalkInput input) {
    // Logic to create and persist talk
    return talkService.save(input.toTalk());
  }
}

This method processes inputs, validates them, and returns the updated entity. Unlike queries, which can execute in parallel for optimization, mutations are sequential to maintain data integrity. Errors in mutations propagate similarly to queries, with customizable handlers to continue processing or halt execution.

The implications are profound: mutations reduce boilerplate compared to REST’s multiple endpoints, centralizing logic while allowing clients to request related data in the same response, such as fetching the newly added talk’s speakers.

Subscriptions: Real-Time Data Streams

Subscriptions introduce reactive capabilities, enabling server-push updates over WebSockets. The schema defines:

type Subscription {
  scores(title: String!): Score
}

type Score {
  title: String
  score: Int
}

In Java, using Reactor for reactivity:

@Component
public class Subscription implements GraphQLSubscriptionResolver {
  public Publisher<Score> scores(String title) {
    return Flux.interval(Duration.ofSeconds(2))
      .map(i -> Score.builder()
        .title(title)
        .score(ThreadLocalRandom.current().nextInt(1, 6))
        .build());
  }
}

This generates scores every two seconds, demonstrating backpressure handling to prevent client overload. Subscriptions transform static APIs into dynamic ones, ideal for live updates like conference feedback, though implementation varies—GraphQL Java uses WebSockets, but the specification leaves transport open.

Security and Performance Considerations

Security in GraphQL demands vigilance, as the schema’s public nature exposes potential attack vectors. Authentication and authorization occur via custom contexts:

public class MyGraphQLContext extends GraphQLContext {
  private final User user;

  public MyGraphQLContext(User user) {
    this.user = user;
  }
}

Resolvers access this context via DataFetchingEnvironment to enforce roles. For schema protection, directives or instrumentation filter visibility, though non-standard approaches risk interoperability.

Performance pitfalls include N+1 queries, mitigated by batching or caching in services. Instrumentation traces execution:

public class TracingInstrumentation extends SimpleInstrumentation {
  @Override
  public InstrumentationContext<ExecutionResult> beginExecution(InstrumentationExecutionParameters parameters) {
    // Start timer, log query
    return super.beginExecution(parameters);
  }
}

Query complexity analysis during validation prevents denial-of-service attacks by capping depth or computational cost.

Schema management in large systems involves stitching or extensions to avoid monolithic files:

extend type Speaker {
  twitter: String
}

This federates schemas across services, though conflicts require governance.

Implications for Modern Development

GraphQL’s client-centric model shifts power from servers, fostering agile development but requiring robust safeguards. In Java, its integration with Spring Boot streamlines adoption, yet demands awareness of implementation variances. By enabling precise data fetching and real-time interactions, it addresses REST’s limitations, promoting efficient, scalable architectures. Future specification enhancements, like improved subscription standards, promise broader applicability.

Links:

PostHeaderIcon [SpringIO2019] Boot Loot: Level Up Your Spring Game Like the Pros

Mastering Spring Boot Customization and Configuration

In his Spring I/O 2019 presentation, Joris Kuipers dives deep into the advanced capabilities of Spring Boot, extending beyond its familiar features like autoconfiguration and actuator support. He explores how developers can truly “level up their game” by leveraging custom autoconfiguration and type-safe configuration classes. Kuipers provides practical insights into customizing RestTemplates while ensuring that instrumentation from Boot and Cloud remains intact. The talk also covers strategies for reducing the cardinality of Boot-provided metrics and defining custom ones, as well as handling the migration of older Spring applications to Boot, including considerations for external directories on the classpath.

Throughout this fast-paced session, Joris Kuipers shares a wealth of tips, tricks, and best practices gleaned from his extensive experience with Spring Boot and Cloud in diverse production environments. Whether you’re new to Spring Boot or a seasoned user, this presentation offers hands-on techniques that can be immediately applied to your projects. Key topics include:

  • Custom Autoconfiguration and Type-Safe Configuration: Moving beyond basic configurations to create robust and maintainable applications.
  • RestTemplate Customization: Ensuring proper instrumentation and integration within Spring Boot and Cloud ecosystems.
  • Advanced Metrics Management: Reducing cardinality and defining custom metrics for better observability.
  • Migrating Legacy Spring Applications: Practical approaches to integrate older applications with the Spring Boot environment.
  • Error Handling and Validation: Best practices for managing default error pages and implementing effective bean validation.

Joris Kuipers has been building enterprise Java applications for 25 years and has previously served as a trainer and consultant for SpringSource, continuing to teach Spring training for the Trifork Academy.

Links

PostHeaderIcon [KotlinConf2019] Putting Down the Golden Hammer: Pragmatic Kotlin with Huyen Tue Dao

Learning a new programming language, especially one as rich and expressive as Kotlin, often comes with the temptation to use every new feature and syntactic sugar—the “golden hammer”—everywhere. Huyen Tue Dao, a prominent Android developer then known for her work at Trello and her insightful contributions to the Kotlin community, addressed this phenomenon at KotlinConf 2019. Her talk, “Putting Down the Golden Hammer,” shared valuable lessons learned from nearly three years of full-time Kotlin development, emphasizing the importance of pragmatism, readability, and maintainability over merely clever code. Huyen’s insights can often be found on her blog, randomlytyping.com.

Huyen began by acknowledging the allure of Kotlin’s advanced features. While these constructs can be powerful and lead to concise code, she cautioned that their overuse or misuse can sometimes negatively impact code clarity and long-term maintainability. The journey of a developer learning Kotlin often involves an initial phase of enthusiasm for these new tools, followed by a more mature understanding of when and how to apply them judiciously.

The Evolution of a Kotlin Developer’s Approach

Huyen Tue Dao shared her personal evolution in approaching various Kotlin features. She reflected on how code written early in her Kotlin journey might look different from her current practices, shaped by experience, trial, and error. This evolution is natural and signifies a deeper understanding of the language’s nuances and the trade-offs involved in different coding styles.

One key area she touched upon (common in such discussions) is the balance between conciseness and readability. Kotlin allows for very compact code, but sometimes a slightly more verbose approach can be easier for others (and one’s future self) to understand and maintain. She stressed that while Kotlin’s features are designed to make developers more productive, this productivity should not come at the expense of creating code that is difficult to reason about or debug. The goal should be to write “better Kotlin,” which implies code that is not only functionally correct and efficient but also clear, pragmatic, and maintainable.

Pragmatism in Feature Usage: Scope Functions, Nullability, and More

Huyen Tue Dao delved into specific Kotlin features and utilities, discussing both their “fun and shiny” aspects and how they can be overused or even abused. For instance, scope functions (let, run, with, apply, also) are powerful tools for executing a block of code within the context of an object. However, excessive nesting or unclear usage can lead to code that is hard to follow. Huyen advocated for intentionality: choosing the right scope function for the task and ensuring its use enhances clarity rather than obscuring it.

Null safety is another cornerstone of Kotlin, designed to prevent NullPointerExceptions. Huyen discussed the importance of being deliberate about nullability. While Kotlin’s type system helps manage nulls effectively, developers still need to make conscious decisions about whether a type should be nullable and handle nullable types appropriately, without resorting to excessive safe calls (?.) or non-null asserted calls (!!) that might hide underlying design issues. She emphasized being clear about why something is nullable and documenting such decisions when necessary, especially when assumptions about nullability change or when interacting with APIs where null safety guarantees might be different.

Towards Readable and Maintainable Kotlin

Ultimately, Huyen Tue Dao’s message was a call for mindful Kotlin development. She encouraged the audience to revel in Kotlin’s wonderful syntax and features but to always keep readability, maintainability, and pragmatism at the forefront. Understanding the underlying implementation of certain features can also be crucial to avoid potential performance issues.

The aim is not to write code that merely feels “sexy and Kotlin-y” but to craft solutions that are robust, easy for a team to work with, and stand the test of time. Recognizing the potential pitfalls of overusing certain constructs and consciously choosing simpler, clearer alternatives when appropriate leads to what Huyen termed “even better and even more fun Kotlin”. Her talk served as a valuable reminder that true mastery of a language lies not just in knowing its features, but in knowing when and how to use them wisely.

Links:

PostHeaderIcon [DevoxxFR 2019] Micronaut: The Ultra-Light JVM Framework of the Future

At Devoxx France 2019, Olivier Revial, a developer at Stackeo in Toulouse, presented Micronaut: The Ultra-Light JVM Framework of the Future. This session introduced Micronaut, a modern JVM framework designed for microservices and serverless applications, offering sub-second startup times and a 10MB memory footprint. Through slides and demos, Revial showcased Micronaut’s cloud-native approach and its potential to redefine JVM development.

Limitations of Existing Frameworks

Revial began by contrasting Micronaut with established frameworks like Spring Boot and Grails. While Spring Boot simplifies development with auto-configuration and standalone applications, it suffers from runtime dependency injection and reflection, leading to slow startup times (20–25 seconds) and high memory usage. As codebases grow, these issues worsen, complicating testing and deployment, especially in serverless environments where rapid startup is critical. Frameworks like Spring create a barrier between unit and integration tests, as long-running servers are often relegated to separate CI processes.

Micronaut addresses these pain points by eliminating reflection and using Ahead-of-Time (AOT) compilation, performing dependency injection and configuration at build time. This reduces startup times and memory usage, making it ideal for containerized and serverless deployments.

Micronaut’s Innovative Approach

Micronaut, created by Grails’ founder Graeme Rocher and Spring contributors, builds on the strengths of existing frameworks—dependency injectiaon, auto-configuration, service discovery, and HTTP client/server simplicity—while introducing innovations. It supports Java, Kotlin, and Groovy, using annotation processors and AST transformations for AOT compilation. This eliminates runtime overhead, enabling sub-second startups and minimal memory footprints.

Micronaut is cloud-native, with built-in support for MongoDB, Kafka, JDBC, and providers like Kubernetes and AWS. It embraces reactive programming via Reactor, supports GraalVM for native compilation, and simplifies testing by allowing integration tests to run alongside unit tests. Security features, including JWT and basic authentication, and metrics for Prometheus, enhance its enterprise readiness. Despite its youth (version 1.0 released in 2018), Micronaut’s ecosystem is rapidly growing.

Demonstration

Revial’s demo showcased Micronaut’s capabilities. He used the Micronaut CLI to create a “hello world” application in Kotlin, adding a controller with REST endpoints, one returning a reactive Flowable. The application started in 1–2 seconds locally (6 seconds in the demo due to environment differences) and handled HTTP requests efficiently. A second demo featured a Twitter crawler storing tweets in MongoDB using a reactive driver. It demonstrated dependency injection, validation, scheduled tasks, and security (basic authentication with role-based access). A GraalVM-compiled version started in 20 milliseconds, with a 70MB Docker image compared to 160MB for a JVM-based image, highlighting Micronaut’s efficiency for serverless use cases.

Hashtags: #Micronaut #Microservices #DevoxxFR2019 #OlivierRevial #JVMFramework #CloudNative

PostHeaderIcon [VivaTech 2019] Funding and Growing Tomorrow’s Unicorns

A 25-minute panel at VivaTech 2019, moderated by Emmanuelle Duten of Les Echos/Capital Finance, featured Philippe Botteri, Partner at Accel, Virginie Morgon, CEO of Eurazeo, and David Thevenon, Partner at SoftBank Investment Advisers, available on YouTube. Connected via LinkedIn, LinkedIn, and LinkedIn, they discussed Europe’s unicorn boom. This 1000–1200-word post, for investors, entrepreneurs, and policymakers, explores the drivers of unicorn growth.

Europe’s Unicorn Momentum

Philippe highlighted Europe’s unicorn surge, with 17–18 created in 2018, fueled by $23 billion in investments. Accel’s $575 million fund targets 22 European cities, a shift from London-Tel Aviv dominance 15 years ago. Virginie noted that two-thirds of 2018’s new unicorns were European, driven by ambitious founders and growing growth capital. David emphasized Europe’s robust ecosystem, with SoftBank’s investments in Germany and beyond, signaling that the region now rivals global hubs, supported by professional early-stage and growth investors.

Characteristics of Unicorn Founders

Virginie stressed that unicorn founders, like Farfetch’s José Neves, exhibit exceptional execution and ambition, mastering complex platforms (e.g., logistics, delivery). Philippe cited Doctolib’s Stan, whose passion for transforming European healthcare inspired Accel’s Series A investment, now a unicorn. David pointed to OYO’s Ritesh Agarwal, scaling from 13 to 200,000 hotel rooms since 2015, driven by urgency and global vision. These founders combine strategic thinking, platform-building (e.g., Grab’s shift to financial services), and relentless focus, distinguishing them in competitive markets.

Supporting Unicorn Growth

Beyond capital, VCs provide operational support. Philippe’s Accel leverages its global network (Silicon Valley, London, India) to help software startups relocate to the U.S., hiring top sales talent. Virginie’s Eurazeo offers strategic guidance, from commercial partnerships to U.S. expansion, as seen with ContentSquare. David’s SoftBank provides long-term capital (12-year funds) and market access (China, Latin America), fostering peace of mind for innovation. This hands-on partnership—$100 million on average to reach unicorn status—ensures rapid scaling, even if profitability lags behind growth.

PostHeaderIcon [DotCSS2018] DotCSS 2018: Dan Cederholm – Reflections on Two Decades with CSS

Dan Cederholm, a pioneering figure in web design and founder of SimpleBits, reflected deeply on his journey with CSS during his presentation at DotCSS 2018. Drawing from over two decades of experience, he shared lessons that extend far beyond syntax and selectors, touching on resilience, community, and the ephemeral nature of digital creation. Cederholm’s candid recounting of triumphs and setbacks offers timeless wisdom for developers navigating the ever-evolving landscape of web technologies.

Embracing Bold Steps and Community Sharing

Cederholm’s narrative begins in the early 2000s, a period marked by the shift from table-based layouts to CSS-driven designs. He vividly recalls the 2002 redesign of Wired News, a landmark project that propelled the industry forward by abandoning support for outdated browsers like Netscape 4. Inspired by Jeffrey Zeldman’s provocative article “To Hell with Bad Browsers,” Cederholm approached his then-employer, Fast Company magazine, with a proposal to follow suit. To his surprise, his forward-thinking boss greenlit the initiative, leading to a 2003 overhaul that, despite backlash from a shrinking cohort of legacy users, cemented Cederholm’s commitment to progressive standards.

This pivotal moment not only honed his technical skills but also ignited a passion for documentation and mentorship. While iterating on the Fast Company site, Cederholm chronicled his process on a rudimentary blog, despite lacking formal writing credentials. This habit of sharing raw, in-progress insights—complete with the era’s notorious browser bugs—fostered unexpected connections. Invitations to speak and collaborate followed, transforming personal experimentation into professional opportunities. Cederholm underscores a key takeaway: vulnerability in sharing imperfect knowledge builds bridges, turning solitary coding sessions into collaborative dialogues that propel collective advancement.

Moreover, these early risks taught him the value of persistence amid imperfection. The browser wars demanded ingenious workarounds, yet each hack refined his problem-solving acumen. Today, as frameworks proliferate, Cederholm urges newcomers to view challenges not as barriers but as catalysts for growth, reminding us that mastery emerges from repeated trial and adaptation.

Navigating Evolution and Impermanence

As the web matured, so did Cederholm’s toolkit, evolving from vanilla CSS to preprocessors like Sass. Initially resistant—citing concerns over code readability and the philosophy of keeping CSS accessible for novices—he eventually embraced Sass after a colleague’s pragmatic suggestion to simply rename files. This incremental adoption, starting with variables for vendor prefixes and nesting for media queries, revolutionized his responsive workflows. The experience with Sass, much like his initial foray into CSS, highlighted the pitfalls of premature dismissal; what begins as reluctance often blossoms into indispensable efficiency.

Cederholm also touches on broader philosophical shifts, such as his evolving stance on methodologies like Atomic CSS. Initially skeptical of utility class names, he came to appreciate their utility in rapid prototyping, especially within team environments. This openness stems from a core principle: prioritize tools that minimize code volume and maximize clarity. Yet, he tempers enthusiasm with caution, advocating for mindful integration rather than wholesale overhaul.

Ultimately, Cederholm’s reflections circle back to transience. In an industry where innovations cascade rapidly—rendering yesterday’s hacks obsolete—he finds solace in impermanence. Echoing the sentiment of his Adventure pin design, “Everything is stardust,” he posits that the pressure to master every novelty dissipates when viewed against the web’s fleeting canvas. This perspective liberates creators to experiment joyfully, unburdened by the fear of obsolescence. As he concludes, the true legacy of CSS lies not in enduring code but in the enduring habits of curiosity and camaraderie it instills.

Links:

PostHeaderIcon [KotlinConf2019] KotlinConf 2019 Keynote: People, Ideas, and Software in the Kotlin Ecosystem with Andrey Breslav

The opening keynote of KotlinConf 2019, delivered by Andrey Breslav, the then Lead Language Designer for Kotlin at JetBrains, set an inspiring tone for the conference. Addressing a packed room of 1,700 attendees, with many more watching online, Andrey articulated a vision of Kotlin that extends beyond mere syntax and features, emphasizing it as an ecosystem built upon three pillars: people, ideas, and software. His presentation underscored the collaborative spirit that fuels Kotlin’s growth and the continuous feedback loop that shapes its evolution. The official Kotlin language website, central to this ecosystem, is kotlinlang.org.

Andrey Breslav began by reflecting on Kotlin’s journey and its burgeoning community. He highlighted that the success and adoption of Kotlin are deeply intertwined with the people who use it, contribute to it, and advocate for it. This “people-first” perspective was a recurring theme, as he stressed that Kotlin is designed to bring developers together, fostering a common way of working and shared values. The vibrant interactions at KotlinConf itself, with developers from around the world sharing experiences and knowledge, served as a living testament to this community-centric approach.

The Power of Ideas and Continuous Improvement

A core tenet of Kotlin’s development philosophy, as outlined by Andrey Breslav, is the importance of ideas and the relentless pursuit of improvement. He emphasized that the Kotlin team at JetBrains actively seeks and values feedback from the developer community. This feedback loop is critical, whether it comes through direct communication, bug reports, feature requests, or even passively through anonymized usage statistics collected by JetBrains’ IDEs. These statistics, he explained, help the team understand how Kotlin is used in real-world scenarios, identify pain points (like slow code completion in specific environments), and prioritize areas for enhancement.

This data-informed approach allows the Kotlin team to make more effective decisions about the language’s future direction. Andrey encouraged attendees to participate in this feedback process, assuring them that their input, no matter how small, contributes to making Kotlin better for everyone. He cited examples where community feedback directly influenced language features and tooling improvements, reinforcing the idea that Kotlin’s evolution is a collaborative effort. This commitment to listening and adapting ensures that Kotlin remains a pragmatic and powerful tool that addresses the real-world needs of developers.

Software as a Collaborative Endeavor

The third pillar, software, encompasses not only the Kotlin language itself but also the rich ecosystem of libraries, tools, and frameworks that surround it. Andrey Breslav highlighted the importance of this broader ecosystem in making Kotlin a productive and enjoyable language to work with. He acknowledged the contributions of the community in building these resources, from open-source libraries to educational materials and tutorials.

Furthermore, Andrey spoke about JetBrains’ ongoing efforts to enhance the Kotlin tooling, including the compiler and IDE support, to improve performance, stability, and developer experience. He touched upon initiatives aimed at making Kotlin more versatile, enabling its use across various platforms—JVM, Android, JavaScript, Native—and for different types of applications, from server-side systems to mobile apps and web frontends. The keynote celebrated the milestones achieved, such as the growing adoption of Kotlin Multiplatform, while also looking ahead to future challenges and opportunities. Andrey concluded by reiterating that every form of participation, from writing code and tutorials to sharing experiences and even simple social media interactions, adds value to the Kotlin community and contributes to its collective success.

Links:

PostHeaderIcon Navigating the Application Lifecycle in Kubernetes

At Devoxx France 2019, Charles Sabourdin and Jean-Christophe Sirot, seasoned professionals in cloud-native technologies, delivered an extensive exploration of managing application lifecycles within Kubernetes. Charles, an architect with over 15 years in Linux and Java, and Jean-Christophe, a Docker expert since 2002, combined their expertise to demystify Docker’s underpinnings, Kubernetes’ orchestration, and the practicalities of continuous integration and delivery (CI/CD). Through demos and real-world insights, they addressed security challenges across development and business-as-usual (BAU) phases, proposing organizational strategies to streamline containerized workflows. This post captures their comprehensive session, offering a roadmap for developers and operations teams navigating Kubernetes ecosystems.

Docker’s Foundations: Isolation and Layered Efficiency

Charles opened the session by revisiting Docker’s core principles, emphasizing its reliance on Linux kernel features like namespaces and control groups (cgroups). Unlike virtual machines (VMs), which bundle entire operating systems, Docker containers share the host kernel, isolating processes within lightweight environments. This design achieves hyper-density, allowing more containers to run on a single machine compared to VMs. Charles demonstrated launching a container, highlighting its process isolation using commands like ps within a containerized bash session, contrasting it with the host’s process list. He introduced Docker’s layer system, where images are built as immutable, stacked deltas, optimizing storage through shared base layers. Tools like Dive, he noted, help inspect these layers, revealing command histories and suggesting size optimizations. This foundation sets the stage for Kubernetes, enabling efficient, portable application delivery across environments.

Kubernetes: Orchestrating Scalable Deployments

Jean-Christophe transitioned to Kubernetes, describing it as a resource orchestrator that manages containerized applications across node pools. Kubernetes abstracts infrastructure complexities, using declarative configurations to maintain desired application states. Key components include pods—the smallest deployable units housing containers—replica sets for scaling, and deployments for managing updates. Charles demonstrated creating a namespace and deploying a sample application using kubectl run, which scaffolds deployments, replica sets, and pods. He showcased rolling updates, where Kubernetes progressively replaces pods to ensure zero downtime, configurable via parameters like maxSurge and maxUnavailable. The duo emphasized Kubernetes’ auto-scaling capabilities, which adjust pod counts based on load, and the importance of defining resource limits to prevent performance bottlenecks. Their demo underscored Kubernetes’ role in achieving resilient, scalable deployments, aligning with hyper-density goals.

CI/CD Pipelines: Propagating Versions Seamlessly

The session delved into CI/CD pipelines, illustrating how Docker tags facilitate version propagation across development, pre-production, and production environments. Charles outlined a standard process: developers build Docker images tagged with version numbers (e.g., 1.1, 1.2) or environment labels (e.g., prod, staging). These images, stored in registries like Docker Hub or private repositories, are pulled by Kubernetes clusters for deployment. Jean-Christophe highlighted debates around tagging strategies, noting that version-based tags ensure traceability, while environment tags simplify environment-specific deployments. Their demo integrated tools like Jenkins and JFrog Artifactory, automating builds, tests, and deployments. They stressed the need for robust pipeline configurations to avoid resource overuse, citing Jenkins’ default manual build triggers for tagged releases as a safeguard. This pipeline approach ensures consistent, automated delivery, bridging development and production.

Security Across the Lifecycle: Development vs. BAU

Security emerged as a central theme, with Charles contrasting development and BAU phases. During development, teams rapidly address Common Vulnerabilities and Exposures (CVEs) with frequent releases, leveraging tools like JFrog Xray and Clair to scan images for vulnerabilities. Xray integrates with Artifactory, while Clair, an open-source solution, scans registry images for known CVEs. However, in BAU, where releases are less frequent, unpatched vulnerabilities pose greater risks. Charles shared an anecdote about a PHP project where a dependency switch broke builds after two years, underscoring the need for ongoing maintenance. They advocated for practices like running containers in read-only mode and using non-root users to minimize attack surfaces. Tools like OWASP Dependency-Track, they suggested, could enhance visibility into library vulnerabilities, though current scanners often miss non-package dependencies. This dichotomy highlights the need for automated, proactive security measures throughout the lifecycle.

Organizational Strategies: Balancing Complexity and Responsibility

Drawing from their experiences, Charles and Jean-Christophe proposed organizational solutions to manage Kubernetes complexity. They introduced a “1-2-3 model” for image management: Level 1 uses vendor-provided images (e.g., official MySQL images) managed by operations; Level 2 involves base images built by dedicated teams, incorporating standardized tooling; and Level 3 allows project-specific images, with teams assuming maintenance responsibilities. This model clarifies ownership, reducing risks like disappearing maintainers when projects transition to BAU. They emphasized cross-team collaboration, encouraging developers and operations to share knowledge and align on practices like Dockerfile authorship and resource allocation in YAML configurations. Charles reflected on historical DevOps silos, advocating for shared vocabularies and traceable decisions to navigate evolving best practices. Their return-of-experience underscored the importance of balancing automation with human oversight to maintain robust, secure Kubernetes environments.

Hashtags: #Kubernetes #Docker #DevOps #CICD #Security #DevoxxFR #CharlesSabourdin #JeanChristopheSirot #JFrog #Clair