-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.json
More file actions
1 lines (1 loc) · 296 KB
/
index.json
File metadata and controls
1 lines (1 loc) · 296 KB
1
[{"content":"In early 2024, the mantra for developers was \u0026ldquo;bigger is better.\u0026rdquo; We reached for the largest, most general-purpose models for every task—from writing code to summarizing medical records. But as we move through 2026, the industry has undergone a massive correction.\nThe trend today isn\u0026rsquo;t toward Larger Language Models, but toward Domain-Specific Models (DSMs). Developers are increasingly realizing that a 7B parameter model fine-tuned for a specific vertical often outperforms a 1T+ parameter general model in accuracy, latency, and—most importantly—cost.\nWhy General Models are \u0026ldquo;So 2024\u0026rdquo; While GPT-5 and its peers are incredible feats of engineering, they suffer from \u0026ldquo;Jack of all trades, master of none\u0026rdquo; syndrome when applied to highly specialized fields.\nHallucination in Nuance: General models often smooth over technical jargon or legal specificities, leading to confidently wrong answers in high-stakes environments. The \u0026ldquo;Token Tax\u0026rdquo;: Running a massive model for a task that only requires a fraction of its \u0026ldquo;intelligence\u0026rdquo; is economically unsustainable at scale. Data Privacy: Fine-tuning smaller, open-weight models (like the Llama-4-Small or Mistral-Next series) allows companies to keep sensitive data within their own VPCs while achieving state-of-the-art performance. The Rise of the Vertical AI Stack In 2026, we\u0026rsquo;re seeing \u0026ldquo;Vertical AI\u0026rdquo; take over. Instead of one model for everything, a typical enterprise architecture now looks like a constellation of specialized experts:\nLegal-LLM: Optimized for contract analysis and case law. Bio-Coder: Specifically trained on protein sequences and organic chemistry. Dev-Ops-Genius: A model that only understands Kubernetes manifests and Terraform. Code Example: Efficient Fine-Tuning with PEFT (2026 edition) Fine-tuning used to require a massive cluster. Today, with techniques like QLoRA (Quantized Low-Rank Adaptation), you can fine-tune a domain-specific model on a single high-end consumer GPU.\nHere’s how a developer might approach fine-tuning a base model for \u0026ldquo;Cloud Infrastructure Security\u0026rdquo; using a modern Python stack:\nfrom unsloth import FastLanguageModel import torch from trl import SFTTrainer from transformers import TrainingArguments from datasets import load_dataset # 1. Load a high-efficiency base model (e.g., Llama-3-8B-equivalent in 2026) model, tokenizer = FastLanguageModel.from_pretrained( model_name = \u0026#34;unsloth/llama-3-8b-bnb-4bit\u0026#34;, max_seq_length = 2048, load_in_4bit = True, ) # 2. Add LoRA adapters to make it domain-specific model = FastLanguageModel.get_peft_model( model, r = 16, target_modules = [\u0026#34;q_proj\u0026#34;, \u0026#34;k_proj\u0026#34;, \u0026#34;v_proj\u0026#34;, \u0026#34;o_proj\u0026#34;], lora_alpha = 16, lora_dropout = 0, bias = \u0026#34;none\u0026#34;, ) # 3. Load your domain-specific dataset (e.g., security audits) dataset = load_dataset(\u0026#34;json\u0026#34;, data_files=\u0026#34;cloud_security_audits.jsonl\u0026#34;, split=\u0026#34;train\u0026#34;) # 4. Standard Fine-Tuning (SFT) trainer = SFTTrainer( model = model, tokenizer = tokenizer, train_dataset = dataset, dataset_text_field = \u0026#34;text\u0026#34;, max_seq_length = 2048, args = TrainingArguments( per_device_train_batch_size = 2, gradient_accumulation_steps = 4, warmup_steps = 5, max_steps = 60, learning_rate = 2e-4, fp16 = not torch.cuda.is_supported(), bf16 = torch.cuda.is_supported(), logging_steps = 1, output_dir = \u0026#34;outputs\u0026#34;, ), ) trainer.train() # 5. Save the specialized \u0026#34;expert\u0026#34; model model.save_pretrained(\u0026#34;cloud_security_expert_v1\u0026#34;) The Developer\u0026rsquo;s New Role: Data Curator As models become more specialized, the value shift for developers is clear. We are moving from \u0026ldquo;Prompt Engineers\u0026rdquo; to Data Curators and Model Orchestrators.\nBuilding a great AI product in 2026 isn\u0026rsquo;t about writing the perfect prompt; it\u0026rsquo;s about:\nIdentifying the right specialized model for the job. Curating high-quality, synthetic data to bridge the knowledge gap. Orchestrating multiple experts to solve a complex user problem. Conclusion The \u0026ldquo;One Model to Rule Them All\u0026rdquo; era is over. The future belongs to the \u0026ldquo;Experts\u0026rdquo;—small, fast, and incredibly accurate models tailored for specific domains. For developers, this means more control, lower costs, and ultimately, better software.\nChen Kinnrot is a software engineer exploring the evolution of AI-native development.\n","permalink":"https://kinnrot.github.io/domain-specific-models-2026/","summary":"\u003cp\u003eIn early 2024, the mantra for developers was \u0026ldquo;bigger is better.\u0026rdquo; We reached for the largest, most general-purpose models for every task—from writing code to summarizing medical records. But as we move through 2026, the industry has undergone a massive correction.\u003c/p\u003e\n\u003cp\u003eThe trend today isn\u0026rsquo;t toward \u003cem\u003eLarger\u003c/em\u003e Language Models, but toward \u003cstrong\u003eDomain-Specific Models (DSMs)\u003c/strong\u003e. Developers are increasingly realizing that a 7B parameter model fine-tuned for a specific vertical often outperforms a 1T+ parameter general model in accuracy, latency, and—most importantly—cost.\u003c/p\u003e","title":"Domain-Specific Models: The Shift from General to Specialized AI in 2026"},{"content":"As we move further into 2026, the role of the software engineer continues to shift from \u0026ldquo;code writer\u0026rdquo; to \u0026ldquo;system architect.\u0026rdquo; One of the most significant shifts we\u0026rsquo;ve seen this year is the maturation of AI-powered refactoring tools. No longer just simple linters, today\u0026rsquo;s Generative AI agents are capable of understanding complex architectural patterns and proactively managing technical debt.\nBeyond Simple Auto-Complete In the early days of AI coding assistants, we were impressed by simple completions. Today, we have agents that can ingest an entire repository, identify \u0026ldquo;code smells,\u0026rdquo; and propose large-scale structural changes that align with modern best practices.\nThe real breakthrough in 2026 is context-aware refactoring. These tools don\u0026rsquo;t just fix a single line; they understand how a change in a service layer impacts the controllers and the frontend, ensuring type safety and architectural consistency across the entire stack.\nTackling Technical Debt Automatically Technical debt is the silent killer of velocity. In 2026, we are seeing the rise of \u0026ldquo;Self-Healing Codebases.\u0026rdquo; Imagine a CI/CD pipeline that not only runs tests but also identifies deprecated patterns and automatically creates pull requests to update them.\nHere’s an example of how a modern AI agent might refactor a legacy asynchronous pattern into a more modern, readable structure.\nExample: Refactoring Legacy Callbacks to Modern AI-Optimized Patterns Suppose you have some legacy Node.js code that still uses complex nested callbacks or older Promise patterns. A 2026-era AI agent can refactor this into a clean, agent-friendly structure.\nLegacy Code:\n// old-service.js function fetchUserData(userId, callback) { db.findUser(userId, (err, user) =\u0026gt; { if (err) return callback(err); api.getProfile(user.profileId, (err, profile) =\u0026gt; { if (err) return callback(err); callback(null, { ...user, profile }); }); }); } AI-Refactored Code (2026 Style):\n// modern-service.ts /** * Refactored by AI-Architect-Agent v4.2 * Strategy: Convert to Async/Await with robust error handling and telemetry. */ import { telemetry } from \u0026#39;@infra/monitoring\u0026#39;; export async function getUserData(userId: string): Promise\u0026lt;UserComposite\u0026gt; { try { const user = await db.users.findById(userId); if (!user) throw new Error(`User ${userId} not found`); const profile = await api.profiles.get(user.profileId); return { ...user, profile, timestamp: new Date().toISOString() }; } catch (error) { telemetry.logError(\u0026#39;getUserData_failed\u0026#39;, { userId, error }); throw error; } } The Human in the Loop While the AI can perform the heavy lifting, the engineer\u0026rsquo;s role remains critical. We are now the reviewers and guardians of intent. We define the architectural \u0026ldquo;north star,\u0026rdquo; and the AI helps us get there by handling the thousands of small, tedious changes required to keep a codebase healthy.\nConclusion AI-powered refactoring is not about replacing developers; it\u0026rsquo;s about liberating them from the burden of legacy maintenance. By leveraging these tools, we can spend more time building features that matter and less time fighting with our own codebases.\nWhat does your refactoring workflow look like in 2026? Are you letting the agents lead the way?\n","permalink":"https://kinnrot.github.io/the-evolution-of-code-quality-ai-powered-refactoring-and-technical-debt-management/","summary":"\u003cp\u003eAs we move further into 2026, the role of the software engineer continues to shift from \u0026ldquo;code writer\u0026rdquo; to \u0026ldquo;system architect.\u0026rdquo; One of the most significant shifts we\u0026rsquo;ve seen this year is the maturation of AI-powered refactoring tools. No longer just simple linters, today\u0026rsquo;s Generative AI agents are capable of understanding complex architectural patterns and proactively managing technical debt.\u003c/p\u003e\n\u003ch2 id=\"beyond-simple-auto-complete\"\u003eBeyond Simple Auto-Complete\u003c/h2\u003e\n\u003cp\u003eIn the early days of AI coding assistants, we were impressed by simple completions. Today, we have agents that can ingest an entire repository, identify \u0026ldquo;code smells,\u0026rdquo; and propose large-scale structural changes that align with modern best practices.\u003c/p\u003e","title":"The Evolution of Code Quality: AI-Powered Refactoring and Technical Debt Management"},{"content":"While LLMs changed the world with text, Multi-modal AI is changing how we interact with the physical world. In 2026, we\u0026rsquo;ve moved past \u0026ldquo;GPT-4o style\u0026rdquo; multimodal inputs toward deep, integrated reasoning across vision, voice, and even spatial data.\nDevelopers are no longer just building chatbots; they are building \u0026ldquo;Vision-Native\u0026rdquo; and \u0026ldquo;Voice-First\u0026rdquo; applications that understand context as humans do.\nThe Shift to Multi-modal Reasoning In the early 2020s, multi-modal was often a series of \u0026ldquo;converters\u0026rdquo;—speech-to-text, then text-to-LLM, then text-to-speech. Today, we use single models with unified token spaces. This reduces latency and, more importantly, preserves the nuance lost in transcription.\nWhen an AI hears a user\u0026rsquo;s tone or sees a user\u0026rsquo;s frustration through a camera, it can react emotionally and contextually without needing a text description of that state.\nCode Example: Analyzing Live Video Streams with modern Multi-modal SDKs Here is how you would set up a vision-native observer in a 2026 framework (using a hypothetical standard SDK for a unified model).\nimport multimodal_sdk as mm # Initialize the observer with Vision and Audio capabilities observer = mm.UnifiedModel( capabilities=[\u0026#34;vision\u0026#34;, \u0026#34;audio\u0026#34;, \u0026#34;spatial\u0026#34;], provider=\u0026#34;local-optimized-2026\u0026#34; ) def on_video_frame(frame, audio_snippet): # The model processes raw bytes directly analysis = observer.analyze( inputs={\u0026#34;image\u0026#34;: frame, \u0026#34;audio\u0026#34;: audio_snippet}, prompt=\u0026#34;Observe the user. Are they struggling with the physical assembly? Provide guidance if they look confused.\u0026#34; ) if analysis.sentiment == \u0026#34;confused\u0026#34;: print(f\u0026#34;Assistant Voice Output: {analysis.suggested_guidance}\u0026#34;) # Trigger haptic or audio feedback mm.voice_engine.speak(analysis.suggested_guidance) # Connect to the local camera/mic stream mm.stream_connect(on_frame=on_video_frame) Why Developers Need to Care Context is King: Text-only apps are starting to feel \u0026ldquo;blind.\u0026rdquo; If your app can\u0026rsquo;t \u0026ldquo;see\u0026rdquo; what the user is referring to (e.g., \u0026ldquo;Fix this bug on my screen\u0026rdquo;), it\u0026rsquo;s already behind. Accessibility by Default: Multi-modal isn\u0026rsquo;t a feature for accessibility; it is accessibility. Voice-native apps serve a much wider audience than text-only ones. The Rise of Edge-AI: In 2026, these models are small enough to run on-device. This means low latency and high privacy for vision-based apps. Conclusion The era of the \u0026ldquo;Search Bar\u0026rdquo; is ending. We are entering the era of the \u0026ldquo;Intelligent Observer.\u0026rdquo; As developers, our job is to bridge the gap between digital logic and physical reality using multi-modal models.\nAre you ready to stop typing and start building for eyes and ears?\nChen Kinnrot is a software engineer exploring the intersection of AI and developer productivity.\n","permalink":"https://kinnrot.github.io/multi-modal-ai-beyond-text-2026/","summary":"\u003cp\u003eWhile LLMs changed the world with text, \u003cstrong\u003eMulti-modal AI\u003c/strong\u003e is changing how we interact with the physical world. In 2026, we\u0026rsquo;ve moved past \u0026ldquo;GPT-4o style\u0026rdquo; multimodal inputs toward deep, integrated reasoning across vision, voice, and even spatial data.\u003c/p\u003e\n\u003cp\u003eDevelopers are no longer just building chatbots; they are building \u0026ldquo;Vision-Native\u0026rdquo; and \u0026ldquo;Voice-First\u0026rdquo; applications that understand context as humans do.\u003c/p\u003e\n\u003ch3 id=\"the-shift-to-multi-modal-reasoning\"\u003eThe Shift to Multi-modal Reasoning\u003c/h3\u003e\n\u003cp\u003eIn the early 2020s, multi-modal was often a series of \u0026ldquo;converters\u0026rdquo;—speech-to-text, then text-to-LLM, then text-to-speech. Today, we use single models with unified token spaces. This reduces latency and, more importantly, preserves the \u003cem\u003enuance\u003c/em\u003e lost in transcription.\u003c/p\u003e","title":"Multi-modal AI: Beyond Text - Building with Vision and Voice in 2026"},{"content":"If 2023 was the year of the Chatbot and 2024 was the year of RAG (Retrieval-Augmented Generation), then 2026 is officially the year of Agentic AI.\nWe’ve moved past the novelty of \u0026ldquo;talking to a document.\u0026rdquo; Today’s developers aren\u0026rsquo;t just building interfaces for LLMs; they are building autonomous systems capable of planning, executing, and correcting their own workflows. We are shifting from Generative AI to Agentic AI.\nWhat Makes an AI \u0026ldquo;Agentic\u0026rdquo;? An agent isn\u0026rsquo;t just a wrapper around an LLM. To be truly agentic, a system needs three core capabilities:\nReasoning and Planning: The ability to break down a complex goal (e.g., \u0026ldquo;Research the competitor\u0026rsquo;s pricing and write a summary\u0026rdquo;) into smaller, executable steps. Tool Use: The ability to interact with the real world—searching the web, executing code, calling APIs, or querying databases. Self-Correction (Reflection): The ability to look at its own output or a tool\u0026rsquo;s error and iterate until the goal is achieved. The 2026 Tech Stack: Orchestration Over Prompting In 2026, the focus has shifted from \u0026ldquo;prompt engineering\u0026rdquo; to \u0026ldquo;orchestration.\u0026rdquo; Frameworks like LangGraph, CrewAI, and AutoGPT-Next have matured into the standard library for AI-native development.\nLet’s look at how you might build a simple autonomous research agent using a modern orchestration pattern (pseudo-code inspired by LangGraph\u0026rsquo;s evolution).\nCode Example: A Self-Correcting Research Agent In this example, we define a graph where an agent can \u0026ldquo;Research\u0026rdquo; and then a \u0026ldquo;Reviewer\u0026rdquo; can send it back if the quality isn\u0026rsquo;t high enough.\nfrom langgraph.graph import StateGraph, END from typing import TypedDict, List # 1. Define the state of our agentic workflow class AgentState(TypedDict): task: str report: str review_feedback: str iterations: int # 2. Define the \u0026#34;Research\u0026#34; node def research_node(state: AgentState): print(f\u0026#34;--- Researching: {state[\u0026#39;task\u0026#39;]} ---\u0026#34;) # In a real app, this calls an LLM with search tools return {\u0026#34;report\u0026#34;: \u0026#34;Draft report content...\u0026#34;, \u0026#34;iterations\u0026#34;: state[\u0026#39;iterations\u0026#39;] + 1} # 3. Define the \u0026#34;Review\u0026#34; node def review_node(state: AgentState): print(\u0026#34;--- Reviewing Report ---\u0026#34;) if \u0026#34;data\u0026#34; not in state[\u0026#39;report\u0026#39;]: return {\u0026#34;review_feedback\u0026#34;: \u0026#34;Please include more hard data.\u0026#34;} return {\u0026#34;review_feedback\u0026#34;: \u0026#34;approved\u0026#34;} # 4. Orchestrate the Graph workflow = StateGraph(AgentState) workflow.add_node(\u0026#34;researcher\u0026#34;, research_node) workflow.add_node(\u0026#34;reviewer\u0026#34;, review_node) workflow.set_entry_point(\u0026#34;researcher\u0026#34;) # Logic: If feedback is \u0026#39;approved\u0026#39;, we finish. Otherwise, go back to researcher. def should_continue(state): if state[\u0026#34;review_feedback\u0026#34;] == \u0026#34;approved\u0026#34; or state[\u0026#34;iterations\u0026#34;] \u0026gt; 3: return END return \u0026#34;researcher\u0026#34; workflow.add_edge(\u0026#34;researcher\u0026#34;, \u0026#34;reviewer\u0026#34;) workflow.add_conditional_edges(\u0026#34;reviewer\u0026#34;, should_continue) app = workflow.compile() # Run the autonomous agent final_state = app.invoke({\u0026#34;task\u0026#34;: \u0026#34;Analyze 2026 AI market trends\u0026#34;, \u0026#34;iterations\u0026#34;: 0}) print(final_state[\u0026#39;report\u0026#39;]) Why This Matters for Developers This shift means we are spending less time writing if/else logic and more time defining State, Nodes, and Edges. We are becoming \u0026ldquo;AI Architects.\u0026rdquo;\nAs agents become more reliable, the \u0026ldquo;Human-in-the-Loop\u0026rdquo; (HITL) pattern is evolving. Instead of approving every step, we are moving toward \u0026ldquo;Human-on-the-Loop,\u0026rdquo; where we monitor autonomous workflows and only intervene when the agent hits a high-uncertainty threshold.\nConclusion Agentic AI is more than a trend; it\u0026rsquo;s a fundamental change in how software works. By giving LLMs the power to act and reflect, we are creating tools that don\u0026rsquo;t just help us work—they work with us.\nAre you building agents yet? If not, 2026 is the perfect time to start.\nChen Kinnrot is a software engineer exploring the intersection of AI and developer productivity.\n","permalink":"https://kinnrot.github.io/rise-of-agentic-ai-2026/","summary":"\u003cp\u003eIf 2023 was the year of the Chatbot and 2024 was the year of RAG (Retrieval-Augmented Generation), then 2026 is officially the year of \u003cstrong\u003eAgentic AI\u003c/strong\u003e.\u003c/p\u003e\n\u003cp\u003eWe’ve moved past the novelty of \u0026ldquo;talking to a document.\u0026rdquo; Today’s developers aren\u0026rsquo;t just building interfaces for LLMs; they are building autonomous systems capable of planning, executing, and correcting their own workflows. We are shifting from \u003cem\u003eGenerative AI\u003c/em\u003e to \u003cem\u003eAgentic AI\u003c/em\u003e.\u003c/p\u003e\n\u003ch3 id=\"what-makes-an-ai-agentic\"\u003eWhat Makes an AI \u0026ldquo;Agentic\u0026rdquo;?\u003c/h3\u003e\n\u003cp\u003eAn agent isn\u0026rsquo;t just a wrapper around an LLM. To be truly agentic, a system needs three core capabilities:\u003c/p\u003e","title":"The Rise of Agentic AI: Building Autonomous Workflows in 2026"},{"content":"The world of AI agents is exploding, and while frameworks like LangChain and AutoGen have been dominating the conversation, there\u0026rsquo;s a new player in town that\u0026rsquo;s worth your attention: Strands Agents.\nStrands Agents is an open-source framework developed by AWS, designed to help developers build production-ready, multi-agent AI systems with minimal code. Unlike some heavier frameworks, Strands focuses on providing simple primitives for complex orchestration patterns like handoffs, swarms, and graph workflows.\nIn this post, we\u0026rsquo;ll walk through what makes Strands special and how to get your first agent running in minutes.\nWhy Strands Agents? While you can build agents with just raw LLM calls, things get messy quickly when you need multiple agents to coordinate. Strands solves this by offering:\nModel-Driven Orchestration: Agents decide how to interact based on the model\u0026rsquo;s reasoning capabilities. Model Agnostic: While it integrates seamlessly with Amazon Bedrock, it supports other providers like OpenAI and Anthropic. Type Safety: If you are using the TypeScript SDK, you get first-class type support. The Python SDK is equally robust. Installation Getting started is straightforward. We\u0026rsquo;ll use the Python SDK for this guide.\nFirst, ensure you have Python 3.10+ installed. Then, install the core package and standard tools:\npip install strands-agents strands-agents-tools Your First Agent: Hello World Let\u0026rsquo;s build a simple agent that can perform a basic task. We\u0026rsquo;ll define a tool and give it to an agent.\nCreate a file named agent.py:\nfrom strands import Agent, tool # 1. Define a tool @tool def word_count(text: str) -\u0026gt; int: \u0026#34;\u0026#34;\u0026#34;Count words in text. Useful for checking length constraints.\u0026#34;\u0026#34;\u0026#34; return len(text.split()) # 2. Initialize the Agent # Note: Ensure you have your AWS credentials or other provider API keys configured. # By default, Strands looks for Amazon Bedrock configuration. agent = Agent( name=\u0026#34;Editor\u0026#34;, instructions=\u0026#34;You are a helpful editor. Use tools to analyze text.\u0026#34;, tools=[word_count] ) # 3. Run the agent response = agent(\u0026#34;How many words are in this sentence?\u0026#34;) print(response) Running the Code Before running the script, make sure you have your model provider configured. If you are using AWS Bedrock (the default), you\u0026rsquo;ll need standard AWS credentials set up in your environment.\npython agent.py The agent will analyze your prompt, realize it needs to count words, call the word_count tool, and return the result naturally.\nNext Steps This is just the tip of the iceberg. Strands Agents really shines when you have multiple agents interacting—for example, a \u0026ldquo;Researcher\u0026rdquo; agent handing off findings to a \u0026ldquo;Writer\u0026rdquo; agent.\nIf you are looking to build scalable AI systems on AWS, Strands is definitely a framework to keep on your radar.\nCheck out the official documentation for more advanced patterns and examples.\n","permalink":"https://kinnrot.github.io/getting-started-with-strands-agents/","summary":"\u003cp\u003eThe world of AI agents is exploding, and while frameworks like LangChain and AutoGen have been dominating the conversation, there\u0026rsquo;s a new player in town that\u0026rsquo;s worth your attention: \u003cstrong\u003eStrands Agents\u003c/strong\u003e.\u003c/p\u003e\n\u003cp\u003eStrands Agents is an open-source framework developed by AWS, designed to help developers build production-ready, multi-agent AI systems with minimal code. Unlike some heavier frameworks, Strands focuses on providing simple primitives for complex orchestration patterns like handoffs, swarms, and graph workflows.\u003c/p\u003e","title":"Getting Started with Strands Agents: Build Multi-Agent AI on AWS"},{"content":"For many, AWS is synonymous with \u0026ldquo;cloud.\u0026rdquo; If you are building a serious business around your AI agents, or if you simply want to integrate OpenClaw with other AWS services like S3 (for storage) or Lambda (for serverless functions), running on EC2 is the logical step.\nHere is how to deploy OpenClaw on an Amazon EC2 instance.\n1. Launching the Instance Log in to the AWS Console. Navigate to EC2 -\u0026gt; Launch Instance. Name: OpenClaw-Agent-01. AMI: Ubuntu Server 24.04 LTS (HVM), SSD Volume Type. Instance Type: t3.small. Why? The t3.micro only has 1GB RAM, which can be tight. t3.small gives you 2GB RAM and 2 vCPUs, which is much safer for production. Key Pair: Create a new key pair (openclaw-key) and download the .pem file. 2. Security Groups (The Firewall) AWS blocks everything by default. You need to open ports.\nCreate a security group. Allow SSH (Port 22) from My IP. If OpenClaw has a web interface you want to access, allow HTTP (80) or the specific port (e.g., 3000) from your IP. 3. Connecting Move your key to a secure folder and change permissions:\nchmod 400 openclaw-key.pem ssh -i \u0026#34;openclaw-key.pem\u0026#34; ubuntu@\u0026lt;your-ec2-public-dns\u0026gt; 4. Installation The standard installation applies here.\nsudo apt update sudo apt install git -y # Install Node.js curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - sudo apt install -y nodejs # Clone OpenClaw git clone https://github.com/openclaw/openclaw.git cd openclaw npm install 5. Integration with AWS Services The real power of using AWS is integration. You can configure OpenClaw to save its logs or \u0026ldquo;memories\u0026rdquo; directly to an S3 bucket instead of the local disk.\nTo do this:\nCreate an IAM Role with AmazonS3FullAccess (or a more scoped policy). Attach this IAM Role to your EC2 instance. Install the AWS SDK in your OpenClaw project (npm install @aws-sdk/client-s3) if you are writing custom plugins. By running on AWS, you\u0026rsquo;re ready to scale from one agent to a thousand.\n","permalink":"https://kinnrot.github.io/enterprise-openclaw-aws-ec2/","summary":"\u003cp\u003eFor many, \u003cstrong\u003eAWS\u003c/strong\u003e is synonymous with \u0026ldquo;cloud.\u0026rdquo; If you are building a serious business around your AI agents, or if you simply want to integrate \u003cstrong\u003eOpenClaw\u003c/strong\u003e with other AWS services like S3 (for storage) or Lambda (for serverless functions), running on EC2 is the logical step.\u003c/p\u003e\n\u003cp\u003eHere is how to deploy OpenClaw on an Amazon EC2 instance.\u003c/p\u003e\n\u003ch3 id=\"1-launching-the-instance\"\u003e1. Launching the Instance\u003c/h3\u003e\n\u003col\u003e\n\u003cli\u003eLog in to the \u003ca href=\"https://aws.amazon.com/?utm_source=kinnrot_blog\"\u003eAWS Console\u003c/a\u003e.\u003c/li\u003e\n\u003cli\u003eNavigate to \u003cstrong\u003eEC2\u003c/strong\u003e -\u0026gt; \u003cstrong\u003eLaunch Instance\u003c/strong\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eName:\u003c/strong\u003e \u003ccode\u003eOpenClaw-Agent-01\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAMI:\u003c/strong\u003e Ubuntu Server 24.04 LTS (HVM), SSD Volume Type.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eInstance Type:\u003c/strong\u003e \u003ccode\u003et3.small\u003c/code\u003e.\n\u003cul\u003e\n\u003cli\u003e\u003cem\u003eWhy?\u003c/em\u003e The \u003ccode\u003et3.micro\u003c/code\u003e only has 1GB RAM, which can be tight. \u003ccode\u003et3.small\u003c/code\u003e gives you 2GB RAM and 2 vCPUs, which is much safer for production.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eKey Pair:\u003c/strong\u003e Create a new key pair (\u003ccode\u003eopenclaw-key\u003c/code\u003e) and download the \u003ccode\u003e.pem\u003c/code\u003e file.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch3 id=\"2-security-groups-the-firewall\"\u003e2. Security Groups (The Firewall)\u003c/h3\u003e\n\u003cp\u003eAWS blocks everything by default. You need to open ports.\u003c/p\u003e","title":"Enterprise OpenClaw: Setting up on AWS EC2"},{"content":"Linode (now part of Akamai) has maintained its reputation as the \u0026ldquo;developer\u0026rsquo;s cloud.\u0026rdquo; It doesn\u0026rsquo;t have the flashy UI of some competitors, but it offers rock-solid reliability, excellent documentation, and a great CLI.\nIf you prefer managing your OpenClaw infrastructure with precision, Linode is a great home for it.\nThe Linode Setup Sign up at Linode. Create Linode: Distro: Ubuntu 24.04 LTS. Region: Select one close to you. Plan: Shared CPU -\u0026gt; Nanode 1GB (good for testing) or Linode 2GB (recommended for production). Using StackScripts (Optional) One of Linode\u0026rsquo;s coolest features is StackScripts. You can write a script that runs automatically upon deployment.\nHere is a simple StackScript you can use to deploy OpenClaw automatically:\n#!/bin/bash # \u0026lt;UDF name=\u0026#34;openclaw_repo\u0026#34; label=\u0026#34;OpenClaw Git Repo\u0026#34; default=\u0026#34;https://github.com/openclaw/openclaw.git\u0026#34; /\u0026gt; # Update system apt-get update \u0026amp;\u0026amp; apt-get upgrade -y # Install Node.js curl -fsSL https://deb.nodesource.com/setup_22.x | bash - apt-get install -y nodejs git build-essential # Clone Repo git clone $OPENCLAW_REPO /opt/openclaw cd /opt/openclaw # Install Dependencies npm install # Setup PM2 npm install -g pm2 pm2 start index.js --name openclaw pm2 save Using this script means your server is ready the moment it boots up!\nManual Installation If you prefer the manual route:\nSSH into your Linode. Install npm and node. Clone the repository. Run npm install and npm start. Monitoring Linode\u0026rsquo;s \u0026ldquo;Longview\u0026rdquo; is a great tool for monitoring your system\u0026rsquo;s health. Since OpenClaw can be CPU-intensive during inference (if using local models) or heavy on network (if browsing the web), keeping an eye on these metrics via Longview helps you know when it\u0026rsquo;s time to upgrade your plan.\n","permalink":"https://kinnrot.github.io/deploy-openclaw-linode/","summary":"\u003cp\u003e\u003cstrong\u003eLinode\u003c/strong\u003e (now part of Akamai) has maintained its reputation as the \u0026ldquo;developer\u0026rsquo;s cloud.\u0026rdquo; It doesn\u0026rsquo;t have the flashy UI of some competitors, but it offers rock-solid reliability, excellent documentation, and a great CLI.\u003c/p\u003e\n\u003cp\u003eIf you prefer managing your \u003cstrong\u003eOpenClaw\u003c/strong\u003e infrastructure with precision, Linode is a great home for it.\u003c/p\u003e\n\u003ch3 id=\"the-linode-setup\"\u003eThe Linode Setup\u003c/h3\u003e\n\u003col\u003e\n\u003cli\u003eSign up at \u003ca href=\"https://www.linode.com/?utm_source=kinnrot_blog\"\u003eLinode\u003c/a\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eCreate Linode:\u003c/strong\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eDistro:\u003c/strong\u003e Ubuntu 24.04 LTS.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eRegion:\u003c/strong\u003e Select one close to you.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePlan:\u003c/strong\u003e Shared CPU -\u0026gt; \u003cstrong\u003eNanode 1GB\u003c/strong\u003e (good for testing) or \u003cstrong\u003eLinode 2GB\u003c/strong\u003e (recommended for production).\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch3 id=\"using-stackscripts-optional\"\u003eUsing StackScripts (Optional)\u003c/h3\u003e\n\u003cp\u003eOne of Linode\u0026rsquo;s coolest features is StackScripts. You can write a script that runs automatically upon deployment.\u003c/p\u003e","title":"Deploying OpenClaw on Linode: A Developer's Walkthrough"},{"content":"Let\u0026rsquo;s be honest: cloud costs add up. If you are running multiple AI agents or just want to experiment with OpenClaw without a monthly bill that hurts, Hetzner is the answer.\nKnown for their incredible price-to-performance ratio, specifically with their new ARM64 instances, Hetzner is a favorite among the self-hosting community.\nARM64: The Secret Weapon OpenClaw, being a Node.js application, runs natively on ARM architecture (like the chip in your MacBook or Raspberry Pi). Hetzner\u0026rsquo;s ARM instances are often cheaper and faster than their x86 equivalents.\nGetting Started on Hetzner Cloud Go to Hetzner Cloud. Create a Project. Add Server: Location: Falkenstein or Nuremberg (Germany), or Ashburn (USA). Image: Ubuntu 24.04. Type: Shared vCPU (ARM64) -\u0026gt; CAX11 (2 vCPU, 4GB RAM). Price: This CAX11 instance usually costs less than a cup of coffee per month and is more than powerful enough for OpenClaw. Setting Up the Server The setup on ARM is identical to x86 for Node.js apps.\nssh root@\u0026lt;your-ip\u0026gt; Install Dependencies:\napt update \u0026amp;\u0026amp; apt install -y git Install Node.js:\n# Verify you are getting the ARM64 version automatically curl -fsSL https://deb.nodesource.com/setup_22.x | bash - apt install -y nodejs Clone OpenClaw:\ngit clone https://github.com/openclaw/openclaw.git cd openclaw npm install Why Hetzner? The CAX11 instance gives you 4GB of RAM. Compare this to DigitalOcean or Vultr, where the entry-level price often gets you only 1GB. For an AI agent that might need to hold large conversation contexts in memory, that extra RAM is a game-changer for stability.\nDisclaimer: I am not responsible for how much time you spend tweaking your new affordable server fleet!\n","permalink":"https://kinnrot.github.io/self-hosting-openclaw-hetzner/","summary":"\u003cp\u003eLet\u0026rsquo;s be honest: cloud costs add up. If you are running multiple AI agents or just want to experiment with \u003cstrong\u003eOpenClaw\u003c/strong\u003e without a monthly bill that hurts, \u003cstrong\u003eHetzner\u003c/strong\u003e is the answer.\u003c/p\u003e\n\u003cp\u003eKnown for their incredible price-to-performance ratio, specifically with their new ARM64 instances, Hetzner is a favorite among the self-hosting community.\u003c/p\u003e\n\u003ch3 id=\"arm64-the-secret-weapon\"\u003eARM64: The Secret Weapon\u003c/h3\u003e\n\u003cp\u003eOpenClaw, being a Node.js application, runs natively on ARM architecture (like the chip in your MacBook or Raspberry Pi). Hetzner\u0026rsquo;s ARM instances are often cheaper and faster than their x86 equivalents.\u003c/p\u003e","title":"The Budget Guide: Self-Hosting OpenClaw on Hetzner"},{"content":"When latency matters, Vultr is the cloud provider to beat. Their High Frequency Compute instances are powered by high clock speed CPUs and NVMe storage, making them significantly snappier for IO-heavy operations.\nFor an AI agent like OpenClaw, which might be scraping web pages or processing large context files, this speed difference is noticeable.\nWhy Vultr for OpenClaw? 32+ Locations: Put your agent geographically close to the services it interacts with. NVMe Storage: Faster database reads/writes for your agent\u0026rsquo;s long-term memory. Simple Pricing: You know exactly what you\u0026rsquo;re paying. Step-by-Step Setup Sign Up: Create an account at Vultr. Deploy Instance: Select Cloud Compute -\u0026gt; High Frequency. Server Location: Pick your preferred region. Server Type: Ubuntu 24.04 LTS. Server Size: The 32GB NVMe / 1 vCPU / 1GB Memory plan is often sufficient, but the 2GB Memory plan is safer for stability. Installation Quick-Start Once your instance is live, the process is similar to other Linux environments.\n1. Prepare the environment:\napt update apt install -y git curl build-essential 2. Install Node.js (via NodeSource):\ncurl -fsSL https://deb.nodesource.com/setup_22.x | bash - apt-get install -y nodejs 3. Deploy OpenClaw:\ngit clone https://github.com/openclaw/openclaw.git cd openclaw npm ci 4. Start the Agent: Edit your configuration file:\nnano config.yaml # or .env depending on your version Run it:\nnpm start Pro Tip: Snapshot Backups Vultr makes it incredibly easy to take snapshots. Once you have your OpenClaw configured perfectly (with all your prompts and memory settings), take a snapshot. This allows you to spin up clones or restore your agent instantly if something goes wrong.\n","permalink":"https://kinnrot.github.io/run-openclaw-vultr-performance/","summary":"\u003cp\u003eWhen latency matters, \u003cstrong\u003eVultr\u003c/strong\u003e is the cloud provider to beat. Their High Frequency Compute instances are powered by high clock speed CPUs and NVMe storage, making them significantly snappier for IO-heavy operations.\u003c/p\u003e\n\u003cp\u003eFor an AI agent like OpenClaw, which might be scraping web pages or processing large context files, this speed difference is noticeable.\u003c/p\u003e\n\u003ch3 id=\"why-vultr-for-openclaw\"\u003eWhy Vultr for OpenClaw?\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003e32+ Locations:\u003c/strong\u003e Put your agent geographically close to the services it interacts with.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eNVMe Storage:\u003c/strong\u003e Faster database reads/writes for your agent\u0026rsquo;s long-term memory.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSimple Pricing:\u003c/strong\u003e You know exactly what you\u0026rsquo;re paying.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"step-by-step-setup\"\u003eStep-by-Step Setup\u003c/h3\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eSign Up:\u003c/strong\u003e Create an account at \u003ca href=\"https://www.vultr.com/?utm_source=kinnrot_blog\"\u003eVultr\u003c/a\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDeploy Instance:\u003c/strong\u003e Select \u003cstrong\u003eCloud Compute\u003c/strong\u003e -\u0026gt; \u003cstrong\u003eHigh Frequency\u003c/strong\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eServer Location:\u003c/strong\u003e Pick your preferred region.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eServer Type:\u003c/strong\u003e \u003cstrong\u003eUbuntu 24.04 LTS\u003c/strong\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eServer Size:\u003c/strong\u003e The \u003cstrong\u003e32GB NVMe / 1 vCPU / 1GB Memory\u003c/strong\u003e plan is often sufficient, but the \u003cstrong\u003e2GB Memory\u003c/strong\u003e plan is safer for stability.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch3 id=\"installation-quick-start\"\u003eInstallation Quick-Start\u003c/h3\u003e\n\u003cp\u003eOnce your instance is live, the process is similar to other Linux environments.\u003c/p\u003e","title":"How to Run OpenClaw on Vultr for High-Frequency Performance"},{"content":"DigitalOcean is often the first stop for developers wanting to self-host tools because of its simplicity. If you\u0026rsquo;re looking to get your OpenClaw AI agent running 24/7 without breaking the bank, a DigitalOcean Droplet is a fantastic choice.\nHere is a comprehensive guide to getting started.\n1. Create a Droplet Log in to your DigitalOcean account. Click Create -\u0026gt; Droplets. Region: Choose the datacenter closest to you or your target audience. OS: Ubuntu 24.04 LTS is the standard recommendation. Size: OpenClaw is reasonably lightweight. The Basic plan with 2GB RAM / 1 CPU is the sweet spot. You might get away with 1GB, but 2GB ensures your agent doesn\u0026rsquo;t crash during memory-intensive tasks. Authentication: Upload your SSH Key. Never use a password for a public server. 2. Initial Server Setup SSH into your new droplet:\nssh root@your_droplet_ip Update the package lists:\napt update \u0026amp;\u0026amp; apt upgrade -y 3. Install Node.js OpenClaw relies on a modern Node.js environment. We\u0026rsquo;ll use nvm (Node Version Manager) to install it.\ncurl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash source ~/.bashrc nvm install 22 nvm use 22 4. Clone and Configure OpenClaw Now, let\u0026rsquo;s grab the code.\ngit clone https://github.com/openclaw/openclaw.git cd openclaw npm install Note: You\u0026rsquo;ll need to configure your .env file with your API keys (Anthropic, OpenAI, etc.) and your desired settings. Copy the example file to start:\ncp .env.example .env nano .env 5. Keep it Running with PM2 You don\u0026rsquo;t want your agent to die if you close your SSH session. Use PM2 to manage the process.\nnpm install -g pm2 pm2 start index.js --name \u0026#34;openclaw\u0026#34; pm2 save pm2 startup And that\u0026rsquo;s it! Your OpenClaw agent is now alive and running in the cloud.\n","permalink":"https://kinnrot.github.io/deploy-openclaw-digitalocean-guide/","summary":"\u003cp\u003eDigitalOcean is often the first stop for developers wanting to self-host tools because of its simplicity. If you\u0026rsquo;re looking to get your \u003cstrong\u003eOpenClaw\u003c/strong\u003e AI agent running 24/7 without breaking the bank, a DigitalOcean Droplet is a fantastic choice.\u003c/p\u003e\n\u003cp\u003eHere is a comprehensive guide to getting started.\u003c/p\u003e\n\u003ch3 id=\"1-create-a-droplet\"\u003e1. Create a Droplet\u003c/h3\u003e\n\u003col\u003e\n\u003cli\u003eLog in to your \u003ca href=\"https://www.digitalocean.com/?utm_source=kinnrot_blog\"\u003eDigitalOcean account\u003c/a\u003e.\u003c/li\u003e\n\u003cli\u003eClick \u003cstrong\u003eCreate\u003c/strong\u003e -\u0026gt; \u003cstrong\u003eDroplets\u003c/strong\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eRegion:\u003c/strong\u003e Choose the datacenter closest to you or your target audience.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOS:\u003c/strong\u003e Ubuntu 24.04 LTS is the standard recommendation.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSize:\u003c/strong\u003e OpenClaw is reasonably lightweight. The \u003cstrong\u003eBasic\u003c/strong\u003e plan with \u003cstrong\u003e2GB RAM / 1 CPU\u003c/strong\u003e is the sweet spot. You might get away with 1GB, but 2GB ensures your agent doesn\u0026rsquo;t crash during memory-intensive tasks.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAuthentication:\u003c/strong\u003e Upload your SSH Key. \u003cem\u003eNever\u003c/em\u003e use a password for a public server.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch3 id=\"2-initial-server-setup\"\u003e2. Initial Server Setup\u003c/h3\u003e\n\u003cp\u003eSSH into your new droplet:\u003c/p\u003e","title":"Step-by-Step Guide: Deploying OpenClaw on DigitalOcean"},{"content":"If you\u0026rsquo;ve been following the AI agent space lately, you know that OpenClaw (the project formerly known as Clawdbot and briefly Moltbot) has become the gold standard for self-hosted autonomous assistants.\nWhile running it on your local machine is great for testing, the real power of OpenClaw comes when it\u0026rsquo;s running 24/7 in the cloud. Whether it\u0026rsquo;s managing your WhatsApp messages while you sleep or executing long-running web automations, a cloud VPS is the way to go.\nAfter testing various providers, here are the top 5 ways to run OpenClaw in the cloud right now.\n1. DigitalOcean: The Reliable Choice DigitalOcean remains the favorite for many developers. Their \u0026ldquo;Droplets\u0026rdquo; are incredibly easy to set up, and their documentation is second to none. For OpenClaw, a basic 2GB RAM droplet is usually enough to keep things snappy.\nBest for: Beginners and those who want a \u0026ldquo;set it and forget it\u0026rdquo; experience. Link: DigitalOcean 2. Vultr: Global Performance Vultr offers an impressive array of locations. If you need your OpenClaw agent to have low latency to a specific region, Vultr is likely your best bet. Their high-frequency compute instances are overkill for OpenClaw but make the web browsing features feel instantaneous.\nBest for: Users needing specific geographic locations. Link: Vultr 3. Hetzner: The Value King If you are in Europe or the US and want the most \u0026ldquo;bang for your buck,\u0026rdquo; Hetzner is unbeatable. Their ARM64 cloud instances are dirt cheap and perform remarkably well with OpenClaw’s Node-based architecture.\nBest for: Budget-conscious power users. Link: Hetzner 4. Linode (Akamai): The Developer\u0026rsquo;s Choice Now part of Akamai, Linode continues to offer stellar support and reliable hardware. Their CLI tool makes deploying OpenClaw instances across multiple regions a breeze for those who love the terminal.\nBest for: Developers who prefer a clean, no-nonsense interface. Link: Linode 5. AWS: Enterprise-Grade Scalability For those who want to integrate OpenClaw into a larger ecosystem, AWS (Amazon Web Services) is the natural choice. Using an EC2 t3.small instance gives you access to the entire AWS suite of tools for monitoring and scaling.\nBest for: Users who already live in the AWS ecosystem. Link: AWS How to choose? If you\u0026rsquo;re just starting, go with DigitalOcean. If you want the cheapest reliable option, Hetzner is your friend.\nRegardless of which one you pick, getting OpenClaw off your local machine and into the cloud is the first step toward true AI autonomy.\n","permalink":"https://kinnrot.github.io/run-openclaw-cloud-2026/","summary":"\u003cp\u003eIf you\u0026rsquo;ve been following the AI agent space lately, you know that \u003cstrong\u003eOpenClaw\u003c/strong\u003e (the project formerly known as Clawdbot and briefly Moltbot) has become the gold standard for self-hosted autonomous assistants.\u003c/p\u003e\n\u003cp\u003eWhile running it on your local machine is great for testing, the real power of OpenClaw comes when it\u0026rsquo;s running 24/7 in the cloud. Whether it\u0026rsquo;s managing your WhatsApp messages while you sleep or executing long-running web automations, a cloud VPS is the way to go.\u003c/p\u003e","title":"The Best Ways to Run OpenClaw in the Cloud (2026 Edition)"},{"content":"As developers, we like to build things. When a product manager or a user asks for a feature, our natural response is \u0026ldquo;Sure, I can do that in two days.\u0026rdquo;\nBut every \u0026ldquo;Yes\u0026rdquo; is a commitment to maintain that code forever.\nThe Feature Creep Trap The most successful products aren\u0026rsquo;t the ones with the most features; they\u0026rsquo;re the ones with the right features. Every button you add to a UI makes every other button slightly less important. Every branch in your code makes the next bug slightly harder to find.\nWhy \u0026ldquo;No\u0026rdquo; is Hard It feels like you\u0026rsquo;re being unhelpful. It feels like you\u0026rsquo;re being \u0026ldquo;the blocker.\u0026rdquo; But in reality, saying \u0026ldquo;No\u0026rdquo; is how you protect the product\u0026rsquo;s quality and the team\u0026rsquo;s velocity.\nThe \u0026ldquo;Not Now\u0026rdquo; Alternative Instead of a flat \u0026ldquo;No,\u0026rdquo; I try to use:\n\u0026ldquo;What problem are we trying to solve with this?\u0026rdquo; (Often, there\u0026rsquo;s a simpler way). \u0026ldquo;How does this align with our goals for this quarter?\u0026rdquo; \u0026ldquo;We can do this, but which of these other three features should we drop to make room?\u0026rdquo; Build Less, Better Next time you\u0026rsquo;re asked for a minor tweak that \u0026ldquo;won\u0026rsquo;t take long,\u0026rdquo; ask yourself: \u0026ldquo;Will this still be valuable in a year? Or is it just noise?\u0026rdquo;\nBe a builder, but also be a curator. Your codebase will thank you.\n","permalink":"https://kinnrot.github.io/art-of-saying-no-features/","summary":"\u003cp\u003eAs developers, we like to build things. When a product manager or a user asks for a feature, our natural response is \u0026ldquo;Sure, I can do that in two days.\u0026rdquo;\u003c/p\u003e\n\u003cp\u003eBut every \u0026ldquo;Yes\u0026rdquo; is a commitment to maintain that code forever.\u003c/p\u003e\n\u003ch3 id=\"the-feature-creep-trap\"\u003eThe Feature Creep Trap\u003c/h3\u003e\n\u003cp\u003eThe most successful products aren\u0026rsquo;t the ones with the \u003cem\u003emost\u003c/em\u003e features; they\u0026rsquo;re the ones with the \u003cem\u003eright\u003c/em\u003e features. Every button you add to a UI makes every other button slightly less important. Every branch in your code makes the next bug slightly harder to find.\u003c/p\u003e","title":"The Art of Saying 'No' to a Feature"},{"content":"I see many teams claim they have \u0026ldquo;CI/CD\u0026rdquo; because they have a Jenkins or GitHub Actions pipeline that runs tests. But if your process involves a \u0026ldquo;Freeze Week\u0026rdquo; or a \u0026ldquo;Manual QA Sign-off\u0026rdquo; that takes 3 days, you don\u0026rsquo;t have CI/CD. You have an automated build process.\nThe Goal: Confidence The goal of CI/CD isn\u0026rsquo;t to run scripts. It\u0026rsquo;s to give the team enough confidence that a commit can go to production without human intervention.\nThe \u0026ldquo;Scary\u0026rdquo; Deploy If deploying to production is a \u0026ldquo;scary\u0026rdquo; event that requires everyone to be on a Zoom call, your feedback loop is broken. Deploys should be boring. So boring that they happen 10 times a day and nobody notices.\nHow to get there? Automated Testing (The real kind): Not just unit tests. You need integration tests and \u0026ldquo;smoke tests\u0026rdquo; that run against a real-ish environment. Feature Flags: This is the secret sauce. Separate Deployment from Release. Deploy the code behind a flag, then turn it on for 1% of users. If the errors don\u0026rsquo;t spike, go to 10%. Small PRs: If a PR has +2,000 lines, nobody is actually reviewing it. They\u0026rsquo;re just LGTM-ing it because they\u0026rsquo;re tired. Small PRs = fast reviews = fast CI. Continuous is a Mindset It\u0026rsquo;s not about the tools you use. It\u0026rsquo;s about the trust you have in your automated systems. If you can\u0026rsquo;t trust your tests to catch a breaking change, don\u0026rsquo;t fix the pipeline—fix the tests.\nStop the \u0026ldquo;deploy trains\u0026rdquo; and start the continuous flow.\n","permalink":"https://kinnrot.github.io/is-your-cicd-actually-continuous/","summary":"\u003cp\u003eI see many teams claim they have \u0026ldquo;CI/CD\u0026rdquo; because they have a Jenkins or GitHub Actions pipeline that runs tests. But if your process involves a \u0026ldquo;Freeze Week\u0026rdquo; or a \u0026ldquo;Manual QA Sign-off\u0026rdquo; that takes 3 days, you don\u0026rsquo;t have CI/CD. You have an automated build process.\u003c/p\u003e\n\u003ch3 id=\"the-goal-confidence\"\u003eThe Goal: Confidence\u003c/h3\u003e\n\u003cp\u003eThe goal of CI/CD isn\u0026rsquo;t to run scripts. It\u0026rsquo;s to give the team enough \u003cstrong\u003econfidence\u003c/strong\u003e that a commit can go to production without human intervention.\u003c/p\u003e","title":"Is Your CI/CD Actually Continuous?"},{"content":"Looking back at the XML days of Android development feels like looking at black-and-white television. It worked, but boy, was it clunky.\nToday, in 2026, Jetpack Compose isn\u0026rsquo;t just \u0026ldquo;the new way\u0026rdquo;—it\u0026rsquo;s the only way that makes sense for modern Android apps.\nDeclarative is King The shift from imperative (\u0026ldquo;find this view and set its text\u0026rdquo;) to declarative (\u0026ldquo;here is the state, describe how it looks\u0026rdquo;) has probably saved me thousands of hours of debugging weird UI states. No more null view references. No more findViewById.\nPerformance? Early on, people complained about Compose\u0026rsquo;s performance on low-end devices. In 2026, those issues are largely gone. With the latest compiler optimizations and the maturity of the library, the overhead is negligible. Plus, the developer productivity gains far outweigh any minor performance cost.\nThe \u0026ldquo;Preview\u0026rdquo; Feedback Loop My favorite part? The interactive previews. I can see how my component looks in dark mode, on a small screen, and in Hebrew (RTL support!) all at the same time, without even launching the emulator.\n@Preview(showBackground = true, name = \u0026#34;RTL Check\u0026#34;, locale = \u0026#34;iw\u0026#34;) @Composable fun WelcomeScreenPreview() { MyTheme { WelcomeScreen(\u0026#34;שלום עולם\u0026#34;) } } Is it perfect? Not yet. Navigation in Compose is still\u0026hellip; a journey. Every team seems to have their own \u0026ldquo;perfect\u0026rdquo; wrapper around the official Navigation library. But compared to the Fragment-Hell of 2018, I\u0026rsquo;ll take it any day.\nIf you\u0026rsquo;re still holding onto XML layouts, it\u0026rsquo;s time to let go. The water is fine.\n","permalink":"https://kinnrot.github.io/android-compose-2026/","summary":"\u003cp\u003eLooking back at the XML days of Android development feels like looking at black-and-white television. It worked, but boy, was it clunky.\u003c/p\u003e\n\u003cp\u003eToday, in 2026, Jetpack Compose isn\u0026rsquo;t just \u0026ldquo;the new way\u0026rdquo;—it\u0026rsquo;s the \u003cem\u003eonly\u003c/em\u003e way that makes sense for modern Android apps.\u003c/p\u003e\n\u003ch3 id=\"declarative-is-king\"\u003eDeclarative is King\u003c/h3\u003e\n\u003cp\u003eThe shift from imperative (\u0026ldquo;find this view and set its text\u0026rdquo;) to declarative (\u0026ldquo;here is the state, describe how it looks\u0026rdquo;) has probably saved me thousands of hours of debugging weird UI states. No more \u003ccode\u003enull\u003c/code\u003e view references. No more \u003ccode\u003efindViewById\u003c/code\u003e.\u003c/p\u003e","title":"Android Development: The State of Compose in 2026"},{"content":"\u0026ldquo;Fat models, skinny controllers.\u0026rdquo; That was the mantra for years. But if you\u0026rsquo;ve ever worked on a Rails app that\u0026rsquo;s more than two years old, you know where that leads: a User.rb file that\u0026rsquo;s 2,000 lines long and handles everything from authentication to generating PDF invoices.\nThe Problem with Fat Models When a model knows too much, it becomes impossible to test in isolation. You want to test a simple validation, but you end up triggering five callbacks that send emails and ping Slack hooks.\nEnter Service Objects (and Plain Old Ruby Objects) I prefer keeping my models as thin as possible—ideally just associations and simple validations. For everything else, I use Service Objects.\nInstead of:\n# In the model def register_and_notify save! UserMailer.welcome(self).deliver_later SlackService.notify(\u0026#34;New user: #{email}\u0026#34;) end I do this:\n# In a service object class UserRegistrationService def initialize(params) @params = params end def call user = User.new(@params) if user.save notify_user(user) notify_team(user) end user end private # ... helper methods end Why bother? Testability: I can test the User model without worrying about side effects. I can test the UserRegistrationService by mocking the mailer. Readability: When I open a model, I see what the data is. When I look at the services/ folder, I see what the app does. Reusability: Need to register a user via the API and the Web? Use the same service. Keep your models thin, your services focused, and your sanity intact.\n","permalink":"https://kinnrot.github.io/why-thin-models-rails/","summary":"\u003cp\u003e\u0026ldquo;Fat models, skinny controllers.\u0026rdquo; That was the mantra for years. But if you\u0026rsquo;ve ever worked on a Rails app that\u0026rsquo;s more than two years old, you know where that leads: a \u003ccode\u003eUser.rb\u003c/code\u003e file that\u0026rsquo;s 2,000 lines long and handles everything from authentication to generating PDF invoices.\u003c/p\u003e\n\u003ch3 id=\"the-problem-with-fat-models\"\u003eThe Problem with Fat Models\u003c/h3\u003e\n\u003cp\u003eWhen a model knows too much, it becomes impossible to test in isolation. You want to test a simple validation, but you end up triggering five callbacks that send emails and ping Slack hooks.\u003c/p\u003e","title":"Why I still prefer Thin Models in Rails"},{"content":"We\u0026rsquo;ve all been there. You\u0026rsquo;re working on a feature, and you need to parse some weirdly formatted date or handle a complex file upload. Your first instinct? npm install or bundle add.\nIt feels like winning. Someone else already solved this problem! Why should I reinvent the wheel?\nThe \u0026ldquo;Free\u0026rdquo; Wheel But here\u0026rsquo;s the thing: every dependency you add is a liability. It\u0026rsquo;s code you didn\u0026rsquo;t write, but code you now own. You own its bugs, its security vulnerabilities, and its breaking changes when it decides to \u0026ldquo;improve\u0026rdquo; its API.\nI recently saw a project where a developer added a 2MB library just to capitalize the first letter of a string. Seriously.\nThe Maintenance Tax When you add a dependency, you\u0026rsquo;re not just adding code; you\u0026rsquo;re adding a maintenance tax.\nSecurity: Every week, there\u0026rsquo;s a new CVE. If you have 200 dependencies, you\u0026rsquo;re playing whack-a-mole with security patches. Updates: One library updates and suddenly it\u0026rsquo;s incompatible with another. You spend your Tuesday afternoon fixing a version mismatch instead of shipping features. Bloat: Your build time goes from 30 seconds to 3 minutes. Your feedback loop (remember this post?) starts to crumble. The Rule of Three Before I add a new gem or package, I ask myself:\nCan I write this in 20 lines of vanilla code? Is this core to my business logic? How active is the maintainer? If I can solve it with a small helper class, I do it. It keeps the project lean, the build fast, and my mental model clear.\nDon\u0026rsquo;t be afraid to write code. It\u0026rsquo;s what we\u0026rsquo;re paid for.\n","permalink":"https://kinnrot.github.io/hidden-cost-of-dependencies/","summary":"\u003cp\u003eWe\u0026rsquo;ve all been there. You\u0026rsquo;re working on a feature, and you need to parse some weirdly formatted date or handle a complex file upload. Your first instinct? \u003ccode\u003enpm install\u003c/code\u003e or \u003ccode\u003ebundle add\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eIt feels like winning. Someone else already solved this problem! Why should I reinvent the wheel?\u003c/p\u003e\n\u003ch3 id=\"the-free-wheel\"\u003eThe \u0026ldquo;Free\u0026rdquo; Wheel\u003c/h3\u003e\n\u003cp\u003eBut here\u0026rsquo;s the thing: every dependency you add is a liability. It\u0026rsquo;s code you didn\u0026rsquo;t write, but code you now own. You own its bugs, its security vulnerabilities, and its breaking changes when it decides to \u0026ldquo;improve\u0026rdquo; its API.\u003c/p\u003e","title":"The Hidden Cost of 'Just One More Dependency'"},{"content":"Around 2 years ago, I started a new management gig. it wasn\u0026rsquo;t the first, but it was the first with a relatively large team. One of the most basic things I needed to do as a manager was to bind the team to its mission, and in simple terms: get them super motivated to do their day to day tasks.\nI\u0026rsquo;m a strong preacher for freedom, it gives people a sense of ownership.\nLet\u0026rsquo;s tackle the two edges of freedom:\nNo freedom at all Someone tells you what to do, how to do it, and when to do it.\n\u0026quot; You need to remove some logs related to the checkout process, so please delete lines x and y from file z, make a PR and send it to me \u0026quot;\nWell, this is straight forward, anyone can probably do it, you might think it\u0026rsquo;s a good task for a newcomer. Another perspective is: what message am I sending to this person? This is how it might look from an employee perspective:\n\u0026ldquo;I don\u0026rsquo;t trust your judgment and capabilities, so I\u0026rsquo;m telling you exactly what needs to be done, I don\u0026rsquo;t even bother to give you the bigger context. You probably won\u0026rsquo;t learn anything from this task, but that\u0026rsquo;s the job, and this is what the future looks in this team. I trust you so little I must personally make sure you did it right, so I must review your code.\u0026rdquo;\nSo, as you can see I took it to the extreme, but even if 5% of this thoughts will pop in the employee\u0026rsquo;s mind, it\u0026rsquo;s bad.\nComplete freedom \u0026quot; We\u0026rsquo;re paying too much to our logging storage service \u0026quot;\nThis approach is wide open. no what, when or how, only why. This can go down in one or 2 ways:\nwhen it\u0026rsquo;s a junior developer:\n\u0026ldquo;Ohh sh*t I\u0026rsquo;m clueless, I have no idea what needs to be done, I\u0026rsquo;m too shy to ask anyone anything, this is scary. Why is there no one to guide me?\u0026rdquo;\nwhen it\u0026rsquo;s a senior developer:\n\u0026ldquo;Alright, we\u0026rsquo;ve got a problem, let\u0026rsquo;s solve it. I feel trusted and empowered by my manager to solve problems on my own\u0026rdquo;\n*There\u0026rsquo;s an even higher degree of freedom, one where you don\u0026rsquo;t focus the employee on a specific problem, and let them choose it on their own. This is not an industry standard so I\u0026rsquo;m ignoring it.\nSo, to the point, freedom is awesome, not for everyone and should be dosed right. You\u0026rsquo;re optimizing for independent team members who can do everything. in order to get there, you need to trust them and have high expectations from each team member.\nWith experienced developers it should be relatively easy, just focus on the \u0026ldquo;why\u0026rdquo; and they\u0026rsquo;ll figure out the rest, or ask nudging questions to get more of the \u0026lsquo;what\u0026rsquo;. if it\u0026rsquo;s a feature, a product manager will provide the what. When you focus on the why, you create a strong ownership of the problem. This is good because you never want to get attached to a particular solution, the solution might change tomorrow, it\u0026rsquo;s a fast moving world. However, the problem probably won\u0026rsquo;t change so quickly. When you focus on the why, you give a wider perspective, allowing people to be more creative when it comes to proposing creative solutions. They need to think, and this is exactly why they came to work, and that\u0026rsquo;s why it\u0026rsquo;s so motivating.\nWith less experienced developers, it might be a bit trickier: you want to do the same without getting their frustration level above the tipping point where they feel incapable. You\u0026rsquo;ll need to do some sensing for each task to understand the proper level of freedom that can be given.\nMy recommendation is to start with the why, and start an open discussion about the next steps. Uf things don\u0026rsquo;t evolve, you can push some of the what and how as needed.\n","permalink":"https://kinnrot.github.io/freedom-and-trust/","summary":"\u003cp\u003eAround 2 years ago, I started a new management gig. it wasn\u0026rsquo;t the first, but it was the first with a relatively large team.\nOne of the most basic things I needed to do as a manager was to bind the team to its mission, and in simple terms: get them super motivated to do their day to day tasks.\u003c/p\u003e\n\u003cp\u003eI\u0026rsquo;m a strong preacher for freedom, it gives people a sense of ownership.\u003c/p\u003e","title":"Why focus on why"},{"content":"We all wanna get from 0 to 1 (with many trailing zeros), the sooner the better.\nSo, what\u0026rsquo;s the problem? You build something and you\u0026rsquo;re brave enough to put it out there, now what? Now you start the endless feedback loop cycle, you look at the data, analytics, user recordings, product inputs, and decide what\u0026rsquo;s the next thing that\u0026rsquo;ll make your product better then ever, it\u0026rsquo;s an iterative process that never ends. The faster you iterate, the faster you\u0026rsquo;ll get to your target.\nHow fast can this be done? It depends on so many things, lets try to focus on the dev part, suppose the product is a ninja with an endless queue of things he wants the R\u0026amp;D department to execute, what does it take? what kind of feedback loop do we need as developers?\nThe simplest way to explain what need to be done: \u0026ldquo;Write the correct code, according to product spec, put it on production.\u0026rdquo;\nWriting the correct code - takes time and that\u0026rsquo;s fine, what kind of feedback loop do we have when writing code?\nIt starts with a developer coding on his IDE, gets immediate feedback from it, auto lint/compile issue/warnings etc. This is the most basic and immediate feedback out there, and it should be seamlessly fast (as fast as typing)\nSecond layer of feedback are unit tests, fastest way to run your new code, in a neutral environment allowing to identify and fix issues quickly. This is less basic and immediate, but, an optimal developer experience, allow changing code, running tests almost instantly get results and iterate. In a world of SOA/Micro-services and remote dev environment, this might not be so fast, but it should. Let\u0026rsquo;s take an example, company with 200 great developers, each one constantly coding amazing things, writing tests to make sure their code works, after each test written, developer need to wait 30sec to see the test results, lets say each developer write 20 tests a day. 20X30X200=120K seconds = 33.3 hours, meaning every day, almost 2% of productivity go\u0026rsquo;s on waiting for tests to run. let\u0026rsquo;s continue to the next loop.\nThird layer - running the real product on dev env, mandatory for engineers who make user experience, how much time does it take to make an html/css/js change and see it reflects on the app? it should be instant, if it\u0026rsquo;s 30 sec, we lost another 2% for the waiting, how much time does it take to spin the env? is it fast? stable?\nNote - each time a developer need to wait more then 1 second, she might lose her focus to something else, which is a multiplier for the waiting time, not to mention the frustration when things doesn\u0026rsquo;t work locally.\nForth layer - Pull request, this is an async process, which by definition gets everything stuck, and a time to work on something else. If we need to move super fast, this process should be synchronized, and conducted f2f right after the pr was created, this is also an iterative process, get comment, fix them, re review.\nFifth layer - QA, Again async process, we wanna get here as ready as possible, to avoid another loop, cause cycles are slow here.\nWe just went over 5 layers of feedback loop, from the fastest to slowest. now think about it this way, the more iterations we do on the fast layers (1,2,3) the less chances we\u0026rsquo;ll have many iterations on the slow layers (4-5). To encourage developers to do more iterations, we need a strong infra to allow developers to write and run tests fast, play with their local env, make changes and check them fast. If it\u0026rsquo;s not fast they\u0026rsquo;ll do less iterations, and we\u0026rsquo;ll get to later layers less ready.\nSo in a hypergrowth company, how to maintain fast feedback loop?\nIt should start with observability over the metrics.\nHow much time does it take to run a single test? How much time does it take to spin a new dev env with latest code? How much time does it take to make a code change on dev/staging/production env and see it live? How much time does a pr wait in review on average? Most of the time, when you start, everything is super fast(If you are at the beginning and something is slow, I urge you to stop and optimize), and gradually gets slower and slower, you got chunky modules, more dependencies, files, tooling, scripts and the whole shabang. Keeping things optimal when running fast is almost impossible. At some point you need to stop and think, What feedback cycle is too slow? What can I do about it?\nPossible solution is to have a lab mode where you work in isolation from the entire project, have a thin and lean project that has a shell wrapper that simulates the entire app with stubs.\nAnother one is lot\u0026rsquo;s of separation and decoupling that allows you to work on relatively small parts of the system that can run fast (for example run a test that loads/compiles 15 files of 1 module, instead of all the 3000 files the project need in order to fully run).\nWhat\u0026rsquo;s your feedback loop time? what are you doing to improve it? please share on comment!\n","permalink":"https://kinnrot.github.io/the-value-of-fast-feedback-loop/","summary":"\u003cp\u003eWe all wanna get from 0 to 1 (with many trailing zeros), the sooner the better.\u003c/p\u003e\n\u003ch3 id=\"so-whats-the-problem\"\u003eSo, what\u0026rsquo;s the problem?\u003c/h3\u003e\n\u003cp\u003eYou build something and you\u0026rsquo;re brave enough to put it out there, now what?\nNow you start the endless feedback loop cycle, you look at the data, analytics, user recordings, product inputs, and decide what\u0026rsquo;s the next thing that\u0026rsquo;ll make your product better then ever, it\u0026rsquo;s an iterative process that never ends. The faster you iterate, the faster you\u0026rsquo;ll get to your target.\u003c/p\u003e","title":"The value of fast feedback loop for developers"},{"content":"If you ever used any MVC framework, I\u0026rsquo;m sure you asked yourself more than once, \u0026lsquo;Where should I put this piece of code?\u0026rsquo; (If not that\u0026rsquo;s also fine). Well, there is no one answer for all problems but, I asked it a lot.\nIn this post, I\u0026rsquo;m gonna focus about the view part.\nView objects, AKA view models, but any other name is fine (presenter view object, view controller mediator, whatever).\nWhy do I need it? Well, that\u0026rsquo;s easy, I got a controller action, need to fetch some data from a few places, Data-base, cache, external API, session, and who knows. Next, I need to put this data on a view, the view can be in different formats: HTML, JSON, XML, PDF, whatever, it\u0026rsquo;s the same data, presented in different formats. this data need to go through some manipulations to be more human friendly. What I just described is 80% of apps (web, mobile, desktop) scenarios. Assuming your model is not a read model you can\u0026rsquo;t just fetch one model/list of models and put it on a view. You\u0026rsquo;ll probably have to do some table joins, filters, sorting and a bunch of other things. So first recommendation is to create a query class for each query you need. The controller can call this query directly. Next comes the data manipulation this is where the view model comes to the picture. The view model gets data and make it presentable, Why not putting this logic directly in view. cause views should be stupid as possible, they are not classes, they\u0026rsquo;re hard to debug, so keep them as simple as possible. And if you have multiple views for the same data, like API and a web view, You\u0026rsquo;ll find yourself duplicating logic for each view.\nThere is an issue with directly passing query results to a view model, you are risking with N+1 query performance issues, cause if you pass an active record model to a view model and view model access a referenced object that wasn\u0026rsquo;t pre fetched a DB query will run, If you got a list of 50 models, each with 4 relations not pre-fetched, you got 200 extra queries for a single view, that\u0026rsquo;s not good.\nIt\u0026rsquo;s also considered a bad practice to have data queries in the view layer, but that\u0026rsquo;s for another post.\nTo solve this kind of issue you have a few possible solutions,\nDo not pass active record models to the view models, use data transfer objects, plain poro.\nDo not pass active record models to the view models, use :attributes method, relation won\u0026rsquo;t work, but not unexpected queries\nMake sure you prefetch everything the view needs, and pass the model directly to view model, !danger! if other developers work with you, and they don\u0026rsquo;t know the consequences.\nUse a zero relations read model for each view, query it, and send it as is to the view model.\nIf you don\u0026rsquo;t wanna implement something on you own, here are some gems that\u0026rsquo;ll give you some structure and syntactic sugar:\ndraper - uses the decorator pattern to wrap active record models, allowing to add view specific methods on top of existing models. cells - component based approach to encapsulate view parts, and logic to classes. rom - full blown object mapper dry-view - A component based view framework Personally, I choose to write my own PORO, to keep things as simple as possible, I try to pass data, not models, this way my view models layer is not bound to any data store structure. The query result goes to a view model factory class, that responsible for extracting the relevant data for the view model, and view gets rendered with the view model.\nHere is an example:\nView model -\nmodule ViewModels class GeoMap attr_reader :map_data def map_options { id: \u0026#39;fans-map\u0026#39;, width: \u0026#39;100%\u0026#39;, height: \u0026#39;85%\u0026#39;, label: \u0026#39;Fans\u0026#39;, min_value: 0, colors: %w[#e7f7f0 #19B26C] } end def initialize(map_data, view_context) @map_data = map_data @view_context = view_context end def max_fans @map_data.max_by { |_country, fans| fans }[1] if @map_data.present? end def max_fans_humanize @view_context.number_to_human(max_fans) end def mid_fans_humanize @view_context.number_to_human(max_fans / 2) if max_fans end end end View (Written in slim, using chartkick for the geo map) -\n= geo_chart @geo_map.map_data, @geo_map.map_options Controller -\n# Map data came from a service object @geo_map = GeoMap.new(map_data, view_context) Would love to hear from you, What\u0026rsquo;s your favorite view objects strategy?\n","permalink":"https://kinnrot.github.io/rails-presentation-objects-guide/","summary":"\u003cp\u003eIf you ever used any \u003ca href=\"https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller\"\u003eMVC\u003c/a\u003e framework, I\u0026rsquo;m sure you asked yourself more than once, \u0026lsquo;Where should I put this piece of code?\u0026rsquo; (If not that\u0026rsquo;s also fine).\nWell, there is no one answer for all problems but, I asked it a lot.\u003c/p\u003e\n\u003cp\u003eIn this post, I\u0026rsquo;m gonna focus about the view part.\u003c/p\u003e\n\u003cp\u003eView objects, AKA view models, but any other name is fine (presenter view object, view controller mediator, whatever).\u003c/p\u003e","title":"Rails Presentation Objects"},{"content":"So I found out it\u0026rsquo;s not so documented, hopefully google will index this. I have a page on my system that shows a google geo chart (same as this) When clicking on a country on the map lot\u0026rsquo;s of interesting things happens. And I wanted to implement a ui automation test to cover this use case.\nIt\u0026rsquo;s not so easy cause even if you find the right svg path object and try clicking on it you get some interception errors. So I googled a bit without any luck, but the geo chart documents came to the rescue.\nThe easiest way is to run some javascript:\nvar yourChart = Chartkick.charts[\u0026#39;counutries-map\u0026#39;].chart // Replace with code that gets your chart google.visualization.events.trigger(yourChart, \u0026#39;regionClick\u0026#39;, { region:\u0026#39;US\u0026#39; }); This code triggers an event on the chart object that the United States region was clicked. super simple and easy I\u0026rsquo;m using capybara and it looks like this:\npage.evaluate_script(\u0026lt;\u0026lt;~JS) function(){ var yourChart = Chartkick.charts[\u0026#39;counutries-map\u0026#39;].chart // Replace with code that gets your chart google.visualization.events.trigger(yourChart, \u0026#39;regionClick\u0026#39;, { region:\u0026#39;US\u0026#39; }); }() JS It\u0026rsquo;s just injecting a self executing function to the page.\n","permalink":"https://kinnrot.github.io/simulate-click-on-google-geo-chart/","summary":"\u003cp\u003eSo I found out it\u0026rsquo;s not so documented, hopefully google will index this.\nI have a page on my system that shows a google geo chart (same as \u003ca href=\"https://developers.google.com/chart/interactive/docs/gallery/geochart\"\u003ethis\u003c/a\u003e)\nWhen clicking on a country on the map lot\u0026rsquo;s of interesting things happens. And I wanted to implement a ui automation test to cover this use case.\u003c/p\u003e\n\u003cp\u003eIt\u0026rsquo;s not so easy cause even if you find the right svg path object and try clicking on it you get some interception errors.\nSo I googled a bit without any luck, but the geo chart documents came to the rescue.\u003c/p\u003e","title":"Simulate Click on Google Geo Chart"},{"content":"Recently I discovered Danger, an amazing tool you should check out no matter what.\nI can write a ton of use cases that serves me on my day to day work, but let\u0026rsquo;s start with one which I like a lot.\nDo you know how much of your code is covered by tests?\nDo you keep track on how your code coverage changes over time ?\nI didn\u0026rsquo;t till I installed a simple danger plugin called \u0026lsquo;danger-simplecov_json\u0026rsquo;, It\u0026rsquo;s a ruby gem it\u0026rsquo;s configuration is super easy (check this link to the gem), Once you configure Danger on your CI or locally, you can see after each build (spec run or whatever you use) the percentage of code coverage.\nWhen I started using this plugin my coverage was somewhere in the 40%, currently I\u0026rsquo;m on 85%. This plugin motivates you to increase your coverage push new code with tests.\nI configured it to run on my CI (I use circle) and add a nicely formatted comment on each opened PR.\nIt looks like this:\nCode coverage is now at 83.13% (37790/45395 lines)\nIt\u0026rsquo;s a small thing with big impact, try it!\n","permalink":"https://kinnrot.github.io/keep-track-on-coverage/","summary":"\u003cp\u003eRecently I discovered \u003ca href=\"https://github.com/danger/danger\"\u003eDanger\u003c/a\u003e, an amazing tool you should check out no matter what.\u003c/p\u003e\n\u003cp\u003eI can write a ton of use cases that serves me on my day to day work, but let\u0026rsquo;s start with one which I like a lot.\u003c/p\u003e\n\u003cp\u003eDo you know how much of your code is covered by tests?\u003c/p\u003e\n\u003cp\u003eDo you keep track on how your code coverage changes over time ?\u003c/p\u003e\n\u003cp\u003eI didn\u0026rsquo;t till I installed a simple danger plugin called \u003ca href=\"https://github.com/marcelofabri/danger-simplecov_json\"\u003e\u0026lsquo;danger-simplecov_json\u0026rsquo;\u003c/a\u003e, It\u0026rsquo;s a ruby gem it\u0026rsquo;s configuration is super easy (check this link to the gem),\nOnce you configure Danger on your CI or locally, you can see after each build (spec run or whatever you use) the percentage of code coverage.\u003c/p\u003e","title":"Keep Track on Coverage"},{"content":"If you\u0026rsquo;re building forms with rails, whether you\u0026rsquo;re using a gem for it or working with pure rails forms, you should know this.\nRails uses form builder to allow you to call all the standard label/input/select methods, the exact class name is\nActionView::Helpers::FormBuilder\nWhen calling \u0026lsquo;form_for\u0026rsquo; you get a fresh instance of this FormBuilder which allows you to define your form elements.\nLets say you wanna add another reusable form element, for example a form section with title that uses your own custom style/classes.\nTo achieve that, you should extend the default form builder, just add a new class to your helpers folder lets call it \u0026lsquo;MyFormBuilder\u0026rsquo; it looks like this\n` class MyFormBuilder \u0026lt; ActionView::Helpers::FormBuilder def section(title, id = \u0026#34;section-#{SecureRandom.uuid}\u0026#34;) @template.content_tag(:label, title, { class: \u0026#39;form-label\u0026#39;, id: id }) + @template.content_tag(:div) do yield if block_given? end + @template.content_tag(\u0026#39;hr\u0026#39;, \u0026#39;\u0026#39;, { class: \u0026#39;row-divider\u0026#39; }) end end ` So we defined a form builder with a section method now we just need to tell rails, that when we write in our view\nform_for()\u0026hellip;\nto use our freshly coded MyFormBuilder\nIt\u0026rsquo;s actually super simple ( but not so documented ), if you\u0026rsquo;ll look at https://apidock.com/rails/ActionView/Helpers/FormHelper/form_for there\u0026rsquo;s a section called \u0026lsquo;Customized form builders\u0026rsquo; which explains what I just wrote\nTo make your new form builder the default builder so you won\u0026rsquo;t have to specify it each time you write form_for you can do one of two options, add a new form_for method with a different name, or override existing form_for.\nI prefer adding a new method, so on helpers/application_helper.rb I added the following code:\n` module ApplicationHelper def my_form_for(name, *args, \u0026amp;block) options = args.extract_options! content_tag(\u0026#34;div\u0026#34;, form_for(name, *(args \u0026lt;\u0026lt; options.merge(:builder =\u0026gt; MyFormBuilder)), \u0026amp;block), :class =\u0026gt; \u0026#34;core-form section\u0026#34; ) end def my_fields_for(name, classes, *args, \u0026amp;block) options = args.extract_options! content_tag(\u0026#34;div\u0026#34;, fields_for(name, nil, *(args \u0026lt;\u0026lt; options.merge(:builder =\u0026gt; MyFormBuilder)), \u0026amp;block), :class =\u0026gt; \u0026#34;core-form section #{classes}\u0026#34; ) end end ` Which allows me to use the classic form_for, or my extended my_form_for, and also my_fields_for instead of fields_for when nesting inside existing form.\nIt\u0026rsquo;s super useful when you got forms and wanna keep things DRY and managed, I use it to define a standard label with input with error rendering for example.\nHope you like it, please share your thoughts.\n","permalink":"https://kinnrot.github.io/building-your-own-rails-form-builder/","summary":"\u003cp\u003eIf you\u0026rsquo;re building forms with rails, whether you\u0026rsquo;re using a gem for it or working with pure rails forms, you should know this.\u003c/p\u003e\n\u003cp\u003eRails uses form builder to allow you to call all the standard label/input/select methods, the exact class name is\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eActionView::Helpers::FormBuilder\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eWhen calling \u0026lsquo;form_for\u0026rsquo; you get a fresh instance of this FormBuilder which allows you to define your form elements.\u003c/p\u003e\n\u003cp\u003eLets say you wanna add another reusable form element, for example a form section with title that uses your own custom style/classes.\u003c/p\u003e","title":"Building your own rails form builder"},{"content":"Sometimes we want to show the user an alert when somethings wrong or we just need to give some extra info, For example; Ask the user if he is sure he wanna leave the app.\nThis can be achieved with the following code (runs inside activity):\nAlertDialog.Builder(this) .setMessage(\u0026#34;Are you sure you want to exit?\u0026#34;) .setCancelable(false) .setPositiveButton(\u0026#34;Yes\u0026#34;, object:DialogInterface.OnClickListener() { fun onClick(dialog:DialogInterface, id:Int) { this@YourActivity.finish() } }) .setNegativeButton(\u0026#34;No\u0026#34;, null) .show() This works fine, buy there is one annoying issue, If user clicks home button while dialog displayed, and go back to the app, the dialog will still be there. Now your user experience is seeing a question about getting out of the app while he just went in.\nTo avoid this case, I found an easy solution by making my modal lifecycle aware, If your\u0026rsquo;e not sure what\u0026rsquo;s lifecycle, consider read about it here.\nEvery activity/fragment implements the LifecycleOwner interface so lets add the following method:\nprivate fun subscribeToLifecycleEvents(dialog: Dialog, lifecycleOwner: LifecycleOwner?, dismissHandler: (() -\u0026gt; Unit)? = null) { val lifecycleObserver = GenericLifecycleObserver { _, event -\u0026gt; if (event == Lifecycle.Event.ON_PAUSE \u0026amp;\u0026amp; dialog.isShowing) { dialog.dismiss() dismissHandler?.invoke() } } lifecycleOwner?.apply { this.lifecycle.addObserver(lifecycleObserver) } dialog.setOnDismissListener { lifecycleOwner?.apply { this.lifecycle.removeObserver(lifecycleObserver) } } } This method make every dialog lifecycle aware, meaning, if we add subscription to the dialog display:\nval dialog = AlertDialog.Builder(this) .setMessage(\u0026#34;Are you sure you want to exit?\u0026#34;) .setCancelable(false) .setPositiveButton(\u0026#34;Yes\u0026#34;, object:DialogInterface.OnClickListener() { fun onClick(dialog:DialogInterface, id:Int) { this@YourActivity.finish() } }) .setNegativeButton(\u0026#34;No\u0026#34;, null) .show() subscribeToLifecycleEvents(dialog, this) // add subscription Every time the lifecycle owner of the modal (fragment activity or custom implementation) is paused, the dialog will be automatically dismissed.\nLifecycle architecture opens many options related to bind ui interactions with lifecycle which is extremely important for a mobile phone that can get interrupts like phone calls and messages all the time.\n","permalink":"https://kinnrot.github.io/android-lifecycle-aware-modal/","summary":"\u003cp\u003eSometimes we want to show the user an alert when somethings wrong or we just need to give some extra info,\nFor example; Ask the user if he is sure he wanna leave the app.\u003c/p\u003e\n\u003cp\u003eThis can be achieved with the following code (runs inside activity):\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-kotlin\" data-lang=\"kotlin\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003eAlertDialog\u003c/span\u003e.Builder(\u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e .setMessage(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Are you sure you want to exit?\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e .setCancelable(\u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e .setPositiveButton(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Yes\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#66d9ef\"\u003eobject\u003c/span\u003e:\u003cspan style=\"color:#a6e22e\"\u003eDialogInterface\u003c/span\u003e.OnClickListener() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \u003cspan style=\"color:#66d9ef\"\u003efun\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eonClick\u003c/span\u003e(dialog:DialogInterface, id:Int) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003e@YourActivity\u003c/span\u003e.finish()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e })\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e .setNegativeButton(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;No\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e .show()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThis works fine, buy there is one annoying issue, If user clicks home button while dialog displayed, and go back to the app, the dialog will still be there.\nNow your user experience is seeing a question about getting out of the app while he just went in.\u003c/p\u003e","title":"Android Lifecycle Aware Modal"},{"content":"When working with MutableLiveData you can update the observable value in 2 ways:\nsetValue postValue Both will update the live data value as expected as long as your code is running from the main thread.\nIf you need to update a value from other thread you can use the postValue which is thread safe, and will make sure to notify observers on main thread.\nThis is all nice, but be aware!\nval foo = MutableLiveData\u0026lt;Boolean\u0026gt;() // this foo.value = true foo.value = false // and that foo.postValue(true) foo.postValue(false) Both this and that sets the live data value to true and then to false, so you probably expect, if observing foo, you\u0026rsquo;ll get your code to run twice, once with true and once with false.\nWell for the first section with setValue it works as expected.\nFor the second section with postValue you\u0026rsquo;ll get a surprise, only second call triggers the observer, or is it?\nThe issue with post value is as follows:\nValue is being set immediately in a synchronized code block for thread safety, but the observers notification is scheduled to execute on main thread via the event loop (with handler) So what\u0026rsquo;s happening is value changes to true and false but scheduling code occurs only once.\nthis is the implementation of postValue\nprotected void postValue(T value) { boolean postTask; synchronized (mDataLock) { postTask = mPendingData == NOT_SET; mPendingData = value; } if (!postTask) { return; } ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable); } As you can postTask is a flag that say \u0026ldquo;do I need to schedule a runnable to notify my observers, or did I already do that?\u0026rdquo; for the first call postTask is true, and for the second its false\npostValue is good for ui progress reporting for example, cause ui updates only when main thread is available to perform screen updates. It\u0026rsquo;s not good when you count on getting notified for each change of the LiveDataValue.\nas comment says:\nIf you called this method multiple times before a main thread executed a posted task, only the last value would be dispatched.\nSo I recommend, by default, prefer using setValue, use postValue, only when:\nyou gonna post lots of changes (progress) and you don\u0026rsquo;t need all of them only last value is relevant. you not running on the main thread. ","permalink":"https://kinnrot.github.io/live-data-pitfall-you-should-be-aware-of/","summary":"\u003cp\u003eWhen working with \u003ccode\u003eMutableLiveData\u003c/code\u003e you can update the observable value in 2 ways:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003ccode\u003esetValue\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003epostValue\u003c/code\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eBoth will update the live data value as expected as long as your code is running from the main thread.\u003c/p\u003e\n\u003cp\u003eIf you need to update a value from other thread you can use the \u003ccode\u003epostValue\u003c/code\u003e which is thread safe, and will make sure to notify observers on main thread.\u003c/p\u003e\n\u003cp\u003eThis is all nice, but be aware!\u003c/p\u003e","title":"Live Data Pitfall You Should Be Aware Of"},{"content":"I needed to choose WordPress hosting service for some of clients and decided to do some research to figure out what\u0026rsquo;s best value for each client needs.\nThere are many service providers in this area, After lots of googling I decided to focus on the following:\nWordPress BlueHost Kinsta WordPress If you\u0026rsquo;re building a new site/blog without any technical knowledge, WordPress is the right place for you, owned by the official word press organization offering limited capabilities cheap plans, and more expensive plans with more options like upload a custom theme, and charging money via paypal.\nThey also got a free plan, but you won\u0026rsquo;t get to use your own domain name.\nBlueHost This is the most economy wise solution.\nIf you have technical knowledge and you have a custom theme, and wanna save money, this is the service for you, It\u0026rsquo;s a managed solution with one click WordPress install. BlueHost also offers additional services like seo optimization tool, and backup tool for additional cost.\nKinsta For those of you who run a serious operation but don\u0026rsquo;t wanna setup their own dev ops, and dont have more than 100K monthly visits / don\u0026rsquo;t mind to pay a lot on your web site, This is the service for you, you get:\nOne click SSL setup with let\u0026rsquo;s encrypt Premium DNS by amazon Staging environment with one click push to production One click CDN setup For those of you who want to dig deeper there are many other providers and guides on how to choose the best one for your needs, I found this link\n","permalink":"https://kinnrot.github.io/choosing-the-right-wordpress-hosting-service/","summary":"\u003cp\u003eI needed to choose WordPress hosting service for some of clients and decided to do some research to figure out what\u0026rsquo;s best value for each client needs.\u003c/p\u003e\n\u003cp\u003eThere are many service providers in this area, After lots of googling I decided to focus on the following:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003ca href=\"https://wordpress.com/create/?aff=9716\u0026amp;cid=958799\"\u003eWordPress\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.bluehost.com/track/kinnrot/\"\u003eBlueHost\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://kinsta.com/?utm_source=kinnrot.github.io\"\u003eKinsta\u003c/a\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"wordpress\"\u003eWordPress\u003c/h2\u003e\n\u003cp\u003eIf you\u0026rsquo;re building a new site/blog without any technical knowledge, \u003ca href=\"https://wordpress.com/create/?aff=9716\u0026amp;cid=958799\"\u003eWordPress\u003c/a\u003e is the right place for you,\nowned by the official word press organization offering limited capabilities cheap plans, and more expensive plans with\nmore options like upload a custom theme, and charging money via paypal.\u003c/p\u003e","title":"Choosing the Right WordPress Hosting Service"},{"content":"I tried to build an SPA without a shiny client side framework, I wanted to build something fast with good user experience and keeping it as simple as possible.\nI decided to take rails, use turbolinks and a avoid javascript till its a must.\nIt didn\u0026rsquo;t take more than a few hours and I found myself writing javascript. What I needed to do is simple, I had an input with number, and 2 buttons next to it, one to increase values by 1 and on to decrease it looked like this:\n- 0+\njQuery to the rescue, I had a list of those buttons, so I needed to identify each one, so I added a data-id attr and used it to identify which input I need to update it looked like this:\n` \u0026lt;button data-id=\u0026#34;1\u0026#34; name=\u0026#34;minus\u0026#34;\u0026gt;-\u0026lt;/button\u0026gt; \u0026lt;input id=\u0026#34;1\u0026#34; value=\u0026#34;0\u0026#34; readonly=\u0026#34;readonly\u0026#34;\u0026gt; \u0026lt;button data-id=\u0026#34;1\u0026#34; name=\u0026#34;plus\u0026#34;\u0026gt;+\u0026lt;/button\u0026gt; ` // number_componenet.js export default class NumberComponent { constructor() { $(\u0026#39;button[name=\u0026#34;plus\u0026#34;]\u0026#39;).click(function (e) { e.preventDefault(); var id = $(this).data(\u0026#39;id\u0026#39;); var input = $(id); const lastValue = +input.val(); var num = lastValue + 1; if (num \u0026lt;= 20) { input.val(num); } }); $(\u0026#39;button[name=\u0026#34;minus\u0026#34;]\u0026#39;).click(function (e) { e.preventDefault(); var id = $(this).data(\u0026#39;id\u0026#39;); var input = $(id); const lastValue = +input.val(); var num = lastValue - 1; if (num \u0026gt;= 0) { input.val(num); } }); } } As You can see I added a bit of client side validation to make sure counter does not go below 0 and above 20. Now All left to do is to initialize the NumberComponent when the page loads, so I added it to my packs (I\u0026rsquo;m using webpacker) and wrote:\n$(() =\u0026gt; { new GameOrderComponent() }); And it works!.\nbut it\u0026rsquo;s already a bit of a mess, I need to search for the relevant buttons, I don\u0026rsquo;t know how it\u0026rsquo;ll behave when content of page changes (turbolinks, other dynamic behavior etc.) I though to myself, \u0026ldquo;it would be much easier to annotate the relevant html items to describe their behavior\u0026rdquo;. But I did not want to make the client super complex, I just want something that\u0026rsquo;ll help me to model my code without all the hassle.\nI did some research (very intensive googling) and found Stimulus. Its a library that decouples your javascript from the html like css decouple styling from html, which is pretty nice.\nThe concepts are pretty simple and familiar, you got:\nController - to group a bunch of html elements in one context (numberController) Target - to allow access dom element inside the controller (instead of jQuery selector) (input) Action - to respond to dom element event and act (button click) That\u0026rsquo;s all, simple huh?\nThis is how it looks\n` \u0026lt;div data-controller=\u0026#34;number\u0026#34;\u0026gt; \u0026lt;button data-action=\u0026#34;click-\u0026gt;number#minusOne\u0026#34;\u0026gt;-\u0026lt;/button\u0026gt; \u0026lt;input data-target=\u0026#34;number.input\u0026#34; value=\u0026#34;0\u0026#34; readonly=\u0026#34;readonly\u0026#34;\u0026gt; \u0026lt;button data-action=\u0026#34;click-\u0026gt;number#plusOne\u0026#34;\u0026gt;+\u0026lt;/button\u0026gt; \u0026lt;/div\u0026gt; ` // number_controller.js import {Controller} from \u0026#34;stimulus\u0026#34; export default class extends Controller { minusOne(event) { event.preventDefault() const lastValue = +this.input.value if (lastValue \u0026gt; 0) { this.input.value = +this.input.value - 1 } } plusOne(event) { event.preventDefault() const lastValue = +this.input.value if (lastValue \u0026lt; 20) { this.input.value = +this.input.value + 1 } } get input() { return this.targets.find(\u0026#39;input\u0026#39;) } } I didn\u0026rsquo;t write less code but,\nThe code is more readable No need to initialize the controller, Stimulus take care of that. You get access to the actual html element, which keeps everything straightforward. No need to worry about dom changes, Stimulus take care of that. I know that everyone thinks react angular and vue is the s*** but I think its good for large organizations where you have a separate front-end team and back-end team. When you build something new by yourself or with some friends, there is no good reason to start with client side rendering (unless you got a few million users on day one which is less likely)\nThere are also small companies with a team of full stackers, who might also consider this approach.\nIf you got a bit stimulated, you can read a small guide here\n","permalink":"https://kinnrot.github.io/from-jquery-to-stimulus/","summary":"\u003cp\u003eI tried to build an \u003ca href=\"https://en.wikipedia.org/wiki/Single-page_application\"\u003eSPA\u003c/a\u003e without a shiny client side framework, I wanted to build something fast with good user experience and keeping it as simple as possible.\u003c/p\u003e\n\u003cp\u003eI decided to take \u003ca href=\"https://rubyonrails.org/\"\u003erails\u003c/a\u003e, use \u003ca href=\"https://github.com/turbolinks/turbolinks\"\u003eturbolinks\u003c/a\u003e and a avoid javascript till its a must.\u003c/p\u003e\n\u003cp\u003eIt didn\u0026rsquo;t take more than a few hours and I found myself writing javascript. What I needed to do is simple, I had an input with number, and 2 buttons next to it, one to increase values by 1 and on to decrease it looked like this:\u003c/p\u003e","title":"From jQuery to Stimulus"},{"content":"There is a lot of buzz about asyc await from the javascript world, the concept is very simple and make your code much more readable.\nYou want to execute something without blocking the main thread but you want the next line of code to run once the non blocking code finish, meaning continue code execution in its written order.\nRuby has a great concurrency gem which basically encapsulate low level threading and synchronization code to common patterns like Future, Promise, Actor and much more.\nI\u0026rsquo;d like to talk about concurrent-ruby async await feature, lets look at the following code.\nrequire \u0026#39;concurrent\u0026#39; class Reporter include Concurrent::Async def report(message, sleep_dur=1) sleep(sleep_dur) p \u0026#34;#{Thread.current.object_id}\u0026#34; p message end end The class Reporter knows to do 1 thing, report, it\u0026rsquo;ll sleep and print it\u0026rsquo;s thread id and a message So if we\u0026rsquo;ll open an irb and call\n?\u0026gt; r = Reporter.new =\u0026gt; #\u0026lt;Reporter:0x007f86b19e1940 @__async_initialized__=true, @__async_delegator__=#\u0026lt;Concurrent::Async::AsyncDelegator:0x007f86b19e18a0 @__lock__=#\u0026lt;Thread::Mutex:0x007f86b19e1850\u0026gt;, @__condition__=#\u0026lt;Thread::ConditionVariable:0x007f86b19e1828\u0026gt;, @delegate=#\u0026lt;Reporter:0x007f86b19e1940 ...\u0026gt;, @queue=[], @executor=#\u0026lt;Concurrent::ThreadPoolExecutor:0x007f86b19e0e78 @__lock__=#\u0026lt;Thread::Mutex:0x007f86b19e0d88\u0026gt;, @__condition__=#\u0026lt;Thread::ConditionVariable:0x007f86b19e0d60\u0026gt;, @min_length=8, @max_length=2147483647, @idletime=60, @max_queue=0, @fallback_policy=:abort, @auto_terminate=true, @pool=[], @ready=[], @queue=[], @scheduled_task_count=0, @completed_task_count=0, @largest_length=0, @ruby_pid=59753, @gc_interval=30, @next_gc_time=694963.258667, @StopEvent=#\u0026lt;Concurrent::Event:0x007f86b19e0bd0 @__lock__=#\u0026lt;Thread::Mutex:0x007f86b19e0b80\u0026gt;, @__condition__=#\u0026lt;Thread::ConditionVariable:0x007f86b19e0b58\u0026gt;, @set=false, @iteration=0\u0026gt;, @StoppedEvent=#\u0026lt;Concurrent::Event:0x007f86b19e0ae0 @__lock__=#\u0026lt;Thread::Mutex:0x007f86b19e0a90\u0026gt;, @__condition__=#\u0026lt;Thread::ConditionVariable:0x007f86b19e0a68\u0026gt;, @set=false, @iteration=0\u0026gt;\u0026gt;\u0026gt;, @__await_delegator__=#\u0026lt;Concurrent::Async::AwaitDelegator:0x007f86b19e0a18 @delegate=#\u0026lt;Concurrent::Async::AsyncDelegator:0x007f86b19e18a0 @__lock__=#\u0026lt;Thread::Mutex:0x007f86b19e1850\u0026gt;, @__condition__=#\u0026lt;Thread::ConditionVariable:0x007f86b19e1828\u0026gt;, @delegate=#\u0026lt;Reporter:0x007f86b19e1940 ...\u0026gt;, @queue=[], @executor=#\u0026lt;Concurrent::ThreadPoolExecutor:0x007f86b19e0e78 @__lock__=#\u0026lt;Thread::Mutex:0x007f86b19e0d88\u0026gt;, @__condition__=#\u0026lt;Thread::ConditionVariable:0x007f86b19e0d60\u0026gt;, @min_length=8, @max_length=2147483647, @idletime=60, @max_queue=0, @fallback_policy=:abort, @auto_terminate=true, @pool=[], @ready=[], @queue=[], @scheduled_task_count=0, @completed_task_count=0, @largest_length=0, @ruby_pid=59753, @gc_interval=30, @next_gc_time=694963.258667, @StopEvent=#\u0026lt;Concurrent::Event:0x007f86b19e0bd0 @__lock__=#\u0026lt;Thread::Mutex:0x007f86b19e0b80\u0026gt;, @__condition__=#\u0026lt;Thread::ConditionVariable:0x007f86b19e0b58\u0026gt;, @set=false, @iteration=0\u0026gt;, @StoppedEvent=#\u0026lt;Concurrent::Event:0x007f86b19e0ae0 @__lock__=#\u0026lt;Thread::Mutex:0x007f86b19e0a90\u0026gt;, @__condition__=#\u0026lt;Thread::ConditionVariable:0x007f86b19e0a68\u0026gt;, @set=false, @iteration=0\u0026gt;\u0026gt;\u0026gt;\u0026gt;\u0026gt; \u0026gt;\u0026gt; r.report(\u0026#39;x\u0026#39;) \u0026#34;70108240336860\u0026#34; \u0026#34;x\u0026#34; And it\u0026rsquo;ll take a sec till you see output because of the sleep.\nNow lets try the same with async\n\u0026gt;\u0026gt; r.async.report(\u0026#39;x\u0026#39;) =\u0026gt; #\u0026lt;Concurrent::IVar:0x007f86b087dfc8 @__lock__=#\u0026lt;Thread::Mutex:0x007f86b087df00\u0026gt;, @__condition__=#\u0026lt;Thread::ConditionVariable:0x007f86b087deb0\u0026gt;, @event=#\u0026lt;Concurrent::Event:0x007f86b087dde8 @__lock__=#\u0026lt;Thread::Mutex:0x007f86b087dca8\u0026gt;, @__condition__=#\u0026lt;Thread::ConditionVariable:0x007f86b087dc80\u0026gt;, @set=false, @iteration=0\u0026gt;, @reason=nil, @value=nil, @observers=#\u0026lt;Concurrent::Collection::CopyOnWriteObserverSet:0x007f86b087db90 @__lock__=#\u0026lt;Thread::Mutex:0x007f86b087db18\u0026gt;, @__condition__=#\u0026lt;Thread::ConditionVariable:0x007f86b087daf0\u0026gt;, @observers={}\u0026gt;, @dup_on_deref=nil, @freeze_on_deref=nil, @copy_on_deref=nil, @do_nothing_on_deref=true, @state=:pending\u0026gt; \u0026#34;70108232018840\u0026#34; \u0026#34;x\u0026#34; As you can see the method returns immediately without printing any value, it just returns a promise like object that will hold the result of report method once done. To prove you that report in non blocking try this\n\u0026gt;\u0026gt; r.async.report(\u0026#39;x\u0026#39;); 1+1 =\u0026gt; 2 \u0026#34;70108231957940\u0026#34; \u0026#34;x\u0026#34; As you can see the 1+1 returns before the reporters output\nNow lets try the await method\n\u0026gt;\u0026gt; r.await.report(\u0026#39;x\u0026#39;); 1+1 \u0026#34;70339825139340\u0026#34; \u0026#34;x\u0026#34; =\u0026gt; 2 \u0026gt;\u0026gt; Thread.current.object_id =\u0026gt; 70339824711620 This time code look like it run synchronously, but lets check the main thread id, as you can see the code run on 2 different threads but in sync. this is the actual power of await, sometimes we want to run something in a background thread, and do something on another thread when done.\nThe purpose of the Concurrent::Async is to allow a class methods to be called in a synchronized way, meaning the class will always be thread safe as long as you call it via async or await. What actually happens in the backstage is whenever you use async/await the method invocation is inserted into a queue that got one worker thread that keep this queue empty. because its just one thread that invoke the methods, it is safe for many threads to use the same object.\nHope its clear enough,\nWanna learn more about async await in ruby? enter you email to get exclusive content! Email Address ","permalink":"https://kinnrot.github.io/ruby-async-await/","summary":"\u003cp\u003eThere is a lot of buzz about asyc await from the javascript world, the concept is very simple and make your code much more\nreadable.\u003c/p\u003e\n\u003cp\u003eYou want to execute something without blocking the main thread but you want the next line of code to run once the non blocking code finish, meaning continue\ncode execution in its written order.\u003c/p\u003e\n\u003cp\u003eRuby has a great \u003ca href=\"https://github.com/ruby-concurrency/concurrent-ruby\"\u003econcurrency gem\u003c/a\u003e which basically encapsulate low level threading and synchronization code\nto common patterns like Future, Promise, Actor and much more.\u003c/p\u003e","title":"Ruby async await"},{"content":"I decided to develop my own blog like all the other cool developers. If you got here, this is what I got so far, it\u0026rsquo;s not too much, but it\u0026rsquo;s a start.\nWhen I develop something my rules are very simple\nAvoid writing any code. Keep it simple. Easy to deploy on free hosting environment. Decent code syntax highlight So I heard(mostly in www) people talking about jekyll as a static web site generator and began to dig dipper, I searched a few ruby gems for blogging and found a gem called [octopress](https://github.com/octopress/octopress octopress v3). They, the guys who developed it, calls it Jekyll\u0026rsquo;s Ferrari, sounds good to me, looked pretty straight forward so I gave it a spin.\nFirst thing you need to do it to create a new project for your blog (just a new folder)\nmkdir my-blog Next you should create a Gemfile for easy dependency management.\ngem install bundler bundle init Now lets add octopress as a dependency, inside your Gemfile add\ngem \u0026#39;octopress\u0026#39;, \u0026#39;~\u0026gt; 3.0\u0026#39; Now we should tell bundle to install gems from Gemfile, in terminal run\nbundle Everything is set up, now according to [octopress](https://github.com/octopress/octopress octopress) all we need to do is to run\noctopress init \u0026lt;PATH\u0026gt; and we have a blog ready.\nNow you probably have a blog somewhere, mine is at blogger\nAnd I thought to my self it would be nice to import all my posts to the new blog, well it\u0026rsquo;s super easy, jekyll has many importers read more about it [here](https://import.jekyllrb.com/docs/home/ migrations)\nSo after 3 clicks and one script I got all my old posts on my new blog.\nWhat\u0026rsquo;s next? Well I need some theme, cause I can\u0026rsquo;t design at all, I just know how to design code, when it comes to colors layout and fonts, I suck.\nI googled a bit and found this and that and chose to start simple with minima, which is minimal and simple to install and work with\nyou just need to add it to your Gemfile\ngem \u0026#39;minima\u0026#39; set the theme property in _config.yaml to minima and you are good to go, by running \u0026lsquo;jekyll build\u0026rsquo; you\u0026rsquo;ll be able to see your blog site generated in the _site folder.\nNow we just need to deploy it the easy way, this is where octopress helps. I use github pages, which is very simple to set up, you just need to create a github repo named:\n\u0026lsquo;.github.io\u0026rsquo;\nthen run\nocopress deploy init git \u0026lt;your full repo url\u0026gt; now make sure you are not on master branch and run\nJEKYLL_ENV=production jekyll build JEKYLL_ENV=production octopress deploy that\u0026rsquo;s it you got your blog on jekyll published on git hub.\nReferences Octopress Jekyll\nMinima\nGithub pages\n","permalink":"https://kinnrot.github.io/octopress101/","summary":"\u003cp\u003eI decided to develop my own blog like all the other cool developers.\nIf you got here, this is what I got so far, it\u0026rsquo;s not too much, but it\u0026rsquo;s a start.\u003c/p\u003e\n\u003cp\u003eWhen I develop something my rules are very simple\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eAvoid writing any code.\u003c/li\u003e\n\u003cli\u003eKeep it simple.\u003c/li\u003e\n\u003cli\u003eEasy to deploy on free hosting environment.\u003c/li\u003e\n\u003cli\u003eDecent code syntax highlight\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eSo I heard(mostly in www) people talking about jekyll as a static web site generator and began to dig dipper,\nI searched a few ruby gems for blogging and found a gem called [octopress](\u003ca href=\"https://github.com/octopress/octopress\"\u003ehttps://github.com/octopress/octopress\u003c/a\u003e octopress v3).\nThey, the guys who developed it, calls it Jekyll\u0026rsquo;s Ferrari, sounds good to me, looked pretty straight forward so I gave it a spin.\u003c/p\u003e","title":"Octopress 101"},{"content":"\n# This code will generate 96 instancesViewStatData = Struct.new(:total, :target, :ratio)96.times.map {|_|ViewStatData.new(0, 0, 0)}# And this will not, it\u0026rsquo;ll generate 96 pointers[ViewStatData.new(0, 0, 0)] * 96# So Watch out!!!\n","permalink":"https://kinnrot.github.io/watch-out-for-reference-duplication/","summary":"\u003cp\u003e\u003cbr /\u003e\u003cpre style=\"background-color: #2b2b2b; color: #c7bab9; font-family: 'mononoki'; font-size: 11.3pt;\"\u003e\u003cspan style=\"color: white;\"\u003e# This code will generate 96 instances\u003c/span\u003e\u003c/pre\u003e\u003cpre style=\"background-color: #2b2b2b; color: #c7bab9; font-family: 'mononoki'; font-size: 11.3pt;\"\u003e\u003cspan style=\"color: white;\"\u003eViewStatData \u003c/span\u003e\u003cspan style=\"color: #cc7833;\"\u003e= \u003c/span\u003e\u003cspan style=\"color: #6d9cbe;\"\u003eStruct\u003c/span\u003e.new(\u003cspan style=\"color: #6d9cbe;\"\u003e:\u003c/span\u003e\u003cspan style=\"background-color: #283b5e; color: #6d9cbe;\"\u003etotal\u003c/span\u003e, \u003cspan style=\"color: #6d9cbe;\"\u003e:target\u003c/span\u003e, \u003cspan style=\"color: #6d9cbe;\"\u003e:ratio\u003c/span\u003e)\u003c/pre\u003e\u003cpre style=\"background-color: #2b2b2b; color: #c7bab9; font-family: 'mononoki'; font-size: 11.3pt;\"\u003e\u003cpre style=\"font-family: mononoki; font-size: 11.3pt;\"\u003e\u003cspan style=\"color: #a5c261;\"\u003e96\u003c/span\u003e.times.map {\u003cspan style=\"color: #cc7833;\"\u003e|\u003c/span\u003e_\u003cspan style=\"color: #cc7833;\"\u003e|\u003c/span\u003e\u003cspan style=\"color: #6d9cbe;\"\u003eViewStatData\u003c/span\u003e.new(\u003cspan style=\"color: #a5c261;\"\u003e0\u003c/span\u003e, \u003cspan style=\"color: #a5c261;\"\u003e0\u003c/span\u003e, \u003cspan style=\"color: #a5c261;\"\u003e0\u003c/span\u003e)}\u003c/pre\u003e\u003cpre style=\"font-family: mononoki; font-size: 11.3pt;\"\u003e\u003c/pre\u003e\u003cpre style=\"font-family: mononoki; font-size: 11.3pt;\"\u003e# And this will not, it\u0026rsquo;ll generate 96 pointers\u003c/pre\u003e\u003cpre style=\"font-family: mononoki; font-size: 11.3pt;\"\u003e\u003cpre style=\"font-family: mononoki; font-size: 11.3pt;\"\u003e\u003cspan style=\"color: #6d9cbe;\"\u003e[ViewStatData\u003c/span\u003e.new(\u003cspan style=\"color: #a5c261;\"\u003e0\u003c/span\u003e, \u003cspan style=\"color: #a5c261;\"\u003e0\u003c/span\u003e, \u003cspan style=\"color: #a5c261;\"\u003e0\u003c/span\u003e)] * 96\u003c/pre\u003e\u003cpre style=\"font-family: mononoki; font-size: 11.3pt;\"\u003e# So Watch out!!!\u003c/pre\u003e\u003c/pre\u003e\u003c/pre\u003e\u003c/p\u003e","title":"Watch out for reference duplication instead of instance duplication"},{"content":"When we want to iterate a long list, we can simply write a query and get a cursor, ActiveRecord will do all the heavy lifting for us.\nWhat happens when we need to do some complicated computations on a set of data, which sometimes can be too big to be stored in memory for the entire computing process?\nThis is when we need to start being more creational.\nI\u0026rsquo;d like to introduce what I came up with.\nThe problem:\n- Complex calculation on time based data series for a period of 3 months.\n- Each calculation may depends on previous one and on future and past data.\n- Must be in order.\n- When fetching all data server crash on memory.\nThe solution:\nI wanted to do the most minor code change possible, and currently the data was accessed via a hash. I decided to encapsulate the hash with something I called lazy chunked hash (tried google it see it as standard behavior in clojure).\nIt looks like this:\nclass ValuesProvider def initialize()\n@loaded_date = nil @hash = Hash.new(0) end def [](time_slot) get(time_slot) end private def get(time_slot) relevant_date = time_slot.to_date unless relevant_date == @loaded_date load(relevant_date) end @hash[time_slot.to_i] endend\nPretty simple and does the work, instead of loading the data all at once, the data is being loaded for each day separately, this way we keep it chunky but not too chunky.\nAnd best part, my code that consume the data, didn\u0026rsquo;t change because of the [] method, which makes my ValueProvider behave like an array. This solution is good when the consumer data request(call for[]) implies on what data should be loaded, which most of the times will, but in some cases it won\u0026rsquo;t)\n","permalink":"https://kinnrot.github.io/ruby-lazy-chunked-hash-like-behavior/","summary":"\u003cp\u003e\u003cspan style=\"font-family: Courier New, Courier, monospace;\"\u003eWhen we want to iterate a long list, we can simply write a query and get a cursor, ActiveRecord will do all the heavy lifting for us.\u003c/span\u003e\u003cbr /\u003e\u003cspan style=\"font-family: Courier New, Courier, monospace;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style=\"font-family: Courier New, Courier, monospace;\"\u003eWhat happens when we need to do some complicated computations on a set of data, which sometimes can be too big to be stored in memory for the entire computing process?\u003c/span\u003e\u003cbr /\u003e\u003cspan style=\"font-family: Courier New, Courier, monospace;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style=\"font-family: Courier New, Courier, monospace;\"\u003eThis is when we need to start being more creational.\u003c/span\u003e\u003cbr /\u003e\u003cspan style=\"font-family: Courier New, Courier, monospace;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style=\"font-family: Courier New, Courier, monospace;\"\u003eI\u0026rsquo;d like to introduce what I came up with.\u003c/span\u003e\u003cbr /\u003e\u003cspan style=\"font-family: Courier New, Courier, monospace;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style=\"font-family: Courier New, Courier, monospace;\"\u003eThe problem:\u003c/span\u003e\u003cbr /\u003e\u003cspan style=\"font-family: Courier New, Courier, monospace;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style=\"font-family: Courier New, Courier, monospace;\"\u003e- Complex calculation on time based data series for a period of 3 months.\u003c/span\u003e\u003cbr /\u003e\u003cspan style=\"font-family: Courier New, Courier, monospace;\"\u003e- Each calculation may depends on previous one and on future and past data.\u003c/span\u003e\u003cbr /\u003e\u003cspan style=\"font-family: Courier New, Courier, monospace;\"\u003e- Must be in order.\u003c/span\u003e\u003cbr /\u003e\u003cspan style=\"font-family: Courier New, Courier, monospace;\"\u003e- When fetching all data server crash on memory.\u003c/span\u003e\u003cbr /\u003e\u003cspan style=\"font-family: Courier New, Courier, monospace;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style=\"font-family: Courier New, Courier, monospace;\"\u003eThe solution:\u003c/span\u003e\u003cbr /\u003e\u003cspan style=\"font-family: Courier New, Courier, monospace;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style=\"font-family: Courier New, Courier, monospace;\"\u003eI wanted to do the most minor code change possible, and currently the data was accessed via a hash. \u003c/span\u003e\u003cbr /\u003e\u003cspan style=\"font-family: Courier New, Courier, monospace;\"\u003eI decided to encapsulate the hash with something I called lazy chunked hash (tried google it see it as standard behavior in clojure).\u003c/span\u003e\u003cbr /\u003e\u003cspan style=\"font-family: Courier New, Courier, monospace;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style=\"font-family: Courier New, Courier, monospace;\"\u003eIt looks like this:\u003c/span\u003e\u003cbr /\u003e\u003cspan style=\"font-family: Courier New, Courier, monospace;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cpre style=\"background-color: #2b2b2b; color: #e6e1dc; font-family: 'mononoki'; font-size: 11.3pt;\"\u003e\u003cspan style=\"color: #cc7833;\"\u003eclass \u003c/span\u003e\u003cspan style=\"color: white;\"\u003eValuesProvider\u003c/span\u003e\u003cspan style=\"color: white;\"\u003e \u003c/span\u003e\u003cspan style=\"color: #cc7833;\"\u003edef \u003c/span\u003e\u003cspan style=\"color: #ffc66d;\"\u003einitialize\u003c/span\u003e()\u003cbr /\u003e \u003cspan style=\"color: #d0d0ff;\"\u003e@loaded_date \u003c/span\u003e\u003cspan style=\"color: #cc7833;\"\u003e= nil\u003c/span\u003e\u003c/pre\u003e\u003cpre style=\"background-color: #2b2b2b; color: #e6e1dc; font-family: 'mononoki'; font-size: 11.3pt;\"\u003e\u003cpre style=\"font-family: mononoki; font-size: 11.3pt;\"\u003e\u003cspan style=\"background-color: #3c3c57; color: #d0d0ff;\"\u003e @hash\u003c/span\u003e\u003cspan style=\"color: #d0d0ff;\"\u003e \u003c/span\u003e\u003cspan style=\"color: #cc7833;\"\u003e= \u003c/span\u003e\u003cspan style=\"color: #6d9cbe;\"\u003eHash\u003c/span\u003e.new(\u003cspan style=\"color: #a5c261;\"\u003e0\u003c/span\u003e)\u003c/pre\u003e\u003cspan style=\"color: #cc7833;\"\u003e end\u003c/span\u003e\u003cspan style=\"color: #cc7833;\"\u003e\u003c/span\u003e\u003cspan style=\"color: #cc7833;\"\u003e def \u003c/span\u003e\u003cspan style=\"color: #ffc66d;\"\u003e[]\u003c/span\u003e(time_slot) get(time_slot) \u003cspan style=\"color: #cc7833;\"\u003eend\u003c/span\u003e\u003cspan style=\"color: #cc7833;\"\u003e\u003c/span\u003e\u003cspan style=\"color: #cc7833;\"\u003e private\u003c/span\u003e\u003cspan style=\"color: #cc7833;\"\u003e\u003c/span\u003e\u003cspan style=\"color: #cc7833;\"\u003e def \u003c/span\u003e\u003cspan style=\"color: #ffc66d;\"\u003eget\u003c/span\u003e(time_slot) \u003cspan style=\"color: #d0d0ff;\"\u003erelevant_date \u003c/span\u003e\u003cspan style=\"color: #cc7833;\"\u003e= \u003c/span\u003etime_slot.to_date \u003cspan style=\"color: #cc7833;\"\u003eunless \u003c/span\u003e\u003cspan style=\"color: #d0d0ff;\"\u003erelevant_date \u003c/span\u003e\u003cspan style=\"color: #cc7833;\"\u003e== \u003c/span\u003e\u003cspan style=\"color: #d0d0ff;\"\u003e@loaded_date\u003c/span\u003e\u003cspan style=\"color: #d0d0ff;\"\u003e \u003c/span\u003eload(\u003cspan style=\"color: #d0d0ff;\"\u003erelevant_date\u003c/span\u003e) \u003cspan style=\"color: #cc7833;\"\u003eend\u003c/span\u003e\u003cspan style=\"color: #cc7833;\"\u003e\u003c/span\u003e\u003cspan style=\"color: #cc7833;\"\u003e \u003c/span\u003e\u003cspan style=\"color: #d0d0ff;\"\u003e@hash\u003c/span\u003e[time_slot.to_i] \u003cspan style=\"color: #cc7833;\"\u003eend\u003c/span\u003e\u003c/pre\u003e\u003cpre style=\"background-color: #2b2b2b; color: #e6e1dc; font-family: 'mononoki'; font-size: 11.3pt;\"\u003e\u003cspan style=\"color: #cc7833;\"\u003eend\u003c/span\u003e\u003c/pre\u003e\u003cbr /\u003e\u003cspan style=\"font-family: Courier New, Courier, monospace;\"\u003ePretty simple and does the work, instead of loading the data all at once, the data is being loaded for each day separately, this way we keep it chunky but not too chunky.\u003c/span\u003e\u003cbr /\u003e\u003cspan style=\"font-family: Courier New, Courier, monospace;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style=\"font-family: Courier New, Courier, monospace;\"\u003eAnd best part, my code that consume the data, didn\u0026rsquo;t change because of the [] method, which makes my ValueProvider behave like an array. \u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e \u003cspan style=\"font-family: Courier New, Courier, monospace;\"\u003eThis solution is good when the consumer data request(call for[]) implies on what data should be loaded, which most of the times will, but in some cases it won\u0026rsquo;t)\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003c/p\u003e","title":"Ruby Lazy chunked hash like behavior"},{"content":"I found this only today, you should run Rubymine as 32 bit process.\nIt works much faster and consume half the memory.\nTo set this got to the Applications folder right click on rubymine-\u0026gt;get info and check the \u0026ldquo;open in 32 bit mode\u0026rdquo;\nThat\u0026rsquo;s all!\n","permalink":"https://kinnrot.github.io/rubymine-on-osx/","summary":"\u003cp\u003eI found this only today, you should run Rubymine as 32 bit process.\u003cbr /\u003eIt works much faster and consume half the memory.\u003cbr /\u003e\u003cbr /\u003eTo set this got to the Applications folder right click on rubymine-\u0026gt;get info and check the \u0026ldquo;open in 32 bit mode\u0026rdquo;\u003cbr /\u003e\u003cbr /\u003eThat\u0026rsquo;s all!\u003cbr /\u003e\u003cbr /\u003e\u003c/p\u003e","title":"Rubymine on OSX memory issues"},{"content":"The most irritating thing in writing tests is the data generation preparation process, sometimes you want to create an object with 20 fields that 10 of them are mandatory but you only care about the value of 1, and you don\u0026rsquo;t want to mock, cause you interact with other methods and object that fetch this model from db.\nTo me it happens a lot so I found the FactoryGirl + Faker combination that made my life much more easy and now I can write tests in peace.\nTo add them just put in Gemfile:\ngem \u0026ldquo;factory_girl_rails\u0026rdquo;, \u0026ldquo;~\u0026gt; 4.0\u0026rdquo;\ngem \u0026ldquo;faker\u0026rdquo;\nSo lets take a complex sample to explain all there is to know.\nWe have a User, the User belongs to a Company, User has many tasks.\nCompany has many irritating mandatory fields\nLets define the Company Factory:\nFactoryGirl.define do\nfactory :company do\nname {Faker::Name.name}\ntrp {Faker::Number.between(0,10)}\ngrp {Faker::Number.between(0,5)}\nbudget {Faker::Number.number(4)}\ncpm {Faker::Number.between(1,70)}\ntrp_price {Faker::Number.between(100,700)}\nviewer {Faker::Number.between(0,100000)}\ntotal_viewer {Faker::Number.between(0,200000)}\nunique_viewer {Faker::Number.between(0,50000)}\nspots {Faker::Number.between(0,1000)}\nend\nend\nAs you can see I define lots of fields with random values.\nNow we can create a company by writing\ncreate(:company)Or just build one (without save to db) by calling\nbuild(:company) That\u0026rsquo;s all for now, I\u0026rsquo;ll continue in part2.\n","permalink":"https://kinnrot.github.io/use-factorygirl-and-faker-for-easy-data/","summary":"\u003cp\u003eThe most irritating thing in writing tests is the data generation preparation process, sometimes you want to create an object with 20 fields that 10 of them are mandatory but you only care about the value of 1, and you don\u0026rsquo;t want to mock, cause you interact with other methods and object that fetch this model from db.\u003cbr /\u003e\u003cbr /\u003eTo me it happens a lot so I found the FactoryGirl + Faker combination that made my life much more easy and now I can write tests in peace.\u003cbr /\u003e\u003cbr /\u003eTo add them just put in Gemfile:\u003cbr /\u003e\u003cbr /\u003e gem \u0026ldquo;factory_girl_rails\u0026rdquo;, \u0026ldquo;~\u0026gt; 4.0\u0026rdquo;\u003cbr /\u003e gem \u0026ldquo;faker\u0026rdquo;\u003cbr /\u003e\u003cbr /\u003eSo lets take a complex sample to explain all there is to know.\u003cbr /\u003e\u003cbr /\u003eWe have a User, the User belongs to a Company, User has many tasks.\u003cbr /\u003e\u003cbr /\u003eCompany has many irritating mandatory fields\u003cbr /\u003e\u003cbr /\u003eLets define the Company Factory:\u003cbr /\u003e\u003cbr /\u003e\u003cpre style=\"background-color: #2b2b2b; border: 0.01mm solid rgb(0, 0, 0); font-size: 12pt; line-height: 100%;\"\u003e\u003cspan style=\"color: #6d9cbe;\"\u003eFactoryGirl\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e.define \u003c/span\u003e\u003cspan style=\"color: #cc7833;\"\u003edo\u003cbr /\u003e\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e factory \u003c/span\u003e\u003cspan style=\"color: #6d9cbe;\"\u003e:company\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e \u003c/span\u003e\u003cspan style=\"color: #cc7833;\"\u003edo\u003cbr /\u003e\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e name {\u003c/span\u003e\u003cspan style=\"color: #6d9cbe;\"\u003eFaker\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e::\u003c/span\u003e\u003cspan style=\"color: #6d9cbe;\"\u003eName\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e.name}\u003cbr /\u003e trp {\u003c/span\u003e\u003cspan style=\"color: #6d9cbe;\"\u003eFaker\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e::\u003c/span\u003e\u003cspan style=\"color: #6d9cbe;\"\u003eNumber\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e.between(\u003c/span\u003e\u003cspan style=\"color: #a5c261;\"\u003e0\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e,\u003c/span\u003e\u003cspan style=\"color: #a5c261;\"\u003e10\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e)}\u003cbr /\u003e grp {\u003c/span\u003e\u003cspan style=\"color: #6d9cbe;\"\u003eFaker\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e::\u003c/span\u003e\u003cspan style=\"color: #6d9cbe;\"\u003eNumber\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e.between(\u003c/span\u003e\u003cspan style=\"color: #a5c261;\"\u003e0\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e,\u003c/span\u003e\u003cspan style=\"color: #a5c261;\"\u003e5\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e)}\u003cbr /\u003e budget {\u003c/span\u003e\u003cspan style=\"color: #6d9cbe;\"\u003eFaker\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e::\u003c/span\u003e\u003cspan style=\"color: #6d9cbe;\"\u003eNumber\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e.number(\u003c/span\u003e\u003cspan style=\"color: #a5c261;\"\u003e4\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e)}\u003cbr /\u003e cpm {\u003c/span\u003e\u003cspan style=\"color: #6d9cbe;\"\u003eFaker\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e::\u003c/span\u003e\u003cspan style=\"color: #6d9cbe;\"\u003eNumber\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e.between(\u003c/span\u003e\u003cspan style=\"color: #a5c261;\"\u003e1\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e,\u003c/span\u003e\u003cspan style=\"color: #a5c261;\"\u003e70\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e)}\u003cbr /\u003e trp_price {\u003c/span\u003e\u003cspan style=\"color: #6d9cbe;\"\u003eFaker\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e::\u003c/span\u003e\u003cspan style=\"color: #6d9cbe;\"\u003eNumber\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e.between(\u003c/span\u003e\u003cspan style=\"color: #a5c261;\"\u003e100\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e,\u003c/span\u003e\u003cspan style=\"color: #a5c261;\"\u003e700\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e)}\u003cbr /\u003e viewer {\u003c/span\u003e\u003cspan style=\"color: #6d9cbe;\"\u003eFaker\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e::\u003c/span\u003e\u003cspan style=\"color: #6d9cbe;\"\u003eNumber\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e.between(\u003c/span\u003e\u003cspan style=\"color: #a5c261;\"\u003e0\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e,\u003c/span\u003e\u003cspan style=\"color: #a5c261;\"\u003e100000\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e)}\u003cbr /\u003e total_viewer {\u003c/span\u003e\u003cspan style=\"color: #6d9cbe;\"\u003eFaker\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e::\u003c/span\u003e\u003cspan style=\"color: #6d9cbe;\"\u003eNumber\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e.between(\u003c/span\u003e\u003cspan style=\"color: #a5c261;\"\u003e0\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e,\u003c/span\u003e\u003cspan style=\"color: #a5c261;\"\u003e200000\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e)}\u003cbr /\u003e unique_viewer {\u003c/span\u003e\u003cspan style=\"color: #6d9cbe;\"\u003eFaker\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e::\u003c/span\u003e\u003cspan style=\"color: #6d9cbe;\"\u003eNumber\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e.between(\u003c/span\u003e\u003cspan style=\"color: #a5c261;\"\u003e0\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e,\u003c/span\u003e\u003cspan style=\"color: #a5c261;\"\u003e50000\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e)}\u003cbr /\u003e spots {\u003c/span\u003e\u003cspan style=\"color: #6d9cbe;\"\u003eFaker\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e::\u003c/span\u003e\u003cspan style=\"color: #6d9cbe;\"\u003eNumber\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e.between(\u003c/span\u003e\u003cspan style=\"color: #a5c261;\"\u003e0\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e,\u003c/span\u003e\u003cspan style=\"color: #a5c261;\"\u003e1000\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e)}\u003cbr /\u003e \u003c/span\u003e\u003cspan style=\"color: #cc7833;\"\u003eend\u003cbr /\u003e\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e \u003c/span\u003e\u003cspan style=\"color: #cc7833;\"\u003eend\u003c/span\u003e\u003c/pre\u003e\u003cbr /\u003eAs you can see I define lots of fields with random values.\u003cbr /\u003e\u003cbr /\u003eNow we can create a company by writing\u003cbr /\u003e\u003cblockquote class=\"tr_bq\"\u003ecreate(:company)\u003c/blockquote\u003eOr just build one (without save to db) by calling\u003cbr /\u003e\u003cbr /\u003e\u003cblockquote class=\"tr_bq\"\u003ebuild(:company) \u003c/blockquote\u003e\u003cbr /\u003eThat\u0026rsquo;s all for now, I\u0026rsquo;ll continue in part2.\u003cbr /\u003e\u003cblockquote class=\"tr_bq\"\u003e \u003c/blockquote\u003e\u003cblockquote class=\"tr_bq\"\u003e \u003c/blockquote\u003e\u003c/p\u003e","title":"Use FactoryGirl And Faker for easy data generation in unit testing (Part1)"},{"content":"If you want to provide default localization support for guest user in your website yo can locate their browser locale by the following code:\ndef extract_locale_from_header\nunless request.env[\u0026lsquo;HTTP_ACCEPT_LANGUAGE\u0026rsquo;].nil?\nreturn request.env[\u0026lsquo;HTTP_ACCEPT_LANGUAGE\u0026rsquo;].scan(/^[a-z]{2}/).first\nend\n\u0026lsquo;en\u0026rsquo;\nend\nThis way you can determine on server side the locale of the user currently entered your site.\n","permalink":"https://kinnrot.github.io/get-user-locale-from-http-headers/","summary":"\u003cp\u003eIf you want to provide default localization support for guest user in your website yo can locate their browser locale by the following code:\u003cbr /\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cpre style=\"background-color: #2b2b2b; border-color: #000000; border-style: solid; border-width: 0.01mm; font-family: monospace; font-size: 14pt; line-height: 100%; padding: 4px;\"\u003e\u003cpre style=\"border: 0.01mm solid rgb(0, 0, 0); font-size: 12pt; line-height: 100%;\"\u003e\u003cspan style=\"color: #cc7833;\"\u003edef\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e extract_locale_from_header\u003cbr /\u003e \u003c/span\u003e\u003cspan style=\"color: #cc7833;\"\u003eunless\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e request.env[\u003c/span\u003e\u003cspan style=\"color: #a5c261;\"\u003e\u0026lsquo;HTTP_ACCEPT_LANGUAGE\u0026rsquo;\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e].nil?\u003cbr /\u003e \u003c/span\u003e\u003cspan style=\"color: #cc7833;\"\u003ereturn\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e request.env[\u003c/span\u003e\u003cspan style=\"color: #a5c261;\"\u003e\u0026lsquo;HTTP_ACCEPT_LANGUAGE\u0026rsquo;\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e].scan(\u003c/span\u003e\u003cspan style=\"color: #a5c261;\"\u003e/\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e^[a-z]{2}\u003c/span\u003e\u003cspan style=\"color: #a5c261;\"\u003e/\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e).first\u003cbr /\u003e \u003c/span\u003e\u003cspan style=\"color: #cc7833;\"\u003eend\u003cbr /\u003e\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e \u003c/span\u003e\u003cspan style=\"color: #a5c261;\"\u003e\u0026lsquo;en\u0026rsquo;\u003cbr /\u003e\u003c/span\u003e\u003cspan style=\"color: #e6e1dc;\"\u003e \u003c/span\u003e\u003cspan style=\"color: #cc7833;\"\u003eend\u003c/span\u003e\u003c/pre\u003e\u003c/pre\u003e\u003cbr /\u003eThis way you can determine on server side the locale of the user currently entered your site.\u003c/p\u003e","title":"Get the user locale from http headers"},{"content":"Let\u0026rsquo;s say you have a vey important procedure that takes a while, and you need to process it in background, but you still want to execute ASAP.\nI\u0026rsquo;m using Delayed Job on Heroku, and could not find a lot of tutorials to do this simple task.\nSo here is the simplest way to achieve this ability, you can raise a process/daemon that will have only one queue to work on. (Dealyed job worker by default is queue agnostic, just process all jobs)\nIn procfile:\nurgentworker: QUEUE=urgent bundle exec rake jobs:work\nYou can call the worker in any name you want and even define multiple workers for multiple queues.\nAnd in the \u0026ldquo;urgent\u0026rdquo; job just define the queue name to be \u0026ldquo;urgent\u0026rdquo; the worker will process only jobs in this queue.\nexample:\nhandle_asynchronously :some_job, :queue =\u0026gt; \u0026ldquo;urgent\u0026rsquo;\nThis will also work for Resque.\nNotice that for rescue you can write QUEUE=* but for delayed job you can\u0026rsquo;t.\n","permalink":"https://kinnrot.github.io/dedicating-djdelayed-job-worker-to/","summary":"\u003cp\u003eLet\u0026rsquo;s say you have a vey important procedure that takes a while, and you need to process it in background, but you still want to execute ASAP.\u003cbr /\u003e\u003cbr /\u003eI\u0026rsquo;m using Delayed Job on Heroku, and could not find a lot of tutorials to do this simple task.\u003cbr /\u003e\u003cbr /\u003eSo here is the simplest way to achieve this ability, you can raise a process/daemon that will have only one queue to work on. (Dealyed job worker by default is queue agnostic, just process all jobs)\u003cbr /\u003e\u003cbr /\u003eIn procfile:\u003cbr /\u003e\u003cbr /\u003e\u003cblockquote class=\"tr_bq\"\u003eurgentworker: QUEUE=urgent bundle exec rake jobs:work\u003c/blockquote\u003e\u003cbr /\u003eYou can call the worker in any name you want and even define multiple workers for multiple queues.\u003cbr /\u003eAnd in the \u0026ldquo;urgent\u0026rdquo; job just define the queue name to be \u0026ldquo;urgent\u0026rdquo; the worker will process only jobs in this queue.\u003cbr /\u003e\u003cbr /\u003eexample:\u003cbr /\u003e\u003cbr /\u003e\u003cblockquote class=\"tr_bq\"\u003ehandle_asynchronously :some_job, :queue =\u0026gt; \u0026ldquo;urgent\u0026rsquo;\u003c/blockquote\u003e\u003cbr /\u003eThis will also work for Resque.\u003cbr /\u003e\u003cbr /\u003eNotice that for rescue you can write QUEUE=* \u003cb\u003ebut for delayed job you can\u0026rsquo;t.\u003c/b\u003e\u003c/p\u003e","title":"Dedicating a DJ(Delayed job) worker to a specific queue in heroku."},{"content":"This is an easy one, just want to make sure it\u0026rsquo;s clear.\nAdd the following field to your model:\nfield :_id, type: Moped::BSON::ObjectId\nAnd to allow setting it:\n1 def id=(id)\n2 self[:_id] = id\n3 end\nNow you can just do obj.id=[Some ObjectId] and save the object.\n","permalink":"https://kinnrot.github.io/overriding-default-id-in-mongoid/","summary":"\u003cp\u003eThis is an easy one, just want to make sure it\u0026rsquo;s clear.\u003cbr /\u003e\u003cbr /\u003eAdd the following field to your model:\u003cbr /\u003e\u003cbr /\u003e\u003cpre style=\"background-color: #2b2b2b; border-color: #000000; border-style: solid; border-width: 0.01mm; font-family: monospace; font-size: 14pt; line-height: 100%; padding: 4px;\"\u003e\u003cspan style=\"background-color: #2b2b2b; color: #e6e1dc;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/pre\u003e\u003cpre style=\"background-color: #2b2b2b; border-color: #000000; border-style: solid; border-width: 0.01mm; font-family: monospace; font-size: 14pt; line-height: 100%; padding: 4px;\"\u003e\u003cspan style=\"background-color: #2b2b2b; color: #e6e1dc;\"\u003efield \u003c/span\u003e\u003cspan style=\"background-color: #2b2b2b; color: #6d9cbe;\"\u003e:_id\u003c/span\u003e\u003cspan style=\"background-color: #2b2b2b; color: #e6e1dc;\"\u003e, type: \u003c/span\u003e\u003cspan style=\"background-color: #2b2b2b; color: #6d9cbe;\"\u003eMoped\u003c/span\u003e\u003cspan style=\"background-color: #2b2b2b; color: #e6e1dc;\"\u003e::\u003c/span\u003e\u003cspan style=\"background-color: #2b2b2b; color: #6d9cbe;\"\u003eBSON\u003c/span\u003e\u003cspan style=\"background-color: #2b2b2b; color: #e6e1dc;\"\u003e::\u003c/span\u003e\u003cspan style=\"background-color: #2b2b2b; color: #6d9cbe;\"\u003eObjectId\u003c/span\u003e\u003c/pre\u003e\u003cpre style=\"background-color: #2b2b2b; border-color: #000000; border-style: solid; border-width: 0.01mm; font-family: monospace; font-size: 14pt; line-height: 100%; padding: 4px;\"\u003e\u003c/pre\u003e\u003cpre style=\"background-color: #2b2b2b; border-color: #000000; border-style: solid; border-width: 0.01mm; font-family: monospace; font-size: 14pt; line-height: 100%; padding: 4px;\"\u003e\u003c/pre\u003e\u003cbr /\u003eAnd to allow setting it:\u003cbr /\u003e\u003cbr /\u003e\u003cpre style=\"background-color: #2b2b2b; border-color: #000000; border-style: solid; border-width: 0.01mm; font-family: monospace; font-size: 14pt; line-height: 100%; padding: 4px;\"\u003e\u003cspan style=\"background-color: #2b2b2b; color: #e6e1dc;\"\u003e1 \u003c/span\u003e\u003cspan style=\"background-color: #2b2b2b; color: #cc7833;\"\u003edef\u003c/span\u003e\u003cspan style=\"background-color: #2b2b2b; color: #e6e1dc;\"\u003e id=(id)\u003cbr /\u003e2 \u003c/span\u003e\u003cspan style=\"background-color: #2b2b2b; color: #cc7833;\"\u003eself\u003c/span\u003e\u003cspan style=\"background-color: #2b2b2b; color: #e6e1dc;\"\u003e[\u003c/span\u003e\u003cspan style=\"background-color: #2b2b2b; color: #6d9cbe;\"\u003e:_id\u003c/span\u003e\u003cspan style=\"background-color: #2b2b2b; color: #e6e1dc;\"\u003e] \u003c/span\u003e\u003cspan style=\"background-color: #2b2b2b; color: #cc7833;\"\u003e=\u003c/span\u003e\u003cspan style=\"background-color: #2b2b2b; color: #e6e1dc;\"\u003e id\u003cbr /\u003e3 \u003c/span\u003e\u003cspan style=\"background-color: #2b2b2b; color: #cc7833;\"\u003eend\u003c/span\u003e\u003c/pre\u003e\u003cbr /\u003e\u003cbr /\u003eNow you can just do obj.id=[Some ObjectId] and save the object.\u003cbr /\u003e\u003cbr /\u003e\u003cbr /\u003e\u003c/p\u003e","title":"Overriding default id in mongoid"},{"content":"Popular Science: The War Of Zeros And Ones. http://google.com/newsstand/s/CBIwvZm5zho\n","permalink":"https://kinnrot.github.io/nice-post-about-cyber-war/","summary":"\u003cp\u003ePopular Science: The War Of Zeros And Ones. \u003ca href=\"http://google.com/newsstand/s/CBIwvZm5zho\"\u003ehttp://google.com/newsstand/s/CBIwvZm5zho\u003c/a\u003e\u003c/p\u003e","title":"Nice post about cyber war"},{"content":"Cluster TV is looking for it's next programmer/Superstar!\nIf you can:\n* Write code like an Effin' machine* Test your OWN code* Speak English like it's your mother's tongue* Handle challenges* Be self-driven \u0026amp; independent\nWe would also appreciate if you'll have:\n* Great communications skills* Independent thinking* Passion to learn new things* RoR or Angular experience* Coffee script knowledge* NOSQL understanding\nThen we want you!\nWhat we offer:\n* Great and professional team.* Opportunity to become an integral part of an innovative TV solution.* A chance to learn from the best in the industry.* Full time job in the Tel Aviv area.* Unlimited supply of food and beer. Really.* Flexible work hours.\nIf you like what you see and have da skillz, drop us an email at chen@clustertv.com\nOr, call me\u0026nbsp;tel: +972 542124335.\nGood luck!","permalink":"https://kinnrot.github.io/clustetv-is-hiring/","summary":"\u003cdiv dir=\"ltr\" style=\"line-height: 1.15; margin-bottom: 0pt; margin-top: 0pt;\"\u003e\u003cdiv class=\"p1\"\u003eCluster TV is looking for it's next programmer/Superstar!\u003c/div\u003e\u003cdiv class=\"p2\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv class=\"p1\"\u003eIf you can:\u003c/div\u003e\u003cdiv class=\"p2\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv class=\"p1\"\u003e* Write code like an Effin' machine\u003c/div\u003e\u003cdiv class=\"p1\"\u003e* Test your OWN code\u003c/div\u003e\u003cdiv class=\"p1\"\u003e* Speak English like it's your mother's tongue\u003c/div\u003e\u003cdiv class=\"p1\"\u003e* Handle challenges\u003c/div\u003e\u003cdiv class=\"p1\"\u003e* Be self-driven \u0026amp; independent\u003c/div\u003e\u003cdiv class=\"p2\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv class=\"p2\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv class=\"p1\"\u003eWe would also appreciate if you'll have:\u003c/div\u003e\u003cdiv class=\"p2\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv class=\"p1\"\u003e* Great communications skills\u003c/div\u003e\u003cdiv class=\"p1\"\u003e* Independent thinking\u003c/div\u003e\u003cdiv class=\"p1\"\u003e* Passion to learn new things\u003c/div\u003e\u003cdiv class=\"p1\"\u003e* RoR or Angular experience\u003c/div\u003e\u003cdiv class=\"p1\"\u003e* Coffee script knowledge\u003c/div\u003e\u003cdiv class=\"p1\"\u003e* NOSQL understanding\u003c/div\u003e\u003cdiv class=\"p2\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv class=\"p1\"\u003eThen we want you!\u003c/div\u003e\u003cdiv class=\"p2\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv class=\"p1\"\u003eWhat we offer:\u003c/div\u003e\u003cdiv class=\"p2\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv class=\"p1\"\u003e* Great and professional team.\u003c/div\u003e\u003cdiv class=\"p1\"\u003e* Opportunity to become an integral part of an innovative TV solution.\u003c/div\u003e\u003cdiv class=\"p1\"\u003e* A chance to learn from the best in the industry.\u003c/div\u003e\u003cdiv class=\"p1\"\u003e* Full time job in the Tel Aviv area.\u003c/div\u003e\u003cdiv class=\"p1\"\u003e* Unlimited supply of food and beer. Really.\u003c/div\u003e\u003cdiv class=\"p1\"\u003e* Flexible work hours.\u003c/div\u003e\u003cdiv class=\"p2\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv class=\"p1\"\u003eIf you like what you see and have da skillz, drop us an email at \u003ca href=\"mailto:chen@clustertv.com\"\u003echen@clustertv.com\u003c/a\u003e\u003cbr /\u003eOr, call me\u0026nbsp;\u003ca href=\"tel: +972 542124335\" target=\"_blank\"\u003etel: +972 542124335\u003c/a\u003e\u003cspan style=\"line-height: 1.15;\"\u003e.\u003c/span\u003e\u003c/div\u003e\u003cdiv class=\"p2\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cbr /\u003e\u003cdiv class=\"p1\"\u003eGood luck!\u003c/div\u003e\u003c/div\u003e","title":"ClusteTV is hiring"},{"content":"It took me about an hours and a half because google is not up to date, so here it is:\nFirst - as a rails developer, if you don\u0026rsquo;t have node.js, this is the time to install it.\nIf you don\u0026rsquo;t use RubyMine as you IDE, I recommend it as well, but whatever you prefer is fine by me.\nHere you\u0026rsquo;ll fins instructions about karma installation, follow them carefully.\nYou\u0026rsquo;ll see that you need to tell karma where is your sources and test sources.\nI\u0026rsquo;m working with jasmine, and using angular as a gem, check my configuration:\nframeworks: [\u0026lsquo;jasmine\u0026rsquo;],\n// list of files / patterns to load in the browser\nfiles: [\n//libs\n\u0026lsquo;http://0.0.0.0:3000/assets/application.js\u0026rsquo;,\n\u0026rsquo;/Users/chen/.rvm/gems/ruby-1.9.3-p448/gems/angularjs-rails-1.2.9/vendor/assets/javascripts/angular-mocks.js\u0026rsquo;,\n\u0026lsquo;spec/javascripts/controllers/sample.js\u0026rsquo;,\n\u0026lsquo;spec/javascripts/controllers//_spec.js.coffee\u0026rsquo;,\n\u0026lsquo;spec/javascripts/controllers//*_spec.js.coffee\u0026rsquo;,\n\u0026lsquo;spec/javascripts/controllers//_spec.coffee\u0026rsquo;,\n\u0026lsquo;spec/javascripts/controllers/**/_spec.js\u0026rsquo;\n]\nTo things you should notice:\n1. I use rails assets pipeline to give all my app code js, (just run your server before you test)\n2. I add the angular mocks lib\nAll other stuff are basic, I got code in coffee and js so needed a little more lines to find all my tests.\nthis is the way to make this work pretty fast.\n","permalink":"https://kinnrot.github.io/karma-rails-angular-jasmine-testing-set/","summary":"\u003cp\u003eIt took me about an hours and a half because google is not up to date, so here it is:\u003cbr /\u003e\u003cbr /\u003eFirst - as a rails developer, if you don\u0026rsquo;t have node.js, this is the time to \u003ca href=\"http://nodejs.org/\"\u003einstall\u003c/a\u003e it.\u003cbr /\u003eIf you don\u0026rsquo;t use RubyMine as you IDE, I recommend it as well, but whatever you prefer is fine by me.\u003cbr /\u003e\u003ca href=\"http://www.jetbrains.com/ruby/webhelp/preparing-to-use-karma-test-runner.html\"\u003eHere\u003c/a\u003e you\u0026rsquo;ll fins instructions about karma installation, follow them carefully.\u003cbr /\u003e\u003cbr /\u003eYou\u0026rsquo;ll see that you need to tell karma where is your sources and test sources.\u003cbr /\u003e\u003cbr /\u003eI\u0026rsquo;m working with jasmine, and using angular as a gem, check my configuration:\u003cbr /\u003e\u003cbr /\u003eframeworks: [\u0026lsquo;jasmine\u0026rsquo;],\u003cbr /\u003e\u003cbr /\u003e\u003cbr /\u003e // list of files / patterns to load in the browser\u003cbr /\u003e files: [\u003cbr /\u003e //libs\u003cbr /\u003e\u003cbr /\u003e \u0026lsquo;http://0.0.0.0:3000/assets/application.js\u0026rsquo;,\u003cbr /\u003e \u003cspan style=\"background-color: yellow;\"\u003e\u0026rsquo;/Users/chen/.rvm/gems/ruby-1.9.3-p448/gems/angularjs-rails-1.2.9/vendor/assets/javascripts/angular-mocks.js\u0026rsquo;,\u003c/span\u003e\u003cbr /\u003e \u0026lsquo;spec/javascripts/controllers/sample.js\u0026rsquo;,\u003cbr /\u003e\u003cbr /\u003e \u0026lsquo;spec/javascripts/controllers/\u003cem\u003e/\u003c/em\u003e_spec.js.coffee\u0026rsquo;,\u003cbr /\u003e \u0026lsquo;spec/javascripts/controllers/\u003cstrong\u003e/*_spec.js.coffee\u0026rsquo;,\u003cbr /\u003e \u0026lsquo;spec/javascripts/controllers/\u003c/strong\u003e/\u003cem\u003e_spec.coffee\u0026rsquo;,\u003cbr /\u003e \u0026lsquo;spec/javascripts/controllers/**/\u003c/em\u003e_spec.js\u0026rsquo;\u003cbr /\u003e]\u003cbr /\u003e\u003cbr /\u003e\u003cbr /\u003eTo things you should notice:\u003cbr /\u003e1. I use rails assets pipeline to give all my app code js, (just run your server before you test)\u003cbr /\u003e2. I add the angular mocks lib\u003cbr /\u003e\u003cbr /\u003e\u003cbr /\u003eAll other stuff are basic, I got code in coffee and js so needed a little more lines to find all my tests.\u003cbr /\u003e\u003cbr /\u003ethis is the way to make this work pretty fast.\u003cbr /\u003e\u003cbr /\u003e\u003c/p\u003e","title":"Karma Rails Angular Jasmine testing - set up in 5 minutes"},{"content":"I found it very annoying that php data to excel is not so straight forward as one might think ,lots of wrong stuff here.\nThe thing is, as a developer you don\u0026rsquo;t know a lot about encoding.\nSo you don\u0026rsquo;t really think about it until you have bugs, than you start searching for a better solution, I found this.\nMeaning you manually convert encoding to support excel, and add BOM.\nJust wanted to gather a few links together for future use.\nEnjoy.\n","permalink":"https://kinnrot.github.io/export-hebrew-or-any-non-english/","summary":"\u003cp\u003eI found it very annoying that php data to excel is not so straight forward as one might think \u003ca href=\"http://stackoverflow.com/questions/15699301/export-mysql-data-to-excel-in-php\"\u003e,lots of wrong stuff\u003c/a\u003e here.\u003cbr /\u003e\u003cbr /\u003eThe thing is, as a developer you don\u0026rsquo;t know a lot about \u003ca href=\"http://www.joelonsoftware.com/articles/Unicode.html\"\u003eencoding\u003c/a\u003e.\u003cbr /\u003e\u003cbr /\u003eSo you don\u0026rsquo;t really think about it until you have bugs, than you start searching for a better solution, I found \u003ca href=\"http://stackoverflow.com/a/3466065/67505\"\u003ethis\u003c/a\u003e.\u003cbr /\u003e\u003cbr /\u003eMeaning you manually convert encoding to support excel, and add \u003ca href=\"http://en.wikipedia.org/wiki/Byte_order_mark\"\u003eBOM\u003c/a\u003e.\u003cbr /\u003e\u003cbr /\u003eJust wanted to gather a few links together for future use.\u003cbr /\u003e\u003cbr /\u003eEnjoy.\u003cbr /\u003e\u003cbr /\u003e\u003cbr /\u003e\u003c/p\u003e","title":"Export Hebrew (or any non english language) with php to excel"},{"content":"As a developer@widdit\u0026rsquo;s incredible android team, I decided to write a how to embed Widdit\u0026rsquo;s home base sdk in 5 minutes guide, so here it is:\nStep 1:\ngo to widdit.com and create an account.\nStep 2:\ncreate your first home base in the home base section at widdit site.\nstep 3: go to sdk\u0026rsquo;s tab and follow the installation instructions\nstep 4:\nupload your new apk to the market\nstep 5:\nmake money!\nGood luck.\n","permalink":"https://kinnrot.github.io/home-base-sdk/","summary":"\u003cp\u003eAs a developer@widdit\u0026rsquo;s incredible android team, I decided to write a how to embed Widdit\u0026rsquo;s home base sdk in 5 minutes guide, so here it is:\u003cbr /\u003e\u003cbr /\u003e\u003cb\u003eStep 1:\u003c/b\u003e\u003cbr /\u003ego to widdit.com and create an account.\u003cbr /\u003e\u003cbr /\u003e\u003cb\u003eStep 2:\u003c/b\u003e\u003cbr /\u003ecreate your first home base in the home base section at widdit site.\u003cbr /\u003e\u003cbr /\u003e\u003cb\u003estep 3: \u003c/b\u003e\u003cbr /\u003ego to sdk\u0026rsquo;s tab and follow the installation instructions\u003cbr /\u003e\u003cbr /\u003e\u003cb\u003estep 4:\u003c/b\u003e\u003cbr /\u003eupload your new apk to the market\u003cbr /\u003e\u003cbr /\u003e\u003cb\u003estep 5:\u003c/b\u003e\u003cbr /\u003emake money!\u003cbr /\u003e\u003cbr /\u003eGood luck.\u003cbr /\u003e\u003cbr /\u003e\u003cbr /\u003e\u003c/p\u003e","title":"Home Base SDK"},{"content":"Never create multiple instances of a controller that generates the same view, cause you're event's registrations will be duplicated over and over again!\n","permalink":"https://kinnrot.github.io/spinejs-tip/","summary":"\u003cp dir=ltr\u003eNever create multiple instances of a controller that generates the same view, cause you're event's registrations will be duplicated over and over again!\u003c/p\u003e","title":"SpineJS Tip"},{"content":"Just noticed this method available from API 11 only,\u0026nbsp; so you should find another implementation to avoid unexpected behaviour.\nOr don't call the execute method,\u0026#160; why?\u0026#160; If you'll check documentation you'll see that in some versions of android all tasks will run synchronouslly on the same background thread and on some versions it'll run on a pool of threads. Always use the executeOnExecutor option for consistent behaviour between platform version and avoid unexpected behaviour.\nSee docs\n","permalink":"https://kinnrot.github.io/avoid-usage-of-asynctask-class-on/","summary":"\u003cdiv\u003e\u003cp\u003eJust noticed this method available from API 11 only,\u0026nbsp; so you should find another implementation to avoid unexpected behaviour.\u003c/p\u003e\u003cp\u003eOr don't call the execute method,\u0026#160; why?\u0026#160; If you'll check documentation you'll see that in some versions of android all tasks will run synchronouslly on the same background thread and on some versions it'll run on a pool of threads. Always use the executeOnExecutor option for consistent behaviour between platform version and avoid unexpected behaviour.\u003c/p\u003e","title":"Avoid usage of AsyncTask Class on android"},{"content":"People probably don't read/understand what's new in an app when they update it.\u0026nbsp; Skype did a very nice screen that shows you that something did change\n","permalink":"https://kinnrot.github.io/nice-idea-for-what-new-in-my-app/","summary":"\u003cdiv\u003e\u003cp\u003ePeople probably don't read/understand what's new in an app when they update it.\u0026nbsp; Skype did a very nice screen that shows you that something did \u003cu\u003echange\u003c/u\u003e\u003c/p\u003e\u003cbr/\u003e\u003cimg src='http://lh5.ggpht.com/-bYmkNttd2ag/UEBwPRS7gPI/AAAAAAAAGRA/3w6ThmzjH2c/Screenshot_2012-08-31-11-02-09.png' /\u003e\u003c/div\u003e","title":"Nice idea for what's new in my app"},{"content":"Hi,\nA few months ago I discovered this new stuff called coffee script, and thought to myself, \u0026ldquo;this is awesome I\u0026rsquo;ll write less and do more\u0026rdquo; Today, I tried to continue a development of a pretty fat client side and tried to find myself in the 1000 lines of code I wrote so far (not so many). It was pretty hard, and I\u0026rsquo;m the only programmer for now, can\u0026rsquo;t imagine how a new programmer would enter to this project.\nSo\u0026hellip;\ncoffee-script is java-script that look better, no other benefits, and if you plan to write a little more than 200 lines of code, consider using some strongly typed language(that can generate debugable java script) with good IDE that\u0026rsquo;ll help you maintain your code. ","permalink":"https://kinnrot.github.io/coffee-script-is-another-piece-of-shit/","summary":"\u003cp\u003eHi,\u003cbr /\u003e\u003cbr /\u003eA few months ago I discovered this new stuff called coffee script, and thought to myself, \u0026ldquo;this is awesome I\u0026rsquo;ll write less and do more\u0026rdquo; Today, I tried to continue a development of a pretty fat client side and tried to find myself in the 1000 lines of code I wrote so far (not so many). It was pretty hard, and I\u0026rsquo;m the only programmer for now, can\u0026rsquo;t imagine how a new programmer would enter to this project.\u003cbr /\u003e\u003cbr /\u003e\u003cspan style=\"background-color: white;\"\u003eSo\u0026hellip;\u003c/span\u003e\u003cbr /\u003e\u003cspan style=\"background-color: white;\"\u003ecoffee-script is \u003c/span\u003e\u003cspan style=\"background-color: white;\"\u003ejava-script that look better, no other benefits, and if you plan to write a little more than 200 lines of code, consider using some strongly typed language(that can generate debugable java script) with good IDE that\u0026rsquo;ll help you maintain your code. \u003c/span\u003e\u003c/p\u003e","title":"coffee-script is just another version of javascript"},{"content":"I guess it\u0026rsquo;s nice to have so here you go\n/\nbasically allow a php script to return a response and continue with\n* code execution, good for statistics.\n* before echo anything to user call begin and after call end, than you can continue doing stuff\n/\nclass ScriptContinuationManager\n{\n/**\nthis is the point where we need to give a sign to this class\n* that we wanna write our response.\n* @return void\n/\npublic function beginRespone()\n{\nob_end_clean();\nheader(\u0026ldquo;Connection: close\u0026rdquo;);\nignore_user_abort(); // optional\nob_start();\n}\n/\n* after this function execution the response will be sent to the\n* client, and code continue without client need to wait.\n*/\npublic function endResponse()\n{\n$size = ob_get_length();\nheader(\u0026ldquo;Content-Length: $size\u0026rdquo;);\nob_end_flush(); // Strange behaviour, will not work\nflush(); // Unless both are called !\n}\n}\n","permalink":"https://kinnrot.github.io/php-post-response-script-execution/","summary":"\u003cp\u003eI guess it\u0026rsquo;s nice to have so here you go\u003cbr /\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cpre class=\"lang-php prettyprint\" style=\"background-color: #eeeeee; border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; font-size: 14px; line-height: 18px; margin-bottom: 10px; max-height: 600px; overflow: auto; padding: 5px; text-align: left; vertical-align: baseline; width: auto;\"\u003e\u003ccode style=\"border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e\u003cspan class=\"com\" style=\"background-color: transparent; border: 0px; color: grey; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e/\u003cem\u003e\u003cbr /\u003e \u003c/em\u003e basically allow a php script to return a response and continue with\u003cbr /\u003e * code execution, good for statistics.\u003cbr /\u003e * before echo anything to user call begin and after call end, than you can continue doing stuff\u003cbr /\u003e \u003cem\u003e/\u003c/span\u003e\u003cspan class=\"pln\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan class=\"kwd\" style=\"background-color: transparent; border: 0px; color: darkblue; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003eclass\u003c/span\u003e\u003cspan class=\"pln\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e \u003c/span\u003e\u003cspan class=\"typ\" style=\"background-color: transparent; border: 0px; color: #2b91af; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003eScriptContinuationManager\u003c/span\u003e\u003cspan class=\"pln\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan class=\"pun\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e{\u003c/span\u003e\u003cspan class=\"pln\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e\u003cbr /\u003e \u003c/span\u003e\u003cspan class=\"com\" style=\"background-color: transparent; border: 0px; color: grey; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e/**\u003cbr /\u003e \u003c/em\u003e this is the point where we need to give a sign to this class\u003cbr /\u003e * that we wanna write our response.\u003cbr /\u003e * @return void\u003cbr /\u003e \u003cem\u003e/\u003c/span\u003e\u003cspan class=\"pln\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e\u003cbr /\u003e \u003c/span\u003e\u003cspan class=\"kwd\" style=\"background-color: transparent; border: 0px; color: darkblue; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003epublic\u003c/span\u003e\u003cspan class=\"pln\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e \u003c/span\u003e\u003cspan class=\"kwd\" style=\"background-color: transparent; border: 0px; color: darkblue; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003efunction\u003c/span\u003e\u003cspan class=\"pln\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e beginRespone\u003c/span\u003e\u003cspan class=\"pun\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e()\u003c/span\u003e\u003cspan class=\"pln\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e\u003cbr /\u003e \u003c/span\u003e\u003cspan class=\"pun\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e{\u003c/span\u003e\u003cspan class=\"pln\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e\u003cbr /\u003e ob_end_clean\u003c/span\u003e\u003cspan class=\"pun\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e();\u003c/span\u003e\u003cspan class=\"pln\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e\u003cbr /\u003e header\u003c/span\u003e\u003cspan class=\"pun\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e(\u003c/span\u003e\u003cspan class=\"str\" style=\"background-color: transparent; border: 0px; color: maroon; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e\u0026ldquo;Connection: close\u0026rdquo;\u003c/span\u003e\u003cspan class=\"pun\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e);\u003c/span\u003e\u003cspan class=\"pln\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e\u003cbr /\u003e ignore_user_abort\u003c/span\u003e\u003cspan class=\"pun\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e();\u003c/span\u003e\u003cspan class=\"pln\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e \u003c/span\u003e\u003cspan class=\"com\" style=\"background-color: transparent; border: 0px; color: grey; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e// optional\u003c/span\u003e\u003cspan class=\"pln\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e\u003cbr /\u003e ob_start\u003c/span\u003e\u003cspan class=\"pun\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e();\u003c/span\u003e\u003cspan class=\"pln\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e\u003cbr /\u003e\u003cbr /\u003e \u003c/span\u003e\u003cspan class=\"pun\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e}\u003c/span\u003e\u003cspan class=\"pln\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e\u003cbr /\u003e\u003cbr /\u003e \u003c/span\u003e\u003cspan class=\"com\" style=\"background-color: transparent; border: 0px; color: grey; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e/\u003c/em\u003e\u003cbr /\u003e * after this function execution the response will be sent to the\u003cbr /\u003e * client, and code continue without client need to wait.\u003cbr /\u003e */\u003c/span\u003e\u003cspan class=\"pln\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e\u003cbr /\u003e \u003c/span\u003e\u003cspan class=\"kwd\" style=\"background-color: transparent; border: 0px; color: darkblue; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003epublic\u003c/span\u003e\u003cspan class=\"pln\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e \u003c/span\u003e\u003cspan class=\"kwd\" style=\"background-color: transparent; border: 0px; color: darkblue; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003efunction\u003c/span\u003e\u003cspan class=\"pln\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e endResponse\u003c/span\u003e\u003cspan class=\"pun\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e()\u003c/span\u003e\u003cspan class=\"pln\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e\u003cbr /\u003e \u003c/span\u003e\u003cspan class=\"pun\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e{\u003c/span\u003e\u003cspan class=\"pln\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e\u003cbr /\u003e $size \u003c/span\u003e\u003cspan class=\"pun\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e=\u003c/span\u003e\u003cspan class=\"pln\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e ob_get_length\u003c/span\u003e\u003cspan class=\"pun\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e();\u003c/span\u003e\u003cspan class=\"pln\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e\u003cbr /\u003e header\u003c/span\u003e\u003cspan class=\"pun\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e(\u003c/span\u003e\u003cspan class=\"str\" style=\"background-color: transparent; border: 0px; color: maroon; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e\u0026ldquo;Content-Length: $size\u0026rdquo;\u003c/span\u003e\u003cspan class=\"pun\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e);\u003c/span\u003e\u003cspan class=\"pln\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e\u003cbr /\u003e ob_end_flush\u003c/span\u003e\u003cspan class=\"pun\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e();\u003c/span\u003e\u003cspan class=\"pln\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e \u003c/span\u003e\u003cspan class=\"com\" style=\"background-color: transparent; border: 0px; color: grey; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e// Strange behaviour, will not work\u003c/span\u003e\u003cspan class=\"pln\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e\u003cbr /\u003e flush\u003c/span\u003e\u003cspan class=\"pun\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e();\u003c/span\u003e\u003cspan class=\"pln\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e \u003c/span\u003e\u003cspan class=\"com\" style=\"background-color: transparent; border: 0px; color: grey; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e// Unless both are called !\u003c/span\u003e\u003cspan class=\"pln\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e\u003cbr /\u003e\u003cbr /\u003e \u003c/span\u003e\u003cspan class=\"pun\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e}\u003c/span\u003e\u003cspan class=\"pln\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan class=\"pun\" style=\"background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;\"\u003e}\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/p\u003e","title":"php post response script execution"},{"content":"For all you android developers, If you ever installed a new rom and didn\u0026rsquo;t see any logs from your cat, just do this:\nhttp://stackoverflow.com/a/7272831/67505\n","permalink":"https://kinnrot.github.io/for-all-you-android-developers-if-you/","summary":"\u003cp\u003eFor all you android developers, If you ever installed a new rom and didn\u0026rsquo;t see any logs from your cat, just do this:\u003cbr /\u003e\u003cbr /\u003e\u003ca href=\"http://stackoverflow.com/a/7272831/67505\"\u003e\u003ca href=\"http://stackoverflow.com/a/7272831/67505\"\u003ehttp://stackoverflow.com/a/7272831/67505\u003c/a\u003e\u003c/a\u003e\u003c/p\u003e","title":""},{"content":"After a few hours of fighting with google I decided to write it all here:\n*This post is more relevant for windows users but can help others.\nWhat do you need to have:\nFirst you need to have ruby 1.9.2+\nDevkit\nthen you need rails 3+\nthen u need the bundler gem\nthen go to getting started with mongoid then install mongo locally\nthen check it all good\nthen add account in heroku\nthen create app\nthen add your key\nthen push\n","permalink":"https://kinnrot.github.io/rails-mongo-heroku-how/","summary":"\u003cp dir=ltr\u003eAfter a few hours of fighting with google I decided to write it all here:\u003c/p\u003e\u003cp dir=ltr\u003e*This post is more relevant for windows users but can help others.\u003c/p\u003e\u003cp dir=ltr\u003eWhat do you need to have:\u003cbr\u003eFirst you need to have ruby 1.9.2+\u003cbr\u003eDevkit\u003cbr\u003ethen you need rails 3+\u003cbr\u003ethen u need the bundler gem\u003cbr\u003ethen go to getting started with mongoid \u003cbr\u003ethen install mongo locally\u003cbr\u003ethen check it all good\u003cbr\u003ethen add account in heroku\u003cbr\u003ethen create app\u003cbr\u003ethen add your key\u003cbr\u003ethen push\u003c/p\u003e","title":"Rails + Mongo + Heroku how?"},{"content":"This weekend I learned a new programming language, called coffee script, It\u0026rsquo;s not a real language it\u0026rsquo;s actually compiled to JavaScript, so it\u0026rsquo;s a way to write JavaScript differently.\nAfter a little hands-on and one book read I can say that this is a good language for experienced and non experienced JavaScript programmers. What\u0026rsquo;s awesome about this language is that is fills like someone took all the good stuff from ruby python and java, and put it in one language that eliminates all the crap you need to take form JavaScript programming.\nI can start writing all the good stuff about coffee but there is no need just dive into http://coffeescript.org/ and you\u0026rsquo;ll understand all the benefits.\n","permalink":"https://kinnrot.github.io/coffeescript-language-review/","summary":"\u003cp\u003eThis weekend I learned a new programming language, called coffee script, It\u0026rsquo;s not a real language it\u0026rsquo;s actually compiled to JavaScript, so it\u0026rsquo;s a way to write JavaScript differently.\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eAfter a little hands-on and one \u003ca href=\"http://arcturo.github.com/library/coffeescript/index.html\"\u003ebook\u003c/a\u003e read I can say that this is a good language for experienced and non experienced JavaScript programmers. \u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eWhat\u0026rsquo;s awesome about this language is that is fills like someone took all the good stuff from ruby python and java, and put it in one language that eliminates all the crap you need to take form JavaScript programming.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eI can start writing all the good stuff about coffee but there is no need just dive into \u003c/div\u003e\u003cdiv\u003e\u003ca href=\"http://coffeescript.org/\"\u003e\u003ca href=\"http://coffeescript.org/\"\u003ehttp://coffeescript.org/\u003c/a\u003e\u003c/a\u003e and you\u0026rsquo;ll understand all the benefits.\u003c/div\u003e\u003c/p\u003e","title":"CoffeeScript - language review"},{"content":"One more thing,\nIf you do stuff like put instances of classes inside a session and expect to call methods of this classes later, you must put the session start after you include the classes definitions.\nBut I suggest not to do this kind of stuff.\n","permalink":"https://kinnrot.github.io/php-sessions/","summary":"\u003cp\u003eOne more thing,\u003cbr /\u003e\u003cbr /\u003eIf you do stuff like put instances of classes inside a session and expect to call methods of this classes later, you must put the session start after you include the classes definitions.\u003cbr /\u003e\u003cbr /\u003eBut I suggest not to do this kind of stuff.\u003c/p\u003e","title":"PHP Sessions"},{"content":"There is too much information about problems with sessions in PHP, every dude got it\u0026rsquo;s own problem and it\u0026rsquo;s own solution.\nThe probability that the problem you experiencing is the same is very low. So here is what my little (and very annoying) google journey came up to:\nYou must call session_start(); on each pageIf you use the header(\u0026lsquo;Location: blabla\u0026rsquo;); you should use relative url to keep preserve session some people say before using the header action you need to call session_write_close(); - I\u0026rsquo;m not using it.session_write_close(); could be the reason to your problems, cause after calling it you can\u0026rsquo;t modify the session (in the current http context), that was my problem.on php docs, they say that \u0026ldquo;Session ID is not passed with Location header even if session.use_trans_sid is enabled. It must by passed manually using SID constant.\u0026quot;So first make sure you use session start, if you passed this search for voodoos like session_write_close() in the middle of your infrastructure and remove them.\nIf I didn\u0026rsquo;t help, continue the journey.\n","permalink":"https://kinnrot.github.io/php-sessions-stuff-to-check-when-things/","summary":"\u003cp\u003e\u003cspan style=\"font-family: 'Courier New', Courier, monospace;\"\u003eThere is too much information about problems with sessions in PHP, every dude got it\u0026rsquo;s own problem and it\u0026rsquo;s own solution.\u003c/span\u003e\u003cbr /\u003e\u003cspan style=\"font-family: 'Courier New', Courier, monospace;\"\u003eThe probability that the problem you experiencing is the same is very low. \u003c/span\u003e\u003cbr /\u003e\u003cspan style=\"font-family: 'Courier New', Courier, monospace;\"\u003eSo here is what my little (and very annoying) google journey came up to:\u003c/span\u003e\u003cbr /\u003e\u003cspan style=\"font-family: 'Courier New', Courier, monospace;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cul\u003e\u003cli\u003e\u003cspan style=\"font-family: 'Courier New', Courier, monospace;\"\u003eYou must call session_start(); on each page\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style=\"font-family: 'Courier New', Courier, monospace;\"\u003eIf you use the header(\u0026lsquo;Location: blabla\u0026rsquo;); you should use relative url to keep preserve session \u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style=\"font-family: 'Courier New', Courier, monospace;\"\u003esome people say before using the header action you need to call \u003cspan class=\"methodname\" style=\"background-color: white;\"\u003esession_write_close(); - I\u0026rsquo;m not using it.\u003c/span\u003e\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan class=\"methodname\" style=\"background-color: white;\"\u003e\u003cspan style=\"font-family: 'Courier New', Courier, monospace;\"\u003esession_write_close(); could be the reason to your problems, cause after calling it you can\u0026rsquo;t modify the session (in the current http context), that was my problem.\u003c/span\u003e\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style=\"font-family: 'Courier New', Courier, monospace;\"\u003eon php docs, they say that \u0026ldquo;\u003cspan style=\"background-color: white;\"\u003eSession ID is not passed with Location header even if \u003c/span\u003e\u003ca class=\"link\" href=\"http://www.php.net/manual/en/session.configuration.php#ini.session.use-trans-sid\" style=\"background-color: white; border-bottom-color: rgb(0, 0, 153); border-bottom-style: solid; border-bottom-width: 1px; color: #000099; text-decoration: none;\"\u003esession.use_trans_sid\u003c/a\u003e\u003cspan style=\"background-color: white;\"\u003e is enabled. It must by passed manually using \u003c/span\u003e\u003cspan style=\"background-color: white;\"\u003e\u003ctt\u003eSID\u003c/tt\u003e\u003c/span\u003e\u003cspan style=\"background-color: white;\"\u003e constant.\u0026quot;\u003c/span\u003e\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003e\u003cspan style=\"font-family: 'Courier New', Courier, monospace;\"\u003eSo first make sure you use session start, if you passed this search for voodoos like \u003cspan class=\"methodname\" style=\"background-color: white;\"\u003esession_write_close() in the middle of your infrastructure and remove them.\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style=\"font-family: 'Courier New', Courier, monospace;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style=\"font-family: 'Courier New', Courier, monospace;\"\u003eIf I didn\u0026rsquo;t help, continue the journey.\u003c/span\u003e\u003c/div\u003e\u003c/p\u003e","title":"PHP sessions - stuff to check when things goes wrong."},{"content":"I'm about to end my first gig(already end! yay I'm free!) as a programmer, and want to leave a clean desk. So here is a list of things I'm doing and suggest you all do before you move to your next gig:\n1. Write about your major infrastructure developments on your wiki or any other system you got, in an easy to understand language.\n2. Start lecturing your co-workers about complex parts you developed.\n3. Make sure you got full code coverage with unit tests.\n4. Search for to-do comments and make sure you do those todo's.\n5. If you got unfinished work and think it's worth something make sure someone complete.\nAnd the most important: change your phone number :-) (Bazinga).\n","permalink":"https://kinnrot.github.io/end-of-job-check-list/","summary":"\u003cdiv\u003e\u003cdiv\u003eI'm about to end my first gig(already end! yay I'm free!) as a programmer, and want to leave a clean desk. So here is a list of things I'm doing and suggest you all do before you move to your next gig:\u003cbr /\u003e\u003cbr /\u003e1. Write about your major infrastructure developments on your wiki or any other system you got, in an easy to understand language.\u003cbr /\u003e2. Start lecturing your co-workers about complex parts you developed.\u003cbr /\u003e3. Make sure you got full code coverage with unit tests.\u003cbr /\u003e4. Search for to-do comments and make sure you do those todo's.\u003cbr /\u003e5. If you got unfinished work and think it's worth something make sure someone complete.\u003cbr /\u003e\u003cbr /\u003eAnd the most important: change your phone number :-) (Bazinga).\u003cbr /\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e","title":"End of job check list"},{"content":"The Startup Gamble [infographic] | Daily Infographic\n","permalink":"https://kinnrot.github.io/startups-reshare-very-nice-research/","summary":"\u003cdiv\u003e\u003cp\u003e\u003ca href=\"http://dailyinfographic.com/the-startup-gamble-infographic?utm_source=feedburner\u0026utm_medium=feed\u0026utm_campaign=Feed%3A+DailyInfographic+%28Daily+Infographic%29\"\u003eThe Startup Gamble [infographic] | Daily Infographic\u003c/a\u003e\u003cbr\u003e\u003c/p\u003e\u003c/div\u003e","title":"Startups: reshare very nice research"},{"content":"Didn\u0026rsquo;t find a lot about it on internet so:\nFile-\u0026gt;Settings-\u0026gt;Editor-\u0026gt;colors \u0026amp; fonts-\u0026gt;Font\nfirst save as current schema\nthan click the \u0026hellip; button choose Consolas and set size to 14\nlooks much better!\n","permalink":"https://kinnrot.github.io/rubymine-recommended-font-for-windows/","summary":"\u003cp\u003eDidn\u0026rsquo;t find a lot about it on internet so:\u003cbr /\u003e\u003cbr /\u003eFile-\u0026gt;Settings-\u0026gt;Editor-\u0026gt;colors \u0026amp; fonts-\u0026gt;Font\u003cbr /\u003e first save as current schema\u003cbr /\u003ethan click the \u0026hellip; button choose Consolas and set size to 14\u003cbr /\u003e\u003cbr /\u003elooks much better!\u003c/p\u003e","title":"Rubymine recommended font for windows"},{"content":"Warning! just figure out a mistake that can happen to every other programmer, and even brogrammers.\nI defined a method on my model that has the same name as one of the field of the model, because I used a dynamic language (ruby on rails) it was pretty hard to understand this issue (took me more than 1 hour).\nSo a little tip:\nWhen thinking about names of actions and fields of your model, work with conventions and guidelines like:\nDon\u0026rsquo;t name your fields after action names!!!\nthat\u0026rsquo;s it.\n","permalink":"https://kinnrot.github.io/mvc-frameworks-and-dynamic-languages/","summary":"\u003cp\u003eWarning! just figure out a mistake that can happen to every other programmer, and even brogrammers.\u003cbr /\u003e\u003cbr /\u003eI defined a method on my model that has the same name as one of the field of the model, because I used a dynamic language (ruby on rails) it was pretty hard to understand this issue (took me more than 1 hour).\u003cbr /\u003e\u003cbr /\u003eSo a little tip:\u003cbr /\u003e\u003cbr /\u003eWhen thinking about names of actions and fields of your model, work with conventions and guidelines like:\u003cbr /\u003e\u003cb\u003eDon\u0026rsquo;t name your fields after action names!!!\u003c/b\u003e\u003cbr /\u003e\u003cb\u003e\u003cbr /\u003e\u003c/b\u003e\u003cbr /\u003ethat\u0026rsquo;s it.\u003c/p\u003e","title":"MVC Frameworks and dynamic languages"},{"content":"It\u0026rsquo;s not fun to look at a method call that sends more than 0 boolean parameters.\nCode SnippetSetBinding(false, false, comboBox);\nThere is 100%\u0026nbsp;guarantee\u0026nbsp;that you will look for the documentation about this parameters and it'll slow your code reading speed.\nHere is a nice way to avoid the unreadable code and keep on using this meaningless\u0026nbsp;Boolean.\nCode Snippet SetBinding(/* auto resolve= */ false, /* two way binding? = */ false, comboBox); This is not my idea though, it's from\u0026nbsp;Microsoft\u0026nbsp;pdb's, and I think its\u0026nbsp;awesome.","permalink":"https://kinnrot.github.io/boolean-parameters/","summary":"\u003cp\u003eIt\u0026rsquo;s not fun to look at a method call that sends more than 0 boolean parameters.\u003cbr /\u003e\u003cbr /\u003e\u003cdiv style=\"border: #000080 1px solid; color: black; font-family: 'Courier New', Courier, Monospace; font-size: 10pt;\"\u003e\u003cdiv style=\"background: #000080; color: white; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px;\"\u003eCode Snippet\u003c/div\u003e\u003cdiv style=\"background: #ddd; max-height: 300px; overflow: auto;\"\u003e\u003col style=\"background: #ffffff; margin: 0 0 0 2em; padding: 0 0 0 5px;\"\u003e\u003cli\u003eSetBinding(\u003cspan style=\"color: blue;\"\u003efalse\u003c/span\u003e, \u003cspan style=\"color: blue;\"\u003efalse\u003c/span\u003e, \u003cspan style=\"color: red;\"\u003ecomboBox\u003c/span\u003e);\u003c/li\u003e\u003c/p\u003e\n \u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003cbr /\u003eThere is 100%\u0026nbsp;guarantee\u0026nbsp;that you will look for the documentation about this parameters and it'll slow your code reading speed.\u003cbr /\u003e\u003cbr /\u003eHere is a nice way to avoid the unreadable code and keep on using this meaningless\u0026nbsp;Boolean.\u003cbr /\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cdiv style=\"border: #000080 1px solid; color: black; font-family: 'Courier New', Courier, Monospace; font-size: 10pt;\"\u003e \u003cdiv style=\"background: #000080; color: white; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px;\"\u003eCode Snippet\u003c/div\u003e\u003cdiv style=\"background: #ddd; max-height: 300px; overflow: auto;\"\u003e \u003col style=\"background: #ffffff; margin: 0 0 0 2em; padding: 0 0 0 5px;\"\u003e\u003cli\u003eSetBinding(\u003cspan style=\"color: green;\"\u003e/* auto resolve= */\u003c/span\u003e \u003cspan style=\"color: blue;\"\u003efalse\u003c/span\u003e, \u003cspan style=\"color: green;\"\u003e/* two way binding? = */\u003c/span\u003e \u003cspan style=\"color: blue;\"\u003efalse\u003c/span\u003e, comboBox);\u003c/li\u003e\n \u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003cbr /\u003e\u003cbr /\u003eThis is not my idea though, it's from\u0026nbsp;Microsoft\u0026nbsp;pdb's, and I think its\u0026nbsp;awesome.","title":"Boolean parameters"},{"content":"http://crossrider.com/pages/jobs\nI know this guys and worked with them a little, very recommended for any developer. ","permalink":"https://kinnrot.github.io/if-you-searching-for-good-place-to-grow/","summary":"\u003cdiv\u003e\u003cp\u003ehttp://crossrider.com/pages/jobs\u003c/p\u003e\u003cp\u003eI know this guys and worked with them a little, very recommended for any developer. \u003cbr\u003e \u003cbr\u003e\u003c/p\u003e\u003c/div\u003e","title":"If you're searching for a good place to grow"},{"content":"Just a little tip for writing a friendlier code.\nIf you're method returns an expression, first assign it to a variable and then return him.\nIt'll be much easier to debug inside this method and fetch all results when watching this variable.\nThat's it !","permalink":"https://kinnrot.github.io/dont-return-and-linq-on-same-line/","summary":"\u003cdiv\u003e\u003cdiv\u003e\u003cp\u003eJust a little tip for writing a friendlier code.\u003cbr\u003eIf you're method returns an expression, first assign it to a variable and then return him.\u003cbr\u003eIt'll be much easier to debug inside this method and fetch all results when watching this variable.\u003c/p\u003e\u003c/div\u003eThat's it !\u003c/div\u003e","title":"Dont return and linq on the same line"},{"content":"Code Snippetusing System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;using System.Threading.Tasks;\u0026nbsp;namespace WpfApplication1{ public class TBackgroundWorker\u0026lt;TResult, TProgress\u0026gt; {\u0026nbsp; public static TBackgroundWorker\u0026lt;TResult, TProgress\u0026gt; New() { return new TBackgroundWorker\u0026lt;TResult, TProgress\u0026gt;(); }\u0026nbsp; public TBackgroundWorker\u0026lt;TResult, TProgress\u0026gt; StartWith(Func\u0026lt;object, CancellationToken, TResult\u0026gt; work) { Start = work; return this; }\u0026nbsp; public TBackgroundWorker\u0026lt;TResult, TProgress\u0026gt; FinishWith(Action\u0026lt;TResult,object\u0026gt; finish) { Finish = finish; return this; }\u0026nbsp; private readonly CancellationTokenSource _cancelationTokenSource; private CancellationToken _cancellationToken; private readonly TaskScheduler _uiScheduler;\u0026nbsp;\u0026nbsp; public TBackgroundWorker() { _cancelationTokenSource = new CancellationTokenSource(); _uiScheduler = TaskScheduler.FromCurrentSynchronizationContext(); }\u0026nbsp; protected Func\u0026lt;object, CancellationToken,TResult\u0026gt; Start { get; set; } protected Action\u0026lt;TResult, object\u0026gt; Finish { get; set; }\u0026nbsp; public void ReportProgress(Action\u0026lt;TProgress\u0026gt; progressReport,TProgress progress) { Task.Factory.StartNew(()=\u0026gt;progressReport(progress),CancellationToken.None,TaskCreationOptions.None,_uiScheduler); }\u0026nbsp; public TBackgroundWorker\u0026lt;TResult, TProgress\u0026gt; Begin(object state = null) { _cancellationToken = _cancelationTokenSource.Token; Task\u0026lt;TResult\u0026gt;.Factory. StartNew(()=\u0026gt;Start(state,_cancellationToken),_cancellationToken). ContinueWith(x =\u0026gt; Finish(x.Result,state), _uiScheduler);\u0026nbsp; return this; }\u0026nbsp; public void Cancel() { _cancelationTokenSource.Cancel(true); } }}\nusage\nCode Snippetusing System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;using System.Windows;using System.Windows.Controls;using System.Windows.Data;using System.Windows.Documents;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Imaging;using System.Windows.Navigation;using System.Windows.Shapes;\u0026nbsp;namespace WpfApplication1{ /// \u0026lt;summary\u0026gt; /// Interaction logic for MainWindow.xaml /// \u0026lt;/summary\u0026gt; public partial class MainWindow : Window { private TBackgroundWorker\u0026lt;string, int\u0026gt; _bg;\u0026nbsp; public MainWindow() { InitializeComponent(); }\u0026nbsp; private void a_Click(object sender, RoutedEventArgs e) { _bg = TBackgroundWorker\u0026lt;string, int\u0026gt;.New(). StartWith(StartSomething). FinishWith(ShowResult). Begin(); }\u0026nbsp; private void ShowResult(string obj,object state) { a.Content = obj; }\u0026nbsp; private string StartSomething(object arg, CancellationToken cancellationToken) { int i = 0; while (i \u0026lt; 200) { if (cancellationToken.IsCancellationRequested) { return \u0026quot;Cacncelled\u0026quot;; } i++; Thread.Sleep(50); _bg.ReportProgress(Report,i); }\u0026nbsp; return \u0026quot;Done\u0026quot;; }\u0026nbsp; private void Report(int obj) { a.Content = obj; }\u0026nbsp; private void Button_Click(object sender, RoutedEventArgs e) { _bg.Cancel(); }\u0026nbsp; }}","permalink":"https://kinnrot.github.io/tpling-background-worker-in-10-min/","summary":"\u003cdiv style=\"border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt\"\u003e\u003cdiv style=\"background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px\"\u003eCode Snippet\u003c/div\u003e\u003cdiv style=\"background: #ddd; max-height: 500px; overflow: auto\"\u003e\u003col style=\"background: #ffffff; margin: 0 0 0 2.5em; padding: 0 0 0 5px;\"\u003e\u003cli\u003e\u003cspan style=\"color:#0000ff\"\u003eusing\u003c/span\u003e System;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e\u003cspan style=\"color:#0000ff\"\u003eusing\u003c/span\u003e System.Collections.Generic;\u003c/li\u003e\u003cli\u003e\u003cspan style=\"color:#0000ff\"\u003eusing\u003c/span\u003e System.Linq;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e\u003cspan style=\"color:#0000ff\"\u003eusing\u003c/span\u003e System.Text;\u003c/li\u003e\u003cli\u003e\u003cspan style=\"color:#0000ff\"\u003eusing\u003c/span\u003e System.Threading;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e\u003cspan style=\"color:#0000ff\"\u003eusing\u003c/span\u003e System.Threading.Tasks;\u003c/li\u003e\u003cli\u003e\u0026nbsp;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e\u003cspan style=\"color:#0000ff\"\u003enamespace\u003c/span\u003e WpfApplication1\u003c/li\u003e\u003cli\u003e{\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e \u003cspan style=\"color:#0000ff\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#0000ff\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#2b91af\"\u003eTBackgroundWorker\u003c/span\u003e\u0026lt;TResult, TProgress\u0026gt;\u003c/li\u003e\u003cli\u003e {\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e\u0026nbsp;\u003c/li\u003e\u003cli\u003e \u003cspan style=\"color:#0000ff\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#0000ff\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#2b91af\"\u003eTBackgroundWorker\u003c/span\u003e\u0026lt;TResult, TProgress\u0026gt; New()\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e {\u003c/li\u003e\u003cli\u003e \u003cspan style=\"color:#0000ff\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#0000ff\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#2b91af\"\u003eTBackgroundWorker\u003c/span\u003e\u0026lt;TResult, TProgress\u0026gt;();\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e }\u003c/li\u003e\u003cli\u003e\u0026nbsp;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e \u003cspan style=\"color:#0000ff\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#2b91af\"\u003eTBackgroundWorker\u003c/span\u003e\u0026lt;TResult, TProgress\u0026gt; StartWith(\u003cspan style=\"color:#2b91af\"\u003eFunc\u003c/span\u003e\u0026lt;\u003cspan style=\"color:#0000ff\"\u003eobject\u003c/span\u003e, \u003cspan style=\"color:#2b91af\"\u003eCancellationToken\u003c/span\u003e, TResult\u0026gt; work)\u003c/li\u003e\u003cli\u003e {\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e Start = work;\u003c/li\u003e\u003cli\u003e \u003cspan style=\"color:#0000ff\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#0000ff\"\u003ethis\u003c/span\u003e;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e }\u003c/li\u003e\u003cli\u003e\u0026nbsp;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e \u003cspan style=\"color:#0000ff\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#2b91af\"\u003eTBackgroundWorker\u003c/span\u003e\u0026lt;TResult, TProgress\u0026gt; FinishWith(\u003cspan style=\"color:#2b91af\"\u003eAction\u003c/span\u003e\u0026lt;TResult,\u003cspan style=\"color:#0000ff\"\u003eobject\u003c/span\u003e\u0026gt; finish)\u003c/li\u003e\u003cli\u003e {\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e Finish = finish;\u003c/li\u003e\u003cli\u003e \u003cspan style=\"color:#0000ff\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#0000ff\"\u003ethis\u003c/span\u003e;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e }\u003c/li\u003e\u003cli\u003e\u0026nbsp;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e \u003cspan style=\"color:#0000ff\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#0000ff\"\u003ereadonly\u003c/span\u003e \u003cspan style=\"color:#2b91af\"\u003eCancellationTokenSource\u003c/span\u003e _cancelationTokenSource;\u003c/li\u003e\u003cli\u003e \u003cspan style=\"color:#0000ff\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#2b91af\"\u003eCancellationToken\u003c/span\u003e _cancellationToken;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e \u003cspan style=\"color:#0000ff\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#0000ff\"\u003ereadonly\u003c/span\u003e \u003cspan style=\"color:#2b91af\"\u003eTaskScheduler\u003c/span\u003e _uiScheduler;\u003c/li\u003e\u003cli\u003e\u0026nbsp;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e\u0026nbsp;\u003c/li\u003e\u003cli\u003e \u003cspan style=\"color:#0000ff\"\u003epublic\u003c/span\u003e TBackgroundWorker()\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e {\u003c/li\u003e\u003cli\u003e _cancelationTokenSource = \u003cspan style=\"color:#0000ff\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#2b91af\"\u003eCancellationTokenSource\u003c/span\u003e();\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e _uiScheduler = \u003cspan style=\"color:#2b91af\"\u003eTaskScheduler\u003c/span\u003e.FromCurrentSynchronizationContext();\u003c/li\u003e\u003cli\u003e }\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e\u0026nbsp;\u003c/li\u003e\u003cli\u003e \u003cspan style=\"color:#0000ff\"\u003eprotected\u003c/span\u003e \u003cspan style=\"color:#2b91af\"\u003eFunc\u003c/span\u003e\u0026lt;\u003cspan style=\"color:#0000ff\"\u003eobject\u003c/span\u003e, \u003cspan style=\"color:#2b91af\"\u003eCancellationToken\u003c/span\u003e,TResult\u0026gt; Start { \u003cspan style=\"color:#0000ff\"\u003eget\u003c/span\u003e; \u003cspan style=\"color:#0000ff\"\u003eset\u003c/span\u003e; }\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e \u003cspan style=\"color:#0000ff\"\u003eprotected\u003c/span\u003e \u003cspan style=\"color:#2b91af\"\u003eAction\u003c/span\u003e\u0026lt;TResult, \u003cspan style=\"color:#0000ff\"\u003eobject\u003c/span\u003e\u0026gt; Finish { \u003cspan style=\"color:#0000ff\"\u003eget\u003c/span\u003e; \u003cspan style=\"color:#0000ff\"\u003eset\u003c/span\u003e; }\u003c/li\u003e\u003cli\u003e\u0026nbsp;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e \u003cspan style=\"color:#0000ff\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#0000ff\"\u003evoid\u003c/span\u003e ReportProgress(\u003cspan style=\"color:#2b91af\"\u003eAction\u003c/span\u003e\u0026lt;TProgress\u0026gt; progressReport,TProgress progress)\u003c/li\u003e\u003cli\u003e {\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e \u003cspan style=\"color:#2b91af\"\u003eTask\u003c/span\u003e.Factory.StartNew(()=\u0026gt;progressReport(progress),\u003cspan style=\"color:#2b91af\"\u003eCancellationToken\u003c/span\u003e.None,\u003cspan style=\"color:#2b91af\"\u003eTaskCreationOptions\u003c/span\u003e.None,_uiScheduler);\u003c/li\u003e\u003cli\u003e }\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e\u0026nbsp;\u003c/li\u003e\u003cli\u003e \u003cspan style=\"color:#0000ff\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#2b91af\"\u003eTBackgroundWorker\u003c/span\u003e\u0026lt;TResult, TProgress\u0026gt; Begin(\u003cspan style=\"color:#0000ff\"\u003eobject\u003c/span\u003e state = \u003cspan style=\"color:#0000ff\"\u003enull\u003c/span\u003e)\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e {\u003c/li\u003e\u003cli\u003e _cancellationToken = _cancelationTokenSource.Token;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e \u003cspan style=\"color:#2b91af\"\u003eTask\u003c/span\u003e\u0026lt;TResult\u0026gt;.Factory.\u003c/li\u003e\u003cli\u003e StartNew(()=\u0026gt;Start(state,_cancellationToken),_cancellationToken).\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e ContinueWith(x =\u0026gt;\u003c/li\u003e\u003cli\u003e Finish(x.Result,state),\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e _uiScheduler);\u003c/li\u003e\u003cli\u003e\u0026nbsp;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e \u003cspan style=\"color:#0000ff\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#0000ff\"\u003ethis\u003c/span\u003e;\u003c/li\u003e\u003cli\u003e }\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e\u0026nbsp;\u003c/li\u003e\u003cli\u003e \u003cspan style=\"color:#0000ff\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#0000ff\"\u003evoid\u003c/span\u003e Cancel()\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e {\u003c/li\u003e\u003cli\u003e _cancelationTokenSource.Cancel(\u003cspan style=\"color:#0000ff\"\u003etrue\u003c/span\u003e);\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e }\u003c/li\u003e\u003cli\u003e }\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e}\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003cbr /\u003e\u003cbr /\u003eusage\u003cbr /\u003e\u003cbr /\u003e\u003cdiv style=\"border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt\"\u003e\u003cdiv style=\"background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px\"\u003eCode Snippet\u003c/div\u003e\u003cdiv style=\"background: #ddd; max-height: 300px; overflow: auto\"\u003e\u003col style=\"background: #ffffff; margin: 0 0 0 2.5em; padding: 0 0 0 5px;\"\u003e\u003cli\u003e\u003cspan style=\"color:#0000ff\"\u003eusing\u003c/span\u003e System;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e\u003cspan style=\"color:#0000ff\"\u003eusing\u003c/span\u003e System.Collections.Generic;\u003c/li\u003e\u003cli\u003e\u003cspan style=\"color:#0000ff\"\u003eusing\u003c/span\u003e System.Linq;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e\u003cspan style=\"color:#0000ff\"\u003eusing\u003c/span\u003e System.Text;\u003c/li\u003e\u003cli\u003e\u003cspan style=\"color:#0000ff\"\u003eusing\u003c/span\u003e System.Threading;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e\u003cspan style=\"color:#0000ff\"\u003eusing\u003c/span\u003e System.Windows;\u003c/li\u003e\u003cli\u003e\u003cspan style=\"color:#0000ff\"\u003eusing\u003c/span\u003e System.Windows.Controls;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e\u003cspan style=\"color:#0000ff\"\u003eusing\u003c/span\u003e System.Windows.Data;\u003c/li\u003e\u003cli\u003e\u003cspan style=\"color:#0000ff\"\u003eusing\u003c/span\u003e System.Windows.Documents;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e\u003cspan style=\"color:#0000ff\"\u003eusing\u003c/span\u003e System.Windows.Input;\u003c/li\u003e\u003cli\u003e\u003cspan style=\"color:#0000ff\"\u003eusing\u003c/span\u003e System.Windows.Media;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e\u003cspan style=\"color:#0000ff\"\u003eusing\u003c/span\u003e System.Windows.Media.Imaging;\u003c/li\u003e\u003cli\u003e\u003cspan style=\"color:#0000ff\"\u003eusing\u003c/span\u003e System.Windows.Navigation;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e\u003cspan style=\"color:#0000ff\"\u003eusing\u003c/span\u003e System.Windows.Shapes;\u003c/li\u003e\u003cli\u003e\u0026nbsp;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e\u003cspan style=\"color:#0000ff\"\u003enamespace\u003c/span\u003e WpfApplication1\u003c/li\u003e\u003cli\u003e{\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e \u003cspan style=\"color:#808080\"\u003e///\u003c/span\u003e\u003cspan style=\"color:#008000\"\u003e \u003c/span\u003e\u003cspan style=\"color:#808080\"\u003e\u0026lt;summary\u0026gt;\u003c/span\u003e\u003c/li\u003e\u003cli\u003e \u003cspan style=\"color:#808080\"\u003e///\u003c/span\u003e\u003cspan style=\"color:#008000\"\u003e Interaction logic for MainWindow.xaml\u003c/span\u003e\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e \u003cspan style=\"color:#808080\"\u003e///\u003c/span\u003e\u003cspan style=\"color:#008000\"\u003e \u003c/span\u003e\u003cspan style=\"color:#808080\"\u003e\u0026lt;/summary\u0026gt;\u003c/span\u003e\u003c/li\u003e\u003cli\u003e \u003cspan style=\"color:#0000ff\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#0000ff\"\u003epartial\u003c/span\u003e \u003cspan style=\"color:#0000ff\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#2b91af\"\u003eMainWindow\u003c/span\u003e : \u003cspan style=\"color:#2b91af\"\u003eWindow\u003c/span\u003e\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e {\u003c/li\u003e\u003cli\u003e \u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e \u003cspan style=\"color:#0000ff\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#2b91af\"\u003eTBackgroundWorker\u003c/span\u003e\u0026lt;\u003cspan style=\"color:#0000ff\"\u003estring\u003c/span\u003e, \u003cspan style=\"color:#0000ff\"\u003eint\u003c/span\u003e\u0026gt; _bg;\u003c/li\u003e\u003cli\u003e\u0026nbsp;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e \u003cspan style=\"color:#0000ff\"\u003epublic\u003c/span\u003e MainWindow()\u003c/li\u003e\u003cli\u003e {\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e InitializeComponent();\u003c/li\u003e\u003cli\u003e }\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e\u0026nbsp;\u003c/li\u003e\u003cli\u003e \u003cspan style=\"color:#0000ff\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#0000ff\"\u003evoid\u003c/span\u003e a_Click(\u003cspan style=\"color:#0000ff\"\u003eobject\u003c/span\u003e sender, \u003cspan style=\"color:#2b91af\"\u003eRoutedEventArgs\u003c/span\u003e e)\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e {\u003c/li\u003e\u003cli\u003e _bg = \u003cspan style=\"color:#2b91af\"\u003eTBackgroundWorker\u003c/span\u003e\u0026lt;\u003cspan style=\"color:#0000ff\"\u003estring\u003c/span\u003e, \u003cspan style=\"color:#0000ff\"\u003eint\u003c/span\u003e\u0026gt;.New().\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e StartWith(StartSomething).\u003c/li\u003e\u003cli\u003e FinishWith(ShowResult).\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e Begin();\u003c/li\u003e\u003cli\u003e }\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e\u0026nbsp;\u003c/li\u003e\u003cli\u003e \u003cspan style=\"color:#0000ff\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#0000ff\"\u003evoid\u003c/span\u003e ShowResult(\u003cspan style=\"color:#0000ff\"\u003estring\u003c/span\u003e obj,\u003cspan style=\"color:#0000ff\"\u003eobject\u003c/span\u003e state)\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e {\u003c/li\u003e\u003cli\u003e a.Content = obj;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e }\u003c/li\u003e\u003cli\u003e\u0026nbsp;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e \u003cspan style=\"color:#0000ff\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#0000ff\"\u003estring\u003c/span\u003e StartSomething(\u003cspan style=\"color:#0000ff\"\u003eobject\u003c/span\u003e arg, \u003cspan style=\"color:#2b91af\"\u003eCancellationToken\u003c/span\u003e cancellationToken)\u003c/li\u003e\u003cli\u003e {\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e \u003cspan style=\"color:#0000ff\"\u003eint\u003c/span\u003e i = 0;\u003c/li\u003e\u003cli\u003e \u003cspan style=\"color:#0000ff\"\u003ewhile\u003c/span\u003e (i \u0026lt; 200)\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e {\u003c/li\u003e\u003cli\u003e \u003cspan style=\"color:#0000ff\"\u003eif\u003c/span\u003e (cancellationToken.IsCancellationRequested)\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e {\u003c/li\u003e\u003cli\u003e \u003cspan style=\"color:#0000ff\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a31515\"\u003e\u0026quot;Cacncelled\u0026quot;\u003c/span\u003e;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e \u003c/li\u003e\u003cli\u003e }\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e i++;\u003c/li\u003e\u003cli\u003e \u003cspan style=\"color:#2b91af\"\u003eThread\u003c/span\u003e.Sleep(50);\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e _bg.ReportProgress(Report,i);\u003c/li\u003e\u003cli\u003e }\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e\u0026nbsp;\u003c/li\u003e\u003cli\u003e \u003cspan style=\"color:#0000ff\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a31515\"\u003e\u0026quot;Done\u0026quot;\u003c/span\u003e;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e }\u003c/li\u003e\u003cli\u003e\u0026nbsp;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e \u003cspan style=\"color:#0000ff\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#0000ff\"\u003evoid\u003c/span\u003e Report(\u003cspan style=\"color:#0000ff\"\u003eint\u003c/span\u003e obj)\u003c/li\u003e\u003cli\u003e {\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e a.Content = obj;\u003c/li\u003e\u003cli\u003e }\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e\u0026nbsp;\u003c/li\u003e\u003cli\u003e \u003cspan style=\"color:#0000ff\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#0000ff\"\u003evoid\u003c/span\u003e Button_Click(\u003cspan style=\"color:#0000ff\"\u003eobject\u003c/span\u003e sender, \u003cspan style=\"color:#2b91af\"\u003eRoutedEventArgs\u003c/span\u003e e)\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e {\u003c/li\u003e\u003cli\u003e _bg.Cancel();\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e }\u003c/li\u003e\u003cli\u003e\u0026nbsp;\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e \u003c/li\u003e\u003cli\u003e }\u003c/li\u003e\u003cli style=\"background: #f3f3f3\"\u003e}\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e","title":"TPLing Background worker in 10 min"},{"content":"Recently I tried to find a nice code sample for how to pass complex type through WCF, inside the header, meaning I want to send the client execution context to the server side.\nAll of the samples passes strings or uses custom header that needs to write and read the object manually, I didn\u0026rsquo;t like it.\nSo I wrote one and it\u0026rsquo;s working!\nAll you need is 2 classes, and one is just a factory for the other, very simple:\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Runtime.Serialization;\nusing System.ServiceModel;\nusing System.ServiceModel.Channels;\nusing System.ServiceModel.Dispatcher;\nusing System.Text;\nnamespace debugniv.ComplexTypeOverWcf\n{\nclass HeaderHandler : IDispatchMessageInspector, IClientMessageInspector\n{\n#region Implementation of IDispatchMessageInspector\npublic object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)\n{\n// Read the complex type from header\nvar headerIndex = request.Headers.FindHeader(typeof(MyHeader).Name, typeof(MyHeader).Namespace);\nif (headerIndex \u0026gt;= 0) // found!\n{\nvar serializer = GenerateDataContractSerializer\u0026lt;MyHeader\u0026gt;();\nvar myHeader = request.Headers.GetHeader\u0026lt;MyHeader\u0026gt;(headerIndex, serializer);\n// here you can do something with your header like push it to a global per request context.\n}\nreturn null;\n}\npublic void BeforeSendReply(ref Message reply, object correlationState)\n{\n// nothing here\n}\n#endregion\n#region Implementation of IClientMessageInspector\npublic object BeforeSendRequest(ref Message request, IClientChannel channel)\n{\nvar myHeader = GetMyHeader();\nrequest.Headers.Add(myHeader);\n}\npublic void AfterReceiveReply(ref Message reply, object correlationState)\n{\n// nothing to do here\n}\n#endregion\nprivate DataContractSerializer GenerateDataContractSerializer\u0026lt;T\u0026gt;()\n{\nreturn new DataContractSerializer(typeof(T), typeof(T).Name, typeof(T).Namespace, GetKnownTypes());\n}\nprivate IEnumerable\u0026lt;Type\u0026gt; GetKnownTypes()\n{\n// here return all your types inside the header\nyield return typeof(MyHeader);\nyield return typeof(SubType);\n}\nprivate MessageHeader GetMyHeader()\n{\nvar data = new MyHeader();\nvar serializer = GenerateDataContractSerializer\u0026lt;MyHeader\u0026gt;();\nreturn MessageHeader.CreateHeader(data.GetType().Name, data.GetType().Namespace, data, serializer);\n}\n}\n// this is the header internal class MyHeader\n{\npublic SubType InternalData { get; set; }\n}\ninternal class SubType\n{\n}\n}\nThe second thing you\u0026rsquo;ll need is to attach this stuff to your service and proxy, here is one way to do this\nusing System;\nusing System.ServiceModel.Configuration;\nnamespace debugniv.ComplexTypeOverWcf\n{\npublic class HeaderExtensionElement : BehaviorExtensionElement\n{\npublic override Type BehaviorType\n{\nget { return typeof (HeaderHandler); }\n}\nprotected override object CreateBehavior()\n{\nreturn new HeaderHandler();\n}\n}\n}\nIn you config file add the following ","permalink":"https://kinnrot.github.io/passing-complex-type-through-wcf/","summary":"\u003cp\u003eRecently I tried to find a nice code sample for how to pass complex type through WCF, inside the header, meaning I want to send the client execution context to the server side.\u003cbr /\u003e\u003cbr /\u003eAll of the samples passes strings or uses custom header that needs to write and read the object manually, I didn\u0026rsquo;t like it.\u003cbr /\u003e\u003cbr /\u003eSo I wrote one and it\u0026rsquo;s working!\u003cbr /\u003e\u003cdiv id=\"stackstack-5443871\"\u003e\u003c/div\u003eAll you need is 2 classes, and one is just a factory for the other, very simple:\u003cbr /\u003e\u003cbr /\u003e\u003cpre class=\"brush: csharp;\"\u003eusing System;\u003cbr /\u003eusing System.Collections.Generic;\u003cbr /\u003eusing System.Linq;\u003cbr /\u003eusing System.Runtime.Serialization;\u003cbr /\u003eusing System.ServiceModel;\u003cbr /\u003eusing System.ServiceModel.Channels;\u003cbr /\u003eusing System.ServiceModel.Dispatcher;\u003cbr /\u003eusing System.Text;\u003cbr /\u003e\u003cbr /\u003enamespace debugniv.ComplexTypeOverWcf\u003cbr /\u003e{\u003cbr /\u003e class HeaderHandler : IDispatchMessageInspector, IClientMessageInspector\u003cbr /\u003e {\u003cbr /\u003e #region Implementation of IDispatchMessageInspector\u003cbr /\u003e\u003cbr /\u003e public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)\u003cbr /\u003e {\u003cbr /\u003e // Read the complex type from header\u003cbr /\u003e var headerIndex = request.Headers.FindHeader(typeof(MyHeader).Name, typeof(MyHeader).Namespace);\u003cbr /\u003e\u003cbr /\u003e if (headerIndex \u0026gt;= 0) // found!\u003cbr /\u003e {\u003cbr /\u003e var serializer = GenerateDataContractSerializer\u0026lt;MyHeader\u0026gt;();\u003cbr /\u003e var myHeader = request.Headers.GetHeader\u0026lt;MyHeader\u0026gt;(headerIndex, serializer);\u003cbr /\u003e // here you can do something with your header like push it to a global per request context.\u003cbr /\u003e }\u003cbr /\u003e return null;\u003cbr /\u003e }\u003cbr /\u003e\u003cbr /\u003e public void BeforeSendReply(ref Message reply, object correlationState)\u003cbr /\u003e {\u003cbr /\u003e // nothing here\u003cbr /\u003e }\u003cbr /\u003e\u003cbr /\u003e #endregion\u003cbr /\u003e\u003cbr /\u003e #region Implementation of IClientMessageInspector\u003cbr /\u003e\u003cbr /\u003e public object BeforeSendRequest(ref Message request, IClientChannel channel)\u003cbr /\u003e {\u003cbr /\u003e var myHeader = GetMyHeader();\u003cbr /\u003e request.Headers.Add(myHeader);\u003cbr /\u003e }\u003cbr /\u003e\u003cbr /\u003e public void AfterReceiveReply(ref Message reply, object correlationState)\u003cbr /\u003e {\u003cbr /\u003e // nothing to do here\u003cbr /\u003e }\u003cbr /\u003e\u003cbr /\u003e #endregion\u003cbr /\u003e\u003cbr /\u003e private DataContractSerializer GenerateDataContractSerializer\u0026lt;T\u0026gt;()\u003cbr /\u003e {\u003cbr /\u003e return new DataContractSerializer(typeof(T), typeof(T).Name, typeof(T).Namespace, GetKnownTypes());\u003cbr /\u003e }\u003cbr /\u003e\u003cbr /\u003e private IEnumerable\u0026lt;Type\u0026gt; GetKnownTypes()\u003cbr /\u003e {\u003cbr /\u003e // here return all your types inside the header\u003cbr /\u003e yield return typeof(MyHeader);\u003cbr /\u003e yield return typeof(SubType);\u003cbr /\u003e }\u003cbr /\u003e\u003cbr /\u003e private MessageHeader GetMyHeader()\u003cbr /\u003e {\u003cbr /\u003e var data = new MyHeader();\u003cbr /\u003e var serializer = GenerateDataContractSerializer\u0026lt;MyHeader\u0026gt;();\u003cbr /\u003e return MessageHeader.CreateHeader(data.GetType().Name, data.GetType().Namespace, data, serializer);\u003cbr /\u003e }\u003cbr /\u003e\u003cbr /\u003e\u003cbr /\u003e }\u003cbr /\u003e\u003cbr /\u003e // this is the header \u003cbr /\u003e internal class MyHeader\u003cbr /\u003e {\u003cbr /\u003e public SubType InternalData { get; set; }\u003cbr /\u003e }\u003cbr /\u003e\u003cbr /\u003e internal class SubType\u003cbr /\u003e {\u003cbr /\u003e }\u003cbr /\u003e}\u003cbr /\u003e\u003cbr /\u003e\u003c/pre\u003e\u003cbr /\u003eThe second thing you\u0026rsquo;ll need is to attach this stuff to your service and proxy, here is one way to do this\u003cbr /\u003e\u003cbr /\u003e\u003cpre class=\"brush: csharp;\"\u003eusing System;\u003cbr /\u003eusing System.ServiceModel.Configuration;\u003cbr /\u003e\u003cbr /\u003enamespace debugniv.ComplexTypeOverWcf\u003cbr /\u003e{\u003cbr /\u003e public class HeaderExtensionElement : BehaviorExtensionElement\u003cbr /\u003e {\u003cbr /\u003e\u003cbr /\u003e public override Type BehaviorType\u003cbr /\u003e {\u003cbr /\u003e get { return typeof (HeaderHandler); }\u003cbr /\u003e }\u003cbr /\u003e\u003cbr /\u003e protected override object CreateBehavior()\u003cbr /\u003e {\u003cbr /\u003e return new HeaderHandler();\u003cbr /\u003e }\u003cbr /\u003e }\u003cbr /\u003e}\u003cbr /\u003e\u003c/pre\u003e\u003cbr /\u003eIn you config file add the following \u003cbr /\u003e\u003cextensions\u003e\u003cbr /\u003e \u003cbehaviorExtensions\u003e\u003cbr /\u003e \u003cadd name=\"customEndpointBehavior\" type=\"your extension type name\"/\u003e\u003cbr /\u003e \u003c/behaviorExtensions\u003e\u003c/p\u003e","title":"Passing complex type through WCF header,The simple always work version."},{"content":"Think about a registered component that implement copy constructor.\nYou\u0026rsquo;ll get a Stack Overflow Exception!\nSo avoid it.\n","permalink":"https://kinnrot.github.io/ioc-container-warning/","summary":"\u003cp\u003eThink about a registered component that implement copy constructor.\u003cbr /\u003e\u003cbr /\u003eYou\u0026rsquo;ll get a Stack Overflow Exception!\u003cbr /\u003e\u003cbr /\u003eSo avoid it.\u003cbr /\u003e\u003cbr /\u003e\u003cbr /\u003e\u003ca href=\"http://www.assembla.com?affiliate=Kinnrot\"\u003e\u003cimg src='http://www.assembla.com/images/affiliate_banners/468.png' alt='assembla.com'/\u003e\u003c/a\u003e\u003c/p\u003e","title":"IOC Container warning"},{"content":"Let\u0026rsquo;s say we write an infrastructure of entities and their interaction with Nhibernate and the rest of the server side logic.\nWe want Nhibernate to do whatever it needs. But we also want to limit the application programmer from doing crazy things, for example: Setting the Unique Identifier of an existing entity to another value. I know it sounds crazy but in a medium-sized team, anything can happen and this stuff is critical for the future.\nSo I thought about a very KIS way to implement this kind of protection.\n* What I write here is the most readable version of my code, you can extract method, use interceptor, AOP, whatever works for you.\nprivate long _id;\npublic long ID\n{\nget { return _id; }\nset\n{\nif (!_id.Equals(default(long)) \u0026amp;\u0026amp; !_id.Equals(value))\n{\nthrow new InvalidOperationException(\n\u0026ldquo;You can\u0026rsquo;t set this property, it has already been set\u0026rdquo;);\n}\n_id = value;\n}\n}\nVery simple, easy to test, and it works with NHibernate proxy.\n","permalink":"https://kinnrot.github.io/preventing-from-setting-property-value/","summary":"\u003cp\u003eLet\u0026rsquo;s say we write an infrastructure of entities and their interaction with Nhibernate and the rest of the server side logic.\u003cbr /\u003eWe want Nhibernate to do whatever it needs. But we also want to limit the application programmer from doing crazy things, for example: Setting the Unique Identifier of an existing entity to another value. I know it sounds crazy but in a medium-sized team, anything can happen and this stuff is critical for the future.\u003cbr /\u003e\u003cbr /\u003eSo I thought about a very KIS way to implement this kind of protection.\u003cbr /\u003e\u003cbr /\u003e* What I write here is the most readable version of my code, you can extract method, use interceptor, AOP, whatever works for you.\u003cbr /\u003e\u003cbr /\u003e\u003cpre class=\"brush: csharp;\"\u003eprivate long _id;\u003cbr /\u003e\u003cbr /\u003epublic long ID\u003cbr /\u003e{\u003cbr /\u003e get { return _id; }\u003cbr /\u003e set\u003cbr /\u003e {\u003cbr /\u003e if (!_id.Equals(default(long)) \u0026amp;\u0026amp; !_id.Equals(value))\u003cbr /\u003e {\u003cbr /\u003e throw new InvalidOperationException(\u003cbr /\u003e \u0026ldquo;You can\u0026rsquo;t set this property, it has already been set\u0026rdquo;);\u003cbr /\u003e }\u003cbr /\u003e _id = value;\u003cbr /\u003e }\u003cbr /\u003e}\u003cbr /\u003e\u003cbr /\u003e\u003c/pre\u003e\u003cbr /\u003eVery simple, easy to test, and it works with NHibernate proxy.\u003c/p\u003e","title":"Prevent setting a property value after already been set"},{"content":"I need to support 2 db types on my app, so I thought about a nice pattern that will help me achieve this.\n// I\u0026rsquo;m working with latest Fluent Nhibernate version.\nDefine a folder for each db type you want to support like this:\ncontain conventions for MSSQLCE and the second will contain conventions for OracleClient.\nFor example: Oracle support schemas and sequences, SQLCE does not. lets define some simple conventions\nFor Oracle:\npublic class SchemaConvention : IClassConvention\n{\npublic void Apply(IClassInstance instance)\n{\ninstance.Schema(\u0026ldquo;MY_ORACLE_SPECIFIC_SCHEMA\u0026rdquo;);\n}\n}\npublic class SequenceConvention : IIdConvention\n{\npublic void Apply(IIdentityInstance instance)\n{\ninstance.GeneratedBy.Sequence(instance.Columns.First().Name + \u0026ldquo;_SEQ\u0026rdquo;);\n}\n}\nAnd for SqlCe:\nclass IdentityConvention : IIdConvention\n{\npublic void Apply(IIdentityInstance instance)\n{\ninstance.GeneratedBy.Identity();\n}\n}\nSo the folders will look like this:\nNext thing that we will need is some kind of type retriever that knows what conventions to load according to the db we are currently configuring his nhibernate stuff.\nLets call it PerDBConventionSource and this is how its implemented:\ninternal class PerDBConventionSource : ITypeSource\n{\nprivate readonly string _name;\nprivate IEnumerable\u0026lt;Type\u0026gt; _types;\npublic PerDBConventionSource(string name)\n{\n_name = name;\n}\npublic IEnumerable\u0026lt;Type\u0026gt; GetTypes()\n{\n_types = typeof (PerDBConventionSource).Assembly.GetTypes().Where(t =\u0026gt; t.Namespace.EndsWith(_name));\nreturn _types;\n}\n/// \u0026lt;summary\u0026gt;\n/// Logs the activity of this type source.\n/// \u0026lt;/summary\u0026gt;\n/// \u0026lt;param name=\u0026ldquo;logger\u0026rdquo;\u0026gt;The logger.\u0026lt;/param\u0026gt;\npublic void LogSource(IDiagnosticLogger logger)\n{\n// TODO : Log if you want\n}\npublic string GetIdentifier()\n{\nreturn _name;\n}\n}\nNotice that i\u0026rsquo;m implementing ITypeSource, an interface belong to FluentNhibernate, this is how i tell FluentNhibernate to use this as a convention source: (I used only fluentMappings so I add the conventions only on fluentMappings)\nprivate static IPersistenceConfigurer _persistenceConfigurer;\nprivate static void ConfigureNH(IPersistenceConfigurer persistenceConfigurer)\n{\n_persistenceConfigurer = persistenceConfigurer;\nFluently.\nConfigure().\nDatabase(persistenceConfigurer).\nDiagnostics(x =\u0026gt; x.Enable(true).OutputToConsole()).\nMappings(SomeMappings).\nBuildConfiguration();\n}\nprivate static void SomeMappings(MappingConfiguration mappingConfiguration)\n{\nstring name = _persistenceConfigurer.GetType().Name.Replace(\u0026ldquo;Configuration\u0026rdquo;, string.Empty);\nmappingConfiguration.FluentMappings.Conventions.AddSource(new PerDBConventionSource(name));\n}\nSo when I\u0026rsquo;ll run the following code:\nConsole.BackgroundColor = ConsoleColor.DarkGreen;\nConsole.ForegroundColor= ConsoleColor.Green;\nConfigureNH(OracleClientConfiguration.Oracle10.ConnectionString(\u0026ldquo;some OracleClient connection\u0026rdquo;));\nConsole.BackgroundColor = ConsoleColor.DarkBlue;\nConsole.ForegroundColor = ConsoleColor.Blue;\nConfigureNH(MsSqlCeConfiguration.Standard.ConnectionString(\u0026ldquo;some MsSqlCe connection\u0026rdquo;));\nThe result will be\nWhy you should use his pattern anyway(even if you work with 1 db):\n1. unit testing with sqlite in memory will not work with sequence conventions, so you shouldn\u0026rsquo;t load them when you are unit testing.\n2. If you\u0026rsquo;ll some day change the db type, you\u0026rsquo;ll know where to add its own conventions, just create a folder with db name and add it\u0026rsquo;s conventions inside no other change is necessary.\nYou can find the source here:\n","permalink":"https://kinnrot.github.io/per-db-conventions-with/","summary":"\u003cp\u003eI need to support 2 db types on my app, so I thought about a nice pattern that will help me achieve this.\u003cbr /\u003e\u003cbr /\u003e\u003cspan class=\"Apple-style-span\" style=\"color: lime;\"\u003e// I\u0026rsquo;m working with latest Fluent Nhibernate version.\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003eDefine a folder for each db type you want to support like this:\u003cbr /\u003e\u003cdiv class=\"separator\" style=\"clear: both; text-align: center;\"\u003e\u003c/div\u003e\u003cdiv class=\"separator\" style=\"clear: both; text-align: center;\"\u003e\u003ca href=\"http://4.bp.blogspot.com/-MfFJJoXqa-I/TVwVwTgRK9I/AAAAAAAACNY/bZojqTwNd1A/s1600/Tree.PNG\" imageanchor=\"1\" style=\"margin-left: 1em; margin-right: 1em;\"\u003e\u003cimg border=\"0\" src=\"http://4.bp.blogspot.com/-MfFJJoXqa-I/TVwVwTgRK9I/AAAAAAAACNY/bZojqTwNd1A/s1600/Tree.PNG\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003econtain conventions for MSSQLCE and the second will contain conventions for OracleClient.\u003cbr /\u003e\u003cbr /\u003eFor example: Oracle support schemas and sequences, SQLCE does not. lets define some simple conventions\u003cbr /\u003e\u003cbr /\u003eFor Oracle:\u003cbr /\u003e\u003cbr /\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: monospace; white-space: pre;\"\u003epublic class SchemaConvention : IClassConvention\u003c/span\u003e\u003cbr /\u003e\u003cpre class=\"brush: csharp;\"\u003e{\u003cbr /\u003e public void Apply(IClassInstance instance)\u003cbr /\u003e {\u003cbr /\u003e instance.Schema(\u0026ldquo;MY_ORACLE_SPECIFIC_SCHEMA\u0026rdquo;);\u003cbr /\u003e }\u003cbr /\u003e}\u003cbr /\u003e\u003c/pre\u003e\u003cbr /\u003e\u003cpre class=\"brush: csharp;\"\u003epublic class SequenceConvention : IIdConvention\u003cbr /\u003e{\u003cbr /\u003e public void Apply(IIdentityInstance instance)\u003cbr /\u003e {\u003cbr /\u003e instance.GeneratedBy.Sequence(instance.Columns.First().Name + \u0026ldquo;_SEQ\u0026rdquo;);\u003cbr /\u003e }\u003cbr /\u003e}\u003cbr /\u003e\u003c/pre\u003e\u003cbr /\u003eAnd for SqlCe:\u003cbr /\u003e\u003cbr /\u003e\u003cpre class=\"brush: csharp;\"\u003eclass IdentityConvention : IIdConvention\u003cbr /\u003e{\u003cbr /\u003e public void Apply(IIdentityInstance instance)\u003cbr /\u003e {\u003cbr /\u003e instance.GeneratedBy.Identity();\u003cbr /\u003e }\u003cbr /\u003e}\u003cbr /\u003e\u003c/pre\u003e\u003cpre class=\"brush: csharp;\"\u003e\u003c/pre\u003e\u003cpre class=\"brush: csharp;\"\u003eSo the folders will look like this:\u003c/pre\u003e\u003cdiv class=\"separator\" style=\"clear: both; text-align: center;\"\u003e\u003ca href=\"http://1.bp.blogspot.com/-hhY8AdZIj9U/TVwYkml_xUI/AAAAAAAACNk/yhmHGgp29gs/s1600/files.GIF\" imageanchor=\"1\" style=\"margin-left: 1em; margin-right: 1em;\"\u003e\u003cimg border=\"0\" src=\"http://1.bp.blogspot.com/-hhY8AdZIj9U/TVwYkml_xUI/AAAAAAAACNk/yhmHGgp29gs/s1600/files.GIF\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cpre class=\"brush: csharp;\"\u003e\u003c/pre\u003e\u003cbr /\u003eNext thing that we will need is some kind of type retriever that knows what conventions to load according to the db we are currently configuring his nhibernate stuff.\u003cbr /\u003e\u003cbr /\u003eLets call it PerDBConventionSource and this is how its implemented:\u003cbr /\u003e\u003cbr /\u003e\u003cpre class=\"brush: csharp;\"\u003einternal class PerDBConventionSource : ITypeSource\u003cbr /\u003e{\u003cbr /\u003e private readonly string _name;\u003cbr /\u003e private IEnumerable\u0026lt;Type\u0026gt; _types;\u003cbr /\u003e\u003cbr /\u003e public PerDBConventionSource(string name)\u003cbr /\u003e {\u003cbr /\u003e _name = name;\u003cbr /\u003e }\u003cbr /\u003e\u003cbr /\u003e public IEnumerable\u0026lt;Type\u0026gt; GetTypes()\u003cbr /\u003e {\u003cbr /\u003e _types = typeof (PerDBConventionSource).Assembly.GetTypes().Where(t =\u0026gt; t.Namespace.EndsWith(_name));\u003cbr /\u003e return _types;\u003cbr /\u003e }\u003cbr /\u003e\u003cbr /\u003e /// \u0026lt;summary\u0026gt;\u003cbr /\u003e /// Logs the activity of this type source.\u003cbr /\u003e /// \u0026lt;/summary\u0026gt;\u003cbr /\u003e /// \u0026lt;param name=\u0026ldquo;logger\u0026rdquo;\u0026gt;The logger.\u0026lt;/param\u0026gt;\u003cbr /\u003e public void LogSource(IDiagnosticLogger logger)\u003cbr /\u003e {\u003cbr /\u003e // TODO : Log if you want\u003cbr /\u003e }\u003cbr /\u003e\u003cbr /\u003e public string GetIdentifier()\u003cbr /\u003e {\u003cbr /\u003e return _name;\u003cbr /\u003e }\u003cbr /\u003e}\u003cbr /\u003e\u003c/pre\u003e\u003cbr /\u003eNotice that i\u0026rsquo;m implementing ITypeSource, an interface belong to FluentNhibernate, this is how i tell FluentNhibernate to use this as a convention source: (I used only fluentMappings so I add the conventions only on fluentMappings)\u003cbr /\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cpre class=\"brush: csharp;\"\u003eprivate static IPersistenceConfigurer _persistenceConfigurer;\u003cbr /\u003e\u003cbr /\u003eprivate static void ConfigureNH(IPersistenceConfigurer persistenceConfigurer)\u003cbr /\u003e{\u003cbr /\u003e _persistenceConfigurer = persistenceConfigurer;\u003cbr /\u003e Fluently.\u003cbr /\u003e Configure().\u003cbr /\u003e Database(persistenceConfigurer).\u003cbr /\u003e Diagnostics(x =\u0026gt; x.Enable(true).OutputToConsole()).\u003cbr /\u003e Mappings(SomeMappings).\u003cbr /\u003e BuildConfiguration();\u003cbr /\u003e}\u003cbr /\u003e\u003cbr /\u003eprivate static void SomeMappings(MappingConfiguration mappingConfiguration)\u003cbr /\u003e{\u003cbr /\u003e string name = _persistenceConfigurer.GetType().Name.Replace(\u0026ldquo;Configuration\u0026rdquo;, string.Empty);\u003cbr /\u003e\u003cbr /\u003e mappingConfiguration.FluentMappings.Conventions.AddSource(new PerDBConventionSource(name));\u003cbr /\u003e}\u003cbr /\u003e\u003c/pre\u003e\u003cbr /\u003e\u003cbr /\u003eSo when I\u0026rsquo;ll run the following code:\u003cbr /\u003e\u003cbr /\u003e\u003cpre class=\"brush: csharp;\"\u003eConsole.BackgroundColor = ConsoleColor.DarkGreen;\u003cbr /\u003eConsole.ForegroundColor= ConsoleColor.Green;\u003cbr /\u003e\u003cbr /\u003eConfigureNH(OracleClientConfiguration.Oracle10.ConnectionString(\u0026ldquo;some OracleClient connection\u0026rdquo;));\u003cbr /\u003e\u003cbr /\u003eConsole.BackgroundColor = ConsoleColor.DarkBlue;\u003cbr /\u003eConsole.ForegroundColor = ConsoleColor.Blue;\u003cbr /\u003e\u003cbr /\u003eConfigureNH(MsSqlCeConfiguration.Standard.ConnectionString(\u0026ldquo;some MsSqlCe connection\u0026rdquo;));\u003cbr /\u003e\u003c/pre\u003e\u003cbr /\u003eThe result will be\u003cbr /\u003e\u003cdiv class=\"separator\" style=\"clear: both; text-align: center;\"\u003e\u003ca href=\"http://1.bp.blogspot.com/-7JDQlxsnsNs/TV56uparJZI/AAAAAAAACN4/waScYrGm_tY/s1600/or2.GIF\" imageanchor=\"1\" style=\"margin-left: 1em; margin-right: 1em;\"\u003e\u003cimg border=\"0\" height=\"144\" src=\"http://1.bp.blogspot.com/-7JDQlxsnsNs/TV56uparJZI/AAAAAAAACN4/waScYrGm_tY/s640/or2.GIF\" width=\"640\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\u003cdiv class=\"separator\" style=\"clear: both; text-align: center;\"\u003e\u003ca href=\"http://3.bp.blogspot.com/-wRwtcdZh_z8/TV56xcqDA2I/AAAAAAAACN8/nSsaowp2GTc/s1600/sql2.GIF\" imageanchor=\"1\" style=\"margin-left: 1em; margin-right: 1em;\"\u003e\u003cimg border=\"0\" height=\"118\" src=\"http://3.bp.blogspot.com/-wRwtcdZh_z8/TV56xcqDA2I/AAAAAAAACN8/nSsaowp2GTc/s640/sql2.GIF\" width=\"640\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\u003cdiv class=\"separator\" style=\"clear: both; text-align: center;\"\u003e\u003c/div\u003e\u003cbr /\u003eWhy you should use his pattern anyway(even if you work with 1 db):\u003cbr /\u003e1. unit testing with sqlite in memory will not work with sequence conventions, so you shouldn\u0026rsquo;t load them when you are unit testing.\u003cbr /\u003e2. If you\u0026rsquo;ll some day change the db type, you\u0026rsquo;ll know where to add its own conventions, just create a folder with db name and add it\u0026rsquo;s conventions inside no other change is necessary.\u003cbr /\u003e\u003cbr /\u003eYou can find the source here:\u003cbr /\u003e\u003ciframe title =\"Preview\" scrolling=\"no\" marginheight=\"0\" marginwidth=\"0\" frameborder=\"0\" style=\"width:98px;height:115px;padding:0;background-color:#fcfcfc;\" src=\"http://cid-b7c55b5696998a0e.office.live.com/embedicon.aspx/BLGR/PerDBConventions.7z\"\u003e\u003c/iframe\u003e\u003c/p\u003e","title":"Per DB Conventions With FluentNhibernate"},{"content":"I got a new task: Build Nhibernate based infrastructure, so I decided to check the existing third party tools and my boss gave me a day at home to check them ;-D .\nI only check tools that:\nbased on existing DB support oracle works with NH 3First tool I got my hands on is NH3SQLLogger NH3SQLLogger - Nhibernate 3 SQL logger, this is a cool utility that will help you understand what the hell nhibernate is doing , where he is doing his stuff (yes yes a stack trace) and all parameters of queries are also reflected, this is the perfect development time logger.\ndo not active it on production by default, only if you need to debug prod.\nHere is a sample output of this util:\n\u0026mdash;+ 01/24/2011 10:14:42.57 +\u0026mdash;\n\u0026ndash; Void Logic.Test.UserRepositoryTest.SaveUser() [File=UserRepositoryTest.cs, Line=86]\nINSERT INTO\n\u0026ldquo;User\u0026rdquo;\n(FirstName, LastName, BirthDate, Gender, PhoneNumber, IsDeleted, Created, LastUpdated, Name, Address_id, FacebookProfile_id) VALUES\n(@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);\nselect\nlast_insert_rowid();\n@p0 = \u0026lsquo;Chen\u0026rsquo; [Type: String (0)]\n@p1 = \u0026lsquo;Kinnrot\u0026rsquo; [Type: String (0)]\n@p2 = 24/01/2011 00:00:00 [Type: DateTime (0)]\n@p3 = \u0026lsquo;Male\u0026rsquo; [Type: String (0)]\n@p4 = \u0026lsquo;0578149177\u0026rsquo; [Type: String (0)]\n@p5 = False [Type: Boolean (0)]\n@p6 = 01/01/0001 00:00:00 [Type: DateTime (0)]\n@p7 = 01/01/0001 00:00:00 [Type: DateTime (0)]\n@p8 = \u0026lsquo;kinnrot\u0026rsquo; [Type: String (0)]\n@p9 = 1 [Type: Int64 (0)]\n@p10 = 1 [Type: Int64 (0)]\nNHibernator\nAllows you to load db configuration by a key in the configuration file, good for application that works with more than one DB.Wraps sessions and transactions for session per HTTP session and session per thread. No download available only codeNHibernateIt Allows you to do some basic crud through a generic repository implementation. Has the same session and transaction encapsulation as in Nhibernator.Nhibenrate Mapping Generator - Don\u0026rsquo;t know if working(Need to test on a big DB), but should generate mappings and classes from existing db, support MSSQL,Oracle and Postgre SQL.\nIf you got a DB and don\u0026rsquo;t go fluent, this is probably good solution for a quick start.\nFluent Nhibernate - Framework with fluent interface based mapping and configuration.\nHas an auto map feature with a lot of flexible convention over configuration options. One more thing they supply is an easy to use mapping test classes (called PersistenceSpecification ).\nYou should consider auto mapping if your DB got name conventions, but you loose the flexibility of the mapping file per entity built in Nhibernate, and non conventional changes will make you write patches (AutoMappingOverride).\n","permalink":"https://kinnrot.github.io/building-business-tier-with-nhibernate/","summary":"\u003cp\u003eI got a new task: Build Nhibernate based infrastructure, so I decided to check the existing third party tools and my boss gave me a day at home to check them ;-D .\u003cbr /\u003e\u003cbr /\u003e I only check tools that:\u003cbr /\u003e\u003cul\u003e\u003cli\u003ebased on existing DB \u003c/li\u003e\u003cli\u003esupport oracle \u003c/li\u003e\u003cli\u003eworks with NH 3\u003c/li\u003e\u003c/ul\u003eFirst tool I got my hands on is \u003ca href=\"http://nh3sqllogger.codeplex.com/\"\u003eNH3SQLLogger\u003c/a\u003e \u003cbr /\u003e\u003cbr /\u003eNH3SQLLogger - Nhibernate 3 SQL logger, this is a cool utility that will help you understand what the hell nhibernate is doing , where he is doing his stuff (yes yes a stack trace) and all parameters of queries are also reflected, this is the perfect development time logger.\u003cbr /\u003e\u003cbr /\u003e\u003cem\u003e \u003cspan class=\"Apple-style-span\" style=\"color: red;\"\u003e\u003cb\u003edo not \u003c/b\u003eactive it on production by default, only if you need to debug prod\u003c/span\u003e.\u003cbr /\u003e\u003cbr /\u003eHere is a sample output of this util:\u003cbr /\u003e\u003cbr /\u003e\u003cpre class=\"brush: sql\"\u003e\u0026mdash;+ 01/24/2011 10:14:42.57 +\u0026mdash;\u003cbr /\u003e\u0026ndash; Void Logic.Test.UserRepositoryTest.SaveUser() [File=UserRepositoryTest.cs, Line=86]\u003cbr /\u003e\u003cbr /\u003eINSERT \u003cbr /\u003e INTO\u003cbr /\u003e \u0026ldquo;User\u0026rdquo;\u003cbr /\u003e (FirstName, LastName, BirthDate, Gender, PhoneNumber, IsDeleted, Created, LastUpdated, Name, Address_id, FacebookProfile_id) \u003cbr /\u003e VALUES\u003cbr /\u003e (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);\u003cbr /\u003e\u003cbr /\u003eselect\u003cbr /\u003e last_insert_rowid();\u003cbr /\u003e\u003cbr /\u003e@p0 = \u0026lsquo;Chen\u0026rsquo; [Type: String (0)]\u003cbr /\u003e@p1 = \u0026lsquo;Kinnrot\u0026rsquo; [Type: String (0)]\u003cbr /\u003e@p2 = 24/01/2011 00:00:00 [Type: DateTime (0)]\u003cbr /\u003e@p3 = \u0026lsquo;Male\u0026rsquo; [Type: String (0)]\u003cbr /\u003e@p4 = \u0026lsquo;0578149177\u0026rsquo; [Type: String (0)]\u003cbr /\u003e@p5 = False [Type: Boolean (0)]\u003cbr /\u003e@p6 = 01/01/0001 00:00:00 [Type: DateTime (0)]\u003cbr /\u003e@p7 = 01/01/0001 00:00:00 [Type: DateTime (0)]\u003cbr /\u003e@p8 = \u0026lsquo;kinnrot\u0026rsquo; [Type: String (0)]\u003cbr /\u003e@p9 = 1 [Type: Int64 (0)]\u003cbr /\u003e@p10 = 1 [Type: Int64 (0)]\u003cbr /\u003e\u003cbr /\u003e\u003c/pre\u003e\u003cbr /\u003e\u003ca href=\"http://nhibernator.sourceforge.net/\"\u003eNHibernator\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"http://nhibernator.sourceforge.net/\"\u003e\u003c/a\u003e\u003cbr /\u003e\u003cul\u003e\u003cli\u003eAllows you to load db configuration by a key in the configuration file, good for application that works with more than one DB.\u003c/li\u003e\u003cli\u003eWraps sessions and transactions for session per HTTP session and session per thread. \u003c/li\u003e\u003cli\u003e\u003cb\u003eNo download available only code\u003c/b\u003e\u003c/li\u003e\u003c/ul\u003e\u003cdiv style=\"text-align: -webkit-auto;\"\u003e\u003cspan class=\"Apple-style-span\" style=\"line-height: 16px;\"\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: Arial, Helvetica, sans-serif; font-size: xx-small;\"\u003e\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003ch2 class=\"ph-title\" style=\"display: inline; margin-bottom: 0px !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 0px !important; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left;\"\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: Arial, Helvetica, sans-serif; font-size: x-small;\"\u003e\u003ca href=\"http://nhibernateit.sourceforge.net/\"\u003eNHibernateIt\u003c/a\u003e\u003c/span\u003e\u003c/h2\u003e\u003cdiv style=\"text-align: -webkit-auto;\"\u003e\u003c/div\u003e\u003cul\u003e\u003cli\u003e\u003cspan class=\"Apple-style-span\" style=\"line-height: 16px;\"\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: Arial, Helvetica, sans-serif; font-size: xx-small;\"\u003e \u003c/span\u003e\u003c/span\u003eAllows you to do some basic crud through a generic repository implementation.\u003c/li\u003e\u003cli\u003e Has the same session and transaction encapsulation as in Nhibernator.\u003c/li\u003e\u003c/ul\u003e\u003ca href=\"http://nmg.codeplex.com/\"\u003eNhibenrate Mapping Generator\u003c/a\u003e - Don\u0026rsquo;t know if working(Need to test on a big DB), but should generate mappings and classes from existing db, support MSSQL,Oracle and Postgre SQL.\u003cbr /\u003eIf you got a DB and don\u0026rsquo;t go fluent, this is probably good solution for a quick start.\u003cbr /\u003e\u003cbr /\u003e\u003ca href=\"http://fluentnhibernate.org/\"\u003eFluent Nhibernate\u003c/a\u003e - Framework with fluent interface based mapping and configuration.\u003cbr /\u003eHas an auto map feature with a lot of flexible convention over configuration options. One more thing they supply is an easy to use mapping test classes (called \u003cspan class=\"Apple-style-span\" style=\"font-family: arial, sans-serif; line-height: 19px;\"\u003e\u003ca class=\"spell\" href=\"http://www.google.co.il/search?hl=iw\u0026amp;rlz=1C1CHEU_enIL389IL389\u0026amp;\u0026amp;sa=X\u0026amp;ei=35s9Tc6WOszNswbag8HzBg\u0026amp;ved=0CCYQBSgA\u0026amp;q=PersistenceSpecification\u0026amp;spell=1\" style=\"color: #2200c1; cursor: pointer;\"\u003e\u003cb\u003e\u003ci\u003ePersistenceSpecification\u003c/i\u003e\u003c/b\u003e\u003c/a\u003e \u003c/span\u003e).\u003cbr /\u003e\u003cbr /\u003e\u003c/em\u003e You should consider auto mapping if your DB got name conventions, but you loose the flexibility of the mapping file per entity built in Nhibernate, and non conventional changes will make you write patches (\u003cspan class=\"Apple-style-span\" style=\"font-family: Monaco, 'Courier New', Courier, Fixed; font-size: 12px; line-height: 15px; white-space: pre;\"\u003e\u003ca href=\"http://wiki.fluentnhibernate.org/Auto_mapping#Altering_entities\"\u003eAutoMappingOverride\u003c/a\u003e\u003cspan class=\"Apple-style-span\" style=\"color: #784838;\"\u003e).\u003c/span\u003e\u003c/span\u003e\u003cbr /\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: Monaco, 'Courier New', Courier, Fixed; font-size: 12px; line-height: 15px; white-space: pre;\"\u003e\u003cspan class=\"Apple-style-span\" style=\"color: #784838;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/span\u003e\u003cbr /\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: Monaco, 'Courier New', Courier, Fixed; font-size: 12px; line-height: 15px; white-space: pre;\"\u003e\u003cspan class=\"Apple-style-span\" style=\"color: #784838;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/span\u003e\u003c/p\u003e","title":"Building a business tier with Nhibernate - Tools"},{"content":"I\u0026rsquo;m overriding equals and implementing IEquatable on some of my objects and bind them as an ObservableCollection to the UI.\nHere is a sample: (ugly code do not use)\n\u0026lt;Window x:Class=\u0026ldquo;BindingToItemsWithIEquality.MainWindow\u0026rdquo;\nxmlns=\u0026ldquo;http://schemas.microsoft.com/winfx/2006/xaml/presentation\u0026quot;\nxmlns:x=\u0026ldquo;http://schemas.microsoft.com/winfx/2006/xaml\u0026quot;\nxmlns:local=\u0026ldquo;clr-namespace:BindingToItemsWithIEquality\u0026rdquo;\nTitle=\u0026ldquo;MainWindow\u0026rdquo; Height=\u0026ldquo;350\u0026rdquo; Width=\u0026ldquo;525\u0026rdquo;\n\u0026gt;\n\u0026lt;Window.DataContext\u0026gt;\n\u0026lt;local:SomeContextWithCollection/\u0026gt;\n\u0026lt;/Window.DataContext\u0026gt;\n\u0026lt;StackPanel\u0026gt;\n\u0026lt;ListBox DisplayMemberPath=\u0026ldquo;Name\u0026rdquo; ItemsSource=\u0026quot;{Binding Items}\u0026rdquo;/\u0026gt;\n\u0026lt;Button Click=\u0026ldquo;Button_Click\u0026rdquo;\u0026gt;clear\u0026lt;/Button\u0026gt;\n\u0026lt;/StackPanel\u0026gt;\n\u0026lt;/Window\u0026gt;\n//code behind\nprivate void Button_Click(object sender, RoutedEventArgs e)\n{\n(this.DataContext as SomeContextWithCollection).Items.Clear();\n}\npublic class SomeContextWithCollection {\npublic ObservableCollection\u0026lt;SomeIEqutable\u0026gt; Items { get; set; }\npublic SomeContextWithCollection()\n{\nItems = new ObservableCollection\u0026lt;SomeIEqutable\u0026gt;();\nItems.Add(new SomeIEqutable() { Name = \u0026ldquo;1\u0026rdquo; });\nItems.Add(new SomeIEqutable() { Name = \u0026ldquo;2\u0026rdquo; });\n}\n}\npublic class SomeIEqutable : IEquatable\u0026lt;SomeIEqutable\u0026gt;\n{\npublic string Name { get; set; }\npublic override bool Equals(object obj)\n{\nif (obj == null)\n{\nreturn false;\n}\nreturn Equals((SomeIEqutable)obj);\n}\npublic bool Equals(SomeIEqutable other)\n{\nif (object.ReferenceEquals(this, other))\n{\nreturn true;\n}\nreturn Name == other.Name;\n}\npublic override int GetHashCode()\n{\nreturn Name.GetHashCode();\n}\n}\nWhen calling collection.Clear() I get an invalid cast inside my equals method, when trying to cast to SomeIEquatable.\nThis is pretty strange, object is not null and not SomeIEquatlabe, how did it get to my Equals?\nThe answer is WPF, when working with binding and clearing a bounded collection WPF will compare his internal new MSInternal.NamedObject(named DisconnectedItem) to your SomeIEquatable object and will fail if you try to implicitly cast it to your type.\nThe simple solution is to use the \u0026ldquo;as\u0026rdquo; keyword instead of cast.\nIf my code didn\u0026rsquo;t smell from the start, I would never got to this dark place. But I\u0026rsquo;m glad it happened, now I have another excuse to write defensive code.\n","permalink":"https://kinnrot.github.io/wpf-binding-and-why-you-should-write/","summary":"\u003cp\u003eI\u0026rsquo;m overriding equals and implementing IEquatable on some of my objects and bind them as an ObservableCollection to the UI.\u003cbr /\u003e\u003cbr /\u003eHere is a sample: (ugly code do not use)\u003cbr /\u003e\u003cbr /\u003e\u003cpre class=\"brush: csharp;\"\u003e\u0026lt;Window x:Class=\u0026ldquo;BindingToItemsWithIEquality.MainWindow\u0026rdquo;\u003cbr /\u003e xmlns=\u0026ldquo;\u003ca href=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation%22\"\u003ehttp://schemas.microsoft.com/winfx/2006/xaml/presentation\u0026quot;\u003c/a\u003e\u003cbr /\u003e xmlns:x=\u0026ldquo;\u003ca href=\"http://schemas.microsoft.com/winfx/2006/xaml%22\"\u003ehttp://schemas.microsoft.com/winfx/2006/xaml\u0026quot;\u003c/a\u003e\u003cbr /\u003e xmlns:local=\u0026ldquo;clr-namespace:BindingToItemsWithIEquality\u0026rdquo;\u003cbr /\u003e Title=\u0026ldquo;MainWindow\u0026rdquo; Height=\u0026ldquo;350\u0026rdquo; Width=\u0026ldquo;525\u0026rdquo;\u003cbr /\u003e \u0026gt;\u003cbr /\u003e \u0026lt;Window.DataContext\u0026gt;\u003cbr /\u003e \u0026lt;local:SomeContextWithCollection/\u0026gt;\u003cbr /\u003e \u0026lt;/Window.DataContext\u0026gt;\u003cbr /\u003e \u0026lt;StackPanel\u0026gt;\u003cbr /\u003e \u0026lt;ListBox DisplayMemberPath=\u0026ldquo;Name\u0026rdquo; ItemsSource=\u0026quot;{Binding Items}\u0026rdquo;/\u0026gt;\u003cbr /\u003e \u0026lt;Button Click=\u0026ldquo;Button_Click\u0026rdquo;\u0026gt;clear\u0026lt;/Button\u0026gt;\u003cbr /\u003e \u0026lt;/StackPanel\u0026gt;\u003cbr /\u003e\u0026lt;/Window\u0026gt;\u003cbr /\u003e\u003cbr /\u003e//code behind\u003cbr /\u003eprivate void Button_Click(object sender, RoutedEventArgs e)\u003cbr /\u003e{\u003cbr /\u003e (this.DataContext as SomeContextWithCollection).Items.Clear();\u003cbr /\u003e}\u003cbr /\u003e\u003cbr /\u003epublic class SomeContextWithCollection \u003cbr /\u003e{\u003cbr /\u003e public ObservableCollection\u0026lt;SomeIEqutable\u0026gt; Items { get; set; }\u003cbr /\u003e\u003cbr /\u003e public SomeContextWithCollection()\u003cbr /\u003e {\u003cbr /\u003e Items = new ObservableCollection\u0026lt;SomeIEqutable\u0026gt;();\u003cbr /\u003e Items.Add(new SomeIEqutable() { Name = \u0026ldquo;1\u0026rdquo; });\u003cbr /\u003e Items.Add(new SomeIEqutable() { Name = \u0026ldquo;2\u0026rdquo; });\u003cbr /\u003e }\u003cbr /\u003e}\u003cbr /\u003e\u003cbr /\u003epublic class SomeIEqutable : IEquatable\u0026lt;SomeIEqutable\u0026gt;\u003cbr /\u003e{\u003cbr /\u003e public string Name { get; set; }\u003cbr /\u003e\u003cbr /\u003e public override bool Equals(object obj)\u003cbr /\u003e {\u003cbr /\u003e if (obj == null)\u003cbr /\u003e {\u003cbr /\u003e return false;\u003cbr /\u003e }\u003cbr /\u003e \u003cbr /\u003e return Equals((SomeIEqutable)obj);\u003cbr /\u003e }\u003cbr /\u003e\u003cbr /\u003e public bool Equals(SomeIEqutable other)\u003cbr /\u003e {\u003cbr /\u003e if (object.ReferenceEquals(this, other))\u003cbr /\u003e {\u003cbr /\u003e return true;\u003cbr /\u003e }\u003cbr /\u003e\u003cbr /\u003e return Name == other.Name;\u003cbr /\u003e }\u003cbr /\u003e\u003cbr /\u003e public override int GetHashCode()\u003cbr /\u003e {\u003cbr /\u003e return Name.GetHashCode();\u003cbr /\u003e }\u003cbr /\u003e}\u003cbr /\u003e\u003c/pre\u003e\u003cbr /\u003eWhen calling collection.Clear() I get an invalid cast inside my equals method, when trying to cast to SomeIEquatable.\u003cbr /\u003e\u003cbr /\u003eThis is pretty strange, object is not null and not SomeIEquatlabe, how did it get to my Equals?\u003cbr /\u003e\u003cbr /\u003eThe answer is WPF, when working with binding and clearing a bounded collection WPF will compare his internal new MSInternal.NamedObject(named DisconnectedItem) to your SomeIEquatable object and will fail if you try to implicitly cast it to your type.\u003cbr /\u003e\u003cbr /\u003eThe simple solution is to use the \u0026ldquo;as\u0026rdquo; keyword instead of cast.\u003cbr /\u003e\u003cbr /\u003eIf my code didn\u0026rsquo;t smell from the start, I would never got to this dark place. But I\u0026rsquo;m glad it happened, now I have another excuse to write defensive code.\u003c/p\u003e","title":"WPF Binding and Why you should write defensive code."},{"content":"About a year ago I asked the following question\nThis week I got one more answer and I wanna ask you guys what do you think is the best practice?\n","permalink":"https://kinnrot.github.io/what-do-you-think/","summary":"\u003cp\u003eAbout a year ago I asked the following question\u003cbr /\u003e \u003cdiv id=\"stacktack-1114555\"\u003e\u003c/div\u003eThis week I got one more answer and I wanna ask you guys what do you think is the best practice?\u003c/p\u003e","title":"What do you think?"},{"content":"Hard coded strings are annoying,\nIn XAML, we have a lot of cases of hard coded strings.\nHere is a simple way of implementing static naming class, and use it instead of hard coded strings.\nSuppose this is my xaml:\n\u0026lt;Window x:Class=\u0026ldquo;How.MainWindow\u0026rdquo;\nxmlns=\u0026ldquo;http://schemas.microsoft.com/winfx/2006/xaml/presentation\u0026quot;\nxmlns:x=\u0026ldquo;http://schemas.microsoft.com/winfx/2006/xaml\u0026quot;\nxmlns:local=\u0026ldquo;clr-namespace:How\u0026rdquo;\nTitle=\u0026ldquo;MainWindow\u0026rdquo; Height=\u0026ldquo;350\u0026rdquo; Width=\u0026ldquo;525\u0026rdquo;\u0026gt;\n\u0026lt;Window.Resources\u0026gt;\n\u0026lt;Style TargetType=\u0026quot;{x:Type Button}\u0026rdquo; x:Key=\u0026ldquo;LazyGuyMeaninglessName\u0026rdquo;\u0026gt;\n\u0026lt;Setter Property=\u0026ldquo;Margin\u0026rdquo; Value=\u0026ldquo;30\u0026rdquo;/\u0026gt;\n\u0026lt;Setter Property=\u0026ldquo;Height\u0026rdquo; Value=\u0026ldquo;30\u0026rdquo;/\u0026gt;\n\u0026lt;Setter Property=\u0026ldquo;Width\u0026rdquo; Value=\u0026ldquo;200\u0026rdquo;/\u0026gt;\n\u0026lt;/Style\u0026gt;\n\u0026lt;/Window.Resources\u0026gt;\n\u0026lt;StackPanel\u0026gt;\n\u0026lt;Button Click=\u0026ldquo;Button_Click\u0026rdquo;\u0026gt;Click me to activate my style\u0026lt;/Button\u0026gt;\n\u0026lt;Button Style=\u0026quot;{DynamicResource LazyGuyMeaninglessName}\u0026rdquo;/\u0026gt;\n\u0026lt;/StackPanel\u0026gt;\n\u0026lt;/Window\u0026gt;\nThis is code behind:\nprivate void Button_Click(object sender, RoutedEventArgs e)\n{\nvar button = sender as Button;\nif (button != null)\n{\nbutton.Style = (Style)this.FindResource(\u0026ldquo;LazyGuyMeaninglessNameWithMistake\u0026rdquo;);\n}\n}\nI have a mistake in my code behind, and the program will crash, not so fun, and not simple to test this kind of stuff.\nThere is a very simple solution, Lets define this class:\npublic static class StyleNames\n{\npublic static string ButtonStyleName = \u0026ldquo;Some Hard To write style name\u0026rdquo;;\n}\nThe benefits of using this class instead of hard coded strings are:\nNo need to avoid long meaningful names, cause you have auto complete built in the IDE.The obvious: avoid type mistakes, and unexpected crashes.Make your programmers less lazy, they\u0026rsquo;ll be able to change the resource name in a single place, and even his member name if needed, VS will rename it in all references and in XAML(VS 2010) (with a \u0026ldquo;Ctrl + .\u0026rdquo; after editing the member name).If the style name is not readonly(like in my sample), I\u0026rsquo;m sure there is a simple way to support theming and dynamic style changing, by just assigning new names for all the resource names inside StyleNames class, and telling the app to do something that will reload all styles, I\u0026rsquo;m not sure about it, so don\u0026rsquo;t count on it.No crashes of \u0026ldquo;could not find resource bla bla\u0026rdquo;.\nHere is the code after the use of static class:\n\u0026lt;Window x:Class=\u0026ldquo;How.MainWindow\u0026rdquo;\nxmlns=\u0026ldquo;http://schemas.microsoft.com/winfx/2006/xaml/presentation\u0026quot;\nxmlns:x=\u0026ldquo;http://schemas.microsoft.com/winfx/2006/xaml\u0026quot;\nxmlns:local=\u0026ldquo;clr-namespace:How\u0026rdquo;\nTitle=\u0026ldquo;MainWindow\u0026rdquo; Height=\u0026ldquo;350\u0026rdquo; Width=\u0026ldquo;525\u0026rdquo;\u0026gt;\n\u0026lt;Window.Resources\u0026gt;\n\u0026lt;Style TargetType=\u0026quot;{x:Type Button}\u0026rdquo; x:Key=\u0026quot;{x:Static local:StyleNames.ButtonStyleName}\u0026quot;\u0026gt;\n\u0026lt;Setter Property=\u0026ldquo;Margin\u0026rdquo; Value=\u0026ldquo;30\u0026rdquo;/\u0026gt;\n\u0026lt;Setter Property=\u0026ldquo;Height\u0026rdquo; Value=\u0026ldquo;30\u0026rdquo;/\u0026gt;\n\u0026lt;Setter Property=\u0026ldquo;Width\u0026rdquo; Value=\u0026ldquo;200\u0026rdquo;/\u0026gt;\n\u0026lt;/Style\u0026gt;\n\u0026lt;/Window.Resources\u0026gt;\n\u0026lt;StackPanel\u0026gt;\n\u0026lt;Button Click=\u0026ldquo;Button_Click\u0026rdquo;\u0026gt;Click me to activate my style\u0026lt;/Button\u0026gt;\n\u0026lt;Button Style=\u0026quot;{DynamicResource ResourceKey={x:Static local:StyleNames.ButtonStyleName}}\u0026rdquo;/\u0026gt;\n\u0026lt;/StackPanel\u0026gt;\n\u0026lt;/Window\u0026gt;\nprivate void Button_Click(object sender, RoutedEventArgs e)\n{\nvar button = sender as Button;\nif (button != null)\n{\nbutton.Style = (Style)this.FindResource(StyleNames.ButtonStyleName);\n}\n}\nEnjoy :)\n","permalink":"https://kinnrot.github.io/simple-way-to-avoid-hard-coded-strings/","summary":"\u003cp\u003eHard coded strings are annoying,\u003cbr /\u003eIn XAML, we have a lot of cases of hard coded strings.\u003cbr /\u003e\u003cbr /\u003eHere is a simple way of implementing static naming class, and use it instead of hard coded strings.\u003cbr /\u003e\u003cbr /\u003eSuppose this is my xaml:\u003cbr /\u003e\u003cbr /\u003e\u003cpre class=\"brush: csharp;\"\u003e\u0026lt;Window x:Class=\u0026ldquo;How.MainWindow\u0026rdquo;\u003cbr /\u003e xmlns=\u0026ldquo;\u003ca href=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation%22\"\u003ehttp://schemas.microsoft.com/winfx/2006/xaml/presentation\u0026quot;\u003c/a\u003e\u003cbr /\u003e xmlns:x=\u0026ldquo;\u003ca href=\"http://schemas.microsoft.com/winfx/2006/xaml%22\"\u003ehttp://schemas.microsoft.com/winfx/2006/xaml\u0026quot;\u003c/a\u003e\u003cbr /\u003e xmlns:local=\u0026ldquo;clr-namespace:How\u0026rdquo;\u003cbr /\u003e Title=\u0026ldquo;MainWindow\u0026rdquo; Height=\u0026ldquo;350\u0026rdquo; Width=\u0026ldquo;525\u0026rdquo;\u0026gt;\u003cbr /\u003e \u0026lt;Window.Resources\u0026gt;\u003cbr /\u003e \u0026lt;Style TargetType=\u0026quot;{x:Type Button}\u0026rdquo; x:Key=\u0026ldquo;LazyGuyMeaninglessName\u0026rdquo;\u0026gt;\u003cbr /\u003e \u0026lt;Setter Property=\u0026ldquo;Margin\u0026rdquo; Value=\u0026ldquo;30\u0026rdquo;/\u0026gt;\u003cbr /\u003e \u0026lt;Setter Property=\u0026ldquo;Height\u0026rdquo; Value=\u0026ldquo;30\u0026rdquo;/\u0026gt;\u003cbr /\u003e \u0026lt;Setter Property=\u0026ldquo;Width\u0026rdquo; Value=\u0026ldquo;200\u0026rdquo;/\u0026gt;\u003cbr /\u003e \u0026lt;/Style\u0026gt;\u003cbr /\u003e \u0026lt;/Window.Resources\u0026gt;\u003cbr /\u003e \u0026lt;StackPanel\u0026gt;\u003cbr /\u003e \u0026lt;Button Click=\u0026ldquo;Button_Click\u0026rdquo;\u0026gt;Click me to activate my style\u0026lt;/Button\u0026gt;\u003cbr /\u003e \u0026lt;Button Style=\u0026quot;{DynamicResource LazyGuyMeaninglessName}\u0026rdquo;/\u0026gt;\u003cbr /\u003e \u0026lt;/StackPanel\u0026gt;\u003cbr /\u003e\u0026lt;/Window\u0026gt;\u003cbr /\u003e\u003cbr /\u003e\u003c/pre\u003e\u003cbr /\u003eThis is code behind:\u003cbr /\u003e\u003cbr /\u003e\u003cpre class=\"brush: csharp;\"\u003eprivate void Button_Click(object sender, RoutedEventArgs e)\u003cbr /\u003e{\u003cbr /\u003e var button = sender as Button;\u003cbr /\u003e if (button != null)\u003cbr /\u003e {\u003cbr /\u003e button.Style = (Style)this.FindResource(\u0026ldquo;LazyGuyMeaninglessNameWithMistake\u0026rdquo;);\u003cbr /\u003e }\u003cbr /\u003e}\u003cbr /\u003e\u003c/pre\u003e\u003cbr /\u003eI have a mistake in my code behind, and the program will crash, not so fun, and not simple to test this kind of stuff.\u003cbr /\u003e\u003cbr /\u003eThere is a very simple solution, Lets define this class:\u003cbr /\u003e\u003cbr /\u003e\u003cpre class=\"brush: csharp;\"\u003epublic static class StyleNames\u003cbr /\u003e{\u003cbr /\u003e public static string ButtonStyleName = \u0026ldquo;Some Hard To write style name\u0026rdquo;;\u003cbr /\u003e}\u003cbr /\u003e\u003c/pre\u003e\u003cbr /\u003eThe benefits of using this class instead of hard coded strings are:\u003cbr /\u003e\u003cbr /\u003e\u003cul\u003e\u003cli\u003eNo need to avoid long meaningful names, cause you have auto complete built in the IDE.\u003c/li\u003e\u003cli\u003eThe obvious: avoid type mistakes, and unexpected crashes.\u003c/li\u003e\u003cli\u003eMake your programmers less lazy, they\u0026rsquo;ll be able to change the resource name in a single place, and even his member name if needed, VS will rename it in all references and in XAML(VS 2010) (with a \u0026ldquo;Ctrl + .\u0026rdquo; after editing the member name).\u003c/li\u003e\u003cli\u003eIf the style name is not readonly(like in my sample), I\u0026rsquo;m sure there is a simple way to support theming and dynamic style changing, by just assigning new names for all the resource names inside StyleNames class, and telling the app to do something that will reload all styles, I\u0026rsquo;m not sure about it, so don\u0026rsquo;t count on it.\u003c/li\u003e\u003cli\u003eNo crashes of \u0026ldquo;could not find resource bla bla\u0026rdquo;.\u003c/li\u003e\u003c/ul\u003e\u003cbr /\u003eHere is the code after the use of static class:\u003cbr /\u003e\u003cbr /\u003e\u003cpre class=\"brush: csharp;\"\u003e\u0026lt;Window x:Class=\u0026ldquo;How.MainWindow\u0026rdquo;\u003cbr /\u003e xmlns=\u0026ldquo;\u003ca href=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation%22\"\u003ehttp://schemas.microsoft.com/winfx/2006/xaml/presentation\u0026quot;\u003c/a\u003e\u003cbr /\u003e xmlns:x=\u0026ldquo;\u003ca href=\"http://schemas.microsoft.com/winfx/2006/xaml%22\"\u003ehttp://schemas.microsoft.com/winfx/2006/xaml\u0026quot;\u003c/a\u003e\u003cbr /\u003e xmlns:local=\u0026ldquo;clr-namespace:How\u0026rdquo;\u003cbr /\u003e Title=\u0026ldquo;MainWindow\u0026rdquo; Height=\u0026ldquo;350\u0026rdquo; Width=\u0026ldquo;525\u0026rdquo;\u0026gt;\u003cbr /\u003e\u0026lt;Window.Resources\u0026gt;\u003cbr /\u003e \u0026lt;Style TargetType=\u0026quot;{x:Type Button}\u0026rdquo; x:Key=\u0026quot;{x:Static local:StyleNames.ButtonStyleName}\u0026quot;\u0026gt;\u003cbr /\u003e \u0026lt;Setter Property=\u0026ldquo;Margin\u0026rdquo; Value=\u0026ldquo;30\u0026rdquo;/\u0026gt;\u003cbr /\u003e \u0026lt;Setter Property=\u0026ldquo;Height\u0026rdquo; Value=\u0026ldquo;30\u0026rdquo;/\u0026gt;\u003cbr /\u003e \u0026lt;Setter Property=\u0026ldquo;Width\u0026rdquo; Value=\u0026ldquo;200\u0026rdquo;/\u0026gt;\u003cbr /\u003e \u0026lt;/Style\u0026gt;\u003cbr /\u003e\u0026lt;/Window.Resources\u0026gt;\u003cbr /\u003e\u0026lt;StackPanel\u0026gt;\u003cbr /\u003e \u0026lt;Button Click=\u0026ldquo;Button_Click\u0026rdquo;\u0026gt;Click me to activate my style\u0026lt;/Button\u0026gt;\u003cbr /\u003e \u0026lt;Button Style=\u0026quot;{DynamicResource ResourceKey={x:Static local:StyleNames.ButtonStyleName}}\u0026rdquo;/\u0026gt;\u003cbr /\u003e\u0026lt;/StackPanel\u0026gt;\u003cbr /\u003e\u0026lt;/Window\u0026gt;\u003cbr /\u003e\u003cbr /\u003eprivate void Button_Click(object sender, RoutedEventArgs e)\u003cbr /\u003e{\u003cbr /\u003e var button = sender as Button;\u003cbr /\u003e if (button != null)\u003cbr /\u003e {\u003cbr /\u003e button.Style = (Style)this.FindResource(StyleNames.ButtonStyleName);\u003cbr /\u003e }\u003cbr /\u003e}\u003cbr /\u003e\u003c/pre\u003e\u003cbr /\u003eEnjoy :)\u003c/p\u003e","title":"Simple way to avoid hard coded strings in xaml"},{"content":"Recently a friend recommend me to check the PHP Storm IDE.\nI must say that its a grate IDE, almost same capabilities as IntelliJ, I\u0026rsquo;v never seen a PHP IDE with this refactoring and navigation features.\nSo check it out.\nThank you Gal Batat for the recommendation.\nFeatures and download is here\n","permalink":"https://kinnrot.github.io/nice-php-ide/","summary":"\u003cp\u003eRecently a friend recommend me to check the PHP Storm IDE.\u003cbr /\u003e\u003cbr /\u003eI must say that its a grate IDE, almost same capabilities as IntelliJ, I\u0026rsquo;v never seen a PHP IDE with this refactoring and navigation features.\u003cbr /\u003e\u003cbr /\u003eSo check it out.\u003cbr /\u003e\u003cbr /\u003eThank you Gal Batat for the recommendation.\u003cbr /\u003e\u003cbr /\u003eFeatures and download is \u003ca href=\"http://www.jetbrains.com/phpstorm/\"\u003ehere\u003c/a\u003e\u003c/p\u003e","title":"Nice PHP IDE"},{"content":"This post is relevant for the one\u0026rsquo;s who write tests, all you other programmers, you should learn unit testing and read it.\nOne of the most useful tools in unit testing is a good mocking framework. (I\u0026rsquo;m currently using Moq, and before that I used rhino) We all know that for mocking we need interfaces.\nMy tip is very simple, if you have a class Foo and you wanna mock it, first you should have Interface IFoo (this should be obvious to most of you).Implement on Foo IEquatable\u0026lt;IFoo\u0026gt;, so if you test a list of IFoo and you want to assert Contains() you won\u0026rsquo;t have any problems with the proxy of IFoo that mocking framework generates on the interface and no one will blame you for your awful class that throws cast exception in its equals method :).\nHope it\u0026rsquo;ll save you time in future.\nThat it, KIS.\n","permalink":"https://kinnrot.github.io/unit-testing-with-mock-framework-and/","summary":"\u003cp\u003eThis post is relevant for the one\u0026rsquo;s who write tests, all you other programmers, you should learn unit testing and read it.\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eOne of the most useful tools in unit testing is a good mocking framework. (I\u0026rsquo;m currently using \u003ca href=\"http://code.google.com/p/moq/\"\u003eMoq\u003c/a\u003e, and before that I used \u003ca href=\"http://www.ayende.com/projects/rhino-mocks.aspx\"\u003erhino\u003c/a\u003e)\u003c/div\u003e\u003cdiv\u003e \u003c/div\u003e\u003cdiv\u003eWe all know that for mocking we need interfaces.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eMy tip is very simple, if you have a class Foo and you wanna mock it, first you should have Interface IFoo (this should be obvious to most of you).\u003c/div\u003e\u003cdiv\u003eImplement on Foo IEquatable\u0026lt;IFoo\u0026gt;, so if you test a list of IFoo and you want to assert Contains() you won\u0026rsquo;t have any problems with the proxy of IFoo that mocking framework generates on the interface and no one will blame you for your awful class that throws cast exception in its equals method :).\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eHope it\u0026rsquo;ll save you time in future.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThat it, KIS.\u003c/div\u003e\u003c/p\u003e","title":"Unit testing with mock framework and IEquatable\u003c\u003e"},{"content":"Hello,\nMy Recent problem was: How can I implement minimal decoupling navigation between views?\nI thought about using the EventAggregator already built in my system and create some kind of event that represents a navigation request, so I created a NavigationRequestEvent that contains the view model I want to activate and view.\nNext question I asked myself was: Who needs to request for navigation?\nThis is easy navigation is caused 99% of the times by user interaction, views is a good answer, through their view models or some commands (if not DelegateCommands or SmarterStuff).\nThe problem is that my view models are being created from my IOC Container (not a problem) and I don\u0026rsquo;t want all of my view models to have access to my container cause this is an anti pattern.\nWho\u0026rsquo;ll construct the view model and fire the event?\nCreate a view models factory that will be responsible for creating the view models, he is not the actual factory, just a mediator between the request and the container.\nSo far we got:\nNavigationRequestEvent that holds the view model to showViewModelsFactory - can create view models\nNow I just need someone to listen, this is the advantage of this pattern, anyone can listen and no one is also an option, but nothing will happen of course.\nIn my case the shell is the default listener and each event would be translated to a view shown at the main region of the ui , there is also an option of a split view, when split view activated the main region unregister from event and secondary view is listening to the event.\nWe can also expend this behavior and allow user to choose where next views will be opened.\nIsNice = True;\n","permalink":"https://kinnrot.github.io/event-base-wpf-navigation/","summary":"\u003cp\u003eHello,\u003cbr /\u003e\u003cbr /\u003eMy Recent problem was: \u003ci\u003eHow can I implement minimal decoupling navigation between views?\u003c/i\u003e\u003cbr /\u003e\u003cbr /\u003eI thought about using the \u003ca href=\"http://www.google.co.il/search?hl=iw\u0026amp;q=EventAggregator\u0026amp;meta=\u0026amp;aq=f\u0026amp;aqi=g-s1\u0026amp;aql=\u0026amp;oq=\u0026amp;gs_rfai=\"\u003eEventAggregator\u003c/a\u003e already built in my system and create some kind of event that represents a navigation request, so I created a NavigationRequestEvent that contains the view model I want to activate and view.\u003cbr /\u003e\u003cbr /\u003eNext question I asked myself was: \u003ci\u003eWho needs to request for navigation?\u003c/i\u003e\u003cbr /\u003e\u003ci\u003e\u003cbr /\u003e\u003c/i\u003e\u003cbr /\u003eThis is easy navigation is caused 99% of the times by user interaction, views is a good answer, through their view models or some commands (if not\u003ca href=\"http://www.google.co.il/#hl=iw\u0026amp;q=DelegateCommand\u0026amp;meta=\u0026amp;aq=f\u0026amp;aqi=g-s1\u0026amp;aql=\u0026amp;oq=\u0026amp;gs_rfai=\u0026amp;fp=8bbed8b7b324a60c\"\u003e DelegateCommands\u003c/a\u003e or \u003ca href=\"http://www.google.co.il/url?sa=t\u0026amp;source=web\u0026amp;cd=1\u0026amp;ved=0CAgQFjAA\u0026amp;url=http%3A%2F%2Fcaliburn.codeplex.com%2F\u0026amp;ei=Abi0TLjWKs3Cswa6ysGsCA\u0026amp;usg=AFQjCNEU7re61lN7tQ4BNijEoX0NXtNF6A\u0026amp;sig2=x4Cmo1bQvpS0UezUbDJg_w\"\u003eSmarterStuff\u003c/a\u003e).\u003cbr /\u003eThe problem is that my view models are being created from my \u003ca href=\"http://www.google.co.il/#hl=iw\u0026amp;q=wiki%3A+IOC+Container\u0026amp;meta=\u0026amp;aq=f\u0026amp;aqi=\u0026amp;aql=\u0026amp;oq=\u0026amp;gs_rfai=\u0026amp;fp=8bbed8b7b324a60c\"\u003eIOC Container\u003c/a\u003e (not a problem) and I don\u0026rsquo;t want all of my view models to have access to my container cause this is an anti pattern.\u003cbr /\u003e\u003cbr /\u003e\u003ci\u003eWho\u0026rsquo;ll construct the view model and fire the event?\u003c/i\u003e\u003cbr /\u003e\u003cbr /\u003eCreate a view models factory that will be responsible for creating the view models, he is not the actual factory, just a mediator between the request and the container.\u003cbr /\u003e\u003cbr /\u003eSo far we got:\u003cbr /\u003e\u003cbr /\u003e\u003cul\u003e\u003cli\u003eNavigationRequestEvent that holds the view model to show\u003c/li\u003e\u003cli\u003eViewModelsFactory - can create view models\u003c/li\u003e\u003c/ul\u003e\u003cbr /\u003eNow I just need someone to listen, this is the advantage of this pattern, anyone can listen and no one is also an option, but nothing will happen of course.\u003cbr /\u003e\u003cbr /\u003eIn my case the shell is the default listener and each event would be translated to a view shown at the main region of the ui , there is also an option of a split view, when split view activated the main region unregister from event and secondary view is listening to the event.\u003cbr /\u003eWe can also expend this behavior and allow user to choose where next views will be opened.\u003cbr /\u003e\u003cbr /\u003eIsNice = True;\u003c/p\u003e","title":"Event Base WPF Navigation"},{"content":"Just code.\nWe have a logger and a log viewer, could be better but I wanted it to be simple.\nThis is the window that is also the log viewer\n/// \u0026lt;summary\u0026gt;\n/// Interaction logic for MainWindow.xaml\n/// \u0026lt;/summary\u0026gt;\npublic partial class MainWindow : Window, ILogViewer\n{\npublic MainWindow()\n{\nInitializeComponent();\nLogger.RegisterViewer(this);\n}\npublic void Log(string message)\n{\n// do the write logic\n}\n}\nThis is the interface of viewers\npublic interface ILogViewer\n{\nvoid Log(string message);\n}\nThis is logger\npublic static class Logger\n{\nstatic List\u0026lt;ILogViewer\u0026gt; viewers = new List\u0026lt;ILogViewer\u0026gt;();\npublic static void RegisterViewer(ILogViewer viewer)\n{\nviewers.Add(viewer);\n}\npublic static void Log(string message)\n{\nforeach (ILogViewer viewer in viewers)\n{\nviewer.Log(message);\n}\n}\n}\n","permalink":"https://kinnrot.github.io/simple-abstraction-and-decoupling/","summary":"\u003cp\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: 'Courier New', Courier, monospace;\"\u003eJust code.\u003c/span\u003e\u003cbr /\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: 'Courier New', Courier, monospace;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cbr /\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: 'Courier New', Courier, monospace;\"\u003eWe have a logger and a log viewer, could be better but I wanted it to be simple.\u003c/span\u003e\u003cbr /\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: 'Courier New', Courier, monospace;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cbr /\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: 'Courier New', Courier, monospace;\"\u003eThis is the window that is also the log viewer\u003c/span\u003e\u003cbr /\u003e\u003cpre class=\"brush: csharp;\"\u003e/// \u0026lt;summary\u0026gt;\u003cbr /\u003e /// Interaction logic for MainWindow.xaml\u003cbr /\u003e /// \u0026lt;/summary\u0026gt;\u003cbr /\u003e public partial class MainWindow : Window, ILogViewer\u003cbr /\u003e {\u003cbr /\u003e public MainWindow()\u003cbr /\u003e {\u003cbr /\u003e InitializeComponent();\u003cbr /\u003e Logger.RegisterViewer(this);\u003cbr /\u003e }\u003cbr /\u003e\u003cbr /\u003e public void Log(string message)\u003cbr /\u003e {\u003cbr /\u003e // do the write logic\u003cbr /\u003e }\u003cbr /\u003e }\u003cbr /\u003e\u003cbr /\u003e\u003c/pre\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: 'Courier New', Courier, monospace;\"\u003eThis is the interface of viewers\u003c/span\u003e\u003cbr /\u003e\u003cpre class=\"brush: csharp;\"\u003epublic interface ILogViewer\u003cbr /\u003e{\u003cbr /\u003e void Log(string message);\u003cbr /\u003e}\u003cbr /\u003e\u003c/pre\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: 'Courier New', Courier, monospace;\"\u003eThis is logger\u003c/span\u003e\u003cbr /\u003e\u003cpre class=\"brush: csharp;\"\u003epublic static class Logger\u003cbr /\u003e{\u003cbr /\u003e static List\u0026lt;ILogViewer\u0026gt; viewers = new List\u0026lt;ILogViewer\u0026gt;();\u003cbr /\u003e\u003cbr /\u003e public static void RegisterViewer(ILogViewer viewer)\u003cbr /\u003e {\u003cbr /\u003e viewers.Add(viewer);\u003cbr /\u003e }\u003cbr /\u003e\u003cbr /\u003e public static void Log(string message)\u003cbr /\u003e {\u003cbr /\u003e foreach (ILogViewer viewer in viewers)\u003cbr /\u003e {\u003cbr /\u003e viewer.Log(message);\u003cbr /\u003e }\u003cbr /\u003e }\u003cbr /\u003e}\u003cbr /\u003e\u003c/pre\u003e\u003c/p\u003e","title":"Simple abstraction and decoupling example"},{"content":"The case I\u0026rsquo;m talking about is Binding with the UpdateSourceTrigger = PropertyChanged, and a heavy logic behind each change that can cause bad UX, like ui freeze on each key press in a text box.\nHere is a nice sample that demonstrate this case:\nI have a window with a text box and 2 buttons, the IsEnabled of the buttons is bounded to custom properties that depends on the TextBox text bounded field to decide if the button should be enabled (just like commands).\nThis is the window\nThis is the window xaml\n\u0026lt;Window x:Class=\u0026ldquo;ReactivlyPropertyChanged.MainWindow\u0026rdquo;\nxmlns=\u0026ldquo;http://schemas.microsoft.com/winfx/2006/xaml/presentation\u0026quot;\nxmlns:x=\u0026ldquo;http://schemas.microsoft.com/winfx/2006/xaml\u0026quot;\nTitle=\u0026ldquo;MainWindow\u0026rdquo; Height=\u0026ldquo;350\u0026rdquo; Width=\u0026ldquo;525\u0026rdquo; x:Name=\u0026ldquo;this\u0026rdquo;\u0026gt;\n\u0026lt;Grid\u0026gt;\n\u0026lt;StackPanel\u0026gt;\n\u0026lt;TextBox Text=\u0026quot;{Binding SomeText, ElementName=this, UpdateSourceTrigger=PropertyChanged}\u0026rdquo;/\u0026gt;\n\u0026lt;Button IsEnabled=\u0026quot;{Binding ElementName=this, Path=CanSplitInMiddle}\u0026quot;\u0026gt;2\u0026lt;/Button\u0026gt;\n\u0026lt;Button IsEnabled=\u0026quot;{Binding ElementName=this, Path=CanSplitToThreeParts}\u0026quot;\u0026gt;3\u0026lt;/Button\u0026gt;\n\u0026lt;/StackPanel\u0026gt;\n\u0026lt;/Grid\u0026gt;\n\u0026lt;/Window\u0026gt;\nThis is the bounded properties implementation (I added sleep to demonstrate long time consumers)\nprivate string _someText;\npublic string SomeText\n{\nget { return _someText; }\nset\n{\n_someText = value;\nRaisePropertyChanged(\u0026ldquo;SomeText\u0026rdquo;);\n}\n}\npublic bool CanSplitInMiddle\n{\nget\n{\nif (SomeText == null)\nreturn false;\nThread.Sleep(100);\nreturn SomeText.Length % 2 == 0;\n}\n}\npublic bool CanSplitToThreeParts\n{\nget\n{\nif (SomeText == null)\nreturn false;\nThread.Sleep(100);\nreturn SomeText.Length % 3 == 0;\n}\n}\nAs you can see there is a simple length check of the entered string, now you probably think that the application would get stuck for each key press for at least 200 ms.\nTake a look at the property changed handling:\npublic MainWindow()\n{\n// Sets the buffer time for property changed\nvar interval = 500;\nInitializeComponent();\n// Create observable from the property changed event\nvar propertyChangedObservable = Observable.FromEvent\u0026lt;PropertyChangedEventArgs\u0026gt;(this, \u0026ldquo;PropertyChanged\u0026rdquo;).\nBufferWithTime(TimeSpan.FromMilliseconds(interval));\n// Define our query from the event, we want to get all fired propertyChanged\nvar query = from changedProps in propertyChangedObservable\nwhere changedProps.Count \u0026gt; 0 select changedProps;\n// start listening\nquery.Subscribe(listOfChangedStuff =\u0026gt;\n{\n// When fired group all events by property name and handle each property with Changed method\nvar events = from distinctEvent in listOfChangedStuff\ngroup distinctEvent by distinctEvent.EventArgs.PropertyName into byPropertyName\nselect byPropertyName;\nforeach (IGrouping\u0026lt;string,IEvent\u0026lt;PropertyChangedEventArgs\u0026gt;\u0026gt; groupedEvent in events)\n{\nChanged(groupedEvent.Key);\n}\n}); }\npublic void Changed(string propertyName)\n{\nif (propertyName == \u0026ldquo;SomeText\u0026rdquo;)\n{\n// Make the properties recalculate themself\nRaisePropertyChanged(\u0026ldquo;CanSplitInMiddle\u0026rdquo;);\nRaisePropertyChanged(\u0026ldquo;CanSplitToThreeParts\u0026rdquo;);\n}\n}\npublic void RaisePropertyChanged(string propertyName)\n{\nvar handlers = PropertyChanged;\nif (handlers != null)\n{\nPropertyChanged(this, new PropertyChangedEventArgs(propertyName));\n}\n}\nSo WTF?\nOne of Rx many features is buffer,I can tell property changed event to buffer himself for some time, and when the time passed take all fired events and work with them, what I did is to group all events by the property name (like distinct in sql) and handled each group as a single event.\nSo even if the user is a super turbo writer(or the bot that test the ui) , the event will fired only 2 times in a second, for 500 ms interval.\nI think this is awesome, you can configure the buffer interval according to how complex and time consuming your logic is, and avoid freezing ui.\nI wanted to upload the code to somewhere but o got to fly\u0026hellip;\n","permalink":"https://kinnrot.github.io/simple-rx-sample-ui-performance-tuning/","summary":"\u003cp\u003e\u003cspan class=\"Apple-style-span\" style=\"font-size: small;\"\u003e\u003cspan class=\"Apple-style-span\" style=\"font-size: 13px;\"\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: inherit;\"\u003e\u003cspan class=\"Apple-style-span\" style=\"font-size: medium;\"\u003eThe case I\u0026rsquo;m talking about is Binding with the UpdateSourceTrigger = PropertyChanged, and a heavy logic behind each change that can cause bad UX, like ui freeze on each key press in a text box.\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: inherit;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cbr /\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: inherit;\"\u003eHere is a nice sample that demonstrate this case:\u003c/span\u003e\u003cbr /\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: inherit;\"\u003eI have a window with a text box and 2 buttons, the IsEnabled of the buttons is bounded to custom properties that depends on the TextBox text bounded field to decide if the button should be enabled (just like commands).\u003c/span\u003e\u003cbr /\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: inherit;\"\u003eThis is the window\u003c/span\u003e\u003cbr /\u003e\u003cdiv class=\"separator\" style=\"clear: both; text-align: center;\"\u003e\u003ca href=\"http://4.bp.blogspot.com/_sNh3dtF9YE4/TI_igTblm9I/AAAAAAAACLw/k-zv0aBD_fM/s1600/Rx.bmp\" imageanchor=\"1\" style=\"margin-left: 1em; margin-right: 1em;\"\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: inherit;\"\u003e\u003cimg border=\"0\" src=\"http://4.bp.blogspot.com/_sNh3dtF9YE4/TI_igTblm9I/AAAAAAAACLw/k-zv0aBD_fM/s320/Rx.bmp\" /\u003e\u003c/span\u003e\u003c/a\u003e\u003c/div\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: inherit;\"\u003eThis is the window xaml\u003c/span\u003e\u003cbr /\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: inherit;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cbr /\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: inherit;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cbr /\u003e\u003cpre class=\"brush: csharp;\"\u003e\u0026lt;Window x:Class=\u0026ldquo;ReactivlyPropertyChanged.MainWindow\u0026rdquo;\u003cbr /\u003e xmlns=\u0026ldquo;\u003ca href=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation%22\"\u003ehttp://schemas.microsoft.com/winfx/2006/xaml/presentation\u0026quot;\u003c/a\u003e\u003cbr /\u003e xmlns:x=\u0026ldquo;\u003ca href=\"http://schemas.microsoft.com/winfx/2006/xaml%22\"\u003ehttp://schemas.microsoft.com/winfx/2006/xaml\u0026quot;\u003c/a\u003e\u003cbr /\u003e Title=\u0026ldquo;MainWindow\u0026rdquo; Height=\u0026ldquo;350\u0026rdquo; Width=\u0026ldquo;525\u0026rdquo; x:Name=\u0026ldquo;this\u0026rdquo;\u0026gt;\u003cbr /\u003e \u0026lt;Grid\u0026gt;\u003cbr /\u003e \u0026lt;StackPanel\u0026gt;\u003cbr /\u003e \u0026lt;TextBox Text=\u0026quot;{Binding SomeText, ElementName=this, UpdateSourceTrigger=PropertyChanged}\u0026rdquo;/\u0026gt;\u003cbr /\u003e \u0026lt;Button IsEnabled=\u0026quot;{Binding ElementName=this, Path=CanSplitInMiddle}\u0026quot;\u0026gt;2\u0026lt;/Button\u0026gt;\u003cbr /\u003e \u0026lt;Button IsEnabled=\u0026quot;{Binding ElementName=this, Path=CanSplitToThreeParts}\u0026quot;\u0026gt;3\u0026lt;/Button\u0026gt;\u003cbr /\u003e\u003cbr /\u003e \u0026lt;/StackPanel\u0026gt;\u003cbr /\u003e \u0026lt;/Grid\u0026gt;\u003cbr /\u003e\u0026lt;/Window\u0026gt;\u003c/pre\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: inherit;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cbr /\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: inherit;\"\u003eThis is the bounded properties implementation (I added sleep to demonstrate long time consumers)\u003c/span\u003e\u003cbr /\u003e\u003cpre class=\"brush: csharp;\"\u003eprivate string _someText;\u003cbr /\u003e\u003cbr /\u003e public string SomeText\u003cbr /\u003e {\u003cbr /\u003e get { return _someText; }\u003cbr /\u003e set\u003cbr /\u003e {\u003cbr /\u003e _someText = value;\u003cbr /\u003e RaisePropertyChanged(\u0026ldquo;SomeText\u0026rdquo;);\u003cbr /\u003e }\u003cbr /\u003e }\u003cbr /\u003e\u003cbr /\u003e public bool CanSplitInMiddle\u003cbr /\u003e {\u003cbr /\u003e get\u003cbr /\u003e {\u003cbr /\u003e if (SomeText == null)\u003cbr /\u003e return false;\u003cbr /\u003e Thread.Sleep(100);\u003cbr /\u003e return SomeText.Length % 2 == 0;\u003cbr /\u003e }\u003cbr /\u003e }\u003cbr /\u003e\u003cbr /\u003e public bool CanSplitToThreeParts\u003cbr /\u003e {\u003cbr /\u003e get\u003cbr /\u003e {\u003cbr /\u003e if (SomeText == null)\u003cbr /\u003e return false;\u003cbr /\u003e Thread.Sleep(100);\u003cbr /\u003e return SomeText.Length % 3 == 0;\u003cbr /\u003e }\u003cbr /\u003e }\u003cbr /\u003e\u003cbr /\u003e\u003c/pre\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: inherit;\"\u003eAs you can see there is a simple length check of the entered string, now you probably think that the application would get stuck for each key press for at least 200 ms.\u003c/span\u003e\u003cbr /\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: inherit;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cbr /\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: inherit;\"\u003eTake a look at the property changed handling:\u003c/span\u003e\u003cbr /\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: inherit;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cbr /\u003e\u003cpre class=\"brush: csharp;\"\u003epublic MainWindow()\u003cbr /\u003e{\u003cbr /\u003e // Sets the buffer time for property changed\u003cbr /\u003e var interval = 500;\u003cbr /\u003e\u003cbr /\u003e InitializeComponent();\u003cbr /\u003e\u003cbr /\u003e // Create observable from the property changed event\u003cbr /\u003e var propertyChangedObservable = \u003cbr /\u003e Observable.FromEvent\u0026lt;PropertyChangedEventArgs\u0026gt;(this, \u0026ldquo;PropertyChanged\u0026rdquo;).\u003cbr /\u003e BufferWithTime(TimeSpan.FromMilliseconds(interval));\u003cbr /\u003e\u003cbr /\u003e // Define our query from the event, we want to get all fired propertyChanged\u003cbr /\u003e var query = from changedProps in propertyChangedObservable\u003cbr /\u003e where changedProps.Count \u0026gt; 0 \u003cbr /\u003e select changedProps;\u003cbr /\u003e \u003cbr /\u003e // start listening\u003cbr /\u003e query.Subscribe(listOfChangedStuff =\u0026gt;\u003cbr /\u003e {\u003cbr /\u003e// When fired group all events by property name and handle each property with Changed method\u003cbr /\u003e var events = from distinctEvent in listOfChangedStuff\u003cbr /\u003e group distinctEvent by distinctEvent.EventArgs.PropertyName into byPropertyName\u003cbr /\u003e select byPropertyName;\u003cbr /\u003e\u003cbr /\u003e foreach (IGrouping\u0026lt;string,IEvent\u0026lt;PropertyChangedEventArgs\u0026gt;\u0026gt; groupedEvent in events)\u003cbr /\u003e {\u003cbr /\u003e Changed(groupedEvent.Key);\u003cbr /\u003e }\u003cbr /\u003e }); \u003cbr /\u003e}\u003cbr /\u003e\u003cbr /\u003epublic void Changed(string propertyName)\u003cbr /\u003e{\u003cbr /\u003e if (propertyName == \u0026ldquo;SomeText\u0026rdquo;)\u003cbr /\u003e {\u003cbr /\u003e // Make the properties recalculate themself\u003cbr /\u003e RaisePropertyChanged(\u0026ldquo;CanSplitInMiddle\u0026rdquo;);\u003cbr /\u003e RaisePropertyChanged(\u0026ldquo;CanSplitToThreeParts\u0026rdquo;);\u003cbr /\u003e }\u003cbr /\u003e}\u003cbr /\u003e\u003cbr /\u003epublic void RaisePropertyChanged(string propertyName)\u003cbr /\u003e{\u003cbr /\u003e var handlers = PropertyChanged;\u003cbr /\u003e if (handlers != null)\u003cbr /\u003e {\u003cbr /\u003e PropertyChanged(this, new PropertyChangedEventArgs(propertyName));\u003cbr /\u003e }\u003cbr /\u003e}\u003cbr /\u003e\u003c/pre\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: inherit;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cbr /\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: inherit;\"\u003eSo WTF?\u003c/span\u003e\u003cbr /\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: inherit;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cbr /\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: inherit;\"\u003eOne of Rx many features is buffer,I can tell property changed event to buffer himself for some time, and when the time passed take all fired events and work with them, what I did is to group all events by the property name (like distinct in sql) and handled each group as a single event.\u003c/span\u003e\u003cbr /\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: inherit;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cbr /\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: inherit;\"\u003eSo even if the user is a super turbo writer(or the bot that test the ui) , the event will fired only 2 times in a second, for 500 ms interval.\u003c/span\u003e\u003cbr /\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: inherit;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cbr /\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: inherit;\"\u003eI think this is awesome, you can configure the buffer interval according to how complex and time consuming your logic is, and avoid freezing ui.\u003c/span\u003e\u003cbr /\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: inherit;\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cbr /\u003e\u003cspan class=\"Apple-style-span\" style=\"font-family: inherit;\"\u003eI wanted to upload the code to somewhere but o got to fly\u0026hellip;\u003c/span\u003e\u003c/p\u003e","title":"Simple Rx Sample - UI Performance tuning"},{"content":"Here is a good place to start with Rx for .net\nAnd here you have the wiki with examples\nEnjoy!\n","permalink":"https://kinnrot.github.io/for-amt-rx-for-net/","summary":"\u003cp\u003e\u003ca href=\"http://feedproxy.google.com/~r/CodeBetter/~3/jf3ZYaNOSxw/reactive-extensions-for-net-event-based-async-operations.aspx\"\u003eHere\u003c/a\u003e is a good place to start with Rx for .net\u003cbr /\u003e\u003cbr /\u003eAnd \u003ca href=\"http://rxwiki.wikidot.com/101samples#toc0\"\u003ehere\u003c/a\u003e you have the wiki with examples\u003cbr /\u003e\u003cbr /\u003eEnjoy!\u003c/p\u003e","title":"For AMT Rx for .net"},{"content":"Today I ran into a guy who worked with me on my previous project.\nOn that project I was responsible to rewrite the WCF channels (proxies) generation management and lifetime management of them.\nI decided to do some research and found some good stuff here.\nSo this guy (aka Kurki) tells me they found a memory leak in my manager, what was the problem?\nSo i messed up like I always do (well, only 90% of the time, like a good programmer).\nI wrote a code that registers to the Faulted event of the channel, kills the channel when Faulted and creates a new one to work with, everything looked fine, only one screw up (I\u0026rsquo;m sure some of you can guess).\nI forgot to unregister from the Faulted Event.\nOn the web they tell you to do some unique logic to kill your channel in a safe way, what they don\u0026rsquo;t talk about is that it\u0026rsquo;ll stay in memory and fire events if you won\u0026rsquo;t unregister from stuff although you think it is dead.\nSo please do not forget to unregister from stuff even if the object is disposable.\nOr consider the use of weak event listeners and problem solved.\n","permalink":"https://kinnrot.github.io/wcf-client-side-proxy-memory-leaks/","summary":"\u003cp\u003eToday I ran into a guy who worked with me on my previous project.\u003cbr /\u003eOn that project I was responsible to rewrite the WCF channels (proxies) generation management and lifetime management of them.\u003cbr /\u003eI decided to do some research and found some good stuff \u003ca href=\"http://wcfguidanceforwpf.codeplex.com/\"\u003ehere\u003c/a\u003e.\u003cbr /\u003eSo this guy (aka Kurki) tells me they found a memory leak in my manager, what was the problem?\u003cbr /\u003e\u003cbr /\u003eSo i messed up like I always do (well, only 90% of the time, like a good programmer).\u003cbr /\u003e\u003cbr /\u003eI wrote a code that registers to the Faulted event of the channel, kills the channel when Faulted and creates a new one to work with, everything looked fine, only one screw up (I\u0026rsquo;m sure some of you can guess).\u003cbr /\u003eI forgot to unregister from the Faulted Event.\u003cbr /\u003e\u003cbr /\u003eOn the web they tell you to do some unique logic to kill your channel in a safe way, what they don\u0026rsquo;t talk about is that it\u0026rsquo;ll stay in memory and fire events if you won\u0026rsquo;t unregister from stuff although you think it is dead.\u003cbr /\u003e\u003cbr /\u003eSo please \u003cu\u003edo not forget to unregister from stuff even if the object is disposable\u003c/u\u003e.\u003cbr /\u003e\u003cbr /\u003eOr consider the use of weak event listeners and problem solved.\u003c/p\u003e","title":"WCF client side proxy memory leaks"},{"content":"One of the basic stuff you wanna test as a client side developer, is that all of your UI bounded classes aka Controller, Model, ViewModel, Presenter, PresentationModel, or the code behind of your view if your just having fun.\nLet\u0026rsquo;s assume we have a person class with a name property:\npublic class Person : INotifyPropertyChanged\n{\npublic event PropertyChangedEventHandler PropertyChanged;\nprivate string _name;\npublic virtual string Name\n{\nget { return _name; }\nset { _name = value;\nFirePropertyChanged(\u0026ldquo;Name\u0026rdquo;);\n}\n}\nprotected virtual void FirePropertyChanged(string propertyName)\n{\nvar handlers = PropertyChanged;\nif (handlers != null)\n{\nhandlers(this, new PropertyChangedEventArgs(propertyName));\n}\n}\n}\nThe simplest way to perform this test is to write this code:\n[TestFixture]\npublic class PersonTest\n{\n[Test]\npublic void SetName_SomeNewString_FirePropertyChanged()\n{\nPerson person = new Person();\nstring changedPropertyName = string.Empty;\nperson.PropertyChanged += (sender, args) =\u0026gt; changedPropertyName = args.PropertyName;\nperson.Name = \u0026ldquo;Test\u0026rdquo;;\nAssert.AreEqual(\u0026ldquo;Name\u0026rdquo;, changedPropertyName);\n}\n}\n","permalink":"https://kinnrot.github.io/unit-test-propertychanged/","summary":"\u003cp\u003eOne of the basic stuff you wanna test as a client side developer, is that all of your UI bounded classes aka Controller, Model, ViewModel, Presenter, PresentationModel, or the code behind of your view if your just having fun.\u003cbr /\u003e\u003cdiv\u003e\u003cbr /\u003eLet\u0026rsquo;s assume we have a person class with a name property:\u003cbr /\u003e\u003cbr /\u003e\u003c/div\u003e\u003cpre class=\"brush: csharp; ruler: true;\"\u003epublic class Person : INotifyPropertyChanged\u003cbr /\u003e{\u003cbr /\u003e public event PropertyChangedEventHandler PropertyChanged;\u003cbr /\u003e\u003cbr /\u003e private string _name;\u003cbr /\u003e\u003cbr /\u003e public virtual string Name\u003cbr /\u003e {\u003cbr /\u003e get { return _name; }\u003cbr /\u003e set { _name = value;\u003cbr /\u003e FirePropertyChanged(\u0026ldquo;Name\u0026rdquo;);\u003cbr /\u003e }\u003cbr /\u003e }\u003cbr /\u003e\u003cbr /\u003e protected virtual void FirePropertyChanged(string propertyName)\u003cbr /\u003e {\u003cbr /\u003e var handlers = PropertyChanged;\u003cbr /\u003e if (handlers != null)\u003cbr /\u003e {\u003cbr /\u003e handlers(this, new PropertyChangedEventArgs(propertyName));\u003cbr /\u003e }\u003cbr /\u003e }\u003cbr /\u003e}\u003cbr /\u003e\u003c/pre\u003e\u003cpre class=\"brush: csharp; ruler: true;\"\u003e\u003c/pre\u003e\u003cdiv\u003eThe simplest way to perform this test is to write this code:\u003cbr /\u003e\u003cbr /\u003e\u003cpre class=\"brush: csharp; ruler: true;\"\u003e[TestFixture]\u003cbr /\u003epublic class PersonTest\u003cbr /\u003e{\u003cbr /\u003e [Test]\u003cbr /\u003e public void SetName_SomeNewString_FirePropertyChanged()\u003cbr /\u003e {\u003cbr /\u003e Person person = new Person();\u003cbr /\u003e string changedPropertyName = string.Empty;\u003cbr /\u003e person.PropertyChanged += (sender, args) =\u0026gt; changedPropertyName = args.PropertyName;\u003cbr /\u003e person.Name = \u0026ldquo;Test\u0026rdquo;;\u003cbr /\u003e Assert.AreEqual(\u0026ldquo;Name\u0026rdquo;, changedPropertyName);\u003cbr /\u003e }\u003cbr /\u003e}\u003cbr /\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/p\u003e","title":"Unit Test PropertyChanged"},{"content":"public class Chen\n{\npublic void SayHello()\n{\nConsole.WriteLine(\"Hello everyone! this is my first blog post, its about time\");\n}\n}\n","permalink":"https://kinnrot.github.io/hello-world/","summary":"\u003cpre class=\"brush: csharp\"\u003epublic class Chen\u003cbr /\u003e{\u003cbr /\u003e public void SayHello()\u003cbr /\u003e {\u003cbr /\u003e Console.WriteLine(\"Hello everyone! this is my first blog post, its about time\");\u003cbr /\u003e }\u003cbr /\u003e}\u003cbr /\u003e\u003c/pre\u003e","title":"Hello World"},{"content":"Hi, I\u0026rsquo;m Chen Kinnrot.\nI am a software engineering leader, pragmatic programmer, and problem solver. I believe in lean thinking and impact-driven development.\nCurrently, I work as an Engineering Manager at Lemonade, building the technology that powers the world\u0026rsquo;s most lovable insurance company.\nWhen I\u0026rsquo;m not coding or managing teams, I\u0026rsquo;m likely surfing or spending time with my family.\nYou can find me on GitHub and LinkedIn.\nNote: We are often hiring! Check out our careers page if you\u0026rsquo;re interested in joining us.\n","permalink":"https://kinnrot.github.io/about/","summary":"\u003cp\u003eHi, I\u0026rsquo;m \u003cstrong\u003eChen Kinnrot\u003c/strong\u003e.\u003c/p\u003e\n\u003cp\u003eI am a software engineering leader, pragmatic programmer, and problem solver. I believe in lean thinking and impact-driven development.\u003c/p\u003e\n\u003cp\u003eCurrently, I work as an \u003cstrong\u003eEngineering Manager\u003c/strong\u003e at \u003ca href=\"https://www.lemonade.com/?utm_source=kinnrot.github.io\"\u003eLemonade\u003c/a\u003e, building the technology that powers the world\u0026rsquo;s most lovable insurance company.\u003c/p\u003e\n\u003cp\u003eWhen I\u0026rsquo;m not coding or managing teams, I\u0026rsquo;m likely surfing or spending time with my family.\u003c/p\u003e\n\u003cp\u003eYou can find me on \u003ca href=\"https://github.com/kinnrot\"\u003eGitHub\u003c/a\u003e and \u003ca href=\"https://www.linkedin.com/in/kinnrot\"\u003eLinkedIn\u003c/a\u003e.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\u003cem\u003eNote: We are often hiring! Check out our \u003ca href=\"https://makers.lemonade.com/?utm_source=GxaQjE2meo\"\u003ecareers page\u003c/a\u003e if you\u0026rsquo;re interested in joining us.\u003c/em\u003e\u003c/p\u003e","title":"About Me"}]